| name | migrate-v0.1.0-to-v0.2.0 |
| description | Migrate a loopany workspace from v0.1.0 to v0.2.0. Strips kind ID prefixes (tsk-/sig-/lrn-/...), flattens date-bucketed storage to artifacts/<dirName>/, renames snake_case frontmatter to camelCase, auto-stamps createdAt/updatedAt, builds the journal index, and adds the journal kind. Triggers when bootstrap throws SchemaVersionMismatchError pointing at this skill. |
v0.1.0 → v0.2.0
The first big simplification. Borrowed from crewlet's loopany rewrite —
fewer knobs, slugs as IDs, journal as the time spine.
What changed
- Kind frontmatter shrinks: drop
idPrefix, bodyMode, storage,
idStrategy. Add optional slugLayout: 'flat' | 'year' (default
flat).
- Slugs are IDs: no kind prefix.
tsk-20260427-103045 → 20260427-103045,
prs-self → self. Globally unique across kinds (collision is a fail).
Unicode allowed (CJK fine).
- Storage flattens: every artifact lives at
artifacts/<dirName>/<id>.md. The old artifacts/{YYYY-MM}/... time
bucket is gone — time becomes a journal artifact.
- Frontmatter goes camelCase:
check_at → checkAt,
for_date → forDate, target_skill → targetSkill.
- Auto
createdAt / updatedAt: every write stamps these. Migration
derives createdAt from old timestamp IDs (or file mtime for slug IDs).
journal kind: new auto-managed kind. One entry per day at
artifacts/journal/<YYYY>/<YYYY-MM-DD>.md. Migration backfills it
from every existing artifact's createdAt.
Crewlet-specific extensions (lead, content-piece, signal UI fields
like priority/actionableBy/impact/quickWin, task runtime fields
like executor/prUrl/branchName) are deliberately not brought
over — they're crewlet's domain, not loopany's core.
Why
The v0.1 model carried 4 nobs (idPrefix/storage/idStrategy/bodyMode)
that nobody ever set differently. They added cognitive load to every kind
file without expressing real choice. The journal design folds the time
hierarchy into the same graph everything else uses — refs({id:'2026-05-06', direction:'out'}) is now "what happened that day" without any new query
machinery.
See the upstream design at
/Users/stonex/Workspace/primecrew/apps/crewlet/src/loopany/skills/core-artifacts/.
Pre-flight
cd $LOOPANY_HOME
git init -q 2>/dev/null || true
git add -A && git commit -q -m "pre-migration snapshot v0.1.0" || true
loopany doctor > /tmp/loopany-pre-migration-doctor.txt 2>&1 || true
ls artifacts/ > /tmp/loopany-pre-migration-tree.txt
If doctor reports any fail checks already, fix those first — the
migration assumes a healthy v0.1 workspace.
Steps
Run each script first without --apply (dry-run) and inspect the output.
When it looks right, rerun with --apply. Scripts are idempotent —
rerunning does no harm.
SKILL=skills/migrations/v0.1.0-to-v0.2.0/scripts
bun run $SKILL/01-snapshot.ts
bun run $SKILL/02-transform-artifacts.ts
bun run $SKILL/02-transform-artifacts.ts --apply
bun run $SKILL/03-rebuild-references.ts
bun run $SKILL/03-rebuild-references.ts --apply
bun run $SKILL/04-build-journal.ts
bun run $SKILL/04-build-journal.ts --apply
bun run $SKILL/05-bump-version.ts --apply
bun run $SKILL/06-refresh-kinds.ts
bun run $SKILL/06-refresh-kinds.ts --apply
After step 6, loopany doctor should pass cleanly with schema version: ok.
Rollback
cd $LOOPANY_HOME
git reset --hard HEAD
rm -f .migration-id-map.json
If you've gone past git commit mid-migration, the snapshot still wins —
all migration mutations are within the workspace tree.
Verification
loopany doctor
loopany artifact list --kind task
loopany artifact list --kind journal
ls $LOOPANY_HOME/artifacts/
Any loopany doctor failure should reproduce the exact symptom — file an
issue with the doctor output and the contents of .migration-id-map.json.
Notes
- ID collisions: if two old artifacts strip down to the same slug
(e.g.
mis-self and prs-self both → self), step 02 fails loud.
Resolve by renaming one of the source files before running, e.g.
mv artifacts/missions/mis-self.md artifacts/missions/mis-self-mission.md.
addresses edges: stored in references.jsonl, rewritten in step 03.
No data is lost.
_backfilled: true: every migrated artifact gets this flag — it's
honest about provenance and routes the artifact to the journal's
## Backfilled section instead of ## Activity.
- Scripts never import from
src/core/: they parse the old format
directly so they remain runnable even when the binary no longer
understands v0.1 files.