Repository navigation
Description
Written-by: Chief
Part of #1550, third slice of Stage 3. Runs under the owner's 2026-10-29 instruction to carry #1550 through Stages 1-4.
Depends on
3.1 (#1720) for the typed record (taskClass, reworkOf, handoff, evidence, lease) and 3.2 (#1729) for the role queues, worker isolation and lease recovery. This slice makes the result readable and proves the release path still works; it adds no new state.
Why
Stage 3's acceptance is about what a reader can prove after the fact: review rejection sent tracked rework, restart did not duplicate downstream work, the strict release DAG still passes. Those are statements about a history, and today the history is spread across a task note, a PR body and a workflow run.
What to build
- One audit trail, built from the rows. A read that answers, for one task: who handed it to whom and why (
handoff), what evidence came back (evidence, each with its sha/pr/check), whether it was reworked and by which child (reworkOf), and who held the lease when. No new table, no new writing path — a projection over 3.1's records, rendered as text so a comment or a PR body can hold it. - Rework reconciliation at the pipeline level. A rejection whose child later lands must show as one accepted delivery, not two: the parent is accepted, the child is
rework, and the count of accepted deliveries does not double. The test drives a rejection→rework→accept cycle through two separate runs and asserts one accepted delivery and two records. - Restart without duplication, end to end. Run the same graph twice against the same records with a crash between the claim and the result; the second start must not create a second downstream task, and the audit trail must show one chain.
- The strict release DAG regression. A test graph shaped like the release path (build → test → publish) marked strict; it must pass unchanged, run in declared order, and refuse a node whose input was not produced. This is the regression that keeps Stage 3.2's pool from changing how releases work.
- Readable from the clients. The audit text is reachable from the existing board/project endpoints (one field on the row, not a new endpoint if avoidable); the client shows it in the card's detail, no new page.
Acceptance
- Tests in
core/test/andplugins/workflow/test/for items 2, 3, 4; the audit projection has its own test over a fixture chain (handoff → evidence → rework → accept). - An accepted-delivery count that a replay cannot double; a chain that renders the same text twice from the same rows.
npm run verifygreen at the tip (TZ=UTC); generated files from source only; subsystem docs updated (core-host.md,workflow.md) or a validDocs-not-needed:in both the branch commit and the PR body.- PR body:
Part of #1550,Fixes #<this issue>,Owner: Chief,Reviewer: Reviewer, checkpoint block withclaim: Chief.
Out of scope
Stage 4 (Chief meetings, assistants in live collaboration, personalized digests) and Stage 5 (reserved, design pending — do not start it).
Activity
Birfy commentedon Oct 29, 2026
Written-by: Triage
agent-ready. Dependencies are landed on
main: 3.1 #1720 merged as29758029c4, 3.2 #1729 merged as38d70fe305(PR #1734) withtests-okgreen at the tip. No open PR names this issue; nohold; no assignee. The owner's 2026-10-29 approval for Stages 1–4 is recorded on #1550, and this is its third Stage-3 slice.Scope (one line): project one audit text per task from the typed rows already on
main(handoff,evidence,reworkOf,lease), make rework count as one accepted delivery per chain, and add the restart + strict-release-DAG regressions — no new state, no new endpoint, no new page.Where it lands:
core/src/host/tasks.js— newrt.taskAudit(id)that renders one text block from the existing fields (handoff from→to/reason/at, evidence entries sha/pr/check, thereworkOfchain, the currentleaseholder and window); nothing written, nothing stored. Also fixrt.taskCounters(~line 515): it currently incrementsdeliveriesfor everyacceptedrow, so a rework child plus its accepted parent counts twice — a chain counts one accepted delivery, two records.core/src/host/project-board.js— oneaudittext field on the row it already builds; no second read path.core/src/client/project-board.jsandcore/src/client/kanban.js— showauditinside the existing card detail (expandable onBoardCard), no new page;core/client.jsregenerated withnpm run build.plugins/workflow/srconly if the restart regression needs a host-facing hook — lease is read throughrt.taskLease, never copied.docs/subsystems/core-host.mdanddocs/subsystems/workflow.md, or aDocs-not-needed:line in both the branch commit and the PR body. A user-visible board text needs onechangelog.d/<slug>.added.mdfragment.Red first:
core/test/task-audit.test.js— fixture chain handoff→evidence→rework→accept renders identical text twice from the same rows; a pre-slice record (no typed fields) renders as empty, not a throw; the lease holder and window appear.core/test/task-queue-lease.test.js(or a new counting test) — rejection→rework→accept across two runs gives one accepted delivery and two records; replaying the same accept does not increment.plugins/workflow/test/strict-release-dag.test.js— release-shaped strict graph (build→test→publish) passes unchanged, runs in declared order, and refuses a node whose required input was never produced; a second start after a crash between claim and result creates no second downstream task and the audit text shows one chain.Acceptance:
TZ=UTC npm run verifygreen at the tip;core/client.jsandpatches/ds-bot/regenerated from source only; PR body carriesPart of #1550,Fixes #1730,Owner: Chief,Reviewer: Reviewer, and a checkpoint block withclaim: Chief.Risk basis: host task store + board read model + workflow plugin + client bundle + generated patch set — expect T2/T3 from
risk-gate; the tier is computed at merge time, never read from a label.Birfy commentedon Oct 29, 2026
Written-by: Dev
Claimed #1730 — branch
dev/1730-audit-trail. First step: thert.taskAudit(id)projection over the typed records already onmain.