mandrel 2.40.0 → 2.42.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 (90) hide show
  1. package/.agents/README.md +2 -2
  2. package/.agents/agents/story-worker.md +24 -14
  3. package/.agents/docs/agentrc-reference.json +7 -2
  4. package/.agents/docs/configuration.md +5 -2
  5. package/.agents/instructions.md +5 -6
  6. package/.agents/rules/api-conventions.md +43 -7
  7. package/.agents/rules/ci-remediation.md +3 -14
  8. package/.agents/rules/gherkin-standards.md +21 -6
  9. package/.agents/rules/git-conventions.md +6 -5
  10. package/.agents/rules/security-baseline.md +6 -7
  11. package/.agents/rules/testing-standards.md +75 -198
  12. package/.agents/schemas/agentrc.schema.json +17 -2
  13. package/.agents/schemas/validation-evidence.schema.json +3 -1
  14. package/.agents/scripts/acceptance-eval.js +68 -3
  15. package/.agents/scripts/coverage-capture.js +25 -8
  16. package/.agents/scripts/install-matrix-assert.js +2 -2
  17. package/.agents/scripts/lib/audit-to-stories/epic-grouping-directive.js +6 -0
  18. package/.agents/scripts/lib/baselines/crap-preview-incremental.js +7 -2
  19. package/.agents/scripts/lib/baselines/git-base.js +74 -38
  20. package/.agents/scripts/lib/close-validation/gates.js +153 -25
  21. package/.agents/scripts/lib/close-validation/process.js +30 -1
  22. package/.agents/scripts/lib/close-validation/runner.js +5 -0
  23. package/.agents/scripts/lib/config/gates/crap-incremental-coverage.schema.js +33 -12
  24. package/.agents/scripts/lib/config/quality.js +36 -21
  25. package/.agents/scripts/lib/config-settings-schema-delivery.js +6 -0
  26. package/.agents/scripts/lib/coverage-capture-incremental.js +12 -6
  27. package/.agents/scripts/lib/crap-baseline-join.js +11 -7
  28. package/.agents/scripts/lib/full-suite-lock.js +311 -0
  29. package/.agents/scripts/lib/generated/agentrc-validator.js +1 -1
  30. package/.agents/scripts/lib/orchestration/check-baselines/phases/evaluate.js +11 -104
  31. package/.agents/scripts/lib/orchestration/check-baselines/phases/refresh-ack.js +320 -0
  32. package/.agents/scripts/lib/orchestration/check-baselines/phases/report.js +8 -1
  33. package/.agents/scripts/lib/orchestration/dependency-candidates.js +139 -0
  34. package/.agents/scripts/lib/orchestration/epic-candidates.js +159 -0
  35. package/.agents/scripts/lib/orchestration/epic-checklist.js +103 -0
  36. package/.agents/scripts/lib/orchestration/epic-container.js +18 -2
  37. package/.agents/scripts/lib/orchestration/plan-context.js +97 -36
  38. package/.agents/scripts/lib/orchestration/plan-persist/cross-plan-links.js +80 -0
  39. package/.agents/scripts/lib/orchestration/plan-persist/epic-adoption.js +192 -0
  40. package/.agents/scripts/lib/orchestration/plan-persist/epic-ops.js +5 -1
  41. package/.agents/scripts/lib/orchestration/plan-persist/external-deps.js +164 -0
  42. package/.agents/scripts/lib/orchestration/plan-persist/run-plan-persist.js +14 -2
  43. package/.agents/scripts/lib/orchestration/plan-persist/story-ops.js +26 -5
  44. package/.agents/scripts/lib/orchestration/single-story-close/failed-terminal.js +83 -4
  45. package/.agents/scripts/lib/orchestration/single-story-close/phases/close-validation.js +39 -7
  46. package/.agents/scripts/lib/orchestration/single-story-close/runner.js +70 -18
  47. package/.agents/scripts/lib/orchestration/ticket-validator.js +11 -1
  48. package/.agents/scripts/lib/orchestration/verify-credit.js +207 -0
  49. package/.agents/scripts/lib/single-story-sweep/sweep-lock.js +24 -0
  50. package/.agents/scripts/plan-persist.js +60 -1
  51. package/.agents/skills/core/browser-testing-with-devtools/SKILL.md +5 -10
  52. package/.agents/skills/core/browser-testing-with-devtools/reference.md +7 -46
  53. package/.agents/skills/core/code-review-and-quality/SKILL.md +0 -5
  54. package/.agents/skills/core/documentation-and-adrs/SKILL.md +0 -3
  55. package/.agents/skills/core/gates-and-baselines/SKILL.md +10 -137
  56. package/.agents/skills/core/gates-and-baselines/reference.md +103 -0
  57. package/.agents/skills/core/idea-refinement/SKILL.md +2 -18
  58. package/.agents/skills/core/security-and-hardening/SKILL.md +2 -4
  59. package/.agents/skills/core/security-and-hardening/reference.md +0 -70
  60. package/.agents/skills/skills.index.json +10 -70
  61. package/.agents/skills/stack/qa/gherkin-authoring/SKILL.md +4 -10
  62. package/.agents/skills/stack/qa/gherkin-authoring/reference.md +9 -113
  63. package/.agents/skills/stack/qa/playwright-bdd/SKILL.md +29 -154
  64. package/.agents/skills/stack/qa/qa-harness/SKILL.md +157 -98
  65. package/.agents/workflows/git-cleanup.md +3 -2
  66. package/.agents/workflows/git-deliver.md +3 -2
  67. package/.agents/workflows/helpers/acceptance-self-eval.md +12 -0
  68. package/.agents/workflows/helpers/deliver-digest.md +31 -10
  69. package/.agents/workflows/helpers/deliver-story-reference.md +50 -30
  70. package/.agents/workflows/helpers/deliver-story.md +23 -21
  71. package/.agents/workflows/helpers/plan-reference.md +82 -2
  72. package/.agents/workflows/mandrel-plan.md +45 -45
  73. package/.agents/workflows/qa-assist.md +20 -17
  74. package/.agents/workflows/qa-explore.md +30 -29
  75. package/.agents/workflows/qa-run.md +2 -1
  76. package/docs/CHANGELOG.md +32 -0
  77. package/package.json +1 -1
  78. package/.agents/rules/changelog-style.md +0 -180
  79. package/.agents/rules/shell-conventions.md +0 -61
  80. package/.agents/scripts/lib/qa/coverage-verdict.js +0 -214
  81. package/.agents/skills/core/api-and-interface-design/SKILL.md +0 -55
  82. package/.agents/skills/core/api-and-interface-design/reference.md +0 -76
  83. package/.agents/skills/core/debugging-and-error-recovery/SKILL.md +0 -45
  84. package/.agents/skills/core/debugging-and-error-recovery/reference.md +0 -56
  85. package/.agents/skills/core/git-workflow-and-versioning/SKILL.md +0 -54
  86. package/.agents/skills/core/idea-refinement/refinement-criteria.md +0 -155
  87. package/.agents/skills/core/idea-refinement/scripts/idea-refine.sh +0 -15
  88. package/.agents/skills/core/qa-coverage-mapping/SKILL.md +0 -105
  89. package/.agents/skills/stack/qa/qa-explore-driving/SKILL.md +0 -152
  90. package/.agents/skills/stack/qa/vitest/SKILL.md +0 -22
@@ -1,180 +0,0 @@
1
- # CHANGELOG Style Contract
2
-
3
- This rule governs the shape of per-release entries in the project CHANGELOG
4
- (typically `docs/CHANGELOG.md` or `CHANGELOG.md`). It applies whenever a
5
- release entry is authored or edited — most commonly inside Story #N's
6
- docs sweep before `/mandrel-deliver` opens the release PR.
7
-
8
- The contract is **guidance-tier**: no automated gate fails a close when an
9
- entry drifts off-template. It still binds every author.
10
-
11
- ## Goal
12
-
13
- A reader scanning release notes should identify what ships in a release in
14
- under 30 seconds. Breaking changes, config-shape changes, and CLI renames
15
- must be impossible to miss. Internal refactor detail belongs in commit
16
- messages and PR descriptions — not here.
17
-
18
- ## Per-Release Entry Shape
19
-
20
- Every entry starts with a version header line already produced by the
21
- release tooling:
22
-
23
- ```markdown
24
- ## [X.Y.Z] - YYYY-MM-DD
25
- ```
26
-
27
- Immediately below, the entry MUST have:
28
-
29
- 1. **A short section header** naming the theme of the release — one line,
30
- Sentence case, no trailing punctuation.
31
-
32
- ```markdown
33
- ### Epic-runner throughput & caching pass
34
- ```
35
-
36
- 2. **A 1–3 sentence theme paragraph** that tells the reader, in plain
37
- English, what the release is about and why it matters. No bullets, no
38
- sub-headers, no code fences.
39
-
40
- 3. **Bullets of user-visible changes**, grouped by natural topic if the
41
- release spans more than one theme. Each bullet leads with a bold phrase
42
- naming the change, followed by a one- or two-sentence explanation.
43
-
44
- ```markdown
45
- ## [5.21.0] - 2026-04-24
46
-
47
- ### Epic-runner throughput & caching pass
48
-
49
- Performance and observability pass across the epic-runner hot paths — wave
50
- gating, commit assertion, progress reporting, and label polling. Caching
51
- and bounded concurrency throughout; new per-phase timing surface.
52
-
53
- - **Bounded-concurrency parallelism.** Wave gating, commit assertion, and
54
- progress reporting now fan out in parallel with a configurable cap.
55
- - **Per-phase timing surface.** Story close posts a structured comment
56
- with per-phase timings; the Epic progress comment aggregates median
57
- and p95 across closed stories.
58
- ```
59
-
60
- ## Bullets: What Counts as "User-Visible"
61
-
62
- Include:
63
-
64
- - New CLI commands, flags, or scripts the operator invokes.
65
- - New or renamed labels, ticket shapes, or workflow phases the operator
66
- touches.
67
- - New or renamed configuration keys, with the old → new mapping if any.
68
- - New behavioural guarantees (e.g., "retries on transient errors").
69
- - Bug fixes the operator would otherwise trip over.
70
- - Performance changes with a user-observable magnitude.
71
-
72
- Exclude:
73
-
74
- - Internal refactors with no behavioural delta.
75
- - Test additions, coverage bumps, lint cleanups.
76
- - Module renames or file moves invisible to operators.
77
- - Per-phase implementation details ("now uses a BFS walker").
78
-
79
- ## Banned Content
80
-
81
- The following MUST NOT appear in a release entry:
82
-
83
- - **Per-ticket citations.** No `(Epic #553)`, `(resolves #612)`,
84
- `(Story #645)` in bullet text. The theme paragraph may reference the
85
- Epic once when the release is scoped to one Epic — that is the only
86
- allowed citation, and only there.
87
- - **Internal file paths** (`lib/orchestration/epic-runner/commit-assertion.js`,
88
- `.agents/scripts/story-init.js`). Callers care what changed, not
89
- where it lives.
90
- - **Internal function, class, or method names** (`finalizeMerge`,
91
- `WorkspaceProvisioner.verify`, `cascadeCompletion`). Name the behaviour,
92
- not the symbol — unless the symbol is part of the public API.
93
- - **Test counts** (`47 new tests`, `95% coverage`). Tests are a means, not
94
- a ship artefact.
95
- - **Module-sizing stats** (`shrinks epic-runner from 840 to 420 LOC`).
96
- - **Implementation mechanics** (`BFS walker`, `Promise.all over parents`,
97
- `exponential backoff with 3 attempts, 500ms base`) unless the mechanism
98
- is part of a new public contract.
99
-
100
- ## Mandatory Prominence
101
-
102
- The following categories MUST be called out visibly — typically in **bold**
103
- at the start of a bullet, or in a short dedicated section above the
104
- bullet list:
105
-
106
- - **Breaking changes.** A bullet leading with `**Breaking:**` or a
107
- `### Breaking Changes` sub-section. Include the migration path.
108
- - **Config-shape changes.** Moved, removed, renamed, or newly-required
109
- config keys. Old key → new key, or removal notice with remediation.
110
- - **CLI renames.** Old command → new command, including whether the old
111
- name remains as a deprecation alias and for how long.
112
- - **Schema shape changes** on structured comments, manifest files, or
113
- public API payloads. Readers parsing these surfaces must be told.
114
-
115
- If a release ships any of the above, they belong at the top of the bullet
116
- list (or in a dedicated sub-section), not buried mid-list.
117
-
118
- ## Line-Count Guidance
119
-
120
- Soft ceilings, not hard fails:
121
-
122
- - **Non-major release** (patch or minor): **≤60 lines**, including
123
- header, theme paragraph, blank lines, and bullets.
124
- - **Major release**: **≤150 lines**. Major releases span larger surface
125
- and warrant more prominence.
126
-
127
- If an entry exceeds the ceiling, prefer splitting a genuinely multi-theme
128
- release into grouped sub-sections over padding the bullet list. Before
129
- accepting a long entry, ask: which bullets are user-visible, and which
130
- are internal detail that migrated in from the Epic body?
131
-
132
- ## Worked Example — On-Contract
133
-
134
- Off-contract entries — the style that drove the Epic #553 retro action item —
135
- pack several `###` sub-sections into one release and leak internal function
136
- names (`finalizeMerge`, `mergeFeatureBranch`, `ensure()`, `reap()`),
137
- implementation mechanics, internal step numbering, and lock-file name lists
138
- operators cannot act on. The on-contract version collapses all of that:
139
-
140
- ```markdown
141
- ## [5.8.7] - 2026-04-15
142
-
143
- ### Parallel-wave merge robustness
144
-
145
- Parallel story waves kept tripping over each other at integration time.
146
- This release reduces the conflict surface at story close and stabilises
147
- worktree cleanup.
148
-
149
- - **Pre-merge rebase at story close** shrinks the conflict window to
150
- each story's real delta; conflicts above the triage threshold abort
151
- and surface to the operator.
152
- - **Shared-store worktrees.** Per-story worktrees link a shared
153
- `node_modules` store, so parallel waves no longer duplicate installs
154
- or leave residue that blocks reap.
155
- - **`/mandrel-deliver` auto-invokes pre-merge gates** (code review, retro)
156
- inline. `--skip-code-review` is available as an override.
157
- - **Closure sweep covers Epic Health tickets** in addition to PRD and
158
- Tech Spec tickets.
159
- - **Stale-lock sweep** on the shared `.git/` directory runs at
160
- `/mandrel-deliver` start, clearing lock files left behind by interrupted
161
- operations.
162
- ```
163
-
164
- What changed: one theme section instead of five; the paragraph gives the
165
- "why" in two sentences; each bullet leads with the user-visible behaviour
166
- and drops internal symbols, file paths, and step numbers; the override
167
- flag (`--skip-code-review`) is kept because it is part of the public CLI
168
- surface; the lock-file list is dropped because operators do not act on
169
- individual lock names.
170
-
171
- ## When to Deviate
172
-
173
- - **Major releases** may warrant multiple `###` sub-sections under a
174
- single version header when the release genuinely spans multiple themes.
175
- Keep each sub-section on-contract individually.
176
- - **Security fixes** may include CVE-style detail and remediation steps
177
- beyond normal bullet shape — those callouts are always on-contract.
178
- - **When in doubt**, cut more aggressively. A reader can always follow
179
- the Epic link for detail; they cannot un-read bullets that told them
180
- nothing.
@@ -1,61 +0,0 @@
1
- # Shell & Terminal Conventions
2
-
3
- This rule applies when running shell commands during agent execution. The host
4
- shell varies — agents must adapt to the environment.
5
-
6
- ## Detecting the Shell
7
-
8
- Before chaining commands, check the host shell. Common signals:
9
-
10
- - `$env:COMSPEC` set / `pwsh.exe` or `powershell.exe` → PowerShell
11
- - `$SHELL` set to `/bin/bash`, `/bin/zsh`, etc. → POSIX shell
12
- - Claude Code system prompt or harness directive announces the shell
13
-
14
- ## PowerShell (Windows)
15
-
16
- PowerShell 5.1 (default on Windows) does **not** support `&&` as a statement
17
- separator and will throw a parser error. PowerShell 7+ does, but agents
18
- running on Windows should not assume version 7+.
19
-
20
- - **Standard separator**: `;` runs the next command regardless of the first's
21
- exit status.
22
- - **Success chaining (logical AND)**: `; if ($?) { ... }` runs the second
23
- command only when the first succeeded.
24
- - **Example**: `git add . ; if ($?) { git commit -m "..." }`
25
-
26
- Other PowerShell-isms agents must respect:
27
-
28
- - Use `$null` (not `/dev/null`).
29
- - Use `$env:VAR` (not `$VAR`).
30
- - Use backtick (`` ` ``) for line continuation, not backslash.
31
-
32
- ## POSIX Shells (bash / zsh)
33
-
34
- `&&` and `||` work natively. No translation needed.
35
-
36
- - **Success chaining**: `cmd1 && cmd2`
37
- - **Fallback**: `cmd1 || cmd2`
38
-
39
- ## Cross-Platform Tips
40
-
41
- - Prefer the host's tool wrappers (Bash tool, etc.) over raw shell strings
42
- when the harness exposes them — they normalize quoting and escaping.
43
- - For multi-step pipelines that must run identically across platforms, write
44
- a Node/Python script and invoke that, rather than chaining shell builtins.
45
-
46
- ## Searching the Workspace
47
-
48
- Prefer, in order: the host's dedicated grep tool (ripgrep-backed — normalizes
49
- quoting, respects `.gitignore`, streams results), then `git grep` in a git
50
- repo (`-l` for filenames only), then `rg` outside a git repo or when you need
51
- multiline / type filters. Do not read whole files to scan for a pattern.
52
-
53
- ### PowerShell-specific anti-patterns
54
-
55
- - If you must use `Select-String`, pass `-List` when you only need to
56
- detect existence or collect file paths — without it, every match streams
57
- through the pipeline.
58
- - NEVER chain `Select-Object -Unique` or `Sort-Object` directly after a
59
- highly recursive `Get-ChildItem` on large trees. Both block the pipeline,
60
- hold every result in memory, and frequently hang the terminal. Stream
61
- through `Where-Object` filters first, or pre-narrow with a glob.
@@ -1,214 +0,0 @@
1
- // .agents/scripts/lib/qa/coverage-verdict.js
2
- //
3
- // Deterministic per-tier coverage verdict for a single finding surface.
4
- //
5
- // A "finding surface" is the unit of code a quality finding points at — a
6
- // symbol (function / class / module export) together with the set of tests
7
- // that exercise it. This helper answers one question, purely and without I/O:
8
- // for that surface, which of the three test tiers from
9
- // `.agents/rules/testing-standards.md` (unit / contract / acceptance) are
10
- // PRESENT, and which are ABSENT — and why.
11
- //
12
- // A scenario that is skipped does not exercise anything — a `@skip`
13
- // Gherkin tag (or a runner equivalent such as `it.skip` / `xit` /
14
- // `describe.skip`, or a `skipped: true` descriptor field) means the test is
15
- // inert at run time. This module therefore treats a skipped test as ABSENT
16
- // for its tier: it never bumps a tier into `present`, because a tier whose
17
- // only "coverage" is a skipped scenario is, operationally, uncovered.
18
- //
19
- // The companion process skill is `core/qa-coverage-mapping`, which shows how
20
- // to gather the surface input and act on the verdict. This module is the
21
- // deterministic seam that skill delegates to; it makes no network calls, runs
22
- // no child processes, and reads no environment or files.
23
- //
24
- // Public API:
25
- //
26
- // coverageVerdict(surface) -> {
27
- // unit: { status, note },
28
- // contract: { status, note },
29
- // acceptance: { status, note },
30
- // }
31
- //
32
- // status is 'present' when the tier has at least one classified,
33
- // non-skipped test, or 'absent' otherwise. `note` is a short
34
- // operator-facing string explaining the verdict (always populated,
35
- // including for present tiers).
36
- //
37
- // Story #5008 removed the `acceptanceMatrix` feeder and the markdown report it
38
- // fed: the QA workflows read the per-tier verdict and author the missing-test
39
- // prose directly, so the AC x tier matrix was a round-trip with no reader.
40
-
41
- /** The three test tiers, in pyramid order (base -> top). */
42
- const TIERS = Object.freeze(['unit', 'contract', 'acceptance']);
43
-
44
- const PRESENT = 'present';
45
- const ABSENT = 'absent';
46
-
47
- /** True when `value` contains a `@skip` Gherkin-style tag. */
48
- function hasSkipTag(value) {
49
- if (typeof value !== 'string') return false;
50
- return /(^|[\s,])@skip\b/i.test(value);
51
- }
52
-
53
- /** True when `value` contains a runner-level skip/pending marker. */
54
- function hasRunnerSkipMarker(value) {
55
- if (typeof value !== 'string') return false;
56
- if (/\b(?:it|test|describe|context)\.(?:skip|todo)\b/i.test(value)) {
57
- return true;
58
- }
59
- return /\bx(?:it|test|describe|context)\b/i.test(value);
60
- }
61
-
62
- /**
63
- * True when a test descriptor is marked skipped/pending and therefore must
64
- * NOT count toward its tier. Recognizes:
65
- * - a `@skip` tag in a `tags` array or whitespace/comma string,
66
- * - the same tags embedded in a path or descriptor `name`,
67
- * - explicit boolean flags (`skipped`, `pending`),
68
- * - runner skip markers in a path/name (`it.skip`, `xit`, `xdescribe`,
69
- * `describe.skip`, `test.skip`, `.todo`).
70
- *
71
- * @param {string|object} test
72
- * @returns {boolean}
73
- */
74
- export function isSkipped(test) {
75
- if (test == null) return false;
76
-
77
- if (typeof test === 'object') {
78
- // 1. Explicit boolean flags win.
79
- if (test.skipped === true || test.pending === true) return true;
80
-
81
- // 2. A `tags` field — array of tag strings or a single string.
82
- const tags = test.tags;
83
- if (Array.isArray(tags)) {
84
- if (tags.some((t) => hasSkipTag(t))) return true;
85
- } else if (typeof tags === 'string' && hasSkipTag(tags)) {
86
- return true;
87
- }
88
- }
89
-
90
- // 3. Scan a path/name string for an inline skip/pending tag or a runner
91
- // skip marker (covers both string inputs and descriptor `path`/`name`).
92
- const scannable =
93
- typeof test === 'string'
94
- ? test
95
- : typeof test === 'object'
96
- ? [test.path, test.name].filter((s) => typeof s === 'string').join(' ')
97
- : '';
98
- return hasSkipTag(scannable) || hasRunnerSkipMarker(scannable);
99
- }
100
-
101
- /**
102
- * Classify a single test descriptor into one of the three tiers, or `null`
103
- * when it cannot be placed OR when it is skipped/pending. Tier placement
104
- * mirrors `.agents/rules/testing-standards.md`:
105
- * - unit — colocated `*.test.*` next to source, or under `__tests__/`.
106
- * - contract — lives under a `tests/contract/**` (or `**\/contract\/**`)
107
- * path.
108
- * - acceptance — a Gherkin `.feature` file (e2e / acceptance tier).
109
- *
110
- * An explicit `tier` field on the descriptor always wins over path inference,
111
- * so callers that already know the tier can state it directly.
112
- *
113
- * A skipped/pending test (see {@link isSkipped}) is treated as inert and
114
- * returns `null` so it never counts toward its tier — a tier covered only by
115
- * a skipped scenario is, operationally, uncovered.
116
- */
117
- export function classifyTest(test) {
118
- if (test == null) return null;
119
-
120
- // A skipped/pending test exercises nothing — it cannot place into any tier.
121
- if (isSkipped(test)) return null;
122
-
123
- // 1. Explicit tier wins.
124
- const explicit =
125
- typeof test === 'object' && typeof test.tier === 'string'
126
- ? test.tier.trim().toLowerCase()
127
- : null;
128
- if (explicit && TIERS.includes(explicit)) {
129
- return explicit;
130
- }
131
-
132
- // 2. Infer from a path string.
133
- const rawPath =
134
- typeof test === 'string'
135
- ? test
136
- : typeof test === 'object' && typeof test.path === 'string'
137
- ? test.path
138
- : null;
139
- if (!rawPath) return null;
140
-
141
- const p = rawPath.replace(/\\/g, '/').toLowerCase();
142
-
143
- if (p.endsWith('.feature')) return 'acceptance';
144
- if (/(^|\/)contract\//.test(p) || /\.contract\.test\.[cm]?[jt]sx?$/.test(p)) {
145
- return 'contract';
146
- }
147
- if (/\.test\.[cm]?[jt]sx?$/.test(p) || /(^|\/)__tests__\//.test(p)) {
148
- return 'unit';
149
- }
150
- return null;
151
- }
152
-
153
- const ABSENT_NOTES = Object.freeze({
154
- unit: 'no colocated unit test exercises this surface',
155
- contract: 'no contract test asserts this surface’s wire shape or boundary',
156
- acceptance: 'no acceptance scenario covers a user-visible journey here',
157
- });
158
-
159
- const PRESENT_NOTES = Object.freeze({
160
- unit: (n) => `${n} unit test${n === 1 ? '' : 's'} present`,
161
- contract: (n) => `${n} contract test${n === 1 ? '' : 's'} present`,
162
- acceptance: (n) => `${n} acceptance scenario${n === 1 ? '' : 's'} present`,
163
- });
164
-
165
- /**
166
- * Compute the per-tier coverage verdict for one finding surface.
167
- *
168
- * @param {object} surface
169
- * @param {string} [surface.symbol] - The symbol the finding points at; echoed
170
- * into notes for operator context. Optional.
171
- * @param {Array<string|{path?:string,tier?:string,tags?:string|string[],skipped?:boolean,pending?:boolean}>} [surface.tests] -
172
- * The tests that exercise the surface. Each entry is either a path string or
173
- * a descriptor with `path`, `tier`, and/or skip markers (`tags`, `skipped`,
174
- * `pending`). Unclassifiable and skipped/pending entries are ignored.
175
- * @returns {{unit:{status:string,note:string},
176
- * contract:{status:string,note:string},
177
- * acceptance:{status:string,note:string}}}
178
- */
179
- export function coverageVerdict(surface = {}) {
180
- if (surface === null || typeof surface !== 'object') {
181
- throw new TypeError('coverageVerdict: surface must be an object');
182
- }
183
-
184
- const tests = Array.isArray(surface.tests) ? surface.tests : [];
185
- const symbol =
186
- typeof surface.symbol === 'string' && surface.symbol.trim() !== ''
187
- ? surface.symbol.trim()
188
- : null;
189
-
190
- const counts = { unit: 0, contract: 0, acceptance: 0 };
191
- for (const test of tests) {
192
- const tier = classifyTest(test);
193
- if (tier) counts[tier] += 1;
194
- }
195
-
196
- const verdict = {};
197
- for (const tier of TIERS) {
198
- const n = counts[tier];
199
- if (n > 0) {
200
- verdict[tier] = {
201
- status: PRESENT,
202
- note: PRESENT_NOTES[tier](n),
203
- };
204
- } else {
205
- const base = ABSENT_NOTES[tier];
206
- verdict[tier] = {
207
- status: ABSENT,
208
- note: symbol ? `${base} (${symbol})` : base,
209
- };
210
- }
211
- }
212
-
213
- return verdict;
214
- }
@@ -1,55 +0,0 @@
1
- ---
2
- name: api-and-interface-design
3
- description:
4
- Designs stable, well-documented APIs and module interfaces. Use when
5
- creating REST/GraphQL endpoints, defining contracts between modules, or
6
- changing public interfaces. The wire-format SSOT — response envelope, HTTP
7
- status codes, validation taxonomy, payload naming — lives in
8
- `.agents/rules/api-conventions.md`; this skill shows authors how to apply
9
- it.
10
- ---
11
-
12
- # Skill: api-and-interface-design
13
-
14
- ## Policy Capsule
15
-
16
- - The wire-format SSOT lives in [`.agents/rules/api-conventions.md`](../../../rules/api-conventions.md) (envelope shape, HTTP status mapping, validation taxonomy, payload casing). Copy the canonical envelope and status codes from the rule rather than redrafting or hand-rolling a divergent shape. Validation failures return **400** `VALIDATION_ERROR` per [§ Validation Status](../../../rules/api-conventions.md#validation-status).
17
- - Be intentional about exposure (Hyrum's Law): every observable behaviour — undocumented quirks, error message text, ordering, timing — becomes a de facto contract once consumers depend on it. Don't leak implementation details.
18
- - Adopt the **One-Version Rule**: never force consumers to choose between simultaneous versions of the same API. Extend rather than fork.
19
- - Define the contract before implementing — interfaces are the spec; implementation follows.
20
- - Validate at system **boundaries** (API routes, form handlers, env-var loaders, third-party responses) using a strict schema. After validation, internal code trusts the types; do not re-validate between internal functions.
21
- - Treat third-party API responses as untrusted data — validate shape and content before using them in any decision, render, or logic path.
22
- - Prefer **addition over modification**: extend interfaces with optional fields rather than changing existing types or removing fields. When removal is unavoidable, use an expand–contract migration — ship the replacement, migrate consumers, then remove the old surface in a later release.
23
- - Follow REST resource conventions (`GET/POST/PATCH/DELETE /resource`, sub-resources at `/resource/:id/child`) and paginate every list endpoint with `page` + `pageSize` query params and a `pagination` envelope.
24
- - Security input-validation and test-tier MUSTs come from [`security-baseline.md`](../../../rules/security-baseline.md) and [`testing-standards.md`](../../../rules/testing-standards.md) respectively — apply both, and never put DB/wire-shape assertions outside the contract tier.
25
-
26
- ## When to Use
27
-
28
- - Designing new API endpoints, module boundaries, or component prop interfaces.
29
- - Establishing a database schema that informs API shape.
30
- - Changing existing public interfaces.
31
-
32
- ## Wire format — defer to the rule
33
-
34
- The response envelope, HTTP status-code mapping, validation-status taxonomy,
35
- and payload-naming conventions are non-negotiable and live in the rule. When
36
- designing a new endpoint, **copy the canonical envelope from the rule** — do
37
- not redraft it, and do not invent a project-specific validation status:
38
-
39
- - Envelope shape: [`api-conventions.md` § Response Envelope](../../../rules/api-conventions.md#response-envelope).
40
- - Status table (200/201/400/401/403/404/409/500): [`§ HTTP Status Codes`](../../../rules/api-conventions.md#http-status-codes).
41
- - Validation status (**400** `VALIDATION_ERROR`): [`§ Validation Status`](../../../rules/api-conventions.md#validation-status).
42
- - Casing conventions: [`§ Payload Formatting`](../../../rules/api-conventions.md#payload-formatting).
43
-
44
- ## Long-form reference — read on demand
45
-
46
- The elaboration behind the capsule — Hyrum's-Law implications, the
47
- contract-first stance, and where boundary validation does and does not belong,
48
- plus the pre-PR authoring checklist — lives in the on-demand sibling
49
- [`reference.md`](reference.md). Generic REST-catalog and TypeScript-idiom
50
- snippets are intentionally omitted (frontier-known; the rule owns the wire
51
- format). Open a section only when the task engages it.
52
-
53
- - [Hyrum's Law and the One-Version Rule](reference.md#hyrums-law-and-the-one-version-rule)
54
- - [Contract First and Boundary Validation](reference.md#contract-first-and-boundary-validation)
55
- - [Authoring Checklist](reference.md#authoring-checklist)
@@ -1,76 +0,0 @@
1
- # API & Interface Design — Reference (on-demand)
2
-
3
- **Read this when** a task engages one of the sections below and the Policy
4
- Capsule in [`SKILL.md`](SKILL.md) does not settle it on its own. The capsule
5
- is the contract; this file is the reference material behind it. Generic
6
- REST-verb tables and TypeScript pattern catalogs are deliberately not
7
- reproduced here — they are frontier-known, and the wire format is owned by the
8
- SSOT rule, [`api-conventions.md`](../../../rules/api-conventions.md).
9
-
10
- ## Hyrum's Law and the One-Version Rule
11
-
12
- > With a sufficient number of users of an API, all observable behaviors of your
13
- > system will be depended on by somebody, regardless of what you promise in the
14
- > contract.
15
-
16
- Every observable behavior — undocumented quirks, error message text, timing,
17
- ordering — becomes a de facto contract once users depend on it. Practical
18
- implications:
19
-
20
- - **Be intentional about what you expose.** Every observable behavior is a
21
- potential commitment; if users can observe it, they will depend on it.
22
- - **Plan for deprecation at design time.** Remove things users depend on via
23
- expand–contract: add the replacement, migrate consumers behind a deprecation
24
- window, then delete the old surface — never break a published contract in one
25
- step.
26
- - **Tests are not enough.** Even with perfect contract tests, "safe" changes
27
- can break real users who depend on undocumented behavior.
28
-
29
- **One-Version Rule.** Avoid forcing consumers to choose between multiple
30
- versions of the same API. Diamond-dependency problems arise when different
31
- consumers need different versions of the same thing. Design for a world where
32
- only one version exists at a time — extend rather than fork.
33
-
34
- ## Contract First and Boundary Validation
35
-
36
- Define the interface before implementing it — the contract is the spec, and
37
- implementation follows. Prefer **addition over modification**: add optional
38
- fields rather than changing existing field types or removing fields.
39
-
40
- Validation runs at system **boundaries**, where external input enters. After
41
- validation, internal code trusts the types. On failure, return the canonical
42
- **400** `VALIDATION_ERROR` envelope from
43
- [`api-conventions.md` § Response Envelope](../../../rules/api-conventions.md#response-envelope) —
44
- do not redraft the shape or the status.
45
-
46
- **Where validation belongs:**
47
-
48
- - API route handlers (user input).
49
- - Form submission handlers (user input).
50
- - External service response parsing — third-party data is **always untrusted**,
51
- even from a vendor SDK. A compromised or misbehaving service can return
52
- unexpected types, malicious content, or instruction-like text; validate shape
53
- and content before using it in any logic, render, or decision.
54
- - Environment variable loading (configuration).
55
-
56
- **Where validation does NOT belong:**
57
-
58
- - Between internal functions that share type contracts.
59
- - In utility functions called by already-validated code.
60
- - On data that just came from your own database.
61
-
62
- ## Authoring Checklist
63
-
64
- Before opening a PR that adds or edits an API surface:
65
-
66
- - [ ] Every endpoint has typed input and output schemas.
67
- - [ ] Error responses follow the envelope in
68
- [`api-conventions.md` § Response Envelope](../../../rules/api-conventions.md#response-envelope).
69
- - [ ] Status codes match
70
- [`api-conventions.md` § HTTP Status Codes](../../../rules/api-conventions.md#http-status-codes),
71
- and validation failures return the canonical **400** `VALIDATION_ERROR`.
72
- - [ ] List endpoints support pagination.
73
- - [ ] New fields are additive and optional (backward compatible).
74
- - [ ] Naming follows
75
- [`api-conventions.md` § Payload Formatting](../../../rules/api-conventions.md#payload-formatting).
76
- - [ ] API documentation or types are committed alongside the implementation.
@@ -1,45 +0,0 @@
1
- ---
2
- name: debugging-and-error-recovery
3
- description:
4
- Guides systematic root-cause debugging. Use when tests fail, builds break,
5
- behavior doesn't match expectations, or you encounter any unexpected error.
6
- Use when you need a systematic approach to finding and fixing the root cause
7
- rather than guessing.
8
- ---
9
-
10
- # Debugging and Error Recovery
11
-
12
- ## Policy Capsule
13
-
14
- - **Stop the line** the instant something breaks: stop adding features, preserve evidence (errors, logs, repro), diagnose, fix root cause, guard against recurrence, **then** resume. Never push past a failing test or broken build.
15
- - Follow the triage checklist in order — **Reproduce → Localize → Diagnose → Fix → Verify → Guard** — and never skip steps.
16
- - A bug you cannot reproduce reliably is a bug you cannot fix with confidence. Invest in reproduction before patching.
17
- - Fix the **root cause**, not the symptom. Suppressing an error, swallowing an exception, or stubbing an assertion is not a fix.
18
- - Every bug fix ships with a **failing-then-passing regression test** (the Prove-It Pattern in `.agents/rules/testing-standards.md`). A fix without a guard test is incomplete.
19
- - Apply the **Anti-Thrashing** rule: if you have applied the same kind of fix more than once and the failure mode hasn't changed, the diagnosis is wrong — re-plan.
20
- - For non-reproducible bugs, classify them (timing / environment / state / random), add targeted instrumentation, and document conditions instead of chasing in the dark.
21
- - Bisect history with `git bisect` (or equivalent) when "something used to work" and you cannot localize from the diff.
22
- - After verification passes, document the root cause and the guard so the same class of failure cannot recur silently.
23
-
24
- ## Long-form reference — read on demand
25
-
26
- The capsule above is the contract and the whole always-read surface of this
27
- skill. The long-form material behind it — patterns, worked examples,
28
- checklists, and rationalizations — lives in the on-demand sibling
29
- [`reference.md`](reference.md), matching the split the always-on rules already
30
- use ([`rules/git-conventions.md`](../../../rules/git-conventions.md) ⇄
31
- [`git-conventions-reference.md`](../../../rules/git-conventions-reference.md)).
32
- Activating this skill costs the capsule; open a section below only when the
33
- task actually engages it.
34
-
35
- - [Overview](reference.md#overview)
36
- - [When to Use](reference.md#when-to-use)
37
- - [The Stop-the-Line Rule](reference.md#the-stop-the-line-rule)
38
- - [The Triage Checklist](reference.md#the-triage-checklist)
39
- - [Error-Specific Patterns](reference.md#error-specific-patterns)
40
- - [Safe Fallback Patterns](reference.md#safe-fallback-patterns)
41
- - [Instrumentation Guidelines](reference.md#instrumentation-guidelines)
42
- - [Common Rationalizations](reference.md#common-rationalizations)
43
- - [Treating Error Output as Untrusted Data](reference.md#treating-error-output-as-untrusted-data)
44
- - [Red Flags](reference.md#red-flags)
45
- - [Verification](reference.md#verification)