Cherry-pick heuristics, manifest merge, global file search, scrollbar styling, and pytest/Playwright coverage unblock review and filtered export for mmetl.
6.0 KiB
slack-sieve — handoff
Repo: https://git.levkin.ca/ilia/slack-sieve (public)
Clone: git clone git@git.levkin.ca:ilia/slack-sieve.git
Vikunja: todo.levkin.ca → Homelab → slack-sieve (SLK)
Last updated: 2026-06-03
What this is
Local triage UI for migrating Levkin Slack (levkine.slack.com) → homelab Mattermost (https://slack.levkin.ca, VM 10.0.10.237).
Pipeline:
Official Slack export (JSON)
→ make hydrate # __uploads/ via xoxe URLs in export
→ make preset-skips # optional noise-channel skips
→ make review # manifest.json (gitignored)
→ make prepare-export # prepared-export/ (filtered Slack shape)
→ mmetl transform slack
→ mmctl import
Data on disk (Mac)
| Path | Role |
|---|---|
~/Downloads/Levkin Slack export Sep 29 2016 - May 27 2026 |
Raw official export (~27MB JSON only) |
~/Downloads/Levkin Slack export enriched |
Use for review — JSON + __uploads/ (~1109 files) |
~/Documents/code/slack-sieve/manifest.json |
Triage decisions (local only, not in git) |
Hydrate copied 1109 / 1122 attachments; 13 old files returned HTTP 401 (expired export token).
Commands
cd ~/Documents/code/slack-sieve
export SLACK_EXPORT_PATH="$HOME/Downloads/Levkin Slack export enriched"
make review # http://127.0.0.1:8765
make hydrate # re-download attachments if needed
make preset-skips # apply presets/levkin-skips.json (safe to re-run; keeps your channel decisions)
make cherry-pick # bulk data/files picks on priority channels (optional)
make prepare-export # after review — filtered export for mmetl
make test # pytest + Playwright
Review progress (manifest snapshot)
As of preset + partial manual review:
| Status | Count | Channels |
|---|---|---|
| skip (preset Tier A/B) | 22 | #jewbottest, #meetings, #help, #baby, #garden, #recipes, #grants, #integromat, #clickup, #general, #after-school-activities, #cleaner, #medical, #purchase, #temp, #viewings, #moishe, #520steeles, #29wilson, #york, #jam, Reading List |
| import | 1 | #153niagara |
| partial (cherry-pick) | 3 | #122harmony, #6keefer, #zoey |
| undecided | 14 | See review order below |
Refresh counts after more review:
python3 -c "
import json
from pathlib import Path
m = json.loads(Path('manifest.json').read_text())
from collections import Counter
c = Counter(v.get('status','?') for v in m.get('channels',{}).values())
print(dict(c))
"
Suggested review order
#284richmond→#45ritson→ finish#122harmony,#6keefer,#zoey(partial)#banking→#realestate→#airbnb#izik→#levkin- Tier D (later):
#random,#professional,#parenting,#adhd,#baking-biz,#standup,#zane
Inside a channel
- Shift+S — skip whole channel
- Shift+I — import whole channel
- Cherry-pick mode — only checked messages export (use Import whole thread on parent)
- Skip: join/leave noise, bot posts, bare “ok” / link-only
- Keep: attachments, leases, repairs, banking, decisions with dates/names
Presets
presets/levkin-skips.json — Tier A/B channel names for make preset-skips.
Copy and edit for another workspace.
UI / server notes
- Port: 8765 (
SLACK_IMPORT_PORT) - Attachments: served at
/uploads/…and/api/file-download?file_id=… - DOCX preview: server-side + browser mammoth; spaces in filenames need URL decode (fixed in server)
- Restart after code changes:
make review(kill old process on 8765 if needed)
What not to use
| Tool | Why |
|---|---|
slack-advanced-exporter + rotating xoxe.xoxp token |
Token format rejected; enrich zip stayed ~4MB |
slackdump hydrate |
Rejects ?token=xoxe-… URLs; use this repo’s make hydrate instead |
slackdump browser login |
Failed in headless/automated runs; not required if official export exists |
Open tasks (source of truth)
Tracked in Vikunja → Homelab → slack-sieve. Update here when scope changes.
| P | Task | Owner | Status |
|---|---|---|---|
| P1 | Channel review in UI — make review, finish 14 undecided + 3 partial (order); save manifest |
@you | ⏳ next |
| P1 | Pilot import: one channel via make prepare-export → mmetl → mmctl on MM VM 10.0.10.237 |
@agent | ⏳ blocked on review |
| P2 | User mapping: Slack ID → Mattermost username for mmetl |
@agent | backlog |
| P3 | Re-hydrate 13 files that returned HTTP 401 (expired export token) | @you | optional |
| — | scripts/prepare-export.py + make prepare-export |
@agent | ✅ done |
Mattermost / homelab
- SSO: authentik-apps.md#mattermost (ansible)
- Import docs: https://docs.mattermost.com/administration-guide/onboard/migrate-from-slack.html
Repo layout
slack-sieve/
server.py # HTTP API + static UI
slack_export.py # Parse export, file index, search
static/ # Review UI
scripts/
hydrate-export.sh
preset-skips.py
auto-cherry-pick.py
prepare-export.py
build-test-fixture.py
tests/ # pytest + Playwright (mini-export fixture)
presets/
levkin-skips.json
manifest.json # gitignored — your work in progress
docs/
HANDOFF.md # this file
Moved from ansible
Slack import tooling was removed from git@git.levkin.ca:ilia/ansible.git (2026-05-29). Ansible guide pointer: docs/guides/slack-mattermost-import.md.
Security
- Do not commit
manifest.jsonor Slack export folders. - Rotate any Slack tokens/cookies pasted in chat during setup.
~/.config/hermes/gitea.envused for Gitea API only — unrelated to Slack.