mandrel 1.82.0 → 1.84.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.
Files changed (47) hide show
  1. package/.agents/README.md +41 -0
  2. package/.agents/docs/SDLC.md +4 -2
  3. package/.agents/docs/agentrc-reference.json +10 -2
  4. package/.agents/docs/execution-reference.md +52 -0
  5. package/.agents/instructions.md +76 -38
  6. package/.agents/rules/testing-standards.md +14 -0
  7. package/.agents/schemas/agentrc.schema.json +31 -3
  8. package/.agents/schemas/qa-ledger.schema.json +2 -2
  9. package/.agents/scripts/epic-deliver-prepare.js +41 -1
  10. package/.agents/scripts/lib/config/explain.js +4 -1
  11. package/.agents/scripts/lib/config-settings-schema.js +25 -1
  12. package/.agents/scripts/lib/epic-body-sections.js +88 -0
  13. package/.agents/scripts/lib/findings/promote-finding.js +3 -3
  14. package/.agents/scripts/lib/findings/severity.js +5 -6
  15. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +65 -2
  16. package/.agents/scripts/lib/orchestration/context-hydration-engine.js +96 -11
  17. package/.agents/scripts/lib/orchestration/doc-reader.js +29 -0
  18. package/.agents/scripts/lib/orchestration/docs-digest.js +134 -0
  19. package/.agents/scripts/lib/orchestration/story-close/baseline-attribution/phases/refresh-commit.js +15 -1
  20. package/.agents/scripts/lib/qa/console-allowlist.js +5 -4
  21. package/.agents/scripts/lib/qa/resolve-qa-contract.js +144 -8
  22. package/.agents/skills/core/epic-plan-consolidate/SKILL.md +7 -5
  23. package/.agents/skills/core/epic-plan-consolidate/examples.md +51 -0
  24. package/.agents/skills/core/epic-plan-decompose-author/SKILL.md +4 -22
  25. package/.agents/skills/core/epic-plan-decompose-author/examples.md +47 -0
  26. package/.agents/skills/core/epic-plan-premortem/SKILL.md +9 -8
  27. package/.agents/skills/core/epic-plan-premortem/examples.md +53 -0
  28. package/.agents/skills/core/epic-plan-spec-author/SKILL.md +21 -81
  29. package/.agents/skills/core/epic-plan-spec-author/examples.md +91 -0
  30. package/.agents/skills/skills.index.json +3 -3
  31. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +52 -38
  32. package/.agents/workflows/helpers/code-review.md +70 -5
  33. package/.agents/workflows/helpers/deliver-epic-reference.md +514 -0
  34. package/.agents/workflows/helpers/deliver-epic.md +164 -469
  35. package/.agents/workflows/helpers/epic-deliver-story.md +35 -11
  36. package/.agents/workflows/helpers/plan-epic-reference.md +136 -0
  37. package/.agents/workflows/helpers/plan-epic.md +56 -186
  38. package/.agents/workflows/helpers/plan-story.md +31 -61
  39. package/.agents/workflows/helpers/qa-run-scenario.md +194 -0
  40. package/.agents/workflows/helpers/scope-triage-gate.md +97 -0
  41. package/.agents/workflows/helpers/single-story-deliver-reference.md +423 -0
  42. package/.agents/workflows/helpers/single-story-deliver.md +128 -392
  43. package/.agents/workflows/qa-explore.md +63 -32
  44. package/.agents/workflows/qa-run.md +293 -130
  45. package/docs/CHANGELOG.md +21 -0
  46. package/package.json +1 -1
  47. package/.agents/schemas/qa-finding.schema.json +0 -133
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-07-04T00:29:42.907Z",
2
+ "generatedAt": "2026-07-04T23:12:38.376Z",
3
3
  "generator": "generate-skills-index.js@1",
4
4
  "skills": [
5
5
  {
@@ -567,8 +567,8 @@
567
567
  "tier": "stack",
568
568
  "category": "qa",
569
569
  "path": ".agents/skills/stack/qa/qa-explore-driving/SKILL.md",
570
- "description": "Conventions for agent-driven exploratory QA driving — how the agent itself drives a surface during `/qa-explore` (agent-led), as opposed to the human-led `/qa-assist`. Use when the agent explores a running app via the browser MCP (navigation-first, the default) or walks a static surface (the documented interim until consumer persona-seeding lands), under a strictly read-only capture invariant. The exploration procedure lives in `.agents/workflows/qa-explore.md`; this skill is the driving-conventions reference it leans on.",
571
- "policyCapsuleBullets": 8,
570
+ "description": "Conventions for agent-driven exploratory QA driving — how the agent itself drives a surface during `/qa-explore` (agent-led), as opposed to the human-led `/qa-assist`. Use when the agent explores a running app via the browser MCP (navigation-first, the default) — including authenticated deployed surfaces reached through the resolved environment's sign-in seam — or walks a static surface (the documented interim where no seam resolves), under a strictly read-only capture invariant. The exploration procedure lives in `.agents/workflows/qa-explore.md`; this skill is the driving-conventions reference it leans on.",
571
+ "policyCapsuleBullets": 9,
572
572
  "allowedTools": null,
573
573
  "vendor": null
574
574
  },
@@ -4,9 +4,10 @@ description:
4
4
  Conventions for agent-driven exploratory QA driving — how the agent itself
5
5
  drives a surface during `/qa-explore` (agent-led), as opposed to the
6
6
  human-led `/qa-assist`. Use when the agent explores a running app via the
7
- browser MCP (navigation-first, the default) or walks a static surface (the
8
- documented interim until consumer persona-seeding lands), under a strictly
9
- read-only capture invariant. The exploration procedure lives in
7
+ browser MCP (navigation-first, the default) including authenticated
8
+ deployed surfaces reached through the resolved environment's sign-in seam —
9
+ or walks a static surface (the documented interim where no seam resolves),
10
+ under a strictly read-only capture invariant. The exploration procedure lives in
10
11
  `.agents/workflows/qa-explore.md`; this skill is the driving-conventions
11
12
  reference it leans on.
12
13
  ---
@@ -16,9 +17,10 @@ description:
16
17
  ## Policy Capsule
17
18
 
18
19
  - Drive the running app **by default** through the browser MCP, navigation-first: start at a root and reach each surface only via UI affordances — never URL-jump to a deep link.
19
- - Treat **static driving** (reading source, routes, and rendered markup without a live runtime) as the **documented interim** method, chosen at Plan time when a live runtime is not reachable — never the silent fallback.
20
+ - Resolve the target **environment** at Plan time (via `resolveQaEnvironment`) and record its name in the ledger; each environment keys its own `baseUrl`, `signInSeam`, and `allowWrites`.
21
+ - Treat **static driving** (reading source, routes, and rendered markup without a live runtime) as the **documented interim** method, chosen at Plan time **only where no seam resolves** for the target environment — never the silent fallback.
20
22
  - Hold the **read-only capture invariant** absolutely: the agent makes no source edits and no product mutations while driving; the only write is appending to the `temp/qa/<sessionId>` ledger.
21
- - Authenticated driving depends on **consumer persona-seeding infrastructure that this Epic does not deliver**; without it, drive only the unauthenticated surface or fall back to static, and record the gap never enter real credentials or fabricate a session.
23
+ - Authenticated driving follows the resolved environment's **`signInSeam`**: sign in through a dev `url` seam (persona name substituted into the template) or a `skill` seam (a stored `credentialRef` read by the named sign-in skill), with **mandatory redaction** of all captured evidence. Never type real credentials inline or fabricate a session; where an environment resolves no seam, drive the unauthenticated surface or fall back to static and record the gap.
22
24
  - Pick the driving method explicitly in the Plan phase (drive vs. static) and record it in the ledger; do not switch methods mid-surface without a new Plan note.
23
25
  - Every phase transition and every GitHub write is HITL-gated; the agent drives and captures, but never files or promotes findings autonomously.
24
26
  - Broken navigation, a missing affordance, or a guard redirect loop is a **finding**, not a workaround — record it and move on; do not route around it with a direct URL.
@@ -65,15 +67,14 @@ state rather than an artifact of a deep link.
65
67
 
66
68
  ## 2. Static Driving — the Documented Interim
67
69
 
68
- Static driving is the **explicitly documented interim** method for when a live
69
- runtime is not reachable most commonly because authenticated driving needs
70
- consumer persona-seeding infrastructure that does not yet exist (§ 4). It walks
71
- the surface from source, route definitions, and rendered markup rather than a
72
- running browser.
70
+ Static driving is the **explicitly documented interim** method for when **no
71
+ seam resolves** for the target environment the resolved environment carries
72
+ no `signInSeam` the agent can drive through (§ 4). It walks the surface from
73
+ source, route definitions, and rendered markup rather than a running browser.
73
74
 
74
75
  - **Choose it at Plan time, never silently.** Static is a deliberate Plan-phase
75
- decision recorded in the ledger ("method: static, reason: no reachable
76
- authenticated runtime"), not an unannounced fallback the agent slips into
76
+ decision recorded in the ledger ("environment: preview, method: static,
77
+ reason: no seam resolves"), not an unannounced fallback the agent slips into
77
78
  when the browser MCP hiccups.
78
79
  - **It is interim, not equivalent.** Static driving cannot exercise real
79
80
  authorization, routing guards, or runtime console/network signal. Treat its
@@ -81,10 +82,10 @@ running browser.
81
82
  same coverage a driven pass would.
82
83
  - **Same read-only invariant.** Static driving reads source and routes; it makes
83
84
  no edits. The read-only capture invariant (§ 3) applies identically.
84
- - **Promote to driving when the runtime lands.** Static is the bridge until the
85
- consumer's persona-seeding infrastructure (§ 4) makes authenticated driving
86
- possible. When that lands, re-run the surface driven; do not leave a surface
87
- permanently static when it could be driven.
85
+ - **Promote to driving when a seam lands.** Static is the bridge until the
86
+ target environment resolves a `signInSeam` (§ 4) that makes driven
87
+ authenticated exploration possible. When that lands, re-run the surface
88
+ driven; do not leave a surface permanently static when it could be driven.
88
89
 
89
90
  ## 3. The Read-Only Capture Invariant
90
91
 
@@ -109,29 +110,42 @@ and the Epic's security considerations — it is not a soft preference.
109
110
  (ticket creation, promotion) happen only behind an operator confirmation gate.
110
111
  The agent never files or promotes findings autonomously.
111
112
 
112
- ## 4. Authenticated Driving Depends on Consumer Infra (Not Delivered Here)
113
-
114
- Driving an **authenticated** surface requires signing in as a seeded persona.
115
- That seeding provisioning a test persona with the right org, role, and data
116
- so the agent can reach a logged-in surface navigation-first — is **consumer
117
- persona-seeding infrastructure that this Epic does not deliver**. It is an
118
- explicit non-goal of the `/qa-explore` rebuild.
119
-
120
- - **Unauthenticated surface only, by default.** Without persona-seeding infra in
121
- the consumer project, drive only the surface reachable without sign-in, or
122
- fall back to static driving (§ 2) for the authenticated surface. Record the
123
- gap in the ledger so the partial coverage is visible.
124
- - **Never enter real credentials.** The agent MUST NOT type real usernames,
125
- passwords, or tokens to reach an authenticated surface, and MUST NOT fabricate
126
- or forge a session. This is a hard security boundary, not a convenience to
113
+ ## 4. Authenticated Driving Follows the Per-Environment Seam
114
+
115
+ Driving an **authenticated** surface requires signing in. The resolved target
116
+ environment (via `resolveQaEnvironment`, § Policy Capsule) carries the
117
+ `signInSeam` the agent drives through the same discriminated-union shape
118
+ `qa-harness` resolves via its contract. When a seam resolves, authenticated
119
+ deployed surfaces are **driven**, not statically deferred.
120
+
121
+ - **Drive the authenticated surface through the seam.** When the target
122
+ environment carries a `signInSeam`, sign in via that seam and then reach the
123
+ authenticated surface navigation-first including authenticated **deployed**
124
+ hosts. The two seam kinds:
125
+ - **`kind: 'url'` (dev impersonation).** Substitute the persona **name** into
126
+ the seam's URL template and navigate there. The persona name is the sole
127
+ input; no per-persona auth material is read.
128
+ - **`kind: 'skill'` (procedural / credential).** Invoke the named consumer
129
+ sign-in skill, which reads a per-persona **`credentialRef`** — an indirect
130
+ handle to a stored credential, never an inline secret. Read the skill's
131
+ `SKILL.md` and follow it.
132
+ - **Never enter real credentials inline.** The agent MUST NOT type real
133
+ usernames, passwords, or tokens to reach an authenticated surface, and MUST
134
+ NOT fabricate or forge a session. Sign-in flows only through the seam, which
135
+ consumes a persona name or a `credentialRef` indirection — never a
136
+ hand-typed secret. This is a hard security boundary, not a convenience to
127
137
  work around.
128
- - **The dependency is the consumer's to satisfy.** When a consumer wants driven
129
- authenticated exploration, the consumer supplies a dev sign-in seam and seeded
130
- personas (the same shape `qa-harness` resolves via its contract). Until then,
131
- authenticated coverage is static or deferred say which in the ledger.
132
- - **Surface the gap, don't paper over it.** A surface that could not be driven
133
- because authenticated seeding is absent is itself a coverage signal worth
134
- recording, not a silent skip.
138
+ - **Redaction is mandatory.** Every captured evidence string console,
139
+ network, headers — passes through the shared redaction path 3) before it
140
+ reaches disk or GitHub; bearer tokens, session cookies, `Authorization`
141
+ headers, and PII are masked. Authenticated driving raises the stakes on
142
+ redaction, it does not relax it.
143
+ - **Static only where no seam resolves.** When the target environment resolves
144
+ **no** `signInSeam`, drive only the unauthenticated surface or fall back to
145
+ static driving (§ 2), and record the gap in the ledger so the partial
146
+ coverage is visible. A surface that could not be driven because the
147
+ environment carries no seam is itself a coverage signal worth recording, not
148
+ a silent skip.
135
149
 
136
150
  ## 5. Cross-References
137
151
 
@@ -19,6 +19,18 @@ is merged upstream. It runs in two scopes:
19
19
  - **Epic scope** — reviews the cumulative diff between an Epic branch and
20
20
  `main`, before `/deliver` opens the integration pull request.
21
21
 
22
+ **Invariant — Story-scope review runs outside the maker's LLM context.**
23
+ The Story-scope review executes inside the `story-close.js` /
24
+ `single-story-close.js` close subprocess, **not** in the delivering
25
+ child's (maker agent's) LLM context. The close pipeline invokes it after
26
+ the delivering child has exited, so the change set is reviewed by a
27
+ process the maker cannot influence. The enforcing code path is
28
+ [`.agents/scripts/lib/orchestration/story-close/phases/code-review.js`](../../scripts/lib/orchestration/story-close/phases/code-review.js)
29
+ (invoked from `runStoryCloseLocked`; both close entry points reach it
30
+ through the shared `runStoryReviewCore` spine). A future refactor MUST
31
+ preserve this isolation: do not move Story-scope review into the maker's
32
+ context or run it as a step of the delivering child.
33
+
22
34
  > **Persona**: `architect` · **Skills**: `core/code-review-and-quality`,
23
35
  > `core/security-and-hardening`
24
36
 
@@ -107,18 +119,21 @@ The pipeline will:
107
119
 
108
120
  ## Step 2 — Review Pillars
109
121
 
110
- For each changed file, execute a strict review against three pillars. The
111
- middle pillar (**Integration Review**) deliberately defers the security /
122
+ For each changed file, execute a strict review against four pillars. The
123
+ second pillar (**Integration Review**) deliberately defers the security /
112
124
  performance / quality / coverage sweeps to the change-set-scoped audits
113
125
  that already ran upstream — re-walking them here is duplication, not
114
126
  defense-in-depth.
115
127
 
116
128
  **Apply the `depth` lever** (see **Review depth** above) to how hard you walk
117
129
  these pillars: at `light`, focus on Pillar 1 and reduce Pillars 2–3 to a quick
118
- scan for obvious breakage; at `standard`, cover all three at today's depth; at
119
- `deep`, cover all three at full depth and then make a second adversarial pass
130
+ scan for obvious breakage; at `standard`, cover all four at today's depth; at
131
+ `deep`, cover all four at full depth and then make a second adversarial pass
120
132
  over the diff hunting for integration regressions and security-relevant edges
121
- before finalizing findings.
133
+ before finalizing findings. Pillar 4 (**Anti-Gaming / Shortcut Detection**)
134
+ is walked at **every** depth, including `light` — it targets the class of
135
+ correctness failure the deterministic gates structurally cannot see, so it is
136
+ never reduced to a scan.
122
137
 
123
138
  ### Pillar 1: Spec Adherence
124
139
 
@@ -182,6 +197,56 @@ Verify documentation stays synchronized with code:
182
197
  - README and CHANGELOG reflect the changes if applicable.
183
198
  - Inline comments explain *why*, not *what*.
184
199
 
200
+ ### Pillar 4: Anti-Gaming / Shortcut Detection
201
+
202
+ Does the change reach "done" by *fixing the code*, or by *weakening the check
203
+ that would have caught it broken?* This is the class of correctness failure the
204
+ deterministic `verify[]` commands and the ratchet gates structurally cannot
205
+ see: a green suite, a passing lint, and an unchanged maintainability score all
206
+ report success whether the code got correct or the test got quieter. Walk the
207
+ diff for the shortcut taxonomy below and flag every instance — a plausible-but-
208
+ unjustified match is a 🟠 finding, an unambiguous one (test deletion without a
209
+ spec decision, a swallowed error on a real failure path) is a 🔴.
210
+
211
+ - **Relaxed tests** — an assertion loosened to pass rather than the code fixed
212
+ to satisfy it: a tightened matcher swapped for a looser one
213
+ (`toEqual` → `toBeTruthy`, an exact value → `expect.anything()`), a
214
+ narrowed expected value widened, a strict schema check softened, or a
215
+ threshold moved to admit the current (wrong) output.
216
+ - **Skipped tests** — a failing test quarantined instead of fixed:
217
+ `it.skip` / `test.skip` / `xit` / `describe.skip`, a `return` early in the
218
+ test body, a `--test-name-pattern` / grep exclusion, an `@skip`/`@ignore`
219
+ tag, or a test commented out wholesale. Deleting a test outright is the
220
+ most severe form — treat unexplained coverage removal as `test-deletion`
221
+ (Step 4.5) and never auto-fix it.
222
+ - **Swallowed errors** — a failure path silently absorbed: an empty
223
+ `catch {}`, `catch (e) {}` with no rethrow/log/handle, a bare
224
+ `.catch(() => {})` on a promise, a `try` wrapped solely to suppress a
225
+ throw the caller needs, or an error downgraded to a no-op return so the
226
+ happy path "passes".
227
+ - **Stub returns** — a hardcoded value standing in for real logic: a function
228
+ that `return true` / `return []` / `return null` / `return {}` regardless of
229
+ input, a mock left wired into production code, a `TODO`/`FIXME` guarding an
230
+ unimplemented branch that the acceptance criteria required, or a constant
231
+ substituted for a computation the Story asked for.
232
+ - **Fake renames** — a change dressed up as a rename that is actually a
233
+ deletion or a behavior change: content dropped under cover of a
234
+ move/rename, a "rename" whose diff quietly alters logic, or a re-export
235
+ shim that orphans the real implementation while the symbol name survives.
236
+ - **Comment-deletion-as-fix** — a warning silenced by removing its evidence
237
+ rather than its cause: a failing assertion turned into a comment, a
238
+ `// TODO: this is broken` note deleted while the breakage remains, a
239
+ disabled-code block removed to make a diff look clean, or a lint-suppression
240
+ comment (`biome-ignore`, `eslint-disable`, `@ts-expect-error`) added to mute
241
+ a real diagnostic instead of fixing it.
242
+
243
+ For every hit, name the file and line, the taxonomy category, and *why the
244
+ code — not the check — should have changed*. A finding here is legitimate only
245
+ when the diff itself lacks a recorded rationale (a commit-body or Story-comment
246
+ note explaining a deliberate, spec-sanctioned relaxation clears it — per the
247
+ engineer persona's Implementation Latitude, unlogged reshaping is the
248
+ anti-pattern this pillar surfaces).
249
+
185
250
  ## Step 3 — Maintainability Ratchet
186
251
 
187
252
  Verify that no file's maintainability score has decreased below the project