mandrel 2.24.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.
- package/.agents/agents/acceptance-critic.md +19 -21
- package/.agents/agents/auditor.md +16 -19
- package/.agents/agents/story-worker.md +41 -54
- package/.agents/audit-checklists/architecture.md +5 -1
- package/.agents/audit-checklists/baselines.md +21 -0
- package/.agents/audit-checklists/quality.md +3 -0
- package/.agents/docs/agentrc-reference.json +2 -1
- package/.agents/docs/configuration.md +2 -1
- package/.agents/docs/quality-gates.md +80 -18
- package/.agents/docs/workflows.md +4 -2
- package/.agents/instructions.md +1 -1
- package/.agents/rules/ci-remediation.md +68 -3
- package/.agents/schemas/agentrc.schema.json +6 -1
- package/.agents/schemas/audit-rules.json +15 -0
- package/.agents/schemas/baselines/audit-baselines-envelope.schema.json +242 -0
- package/.agents/schemas/baselines/baseline-envelope.schema.json +8 -0
- package/.agents/schemas/baselines/crap.schema.json +13 -1
- package/.agents/schemas/crap-report.schema.json +37 -0
- package/.agents/schemas/model-attribution.schema.json +4 -0
- package/.agents/scripts/acceptance-eval.js +124 -15
- package/.agents/scripts/audit-baselines.js +136 -0
- package/.agents/scripts/audit-labels-bootstrap.js +16 -95
- package/.agents/scripts/audit-to-stories.js +33 -3
- package/.agents/scripts/check-arch-cycles.js +12 -93
- package/.agents/scripts/check-baseline-drift.js +16 -3
- package/.agents/scripts/check-baselines.js +19 -3
- package/.agents/scripts/check-context-budget.js +95 -14
- package/.agents/scripts/check-cyclomatic.js +214 -0
- package/.agents/scripts/check-schema-references.js +392 -0
- package/.agents/scripts/check-test-temp-hygiene.js +121 -1
- package/.agents/scripts/check-workflow-timeouts.js +291 -0
- package/.agents/scripts/cleanup-repo-test-temp.js +7 -5
- package/.agents/scripts/deliver-light.js +3 -4
- package/.agents/scripts/deliver-recover.js +13 -0
- package/.agents/scripts/diagnose-friction.js +85 -19
- package/.agents/scripts/lib/audit-baselines/engine.js +177 -0
- package/.agents/scripts/lib/audit-baselines/gate-surface.js +63 -0
- package/.agents/scripts/lib/audit-baselines/headroom.js +72 -0
- package/.agents/scripts/lib/audit-baselines/hotspots.js +69 -0
- package/.agents/scripts/lib/audit-baselines/kinds.js +313 -0
- package/.agents/scripts/lib/audit-baselines/outliers.js +100 -0
- package/.agents/scripts/lib/audit-baselines/read.js +87 -0
- package/.agents/scripts/lib/audit-baselines/staleness.js +123 -0
- package/.agents/scripts/lib/audit-baselines/surface-entry.js +106 -0
- package/.agents/scripts/lib/audit-baselines/trend.js +125 -0
- package/.agents/scripts/lib/audit-baselines/weights.js +193 -0
- package/.agents/scripts/lib/audit-suite/index.js +0 -5
- package/.agents/scripts/lib/audit-suite/selector.js +9 -62
- package/.agents/scripts/lib/audit-to-stories/audit-label-taxonomy.js +177 -0
- package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +1 -0
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +35 -3
- package/.agents/scripts/lib/audit-to-stories/group-findings.js +20 -11
- package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +23 -9
- package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +9 -2
- package/.agents/scripts/lib/baseline-loader.js +0 -0
- package/.agents/scripts/lib/baseline-schema-registry.js +13 -1
- package/.agents/scripts/lib/baselines/diff-scope-cli.js +22 -160
- package/.agents/scripts/lib/baselines/duplication-scanner.js +27 -0
- package/.agents/scripts/lib/baselines/git-base.js +0 -0
- package/.agents/scripts/lib/baselines/kinds/crap.js +499 -57
- package/.agents/scripts/lib/baselines/preview-gates.js +58 -15
- package/.agents/scripts/lib/baselines/reader.js +10 -0
- package/.agents/scripts/lib/baselines/refresh-service.js +69 -11
- package/.agents/scripts/lib/baselines/scope.js +39 -90
- package/.agents/scripts/lib/baselines/writer.js +16 -7
- package/.agents/scripts/lib/changed-files.js +8 -1
- package/.agents/scripts/lib/cli-args.js +115 -1
- package/.agents/scripts/lib/close-validation/runner.js +70 -25
- package/.agents/scripts/lib/config-settings-schema-delivery.js +5 -0
- package/.agents/scripts/lib/crap-engine.js +124 -27
- package/.agents/scripts/lib/crap-method-identity.js +153 -0
- package/.agents/scripts/lib/crap-utils.js +86 -13
- package/.agents/scripts/lib/cyclomatic-ceiling.js +265 -0
- package/.agents/scripts/lib/env-loader.js +46 -16
- package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +0 -2
- package/.agents/scripts/lib/feedback-loop/prior-feedback-fetcher.js +0 -2
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +0 -2
- package/.agents/scripts/lib/findings/route-finding.js +123 -17
- package/.agents/scripts/lib/findings/severity.js +80 -2
- package/.agents/scripts/lib/git/cached-fetch.js +0 -0
- package/.agents/scripts/lib/git-utils.js +136 -80
- package/.agents/scripts/lib/import-graph.js +156 -0
- package/.agents/scripts/lib/label-constants.js +17 -0
- package/.agents/scripts/lib/observability/runtime-friction.js +17 -2
- package/.agents/scripts/lib/observability/source-classifier.js +175 -2
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +110 -17
- package/.agents/scripts/lib/orchestration/ceremony-routing.js +17 -12
- package/.agents/scripts/lib/orchestration/check-baselines/phases/compare.js +36 -6
- package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +5 -0
- package/.agents/scripts/lib/orchestration/check-baselines/phases/floors.js +12 -1
- package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +8 -1
- package/.agents/scripts/lib/orchestration/ci-rerun-guard.js +548 -0
- package/.agents/scripts/lib/orchestration/deliver-recover.js +2 -2
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/phase-drivers.js +10 -5
- package/.agents/scripts/lib/orchestration/git-cleanup/phases/render.js +39 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/watcher.js +71 -20
- package/.agents/scripts/lib/orchestration/light-backstop.js +20 -3
- package/.agents/scripts/lib/orchestration/light-escalation.js +82 -3
- package/.agents/scripts/lib/orchestration/light-suitability.js +103 -5
- package/.agents/scripts/lib/orchestration/plan-context.js +119 -66
- package/.agents/scripts/lib/orchestration/plan-persist/fan-out-gate.js +31 -5
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +216 -109
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +61 -13
- package/.agents/scripts/lib/orchestration/plan-persist/supersede-ops.js +79 -22
- package/.agents/scripts/lib/orchestration/plan-text-hygiene.js +51 -20
- package/.agents/scripts/lib/orchestration/planning/authoring-context.js +70 -74
- package/.agents/scripts/lib/orchestration/planning/memory-pool-advisory.js +231 -0
- package/.agents/scripts/lib/orchestration/resolve-stories.js +18 -17
- package/.agents/scripts/lib/orchestration/retro-proposals.js +0 -0
- package/.agents/scripts/lib/orchestration/run-epilogue.js +12 -0
- package/.agents/scripts/lib/orchestration/run-scoped-config.js +276 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/base-sync.js +41 -10
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +125 -37
- package/.agents/scripts/lib/orchestration/single-story-close/phases/normalize-pr-title.js +6 -6
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +42 -38
- package/.agents/scripts/lib/orchestration/single-story-close/phases/pull-request.js +129 -21
- package/.agents/scripts/lib/orchestration/single-story-close/phases/push.js +6 -1
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +267 -125
- package/.agents/scripts/lib/orchestration/spec-budget.js +16 -5
- package/.agents/scripts/lib/orchestration/story-follow-ups.js +182 -95
- package/.agents/scripts/lib/orchestration/ticket-validator-conflicts.js +22 -0
- package/.agents/scripts/lib/orchestration/ticket-validator.js +5 -11
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +4 -4
- package/.agents/scripts/lib/reserved-test-ids.js +77 -0
- package/.agents/scripts/lib/story-adjacency.js +3 -3
- package/.agents/scripts/lib/story-plan.js +137 -42
- package/.agents/scripts/lib/templates/decomposer-prompts.js +4 -4
- package/.agents/scripts/lib/test-runner-contract.js +134 -0
- package/.agents/scripts/lib/test-tiers.js +11 -2
- package/.agents/scripts/lib/ticket-body-sections.js +1 -1
- package/.agents/scripts/lib/util/concurrent-map.js +17 -0
- package/.agents/scripts/lib/util/parse-id-list.js +103 -0
- package/.agents/scripts/lib/util/poll-loop.js +18 -2
- package/.agents/scripts/lib/wave-runner/live-probe.js +29 -13
- package/.agents/scripts/lib/wave-runner/ready-set.js +254 -43
- package/.agents/scripts/lib/workers/combined-mi-crap-worker.js +10 -13
- package/.agents/scripts/lib/workers/crap-worker.js +8 -13
- package/.agents/scripts/lib/workers/maintainability-report-worker.js +4 -10
- package/.agents/scripts/lib/workers/maintainability-worker.js +4 -10
- package/.agents/scripts/lib/workers/serve-worker-messages.js +35 -0
- package/.agents/scripts/lib/worktree/git-hooks.js +206 -0
- package/.agents/scripts/lib/worktree/lifecycle/creation.js +6 -0
- package/.agents/scripts/lib/worktree-manager.js +14 -0
- package/.agents/scripts/plan-run-epilogue.js +17 -5
- package/.agents/scripts/pr-watch-with-update.js +568 -213
- package/.agents/scripts/providers/github/tickets.js +33 -10
- package/.agents/scripts/provision-git-hooks.js +85 -0
- package/.agents/scripts/quality-preview.js +137 -28
- package/.agents/scripts/resolve-stories.js +4 -1
- package/.agents/scripts/run-coverage.js +86 -35
- package/.agents/scripts/run-lint.js +20 -0
- package/.agents/scripts/run-tests.js +36 -36
- package/.agents/scripts/single-story-close.js +34 -2
- package/.agents/scripts/single-story-confirm-merge.js +22 -6
- package/.agents/scripts/single-story-init.js +7 -0
- package/.agents/scripts/stories-wave-tick.js +308 -47
- package/.agents/scripts/story-plan.js +65 -9
- package/.agents/scripts/update-coverage-baseline.js +34 -4
- package/.agents/scripts/update-crap-baseline.js +42 -4
- package/.agents/scripts/update-duplication-baseline.js +209 -83
- package/.agents/scripts/update-maintainability-baseline.js +31 -4
- package/.agents/scripts/validate-docs-freshness.js +1 -0
- package/.agents/skills/core/diagnose-friction/SKILL.md +4 -1
- package/.agents/skills/core/gates-and-baselines/SKILL.md +17 -11
- package/.agents/skills/skills.index.json +2 -2
- package/.agents/templates/single-story-body.md +16 -8
- package/.agents/workflows/audit-architecture.md +69 -13
- package/.agents/workflows/audit-baselines.md +289 -0
- package/.agents/workflows/audit-navigability.md +5 -4
- package/.agents/workflows/audit-quality.md +26 -0
- package/.agents/workflows/audit-to-stories.md +30 -4
- package/.agents/workflows/deliver.md +92 -97
- package/.agents/workflows/helpers/acceptance-self-eval.md +47 -10
- package/.agents/workflows/helpers/audit-lens-core.md +25 -4
- package/.agents/workflows/helpers/code-quality-guardrails.md +9 -2
- package/.agents/workflows/helpers/deliver-digest.md +41 -21
- package/.agents/workflows/helpers/deliver-reference.md +95 -4
- package/.agents/workflows/helpers/deliver-story-reference.md +174 -52
- package/.agents/workflows/helpers/deliver-story.md +104 -119
- package/.agents/workflows/helpers/plan-reference.md +49 -5
- package/.agents/workflows/memory-consolidate.md +116 -0
- package/.agents/workflows/plan.md +62 -75
- package/README.md +13 -6
- package/docs/CHANGELOG.md +93 -0
- package/lib/cli/update.js +14 -11
- package/lib/cli/version-check.js +9 -1
- package/package.json +9 -4
- package/.agents/schemas/friction-event.schema.json +0 -56
- package/.agents/scripts/lib/feedback-loop/memory-freshness.js +0 -707
|
@@ -7,47 +7,43 @@ description:
|
|
|
7
7
|
|
|
8
8
|
# /plan
|
|
9
9
|
|
|
10
|
-
> **Lean spine.** Happy path + gate list; edge-case detail lives
|
|
10
|
+
> **Lean spine.** Happy path + gate list; edge-case detail lives on demand in
|
|
11
11
|
> [`helpers/plan-reference.md`](helpers/plan-reference.md).
|
|
12
12
|
|
|
13
13
|
## Inputs
|
|
14
14
|
|
|
15
15
|
Single planning path — there is no Epic/Story router, no scope-triage
|
|
16
16
|
`epic|story` verdict. **Derive the mode from what the operator typed, announce
|
|
17
|
-
it,
|
|
17
|
+
it, act**:
|
|
18
18
|
|
|
19
19
|
| Invocation | Mode | Behavior |
|
|
20
20
|
| --- | --- | --- |
|
|
21
21
|
| `/plan` | ask | Ask what to plan; nothing runs first. |
|
|
22
|
-
| `/plan add a --json flag to doctor` | seed | Ideation from
|
|
23
|
-
| `/plan temp/notes/idea.md` | seed-file | Same, from notes. An
|
|
22
|
+
| `/plan add a --json flag to doctor` | seed | Ideation from prose: interrogate → author **one Story by default** → persist. |
|
|
23
|
+
| `/plan temp/notes/idea.md` | seed-file | Same, from notes. An existing file is a path, not prose. |
|
|
24
24
|
| `/plan 4712[,4713…]` | tickets | Fetch issue(s), analyze into proper Stories (prefer N=1 rewrite). |
|
|
25
25
|
| `/plan 4712`, already delivered | amends | Amend a shipped Story from a **delta envelope**, not a re-interrogation. |
|
|
26
26
|
|
|
27
27
|
**Resolving a bare id.** Read live state rather than asking: `agent::done` can
|
|
28
28
|
only be amended, an open unplanned issue can only be planned. **Announce the
|
|
29
|
-
derivation** — "4712 is `agent::done` → amending"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
`--body` is **not** a `/plan` entry; persist goes through `plan-persist.js`.
|
|
29
|
+
derivation** — "4712 is `agent::done` → amending". Ask **only** for an open
|
|
30
|
+
Story already at `agent::ready`.
|
|
33
31
|
|
|
34
32
|
## Saying what you want
|
|
35
33
|
|
|
36
|
-
No flags to remember — state intent
|
|
37
|
-
([reference](helpers/plan-reference.md)). Run
|
|
38
|
-
than copying its surface here.
|
|
34
|
+
No flags to remember — state intent; the workflow fills in the CLI
|
|
35
|
+
([reference](helpers/plan-reference.md)). Run scripts with `--help`.
|
|
39
36
|
|
|
40
37
|
`--yes` is **runner-set, never operator-typed** — cron, `/loop`, and headless
|
|
41
|
-
dispatch set it to mean *nobody is at the keyboard*, which
|
|
42
|
-
|
|
38
|
+
dispatch set it to mean *nobody is at the keyboard*, which auto-proceeds the
|
|
39
|
+
gates below (#1 and #2). Never offer it to an operator or an attended run.
|
|
43
40
|
|
|
44
41
|
## Default-single split policy
|
|
45
42
|
|
|
46
43
|
Author **one Story** unless the pieces have **near-zero overlap** or sit across
|
|
47
|
-
an **architectural seam
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
(`assertAcceptancePartition` refuses coupled splits). **N=1 is the lean path.**
|
|
44
|
+
an **architectural seam**. Coupled work stays one Story — `## Slicing`
|
|
45
|
+
checkpoints, not sibling tickets
|
|
46
|
+
([detail](helpers/plan-reference.md)). **N=1 is lean.**
|
|
51
47
|
|
|
52
48
|
## Procedure
|
|
53
49
|
|
|
@@ -63,54 +59,49 @@ node .agents/scripts/plan-context.js --seed "<seed>" \
|
|
|
63
59
|
and derives source ids from its `sourceTickets[]`; the CLI also writes
|
|
64
60
|
**`stories.template.json`**, step 2's skeleton.
|
|
65
61
|
|
|
66
|
-
The envelope carries docs context, the story-author
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
**Triage each unknown by resolver**
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
only HITL unknowns land in Key Assumptions, each marked a
|
|
62
|
+
The envelope carries docs context, the story-author prompt, `sourceTickets[]`,
|
|
63
|
+
`duplicates[]` (open **Stories**, never Epics) and advisory `complexitySignals`
|
|
64
|
+
(**no routing authority**). A trivial scope can claim the lite route at
|
|
65
|
+
persist — shape-validated, failing closed to `full`
|
|
66
|
+
([detail](helpers/plan-reference.md)).
|
|
67
|
+
|
|
68
|
+
**Triage each unknown by resolver** ([detail](helpers/plan-reference.md)): an
|
|
69
|
+
**AFK** unknown (research settles it) is resolved before authoring, never
|
|
70
|
+
assumed; a **HITL** unknown (an operator call) goes to Gate #1 as "needs your
|
|
71
|
+
decision". Under `--yes` do not ask free-form operator questions — AFK unknowns
|
|
72
|
+
are still researched; only HITL unknowns land in Key Assumptions, each marked a
|
|
78
73
|
decision-made-by-default.
|
|
79
74
|
|
|
80
75
|
**Gate #1** — STOP to confirm the sharpened plan intent and any
|
|
81
76
|
duplicate-candidate review. Under `--yes`, auto-proceed.
|
|
82
77
|
|
|
83
|
-
On a truthy `
|
|
84
|
-
|
|
85
|
-
planning it. On confirm, route **in this session** into
|
|
86
|
-
[`helpers/deliver-light.md`](helpers/deliver-light.md), filling its gate from
|
|
87
|
-
this envelope, not the raw seed; an `ask-operator` verdict returns here to
|
|
88
|
-
step 2 with the interrogation intact. Under `--yes` it is recorded and planning
|
|
89
|
-
proceeds — never auto-downgraded to light.
|
|
78
|
+
On a truthy `memoryPoolAdvisory.recommend`, name [`/memory-consolidate`](memory-consolidate.md)
|
|
79
|
+
as an operator option, quoting its `reasons[]` — advisory, never invoked here.
|
|
90
80
|
|
|
91
|
-
|
|
92
|
-
|
|
81
|
+
On a truthy `deliverLightSuggestion.suggested`, offer — advisory, never an
|
|
82
|
+
automatic reroute — to deliver the seed instead; on confirm, route **in this
|
|
83
|
+
session** into [`helpers/deliver-light.md`](helpers/deliver-light.md), its gate
|
|
84
|
+
filled from this envelope. A truthy `complexitySignals.uiSurface` marks a
|
|
85
|
+
UI-touching plan: name [`/prototype`](prototype.md) as an operator option,
|
|
86
|
+
never invoke it here. [Both offers](helpers/plan-reference.md).
|
|
93
87
|
|
|
94
88
|
### 2. Author
|
|
95
89
|
|
|
96
90
|
**One-shot authoring.** Start from `stories.template.json`; author
|
|
97
|
-
`stories.json` in one pass. `body` is
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
`verify[]` into it — never dual-author those lists.
|
|
101
|
-
|
|
102
|
-
**Grounding = your reads + Phase 8.** Nothing inventories the repo for you:
|
|
103
|
-
read each file you cite, then persist's file-assumption gate hard-errors on
|
|
104
|
-
every `{path, assumption}` that misses the real tree.
|
|
91
|
+
`stories.json` in one pass. `body` is markdown **or** a structured object;
|
|
92
|
+
persist parses either, serializes canonical markdown and syncs top-level
|
|
93
|
+
`acceptance[]` / `verify[]` into it — never dual-author those lists.
|
|
105
94
|
|
|
106
|
-
|
|
95
|
+
**Grounding = your reads + Phase 8.** Nothing inventories the repo: read each
|
|
96
|
+
file you cite; persist's file-assumption gate hard-errors on any
|
|
97
|
+
`{path, assumption}` absent from the tree. Entry fields:
|
|
107
98
|
[reference](helpers/plan-reference.md).
|
|
108
99
|
|
|
109
100
|
Artifacts under `temp/plan-<slug>/`: `stories.json` (**length 1 by default**;
|
|
110
|
-
over-budget Specs fail closed — split or tighten, never under `docs/`);
|
|
111
|
-
|
|
112
|
-
`acceptance-manifest.json` (N>1 partition
|
|
113
|
-
|
|
101
|
+
over-budget Specs fail closed — split or tighten, never under `docs/`); optional
|
|
102
|
+
`techspec.md` (**N===1 only** — folded into `## Spec`); optional
|
|
103
|
+
`acceptance-manifest.json` (N>1 partition — `--plan-acceptance`). For N=1 use
|
|
104
|
+
the envelope `systemPrompts.story`; split only under the policy above.
|
|
114
105
|
|
|
115
106
|
**Tickets mode:** every Story authors a top-level `supersedes[]`; persist
|
|
116
107
|
refuses a partial map ([shape](helpers/plan-reference.md)).
|
|
@@ -123,28 +114,27 @@ node .agents/scripts/plan-critics.js \
|
|
|
123
114
|
[--tech-spec temp/plan-<slug>/techspec.md]
|
|
124
115
|
```
|
|
125
116
|
|
|
126
|
-
Run **before** persist — the last point a finding folds into a re-author
|
|
117
|
+
Run **before** persist — the last point a finding folds into a re-author.
|
|
127
118
|
It exits 0 on **any** verdict (verdicts route work, they do not gate) and exits
|
|
128
119
|
**1** only on a usage/IO error — no critic ran, no skip ledgered: **do not
|
|
129
|
-
proceed to Persist
|
|
120
|
+
proceed to Persist**, fix and re-run.
|
|
130
121
|
|
|
131
122
|
- **Both `dispatch: false`** — proceed to Persist (each skip is ledgered).
|
|
132
123
|
- **Either `dispatch: true`** — dispatch **one fresh-context, maker-blind
|
|
133
124
|
sub-agent per firing critic** (hand it only the draft artifacts, never the
|
|
134
125
|
authoring transcript), fold findings into Gate #2 or a re-author round, re-run
|
|
135
126
|
this step. Pre-mortem triggers (incl. the external-dependency probe), the
|
|
136
|
-
advisory-only `textHygiene.findings[]` lints
|
|
137
|
-
[
|
|
127
|
+
advisory-only `textHygiene.findings[]` lints and dispatch shape:
|
|
128
|
+
[reference § Critic dispatch detail](helpers/plan-reference.md).
|
|
138
129
|
|
|
139
130
|
### 3. Persist
|
|
140
131
|
|
|
141
132
|
**Gate #2** — STOP for approval before persist **only** when the operator asked
|
|
142
133
|
to review (`--force-review`). Under `--yes`, auto-proceed.
|
|
143
134
|
|
|
144
|
-
Run persist with `--dry-run` **first** — same command,
|
|
145
|
-
every gate
|
|
146
|
-
|
|
147
|
-
Then:
|
|
135
|
+
Run persist with `--dry-run` **first** — same command, writes suppressed;
|
|
136
|
+
every gate runs before the first `createIssue`
|
|
137
|
+
([the list](helpers/plan-reference.md)):
|
|
148
138
|
|
|
149
139
|
```bash
|
|
150
140
|
node .agents/scripts/plan-persist.js \
|
|
@@ -155,28 +145,25 @@ node .agents/scripts/plan-persist.js \
|
|
|
155
145
|
[--source-tickets 123,456]
|
|
156
146
|
```
|
|
157
147
|
|
|
158
|
-
At lite shape, `--chain-on-clean`
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
Persist creates `type::story` issue(s) plus a `plan-run::<id>` grouping label
|
|
162
|
-
(**metadata only**); N>1 `depends_on` edges become `blocked by #<id>` footers.
|
|
163
|
-
`agent::ready` is the **terminal** flip after all receipts land. stdout is pure
|
|
164
|
-
JSON.
|
|
148
|
+
At lite shape, `--chain-on-clean` folds a clean dry-run into the real persist;
|
|
149
|
+
a full plan keeps its review trip.
|
|
165
150
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
151
|
+
Persist creates `type::story` issue(s), a **metadata-only** `plan-run::<id>`
|
|
152
|
+
label, and `blocked by #<id>` footers for N>1 `depends_on` edges.
|
|
153
|
+
`agent::ready` is the **terminal** flip after receipts land; stdout is pure
|
|
154
|
+
JSON. Tickets mode also comments on and closes each source id
|
|
155
|
+
([detail](helpers/plan-reference.md)).
|
|
169
156
|
|
|
170
157
|
## Constraints
|
|
171
158
|
|
|
172
159
|
- `/plan` starts delivery **only** through a confirmed Gate #1 light route —
|
|
173
160
|
never off its own authored Stories, which land via [`/deliver`](deliver.md).
|
|
174
|
-
- Duplicate search targets open Stories (`type::story`), not Epics
|
|
175
|
-
|
|
161
|
+
- Duplicate search targets open Stories (`type::story`), not Epics; and
|
|
162
|
+
deterministic gates still fail closed under `--yes`.
|
|
176
163
|
|
|
177
164
|
## See also
|
|
178
165
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
166
|
+
[`/deliver`](deliver.md), [`/audit-to-stories`](audit-to-stories.md),
|
|
167
|
+
[`helpers/plan-reference.md`](helpers/plan-reference.md) (on-demand detail),
|
|
168
|
+
[`core/scope-triage`](../skills/core/scope-triage/SKILL.md) — optional
|
|
169
|
+
split-advisory notes only (no routing verdict).
|
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/`
|
|
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 #
|
|
197
|
-
npm run 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
|
|
230
|
-
(
|
|
231
|
-
|
|
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,99 @@
|
|
|
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
|
+
|
|
69
|
+
## [2.25.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.24.0...mandrel-v2.25.0) (2026-08-01)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
### Added
|
|
73
|
+
|
|
74
|
+
* enforce the no-rerun verifier: disarm auto-merge on the first red and gate re-arming on the head SHA moving ([#4865](https://github.com/dsj1984/mandrel/issues/4865)) ([#4867](https://github.com/dsj1984/mandrel/issues/4867)) ([b95267f](https://github.com/dsj1984/mandrel/commit/b95267fe49cd27ca7cd42bb3bc7ae0c6ceaa5a3a))
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### Fixed
|
|
78
|
+
|
|
79
|
+
* **crap:** measure coordinate mixing, not ordinary drift, in the preview gate (refs [#4871](https://github.com/dsj1984/mandrel/issues/4871)) ([#4881](https://github.com/dsj1984/mandrel/issues/4881)) ([63bcb66](https://github.com/dsj1984/mandrel/commit/63bcb66ab46471cfc1b8ad957d60dd1526d0f679))
|
|
80
|
+
* escape the remaining raw NUL delimiters so these diffs are reviewable ([#4896](https://github.com/dsj1984/mandrel/issues/4896)) ([992fc46](https://github.com/dsj1984/mandrel/commit/992fc46b7675736c8fc7af546600cc59ef5ec96d))
|
|
81
|
+
* make the sanctioned CI watch survive a late-arriving required context, and pass --repo through as a real gh flag ([#4890](https://github.com/dsj1984/mandrel/issues/4890)) ([#4893](https://github.com/dsj1984/mandrel/issues/4893)) ([00c23f4](https://github.com/dsj1984/mandrel/commit/00c23f45f57f6b9d11c7314b92f337a31dda4c2b))
|
|
82
|
+
* normalize audit severity and labels without re-minting fingerprints, carry dedupe provenance, and give the lenses a built-but-not-wired mandate ([#4877](https://github.com/dsj1984/mandrel/issues/4877)) ([#4888](https://github.com/dsj1984/mandrel/issues/4888)) ([04f8937](https://github.com/dsj1984/mandrel/commit/04f89373e4dcaa0a47d5501381fb02b5e29bcef6))
|
|
83
|
+
* pin the run's base branch at init and fail closed when config changed mid-run (refs [#4891](https://github.com/dsj1984/mandrel/issues/4891)) ([#4894](https://github.com/dsj1984/mandrel/issues/4894)) ([8099020](https://github.com/dsj1984/mandrel/commit/8099020a9ea2e662c19a1c8a3d9e32d6269df863))
|
|
84
|
+
* **plan:** reconcile the persist body contract and stop acceptance-eval burning a round on every read (refs [#4874](https://github.com/dsj1984/mandrel/issues/4874)) ([#4882](https://github.com/dsj1984/mandrel/issues/4882)) ([33512b4](https://github.com/dsj1984/mandrel/commit/33512b48702e50d9ebaf98dffc396a9ce0091290))
|
|
85
|
+
* ratchet context-budget shrinkage and stop the baseline updaters writing on --help (refs [#4872](https://github.com/dsj1984/mandrel/issues/4872)) ([#4879](https://github.com/dsj1984/mandrel/issues/4879)) ([8d445a4](https://github.com/dsj1984/mandrel/commit/8d445a45e8a4c57b65573213042fb4aec557af08))
|
|
86
|
+
* stamp the version cache with the real clock and end unquoted env values at an unescaped comment marker (refs [#4878](https://github.com/dsj1984/mandrel/issues/4878)) ([#4883](https://github.com/dsj1984/mandrel/issues/4883)) ([d73ee10](https://github.com/dsj1984/mandrel/commit/d73ee10c2f15c3698705281a5979c7394eb03fa4))
|
|
87
|
+
* stop close-resume opening duplicate empty PRs and stop the PR watcher reporting green on a blocked PR ([#4873](https://github.com/dsj1984/mandrel/issues/4873)) ([#4884](https://github.com/dsj1984/mandrel/issues/4884)) ([9d12f8d](https://github.com/dsj1984/mandrel/commit/9d12f8dcd4badbe3b657f1526c284f7689bf04ee))
|
|
88
|
+
* stop the CRAP row builder silently mixing transpiled and original line coordinates, and refuse to compare on an unsound basis ([#4866](https://github.com/dsj1984/mandrel/issues/4866)) ([#4868](https://github.com/dsj1984/mandrel/issues/4868)) ([a6c8c88](https://github.com/dsj1984/mandrel/commit/a6c8c8866c72b1372eb5fd5b7232fb3833e33f93))
|
|
89
|
+
* stop the test suite writing fixture friction signals into the real ledger, and stop unresolvable Story ids reaching an auto-filed ticket ([#4892](https://github.com/dsj1984/mandrel/issues/4892)) ([#4895](https://github.com/dsj1984/mandrel/issues/4895)) ([a607de4](https://github.com/dsj1984/mandrel/commit/a607de49a09c778c1fbefe68d4c57d6a75f0b648))
|
|
90
|
+
* warn about the un-waivable light-path verdict up front, de-conflict on actual footprints, and reconcile the concurrency override ([#4875](https://github.com/dsj1984/mandrel/issues/4875)) ([#4880](https://github.com/dsj1984/mandrel/issues/4880)) ([16d4958](https://github.com/dsj1984/mandrel/commit/16d49584227d783695bb36043e29c64a58aaab39))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
### Changed
|
|
94
|
+
|
|
95
|
+
* reclaim workflow-spine byte headroom and move the close-and-land tail to the orchestrator (refs [#4876](https://github.com/dsj1984/mandrel/issues/4876)) ([#4885](https://github.com/dsj1984/mandrel/issues/4885)) ([7d981cd](https://github.com/dsj1984/mandrel/commit/7d981cde4f8c3d1047a09e64d1f193b85fbfd4b6))
|
|
96
|
+
* widen workflow-spine and agent-boot headroom to a real editing margin (refs [#4876](https://github.com/dsj1984/mandrel/issues/4876)) ([#4889](https://github.com/dsj1984/mandrel/issues/4889)) ([45f5482](https://github.com/dsj1984/mandrel/commit/45f548238c9c82a1e36df11320b73c8f9dea27f5))
|
|
97
|
+
|
|
5
98
|
## [2.24.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.23.0...mandrel-v2.24.0) (2026-07-31)
|
|
6
99
|
|
|
7
100
|
|
package/lib/cli/update.js
CHANGED
|
@@ -247,10 +247,15 @@ function resolveProjectRoot() {
|
|
|
247
247
|
* `mandrel` version via the daily freshness cache (`version-check.js`).
|
|
248
248
|
*
|
|
249
249
|
* When `bypassCache` is `true` (the default for an explicit `mandrel update`
|
|
250
|
-
* call — Story #4046 A1b),
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
250
|
+
* call — Story #4046 A1b), `isStale` is asked to skip its freshness read via
|
|
251
|
+
* `forceRefresh`, so any existing cache is ignored and exactly one network
|
|
252
|
+
* probe is issued. The cache is still written so the post-update
|
|
253
|
+
* `version-current` advisory has a fresh baseline.
|
|
254
|
+
*
|
|
255
|
+
* The bypass deliberately does **not** shift `now`: the same clock is stamped
|
|
256
|
+
* into the refreshed `checkedAt`, so a shifted clock would persist a
|
|
257
|
+
* ~48h-future timestamp and defeat the 24h window for every later passive
|
|
258
|
+
* check until real time caught up (Story #4878).
|
|
254
259
|
*
|
|
255
260
|
* When `bypassCache` is `false` (passive staleness checks only), the normal
|
|
256
261
|
* 24h-cache semantics apply: a fresh cache returns the cached version with
|
|
@@ -281,16 +286,14 @@ async function defaultResolveTargetVersion({
|
|
|
281
286
|
bypassCache = false,
|
|
282
287
|
log = () => {},
|
|
283
288
|
} = {}) {
|
|
284
|
-
//
|
|
285
|
-
//
|
|
286
|
-
//
|
|
287
|
-
const effectiveNow = bypassCache
|
|
288
|
-
? new Date(now.getTime() + 48 * 60 * 60 * 1000)
|
|
289
|
-
: now;
|
|
289
|
+
// Bypass the cache by telling isStale to skip its freshness read — never by
|
|
290
|
+
// shifting `now`, which is also the clock persisted as `checkedAt`
|
|
291
|
+
// (Story #4046 A1b forcing the probe; Story #4878 keeping the stamp honest).
|
|
290
292
|
const result = await isStale({
|
|
291
293
|
cachePath,
|
|
292
|
-
now
|
|
294
|
+
now,
|
|
293
295
|
runner,
|
|
296
|
+
forceRefresh: bypassCache,
|
|
294
297
|
fs,
|
|
295
298
|
log,
|
|
296
299
|
});
|
package/lib/cli/version-check.js
CHANGED
|
@@ -142,10 +142,17 @@ export function refreshCache({
|
|
|
142
142
|
* The freshness comparison uses `>=` so an exactly-24h-old cache counts as
|
|
143
143
|
* stale (the boundary is treated as "due for refresh").
|
|
144
144
|
*
|
|
145
|
+
* `forceRefresh` skips the freshness read entirely and always probes. It is
|
|
146
|
+
* the supported way to bypass the cache: callers must **not** fake staleness
|
|
147
|
+
* by shifting `now` forward, because `now` is also the clock stamped into the
|
|
148
|
+
* refreshed `checkedAt` — a shifted clock persists a future timestamp and
|
|
149
|
+
* defeats the freshness window for every later reader (Story #4878).
|
|
150
|
+
*
|
|
145
151
|
* @param {{
|
|
146
152
|
* cachePath: string,
|
|
147
153
|
* now?: Date,
|
|
148
154
|
* runner: () => (string | Promise<string>),
|
|
155
|
+
* forceRefresh?: boolean,
|
|
149
156
|
* fs?: typeof import('node:fs'),
|
|
150
157
|
* log?: (msg: string) => void,
|
|
151
158
|
* }} opts
|
|
@@ -160,10 +167,11 @@ export async function isStale({
|
|
|
160
167
|
cachePath,
|
|
161
168
|
now = new Date(),
|
|
162
169
|
runner,
|
|
170
|
+
forceRefresh = false,
|
|
163
171
|
fs = nodeFs,
|
|
164
172
|
log = () => {},
|
|
165
173
|
}) {
|
|
166
|
-
const cached = readCache({ cachePath, fs });
|
|
174
|
+
const cached = forceRefresh ? null : readCache({ cachePath, fs });
|
|
167
175
|
|
|
168
176
|
if (cached) {
|
|
169
177
|
const ageMs = now.getTime() - new Date(cached.checkedAt).getTime();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mandrel",
|
|
3
|
-
"version": "2.
|
|
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
|
-
"
|
|
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
|
-
}
|