mandrel 1.88.0 → 1.90.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 +62 -27
- package/.agents/docs/configuration.md +5 -4
- 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 +10 -6
- package/.agents/schemas/audit-rules.json +16 -2
- package/.agents/schemas/audit-rules.schema.json +7 -6
- package/.agents/schemas/lifecycle/epic.blocked.schema.json +1 -1
- package/.agents/schemas/lifecycle/merge.unlanded.schema.json +39 -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/coverage-capture.js +17 -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/close-validation/gates.js +64 -24
- package/.agents/scripts/lib/config/ci.js +12 -1
- package/.agents/scripts/lib/config/runners.js +13 -5
- package/.agents/scripts/lib/config/temp-paths.js +24 -0
- package/.agents/scripts/lib/config-settings-schema-delivery.js +28 -8
- 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 +47 -15
- 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/npm-scripts.js +55 -0
- 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 +193 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/README.md +6 -0
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-armer.js +248 -13
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/automerge-predicate.js +109 -12
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/finalizer.js +47 -61
- package/.agents/scripts/lib/orchestration/lifecycle/listeners/index.js +46 -4
- 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 +246 -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/close-validation.js +5 -1
- 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/pre-merge-validation.js +8 -1
- 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 +116 -43
- package/.agents/workflows/helpers/deliver-epic.md +123 -54
- package/.agents/workflows/helpers/deliver-stories.md +26 -0
- package/.agents/workflows/helpers/epic-audit.md +116 -366
- 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 -224
- package/.agents/scripts/lib/orchestration/epic-plan-spec/phases/prompts.js +0 -58
- package/.agents/scripts/lib/signals/detectors/hotspot.js +0 -292
|
@@ -34,6 +34,7 @@ allowed_tools:
|
|
|
34
34
|
|
|
35
35
|
- Run only during `/plan` Phase 7, after `epic-plan-spec.js --emit-context` has written `temp/epic-<Epic_ID>/planner-context.json`; fail loudly if the file is missing rather than fabricating context.
|
|
36
36
|
- Write exactly three artifacts and only inside `temp/epic-<Epic_ID>/`: `techspec.md`, `risk-verdict.json`, `acceptance-spec.md`. All three MUST exist on disk before returning.
|
|
37
|
+
- **Re-emit rule (amend, don't regenerate — Story #4431).** On a re-emit — the Phase 7 persist call rejecting an artifact (e.g. a missing `## Delivery Slicing` heading, a schema-invalid risk verdict) — apply **targeted edits** to the existing `temp/epic-<Epic_ID>/` artifact that fix only what the rejection named; do NOT rewrite an artifact wholesale from a blank draft. `helpers/plan-epic.md` bounds this to **one refinement pass** per invocation (the same shape as the Epic Clarity Gate's own "one refinement pass per invocation" contract) — do not loop.
|
|
37
38
|
- Start each markdown artifact at the correct `##` heading (Tech Spec → `## Delivery Slicing`, Acceptance Spec → `## Acceptance Table` — never the Epic's own `## Acceptance Criteria` heading, which stays the ideation bullets) — never emit a top-level `#` heading. `risk-verdict.json` is raw JSON conforming to `.agents/schemas/risk-verdict.schema.json`.
|
|
38
39
|
- The Tech Spec MUST open with `## Delivery Slicing` and MUST NOT restate the Epic's Context, Goal, or Scope — your output lands as sections of the same Epic body, which travels into every downstream story agent's prompt, so any restatement is duplication and a drift risk. A `## Technical Overview` section is optional and, when present, is a 2–3 sentence orientation of the *technical approach* only (which subsystems are touched and reused), never a re-narration of the problem statement, goals, or scope.
|
|
39
40
|
- Judge risk from what the change *does* (the Epic body / Tech Spec you just wrote), never from keyword presence — "out of scope: billing" is not a billing change; "rotate the credential vault" is high-risk even without a security keyword.
|
|
@@ -75,15 +76,24 @@ reads:
|
|
|
75
76
|
Fields:
|
|
76
77
|
- `epic.id`, `epic.title`, `epic.body` (or `epic.bodySummary` when the
|
|
77
78
|
planning-context budget downgrades the body to a summary)
|
|
78
|
-
- `docsContext
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
- `docsContext` — digest-first (Story #4433, hard cutover of the § 3.1
|
|
80
|
+
planning read contract): `{ mode: 'digest', digestPath }` pointing at
|
|
81
|
+
the per-Epic docs digest (`<tempRoot>/epic-<Epic_ID>/docs-digest.md` —
|
|
82
|
+
the same file the `/deliver` story sub-agents already consume, Story
|
|
83
|
+
#4338 / #4324), or `null` when `project.docsContextFiles` is unset. Read
|
|
84
|
+
the digest at `digestPath` for "how does the codebase do X today?"
|
|
85
|
+
orientation (path, byte size, heading outline with line numbers, first
|
|
86
|
+
paragraph per `##` section), then pull the full file on demand with your
|
|
87
|
+
own Read tool — jump straight to the line the digest names — only when a
|
|
88
|
+
section bears on the spec. There is no full-content `items[]` field;
|
|
89
|
+
embedding whole/summarized doc bodies in this envelope was retired in
|
|
90
|
+
the same cutover that made the `/deliver` children digest-first.
|
|
81
91
|
- `codebaseSnapshot` — Story #2634 structural view of the consumer repo
|
|
82
92
|
(file tree, `package.json` exports + scripts, recently-touched
|
|
83
93
|
directories, detected test runner + BDD feature roots, and — at the
|
|
84
94
|
`medium` tier — per-file export signatures). Prefer module / file
|
|
85
95
|
names that appear in this snapshot over names that appear only in
|
|
86
|
-
|
|
96
|
+
the docs digest; the docs may be stale relative to the actual
|
|
87
97
|
source tree. When the spec needs to cite a file that is **not** in
|
|
88
98
|
`codebaseSnapshot.files`, surface that as a `<!-- DRIFT -->` callout
|
|
89
99
|
in the Tech Spec body naming the cited path, so the freshness gate
|
|
@@ -151,13 +161,16 @@ or (for the verdict) schema-invalid.
|
|
|
151
161
|
|
|
152
162
|
Read `temp/epic-<Epic_ID>/planner-context.json` with the `Read` tool. Pull
|
|
153
163
|
the Epic title, body (or body summary, including the Epic's `## User Stories`
|
|
154
|
-
section), the `docsContext`
|
|
164
|
+
section), and the `docsContext` digest pointer (`digestPath`, or `null`).
|
|
165
|
+
When non-null, read the digest file at `digestPath` next — that outline,
|
|
166
|
+
not the planner-context envelope, is where the actual doc orientation
|
|
167
|
+
lives; pull a full doc on demand only when a section looks relevant.
|
|
155
168
|
|
|
156
169
|
### Step 2 — Author the Tech Spec (Engineering Architect persona)
|
|
157
170
|
|
|
158
171
|
Apply the Tech Spec system prompt below to the Epic body (Context / Goal /
|
|
159
|
-
Scope / User Stories), the
|
|
160
|
-
|
|
172
|
+
Scope / User Stories), the docs digest (plus any full file pulled on
|
|
173
|
+
demand), and the `codebaseSnapshot` envelope (so the spec is
|
|
161
174
|
grounded in the actual codebase, not hallucinated patterns). Cite module
|
|
162
175
|
and file names from `codebaseSnapshot.files` / `codebaseSnapshot.signatures`
|
|
163
176
|
before reaching for names that appear only in the documentation. Write to
|
|
@@ -86,6 +86,67 @@ or a small Epic, and neither call is clearly right. **Present the choice rather
|
|
|
86
86
|
than deciding for the operator.** Do not force a verdict to avoid the third
|
|
87
87
|
option; a borderline scope surfaced as borderline is the correct output.
|
|
88
88
|
|
|
89
|
+
## Change-Request Triage Rubric
|
|
90
|
+
|
|
91
|
+
A **change request** — "fix this", "tweak that", "extend the existing X" —
|
|
92
|
+
is the common case this rubric routes cheaply: a delta against a surface the
|
|
93
|
+
project already shipped, not a from-scratch capability. Route it to `story`
|
|
94
|
+
by default when all three delta signals hold; treat any one signal's absence
|
|
95
|
+
as a prompt to re-check, not an automatic `epic` bump.
|
|
96
|
+
|
|
97
|
+
### Delta signals
|
|
98
|
+
|
|
99
|
+
- **Delta to an already-delivered surface.** The request references a
|
|
100
|
+
concrete existing capability (a module, workflow, script, or shipped
|
|
101
|
+
feature) rather than proposing a new one. "Fix the flaky retry in
|
|
102
|
+
`evidence-gate.js`" is a delta; "add a retry framework" is not.
|
|
103
|
+
- **Existing corpus covers the touched area.** The project's docs digest
|
|
104
|
+
and/or an already-closed or in-flight Epic's Tech Spec section already
|
|
105
|
+
describe the surface being changed — the standalone-Story path can draft
|
|
106
|
+
against that inherited context (`corpusContext` in the `/plan --idea`
|
|
107
|
+
envelope) instead of re-deriving architecture from a blank slate. When no
|
|
108
|
+
corpus hit exists for the touched area, that is a signal the request may
|
|
109
|
+
be reaching into genuinely new territory — re-check the `epic` signals
|
|
110
|
+
below before defaulting to `story`.
|
|
111
|
+
- **Footprint fits Story sizing.** The plausible file footprint and
|
|
112
|
+
acceptance-criteria count still fit the Story width in
|
|
113
|
+
`DEFAULT_TASK_SIZING` (per the `story` verdict signals above) — a change
|
|
114
|
+
request that fans out across independent subsystems is sized like an Epic
|
|
115
|
+
regardless of how small the originating request sounded.
|
|
116
|
+
|
|
117
|
+
### Story-verdict rationale template
|
|
118
|
+
|
|
119
|
+
Use this template to record the verdict — it names which delta signal
|
|
120
|
+
carried the call, so a reviewer can sanity-check the routing decision without
|
|
121
|
+
re-deriving it:
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
Verdict: story
|
|
125
|
+
Delta: <the existing surface this change targets>
|
|
126
|
+
Corpus hit: <docs digest section / Epic # and Tech Spec excerpt that covers
|
|
127
|
+
this area, or "none — re-checked epic signals, still story-sized">
|
|
128
|
+
Footprint: <rough file/AC count vs DEFAULT_TASK_SIZING>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Worked example
|
|
132
|
+
|
|
133
|
+
> Request: "The `/plan` standalone-Story path always drafts from a blank
|
|
134
|
+
> slate even when a change request is a small delta against something we
|
|
135
|
+
> already shipped — thread the existing docs digest and matching Epic
|
|
136
|
+
> Tech Spec sections into the draft context."
|
|
137
|
+
>
|
|
138
|
+
> ```text
|
|
139
|
+
> Verdict: story
|
|
140
|
+
> Delta: story-plan.js's --emit-context envelope and the plan-story.md
|
|
141
|
+
> Phase 2 drafting instructions — both already exist and ship today.
|
|
142
|
+
> Corpus hit: Epic #4429's own Tech Spec section (this rubric's parent
|
|
143
|
+
> Epic) already describes the docs-digest reuse pattern from
|
|
144
|
+
> orchestration/docs-digest.js.
|
|
145
|
+
> Footprint: one new lib module (planning-corpus.js), one envelope field,
|
|
146
|
+
> one helper-doc instruction — comfortably inside DEFAULT_TASK_SIZING's
|
|
147
|
+
> softFiles/softAcceptanceCount band.
|
|
148
|
+
> ```
|
|
149
|
+
|
|
89
150
|
## Handoff & no-re-triage rule
|
|
90
151
|
|
|
91
152
|
A workflow entered via a scope-triage **handoff** MUST NOT re-triage. A handoff
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"generatedAt": "2026-07-
|
|
2
|
+
"generatedAt": "2026-07-11T11:32:48.235Z",
|
|
3
3
|
"generator": "generate-skills-index.js@1",
|
|
4
4
|
"skills": [
|
|
5
5
|
{
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
"category": "core",
|
|
139
139
|
"path": ".agents/skills/core/epic-plan-decompose-author/SKILL.md",
|
|
140
140
|
"description": "Author the Story ticket JSON for an Epic from the decomposer authoring context emitted by `epic-plan-decompose.js --emit-context`. Use during Phase 8 of `/plan` when the host LLM needs to write the ticket array before `epic-plan-decompose.js` validates and persists it.",
|
|
141
|
-
"policyCapsuleBullets":
|
|
141
|
+
"policyCapsuleBullets": 15,
|
|
142
142
|
"allowedTools": ["Read", "Write", "Bash"],
|
|
143
143
|
"vendor": null
|
|
144
144
|
},
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
"category": "core",
|
|
159
159
|
"path": ".agents/skills/core/epic-plan-spec-author/SKILL.md",
|
|
160
160
|
"description": "Author the Tech Spec, Acceptance Table markdown, and risk-verdict JSON for an Epic from the planner authoring context emitted by `epic-plan-spec.js --emit-context`. Use during Phase 7 of `/plan` when the host LLM needs to write the three artifacts before `epic-plan-spec.js` folds them into the Epic body's managed sections.",
|
|
161
|
-
"policyCapsuleBullets":
|
|
161
|
+
"policyCapsuleBullets": 14,
|
|
162
162
|
"allowedTools": ["Read", "Write", "Bash"],
|
|
163
163
|
"vendor": null
|
|
164
164
|
},
|
|
@@ -135,6 +135,7 @@ node .agents/scripts/check-lifecycle-doc-drift.js
|
|
|
135
135
|
node .agents/scripts/generate-config-docs.js --check
|
|
136
136
|
node .agents/scripts/generate-lifecycle-docs.js --check
|
|
137
137
|
node .agents/scripts/generate-workflows-doc.js --check
|
|
138
|
+
node .agents/scripts/resolve-doc-tiers.js --json
|
|
138
139
|
```
|
|
139
140
|
|
|
140
141
|
Fold the results in as findings:
|
|
@@ -148,6 +149,13 @@ Fold the results in as findings:
|
|
|
148
149
|
remediation is "rerun `npm run docs:gen` / `npm run sync:commands` and
|
|
149
150
|
commit the regenerated output".
|
|
150
151
|
|
|
152
|
+
The **read-tier map** — `resolve-doc-tiers.js --json` — is not itself a
|
|
153
|
+
finding. It emits `{ tiers: { alwaysLoaded, mandatoryRead, digestVisible,
|
|
154
|
+
onDemand } }`, each a `[{ path, bytes }]` list classifying every doc by how
|
|
155
|
+
often it is loaded into agent context. Hold that map for the Context Economy
|
|
156
|
+
severity-weighting rule (Step 2.5) — it decides how much a Context-Economy
|
|
157
|
+
finding's location amplifies its cost.
|
|
158
|
+
|
|
151
159
|
This lens orchestrates the existing checkers only; it does not add new
|
|
152
160
|
deterministic checker scripts.
|
|
153
161
|
|
|
@@ -182,6 +190,56 @@ works (wrong command, deleted script, contract mismatch); **Medium** =
|
|
|
182
190
|
materially outdated description or missing coverage of a major surface;
|
|
183
191
|
**Low** = cosmetic drift, stale examples, tone/format inconsistencies.
|
|
184
192
|
|
|
193
|
+
## Step 2.5: Context Economy
|
|
194
|
+
|
|
195
|
+
Steps 1–2 verify the docs are **accurate**. This step verifies they are
|
|
196
|
+
**economical** — that a doc still earns the context every reader (human or
|
|
197
|
+
agent) pays to load it. A doc can be entirely accurate and still cost far
|
|
198
|
+
more than it returns: it accretes finished-work history, states the same fact
|
|
199
|
+
two incompatible ways, or claims an authority the code has outgrown. Flag
|
|
200
|
+
these under the three Context Economy categories below. Each carries a
|
|
201
|
+
recognition heuristic — a shape you can spot from the prose itself.
|
|
202
|
+
|
|
203
|
+
- **History Bloat:** the doc carries verbatim finished-work history that
|
|
204
|
+
crowds out its live guidance — fully-checked (all-`[x]`) checklists,
|
|
205
|
+
step-by-step phase / rollout logs, and past-tense "shipped" / "completed"
|
|
206
|
+
narratives no reader acts on anymore. Recognition: a section whose every
|
|
207
|
+
checkbox is ticked, or a changelog / decision run whose historical rows
|
|
208
|
+
dwarf the live ones. **Remediation:** apply the documentation-and-adrs
|
|
209
|
+
[Pruning & Archiving](../skills/core/documentation-and-adrs/SKILL.md#pruning--archiving)
|
|
210
|
+
convention — lift any still-live gotcha into the live doc **first**, then
|
|
211
|
+
**archive, don't delete**: relocate the verbatim history to a dated
|
|
212
|
+
`docs/archive/<name>-<YYYY-MM>.md`, collapse each completed checklist to a
|
|
213
|
+
one-line outcome, and leave a one-line pointer behind. Never prune ADRs by
|
|
214
|
+
archiving — supersede them in place.
|
|
215
|
+
- **Contradiction:** the doc states the same fact two incompatible ways, so a
|
|
216
|
+
reader cannot tell which is current. Recognition: a footnote- or
|
|
217
|
+
parenthetical-corrected table cell (a value carrying an inline `(now X)` /
|
|
218
|
+
`~~old~~` correction), or two prose statements that assert different values
|
|
219
|
+
for the same command, path, count, or contract. **Remediation:** collapse
|
|
220
|
+
to the single verified-current statement and delete the stale twin.
|
|
221
|
+
- **Authority Drift:** the doc is crowned the source of truth for a surface
|
|
222
|
+
the verified code has since outgrown — the prose still presents itself as
|
|
223
|
+
canonical, but the implementation is now the real authority. Recognition: a
|
|
224
|
+
doc that declares itself SSOT / "canonical" / "single source of truth" for
|
|
225
|
+
a contract whose current shape you had to read the code to confirm, because
|
|
226
|
+
the doc no longer matches it. **Remediation:** either re-sync the doc to the
|
|
227
|
+
code and keep the SSOT claim, or demote the claim and point at the code as
|
|
228
|
+
the authority.
|
|
229
|
+
|
|
230
|
+
### Read-tier severity weighting
|
|
231
|
+
|
|
232
|
+
A Context-Economy finding's cost scales with how often the doc is actually
|
|
233
|
+
read. Step 1 ran `resolve-doc-tiers.js --json`, which classifies every
|
|
234
|
+
target-set doc into a read tier (`alwaysLoaded`, `mandatoryRead`,
|
|
235
|
+
`digestVisible`, `onDemand`). **A finding whose doc falls in the
|
|
236
|
+
`alwaysLoaded` or `mandatoryRead` tier escalates one severity band**
|
|
237
|
+
(Low→Medium, Medium→High): bloat, contradiction, or drift in a doc every task
|
|
238
|
+
loads costs far more than the same defect in an on-demand reference. Apply the
|
|
239
|
+
escalation **after** assigning the base severity from the Step 2 guidance, and
|
|
240
|
+
name the doc's tier in the finding's Current State so the escalation is
|
|
241
|
+
auditable.
|
|
242
|
+
|
|
185
243
|
## Step 3: Output Requirements
|
|
186
244
|
|
|
187
245
|
Generate and save a highly structured Markdown audit report to
|
|
@@ -208,8 +266,8 @@ match the code), the deterministic-gate verdicts, and primary drift themes.]
|
|
|
208
266
|
|
|
209
267
|
### [Short Title of the Issue]
|
|
210
268
|
|
|
211
|
-
- **Category:** [Broken Instruction | Stale Description | Missing Coverage | Generator Drift | Link Integrity]
|
|
212
|
-
- **Impact:** [High | Medium | Low]
|
|
269
|
+
- **Category:** [Broken Instruction | Stale Description | Missing Coverage | Generator Drift | Link Integrity | History Bloat | Contradiction | Authority Drift]
|
|
270
|
+
- **Impact:** [High | Medium | Low] — for a Context Economy finding, this is the base severity **after** any read-tier escalation (Step 2.5); state the doc's tier in Current State.
|
|
213
271
|
- **Current State:** [The doc, the exact claim, and what the code actually
|
|
214
272
|
does — cite file paths and lines on both sides]
|
|
215
273
|
- **Recommendation & Rationale:** [The specific doc edit (or generator
|
|
@@ -218,6 +276,28 @@ match the code), the deterministic-gate verdicts, and primary drift themes.]
|
|
|
218
276
|
`[A copy-pasteable, highly specific prompt to execute this doc fix independently]`
|
|
219
277
|
```
|
|
220
278
|
|
|
279
|
+
## Periodic full-scope sweep
|
|
280
|
+
|
|
281
|
+
Context Economy findings accrete slowly — a doc that is lean today grows a
|
|
282
|
+
bloated tail over many Epics, and no single change-set-scoped `/deliver`
|
|
283
|
+
Phase 4 run sees the whole picture. Run this lens **full-scope** on a
|
|
284
|
+
recurring cadence so the drift is caught before it compounds:
|
|
285
|
+
|
|
286
|
+
- **Cron loop** — [`loops:nightly-audit`](loops/nightly-audit.md)
|
|
287
|
+
runs the audit sweep unattended each night; the host (`/schedule` or a
|
|
288
|
+
cron-driven `/loop`) owns the cadence. Point it at this lens full-scope
|
|
289
|
+
(no `--paths`, no change-set filter — the `{{changedFiles}}` block renders
|
|
290
|
+
the literal token, so the whole target-set union is audited).
|
|
291
|
+
- **Scheduled invocation** — `/schedule` running `/audit-documentation`
|
|
292
|
+
full-scope on a daily/weekly cron is the equivalent one-shot form when a
|
|
293
|
+
standing loop is not wired up.
|
|
294
|
+
|
|
295
|
+
Route the resulting `audit-documentation-results.md` through
|
|
296
|
+
[`/audit-to-stories`](audit-to-stories.md), which groups the findings,
|
|
297
|
+
deduplicates them against existing Issues by fingerprint, and opens
|
|
298
|
+
remediation Stories (or chains into `/plan --idea`) so the Context-Economy
|
|
299
|
+
findings land as actionable, tracked work rather than a report nobody reads.
|
|
300
|
+
|
|
221
301
|
## Constraint
|
|
222
302
|
|
|
223
303
|
This workflow is **read-only** with respect to the repository: run the
|
|
@@ -64,7 +64,7 @@ envelope via
|
|
|
64
64
|
|
|
65
65
|
It is an **input-only** signal: it changes *how thorough* the review is, never
|
|
66
66
|
the findings envelope (`{ status, severity, posted, report, halted,
|
|
67
|
-
blockerReason }`) nor the posted `
|
|
67
|
+
blockerReason }`) nor the posted `verification-results` structured-comment body. An
|
|
68
68
|
absent or malformed `depth` is treated as `standard`, so an Epic that skipped
|
|
69
69
|
`/plan` still gets a passing review with no new failure mode.
|
|
70
70
|
|
|
@@ -117,13 +117,82 @@ The pipeline will:
|
|
|
117
117
|
- Run a focused lint check on the change set.
|
|
118
118
|
- Post a structured summary report to the `[TICKET_ID]` issue.
|
|
119
119
|
|
|
120
|
+
### Step 1a — Story-scope local-lens pass (`scope: story` only, Epic #4405)
|
|
121
|
+
|
|
122
|
+
When `scope === 'story'`, the shared review spine
|
|
123
|
+
[`runStoryReviewCore`](../../scripts/lib/orchestration/story-close/phases/code-review.js)
|
|
124
|
+
runs a **shift-left local-lens pass** in the same close subprocess, *before*
|
|
125
|
+
returning the review envelope. It:
|
|
126
|
+
|
|
127
|
+
1. Enumerates the actual Story diff (`baseRef...headRef` via
|
|
128
|
+
`git diff --name-only`).
|
|
129
|
+
2. Selects the **local-tier** lenses that own a concern decidable from a single
|
|
130
|
+
Story's diff — `resolveLensTier(lens) === 'local'` **plus** the pure
|
|
131
|
+
`matchesAnyFilePattern` matcher against the diff (the audit-suite SDK's
|
|
132
|
+
[`selectLocalLenses`](../../scripts/lib/audit-suite/selector.js)). This is
|
|
133
|
+
deliberately **not** `selectAudits`: `selectAudits` unions in keyword and
|
|
134
|
+
gate matches and has no per-tier gate, so it would widen the roster past the
|
|
135
|
+
footprint-matched local set this tier owns.
|
|
136
|
+
3. Materializes the matched roster at **`light`** depth
|
|
137
|
+
(`STORY_SCOPE_LENS_DEPTH`) via `runAuditSuite`, surfacing the outcome on the
|
|
138
|
+
review envelope's `localLensReview` field.
|
|
139
|
+
|
|
140
|
+
A diff that matches no local lens adds **no** lens work (the roster is empty and
|
|
141
|
+
`runAuditSuite` is never invoked). The pass is advisory and best-effort: a git
|
|
142
|
+
or materialization failure degrades to a skipped envelope and never blocks the
|
|
143
|
+
close.
|
|
144
|
+
|
|
145
|
+
Both close entry points —
|
|
146
|
+
[`runStoryCodeReview`](../../scripts/lib/orchestration/story-close/phases/code-review.js)
|
|
147
|
+
(Epic-attached) and
|
|
148
|
+
[`runStoryScopeReview`](../../scripts/lib/orchestration/single-story-close/phases/code-review.js)
|
|
149
|
+
(standalone) — reach this pass through the single `runStoryReviewCore` spine, so
|
|
150
|
+
standalone Stories gain local-lens coverage for the first time. Because the pass
|
|
151
|
+
lives inside the close subprocess (invoked after the delivering child exits), it
|
|
152
|
+
honors the maker-blind invariant above: a maker never runs its own local-lens
|
|
153
|
+
review. This step does not apply to `scope: epic`, whose lens roster is the
|
|
154
|
+
cumulative + global + risk-routed set resolved at Epic close (Step 1b).
|
|
155
|
+
|
|
156
|
+
### Step 1b — Epic-close lens roster (`scope: epic` only, Epic #4405)
|
|
157
|
+
|
|
158
|
+
When `scope === 'epic'`, the cumulative Epic diff is walked **once** at close:
|
|
159
|
+
the Epic-close lens roster is executed as **dimensions of this same review
|
|
160
|
+
pass**, not as a separate Phase 4 walk (Story #4412 folded the standalone
|
|
161
|
+
epic-audit lens walk into this pass). Resolve and walk the roster inline:
|
|
162
|
+
|
|
163
|
+
1. Resolve the roster via [`helpers/epic-audit.md`](epic-audit.md) Step 1 —
|
|
164
|
+
run `epic-audit-prepare.js --gate gate3` and take its **`epicCloseLenses`**
|
|
165
|
+
field: the slim roster of cumulative + global + risk-routed lenses, with
|
|
166
|
+
every local-tier change-set lens excluded (routed off `resolveLensTier` in
|
|
167
|
+
[`selectEpicCloseLenses`](../../scripts/lib/orchestration/code-review.js)).
|
|
168
|
+
Local-tier concerns are already verified shift-left (write-time checklists +
|
|
169
|
+
the Story-scope local-lens pass), so they are **not** re-run here.
|
|
170
|
+
2. Materialize each rostered lens via
|
|
171
|
+
[`runAuditSuite`](../../scripts/lib/audit-suite/index.js) at the envelope's
|
|
172
|
+
`depth`, applying the `{{changedFiles}}` substitution, and walk each lens's
|
|
173
|
+
`.agents/workflows/audit-<lens>.md` procedure over the cumulative
|
|
174
|
+
`main..epic/<epicId>` diff. Global lenses (`globalLenses`, e.g.
|
|
175
|
+
`audit-navigability`) run against the WHOLE route tree, exempt from the
|
|
176
|
+
change-set narrowing.
|
|
177
|
+
3. Fold the lens findings into this pass's severity aggregate **alongside** the
|
|
178
|
+
Step 2 review pillars — one walk of the cumulative diff, one aggregate, one
|
|
179
|
+
`verification-results` comment (Step 4). An empty `epicCloseLenses` roster
|
|
180
|
+
(docs-only, or every selected lens already covered shift-left, and no
|
|
181
|
+
risk-routed lens) adds no lens dimension — the pillars still run.
|
|
182
|
+
|
|
183
|
+
This step does not apply to `scope: story` (its roster is the local-tier set of
|
|
184
|
+
Step 1a) and is skipped when `epic-audit-prepare.js` returns `degraded: true`
|
|
185
|
+
(propagate the reason and STOP, per `epic-audit.md`).
|
|
186
|
+
|
|
120
187
|
## Step 2 — Review Pillars
|
|
121
188
|
|
|
122
189
|
For each changed file, execute a strict review against four pillars. The
|
|
123
190
|
second pillar (**Integration Review**) deliberately defers the security /
|
|
124
|
-
performance / quality / coverage sweeps to the change-set-scoped
|
|
125
|
-
|
|
126
|
-
|
|
191
|
+
performance / quality / coverage sweeps to the change-set-scoped lenses — at
|
|
192
|
+
`scope: story` those ran shift-left in the Story-scope local-lens pass (Step
|
|
193
|
+
1a); at `scope: epic` they run inline in this same pass as the Epic-close lens
|
|
194
|
+
roster (Step 1b). Re-walking those sweeps a second time in this pillar is
|
|
195
|
+
duplication, not defense-in-depth.
|
|
127
196
|
|
|
128
197
|
**Apply the `depth` lever** (see **Review depth** above) to how hard you walk
|
|
129
198
|
these pillars: at `light`, focus on Pillar 1 and reduce Pillars 2–3 to a quick
|
|
@@ -151,11 +220,11 @@ The integration view depends on `scope`. The diff under review is always
|
|
|
151
220
|
against differs:
|
|
152
221
|
|
|
153
222
|
- **`scope: story`** — the diff is `epic/<epicId>..story-<storyId>` (i.e.
|
|
154
|
-
one Story's contribution to the Epic).
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
cross-Task ripple within the Story and
|
|
158
|
-
branch tip. Look for:
|
|
223
|
+
one Story's contribution to the Epic). The Story-scope local-lens pass
|
|
224
|
+
(Step 1a) has already covered the local-tier concerns; the Epic-close lens
|
|
225
|
+
roster has not run for this change set (it runs once at Epic close). The
|
|
226
|
+
integration view here focuses on cross-Task ripple within the Story and
|
|
227
|
+
contract drift against the Epic branch tip. Look for:
|
|
159
228
|
- Cross-Task contract drift inside the Story (one Task's API change vs.
|
|
160
229
|
another Task's caller in the same branch).
|
|
161
230
|
- Shared-module ripple effects from this Story onto siblings already
|
|
@@ -163,30 +232,31 @@ against differs:
|
|
|
163
232
|
- Spec deviations that the per-Task commits papered over.
|
|
164
233
|
|
|
165
234
|
- **`scope: epic`** — the diff is `main..epic/<epicId>` (the cumulative
|
|
166
|
-
Epic change set).
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
235
|
+
Epic change set). The Epic-close lens roster (`epicCloseLenses`) is walked
|
|
236
|
+
**inline as part of this pass** (Step 1b) — the cumulative diff is read once,
|
|
237
|
+
and the security, privacy, performance, code-quality, and test-coverage
|
|
238
|
+
findings the rostered lenses produce feed this pass's aggregate directly.
|
|
239
|
+
There is no separate `audit-results` comment to read (Story #4412 retired it);
|
|
240
|
+
the lens findings and the pillar findings share the single
|
|
241
|
+
`verification-results` comment this pass posts.
|
|
173
242
|
|
|
174
243
|
The integration view at epic scope is what the per-lens audits cannot
|
|
175
244
|
produce because each lens runs in isolation:
|
|
176
245
|
|
|
177
|
-
- Cross-reference 🔴 / 🟠
|
|
246
|
+
- Cross-reference 🔴 / 🟠 lens findings against the spec deviations
|
|
178
247
|
flagged in Pillar 1 — a finding that traces back to a deliberate
|
|
179
248
|
Tech-Spec decision is different from one that traces back to an
|
|
180
249
|
oversight.
|
|
181
250
|
- Look for cross-cutting concerns no single lens owns: contract drift
|
|
182
251
|
between Stories, shared-module ripple effects, boundary changes that
|
|
183
252
|
thread security and performance implications together.
|
|
184
|
-
- Note any
|
|
253
|
+
- Note any lens finding that the operator's remediation flow should
|
|
185
254
|
bundle (e.g. one refactor closes findings from multiple lenses).
|
|
186
255
|
|
|
187
|
-
If the Epic
|
|
188
|
-
|
|
189
|
-
|
|
256
|
+
If the Epic-close roster is empty (docs-only Epic, every selected lens
|
|
257
|
+
already covered shift-left, or the pass was skipped via
|
|
258
|
+
`--skip-epic-audit` / `--skip-code-review`), record that explicitly in the
|
|
259
|
+
findings report and proceed — there is no lens dimension to integrate.
|
|
190
260
|
|
|
191
261
|
### Pillar 3: Documentation Integrity
|
|
192
262
|
|
|
@@ -261,9 +331,11 @@ prior baseline before merging.
|
|
|
261
331
|
|
|
262
332
|
## Step 4 — Produce Findings Report
|
|
263
333
|
|
|
264
|
-
Findings are **persisted as a `
|
|
265
|
-
`[TICKET_ID]` issue** by `runCodeReview
|
|
266
|
-
|
|
334
|
+
Findings are **persisted as a `verification-results` structured comment on
|
|
335
|
+
the `[TICKET_ID]` issue** by `runCodeReview` (the unified findings contract of
|
|
336
|
+
Story #4411; at `scope: epic` this single comment also carries the Step 1b
|
|
337
|
+
Epic-close lens findings). The target ticket is the Story when
|
|
338
|
+
`scope === 'story'` and the Epic when `scope === 'epic'`. The comment
|
|
267
339
|
is idempotent — re-runs replace the prior one — and its body includes
|
|
268
340
|
severity-tier counts plus the full findings list so downstream workflows
|
|
269
341
|
(notably the retro helper) can summarise blockers/high findings without
|
|
@@ -299,7 +371,8 @@ Findings that Step 4.5 remediated on `[HEAD_REF]` MUST be rendered under a
|
|
|
299
371
|
dedicated **`## Fixed on-branch`** heading, **not** in the severity groups
|
|
300
372
|
above. This is the contract seam that keeps remediated findings from
|
|
301
373
|
spawning ghost follow-up issues: the
|
|
302
|
-
[
|
|
374
|
+
[audit-results graduator](../../scripts/lib/feedback-loop/audit-results-graduator.js)
|
|
375
|
+
(the sole canonical reader of the unified comment)
|
|
303
376
|
skips every entry inside this section (both because a fixed entry is
|
|
304
377
|
rendered with a **✅ prefix** — so it carries no leading severity emoji the
|
|
305
378
|
parser would match — and because the parser has an explicit
|
|
@@ -322,8 +395,8 @@ their leading severity emoji so the graduator still files them.
|
|
|
322
395
|
|
|
323
396
|
There is **no runtime auto-fix function** at this phase. The host LLM is
|
|
324
397
|
the executor: it decides, per finding, between a focused fix on
|
|
325
|
-
`[HEAD_REF]` and leaving the finding on the `
|
|
326
|
-
comment for the operator.
|
|
398
|
+
`[HEAD_REF]` and leaving the finding on the `verification-results`
|
|
399
|
+
structured comment for the operator.
|
|
327
400
|
|
|
328
401
|
### Resolve the remediation threshold (Story #4399)
|
|
329
402
|
|
|
@@ -348,7 +421,7 @@ Cutovers — no back-compat flag; `high` is opt-in to the old routing.
|
|
|
348
421
|
### 🔴 / 🟠 findings — per-finding ceremony (unchanged)
|
|
349
422
|
|
|
350
423
|
For each 🔴 / 🟠 finding from Step 4, decide between two paths and keep the
|
|
351
|
-
`
|
|
424
|
+
`verification-results` structured comment authoritative for anything not fixed
|
|
352
425
|
in-place.
|
|
353
426
|
|
|
354
427
|
1. **Apply a focused fix on `[HEAD_REF]`.** Permitted only when the
|
|
@@ -401,8 +474,8 @@ ceremony above:
|
|
|
401
474
|
findings stay on the comment for Step 5.
|
|
402
475
|
|
|
403
476
|
Record every remediated finding (🟠 or 🟡) in the **"Fixed on-branch"**
|
|
404
|
-
section of the `
|
|
405
|
-
follow-up issue.
|
|
477
|
+
section of the `verification-results` comment (Step 4) so it does not graduate
|
|
478
|
+
to a follow-up issue.
|
|
406
479
|
|
|
407
480
|
Do not invent a programmatic retry budget. The host LLM applies *at most
|
|
408
481
|
one* focused-fix attempt per finding (or per batched finding) before
|
|
@@ -413,18 +486,18 @@ consumers) see exactly why each one was not auto-remediated.
|
|
|
413
486
|
## Step 4.6 — Cross-phase re-check trigger
|
|
414
487
|
|
|
415
488
|
After the focused-fix routing in Step 4.5 completes, any host-LLM-applied
|
|
416
|
-
fix commits have modified files on `[HEAD_REF]` that the
|
|
417
|
-
|
|
418
|
-
of one or more lenses (e.g. a fix landing in `**/auth/*.js`
|
|
419
|
-
`audit-security` lens). When that happens, the
|
|
420
|
-
|
|
421
|
-
non-overlapping findings remain authoritative and MUST NOT be
|
|
489
|
+
fix commits have modified files on `[HEAD_REF]` that the Epic-close lens
|
|
490
|
+
roster already walked (Step 1b). Some of those edits may overlap the
|
|
491
|
+
`filePatterns` of one or more lenses (e.g. a fix landing in `**/auth/*.js`
|
|
492
|
+
overlaps the `audit-security` lens). When that happens, the lens findings in
|
|
493
|
+
the `verification-results` comment are **stale for the overlapping lenses
|
|
494
|
+
only** — the non-overlapping findings remain authoritative and MUST NOT be
|
|
422
495
|
re-derived.
|
|
423
496
|
|
|
424
497
|
> **Scope note.** This cross-phase re-check applies only when
|
|
425
|
-
> `scope === 'epic'`. Story-scope reviews
|
|
426
|
-
>
|
|
427
|
-
>
|
|
498
|
+
> `scope === 'epic'`. Story-scope reviews carry no Epic-close lens roster,
|
|
499
|
+
> so there is nothing to invalidate; skip this step entirely for
|
|
500
|
+
> `scope === 'story'`.
|
|
428
501
|
|
|
429
502
|
Invoke the re-check selector with the cumulative set of paths touched by
|
|
430
503
|
the focused-fix commits:
|
|
@@ -445,11 +518,11 @@ no-op.
|
|
|
445
518
|
When `selectedAudits` is non-empty:
|
|
446
519
|
|
|
447
520
|
1. Re-invoke each listed lens prompt under
|
|
448
|
-
[`../audit-*.md`](../) the same way
|
|
521
|
+
[`../audit-*.md`](../) the same way the Step 1b Epic-close walk does —
|
|
449
522
|
one lens at a time, against the current `[HEAD_REF]` tip.
|
|
450
523
|
2. **Append** a `## Cross-phase re-check` section to the **existing**
|
|
451
|
-
`
|
|
452
|
-
a new comment; the comment is idempotent and downstream consumers
|
|
524
|
+
`verification-results` structured comment on the Epic ticket. Do **not**
|
|
525
|
+
post a new comment; the comment is idempotent and downstream consumers
|
|
453
526
|
(the code-review trim, `/deliver` Pillar 2, the retro helper)
|
|
454
527
|
read it once. The append carries the re-checked lens names, the new
|
|
455
528
|
findings (if any), and the focused-fix commit SHAs that triggered the
|
|
@@ -459,7 +532,7 @@ When `selectedAudits` is non-empty:
|
|
|
459
532
|
through Step 4.5's focused-fix routing. Findings that already
|
|
460
533
|
received a focused-fix attempt in the first pass do not get a fresh
|
|
461
534
|
attempt when the cross-phase re-check resurfaces an adjacent one —
|
|
462
|
-
leave them on the `
|
|
535
|
+
leave them on the `verification-results` comment for the operator.
|
|
463
536
|
|
|
464
537
|
If `selectedAudits` is empty, skip silently and proceed to Step 5. The
|
|
465
538
|
re-check trigger is **read-only signal** — it never mutates the Epic
|