mandrel 2.14.0 → 2.15.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 (68) hide show
  1. package/.agents/audit-checklists/navigability.md +1 -1
  2. package/.agents/docs/workflows.md +4 -5
  3. package/.agents/scripts/acceptance-eval.js +18 -1
  4. package/.agents/scripts/agents-bootstrap-github.js +22 -1
  5. package/.agents/scripts/apply-quality-bootstrap.js +6 -0
  6. package/.agents/scripts/audit-labels-bootstrap.js +15 -1
  7. package/.agents/scripts/audit-to-stories.js +26 -1
  8. package/.agents/scripts/boot-sweep.js +4 -1
  9. package/.agents/scripts/bootstrap.js +1 -0
  10. package/.agents/scripts/check-arch-cycles.js +20 -0
  11. package/.agents/scripts/check-baselines.js +8 -2
  12. package/.agents/scripts/check-context-budget.js +40 -5
  13. package/.agents/scripts/check-dead-exports.js +21 -0
  14. package/.agents/scripts/check-doc-links.js +12 -1
  15. package/.agents/scripts/check-lifecycle-doc-drift.js +9 -0
  16. package/.agents/scripts/check-workflow-citations.js +332 -0
  17. package/.agents/scripts/deliver-light.js +1 -0
  18. package/.agents/scripts/deliver-recover.js +4 -1
  19. package/.agents/scripts/diagnose-friction.js +17 -1
  20. package/.agents/scripts/diagnose.js +20 -14
  21. package/.agents/scripts/drain-pending-cleanup.js +20 -1
  22. package/.agents/scripts/evidence-gate.js +20 -1
  23. package/.agents/scripts/generate-config-docs.js +14 -1
  24. package/.agents/scripts/generate-lifecycle-docs.js +14 -1
  25. package/.agents/scripts/generate-workflows-doc.js +14 -1
  26. package/.agents/scripts/git-cleanup.js +32 -1
  27. package/.agents/scripts/lib/cli-usage.js +174 -0
  28. package/.agents/scripts/lib/cli-utils.js +12 -0
  29. package/.agents/scripts/lib/doc-tiers.js +53 -10
  30. package/.agents/scripts/lib/orchestration/plan-context.js +16 -11
  31. package/.agents/scripts/lib/workflow-closure.js +431 -0
  32. package/.agents/scripts/mandrel-update-preflight.js +9 -0
  33. package/.agents/scripts/nav-registry-diff.js +13 -0
  34. package/.agents/scripts/plan-context.js +17 -1
  35. package/.agents/scripts/plan-critics.js +10 -0
  36. package/.agents/scripts/plan-persist.js +33 -1
  37. package/.agents/scripts/plan-run-epilogue.js +12 -1
  38. package/.agents/scripts/quality-preview.js +17 -1
  39. package/.agents/scripts/resolve-doc-tiers.js +13 -0
  40. package/.agents/scripts/resolve-stories.js +1 -0
  41. package/.agents/scripts/resync-status-column.js +4 -1
  42. package/.agents/scripts/signals-view.js +11 -0
  43. package/.agents/scripts/single-story-close.js +24 -0
  44. package/.agents/scripts/single-story-confirm-merge.js +16 -0
  45. package/.agents/scripts/single-story-init.js +21 -1
  46. package/.agents/scripts/stories-wave-tick.js +1 -0
  47. package/.agents/scripts/sync-agentrc.js +16 -4
  48. package/.agents/scripts/update-ticket-state.js +23 -2
  49. package/.agents/workflows/audit-navigability.md +2 -2
  50. package/.agents/workflows/audit-to-stories.md +1 -1
  51. package/.agents/workflows/deliver.md +80 -81
  52. package/.agents/workflows/git-cleanup.md +9 -14
  53. package/.agents/workflows/helpers/acceptance-self-eval.md +14 -13
  54. package/.agents/workflows/helpers/audit-lens-core.md +2 -2
  55. package/.agents/workflows/helpers/code-review.md +11 -11
  56. package/.agents/workflows/helpers/deliver-digest.md +7 -8
  57. package/.agents/workflows/{deliver-light.md → helpers/deliver-light.md} +72 -24
  58. package/.agents/workflows/helpers/deliver-reference.md +46 -14
  59. package/.agents/workflows/helpers/deliver-story-reference.md +55 -63
  60. package/.agents/workflows/helpers/deliver-story.md +22 -22
  61. package/.agents/workflows/helpers/mandrel-sync-config.md +2 -2
  62. package/.agents/workflows/helpers/parallel-tooling.md +1 -2
  63. package/.agents/workflows/helpers/plan-reference.md +72 -14
  64. package/.agents/workflows/helpers/worktree-lifecycle.md +1 -4
  65. package/.agents/workflows/mandrel-update.md +6 -6
  66. package/.agents/workflows/plan.md +86 -83
  67. package/docs/CHANGELOG.md +15 -0
  68. package/package.json +2 -1
@@ -6,7 +6,7 @@
6
6
 
7
7
  # Navigability Audit — authoring checklist
8
8
 
9
- > Audit the whole route tree against the consumer's nav-registry SSOT — every route has a persona nav door and no nav href is dead. A deliberately-global lens (Epic #4131, F2/F3) exempt from the cross-epic-leak guard and routed onto route-adding change sets.
9
+ > Audit the whole route tree against the consumer's nav-registry SSOT — every route has a persona nav door and no nav href is dead. A deliberately-global lens exempt from the cross-epic-leak guard and routed onto route-adding change sets.
10
10
 
11
11
  Self-check your change against this lens's concerns before you ship:
12
12
 
@@ -32,7 +32,7 @@ by `node .agents/scripts/generate-workflows-doc.js`; `npm run docs:check`
32
32
  fails when it drifts from the on-disk workflow set. To change a command’s
33
33
  description, edit the workflow file’s front-matter and regenerate.
34
34
 
35
- ## Commands (25)
35
+ ## Commands (24)
36
36
 
37
37
  | Command | Description |
38
38
  | --- | --- |
@@ -43,7 +43,7 @@ description, edit the workflow file’s front-matter and regenerate.
43
43
  | `/audit-dependencies` | Audit `package.json` for unused, outdated, and major-version-stale dependencies; surface Node-engine drift and propose upgrade batches. |
44
44
  | `/audit-devops` | Audit CI/CD workflows, container images, infrastructure-as-code, and deployment pipelines; surface failure modes and hardening gaps. |
45
45
  | `/audit-documentation` | Audit the repository's main documentation for staleness, semantic drift, and completeness; emit a structured High/Medium/Low findings report. |
46
- | `/audit-navigability` | Audit the whole route tree against the consumer's nav-registry SSOT — every route has a persona nav door and no nav href is dead. A deliberately-global lens (Epic #4131, F2/F3) exempt from the cross-epic-leak guard and routed onto route-adding change sets. |
46
+ | `/audit-navigability` | Audit the whole route tree against the consumer's nav-registry SSOT — every route has a persona nav door and no nav href is dead. A deliberately-global lens exempt from the cross-epic-leak guard and routed onto route-adding change sets. |
47
47
  | `/audit-performance` | Audit performance by measuring first — profile hot paths, I/O, memory, and payload against the repo's own numbers — and audit interleaving/partial-failure correctness (TOCTOU, unawaited promises, non-atomic writes) as a first-class dimension. |
48
48
  | `/audit-privacy` | Audit logs, telemetry, and persistence paths for PII leakage and retention violations; surface secrets exposure and consent gaps. |
49
49
  | `/audit-quality` | Audit test coverage gaps, flaky tests, missing assertions, and test-pyramid balance; recommend a remediation batch. |
@@ -52,11 +52,10 @@ description, edit the workflow file’s front-matter and regenerate.
52
52
  | `/audit-sre` | "Audit production-readiness for a release candidate: SLOs, observability, runbooks, error budgets, and rollback paths." |
53
53
  | `/audit-to-stories` | Convert findings produced by the audit-\* workflows into actionable GitHub Stories. Reads temp/audits/audit-\*-results.md, groups findings cross-audit, deduplicates against existing Issues by fingerprint, and either chains into /plan --seed-file or opens standalone Stories. |
54
54
  | `/audit-ux-ui` | Audit UX/UI consistency and design system adherence |
55
- | `/deliver` | Unified delivery entry point. Takes a list of Story ids, resolves their dependency graph from live state, and delivers each via the single deliver-story engine — story-<id> → PR → main. |
56
- | `/deliver-light` | Single-session delivery for genuinely small work. Judges a prompt's predicted footprint, authors a receipt Story, then lands it through the same single-story-init / single-story-close engine — every close gate unchanged. |
55
+ | `/deliver` | Unified delivery entry point. Takes Story ids or a plain-language prompt, derives which path the work belongs on, and lands it via the single deliver-story engine — story-<id> → PR → main. |
57
56
  | `/git-cleanup` | Tidy the local checkout in four phases: fast-forward `main`, prune stale remote-tracking refs, sweep merged branches (squash-aware), and triage `git stash` entries — each step gated by operator confirmation. |
58
57
  | `/git-deliver` | Single ad-hoc delivery command for working-tree changes. Detects the git setup and escalates to the right terminal step — commit only, commit + push, or commit + push + open a PR with native auto-merge — picking the default from observable state and letting flags pin any level explicitly. Replaces the retired git-commit-all, git-push, and git-pr-all trio. |
59
- | `/mandrel-update` | npm-era upgrade wraparound for a Mandrel consumer. Runs `npx mandrel update` (resolve newest published version → install → re-materialize `.agents/` → migrate → doctor → surface changelog) as the single mechanical step, then walks the operator through the judgment wraparound the CLI deliberately leaves unowned: reconcile `.agentrc.json`, install the Epic #1386 quality-gate surface, refresh the harness permission allowlist, reconcile the consumer's `AGENTS.md` / runbooks against the surfaced changelog, and stage + commit the staged lockfile bump. |
58
+ | `/mandrel-update` | npm-era upgrade wraparound for a Mandrel consumer. Runs `npx mandrel update` (resolve newest published version → install → re-materialize `.agents/` → migrate → doctor → surface changelog) as the single mechanical step, then walks the operator through the judgment wraparound the CLI deliberately leaves unowned: reconcile `.agentrc.json`, install the stabilized quality-gate surface, refresh the harness permission allowlist, reconcile the consumer's `AGENTS.md` / runbooks against the surfaced changelog, and stage + commit the staged lockfile bump. |
60
59
  | `/plan` | Unified planning entry point. Interrogate → author → persist. Emits one Story by default; splits into N>1 only under the default-single split policy. |
61
60
  | `/qa-assist` | Human-led QA assist loop — set up, then ride a rolling multi-observation intake session. The operator reports observations in any order; the agent enriches each (repro + root-cause file:line + coverage verdict for bugs; analysis + options + recommendation for enhancements), asks clarifying questions only when ambiguous, and appends a redacted ledger item — recording, never planning — to a persistent, resumable session under temp/qa/. Only when the operator says they are done does it review the full ledger and hand off to /plan. |
62
61
  | `/qa-explore` | Agent-led exploratory-QA loop — the agent Plans a surface with an explicit static-vs-drive method choice, drives it (browser MCP or static), and captures ledger items read-only, then Triages — a bounded per-surface session, HITL-gated at every phase transition, routed through the shared dedup/coverage/classification/missing-test/redaction/session core under temp/qa/ |
@@ -302,4 +302,21 @@ export async function main(argv = process.argv.slice(2)) {
302
302
  return envelope;
303
303
  }
304
304
 
305
- runAsCli(import.meta.url, main, { source: 'acceptance-eval' });
305
+ runAsCli(import.meta.url, main, {
306
+ source: 'acceptance-eval',
307
+ usage: {
308
+ invocation:
309
+ 'node .agents/scripts/acceptance-eval.js --story <id> --verdict <path> [--no-signal]',
310
+ summary:
311
+ "Score an authored acceptance verdict against the Story's acceptance[] criteria and emit the bounded loop's proceed / redraft / block decision.",
312
+ flags: [
313
+ ['--story <id>', 'GitHub issue number of the Story (required).'],
314
+ ['--verdict <path>', 'Path to the authored verdict JSON (required).'],
315
+ [
316
+ '--no-signal',
317
+ "Skip appending the per-criterion signal to the Story's signals ledger.",
318
+ ],
319
+ ],
320
+ notes: ['Exit codes:\n 0 proceed or redraft\n 1 block'],
321
+ },
322
+ });
@@ -526,4 +526,25 @@ export {
526
526
  verifyApiAccess,
527
527
  };
528
528
 
529
- runAsCli(import.meta.url, main, { source: 'Bootstrap' });
529
+ runAsCli(import.meta.url, main, {
530
+ source: 'Bootstrap',
531
+ usage: {
532
+ invocation:
533
+ 'node .agents/scripts/agents-bootstrap-github.js [--assume-yes|--assume-no] [--approve-github-admin] [--with-project-board] [--reap-conflicting-workflows]',
534
+ summary:
535
+ 'Bootstrap the GitHub side of a consumer repo: label taxonomy, issue forms, workflows, and the optional project board.',
536
+ flags: [
537
+ ['--assume-yes', 'Answer yes to every prompt (non-interactive run).'],
538
+ ['--assume-no', 'Answer no to every prompt (probe only).'],
539
+ [
540
+ '--approve-github-admin',
541
+ 'Consent to admin-scoped GitHub mutations (implied by --assume-yes).',
542
+ ],
543
+ ['--with-project-board', 'Also provision the GitHub Project board.'],
544
+ [
545
+ '--reap-conflicting-workflows',
546
+ 'Remove pre-existing workflow files that clash with the framework set.',
547
+ ],
548
+ ],
549
+ },
550
+ });
@@ -76,4 +76,10 @@ async function main() {
76
76
  runAsCli(import.meta.url, main, {
77
77
  source: 'apply-quality-bootstrap',
78
78
  propagateExitCode: true,
79
+ usage: {
80
+ invocation: 'node .agents/scripts/apply-quality-bootstrap.js',
81
+ summary:
82
+ 'Install the quality-gate surface into the consumer repo (guardrails helper, pre-commit line, npm scripts, config defaults) and migrate the baselines layout. Idempotent; prints { quality, baselines } JSON to stdout.',
83
+ flags: [],
84
+ },
79
85
  });
@@ -272,4 +272,18 @@ async function main() {
272
272
  }
273
273
  }
274
274
 
275
- runAsCli(import.meta.url, main, { source: 'audit-labels-bootstrap' });
275
+ runAsCli(import.meta.url, main, {
276
+ source: 'audit-labels-bootstrap',
277
+ usage: {
278
+ invocation:
279
+ 'node .agents/scripts/audit-labels-bootstrap.js [--owner <owner>] [--repo <repo>] [--force] [--dry-run]',
280
+ summary:
281
+ 'Create the audit-finding label taxonomy in the target repository. Idempotent.',
282
+ flags: [
283
+ ['--owner <owner>', 'Repository owner (default: github.owner).'],
284
+ ['--repo <repo>', 'Repository name (default: github.repo).'],
285
+ ['--force', 'Update colour/description of labels that already exist.'],
286
+ ['--dry-run', 'Report what would be created; mutate nothing.'],
287
+ ],
288
+ },
289
+ });
@@ -626,4 +626,29 @@ async function main() {
626
626
  );
627
627
  }
628
628
 
629
- runAsCli(import.meta.url, main, { source: 'audit-to-stories' });
629
+ runAsCli(import.meta.url, main, {
630
+ source: 'audit-to-stories',
631
+ usage: {
632
+ invocation:
633
+ 'node .agents/scripts/audit-to-stories.js (--scan | --auto | --emit-plan-seed | --emit-stories) [options]',
634
+ summary:
635
+ 'Turn audit-lens findings under temp/audits/ into a dedup-checked plan seed or standalone Stories.',
636
+ flags: [
637
+ ['--scan', 'Print the grouped, deduplicated plan as JSON.'],
638
+ ['--auto', 'Run the full scan → file pipeline and print the summary.'],
639
+ ['--emit-plan-seed', 'Emit a /plan --seed-file document.'],
640
+ ['--emit-stories', 'Emit the Story drafts as JSON.'],
641
+ ['--glob <pattern>', 'Override the audit-results glob.'],
642
+ ['--severity <level>', 'Lowest severity to include (high|medium|low).'],
643
+ ['--ledger <path>', 'Path to the dedup ledger.'],
644
+ [
645
+ '--plan <path>',
646
+ 'Read a previously emitted plan instead of re-scanning.',
647
+ ],
648
+ ['--out <path>', 'Write output to a file instead of stdout.'],
649
+ ['--no-provider', 'Skip live GitHub dedup lookups (offline).'],
650
+ ['--json', 'Force JSON output.'],
651
+ ['--dry-run', 'Report what would be filed; create nothing.'],
652
+ ],
653
+ },
654
+ });
@@ -212,4 +212,7 @@ async function main() {
212
212
  }
213
213
  }
214
214
 
215
- runAsCli(import.meta.url, main, { source: 'boot-sweep' });
215
+ runAsCli(import.meta.url, main, {
216
+ source: 'boot-sweep',
217
+ usage: HELP,
218
+ });
@@ -1467,4 +1467,5 @@ export async function main(argv = process.argv.slice(2), deps = {}) {
1467
1467
  runAsCli(import.meta.url, main, {
1468
1468
  source: 'Bootstrap',
1469
1469
  propagateExitCode: true,
1470
+ usage: HELP,
1470
1471
  });
@@ -381,4 +381,24 @@ runAsCli(import.meta.url, main, {
381
381
  source: 'arch-cycles',
382
382
  propagateExitCode: true,
383
383
  errorPrefix: '[arch-cycles] ❌ Fatal error',
384
+ usage: {
385
+ invocation:
386
+ 'node .agents/scripts/check-arch-cycles.js [--baseline <path>] [--root <dir>] [--json]',
387
+ summary:
388
+ 'Ratchet on module-dependency cycles: compare the live import graph against the recorded baseline and fail on any newly added cycle.',
389
+ flags: [
390
+ [
391
+ '--baseline <path>',
392
+ 'Baseline file (default: baselines/arch-cycles.json).',
393
+ ],
394
+ [
395
+ '--root <dir>',
396
+ 'Scan a single root instead of the distributed surface.',
397
+ ],
398
+ ['--json', 'Emit the comparison envelope as JSON.'],
399
+ ],
400
+ notes: [
401
+ 'Exit codes:\n 0 clean, or removals only\n 1 a new cycle was detected',
402
+ ],
403
+ },
384
404
  });
@@ -43,7 +43,10 @@ import {
43
43
  assertFloorAxesExist,
44
44
  compareToFloor,
45
45
  } from './lib/orchestration/check-baselines/phases/floors.js';
46
- import { parseArgs } from './lib/orchestration/check-baselines/phases/parse-args.js';
46
+ import {
47
+ HELP_TEXT,
48
+ parseArgs,
49
+ } from './lib/orchestration/check-baselines/phases/parse-args.js';
47
50
  import {
48
51
  runCheckBaselines,
49
52
  selectEnabledGates,
@@ -78,4 +81,7 @@ async function main() {
78
81
  process.exit(result.exitCode);
79
82
  }
80
83
 
81
- runAsCli(import.meta.url, main, { source: 'check-baselines' });
84
+ runAsCli(import.meta.url, main, {
85
+ source: 'check-baselines',
86
+ usage: HELP_TEXT,
87
+ });
@@ -11,6 +11,13 @@
11
11
  * - `alwaysLoaded` — the `CLAUDE.md` `@`-import closure re-paid on every
12
12
  * session and every subagent spawn (instructions.md § 4).
13
13
  * - `mandatoryRead` — the resolved `project.docsContextFiles` set.
14
+ * - `workflow` — the workflow **mandatory closure** (Story #4752): every
15
+ * `.agents/workflows/**` entry point plus the transitive
16
+ * closure of its `mandatoryReads:` frontmatter edges. The
17
+ * companion **reachable** closure (per entry point) is
18
+ * recorded under the top-level `workflowClosure` key as a
19
+ * drift signal and never gates — growth there is a
20
+ * reading-cost signal, not a contract violation.
14
21
  *
15
22
  * It additionally enforces a **per-file** ceiling on the role-scoped agent-boot
16
23
  * tier (`.agents/agents/*.md`, #4478): no single boot context may exceed
@@ -52,12 +59,12 @@ import { resolveConfig } from './lib/config-resolver.js';
52
59
  import { resolveDocTiers, tierTotalBytes } from './lib/doc-tiers.js';
53
60
 
54
61
  /**
55
- * The tiers this ratchet gates (in report order). `digestVisible` and
56
- * `onDemand` are resolved by the tier map for the lens, but the byte budget
57
- * intentionally gates only the two tiers the Epic AC names.
58
- * @type {Array<'alwaysLoaded' | 'mandatoryRead'>}
62
+ * The tiers this ratchet gates (in report order). `digestVisible`, `onDemand`
63
+ * and `workflowOnDemand` are resolved by the tier map for the lens, but the
64
+ * byte budget intentionally gates only the tiers a session is *forced* to read.
65
+ * @type {Array<'alwaysLoaded' | 'mandatoryRead' | 'workflow'>}
59
66
  */
60
- export const GATED_TIERS = ['alwaysLoaded', 'mandatoryRead'];
67
+ export const GATED_TIERS = ['alwaysLoaded', 'mandatoryRead', 'workflow'];
61
68
 
62
69
  /**
63
70
  * Default tolerance (bytes) seeded into a fresh baseline by `--update` when the
@@ -171,6 +178,12 @@ export function buildBaseline(tierMap, toleranceBytes) {
171
178
  ceilingBytes: AGENT_BOOT_CEILING_BYTES,
172
179
  files: agentBootFiles,
173
180
  },
181
+ // Recorded, never gated (#4752): the total reachable closure per workflow
182
+ // entry point. It is a drift signal — the gate is `tiers.workflow`.
183
+ workflowClosure: {
184
+ reachableTotalBytes: tierMap.workflowClosure?.reachableTotalBytes ?? 0,
185
+ entryPoints: tierMap.workflowClosure?.entryPoints ?? [],
186
+ },
174
187
  };
175
188
  }
176
189
 
@@ -249,6 +262,25 @@ export function renderDiff(diff) {
249
262
  return lines.join('\n');
250
263
  }
251
264
 
265
+ /**
266
+ * Render the workflow **reachable** closure line — recorded, never gated
267
+ * (Story #4752). Returns `''` when there is no workflow tier to report, so the
268
+ * caller can stay a one-liner.
269
+ *
270
+ * @param {{ workflowClosure?: { reachableTotalBytes?: number, entryPoints?: unknown[] } }} tierMap
271
+ * @param {{ workflowClosure?: { reachableTotalBytes?: number } } | null} [baseline]
272
+ * @returns {string}
273
+ */
274
+ export function renderReachable(tierMap, baseline) {
275
+ const closure = tierMap?.workflowClosure;
276
+ const current = closure?.reachableTotalBytes ?? 0;
277
+ if (current <= 0) return '';
278
+ const recorded = baseline?.workflowClosure?.reachableTotalBytes;
279
+ const against = Number.isFinite(recorded) ? ` (recorded ${recorded})` : '';
280
+ const entries = closure.entryPoints?.length ?? 0;
281
+ return ` workflow reachable closure: ${current} bytes across ${entries} entry points${against} — drift signal, never gated`;
282
+ }
283
+
252
284
  /**
253
285
  * Top-level CLI entry. Exported so tests can drive the full pipeline against a
254
286
  * tmpdir fixture with an injected config and sinks.
@@ -338,12 +370,15 @@ export async function runCli({
338
370
  skipped: diff.skipped,
339
371
  agentBootCeilingBytes: ceiling,
340
372
  agentBootOverflow: bootOverflow,
373
+ workflowReachableBytes: tierMap.workflowClosure?.reachableTotalBytes ?? 0,
341
374
  exitCode,
342
375
  };
343
376
  stdout.write(`${JSON.stringify(envelope, null, 2)}\n`);
344
377
  } else {
345
378
  stdout.write(`\n--- context-budget preview ---\n`);
346
379
  stdout.write(`${renderDiff(diff)}\n`);
380
+ const reachable = renderReachable(tierMap, baseline);
381
+ if (reachable) stdout.write(`${reachable}\n`);
347
382
  for (const o of bootOverflow) {
348
383
  stdout.write(
349
384
  `+ agentBoot: ${o.path} is ${o.bytes} bytes, over the ${o.ceiling}-byte per-agent ceiling\n`,
@@ -247,4 +247,25 @@ runAsCli(import.meta.url, main, {
247
247
  source: 'dead-exports',
248
248
  propagateExitCode: true,
249
249
  errorPrefix: '[dead-exports] ❌ Fatal error',
250
+ usage: {
251
+ invocation:
252
+ 'node .agents/scripts/check-dead-exports.js [--production] [--baseline <path>] [--knip-output <path>] [--json]',
253
+ summary:
254
+ 'Ratchet on unused exports reported by knip: fail when an export is added above the recorded baseline.',
255
+ flags: [
256
+ [
257
+ '--production',
258
+ 'Score the production-only surface (separate baseline).',
259
+ ],
260
+ ['--baseline <path>', 'Baseline file (default: mode-specific).'],
261
+ [
262
+ '--knip-output <path>',
263
+ 'Read a saved knip JSON envelope instead of running knip.',
264
+ ],
265
+ ['--json', 'Emit the comparison envelope as JSON.'],
266
+ ],
267
+ notes: [
268
+ 'Exit codes:\n 0 clean, or removals only\n 1 newly added unused exports',
269
+ ],
270
+ },
250
271
  });
@@ -423,4 +423,15 @@ async function main() {
423
423
  process.exit(1);
424
424
  }
425
425
 
426
- runAsCli(import.meta.url, main, { source: 'check-doc-links' });
426
+ runAsCli(import.meta.url, main, {
427
+ source: 'check-doc-links',
428
+ usage: {
429
+ invocation: 'node .agents/scripts/check-doc-links.js',
430
+ summary:
431
+ 'Validate every relative Markdown link and /slash-command token across docs/ and .agents/, and reject mentions of retired commands.',
432
+ flags: [],
433
+ notes: [
434
+ 'Exit codes:\n 0 every link and command token resolves\n 1 at least one violation (file:line on stderr)',
435
+ ],
436
+ },
437
+ });
@@ -399,4 +399,13 @@ async function main() {
399
399
  await runAsCli(import.meta.url, main, {
400
400
  source: 'check-lifecycle-doc-drift',
401
401
  propagateExitCode: true,
402
+ usage: {
403
+ invocation: 'node .agents/scripts/check-lifecycle-doc-drift.js',
404
+ summary:
405
+ "Fail when the listener-model table in docs/LIFECYCLE.md drifts from the lifecycle listeners' declared subscriptions.",
406
+ flags: [],
407
+ notes: [
408
+ 'Exit codes:\n 0 doc and code agree\n 1 drift in either direction',
409
+ ],
410
+ },
402
411
  });