mandrel 2.25.0 → 2.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/.agents/agents/acceptance-critic.md +10 -6
  2. package/.agents/audit-checklists/baselines.md +21 -0
  3. package/.agents/docs/quality-gates.md +80 -18
  4. package/.agents/docs/workflows.md +3 -1
  5. package/.agents/instructions.md +1 -1
  6. package/.agents/schemas/audit-rules.json +15 -0
  7. package/.agents/schemas/baselines/audit-baselines-envelope.schema.json +242 -0
  8. package/.agents/schemas/baselines/baseline-envelope.schema.json +4 -0
  9. package/.agents/schemas/baselines/crap.schema.json +8 -0
  10. package/.agents/schemas/model-attribution.schema.json +4 -0
  11. package/.agents/scripts/acceptance-eval.js +89 -6
  12. package/.agents/scripts/audit-baselines.js +136 -0
  13. package/.agents/scripts/check-arch-cycles.js +12 -93
  14. package/.agents/scripts/check-baseline-drift.js +16 -3
  15. package/.agents/scripts/check-baselines.js +19 -3
  16. package/.agents/scripts/check-cyclomatic.js +214 -0
  17. package/.agents/scripts/check-schema-references.js +392 -0
  18. package/.agents/scripts/check-test-temp-hygiene.js +38 -1
  19. package/.agents/scripts/check-workflow-timeouts.js +291 -0
  20. package/.agents/scripts/diagnose-friction.js +85 -19
  21. package/.agents/scripts/lib/audit-baselines/engine.js +177 -0
  22. package/.agents/scripts/lib/audit-baselines/gate-surface.js +63 -0
  23. package/.agents/scripts/lib/audit-baselines/headroom.js +72 -0
  24. package/.agents/scripts/lib/audit-baselines/hotspots.js +69 -0
  25. package/.agents/scripts/lib/audit-baselines/kinds.js +313 -0
  26. package/.agents/scripts/lib/audit-baselines/outliers.js +100 -0
  27. package/.agents/scripts/lib/audit-baselines/read.js +87 -0
  28. package/.agents/scripts/lib/audit-baselines/staleness.js +123 -0
  29. package/.agents/scripts/lib/audit-baselines/surface-entry.js +106 -0
  30. package/.agents/scripts/lib/audit-baselines/trend.js +125 -0
  31. package/.agents/scripts/lib/audit-baselines/weights.js +193 -0
  32. package/.agents/scripts/lib/audit-suite/index.js +0 -5
  33. package/.agents/scripts/lib/audit-suite/selector.js +9 -62
  34. package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +1 -0
  35. package/.agents/scripts/lib/baseline-schema-registry.js +13 -1
  36. package/.agents/scripts/lib/baselines/diff-scope-cli.js +22 -160
  37. package/.agents/scripts/lib/baselines/duplication-scanner.js +27 -0
  38. package/.agents/scripts/lib/baselines/git-base.js +26 -4
  39. package/.agents/scripts/lib/baselines/kinds/crap.js +112 -15
  40. package/.agents/scripts/lib/baselines/refresh-service.js +69 -11
  41. package/.agents/scripts/lib/baselines/scope.js +39 -90
  42. package/.agents/scripts/lib/baselines/writer.js +16 -11
  43. package/.agents/scripts/lib/changed-files.js +8 -1
  44. package/.agents/scripts/lib/cli-args.js +115 -1
  45. package/.agents/scripts/lib/close-validation/runner.js +70 -25
  46. package/.agents/scripts/lib/crap-engine.js +32 -13
  47. package/.agents/scripts/lib/crap-method-identity.js +153 -0
  48. package/.agents/scripts/lib/crap-utils.js +13 -0
  49. package/.agents/scripts/lib/cyclomatic-ceiling.js +265 -0
  50. package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +0 -2
  51. package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +0 -2
  52. package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +0 -2
  53. package/.agents/scripts/lib/git-utils.js +136 -80
  54. package/.agents/scripts/lib/import-graph.js +156 -0
  55. package/.agents/scripts/lib/observability/runtime-friction.js +17 -2
  56. package/.agents/scripts/lib/observability/source-classifier.js +175 -2
  57. package/.agents/scripts/lib/orchestration/ceremony-routing.js +17 -12
  58. package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +36 -6
  59. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +5 -0
  60. package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +12 -1
  61. package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +8 -1
  62. package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +10 -5
  63. package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +39 -3
  64. package/.agents/scripts/lib/orchestration/plan-context.js +119 -66
  65. package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +31 -5
  66. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +209 -109
  67. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +48 -12
  68. package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +79 -22
  69. package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +51 -20
  70. package/.agents/scripts/lib/orchestration/planning/authoring-context.js +70 -74
  71. package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +231 -0
  72. package/.agents/scripts/lib/orchestration/resolve-stories.js +18 -17
  73. package/.agents/scripts/lib/orchestration/run-epilogue.js +12 -0
  74. package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +29 -3
  75. package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +6 -6
  76. package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +42 -38
  77. package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -1
  78. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +245 -140
  79. package/.agents/scripts/lib/orchestration/spec-budget.js +16 -5
  80. package/.agents/scripts/lib/orchestration/story-follow-ups.js +182 -95
  81. package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +22 -0
  82. package/.agents/scripts/lib/orchestration/ticket-validator.js +5 -11
  83. package/.agents/scripts/lib/orchestration/ticketing/reads.js +4 -4
  84. package/.agents/scripts/lib/story-adjacency.js +3 -3
  85. package/.agents/scripts/lib/test-runner-contract.js +134 -0
  86. package/.agents/scripts/lib/test-tiers.js +11 -2
  87. package/.agents/scripts/lib/util/concurrent-map.js +17 -0
  88. package/.agents/scripts/lib/util/parse-id-list.js +103 -0
  89. package/.agents/scripts/lib/wave-runner/live-probe.js +24 -14
  90. package/.agents/scripts/lib/wave-runner/ready-set.js +189 -42
  91. package/.agents/scripts/lib/workers/combined-mi-crap-worker.js +4 -10
  92. package/.agents/scripts/lib/workers/crap-worker.js +2 -10
  93. package/.agents/scripts/lib/workers/maintainability-report-worker.js +4 -10
  94. package/.agents/scripts/lib/workers/maintainability-worker.js +4 -10
  95. package/.agents/scripts/lib/workers/serve-worker-messages.js +35 -0
  96. package/.agents/scripts/lib/worktree/git-hooks.js +206 -0
  97. package/.agents/scripts/lib/worktree/lifecycle/creation.js +6 -0
  98. package/.agents/scripts/lib/worktree-manager.js +14 -0
  99. package/.agents/scripts/plan-run-epilogue.js +17 -5
  100. package/.agents/scripts/providers/github/tickets.js +33 -10
  101. package/.agents/scripts/provision-git-hooks.js +85 -0
  102. package/.agents/scripts/quality-preview.js +112 -28
  103. package/.agents/scripts/resolve-stories.js +4 -1
  104. package/.agents/scripts/run-coverage.js +86 -35
  105. package/.agents/scripts/run-lint.js +20 -0
  106. package/.agents/scripts/run-tests.js +26 -36
  107. package/.agents/scripts/single-story-close.js +28 -2
  108. package/.agents/scripts/single-story-confirm-merge.js +22 -6
  109. package/.agents/scripts/stories-wave-tick.js +214 -38
  110. package/.agents/scripts/update-coverage-baseline.js +34 -4
  111. package/.agents/scripts/update-duplication-baseline.js +209 -83
  112. package/.agents/scripts/validate-docs-freshness.js +1 -0
  113. package/.agents/skills/core/diagnose-friction/SKILL.md +4 -1
  114. package/.agents/skills/core/gates-and-baselines/SKILL.md +17 -11
  115. package/.agents/skills/skills.index.json +2 -2
  116. package/.agents/workflows/audit-baselines.md +289 -0
  117. package/.agents/workflows/audit-navigability.md +5 -4
  118. package/.agents/workflows/deliver.md +13 -4
  119. package/.agents/workflows/helpers/acceptance-self-eval.md +47 -10
  120. package/.agents/workflows/helpers/code-quality-guardrails.md +9 -2
  121. package/.agents/workflows/helpers/deliver-digest.md +41 -21
  122. package/.agents/workflows/helpers/deliver-reference.md +77 -1
  123. package/.agents/workflows/helpers/deliver-story-reference.md +47 -6
  124. package/.agents/workflows/helpers/plan-reference.md +15 -5
  125. package/.agents/workflows/memory-consolidate.md +116 -0
  126. package/.agents/workflows/plan.md +3 -0
  127. package/README.md +13 -6
  128. package/docs/CHANGELOG.md +64 -0
  129. package/package.json +9 -4
  130. package/.agents/schemas/friction-event.schema.json +0 -56
  131. package/.agents/scripts/lib/feedback-loop/memory-freshness.js +0 -707
@@ -12,6 +12,34 @@ Reference-only detail split out of [`deliver.md`](../deliver.md) so the
12
12
  always-resident spine stays lean. Nothing here is a new MUST —
13
13
  it is the mechanics an operator consults when the matching lever is engaged.
14
14
 
15
+ ## Ranges (`4922 - 4926`) {#ranges}
16
+
17
+ A contiguous span is how an operator reads a plan run, so the dash range is a
18
+ first-class id shape rather than prose to interpret — `/deliver 4922 - 4926`
19
+ means exactly the five ids in it.
20
+
21
+ **Pass the span through; never expand it by hand.** Every id-list flag on the
22
+ delivery path takes range tokens — `resolve-stories.js --ids`,
23
+ `stories-wave-tick.js --stories` and `--dispatched`, and
24
+ `plan-run-epilogue.js --stories`. Normalize the operator's spacing away and hand
25
+ the scripts one unspaced token (`--ids 4922-4926`), mixed freely with singles
26
+ and commas (`--ids 4901,4922-4926`); overlaps dedupe. A hand-typed enumeration
27
+ is where an id gets dropped or invented, and the drop is silent.
28
+
29
+ The shared expander (`lib/util/parse-id-list.js`) refuses rather than guesses,
30
+ so a typo fails where it was typed instead of resolving the wrong set:
31
+
32
+ | Input | Outcome |
33
+ | --- | --- |
34
+ | `4922-4926`, `4922 - 4926` | Expands to the inclusive span. En and em dashes, and a `#` on either endpoint, are accepted too. |
35
+ | `4926-4922` | Refused — write it low-to-high. |
36
+ | `1-4926` | Refused — above the 50-id span cap (`MAX_RANGE_SPAN`). |
37
+ | `4922-`, `-4926`, `4922-4923-4924` | Refused as a malformed token. |
38
+
39
+ The cap is per range token, not per run: a genuine 60-Story delivery is still
40
+ expressible as two ranges, but a slipped digit cannot fan out into a live
41
+ resolution sweep of thousands of issues.
42
+
15
43
  ## Sequencing edge cases (`stories-wave-tick.js`)
16
44
 
17
45
  **What "discovered, not declared" means concretely.** `resolve-stories.js` reads
@@ -63,6 +91,18 @@ different operator holds, unless you pass `--steal`. Assignee-based withholding
63
91
  needs `github.operatorHandle` set (in `.agentrc.local.json`); without it the
64
92
  probe logs a warning and leans on init's lease refusal alone.
65
93
 
94
+ **Overlapping footprints are reserved across beats, not just within one.** A
95
+ Story sharing a **concrete** path with a still-implementing Story is withheld
96
+ and named in `inFlightReservation: { available, withheld: [{ id, blockedBy,
97
+ reason }], note }`, where `reason` is `in-flight-earlier-beat` or
98
+ `foreign-lease`. Like `foreignHeld` this is neither a failure nor a wedge — the
99
+ Story re-admits automatically once its blocker leaves the in-flight set — and
100
+ it exists so an unfilled slot is explained rather than mysterious. A **glob**
101
+ footprint (or the UNKNOWN sentinel for an unparseable body) reserves nothing
102
+ across beats; it still serializes its own beat. Reservation needs the in-flight
103
+ Stories' footprints, so it is a `--probe-live` capability: under `--dag` the
104
+ report is `available: false` and selection de-conflicts within the beat only.
105
+
66
106
  ## Dispatch mechanics (role-scoped by default)
67
107
 
68
108
  **A single-Story run executes inline.** Sub-agent isolation is
@@ -96,6 +136,18 @@ footprint keeps the fresh acceptance critic), and the `route::lite` label
96
136
  remains a human-visible hint only, never the control signal — a lost or
97
137
  never-written label cannot misroute delivery.
98
138
 
139
+ **Issue a beat's spawns in one turn.** A wave tick hands you a ready set, not a
140
+ queue: those Stories have no dependency edge between them (the resolver already
141
+ withheld any that do) and no shared write paths (each owns its own worktree and
142
+ branch). Dispatch them the way
143
+ [`parallel-tooling.md`](parallel-tooling.md) Rule 3 prescribes — **N `Agent`
144
+ calls issued together in a single assistant turn**, one per ready Story, not
145
+ `Agent` → wait → `Agent`. Serial dispatch is compliant with every other rule on
146
+ this page and costs the run a full Story's implementation time per sibling for
147
+ nothing; the wave aggregator is built for the parallel shape. Respect
148
+ `delivery.deliverRunner.concurrencyCap`: when the ready set exceeds it, slice
149
+ into batches of `cap` and dispatch each batch in its own turn.
150
+
99
151
  **Dispatch each `ready` Story (role-scoped by default).** When
100
152
  `delivery.routing.roleScopedAgents` is enabled (the **default**) and the host
101
153
  exposes agent dispatch, spawn each ready Story as its own
@@ -235,8 +287,32 @@ A slow-CI consumer can opt the close into `"async"` mode so the merge wait
235
287
  probes once for ~60s (catching an instant merge or an instantly-red required
236
288
  check) and then returns `pending` instead of burning ~5 minutes of the host
237
289
  tool slot polling a merge that lands after the wait would have expired anyway.
238
- When a worker returns that `pending` envelope, launch its `nextCommand` as a
290
+ When a close returns that `pending` envelope, launch its `nextCommand` as a
239
291
  **background** invocation (host background Bash — its completion re-invokes the
240
292
  agent) and move on to the next Story; `single-story-confirm-merge.js` is
241
293
  idempotent and owns the whole tail. Do not foreground-poll the merge. The
242
294
  default `"sync"` behaviour is unchanged.
295
+
296
+ **On a multi-Story run, pass `--merge-watch-mode async` on every close.** Close
297
+ sees one Story and cannot see run topology, so it cannot make this call for
298
+ itself — you can. Implementation runs in parallel but the close tail is
299
+ serialized one at a time, and under `sync` each of those closes holds the
300
+ foreground for its full merge wait before the next Story's close may start.
301
+ That is the run's dominant serialized cost, and it is paid per sibling:
302
+
303
+ ```bash
304
+ node <main-repo>/.agents/scripts/single-story-close.js \
305
+ --story <storyId> --cwd <main-repo> --merge-watch-mode async
306
+ ```
307
+
308
+ The flag overrides `delivery.mergeWatch.mode` for that invocation only — the
309
+ config default stays `"sync"`, which is right for the solo delivery that has no
310
+ sibling waiting behind it. It composes with `--max-wait-seconds`: pass both and
311
+ the explicit bound still wins over the async probe cap. An unrecognized value
312
+ exits non-zero before any phase runs, so a typo cannot silently drop the run
313
+ back onto synchronous waiting. Expect a `pending` envelope from each async
314
+ close — that is the designed ending here, not a failure; background its
315
+ `nextCommand` and move to the next Story's close immediately.
316
+
317
+ A one-Story run should keep the `sync` default: there is no sibling to unblock,
318
+ and the foreground wait is the cheapest path to `landed`.
@@ -203,6 +203,29 @@ round cap, proceed / redraft / block — not an independent additional pass
203
203
  over the criteria. The M4-B floor holds: one verdict per cluster, the
204
204
  cluster count owned by `acceptance-clusters.js` alone.
205
205
 
206
+ **One round = N cluster critics → ONE merged verdict → ONE gate call.** The
207
+ clusters are how a round is _authored_; they are not how it is _scored_.
208
+ Concatenate every cluster's records into a single `criteria[]` ordered by
209
+ `index` — exactly one per `acceptance[]` item, under one `storyId`,
210
+ `schemaVersion`, `round` and `commitSha` — and hand that merged file to the
211
+ gate once, with `--expected-criteria` set to the Story's `acceptance[]` count:
212
+
213
+ ```bash
214
+ node <main-repo>/.agents/scripts/acceptance-eval.js \
215
+ --story <storyId> --verdict <merged-verdict-path> \
216
+ --expected-criteria <acceptance[] count>
217
+ ```
218
+
219
+ The flag is what makes the merge enforceable: `assertCriteriaCoverage` returns
220
+ early on the `null` default, so **omitting it leaves the guard inert** and a
221
+ single cluster's verdict handed over unmerged scores a fraction of the criteria
222
+ and still reports `proceed`. A length mismatch is rejected before scoring and
223
+ consumes no round. Calling the gate once per cluster instead spends a round
224
+ _per cluster_ — a Story past the cluster ceiling would burn its whole redraft
225
+ budget on cluster arithmetic — and N concurrent calls race the Story-scoped
226
+ round ledger. Full per-round mechanics, including the parallel dispatch and the
227
+ merge shape: [`acceptance-self-eval.md`](acceptance-self-eval.md).
228
+
206
229
  **Critic evidence-share.** When the critic runs a `verify[]`
207
230
  command that is byte-identical to a close gate (`lint` / `typecheck`), it
208
231
  records the pass into the Story evidence keyspace via `--standalone` so
@@ -318,12 +341,23 @@ The wait probes the checks every poll: a red required check fails fast as
318
341
  base is brought up to date within `updateAttempts` tries.
319
342
 
320
343
  **Async merge-confirm mode (`delivery.mergeWatch.mode: "async"`).** Under
321
- the default `"sync"` the merge wait runs in the foreground as
322
- described above. When a consumer's CI routinely takes longer than the host
323
- tool ceiling (~10 min) can hold a single close invocation, the foreground
324
- wait almost always expires `pending` after burning ~5 minutes of the slot
325
- so `"async"` makes that async confirm a designed mode instead of an expiry
326
- accident. In async mode the close arms auto-merge, runs one short **~60s
344
+ the default `"sync"` the merge wait runs in the foreground as described above.
345
+
346
+ **On a multi-Story run, async is the posture pass `--merge-watch-mode async`
347
+ on every close.** This is not a slow-CI opt-in. Implementation fans out, but
348
+ the close tail is serialized one Story at a time, and under `sync` each close
349
+ holds the foreground for its full merge wait before the next may start; that
350
+ is the run's dominant serialized cost, paid once per sibling. Close sees one
351
+ Story and cannot see run topology, so the orchestrator — which can — makes the
352
+ call per invocation while the config default stays `"sync"`, which is right for
353
+ a solo delivery with no sibling waiting behind it
354
+ ([`deliver-reference.md`](deliver-reference.md) § Async merge-confirm mode).
355
+ A slow-CI consumer reaches for the same mode for the separate reason that a
356
+ foreground wait longer than the host tool ceiling (~10 min) almost always
357
+ expires `pending` after burning ~5 minutes of the slot — `"async"` makes that
358
+ confirm a designed ending instead of an expiry accident.
359
+
360
+ In async mode the close arms auto-merge, runs one short **~60s
327
361
  probe window** (long enough to catch an instant merge and, via the
328
362
  head-anchored required-check predicate, an instantly-red required check),
329
363
  then returns the standard `pending` terminal with a `nextCommand`. When you
@@ -362,6 +396,13 @@ judgment that help text cannot carry.
362
396
  - `--max-wait-seconds <n>` — from a headless caller with no host
363
397
  tool-invocation ceiling, to keep single-block semantics
364
398
  without editing the consumer's config.
399
+ - `--merge-watch-mode <sync|async>` — the per-invocation override of
400
+ `delivery.mergeWatch.mode`. **Pass `async` on every close of a multi-Story
401
+ run** (above); leave it off for a solo delivery. It composes with
402
+ `--max-wait-seconds` — pass both and the explicit bound still wins over the
403
+ async probe cap. An unrecognized value is refused before any phase runs, so a
404
+ typo cannot silently drop the run back onto synchronous waiting; the refusal
405
+ reports a `failed` terminal envelope at `phase: init`, mutating nothing.
365
406
 
366
407
  ---
367
408
 
@@ -215,12 +215,14 @@ ceilings on `STORY_SHAPE_CEILINGS` in
215
215
  against the repo before overriding one (authoring `creates` for a file
216
216
  that exists at base is a validator rejection). The persist gates stay
217
217
  authoritative: they probe the base branch ref, not the working tree.
218
- - **Keep `## Spec` near contract-level prose.** Persist emits an
219
- **advisory** warning past ~250 words (`SPEC_SOFT_WORD_BUDGET`) it never
220
- fails the persist, but it is the nudge toward a contract-level
218
+ - **Keep `## Spec` near contract-level prose.** **Aim for ~250 words; an
219
+ advisory warning fires past 350** (`SPEC_SOFT_WORD_BUDGET`). Two numbers,
220
+ two jobs: ~250 is the authoring target the nudge toward a contract-level
221
221
  Spec (interfaces, invariants, load-bearing constraints; no per-file
222
- behavior narration). The hard fail-closed ceiling (~1500 tokens,
223
- `spec-spill.js`) is unchanged.
222
+ behavior narration) while 350 is the slacker threshold at which persist
223
+ actually warns, so the warning marks a real outlier instead of ordinary
224
+ variance. Neither fails the persist. The hard fail-closed ceiling
225
+ (~1500 tokens, `spec-spill.js`) is unchanged.
224
226
 
225
227
  A faithfully-filled skeleton — placeholders replaced, pre-resolved entries
226
228
  kept, tags valid — passes the persist ticket validators with no
@@ -313,6 +315,14 @@ output shape standalone. When the kill-switch is off
313
315
  (`roleScopedAgents: false`) or the host cannot spawn at this depth, fall back
314
316
  to a generic sub-agent and hand it the same charter (the `consolidation` /
315
317
  `pre-mortem` definitions in [`plan-critic.md`](../../agents/plan-critic.md)).
318
+ **When both critics fire, dispatch them in a single turn.** Consolidation and
319
+ pre-mortem read the same immutable draft, share no write path, and neither
320
+ consumes the other's verdict — the textbook independent fan-out of
321
+ [`parallel-tooling.md`](parallel-tooling.md) Rule 3. Issue both `Agent` calls
322
+ together in one assistant turn rather than awaiting the first verdict before
323
+ spawning the second; serialized critics double the round's wall clock and buy
324
+ nothing, because you fold both verdicts into the same re-author round anyway.
325
+
316
326
  Either way the critic is **maker-blind**: hand it the draft artifacts
317
327
  (`stories.json`, and `techspec.md` when present) — never the authoring
318
328
  transcript or the reasons the planner believed its own draft is sound. A
@@ -0,0 +1,116 @@
1
+ ---
2
+ description: >-
3
+ Attended consolidation pass over this project's agent memory pool — merge
4
+ duplicates, verify claims against the current tree, prune with operator
5
+ confirmation, rewrite the index, and stamp the pool so the /plan advisory
6
+ goes quiet.
7
+ ---
8
+
9
+ # /memory-consolidate [--dry-run]
10
+
11
+ Agent memory drifts as the codebase moves: a workaround gets fixed, a budget
12
+ changes, two sessions save the same lesson twice. This is the sweep that
13
+ corrects it — and the **only** sanctioned writer of the memory pool outside a
14
+ session's own point-of-write corrections.
15
+
16
+ **Attended by contract.** Mandrel ships the trigger, the grounding and the
17
+ receipt; it never mutates the operator's personal memory store unsupervised.
18
+ Nothing here runs on a schedule, and no step deletes a file before Gate #2.
19
+
20
+ ## Step 0 — Resolve the pool
21
+
22
+ `MANDREL_MEMORY_DIR` wins outright; otherwise the pool is
23
+ `~/.claude/projects/<cwd-slug>/memory/`, where `<cwd-slug>` is the absolute
24
+ working directory with every `/` and `.` replaced by `-`.
25
+
26
+ Report the resolved path and the entry count. **No pool → say so in one line
27
+ and stop** — an absent substrate is a clean no-op, never an error, and never a
28
+ reason to create one.
29
+
30
+ Each project (and each worktree) has its own pool: consolidate the pool of the
31
+ checkout you are in, and never reach across into another.
32
+
33
+ ## Step 1 — Read the pool
34
+
35
+ Read `MEMORY.md` and every `*.md` entry. Group them by subject so duplicates
36
+ and supersessions surface together. Do not judge an entry from its index line —
37
+ the index is a pointer, the file is the claim.
38
+
39
+ ## Step 2 — Classify each entry
40
+
41
+ Verify before you keep. Run `ls` / `grep` against the **current tree** for the
42
+ paths, flags, budgets and gate names an entry cites; re-measure a number rather
43
+ than trusting it (`wc -c` a file whose byte budget is quoted).
44
+
45
+ | Verdict | Means | Action |
46
+ | --- | --- | --- |
47
+ | `fresh` | Claims re-confirmed against the tree | Leave byte-identical |
48
+ | `correct` | Core lesson holds, a detail has moved | Rewrite the detail in place, keep the entry |
49
+ | `duplicate` | Same lesson as another entry | Merge into the richer one, propose the thinner for pruning |
50
+ | `superseded` | The thing it warns about is fixed or retired | Strike the claim, keep the correction visible |
51
+ | `dead` | Subject no longer exists at all | Propose for pruning |
52
+
53
+ **A closed issue is the subject of a retrospective, never evidence of
54
+ staleness.** These pools are largely delivery write-ups — "delivered this
55
+ Story", "fixed by that PR". The referenced issue being closed is what the
56
+ memory is *about*: the normal, healthy shape. A retired predecessor of this
57
+ workflow marked exactly that pattern stale, which is why it no longer exists.
58
+ Use `github.owner` / `github.repo` from `.agentrc.json` when an issue
59
+ genuinely needs probing, and treat an unreachable probe as unknown — never
60
+ as dead.
61
+
62
+ Prefer `correct` over `dead`. A rewritten entry keeps hard-won context; a
63
+ deleted one costs a future session the same mistake.
64
+
65
+ ## Step 3 — Gate #1: present the plan
66
+
67
+ Write the full proposal to `temp/memory/consolidation-<date>.md` — per entry:
68
+ verdict, evidence, and the exact edit or merge proposed. Summarize inline:
69
+ counts per verdict and the specific prune candidates by name.
70
+
71
+ **STOP.** Do not edit until the operator responds.
72
+
73
+ ## Step 4 — Apply the edits
74
+
75
+ On confirmation, apply the `correct`, `duplicate` and `superseded` rewrites.
76
+ Preserve each entry's frontmatter contract (`name`, `description`, `metadata`)
77
+ and keep `[[wiki-link]]` references resolvable — a merge that orphans a link
78
+ has moved the problem, not fixed it.
79
+
80
+ ## Step 5 — Gate #2: confirm every deletion
81
+
82
+ **Deletion is never implied by Gate #1.** Name each file proposed for pruning
83
+ with its one-line reason, and offer **mark-vs-delete**: marking the claim
84
+ superseded in place is the default and always available. Wait for an explicit
85
+ yes; delete only what the operator names. Silence is not consent.
86
+
87
+ ## Step 6 — Rewrite the index and stamp
88
+
89
+ Rewrite `MEMORY.md` so it holds exactly one pointer line per surviving entry —
90
+ title, link, hook. It is loaded into context every session, so it carries
91
+ pointers only, never memory content.
92
+
93
+ Then write the receipt to `.consolidation-stamp.json` in the pool root:
94
+
95
+ ```json
96
+ { "lastConsolidatedAt": "<ISO-8601 timestamp>" }
97
+ ```
98
+
99
+ The `/plan` Phase 0 advisory reads this file; until it is written, the nudge
100
+ keeps firing. Write it **only** after Gate #2 — the stamp asserts an operator
101
+ reviewed the pass, so writing it early makes it a lie.
102
+
103
+ Close with counts: entries read, corrected, merged, pruned, and the new total.
104
+
105
+ ## Constraints
106
+
107
+ - `--dry-run` runs Steps 0–3 and stops: the report is written, nothing mutates.
108
+ - Never delete an entry the operator did not name. Never write the stamp on a
109
+ dry run or a declined gate.
110
+ - Never invent memories here — this pass corrects and prunes what sessions
111
+ wrote; new memories come from the sessions that learned them.
112
+
113
+ ## See also
114
+
115
+ [`/plan`](plan.md) (surfaces the advisory at its Gate #1),
116
+ [`/deliver`](deliver.md) (point-of-write corrections as work lands).
@@ -75,6 +75,9 @@ decision-made-by-default.
75
75
  **Gate #1** — STOP to confirm the sharpened plan intent and any
76
76
  duplicate-candidate review. Under `--yes`, auto-proceed.
77
77
 
78
+ On a truthy `memoryPoolAdvisory.recommend`, name [`/memory-consolidate`](memory-consolidate.md)
79
+ as an operator option, quoting its `reasons[]` — advisory, never invoked here.
80
+
78
81
  On a truthy `deliverLightSuggestion.suggested`, offer — advisory, never an
79
82
  automatic reroute — to deliver the seed instead; on confirm, route **in this
80
83
  session** into [`helpers/deliver-light.md`](helpers/deliver-light.md), its gate
package/README.md CHANGED
@@ -182,7 +182,9 @@ dimensions, run model, and how to benchmark a new version.
182
182
  ## Contributors
183
183
 
184
184
  The published `mandrel` package ships three directories — `.agents/`, `bin/`,
185
- and `lib/` (see the `files` array in [`package.json`](package.json)).
185
+ and `lib/` plus the single file `docs/CHANGELOG.md`, and excludes the
186
+ `__tests__` subtrees under `.agents/` and `lib/` (see the `files` array in
187
+ [`package.json`](package.json)).
186
188
  `.agents/` is the payload `mandrel sync` materializes into a consumer's
187
189
  `./.agents/` directory; `bin/mandrel.js` and its `lib/` implementation stay
188
190
  inside `node_modules/mandrel/` and back the `npx mandrel …` CLI used
@@ -193,8 +195,8 @@ tooling and is not published.
193
195
  Common commands while developing the framework itself:
194
196
 
195
197
  ```bash
196
- npm run lint # markdown + biome
197
- npm run format # auto-format
198
+ npm run lint # biome + markdownlint + repo ratchets + generated-doc drift
199
+ npm run format # biome format — JavaScript/JSON only, not markdown
198
200
  npm test # framework tests
199
201
  npm run test:coverage # tests with coverage gate
200
202
  ```
@@ -226,9 +228,14 @@ against malicious lifecycle scripts in compromised transitive packages
226
228
  install scripts for a specific install, run
227
229
  `npm install --ignore-scripts=false` for that invocation only.
228
230
 
229
- CRAP and Maintainability gates fire at three sites — close-validation
230
- (story close), `.husky/pre-push`, and CI (`ci.yml`, push + PR) — against
231
- the same thresholds from `delivery.quality.*` in `.agentrc.json`.
231
+ CRAP and Maintainability gates fire at four sites — `.husky/pre-commit`
232
+ (`quality-preview.js --staged`, scored on the staged index), `.husky/pre-push`
233
+ (diff-scoped against `origin/main`), close-validation (story close), and CI
234
+ (`ci.yml`, push + PR) — against the same thresholds from
235
+ `delivery.quality.*` in `.agentrc.json`. All four are **blocking**: the
236
+ pre-commit hook fires earliest and refuses the commit on a threshold
237
+ violation, and a green `npm run lint` / `npm test` / `check-baselines.js`
238
+ run does not predict it.
232
239
 
233
240
  ## License
234
241
 
package/docs/CHANGELOG.md CHANGED
@@ -2,6 +2,70 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ <!--
6
+ Machine-generated by release-please (`changelog-path` in
7
+ `release-please-config.json`); only the header above is hand-owned — every
8
+ release prepends a section beneath it. The three rules below are properties
9
+ of conventional-changelog-writer's output, not of this repository's prose
10
+ style: `*` list markers (MD004), a double blank line before each `###`
11
+ section (MD012), and `*`-wrapped commit subjects that read as unbalanced
12
+ emphasis (MD037). They would be reintroduced on every release cut, failing
13
+ lint on release-please's own PR, so they are exempted file-wide rather than
14
+ hand-repaired. Do not extend this list to cover hand-written prose defects.
15
+ -->
16
+ <!-- markdownlint-disable-file MD004 MD012 MD037 -->
17
+
18
+ ## [2.26.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.25.0...mandrel-v2.26.0) (2026-08-03)
19
+
20
+
21
+ ### Added
22
+
23
+ * /audit-baselines lens: ratchet-tightening audit workflow over the committed baseline surface ([#4903](https://github.com/dsj1984/mandrel/issues/4903)) ([#4913](https://github.com/dsj1984/mandrel/issues/4913)) ([420fb09](https://github.com/dsj1984/mandrel/commit/420fb09df605edfd8ace86e6b2295c7bd6909c3f))
24
+ * **acceptance-eval:** merge parallel cluster verdicts into one gate call per round (refs [#4951](https://github.com/dsj1984/mandrel/issues/4951)) ([#4954](https://github.com/dsj1984/mandrel/issues/4954)) ([56b69dd](https://github.com/dsj1984/mandrel/commit/56b69dde0a5faee418d5f49f4b0c3eab5f682245))
25
+ * **audit:** add the read-only baseline hotspot engine (refs [#4902](https://github.com/dsj1984/mandrel/issues/4902)) ([#4910](https://github.com/dsj1984/mandrel/issues/4910)) ([22a2245](https://github.com/dsj1984/mandrel/commit/22a22458645823705a2cfcf94ea6d1a7acb4546e))
26
+ * **deliver:** accept dash ranges in delivery Story-id lists (refs [#4927](https://github.com/dsj1984/mandrel/issues/4927)) ([#4928](https://github.com/dsj1984/mandrel/issues/4928)) ([9000044](https://github.com/dsj1984/mandrel/commit/90000442d5f578a4895b5950784e2fb8493d316a))
27
+ * **deliver:** add --merge-watch-mode and mandate one-turn fan-out dispatch (refs [#4949](https://github.com/dsj1984/mandrel/issues/4949)) ([#4957](https://github.com/dsj1984/mandrel/issues/4957)) ([fa1c426](https://github.com/dsj1984/mandrel/commit/fa1c426c181cb3696b4ea34166c99719cea877c2))
28
+ * make the coverage instrument measure: widen CI's run to every test tier, configure the gate, and reseed the baseline ([#4922](https://github.com/dsj1984/mandrel/issues/4922)) ([#4931](https://github.com/dsj1984/mandrel/issues/4931)) ([bc94fbf](https://github.com/dsj1984/mandrel/commit/bc94fbf65b41d53098606aff7f7b58dc1679ea5d))
29
+ * repair the inert quality instruments and tighten the ratchets behind the reclaimed slack ([#4923](https://github.com/dsj1984/mandrel/issues/4923)) ([#4933](https://github.com/dsj1984/mandrel/issues/4933)) ([3cc3a30](https://github.com/dsj1984/mandrel/commit/3cc3a30b5e54b3dac78649dd9536ad617086ee0c))
30
+ * retire friction-event.schema.json or wire it, and stop four docs citing a schema nothing compiles ([#4938](https://github.com/dsj1984/mandrel/issues/4938)) ([#4941](https://github.com/dsj1984/mandrel/issues/4941)) ([259f6e6](https://github.com/dsj1984/mandrel/commit/259f6e6cc47db88434b0612aa9327638afb73911))
31
+ * retire the memory-freshness scanner and ship the visible memory-hygiene loop ([#4919](https://github.com/dsj1984/mandrel/issues/4919)) ([#4921](https://github.com/dsj1984/mandrel/issues/4921)) ([54cf87c](https://github.com/dsj1984/mandrel/commit/54cf87c1a4e929681f194fc899decb24636bd5f2))
32
+
33
+
34
+ ### Fixed
35
+
36
+ * **baselines:** settle the exit through runAsCli so a piped report is not truncated ([#4932](https://github.com/dsj1984/mandrel/issues/4932)) ([d3670de](https://github.com/dsj1984/mandrel/commit/d3670dec493c2ba60a60e365c1ab809bde58ce43)), closes [#4783](https://github.com/dsj1984/mandrel/issues/4783)
37
+ * close three harness gaps: unbounded CI jobs, divergent runner flags, and inert pretest hooks ([#4936](https://github.com/dsj1984/mandrel/issues/4936)) ([#4942](https://github.com/dsj1984/mandrel/issues/4942)) ([d71040d](https://github.com/dsj1984/mandrel/commit/d71040dc0b558906a42327dcd9bd88ccfc26694c))
38
+ * exclude transpiled-coordinate rows from the 0%-coverage fill, and refuse a baseline that predates provenance stamping ([#4901](https://github.com/dsj1984/mandrel/issues/4901)) ([#4905](https://github.com/dsj1984/mandrel/issues/4905)) ([adc135b](https://github.com/dsj1984/mandrel/commit/adc135b3338550e2911e7139d638be8670eb5bab))
39
+ * **friction:** refuse a quoted --cmd as a usage error and split ENOBUFS from timeout (refs [#4915](https://github.com/dsj1984/mandrel/issues/4915)) ([#4918](https://github.com/dsj1984/mandrel/issues/4918)) ([64989aa](https://github.com/dsj1984/mandrel/commit/64989aa4a5cf746d959b649e760bf93f96f2ead0))
40
+ * **git:** give the git runners an explicit 64 MB stdout ceiling, unblocking Story close ([#4953](https://github.com/dsj1984/mandrel/issues/4953)) ([75160a4](https://github.com/dsj1984/mandrel/commit/75160a491704acc2de127d9135bcfcbc846bdfee))
41
+ * give the raised GitHub write fan-outs transient-retry backoff and single-source their concurrency bound ([#4961](https://github.com/dsj1984/mandrel/issues/4961)) ([#4964](https://github.com/dsj1984/mandrel/issues/4964)) ([459a3f1](https://github.com/dsj1984/mandrel/commit/459a3f12da0280881b757c0855d33d0a89221320))
42
+ * let a dangling-citation anchor count inside a code span (refs [#4906](https://github.com/dsj1984/mandrel/issues/4906)) ([#4911](https://github.com/dsj1984/mandrel/issues/4911)) ([a96ae9f](https://github.com/dsj1984/mandrel/commit/a96ae9fbed4b701ff45d13e268d91e960ebbe595))
43
+ * **lint:** lint docs/ so the gate matches the code-review lens ([#4971](https://github.com/dsj1984/mandrel/issues/4971)) ([b1f4e65](https://github.com/dsj1984/mandrel/commit/b1f4e6551670f145fa6f6e688a16130e8da644d7))
44
+ * make git hooks fire in linked worktrees and stop bypassing pre-push at close ([#4943](https://github.com/dsj1984/mandrel/issues/4943)) ([#4946](https://github.com/dsj1984/mandrel/issues/4946)) ([2ac0597](https://github.com/dsj1984/mandrel/commit/2ac05979241ca2ad061e14fbeda2b71c1b299da7))
45
+ * make the ratchet trend roll-up count what it measures and baseline staleness commit-aware ([#4962](https://github.com/dsj1984/mandrel/issues/4962)) ([#4967](https://github.com/dsj1984/mandrel/issues/4967)) ([fff36bf](https://github.com/dsj1984/mandrel/commit/fff36bf79ab4c75a2f4274c60228ab0942ded65a))
46
+ * **observability:** attribute terminal friction to the emitting CLI ([#4966](https://github.com/dsj1984/mandrel/issues/4966)) ([5aa986a](https://github.com/dsj1984/mandrel/commit/5aa986aaee97e858329ab8f948a1a59db8aeb1c4))
47
+ * **observability:** classify a bare framework-script basename as framework (refs [#4916](https://github.com/dsj1984/mandrel/issues/4916)) ([#4920](https://github.com/dsj1984/mandrel/issues/4920)) ([a8e0bbc](https://github.com/dsj1984/mandrel/commit/a8e0bbc22ad1cc8e0ab3ce117e597c537be96d7c))
48
+ * **plan-persist:** re-carry audit provenance onto dependent Stories (refs [#4935](https://github.com/dsj1984/mandrel/issues/4935)) ([#4939](https://github.com/dsj1984/mandrel/issues/4939)) ([6866b0c](https://github.com/dsj1984/mandrel/commit/6866b0c368de0ff438b565d5049a38273b56ef8c))
49
+ * **quality:** key anonymous CRAP methods by enclosing scope, not escomplex ordinal (refs [#4969](https://github.com/dsj1984/mandrel/issues/4969)) ([#4970](https://github.com/dsj1984/mandrel/issues/4970)) ([ca5da99](https://github.com/dsj1984/mandrel/commit/ca5da9940da57aaf20d34844afa835f6a8b127f0))
50
+ * read prior baseline rows per kind so duplication's diff-scope preservation and epsilon damping actually work ([#4937](https://github.com/dsj1984/mandrel/issues/4937)) ([#4940](https://github.com/dsj1984/mandrel/issues/4940)) ([e7d13b5](https://github.com/dsj1984/mandrel/commit/e7d13b551fb958c38833a7946785929dd17907a3))
51
+ * retune the advisory Spec word budget to 350 and repair its report channel (refs [#4907](https://github.com/dsj1984/mandrel/issues/4907)) ([#4909](https://github.com/dsj1984/mandrel/issues/4909)) ([3c914ba](https://github.com/dsj1984/mandrel/commit/3c914ba9430743f2e5399ded6ac74aee4c4148d1))
52
+ * **scripts:** make --help short-circuit before check-test-temp-hygiene does work ([#4968](https://github.com/dsj1984/mandrel/issues/4968)) ([5e873ac](https://github.com/dsj1984/mandrel/commit/5e873acbc316a37e5a173a94bb2fe52090614493))
53
+ * stop check-baselines silently disabling its compare arm when the base baseline cannot be read ([#4914](https://github.com/dsj1984/mandrel/issues/4914)) ([#4917](https://github.com/dsj1984/mandrel/issues/4917)) ([d62a334](https://github.com/dsj1984/mandrel/commit/d62a334555bccd605bd37bd9d8a544fdcc4e3710))
54
+ * stop the git-cleanup branches phase announcing a DRY RUN before it deletes ([#4898](https://github.com/dsj1984/mandrel/issues/4898)) ([3edad1e](https://github.com/dsj1984/mandrel/commit/3edad1e8c9a8906c1abc5f02e79e7ee4792775b2))
55
+ * **wave-runner:** exempt glob footprints from cross-beat reservation (refs [#4960](https://github.com/dsj1984/mandrel/issues/4960)) ([#4963](https://github.com/dsj1984/mandrel/issues/4963)) ([ca935e2](https://github.com/dsj1984/mandrel/commit/ca935e223f211340c671668a53738de634c12c04))
56
+ * **wave-runner:** reserve in-flight Story footprints in the ready-set guard (refs [#4950](https://github.com/dsj1984/mandrel/issues/4950)) ([#4955](https://github.com/dsj1984/mandrel/issues/4955)) ([7f8ffb3](https://github.com/dsj1984/mandrel/commit/7f8ffb31c523dba01fb9cffe376a5149d92d7c08))
57
+
58
+
59
+ ### Performance
60
+
61
+ * **plan:** run the /plan path's independent gathers and write loops concurrently (refs [#4952](https://github.com/dsj1984/mandrel/issues/4952)) ([#4956](https://github.com/dsj1984/mandrel/issues/4956)) ([8c8ec6c](https://github.com/dsj1984/mandrel/commit/8c8ec6c1134f23fbf8214d138438b3febc6014c8))
62
+
63
+
64
+ ### Changed
65
+
66
+ * **baselines:** migrate the duplication CLI onto refreshBaseline (refs [#4944](https://github.com/dsj1984/mandrel/issues/4944)) ([#4945](https://github.com/dsj1984/mandrel/issues/4945)) ([38e43d2](https://github.com/dsj1984/mandrel/commit/38e43d2362031cfaebbfeeaa8bec75c3c5ecf56b))
67
+ * burn down the cross-gate hotspot clusters and remove the shipped seams nothing calls ([#4926](https://github.com/dsj1984/mandrel/issues/4926)) ([#4934](https://github.com/dsj1984/mandrel/issues/4934)) ([970c7f8](https://github.com/dsj1984/mandrel/commit/970c7f88f5d198b685f90ede5358beea5b2896ce))
68
+
5
69
  ## [2.25.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.24.0...mandrel-v2.25.0) (2026-08-01)
6
70
 
7
71
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mandrel",
3
- "version": "2.25.0",
3
+ "version": "2.26.0",
4
4
  "description": "Claude Code-first opinionated workflow framework: instructions, skills, rules, and SDLC workflows that govern AI coding assistants.",
5
5
  "files": [
6
6
  ".agents/",
@@ -15,9 +15,7 @@
15
15
  "provenance": true
16
16
  },
17
17
  "scripts": {
18
- "pretest": "node .agents/scripts/test-wrapper.js && node .agents/scripts/validate-skills.js",
19
- "pretest:quick": "node .agents/scripts/test-wrapper.js",
20
- "pretest:integration": "node .agents/scripts/test-wrapper.js",
18
+ "//test-preflight": "There are deliberately NO pretest* scripts (Story #4936). .npmrc sets ignore-scripts=true as supply-chain defence (CWE-1357), and that suppresses every pre*/post* lifecycle script for `npm run` too — so a pretest entry here would look like a gate and never execute. Each tier's preflight is declared once in .agents/scripts/lib/test-runner-contract.js and invoked by the runners themselves, which is why it fires for `npm test`, `npm run test:coverage` and a bare `node .agents/scripts/run-tests.js` alike.",
21
19
  "test": "node .agents/scripts/run-tests.js",
22
20
  "test:quick": "node .agents/scripts/run-tests.js --tier quick",
23
21
  "test:integration": "node .agents/scripts/run-tests.js --tier integration",
@@ -28,6 +26,7 @@
28
26
  "test:coverage": "node .agents/scripts/run-coverage.js",
29
27
  "coverage:check": "node .agents/scripts/check-baselines.js --gate coverage",
30
28
  "coverage:update": "node .agents/scripts/update-coverage-baseline.js",
29
+ "coverage:reanchor": "node .agents/scripts/update-coverage-baseline.js --full-scope",
31
30
  "baseline:agents-loc": "node baselines/agents-loc-baseline.mjs",
32
31
  "lint:md": "markdownlint-cli2 \".agents/**/*.md\" \"*.md\" \"!node_modules/**\" \"!.worktrees/**\"",
33
32
  "lint": "node .agents/scripts/run-lint.js && npm run docs:check",
@@ -39,13 +38,19 @@
39
38
  "format:check": "biome ci .",
40
39
  "maintainability:check": "node .agents/scripts/check-baselines.js --gate maintainability",
41
40
  "maintainability:update": "node .agents/scripts/update-maintainability-baseline.js",
41
+ "maintainability:reanchor": "node .agents/scripts/update-maintainability-baseline.js --full-scope",
42
42
  "check:arch": "node .agents/scripts/check-arch-cycles.js",
43
43
  "check:context-budget": "node .agents/scripts/check-context-budget.js",
44
+ "check:cyclomatic": "node .agents/scripts/check-cyclomatic.js",
45
+ "cyclomatic:update": "node .agents/scripts/check-cyclomatic.js --update",
46
+ "check:schema-refs": "node .agents/scripts/check-schema-references.js",
44
47
  "check:workflow-citations": "node .agents/scripts/check-workflow-citations.js",
45
48
  "crap:check": "node .agents/scripts/check-baselines.js --gate crap",
46
49
  "crap:update": "node .agents/scripts/update-crap-baseline.js",
50
+ "crap:reanchor": "node .agents/scripts/update-crap-baseline.js --full-scope",
47
51
  "duplication:check": "node .agents/scripts/check-baselines.js --gate duplication",
48
52
  "duplication:update": "node .agents/scripts/update-duplication-baseline.js",
53
+ "duplication:reanchor": "node .agents/scripts/update-duplication-baseline.js --full-scope",
49
54
  "quality:preview": "node .agents/scripts/check-dead-exports.js && node .agents/scripts/quality-preview.js",
50
55
  "quality:watch": "node .agents/scripts/quality-watch.js",
51
56
  "sync:commands": "node bin/mandrel.js sync-commands",
@@ -1,56 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "title": "FrictionEvent",
4
- "type": "object",
5
- "additionalProperties": false,
6
- "properties": {
7
- "eventId": {
8
- "type": "string",
9
- "format": "uuid"
10
- },
11
- "timestamp": {
12
- "type": "string",
13
- "format": "date-time"
14
- },
15
- "sprintId": {
16
- "type": "string"
17
- },
18
- "category": {
19
- "type": "string",
20
- "enum": [
21
- "Prompt Ambiguity",
22
- "Missing Skill",
23
- "Incorrect Persona",
24
- "Tool Limitation",
25
- "Execution Error"
26
- ]
27
- },
28
- "source": {
29
- "type": "object",
30
- "additionalProperties": false,
31
- "properties": {
32
- "tool": {
33
- "type": "string"
34
- },
35
- "command": {
36
- "type": "string"
37
- }
38
- }
39
- },
40
- "details": {
41
- "type": "string",
42
- "description": "Specific error message or observation."
43
- },
44
- "context": {
45
- "type": "object",
46
- "additionalProperties": false,
47
- "properties": {
48
- "protocolFile": {
49
- "type": "string",
50
- "description": "Path to relevant protocol file, e.g., '.agents/skills/core/tdd.md'"
51
- }
52
- }
53
- }
54
- },
55
- "required": ["eventId", "timestamp", "sprintId", "category", "details"]
56
- }