T-YGJ1-schema-migration-sweeps-concurrent-tasks
Status: closed/superseded · Impact: medium · Complexity: small
Auto-generated from a /sdlc:task-work post-mortem. Review and
promote to open/ready before picking up.
A schema bump (e.g. task v3→v4) bulk-stamps the entities that exist at
the moment the migration runs. Tasks authored on a feature branch and
merged concurrently with the bump miss the sweep — they land on main
still at the old schema_version, and the drift only surfaces later
when /sdlc:task-work picks one up and audit_entities fails the
gate, forcing a mid-task bump. Closing this gap means a bump’s
follow-through accounts for the in-flight corpus, not just the
snapshot at migration time. Surfaced by
T-1KPE-add-backlog-capture, which was authored at
schema_version: '3', missed the v4 bulk-stamp, and required a
mid-task bump to clear the resulting audit_entities drift.
| Location | Role today |
|---|---|
plugin/skills/entities-migrate/migrate_entities.ts | Applies mechanical schema-drift fixes (including stamping schema_version) across docs/planning/<plural>/ at the moment it runs — a one-shot snapshot of the corpus. |
plugin/skills/entities-migrate/SKILL.md | Spins up a worktree, runs the audit, stamps missing schema_version, opens a PR. Sees only entities present when invoked; tasks merged after (but authored at the old version) are not re-swept. |
plugin/skills/entities-audit/SKILL.md | Reports schema_version drift but is the late detector — it fires at task-pickup time inside the quality gate, after the stale task has merged. |
docs/planning/tasks/ | Carries the active task corpus; a task merged on its own branch concurrently with a bump arrives stamped at the pre-bump version and becomes silent drift. |
From T-1KPE-add-backlog-capture’s post-mortem: “The task was authored at
schema_version: '3'and missed the v4 bulk-stamp, forcing a mid-task bump to clear anaudit_entitiesdrift — the v4 migration should sweep tasks created/merged concurrently with the bump.”
Proposed
Section titled “Proposed”A schema bump’s migration leaves no stale-version task behind even when
tasks merge concurrently. Concretely: the bump procedure (the
schema-bump task template and/or /sdlc:entities-migrate) gains a
follow-through that re-sweeps the corpus after the concurrently-open
branches have merged — either by re-running the stamp after the bump’s
own PR lands, or by an idempotent re-sweep the orchestrator triggers
once the in-flight PRs that predate the bump have all merged. The
re-sweep is mechanical (stamp-only) and idempotent, so running it twice
is a no-op.
Approach
Section titled “Approach”- Decide the trigger mechanism. These are candidate mechanisms, not a
foregone manual sweep — pick during implementation:
(a) the schema-bump task template gains an explicit final step
“after concurrent in-flight PRs merge, re-run
/sdlc:entities-migrateto stamp stragglers” (cheapest, explicit, but operator-driven); (b) make ongoing schema verification a step in the/sdlc:orchestrateloop — each tick the orchestrator runs the audit (and, when drift is purely a stamp-version straggler, an idempotent re-stamp) so concurrently-merged tasks are caught on the next tick without an operator remembering to re-sweep; (c) run the sweep/verification as a GitHub Action / CI check — a workflow (on push tomain, and/or scheduled) runs the audit and either fails the check on drift or opens a stamp PR, so the corpus is verified continuously rather than only at bump time or task pickup; (d)audit_entities//sdlc:setupruns the stamp opportunistically. Options (b) and (c) make verification continuous (no reliance on remembering to re-sweep) at the cost of standing infrastructure; (a) is the cheapest one-shot. Whichever is chosen, document the re-sweep as idempotent so it’s safe to repeat. - Confirm
migrate_entities.ts’s stamp pass is idempotent on already-current entities (re-running stamps nothing new) so a re-sweep is a clean no-op when there are no stragglers — this is the precondition that makes any of (a)-(d) safe to run repeatedly. - Implement the chosen trigger (template step, orchestrate-loop step, CI workflow, or opportunistic stamp) and add a fixture: a corpus where one task is one version behind after a bump, re-swept to current; plus an already-current corpus that stays unchanged.
Root cause note. The recurring stale-version drift is a symptom of modeling entity state as files (frontmatter the migration must physically rewrite across the corpus). The deeper fix — an append-only event log so state is derived rather than bulk-rewritten — is tracked separately by the append-only event-log backlog item (filed in PR #151). This task closes the coverage gap for the file-based model we have today; it does not block on that larger change.
Files to touch
Section titled “Files to touch”The first two rows hold regardless of which trigger mechanism is chosen; the remaining rows depend on the Approach-1 decision (one of them, not all).
| Location | Kind | Change |
|---|---|---|
plugin/skills/entities-migrate/migrate_entities.ts | modify | Ensure / assert the stamp pass is idempotent so a re-sweep is a no-op when clean. |
plugin/skills/entities-migrate/tests/ | modify | Fixture: a one-version-behind straggler is stamped to current on re-sweep; an already-current corpus is unchanged. |
plugin/skills/entities-migrate/SKILL.md | modify | (trigger (a)) Document the post-bump re-sweep for concurrently-merged stragglers; note idempotency. |
plugin/skills/orchestrate/SKILL.md | modify | (trigger (b)) Add an audit/re-stamp step to the orchestrate tick so concurrently-merged stragglers are caught the next tick. |
.github/workflows/ | new | (trigger (c)) A workflow that runs audit_entities on push to main (and/or scheduled), failing on drift or opening a stamp PR. |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: A task that merges to main at the pre-bump
schema_versionafter a bump has run is brought to the current version by the documented re-sweep, without a/sdlc:task-workpickup being required to surface the drift. - AC-2: Re-running the stamp pass against an already-current corpus produces no diff (idempotent no-op).
- AC-3: The schema-bump procedure (template and/or
/sdlc:entities-migrateSKILL) documents the concurrent-merge re-sweep so a future bump’s author follows it.
Out of scope
Section titled “Out of scope”- Blocking concurrent merges during a bump (a merge-queue / freeze policy) — heavier coordination than this stamp-sweep follow-through.
- Changing what a bump migrates beyond
schema_versionstamping — this task is about coverage of the existing stamp, not new migration rules.
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”Spawned by /sdlc:task-work post-mortem of T-1KPE-add-backlog-capture on 2026-05-27.
Related (distinct) observed case — 2026-06-02
Section titled “Related (distinct) observed case — 2026-06-02”A sibling concurrency hazard surfaced during the .claude/->TS migration
dogfood: two concurrent /sdlc:task-work PRs, squash-merged out of
dispatch order, produced a phantom merge conflict on the task file.
Because task-state commits (verify / start / record-PR) land on main
directly, the lagging PR carried the same task-file edits via a divergent
commit ancestry that GitHub’s 3-way merge could not auto-reconcile;
git rebase --onto origin/main cleared it (the duplicate commits were
dropped by patch-equivalence, leaving only the real work commits). This
is a distinct root cause from this task’s schema-stamp gap but the same
family (concurrent task PRs + main-side coordination). A fix likely lives
in extending T-61OI-check-ancestry-flags-stale-base (auto-detect
the stale base) and/or auto-rebasing a lagging task PR before merge.
Dedup search (spawn-from-post-mortem)
Section titled “Dedup search (spawn-from-post-mortem)”Bullet: The task was authored at schema_version: ‘3’ and missed the v4 bulk-stamp, forcing a mid-task bump to clear an audit_entities drift — the v4 migration should sweep tasks created/merged concurrently with the bump. Keywords searched: schema_version, audit_entities, concurrently, bulk-stamp, migration, authored, mid-task, forcing Excluded: 2026-05-27-add-backlog-capture Top candidates (score / status / headline):
- 39 / closed/done / 2026-05-19-consolidate-task-status-enum — Consolidate task status enum and migrate existing instances
- 36 / closed/done / 2026-05-19-implement-entities-migrate — Implement /sdlc:entities-migrate to apply mechanical schema-drift fixes
- 30 / planning/needs-definition / 2026-05-23-archive-closed-tasks-in-subdirectory — Move closed tasks to docs/planning/tasks/archive/; default scans to active-only
- 22 / closed/done / 2026-05-22-restructure-task-touchpoints-as-a-table-with-symbol-dir-glob — Restructure task touchpoints as a table with symbol/dir/glob citation grammar
- 20 / planning/draft / 2026-05-25-add-sdlc-lease-migrate-and-control-plane-bootstrap — Add
sdlc lease migrateone-shot cutover (with control-plane bootstrap) Decision: SPAWNED