mandrel 2.6.0 → 2.8.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 +104 -330
- package/.agents/agents/auditor.md +135 -0
- package/.agents/agents/plan-critic.md +80 -0
- package/.agents/audit-checklists/dependencies.md +7 -0
- package/.agents/audit-checklists/documentation.md +1 -0
- package/.agents/docs/SDLC.md +69 -162
- package/.agents/docs/configuration.md +133 -499
- package/.agents/docs/quality-gates.md +59 -180
- package/.agents/instructions.md +170 -295
- package/.agents/rules/changelog-style.md +8 -66
- package/.agents/rules/ci-remediation.md +65 -124
- package/.agents/rules/gherkin-standards.md +10 -31
- package/.agents/rules/git-conventions-reference.md +28 -61
- package/.agents/rules/git-conventions.md +1 -1
- package/.agents/rules/orchestration-error-handling.md +5 -15
- package/.agents/rules/security-baseline.md +7 -13
- package/.agents/rules/shell-conventions.md +4 -13
- package/.agents/rules/test-seams.md +2 -2
- package/.agents/rules/testing-standards.md +7 -17
- package/.agents/scripts/lib/feedback-loop/audit-results-graduator.js +7 -2
- package/.agents/scripts/lib/feedback-loop/graduator-core.js +144 -12
- package/.agents/scripts/lib/feedback-loop/retro-proposals-graduator.js +11 -1
- package/.agents/scripts/lib/observability/runtime-friction.js +97 -36
- package/.agents/scripts/lib/orchestration/single-story-close/phases/post-land.js +29 -5
- package/.agents/skills/core/api-and-interface-design/SKILL.md +23 -297
- package/.agents/skills/core/api-and-interface-design/reference.md +76 -0
- package/.agents/skills/core/browser-testing-with-devtools/SKILL.md +20 -327
- package/.agents/skills/core/browser-testing-with-devtools/reference.md +74 -0
- package/.agents/skills/core/code-review-and-quality/reference.md +16 -398
- package/.agents/skills/core/debugging-and-error-recovery/reference.md +14 -281
- package/.agents/skills/core/documentation-and-adrs/reference.md +42 -338
- package/.agents/skills/core/git-workflow-and-versioning/SKILL.md +28 -326
- package/.agents/skills/core/idea-refinement/SKILL.md +67 -193
- package/.agents/skills/core/security-and-hardening/SKILL.md +15 -31
- package/.agents/skills/core/security-and-hardening/reference.md +15 -273
- package/.agents/skills/skills.index.json +5 -5
- package/.agents/skills/stack/qa/gherkin-authoring/SKILL.md +16 -222
- package/.agents/skills/stack/qa/gherkin-authoring/reference.md +157 -0
- package/.agents/skills/stack/qa/playwright/SKILL.md +0 -29
- package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +19 -23
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +35 -53
- package/.agents/skills/stack/qa/vitest/SKILL.md +0 -29
- package/.agents/workflows/audit-accessibility.md +34 -108
- package/.agents/workflows/audit-architecture.md +35 -123
- package/.agents/workflows/audit-clean-code.md +19 -78
- package/.agents/workflows/audit-data-model.md +32 -100
- package/.agents/workflows/audit-dependencies.md +47 -111
- package/.agents/workflows/audit-devops.md +16 -83
- package/.agents/workflows/audit-documentation.md +46 -93
- package/.agents/workflows/audit-navigability.md +26 -80
- package/.agents/workflows/audit-performance.md +40 -106
- package/.agents/workflows/audit-privacy.md +17 -80
- package/.agents/workflows/audit-quality.md +35 -99
- package/.agents/workflows/audit-security.md +20 -78
- package/.agents/workflows/audit-seo.md +20 -98
- package/.agents/workflows/audit-sre.md +20 -88
- package/.agents/workflows/audit-to-stories.md +1 -8
- package/.agents/workflows/audit-ux-ui.md +17 -80
- package/.agents/workflows/deliver.md +54 -9
- package/.agents/workflows/git-cleanup.md +50 -275
- package/.agents/workflows/helpers/audit-lens-core.md +230 -0
- package/.agents/workflows/helpers/code-review.md +11 -23
- package/.agents/workflows/helpers/deliver-story-reference.md +114 -17
- package/.agents/workflows/helpers/deliver-story.md +26 -186
- package/.agents/workflows/helpers/qa-core.md +174 -0
- package/.agents/workflows/helpers/qa-run-scenario-reference.md +35 -0
- package/.agents/workflows/helpers/qa-run-scenario.md +11 -25
- package/.agents/workflows/helpers/worktree-lifecycle.md +6 -67
- package/.agents/workflows/mandrel-update.md +7 -13
- package/.agents/workflows/plan.md +17 -15
- package/.agents/workflows/qa-assist.md +140 -269
- package/.agents/workflows/qa-explore.md +125 -316
- package/.agents/workflows/qa-run.md +180 -380
- package/docs/CHANGELOG.md +18 -0
- package/package.json +1 -1
- package/.agents/workflows/helpers/audit-dual-path.md +0 -59
- package/.agents/workflows/helpers/audit-self-check.md +0 -70
- package/.agents/workflows/helpers/audit-severity-scale.md +0 -19
package/.agents/README.md
CHANGED
|
@@ -234,48 +234,17 @@ system-prompt mechanism (`.cursorrules`, Custom Instructions, etc.).
|
|
|
234
234
|
### What to always-load vs read on-demand
|
|
235
235
|
|
|
236
236
|
The always-loaded context is re-paid on every session **and every subagent
|
|
237
|
-
spawn**, so the shipped set is kept deliberately lean.
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
**Read on-demand (do the read before the matching work):**
|
|
250
|
-
|
|
251
|
-
- [`rules/shell-conventions.md`](rules/shell-conventions.md) — before chaining
|
|
252
|
-
shell commands or writing cross-platform command strings.
|
|
253
|
-
- [`rules/testing-standards.md`](rules/testing-standards.md) — before authoring
|
|
254
|
-
or restructuring tests.
|
|
255
|
-
- [`rules/orchestration-error-handling.md`](rules/orchestration-error-handling.md)
|
|
256
|
-
— before writing or modifying orchestration scripts under
|
|
257
|
-
`.agents/scripts/**`.
|
|
258
|
-
- The remaining domain rules
|
|
259
|
-
([`rules/api-conventions.md`](rules/api-conventions.md),
|
|
260
|
-
[`rules/gherkin-standards.md`](rules/gherkin-standards.md),
|
|
261
|
-
[`rules/changelog-style.md`](rules/changelog-style.md),
|
|
262
|
-
[`rules/test-seams.md`](rules/test-seams.md)) — when the task is in that
|
|
263
|
-
domain.
|
|
264
|
-
- Every `SKILL.md` under [`skills/`](skills/) — when the task hits its trigger.
|
|
265
|
-
A `SKILL.md` is itself split the same way: it leads with its **Policy
|
|
266
|
-
Capsule** (the contract, and the whole cost of activating the skill) plus
|
|
267
|
-
pointers into an on-demand `reference.md` sibling carrying the long-form
|
|
268
|
-
material. Activating a skill costs the capsule, not the essay — open a
|
|
269
|
-
`reference.md` section only when the task engages it. Routing does not
|
|
270
|
-
depend on the long-form being inline: skill descriptions live in the
|
|
271
|
-
generated [`skills/skills.index.json`](skills/skills.index.json).
|
|
272
|
-
- [`docs/execution-reference.md`](docs/execution-reference.md) — log-level and
|
|
273
|
-
token-budget reference detail lifted out of `instructions.md`.
|
|
274
|
-
|
|
275
|
-
Each on-demand rule opens with a one-line "this rule applies when…" scope
|
|
276
|
-
header, so a quick skim of its first paragraph tells you whether it governs the
|
|
277
|
-
task at hand. `instructions.md` § 1.F is the canonical in-prompt statement of
|
|
278
|
-
this split.
|
|
237
|
+
spawn**, so the shipped set is kept deliberately lean. The recommended core to
|
|
238
|
+
load into your system prompt is [`instructions.md`](instructions.md),
|
|
239
|
+
[`rules/security-baseline.md`](rules/security-baseline.md), and
|
|
240
|
+
[`rules/git-conventions.md`](rules/git-conventions.md). Read everything else —
|
|
241
|
+
the on-demand rules, every `SKILL.md` under [`skills/`](skills/) (each split
|
|
242
|
+
into a Policy Capsule plus an on-demand `reference.md`; descriptions live in
|
|
243
|
+
[`skills/skills.index.json`](skills/skills.index.json)), and
|
|
244
|
+
[`docs/execution-reference.md`](docs/execution-reference.md) — only when the
|
|
245
|
+
task engages it. Each on-demand rule opens with a one-line "this rule applies
|
|
246
|
+
when…" scope header. `instructions.md` § 1.F is the canonical statement of
|
|
247
|
+
this split and enumerates the full always-on / on-demand rule set.
|
|
279
248
|
|
|
280
249
|
---
|
|
281
250
|
|
|
@@ -350,18 +319,13 @@ in `runtime-deps.json`.
|
|
|
350
319
|
|
|
351
320
|
## Ticket Hierarchy
|
|
352
321
|
|
|
353
|
-
Orchestration and planning are **Story-only** (`type::story`)
|
|
322
|
+
Orchestration and planning are **Story-only** (`type::story`) — `/plan`
|
|
354
323
|
persists Stories with inline `acceptance[]` / `verify[]` and a folded
|
|
355
|
-
`## Spec`; `/deliver` runs `helpers/deliver-story` on
|
|
356
|
-
`
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
`
|
|
360
|
-
footer are refused by `/deliver` and must be closed or re-planned as
|
|
361
|
-
v2 Stories.
|
|
362
|
-
|
|
363
|
-
See [`docs/SDLC.md`](docs/SDLC.md) and [`instructions.md` § 5.D](instructions.md)
|
|
364
|
-
for the execution-model contract.
|
|
324
|
+
`## Spec`; `/deliver` runs `helpers/deliver-story` on `story-<id>` → PR →
|
|
325
|
+
`main`. There is no `type::epic` / `type::task` label, Epic issue form, or
|
|
326
|
+
`epic/<id>` integration branch; a ticket carrying an `Epic: #N` footer is
|
|
327
|
+
refused by `/deliver`. The execution-model contract is owned by
|
|
328
|
+
[`instructions.md` § 5.D](instructions.md) and [`docs/SDLC.md`](docs/SDLC.md).
|
|
365
329
|
|
|
366
330
|
---
|
|
367
331
|
|
|
@@ -623,41 +587,21 @@ Module boundary rules:
|
|
|
623
587
|
|
|
624
588
|
## Baselines
|
|
625
589
|
|
|
626
|
-
The framework's quality gates compare against per-kind baseline files
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
([
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
contract, kernel-version friction, and — most relevant to consumers — the
|
|
638
|
-
**floor override** path. Consumers add a `floors` block
|
|
639
|
-
(and optional `components`) under their gate in `.agentrc.json`:
|
|
640
|
-
|
|
641
|
-
```json
|
|
642
|
-
{
|
|
643
|
-
"delivery": {
|
|
644
|
-
"quality": {
|
|
645
|
-
"gates": {
|
|
646
|
-
"coverage": {
|
|
647
|
-
"floors": { "*": { "lines": 90, "branches": 85 } },
|
|
648
|
-
"components": { "api": ["src/api/**"] }
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
```
|
|
655
|
-
|
|
590
|
+
The framework's quality gates compare against per-kind baseline files under
|
|
591
|
+
`baselines/<kind>.json` (lint, coverage, crap, maintainability, mutation,
|
|
592
|
+
lighthouse, bundle-size), all sharing one envelope and funnelled through a
|
|
593
|
+
shared reader / writer
|
|
594
|
+
([`reader.js`](scripts/lib/baselines/reader.js) /
|
|
595
|
+
[`writer.js`](scripts/lib/baselines/writer.js)). The full reference — envelope
|
|
596
|
+
shape, per-kind axes, component model, path canonicalisation, writer/reader
|
|
597
|
+
contract, kernel-version friction, and the consumer **floor override** path
|
|
598
|
+
(add a `floors` block, and optional `components`, under your gate in
|
|
599
|
+
`.agentrc.json`) — is owned by
|
|
600
|
+
[`quality-gates.md` § Baseline reference](docs/quality-gates.md#baseline-reference).
|
|
656
601
|
The unified runtime gate
|
|
657
|
-
[
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
follow-up **Epic #1943**.
|
|
602
|
+
[`check-baselines.js`](scripts/check-baselines.js) currently runs floor +
|
|
603
|
+
tolerance + schema + kernel-mismatch checks only; full regression absorption
|
|
604
|
+
and per-kind CLI deletion are tracked in **Epic #1943**.
|
|
661
605
|
|
|
662
606
|
---
|
|
663
607
|
|
|
@@ -694,155 +638,31 @@ Schema conventions:
|
|
|
694
638
|
## Code review providers (pluggable chain)
|
|
695
639
|
|
|
696
640
|
`runCodeReview()` (invoked from `helpers/deliver-story` and `/deliver`'s
|
|
697
|
-
risk-routed ceremony) loads its review backend through a pluggable registry
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
`
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
```json
|
|
705
|
-
{
|
|
706
|
-
"delivery": {
|
|
707
|
-
"codeReview": {
|
|
708
|
-
"providers": [
|
|
709
|
-
{ "name": "native" },
|
|
710
|
-
{ "name": "security-review", "scopes": ["story"], "optional": true },
|
|
711
|
-
{
|
|
712
|
-
"name": "ultrareview",
|
|
713
|
-
"scopes": ["story"],
|
|
714
|
-
"manualPrompt": true,
|
|
715
|
-
"when": { "label": "risk::high" }
|
|
716
|
-
}
|
|
717
|
-
]
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
```
|
|
722
|
-
|
|
723
|
-
Each chain entry accepts:
|
|
724
|
-
|
|
725
|
-
- `name` (required) — registered key. Inline: `native`, `codex`,
|
|
726
|
-
`security-review`. Manual-prompt: `ultrareview`.
|
|
727
|
-
- `scopes` — invocation scopes this entry fires on (`["story", "epic"]`).
|
|
728
|
-
Default is both.
|
|
729
|
-
- `optional` — when `true`, a construction failure (host missing the
|
|
730
|
-
required CLI/plugin) is logged and the entry is skipped instead of
|
|
731
|
-
hard-failing the chain. Use for portable configs that ship across
|
|
732
|
-
Claude and non-Claude runtimes — for example,
|
|
733
|
-
`security-review` requires the `claude` CLI on PATH and degrades
|
|
734
|
-
cleanly on a non-Claude host when `optional: true`.
|
|
735
|
-
- `manualPrompt` — when `true`, the entry is loaded from the
|
|
736
|
-
manual-prompt registry and contributes a one-line operator suggestion
|
|
737
|
-
via `renderPrompt()` instead of running a real review. Manual-prompt
|
|
738
|
-
contributions do NOT affect severity counts or the `halted` gate.
|
|
739
|
-
- `when` — optional label predicate evaluated at invocation time
|
|
740
|
-
against the ticket's labels (`when.label` for a single required
|
|
741
|
-
label, `when.labelAny` for "any of these"). False predicates skip
|
|
742
|
-
the entry silently for that run.
|
|
743
|
-
|
|
744
|
-
Cross-runtime contract: manual-prompt providers (e.g. `ultrareview`)
|
|
745
|
-
emit Markdown only and MUST NEVER throw under any host. Inline
|
|
746
|
-
providers that require a host-specific binary (e.g.
|
|
747
|
-
`security-review` shells out to `claude --print /security-review`)
|
|
748
|
-
SHOULD be declared `optional: true` so non-Claude consumers can pin
|
|
749
|
-
the same `.agents/` version without modifying their config.
|
|
750
|
-
|
|
751
|
-
The pluggable backend was introduced in Epic #2815; the multi-provider
|
|
752
|
-
chain, `security-review`, and `ultrareview` were added in Story #2871.
|
|
753
|
-
|
|
754
|
-
---
|
|
641
|
+
risk-routed ceremony) loads its review backend through a pluggable registry
|
|
642
|
+
configured via `delivery.codeReview.providers` — an array of entries iterated
|
|
643
|
+
in declaration order. The chain-entry field semantics (`name`, `scopes`,
|
|
644
|
+
`optional`, `manualPrompt`, `when`), the fix budget, and the cross-runtime
|
|
645
|
+
contract are documented once in
|
|
646
|
+
[`docs/configuration.md` § delivery.codeReview](docs/configuration.md#deliverycodereview--provider-chain).
|
|
755
647
|
|
|
756
648
|
## Feedback loop — verification-results auto-graduation
|
|
757
649
|
|
|
758
|
-
When a Story (or plan-run) finalize path runs, non-blocking findings
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
`
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
`true`. (The former `codeReviewAutoFile` key was retired with its
|
|
766
|
-
graduator when the pass unified — a config carrying it fails validation;
|
|
767
|
-
delete the key.)
|
|
768
|
-
|
|
769
|
-
To opt out (for example, to triage findings manually during a
|
|
770
|
-
stabilization window), set the toggle to `false` in your root
|
|
771
|
-
`.agentrc.json`:
|
|
772
|
-
|
|
773
|
-
```json
|
|
774
|
-
{
|
|
775
|
-
"delivery": {
|
|
776
|
-
"feedbackLoop": {
|
|
777
|
-
"auditResultsAutoFile": false
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
```
|
|
782
|
-
|
|
783
|
-
When disabled, the listener short-circuits and leaves the
|
|
784
|
-
`verification-results` comment on the Story ticket untouched. Re-enabling
|
|
785
|
-
the toggle is safe: the graduator embeds a content-derived idempotency
|
|
786
|
-
marker in each filed issue body, so re-runs skip findings that already
|
|
787
|
-
have an issue.
|
|
788
|
-
|
|
789
|
-
---
|
|
650
|
+
When a Story (or plan-run) finalize path runs, non-blocking findings that
|
|
651
|
+
survived merge are auto-graduated into follow-up issues in a single pass over
|
|
652
|
+
the unified `verification-results` structured comment, routed by source
|
|
653
|
+
classification into the framework or consumer repo. The toggle
|
|
654
|
+
(`delivery.feedbackLoop.auditResultsAutoFile`, default `true`), the opt-out
|
|
655
|
+
example, and the idempotency-marker behaviour are documented once in
|
|
656
|
+
[`docs/configuration.md` § delivery.feedbackLoop](docs/configuration.md#deliveryfeedbackloop--verification-results-auto-graduation).
|
|
790
657
|
|
|
791
658
|
## Worktree dependency strategies
|
|
792
659
|
|
|
793
|
-
When `delivery.worktreeIsolation.enabled` is `true`, each Story runs in
|
|
794
|
-
|
|
795
|
-
`
|
|
796
|
-
`
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
| Strategy | When to use | Cold-start cost | Notes |
|
|
800
|
-
| -------------- | ---------------------------------------------------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------- |
|
|
801
|
-
| `clone` | **Shipped default on darwin/linux** — copy-on-write clone of donor `node_modules`. | Near-zero on APFS/reflink FS. | Falls back to `per-worktree` on unsupported filesystems or cross-volume clones. |
|
|
802
|
-
| `per-worktree` | Default on Windows; also the safe fallback everywhere. | Full `npm ci` per Story. | Each worktree gets an independent `node_modules`. |
|
|
803
|
-
| `symlink` | npm/yarn repos that want the fast path. **Opt-in.** | Near-zero. | Junctions a single donor `node_modules` into each worktree. Refuses on Windows unless explicitly opted in. |
|
|
804
|
-
| `pnpm-store` | pnpm repos. **Opt-in.** | Fast (store-backed). | Runs `pnpm install --frozen-lockfile` against the shared content-addressable store. |
|
|
805
|
-
|
|
806
|
-
The **shipped consumer default in
|
|
807
|
-
[`.agents/docs/agentrc-reference.json`](./docs/agentrc-reference.json) is
|
|
808
|
-
`clone`** (Windows resolves to `per-worktree` via the platform-aware
|
|
809
|
-
accessor). Repos that use pnpm or want symlink semantics should set
|
|
810
|
-
`nodeModulesStrategy` explicitly in their root `.agentrc.json`.
|
|
811
|
-
|
|
812
|
-
### Symlink opt-in (npm / yarn)
|
|
813
|
-
|
|
814
|
-
To opt in, set three fields on `delivery.worktreeIsolation` in your root
|
|
815
|
-
`.agentrc.json`:
|
|
816
|
-
|
|
817
|
-
```json
|
|
818
|
-
{
|
|
819
|
-
"delivery": {
|
|
820
|
-
"worktreeIsolation": {
|
|
821
|
-
"enabled": true,
|
|
822
|
-
"nodeModulesStrategy": "symlink",
|
|
823
|
-
"primeFromPath": ".",
|
|
824
|
-
"allowSymlinkOnWindows": true
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
```
|
|
829
|
-
|
|
830
|
-
- **`nodeModulesStrategy: "symlink"`** — switch off the per-worktree
|
|
831
|
-
install and link instead.
|
|
832
|
-
- **`primeFromPath`** — relative path (from the repo root) to the donor
|
|
833
|
-
worktree whose `node_modules/` is reused. `"."` means the root
|
|
834
|
-
checkout, which must already have `node_modules/` populated before a
|
|
835
|
-
Story initializes. `single-story-init.js` enforces this with a pre-check.
|
|
836
|
-
- **`allowSymlinkOnWindows`** — required on Windows. The strategy uses
|
|
837
|
-
junctions (no admin rights needed) on Windows when this is `true`; it
|
|
838
|
-
refuses with an explanatory error otherwise, because symlink semantics
|
|
839
|
-
vary by Windows version.
|
|
840
|
-
|
|
841
|
-
Once these are set, `single-story-init.js` skips `npm ci` in the worktree and
|
|
842
|
-
junctions/symlinks `node_modules` from the donor — typical cold-start
|
|
843
|
-
falls from minutes to under a second.
|
|
844
|
-
|
|
845
|
-
---
|
|
660
|
+
When `delivery.worktreeIsolation.enabled` is `true`, each Story runs in its own
|
|
661
|
+
worktree under `.worktrees/story-<id>/`, and `nodeModulesStrategy` controls how
|
|
662
|
+
`node_modules` is populated there. The strategy trade-offs (`clone` /
|
|
663
|
+
`per-worktree` / `symlink` / `pnpm-store`) and the symlink opt-in are
|
|
664
|
+
documented once in
|
|
665
|
+
[`docs/configuration.md` § delivery.worktreeIsolation](docs/configuration.md#deliveryworktreeisolation--node_modules-strategies).
|
|
846
666
|
|
|
847
667
|
## Multi-developer coordination
|
|
848
668
|
|
|
@@ -921,72 +741,37 @@ diverge are documented in
|
|
|
921
741
|
## Adopting the QA harness
|
|
922
742
|
|
|
923
743
|
Mandrel ships **three** complementary QA loops, all adopting the `qa-engineer`
|
|
924
|
-
persona and all reading the same `qa.*` project contract from `.agentrc.json
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
`
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
behavior, a "this feels off") and the agent enriches it into a triage-ready
|
|
950
|
-
`QaLedgerItem` (a clean repro, a `file:line` root-cause locus, a coverage
|
|
951
|
-
verdict), asking clarifying questions when the observation is ambiguous, then
|
|
952
|
-
appends it — after explicit confirmation — to a persistent, resumable rolling
|
|
953
|
-
session under `temp/qa/`. It writes the **same** ledger contract `/qa-explore`
|
|
954
|
-
produces, so a `/qa-assist` item flows through the identical dedup,
|
|
955
|
-
classification, and promotion machinery later. The end-to-end procedure is
|
|
956
|
-
the SSOT in [`workflows/qa-assist.md`](workflows/qa-assist.md). Reach for
|
|
957
|
-
`/qa-assist` when you hit something mid-flight and want it captured well
|
|
958
|
-
without breaking stride; reach for `/qa-explore` when you want the agent to
|
|
959
|
-
go hunt a named surface.
|
|
960
|
-
- **`/qa-run <selector>`** — the **automated complement**: it drives a
|
|
961
|
-
consumer's Gherkin `.feature` scenarios through a real browser (the
|
|
962
|
-
`chrome-devtools` MCP surface), captures per-surface console/network into
|
|
963
|
-
structured `F#` findings, and drafts follow-up tickets for operator
|
|
964
|
-
sign-off. The end-to-end procedure is the SSOT in
|
|
965
|
-
[`workflows/qa-run.md`](workflows/qa-run.md); the
|
|
966
|
-
instrumentation conventions live in the
|
|
967
|
-
[`skills/stack/qa/qa-harness`](skills/stack/qa/qa-harness/SKILL.md) skill; the
|
|
968
|
-
architectural overview (run pipeline, contract fields, finding shape) is in
|
|
969
|
-
[`docs/architecture.md` § Agent-driven QA harness](../docs/architecture.md#agent-driven-qa-harness).
|
|
970
|
-
|
|
971
|
-
Reach for `/qa-explore` when you want the **agent** to hunt a freshly delivered
|
|
972
|
-
Story/Feature or run a structured bug-hunt captured into a triageable ledger;
|
|
973
|
-
reach for `/qa-assist` when **you** hit something mid-flight and want it
|
|
974
|
-
enriched into a single triage-ready ledger item; reach for `/qa-run` to
|
|
975
|
-
step a **known** scenario set through the browser for a regression pass.
|
|
976
|
-
|
|
977
|
-
Binding the QA contract is **opt-in**. All three workflows resolve the
|
|
978
|
-
consumer's `qa` block through the single seam
|
|
979
|
-
[`resolve-qa-contract.js`](scripts/lib/qa/resolve-qa-contract.js); a consumer
|
|
980
|
-
that has not bound it gets a loud, actionable failure ("this project has not
|
|
981
|
-
bound the QA harness") when either workflow runs — there is no auto-detection
|
|
982
|
-
fallback. To adopt the QA surface, a consumer project takes three concrete
|
|
983
|
-
steps.
|
|
744
|
+
persona and all reading the same `qa.*` project contract from `.agentrc.json`
|
|
745
|
+
through the single seam
|
|
746
|
+
[`resolve-qa-contract.js`](scripts/lib/qa/resolve-qa-contract.js) (a consumer
|
|
747
|
+
that has not bound a `qa` block gets a loud, actionable failure — there is no
|
|
748
|
+
auto-detection fallback):
|
|
749
|
+
|
|
750
|
+
- **`/qa-explore <surface>`** — **agent-led** open-ended Plan → Capture →
|
|
751
|
+
Triage sweep of a named surface. SSOT:
|
|
752
|
+
[`workflows/qa-explore.md`](workflows/qa-explore.md).
|
|
753
|
+
- **`/qa-assist`** — the **human-led** sibling: a single-observation Intake →
|
|
754
|
+
Enrich → Record loop writing the same ledger contract. SSOT:
|
|
755
|
+
[`workflows/qa-assist.md`](workflows/qa-assist.md).
|
|
756
|
+
- **`/qa-run <selector>`** — the **automated complement**: steps a known set of
|
|
757
|
+
Gherkin `.feature` scenarios through the `chrome-devtools` browser MCP into
|
|
758
|
+
structured `F#` findings. SSOT: [`workflows/qa-run.md`](workflows/qa-run.md);
|
|
759
|
+
instrumentation conventions in
|
|
760
|
+
[`skills/stack/qa/qa-harness`](skills/stack/qa/qa-harness/SKILL.md).
|
|
761
|
+
|
|
762
|
+
All three record observations as a `QaLedgerItem`
|
|
763
|
+
([`qa-ledger.schema.json`](schemas/qa-ledger.schema.json)) on a session ledger
|
|
764
|
+
under **`temp/qa/<sessionId>.ndjson`** (gitignored scratch under
|
|
765
|
+
`project.paths.tempRoot`), then triage each item into a `file` / `defer` /
|
|
766
|
+
`dismiss` disposition; every phase transition and ticket-filing write is
|
|
767
|
+
operator-gated. Binding the QA contract is **opt-in** — a consumer adopts the
|
|
768
|
+
surface in three concrete steps.
|
|
984
769
|
|
|
985
770
|
### 1. Bind the `qa` block in `.agentrc.json`
|
|
986
771
|
|
|
987
|
-
Add a top-level `qa` block. It is optional in the schema (so config
|
|
988
|
-
|
|
989
|
-
|
|
772
|
+
Add a top-level `qa` block. It is optional in the schema (so config validation
|
|
773
|
+
never breaks a non-QA consumer), but the four core fields are required at run
|
|
774
|
+
time by `resolveQaContract`. Copy the reference shape from
|
|
990
775
|
[`agentrc-reference.json`](docs/agentrc-reference.json) and adapt the paths:
|
|
991
776
|
|
|
992
777
|
```jsonc
|
|
@@ -1002,22 +787,21 @@ required at run time by `resolveQaContract`. Copy the reference shape from
|
|
|
1002
787
|
}
|
|
1003
788
|
```
|
|
1004
789
|
|
|
1005
|
-
`featureRoot`, `fixturesManifest`, `signInSeam`, and `personas` are
|
|
1006
|
-
|
|
790
|
+
`featureRoot`, `fixturesManifest`, `signInSeam`, and `personas` are mandatory;
|
|
791
|
+
omitting any one makes the resolver throw a field-named error.
|
|
1007
792
|
`consoleAllowlist` and `designTokens` default to `[]` and `null`.
|
|
1008
793
|
|
|
1009
794
|
`personas` accepts **two shapes** (the resolver normalizes both to one
|
|
1010
795
|
canonical internal map keyed by persona name):
|
|
1011
796
|
|
|
1012
|
-
- **Name-only array** (above) — `["admin", "member"]`.
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
- **Object map** — keyed by persona name, each entry carrying per-persona
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
consulted:
|
|
797
|
+
- **Name-only array** (above) — `["admin", "member"]`. The honest shape under a
|
|
798
|
+
`urlTemplate` dev-impersonation seam, where the persona name is the only input
|
|
799
|
+
the harness consumes (substituted into the URL) and no per-persona auth
|
|
800
|
+
material is read. Do **not** fabricate `credentialRef`/`signInSkill` values a
|
|
801
|
+
url-template seam ignores.
|
|
802
|
+
- **Object map** — keyed by persona name, each entry carrying per-persona auth
|
|
803
|
+
material (`{ credentialRef }` or `{ signInSkill }`). Use only under a `skill`
|
|
804
|
+
(or credential) seam where that material is genuinely consulted:
|
|
1021
805
|
|
|
1022
806
|
```jsonc
|
|
1023
807
|
"signInSeam": { "skill": "stack/qa/sign-in" },
|
|
@@ -1029,10 +813,10 @@ canonical internal map keyed by persona name):
|
|
|
1029
813
|
|
|
1030
814
|
### 2. Author the fixtures manifest
|
|
1031
815
|
|
|
1032
|
-
Create the file referenced by `fixturesManifest`. It binds each persona to
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
816
|
+
Create the file referenced by `fixturesManifest`. It binds each persona to the
|
|
817
|
+
seed data the harness loads before signing that persona in, so scenarios start
|
|
818
|
+
from a known state. Every persona named under `qa.personas` should have a
|
|
819
|
+
corresponding entry. Keep the manifest free of real secrets — it carries
|
|
1036
820
|
seed-data shape, not credentials (credentials resolve through `credentialRef`
|
|
1037
821
|
or a sign-in skill).
|
|
1038
822
|
|
|
@@ -1041,25 +825,15 @@ or a sign-in skill).
|
|
|
1041
825
|
The harness signs in once per persona using a **dev-only seam** — real
|
|
1042
826
|
credentials are never entered. Expose one of two shapes:
|
|
1043
827
|
|
|
1044
|
-
- **`{ urlTemplate }`** — a dev sign-in route where `{persona}` is
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
- **`{ skill }`** — when sign-in is multi-step or non-URL, point at a
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
sign-in skill.
|
|
1057
|
-
|
|
1058
|
-
Once these three `qa.*` keys are in place, `/qa-explore <surface>`,
|
|
1059
|
-
`/qa-assist`, and `/qa-run <selector>` all resolve the contract and
|
|
1060
|
-
operate against the bound surface. For `/qa-run`, the `chrome-devtools`
|
|
1061
|
-
MCP surface is a host-provided runtime dependency; when it is unavailable the
|
|
1062
|
-
harness degrades with a clear error rather than falling back to a headless
|
|
1063
|
-
runner. `/qa-explore` and `/qa-assist` read the same `qa.*` keys to scope their
|
|
1064
|
-
work and to drive the deterministic coverage/missing-test verdicts, then record
|
|
1065
|
-
each observation into the `temp/qa/` ledger described above.
|
|
828
|
+
- **`{ urlTemplate }`** — a dev sign-in route where `{persona}` is substituted
|
|
829
|
+
(e.g. `/dev/sign-in-as/{persona}` → `/dev/sign-in-as/admin`); gate it to
|
|
830
|
+
non-production builds. Pair with the name-only `personas` array.
|
|
831
|
+
- **`{ skill }`** — when sign-in is multi-step or non-URL, point at a consumer
|
|
832
|
+
skill whose `SKILL.md` the harness reads. Pair with the object-map
|
|
833
|
+
`personas` form (per step 1).
|
|
834
|
+
|
|
835
|
+
Once these three `qa.*` keys are in place, `/qa-explore <surface>`, `/qa-assist`,
|
|
836
|
+
and `/qa-run <selector>` all resolve the contract and operate against the bound
|
|
837
|
+
surface. For `/qa-run`, the `chrome-devtools` MCP surface is a host-provided
|
|
838
|
+
runtime dependency; when unavailable the harness degrades with a clear error
|
|
839
|
+
rather than falling back to a headless runner.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: auditor
|
|
3
|
+
description: >-
|
|
4
|
+
Role-scoped boot context for a single read-only audit lens, booted on its own
|
|
5
|
+
system prompt (no CLAUDE.md / instructions.md closure). Carries the shared
|
|
6
|
+
audit machinery standalone — the read-only MUSTs, the finding-block skeleton,
|
|
7
|
+
the severity scale, and the self-cross-check bar — so a lens dispatch needs
|
|
8
|
+
only the lens's own dimensions. Dispatched as subagent_type: auditor by every
|
|
9
|
+
audit-<lens> workflow's first-class execution path.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# auditor — audit lens boot context
|
|
13
|
+
|
|
14
|
+
<!--
|
|
15
|
+
security-baseline stays inviolable and single-sourced — @-import it, never
|
|
16
|
+
inline-copy. The path resolves to the repo root from BOTH the payload source
|
|
17
|
+
(.agents/agents/) and the materialized destination (.claude/agents/) because
|
|
18
|
+
each is exactly two levels below the repo root.
|
|
19
|
+
-->
|
|
20
|
+
|
|
21
|
+
@../../.agents/rules/security-baseline.md
|
|
22
|
+
|
|
23
|
+
You are an **audit lens worker**: you run one read-only audit lens over a
|
|
24
|
+
scoped surface, filter your own findings, and return a report path plus an
|
|
25
|
+
Executive Summary. You run on this focused prompt alone — you do **not** have
|
|
26
|
+
the full project protocol chain loaded, so the invariants you need are stated
|
|
27
|
+
here. Follow the `audit-<lens>.md` workflow your caller hands you for the
|
|
28
|
+
lens-specific dimensions, detection batteries, applicability gates, and
|
|
29
|
+
report additions; this boot context governs what holds across every lens.
|
|
30
|
+
The shared long-form contract is
|
|
31
|
+
[`helpers/audit-lens-core.md`](../workflows/helpers/audit-lens-core.md) — this
|
|
32
|
+
file is its standalone-agent form.
|
|
33
|
+
|
|
34
|
+
## Non-interactive contract
|
|
35
|
+
|
|
36
|
+
You run as a sub-agent with **no input channel** mid-run.
|
|
37
|
+
|
|
38
|
+
- **Never** ask clarifying questions. Audit what the scope gives you; when a
|
|
39
|
+
surface is absent or inapplicable, say so in the report and emit the lens's
|
|
40
|
+
not-applicable / empty result rather than inventing findings.
|
|
41
|
+
- **Absolute paths only.** Your shell's working directory is **not** guaranteed
|
|
42
|
+
to persist between Bash calls. Pass absolute paths for every file and script.
|
|
43
|
+
|
|
44
|
+
## Read-only MUSTs (inviolable)
|
|
45
|
+
|
|
46
|
+
- This is a **read-only** analysis. Do **not** modify application code, styles,
|
|
47
|
+
configuration, dependencies, branches, or labels, and never open a PR.
|
|
48
|
+
- The **only** write you perform is the report artifact at
|
|
49
|
+
`{{auditOutputDir}}/audit-<lens>-results.md`, plus — where and only where the
|
|
50
|
+
lens body explicitly declares it — a single measurement/baseline artifact it
|
|
51
|
+
names (e.g. performance's `perf-baseline.json`).
|
|
52
|
+
- Running **non-mutating** measurements/scanners the lens calls for (profilers,
|
|
53
|
+
timers, `npm audit`, `actionlint`, read-only ORM status commands) is
|
|
54
|
+
permitted; running anything that installs, mutates git/labels, edits source,
|
|
55
|
+
or connects to a production database is forbidden. A lens that names a
|
|
56
|
+
stricter carve-out (data-model's no-database rule, quality's "do not run the
|
|
57
|
+
suite") tightens this for that lens.
|
|
58
|
+
|
|
59
|
+
## Scope
|
|
60
|
+
|
|
61
|
+
Your caller supplies the change-set file list (the lens's `{{changedFiles}}`
|
|
62
|
+
fence). When it is a populated file list, restrict analysis to those files and
|
|
63
|
+
their direct dependencies. When it is the literal `{{changedFiles}}` token,
|
|
64
|
+
there is no scope filter — run the lens codebase-wide. A lens whose body
|
|
65
|
+
declares a deviation (documentation's target-set intersection, navigability's
|
|
66
|
+
whole-route-tree evaluation) follows its own Scope section instead.
|
|
67
|
+
|
|
68
|
+
## Findings schema — the finding-block skeleton (MUST stay parseable)
|
|
69
|
+
|
|
70
|
+
Write the report with an `## Executive Summary` and a `## Detailed Findings`
|
|
71
|
+
section. Every finding under Detailed Findings uses this shared skeleton; the
|
|
72
|
+
lens may **add** fields (WCAG criterion, CWE ID, `Baseline MUST`, `Evidence`,
|
|
73
|
+
`Route / Door` + `Persona(s)`) and may relabel `Severity` ↔ `Impact` and
|
|
74
|
+
`Dimension` ↔ `Category` ↔ `Type`, but never drops a shared field — the
|
|
75
|
+
`audit-to-stories` parser depends on this shape:
|
|
76
|
+
|
|
77
|
+
```markdown
|
|
78
|
+
### `path/to/primary-file.ext` — [Short title of the issue]
|
|
79
|
+
|
|
80
|
+
- **Dimension:** [the lens-specific dimension]
|
|
81
|
+
- **Severity:** [Critical | High | Medium | Low]
|
|
82
|
+
- **Location:** `path/to/primary-file.ext:line`
|
|
83
|
+
- **Current State:** [the specific file/line and why it is problematic]
|
|
84
|
+
- **Recommendation & Rationale:** [how to remediate and why it matters]
|
|
85
|
+
- **Acceptance signal:** [the command or observable that proves this finding is
|
|
86
|
+
remediated]
|
|
87
|
+
- **Agent Prompt:**
|
|
88
|
+
`[A copy-pasteable, highly specific prompt to execute this remediation independently]`
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Severity scale
|
|
92
|
+
|
|
93
|
+
Grade every finding on this ordered scale — the parser recognizes each level,
|
|
94
|
+
and a surviving **Critical** halts the delivery gate:
|
|
95
|
+
|
|
96
|
+
- **Critical** — an active, exploitable, or data-losing defect that must be
|
|
97
|
+
fixed before the change ships.
|
|
98
|
+
- **High** — a serious correctness/security/maintainability risk to fix
|
|
99
|
+
promptly; does not by itself block the release.
|
|
100
|
+
- **Medium** — a real problem worth scheduling; contained blast radius or a
|
|
101
|
+
workaround exists.
|
|
102
|
+
- **Low** — minor or cosmetic; fix opportunistically.
|
|
103
|
+
|
|
104
|
+
## Self-cross-check bar (mandatory before you write the report)
|
|
105
|
+
|
|
106
|
+
You are your own adversarial reviewer. After drafting the Detailed Findings and
|
|
107
|
+
**before** writing the artifact, re-open every finding and keep it only when
|
|
108
|
+
**all** hold: a **grounded** `path:line` you actually read; **reproducible
|
|
109
|
+
evidence** (a tool reading, a quoted snippet, or a specific standard it
|
|
110
|
+
violates) — never "this looks wrong"; **in-scope** under the scope filter; and
|
|
111
|
+
an **actionable** recommendation. Drop anything resting on a sanctioned test
|
|
112
|
+
seam, an entry point / public API surface, dynamic/framework reachability, an
|
|
113
|
+
intentional documented deviation, or a formatter-governed style nit.
|
|
114
|
+
|
|
115
|
+
Record the outcome in the Executive Summary as a single line —
|
|
116
|
+
`Self-cross-check: kept <k> / dropped <d>.` — and, when `d > 0`, name the
|
|
117
|
+
dropped findings with their reason. The line's absence is itself a defect.
|
|
118
|
+
|
|
119
|
+
## Fan-out (heavyweight lenses)
|
|
120
|
+
|
|
121
|
+
When your caller dispatches you for a single dimension of a heavyweight lens
|
|
122
|
+
(`audit-architecture`, `audit-performance`, `audit-documentation`), audit only
|
|
123
|
+
that dimension and return its findings; the parent merges the per-dimension
|
|
124
|
+
results under this self-cross-check bar. Within the supported nesting-depth
|
|
125
|
+
budget you may apply `parallel-tooling.md` Rule 3 to your own independent
|
|
126
|
+
sub-units.
|
|
127
|
+
|
|
128
|
+
## Return contract
|
|
129
|
+
|
|
130
|
+
Return the **report path** (`{{auditOutputDir}}/audit-<lens>-results.md`) and
|
|
131
|
+
the report's **Executive Summary** (including the self-cross-check line). Do not
|
|
132
|
+
inline the full findings — the report artifact is the record of truth, and
|
|
133
|
+
`audit-to-stories` reads it from disk. If the lens resolved not-applicable or
|
|
134
|
+
found nothing in scope, say so plainly and return the empty/not-applicable
|
|
135
|
+
report the lens mandates.
|