mandrel 1.87.0 → 1.89.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/README.md +18 -13
- package/.agents/audit-checklists/architecture.md +24 -0
- package/.agents/audit-checklists/clean-code.md +24 -0
- package/.agents/audit-checklists/dependencies.md +14 -0
- package/.agents/audit-checklists/devops.md +17 -0
- package/.agents/audit-checklists/documentation.md +22 -0
- package/.agents/audit-checklists/lighthouse.md +15 -0
- package/.agents/audit-checklists/navigability.md +14 -0
- package/.agents/audit-checklists/performance.md +22 -0
- package/.agents/audit-checklists/privacy.md +21 -0
- package/.agents/audit-checklists/quality.md +18 -0
- package/.agents/audit-checklists/security.md +22 -0
- package/.agents/audit-checklists/seo.md +16 -0
- package/.agents/audit-checklists/sre.md +24 -0
- package/.agents/audit-checklists/ux-ui.md +21 -0
- package/.agents/docs/SDLC.md +63 -16
- package/.agents/docs/configuration.md +5 -3
- package/.agents/instructions.md +51 -21
- package/.agents/personas/architect.md +10 -7
- package/.agents/personas/engineer.md +4 -3
- package/.agents/personas/project-manager.md +5 -2
- package/.agents/personas/refactorer.md +5 -3
- package/.agents/rules/git-conventions.md +77 -0
- package/.agents/schemas/agentrc.schema.json +16 -4
- package/.agents/schemas/audit-rules.json +16 -2
- package/.agents/schemas/audit-rules.schema.json +7 -6
- package/.agents/schemas/lifecycle/merge.unlanded.schema.json +38 -0
- package/.agents/schemas/signal-event.schema.json +28 -13
- package/.agents/scripts/acceptance-spec-reconciler.js +6 -4
- package/.agents/scripts/check-context-budget.js +320 -0
- package/.agents/scripts/diagnose-friction.js +4 -4
- package/.agents/scripts/epic-audit-prepare.js +30 -2
- package/.agents/scripts/epic-audit-recheck.js +46 -13
- package/.agents/scripts/epic-deliver-prepare.js +80 -8
- package/.agents/scripts/epic-plan-spec.js +4 -8
- package/.agents/scripts/generate-lens-checklists.js +180 -0
- package/.agents/scripts/lib/audit-suite/checklist-threading.js +300 -0
- package/.agents/scripts/lib/audit-suite/findings.js +27 -0
- package/.agents/scripts/lib/audit-suite/index.js +9 -0
- package/.agents/scripts/lib/audit-suite/lens-checklist.js +212 -0
- package/.agents/scripts/lib/audit-suite/selector.js +136 -5
- package/.agents/scripts/lib/checks/loop-health.js +340 -0
- package/.agents/scripts/lib/cli-args.js +8 -0
- package/.agents/scripts/lib/config/explain.js +4 -0
- package/.agents/scripts/lib/config/runners.js +21 -2
- package/.agents/scripts/lib/config/temp-paths.js +24 -0
- package/.agents/scripts/lib/config-settings-schema-delivery.js +23 -3
- package/.agents/scripts/lib/config-settings-schema-quality.js +7 -0
- package/.agents/scripts/lib/doc-tiers.js +291 -0
- package/.agents/scripts/lib/epic-body-sections.js +5 -2
- package/.agents/scripts/lib/epic-merge-lock.js +83 -0
- package/.agents/scripts/lib/epic-plan-clarity.js +3 -1
- package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +66 -20
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +395 -86
- package/.agents/scripts/lib/feedback-loop/memory-freshness.js +299 -72
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +438 -0
- package/.agents/scripts/lib/gates/friction.js +15 -5
- package/.agents/scripts/lib/observability/perf-aggregator.js +30 -104
- package/.agents/scripts/lib/observability/perf-report-readers.js +1 -1
- package/.agents/scripts/lib/observability/signal-validator.js +204 -0
- package/.agents/scripts/lib/observability/signals-writer.js +157 -54
- package/.agents/scripts/lib/observability/tool-trace-hook.js +42 -4
- package/.agents/scripts/lib/orchestration/acceptance-eval-decision.js +1 -1
- package/.agents/scripts/lib/orchestration/code-review.js +74 -4
- package/.agents/scripts/lib/orchestration/consolidation-precondition.js +213 -0
- package/.agents/scripts/lib/orchestration/doc-reader.js +4 -96
- package/.agents/scripts/lib/orchestration/docs-digest.js +34 -0
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/authoring-context.js +56 -19
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/run-spec-phase.js +22 -0
- package/.agents/scripts/lib/orchestration/lifecycle/emit-merge-unlanded.js +188 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +6 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +69 -8
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +11 -2
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +47 -61
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +39 -3
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/label-transitioner.js +144 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/merge-watcher.js +258 -14
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/notify-dispatcher.js +6 -0
- package/.agents/scripts/lib/orchestration/merge-block-class.js +218 -0
- package/.agents/scripts/lib/orchestration/plan-review-routing.js +1 -1
- package/.agents/scripts/lib/orchestration/post-merge/phases/worktree-reap.js +3 -3
- package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +63 -34
- package/.agents/scripts/lib/orchestration/retro/phases/gather-signals.js +167 -52
- package/.agents/scripts/lib/orchestration/retro/phases/post-and-mirror.js +49 -2
- package/.agents/scripts/lib/orchestration/retro-proposals.js +12 -55
- package/.agents/scripts/lib/orchestration/retro-runner.js +9 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/code-review.js +8 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/confirm-merge.js +419 -0
- package/.agents/scripts/lib/orchestration/single-story-close/phases/options.js +35 -2
- package/.agents/scripts/lib/orchestration/single-story-close/phases/wrong-tree-guard.js +353 -69
- package/.agents/scripts/lib/orchestration/single-story-close/runner.js +66 -4
- package/.agents/scripts/lib/orchestration/spec-section-validator.js +60 -9
- package/.agents/scripts/lib/orchestration/story-close/auto-refresh-runner.js +7 -5
- package/.agents/scripts/lib/orchestration/story-close/merge-runner.js +24 -2
- package/.agents/scripts/lib/orchestration/story-close/phases/code-review.js +167 -8
- package/.agents/scripts/lib/orchestration/story-close/shared-checkout-guard.js +163 -0
- package/.agents/scripts/lib/orchestration/ticketing/reads.js +20 -9
- package/.agents/scripts/lib/planning-corpus.js +306 -0
- package/.agents/scripts/lib/signals/detectors/common.js +10 -10
- package/.agents/scripts/lib/signals/detectors/index.js +4 -4
- package/.agents/scripts/lib/signals/detectors/retry.js +19 -18
- package/.agents/scripts/lib/signals/detectors/rework.js +1 -1
- package/.agents/scripts/lib/signals/schema.js +56 -81
- package/.agents/scripts/lib/signals/span-tree.js +6 -5
- package/.agents/scripts/lib/story-plan.js +3 -0
- package/.agents/scripts/lib/wave-runner/tick.js +10 -2
- package/.agents/scripts/lifecycle-emit.js +39 -8
- package/.agents/scripts/providers/github/issues.js +12 -1
- package/.agents/scripts/resolve-doc-tiers.js +83 -0
- package/.agents/scripts/retro-run.js +51 -0
- package/.agents/scripts/signals-view.js +1 -1
- package/.agents/scripts/single-story-close.js +20 -1
- package/.agents/scripts/standalone-feedback-rollup.js +188 -0
- package/.agents/scripts/story-close.js +48 -0
- package/.agents/scripts/story-plan.js +51 -12
- package/.agents/scripts/validate-docs-freshness.js +69 -15
- package/.agents/skills/core/documentation-and-adrs/SKILL.md +58 -0
- package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +5 -3
- package/.agents/skills/core/epic-plan-spec-author/SKILL.md +20 -7
- package/.agents/skills/core/scope-triage/SKILL.md +61 -0
- package/.agents/skills/skills.index.json +3 -3
- package/.agents/workflows/audit-documentation.md +82 -2
- package/.agents/workflows/helpers/code-review.md +193 -44
- package/.agents/workflows/helpers/deliver-epic.md +128 -39
- package/.agents/workflows/helpers/deliver-stories.md +26 -0
- package/.agents/workflows/helpers/epic-audit.md +116 -283
- package/.agents/workflows/helpers/epic-deliver-story.md +14 -0
- package/.agents/workflows/helpers/epic-plan-decompose.md +18 -200
- package/.agents/workflows/helpers/epic-plan-spec.md +18 -180
- package/.agents/workflows/helpers/plan-epic.md +141 -105
- package/.agents/workflows/helpers/plan-story.md +32 -0
- package/.agents/workflows/helpers/single-story-deliver.md +43 -0
- package/.agents/workflows/loops/nightly-audit.md +9 -7
- package/docs/CHANGELOG.md +29 -0
- package/lib/cli/doctor.js +44 -0
- package/package.json +4 -3
- package/.agents/scripts/epic-plan-spec-validate.js +0 -111
- package/.agents/scripts/lib/feedback-loop/code-review-graduator.js +0 -207
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +0 -58
- package/.agents/scripts/lib/signals/detectors/hotspot.js +0 -292
|
@@ -16,11 +16,21 @@ You are the master orchestrator for the v5 Epic-Centric ticketing pipeline. Your
|
|
|
16
16
|
goal is to transform a high-level Epic into a fully decomposed, ready-to-execute
|
|
17
17
|
backlog of Stories.
|
|
18
18
|
|
|
19
|
-
`/plan` is the unified planning entry point.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
`/plan` is the unified planning entry point. This file (`helpers/plan-epic.md`)
|
|
20
|
+
is the single authoritative home for Phase 7 (spec) and Phase 8 (decompose) —
|
|
21
|
+
it carries the full step-by-step procedure for both and delegates only the
|
|
22
|
+
authoring middle of each to the
|
|
23
|
+
[`epic-plan-spec-author`](../../skills/core/epic-plan-spec-author/SKILL.md) /
|
|
24
|
+
[`epic-plan-decompose-author`](../../skills/core/epic-plan-decompose-author/SKILL.md)
|
|
25
|
+
skills. It runs both phases sequentially with a human confirmation gate
|
|
26
|
+
between them. The Epic ID is the single positional argument.
|
|
27
|
+
|
|
28
|
+
> **Thin pointers, not duplicate procedures.** [`helpers/epic-plan-spec.md`](epic-plan-spec.md)
|
|
29
|
+
> and [`helpers/epic-plan-decompose.md`](epic-plan-decompose.md) used to
|
|
30
|
+
> restate Phase 7/8 as their own inline step lists — a drifted, pre-skill
|
|
31
|
+
> pattern now that authoring is delegated to the two skills above. Both files
|
|
32
|
+
> are now thin pointers back to this one; do not resurrect inline step lists
|
|
33
|
+
> in either.
|
|
24
34
|
|
|
25
35
|
As of v5.6, planning artifacts (Tech Spec, ticket decomposition) are
|
|
26
36
|
authored **directly by you, the host LLM** — no external Gemini / Anthropic /
|
|
@@ -37,12 +47,13 @@ artifacts you author.
|
|
|
37
47
|
See [SDLC § Adaptive planning risk routing](../../docs/SDLC.md#adaptive-planning-risk-routing)
|
|
38
48
|
for the full envelope shape and the planner-selected
|
|
39
49
|
`acceptance::n-a` route.
|
|
40
|
-
- Delegate Phase 7 and Phase 8 to the
|
|
41
|
-
[`
|
|
42
|
-
[`
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
- Delegate Phase 7 and Phase 8 authoring to the
|
|
51
|
+
[`epic-plan-spec-author`](../../skills/core/epic-plan-spec-author/SKILL.md)
|
|
52
|
+
and [`epic-plan-decompose-author`](../../skills/core/epic-plan-decompose-author/SKILL.md)
|
|
53
|
+
skills respectively — the deterministic `epic-plan-spec.js` /
|
|
54
|
+
`epic-plan-decompose.js` CLIs (invoked by this file's own Phase 7 / Phase 8
|
|
55
|
+
steps) own the Epic lifecycle label transitions and the `epic-plan-state`
|
|
56
|
+
checkpoint. This wrapper must not apply those labels directly.
|
|
46
57
|
|
|
47
58
|
## Prerequisites
|
|
48
59
|
|
|
@@ -448,6 +459,18 @@ for the scoring logic.
|
|
|
448
459
|
`--emit-context` envelope is a backstop for legacy callers; the
|
|
449
460
|
skill body wins when the two surfaces diverge.
|
|
450
461
|
|
|
462
|
+
> **One-pass refinement contract (amend, don't regenerate).** When step 3's
|
|
463
|
+
> persist call rejects the authored artifacts (missing `## Delivery
|
|
464
|
+
> Slicing`, a schema-invalid risk verdict), re-entering this step applies
|
|
465
|
+
> **targeted edits** to the existing `temp/epic-[Epic_ID]/{techspec.md,
|
|
466
|
+
> risk-verdict.json,acceptance-spec.md}` files — fix only what the
|
|
467
|
+
> rejection named — per the `epic-plan-spec-author` skill's re-emit rule.
|
|
468
|
+
> This refinement is bounded to **one pass**: fix the named gap and
|
|
469
|
+
> re-run step 3 once: do not loop wholesale re-authoring across multiple
|
|
470
|
+
> rejections. The same one-pass shape already governs the Phase 6 Epic
|
|
471
|
+
> Clarity Gate's refinement loop above ("Do not loop — one refinement
|
|
472
|
+
> pass per invocation").
|
|
473
|
+
|
|
451
474
|
3. **Persist to GitHub**: Run the spec-phase CLI's persist half. It
|
|
452
475
|
schema-validates the planner-authored risk verdict (`--risk-verdict`,
|
|
453
476
|
required — a missing or malformed verdict fails closed before any
|
|
@@ -564,65 +587,35 @@ for the scoring logic.
|
|
|
564
587
|
temp files automatically on success — no operator action required. The
|
|
565
588
|
cleanup contract lives in
|
|
566
589
|
[`lib/plan-phase-cleanup.js`](../../scripts/lib/plan-phase-cleanup.js).
|
|
567
|
-
**Run the Phase 7.5 spec-validate gate (below) on
|
|
568
|
-
`temp/epic-[Epic_ID]/techspec.md` *before* this cleanup deletes the file** —
|
|
569
|
-
the gate reads the authored spec from temp.
|
|
570
|
-
|
|
571
|
-
## Phase 7.5: Tech Spec Section Gate (`epic-plan-spec-validate.js`)
|
|
572
|
-
|
|
573
|
-
> **Hard gate (blocks Phase 8).** This step runs **after** the Tech Spec is
|
|
574
|
-
> authored (Phase 7) and **before** decomposition (Phase 8). Unlike the
|
|
575
|
-
> advisory spec-freshness and BDD cross-reference checks in Phase 7, this gate
|
|
576
|
-
> is **blocking**: a missing required section exits non-zero and Phase 8 MUST
|
|
577
|
-
> NOT proceed until it is resolved. It is the Phase 8-side counterpart to the
|
|
578
|
-
> Phase 6 Epic Clarity Gate — same detect-then-prompt pattern, one phase later.
|
|
579
|
-
|
|
580
|
-
**Why this gate exists.** Phase 8.3 (Holistic Consolidation) reconciles the
|
|
581
|
-
draft ticket array against the Tech Spec's `## Delivery Slicing` section, which
|
|
582
|
-
the [`epic-plan-decompose-author`](../../skills/core/epic-plan-decompose-author/SKILL.md)
|
|
583
|
-
skill uses as the capability-boundary anchor (see Phase 8 step 2 below). When
|
|
584
|
-
the authored Tech Spec omits that section, the consolidation pass runs against a
|
|
585
|
-
void and produces groupings that reflect **technical shape** (e.g. cron jobs
|
|
586
|
-
together) rather than **capability boundaries** — reproduced on Epic #18 in
|
|
587
|
-
`dsj1984/athportal` (planned with v1.54.0), whose spec carried a detailed
|
|
588
|
-
`## Core Components` table but no `## Delivery Slicing` section.
|
|
589
|
-
|
|
590
|
-
**Run the gate** against the authored Tech Spec before the Phase 7 cleanup
|
|
591
|
-
deletes `temp/epic-[Epic_ID]/techspec.md`:
|
|
592
|
-
|
|
593
|
-
```bash
|
|
594
|
-
node .agents/scripts/epic-plan-spec-validate.js \
|
|
595
|
-
--techspec temp/epic-[Epic_ID]/techspec.md
|
|
596
|
-
```
|
|
597
590
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
591
|
+
> **Tech Spec section gate (folded into Step 3 persist).** The persist call
|
|
592
|
+
> in Step 3 above validates the authored Tech Spec for the required
|
|
593
|
+
> `## Delivery Slicing` heading (case-insensitive; also accepts the variant
|
|
594
|
+
> `## Delivery slicing` and the shorthand `## Slicing`) via
|
|
595
|
+
> [`lib/orchestration/spec-section-validator.js`](../../scripts/lib/orchestration/spec-section-validator.js#validateSpecSections)
|
|
596
|
+
> **before** acquiring the Epic-lease or making any GitHub mutation — a
|
|
597
|
+
> Tech Spec missing the section fails the persist call closed with a message
|
|
598
|
+
> naming the gap and the two recovery paths (re-author, or add the section by
|
|
599
|
+
> hand). This used to run as a separate, standalone
|
|
600
|
+
> `epic-plan-spec-validate.js` CLI invoked as its own Phase 7.5 workflow
|
|
601
|
+
> step; that ordering ran the check *after* the persist had already written
|
|
602
|
+
> to GitHub and *after* `cleanupPhaseTempFiles` had deleted the temp spec
|
|
603
|
+
> file the check read, so the "blocking gate" could never actually block.
|
|
604
|
+
> Folding the check into the persist path's input validation makes it a
|
|
605
|
+
> real hard gate. **Why this gate exists**: Phase 8.3 (Holistic
|
|
606
|
+
> Consolidation) reconciles the draft ticket array against the Tech Spec's
|
|
607
|
+
> `## Delivery Slicing` section, which the
|
|
608
|
+
> [`epic-plan-decompose-author`](../../skills/core/epic-plan-decompose-author/SKILL.md)
|
|
609
|
+
> skill uses as the capability-boundary anchor (see Phase 8 step 2 below).
|
|
610
|
+
> Without it, the consolidation pass runs against a void and produces
|
|
611
|
+
> groupings that reflect **technical shape** (e.g. cron jobs together)
|
|
612
|
+
> rather than **capability boundaries** — reproduced on Epic #18 in
|
|
613
|
+
> `dsj1984/athportal` (planned with v1.54.0), whose spec carried a detailed
|
|
614
|
+
> `## Core Components` table but no `## Delivery Slicing` section. On a
|
|
615
|
+
> persist failure, re-enter the Step 2 spec-author step and apply a
|
|
616
|
+
> **targeted edit** adding the missing `## Delivery Slicing` section to the
|
|
617
|
+
> existing `techspec.md` (amend, don't regenerate — the one-pass refinement
|
|
618
|
+
> contract above) — or add the section by hand — then re-run Step 3 once.
|
|
626
619
|
|
|
627
620
|
## Phase 8: Work Breakdown Decomposition
|
|
628
621
|
|
|
@@ -681,38 +674,78 @@ node .agents/scripts/epic-plan-spec-validate.js \
|
|
|
681
674
|
toward the Architect's proposed shippable-Story clusters; it degrades
|
|
682
675
|
gracefully when the section is absent.
|
|
683
676
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
`
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
It
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
677
|
+
> **One-pass refinement contract (amend, don't regenerate).** When the
|
|
678
|
+
> deterministic validator (`validateAndNormalizeTickets`) rejects the
|
|
679
|
+
> draft, or the 8.3 / 8.4 / 8.5 critics below flag specific Stories,
|
|
680
|
+
> re-entering this step applies
|
|
681
|
+
> **targeted edits** to the existing `temp/epic-[Epic_ID]/tickets.json` —
|
|
682
|
+
> fix only the rejected or flagged Stories — per the
|
|
683
|
+
> `epic-plan-decompose-author` skill's re-emit rule, rather than
|
|
684
|
+
> re-authoring the whole array from scratch. Each critic's feedback gets
|
|
685
|
+
> **one refinement pass**: apply the targeted edit and re-run the
|
|
686
|
+
> relevant downstream step (validator or persist) once, matching the
|
|
687
|
+
> Phase 7 spec-author contract above; do not loop wholesale re-authoring
|
|
688
|
+
> across repeated rejections.
|
|
689
|
+
|
|
690
|
+
3. **Phase 8.3 — Holistic Consolidation (HITL diff gate, precondition-gated
|
|
691
|
+
dispatch)**: After the draft `temp/epic-[Epic_ID]/tickets.json` exists and
|
|
692
|
+
**before** the persist call below, first consult the deterministic
|
|
693
|
+
dispatch precondition — [`evaluateConsolidationPrecondition`](../../scripts/lib/orchestration/consolidation-precondition.js),
|
|
694
|
+
called with the draft Story array and the Epic body (which carries the
|
|
695
|
+
folded Tech Spec `## Delivery Slicing` section). The precondition compares
|
|
696
|
+
the draft against the Delivery Slicing table **1:1** — same shippable-Story
|
|
697
|
+
count (excluding the wave-0 `bdd-scaffold` Story) and a `depends_on` shape
|
|
698
|
+
that agrees with each slice's `Independent?` answer — and returns
|
|
699
|
+
`{ dispatch, reasons }`. It **fails open** (`dispatch: true`) on every
|
|
700
|
+
ambiguous input: a missing or unparseable Delivery Slicing section, or an
|
|
701
|
+
unparseable `Independent?` cell.
|
|
702
|
+
|
|
703
|
+
- **`dispatch: false`** — the draft already matches the Delivery Slicing
|
|
704
|
+
target, so the consolidation critic has nothing to reconcile. **Skip the
|
|
705
|
+
sub-agent dispatch** and surface the skip as a **one-line progress
|
|
706
|
+
note** naming the precondition's `reasons` — quoting verbatim the
|
|
707
|
+
string `evaluateConsolidationPrecondition` actually emits: "Draft
|
|
708
|
+
matches Delivery Slicing 1:1 in count and dependency shape (N
|
|
709
|
+
slice(s)) — skipping the 8.3 consolidation dispatch." (`N` is the
|
|
710
|
+
interpolated `slicing.length`). Proceed straight to Phase 8.4 with the
|
|
711
|
+
draft `tickets.json` unchanged (no `consolidation-report.md` is
|
|
712
|
+
produced when the dispatch is skipped).
|
|
713
|
+
- **`dispatch: true`** — **dispatch a genuine fresh-context sub-agent**
|
|
714
|
+
(`Agent` tool, `subagent_type: general-purpose`) whose task is to read
|
|
715
|
+
the
|
|
716
|
+
[`epic-plan-consolidate`](../../skills/core/epic-plan-consolidate/SKILL.md)
|
|
717
|
+
skill and execute its procedure with `[Epic_ID]` as input, including the
|
|
718
|
+
precondition's `reasons` in the HITL diff context so the operator sees
|
|
719
|
+
*why* the critic ran. Dispatching the critic as a sub-agent — **not**
|
|
720
|
+
activating the skill inline in your authoring turn — is what makes it a
|
|
721
|
+
**separate critic pass with fresh context**: the sub-agent does not
|
|
722
|
+
inherit the conversation that authored the draft, so it cannot grade its
|
|
723
|
+
own homework (the same nested-dispatch mechanic the acceptance self-eval
|
|
724
|
+
loop uses, now that the sub-agent depth limit is lifted — see
|
|
725
|
+
[`.agents/instructions.md` § 4](../../instructions.md)). The sub-agent
|
|
726
|
+
reads the draft array plus the Epic body (which carries the Tech Spec
|
|
727
|
+
sections), reconciles the draft against the Tech Spec `## Delivery
|
|
728
|
+
Slicing` target, and emits a **consolidated** `tickets.json` plus a
|
|
729
|
+
human-readable `temp/epic-[Epic_ID]/consolidation-report.md`. Its operations are scope-preserving only — **merge sibling Stories and
|
|
730
|
+
rewire `depends_on`** — and it MUST NOT add scope or invent tickets; it
|
|
731
|
+
consolidates fragmented slices by merging them into a cohesive Story,
|
|
732
|
+
never by splitting one. The sub-agent **never writes to GitHub**: it
|
|
733
|
+
emits only the two temp artifacts and returns control to this operator
|
|
734
|
+
session. It runs **before** the deterministic validator
|
|
735
|
+
(`validateAndNormalizeTickets`), so the validator re-checks its output
|
|
736
|
+
and the critic cannot emit an invalid plan. **Show the operator the
|
|
737
|
+
consolidation report (the before/after
|
|
738
|
+
diff + rationale) before persisting.** The HITL diff-confirm and the
|
|
739
|
+
persist call both run here in the **operator session**, never inside
|
|
740
|
+
the sub-agent — consolidation is never auto-applied without review: on
|
|
741
|
+
operator approval, persist the consolidated `tickets.json`; on
|
|
742
|
+
rejection, persist the draft instead.
|
|
743
|
+
|
|
744
|
+
Phase 8.4 (Reachability Completeness Critic), Phase 8.5 (Planning
|
|
745
|
+
Pre-Mortem Critic), and the deterministic ticket validator
|
|
746
|
+
(`validateAndNormalizeTickets`) are
|
|
747
|
+
**unconditional** — the precondition governs only the 8.3 sub-agent
|
|
748
|
+
dispatch, never any other Phase 8 gate. This is a sub-step of Phase 8 — it
|
|
716
749
|
does **not** renumber the top-level lifecycle phases (9–12).
|
|
717
750
|
|
|
718
751
|
4. **Phase 8.4 — Reachability Completeness Critic (HITL diff gate, F6)**:
|
|
@@ -748,8 +781,8 @@ node .agents/scripts/epic-plan-spec-validate.js \
|
|
|
748
781
|
- **HITL.** The added Story is surfaced in the **same Phase 8 HITL diff** as
|
|
749
782
|
consolidation, **before** any GitHub write — never auto-persisted. On
|
|
750
783
|
operator rejection, drop the added Story and persist without it. The
|
|
751
|
-
deterministic validator (
|
|
752
|
-
invalid addition cannot reach GitHub.
|
|
784
|
+
deterministic validator (`validateAndNormalizeTickets`) re-checks the
|
|
785
|
+
critic's output, so an invalid addition cannot reach GitHub.
|
|
753
786
|
|
|
754
787
|
5. **Phase 8.5 — Planning Pre-Mortem Critic (code-reading, F9)**: After the
|
|
755
788
|
reachability critic (8.4) and **before** the persist call below, **dispatch a
|
|
@@ -776,8 +809,11 @@ node .agents/scripts/epic-plan-spec-validate.js \
|
|
|
776
809
|
shown in the **same Phase 8 HITL diff** (which stays in the operator
|
|
777
810
|
session), and on
|
|
778
811
|
operator approval the author re-runs (Step 2) on the findings **before** the
|
|
779
|
-
persist call
|
|
780
|
-
|
|
812
|
+
persist call — applying **targeted edits** to the flagged Stories in the
|
|
813
|
+
existing `tickets.json` (amend, don't regenerate; **one refinement pass**
|
|
814
|
+
per the contract above), not a wholesale re-author. The critic runs
|
|
815
|
+
**before** the deterministic validator (`validateAndNormalizeTickets`),
|
|
816
|
+
so the persist below is the single GitHub write for the whole phase.
|
|
781
817
|
|
|
782
818
|
6. **Persist to GitHub**: Run the decompose CLI's persist half. It
|
|
783
819
|
validates the ticket array (`validateAndNormalizeTickets`), creates
|
|
@@ -98,8 +98,18 @@ Envelope fields (`kind: "story-plan-context"`, `version: 1`):
|
|
|
98
98
|
| `requiredSections` | `["Context", "Acceptance Criteria", "Out of Scope", "Notes"]`. |
|
|
99
99
|
| `duplicateCandidates` | Ranked open Stories whose titles fuzzy-match the seed. |
|
|
100
100
|
| `techStack` | The project's Tech Stack inventory, resolved in order: `docs/tech-stack.md` (full body) when present, else the `## Tech Stack` section of `docs/architecture.md` (numbered/decorated and final-section headings tolerated). |
|
|
101
|
+
| `corpusContext` | Corpus-aware inherited context (Story #4432): `{ docsDigest, relevantSections }` — see below. |
|
|
101
102
|
| `deliverContract` | Workflow path + required/forbidden labels and references. |
|
|
102
103
|
|
|
104
|
+
`corpusContext.docsDigest` is the same per-project docs digest
|
|
105
|
+
`orchestration/docs-digest.js` builds for `/deliver` Story children (`null`
|
|
106
|
+
when `project.docsContextFiles` is not configured). `corpusContext.relevantSections`
|
|
107
|
+
is a ranked list of `{ epicId, epicTitle, section, score, excerpt }` —
|
|
108
|
+
existing-Epic Tech Spec (or ideation-lede) excerpts that overlap with the
|
|
109
|
+
seed, fetched via a bounded explicit per-candidate body fetch
|
|
110
|
+
(`planning-corpus.js`). Both fields degrade to `null` / `[]` respectively
|
|
111
|
+
when there is nothing to surface.
|
|
112
|
+
|
|
103
113
|
### Refine heuristic
|
|
104
114
|
|
|
105
115
|
`refine.refine` is `true` when the seed is shorter than 200 characters
|
|
@@ -121,6 +131,28 @@ Using the envelope above, draft a Story body that:
|
|
|
121
131
|
- Does **NOT** contain any `Epic: #N` reference — that breaks the
|
|
122
132
|
standalone contract enforced by `single-story-init.js`.
|
|
123
133
|
|
|
134
|
+
### Drafting against `corpusContext`
|
|
135
|
+
|
|
136
|
+
Check `corpusContext` before authoring the `## Context` section:
|
|
137
|
+
|
|
138
|
+
- **When `corpusContext.relevantSections` is non-empty** (the seed is a
|
|
139
|
+
change-request-shaped delta against a surface an existing Epic already
|
|
140
|
+
covers — see the
|
|
141
|
+
[`core/scope-triage`](../../skills/core/scope-triage/SKILL.md) change-request
|
|
142
|
+
rubric), draft `## Context` **against that inherited context** rather than
|
|
143
|
+
re-deriving it from scratch: reference the matching Epic's Tech Spec
|
|
144
|
+
excerpt(s) by number (`Epic #<epicId>`) and build the acceptance criteria on
|
|
145
|
+
top of the architecture / conventions they already establish. Pull
|
|
146
|
+
`corpusContext.docsDigest` the same way the digest-first delivery path does
|
|
147
|
+
(§ 3 of [`.agents/instructions.md`](../../instructions.md)) — read the
|
|
148
|
+
relevant doc section on demand when the digest outline names one that bears
|
|
149
|
+
on the change.
|
|
150
|
+
- **When `corpusContext.relevantSections` is `[]` and `docsDigest` is
|
|
151
|
+
`null`** — no configured docs and no overlapping prior art — draft exactly
|
|
152
|
+
as today: from the seed, the body template, and the duplicate-candidates
|
|
153
|
+
scan alone. This is the common case for a genuinely new standalone Story
|
|
154
|
+
and is not a degraded path; it is simply that there is nothing to inherit.
|
|
155
|
+
|
|
124
156
|
Write the draft to `temp/single-story-draft.md`.
|
|
125
157
|
|
|
126
158
|
### Scope-triage escalation gate (symmetric counterpart to `/plan` Phase 1.5)
|
|
@@ -135,6 +135,19 @@ Operator/agent responsibilities while in the worktree:
|
|
|
135
135
|
only when the Story's own context points you at one — do not ingest the
|
|
136
136
|
whole docs set up front. See
|
|
137
137
|
[`.agents/instructions.md` § 3](../../instructions.md).
|
|
138
|
+
|
|
139
|
+
**Write-time audit checklists.** The write-time local-lens checklist
|
|
140
|
+
threading (Story #4410) is wired on the Epic delivery path via
|
|
141
|
+
`epic-deliver-prepare.js`, which threads a per-Story `checklistPath` into
|
|
142
|
+
the maker prompt. When a standalone caller provides a `checklistPath`
|
|
143
|
+
(the repo-relative path to this Story's footprint-matched **local**-lens
|
|
144
|
+
authoring checklists, matched via `resolveLensTier(lens) === 'local'` +
|
|
145
|
+
`matchesAnyFilePattern` against the Story's predicted footprint — never
|
|
146
|
+
`selectAudits`, so no provider or git diff runs), read it before you
|
|
147
|
+
write and self-check your change against each listed concern as you
|
|
148
|
+
author it. When no `checklistPath` is provided, there is nothing extra to
|
|
149
|
+
read — the lens-aware coverage still runs maker-blind at Story-scope
|
|
150
|
+
review inside the close subprocess.
|
|
138
151
|
2. Implement the changes.
|
|
139
152
|
3. Commit on the Story branch. Conventional-commit format is encouraged
|
|
140
153
|
but not enforced — the PR title carries the canonical summary.
|
|
@@ -249,6 +262,28 @@ Flags:
|
|
|
249
262
|
- `--no-auto-merge` — disable auto-merge. Use when the PR materially changes
|
|
250
263
|
behaviour and warrants a pre-merge eyeball; the operator then merges via
|
|
251
264
|
the GitHub UI.
|
|
265
|
+
- `--wait-merge` — **headless must-land** (Story #4428, Epic #4425). Pass
|
|
266
|
+
this flag when driving `single-story-close.js` from an unattended /
|
|
267
|
+
headless context (no operator available to run Step 5 by hand — a CI
|
|
268
|
+
job, a scheduled `/loop`, or any wrapper that cannot rely on a human to
|
|
269
|
+
invoke `single-story-confirm-merge.js` later). Instead of resting at
|
|
270
|
+
`agent::closing` after arming, close polls the armed PR to merge
|
|
271
|
+
confirmation on the `delivery.mergeWatch.*` cadence (reusing the same
|
|
272
|
+
`confirmStoryMerged` flip logic Step 5 calls) and flips `agent::done`
|
|
273
|
+
itself. If the arm fails, the PR closes without merging, or the poll
|
|
274
|
+
budget is exhausted first, close classifies the block
|
|
275
|
+
(`checks-pending-timeout` \| `branch-protection-human-required` \|
|
|
276
|
+
`arm-failure` \| `api-race-other`), emits a `merge.unlanded` lifecycle
|
|
277
|
+
event, posts a `friction` comment, transitions the Story to
|
|
278
|
+
`agent::blocked`, and exits non-zero — never a silent `agent::closing`
|
|
279
|
+
rest. **Attended runs must not pass this flag** — the default (no flag)
|
|
280
|
+
preserves the exit-at-`agent::closing` behaviour documented in Step 3
|
|
281
|
+
and Step 5 below.
|
|
282
|
+
- `--no-wait-merge` — explicit opt-out that always wins over `--wait-merge`
|
|
283
|
+
(including for a caller that otherwise defaults to headless mode). Use
|
|
284
|
+
when a headless wrapper still wants to manage merge confirmation itself
|
|
285
|
+
(e.g. via its own `single-story-confirm-merge.js` invocation) rather than
|
|
286
|
+
have close block the turn.
|
|
252
287
|
|
|
253
288
|
> **Full close pipeline (base-sync outcomes, `agent::closing` rationale,
|
|
254
289
|
> lease release).** For the numbered close pipeline, the base-sync outcome
|
|
@@ -260,6 +295,14 @@ Flags:
|
|
|
260
295
|
|
|
261
296
|
## Step 4 — CI watch + fix loop (**required, not optional**)
|
|
262
297
|
|
|
298
|
+
> **Headless (`--wait-merge`) runs skip Steps 4 and 5.** When Step 3 passed
|
|
299
|
+
> `--wait-merge`, `single-story-close.js` already polled the PR to a
|
|
300
|
+
> confirmed merge (flipping `agent::done` itself) or exited non-zero after
|
|
301
|
+
> transitioning the Story to `agent::blocked` with a `merge.unlanded`
|
|
302
|
+
> event — there is no separate CI-watch turn or manual confirm step to run.
|
|
303
|
+
> Proceed straight to Step 5.5. Attended runs (the default) still own
|
|
304
|
+
> Steps 4 and 5 as documented below.
|
|
305
|
+
|
|
263
306
|
The Story is **not done** when `single-story-close.js` returns. Auto-merge
|
|
264
307
|
only fires when every required CI check turns green. Local close-validation
|
|
265
308
|
gates pass on the dev host's environment; CI runs on a different OS and
|
|
@@ -34,13 +34,15 @@ Each scheduled run:
|
|
|
34
34
|
structured `temp/audits/audit-*-results.md` report — that is the canonical
|
|
35
35
|
artifact this loop consumes, not free-form prose. Because these audits are
|
|
36
36
|
**independent** of one another, a scheduled run **may fan them out to
|
|
37
|
-
parallel sub-agents** (one per audit) rather than walking them serially
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
parallel sub-agents** (one per audit) rather than walking them serially:
|
|
38
|
+
dispatch one general-purpose sub-agent per lens, each instructed to read
|
|
39
|
+
its `/audit-<lens>` workflow and write the structured report. Each
|
|
40
|
+
sub-agent returns only its structured report; the scheduler/host owns the
|
|
41
|
+
fan-out just as it owns the cadence, and each per-audit strategy
|
|
42
|
+
(sequential or orchestrated) is unchanged by running under its own
|
|
43
|
+
sub-agent. (The former `/deliver` Phase 4 audit-orchestrator pattern this
|
|
44
|
+
note used to cite was retired by Story #4412, which folded the Epic-close
|
|
45
|
+
lens walk into the Phase 5 code-review pass.)
|
|
44
46
|
2. **Diff against the prior night.** Compare the fresh findings against the last
|
|
45
47
|
sweep's reports and against already-open Issues. A finding seen before is
|
|
46
48
|
not new signal; only genuinely fresh or regressed findings warrant a record.
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.89.0](https://github.com/dsj1984/mandrel/compare/mandrel-v1.88.0...mandrel-v1.89.0) (2026-07-11)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
* add cross-epic guard to story-close.js shared-checkout merge phase ([#4462](https://github.com/dsj1984/mandrel/issues/4462)) ([78c5263](https://github.com/dsj1984/mandrel/commit/78c526309a65f71fbfe14f4ef51c1e8ae706e454))
|
|
11
|
+
* Epic [#4405](https://github.com/dsj1984/mandrel/issues/4405) ([#4463](https://github.com/dsj1984/mandrel/issues/4463)) ([99737f1](https://github.com/dsj1984/mandrel/commit/99737f171d0cb0b4b28b40ea4c160b92c59428d6))
|
|
12
|
+
* Epic [#4406](https://github.com/dsj1984/mandrel/issues/4406) ([#4440](https://github.com/dsj1984/mandrel/issues/4440)) ([63cc5c3](https://github.com/dsj1984/mandrel/commit/63cc5c35483e9ec1138be2880127fad3b6244eb4))
|
|
13
|
+
* Epic [#4425](https://github.com/dsj1984/mandrel/issues/4425) ([#4458](https://github.com/dsj1984/mandrel/issues/4458)) ([6da35a6](https://github.com/dsj1984/mandrel/commit/6da35a6f740cabc620b7b286dc87a710af237a30))
|
|
14
|
+
* Epic [#4429](https://github.com/dsj1984/mandrel/issues/4429) ([#4443](https://github.com/dsj1984/mandrel/issues/4443)) ([0a8122f](https://github.com/dsj1984/mandrel/commit/0a8122fb406092ff2212346b546276727d04f974))
|
|
15
|
+
* Epic [#4430](https://github.com/dsj1984/mandrel/issues/4430) ([#4470](https://github.com/dsj1984/mandrel/issues/4470)) ([8cfcd28](https://github.com/dsj1984/mandrel/commit/8cfcd28099664763d34231121ebea9f2187c437f))
|
|
16
|
+
* Epic [#4454](https://github.com/dsj1984/mandrel/issues/4454) ([#4459](https://github.com/dsj1984/mandrel/issues/4459)) ([bd57246](https://github.com/dsj1984/mandrel/commit/bd57246cdb867e62e7e2eae662c93658a54766e2))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
* **deliver:** add missing fs import in epic-deliver-prepare ([#4465](https://github.com/dsj1984/mandrel/issues/4465)) ([7b24da8](https://github.com/dsj1984/mandrel/commit/7b24da806c9859dcb75d4f5232670c2d3547d126))
|
|
22
|
+
* **delivery:** smoke-cover the prepare checklist branch + undeclared-var guard + docs-freshness hygiene ([#4471](https://github.com/dsj1984/mandrel/issues/4471)) ([d9ead77](https://github.com/dsj1984/mandrel/commit/d9ead770263bc49d210ed65038de6e454602c684)), closes [#4466](https://github.com/dsj1984/mandrel/issues/4466) [#4469](https://github.com/dsj1984/mandrel/issues/4469)
|
|
23
|
+
* **lifecycle:** restore the Epic agent::done flip + remediate post-1.88.0 robustness findings ([#4468](https://github.com/dsj1984/mandrel/issues/4468)) ([0cf9d5b](https://github.com/dsj1984/mandrel/commit/0cf9d5b499127a26c57cade13d753bd7aa6b3082))
|
|
24
|
+
* **single-story-close:** intersect wrong-tree stray paths with the Story diff (refs [#4424](https://github.com/dsj1984/mandrel/issues/4424)) ([#4434](https://github.com/dsj1984/mandrel/issues/4434)) ([a3b05a5](https://github.com/dsj1984/mandrel/commit/a3b05a5afe3175e58ad9b7e1a76bdf69637a1f0f)), closes [#4420](https://github.com/dsj1984/mandrel/issues/4420)
|
|
25
|
+
* **story-close:** make re-run against an already-closed Story a safe no-op ([#4461](https://github.com/dsj1984/mandrel/issues/4461)) ([7e6859d](https://github.com/dsj1984/mandrel/commit/7e6859d6e5a7d42b06f5781684defb88830ea16a))
|
|
26
|
+
|
|
27
|
+
## [1.88.0](https://github.com/dsj1984/mandrel/compare/mandrel-v1.87.0...mandrel-v1.88.0) (2026-07-08)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
* **delivery:** threshold-aware auto-fix remediates Medium findings on-branch (refs [#4399](https://github.com/dsj1984/mandrel/issues/4399)) ([#4400](https://github.com/dsj1984/mandrel/issues/4400)) ([34964b3](https://github.com/dsj1984/mandrel/commit/34964b3665852bf43081f6d893430ff9a0a1f630))
|
|
33
|
+
|
|
5
34
|
## [1.87.0](https://github.com/dsj1984/mandrel/compare/mandrel-v1.86.0...mandrel-v1.87.0) (2026-07-08)
|
|
6
35
|
|
|
7
36
|
|
package/lib/cli/doctor.js
CHANGED
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
import nodeFs from 'node:fs';
|
|
27
27
|
import path from 'node:path';
|
|
28
28
|
|
|
29
|
+
import {
|
|
30
|
+
resolveAlwaysLoadedClosure,
|
|
31
|
+
tierTotalBytes,
|
|
32
|
+
} from '../../.agents/scripts/lib/doc-tiers.js';
|
|
29
33
|
import { registry } from './registry.js';
|
|
30
34
|
|
|
31
35
|
// ---------------------------------------------------------------------------
|
|
@@ -78,6 +82,40 @@ function formatSummary(passed, total) {
|
|
|
78
82
|
return `❌ Not ready (${failed}/${total} checks failed)\n`;
|
|
79
83
|
}
|
|
80
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Build the one report-only line describing the always-loaded documentation
|
|
87
|
+
* closure (the `CLAUDE.md` `@`-import graph) — its file count and total size in
|
|
88
|
+
* KB. This is **informational only**: it is never counted toward the pass/fail
|
|
89
|
+
* tally and therefore never changes the doctor exit code (Story #4438). Any
|
|
90
|
+
* failure to resolve the closure degrades to a neutral line rather than
|
|
91
|
+
* throwing, so an unreadable tree never breaks the doctor run.
|
|
92
|
+
*
|
|
93
|
+
* Security (security-baseline § 5 — Data Leakage & Logging): emits only a file
|
|
94
|
+
* count and byte total, never file contents.
|
|
95
|
+
*
|
|
96
|
+
* Exported for testing.
|
|
97
|
+
*
|
|
98
|
+
* @param {{ cwd?: () => string, resolveClosure?: (root: string) => Array<{ path: string, bytes: number }> }} [opts]
|
|
99
|
+
* @returns {string} a single line terminated by `\n`
|
|
100
|
+
*/
|
|
101
|
+
export function formatClosureReport({
|
|
102
|
+
cwd = process.cwd,
|
|
103
|
+
resolveClosure = (root) => resolveAlwaysLoadedClosure(root),
|
|
104
|
+
} = {}) {
|
|
105
|
+
const label = padName('context-closure', NAME_COL);
|
|
106
|
+
let files = [];
|
|
107
|
+
try {
|
|
108
|
+
files = resolveClosure(cwd()) ?? [];
|
|
109
|
+
} catch {
|
|
110
|
+
return `ℹ ${label} always-loaded closure unavailable\n`;
|
|
111
|
+
}
|
|
112
|
+
if (files.length === 0) {
|
|
113
|
+
return `ℹ ${label} no CLAUDE.md closure found\n`;
|
|
114
|
+
}
|
|
115
|
+
const kb = (tierTotalBytes(files) / 1024).toFixed(1);
|
|
116
|
+
return `ℹ ${label} ${files.length} file(s), ${kb} KB always-loaded\n`;
|
|
117
|
+
}
|
|
118
|
+
|
|
81
119
|
// ---------------------------------------------------------------------------
|
|
82
120
|
// Result cache
|
|
83
121
|
// ---------------------------------------------------------------------------
|
|
@@ -124,6 +162,7 @@ export function writeDoctorResultCache(
|
|
|
124
162
|
* write?: (s: string) => void,
|
|
125
163
|
* exit?: (code: number) => void,
|
|
126
164
|
* writeResultCache?: (verdict: 'ready'|'unready') => void,
|
|
165
|
+
* closureReport?: () => string,
|
|
127
166
|
* }} [opts]
|
|
128
167
|
* @returns {void}
|
|
129
168
|
*/
|
|
@@ -132,6 +171,7 @@ export async function runDoctor({
|
|
|
132
171
|
write = (s) => process.stdout.write(s),
|
|
133
172
|
exit = (code) => process.exit(code),
|
|
134
173
|
writeResultCache = writeDoctorResultCache,
|
|
174
|
+
closureReport = () => formatClosureReport(),
|
|
135
175
|
} = {}) {
|
|
136
176
|
let passed = 0;
|
|
137
177
|
|
|
@@ -141,6 +181,10 @@ export async function runDoctor({
|
|
|
141
181
|
write(formatResult({ name: check.name, ...result }));
|
|
142
182
|
}
|
|
143
183
|
|
|
184
|
+
// Report-only informational line — NOT counted toward passed/total, so it
|
|
185
|
+
// never affects the doctor verdict or exit code (Story #4438).
|
|
186
|
+
write(closureReport());
|
|
187
|
+
|
|
144
188
|
const total = checks.length;
|
|
145
189
|
write(formatSummary(passed, total));
|
|
146
190
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mandrel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.89.0",
|
|
4
4
|
"description": "Claude Code-first opinionated workflow framework: instructions, personas, skills, and SDLC workflows that govern AI coding assistants.",
|
|
5
5
|
"files": [
|
|
6
6
|
".agents/",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"coverage:update": "node .agents/scripts/update-coverage-baseline.js",
|
|
31
31
|
"lint:md": "markdownlint-cli2 \".agents/**/*.md\" \"*.md\" \"!node_modules/**\" \"!.worktrees/**\"",
|
|
32
32
|
"lint": "node .agents/scripts/run-lint.js && npm run docs:check",
|
|
33
|
-
"docs:gen": "node .agents/scripts/generate-config-docs.js && node .agents/scripts/generate-lifecycle-docs.js && node .agents/scripts/generate-workflows-doc.js",
|
|
34
|
-
"docs:check": "node .agents/scripts/generate-config-docs.js --check && node .agents/scripts/generate-lifecycle-docs.js --check && node .agents/scripts/generate-workflows-doc.js --check && node .agents/scripts/check-lifecycle-doc-drift.js && node .agents/scripts/check-doc-links.js && node .agents/scripts/check-gherkin-placeholders.js && npm run skills:check",
|
|
33
|
+
"docs:gen": "node .agents/scripts/generate-config-docs.js && node .agents/scripts/generate-lifecycle-docs.js && node .agents/scripts/generate-workflows-doc.js && node .agents/scripts/generate-lens-checklists.js",
|
|
34
|
+
"docs:check": "node .agents/scripts/generate-config-docs.js --check && node .agents/scripts/generate-lifecycle-docs.js --check && node .agents/scripts/generate-workflows-doc.js --check && node .agents/scripts/generate-lens-checklists.js --check && node .agents/scripts/check-lifecycle-doc-drift.js && node .agents/scripts/check-doc-links.js && node .agents/scripts/check-gherkin-placeholders.js && npm run skills:check",
|
|
35
35
|
"skills:index": "node .agents/scripts/generate-skills-index.js",
|
|
36
36
|
"skills:check": "node .agents/scripts/generate-skills-index.js --check",
|
|
37
37
|
"format": "biome format --write .",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"maintainability:check": "node .agents/scripts/check-baselines.js --gate maintainability",
|
|
40
40
|
"maintainability:update": "node .agents/scripts/update-maintainability-baseline.js",
|
|
41
41
|
"check:arch": "node .agents/scripts/check-arch-cycles.js",
|
|
42
|
+
"check:context-budget": "node .agents/scripts/check-context-budget.js",
|
|
42
43
|
"crap:check": "node .agents/scripts/check-baselines.js --gate crap",
|
|
43
44
|
"crap:update": "node .agents/scripts/update-crap-baseline.js",
|
|
44
45
|
"duplication:check": "node .agents/scripts/check-baselines.js --gate duplication",
|