@event4u/agent-config 8.7.0 → 8.9.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 (171) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +109 -222
  3. package/CONTRIBUTING.md +25 -0
  4. package/README.md +7 -4
  5. package/dist/agent-src/commands/agent-handoff.md +39 -2
  6. package/dist/agent-src/commands/research/deep.md +8 -0
  7. package/dist/agent-src/commands/research/report.md +7 -0
  8. package/dist/agent-src/commands/roadmap/create.md +12 -0
  9. package/dist/agent-src/commands/roadmap/process-full.md +31 -5
  10. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +30 -1
  11. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
  12. package/dist/agent-src/contexts/execution/orchestration-benchmark-gate.md +28 -16
  13. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +36 -5
  14. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +37 -0
  15. package/dist/agent-src/contexts/execution/subagent-topologies.md +34 -0
  16. package/dist/agent-src/contexts/execution/verification-mechanics.md +9 -9
  17. package/dist/agent-src/rules/active-remediation.md +92 -0
  18. package/dist/agent-src/rules/agent-authority.md +1 -1
  19. package/dist/agent-src/rules/broken-access-control.md +106 -0
  20. package/dist/agent-src/rules/communication-through-line.md +42 -0
  21. package/dist/agent-src/rules/decision-revisit-gate.md +8 -0
  22. package/dist/agent-src/rules/delegation-policy.md +5 -0
  23. package/dist/agent-src/rules/direct-answers.md +1 -1
  24. package/dist/agent-src/rules/downstream-changes.md +1 -0
  25. package/dist/agent-src/rules/external-code-graph-interop.md +65 -0
  26. package/dist/agent-src/rules/git-history-discipline.md +18 -0
  27. package/dist/agent-src/rules/lethal-trifecta-guard.md +6 -1
  28. package/dist/agent-src/rules/minimal-safe-diff.md +66 -1
  29. package/dist/agent-src/rules/non-destructive-by-default.md +3 -0
  30. package/dist/agent-src/rules/prefer-enums-over-literals.md +65 -0
  31. package/dist/agent-src/rules/question-not-instruction.md +76 -0
  32. package/dist/agent-src/rules/senior-engineering-discipline.md +82 -0
  33. package/dist/agent-src/rules/think-before-action.md +1 -0
  34. package/dist/agent-src/rules/tool-safety.md +8 -0
  35. package/dist/agent-src/rules/untrusted-input-defense.md +87 -22
  36. package/dist/agent-src/scripts/update_roadmap_progress.ts +2 -1
  37. package/dist/agent-src/skills/accessibility-auditor/SKILL.md +19 -0
  38. package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +112 -0
  39. package/dist/agent-src/skills/ai-code-blindspots/evals/triggers.json +52 -0
  40. package/dist/agent-src/skills/authz-review/SKILL.md +21 -4
  41. package/dist/agent-src/skills/code-review/SKILL.md +2 -0
  42. package/dist/agent-src/skills/command-writing/SKILL.md +53 -40
  43. package/dist/agent-src/skills/dcf-modeling/evals/domain-truth.json +29 -0
  44. package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +1 -0
  45. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +20 -0
  46. package/dist/agent-src/skills/design-intelligence/SKILL.md +49 -12
  47. package/dist/agent-src/skills/design-review/SKILL.md +29 -15
  48. package/dist/agent-src/skills/design-system-capture/SKILL.md +63 -24
  49. package/dist/agent-src/skills/forecasting/evals/domain-truth.json +29 -0
  50. package/dist/agent-src/skills/frontend-render-security/SKILL.md +104 -0
  51. package/dist/agent-src/skills/frontend-render-security/evals/triggers.json +52 -0
  52. package/dist/agent-src/skills/markitdown/SKILL.md +1 -0
  53. package/dist/agent-src/skills/mcp/SKILL.md +24 -0
  54. package/dist/agent-src/skills/mcp-builder/SKILL.md +9 -1
  55. package/dist/agent-src/skills/memory-consolidation/SKILL.md +55 -4
  56. package/dist/agent-src/skills/roadmap-writing/SKILL.md +46 -5
  57. package/dist/agent-src/skills/runway-cognition/evals/domain-truth.json +29 -0
  58. package/dist/agent-src/skills/scenario-modeling/evals/domain-truth.json +29 -0
  59. package/dist/agent-src/skills/secrets-management/SKILL.md +7 -0
  60. package/dist/agent-src/skills/skill-writing/SKILL.md +12 -3
  61. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +27 -33
  62. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +112 -0
  63. package/dist/agent-src/skills/supply-chain-intake/evals/triggers.json +52 -0
  64. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +72 -2
  65. package/dist/agent-src/skills/ui-component-architect/SKILL.md +9 -0
  66. package/dist/agent-src/skills/unit-economics-modeling/evals/domain-truth.json +40 -0
  67. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  68. package/dist/agent-src/templates/roadmaps.md +60 -0
  69. package/dist/cli/registry.js +3 -0
  70. package/dist/cli/registry.js.map +1 -1
  71. package/dist/discovery/deprecation-report.md +1 -1
  72. package/dist/discovery/discovery-manifest.json +268 -46
  73. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  74. package/dist/discovery/discovery-manifest.summary.md +4 -4
  75. package/dist/discovery/orphan-report.md +1 -1
  76. package/dist/discovery/packs.json +18 -8
  77. package/dist/discovery/trust-report.md +11 -11
  78. package/dist/discovery/workspaces.json +16 -6
  79. package/dist/install/install.mjs +141 -3
  80. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  81. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  82. package/dist/mcp/registry-manifest.json +4 -4
  83. package/dist/router.json +1 -1
  84. package/dist/scripts/_lib/claude_builtin_names.js +145 -0
  85. package/dist/scripts/_lib/claude_builtin_names.js.map +1 -0
  86. package/dist/scripts/condense.js +14 -0
  87. package/dist/scripts/condense.js.map +1 -1
  88. package/dist/server/schemas/settings.js +2 -1
  89. package/dist/server/schemas/settings.js.map +1 -1
  90. package/docs/CLAIMS.md +58 -2
  91. package/docs/architecture.md +3 -3
  92. package/docs/archive/CHANGELOG-pre-8.9.0.md +306 -0
  93. package/docs/benchmark.md +113 -0
  94. package/docs/catalog.md +32 -5
  95. package/docs/contracts/command-clusters.md +18 -0
  96. package/docs/contracts/design-artifact-verification.md +124 -0
  97. package/docs/contracts/injected-block-authenticity-model.md +66 -0
  98. package/docs/contracts/mcp-tool-inventory.md +31 -30
  99. package/docs/decisions/ADR-061-corpus-grounding-layer.md +13 -0
  100. package/docs/decisions/ADR-105-automatic-subagent-orchestration.md +6 -0
  101. package/docs/decisions/ADR-116-memory-tripwire-activation-path.md +11 -2
  102. package/docs/decisions/ADR-117-subagents-auto-default-on.md +88 -0
  103. package/docs/decisions/INDEX.md +1 -0
  104. package/docs/experiences/content_creator.md +2 -0
  105. package/docs/experiences/finance.md +2 -0
  106. package/docs/experiences/founder.md +2 -0
  107. package/docs/experiences/ops.md +2 -0
  108. package/docs/featured-skills.md +2 -2
  109. package/docs/getting-started-by-role.md +1 -1
  110. package/docs/getting-started.md +1 -1
  111. package/docs/governance-advantage.md +1 -1
  112. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +27 -0
  113. package/docs/guidelines/agent-infra/emphasis-budget.md +45 -0
  114. package/docs/guidelines/agent-infra/memory-access.md +12 -0
  115. package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +151 -0
  116. package/docs/guidelines/agent-infra/tool-description-as-policy.md +35 -0
  117. package/docs/guidelines/design-canon.md +1 -0
  118. package/docs/proof.md +60 -3
  119. package/docs/release-runbook.md +138 -0
  120. package/docs/second-brain-scope.md +116 -0
  121. package/docs/succession.md +80 -0
  122. package/package.json +2 -2
  123. package/src/agent-src/scripts/update_roadmap_progress.ts +2 -1
  124. package/src/config/agent-settings.template.yml +25 -6
  125. package/src/scripts/_dispatch.bash +27 -0
  126. package/src/scripts/_lib/claude_builtin_names.ts +148 -0
  127. package/src/scripts/_lib/file_slicer.ts +117 -0
  128. package/src/scripts/_lib/lexical_index.ts +155 -0
  129. package/src/scripts/_lib/orchestration_gate.ts +12 -8
  130. package/src/scripts/_lib/orchestration_record.ts +170 -0
  131. package/src/scripts/_lib/orchestration_savings.ts +180 -0
  132. package/src/scripts/_lib/retrieval_sanitize.ts +71 -0
  133. package/src/scripts/_lib/security_lint.ts +1 -0
  134. package/src/scripts/_lib/stat_index.ts +98 -0
  135. package/src/scripts/benchmark.ts +122 -0
  136. package/src/scripts/build_proof.ts +51 -0
  137. package/src/scripts/chat_history.ts +79 -7
  138. package/src/scripts/check_memory.ts +2 -0
  139. package/src/scripts/check_quality_regression.ts +51 -0
  140. package/src/scripts/check_roadmap_trackable.ts +3 -2
  141. package/src/scripts/condense.ts +14 -0
  142. package/src/scripts/discovery_graph.ts +0 -0
  143. package/src/scripts/domain_soundness_status.ts +236 -0
  144. package/src/scripts/external_sources_denylist.json +4 -1
  145. package/src/scripts/generate_index.ts +17 -0
  146. package/src/scripts/hot_context_hook.ts +47 -2
  147. package/src/scripts/install-hooks.sh +25 -0
  148. package/src/scripts/install.ts +35 -2
  149. package/src/scripts/learning_sidecar.ts +0 -0
  150. package/src/scripts/lint_agent_skill_names.ts +29 -0
  151. package/src/scripts/lint_behavioural_eval_freshness.ts +140 -0
  152. package/src/scripts/lint_knowledge_scale.ts +4 -3
  153. package/src/scripts/lint_roadmap_complexity.ts +124 -0
  154. package/src/scripts/lint_versioned_cache.ts +195 -0
  155. package/src/scripts/mcp_server/consumer_tool_catalog.json +23 -3
  156. package/src/scripts/mcp_server/tools.ts +182 -1
  157. package/src/scripts/measure_lexical_ranking.ts +173 -0
  158. package/src/scripts/memory_lookup.ts +0 -0
  159. package/src/scripts/memory_replay.ts +285 -0
  160. package/src/scripts/orchestration_record.ts +140 -0
  161. package/src/scripts/orchestration_savings_report.ts +124 -0
  162. package/src/scripts/schemas/domain-truth.schema.json +94 -0
  163. package/src/scripts/schemas/evals.schema.json +113 -0
  164. package/src/scripts/schemas/skill.schema.json +4 -0
  165. package/src/scripts/score_domain_truth.ts +192 -0
  166. package/src/scripts/second_brain_retrieval.ts +278 -0
  167. package/src/scripts/second_brain_run.ts +341 -0
  168. package/src/scripts/second_brain_score.ts +186 -0
  169. package/src/scripts/session_memory_index.ts +94 -0
  170. package/src/scripts/skill_eval_coverage.ts +318 -0
  171. package/src/server/schemas/settings.ts +5 -2
@@ -0,0 +1,318 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Behavioural-eval coverage metric + ratchet
4
+ * (road-to-skill-eval-coverage Phase 1 + Phase 3).
5
+ *
6
+ * Counts, per tier, how many skills carry a behavioural `evals.json`
7
+ * (`src/skills/<skill>/evals/evals.json`). This is the BEHAVIOURAL axis
8
+ * (does the skill produce good output), distinct from the trigger/activation
9
+ * axis (`triggers.json` — does the right skill fire); never conflate the two
10
+ * coverage numbers.
11
+ *
12
+ * Tiers are derived from source, never hardcoded, so the metric stays honest
13
+ * as profiles / rich-tagging change:
14
+ * - `rich` — skills with `token_budget_class: rich` (highest cost).
15
+ * - `default-surface` — union of every profile's `skills_hint` (what a fresh
16
+ * installer hits first).
17
+ * - `router` — the routing skills a mis-fire poisons downstream
18
+ * (`analysis-skill-router`, `command-routing`).
19
+ * - `priority` — the union of the three gated tiers above.
20
+ * - `other` — everything else (the long tail).
21
+ *
22
+ * Modes:
23
+ * (default) human report: overall + per-tier covered/total.
24
+ * --json machine-readable JSON (wired into discovery reporting).
25
+ * --check ratchet gate (CI): fail if overall OR any tier coverage
26
+ * drops below the pinned floor (internal/evals/coverage-floor.json).
27
+ * A missing floor file is treated as an all-zero floor
28
+ * (bootstrap-inert: never fails before the first --write-floor).
29
+ * --write-floor pin the current coverage as the new floor. Maintainer action
30
+ * after authoring evals — the ratchet only ever rises.
31
+ *
32
+ * Exit codes: 0 ok / 1 ratchet regression / 2 usage error.
33
+ */
34
+ import * as fs from 'node:fs';
35
+ import * as path from 'node:path';
36
+ import { fileURLToPath, pathToFileURL } from 'node:url';
37
+
38
+ import { parse as parseYaml } from 'yaml';
39
+
40
+ const _HERE = fileURLToPath(import.meta.url);
41
+ export const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
42
+
43
+ /** The two router skills whose mis-routing poisons everything downstream. */
44
+ const ROUTER_SKILLS: readonly string[] = ['analysis-skill-router', 'command-routing'];
45
+
46
+ export interface CoverageOptions {
47
+ skillsDir?: string;
48
+ profilesDir?: string;
49
+ floorPath?: string;
50
+ }
51
+
52
+ export interface TierCoverage {
53
+ covered: number;
54
+ total: number;
55
+ uncovered: string[];
56
+ }
57
+
58
+ export interface CoverageReport {
59
+ overall: TierCoverage;
60
+ tiers: {
61
+ rich: TierCoverage;
62
+ 'default-surface': TierCoverage;
63
+ router: TierCoverage;
64
+ priority: TierCoverage;
65
+ other: TierCoverage;
66
+ };
67
+ }
68
+
69
+ type Json = string | number | boolean | null | Json[] | { [k: string]: Json };
70
+
71
+ /** Split a leading `---\n…\n---` frontmatter block; `[frontmatter, body]`. */
72
+ function _splitFrontmatter(text: string): [Record<string, Json>, string] {
73
+ if (!text.startsWith('---\n')) return [{}, text];
74
+ const end = text.indexOf('\n---', 4);
75
+ if (end === -1) return [{}, text];
76
+ const fmText = text.slice(4, end);
77
+ const body = text.slice(end + 4).replace(/^\n+/, '');
78
+ let parsed: unknown = {};
79
+ try {
80
+ parsed = parseYaml(fmText);
81
+ } catch {
82
+ parsed = {};
83
+ }
84
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
85
+ return [{}, body];
86
+ }
87
+ return [parsed as Record<string, Json>, body];
88
+ }
89
+
90
+ function _skillsDir(opts: CoverageOptions): string {
91
+ return opts.skillsDir ?? path.join(REPO_ROOT, 'src', 'skills');
92
+ }
93
+
94
+ function _profilesDir(opts: CoverageOptions): string {
95
+ return opts.profilesDir ?? path.join(REPO_ROOT, 'src', 'agent-src', 'profiles');
96
+ }
97
+
98
+ export function _floorPath(opts: CoverageOptions = {}): string {
99
+ return opts.floorPath ?? path.join(REPO_ROOT, 'internal', 'evals', 'coverage-floor.json');
100
+ }
101
+
102
+ /** Every skill slug that ships a SKILL.md, with its token_budget_class. */
103
+ function _allSkills(skillsDir: string): Array<{ name: string; richTagged: boolean }> {
104
+ let entries: fs.Dirent[];
105
+ try {
106
+ entries = fs.readdirSync(skillsDir, { withFileTypes: true });
107
+ } catch {
108
+ return [];
109
+ }
110
+ const out: Array<{ name: string; richTagged: boolean }> = [];
111
+ for (const e of entries) {
112
+ if (!e.isDirectory()) continue;
113
+ const skillMd = path.join(skillsDir, e.name, 'SKILL.md');
114
+ if (!fs.existsSync(skillMd)) continue;
115
+ const [fm] = _splitFrontmatter(fs.readFileSync(skillMd, 'utf-8'));
116
+ out.push({ name: e.name, richTagged: fm['token_budget_class'] === 'rich' });
117
+ }
118
+ out.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
119
+ return out;
120
+ }
121
+
122
+ /** Union of every profile's `skills_hint` — the default surface. */
123
+ function _defaultSurface(profilesDir: string): Set<string> {
124
+ const out = new Set<string>();
125
+ let files: string[];
126
+ try {
127
+ files = fs.readdirSync(profilesDir).filter((f) => f.endsWith('.yml'));
128
+ } catch {
129
+ return out;
130
+ }
131
+ for (const f of files) {
132
+ let doc: unknown;
133
+ try {
134
+ doc = parseYaml(fs.readFileSync(path.join(profilesDir, f), 'utf-8'));
135
+ } catch {
136
+ continue;
137
+ }
138
+ const profile = (doc as { profile?: Json } | null)?.profile;
139
+ const defaults = (profile as { defaults?: Json } | null)?.defaults;
140
+ const hint = (defaults as { skills_hint?: Json } | null)?.skills_hint;
141
+ if (Array.isArray(hint)) {
142
+ for (const s of hint) if (typeof s === 'string') out.add(s);
143
+ }
144
+ }
145
+ return out;
146
+ }
147
+
148
+ function _isCovered(skillsDir: string, name: string): boolean {
149
+ return fs.existsSync(path.join(skillsDir, name, 'evals', 'evals.json'));
150
+ }
151
+
152
+ function _tier(members: string[], covered: (n: string) => boolean): TierCoverage {
153
+ const sorted = [...new Set(members)].sort();
154
+ const uncovered = sorted.filter((n) => !covered(n));
155
+ return { covered: sorted.length - uncovered.length, total: sorted.length, uncovered };
156
+ }
157
+
158
+ export function computeCoverage(opts: CoverageOptions = {}): CoverageReport {
159
+ const skillsDir = _skillsDir(opts);
160
+ const skills = _allSkills(skillsDir);
161
+ const names = skills.map((s) => s.name);
162
+ const richSet = new Set(skills.filter((s) => s.richTagged).map((s) => s.name));
163
+ const defaultSet = _defaultSurface(_profilesDir(opts));
164
+ const routerSet = new Set(ROUTER_SKILLS.filter((r) => names.includes(r)));
165
+ const prioritySet = new Set<string>([...richSet, ...defaultSet, ...routerSet]);
166
+ const covered = (n: string): boolean => _isCovered(skillsDir, n);
167
+
168
+ return {
169
+ overall: _tier(names, covered),
170
+ tiers: {
171
+ rich: _tier([...richSet], covered),
172
+ 'default-surface': _tier([...defaultSet].filter((n) => names.includes(n)), covered),
173
+ router: _tier([...routerSet], covered),
174
+ priority: _tier([...prioritySet].filter((n) => names.includes(n)), covered),
175
+ other: _tier(
176
+ names.filter((n) => !prioritySet.has(n)),
177
+ covered,
178
+ ),
179
+ },
180
+ };
181
+ }
182
+
183
+ interface Floor {
184
+ overall: number;
185
+ tiers: Record<string, number>;
186
+ }
187
+
188
+ function _readFloor(floorPath: string): Floor {
189
+ try {
190
+ const raw = JSON.parse(fs.readFileSync(floorPath, 'utf-8')) as Partial<Floor>;
191
+ return { overall: raw.overall ?? 0, tiers: raw.tiers ?? {} };
192
+ } catch {
193
+ return { overall: 0, tiers: {} };
194
+ }
195
+ }
196
+
197
+ /** Pin current coverage as the ratchet floor. */
198
+ export function writeFloor(opts: CoverageOptions = {}): CoverageReport {
199
+ const report = computeCoverage(opts);
200
+ const floor: Floor = {
201
+ overall: report.overall.covered,
202
+ tiers: Object.fromEntries(
203
+ Object.entries(report.tiers).map(([k, v]) => [k, v.covered]),
204
+ ),
205
+ };
206
+ const p = _floorPath(opts);
207
+ fs.mkdirSync(path.dirname(p), { recursive: true });
208
+ fs.writeFileSync(
209
+ p,
210
+ JSON.stringify(
211
+ {
212
+ _comment:
213
+ 'Behavioural-eval coverage ratchet floor (road-to-skill-eval-coverage Phase 3). ' +
214
+ 'skill_eval_coverage --check fails if coverage drops below these counts. ' +
215
+ 'Regenerate with `--write-floor` ONLY after authoring evals — the floor only rises.',
216
+ ...floor,
217
+ },
218
+ null,
219
+ 2,
220
+ ) + '\n',
221
+ );
222
+ return report;
223
+ }
224
+
225
+ /** Ratchet: current coverage must be >= floor, overall and per tier. */
226
+ export function checkRatchet(opts: CoverageOptions = {}): { ok: boolean; regressions: string[] } {
227
+ const report = computeCoverage(opts);
228
+ const floor = _readFloor(_floorPath(opts));
229
+ const regressions: string[] = [];
230
+ if (report.overall.covered < floor.overall) {
231
+ regressions.push(
232
+ `overall coverage ${report.overall.covered} < floor ${floor.overall}`,
233
+ );
234
+ }
235
+ for (const [tier, cov] of Object.entries(report.tiers)) {
236
+ const f = floor.tiers[tier] ?? 0;
237
+ if (cov.covered < f) {
238
+ regressions.push(`tier '${tier}' coverage ${cov.covered} < floor ${f}`);
239
+ }
240
+ }
241
+ return { ok: regressions.length === 0, regressions };
242
+ }
243
+
244
+ function _pct(c: TierCoverage): string {
245
+ if (c.total === 0) return 'n/a';
246
+ return `${((c.covered / c.total) * 100).toFixed(1)}%`;
247
+ }
248
+
249
+ function _renderHuman(r: CoverageReport): string {
250
+ const row = (label: string, c: TierCoverage): string =>
251
+ ` ${label.padEnd(16)} ${String(c.covered).padStart(3)}/${String(c.total).padEnd(3)} ${_pct(c)}`;
252
+ return [
253
+ 'Behavioural-eval coverage (src/skills/*/evals/evals.json)',
254
+ row('overall', r.overall),
255
+ row('rich', r.tiers.rich),
256
+ row('default-surface', r.tiers['default-surface']),
257
+ row('router', r.tiers.router),
258
+ row('priority', r.tiers.priority),
259
+ row('other', r.tiers.other),
260
+ ].join('\n');
261
+ }
262
+
263
+ export function main(argv: readonly string[] = process.argv.slice(2)): number {
264
+ const known = new Set(['--json', '--check', '--write-floor']);
265
+ for (const a of argv) {
266
+ if (!known.has(a)) {
267
+ process.stderr.write(
268
+ `usage: skill_eval_coverage [--json | --check | --write-floor]\n`,
269
+ );
270
+ return 2;
271
+ }
272
+ }
273
+
274
+ if (argv.includes('--write-floor')) {
275
+ const report = writeFloor();
276
+ process.stdout.write(
277
+ `✅ coverage floor pinned: overall ${report.overall.covered}/${report.overall.total}\n`,
278
+ );
279
+ return 0;
280
+ }
281
+
282
+ if (argv.includes('--check')) {
283
+ const { ok, regressions } = checkRatchet();
284
+ if (!ok) {
285
+ process.stdout.write('❌ eval-coverage ratchet regressed:\n');
286
+ for (const r of regressions) process.stdout.write(` - ${r}\n`);
287
+ return 1;
288
+ }
289
+ process.stdout.write('✅ eval-coverage ratchet: no regression.\n');
290
+ return 0;
291
+ }
292
+
293
+ const report = computeCoverage();
294
+ if (argv.includes('--json')) {
295
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
296
+ return 0;
297
+ }
298
+ process.stdout.write(_renderHuman(report) + '\n');
299
+ return 0;
300
+ }
301
+
302
+ function _isCliEntry(): boolean {
303
+ if (process.argv[1] === undefined) return false;
304
+ const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
305
+ if (import.meta.url === argvUrl) return true;
306
+ try {
307
+ return (
308
+ fs.realpathSync(fileURLToPath(import.meta.url)) ===
309
+ fs.realpathSync(path.resolve(process.argv[1]))
310
+ );
311
+ } catch {
312
+ return false;
313
+ }
314
+ }
315
+
316
+ if (_isCliEntry()) {
317
+ process.exit(main());
318
+ }
@@ -249,8 +249,8 @@ export const settingsSchema = z.object({
249
249
  enabled: z.boolean().default(true).describe(
250
250
  'Global master switch for the subagent layer. true (default) = available; false = fully disabled (the canonical kill-switch — no auto-dispatch, no routing, everything runs in-session).',
251
251
  ),
252
- auto: z.enum(['off', 'ask', 'on']).default('ask').describe(
253
- 'Automatic-dispatch mode. off = subagents only via explicit command. ask = classify the task and ask once before dispatching. on = auto-dispatch delegable tasks (surface the choice in one line). Shipped default is ask on subagent-capable hosts, off elsewhere; no-op where the host has no subagent primitive.',
252
+ auto: z.enum(['off', 'ask', 'on']).default('on').describe(
253
+ 'Automatic-dispatch mode. off = subagents only via explicit command. ask = classify the task and ask once before dispatching. on = auto-dispatch delegable tasks (surface the choice in one line). Shipped default is on on subagent-capable hosts (flipped from ask 2026-07-09, ADR-117), off elsewhere; no-op where the host has no subagent primitive.',
254
254
  ),
255
255
  downshift: z.boolean().default(true).describe(
256
256
  'Route delegable sub-tasks to the lowest-capable model tier (cost + speed via model downshift). false = every subagent runs on the session tier.',
@@ -325,6 +325,9 @@ export const settingsSchema = z.object({
325
325
  redact_patterns: z.array(z.string()).default([]).describe(
326
326
  'Regex patterns (one per line) that scrub matches from chat-history transcripts and memory before they hit disk. Use for secrets, customer names, internal URLs. Patterns are anchored and case-insensitive.',
327
327
  ),
328
+ session_index: z.enum(['on', 'off']).default('off').describe(
329
+ 'Opt-in compact memory index at session start (road-to-memory-retrieval-economy P5). on = inject a compact id + title + ~tokens index of curated entries (hard cap 30 rows, bodies never included) through the hot-context hook; the agent fetches full entries via memory_get on demand. off (default) = no injection — the ship-criterion (measured hit-rate gain) is unproven, so off unless proven.',
330
+ ),
328
331
  }),
329
332
  knowledge: z.object({
330
333
  global_sharing: z.object({