Skip to content

T-H7LB-task-work-appends-post-mortem-stub

Status: closed/done · Impact: medium · Complexity: small

Have /sdlc:task-work append a post-mortem template stub — correctly placed at the end of the task document, pre-seeded with the three required H3 subsections — to the task file at start-time, so the implementation sub-agent fills a pre-positioned, pre-structured section rather than authoring placement and structure from scratch.

During /sdlc:task-work, the implementation sub-agent placed the

Post-mortem section mid-document (before ## Out of scope) instead

Section titled “Post-mortem section mid-document (before ## Out of scope) instead”

of at the end, and omitted the required ### Acceptance criteria coverage / ### What worked / ### Friction and automation gaps substructure, forcing the orchestrator to relocate and restructure it. Have task-work append a post-mortem template stub (correct end-of-document placement plus the three required H3 subsections) to the task file at start-time so the sub-agent fills a pre-positioned, pre-structured section rather than authoring placement and structure from scratch — preventing the recurring placement/structure drift.

— from T-J71K-backport-events-collection-to-wikilink-refs

/sdlc:task-work Step 8 (plugin/skills/task-work/SKILL.md, the ## 8. Post-mortem section) documents the required post-mortem structure — an H2 ## Post-mortem, a _Captured by …_ caption line, and exactly three H3 subsections (### Acceptance criteria coverage, ### What worked, ### Friction and automation gaps) — but nothing materializes that structure into the task file before the implementation sub-agent runs. Step 5b’s start_task.ts is the only start-time mechanical mutation of the task file (it flips frontmatter to in-progress, validates, stages one file, and lands the chore(tasks): start <basename> commit on main); it does not touch the body. So at Step 8 the sub-agent authors the section from scratch — inventing its placement and re-deriving its three H3 headings from the prose in Step 8 — and placement/structure drift (the section landing mid-document, or one H3 missing) is recurring.

LocationRole today
plugin/skills/task-work/SKILL.mdStep 8 (## 8. Post-mortem …, ~line 900) documents the required ## Post-mortem H2 + caption + three H3 subsections as a fenced template; Step 5b (### 5b. Mark the task started …, ~line 608) shells out to start_task.ts as the sole start-time task-file mutation.
plugin/skills/task-work/start_task.tsStart-time mechanical mutator: edits frontmatter (statusin-progress, last_reviewed), validates, stages only the task file, commits chore(tasks): start <basename> on main, transitions the lease, resets the feature branch. Never edits the body.
plugin/skills/task-work/tests/start_task.test.tsBehavioral tests for start_task.ts (frontmatter flip, commit, lease transition, idempotency). No coverage of body mutation today.

start_task.ts (invoked from Step 5b) appends a ## Post-mortem template stub to the end of the task-file body, on the main-repo copy, as part of the same chore(tasks): start <basename> commit — but only when no ## Post-mortem H2 already exists. The stub is the exact structure Step 8 documents: the ## Post-mortem H2, the _Captured by /sdlc:task-work on <YYYY-MM-DD>. PR: pending._ caption, and the three H3 subsections ### Acceptance criteria coverage, ### What worked, ### Friction and automation gaps, each with a single _TBD — filled at Step 8._ placeholder line. The H2 lands after the last existing body section, so placement is fixed by the tool, not the sub-agent.

Step 8 prose is reworded from “append a ## Post-mortem section” to “fill the ## Post-mortem stub that Step 5b already appended” — Step 8 now fills a pre-positioned, pre-structured section rather than authoring placement and structure. The three documented H3 headings stay in Step 8 as the source of truth for the stub’s content (so the stub and the fill-time guidance can never drift apart silently).

Idempotency is preserved: re-running start_task.ts against a task that already carries a ## Post-mortem H2 (resumed session, or a task that reached Step 8 on an earlier run) leaves the body untouched and produces no new commit when frontmatter is also already current.

  1. In start_task.ts, add a body-mutation step that runs against mainTaskPath alongside the existing frontmatter edit. Parse the body (the text after the frontmatter block) and detect an existing ## Post-mortem H2 with a line-anchored, case-sensitive scan (/^## Post-mortem\s*$/m). If present, skip — the body is already stubbed.
  2. When absent, append the stub to the end of the body: ensure exactly one trailing blank line before it, emit the H2, the _Captured by /sdlc:task-work on <YYYY-MM-DD>. PR: pending._ caption (UTC date from the existing todayUtc() helper / --today), then the three H3 subsections in documented order, each followed by a single _TBD — filled at Step 8._ line. Single-source the stub text and the three H3 headings as a module-level constant in start_task.ts so there is one literal to maintain.
  3. Fold the body change into the existing semantic-change path: the stub append counts as a semantic change, so the file is written, validated (sdlc entities validate), staged (still exactly one file — mainTaskPath), and committed under the same chore(tasks): start <basename> message. No second commit; no change to the staged-file sanity check (one file in, one file out).
  4. Update Step 5b prose in SKILL.md to state that start_task.ts now also appends the ## Post-mortem stub at the end of the body when one is absent. Update Step 8 prose to say it fills the stub Step 5b appended (not appends a section), keeping the three documented H3 headings as the structure source.
  5. Extend plugin/skills/task-work/tests/start_task.test.ts: assert that after startTask() on a stub-less task the body ends with the ## Post-mortem H2 followed by the three H3 subsections in order; that the H2 is the last H2 in the document (correct placement); that a second startTask() run is a no-op on the body (no duplicate ## Post-mortem); and that a task already carrying a ## Post-mortem H2 is left unchanged.
LocationKindChange
plugin/skills/task-work/start_task.tsmodifyAdd the end-of-body ## Post-mortem stub-append (H2 + caption + three H3 subsections), guarded by an “H2 already present” check; fold into the existing semantic-change write/validate/stage/commit path; single-source the stub literal.
plugin/skills/task-work/SKILL.mdmodifyStep 5b: note that start_task.ts appends the stub at start-time. Step 8: reword from “append a ## Post-mortem section” to “fill the stub Step 5b appended,” keeping the three documented H3 headings as the structure source.
plugin/skills/task-work/tests/start_task.test.tsmodifyAdd cases: stub appended at end with the three H3s in order; H2 is last in doc; second run is a body no-op; pre-existing ## Post-mortem left untouched.
  • AC-1: After startTask() runs on a task file with no ## Post-mortem H2, the resulting body contains a ## Post-mortem H2 followed (in order) by ### Acceptance criteria coverage, ### What worked, and ### Friction and automation gaps — asserted by a new case in plugin/skills/task-work/tests/start_task.test.ts.
  • AC-2: The appended ## Post-mortem H2 is the last H2 heading in the document (correct end-of-document placement) — asserted in start_task.test.ts.
  • AC-3: Running startTask() a second time against a task that already carries a ## Post-mortem H2 leaves the body byte-identical (no duplicate section, no new commit from the body) — asserted in start_task.test.ts.
  • AC-4: After the stub append, sdlc entities validate <task> passes on the mutated file (frontmatter valid; the _TBD —_ placeholders are in body prose, not in a required-section gate position) — exercised by the validate call inside start_task.ts’s commit path and confirmed by the existing test that asserts a clean commit.
  • AC-5: SKILL.md Step 8 no longer instructs the sub-agent to author the section’s placement/structure — it instructs filling the stub Step 5b appended — and Step 5b documents the stub-append; verifiable by grepping plugin/skills/task-work/SKILL.md for the reworded phrasing.
  • AC-6: The start-task test suite at plugin/skills/task-work/tests/start_task.test.ts passes under bun test.
  • Backfilling the stub into already-open or already-closed task files — the stub is appended only at Step 5b start-time for newly-started tasks.
  • Changing the post-mortem’s three-H3 schema, the caption wording, or the spawn-from-post-mortem friction-parsing contract — this task fixes where and how the section is materialized, not what it captures.
  • Adding a ## Post-mortem H2 to the task body-template.eta — the stub is start-time tooling, not part of the authored task template (a template H2 would trip the readiness gate before work begins).
  • none

Spawned by /sdlc:spawn-task-pr on 2026-06-11 UTC from T-J71K-backport-events-collection-to-wikilink-refs in git@github.com:sksizer/family.git.

Captured by /sdlc:task-work on 2026-06-20. PR: pending.

  • AC-1: auto — start_task.test.ts case “stub-less task → body gains ## Post-mortem H2 + the three H3s in order”.
  • AC-2: auto — start_task.test.ts case “appended ## Post-mortem H2 is the last H2 in the document”.
  • AC-3: auto — start_task.test.ts case “second run on an already-stubbed task: body byte-identical, no new body commit”.
  • AC-4: auto — exercised by start_task.ts’s validate-in-commit path; the AC-1/AC-2 tests land the start commit, which throws if entities validate rejects the appended stub.
  • AC-5: auto — grep on SKILL.md: Step 5b (line 643) documents the stub-append; Step 8 (line 889) instructs filling the Step-5b stub; the old “append a ## Post-mortem section” phrasing count is 0.
  • AC-6: auto — bun test plugin/skills/task-work/tests/start_task.test.ts → 12 pass / 0 fail.
  • The deterministic readiness gate (task gap-report) passed in one shot — all six required sections present, both touchpoint tables resolved, zero placeholders — so the task went start→implement with no definition round-trip.
  • The sub-agent landed all three source edits plus the regenerated site mirror in a single focused commit, and every pre-commit hook passed without --no-verify.
  • project-check-task-state-origin blocked the implementation commit because Step 5a/5b’s verify+start commits sat on local main un-pushed while origin/main was stale — the hook compares the task branch against origin/main. It resolved only when a parallel session pushed origin/main. Candidate fix: have the hook resolve its base to local main when origin/main is an ancestor of local main (T-6R73-pre-commit-drift-hooks-gate-unconditionally-forcing-no). → T-6R73-pre-commit-drift-hooks-gate-unconditionally-forcing-no
  • sdlc quality run --diff-against-baseline from a worktree defaulted --baseline-dir to the worktree-local path, so the first run errored baseline not found; the baseline lives in the superproject. Needed an explicit --baseline-dir <superproject>/.sdlc/quality-baselines (T-44OO-plugin-scripts-self-discover-project-root). → T-44OO-plugin-scripts-self-discover-project-root
  • The baseline-gated gate reported new-drift=10, all of it bun test ephemeral stdout (random http://127.0.0.1:<port>/ ports, PIDs, and example PR URLs from the parallel T-CW4K dashboard tests) — normalizeFinding masks neither the URL port nor bare PID columns, so the lines mismatch the baseline and surface as false new-drift that FAILS an unrelated task’s gate. This makes T-BQRU-quality-normalize-ports-pids-timings a concrete cross-task gate-blocker, not just cosmetic noise. → T-BQRU-quality-normalize-ports-pids-timings
  • Editing plugin/skills/task-work/SKILL.md regenerates site/src/content/docs/reference/skills/task-work.md; that mirror must be staged in the same commit or project-check-docs-drift blocks. Known pattern — handled by sdlc docs generate + staging the page. (SKIPPED — no new automation gap; the regenerate-and-stage fix at its source is already in flight via T-PA51-task-state-commits-regen-site-page, PR #443.)

← Back to Tasks