@event4u/agent-config 13.0.0 → 14.1.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 (123) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +195 -315
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/evals/roadmap.json +8 -0
  5. package/dist/agent-src/commands/fix/ci.md +39 -1
  6. package/dist/agent-src/commands/pr/create.md +65 -4
  7. package/dist/agent-src/commands/roadmap/next.md +28 -5
  8. package/dist/agent-src/commands/work.md +16 -0
  9. package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +47 -0
  10. package/dist/agent-src/contexts/execution/contract-decision-sheet.md +94 -0
  11. package/dist/agent-src/contexts/execution/plan-confidence-gate.md +30 -0
  12. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +21 -8
  13. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +55 -8
  14. package/dist/agent-src/contexts/execution/subagent-response-contract.md +42 -0
  15. package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +29 -0
  16. package/dist/agent-src/rules/command-suggestion-policy.md +33 -0
  17. package/dist/agent-src/rules/design-review-after-ui-write.md +25 -8
  18. package/dist/agent-src/rules/ui-audit-gate.md +25 -8
  19. package/dist/agent-src/scripts/gate_execute.ts +395 -0
  20. package/dist/agent-src/scripts/resume_probe.ts +422 -0
  21. package/dist/agent-src/scripts/roadmap_gates.ts +138 -4
  22. package/dist/agent-src/scripts/update_roadmap_progress.ts +53 -2
  23. package/dist/agent-src/skills/ai-council/SKILL.md +61 -0
  24. package/dist/agent-src/skills/experiment-loop/SKILL.md +116 -0
  25. package/dist/agent-src/skills/experiment-loop/evals/output-schema.yml +27 -0
  26. package/dist/agent-src/skills/experiment-loop/evals/triggers.json +17 -0
  27. package/dist/agent-src/skills/experiment-loop/references/pivot-ladder.md +54 -0
  28. package/dist/agent-src/skills/experiment-loop/references/protocol.md +61 -0
  29. package/dist/agent-src/skills/experiment-loop/references/register-format.md +66 -0
  30. package/dist/agent-src/skills/roadmap-management/SKILL.md +2 -2
  31. package/dist/agent-src/skills/roadmap-writing/SKILL.md +1 -1
  32. package/dist/agent-src/skills/subagent-orchestration/schemas/team-review-status.json +8 -3
  33. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  34. package/dist/agent-src/templates/roadmaps.md +43 -3
  35. package/dist/cli/registry.js +1 -0
  36. package/dist/cli/registry.js.map +1 -1
  37. package/dist/cli-delegate/{chunk-N7FEST6D.js → chunk-7PZ4FSZB.js} +351 -174
  38. package/dist/cli-delegate/{chunk-3B72LSZL.js → chunk-F3YUF7SA.js} +1 -1
  39. package/dist/cli-delegate/cmd_conformance.js +336 -112
  40. package/dist/cli-delegate/cmd_doctor.js +2 -2
  41. package/dist/cli-delegate/cmd_handoff.js +1 -1
  42. package/dist/discovery/deprecation-report.md +1 -1
  43. package/dist/discovery/discovery-manifest.json +40 -18
  44. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  45. package/dist/discovery/discovery-manifest.summary.md +3 -3
  46. package/dist/discovery/dormancy-report.md +1 -1
  47. package/dist/discovery/orphan-report.md +1 -1
  48. package/dist/discovery/packs.json +6 -5
  49. package/dist/discovery/trust-report.md +2 -2
  50. package/dist/discovery/workspaces.json +5 -4
  51. package/dist/hooks/dispatch.js +2128 -1326
  52. package/dist/mcp/registry-manifest.json +3 -3
  53. package/dist/mcp/server.json +2 -2
  54. package/dist/mcp/server.mjs +1764 -899
  55. package/dist/router.json +1 -1
  56. package/dist/scripts/condense.js +1 -1
  57. package/dist/scripts/condense.js.map +1 -1
  58. package/dist/ui/assets/{index-B0aMJnuz.js → index-C1pBRm1f.js} +2 -2
  59. package/dist/ui/assets/index-C1pBRm1f.js.map +1 -0
  60. package/dist/ui/index.html +1 -1
  61. package/package.json +1 -1
  62. package/src/agent-src/scripts/gate_execute.ts +395 -0
  63. package/src/agent-src/scripts/resume_probe.ts +422 -0
  64. package/src/agent-src/scripts/roadmap_gates.ts +138 -4
  65. package/src/agent-src/scripts/update_roadmap_progress.ts +53 -2
  66. package/src/config/ci-local-parity.yml +13 -0
  67. package/src/config/evaluator-budgets.json +4 -4
  68. package/src/config/gate-coverage.yml +111 -5
  69. package/src/config/gate-violation-baselines.json +5 -5
  70. package/src/config/rule-activation-census.json +41 -0
  71. package/src/config/rule-stub-ceilings.json +52 -0
  72. package/src/scripts/_dispatch.bash +4 -0
  73. package/src/scripts/_lib/evaluator_contract.ts +159 -0
  74. package/src/scripts/_lib/gate_ledger.ts +5 -1
  75. package/src/scripts/_lib/gh_transient.ts +80 -0
  76. package/src/scripts/_lib/release_material.ts +16 -5
  77. package/src/scripts/_lib/review_independence.ts +111 -0
  78. package/src/scripts/_lib/session_register.ts +14 -0
  79. package/src/scripts/_lib/skill_catalogue.ts +20 -0
  80. package/src/scripts/_lib/skill_catalogue_series.ts +411 -0
  81. package/src/scripts/_lib/turn_end_refusals.ts +482 -0
  82. package/src/scripts/ai_council/_py_json.ts +96 -0
  83. package/src/scripts/ai_council/cli_call_budget.ts +357 -0
  84. package/src/scripts/ai_council/clients.ts +80 -143
  85. package/src/scripts/ai_council/config.ts +25 -11
  86. package/src/scripts/ai_council/probe_store.ts +196 -0
  87. package/src/scripts/ai_council/qualification.ts +425 -0
  88. package/src/scripts/ai_council/qualification_wiring.ts +243 -0
  89. package/src/scripts/ai_council/quorum_wiring.ts +211 -0
  90. package/src/scripts/ai_team/team_dispatch.ts +40 -6
  91. package/src/scripts/build_archive_index.ts +62 -3
  92. package/src/scripts/capture_skill_catalogue.ts +264 -4
  93. package/src/scripts/check_evaluator_schema.ts +249 -0
  94. package/src/scripts/check_gate_coverage.ts +93 -0
  95. package/src/scripts/check_pr_ci_current.ts +492 -0
  96. package/src/scripts/check_review_schema.ts +195 -0
  97. package/src/scripts/check_rule_activation_census.ts +451 -0
  98. package/src/scripts/check_rule_stub_ceiling.ts +1128 -0
  99. package/src/scripts/condense.ts +1 -1
  100. package/src/scripts/council_cli.ts +141 -191
  101. package/src/scripts/dispatch_r2_reviewer.ts +8 -1
  102. package/src/scripts/git_authorization_hook.ts +186 -1
  103. package/src/scripts/hook_manifest.yaml +72 -5
  104. package/src/scripts/hooks/block_unauthorized_git.ts +62 -6
  105. package/src/scripts/hooks/concern_registry.ts +4 -0
  106. package/src/scripts/hooks/dispatch_hook.ts +43 -1
  107. package/src/scripts/hooks/interruption_ledger_hook.ts +256 -0
  108. package/src/scripts/hooks/ship_diff_volume_hook.ts +180 -0
  109. package/src/scripts/hooks/turn_end_gate_hook.ts +119 -26
  110. package/src/scripts/hooks_doctor.ts +112 -0
  111. package/src/scripts/interruption_report.ts +443 -0
  112. package/src/scripts/lint_evidence_artifacts.ts +359 -0
  113. package/src/scripts/lint_roadmap_blockers.ts +65 -0
  114. package/src/scripts/lint_roadmap_complexity.ts +7 -1
  115. package/src/scripts/release.ts +38 -53
  116. package/src/scripts/rule_activation_census.ts +292 -0
  117. package/src/scripts/schemas/evaluator-output.schema.json +60 -0
  118. package/src/scripts/schemas/review-findings.schema.json +31 -0
  119. package/src/scripts/self_review_gate.ts +6 -0
  120. package/src/scripts/session_register_hook.ts +30 -1
  121. package/src/scripts/sync_pr_branch.ts +271 -0
  122. package/src/scripts/test_council_qualification.ts +213 -0
  123. package/dist/ui/assets/index-B0aMJnuz.js.map +0 -1
@@ -22,7 +22,7 @@ import {
22
22
  frontmatterPaths,
23
23
  proseEqual,
24
24
  splitFrontmatter
25
- } from "./chunk-3B72LSZL.js";
25
+ } from "./chunk-F3YUF7SA.js";
26
26
  import "./chunk-FTAISGDQ.js";
27
27
  import {
28
28
  atomic_write_json,
@@ -33,7 +33,7 @@ import "./chunk-Q26HT4QT.js";
33
33
  import {
34
34
  projectStoreSlug,
35
35
  resolveSessionRole
36
- } from "./chunk-N7FEST6D.js";
36
+ } from "./chunk-7PZ4FSZB.js";
37
37
  import "./chunk-PZWRPRWP.js";
38
38
  import "./chunk-M2DPGFZ4.js";
39
39
  import {
@@ -41,7 +41,9 @@ import {
41
41
  manifest_path,
42
42
  read_manifest
43
43
  } from "./chunk-63WSP6YZ.js";
44
- import "./chunk-GRRPEPRN.js";
44
+ import {
45
+ read_lockfile
46
+ } from "./chunk-GRRPEPRN.js";
45
47
  import "./chunk-NXFWFAYV.js";
46
48
  import {
47
49
  load_agent_settings
@@ -64,7 +66,7 @@ import {
64
66
  var YAML = __toESM(require_dist(), 1);
65
67
  import * as fs15 from "node:fs";
66
68
  import * as os7 from "node:os";
67
- import * as path15 from "node:path";
69
+ import * as path16 from "node:path";
68
70
  import process6 from "node:process";
69
71
  import { spawnSync as spawnSync2 } from "node:child_process";
70
72
  import { fileURLToPath as fileURLToPath15, pathToFileURL as pathToFileURL15 } from "node:url";
@@ -130,7 +132,7 @@ function routeTargetPathsPosix(target) {
130
132
  // src/scripts/report_conformance_funnel.ts
131
133
  import * as fs14 from "node:fs";
132
134
  import * as os6 from "node:os";
133
- import * as path14 from "node:path";
135
+ import * as path15 from "node:path";
134
136
  import process5 from "node:process";
135
137
  import { fileURLToPath as fileURLToPath14, pathToFileURL as pathToFileURL14 } from "node:url";
136
138
 
@@ -138,7 +140,7 @@ import { fileURLToPath as fileURLToPath14, pathToFileURL as pathToFileURL14 } fr
138
140
  import { createHash as createHash4 } from "node:crypto";
139
141
  import fs10 from "node:fs";
140
142
  import os2 from "node:os";
141
- import path10 from "node:path";
143
+ import path11 from "node:path";
142
144
  import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL10 } from "node:url";
143
145
 
144
146
  // src/scripts/_lib/transcript_entry.ts
@@ -506,9 +508,38 @@ import path2 from "node:path";
506
508
  import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
507
509
  var EXIT_ALLOW2 = 0;
508
510
  var STATE_FILE2 = path2.join("agents", "state", "git-authorization.json");
511
+ var STATE_DIR = path2.join("agents", "state", "git-authorization");
512
+ var PENDING_DIR = path2.join("agents", "state", "git-authorization-pending");
513
+ function sessionSlug(session_id) {
514
+ return session_id.replace(/[^A-Za-z0-9._-]/gu, "_").slice(0, 80);
515
+ }
516
+ function ledgerFileFor(session_id) {
517
+ if (!session_id) {
518
+ return STATE_FILE2;
519
+ }
520
+ return path2.join(STATE_DIR, `${sessionSlug(session_id)}.json`);
521
+ }
522
+ function pendingFileFor(session_id) {
523
+ if (!session_id) {
524
+ return PENDING_FILE;
525
+ }
526
+ return path2.join(PENDING_DIR, `${sessionSlug(session_id)}.json`);
527
+ }
528
+ var PENDING_FILE = path2.join("agents", "state", "git-authorization-pending.json");
529
+ var PENDING_MAX_AGE_MS = 10 * 60 * 1e3;
509
530
  function _isObject3(v) {
510
531
  return typeof v === "object" && v !== null && !Array.isArray(v);
511
532
  }
533
+ var ALL_OPS = [
534
+ "commit",
535
+ "push",
536
+ "branch",
537
+ "pr-create",
538
+ "pr-merge",
539
+ "tag",
540
+ "release",
541
+ "publish"
542
+ ];
512
543
  var PHRASES = [
513
544
  { op: "commit", re: /\b(commit(e|et|te|ten)?|committe|einchecken)\b/i },
514
545
  { op: "push", re: /\b(push(e|en|t)?|hochladen|hochschieben|raufschieben)\b/i },
@@ -546,6 +577,18 @@ function isInterrogative(prose) {
546
577
  t
547
578
  );
548
579
  }
580
+ function isAffirmative(prose) {
581
+ const t = prose.trim().replace(/[.!]+$/u, "");
582
+ if (!t || t.length > 24) {
583
+ return false;
584
+ }
585
+ if (isInterrogative(t)) {
586
+ return false;
587
+ }
588
+ return /^(?:option\s*)?\d{1,2}[.)]?$/iu.test(t) || /^(ja|jo|jep|yes|yep|yeah|ok|okay|okey|klar|passt|gut|los|go|go ahead|mach|mach das|mach es|leg los|do it|proceed|bitte)$/iu.test(
589
+ t
590
+ );
591
+ }
549
592
  var PASTED_COMMANDS = [
550
593
  { op: "publish", re: /\bnpm\s+publish\b/i },
551
594
  { op: "tag", re: /\bgit\s+push\s+[^\n]*--tags\b|\bgit\s+tag\s+-a\b/i },
@@ -594,6 +637,40 @@ function classifyAuthorization(prompt) {
594
637
  }
595
638
  return { authorized: [...authorized], evidence };
596
639
  }
640
+ function takePending(consumer_root, session_id, now) {
641
+ const file = path2.join(consumer_root, pendingFileFor(session_id));
642
+ let raw;
643
+ try {
644
+ raw = fs2.readFileSync(file, "utf8");
645
+ } catch {
646
+ return null;
647
+ }
648
+ try {
649
+ fs2.rmSync(file, { force: true });
650
+ } catch {
651
+ }
652
+ try {
653
+ const decoded = JSON.parse(raw);
654
+ if (!_isObject3(decoded)) {
655
+ return null;
656
+ }
657
+ const op = decoded["op"];
658
+ if (typeof op !== "string" || !ALL_OPS.includes(op)) {
659
+ return null;
660
+ }
661
+ const recorded = typeof decoded["session_id"] === "string" ? decoded["session_id"] : "";
662
+ if (session_id && recorded && recorded !== session_id) {
663
+ return null;
664
+ }
665
+ const at = Date.parse(String(decoded["refused_at"] ?? ""));
666
+ if (!Number.isFinite(at) || now - at > PENDING_MAX_AGE_MS) {
667
+ return null;
668
+ }
669
+ return { op, session_id: recorded, refused_at: String(decoded["refused_at"]) };
670
+ } catch {
671
+ return null;
672
+ }
673
+ }
597
674
  function run2(stdin_text, options) {
598
675
  let envelope = {};
599
676
  if (stdin_text.trim()) {
@@ -619,6 +696,12 @@ function run2(stdin_text, options) {
619
696
  return EXIT_ALLOW2;
620
697
  }
621
698
  const { authorized, evidence } = classifyAuthorization(prompt);
699
+ const session = typeof envelope["session_id"] === "string" ? envelope["session_id"] : "";
700
+ const pending = takePending(options.consumer_root, session, Date.now());
701
+ if (pending && !authorized.includes(pending.op) && isAffirmative(prompt)) {
702
+ authorized.push(pending.op);
703
+ evidence[pending.op] = `confirmation of the refused \`${pending.op}\` (refused ${pending.refused_at}): "${prompt.trim().slice(0, 40)}"`;
704
+ }
622
705
  const ledger = {
623
706
  session_id: typeof envelope["session_id"] === "string" ? envelope["session_id"] : "",
624
707
  detected_at: (/* @__PURE__ */ new Date()).toISOString(),
@@ -627,7 +710,7 @@ function run2(stdin_text, options) {
627
710
  prompt_chars: prompt.length
628
711
  };
629
712
  try {
630
- atomic_write_json(path2.join(options.consumer_root, STATE_FILE2), ledger);
713
+ atomic_write_json(path2.join(options.consumer_root, ledgerFileFor(session)), ledger);
631
714
  } catch {
632
715
  }
633
716
  return EXIT_ALLOW2;
@@ -913,17 +996,30 @@ function commandOp(command) {
913
996
  }
914
997
  var LEDGER_MAX_AGE_MS = 30 * 60 * 1e3;
915
998
  function _loadLedger(consumer_root, session_id, now) {
999
+ const candidates = [ledgerFileFor(session_id)];
1000
+ if (!candidates.includes(STATE_FILE2)) {
1001
+ candidates.push(STATE_FILE2);
1002
+ }
1003
+ for (const rel of candidates) {
1004
+ const found = _readLedgerFile(path3.join(consumer_root, rel), session_id, now);
1005
+ if (found !== null) {
1006
+ return found;
1007
+ }
1008
+ }
1009
+ return { authorized: /* @__PURE__ */ new Set(), present: false };
1010
+ }
1011
+ function _readLedgerFile(file, session_id, now) {
916
1012
  try {
917
- const raw = fs3.readFileSync(path3.join(consumer_root, STATE_FILE2), "utf8");
1013
+ const raw = fs3.readFileSync(file, "utf8");
918
1014
  const decoded = JSON.parse(raw);
919
1015
  if (_isObject4(decoded) && Array.isArray(decoded["authorized"])) {
920
1016
  const ledgerSession = typeof decoded["session_id"] === "string" ? decoded["session_id"] : "";
921
1017
  if (session_id && ledgerSession && ledgerSession !== session_id) {
922
- return { authorized: /* @__PURE__ */ new Set(), present: false };
1018
+ return null;
923
1019
  }
924
1020
  const at = Date.parse(String(decoded["detected_at"] ?? ""));
925
1021
  if (Number.isFinite(at) && now - at > LEDGER_MAX_AGE_MS) {
926
- return { authorized: /* @__PURE__ */ new Set(), present: false };
1022
+ return null;
927
1023
  }
928
1024
  return {
929
1025
  authorized: new Set(decoded["authorized"].filter(Boolean)),
@@ -932,7 +1028,7 @@ function _loadLedger(consumer_root, session_id, now) {
932
1028
  }
933
1029
  } catch {
934
1030
  }
935
- return { authorized: /* @__PURE__ */ new Set(), present: false };
1031
+ return null;
936
1032
  }
937
1033
  function decide(command, ledger) {
938
1034
  if (command === null) {
@@ -946,7 +1042,7 @@ function decide(command, ledger) {
946
1042
  if (BLOCK_OPS.has(op)) {
947
1043
  const reason = `Blocked: \`${op}\` with no authorization in this turn's prompt. This operation is irreversible and non-destructive-by-default already declares it never-autonomous. Command: ${shown}. Ask the user, in one numbered-options block, and run it only after they answer this turn.`;
948
1044
  return { exit: EXIT_BLOCK, stdout: "", stderr: `${reason}
949
- ` };
1045
+ `, blockedOp: op };
950
1046
  }
951
1047
  if (WARN_OPS.has(op)) {
952
1048
  const reason = `No \`${op}\` authorization found in this turn's prompt (commit-policy: a one-shot authorization is spent on the operation it named). If the user did authorize it this turn, proceed; otherwise stop and ask. Command: ${shown}`;
@@ -976,6 +1072,16 @@ function run3(stdin_text, options) {
976
1072
  extractCommand(envelope),
977
1073
  _loadLedger(options.consumer_root, session_id, Date.now())
978
1074
  );
1075
+ if (decision.blockedOp) {
1076
+ try {
1077
+ atomic_write_json(path3.join(options.consumer_root, pendingFileFor(session_id)), {
1078
+ op: decision.blockedOp,
1079
+ session_id,
1080
+ refused_at: (/* @__PURE__ */ new Date()).toISOString()
1081
+ });
1082
+ } catch {
1083
+ }
1084
+ }
979
1085
  if (decision.stdout) {
980
1086
  process.stdout.write(decision.stdout);
981
1087
  }
@@ -1342,9 +1448,8 @@ if (isCliEntry) {
1342
1448
  }
1343
1449
 
1344
1450
  // src/scripts/hooks/turn_end_gate_hook.ts
1345
- import * as crypto3 from "node:crypto";
1346
1451
  import * as fs7 from "node:fs";
1347
- import * as path7 from "node:path";
1452
+ import * as path8 from "node:path";
1348
1453
  import { fileURLToPath as fileURLToPath7, pathToFileURL as pathToFileURL7 } from "node:url";
1349
1454
 
1350
1455
  // src/scripts/hooks/end_review_nudge_hook.ts
@@ -1944,12 +2049,12 @@ function resolveDepth(parentRef, open) {
1944
2049
  if (!parent) return { depth: 2, depth_basis: "asserted-parent" };
1945
2050
  return { depth: parent.depth + 1, depth_basis: "observed" };
1946
2051
  }
1947
- function ledgerFileFor(root, ts) {
2052
+ function ledgerFileFor2(root, ts) {
1948
2053
  return path6.join(root, LEDGER_DIR, `${ts.slice(0, 7)}.jsonl`);
1949
2054
  }
1950
2055
  function appendLedgerLine(root, ts, line) {
1951
2056
  if (is_replay_mode()) return;
1952
- const file = ledgerFileFor(root, ts);
2057
+ const file = ledgerFileFor2(root, ts);
1953
2058
  fs6.mkdirSync(path6.dirname(file), { recursive: true });
1954
2059
  fs6.appendFileSync(file, `${JSON.stringify(line)}
1955
2060
  `, "utf8");
@@ -2172,6 +2277,110 @@ function _isCliEntry6() {
2172
2277
  }
2173
2278
  if (_isCliEntry6()) process.exit(main6());
2174
2279
 
2280
+ // src/scripts/_lib/turn_end_refusals.ts
2281
+ import * as crypto3 from "node:crypto";
2282
+ import * as path7 from "node:path";
2283
+ var DETECTOR_IDS = [
2284
+ "promissory",
2285
+ "language",
2286
+ "verification",
2287
+ "completion"
2288
+ ];
2289
+ var REFUSAL_STATE_REL = path7.join("agents", "runtime", "state", "turn-end-gate");
2290
+ function refusalStateDir(workspaceRoot) {
2291
+ return path7.join(workspaceRoot, REFUSAL_STATE_REL);
2292
+ }
2293
+ function deriveSessionKey2(sessionId) {
2294
+ return crypto3.createHash("sha256").update(sessionId).digest("hex").slice(0, 32);
2295
+ }
2296
+ function sessionRefusalFile(workspaceRoot, sessionKey) {
2297
+ return path7.join(refusalStateDir(workspaceRoot), `${sessionKey}.json`);
2298
+ }
2299
+ function emptyCounts() {
2300
+ return { promissory: 0, language: 0, verification: 0, completion: 0 };
2301
+ }
2302
+ function isDetector(v) {
2303
+ return typeof v === "string" && DETECTOR_IDS.includes(v);
2304
+ }
2305
+ function parseRecord(raw) {
2306
+ let decoded;
2307
+ try {
2308
+ decoded = JSON.parse(raw);
2309
+ } catch {
2310
+ return null;
2311
+ }
2312
+ if (typeof decoded !== "object" || decoded === null || Array.isArray(decoded)) return null;
2313
+ const o = decoded;
2314
+ if (typeof o["refused_at"] !== "string") return null;
2315
+ if (typeof o["refused_turn"] !== "number") return null;
2316
+ if (!isDetector(o["detector"])) return null;
2317
+ const rec = {
2318
+ refused_at: o["refused_at"],
2319
+ refused_turn: o["refused_turn"],
2320
+ detector: o["detector"]
2321
+ };
2322
+ if (typeof o["first_refused_at"] === "string") rec.first_refused_at = o["first_refused_at"];
2323
+ if (typeof o["agent_config_version"] === "string") {
2324
+ rec.agent_config_version = o["agent_config_version"];
2325
+ }
2326
+ const counts = o["counts"];
2327
+ if (typeof counts === "object" && counts !== null && !Array.isArray(counts)) {
2328
+ const parsed = {};
2329
+ for (const id of DETECTOR_IDS) {
2330
+ const n = counts[id];
2331
+ if (typeof n === "number" && Number.isFinite(n) && n >= 0) parsed[id] = n;
2332
+ }
2333
+ rec.counts = parsed;
2334
+ }
2335
+ return rec;
2336
+ }
2337
+ function countsOf(rec) {
2338
+ const out = emptyCounts();
2339
+ if (rec.counts === void 0) {
2340
+ out[rec.detector] = 1;
2341
+ return out;
2342
+ }
2343
+ let any = false;
2344
+ for (const id of DETECTOR_IDS) {
2345
+ const n = rec.counts[id];
2346
+ if (typeof n === "number" && n > 0) {
2347
+ out[id] = n;
2348
+ any = true;
2349
+ }
2350
+ }
2351
+ if (!any) out[rec.detector] = 1;
2352
+ return out;
2353
+ }
2354
+ function foldRefusal(prev, input) {
2355
+ const counts = prev === null ? emptyCounts() : countsOf(prev);
2356
+ for (const d of input.detectors) counts[d] += 1;
2357
+ const primary = input.detectors[0] ?? prev?.detector ?? "verification";
2358
+ const rec = {
2359
+ refused_at: input.at,
2360
+ refused_turn: input.turnOrdinal,
2361
+ detector: primary,
2362
+ first_refused_at: prev?.first_refused_at ?? prev?.refused_at ?? input.at,
2363
+ counts
2364
+ };
2365
+ if (input.version !== void 0) rec.agent_config_version = input.version;
2366
+ else if (prev?.agent_config_version !== void 0) {
2367
+ rec.agent_config_version = prev.agent_config_version;
2368
+ }
2369
+ return rec;
2370
+ }
2371
+ function readInstallBoundary() {
2372
+ try {
2373
+ const lock = read_lockfile();
2374
+ if (lock === null) return { version: null, installed_at: null };
2375
+ return {
2376
+ version: lock.agent_config_version ?? null,
2377
+ installed_at: lock.installed_at ?? null
2378
+ };
2379
+ } catch {
2380
+ return { version: null, installed_at: null };
2381
+ }
2382
+ }
2383
+
2175
2384
  // src/scripts/hooks/turn_end_gate_hook.ts
2176
2385
  var EXIT_BLOCK2 = 1;
2177
2386
  var EXIT_ALLOW5 = 0;
@@ -2278,7 +2487,7 @@ function detectPromissory(reply) {
2278
2487
  }
2279
2488
  function readCiSettled(workspaceRoot) {
2280
2489
  try {
2281
- const raw = fs7.readFileSync(path7.join(workspaceRoot, STATE_FILE3), "utf-8");
2490
+ const raw = fs7.readFileSync(path8.join(workspaceRoot, STATE_FILE3), "utf-8");
2282
2491
  const decoded = JSON.parse(raw);
2283
2492
  if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
2284
2493
  const ci = decoded["ci_last"];
@@ -2312,7 +2521,7 @@ function detectCompletionClaim(reply, ci) {
2312
2521
  }
2313
2522
  function readLanguagePin(workspaceRoot) {
2314
2523
  try {
2315
- const raw = fs7.readFileSync(path7.join(workspaceRoot, STATE_FILE), "utf-8");
2524
+ const raw = fs7.readFileSync(path8.join(workspaceRoot, STATE_FILE), "utf-8");
2316
2525
  const decoded = JSON.parse(raw);
2317
2526
  if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
2318
2527
  const lang = decoded["language"];
@@ -2335,7 +2544,7 @@ function detectLanguage(reply, pinned) {
2335
2544
  };
2336
2545
  }
2337
2546
  var _EDIT_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
2338
- var _VERIFY_RE = /\b(test|tests|vitest|jest|pytest|phpunit|pest|tsc|eslint|ruff|mypy|pyright|clippy|typecheck|lint|build|ci|preflight|smoke[-_:a-z]*|check[-_:a-z]*|validate[-_:a-z]*)\b|\b(task|npm|pnpm|yarn|composer|cargo|go|make|php artisan|bun)\s+(run\s+)?\S*(test|check|lint|build|ci|typecheck)/i;
2547
+ var _VERIFY_RE = /\b(test|tests|vitest|jest|pytest|phpunit|pest|tsc|eslint|ruff|mypy|pyright|clippy|phpstan|typecheck|lint[-_:a-z]*|build|ci|preflight|smoke[-_:a-z]*|check[-_:a-z]*|validate[-_:a-z]*)\b|\b(task|npm|pnpm|yarn|composer|cargo|go|make|php artisan|bun)\s+(run\s+)?\S*(test|check|lint|build|ci|typecheck)/i;
2339
2548
  function isVerificationCommand(command) {
2340
2549
  return _VERIFY_RE.test(command);
2341
2550
  }
@@ -2360,14 +2569,8 @@ function detectUnverifiedEdit(toolCalls) {
2360
2569
  reason: "this turn changed a file and then ran no verification command \u2014 no test, type-check, lint or build call follows the last edit (verify-before-complete: a claim without a fresh run is unverified)"
2361
2570
  };
2362
2571
  }
2363
- function stateDir(workspaceRoot) {
2364
- return path7.join(workspaceRoot, "agents", "runtime", "state", "turn-end-gate");
2365
- }
2366
2572
  function sessionStateFile2(workspaceRoot, sessionKey) {
2367
- return path7.join(stateDir(workspaceRoot), `${sessionKey}.json`);
2368
- }
2369
- function deriveSessionKey2(sessionId) {
2370
- return crypto3.createHash("sha256").update(sessionId).digest("hex").slice(0, 32);
2573
+ return sessionRefusalFile(workspaceRoot, sessionKey);
2371
2574
  }
2372
2575
  function alreadyRefusedTurn(workspaceRoot, sessionKey, turnOrdinal) {
2373
2576
  try {
@@ -2380,14 +2583,30 @@ function alreadyRefusedTurn(workspaceRoot, sessionKey, turnOrdinal) {
2380
2583
  }
2381
2584
  return false;
2382
2585
  }
2383
- function markRefusedTurn(workspaceRoot, sessionKey, turnOrdinal, detector) {
2586
+ function markRefusedTurn(workspaceRoot, sessionKey, turnOrdinal, detectors) {
2384
2587
  if (is_replay_mode()) return;
2588
+ const file = sessionStateFile2(workspaceRoot, sessionKey);
2589
+ let prev = null;
2385
2590
  try {
2386
- atomic_write_json(sessionStateFile2(workspaceRoot, sessionKey), {
2387
- refused_at: (/* @__PURE__ */ new Date()).toISOString(),
2388
- refused_turn: turnOrdinal,
2389
- detector
2390
- });
2591
+ prev = parseRecord(fs7.readFileSync(file, "utf-8"));
2592
+ } catch {
2593
+ }
2594
+ let version;
2595
+ try {
2596
+ version = readInstallBoundary().version ?? void 0;
2597
+ } catch {
2598
+ version = void 0;
2599
+ }
2600
+ try {
2601
+ atomic_write_json(
2602
+ file,
2603
+ foldRefusal(prev, {
2604
+ detectors,
2605
+ turnOrdinal,
2606
+ at: (/* @__PURE__ */ new Date()).toISOString(),
2607
+ version
2608
+ })
2609
+ );
2391
2610
  } catch {
2392
2611
  }
2393
2612
  }
@@ -2521,7 +2740,12 @@ function main7() {
2521
2740
  if (f) findings.push(f);
2522
2741
  }
2523
2742
  if (findings.length === 0) return EXIT_ALLOW5;
2524
- markRefusedTurn(workspaceRoot, sessionKey, turnOrdinal, findings[0].detector);
2743
+ markRefusedTurn(
2744
+ workspaceRoot,
2745
+ sessionKey,
2746
+ turnOrdinal,
2747
+ findings.map((f) => f.detector)
2748
+ );
2525
2749
  const lines = findings.map(
2526
2750
  (f) => ` \xB7 ${f.detector}: ${f.reason}
2527
2751
  evidence: ${JSON.stringify(f.evidence)}`
@@ -2542,13 +2766,13 @@ function _isCliEntry7() {
2542
2766
  if (process.argv[1] === void 0) {
2543
2767
  return false;
2544
2768
  }
2545
- const argvUrl = pathToFileURL7(path7.resolve(process.argv[1])).href;
2769
+ const argvUrl = pathToFileURL7(path8.resolve(process.argv[1])).href;
2546
2770
  if (import.meta.url === argvUrl) {
2547
2771
  return true;
2548
2772
  }
2549
2773
  try {
2550
2774
  const here = fs7.realpathSync(fileURLToPath7(import.meta.url));
2551
- const argv = fs7.realpathSync(path7.resolve(process.argv[1]));
2775
+ const argv = fs7.realpathSync(path8.resolve(process.argv[1]));
2552
2776
  return here === argv;
2553
2777
  } catch {
2554
2778
  return false;
@@ -2561,11 +2785,11 @@ if (_isCliEntry7()) {
2561
2785
  // src/scripts/hooks/evidence_independence.ts
2562
2786
  import crypto4 from "node:crypto";
2563
2787
  import fs8 from "node:fs";
2564
- import path8 from "node:path";
2788
+ import path9 from "node:path";
2565
2789
  import { fileURLToPath as fileURLToPath8, pathToFileURL as pathToFileURL8 } from "node:url";
2566
2790
  var EXIT_ALLOW6 = 0;
2567
2791
  var EXIT_BLOCK3 = 1;
2568
- var STATE_FILE4 = path8.join("agents", "state", "evidence-dispatch.json");
2792
+ var STATE_FILE4 = path9.join("agents", "state", "evidence-dispatch.json");
2569
2793
  function _isObject6(v) {
2570
2794
  return typeof v === "object" && v !== null && !Array.isArray(v);
2571
2795
  }
@@ -2634,7 +2858,7 @@ function extractDispatch(envelope) {
2634
2858
  function _ledgerStamp(consumer_root) {
2635
2859
  try {
2636
2860
  const raw = fs8.readFileSync(
2637
- path8.join(consumer_root, "agents", "state", "git-authorization.json"),
2861
+ path9.join(consumer_root, "agents", "state", "git-authorization.json"),
2638
2862
  "utf8"
2639
2863
  );
2640
2864
  const d = JSON.parse(raw);
@@ -2703,7 +2927,7 @@ function run5(stdin_text, options) {
2703
2927
  return EXIT_ALLOW6;
2704
2928
  }
2705
2929
  }
2706
- const target = path8.join(options.consumer_root, STATE_FILE4);
2930
+ const target = path9.join(options.consumer_root, STATE_FILE4);
2707
2931
  const state = _load(target);
2708
2932
  const session_id = typeof envelope["session_id"] === "string" ? envelope["session_id"] : "";
2709
2933
  const turnMarker = `${session_id}:${_ledgerStamp(options.consumer_root)}`;
@@ -2754,13 +2978,13 @@ function _isCliEntry8() {
2754
2978
  if (process.argv[1] === void 0) {
2755
2979
  return false;
2756
2980
  }
2757
- const argvUrl = pathToFileURL8(path8.resolve(process.argv[1])).href;
2981
+ const argvUrl = pathToFileURL8(path9.resolve(process.argv[1])).href;
2758
2982
  if (import.meta.url === argvUrl) {
2759
2983
  return true;
2760
2984
  }
2761
2985
  try {
2762
2986
  const here = fs8.realpathSync(fileURLToPath8(import.meta.url));
2763
- const argv = fs8.realpathSync(path8.resolve(process.argv[1]));
2987
+ const argv = fs8.realpathSync(path9.resolve(process.argv[1]));
2764
2988
  return here === argv;
2765
2989
  } catch {
2766
2990
  return false;
@@ -2772,7 +2996,7 @@ if (_isCliEntry8()) {
2772
2996
 
2773
2997
  // src/scripts/hooks/delegation_nudge_hook.ts
2774
2998
  import fs9 from "node:fs";
2775
- import path9 from "node:path";
2999
+ import path10 from "node:path";
2776
3000
  import { fileURLToPath as fileURLToPath9, pathToFileURL as pathToFileURL9 } from "node:url";
2777
3001
 
2778
3002
  // src/scripts/_lib/host_capability.ts
@@ -3307,13 +3531,13 @@ function _isCliEntry9() {
3307
3531
  if (process.argv[1] === void 0) {
3308
3532
  return false;
3309
3533
  }
3310
- const argvUrl = pathToFileURL9(path9.resolve(process.argv[1])).href;
3534
+ const argvUrl = pathToFileURL9(path10.resolve(process.argv[1])).href;
3311
3535
  if (import.meta.url === argvUrl) {
3312
3536
  return true;
3313
3537
  }
3314
3538
  try {
3315
3539
  const here = fs9.realpathSync(fileURLToPath9(import.meta.url));
3316
- const argv = fs9.realpathSync(path9.resolve(process.argv[1]));
3540
+ const argv = fs9.realpathSync(path10.resolve(process.argv[1]));
3317
3541
  return here === argv;
3318
3542
  } catch {
3319
3543
  return false;
@@ -3324,7 +3548,7 @@ if (_isCliEntry9()) {
3324
3548
  }
3325
3549
 
3326
3550
  // src/scripts/conformance_scan.ts
3327
- var REPO_ROOT = path10.resolve(path10.dirname(fileURLToPath10(import.meta.url)), "..", "..");
3551
+ var REPO_ROOT = path11.resolve(path11.dirname(fileURLToPath10(import.meta.url)), "..", "..");
3328
3552
  var OBSERVED_BAND = { low: 9.1, high: 39.2 };
3329
3553
  var BAND_MIN_TURNS = 1978;
3330
3554
  var CARRIER_CHANGES = [
@@ -3674,7 +3898,7 @@ function scanSession(sessionId, lines) {
3674
3898
  closeWindow();
3675
3899
  return report;
3676
3900
  }
3677
- var DEFAULT_RATE_SERIES = path10.join(
3901
+ var DEFAULT_RATE_SERIES = path11.join(
3678
3902
  REPO_ROOT,
3679
3903
  "agents",
3680
3904
  "runtime",
@@ -3683,7 +3907,7 @@ var DEFAULT_RATE_SERIES = path10.join(
3683
3907
  );
3684
3908
  function defaultStore(projectDir) {
3685
3909
  const slug = projectStoreSlug(projectDir);
3686
- return path10.join(process.env["HOME"] ?? "", ".claude", "projects", slug);
3910
+ return path11.join(process.env["HOME"] ?? "", ".claude", "projects", slug);
3687
3911
  }
3688
3912
  function _tokens(chars) {
3689
3913
  return Math.round(chars / 4);
@@ -3708,13 +3932,13 @@ function measureDelivered(projectRulesDir, globalRulesDir) {
3708
3932
  };
3709
3933
  }
3710
3934
  function storeKey(store) {
3711
- return createHash4("sha256").update(path10.resolve(store)).digest("hex").slice(0, 12);
3935
+ return createHash4("sha256").update(path11.resolve(store)).digest("hex").slice(0, 12);
3712
3936
  }
3713
3937
  function scanStore(store, limit) {
3714
- const files = fs10.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ f, m: fs10.statSync(path10.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.f);
3938
+ const files = fs10.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ f, m: fs10.statSync(path11.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.f);
3715
3939
  const per_session = [];
3716
3940
  for (const f of files) {
3717
- const lines = fs10.readFileSync(path10.join(store, f), "utf8").split("\n");
3941
+ const lines = fs10.readFileSync(path11.join(store, f), "utf8").split("\n");
3718
3942
  const r = scanSession(f.replace(/\.jsonl$/, "").slice(0, 8), lines);
3719
3943
  if (r.assistant_turns > 0) {
3720
3944
  per_session.push(r);
@@ -3742,10 +3966,10 @@ function scanStore(store, limit) {
3742
3966
  const task_completeness_rate_pct = completeness_windows === 0 ? 0 : Number((100 * task_completeness / completeness_windows).toFixed(1));
3743
3967
  const era = spansCarrierChange(per_session.map((s) => s.first_at));
3744
3968
  const delivered = measureDelivered(
3745
- path10.join(REPO_ROOT, ".claude", "rules"),
3746
- path10.join(process.env["HOME"] ?? os2.homedir(), ".claude", "rules")
3969
+ path11.join(REPO_ROOT, ".claude", "rules"),
3970
+ path11.join(process.env["HOME"] ?? os2.homedir(), ".claude", "rules")
3747
3971
  );
3748
- const ownStore = path10.resolve(store) === path10.resolve(defaultStore(REPO_ROOT));
3972
+ const ownStore = path11.resolve(store) === path11.resolve(defaultStore(REPO_ROOT));
3749
3973
  return {
3750
3974
  scanned_at: (/* @__PURE__ */ new Date()).toISOString(),
3751
3975
  store,
@@ -3775,7 +3999,7 @@ function scanStore(store, limit) {
3775
3999
  };
3776
4000
  }
3777
4001
  function recordRate(file, scanned_at, rate) {
3778
- fs10.mkdirSync(path10.dirname(file), { recursive: true });
4002
+ fs10.mkdirSync(path11.dirname(file), { recursive: true });
3779
4003
  fs10.appendFileSync(file, `${JSON.stringify({ measured_at: scanned_at, ...rate })}
3780
4004
  `, "utf8");
3781
4005
  }
@@ -3954,13 +4178,13 @@ function _isCliEntry10() {
3954
4178
  if (process.argv[1] === void 0) {
3955
4179
  return false;
3956
4180
  }
3957
- const argvUrl = pathToFileURL10(path10.resolve(process.argv[1])).href;
4181
+ const argvUrl = pathToFileURL10(path11.resolve(process.argv[1])).href;
3958
4182
  if (import.meta.url === argvUrl) {
3959
4183
  return true;
3960
4184
  }
3961
4185
  try {
3962
4186
  const here = fs10.realpathSync(fileURLToPath10(import.meta.url));
3963
- const argv = fs10.realpathSync(path10.resolve(process.argv[1]));
4187
+ const argv = fs10.realpathSync(path11.resolve(process.argv[1]));
3964
4188
  return here === argv;
3965
4189
  } catch {
3966
4190
  return false;
@@ -3973,14 +4197,14 @@ if (_isCliEntry10()) {
3973
4197
  // src/scripts/report_carrier_divergence.ts
3974
4198
  import * as fs11 from "node:fs";
3975
4199
  import * as os3 from "node:os";
3976
- import * as path11 from "node:path";
4200
+ import * as path12 from "node:path";
3977
4201
  import process3 from "node:process";
3978
4202
  import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL11 } from "node:url";
3979
4203
  var _HERE = fileURLToPath11(import.meta.url);
3980
- var REPO_ROOT2 = path11.resolve(path11.dirname(_HERE), "..", "..");
3981
- var PROJECT_RULES = path11.join(".claude", "rules");
3982
- var PROJECTION_SOURCE = path11.join("dist", "agent-src", "rules");
3983
- var GLOBAL_RULES = path11.join(".claude", "rules");
4204
+ var REPO_ROOT2 = path12.resolve(path12.dirname(_HERE), "..", "..");
4205
+ var PROJECT_RULES = path12.join(".claude", "rules");
4206
+ var PROJECTION_SOURCE = path12.join("dist", "agent-src", "rules");
4207
+ var GLOBAL_RULES = path12.join(".claude", "rules");
3984
4208
  function _listRules(dir) {
3985
4209
  try {
3986
4210
  return fs11.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
@@ -4026,7 +4250,7 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
4026
4250
  }
4027
4251
  if (!inP && inG) {
4028
4252
  out.globalOnly.push(rule);
4029
- if (sourceDir !== void 0 && _ruleType(path11.join(sourceDir, rule)) === "manual") {
4253
+ if (sourceDir !== void 0 && _ruleType(path12.join(sourceDir, rule)) === "manual") {
4030
4254
  out.manualOnlyGlobal.push(rule);
4031
4255
  }
4032
4256
  continue;
@@ -4036,8 +4260,8 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
4036
4260
  let projectCopy;
4037
4261
  let globalCopy;
4038
4262
  try {
4039
- projectCopy = fs11.readFileSync(path11.join(projectDir, rule));
4040
- globalCopy = fs11.readFileSync(path11.join(globalDir, rule));
4263
+ projectCopy = fs11.readFileSync(path12.join(projectDir, rule));
4264
+ globalCopy = fs11.readFileSync(path12.join(globalDir, rule));
4041
4265
  verdict = comparePair(projectCopy, globalCopy);
4042
4266
  } catch {
4043
4267
  out.shared -= 1;
@@ -4184,9 +4408,9 @@ function render2(d) {
4184
4408
  }
4185
4409
  function main11(argv) {
4186
4410
  const args = argv ?? process3.argv.slice(2);
4187
- let projectDir = path11.join(REPO_ROOT2, PROJECT_RULES);
4188
- let globalDir = path11.join(os3.homedir(), GLOBAL_RULES);
4189
- let sourceDir = path11.join(REPO_ROOT2, PROJECTION_SOURCE);
4411
+ let projectDir = path12.join(REPO_ROOT2, PROJECT_RULES);
4412
+ let globalDir = path12.join(os3.homedir(), GLOBAL_RULES);
4413
+ let sourceDir = path12.join(REPO_ROOT2, PROJECTION_SOURCE);
4190
4414
  const value = (i) => {
4191
4415
  const v = args[i + 1];
4192
4416
  return v === void 0 || v.startsWith("-") ? null : v;
@@ -4200,7 +4424,7 @@ function main11(argv) {
4200
4424
  `);
4201
4425
  return 1;
4202
4426
  }
4203
- const resolved = path11.resolve(v);
4427
+ const resolved = path12.resolve(v);
4204
4428
  if (a === "--project") projectDir = resolved;
4205
4429
  else if (a === "--global") globalDir = resolved;
4206
4430
  else sourceDir = resolved;
@@ -4222,9 +4446,9 @@ function main11(argv) {
4222
4446
  }
4223
4447
  function _isCliEntry11() {
4224
4448
  if (process3.argv[1] === void 0) return false;
4225
- if (import.meta.url === pathToFileURL11(path11.resolve(process3.argv[1])).href) return true;
4449
+ if (import.meta.url === pathToFileURL11(path12.resolve(process3.argv[1])).href) return true;
4226
4450
  try {
4227
- return fs11.realpathSync(_HERE) === fs11.realpathSync(path11.resolve(process3.argv[1]));
4451
+ return fs11.realpathSync(_HERE) === fs11.realpathSync(path12.resolve(process3.argv[1]));
4228
4452
  } catch {
4229
4453
  return false;
4230
4454
  }
@@ -4236,10 +4460,10 @@ if (_isCliEntry11()) {
4236
4460
  // src/scripts/report_skill_activation.ts
4237
4461
  import * as fs12 from "node:fs";
4238
4462
  import * as os4 from "node:os";
4239
- import * as path12 from "node:path";
4463
+ import * as path13 from "node:path";
4240
4464
  import { fileURLToPath as fileURLToPath12, pathToFileURL as pathToFileURL12 } from "node:url";
4241
4465
  var _HERE2 = fileURLToPath12(import.meta.url);
4242
- var REPO_ROOT3 = path12.resolve(path12.dirname(_HERE2), "..", "..");
4466
+ var REPO_ROOT3 = path13.resolve(path13.dirname(_HERE2), "..", "..");
4243
4467
  var SKILLS_ROOT = "src/skills";
4244
4468
  var TRIGGER_KEYS = ["triggers:", "trigger_description:", "file_pattern:", "path_prefix:"];
4245
4469
  var DETERMINISTIC_RE = /^\s*(?:[-*]\s*)?(?:\*\*)?(MUST|NEVER|ALWAYS)\b/m;
@@ -4252,7 +4476,7 @@ function censusSkills(root) {
4252
4476
  if (!entry.isDirectory()) {
4253
4477
  continue;
4254
4478
  }
4255
- const file = path12.join(root, entry.name, "SKILL.md");
4479
+ const file = path13.join(root, entry.name, "SKILL.md");
4256
4480
  if (!fs12.existsSync(file)) {
4257
4481
  continue;
4258
4482
  }
@@ -4271,14 +4495,14 @@ function censusSkills(root) {
4271
4495
  return out;
4272
4496
  }
4273
4497
  function defaultStore2(cwd) {
4274
- return path12.join(os4.homedir(), ".claude", "projects", projectStoreSlug(cwd));
4498
+ return path13.join(os4.homedir(), ".claude", "projects", projectStoreSlug(cwd));
4275
4499
  }
4276
4500
  function measureUsage(store, limit) {
4277
4501
  const rep = { store, sessions: 0, assistantTurns: 0, invocations: 0, bySkill: {} };
4278
4502
  if (!fs12.existsSync(store)) {
4279
4503
  return rep;
4280
4504
  }
4281
- const files = fs12.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => path12.join(store, f)).sort((a, b) => fs12.statSync(b).mtimeMs - fs12.statSync(a).mtimeMs).slice(0, limit);
4505
+ const files = fs12.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => path13.join(store, f)).sort((a, b) => fs12.statSync(b).mtimeMs - fs12.statSync(a).mtimeMs).slice(0, limit);
4282
4506
  rep.sessions = files.length;
4283
4507
  for (const file of files) {
4284
4508
  for (const line of fs12.readFileSync(file, "utf8").split("\n")) {
@@ -4344,7 +4568,7 @@ function render3(census, usage) {
4344
4568
  }
4345
4569
  totalInv += u.invocations;
4346
4570
  lines.push(
4347
- ` ${path12.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)}`
4571
+ ` ${path13.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)}`
4348
4572
  );
4349
4573
  }
4350
4574
  lines.push("");
@@ -4392,24 +4616,24 @@ function main12(argv) {
4392
4616
  if (stores.length === 0) {
4393
4617
  stores.push(defaultStore2(REPO_ROOT3));
4394
4618
  }
4395
- const census = censusSkills(path12.join(REPO_ROOT3, SKILLS_ROOT));
4619
+ const census = censusSkills(path13.join(REPO_ROOT3, SKILLS_ROOT));
4396
4620
  const usage = stores.map((s) => measureUsage(s, limit));
4397
4621
  process.stdout.write(`${render3(census, usage)}
4398
4622
  `);
4399
4623
  return 0;
4400
4624
  }
4401
- if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL12(path12.resolve(process.argv[1])).href) {
4625
+ if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL12(path13.resolve(process.argv[1])).href) {
4402
4626
  process.exit(main12(process.argv.slice(2)));
4403
4627
  }
4404
4628
 
4405
4629
  // src/scripts/report_skill_obligation_violations.ts
4406
4630
  import * as fs13 from "node:fs";
4407
4631
  import * as os5 from "node:os";
4408
- import * as path13 from "node:path";
4632
+ import * as path14 from "node:path";
4409
4633
  import process4 from "node:process";
4410
4634
  import { fileURLToPath as fileURLToPath13, pathToFileURL as pathToFileURL13 } from "node:url";
4411
4635
  var _HERE3 = fileURLToPath13(import.meta.url);
4412
- var REPO_ROOT4 = path13.resolve(path13.dirname(_HERE3), "..", "..");
4636
+ var REPO_ROOT4 = path14.resolve(path14.dirname(_HERE3), "..", "..");
4413
4637
  var OBLIGATION_LINE_RE = new RegExp(`${DETERMINISTIC_RE.source}.*`, "gm");
4414
4638
  var PATH_RE = /`([A-Za-z0-9_./-]*\/[A-Za-z0-9_.-]+\.[a-z]{2,6})`/g;
4415
4639
  var CMD_RE = /`([a-z][a-z0-9-]*(?: [a-z][a-z0-9:._-]*){1,3})`/g;
@@ -4447,7 +4671,7 @@ function _artefacts(line) {
4447
4671
  return out;
4448
4672
  }
4449
4673
  function extractObligations(repoRoot) {
4450
- const skillsRoot = path13.join(repoRoot, SKILLS_ROOT);
4674
+ const skillsRoot = path14.join(repoRoot, SKILLS_ROOT);
4451
4675
  const census = censusSkills(skillsRoot);
4452
4676
  const out = {
4453
4677
  skills: census.withDeterministicObligation,
@@ -4461,7 +4685,7 @@ function extractObligations(repoRoot) {
4461
4685
  for (const skill of census.withDeterministicObligation) {
4462
4686
  let text;
4463
4687
  try {
4464
- text = fs13.readFileSync(path13.join(skillsRoot, skill, "SKILL.md"), "utf-8");
4688
+ text = fs13.readFileSync(path14.join(skillsRoot, skill, "SKILL.md"), "utf-8");
4465
4689
  } catch {
4466
4690
  continue;
4467
4691
  }
@@ -4577,7 +4801,7 @@ function scanSessionForViolations(session, lines, forbidden, parsed) {
4577
4801
  return flags;
4578
4802
  }
4579
4803
  function defaultStore3(cwd) {
4580
- return path13.join(os5.homedir(), ".claude", "projects", projectStoreSlug(cwd));
4804
+ return path14.join(os5.homedir(), ".claude", "projects", projectStoreSlug(cwd));
4581
4805
  }
4582
4806
  function scanStore2(repoRoot, store, limit) {
4583
4807
  const census = extractObligations(repoRoot);
@@ -4590,14 +4814,14 @@ function scanStore2(repoRoot, store, limit) {
4590
4814
  };
4591
4815
  let files;
4592
4816
  try {
4593
- files = fs13.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ p: path13.join(store, f), m: fs13.statSync(path13.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.p);
4817
+ files = fs13.readdirSync(store).filter((f) => f.endsWith(".jsonl")).map((f) => ({ p: path14.join(store, f), m: fs13.statSync(path14.join(store, f)).mtimeMs })).sort((a, b) => b.m - a.m).slice(0, limit).map((x) => x.p);
4594
4818
  } catch {
4595
4819
  return report;
4596
4820
  }
4597
4821
  report.sessions = files.length;
4598
4822
  for (const file of files) {
4599
4823
  const lines = fs13.readFileSync(file, "utf-8").split("\n");
4600
- const id = path13.basename(file).replace(/\.jsonl$/, "").slice(0, 8);
4824
+ const id = path14.basename(file).replace(/\.jsonl$/, "").slice(0, 8);
4601
4825
  const entries = _parseSession(lines);
4602
4826
  if (loadedSkillsFrom(entries).size > 0) report.sessionsWithASkill += 1;
4603
4827
  report.flags.push(...scanSessionForViolations(id, lines, census.forbidden, entries));
@@ -4722,9 +4946,9 @@ function main13(argv) {
4722
4946
  }
4723
4947
  function _isCliEntry12() {
4724
4948
  if (process4.argv[1] === void 0) return false;
4725
- if (import.meta.url === pathToFileURL13(path13.resolve(process4.argv[1])).href) return true;
4949
+ if (import.meta.url === pathToFileURL13(path14.resolve(process4.argv[1])).href) return true;
4726
4950
  try {
4727
- return fs13.realpathSync(_HERE3) === fs13.realpathSync(path13.resolve(process4.argv[1]));
4951
+ return fs13.realpathSync(_HERE3) === fs13.realpathSync(path14.resolve(process4.argv[1]));
4728
4952
  } catch {
4729
4953
  return false;
4730
4954
  }
@@ -4735,18 +4959,18 @@ if (_isCliEntry12()) {
4735
4959
 
4736
4960
  // src/scripts/report_conformance_funnel.ts
4737
4961
  var _HERE4 = fileURLToPath14(import.meta.url);
4738
- var REPO_ROOT5 = path14.resolve(path14.dirname(_HERE4), "..", "..");
4962
+ var REPO_ROOT5 = path15.resolve(path15.dirname(_HERE4), "..", "..");
4739
4963
  function buildFunnel(opts = {}) {
4740
4964
  const repoRoot = opts.repoRoot ?? REPO_ROOT5;
4741
- const projectRulesDir = opts.projectRulesDir ?? path14.join(repoRoot, PROJECT_RULES);
4742
- const globalRulesDir = opts.globalRulesDir ?? path14.join(os6.homedir(), GLOBAL_RULES);
4743
- const sourceDir = opts.sourceDir ?? path14.join(repoRoot, PROJECTION_SOURCE);
4965
+ const projectRulesDir = opts.projectRulesDir ?? path15.join(repoRoot, PROJECT_RULES);
4966
+ const globalRulesDir = opts.globalRulesDir ?? path15.join(os6.homedir(), GLOBAL_RULES);
4967
+ const sourceDir = opts.sourceDir ?? path15.join(repoRoot, PROJECTION_SOURCE);
4744
4968
  const store = opts.store ?? defaultStore(repoRoot);
4745
4969
  const limit = opts.limit ?? 30;
4746
4970
  return {
4747
4971
  delivered: measureDelivered(projectRulesDir, globalRulesDir),
4748
4972
  divergence: compareCarriers(projectRulesDir, globalRulesDir, sourceDir),
4749
- skills: censusSkills(path14.join(repoRoot, SKILLS_ROOT)),
4973
+ skills: censusSkills(path15.join(repoRoot, SKILLS_ROOT)),
4750
4974
  usage: measureUsage(store, limit),
4751
4975
  storePresent: fs14.existsSync(store),
4752
4976
  sk2: scanStore2(repoRoot, store, limit)
@@ -4889,7 +5113,7 @@ function main14(argv) {
4889
5113
  `);
4890
5114
  return 1;
4891
5115
  }
4892
- const resolved = path14.resolve(v);
5116
+ const resolved = path15.resolve(v);
4893
5117
  if (a === "--store") opts.store = resolved;
4894
5118
  else if (a === "--project") opts.projectRulesDir = resolved;
4895
5119
  else if (a === "--global") opts.globalRulesDir = resolved;
@@ -4921,9 +5145,9 @@ function main14(argv) {
4921
5145
  }
4922
5146
  function _isCliEntry13() {
4923
5147
  if (process5.argv[1] === void 0) return false;
4924
- if (import.meta.url === pathToFileURL14(path14.resolve(process5.argv[1])).href) return true;
5148
+ if (import.meta.url === pathToFileURL14(path15.resolve(process5.argv[1])).href) return true;
4925
5149
  try {
4926
- return fs14.realpathSync(_HERE4) === fs14.realpathSync(path14.resolve(process5.argv[1]));
5150
+ return fs14.realpathSync(_HERE4) === fs14.realpathSync(path15.resolve(process5.argv[1]));
4927
5151
  } catch {
4928
5152
  return false;
4929
5153
  }
@@ -4956,14 +5180,14 @@ function conformanceLogPath() {
4956
5180
  if (override && override.trim().length > 0) {
4957
5181
  return override;
4958
5182
  }
4959
- return path15.join(os7.homedir(), ".event4u", "agent-config", "conformance-log.jsonl");
5183
+ return path16.join(os7.homedir(), ".event4u", "agent-config", "conformance-log.jsonl");
4960
5184
  }
4961
5185
  function installLogPath() {
4962
5186
  const override = process6.env["AGENT_CONFIG_INSTALL_LOG"];
4963
5187
  if (override && override.trim().length > 0) {
4964
5188
  return override;
4965
5189
  }
4966
- return path15.join(os7.homedir(), ".event4u", "agent-config", "install-log.jsonl");
5190
+ return path16.join(os7.homedir(), ".event4u", "agent-config", "install-log.jsonl");
4967
5191
  }
4968
5192
  function _check_txlog_clean(logPath = installLogPath()) {
4969
5193
  if (!fs15.existsSync(logPath)) {
@@ -5000,10 +5224,10 @@ function _check_txlog_clean(logPath = installLogPath()) {
5000
5224
  };
5001
5225
  }
5002
5226
  function routeTargetPaths(target) {
5003
- return routeTargetPathsPosix(target).map((rel) => path15.join(...rel.split("/")));
5227
+ return routeTargetPathsPosix(target).map((rel) => path16.join(...rel.split("/")));
5004
5228
  }
5005
5229
  function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
5006
- const routerPath = path15.join(packageRoot, "dist", "router.json");
5230
+ const routerPath = path16.join(packageRoot, "dist", "router.json");
5007
5231
  if (!fs15.existsSync(routerPath)) {
5008
5232
  return {
5009
5233
  id: "router-pointers",
@@ -5023,13 +5247,13 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
5023
5247
  remedy: "reinstall the package \u2014 dist/router.json is corrupt"
5024
5248
  };
5025
5249
  }
5026
- const rulesDir = path15.join(packageRoot, "dist", "agent-src", "rules");
5250
+ const rulesDir = path16.join(packageRoot, "dist", "agent-src", "rules");
5027
5251
  const broken = [];
5028
5252
  let ids = 0;
5029
5253
  let targets = 0;
5030
5254
  for (const kernelId of router["kernel"] ?? []) {
5031
5255
  ids += 1;
5032
- if (!fs15.existsSync(path15.join(rulesDir, `${kernelId}.md`))) {
5256
+ if (!fs15.existsSync(path16.join(rulesDir, `${kernelId}.md`))) {
5033
5257
  broken.push(`kernel:${kernelId} \u2192 rules/${kernelId}.md missing`);
5034
5258
  }
5035
5259
  }
@@ -5037,7 +5261,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
5037
5261
  for (const entry of router[tier] ?? []) {
5038
5262
  const ruleId = String(entry["id"] ?? "");
5039
5263
  ids += 1;
5040
- if (!fs15.existsSync(path15.join(rulesDir, `${ruleId}.md`))) {
5264
+ if (!fs15.existsSync(path16.join(rulesDir, `${ruleId}.md`))) {
5041
5265
  broken.push(`${tier}:${ruleId} \u2192 rules/${ruleId}.md missing`);
5042
5266
  }
5043
5267
  for (const target of entry["routes_to"] ?? []) {
@@ -5047,7 +5271,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
5047
5271
  broken.push(`${ruleId} \u2192 unparseable routes_to ${JSON.stringify(target)}`);
5048
5272
  continue;
5049
5273
  }
5050
- if (!candidates.some((rel) => fs15.existsSync(path15.join(packageRoot, rel)))) {
5274
+ if (!candidates.some((rel) => fs15.existsSync(path16.join(packageRoot, rel)))) {
5051
5275
  broken.push(`${ruleId} \u2192 ${target} (${candidates[0]} missing)`);
5052
5276
  }
5053
5277
  }
@@ -5079,8 +5303,8 @@ function detectSmokePlatform(projectRoot) {
5079
5303
  return "claude";
5080
5304
  }
5081
5305
  function dispatcherRunner(packageRoot) {
5082
- const localTsx = path15.join(packageRoot, "node_modules", ".bin", "tsx");
5083
- const script = path15.join(packageRoot, "src", "scripts", "hooks", "dispatch_hook.ts");
5306
+ const localTsx = path16.join(packageRoot, "node_modules", ".bin", "tsx");
5307
+ const script = path16.join(packageRoot, "src", "scripts", "hooks", "dispatch_hook.ts");
5084
5308
  if (fs15.existsSync(localTsx)) {
5085
5309
  return [localTsx, script];
5086
5310
  }
@@ -5131,7 +5355,7 @@ function _check_hook_dispatcher(projectRoot, packageRoot = PACKAGE_ROOT, opts =
5131
5355
  };
5132
5356
  }
5133
5357
  function readSettingsMode(projectRoot) {
5134
- const settingsPath = path15.join(projectRoot, ".agent-settings.yml");
5358
+ const settingsPath = path16.join(projectRoot, ".agent-settings.yml");
5135
5359
  if (!fs15.existsSync(settingsPath)) {
5136
5360
  return "eager-all";
5137
5361
  }
@@ -5147,7 +5371,7 @@ function readSettingsMode(projectRoot) {
5147
5371
  function kernelIdsFromRouter(packageRoot) {
5148
5372
  try {
5149
5373
  const router = JSON.parse(
5150
- fs15.readFileSync(path15.join(packageRoot, "dist", "router.json"), "utf8")
5374
+ fs15.readFileSync(path16.join(packageRoot, "dist", "router.json"), "utf8")
5151
5375
  );
5152
5376
  return new Set((router["kernel"] ?? []).map(String));
5153
5377
  } catch {
@@ -5164,7 +5388,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
5164
5388
  remedy: "set lean_projection.mode to 'eager-all' or 'thin' in .agent-settings.yml"
5165
5389
  };
5166
5390
  }
5167
- const rulesDir = projectedRulesDir ?? path15.join(projectRoot, ".augment", "rules");
5391
+ const rulesDir = projectedRulesDir ?? path16.join(projectRoot, ".augment", "rules");
5168
5392
  if (!fs15.existsSync(rulesDir)) {
5169
5393
  return {
5170
5394
  id: "lean-projection",
@@ -5188,7 +5412,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
5188
5412
  for (const f of nonKernel) {
5189
5413
  let text = "";
5190
5414
  try {
5191
- text = fs15.readFileSync(path15.join(rulesDir, f), "utf8");
5415
+ text = fs15.readFileSync(path16.join(rulesDir, f), "utf8");
5192
5416
  } catch {
5193
5417
  continue;
5194
5418
  }
@@ -5219,7 +5443,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
5219
5443
  function _check_host_manifest(projectRoot) {
5220
5444
  const detected = Object.entries(detectToolPresence(projectRoot)).filter(([, v]) => v === true).map(([k]) => k);
5221
5445
  const detectedNote = detected.length > 0 ? `detected surfaces: ${detected.join(", ")}` : "no surfaces detected";
5222
- const settingsPath = path15.join(projectRoot, ".agent-settings.yml");
5446
+ const settingsPath = path16.join(projectRoot, ".agent-settings.yml");
5223
5447
  if (!fs15.existsSync(settingsPath)) {
5224
5448
  return {
5225
5449
  id: "host-manifest",
@@ -5404,13 +5628,13 @@ function _isCliEntry14() {
5404
5628
  if (process6.argv[1] === void 0) {
5405
5629
  return false;
5406
5630
  }
5407
- const argvUrl = pathToFileURL15(path15.resolve(process6.argv[1])).href;
5631
+ const argvUrl = pathToFileURL15(path16.resolve(process6.argv[1])).href;
5408
5632
  if (import.meta.url === argvUrl) {
5409
5633
  return true;
5410
5634
  }
5411
5635
  try {
5412
5636
  const here = fs15.realpathSync(fileURLToPath15(import.meta.url));
5413
- const argv = fs15.realpathSync(path15.resolve(process6.argv[1]));
5637
+ const argv = fs15.realpathSync(path16.resolve(process6.argv[1]));
5414
5638
  return here === argv;
5415
5639
  } catch {
5416
5640
  return false;