mandrel 2.39.0 → 2.41.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 +8 -5
- package/.agents/agents/auditor.md +5 -0
- package/.agents/docs/SDLC.md +21 -12
- package/.agents/instructions.md +22 -22
- package/.agents/rules/api-conventions.md +43 -7
- package/.agents/rules/ci-remediation.md +3 -14
- package/.agents/rules/gherkin-standards.md +21 -6
- package/.agents/rules/git-conventions.md +6 -5
- package/.agents/rules/security-baseline.md +6 -7
- package/.agents/rules/testing-standards.md +75 -198
- package/.agents/scripts/audit-to-stories.js +510 -66
- package/.agents/scripts/install-matrix-assert.js +2 -2
- package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +45 -0
- package/.agents/scripts/lib/audit-to-stories/ledger-commit.js +290 -0
- package/.agents/scripts/lib/audit-to-stories/parse-audit-md.js +94 -3
- package/.agents/scripts/lib/audit-to-stories/seed-from-findings.js +10 -0
- package/.agents/scripts/lib/label-constants.js +18 -0
- package/.agents/scripts/lib/label-taxonomy.js +18 -5
- package/.agents/scripts/lib/orchestration/dependency-candidates.js +139 -0
- package/.agents/scripts/lib/orchestration/epic-candidates.js +159 -0
- package/.agents/scripts/lib/orchestration/epic-checklist.js +103 -0
- package/.agents/scripts/lib/orchestration/epic-container.js +202 -0
- package/.agents/scripts/lib/orchestration/epic-expansion.js +148 -0
- package/.agents/scripts/lib/orchestration/plan-context.js +97 -36
- package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +80 -0
- package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +192 -0
- package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +324 -0
- package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +164 -0
- package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +30 -0
- package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +26 -5
- package/.agents/scripts/lib/orchestration/run-epilogue.js +130 -1
- package/.agents/scripts/lib/orchestration/ticket-validator.js +11 -1
- package/.agents/scripts/plan-persist.js +98 -1
- package/.agents/scripts/providers/github/sub-issue-add.js +218 -0
- package/.agents/scripts/resolve-stories.js +42 -2
- package/.agents/skills/core/browser-testing-with-devtools/SKILL.md +5 -10
- package/.agents/skills/core/browser-testing-with-devtools/reference.md +7 -46
- package/.agents/skills/core/code-review-and-quality/SKILL.md +0 -5
- package/.agents/skills/core/documentation-and-adrs/SKILL.md +0 -3
- package/.agents/skills/core/gates-and-baselines/SKILL.md +10 -137
- package/.agents/skills/core/gates-and-baselines/reference.md +103 -0
- package/.agents/skills/core/idea-refinement/SKILL.md +2 -18
- package/.agents/skills/core/security-and-hardening/SKILL.md +2 -4
- package/.agents/skills/core/security-and-hardening/reference.md +0 -70
- package/.agents/skills/skills.index.json +10 -70
- package/.agents/skills/stack/qa/gherkin-authoring/SKILL.md +4 -10
- package/.agents/skills/stack/qa/gherkin-authoring/reference.md +9 -113
- package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +29 -154
- package/.agents/skills/stack/qa/qa-harness/SKILL.md +157 -98
- package/.agents/templates/docs/audit-sweep-runbook.md +169 -0
- package/.agents/workflows/audit-to-stories.md +85 -7
- package/.agents/workflows/git-cleanup.md +3 -2
- package/.agents/workflows/git-deliver.md +3 -2
- package/.agents/workflows/helpers/audit-lens-core.md +24 -4
- package/.agents/workflows/helpers/deliver-reference.md +8 -0
- package/.agents/workflows/helpers/plan-reference.md +109 -1
- package/.agents/workflows/mandrel-deliver.md +47 -43
- package/.agents/workflows/mandrel-plan.md +61 -55
- package/.agents/workflows/qa-assist.md +20 -17
- package/.agents/workflows/qa-explore.md +30 -29
- package/.agents/workflows/qa-run.md +2 -1
- package/docs/CHANGELOG.md +30 -0
- package/package.json +1 -1
- package/.agents/rules/changelog-style.md +0 -180
- package/.agents/rules/shell-conventions.md +0 -61
- package/.agents/scripts/lib/qa/coverage-verdict.js +0 -214
- package/.agents/skills/core/api-and-interface-design/SKILL.md +0 -55
- package/.agents/skills/core/api-and-interface-design/reference.md +0 -76
- package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +0 -45
- package/.agents/skills/core/debugging-and-error-recovery/reference.md +0 -56
- package/.agents/skills/core/git-workflow-and-versioning/SKILL.md +0 -54
- package/.agents/skills/core/idea-refinement/refinement-criteria.md +0 -155
- package/.agents/skills/core/idea-refinement/scripts/idea-refine.sh +0 -15
- package/.agents/skills/core/qa-coverage-mapping/SKILL.md +0 -105
- package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +0 -152
- package/.agents/skills/stack/qa/vitest/SKILL.md +0 -22
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
**Read this when** a task engages one of the sections below and the Policy
|
|
4
4
|
Capsule in [`SKILL.md`](SKILL.md) does not settle it on its own. The capsule
|
|
5
5
|
is the contract; this file is the reference material behind it. The
|
|
6
|
-
untrusted-
|
|
7
|
-
|
|
6
|
+
untrusted-content and JS-execution constraints live in the capsule and the
|
|
7
|
+
security baseline it cites; generic DevTools tool tables and symptom-by-symptom
|
|
8
8
|
workflow ladders are omitted as frontier-known.
|
|
9
9
|
|
|
10
10
|
## Setting Up Chrome DevTools MCP
|
|
@@ -17,7 +17,7 @@ Code settings):
|
|
|
17
17
|
"mcpServers": {
|
|
18
18
|
"chrome-devtools": {
|
|
19
19
|
"command": "npx",
|
|
20
|
-
"args": ["
|
|
20
|
+
"args": ["chrome-devtools-mcp@latest"]
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -28,47 +28,8 @@ network monitor, performance traces, computed styles, the accessibility tree,
|
|
|
28
28
|
and read-only JavaScript execution — the runtime evidence that static code
|
|
29
29
|
analysis cannot provide.
|
|
30
30
|
|
|
31
|
-
##
|
|
31
|
+
## The clean-console standard
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
```markdown
|
|
38
|
-
## Test Plan: Task completion animation bug
|
|
39
|
-
|
|
40
|
-
### Setup
|
|
41
|
-
|
|
42
|
-
1. Navigate to http://localhost:3000/tasks
|
|
43
|
-
2. Ensure at least 3 tasks exist
|
|
44
|
-
|
|
45
|
-
### Steps
|
|
46
|
-
|
|
47
|
-
1. Click the checkbox on the first task
|
|
48
|
-
- Expected: strikethrough animation, task moves to "completed" section
|
|
49
|
-
- Check: console has no errors
|
|
50
|
-
- Check: network shows PATCH /api/tasks/:id with { status: "completed" }
|
|
51
|
-
|
|
52
|
-
2. Click undo within 3 seconds
|
|
53
|
-
- Expected: task returns to the active list with reverse animation
|
|
54
|
-
- Check: network shows PATCH /api/tasks/:id with { status: "pending" }
|
|
55
|
-
|
|
56
|
-
### Verification
|
|
57
|
-
|
|
58
|
-
- [ ] All steps completed without console errors
|
|
59
|
-
- [ ] Network requests are correct and not duplicated
|
|
60
|
-
- [ ] Visual state matches expected behavior
|
|
61
|
-
- [ ] Accessibility: task status changes are announced to screen readers
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## Screenshot-Based Verification
|
|
65
|
-
|
|
66
|
-
Use screenshots for visual regression checks: take a "before" screenshot, make
|
|
67
|
-
the code change, reload, take an "after" screenshot, and compare. This is
|
|
68
|
-
especially valuable for CSS changes, responsive layouts at different viewports,
|
|
69
|
-
loading/empty/error states, and transitions.
|
|
70
|
-
|
|
71
|
-
**Clean-console standard.** A production-quality page has **zero** console
|
|
72
|
-
errors and warnings. If the console is not clean after a browser-touching
|
|
73
|
-
change, fix the warnings before shipping — warnings become errors, and a clean
|
|
74
|
-
console catches bugs early.
|
|
33
|
+
A production-quality page has **zero** console errors and warnings. If the
|
|
34
|
+
console is not clean after a browser-touching change, fix the warnings before
|
|
35
|
+
shipping — warnings become errors, and a clean console catches bugs early.
|
|
@@ -14,13 +14,8 @@ description:
|
|
|
14
14
|
|
|
15
15
|
- Every change gets reviewed before merge — no exceptions, including agent-authored code.
|
|
16
16
|
- Apply the **five-axis review** to every change: **Correctness, Readability & Simplicity, Architecture, Security, Performance**.
|
|
17
|
-
- Approval standard: approve when the change **definitely improves overall code health**, even if it isn't perfect. Don't block on stylistic preferences that match project conventions.
|
|
18
|
-
- Verify the spec/task requirements are met, edge cases (null, empty, boundary) and error paths are handled, and the tests are actually testing the right things — not just that they pass.
|
|
19
|
-
- Reject "clever" code in favour of the boring, obvious solution. Abstractions MUST earn their complexity (no generalizing before the third use case).
|
|
20
17
|
- Flag dead code artifacts (`_unused` vars, backwards-compat shims, `// removed` comments) and require their removal before merge.
|
|
21
18
|
- Defer to `.agents/rules/security-baseline.md` and the `security-and-hardening` skill for security review; explicit checks include input validation, no hardcoded secrets, parameterized queries, encoded output, authn+authz, and treating external data as untrusted.
|
|
22
|
-
- Review performance on the hot path only, and measure before optimizing; explicit checks include no N+1 queries, no unbounded fetches, no blocking sync work, no obviously oversized bundles.
|
|
23
|
-
- Disallow scope creep in a PR: drive-by cleanups, adjacent refactors, and "while I'm here" edits should be split into a separate change.
|
|
24
19
|
- Bug-fix reviews cover **both** the fix and the regression test; a fix without a failing-then-passing test is not approvable.
|
|
25
20
|
- **Refactoring is post-green and behaviour-preserving.** Run the refactor pass only when the suite is already green and gates pass; inputs, outputs, side effects, error semantics, and ordering MUST be identical before and after, and existing tests MUST keep passing **without modification** (if a test had to change, behaviour changed — revert).
|
|
26
21
|
- **Lower CRAP by lowering complexity, and remove duplication at the root.** Target the highest-CRAP well-covered functions and the largest verbatim duplications by measurement (`check-baselines.js`), not by smell; extract one well-named helper rather than leaving near-copies. CRAP must not rise and maintainability must not fall on any touched file, and no gate, floor, or threshold may be retuned to make the pass "succeed".
|
|
@@ -14,11 +14,8 @@ description:
|
|
|
14
14
|
- Write an ADR for any decision that would be expensive to reverse (framework choice, data model, auth strategy, API architecture, hosting platform).
|
|
15
15
|
- Mandrel ships **two first-class decisions-log layouts** — pick one at onboarding (see [Decisions-log layouts](reference.md#decisions-log-layouts)): the **single-file dated-entry** `docs/decisions.md` (default; best for small projects) or the **index + `docs/decisions/` directory** (MADR-style, one file per ADR; best once the log outgrows a single file). Either way, the canonical ADR sections are **Status, Date, Deciders, Context, Decision, (Alternatives Considered), Consequences**.
|
|
16
16
|
- Mark an ADR's status as `Accepted`, `Superseded by ADR-XXX`, `Deprecated`, or `Reverted (<date>)` — a reverted decision was **undone** rather than replaced, so unlike a superseded one it has no successor to point at. Never silently delete an ADR — supersede it.
|
|
17
|
-
- Do **not** document obvious code; do **not** restate what the code already says. Stale or redundant docs are worse than no docs.
|
|
18
|
-
- Comments explain **non-obvious intent** (the why). If a comment describes what the code does, refactor the code instead.
|
|
19
17
|
- Keep user-facing docs (README, API docs, changelog) updated as part of the change — out-of-date docs are bugs.
|
|
20
18
|
- Pair every public API change with a changelog entry that links the relevant Story and any superseding ADR.
|
|
21
|
-
- When you find yourself explaining the same thing repeatedly in chat, write it down — the explanation belongs in the project docs or an ADR.
|
|
22
19
|
|
|
23
20
|
## Long-form reference — read on demand
|
|
24
21
|
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
name: gates-and-baselines
|
|
3
3
|
description:
|
|
4
4
|
Governs quality gates and the unified-baseline snapshots. Use when authoring
|
|
5
|
-
a baseline refresh commit (CRAP, maintainability,
|
|
6
|
-
when setting up or modifying CI quality gates, or when
|
|
7
|
-
that asserts on pre-existing state without turning the
|
|
5
|
+
a baseline refresh commit (coverage, CRAP, maintainability, duplication,
|
|
6
|
+
dead-exports), when setting up or modifying CI quality gates, or when
|
|
7
|
+
introducing a new gate that asserts on pre-existing state without turning the
|
|
8
|
+
base branch red.
|
|
8
9
|
allowed_tools:
|
|
9
10
|
- Read
|
|
10
11
|
- Write
|
|
@@ -15,141 +16,13 @@ allowed_tools:
|
|
|
15
16
|
|
|
16
17
|
## Policy Capsule
|
|
17
18
|
|
|
18
|
-
- **No gate may be skipped.** Failing lint means fix lint
|
|
19
|
+
- **No gate may be skipped.** Failing lint means fix lint; a failing test means fix the code, not `.skip` or delete the test. Feed CI failure output back verbatim and reproduce locally before re-pushing.
|
|
19
20
|
- **Introducing a gate that asserts on pre-existing state** (doc-drift, lint-vocabulary, dependency-cycle, missing-coverage) MUST land green at merge: either advisory-first (report-only until the backlog is burned down) or with the populated baseline committed in the same change that turns the gate on. Never wire a gate into `requiredChecks` that lands red on latent findings nobody authored.
|
|
20
21
|
- **Refresh a baseline only when the change is deliberate** — a rename/move, an operator-approved complexity bump, a signed-off perf delta, an intentional API-surface change. Never refresh to paper over an unintentional regression; fix the regression instead.
|
|
21
|
-
- **Pick the refresh that matches why you are refreshing** — the
|
|
22
|
+
- **Pick the refresh that matches why you are refreshing** — the wrong scope silently no-ops. `npm run <kind>:update` is **diff-scoped**: it re-scores only files changed in `origin/main..HEAD` and preserves every other row verbatim; that is what you want after changing code. `npm run <kind>:reanchor` is the same script with `--full-scope` and re-scores every file in every target dir; that is what you want when the baseline is **stale** (a scorer-version bump, a coverage-shape change, accumulated drift), because a diff-scoped run would leave the stale rows exactly as they were.
|
|
23
|
+
- Kinds carrying both scopes: `coverage`, `crap`, `maintainability`, `duplication`. Dead-exports has no scope axis — knip scores the whole graph, so `npm run dead-exports:update` (both passes) is the only sanctioned way to write `baselines/dead-exports.json` / `baselines/dead-exports-production.json`; never hand-edit them. Run any refresh on the **Story branch**, never on `main`.
|
|
22
24
|
- Verify the refresh diff is scoped to the relevant `baselines/<kind>.json` (plus cosmetic `package-lock.json` churn only). If unrelated files appear, STOP — the refresh is contaminated. Stage baseline files **explicitly** (`git add baselines/<kind>.json`); never `git add -A` in a refresh commit.
|
|
23
|
-
- Commit-subject contract:
|
|
24
|
-
- Add the machine-readable trailer `baseline-refresh: true` (git-trailer `Key: value` style) and `Story: #<storyId>` to
|
|
25
|
+
- Commit-subject contract: the **Conventional-Commits** subject `chore(baselines): refresh <kind> snapshot for <reason>` — never an ad-hoc leading token like `baseline-refresh:` (commitlint and the planner validator reject it). The body is **mandatory** and non-empty: what changed, why the new floor is correct, and the Story that triggered it.
|
|
26
|
+
- Add the machine-readable trailer `baseline-refresh: true` (git-trailer `Key: value` style) and `Story: #<storyId>` to that body. Never pass `--no-verify`; the `commit-msg` hook (commitlint) MUST run and pass.
|
|
25
27
|
- After the refresh lands, re-run `node .agents/scripts/check-baselines.js` to confirm the gate passes against the new snapshot; if it still fails, a sibling kind drifted — refresh that kind too.
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
## The Quality Gate Pipeline
|
|
29
|
-
|
|
30
|
-
Automate quality gates so no change reaches production without passing tests,
|
|
31
|
-
lint, type checking, and build. **Shift left** — a bug caught in linting costs
|
|
32
|
-
minutes; the same bug caught in production costs hours — and prefer many small,
|
|
33
|
-
frequent releases over big-bang merges (a deploy of 3 changes is debuggable, one
|
|
34
|
-
of 30 is not).
|
|
35
|
-
|
|
36
|
-
```text
|
|
37
|
-
lint → typecheck → unit tests → build → integration → E2E (optional)
|
|
38
|
-
→ security audit → bundle-size
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
**No gate can be skipped.** If lint fails, fix lint. If a test fails, fix the
|
|
42
|
-
code. When CI fails, feed the specific error back into the agent loop with the
|
|
43
|
-
directive to verify locally before re-pushing.
|
|
44
|
-
|
|
45
|
-
### Introducing a gate on pre-existing state
|
|
46
|
-
|
|
47
|
-
A new gate that asserts on latent state (doc-drift, lint-vocabulary,
|
|
48
|
-
dependency-cycle, missing-test-coverage) lands red because of findings nobody
|
|
49
|
-
authored, and every downstream PR is blocked until someone hotfixes the
|
|
50
|
-
integration branch. Before wiring such a gate into `requiredChecks`, land it in
|
|
51
|
-
a shape that is green at merge — **advisory-first** (report-only until the
|
|
52
|
-
backlog is burned down) or by **committing the populated baseline in the same
|
|
53
|
-
change** that turns the gate on.
|
|
54
|
-
|
|
55
|
-
## Baseline Refresh
|
|
56
|
-
|
|
57
|
-
The close-validation chain enforces unified baseline snapshots
|
|
58
|
-
(`baselines/crap.json`, `baselines/maintainability.json`,
|
|
59
|
-
`baselines/dead-exports.json`, `baselines/lighthouse.json`). A refresh is **not**
|
|
60
|
-
a regression entry — it tells the ratchet that the new baseline key is
|
|
61
|
-
intentional, so the gate compares future runs against the refreshed snapshot
|
|
62
|
-
rather than the prior one.
|
|
63
|
-
|
|
64
|
-
**When to refresh:** a file rename/move detached an MI/CRAP key; a method rename
|
|
65
|
-
inside a file produced a phantom new + phantom deleted key (escomplex keys CRAP
|
|
66
|
-
rows on `<file>::<methodName>`); an operator-approved complexity bump or perf
|
|
67
|
-
delta needs to be enshrined as the new floor; a dead-export gate flagged a
|
|
68
|
-
signed-off API-surface change. If the underlying change is an **unintentional**
|
|
69
|
-
regression, do not refresh — remediate first.
|
|
70
|
-
|
|
71
|
-
### Commit-subject contract (authoritative)
|
|
72
|
-
|
|
73
|
-
```text
|
|
74
|
-
chore(baselines): refresh <kind> snapshot for <reason>
|
|
75
|
-
|
|
76
|
-
<non-empty body explaining the refresh — what changed, why the new
|
|
77
|
-
baseline is the correct floor, and any operator sign-off reference>
|
|
78
|
-
|
|
79
|
-
baseline-refresh: true
|
|
80
|
-
Story: #<storyId>
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
The `commit-msg` hook (`commitlint`) rejects any subject whose leading token is
|
|
84
|
-
not one of `feat|fix|chore|refactor|perf|docs|style|test|build|ci|revert`, and
|
|
85
|
-
`--no-verify` is forbidden by
|
|
86
|
-
[`.agents/rules/git-conventions.md`](../../../rules/git-conventions.md), so the
|
|
87
|
-
subject MUST conform. `release-please` consumes the subject on `main`;
|
|
88
|
-
`chore(baselines):` keeps the refresh out of the user-facing changelog (correct —
|
|
89
|
-
it is internal hygiene) while staying machine-parseable. The
|
|
90
|
-
`baseline-refresh: true` **body trailer** is the canonical machine-readable
|
|
91
|
-
marker — subject-level leading tokens are not, and must not be, used for this
|
|
92
|
-
purpose. (Its only reader, `baseline-refresh-rate.js`, went with the
|
|
93
|
-
execution-analysis surface in Story #4545; the trailer convention stands on its
|
|
94
|
-
own as the parseable marker for any future reader.)
|
|
95
|
-
|
|
96
|
-
### Procedure
|
|
97
|
-
|
|
98
|
-
| Kind | After a code change (diff-scoped) | Stale baseline (full re-anchor) |
|
|
99
|
-
| --------------- | ---------------------------------- | ------------------------------------ |
|
|
100
|
-
| CRAP | `npm run crap:update` | `npm run crap:reanchor` |
|
|
101
|
-
| Maintainability | `npm run maintainability:update` | `npm run maintainability:reanchor` |
|
|
102
|
-
| Coverage | `npm run coverage:update` | `npm run coverage:reanchor` |
|
|
103
|
-
| Duplication | `npm run duplication:update` | `npm run duplication:reanchor` |
|
|
104
|
-
| Dead-exports | `npm run dead-exports:update` (regenerates both passes; never hand-edit the JSON) | same — no scope flag applies |
|
|
105
|
-
| Lighthouse | edit `baselines/lighthouse.json` | same — no scope flag applies |
|
|
106
|
-
|
|
107
|
-
1. **Run the matching command for your reason** — left column after a code
|
|
108
|
-
change, right column for a stale baseline — on the Story branch (HEAD must
|
|
109
|
-
already be the Story branch, not `main`).
|
|
110
|
-
2. **Verify the diff is scoped** to the relevant `baselines/<kind>.json` (and
|
|
111
|
-
possibly cosmetic `package-lock.json` churn). Unrelated files → STOP, the
|
|
112
|
-
refresh is contaminated. Judge contamination by **which files** changed, not
|
|
113
|
-
how many rows moved inside the baseline: a `:reanchor` legitimately rewrites
|
|
114
|
-
most of its own file, so say in the commit body that the breadth is a
|
|
115
|
-
re-anchor and not a mass regression.
|
|
116
|
-
3. **Author the commit.** Stage the baseline file(s) explicitly, then commit with
|
|
117
|
-
the Conventional-Commits subject + body trailer above:
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
git add baselines/<kind>.json
|
|
121
|
-
git commit -m "$(cat <<'EOF'
|
|
122
|
-
chore(baselines): refresh <kind> snapshot for <reason>
|
|
123
|
-
|
|
124
|
-
<body: what changed, why the new floor is correct, linking the Story.>
|
|
125
|
-
|
|
126
|
-
baseline-refresh: true
|
|
127
|
-
Story: #<storyId>
|
|
128
|
-
EOF
|
|
129
|
-
)"
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
Do NOT pass `--no-verify`.
|
|
133
|
-
4. **Re-run the gate** — `node .agents/scripts/check-baselines.js`. If it still
|
|
134
|
-
fails, a sibling kind drifted; repeat from step 1 for that kind.
|
|
135
|
-
|
|
136
|
-
## Red Flags
|
|
137
|
-
|
|
138
|
-
- CI failures ignored or silenced; tests disabled in CI to make the pipeline pass.
|
|
139
|
-
- A new required gate merged red on pre-existing findings, blocking every
|
|
140
|
-
downstream PR.
|
|
141
|
-
- A legacy ad-hoc leading token (`baseline-refresh:`) as the commit subject type.
|
|
142
|
-
- An empty-body refresh — unreviewable, hides the operator decision.
|
|
143
|
-
- A refresh commit whose diff touches unrelated files (contaminated refresh).
|
|
144
|
-
- Refreshing to paper over an unintentional regression.
|
|
145
|
-
- Secrets stored in code or CI config instead of a secrets manager.
|
|
146
|
-
|
|
147
|
-
## Verification
|
|
148
|
-
|
|
149
|
-
- [ ] Every quality gate is present (lint, types, tests, build, audit) and
|
|
150
|
-
failures block merge (branch protection configured).
|
|
151
|
-
- [ ] Any newly introduced gate is green at merge (advisory-first or
|
|
152
|
-
baseline-in-same-change).
|
|
153
|
-
- [ ] A baseline refresh uses the Conventional-Commits subject + non-empty body
|
|
154
|
-
+ `baseline-refresh: true` trailer, staged explicitly, no `--no-verify`.
|
|
155
|
-
- [ ] `check-baselines.js` passes against the refreshed snapshot.
|
|
28
|
+
- Open a [`reference.md`](reference.md) section only when the task engages it: the baseline roster, the per-kind refresh table, and the step-by-step procedure live there.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Gates and Baselines — Reference (on-demand)
|
|
2
|
+
|
|
3
|
+
**Read this when** a refresh is actually in front of you and the Policy Capsule
|
|
4
|
+
in [`SKILL.md`](SKILL.md) does not settle it. The capsule is the contract; this
|
|
5
|
+
file is the roster, the per-kind command table, and the procedure.
|
|
6
|
+
|
|
7
|
+
## The baseline roster
|
|
8
|
+
|
|
9
|
+
`baselines/` holds one snapshot per gate kind. What is present here is what
|
|
10
|
+
`check-baselines.js` and its siblings enforce:
|
|
11
|
+
|
|
12
|
+
| Baseline | Enforced by |
|
|
13
|
+
| --- | --- |
|
|
14
|
+
| `coverage.json` | `npm run coverage:check` |
|
|
15
|
+
| `crap.json` | `npm run crap:check` |
|
|
16
|
+
| `maintainability.json` | `npm run maintainability:check` |
|
|
17
|
+
| `duplication.json` | `npm run duplication:check` |
|
|
18
|
+
| `dead-exports.json`, `dead-exports-production.json` | `check-dead-exports.js` |
|
|
19
|
+
| `arch-cycles.json` | `npm run check:arch` |
|
|
20
|
+
| `cyclomatic.json` | `npm run check:cyclomatic` |
|
|
21
|
+
| `context-budget.json` | `npm run check:context-budget` |
|
|
22
|
+
| `workflow-citations.json` | `npm run check:workflow-citations` |
|
|
23
|
+
| `agents-loc.csv` | `npm run baseline:agents-loc` |
|
|
24
|
+
|
|
25
|
+
A refresh is **not** a regression entry — it tells the ratchet that the new
|
|
26
|
+
baseline key is intentional, so the gate compares future runs against the
|
|
27
|
+
refreshed snapshot rather than the prior one.
|
|
28
|
+
|
|
29
|
+
**When to refresh:** a file rename/move detached an MI/CRAP key; a method
|
|
30
|
+
rename inside a file produced a phantom new + phantom deleted key (escomplex
|
|
31
|
+
keys CRAP rows on `<file>::<methodName>`); an operator-approved complexity bump
|
|
32
|
+
or perf delta needs to be enshrined as the new floor; a dead-export gate
|
|
33
|
+
flagged a signed-off API-surface change. If the underlying change is an
|
|
34
|
+
**unintentional** regression, do not refresh — remediate first.
|
|
35
|
+
|
|
36
|
+
## Per-kind refresh commands
|
|
37
|
+
|
|
38
|
+
| Kind | After a code change (diff-scoped) | Stale baseline (full re-anchor) |
|
|
39
|
+
| --------------- | ---------------------------------- | ------------------------------------ |
|
|
40
|
+
| CRAP | `npm run crap:update` | `npm run crap:reanchor` |
|
|
41
|
+
| Maintainability | `npm run maintainability:update` | `npm run maintainability:reanchor` |
|
|
42
|
+
| Coverage | `npm run coverage:update` | `npm run coverage:reanchor` |
|
|
43
|
+
| Duplication | `npm run duplication:update` | `npm run duplication:reanchor` |
|
|
44
|
+
| Dead-exports | `npm run dead-exports:update` (regenerates both passes; never hand-edit the JSON) | same — no scope flag applies |
|
|
45
|
+
| Cyclomatic | `npm run cyclomatic:update` | same — no scope flag applies |
|
|
46
|
+
| Context budget | `node .agents/scripts/check-context-budget.js --update` | same — no scope flag applies |
|
|
47
|
+
|
|
48
|
+
## Procedure
|
|
49
|
+
|
|
50
|
+
1. **Run the matching command for your reason** — left column after a code
|
|
51
|
+
change, right column for a stale baseline — on the Story branch (HEAD must
|
|
52
|
+
already be the Story branch, not `main`).
|
|
53
|
+
2. **Verify the diff is scoped** to the relevant `baselines/<kind>.json` (and
|
|
54
|
+
possibly cosmetic `package-lock.json` churn). Unrelated files → STOP, the
|
|
55
|
+
refresh is contaminated. Judge contamination by **which files** changed, not
|
|
56
|
+
how many rows moved inside the baseline: a `:reanchor` legitimately rewrites
|
|
57
|
+
most of its own file, so say in the commit body that the breadth is a
|
|
58
|
+
re-anchor and not a mass regression.
|
|
59
|
+
3. **Author the commit.** Stage the baseline file(s) explicitly, then commit
|
|
60
|
+
with the Conventional-Commits subject the capsule pins, plus the body and
|
|
61
|
+
trailers:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
git add baselines/<kind>.json
|
|
65
|
+
git commit -m "$(cat <<'EOF'
|
|
66
|
+
<the refresh subject the Policy Capsule pins>
|
|
67
|
+
|
|
68
|
+
<body: what changed, why the new floor is correct, linking the Story.>
|
|
69
|
+
|
|
70
|
+
baseline-refresh: true
|
|
71
|
+
Story: #<storyId>
|
|
72
|
+
EOF
|
|
73
|
+
)"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Do NOT pass `--no-verify`.
|
|
77
|
+
4. **Re-run the gate** — `node .agents/scripts/check-baselines.js`. If it still
|
|
78
|
+
fails, a sibling kind drifted; repeat from step 1 for that kind.
|
|
79
|
+
|
|
80
|
+
The `baseline-refresh: true` body trailer — not a subject-level token — is the
|
|
81
|
+
canonical machine-readable marker for a refresh commit; the decision and its
|
|
82
|
+
history are recorded in
|
|
83
|
+
[`docs/decisions.md` ADR 20260906-5160b](../../../../docs/decisions.md).
|
|
84
|
+
|
|
85
|
+
## Red Flags
|
|
86
|
+
|
|
87
|
+
- CI failures ignored or silenced; tests disabled in CI to make the pipeline
|
|
88
|
+
pass.
|
|
89
|
+
- A new required gate merged red on pre-existing findings, blocking every
|
|
90
|
+
downstream PR.
|
|
91
|
+
- A legacy ad-hoc leading token (`baseline-refresh:`) as the commit subject
|
|
92
|
+
type.
|
|
93
|
+
- An empty-body refresh — unreviewable, hides the operator decision.
|
|
94
|
+
- A refresh commit whose diff touches unrelated files (contaminated refresh).
|
|
95
|
+
- Refreshing to paper over an unintentional regression.
|
|
96
|
+
|
|
97
|
+
## Verification
|
|
98
|
+
|
|
99
|
+
- [ ] Any newly introduced gate is green at merge (advisory-first or
|
|
100
|
+
baseline-in-same-change).
|
|
101
|
+
- [ ] A baseline refresh uses the pinned subject + non-empty body +
|
|
102
|
+
`baseline-refresh: true` trailer, staged explicitly, no `--no-verify`.
|
|
103
|
+
- [ ] `check-baselines.js` passes against the refreshed snapshot.
|
|
@@ -34,15 +34,6 @@ separate Epic Clarity Gate path in v2 — N=1 Story authoring with a folded
|
|
|
34
34
|
You are an ideation partner. Your job is to help refine raw ideas into sharp,
|
|
35
35
|
actionable concepts worth building.
|
|
36
36
|
|
|
37
|
-
### Philosophy
|
|
38
|
-
|
|
39
|
-
- Simplicity is the ultimate sophistication. Push toward the simplest version
|
|
40
|
-
that still solves the real problem.
|
|
41
|
-
- Start with the user experience, work backwards to technology.
|
|
42
|
-
- Say no to 1,000 things. Focus beats breadth.
|
|
43
|
-
- Challenge every assumption. "How it's usually done" is not a reason.
|
|
44
|
-
- Show people the future — don't just give them better horses.
|
|
45
|
-
|
|
46
37
|
### Process
|
|
47
38
|
|
|
48
39
|
When the user invokes this skill with an idea (`$ARGUMENTS`), guide them through
|
|
@@ -93,9 +84,8 @@ before anything lands in the Phase 3 one-pager.
|
|
|
93
84
|
vitamin), feasibility branches (cost, hardest part, build vs. buy,
|
|
94
85
|
sequencing), differentiation branches (why switch), and hidden assumptions
|
|
95
86
|
(what you're betting is true, what could kill this, what you're ignoring and
|
|
96
|
-
why that's okay for now).
|
|
97
|
-
|
|
98
|
-
enumeration, take the off-ramp.
|
|
87
|
+
why that's okay for now). If the list is empty after enumeration, take the
|
|
88
|
+
off-ramp.
|
|
99
89
|
|
|
100
90
|
3. **Interrogate sequentially.** For each branch, in priority order
|
|
101
91
|
(highest-leverage / most blocking first):
|
|
@@ -177,9 +167,3 @@ saying no to good ideas. Make the trade-offs explicit.
|
|
|
177
167
|
|
|
178
168
|
Ask the user if they'd like to save this to `docs/ideas/[idea-name].md` (or a
|
|
179
169
|
location of their choosing). Only save if they confirm.
|
|
180
|
-
|
|
181
|
-
### Tone
|
|
182
|
-
|
|
183
|
-
Direct, thoughtful, slightly provocative. You're a sharp thinking partner, not a
|
|
184
|
-
facilitator reading from a script. Channel the energy of "that's interesting,
|
|
185
|
-
but what if…" — always pushing one step further without being exhausting.
|
|
@@ -4,8 +4,8 @@ description:
|
|
|
4
4
|
Hardens code against vulnerabilities. Use when handling user input,
|
|
5
5
|
authentication, data storage, or external integrations. The non-negotiable
|
|
6
6
|
security MUSTs live in `.agents/rules/security-baseline.md`; this skill shows
|
|
7
|
-
how to apply them with
|
|
8
|
-
|
|
7
|
+
how to apply them, with the project's surfacing and validation-response
|
|
8
|
+
process.
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Security and Hardening
|
|
@@ -35,5 +35,3 @@ task engages it.
|
|
|
35
35
|
|
|
36
36
|
- [Security Surfacing, Not Runtime Pause](reference.md#security-surfacing-not-runtime-pause)
|
|
37
37
|
- [Validation-Error Responses](reference.md#validation-error-responses)
|
|
38
|
-
- [Triaging npm audit Results](reference.md#triaging-npm-audit-results)
|
|
39
|
-
- [Security Review Checklist](reference.md#security-review-checklist)
|
|
@@ -45,73 +45,3 @@ and [§ Response Envelope](../../../rules/api-conventions.md#response-envelope).
|
|
|
45
45
|
Do not hand-roll a divergent status (e.g. 422) or envelope shape in
|
|
46
46
|
security-relevant handlers — cite the rule and reuse its shape, keeping the
|
|
47
47
|
security skill and the api skill in agreement.
|
|
48
|
-
|
|
49
|
-
## Triaging npm audit Results
|
|
50
|
-
|
|
51
|
-
The MUST is in [security-baseline § Dependency Hygiene](../../../rules/security-baseline.md#dependency-hygiene).
|
|
52
|
-
This decision tree shows how to prioritize:
|
|
53
|
-
|
|
54
|
-
```text
|
|
55
|
-
npm audit reports a vulnerability
|
|
56
|
-
├── Severity: critical or high
|
|
57
|
-
│ ├── Is the vulnerable code reachable in your app?
|
|
58
|
-
│ │ ├── YES --> Fix immediately (update, patch, or replace the dependency)
|
|
59
|
-
│ │ └── NO (dev-only dep, unused code path) --> Fix soon, but not a blocker
|
|
60
|
-
│ └── Is a fix available?
|
|
61
|
-
│ ├── YES --> Update to the patched version
|
|
62
|
-
│ └── NO --> Check for workarounds, consider replacing the dependency, or add to allowlist with a review date
|
|
63
|
-
├── Severity: moderate
|
|
64
|
-
│ ├── Reachable in production? --> Fix in the next release cycle
|
|
65
|
-
│ └── Dev-only? --> Fix when convenient, track in backlog
|
|
66
|
-
└── Severity: low
|
|
67
|
-
└── Track and fix during regular dependency updates
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
**Key questions:**
|
|
71
|
-
|
|
72
|
-
- Is the vulnerable function actually called in your code path?
|
|
73
|
-
- Is the dependency a runtime dependency or dev-only?
|
|
74
|
-
- Is the vulnerability exploitable given your deployment context (e.g., a
|
|
75
|
-
server-side vulnerability in a client-only app)?
|
|
76
|
-
|
|
77
|
-
When you defer a fix, document the reason and set a review date.
|
|
78
|
-
|
|
79
|
-
## Security Review Checklist
|
|
80
|
-
|
|
81
|
-
Use this when reviewing your own change before requesting human review. Each
|
|
82
|
-
item maps to a section in
|
|
83
|
-
[`security-baseline.md`](../../../rules/security-baseline.md).
|
|
84
|
-
|
|
85
|
-
```markdown
|
|
86
|
-
### Authentication
|
|
87
|
-
|
|
88
|
-
- [ ] Passwords hashed with bcrypt/scrypt/argon2 (salt rounds ≥ 12)
|
|
89
|
-
- [ ] Session tokens are httpOnly, secure, sameSite
|
|
90
|
-
- [ ] Login has rate limiting
|
|
91
|
-
- [ ] Password reset tokens expire
|
|
92
|
-
|
|
93
|
-
### Authorization
|
|
94
|
-
|
|
95
|
-
- [ ] Every endpoint checks user permissions
|
|
96
|
-
- [ ] Users can only access their own resources
|
|
97
|
-
- [ ] Admin actions require admin role verification
|
|
98
|
-
|
|
99
|
-
### Input
|
|
100
|
-
|
|
101
|
-
- [ ] All user input validated at the boundary
|
|
102
|
-
- [ ] SQL queries are parameterized
|
|
103
|
-
- [ ] HTML output is encoded/escaped
|
|
104
|
-
|
|
105
|
-
### Data
|
|
106
|
-
|
|
107
|
-
- [ ] No secrets in code or version control
|
|
108
|
-
- [ ] Sensitive fields excluded from API responses
|
|
109
|
-
- [ ] PII encrypted at rest (if applicable)
|
|
110
|
-
|
|
111
|
-
### Infrastructure
|
|
112
|
-
|
|
113
|
-
- [ ] Security headers configured (CSP, HSTS, etc.)
|
|
114
|
-
- [ ] CORS restricted to known origins
|
|
115
|
-
- [ ] Dependencies audited for vulnerabilities
|
|
116
|
-
- [ ] Error messages don't expose internals
|
|
117
|
-
```
|