mandrel 2.4.0 → 2.5.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/audit-checklists/accessibility.md +29 -0
- package/.agents/audit-checklists/architecture.md +4 -5
- package/.agents/audit-checklists/clean-code.md +10 -0
- package/.agents/audit-checklists/data-model.md +22 -0
- package/.agents/audit-checklists/dependencies.md +11 -2
- package/.agents/audit-checklists/devops.md +4 -0
- package/.agents/audit-checklists/navigability.md +3 -0
- package/.agents/audit-checklists/performance.md +8 -11
- package/.agents/audit-checklists/privacy.md +3 -4
- package/.agents/audit-checklists/quality.md +2 -0
- package/.agents/audit-checklists/security.md +4 -5
- package/.agents/audit-checklists/seo.md +7 -1
- package/.agents/audit-checklists/sre.md +14 -12
- package/.agents/audit-checklists/ux-ui.md +4 -0
- package/.agents/docs/configuration.md +3 -0
- package/.agents/docs/workflows.md +4 -3
- package/.agents/schemas/agentrc.schema.json +17 -0
- package/.agents/schemas/audit-rules.json +134 -19
- package/.agents/schemas/audit-rules.schema.json +6 -2
- package/.agents/scripts/audit-labels-bootstrap.js +4 -4
- package/.agents/scripts/audit-to-stories.js +244 -19
- package/.agents/scripts/lib/audit-suite/checklist-threading.js +26 -3
- package/.agents/scripts/lib/audit-suite/dispatch-checklist.js +132 -0
- package/.agents/scripts/lib/audit-suite/index.js +1 -0
- package/.agents/scripts/lib/audit-suite/selector.js +290 -14
- package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +2 -1
- package/.agents/scripts/lib/audit-to-stories/build-story-body.js +5 -1
- package/.agents/scripts/lib/audit-to-stories/dedupe-against-github.js +23 -3
- package/.agents/scripts/lib/audit-to-stories/finding-adapter.js +38 -0
- package/.agents/scripts/lib/audit-to-stories/ledger.js +256 -0
- package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +41 -7
- package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +20 -2
- package/.agents/scripts/lib/command-header.js +1 -1
- package/.agents/scripts/lib/config-settings-schema-delivery.js +21 -0
- package/.agents/scripts/lib/dynamic-workflow/performance-report-contract.js +5 -3
- package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +56 -0
- package/.agents/scripts/lib/findings/route-finding.js +108 -10
- package/.agents/scripts/lib/orchestration/story-close/phases/local-lens-review.js +81 -1
- package/.agents/scripts/lib/orchestration/story-close/phases/review-core.js +1 -0
- package/.agents/scripts/nav-registry-diff.js +449 -0
- package/.agents/workflows/audit-accessibility.md +243 -0
- package/.agents/workflows/audit-architecture.md +89 -71
- package/.agents/workflows/audit-clean-code.md +87 -53
- package/.agents/workflows/audit-data-model.md +198 -0
- package/.agents/workflows/audit-dependencies.md +143 -28
- package/.agents/workflows/audit-devops.md +109 -18
- package/.agents/workflows/audit-documentation.md +25 -53
- package/.agents/workflows/audit-navigability.md +78 -22
- package/.agents/workflows/audit-performance.md +207 -103
- package/.agents/workflows/audit-privacy.md +51 -13
- package/.agents/workflows/audit-quality.md +71 -61
- package/.agents/workflows/audit-security.md +94 -71
- package/.agents/workflows/audit-seo.md +80 -25
- package/.agents/workflows/audit-sre.md +99 -66
- package/.agents/workflows/audit-to-stories.md +44 -5
- package/.agents/workflows/audit-ux-ui.md +71 -17
- package/.agents/workflows/helpers/audit-dual-path.md +59 -0
- package/.agents/workflows/helpers/audit-self-check.md +70 -0
- package/.agents/workflows/helpers/audit-severity-scale.md +19 -0
- package/.agents/workflows/helpers/deliver-story.md +25 -0
- package/docs/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/.agents/audit-checklists/lighthouse.md +0 -15
- package/.agents/schemas/audit-results.schema.json +0 -69
- package/.agents/workflows/audit-lighthouse.md +0 -269
|
@@ -210,10 +210,37 @@ workflow owns **no** parallel dedup or footer-parsing code: the
|
|
|
210
210
|
fingerprint, footer round-trip, and routing all live in that one shared
|
|
211
211
|
module.
|
|
212
212
|
|
|
213
|
+
Dedup runs in **two stages** when a provider resolves (Story #4626): a
|
|
214
|
+
meaning-first **semantic candidate** pass (`searchCandidates`, wired to
|
|
215
|
+
[`lib/findings/semantic-issue-search.js`](../scripts/lib/findings/semantic-issue-search.js))
|
|
216
|
+
runs FIRST and widens the net across open + closed issues; the exact
|
|
217
|
+
**fingerprint / semantic-key** confirmation runs SECOND. A finding whose title
|
|
218
|
+
was reworded but whose *location* is unchanged still confirms against the Issue
|
|
219
|
+
that already tracks that location, because the audit filers stamp a
|
|
220
|
+
location-based `audit-semantic-keys` footer alongside the `audit-fingerprints`
|
|
221
|
+
footer. Close-time filings from the
|
|
222
|
+
[`audit-results-graduator`](../scripts/lib/feedback-loop/audit-results-graduator.js)
|
|
223
|
+
carry the same canonical `audit-fingerprints` footer, so a sweep recognizes a
|
|
224
|
+
graduator-filed issue and never re-files it.
|
|
225
|
+
|
|
213
226
|
When no provider is available (e.g. air-gapped dev environment), pass
|
|
214
227
|
`--no-provider` to the `--scan` step — every group is classified
|
|
215
228
|
`create` and the operator is informed that dedupe was skipped.
|
|
216
229
|
|
|
230
|
+
### Cross-run ledger
|
|
231
|
+
|
|
232
|
+
The `--scan` classifications only see *live* issues. To decay findings across
|
|
233
|
+
runs — recognizing re-detections, suppressing deliberately-rejected findings,
|
|
234
|
+
and flagging genuine regressions — the sweep folds each scan onto a committed
|
|
235
|
+
**ledger** (`baselines/audit-ledger.json`, the arch-cycles-baseline envelope
|
|
236
|
+
shape). Each entry is keyed by the finding's fingerprint plus a location-based
|
|
237
|
+
`semanticKey` and carries a lifecycle `status`
|
|
238
|
+
(`new | filed | fixed | accepted-risk | regressed`). A finding whose tracking
|
|
239
|
+
Issue was closed as `not_planned` becomes `accepted-risk` and is **suppressed**
|
|
240
|
+
on every later scan; a `fixed` finding that re-appears becomes `regressed`. The
|
|
241
|
+
ledger is written by the unattended `--auto` sweep and by any `--scan --ledger`
|
|
242
|
+
run; the plain `--scan` path leaves it untouched.
|
|
243
|
+
|
|
217
244
|
## Phase 7 — Summary & cleanup
|
|
218
245
|
|
|
219
246
|
Persist `temp/audits/audit-to-stories-$(date +%Y%m%dT%H%M%S).md`
|
|
@@ -253,11 +280,23 @@ When the single-plan path ran, link the Story (or plan-run) the chained
|
|
|
253
280
|
To run an unattended maintenance sweep, `/schedule` a nightly (or weekly)
|
|
254
281
|
job that (1) runs the relevant `audit-*` lens workflows full-scope — no
|
|
255
282
|
`--paths`, no change-set filter, so the whole target-set union is audited —
|
|
256
|
-
writing their `temp/audits/audit-*-results.md` reports, then (2) invokes
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
283
|
+
writing their `temp/audits/audit-*-results.md` reports, then (2) invokes the
|
|
284
|
+
CLI's **`--auto` mode** over those results:
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
node .agents/scripts/audit-to-stories.js --auto [--dry-run] \
|
|
288
|
+
[--glob "temp/audits/audit-*-results.md"] [--severity <floor>]
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
`--auto` runs with **no interactive gates**: it resolves the severity floor
|
|
292
|
+
from `delivery.auditToStories.severityFloor` (default `high`, overridable with
|
|
293
|
+
`--severity`), applies the two-stage dedup, reconciles the cross-run ledger,
|
|
294
|
+
and prints a run-summary JSON (create / skip-open / skip-reoccurring /
|
|
295
|
+
suppressed-by-ledger tallies, plus the re-detected open Issue numbers an
|
|
296
|
+
operator may want a "re-detected" comment on). `--dry-run` performs zero GitHub
|
|
297
|
+
writes and skips the ledger write, emitting only the summary. The host
|
|
298
|
+
scheduler owns the cadence; this workflow owns the routing. (This paragraph
|
|
299
|
+
folds in the `loops/nightly-audit.md` starter unit retired in issue 4482.)
|
|
261
300
|
|
|
262
301
|
## See also
|
|
263
302
|
|
|
@@ -42,21 +42,54 @@ before this section existed.
|
|
|
42
42
|
proceed with the full codebase-wide scan defined in the remaining
|
|
43
43
|
steps.
|
|
44
44
|
|
|
45
|
-
## Step
|
|
45
|
+
## Step 0: Discover the design-system SSOT (run first)
|
|
46
|
+
|
|
47
|
+
**You cannot audit "adherence to the design system" until you have located the
|
|
48
|
+
design system.** There is no universal baseline — a hardcoded `#3b82f6` is a
|
|
49
|
+
defect only when the project defines that colour as a token. Before any
|
|
50
|
+
detection, locate the consumer's design-system sources of truth and read what
|
|
51
|
+
they define:
|
|
52
|
+
|
|
53
|
+
- **Design tokens / theme:** a `tailwind.config.{js,ts}`, CSS custom properties
|
|
54
|
+
(`:root { --color-*, --space-* }`), a `theme/`, `tokens/`, or `design-system/`
|
|
55
|
+
directory, or a `styled-system` / CSS-in-JS theme object.
|
|
56
|
+
- **Component library:** the shared component directory (`components/ui/**`,
|
|
57
|
+
a published design-system package) that raw elements are expected to defer to.
|
|
58
|
+
- **Documented conventions:** `docs/style-guide.md` (and `docs/web-routes.md`
|
|
59
|
+
when routing copy is in scope) — the human-authored rules the mechanical
|
|
60
|
+
detectors below cannot infer.
|
|
61
|
+
|
|
62
|
+
Record the token names, the component roster, and the style-guide rules. Every
|
|
63
|
+
finding downstream is measured against *this discovered baseline*, not a generic
|
|
64
|
+
ideal. If **no** design-system SSOT exists, say so and downgrade findings to
|
|
65
|
+
"no baseline defined — recommend establishing tokens/components first".
|
|
66
|
+
|
|
67
|
+
## Step 1: Mechanical detector battery, then LLM triage
|
|
46
68
|
|
|
47
69
|
> Apply [`helpers/parallel-tooling.md`](helpers/parallel-tooling.md) when batching the scan below — independent reads belong in one turn, long shells run via `run_in_background` + `Monitor`.
|
|
48
70
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
- **
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- **
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
Run the **mechanical detectors first** (cheap, deterministic greps that surface
|
|
72
|
+
candidates), then apply **LLM triage** to each candidate against the Step 0
|
|
73
|
+
baseline — a mechanical hit is a *candidate*, not automatically a finding.
|
|
74
|
+
|
|
75
|
+
- **Hardcoded Values:** grep for raw `#hex` / `rgb()` colour literals and raw
|
|
76
|
+
`px` font-size / spacing literals **outside** the token/theme files. Each hit
|
|
77
|
+
is a candidate bypass of a defined token.
|
|
78
|
+
- **Component Re-implementation:** census raw HTML elements (`<button>`,
|
|
79
|
+
`<input>`, `<select>`, `<a>` styled as a button) versus the design-system
|
|
80
|
+
component that should replace them; a high raw-vs-component ratio is the
|
|
81
|
+
signal.
|
|
82
|
+
- **Inline-style census:** count inline `style=` / `style={{…}}` usages that
|
|
83
|
+
encode spacing, colour, or typography a token should own.
|
|
84
|
+
- **Interactive States:** scan for `:hover` (or `hover:` utilities) without a
|
|
85
|
+
matching `:focus-visible` / `focus-visible:` — a hover state with no keyboard
|
|
86
|
+
focus state is a candidate accessibility-of-interaction gap.
|
|
87
|
+
- **Typography:** flag font families / weights used outside the type scale.
|
|
88
|
+
|
|
89
|
+
> **Detector output is candidates.** Triage each with the discovered baseline
|
|
90
|
+
> before promoting it to a finding — a `px` value inside a token definition file,
|
|
91
|
+
> or a raw `<button>` inside the design-system's own `Button` implementation, is
|
|
92
|
+
> expected, not a defect.
|
|
60
93
|
|
|
61
94
|
## Step 2: UX Best Practices
|
|
62
95
|
|
|
@@ -66,14 +99,23 @@ Scan frontend components for:
|
|
|
66
99
|
frustrating?
|
|
67
100
|
3. **Loading States:** Are there skeletons or spinners for async operations?
|
|
68
101
|
4. **Responsiveness:** Check layouts at mobile, tablet, and desktop breakpoints.
|
|
69
|
-
5. **Accessibility (UX-focused):** Focus on tab order, touch
|
|
70
|
-
|
|
102
|
+
5. **Accessibility (UX-focused):** Focus on tab order, touch-target sizes, and
|
|
103
|
+
whether interaction colours come from a sanctioned token. **WCAG conformance
|
|
104
|
+
is out of scope here** — semantic structure, ARIA correctness,
|
|
105
|
+
keyboard/focus operability, form labelling, media alternatives, and the WCAG
|
|
106
|
+
contrast-ratio verdict are owned by [`/audit-accessibility`](audit-accessibility.md).
|
|
107
|
+
This lens keeps token/component design-system adherence; defer every WCAG
|
|
108
|
+
success-criterion judgement to the accessibility lens so the two never
|
|
109
|
+
double-report.
|
|
71
110
|
|
|
72
111
|
## Step 3: Output Requirements
|
|
73
112
|
|
|
74
113
|
Generate and save a highly structured Markdown audit report to
|
|
75
114
|
`{{auditOutputDir}}/audit-ux-ui-results.md`, using the exact template below.
|
|
76
115
|
|
|
116
|
+
> Grade every finding's severity on the shared
|
|
117
|
+
> [`Critical | High | Medium | Low` scale](helpers/audit-severity-scale.md).
|
|
118
|
+
|
|
77
119
|
```markdown
|
|
78
120
|
# UX/UI & Design System Audit report
|
|
79
121
|
|
|
@@ -85,15 +127,17 @@ tokens/components.]
|
|
|
85
127
|
## Detailed Findings
|
|
86
128
|
|
|
87
129
|
[For every inconsistency or UX improvement identified, use the following strict
|
|
88
|
-
structure:]
|
|
130
|
+
structure. Lead each title with the primary file the finding lives in:]
|
|
89
131
|
|
|
90
|
-
### [Short
|
|
132
|
+
### `path/to/primary-file.ext` — [Short title of the issue]
|
|
91
133
|
|
|
92
134
|
- **Dimension:** [e.g., Visual Consistency | UX Best Practices | Accessibility]
|
|
93
|
-
- **Impact:** [High | Medium | Low]
|
|
135
|
+
- **Impact:** [Critical | High | Medium | Low]
|
|
136
|
+
- **Location:** `path/to/primary-file.ext:line`
|
|
94
137
|
- **Current State:** [What is currently implemented and why it is sub-optimal]
|
|
95
138
|
- **Recommendation & Rationale:** [The specific UI/UX change and how it improves
|
|
96
139
|
premium feel or usability]
|
|
140
|
+
- **Acceptance signal:** [the command or observable that proves this finding is remediated — e.g. the token now applied in the rendered component, or a re-run of this lens]
|
|
97
141
|
- **Agent Prompt:**
|
|
98
142
|
`[A copy-pasteable, highly specific prompt to execute this UI change independently]`
|
|
99
143
|
|
|
@@ -107,3 +151,13 @@ structure:]
|
|
|
107
151
|
|
|
108
152
|
This is a **read-only** audit. Provide the critique and implementation
|
|
109
153
|
suggestions, but do not modify styles or components.
|
|
154
|
+
|
|
155
|
+
## Self-cross-check (mandatory — filter false positives before you finalize)
|
|
156
|
+
|
|
157
|
+
Before you write the report artifact from the previous step, run the shared
|
|
158
|
+
adversarial self-cross-check over your Detailed Findings — see
|
|
159
|
+
[`helpers/audit-self-check.md`](helpers/audit-self-check.md). It defines the
|
|
160
|
+
per-finding evidence bar, the exclusion list, and the final re-open-and-drop
|
|
161
|
+
pass whose `kept <k> / dropped <d>` counts you record in the Executive
|
|
162
|
+
Summary, so the sequential single-pass path filters unverified findings just as
|
|
163
|
+
the orchestrated path's adversarial reviewer does.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Audit lens execution strategy (dual-path)
|
|
2
|
+
|
|
3
|
+
> **Single source for the dual-path preamble (Story #4625).** Every lens whose
|
|
4
|
+
> `## Execution strategy (dual-path)` section points here shares this exact
|
|
5
|
+
> contract. Read `audit-<lens>` and
|
|
6
|
+
> `.claude/workflows/audit-<lens>.workflow.js` below as this lens's own name.
|
|
7
|
+
|
|
8
|
+
A lens that references this helper runs along one of two execution paths. Both
|
|
9
|
+
emit the **identical** report contract (the lens's Output Requirements step);
|
|
10
|
+
downstream consumers (`audit-to-stories`) are agnostic to which path produced
|
|
11
|
+
it.
|
|
12
|
+
|
|
13
|
+
- **Orchestrated (dynamic-workflow) path.** When Claude Code's
|
|
14
|
+
[dynamic workflows](https://code.claude.com/docs/en/workflows) are
|
|
15
|
+
available, the saved project workflow
|
|
16
|
+
`.claude/workflows/audit-<lens>.workflow.js` fans the lens's dimensions out
|
|
17
|
+
as parallel read-only subagents, runs an **adversarial cross-check** stage
|
|
18
|
+
(an independent agent reviews each dimension's findings and drops false
|
|
19
|
+
positives before they enter the report), then synthesises the report. The
|
|
20
|
+
orchestrator derives its per-dimension prompts from the *lens* markdown at
|
|
21
|
+
run time — the lens stays the single source of truth; the script does not
|
|
22
|
+
fork a second copy of the spec.
|
|
23
|
+
- **Sequential (single-pass) path.** When dynamic workflows are unavailable,
|
|
24
|
+
follow the lens's Steps turn-by-turn exactly as before. This is the default
|
|
25
|
+
fallback and changes nothing about the existing behaviour.
|
|
26
|
+
|
|
27
|
+
**Strategy selection** is computed by
|
|
28
|
+
[`lib/dynamic-workflow/capability.js`](../../scripts/lib/dynamic-workflow/capability.js)
|
|
29
|
+
(`selectAuditStrategy`). The orchestrated path is chosen only when the runtime
|
|
30
|
+
is Claude Code, `disableWorkflows` is not set (settings.json **or**
|
|
31
|
+
`CLAUDE_CODE_DISABLE_WORKFLOWS`), and the Claude Code version meets the
|
|
32
|
+
research-preview floor (`>= 2.1.154`). Any other runtime, a disabled setting,
|
|
33
|
+
or an older version degrades gracefully to the sequential path.
|
|
34
|
+
|
|
35
|
+
> **Capability degradation, not a contract shim.** This dual path is **not**
|
|
36
|
+
> covered by the No-Shim / hard-cutover rule in
|
|
37
|
+
> [`git-conventions.md`](../../rules/git-conventions.md). That rule forbids
|
|
38
|
+
> running two shapes of the *same contract* side by side. Here there is **one**
|
|
39
|
+
> report contract; only the *execution strategy* is selected from a runtime
|
|
40
|
+
> capability — the same pattern the protocol already endorses for live-docs
|
|
41
|
+
> fallback in [`instructions.md` §1.C/§1.D](../../instructions.md). The full
|
|
42
|
+
> capability-degradation rationale lives in the
|
|
43
|
+
> [`capability.js`](../../scripts/lib/dynamic-workflow/capability.js) module
|
|
44
|
+
> docstring; the orchestrated-run evidence and per-lens cost/precision gate
|
|
45
|
+
> verdicts live in [`docs/roadmap.md`](../../../docs/roadmap.md) (Part 3 —
|
|
46
|
+
> Dynamic-Workflow Orchestration).
|
|
47
|
+
|
|
48
|
+
**Forcing a path (for testing).** Set `MANDREL_AUDIT_STRATEGY=sequential` to
|
|
49
|
+
verify the fallback path with the feature notionally disabled, or
|
|
50
|
+
`MANDREL_AUDIT_STRATEGY=orchestrated` to pin the dynamic path. To exercise the
|
|
51
|
+
real disable signals instead, set `CLAUDE_CODE_DISABLE_WORKFLOWS=1` (env) or
|
|
52
|
+
`disableWorkflows: true` in `.claude/settings.json` and re-run the lens — both
|
|
53
|
+
degrade to the sequential path.
|
|
54
|
+
|
|
55
|
+
> **Read-only on both paths.** The lens is read-only (see its Constraint). The
|
|
56
|
+
> orchestrated subagents run in `acceptEdits` and inherit the session tool
|
|
57
|
+
> allowlist, but the workflow script grants the analysis agents only
|
|
58
|
+
> read/search tools (`Read`, `Grep`, `Glob`) — no write/edit/shell-mutation
|
|
59
|
+
> tools. The single write in an orchestrated run is the final report artifact.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Audit finding self-cross-check (shared)
|
|
2
|
+
|
|
3
|
+
> **Single source of truth for the sequential-path false-positive guard
|
|
4
|
+
> (Story #4627).** Every non-retired audit lens references this file and runs
|
|
5
|
+
> this pass over its Detailed Findings before finalizing its report. The
|
|
6
|
+
> orchestrated dynamic-workflow path already fans out an independent
|
|
7
|
+
> adversarial reviewer; this pass gives the **sequential single-pass** path —
|
|
8
|
+
> the one consumer runs take, where the npm payload ships no per-lens
|
|
9
|
+
> `*.workflow.js` — the same false-positive filter, so a lens cannot report an
|
|
10
|
+
> unverified finding just because it ran single-pass.
|
|
11
|
+
|
|
12
|
+
You are your own adversarial reviewer. After you have drafted the Detailed
|
|
13
|
+
Findings but **before** you write the report artifact, re-open every finding
|
|
14
|
+
and hold it to the bar below. This pass is **read-only** — it filters and
|
|
15
|
+
tightens the findings you already have; it never invents new ones.
|
|
16
|
+
|
|
17
|
+
## Per-finding evidence bar (keep or drop)
|
|
18
|
+
|
|
19
|
+
Keep a finding only when **all** of the following hold. Drop it otherwise.
|
|
20
|
+
|
|
21
|
+
- **Grounded location** — it names a concrete `path:line` (or a concrete
|
|
22
|
+
symbol / config key) that you have actually read, not a hypothetical or a
|
|
23
|
+
"somewhere in the codebase" claim.
|
|
24
|
+
- **Reproducible evidence** — the problem is backed by an observable: a tool
|
|
25
|
+
reading (a baseline row, a complexity/MI/duplication number, a failing
|
|
26
|
+
command), a quoted code snippet, or a specific standard it violates. A
|
|
27
|
+
finding whose entire basis is "this looks wrong" does not clear the bar.
|
|
28
|
+
- **In-scope** — when a change-set scope filter was supplied (the `Scope`
|
|
29
|
+
block resolved to a file list), the finding lives in that scope or a direct
|
|
30
|
+
dependency the lens explicitly reasons across. A finding outside the scope
|
|
31
|
+
filter is dropped, not reported.
|
|
32
|
+
- **Actionable** — the recommendation is specific enough to execute. Drop
|
|
33
|
+
vague exhortations ("improve error handling generally") that carry no
|
|
34
|
+
concrete change.
|
|
35
|
+
|
|
36
|
+
## Exclusion list (never a finding)
|
|
37
|
+
|
|
38
|
+
Treat the following as **out of scope by construction** and drop any finding
|
|
39
|
+
that rests on one of them:
|
|
40
|
+
|
|
41
|
+
- **Sanctioned test seams** — exports consumed only by tests, and other
|
|
42
|
+
patterns the `test-seams` rule blesses. Never a production defect.
|
|
43
|
+
- **Entry points & public API surface** — CLI mains, `bin/` scripts, declared
|
|
44
|
+
`exports` / `bin` / `main`, and barrel contracts consumed out-of-tree. A
|
|
45
|
+
zero in-repo consumer count is not death.
|
|
46
|
+
- **Dynamic / framework reachability** — symbols reached via `import()`,
|
|
47
|
+
string-keyed dispatch, decorators, lifecycle listeners, or convention-loaded
|
|
48
|
+
plugin directories. Invisible to static analysis, not dead.
|
|
49
|
+
- **Intentional, documented deviations** — a pattern an in-tree comment, ADR,
|
|
50
|
+
or config explicitly sanctions. Cite it and drop the finding.
|
|
51
|
+
- **Style-only nits already enforced by a formatter/linter** — do not
|
|
52
|
+
re-litigate what the committed tooling already governs.
|
|
53
|
+
|
|
54
|
+
## Final re-open-and-drop pass (mandatory)
|
|
55
|
+
|
|
56
|
+
1. Walk your Detailed Findings once more, applying the bar and the exclusion
|
|
57
|
+
list above. Remove every finding that fails.
|
|
58
|
+
2. Count what you kept (`k`) and what you dropped (`d`).
|
|
59
|
+
3. Record the outcome in the report's **Executive Summary** as a single line:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
Self-cross-check: kept <k> / dropped <d>.
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
When `d > 0`, name the dropped findings (title + the bar/exclusion reason)
|
|
66
|
+
in one short list under that line, so the filtering is auditable and never
|
|
67
|
+
silent.
|
|
68
|
+
|
|
69
|
+
A lens that keeps every finding still records `dropped 0` — the line's absence
|
|
70
|
+
is itself a defect (it means the pass did not run).
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Audit finding severity scale (shared)
|
|
2
|
+
|
|
3
|
+
> **Single source of truth for the `Severity` axis (Story #4625).** Every audit
|
|
4
|
+
> lens report references this file so the four levels — and the parser that
|
|
5
|
+
> ranks them — never drift per lens.
|
|
6
|
+
|
|
7
|
+
Every finding grades its severity (labelled `Severity` or `Impact` on a given
|
|
8
|
+
lens) on this ordered scale. `parse-audit-md.js` recognizes every level, and a
|
|
9
|
+
surviving **Critical** finding halts the delivery gate
|
|
10
|
+
(`lib/audit-suite/findings.js#hasSurvivingCritical`).
|
|
11
|
+
|
|
12
|
+
- **Critical** — an active, exploitable, or data-losing defect that must be
|
|
13
|
+
fixed before the change can ship (e.g. a leaked secret, an auth bypass, a
|
|
14
|
+
guaranteed production outage or data-loss path).
|
|
15
|
+
- **High** — a serious correctness, security, or maintainability risk that
|
|
16
|
+
should be fixed promptly, but does not by itself block the release.
|
|
17
|
+
- **Medium** — a real problem worth scheduling; contained blast radius, or a
|
|
18
|
+
reasonable workaround exists.
|
|
19
|
+
- **Low** — minor or cosmetic; fix opportunistically.
|
|
@@ -132,6 +132,31 @@ Operator/agent responsibilities while in the worktree:
|
|
|
132
132
|
read it before you write and self-check as you author. When absent,
|
|
133
133
|
lens-aware coverage still runs maker-blind at Story-scope review inside
|
|
134
134
|
the close subprocess.
|
|
135
|
+
|
|
136
|
+
**Producing `checklistPath` at dispatch (Story #4627).** The dispatch that
|
|
137
|
+
spawns this worker threads `checklistPath` the same way it threads
|
|
138
|
+
`docsDigestPath`. Before the spawn, compute the payload from the Story's
|
|
139
|
+
predicted footprint (its `changes[]` / `references[]` path entries) with
|
|
140
|
+
`buildDispatchChecklist` and write it to the run temp dir:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
node --input-type=module -e '
|
|
144
|
+
import { buildDispatchChecklist } from "<main-repo>/.agents/scripts/lib/audit-suite/index.js";
|
|
145
|
+
import { parse } from "<main-repo>/.agents/scripts/lib/story-body/story-body.js";
|
|
146
|
+
// storyBody is the fetched Story issue body.
|
|
147
|
+
const { changes, references } = parse(process.env.STORY_BODY);
|
|
148
|
+
const { checklistPath } = buildDispatchChecklist({
|
|
149
|
+
storyId: <storyId>, changes, references, runTempDir: "temp/run-<id>",
|
|
150
|
+
});
|
|
151
|
+
console.log(checklistPath ?? "");
|
|
152
|
+
'
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
A non-empty `checklistPath` is threaded into this worker's prompt; an empty
|
|
156
|
+
footprint match prints nothing and the worker runs with no write-time
|
|
157
|
+
checklist (the maker-blind close-scope pass still covers it). The builder is
|
|
158
|
+
a pure function of the footprint and the on-disk checklists —
|
|
159
|
+
`buildDispatchChecklist` (`lib/audit-suite/dispatch-checklist.js`).
|
|
135
160
|
2. Implement the changes. When the body has a `## Slicing` / Delivery
|
|
136
161
|
Slicing table, walk rows as **intra-session checkpoints** (commit +
|
|
137
162
|
flip each row when done) — never as sibling tickets.
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [2.5.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.4.0...mandrel-v2.5.0) (2026-07-19)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
* audit findings contract: parse-visible templates, unified severity, deterministic identity, CI conformance gate ([#4625](https://github.com/dsj1984/mandrel/issues/4625)) ([#4635](https://github.com/dsj1984/mandrel/issues/4635)) ([63a4f63](https://github.com/dsj1984/mandrel/commit/63a4f639a5626467c5eb6bbb5ef1944fa431782d))
|
|
11
|
+
* **audit:** activate dormant shift-left tiers — lens delivery, checklist dispatch, self-check guard (refs [#4627](https://github.com/dsj1984/mandrel/issues/4627)) ([#4639](https://github.com/dsj1984/mandrel/issues/4639)) ([3d3b1ee](https://github.com/dsj1984/mandrel/commit/3d3b1ee1493117d11f1e1d000239fbc823c8ac64))
|
|
12
|
+
* **audit:** add audit-data-model lens with persistence-layer applicability probe (refs [#4633](https://github.com/dsj1984/mandrel/issues/4633)) ([#4644](https://github.com/dsj1984/mandrel/issues/4644)) ([c584293](https://github.com/dsj1984/mandrel/commit/c58429323b4cdde8d6aaf2358d71963c85bb7a0a))
|
|
13
|
+
* **audit:** implement advertised dependency checks, reachability-triaged vulns, and supply-chain scoped mode (refs [#4632](https://github.com/dsj1984/mandrel/issues/4632)) ([#4643](https://github.com/dsj1984/mandrel/issues/4643)) ([47f18f6](https://github.com/dsj1984/mandrel/commit/47f18f68fca3c86904ebf77b2558522f21e6b4d2))
|
|
14
|
+
* **audit:** replace audit-lighthouse with WCAG audit-accessibility lens (refs [#4634](https://github.com/dsj1984/mandrel/issues/4634)) ([#4645](https://github.com/dsj1984/mandrel/issues/4645)) ([800c69e](https://github.com/dsj1984/mandrel/commit/800c69e96701f321619febe12a4b2f9f30fd35d7))
|
|
15
|
+
* **audit:** rework audit-performance — measure-first, repo profiling, concurrency dimension (refs [#4631](https://github.com/dsj1984/mandrel/issues/4631)) ([#4642](https://github.com/dsj1984/mandrel/issues/4642)) ([ed5fd9a](https://github.com/dsj1984/mandrel/commit/ed5fd9a39b9fc4b9442484822e17553380ddccc8))
|
|
16
|
+
* **audit:** tool-first detection for ops/security lenses + SRE rewrite (refs [#4629](https://github.com/dsj1984/mandrel/issues/4629)) ([#4640](https://github.com/dsj1984/mandrel/issues/4640)) ([13d0439](https://github.com/dsj1984/mandrel/commit/13d0439b0a6adb6235cf305a16ee5abce61c919d))
|
|
17
|
+
* **audit:** tool-first detection for the code-quality lenses (refs [#4628](https://github.com/dsj1984/mandrel/issues/4628)) ([#4637](https://github.com/dsj1984/mandrel/issues/4637)) ([858f793](https://github.com/dsj1984/mandrel/commit/858f793f4d24a6b6059dc97da2067337a6937713))
|
|
18
|
+
* **audit:** tool-first detection for the seo, ux-ui, and navigability web lenses (refs [#4630](https://github.com/dsj1984/mandrel/issues/4630)) ([#4641](https://github.com/dsj1984/mandrel/issues/4641)) ([3885d22](https://github.com/dsj1984/mandrel/commit/3885d227087311de3a28bdaa4e882c69915b0a00))
|
|
19
|
+
* cross-run audit findings ledger, dedup repair, and unattended /audit-to-stories ([#4626](https://github.com/dsj1984/mandrel/issues/4626)) ([#4638](https://github.com/dsj1984/mandrel/issues/4638)) ([d8ecc2d](https://github.com/dsj1984/mandrel/commit/d8ecc2dbc23840f9ca071ce858c93a65506dfc14))
|
|
20
|
+
|
|
5
21
|
## [2.4.0](https://github.com/dsj1984/mandrel/compare/mandrel-v2.3.0...mandrel-v2.4.0) (2026-07-17)
|
|
6
22
|
|
|
7
23
|
|
package/package.json
CHANGED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<!-- GENERATED FILE — do not edit by hand.
|
|
2
|
-
Source of truth: .agents/workflows/audit-lighthouse.md
|
|
3
|
-
Regenerate: node .agents/scripts/generate-lens-checklists.js
|
|
4
|
-
Drift is gated by: npm run docs:check
|
|
5
|
-
-->
|
|
6
|
-
|
|
7
|
-
# Lighthouse Audit & Analysis — authoring checklist
|
|
8
|
-
|
|
9
|
-
> Run a Lighthouse audit (Performance / Accessibility / Best Practices / SEO) and produce a structured findings report
|
|
10
|
-
|
|
11
|
-
Self-check your change against this lens's concerns before you ship:
|
|
12
|
-
|
|
13
|
-
- [ ] Opportunities
|
|
14
|
-
- [ ] Diagnostics
|
|
15
|
-
- [ ] Failed audits
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"title": "AuditResults",
|
|
4
|
-
"description": "Standardized output format for the audit orchestration suite",
|
|
5
|
-
"type": "object",
|
|
6
|
-
"required": ["summary", "results"],
|
|
7
|
-
"additionalProperties": false,
|
|
8
|
-
"properties": {
|
|
9
|
-
"summary": {
|
|
10
|
-
"type": "object",
|
|
11
|
-
"required": [
|
|
12
|
-
"auditsRun",
|
|
13
|
-
"totalFindings",
|
|
14
|
-
"critical",
|
|
15
|
-
"high",
|
|
16
|
-
"medium",
|
|
17
|
-
"low"
|
|
18
|
-
],
|
|
19
|
-
"additionalProperties": false,
|
|
20
|
-
"properties": {
|
|
21
|
-
"auditsRun": {
|
|
22
|
-
"type": "array",
|
|
23
|
-
"items": { "type": "string" }
|
|
24
|
-
},
|
|
25
|
-
"totalFindings": { "type": "integer", "minimum": 0 },
|
|
26
|
-
"critical": { "type": "integer", "minimum": 0 },
|
|
27
|
-
"high": { "type": "integer", "minimum": 0 },
|
|
28
|
-
"medium": { "type": "integer", "minimum": 0 },
|
|
29
|
-
"low": { "type": "integer", "minimum": 0 }
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
"results": {
|
|
33
|
-
"type": "array",
|
|
34
|
-
"items": {
|
|
35
|
-
"type": "object",
|
|
36
|
-
"required": [
|
|
37
|
-
"auditId",
|
|
38
|
-
"checkId",
|
|
39
|
-
"severity",
|
|
40
|
-
"message",
|
|
41
|
-
"location",
|
|
42
|
-
"recommendation"
|
|
43
|
-
],
|
|
44
|
-
"additionalProperties": false,
|
|
45
|
-
"properties": {
|
|
46
|
-
"auditId": { "type": "string" },
|
|
47
|
-
"checkId": { "type": "string" },
|
|
48
|
-
"fixId": { "type": "string" },
|
|
49
|
-
"severity": {
|
|
50
|
-
"type": "string",
|
|
51
|
-
"enum": ["Critical", "High", "Medium", "Low", "Info"]
|
|
52
|
-
},
|
|
53
|
-
"message": { "type": "string" },
|
|
54
|
-
"location": {
|
|
55
|
-
"type": "object",
|
|
56
|
-
"required": ["file"],
|
|
57
|
-
"additionalProperties": false,
|
|
58
|
-
"properties": {
|
|
59
|
-
"file": { "type": "string" },
|
|
60
|
-
"line": { "type": "integer" },
|
|
61
|
-
"column": { "type": "integer" }
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
"recommendation": { "type": "string" }
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|