@event4u/agent-config 10.1.0 → 10.3.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 (158) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +110 -167
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/analyze/reference-repo.md +62 -0
  5. package/dist/agent-src/commands/roadmap/create.md +4 -1
  6. package/dist/agent-src/commands/roadmap/next.md +38 -0
  7. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +22 -1
  8. package/dist/agent-src/contexts/contracts/frugality-charter.md +1 -1
  9. package/dist/agent-src/personas/advisors/first-principles.md +6 -0
  10. package/dist/agent-src/rules/active-remediation.md +53 -2
  11. package/dist/agent-src/rules/code-provenance.md +66 -4
  12. package/dist/agent-src/rules/content-quoting-floor.md +6 -0
  13. package/dist/agent-src/rules/context-hygiene.md +39 -0
  14. package/dist/agent-src/rules/design-fidelity.md +49 -3
  15. package/dist/agent-src/rules/token-budget-discipline.md +3 -2
  16. package/dist/agent-src/rules/token-efficiency.md +22 -0
  17. package/dist/agent-src/skills/ai-council/SKILL.md +28 -6
  18. package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
  19. package/dist/agent-src/skills/design-review/references/verification-automation.md +23 -1
  20. package/dist/agent-src/skills/fe-design/SKILL.md +27 -3
  21. package/dist/agent-src/skills/judge-synthesis/SKILL.md +30 -0
  22. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +11 -0
  23. package/dist/agent-src/skills/roadmap-writing/SKILL.md +9 -9
  24. package/dist/agent-src/skills/skill-writing/SKILL.md +4 -0
  25. package/dist/agent-src/skills/token-optimizer/SKILL.md +5 -1
  26. package/dist/agent-src/templates/agent-settings.md +12 -28
  27. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +2 -2
  28. package/dist/agent-src/templates/persona.md +26 -0
  29. package/dist/agent-src/templates/roadmaps.md +27 -7
  30. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -1
  31. package/dist/agent-src/templates/skill.md +35 -1
  32. package/dist/cli/commands/commands.candidates.test.js +257 -0
  33. package/dist/cli/commands/commands.candidates.test.js.map +1 -0
  34. package/dist/cli/commands/commands.js +199 -0
  35. package/dist/cli/commands/commands.js.map +1 -1
  36. package/dist/cli/main.js +1 -0
  37. package/dist/cli/main.js.map +1 -1
  38. package/dist/cli/registry.js +2 -2
  39. package/dist/cli/registry.js.map +1 -1
  40. package/dist/cli-delegate/{chunk-3JUTT26I.js → chunk-6ENSXSBW.js} +1 -1
  41. package/dist/cli-delegate/{chunk-TVGXH7VA.js → chunk-6LOPHJLD.js} +1 -1
  42. package/dist/cli-delegate/{chunk-XT2YTJCZ.js → chunk-AYKQGIBG.js} +4 -0
  43. package/dist/cli-delegate/{chunk-HJSKTMIF.js → chunk-BV3WR67D.js} +3 -19
  44. package/dist/cli-delegate/{chunk-HTIU3W56.js → chunk-BWMXLD4B.js} +6 -2
  45. package/dist/cli-delegate/{chunk-2H5SE7DU.js → chunk-FV34EGEX.js} +166 -39
  46. package/dist/cli-delegate/{chunk-XTC5ARB6.js → chunk-IR3IVRVC.js} +7 -2
  47. package/dist/cli-delegate/{chunk-LRXJK6GN.js → chunk-JMQZ7MM5.js} +1 -1
  48. package/dist/cli-delegate/{chunk-NX5AXSLD.js → chunk-X3VOARZD.js} +3 -3
  49. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  50. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  51. package/dist/cli-delegate/cmd_conformance.js +881 -204
  52. package/dist/cli-delegate/cmd_doctor.js +3 -3
  53. package/dist/cli-delegate/cmd_explain.js +2 -2
  54. package/dist/cli-delegate/cmd_export.js +4 -4
  55. package/dist/cli-delegate/cmd_handoff.js +6 -5
  56. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  57. package/dist/cli-delegate/cmd_migrate.js +2 -2
  58. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  59. package/dist/cli-delegate/cmd_prune.js +4 -4
  60. package/dist/cli-delegate/cmd_route_audit.js +2 -2
  61. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  62. package/dist/cli-delegate/cmd_session_recycle.js +44 -9
  63. package/dist/cli-delegate/cmd_settings_get.js +2 -2
  64. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  65. package/dist/cli-delegate/cmd_settings_set.js +2 -2
  66. package/dist/cli-delegate/cmd_sync.js +4 -4
  67. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  68. package/dist/cli-delegate/cmd_update.js +1 -1
  69. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  70. package/dist/cli-delegate/cmd_validate.js +4 -4
  71. package/dist/cli-delegate/cmd_versions.js +1 -1
  72. package/dist/discovery/deprecation-report.md +1 -1
  73. package/dist/discovery/discovery-manifest.json +21 -21
  74. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  75. package/dist/discovery/discovery-manifest.summary.md +1 -1
  76. package/dist/discovery/dormancy-report.md +1 -1
  77. package/dist/discovery/orphan-report.md +1 -1
  78. package/dist/discovery/packs.json +2 -2
  79. package/dist/discovery/trust-report.md +1 -1
  80. package/dist/discovery/workspaces.json +2 -2
  81. package/dist/hooks/dispatch.js +204 -44
  82. package/dist/install/install.mjs +9 -21
  83. package/dist/mcp/registry-manifest.json +2 -2
  84. package/dist/mcp/server.json +2 -2
  85. package/dist/mcp/server.mjs +1337 -490
  86. package/dist/router.json +1 -1
  87. package/dist/scripts/_lib/agent_settings.js +25 -2
  88. package/dist/scripts/_lib/agent_settings.js.map +1 -1
  89. package/dist/scripts/_lib/compile_time_toggles.js +4 -3
  90. package/dist/scripts/_lib/compile_time_toggles.js.map +1 -1
  91. package/dist/server/io/yamlIO.js +0 -2
  92. package/dist/server/io/yamlIO.js.map +1 -1
  93. package/dist/server/schemas/settings.js +3 -9
  94. package/dist/server/schemas/settings.js.map +1 -1
  95. package/dist/shared/settingsClasses.js +64 -2
  96. package/dist/shared/settingsClasses.js.map +1 -1
  97. package/dist/ui/assets/{index-B5qGYOJo.js → index-5fXOHoVh.js} +2 -2
  98. package/dist/ui/assets/index-5fXOHoVh.js.map +1 -0
  99. package/dist/ui/index.html +1 -1
  100. package/docs/contracts/settings-classes.md +307 -145
  101. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +54 -0
  102. package/docs/guidelines/agent-infra/layered-settings.md +1 -2
  103. package/docs/guidelines/agent-infra/symptom-driven-harvest-loop.md +104 -0
  104. package/docs/guidelines/design-antipatterns.md +79 -10
  105. package/docs/guidelines/design-fidelity-mechanics.md +120 -2
  106. package/package.json +1 -1
  107. package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -1
  108. package/src/config/agent-settings.template.yml +12 -30
  109. package/src/config/gate-coverage.yml +42 -8
  110. package/src/config/gate-violation-baselines.json +15 -3
  111. package/src/config/profiles/balanced.ini +0 -2
  112. package/src/config/profiles/full.ini +1 -3
  113. package/src/config/profiles/minimal.ini +0 -2
  114. package/src/config/review-prompt-binding-baseline.json +19 -0
  115. package/src/config/rule-enforcement-baseline.json +0 -1
  116. package/src/scripts/_cli/cmd_session_recycle.ts +66 -9
  117. package/src/scripts/_cli/handoff_sessions.ts +3 -2
  118. package/src/scripts/_dispatch.bash +1 -0
  119. package/src/scripts/_lib/agent_settings.ts +25 -2
  120. package/src/scripts/_lib/bench_telegraph.ts +1 -1
  121. package/src/scripts/_lib/cc_transcript.ts +25 -0
  122. package/src/scripts/_lib/compile_time_toggles.ts +4 -3
  123. package/src/scripts/ai_council/clients.ts +243 -34
  124. package/src/scripts/cache_realization_report.ts +3 -2
  125. package/src/scripts/check_ci_local_parity.ts +60 -6
  126. package/src/scripts/check_review_prompt_binding.ts +553 -0
  127. package/src/scripts/check_rule_projection_integrity.ts +3 -1
  128. package/src/scripts/check_suppression_hygiene.ts +19 -3
  129. package/src/scripts/conformance_scan.ts +282 -9
  130. package/src/scripts/cost/track.mjs +10 -4
  131. package/src/scripts/council_cli.ts +33 -3
  132. package/src/scripts/design_slop_rules.test.ts +37 -6
  133. package/src/scripts/design_slop_rules.ts +150 -22
  134. package/src/scripts/dispatch_r2_reviewer.ts +15 -1
  135. package/src/scripts/external_sources_denylist.json +3 -1
  136. package/src/scripts/hook_manifest.yaml +17 -6
  137. package/src/scripts/hooks/block_unauthorized_git.ts +54 -8
  138. package/src/scripts/hooks/delegation_nudge_hook.ts +33 -8
  139. package/src/scripts/hooks/evidence_independence.ts +61 -9
  140. package/src/scripts/hooks/session_eol_hook.ts +123 -3
  141. package/src/scripts/hooks/turn_end_gate_hook.ts +31 -0
  142. package/src/scripts/hooks/ui_route_nudge_hook.ts +55 -2
  143. package/src/scripts/lint_design_antipattern_parity.ts +201 -0
  144. package/src/scripts/lint_harvest_provenance.ts +483 -0
  145. package/src/scripts/lint_settings_classes.ts +273 -11
  146. package/src/scripts/lint_skill_router_head.ts +254 -0
  147. package/src/scripts/lint_symptom_intake.ts +241 -0
  148. package/src/scripts/report_consultation_rate.ts +128 -2
  149. package/src/scripts/report_skill_activation.ts +6 -4
  150. package/src/scripts/report_skill_obligation_violations.ts +2 -1
  151. package/src/scripts/run_skill_evals.ts +10 -5
  152. package/src/scripts/schemas/persona.schema.json +8 -0
  153. package/src/scripts/schemas/provenance-harvest.schema.json +39 -0
  154. package/src/scripts/sweep_dead_scan_roots.ts +51 -0
  155. package/src/server/io/yamlIO.ts +0 -2
  156. package/src/server/schemas/settings.ts +3 -19
  157. package/src/shared/settingsClasses.ts +93 -2
  158. package/dist/ui/assets/index-B5qGYOJo.js.map +0 -1
@@ -18,8 +18,9 @@ import {
18
18
  comparePair,
19
19
  frontmatterPaths,
20
20
  proseEqual,
21
+ resolveSessionRole,
21
22
  splitFrontmatter
22
- } from "./chunk-2H5SE7DU.js";
23
+ } from "./chunk-FV34EGEX.js";
23
24
  import "./chunk-FTAISGDQ.js";
24
25
  import {
25
26
  atomic_write_json,
@@ -27,7 +28,9 @@ import {
27
28
  is_replay_mode
28
29
  } from "./chunk-EJITJBJX.js";
29
30
  import "./chunk-Q26HT4QT.js";
30
- import "./chunk-XT2YTJCZ.js";
31
+ import {
32
+ projectStoreSlug
33
+ } from "./chunk-AYKQGIBG.js";
31
34
  import "./chunk-PZWRPRWP.js";
32
35
  import "./chunk-M2DPGFZ4.js";
33
36
  import {
@@ -37,7 +40,9 @@ import {
37
40
  } from "./chunk-63WSP6YZ.js";
38
41
  import "./chunk-GRRPEPRN.js";
39
42
  import "./chunk-NXFWFAYV.js";
40
- import "./chunk-XTC5ARB6.js";
43
+ import {
44
+ load_agent_settings
45
+ } from "./chunk-IR3IVRVC.js";
41
46
  import "./chunk-NDJLNC6Q.js";
42
47
  import {
43
48
  detectToolPresence
@@ -54,12 +59,12 @@ import {
54
59
 
55
60
  // src/scripts/_cli/cmd_conformance.ts
56
61
  var YAML = __toESM(require_dist(), 1);
57
- import * as fs13 from "node:fs";
62
+ import * as fs14 from "node:fs";
58
63
  import * as os7 from "node:os";
59
- import * as path13 from "node:path";
60
- import process5 from "node:process";
64
+ import * as path14 from "node:path";
65
+ import process6 from "node:process";
61
66
  import { spawnSync as spawnSync2 } from "node:child_process";
62
- import { fileURLToPath as fileURLToPath13, pathToFileURL as pathToFileURL13 } from "node:url";
67
+ import { fileURLToPath as fileURLToPath14, pathToFileURL as pathToFileURL14 } from "node:url";
63
68
 
64
69
  // src/install/txlog.ts
65
70
  import { createReadStream, createWriteStream, existsSync, readFileSync, renameSync, statSync, unlinkSync } from "node:fs";
@@ -120,18 +125,18 @@ function routeTargetPathsPosix(target) {
120
125
  }
121
126
 
122
127
  // src/scripts/report_conformance_funnel.ts
123
- import * as fs12 from "node:fs";
128
+ import * as fs13 from "node:fs";
124
129
  import * as os6 from "node:os";
125
- import * as path12 from "node:path";
126
- import process4 from "node:process";
127
- import { fileURLToPath as fileURLToPath12, pathToFileURL as pathToFileURL12 } from "node:url";
130
+ import * as path13 from "node:path";
131
+ import process5 from "node:process";
132
+ import { fileURLToPath as fileURLToPath13, pathToFileURL as pathToFileURL13 } from "node:url";
128
133
 
129
134
  // src/scripts/conformance_scan.ts
130
135
  import { createHash as createHash3 } from "node:crypto";
131
- import fs8 from "node:fs";
136
+ import fs9 from "node:fs";
132
137
  import os2 from "node:os";
133
- import path8 from "node:path";
134
- import { fileURLToPath as fileURLToPath8, pathToFileURL as pathToFileURL8 } from "node:url";
138
+ import path9 from "node:path";
139
+ import { fileURLToPath as fileURLToPath9, pathToFileURL as pathToFileURL9 } from "node:url";
135
140
 
136
141
  // src/scripts/_lib/transcript_entry.ts
137
142
  function _isObject(v) {
@@ -683,21 +688,37 @@ var WARN_OPS = /* @__PURE__ */ new Set([
683
688
  "branch"
684
689
  ]);
685
690
  var G = "(?:-[A-Za-z-]+(?:=\\S+)?(?:\\s+\\S+)?\\s+)*";
691
+ var P = "^(?:\\S*\\/)?";
692
+ function ghApiWrite(pathRe) {
693
+ return new RegExp(
694
+ `${P}gh\\s+api\\b(?=[^\\n]*${pathRe})(?=[^\\n]*(?:-X|--method)\\s+(?:POST|PATCH|PUT|DELETE)\\b)`,
695
+ "i"
696
+ );
697
+ }
686
698
  var COMMAND_OPS = [
687
- { op: "publish", re: new RegExp(`\\b(npm|pnpm|yarn)\\s+${G}publish\\b`, "i") },
688
- { op: "release", re: /\bgh\s+release\s+create\b|\bgh\s+api\b[^\n]*\/releases\b/i },
699
+ { op: "publish", re: new RegExp(`${P}(npm|pnpm|yarn)\\s+${G}publish\\b`, "i") },
700
+ {
701
+ op: "release",
702
+ re: new RegExp(`${P}gh\\s+release\\s+create\\b|${ghApiWrite("\\/releases\\b").source}`, "i")
703
+ },
689
704
  {
690
705
  op: "tag",
706
+ re: new RegExp(`${P}git\\s+${G}push\\b[^\\n;|&]*(--tags|--follow-tags|refs\\/tags\\/)`, "i")
707
+ },
708
+ {
709
+ op: "pr-merge",
691
710
  re: new RegExp(
692
- `\\bgit\\s+${G}push\\b[^\\n;|&]*(--tags|--follow-tags|refs\\/tags\\/)`,
711
+ `${P}gh\\s+pr\\s+merge\\b|${ghApiWrite("\\/pulls\\/\\d+\\/merge\\b").source}`,
693
712
  "i"
694
713
  )
695
714
  },
696
- { op: "pr-merge", re: /\bgh\s+pr\s+merge\b|\bgh\s+api\b[^\n]*\/pulls\/\d+\/merge\b/i },
697
- { op: "pr-create", re: /\bgh\s+pr\s+create\b|\bgh\s+api\b[^\n]*-X\s+POST[^\n]*\/pulls\b/i },
698
- { op: "push", re: new RegExp(`\\bgit\\s+${G}push\\b`, "i") },
699
- { op: "commit", re: new RegExp(`\\bgit\\s+${G}commit\\b`, "i") },
700
- { op: "branch", re: new RegExp(`\\bgit\\s+${G}(checkout\\s+-b|switch\\s+-c)\\b`, "i") }
715
+ {
716
+ op: "pr-create",
717
+ re: new RegExp(`${P}gh\\s+pr\\s+create\\b|${ghApiWrite("\\/pulls\\b").source}`, "i")
718
+ },
719
+ { op: "push", re: new RegExp(`${P}git\\s+${G}push\\b`, "i") },
720
+ { op: "commit", re: new RegExp(`${P}git\\s+${G}commit\\b`, "i") },
721
+ { op: "branch", re: new RegExp(`${P}git\\s+${G}(checkout\\s+-b|switch\\s+-c)\\b`, "i") }
701
722
  ];
702
723
  var COMMAND_TOOLS = /* @__PURE__ */ new Set([
703
724
  "launch-process",
@@ -1808,12 +1829,19 @@ function readCiSettled(workspaceRoot) {
1808
1829
  return { seen: false, settled: false };
1809
1830
  }
1810
1831
  var _COMPLETION_RE = /(^|\n)\s*(?:\*\*)?(?:fertig\b|damit ist alles erledigt|aufgabe erledigt|alles erledigt\b|komplett(?:er)? (?:auftrag|abgearbeitet)|der komplette auftrag ist durch|done[.!]|all done\b|task complete)/i;
1832
+ var _NEGATED_CLAIM_RE = /\b(noch nicht|nicht fertig|nicht durch|wäre verfrüht|ist verfrüht|not yet|not done|isn'?t done|nein)\b/i;
1833
+ function _lineAround(prose, at) {
1834
+ const start = prose.lastIndexOf("\n", at) + 1;
1835
+ const end = prose.indexOf("\n", at);
1836
+ return prose.slice(start, end === -1 ? prose.length : end);
1837
+ }
1811
1838
  function detectCompletionClaim(reply, ci) {
1812
1839
  if (!ci.seen || ci.settled) return null;
1813
1840
  const prose = visibleProse(reply);
1814
1841
  const m = _COMPLETION_RE.exec(prose);
1815
1842
  if (!m) return null;
1816
1843
  const at = m.index;
1844
+ if (_NEGATED_CLAIM_RE.test(_lineAround(prose, at))) return null;
1817
1845
  return {
1818
1846
  detector: "completion",
1819
1847
  evidence: prose.slice(at, at + 120).trim(),
@@ -2107,7 +2135,7 @@ function isDispatchTool(tool) {
2107
2135
  function isEvaluationPrompt(prompt) {
2108
2136
  return EVALUATION_RE.test(prompt);
2109
2137
  }
2110
- var SELF_SCOPE_RE = /\b(my (work|change|diff|implementation|code|fix|patch|branch|pr)|this (diff|change|branch|pr|delta|implementation|patch)|the delta|the change i|what i (wrote|built|changed|implemented)|i just (wrote|built|changed|implemented))\b/i;
2138
+ var SELF_SCOPE_RE = /\b(my (work|change|diff|implementation|code|fix|patch|branch|pr)|this (diff|change|pr|delta|implementation|patch)|the delta|the change i|what i (wrote|built|changed|implemented)|i just (wrote|built|changed|implemented))\b/i;
2111
2139
  function isSelfScoped(prompt) {
2112
2140
  return SELF_SCOPE_RE.test(prompt);
2113
2141
  }
@@ -2175,11 +2203,14 @@ function decide2(tool, prompt, priorEvaluations) {
2175
2203
  }
2176
2204
  if (priorEvaluations >= 1) {
2177
2205
  return {
2178
- exit: EXIT_BLOCK3,
2179
- stdout: "",
2180
- stderr: `Blocked: second evaluation dispatch of your own work in this turn (verdict shopping). One evaluation has already run; commissioning another with a different prompt or scope selects the answer instead of measuring it. Report what the first pass returned, then re-plan.
2206
+ exit: EXIT_ALLOW5,
2207
+ stdout: `${JSON.stringify({
2208
+ decision: "warn",
2209
+ reason: `Second evaluation dispatch of your own work in this turn. If both passes judge the SAME subject, that is verdict shopping \u2014 commissioning another with a different prompt or scope selects the answer instead of measuring it. Report what the first pass returned, then re-plan. If this is an implementation fan-out rather than a second review, carry on: this check reads prose and cannot tell the two apart with certainty.`
2210
+ })}
2181
2211
  `,
2182
- evaluations: priorEvaluations
2212
+ stderr: "",
2213
+ evaluations: priorEvaluations + 1
2183
2214
  };
2184
2215
  }
2185
2216
  return {
@@ -2269,8 +2300,561 @@ if (_isCliEntry7()) {
2269
2300
  process.exit(main7());
2270
2301
  }
2271
2302
 
2303
+ // src/scripts/hooks/delegation_nudge_hook.ts
2304
+ import fs8 from "node:fs";
2305
+ import path8 from "node:path";
2306
+ import { fileURLToPath as fileURLToPath8, pathToFileURL as pathToFileURL8 } from "node:url";
2307
+
2308
+ // src/scripts/_lib/host_capability.ts
2309
+ import process2 from "node:process";
2310
+ var SAFE_DEFAULT = {
2311
+ schema_version: 1,
2312
+ subagent_spawn: false,
2313
+ parallel_spawn: false,
2314
+ status_polling: false,
2315
+ separate_quota_pool: false,
2316
+ agent_teams: false,
2317
+ worker_respawn: false
2318
+ };
2319
+ function asBool(value) {
2320
+ return value === true;
2321
+ }
2322
+ function normalizeHostManifest(input) {
2323
+ if (input === null || typeof input !== "object") {
2324
+ return { ...SAFE_DEFAULT };
2325
+ }
2326
+ const src = input;
2327
+ return {
2328
+ schema_version: 1,
2329
+ subagent_spawn: asBool(src.subagent_spawn),
2330
+ parallel_spawn: asBool(src.parallel_spawn),
2331
+ status_polling: asBool(src.status_polling),
2332
+ separate_quota_pool: asBool(src.separate_quota_pool),
2333
+ agent_teams: asBool(src.agent_teams),
2334
+ worker_respawn: asBool(src.worker_respawn)
2335
+ };
2336
+ }
2337
+ var HOST_CAPABILITY_REGISTRY = {
2338
+ claude: { subagent_spawn: true, parallel_spawn: true }
2339
+ };
2340
+ function resolveHostCapabilities(hostId, override) {
2341
+ if (override !== void 0 && override !== null && typeof override === "object" && !Array.isArray(override)) {
2342
+ return normalizeHostManifest(override);
2343
+ }
2344
+ const row = hostId !== null && hostId !== void 0 ? HOST_CAPABILITY_REGISTRY[hostId] : void 0;
2345
+ if (row === void 0) {
2346
+ return { ...SAFE_DEFAULT };
2347
+ }
2348
+ return { ...SAFE_DEFAULT, ...row, schema_version: 1 };
2349
+ }
2350
+ function probeHostCapabilities(hostId) {
2351
+ const base = resolveHostCapabilities(hostId);
2352
+ const flag = process2.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS;
2353
+ const probedAgentTeams = typeof flag === "string" && flag !== "";
2354
+ return { ...base, agent_teams: base.agent_teams || probedAgentTeams };
2355
+ }
2356
+
2357
+ // src/scripts/_lib/auto_dispatch.ts
2358
+ var SIZE_FLOOR = 1;
2359
+ function inSession(reason) {
2360
+ return { delegable: false, action: "in-session", mode: null, reason };
2361
+ }
2362
+ function classifyTask(signals, activation) {
2363
+ if (activation.halted) return inSession("emergency.orchestration_halt is set");
2364
+ if (!activation.subagent_spawn) return inSession("host has no subagent_spawn primitive");
2365
+ if (!(signals.size_estimate > SIZE_FLOOR)) {
2366
+ return inSession(`task below size floor (${signals.size_estimate} <= ${SIZE_FLOOR})`);
2367
+ }
2368
+ const slices = signals.independent_slices ?? 0;
2369
+ let mode = null;
2370
+ let reason = "";
2371
+ if (signals.parallelizable === "steps" || signals.ordered_plan === true) {
2372
+ mode = "do-in-steps";
2373
+ reason = signals.parallelizable === "steps" ? "declared parallelizable: steps" : "ordered-plan structure";
2374
+ } else if (signals.parallelizable === "files" || signals.parallelizable === "independent" || slices >= 2) {
2375
+ mode = "do-in-parallel";
2376
+ reason = signals.parallelizable ? `declared parallelizable: ${signals.parallelizable}` : `independent slices (${slices})`;
2377
+ }
2378
+ if (mode === null) {
2379
+ return { delegable: false, action: "ask", mode: null, reason: "no delegable signal \u2014 borderline, ask" };
2380
+ }
2381
+ return { delegable: true, action: "dispatch", mode, reason };
2382
+ }
2383
+ var LOOKUP_PATTERNS = [
2384
+ {
2385
+ cls: "definition",
2386
+ primitive: "code-graph-query",
2387
+ re: /\b(where\s+is\s+\S+\s+defined|definition\s+(location|of|site)|find\s+the\s+definition|locate\s+the\s+(class|enum|function|type|interface|symbol)|confirm\w*\s+\S+\s+definition)\b/i
2388
+ },
2389
+ {
2390
+ cls: "references",
2391
+ primitive: "code-graph-query",
2392
+ re: /\b(who\s+(calls|imports|uses|references)|call\s*sites?|import\s+(call\s*)?sites?|reverse\s+references|where\s+is\s+\S+\s+(used|imported|referenced|called)|all\s+(callers|usages|references)\s+of)\b/i
2393
+ },
2394
+ {
2395
+ cls: "string-existence",
2396
+ primitive: "fts-or-capped-grep",
2397
+ re: /\b(does\s+(the\s+)?string\s+.*\bexist|is\s+(the\s+)?string\s+.*\b(present|used)\b|prob\w+\s+(candidate\s+)?strings?|search\s+for\s+the\s+(exact\s+)?string|(grep|check)\s+(for\s+)?(the\s+)?(literal|string)\b|does\s+\S+\s+appear\s+anywhere)/i
2398
+ },
2399
+ {
2400
+ cls: "report-run",
2401
+ primitive: "script-run-rtk",
2402
+ re: /\b(run(ning)?\s+(the\s+)?\S*(report|check|lint\w*|coverage)\b|run(ning)?\s+(check|lint|report)_\w+|regenerate\s+the\s+\S+\s+report)/i
2403
+ }
2404
+ ];
2405
+ function classifyLookup(taskText) {
2406
+ for (const p of LOOKUP_PATTERNS) {
2407
+ if (p.re.test(taskText)) {
2408
+ return {
2409
+ lookup_class: p.cls,
2410
+ route: "primitive",
2411
+ primitive: p.primitive,
2412
+ reason: `lookup-class ${p.cls} \u2014 deterministic primitive, no spawn`
2413
+ };
2414
+ }
2415
+ }
2416
+ return {
2417
+ lookup_class: null,
2418
+ route: "escalate",
2419
+ primitive: null,
2420
+ reason: "not lookup-shaped \u2014 regular classification path (never down-guessed)"
2421
+ };
2422
+ }
2423
+
2424
+ // src/scripts/_lib/judgment_ladder.ts
2425
+ var RENAME_RE = /\brename\s+\S+\s+to\s+\S+\b/i;
2426
+ var CODEMOD_RE = /\bcodemod\b/i;
2427
+ var FORMATTER_RUN_RE = /\bauto-?format(?:ting)?\b|\breformat(?:ting)?\b|\brun(?:ning)?\s+prettier\b|\brun(?:ning)?\s+eslint\s*--fix\b|\bapply\s+eslint\s*--fix\b/i;
2428
+ var SEARCH_REPLACE_RE = /\bsearch-and-replace\b|\bfind-and-replace\b|\bbulk\s+rename\b/i;
2429
+ function detectMechanicalTransform(text) {
2430
+ const rename = RENAME_RE.exec(text);
2431
+ if (rename) {
2432
+ return { matched: true, reason: `rename signal ("${rename[0]}") \u2014 deterministic script, no spawn` };
2433
+ }
2434
+ const codemod = CODEMOD_RE.exec(text);
2435
+ if (codemod) {
2436
+ return { matched: true, reason: `codemod signal ("${codemod[0]}") \u2014 deterministic script, no spawn` };
2437
+ }
2438
+ const formatter = FORMATTER_RUN_RE.exec(text);
2439
+ if (formatter) {
2440
+ return { matched: true, reason: `formatter-run signal ("${formatter[0]}") \u2014 deterministic script, no spawn` };
2441
+ }
2442
+ const searchReplace = SEARCH_REPLACE_RE.exec(text);
2443
+ if (searchReplace) {
2444
+ return {
2445
+ matched: true,
2446
+ reason: `search-and-replace/bulk-rename signal ("${searchReplace[0]}") \u2014 deterministic script, no spawn`
2447
+ };
2448
+ }
2449
+ return { matched: false, reason: "no mechanical-transform signal" };
2450
+ }
2451
+ var SINGLE_SLICE_READHEAVY_RE = /\b(?:read|review|summarize|summarise|inventory|audit|investigate|research|inspect|dig into|look into)\b[^.!?\n]{0,80}\b(?:this file|the file|this codebase|the codebase|this transcript|the transcript|this log|the log|this document|the document|this diff|the diff)\b/i;
2452
+ function detectBoundedReadHeavySlice(text) {
2453
+ const m = SINGLE_SLICE_READHEAVY_RE.exec(text);
2454
+ return m ? {
2455
+ matched: true,
2456
+ reason: `single bounded read-heavy slice ("${m[0]}") \u2014 one lite-tier subagent instead of session-context burn`
2457
+ } : { matched: false, reason: "no single-slice read-heavy signal" };
2458
+ }
2459
+ var CROSS_LAYER_RE = /\bcross[- ]layer\b|\bcross[- ]cutting\b|\bback[- ]?end\s+and\s+front[- ]?end\b|\bfront[- ]?end\s+and\s+back[- ]?end\b/i;
2460
+ var REVIEW_WITH_CHALLENGE_RE = /\breview[- ]with[- ]challenge\b|\bchallenge[- ]and[- ]implement\b|\bimplementer\s+and\s+(?:a\s+)?(?:judge|reviewer)\s+(?:working\s+)?together\b|\bsecond\s+opinion\s+while\s+(?:building|implementing)\b/i;
2461
+ var SHARED_TASK_LIST_RE = /\bshared\s+(?:task\s+list|todo\s+list|backlog)\b|\bcoordinat(?:e|ed|ing)\s+(?:with|between|across)\s+(?:multiple\s+|several\s+)?(?:agents|workers|subagents|teammates)\b/i;
2462
+ function detectCommunicationNeed(text) {
2463
+ const crossLayer = CROSS_LAYER_RE.exec(text);
2464
+ if (crossLayer) {
2465
+ return { matched: true, reason: `cross-layer communication signal ("${crossLayer[0]}")` };
2466
+ }
2467
+ const reviewChallenge = REVIEW_WITH_CHALLENGE_RE.exec(text);
2468
+ if (reviewChallenge) {
2469
+ return { matched: true, reason: `review-with-challenge signal ("${reviewChallenge[0]}")` };
2470
+ }
2471
+ const sharedList = SHARED_TASK_LIST_RE.exec(text);
2472
+ if (sharedList) {
2473
+ return { matched: true, reason: `shared-task-list signal ("${sharedList[0]}")` };
2474
+ }
2475
+ return { matched: false, reason: "no communication-need signal" };
2476
+ }
2477
+ var DESIGN_DECISION_RE = /\bdesign\s+decision\b|\barchitectur(?:e|al)\s+decision\b|\b(?:record(?:ing)?|decide|deciding|decision|accept(?:ed|ing)?|approv(?:e|ed|ing|al)|challeng(?:e|ed|ing)|choos(?:e|ing)|reject(?:ed|ing)?)\b[^.!?\n]{0,40}\bADR\b|\bADR\b[^.!?\n]{0,40}\b(?:record(?:ing)?|decide|deciding|decision|accept(?:ed|ing)?|approv(?:e|ed|ing|al)|challeng(?:e|ed|ing)|choos(?:e|ing)|reject(?:ed|ing)?)\b/i;
2478
+ var SECURITY_DOWNGRADE_RE = /\bsecurity\s+downgrade\b|\bdowngrade\s+(?:the\s+)?security\b|\bsecurity\s+exception\b/i;
2479
+ var RELEASE_GATE_ESCALATION_RE = /\bgate\s+escalation\b|\bescalat(?:e|ion)\s+to\s+(?:the\s+)?council\b|\b(?:escalat(?:e|ing|ion)|contest(?:ed|ing)?|dispute|disputing|override|overriding|waiv(?:e|ing)|bypass(?:ed|ing)?|challeng(?:e|ed|ing))\b[^.!?\n]{0,40}\brelease[- ]gate\b|\brelease[- ]gate\b[^.!?\n]{0,40}\b(?:escalat(?:e|ing|ion)|contest(?:ed|ing)?|dispute|disputing|override|overriding|waiv(?:e|ing)|bypass(?:ed|ing)?|challeng(?:e|ed|ing))\b/i;
2480
+ function detectContestedJudgment(text) {
2481
+ const design = DESIGN_DECISION_RE.exec(text);
2482
+ if (design) {
2483
+ return { matched: true, reason: `design-decision signal ("${design[0]}")` };
2484
+ }
2485
+ const security = SECURITY_DOWNGRADE_RE.exec(text);
2486
+ if (security) {
2487
+ return { matched: true, reason: `security-downgrade signal ("${security[0]}")` };
2488
+ }
2489
+ const releaseGate = RELEASE_GATE_ESCALATION_RE.exec(text);
2490
+ if (releaseGate) {
2491
+ return { matched: true, reason: `release-gate-escalation signal ("${releaseGate[0]}")` };
2492
+ }
2493
+ return { matched: false, reason: "no contested-judgment signal" };
2494
+ }
2495
+ var _QUESTION_IMPERATIVE_RE = /\b(fix|implement|refactor|build|create|write|add|update|delete|remove|rename|migrate|install|deploy|commit|push|merge|run|execute|generate|erstelle|baue|implementiere|schreibe|behebe)\b/i;
2496
+ var _QUESTION_LEAD_RE = /^(is|are|does|do|did|can|could|should|would|will|which|what|why|how|when|where|who|whose|ist|sind|hat|haben|kann|welche[rs]?|was|warum|wie|wann|wo|wer)\b/i;
2497
+ var _CLASSIFY_LEAD_RE = /^(classify|categori[sz]e|klassifiziere)\b/i;
2498
+ var _QUESTION_MAX_LEN = 240;
2499
+ var _NEEDS_TOOLS_RE = /\b(this|the|that|my|our)\s+(?:[\w-]+\s+){0,2}?(file|files|codebase|repo|repository|transcript|log|logs|diff|document|branch|pr|route|routes|schema|module|class|function|endpoint|test|tests)\b|[\w.-]+\/[\w.-]+|\b[\w-]+\.(ts|js|py|php|md|json|yaml|yml|sh|go|rs)\b/i;
2500
+ function detectBoundedQuestion(taskText) {
2501
+ const text = taskText.trim();
2502
+ if (!text || text.length > _QUESTION_MAX_LEN || text.includes("\n")) {
2503
+ return { matched: false, reason: "not-bounded" };
2504
+ }
2505
+ if (_NEEDS_TOOLS_RE.test(text)) {
2506
+ return { matched: false, reason: "references-tool-requiring-objects" };
2507
+ }
2508
+ if (_CLASSIFY_LEAD_RE.test(text)) {
2509
+ return {
2510
+ matched: true,
2511
+ reason: "bounded-question (classification) \u2014 rung-0.5 single completion via ask_transport, no session"
2512
+ };
2513
+ }
2514
+ if (_QUESTION_IMPERATIVE_RE.test(text)) {
2515
+ return { matched: false, reason: "imperative-work-verb" };
2516
+ }
2517
+ if (_QUESTION_LEAD_RE.test(text) && text.endsWith("?")) {
2518
+ return {
2519
+ matched: true,
2520
+ reason: "bounded-question \u2014 rung-0.5 single completion via ask_transport, no session"
2521
+ };
2522
+ }
2523
+ return { matched: false, reason: "no-interrogative-shape" };
2524
+ }
2525
+ function classifyLadder(inp) {
2526
+ if (inp.interactiveApprovalRequired === true) {
2527
+ return {
2528
+ rung: null,
2529
+ verdict: "in-session",
2530
+ reason: "interactive-approval-required \u2014 caller-stated, needs a human decision before anything may run"
2531
+ };
2532
+ }
2533
+ const lookup = classifyLookup(inp.taskText);
2534
+ if (lookup.route === "primitive") {
2535
+ return { rung: 0, verdict: "script", reason: `lookup-class ${lookup.lookup_class} \u2014 ${lookup.reason}` };
2536
+ }
2537
+ const mechanical = detectMechanicalTransform(inp.taskText);
2538
+ if (mechanical.matched) {
2539
+ return { rung: 0, verdict: "script", reason: mechanical.reason };
2540
+ }
2541
+ if (inp.insideSubagentSession === true) {
2542
+ return {
2543
+ rung: null,
2544
+ verdict: "in-session",
2545
+ reason: "recursive-dispatch guard: this classification runs inside a subagent/teammate session \u2014 rungs 1-4 resolve in-session"
2546
+ };
2547
+ }
2548
+ if (inp.activation.halted) {
2549
+ return { rung: null, verdict: "in-session", reason: "emergency.orchestration_halt is set" };
2550
+ }
2551
+ if (!inp.activation.subagent_spawn) {
2552
+ return { rung: null, verdict: "in-session", reason: "host has no subagent_spawn primitive" };
2553
+ }
2554
+ const contested = detectContestedJudgment(inp.taskText);
2555
+ if (contested.matched) {
2556
+ return { rung: 4, verdict: "council", reason: contested.reason };
2557
+ }
2558
+ const communication = detectCommunicationNeed(inp.taskText);
2559
+ if (communication.matched) {
2560
+ if (inp.agentTeams) {
2561
+ return { rung: 3, verdict: "team", reason: communication.reason };
2562
+ }
2563
+ const fallback = classifyTask(inp.signals, inp.activation);
2564
+ if (fallback.action === "dispatch" && fallback.mode !== null) {
2565
+ return {
2566
+ rung: 2,
2567
+ verdict: "subagent",
2568
+ mode: fallback.mode,
2569
+ degraded_from: 3,
2570
+ reason: `${communication.reason} \u2014 no agent_teams host capability, degraded to rung 2 (${fallback.reason})`
2571
+ };
2572
+ }
2573
+ return {
2574
+ rung: null,
2575
+ verdict: fallback.action === "ask" ? "ask" : "in-session",
2576
+ degraded_from: 3,
2577
+ reason: `${communication.reason} \u2014 no agent_teams host capability, degraded below rung 2 (${fallback.reason})`
2578
+ };
2579
+ }
2580
+ const classification = classifyTask(inp.signals, inp.activation);
2581
+ if (classification.action === "dispatch" && classification.mode !== null) {
2582
+ return { rung: 2, verdict: "subagent", mode: classification.mode, reason: classification.reason };
2583
+ }
2584
+ if (inp.signals.size_estimate <= SIZE_FLOOR) {
2585
+ const question = detectBoundedQuestion(inp.taskText);
2586
+ if (question.matched) {
2587
+ return { rung: 0.5, verdict: "ask", reason: question.reason };
2588
+ }
2589
+ return {
2590
+ rung: null,
2591
+ verdict: classification.action === "ask" ? "ask" : "in-session",
2592
+ reason: classification.reason
2593
+ };
2594
+ }
2595
+ const single = detectBoundedReadHeavySlice(inp.taskText);
2596
+ if (single.matched) {
2597
+ return { rung: 1, verdict: "subagent", mode: null, reason: single.reason };
2598
+ }
2599
+ return {
2600
+ rung: null,
2601
+ verdict: classification.action === "ask" ? "ask" : "in-session",
2602
+ reason: classification.reason
2603
+ };
2604
+ }
2605
+
2606
+ // src/scripts/_lib/subagent_routing.ts
2607
+ function modelForTier(tier, map) {
2608
+ if (tier === "lite") return map.lite ?? "";
2609
+ if (tier === "medium") return map.medium ?? "";
2610
+ if (tier === "high") return map.high ?? "";
2611
+ return "";
2612
+ }
2613
+ function resolveSubagentRouting(inp) {
2614
+ const tier = !inp.downshift || inp.task_tier === "inherit" ? inp.session_tier : inp.task_tier;
2615
+ const downshifted = inp.downshift && inp.task_tier !== "inherit" && tier !== inp.session_tier;
2616
+ const applied = inp.downshift && inp.task_tier !== "inherit";
2617
+ const tier_source = applied ? inp.task_tier_origin ?? "static" : "inherit";
2618
+ const useSeparate = inp.quota_arbitrage && inp.separate_quota_pool;
2619
+ const quota_pool = useSeparate ? "separate" : "shared";
2620
+ const reasonParts = [];
2621
+ reasonParts.push(downshifted ? `downshift to ${tier}` : `session tier ${tier}`);
2622
+ reasonParts.push(useSeparate ? "separate quota pool (bonus)" : "shared quota pool");
2623
+ return {
2624
+ tier,
2625
+ model: modelForTier(tier, inp.model_map),
2626
+ quota_pool,
2627
+ tier_source,
2628
+ reason: reasonParts.join(" \xB7 ")
2629
+ };
2630
+ }
2631
+
2632
+ // src/scripts/hooks/delegation_nudge_hook.ts
2633
+ var EXIT_ALLOW6 = 0;
2634
+ var EXIT_WARN3 = 2;
2635
+ function _isObject7(v) {
2636
+ return typeof v === "object" && v !== null && !Array.isArray(v);
2637
+ }
2638
+ var FILE_TOKEN_RE = /`?\b[\w][\w.\-]{0,80}\.(ts|tsx|js|jsx|mjs|cjs|py|php|rb|go|rs|java|kt|swift|md|mdx|json|ya?ml|css|scss|less|html|vue|svelte|sql|sh|bash|c|cpp|h|hpp|cs|toml|xml)\b`?/gi;
2639
+ var FILE_SIGNAL_FLOOR = 3;
2640
+ function enumeratedFileTokens(text) {
2641
+ const matches = text.match(FILE_TOKEN_RE) ?? [];
2642
+ return [...new Set(matches.map((m) => m.replace(/`/g, "").toLowerCase()))];
2643
+ }
2644
+ function detectEnumeratedFiles(text) {
2645
+ return enumeratedFileTokens(text).length;
2646
+ }
2647
+ var EXPLICIT_COUNT_RE = /\b(\d+)\s+(files?|modules?|components?|endpoints?|scripts?|skills?|rules?|tickets?|tests?|screens?|pages?|repos?|services?|classes?|functions?|methods?|slices?|tasks?|items?|targets?|routes?|controllers?|Dateien|Module|Tests|Komponenten|Skripte|Regeln|Tickets|Aufgaben|Klassen|Funktionen|Endpunkte)\b/i;
2648
+ function detectExplicitSliceCount(text) {
2649
+ const m = EXPLICIT_COUNT_RE.exec(text);
2650
+ if (!m) return null;
2651
+ const n = Number.parseInt(m[1] ?? "", 10);
2652
+ return Number.isFinite(n) && n > 0 ? n : null;
2653
+ }
2654
+ var FOR_EACH_RE = /\bfor\s+each\b|\bfor\s+every\b|\beach\s+of\s+the\b|\bevery\s+one\s+of\b|\ball(?:e|en)\b|\bjed(?:e|er|es|en)\b|\bjeweils\b/i;
2655
+ function detectForEachShape(text) {
2656
+ return FOR_EACH_RE.test(text);
2657
+ }
2658
+ function detectMultiDeliverableConjunction(text) {
2659
+ for (const sentence of text.split(/[.!?\n]+/)) {
2660
+ const commaCount = (sentence.match(/,/g) ?? []).length;
2661
+ if (commaCount < 2) continue;
2662
+ const tail = sentence.slice(sentence.lastIndexOf(",") + 1);
2663
+ if (/^\s*(and|und)\b/i.test(tail)) {
2664
+ return commaCount + 1;
2665
+ }
2666
+ }
2667
+ return 0;
2668
+ }
2669
+ var STEP_WORD_RE = /\b(?:step|schritt)\s*\d+\b/gi;
2670
+ var STEP_LINE_RE = /^\s*\d+[.)]\s+\S/gm;
2671
+ var ORDERED_LINE_FLOOR = 3;
2672
+ var ORDERED_WORD_FLOOR = 2;
2673
+ function detectOrderedPlan(text) {
2674
+ const wordMatches = text.match(STEP_WORD_RE) ?? [];
2675
+ const lineMatches = text.match(STEP_LINE_RE) ?? [];
2676
+ const ordered = wordMatches.length >= ORDERED_WORD_FLOOR || lineMatches.length >= ORDERED_LINE_FLOOR;
2677
+ const count = Math.max(wordMatches.length, lineMatches.length);
2678
+ return { ordered, stepCount: count };
2679
+ }
2680
+ function extractTaskSignals(text) {
2681
+ const ordered = detectOrderedPlan(text);
2682
+ if (ordered.ordered) {
2683
+ return {
2684
+ signals: {
2685
+ parallelizable: null,
2686
+ ordered_plan: true,
2687
+ independent_slices: 0,
2688
+ size_estimate: Math.max(ordered.stepCount, 2)
2689
+ },
2690
+ sliceCountForLine: ordered.stepCount
2691
+ };
2692
+ }
2693
+ const fileCount = detectEnumeratedFiles(text);
2694
+ const explicit = detectExplicitSliceCount(text) ?? 0;
2695
+ const conjunction = detectMultiDeliverableConjunction(text);
2696
+ const forEach = detectForEachShape(text);
2697
+ const fileSignal = fileCount >= FILE_SIGNAL_FLOOR ? fileCount : 0;
2698
+ let slices = Math.max(fileSignal, explicit, conjunction);
2699
+ if (slices === 0 && forEach) {
2700
+ slices = 2;
2701
+ }
2702
+ const parallelizable = fileSignal >= 3 ? "files" : forEach ? "independent" : null;
2703
+ return {
2704
+ signals: {
2705
+ parallelizable,
2706
+ ordered_plan: false,
2707
+ independent_slices: slices,
2708
+ size_estimate: slices > 0 ? Math.max(slices, 2) : 0
2709
+ },
2710
+ sliceCountForLine: slices
2711
+ };
2712
+ }
2713
+ function resolveActivation(workspace_root, hostId) {
2714
+ const settings = load_agent_settings({ cwd: workspace_root });
2715
+ const emergency = settings["emergency"] ?? {};
2716
+ const halted = emergency["orchestration_halt"] === true;
2717
+ const host_manifest = probeHostCapabilities(hostId);
2718
+ const sub = settings["subagents"] ?? {};
2719
+ const downshift = sub["downshift"] !== false;
2720
+ return {
2721
+ activation: { halted, subagent_spawn: host_manifest.subagent_spawn },
2722
+ downshift,
2723
+ separate_quota_pool: host_manifest.separate_quota_pool,
2724
+ agentTeams: host_manifest.agent_teams
2725
+ };
2726
+ }
2727
+ function recommendSliceTier(downshift, separate_quota_pool) {
2728
+ const decision = resolveSubagentRouting({
2729
+ task_tier: "lite",
2730
+ session_tier: "high",
2731
+ downshift,
2732
+ quota_arbitrage: false,
2733
+ model_map: {},
2734
+ separate_quota_pool
2735
+ });
2736
+ return decision.tier;
2737
+ }
2738
+ function buildNudgeLine(rung, classification, sliceCount, tier) {
2739
+ const unit = sliceCount === 1 ? "slice" : "slices";
2740
+ const rungLabel = rung === null ? "rung-?" : `rung-${rung}`;
2741
+ if (rung === 0.5) {
2742
+ return `<delegation-nudge>rung-0.5: ask, est. <1k tokens. This is a single bounded question \u2014 answer it via ONE completion (\`./scripts-run src/scripts/ask_transport "<question>"\`) instead of a subagent spawn (measured spawn floor: ~251k tokens) \u2014 ${classification.reason}.</delegation-nudge>`;
2743
+ }
2744
+ const modeLabel = classification.mode ?? "single-slice";
2745
+ return `<delegation-nudge>${rungLabel}: dispatch ${modeLabel} (${sliceCount} ${unit}, ${tier} tier recommended). Consider dispatching via subagent-orchestration instead of doing every slice in-session \u2014 ${classification.reason}.</delegation-nudge>`;
2746
+ }
2747
+ function classifyPrompt(prompt, workspace_root, hostId) {
2748
+ try {
2749
+ const { signals, sliceCountForLine } = extractTaskSignals(prompt);
2750
+ const { activation, downshift, separate_quota_pool, agentTeams } = resolveActivation(
2751
+ workspace_root,
2752
+ hostId
2753
+ );
2754
+ const sessionRole = resolveSessionRole(process.env);
2755
+ const ladder = classifyLadder({
2756
+ taskText: prompt,
2757
+ signals,
2758
+ activation,
2759
+ agentTeams,
2760
+ insideSubagentSession: sessionRole !== "orchestrator"
2761
+ });
2762
+ if (ladder.verdict !== "subagent") {
2763
+ return null;
2764
+ }
2765
+ const tier = recommendSliceTier(downshift, separate_quota_pool);
2766
+ const sliceCount = ladder.rung === 1 ? 1 : sliceCountForLine;
2767
+ const classification = {
2768
+ delegable: true,
2769
+ action: "dispatch",
2770
+ mode: ladder.mode ?? null,
2771
+ reason: ladder.reason
2772
+ };
2773
+ return { classification, sliceCount, tier, rung: ladder.rung };
2774
+ } catch {
2775
+ return null;
2776
+ }
2777
+ }
2778
+ function _extractPrompt2(payload) {
2779
+ for (const key of ["prompt", "userPrompt", "user_prompt", "message", "text"]) {
2780
+ const v = payload[key];
2781
+ if (typeof v === "string" && v.trim()) {
2782
+ return v;
2783
+ }
2784
+ }
2785
+ return "";
2786
+ }
2787
+ function _workspaceRoot(envelope) {
2788
+ const v = envelope["workspace_root"];
2789
+ if (typeof v === "string" && v) {
2790
+ return v;
2791
+ }
2792
+ return process.cwd();
2793
+ }
2794
+ function main8() {
2795
+ let envelope = {};
2796
+ try {
2797
+ const raw = readHookStdin();
2798
+ envelope = raw.trim() ? JSON.parse(raw) : {};
2799
+ } catch {
2800
+ return EXIT_ALLOW6;
2801
+ }
2802
+ const env = _isObject7(envelope) ? envelope : {};
2803
+ const event = env["event"];
2804
+ const slot = typeof event === "string" && event !== "" ? event : "user_prompt_submit";
2805
+ if (slot !== "user_prompt_submit") {
2806
+ return EXIT_ALLOW6;
2807
+ }
2808
+ const payload = _isObject7(env["payload"]) ? env["payload"] : env;
2809
+ const prompt = _extractPrompt2(payload);
2810
+ if (!prompt) {
2811
+ return EXIT_ALLOW6;
2812
+ }
2813
+ if (isSyntheticPrompt(prompt)) {
2814
+ return EXIT_ALLOW6;
2815
+ }
2816
+ const root = _workspaceRoot(env);
2817
+ const platform = env["platform"];
2818
+ const hostId = typeof platform === "string" && platform ? platform : null;
2819
+ const result = classifyPrompt(prompt, root, hostId);
2820
+ if (!result) {
2821
+ return EXIT_ALLOW6;
2822
+ }
2823
+ process.stdout.write(
2824
+ `${JSON.stringify({
2825
+ decision: "warn",
2826
+ reason: `delegation-nudge: rung-${result.rung} verdict (${result.sliceCount} slices, ${result.tier} tier)`,
2827
+ additional_context: buildNudgeLine(result.rung, result.classification, result.sliceCount, result.tier)
2828
+ })}
2829
+ `
2830
+ );
2831
+ return EXIT_WARN3;
2832
+ }
2833
+ function _isCliEntry8() {
2834
+ if (true) {
2835
+ return false;
2836
+ }
2837
+ if (process.argv[1] === void 0) {
2838
+ return false;
2839
+ }
2840
+ const argvUrl = pathToFileURL8(path8.resolve(process.argv[1])).href;
2841
+ if (import.meta.url === argvUrl) {
2842
+ return true;
2843
+ }
2844
+ try {
2845
+ const here = fs8.realpathSync(fileURLToPath8(import.meta.url));
2846
+ const argv = fs8.realpathSync(path8.resolve(process.argv[1]));
2847
+ return here === argv;
2848
+ } catch {
2849
+ return false;
2850
+ }
2851
+ }
2852
+ if (_isCliEntry8()) {
2853
+ process.exit(main8());
2854
+ }
2855
+
2272
2856
  // src/scripts/conformance_scan.ts
2273
- var REPO_ROOT = path8.resolve(path8.dirname(fileURLToPath8(import.meta.url)), "..", "..");
2857
+ var REPO_ROOT = path9.resolve(path9.dirname(fileURLToPath9(import.meta.url)), "..", "..");
2274
2858
  var OBSERVED_BAND = { low: 9.1, high: 39.2 };
2275
2859
  var BAND_MIN_TURNS = 1978;
2276
2860
  var CARRIER_CHANGES = [
@@ -2304,14 +2888,19 @@ var CHECK_IDS = [
2304
2888
  "git-authorization",
2305
2889
  "vacuous-evidence",
2306
2890
  "evidence-steering",
2307
- "completion-claim"
2891
+ "completion-claim",
2892
+ "task-completeness"
2308
2893
  ];
2309
2894
  var CHECK_MEANINGS = {
2310
2895
  "language-pin": "An assistant turn whose user-visible prose is not in the language that turn's own pin named. Carries provenance (turns_since_prompt, compaction_since_prompt) so a pin that was ABSENT because compaction removed it stays distinguishable from one that was present and ignored.",
2311
2896
  "git-authorization": "A gated git operation performed in a session where no authorization for that operation was observed. Authorization is per-operation and never carries from one to the next.",
2312
2897
  "vacuous-evidence": "A CI poll read as settled without ever observing an in-flight run \u2014 the poll gap that reports a green settle over a window in which nothing was pending yet.",
2313
2898
  "evidence-steering": "A self-commissioned evaluation whose prompt pre-loaded its own verdict, or a second self-scoped evaluation of the same subject within one turn.",
2314
- "completion-claim": "An assistant turn claiming the work is complete while the last CI read in that session was NOT settled. Round 7 measured 14 instances by reading, each followed by the user handing the work back; this is the same predicate `turn-end-gate`'s completion detector refuses on, so the rate and the gate cannot disagree. A session that never polled CI can never hit."
2899
+ "completion-claim": "An assistant turn claiming the work is complete while the last CI read in that session was NOT settled. Round 7 measured 14 instances by reading, each followed by the user handing the work back; this is the same predicate `turn-end-gate`'s completion detector refuses on, so the rate and the gate cannot disagree. A session that never polled CI can never hit.",
2900
+ "task-completeness": `A reply window that left at least one file the prompt ENUMERATED untouched \u2014 the token appears in neither any tool-call input nor any assistant prose before the next user prompt. Scope is deliberately narrow: only prompts naming >= ${FILE_SIGNAL_FLOOR} distinct file tokens are measured, the same floor \`delegation_nudge_hook\` uses for its FILE shape, and the token list comes from that module rather than a second regex.
2901
+ What distinguishes a hit from a false read: a hit is EVIDENCE OF AN OMISSION, not proof of one. Four legitimate shapes produce the same signature and are NOT excluded here \u2014 a blocking question, a hand-back, a user-fenced scope, and an explicitly deferred item all address fewer files than the prompt named, correctly. That is why every hit is hand-validated and a precision is published beside the rate; an unvalidated count from this check means nothing.
2902
+ What it cannot see, stated so a zero is not misread as health: the ordered-plan, explicit-count, for-each and conjunction shapes name a COUNT of deliverables but not their identities, so this check is blind to them by construction \u2014 it does not score them complete, it does not score them at all. A prose deliverable that is not a filename is invisible to it.
2903
+ MEASURED PRECISION: 0 of 3 hits, over 4 eligible windows in 28 sessions (2026-08-12). All three were false positives from ONE extraction defect: the token list is taken from the whole prompt, so files quoted inside material the user PASTED \u2014 a review, a log, an example \u2014 read as deliverables. In all three, the user's own ask contributed zero tokens. \`isInjectedBody\` did not filter them because it only excludes long ENGLISH text, and this corpus is mostly German (12 295 and 7 656 chars, both classified \`de\`, both passed); the one English case missed the 2 500-char cut by 12. So a hit here is not evidence of anything until the ask is separated from the pasted material. Detector D was NOT built on this result \u2014 see \`agents/evidence/analysis/task-completeness-measurement.md\`.`
2315
2904
  };
2316
2905
  function renderWhy(report, id) {
2317
2906
  const hits = report.per_session.flatMap((s) => s.violations.filter((v) => v.check === id));
@@ -2338,10 +2927,18 @@ function renderWhy(report, id) {
2338
2927
  ` provenance: turns_since_prompt=${since ?? "\u2014"} \xB7 compaction_since_prompt=${compacted ?? "\u2014"}`
2339
2928
  );
2340
2929
  }
2930
+ const missed = v.missed;
2931
+ if (missed !== void 0) {
2932
+ const enumerated = v.enumerated;
2933
+ const addressed = v.addressed;
2934
+ lines.push(
2935
+ ` provenance: enumerated=${enumerated ?? "\u2014"} \xB7 addressed=${addressed ?? "\u2014"} \xB7 missed=[${missed.join(", ")}]`
2936
+ );
2937
+ }
2341
2938
  }
2342
2939
  return lines.join("\n");
2343
2940
  }
2344
- function _isObject7(v) {
2941
+ function _isObject8(v) {
2345
2942
  return typeof v === "object" && v !== null && !Array.isArray(v);
2346
2943
  }
2347
2944
  function userText(entry) {
@@ -2365,15 +2962,15 @@ function assistantText(entry) {
2365
2962
  }
2366
2963
  function toolUses2(entry) {
2367
2964
  const msg = entry["message"];
2368
- const content = _isObject7(msg) ? msg["content"] : void 0;
2965
+ const content = _isObject8(msg) ? msg["content"] : void 0;
2369
2966
  if (!Array.isArray(content)) {
2370
2967
  return [];
2371
2968
  }
2372
- return content.filter((b) => _isObject7(b) && b["type"] === "tool_use").map((b) => {
2969
+ return content.filter((b) => _isObject8(b) && b["type"] === "tool_use").map((b) => {
2373
2970
  const o = b;
2374
2971
  return {
2375
2972
  name: String(o["name"] ?? ""),
2376
- input: _isObject7(o["input"]) ? o["input"] : {}
2973
+ input: _isObject8(o["input"]) ? o["input"] : {}
2377
2974
  };
2378
2975
  });
2379
2976
  }
@@ -2385,6 +2982,24 @@ function isInjectedBody(text) {
2385
2982
  }
2386
2983
  var HARNESS_TEXT = /^(API Error:|Request (timed out|was aborted)|\[Request interrupted|Error: |Credit balance is too low|You've hit your|Prompt is too long)/i;
2387
2984
  var EN_OPENER = /^(let me|i'?ll |i'?m |found it|ok[,. ]|okay|alright|here'?s|now[,. ]|looking|checking|reading|running|the |this |that |there |we |you |good |right[,. ]|perfect|done[.,]|all |confirmed|correct)/i;
2985
+ function markAddressed(text, w) {
2986
+ if (w.tokens.length === 0) {
2987
+ return;
2988
+ }
2989
+ const hay = text.toLowerCase();
2990
+ for (const t of w.tokens) {
2991
+ if (!w.addressed.has(t) && hay.includes(t)) {
2992
+ w.addressed.add(t);
2993
+ }
2994
+ }
2995
+ }
2996
+ function evaluateWindow(w) {
2997
+ if (!w.worked || w.tokens.length === 0) {
2998
+ return null;
2999
+ }
3000
+ const missed = w.tokens.filter((t) => !w.addressed.has(t));
3001
+ return missed.length > 0 ? { missed } : null;
3002
+ }
2388
3003
  function scanSession(sessionId, lines) {
2389
3004
  const report = {
2390
3005
  session: sessionId,
@@ -2392,7 +3007,8 @@ function scanSession(sessionId, lines) {
2392
3007
  assistant_turns: 0,
2393
3008
  violations: [],
2394
3009
  de_pin_turns: 0,
2395
- first_at: ""
3010
+ first_at: "",
3011
+ completeness_windows: 0
2396
3012
  };
2397
3013
  let pinned = null;
2398
3014
  let pendingPoll = null;
@@ -2403,6 +3019,29 @@ function scanSession(sessionId, lines) {
2403
3019
  let compactionSincePrompt = false;
2404
3020
  let ciSeen = false;
2405
3021
  let ciSettled = false;
3022
+ let openWindow = null;
3023
+ const closeWindow = () => {
3024
+ if (openWindow === null) {
3025
+ return;
3026
+ }
3027
+ if (openWindow.worked) {
3028
+ report.completeness_windows += 1;
3029
+ }
3030
+ const verdict = evaluateWindow(openWindow);
3031
+ if (verdict !== null) {
3032
+ const addressed = openWindow.tokens.length - verdict.missed.length;
3033
+ report.violations.push({
3034
+ check: "task-completeness",
3035
+ session: sessionId,
3036
+ at: openWindow.at,
3037
+ detail: `prompt enumerated ${openWindow.tokens.length} file(s), reply window touched ${addressed}; untouched: ${verdict.missed.join(", ").slice(0, 160)}`,
3038
+ enumerated: openWindow.tokens.length,
3039
+ addressed,
3040
+ missed: verdict.missed
3041
+ });
3042
+ }
3043
+ openWindow = null;
3044
+ };
2406
3045
  for (const line of lines) {
2407
3046
  if (!line.trim()) {
2408
3047
  continue;
@@ -2451,6 +3090,16 @@ function scanSession(sessionId, lines) {
2451
3090
  continue;
2452
3091
  }
2453
3092
  report.user_turns += 1;
3093
+ closeWindow();
3094
+ const deliverables = enumeratedFileTokens(ut);
3095
+ if (deliverables.length >= FILE_SIGNAL_FLOOR) {
3096
+ openWindow = {
3097
+ at: String(entry["timestamp"] ?? ""),
3098
+ tokens: deliverables,
3099
+ addressed: /* @__PURE__ */ new Set(),
3100
+ worked: false
3101
+ };
3102
+ }
2454
3103
  turnsSincePrompt = 0;
2455
3104
  compactionSincePrompt = false;
2456
3105
  const c = classify(ut);
@@ -2471,6 +3120,11 @@ function scanSession(sessionId, lines) {
2471
3120
  if (prose !== null) {
2472
3121
  report.assistant_turns += 1;
2473
3122
  turnsSincePrompt += 1;
3123
+ const firstLine = (prose.split("\n").find((l) => l.trim()) ?? "").trim();
3124
+ if (openWindow !== null && !HARNESS_TEXT.test(firstLine)) {
3125
+ openWindow.worked = true;
3126
+ markAddressed(prose, openWindow);
3127
+ }
2474
3128
  if (pinned === "de") {
2475
3129
  report.de_pin_turns += 1;
2476
3130
  }
@@ -2504,6 +3158,10 @@ function scanSession(sessionId, lines) {
2504
3158
  }
2505
3159
  }
2506
3160
  for (const tu of toolUses2(entry)) {
3161
+ if (openWindow !== null) {
3162
+ openWindow.worked = true;
3163
+ markAddressed(`${tu.name} ${JSON.stringify(tu.input)}`, openWindow);
3164
+ }
2507
3165
  const cmd = typeof tu.input["command"] === "string" ? tu.input["command"] : null;
2508
3166
  if (cmd !== null) {
2509
3167
  const op = commandOp(cmd);
@@ -2543,9 +3201,10 @@ function scanSession(sessionId, lines) {
2543
3201
  }
2544
3202
  }
2545
3203
  }
3204
+ closeWindow();
2546
3205
  return report;
2547
3206
  }
2548
- var DEFAULT_RATE_SERIES = path8.join(
3207
+ var DEFAULT_RATE_SERIES = path9.join(
2549
3208
  REPO_ROOT,
2550
3209
  "agents",
2551
3210
  "runtime",
@@ -2553,8 +3212,8 @@ var DEFAULT_RATE_SERIES = path8.join(
2553
3212
  "conformance-rates.jsonl"
2554
3213
  );
2555
3214
  function defaultStore(projectDir) {
2556
- const slug = projectDir.replace(/[/.]/g, "-");
2557
- return path8.join(process.env["HOME"] ?? "", ".claude", "projects", slug);
3215
+ const slug = projectStoreSlug(projectDir);
3216
+ return path9.join(process.env["HOME"] ?? "", ".claude", "projects", slug);
2558
3217
  }
2559
3218
  function _tokens(chars) {
2560
3219
  return Math.round(chars / 4);
@@ -2565,13 +3224,13 @@ function measureDelivered(projectRulesDir, globalRulesDir) {
2565
3224
  return {
2566
3225
  project: {
2567
3226
  dir: projectRulesDir,
2568
- present: fs8.existsSync(projectRulesDir),
3227
+ present: fs9.existsSync(projectRulesDir),
2569
3228
  files: p.files,
2570
3229
  tokens: _tokens(p.chars)
2571
3230
  },
2572
3231
  global: {
2573
3232
  dir: globalRulesDir,
2574
- present: fs8.existsSync(globalRulesDir),
3233
+ present: fs9.existsSync(globalRulesDir),
2575
3234
  files: g.files,
2576
3235
  tokens: _tokens(g.chars)
2577
3236
  },
@@ -2579,13 +3238,13 @@ function measureDelivered(projectRulesDir, globalRulesDir) {
2579
3238
  };
2580
3239
  }
2581
3240
  function storeKey(store) {
2582
- return createHash3("sha256").update(path8.resolve(store)).digest("hex").slice(0, 12);
3241
+ return createHash3("sha256").update(path9.resolve(store)).digest("hex").slice(0, 12);
2583
3242
  }
2584
3243
  function scanStore(store, limit) {
2585
- const files = fs8.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ f, m: fs8.statSync(path8.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.f);
3244
+ const files = fs9.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ f, m: fs9.statSync(path9.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.f);
2586
3245
  const per_session = [];
2587
3246
  for (const f of files) {
2588
- const lines = fs8.readFileSync(path8.join(store, f), "utf8").split("\n");
3247
+ const lines = fs9.readFileSync(path9.join(store, f), "utf8").split("\n");
2589
3248
  const r = scanSession(f.replace(/\.jsonl$/, "").slice(0, 8), lines);
2590
3249
  if (r.assistant_turns > 0) {
2591
3250
  per_session.push(r);
@@ -2608,12 +3267,15 @@ function scanStore(store, limit) {
2608
3267
  const rate_pct = assistant_turns === 0 ? 0 : Number((100 * language_pin / assistant_turns).toFixed(1));
2609
3268
  const de_pin_turns = per_session.reduce((n, s) => n + s.de_pin_turns, 0);
2610
3269
  const rate_pct_de_pin = de_pin_turns === 0 ? 0 : Number((100 * language_pin / de_pin_turns).toFixed(1));
3270
+ const completeness_windows = per_session.reduce((n, s) => n + s.completeness_windows, 0);
3271
+ const task_completeness = totals["task-completeness"] ?? 0;
3272
+ const task_completeness_rate_pct = completeness_windows === 0 ? 0 : Number((100 * task_completeness / completeness_windows).toFixed(1));
2611
3273
  const era = spansCarrierChange(per_session.map((s) => s.first_at));
2612
3274
  const delivered = measureDelivered(
2613
- path8.join(REPO_ROOT, ".claude", "rules"),
2614
- path8.join(process.env["HOME"] ?? os2.homedir(), ".claude", "rules")
3275
+ path9.join(REPO_ROOT, ".claude", "rules"),
3276
+ path9.join(process.env["HOME"] ?? os2.homedir(), ".claude", "rules")
2615
3277
  );
2616
- const ownStore = path8.resolve(store) === path8.resolve(defaultStore(REPO_ROOT));
3278
+ const ownStore = path9.resolve(store) === path9.resolve(defaultStore(REPO_ROOT));
2617
3279
  return {
2618
3280
  scanned_at: (/* @__PURE__ */ new Date()).toISOString(),
2619
3281
  store,
@@ -2629,6 +3291,9 @@ function scanStore(store, limit) {
2629
3291
  rate_pct,
2630
3292
  de_pin_turns,
2631
3293
  rate_pct_de_pin,
3294
+ completeness_windows,
3295
+ task_completeness,
3296
+ task_completeness_rate_pct,
2632
3297
  era_spanning: era.spans,
2633
3298
  era_reason: era.what,
2634
3299
  band: bandVerdict(rate_pct, assistant_turns, { spansCarrier: era.spans }),
@@ -2640,8 +3305,8 @@ function scanStore(store, limit) {
2640
3305
  };
2641
3306
  }
2642
3307
  function recordRate(file, scanned_at, rate) {
2643
- fs8.mkdirSync(path8.dirname(file), { recursive: true });
2644
- fs8.appendFileSync(file, `${JSON.stringify({ measured_at: scanned_at, ...rate })}
3308
+ fs9.mkdirSync(path9.dirname(file), { recursive: true });
3309
+ fs9.appendFileSync(file, `${JSON.stringify({ measured_at: scanned_at, ...rate })}
2645
3310
  `, "utf8");
2646
3311
  }
2647
3312
  function render(report) {
@@ -2683,6 +3348,18 @@ function render(report) {
2683
3348
  );
2684
3349
  lines.push(" is the comparable one and the second is the honest one. Both are printed.");
2685
3350
  }
3351
+ const cWindows = report.rate.completeness_windows;
3352
+ const cRate = report.rate.task_completeness_rate_pct;
3353
+ if (typeof cWindows === "number" && typeof cRate === "number") {
3354
+ lines.push("");
3355
+ lines.push(
3356
+ ` task-completeness ${cRate.toFixed(1)}% (${report.rate.task_completeness ?? 0} of ${cWindows} eligible reply windows)`
3357
+ );
3358
+ lines.push(" A hit is EVIDENCE of an omission, never proof: a blocking question, a");
3359
+ lines.push(" hand-back, a fenced scope and a deferred item all produce this signature");
3360
+ lines.push(" correctly. Read the hand-validated precision beside this figure or not");
3361
+ lines.push(" at all \u2014 `--why task-completeness` lists every hit with its missed tokens.");
3362
+ }
2686
3363
  if (report.rate.band === "era-spanning") {
2687
3364
  lines.push(
2688
3365
  ` Not compared: the corpus SPANS a carrier landing \u2014 ${report.rate.era_reason || "see CARRIER_CHANGES"}.`
@@ -2728,7 +3405,7 @@ function render(report) {
2728
3405
  lines.push(" checkbox batching \u2014 measured NOWHERE. ~5 low-severity findings.");
2729
3406
  return lines.join("\n");
2730
3407
  }
2731
- function main8(argv) {
3408
+ function main9(argv) {
2732
3409
  const args = argv ?? process.argv.slice(2);
2733
3410
  let store = null;
2734
3411
  let limit = 30;
@@ -2760,14 +3437,14 @@ function main8(argv) {
2760
3437
  return 2;
2761
3438
  }
2762
3439
  const resolved = store ?? defaultStore(process.cwd());
2763
- if (!fs8.existsSync(resolved)) {
3440
+ if (!fs9.existsSync(resolved)) {
2764
3441
  process.stderr.write(`conformance:behavior: no transcript store at ${resolved}
2765
3442
  `);
2766
3443
  return 1;
2767
3444
  }
2768
3445
  const report = scanStore(resolved, Number.isFinite(limit) && limit > 0 ? limit : 30);
2769
3446
  if (out) {
2770
- fs8.writeFileSync(out, `${JSON.stringify(report, null, 2)}
3447
+ fs9.writeFileSync(out, `${JSON.stringify(report, null, 2)}
2771
3448
  `, "utf8");
2772
3449
  }
2773
3450
  if (record) {
@@ -2775,7 +3452,7 @@ function main8(argv) {
2775
3452
  }
2776
3453
  if (why !== null) {
2777
3454
  const id = why;
2778
- fs8.writeSync(
3455
+ fs9.writeSync(
2779
3456
  1,
2780
3457
  json ? `${JSON.stringify(
2781
3458
  {
@@ -2795,48 +3472,48 @@ function main8(argv) {
2795
3472
  );
2796
3473
  return 0;
2797
3474
  }
2798
- fs8.writeSync(1, json ? `${JSON.stringify(report, null, 2)}
3475
+ fs9.writeSync(1, json ? `${JSON.stringify(report, null, 2)}
2799
3476
  ` : `${render(report)}
2800
3477
  `);
2801
3478
  return 0;
2802
3479
  }
2803
- function _isCliEntry8() {
3480
+ function _isCliEntry9() {
2804
3481
  if (true) {
2805
3482
  return false;
2806
3483
  }
2807
3484
  if (process.argv[1] === void 0) {
2808
3485
  return false;
2809
3486
  }
2810
- const argvUrl = pathToFileURL8(path8.resolve(process.argv[1])).href;
3487
+ const argvUrl = pathToFileURL9(path9.resolve(process.argv[1])).href;
2811
3488
  if (import.meta.url === argvUrl) {
2812
3489
  return true;
2813
3490
  }
2814
3491
  try {
2815
- const here = fs8.realpathSync(fileURLToPath8(import.meta.url));
2816
- const argv = fs8.realpathSync(path8.resolve(process.argv[1]));
3492
+ const here = fs9.realpathSync(fileURLToPath9(import.meta.url));
3493
+ const argv = fs9.realpathSync(path9.resolve(process.argv[1]));
2817
3494
  return here === argv;
2818
3495
  } catch {
2819
3496
  return false;
2820
3497
  }
2821
3498
  }
2822
- if (_isCliEntry8()) {
2823
- process.exit(main8());
3499
+ if (_isCliEntry9()) {
3500
+ process.exit(main9());
2824
3501
  }
2825
3502
 
2826
3503
  // src/scripts/report_carrier_divergence.ts
2827
- import * as fs9 from "node:fs";
3504
+ import * as fs10 from "node:fs";
2828
3505
  import * as os3 from "node:os";
2829
- import * as path9 from "node:path";
2830
- import process2 from "node:process";
2831
- import { fileURLToPath as fileURLToPath9, pathToFileURL as pathToFileURL9 } from "node:url";
2832
- var _HERE = fileURLToPath9(import.meta.url);
2833
- var REPO_ROOT2 = path9.resolve(path9.dirname(_HERE), "..", "..");
2834
- var PROJECT_RULES = path9.join(".claude", "rules");
2835
- var PROJECTION_SOURCE = path9.join("dist", "agent-src", "rules");
2836
- var GLOBAL_RULES = path9.join(".claude", "rules");
3506
+ import * as path10 from "node:path";
3507
+ import process3 from "node:process";
3508
+ import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL10 } from "node:url";
3509
+ var _HERE = fileURLToPath10(import.meta.url);
3510
+ var REPO_ROOT2 = path10.resolve(path10.dirname(_HERE), "..", "..");
3511
+ var PROJECT_RULES = path10.join(".claude", "rules");
3512
+ var PROJECTION_SOURCE = path10.join("dist", "agent-src", "rules");
3513
+ var GLOBAL_RULES = path10.join(".claude", "rules");
2837
3514
  function _listRules(dir) {
2838
3515
  try {
2839
- return fs9.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
3516
+ return fs10.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
2840
3517
  } catch {
2841
3518
  return [];
2842
3519
  }
@@ -2844,7 +3521,7 @@ function _listRules(dir) {
2844
3521
  function _ruleType(file) {
2845
3522
  let text;
2846
3523
  try {
2847
- text = fs9.readFileSync(file, "utf-8");
3524
+ text = fs10.readFileSync(file, "utf-8");
2848
3525
  } catch {
2849
3526
  return "";
2850
3527
  }
@@ -2855,8 +3532,8 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
2855
3532
  const out = {
2856
3533
  projectDir,
2857
3534
  globalDir,
2858
- globalPresent: fs9.existsSync(globalDir),
2859
- projectPresent: fs9.existsSync(projectDir),
3535
+ globalPresent: fs10.existsSync(globalDir),
3536
+ projectPresent: fs10.existsSync(projectDir),
2860
3537
  shared: 0,
2861
3538
  identical: [],
2862
3539
  provenanceOnly: [],
@@ -2879,7 +3556,7 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
2879
3556
  }
2880
3557
  if (!inP && inG) {
2881
3558
  out.globalOnly.push(rule);
2882
- if (sourceDir !== void 0 && _ruleType(path9.join(sourceDir, rule)) === "manual") {
3559
+ if (sourceDir !== void 0 && _ruleType(path10.join(sourceDir, rule)) === "manual") {
2883
3560
  out.manualOnlyGlobal.push(rule);
2884
3561
  }
2885
3562
  continue;
@@ -2889,8 +3566,8 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
2889
3566
  let projectCopy;
2890
3567
  let globalCopy;
2891
3568
  try {
2892
- projectCopy = fs9.readFileSync(path9.join(projectDir, rule));
2893
- globalCopy = fs9.readFileSync(path9.join(globalDir, rule));
3569
+ projectCopy = fs10.readFileSync(path10.join(projectDir, rule));
3570
+ globalCopy = fs10.readFileSync(path10.join(globalDir, rule));
2894
3571
  verdict = comparePair(projectCopy, globalCopy);
2895
3572
  } catch {
2896
3573
  out.shared -= 1;
@@ -3035,11 +3712,11 @@ function render2(d) {
3035
3712
  }
3036
3713
  return lines.join("\n");
3037
3714
  }
3038
- function main9(argv) {
3039
- const args = argv ?? process2.argv.slice(2);
3040
- let projectDir = path9.join(REPO_ROOT2, PROJECT_RULES);
3041
- let globalDir = path9.join(os3.homedir(), GLOBAL_RULES);
3042
- let sourceDir = path9.join(REPO_ROOT2, PROJECTION_SOURCE);
3715
+ function main10(argv) {
3716
+ const args = argv ?? process3.argv.slice(2);
3717
+ let projectDir = path10.join(REPO_ROOT2, PROJECT_RULES);
3718
+ let globalDir = path10.join(os3.homedir(), GLOBAL_RULES);
3719
+ let sourceDir = path10.join(REPO_ROOT2, PROJECTION_SOURCE);
3043
3720
  const value = (i) => {
3044
3721
  const v = args[i + 1];
3045
3722
  return v === void 0 || v.startsWith("-") ? null : v;
@@ -3049,68 +3726,68 @@ function main9(argv) {
3049
3726
  if (a === "--project" || a === "--global" || a === "--source") {
3050
3727
  const v = value(i);
3051
3728
  if (v === null) {
3052
- process2.stderr.write(`report_carrier_divergence: ${a} needs a directory
3729
+ process3.stderr.write(`report_carrier_divergence: ${a} needs a directory
3053
3730
  `);
3054
3731
  return 1;
3055
3732
  }
3056
- const resolved = path9.resolve(v);
3733
+ const resolved = path10.resolve(v);
3057
3734
  if (a === "--project") projectDir = resolved;
3058
3735
  else if (a === "--global") globalDir = resolved;
3059
3736
  else sourceDir = resolved;
3060
3737
  i += 1;
3061
3738
  } else if (a === "--help" || a === "-h") {
3062
- process2.stdout.write(
3739
+ process3.stdout.write(
3063
3740
  "usage: report_carrier_divergence [--project DIR] [--global DIR] [--source DIR]\n"
3064
3741
  );
3065
3742
  return 0;
3066
3743
  } else if (a !== void 0 && a.startsWith("--") && a !== "--quiet") {
3067
- process2.stderr.write(`report_carrier_divergence: unknown flag ${a}
3744
+ process3.stderr.write(`report_carrier_divergence: unknown flag ${a}
3068
3745
  `);
3069
3746
  return 1;
3070
3747
  }
3071
3748
  }
3072
- process2.stdout.write(`${render2(compareCarriers(projectDir, globalDir, sourceDir))}
3749
+ process3.stdout.write(`${render2(compareCarriers(projectDir, globalDir, sourceDir))}
3073
3750
  `);
3074
3751
  return 0;
3075
3752
  }
3076
- function _isCliEntry9() {
3077
- if (process2.argv[1] === void 0) return false;
3078
- if (import.meta.url === pathToFileURL9(path9.resolve(process2.argv[1])).href) return true;
3753
+ function _isCliEntry10() {
3754
+ if (process3.argv[1] === void 0) return false;
3755
+ if (import.meta.url === pathToFileURL10(path10.resolve(process3.argv[1])).href) return true;
3079
3756
  try {
3080
- return fs9.realpathSync(_HERE) === fs9.realpathSync(path9.resolve(process2.argv[1]));
3757
+ return fs10.realpathSync(_HERE) === fs10.realpathSync(path10.resolve(process3.argv[1]));
3081
3758
  } catch {
3082
3759
  return false;
3083
3760
  }
3084
3761
  }
3085
- if (_isCliEntry9()) {
3086
- process2.exit(main9());
3762
+ if (_isCliEntry10()) {
3763
+ process3.exit(main10());
3087
3764
  }
3088
3765
 
3089
3766
  // src/scripts/report_skill_activation.ts
3090
- import * as fs10 from "node:fs";
3767
+ import * as fs11 from "node:fs";
3091
3768
  import * as os4 from "node:os";
3092
- import * as path10 from "node:path";
3093
- import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL10 } from "node:url";
3094
- var _HERE2 = fileURLToPath10(import.meta.url);
3095
- var REPO_ROOT3 = path10.resolve(path10.dirname(_HERE2), "..", "..");
3769
+ import * as path11 from "node:path";
3770
+ import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL11 } from "node:url";
3771
+ var _HERE2 = fileURLToPath11(import.meta.url);
3772
+ var REPO_ROOT3 = path11.resolve(path11.dirname(_HERE2), "..", "..");
3096
3773
  var SKILLS_ROOT = "src/skills";
3097
3774
  var TRIGGER_KEYS = ["triggers:", "trigger_description:", "file_pattern:", "path_prefix:"];
3098
3775
  var DETERMINISTIC_RE = /^\s*(?:[-*]\s*)?(?:\*\*)?(MUST|NEVER|ALWAYS)\b/m;
3099
3776
  function censusSkills(root) {
3100
3777
  const out = { total: 0, withTriggerKey: [], withDeterministicObligation: [] };
3101
- if (!fs10.existsSync(root)) {
3778
+ if (!fs11.existsSync(root)) {
3102
3779
  return out;
3103
3780
  }
3104
- for (const entry of fs10.readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
3781
+ for (const entry of fs11.readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
3105
3782
  if (!entry.isDirectory()) {
3106
3783
  continue;
3107
3784
  }
3108
- const file = path10.join(root, entry.name, "SKILL.md");
3109
- if (!fs10.existsSync(file)) {
3785
+ const file = path11.join(root, entry.name, "SKILL.md");
3786
+ if (!fs11.existsSync(file)) {
3110
3787
  continue;
3111
3788
  }
3112
3789
  out.total += 1;
3113
- const text = fs10.readFileSync(file, "utf8");
3790
+ const text = fs11.readFileSync(file, "utf8");
3114
3791
  const fmEnd = text.startsWith("---") ? text.indexOf("\n---", 3) : -1;
3115
3792
  const fm = fmEnd === -1 ? "" : text.slice(0, fmEnd);
3116
3793
  if (TRIGGER_KEYS.some((k) => new RegExp(`^${k}`, "m").test(fm))) {
@@ -3124,17 +3801,17 @@ function censusSkills(root) {
3124
3801
  return out;
3125
3802
  }
3126
3803
  function defaultStore2(cwd) {
3127
- return path10.join(os4.homedir(), ".claude", "projects", cwd.replace(/[/.]/g, "-"));
3804
+ return path11.join(os4.homedir(), ".claude", "projects", projectStoreSlug(cwd));
3128
3805
  }
3129
3806
  function measureUsage(store, limit) {
3130
3807
  const rep = { store, sessions: 0, assistantTurns: 0, invocations: 0, bySkill: {} };
3131
- if (!fs10.existsSync(store)) {
3808
+ if (!fs11.existsSync(store)) {
3132
3809
  return rep;
3133
3810
  }
3134
- const files = fs10.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => path10.join(store, f)).sort((a, b) => fs10.statSync(b).mtimeMs - fs10.statSync(a).mtimeMs).slice(0, limit);
3811
+ const files = fs11.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => path11.join(store, f)).sort((a, b) => fs11.statSync(b).mtimeMs - fs11.statSync(a).mtimeMs).slice(0, limit);
3135
3812
  rep.sessions = files.length;
3136
3813
  for (const file of files) {
3137
- for (const line of fs10.readFileSync(file, "utf8").split("\n")) {
3814
+ for (const line of fs11.readFileSync(file, "utf8").split("\n")) {
3138
3815
  if (!line.trim()) {
3139
3816
  continue;
3140
3817
  }
@@ -3197,7 +3874,7 @@ function render3(census, usage) {
3197
3874
  }
3198
3875
  totalInv += u.invocations;
3199
3876
  lines.push(
3200
- ` ${path10.basename(u.store).slice(-38).padEnd(38)} sessions=${String(u.sessions).padStart(3)} asst=${String(u.assistantTurns).padStart(6)} Skill calls=${String(u.invocations).padStart(3)}`
3877
+ ` ${path11.basename(u.store).slice(-38).padEnd(38)} sessions=${String(u.sessions).padStart(3)} asst=${String(u.assistantTurns).padStart(6)} Skill calls=${String(u.invocations).padStart(3)}`
3201
3878
  );
3202
3879
  }
3203
3880
  lines.push("");
@@ -3222,7 +3899,7 @@ function render3(census, usage) {
3222
3899
  lines.push(" catalogue once per session, then count descriptions against bare names.");
3223
3900
  return lines.join("\n");
3224
3901
  }
3225
- function main10(argv) {
3902
+ function main11(argv) {
3226
3903
  let limit = 30;
3227
3904
  const stores = [];
3228
3905
  for (let i = 0; i < argv.length; i += 1) {
@@ -3245,24 +3922,24 @@ function main10(argv) {
3245
3922
  if (stores.length === 0) {
3246
3923
  stores.push(defaultStore2(REPO_ROOT3));
3247
3924
  }
3248
- const census = censusSkills(path10.join(REPO_ROOT3, SKILLS_ROOT));
3925
+ const census = censusSkills(path11.join(REPO_ROOT3, SKILLS_ROOT));
3249
3926
  const usage = stores.map((s) => measureUsage(s, limit));
3250
3927
  process.stdout.write(`${render3(census, usage)}
3251
3928
  `);
3252
3929
  return 0;
3253
3930
  }
3254
- if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL10(path10.resolve(process.argv[1])).href) {
3255
- process.exit(main10(process.argv.slice(2)));
3931
+ if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL11(path11.resolve(process.argv[1])).href) {
3932
+ process.exit(main11(process.argv.slice(2)));
3256
3933
  }
3257
3934
 
3258
3935
  // src/scripts/report_skill_obligation_violations.ts
3259
- import * as fs11 from "node:fs";
3936
+ import * as fs12 from "node:fs";
3260
3937
  import * as os5 from "node:os";
3261
- import * as path11 from "node:path";
3262
- import process3 from "node:process";
3263
- import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL11 } from "node:url";
3264
- var _HERE3 = fileURLToPath11(import.meta.url);
3265
- var REPO_ROOT4 = path11.resolve(path11.dirname(_HERE3), "..", "..");
3938
+ import * as path12 from "node:path";
3939
+ import process4 from "node:process";
3940
+ import { fileURLToPath as fileURLToPath12, pathToFileURL as pathToFileURL12 } from "node:url";
3941
+ var _HERE3 = fileURLToPath12(import.meta.url);
3942
+ var REPO_ROOT4 = path12.resolve(path12.dirname(_HERE3), "..", "..");
3266
3943
  var OBLIGATION_LINE_RE = new RegExp(`${DETERMINISTIC_RE.source}.*`, "gm");
3267
3944
  var PATH_RE = /`([A-Za-z0-9_./-]*\/[A-Za-z0-9_.-]+\.[a-z]{2,6})`/g;
3268
3945
  var CMD_RE = /`([a-z][a-z0-9-]*(?: [a-z][a-z0-9:._-]*){1,3})`/g;
@@ -3300,7 +3977,7 @@ function _artefacts(line) {
3300
3977
  return out;
3301
3978
  }
3302
3979
  function extractObligations(repoRoot) {
3303
- const skillsRoot = path11.join(repoRoot, SKILLS_ROOT);
3980
+ const skillsRoot = path12.join(repoRoot, SKILLS_ROOT);
3304
3981
  const census = censusSkills(skillsRoot);
3305
3982
  const out = {
3306
3983
  skills: census.withDeterministicObligation,
@@ -3314,7 +3991,7 @@ function extractObligations(repoRoot) {
3314
3991
  for (const skill of census.withDeterministicObligation) {
3315
3992
  let text;
3316
3993
  try {
3317
- text = fs11.readFileSync(path11.join(skillsRoot, skill, "SKILL.md"), "utf-8");
3994
+ text = fs12.readFileSync(path12.join(skillsRoot, skill, "SKILL.md"), "utf-8");
3318
3995
  } catch {
3319
3996
  continue;
3320
3997
  }
@@ -3430,7 +4107,7 @@ function scanSessionForViolations(session, lines, forbidden, parsed) {
3430
4107
  return flags;
3431
4108
  }
3432
4109
  function defaultStore3(cwd) {
3433
- return path11.join(os5.homedir(), ".claude", "projects", cwd.replace(/[/.]/g, "-"));
4110
+ return path12.join(os5.homedir(), ".claude", "projects", projectStoreSlug(cwd));
3434
4111
  }
3435
4112
  function scanStore2(repoRoot, store, limit) {
3436
4113
  const census = extractObligations(repoRoot);
@@ -3443,14 +4120,14 @@ function scanStore2(repoRoot, store, limit) {
3443
4120
  };
3444
4121
  let files;
3445
4122
  try {
3446
- files = fs11.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ p: path11.join(store, f), m: fs11.statSync(path11.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.p);
4123
+ files = fs12.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ p: path12.join(store, f), m: fs12.statSync(path12.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.p);
3447
4124
  } catch {
3448
4125
  return report;
3449
4126
  }
3450
4127
  report.sessions = files.length;
3451
4128
  for (const file of files) {
3452
- const lines = fs11.readFileSync(file, "utf-8").split("\n");
3453
- const id = path11.basename(file).replace(/\.jsonl$/, "").slice(0, 8);
4129
+ const lines = fs12.readFileSync(file, "utf-8").split("\n");
4130
+ const id = path12.basename(file).replace(/\.jsonl$/, "").slice(0, 8);
3454
4131
  const entries = _parseSession(lines);
3455
4132
  if (loadedSkillsFrom(entries).size > 0) report.sessionsWithASkill += 1;
3456
4133
  report.flags.push(...scanSessionForViolations(id, lines, census.forbidden, entries));
@@ -3520,8 +4197,8 @@ function render4(r) {
3520
4197
  lines.push(" ships as detection-only, and this one says so.");
3521
4198
  return lines.join("\n");
3522
4199
  }
3523
- function main11(argv) {
3524
- const args = argv ?? process3.argv.slice(2);
4200
+ function main12(argv) {
4201
+ const args = argv ?? process4.argv.slice(2);
3525
4202
  let limit = 30;
3526
4203
  let json = false;
3527
4204
  const stores = [];
@@ -3534,7 +4211,7 @@ function main11(argv) {
3534
4211
  if (a === "--limit") {
3535
4212
  const v = value(i);
3536
4213
  if (v === null) {
3537
- process3.stderr.write("report_skill_obligation_violations: --limit needs a number\n");
4214
+ process4.stderr.write("report_skill_obligation_violations: --limit needs a number\n");
3538
4215
  return 1;
3539
4216
  }
3540
4217
  limit = Number.parseInt(v, 10);
@@ -3542,7 +4219,7 @@ function main11(argv) {
3542
4219
  } else if (a === "--store") {
3543
4220
  const v = value(i);
3544
4221
  if (v === null) {
3545
- process3.stderr.write("report_skill_obligation_violations: --store needs a path\n");
4222
+ process4.stderr.write("report_skill_obligation_violations: --store needs a path\n");
3546
4223
  return 1;
3547
4224
  }
3548
4225
  stores.push(v);
@@ -3550,58 +4227,58 @@ function main11(argv) {
3550
4227
  } else if (a === "--json") {
3551
4228
  json = true;
3552
4229
  } else if (a === "--help" || a === "-h") {
3553
- process3.stdout.write(
4230
+ process4.stdout.write(
3554
4231
  "usage: report_skill_obligation_violations [--limit N] [--store PATH]... [--json]\n"
3555
4232
  );
3556
4233
  return 0;
3557
4234
  } else if (a !== void 0 && a.startsWith("--") && a !== "--quiet") {
3558
- process3.stderr.write(`report_skill_obligation_violations: unknown flag ${a}
4235
+ process4.stderr.write(`report_skill_obligation_violations: unknown flag ${a}
3559
4236
  `);
3560
4237
  return 1;
3561
4238
  }
3562
4239
  }
3563
4240
  if (!Number.isFinite(limit) || limit <= 0) {
3564
- process3.stderr.write("report_skill_obligation_violations: --limit must be a positive integer\n");
4241
+ process4.stderr.write("report_skill_obligation_violations: --limit must be a positive integer\n");
3565
4242
  return 1;
3566
4243
  }
3567
4244
  if (stores.length === 0) stores.push(defaultStore3(REPO_ROOT4));
3568
4245
  for (const store of stores) {
3569
4246
  const r = scanStore2(REPO_ROOT4, store, limit);
3570
- process3.stdout.write(json ? `${JSON.stringify(r, null, 2)}
4247
+ process4.stdout.write(json ? `${JSON.stringify(r, null, 2)}
3571
4248
  ` : `${render4(r)}
3572
4249
  `);
3573
4250
  }
3574
4251
  return 0;
3575
4252
  }
3576
- function _isCliEntry10() {
3577
- if (process3.argv[1] === void 0) return false;
3578
- if (import.meta.url === pathToFileURL11(path11.resolve(process3.argv[1])).href) return true;
4253
+ function _isCliEntry11() {
4254
+ if (process4.argv[1] === void 0) return false;
4255
+ if (import.meta.url === pathToFileURL12(path12.resolve(process4.argv[1])).href) return true;
3579
4256
  try {
3580
- return fs11.realpathSync(_HERE3) === fs11.realpathSync(path11.resolve(process3.argv[1]));
4257
+ return fs12.realpathSync(_HERE3) === fs12.realpathSync(path12.resolve(process4.argv[1]));
3581
4258
  } catch {
3582
4259
  return false;
3583
4260
  }
3584
4261
  }
3585
- if (_isCliEntry10()) {
3586
- process3.exit(main11());
4262
+ if (_isCliEntry11()) {
4263
+ process4.exit(main12());
3587
4264
  }
3588
4265
 
3589
4266
  // src/scripts/report_conformance_funnel.ts
3590
- var _HERE4 = fileURLToPath12(import.meta.url);
3591
- var REPO_ROOT5 = path12.resolve(path12.dirname(_HERE4), "..", "..");
4267
+ var _HERE4 = fileURLToPath13(import.meta.url);
4268
+ var REPO_ROOT5 = path13.resolve(path13.dirname(_HERE4), "..", "..");
3592
4269
  function buildFunnel(opts = {}) {
3593
4270
  const repoRoot = opts.repoRoot ?? REPO_ROOT5;
3594
- const projectRulesDir = opts.projectRulesDir ?? path12.join(repoRoot, PROJECT_RULES);
3595
- const globalRulesDir = opts.globalRulesDir ?? path12.join(os6.homedir(), GLOBAL_RULES);
3596
- const sourceDir = opts.sourceDir ?? path12.join(repoRoot, PROJECTION_SOURCE);
4271
+ const projectRulesDir = opts.projectRulesDir ?? path13.join(repoRoot, PROJECT_RULES);
4272
+ const globalRulesDir = opts.globalRulesDir ?? path13.join(os6.homedir(), GLOBAL_RULES);
4273
+ const sourceDir = opts.sourceDir ?? path13.join(repoRoot, PROJECTION_SOURCE);
3597
4274
  const store = opts.store ?? defaultStore(repoRoot);
3598
4275
  const limit = opts.limit ?? 30;
3599
4276
  return {
3600
4277
  delivered: measureDelivered(projectRulesDir, globalRulesDir),
3601
4278
  divergence: compareCarriers(projectRulesDir, globalRulesDir, sourceDir),
3602
- skills: censusSkills(path12.join(repoRoot, SKILLS_ROOT)),
4279
+ skills: censusSkills(path13.join(repoRoot, SKILLS_ROOT)),
3603
4280
  usage: measureUsage(store, limit),
3604
- storePresent: fs12.existsSync(store),
4281
+ storePresent: fs13.existsSync(store),
3605
4282
  sk2: scanStore2(repoRoot, store, limit)
3606
4283
  };
3607
4284
  }
@@ -3726,8 +4403,8 @@ function render5(r) {
3726
4403
  lines.push("workflow without a measured false-positive rate first (locked policy).");
3727
4404
  return lines.join("\n");
3728
4405
  }
3729
- function main12(argv) {
3730
- const args = argv ?? process4.argv.slice(2);
4406
+ function main13(argv) {
4407
+ const args = argv ?? process5.argv.slice(2);
3731
4408
  const opts = {};
3732
4409
  const value = (i) => {
3733
4410
  const v = args[i + 1];
@@ -3738,11 +4415,11 @@ function main12(argv) {
3738
4415
  if (a === "--store" || a === "--project" || a === "--global" || a === "--source") {
3739
4416
  const v = value(i);
3740
4417
  if (v === null) {
3741
- process4.stderr.write(`report_conformance_funnel: ${a} needs a value
4418
+ process5.stderr.write(`report_conformance_funnel: ${a} needs a value
3742
4419
  `);
3743
4420
  return 1;
3744
4421
  }
3745
- const resolved = path12.resolve(v);
4422
+ const resolved = path13.resolve(v);
3746
4423
  if (a === "--store") opts.store = resolved;
3747
4424
  else if (a === "--project") opts.projectRulesDir = resolved;
3748
4425
  else if (a === "--global") opts.globalRulesDir = resolved;
@@ -3752,41 +4429,41 @@ function main12(argv) {
3752
4429
  const v = value(i);
3753
4430
  const n = v === null ? Number.NaN : Number.parseInt(v, 10);
3754
4431
  if (!Number.isFinite(n) || n <= 0) {
3755
- process4.stderr.write("report_conformance_funnel: --limit must be a positive integer\n");
4432
+ process5.stderr.write("report_conformance_funnel: --limit must be a positive integer\n");
3756
4433
  return 1;
3757
4434
  }
3758
4435
  opts.limit = n;
3759
4436
  i += 1;
3760
4437
  } else if (a === "--help" || a === "-h") {
3761
- process4.stdout.write(
4438
+ process5.stdout.write(
3762
4439
  "usage: report_conformance_funnel [--store PATH] [--limit N]\n [--project DIR] [--global DIR] [--source DIR]\n"
3763
4440
  );
3764
4441
  return 0;
3765
4442
  } else if (a !== void 0 && a.startsWith("--") && a !== "--quiet") {
3766
- process4.stderr.write(`report_conformance_funnel: unknown flag ${a}
4443
+ process5.stderr.write(`report_conformance_funnel: unknown flag ${a}
3767
4444
  `);
3768
4445
  return 1;
3769
4446
  }
3770
4447
  }
3771
- process4.stdout.write(`${render5(buildFunnel(opts))}
4448
+ process5.stdout.write(`${render5(buildFunnel(opts))}
3772
4449
  `);
3773
4450
  return 0;
3774
4451
  }
3775
- function _isCliEntry11() {
3776
- if (process4.argv[1] === void 0) return false;
3777
- if (import.meta.url === pathToFileURL12(path12.resolve(process4.argv[1])).href) return true;
4452
+ function _isCliEntry12() {
4453
+ if (process5.argv[1] === void 0) return false;
4454
+ if (import.meta.url === pathToFileURL13(path13.resolve(process5.argv[1])).href) return true;
3778
4455
  try {
3779
- return fs12.realpathSync(_HERE4) === fs12.realpathSync(path12.resolve(process4.argv[1]));
4456
+ return fs13.realpathSync(_HERE4) === fs13.realpathSync(path13.resolve(process5.argv[1]));
3780
4457
  } catch {
3781
4458
  return false;
3782
4459
  }
3783
4460
  }
3784
- if (_isCliEntry11()) {
3785
- process4.exit(main12());
4461
+ if (_isCliEntry12()) {
4462
+ process5.exit(main13());
3786
4463
  }
3787
4464
 
3788
4465
  // src/scripts/_cli/cmd_conformance.ts
3789
- var _HERE5 = fileURLToPath13(import.meta.url);
4466
+ var _HERE5 = fileURLToPath14(import.meta.url);
3790
4467
  var PACKAGE_ROOT = resolvePackageRoot(import.meta.url);
3791
4468
  var CONFORMANCE_CHECK_IDS = [
3792
4469
  "txlog-clean",
@@ -3797,29 +4474,29 @@ var CONFORMANCE_CHECK_IDS = [
3797
4474
  ];
3798
4475
  var THIN_STUB_MARKER = "Routed rule \u2014 load the body on trigger-match";
3799
4476
  function print(s = "") {
3800
- process5.stdout.write(`${s}
4477
+ process6.stdout.write(`${s}
3801
4478
  `);
3802
4479
  }
3803
4480
  function eprint(s = "") {
3804
- process5.stderr.write(`${s}
4481
+ process6.stderr.write(`${s}
3805
4482
  `);
3806
4483
  }
3807
4484
  function conformanceLogPath() {
3808
- const override = process5.env["AGENT_CONFIG_CONFORMANCE_LOG"];
4485
+ const override = process6.env["AGENT_CONFIG_CONFORMANCE_LOG"];
3809
4486
  if (override && override.trim().length > 0) {
3810
4487
  return override;
3811
4488
  }
3812
- return path13.join(os7.homedir(), ".event4u", "agent-config", "conformance-log.jsonl");
4489
+ return path14.join(os7.homedir(), ".event4u", "agent-config", "conformance-log.jsonl");
3813
4490
  }
3814
4491
  function installLogPath() {
3815
- const override = process5.env["AGENT_CONFIG_INSTALL_LOG"];
4492
+ const override = process6.env["AGENT_CONFIG_INSTALL_LOG"];
3816
4493
  if (override && override.trim().length > 0) {
3817
4494
  return override;
3818
4495
  }
3819
- return path13.join(os7.homedir(), ".event4u", "agent-config", "install-log.jsonl");
4496
+ return path14.join(os7.homedir(), ".event4u", "agent-config", "install-log.jsonl");
3820
4497
  }
3821
4498
  function _check_txlog_clean(logPath = installLogPath()) {
3822
- if (!fs13.existsSync(logPath)) {
4499
+ if (!fs14.existsSync(logPath)) {
3823
4500
  return {
3824
4501
  id: "txlog-clean",
3825
4502
  status: "ok",
@@ -3853,11 +4530,11 @@ function _check_txlog_clean(logPath = installLogPath()) {
3853
4530
  };
3854
4531
  }
3855
4532
  function routeTargetPaths(target) {
3856
- return routeTargetPathsPosix(target).map((rel) => path13.join(...rel.split("/")));
4533
+ return routeTargetPathsPosix(target).map((rel) => path14.join(...rel.split("/")));
3857
4534
  }
3858
4535
  function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
3859
- const routerPath = path13.join(packageRoot, "dist", "router.json");
3860
- if (!fs13.existsSync(routerPath)) {
4536
+ const routerPath = path14.join(packageRoot, "dist", "router.json");
4537
+ if (!fs14.existsSync(routerPath)) {
3861
4538
  return {
3862
4539
  id: "router-pointers",
3863
4540
  status: "fail",
@@ -3867,7 +4544,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
3867
4544
  }
3868
4545
  let router;
3869
4546
  try {
3870
- router = JSON.parse(fs13.readFileSync(routerPath, "utf8"));
4547
+ router = JSON.parse(fs14.readFileSync(routerPath, "utf8"));
3871
4548
  } catch (exc) {
3872
4549
  return {
3873
4550
  id: "router-pointers",
@@ -3876,13 +4553,13 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
3876
4553
  remedy: "reinstall the package \u2014 dist/router.json is corrupt"
3877
4554
  };
3878
4555
  }
3879
- const rulesDir = path13.join(packageRoot, "dist", "agent-src", "rules");
4556
+ const rulesDir = path14.join(packageRoot, "dist", "agent-src", "rules");
3880
4557
  const broken = [];
3881
4558
  let ids = 0;
3882
4559
  let targets = 0;
3883
4560
  for (const kernelId of router["kernel"] ?? []) {
3884
4561
  ids += 1;
3885
- if (!fs13.existsSync(path13.join(rulesDir, `${kernelId}.md`))) {
4562
+ if (!fs14.existsSync(path14.join(rulesDir, `${kernelId}.md`))) {
3886
4563
  broken.push(`kernel:${kernelId} \u2192 rules/${kernelId}.md missing`);
3887
4564
  }
3888
4565
  }
@@ -3890,7 +4567,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
3890
4567
  for (const entry of router[tier] ?? []) {
3891
4568
  const ruleId = String(entry["id"] ?? "");
3892
4569
  ids += 1;
3893
- if (!fs13.existsSync(path13.join(rulesDir, `${ruleId}.md`))) {
4570
+ if (!fs14.existsSync(path14.join(rulesDir, `${ruleId}.md`))) {
3894
4571
  broken.push(`${tier}:${ruleId} \u2192 rules/${ruleId}.md missing`);
3895
4572
  }
3896
4573
  for (const target of entry["routes_to"] ?? []) {
@@ -3900,7 +4577,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
3900
4577
  broken.push(`${ruleId} \u2192 unparseable routes_to ${JSON.stringify(target)}`);
3901
4578
  continue;
3902
4579
  }
3903
- if (!candidates.some((rel) => fs13.existsSync(path13.join(packageRoot, rel)))) {
4580
+ if (!candidates.some((rel) => fs14.existsSync(path14.join(packageRoot, rel)))) {
3904
4581
  broken.push(`${ruleId} \u2192 ${target} (${candidates[0]} missing)`);
3905
4582
  }
3906
4583
  }
@@ -3932,9 +4609,9 @@ function detectSmokePlatform(projectRoot) {
3932
4609
  return "claude";
3933
4610
  }
3934
4611
  function dispatcherRunner(packageRoot) {
3935
- const localTsx = path13.join(packageRoot, "node_modules", ".bin", "tsx");
3936
- const script = path13.join(packageRoot, "src", "scripts", "hooks", "dispatch_hook.ts");
3937
- if (fs13.existsSync(localTsx)) {
4612
+ const localTsx = path14.join(packageRoot, "node_modules", ".bin", "tsx");
4613
+ const script = path14.join(packageRoot, "src", "scripts", "hooks", "dispatch_hook.ts");
4614
+ if (fs14.existsSync(localTsx)) {
3938
4615
  return [localTsx, script];
3939
4616
  }
3940
4617
  return ["npx", "tsx", script];
@@ -3984,12 +4661,12 @@ function _check_hook_dispatcher(projectRoot, packageRoot = PACKAGE_ROOT, opts =
3984
4661
  };
3985
4662
  }
3986
4663
  function readSettingsMode(projectRoot) {
3987
- const settingsPath = path13.join(projectRoot, ".agent-settings.yml");
3988
- if (!fs13.existsSync(settingsPath)) {
4664
+ const settingsPath = path14.join(projectRoot, ".agent-settings.yml");
4665
+ if (!fs14.existsSync(settingsPath)) {
3989
4666
  return "eager-all";
3990
4667
  }
3991
4668
  try {
3992
- const parsed = YAML.parse(fs13.readFileSync(settingsPath, "utf8"));
4669
+ const parsed = YAML.parse(fs14.readFileSync(settingsPath, "utf8"));
3993
4670
  const lean = parsed?.["lean_projection"] ?? null;
3994
4671
  const mode = lean?.["mode"];
3995
4672
  return typeof mode === "string" && mode.length > 0 ? mode : "eager-all";
@@ -4000,7 +4677,7 @@ function readSettingsMode(projectRoot) {
4000
4677
  function kernelIdsFromRouter(packageRoot) {
4001
4678
  try {
4002
4679
  const router = JSON.parse(
4003
- fs13.readFileSync(path13.join(packageRoot, "dist", "router.json"), "utf8")
4680
+ fs14.readFileSync(path14.join(packageRoot, "dist", "router.json"), "utf8")
4004
4681
  );
4005
4682
  return new Set((router["kernel"] ?? []).map(String));
4006
4683
  } catch {
@@ -4017,8 +4694,8 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
4017
4694
  remedy: "set lean_projection.mode to 'eager-all' or 'thin' in .agent-settings.yml"
4018
4695
  };
4019
4696
  }
4020
- const rulesDir = projectedRulesDir ?? path13.join(projectRoot, ".augment", "rules");
4021
- if (!fs13.existsSync(rulesDir)) {
4697
+ const rulesDir = projectedRulesDir ?? path14.join(projectRoot, ".augment", "rules");
4698
+ if (!fs14.existsSync(rulesDir)) {
4022
4699
  return {
4023
4700
  id: "lean-projection",
4024
4701
  status: "skipped",
@@ -4027,7 +4704,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
4027
4704
  };
4028
4705
  }
4029
4706
  const kernel = kernelIdsFromRouter(packageRoot);
4030
- const files = fs13.readdirSync(rulesDir).filter((f) => f.endsWith(".md") && f !== "INDEX.md").sort();
4707
+ const files = fs14.readdirSync(rulesDir).filter((f) => f.endsWith(".md") && f !== "INDEX.md").sort();
4031
4708
  const nonKernel = files.filter((f) => !kernel.has(f.replace(/\.md$/, "")));
4032
4709
  if (nonKernel.length === 0) {
4033
4710
  return {
@@ -4041,7 +4718,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
4041
4718
  for (const f of nonKernel) {
4042
4719
  let text = "";
4043
4720
  try {
4044
- text = fs13.readFileSync(path13.join(rulesDir, f), "utf8");
4721
+ text = fs14.readFileSync(path14.join(rulesDir, f), "utf8");
4045
4722
  } catch {
4046
4723
  continue;
4047
4724
  }
@@ -4072,8 +4749,8 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
4072
4749
  function _check_host_manifest(projectRoot) {
4073
4750
  const detected = Object.entries(detectToolPresence(projectRoot)).filter(([, v]) => v === true).map(([k]) => k);
4074
4751
  const detectedNote = detected.length > 0 ? `detected surfaces: ${detected.join(", ")}` : "no surfaces detected";
4075
- const settingsPath = path13.join(projectRoot, ".agent-settings.yml");
4076
- if (!fs13.existsSync(settingsPath)) {
4752
+ const settingsPath = path14.join(projectRoot, ".agent-settings.yml");
4753
+ if (!fs14.existsSync(settingsPath)) {
4077
4754
  return {
4078
4755
  id: "host-manifest",
4079
4756
  status: "ok",
@@ -4083,7 +4760,7 @@ function _check_host_manifest(projectRoot) {
4083
4760
  }
4084
4761
  let parsed = null;
4085
4762
  try {
4086
- parsed = YAML.parse(fs13.readFileSync(settingsPath, "utf8"));
4763
+ parsed = YAML.parse(fs14.readFileSync(settingsPath, "utf8"));
4087
4764
  } catch (exc) {
4088
4765
  return {
4089
4766
  id: "host-manifest",
@@ -4110,7 +4787,7 @@ function _check_host_manifest(projectRoot) {
4110
4787
  };
4111
4788
  }
4112
4789
  function runConformanceChecks(opts = {}) {
4113
- const projectRoot = opts.projectRoot ?? process5.cwd();
4790
+ const projectRoot = opts.projectRoot ?? process6.cwd();
4114
4791
  const packageRoot = opts.packageRoot ?? PACKAGE_ROOT;
4115
4792
  const checks = [];
4116
4793
  checks.push(_check_txlog_clean());
@@ -4151,7 +4828,7 @@ function _parse(argv) {
4151
4828
  while (i < argv.length) {
4152
4829
  const a = argv[i];
4153
4830
  if (a === "-h" || a === "--help") {
4154
- process5.stdout.write(USAGE);
4831
+ process6.stdout.write(USAGE);
4155
4832
  throw new ArgparseExit(0);
4156
4833
  }
4157
4834
  if (a === "--json") {
@@ -4165,16 +4842,16 @@ function _parse(argv) {
4165
4842
  opts.project = a.slice(a.indexOf("=") + 1);
4166
4843
  } else {
4167
4844
  if (i + 1 >= argv.length) {
4168
- process5.stderr.write(USAGE);
4169
- process5.stderr.write("agent-config conformance: error: --project expects a value\n");
4845
+ process6.stderr.write(USAGE);
4846
+ process6.stderr.write("agent-config conformance: error: --project expects a value\n");
4170
4847
  throw new ArgparseExit(2);
4171
4848
  }
4172
4849
  opts.project = argv[i + 1];
4173
4850
  i += 1;
4174
4851
  }
4175
4852
  } else {
4176
- process5.stderr.write(USAGE);
4177
- process5.stderr.write(`agent-config conformance: error: unrecognized argument ${a}
4853
+ process6.stderr.write(USAGE);
4854
+ process6.stderr.write(`agent-config conformance: error: unrecognized argument ${a}
4178
4855
  `);
4179
4856
  throw new ArgparseExit(2);
4180
4857
  }
@@ -4182,8 +4859,8 @@ function _parse(argv) {
4182
4859
  }
4183
4860
  return opts;
4184
4861
  }
4185
- function main13(argv = null) {
4186
- const opts = _parse(argv !== null ? Array.from(argv) : process5.argv.slice(2));
4862
+ function main14(argv = null) {
4863
+ const opts = _parse(argv !== null ? Array.from(argv) : process6.argv.slice(2));
4187
4864
  if (opts.funnel) {
4188
4865
  print(render5(buildFunnel()));
4189
4866
  return 0;
@@ -4253,28 +4930,28 @@ function main13(argv = null) {
4253
4930
  }
4254
4931
  return failed ? 1 : 0;
4255
4932
  }
4256
- function _isCliEntry12() {
4257
- if (process5.argv[1] === void 0) {
4933
+ function _isCliEntry13() {
4934
+ if (process6.argv[1] === void 0) {
4258
4935
  return false;
4259
4936
  }
4260
- const argvUrl = pathToFileURL13(path13.resolve(process5.argv[1])).href;
4937
+ const argvUrl = pathToFileURL14(path14.resolve(process6.argv[1])).href;
4261
4938
  if (import.meta.url === argvUrl) {
4262
4939
  return true;
4263
4940
  }
4264
4941
  try {
4265
- const here = fs13.realpathSync(fileURLToPath13(import.meta.url));
4266
- const argv = fs13.realpathSync(path13.resolve(process5.argv[1]));
4942
+ const here = fs14.realpathSync(fileURLToPath14(import.meta.url));
4943
+ const argv = fs14.realpathSync(path14.resolve(process6.argv[1]));
4267
4944
  return here === argv;
4268
4945
  } catch {
4269
4946
  return false;
4270
4947
  }
4271
4948
  }
4272
- if (_isCliEntry12() || process5.argv[1] === _HERE5) {
4949
+ if (_isCliEntry13() || process6.argv[1] === _HERE5) {
4273
4950
  try {
4274
- process5.exitCode = main13(process5.argv.slice(2));
4951
+ process6.exitCode = main14(process6.argv.slice(2));
4275
4952
  } catch (e) {
4276
4953
  if (e instanceof ArgparseExit) {
4277
- process5.exitCode = e.code;
4954
+ process6.exitCode = e.code;
4278
4955
  } else {
4279
4956
  throw e;
4280
4957
  }
@@ -4294,7 +4971,7 @@ export {
4294
4971
  conformanceLogPath,
4295
4972
  detectSmokePlatform,
4296
4973
  installLogPath,
4297
- main13 as main,
4974
+ main14 as main,
4298
4975
  routeTargetPaths,
4299
4976
  runConformanceChecks
4300
4977
  };