@event4u/agent-config 15.0.0 → 16.0.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 (78) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +142 -348
  5. package/dist/agent-src/commands/roadmap/create.md +3 -2
  6. package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +50 -0
  7. package/dist/agent-src/rules/user-interaction.md +31 -30
  8. package/dist/agent-src/skills/error-handling-patterns/SKILL.md +9 -0
  9. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  10. package/dist/cli-delegate/{chunk-HZ52BRGG.js → chunk-H32DGUJH.js} +14 -89
  11. package/dist/cli-delegate/chunk-NUHLI2RX.js +80 -0
  12. package/dist/cli-delegate/{chunk-TYSY33MD.js → chunk-QJWAUMJW.js} +12 -2
  13. package/dist/cli-delegate/{chunk-2KKXJW25.js → chunk-S3VFXMTM.js} +1 -1
  14. package/dist/cli-delegate/cmd_conformance.js +831 -272
  15. package/dist/cli-delegate/cmd_explain.js +4 -2
  16. package/dist/cli-delegate/cmd_handoff.js +2 -2
  17. package/dist/cli-delegate/cmd_packs_active.js +2 -1
  18. package/dist/cli-delegate/cmd_session_recycle.js +2 -2
  19. package/dist/cli-delegate/cmd_settings_set.js +13 -0
  20. package/dist/discovery/deprecation-report.md +1 -1
  21. package/dist/discovery/discovery-manifest.json +5 -5
  22. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  23. package/dist/discovery/discovery-manifest.summary.md +1 -1
  24. package/dist/discovery/dormancy-report.md +1 -1
  25. package/dist/discovery/orphan-report.md +1 -1
  26. package/dist/discovery/packs.json +2 -2
  27. package/dist/discovery/trust-report.md +1 -1
  28. package/dist/discovery/workspaces.json +2 -2
  29. package/dist/hooks/dispatch.js +1274 -571
  30. package/dist/install/install.mjs +1 -0
  31. package/dist/mcp/registry-manifest.json +2 -2
  32. package/dist/mcp/server.json +2 -2
  33. package/dist/mcp/server.mjs +1218 -632
  34. package/dist/scripts/_lib/installed_lock.js +1 -1
  35. package/dist/server/io/yamlIO.js +50 -0
  36. package/package.json +1 -1
  37. package/src/config/continuity-surface.json +7 -0
  38. package/src/config/gate-violation-baselines.json +3 -3
  39. package/src/config/host-injection-effect.json +1 -1
  40. package/src/config/preamble-payload-budget.json +12 -7
  41. package/src/config/preamble-payload-exceptions.json +28 -0
  42. package/src/scripts/_dispatch.bash +3 -1
  43. package/src/scripts/_lib/base_ref_payload.ts +315 -0
  44. package/src/scripts/_lib/dropped_decision.ts +142 -0
  45. package/src/scripts/_lib/installed_lock.ts +1 -1
  46. package/src/scripts/_lib/measured_payload_ceiling.ts +424 -0
  47. package/src/scripts/_lib/payload_catalogue_completeness.ts +211 -0
  48. package/src/scripts/_lib/release_findings_ingest.ts +324 -0
  49. package/src/scripts/_lib/release_tag_dispatch.ts +63 -0
  50. package/src/scripts/_lib/review_baseline.ts +254 -0
  51. package/src/scripts/_lib/review_skipped_record.ts +61 -1
  52. package/src/scripts/_lib/standing_bound_ratchet.ts +216 -103
  53. package/src/scripts/_lib/turn_end_refusals.ts +51 -4
  54. package/src/scripts/check_beta_review_markers.ts +35 -4
  55. package/src/scripts/check_finding_dispositions.ts +167 -16
  56. package/src/scripts/check_held_object_arrivals.ts +381 -0
  57. package/src/scripts/check_preamble_payload_budget.ts +399 -122
  58. package/src/scripts/check_release_published.ts +1 -1
  59. package/src/scripts/check_reply_consistency.ts +86 -17
  60. package/src/scripts/hook_manifest.json +1 -1
  61. package/src/scripts/hook_manifest.yaml +39 -3
  62. package/src/scripts/hooks/block_kernel_rule_writes.ts +12 -2
  63. package/src/scripts/hooks/concern_registry.ts +2 -0
  64. package/src/scripts/hooks/end_review_nudge_hook.ts +101 -21
  65. package/src/scripts/hooks/review_baseline_hook.ts +130 -0
  66. package/src/scripts/hooks/turn_end_gate_hook.ts +232 -14
  67. package/src/scripts/hooks_doctor.ts +4 -1
  68. package/src/scripts/install.ts +1 -1
  69. package/src/scripts/interruption_report.ts +8 -2
  70. package/src/scripts/janitor.ts +8 -1
  71. package/src/scripts/measure_turn_end_gate.ts +302 -5
  72. package/src/scripts/release.ts +52 -64
  73. package/src/scripts/release_drill.ts +193 -14
  74. package/src/scripts/release_env.ts +1 -1
  75. package/src/scripts/release_publication.ts +1 -1
  76. package/src/scripts/report_held_object_arrivals.ts +456 -0
  77. package/src/scripts/sync_agent_settings.ts +140 -18
  78. package/src/server/io/yamlIO.ts +48 -0
@@ -10,11 +10,13 @@ import {
10
10
  sessionRefusalFile,
11
11
  statePathFor,
12
12
  validateAssumption
13
- } from "./chunk-TYSY33MD.js";
13
+ } from "./chunk-QJWAUMJW.js";
14
14
  import {
15
15
  readHookStdin
16
16
  } from "./chunk-F7DQWYR5.js";
17
17
  import {
18
+ DeadScopeError,
19
+ assertScanned,
18
20
  reportScanned
19
21
  } from "./chunk-I3EIN2YG.js";
20
22
  import {
@@ -52,6 +54,9 @@ import {
52
54
  prune_stale_session_states,
53
55
  session_state_file
54
56
  } from "./chunk-E4XIZDIB.js";
57
+ import {
58
+ artefact_roots
59
+ } from "./chunk-NUHLI2RX.js";
55
60
  import {
56
61
  detectToolPresence
57
62
  } from "./chunk-A4QJ6ENT.js";
@@ -80,12 +85,12 @@ import {
80
85
 
81
86
  // src/scripts/_cli/cmd_conformance.ts
82
87
  var YAML = __toESM(require_dist(), 1);
83
- import * as fs13 from "node:fs";
88
+ import * as fs15 from "node:fs";
84
89
  import * as os7 from "node:os";
85
- import * as path13 from "node:path";
90
+ import * as path15 from "node:path";
86
91
  import process5 from "node:process";
87
- import { spawnSync as spawnSync2 } from "node:child_process";
88
- import { fileURLToPath as fileURLToPath13, pathToFileURL as pathToFileURL13 } from "node:url";
92
+ import { spawnSync as spawnSync3 } from "node:child_process";
93
+ import { fileURLToPath as fileURLToPath14, pathToFileURL as pathToFileURL14 } from "node:url";
89
94
 
90
95
  // src/install/txlog.ts
91
96
  import { createReadStream, createWriteStream, existsSync, readFileSync, renameSync, statSync, unlinkSync } from "node:fs";
@@ -131,10 +136,10 @@ var ROUTE_TARGET_TEMPLATES = Object.freeze({
131
136
  ])
132
137
  });
133
138
  function parseRouteTarget(target) {
134
- const sep = target.indexOf(":");
135
- if (sep <= 0) return null;
136
- const kind = target.slice(0, sep);
137
- const id = target.slice(sep + 1);
139
+ const sep2 = target.indexOf(":");
140
+ if (sep2 <= 0) return null;
141
+ const kind = target.slice(0, sep2);
142
+ const id = target.slice(sep2 + 1);
138
143
  if (!id) return null;
139
144
  if (!Object.prototype.hasOwnProperty.call(ROUTE_TARGET_TEMPLATES, kind)) return null;
140
145
  return { kind, id };
@@ -146,18 +151,18 @@ function routeTargetPathsPosix(target) {
146
151
  }
147
152
 
148
153
  // src/scripts/report_conformance_funnel.ts
149
- import * as fs12 from "node:fs";
154
+ import * as fs14 from "node:fs";
150
155
  import * as os6 from "node:os";
151
- import * as path12 from "node:path";
156
+ import * as path14 from "node:path";
152
157
  import process4 from "node:process";
153
- import { fileURLToPath as fileURLToPath12, pathToFileURL as pathToFileURL12 } from "node:url";
158
+ import { fileURLToPath as fileURLToPath13, pathToFileURL as pathToFileURL13 } from "node:url";
154
159
 
155
160
  // src/scripts/conformance_scan.ts
156
161
  import { createHash as createHash3 } from "node:crypto";
157
- import fs8 from "node:fs";
162
+ import fs10 from "node:fs";
158
163
  import os2 from "node:os";
159
- import path8 from "node:path";
160
- import { fileURLToPath as fileURLToPath8, pathToFileURL as pathToFileURL8 } from "node:url";
164
+ import path10 from "node:path";
165
+ import { fileURLToPath as fileURLToPath9, pathToFileURL as pathToFileURL9 } from "node:url";
161
166
 
162
167
  // src/scripts/_lib/transcript_entry.ts
163
168
  function _isObject(v) {
@@ -1940,17 +1945,464 @@ var COMMAND_OBJECTS = {
1940
1945
  };
1941
1946
 
1942
1947
  // src/scripts/hooks/turn_end_gate_hook.ts
1943
- import * as fs5 from "node:fs";
1944
- import * as path5 from "node:path";
1945
- import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL5 } from "node:url";
1948
+ import * as fs7 from "node:fs";
1949
+ import * as path7 from "node:path";
1950
+ import { fileURLToPath as fileURLToPath6, pathToFileURL as pathToFileURL6 } from "node:url";
1946
1951
 
1947
- // src/scripts/hooks/end_review_nudge_hook.ts
1948
- import { spawnSync } from "node:child_process";
1949
- import * as crypto from "node:crypto";
1952
+ // src/scripts/check_reply_consistency.ts
1950
1953
  import * as fs3 from "node:fs";
1951
- import * as os from "node:os";
1952
1954
  import * as path3 from "node:path";
1953
1955
  import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL3 } from "node:url";
1956
+ var _HERE = fileURLToPath3(import.meta.url);
1957
+ var ROOT = path3.resolve(path3.dirname(_HERE), "..", "..");
1958
+ var QUIET = process.argv.slice(2).includes("--quiet");
1959
+ var OPTION_LINE_RE = /^\s*>?\s*(\d+)\.\s+\S/;
1960
+ var REC_LINE_RE = /(?:Recommendation|Empfehlung)\s*:\s*(\d+)\b/i;
1961
+ var TAG_RE = /\((?:recommended|rec|empfohlen)\)/i;
1962
+ var CODESPAN_RE = /`[^`\n]*`/g;
1963
+ var HEADING_RE = /^#{1,6}\s/;
1964
+ var FENCE_RE = /^\s*(```|~~~)/;
1965
+ var REC_ADJACENCY_WINDOW = 2;
1966
+ function _strip_codespans(line) {
1967
+ return line.replace(CODESPAN_RE, "``");
1968
+ }
1969
+ function splitAndMask(text) {
1970
+ return mask_fences(_splitlines(text));
1971
+ }
1972
+ function _splitlines(text) {
1973
+ if (text === "") return [];
1974
+ const parts = text.split(/\r\n|\r|\n/);
1975
+ if (parts.length > 0 && parts[parts.length - 1] === "") {
1976
+ parts.pop();
1977
+ }
1978
+ return parts;
1979
+ }
1980
+ function mask_fences(lines) {
1981
+ const out = [];
1982
+ let fence = null;
1983
+ for (const raw of lines) {
1984
+ const m = FENCE_RE.exec(raw);
1985
+ if (m) {
1986
+ const marker = m[1];
1987
+ if (fence === null) {
1988
+ fence = marker;
1989
+ } else if (fence === marker) {
1990
+ fence = null;
1991
+ }
1992
+ out.push("");
1993
+ continue;
1994
+ }
1995
+ out.push(fence === null ? raw : "");
1996
+ }
1997
+ return out;
1998
+ }
1999
+ function find_option_blocks(text) {
2000
+ const lines = mask_fences(_splitlines(text));
2001
+ const blocks = [];
2002
+ let current = null;
2003
+ for (let idx = 0; idx < lines.length; idx++) {
2004
+ const m = OPTION_LINE_RE.exec(lines[idx]);
2005
+ if (m) {
2006
+ const num = parseInt(m[1], 10);
2007
+ if (current === null) {
2008
+ current = { startLine: idx + 1, endLine: idx + 1, numbers: [num] };
2009
+ } else {
2010
+ current.endLine = idx + 1;
2011
+ current.numbers.push(num);
2012
+ }
2013
+ } else {
2014
+ if (current !== null && current.numbers.length >= 2) {
2015
+ blocks.push(current);
2016
+ }
2017
+ current = null;
2018
+ }
2019
+ }
2020
+ if (current !== null && current.numbers.length >= 2) {
2021
+ blocks.push(current);
2022
+ }
2023
+ return blocks;
2024
+ }
2025
+ function recommendationsUnder(text, block, maskedLines) {
2026
+ const lines = maskedLines ?? mask_fences(_splitlines(text));
2027
+ const recs = [];
2028
+ let inspected = 0;
2029
+ for (let idx = block.endLine; idx < lines.length && inspected < REC_ADJACENCY_WINDOW; idx++) {
2030
+ const line = lines[idx];
2031
+ if (line.trim() === "") {
2032
+ continue;
2033
+ }
2034
+ if (HEADING_RE.test(line) || OPTION_LINE_RE.test(line)) {
2035
+ break;
2036
+ }
2037
+ inspected += 1;
2038
+ const m = REC_LINE_RE.exec(line);
2039
+ if (m) {
2040
+ recs.push({ line: idx + 1, num: parseInt(m[1], 10) });
2041
+ }
2042
+ }
2043
+ return recs;
2044
+ }
2045
+ function check_reply(text) {
2046
+ const rawLines = _splitlines(text);
2047
+ const lines = mask_fences(rawLines);
2048
+ const findings = [];
2049
+ for (let idx = 0; idx < lines.length; idx++) {
2050
+ const stripped = _strip_codespans(lines[idx]);
2051
+ if (OPTION_LINE_RE.test(stripped) && TAG_RE.test(stripped)) {
2052
+ findings.push({
2053
+ line: idx + 1,
2054
+ message: `inline tag on numbered option \u2014 ${rawLines[idx].trim()}`
2055
+ });
2056
+ }
2057
+ }
2058
+ const blocks = find_option_blocks(text);
2059
+ for (const block of blocks) {
2060
+ const recs = recommendationsUnder(text, block);
2061
+ if (recs.length === 0) {
2062
+ findings.push({
2063
+ line: block.startLine,
2064
+ message: "numbered options block without a Recommendation:/Empfehlung: line directly under it"
2065
+ });
2066
+ continue;
2067
+ }
2068
+ if (recs.length > 1) {
2069
+ findings.push({
2070
+ line: recs[1].line,
2071
+ message: `multiple recommendation lines under one options block: [${recs.map((r) => r.num).join(", ")}]`
2072
+ });
2073
+ continue;
2074
+ }
2075
+ const rec = recs[0];
2076
+ if (!block.numbers.includes(rec.num)) {
2077
+ findings.push({
2078
+ line: rec.line,
2079
+ message: `recommendation ${String(rec.num)} not present in the options block above it (options: [${block.numbers.join(", ")}])`
2080
+ });
2081
+ }
2082
+ }
2083
+ findings.sort((a, b) => a.line - b.line);
2084
+ return findings;
2085
+ }
2086
+ function _isDir(p) {
2087
+ try {
2088
+ return fs3.statSync(p).isDirectory();
2089
+ } catch {
2090
+ return false;
2091
+ }
2092
+ }
2093
+ function _rglobMdSorted(dir) {
2094
+ const out = [];
2095
+ const walk = (current) => {
2096
+ let entries;
2097
+ try {
2098
+ entries = fs3.readdirSync(current, { withFileTypes: true });
2099
+ } catch {
2100
+ return;
2101
+ }
2102
+ for (const ent of entries) {
2103
+ const full = path3.join(current, ent.name);
2104
+ if (ent.isDirectory() || ent.isSymbolicLink() && _isDir(full)) {
2105
+ walk(full);
2106
+ } else if (ent.name.endsWith(".md")) {
2107
+ out.push(full);
2108
+ }
2109
+ }
2110
+ };
2111
+ walk(dir);
2112
+ out.sort();
2113
+ return out;
2114
+ }
2115
+ function _relToPosixOrAbs(child, root) {
2116
+ const rel = path3.relative(root, child);
2117
+ if (rel === "" || rel.startsWith("..") || path3.isAbsolute(rel)) {
2118
+ return child.split(path3.sep).join("/");
2119
+ }
2120
+ return rel.split(path3.sep).join("/");
2121
+ }
2122
+ function cmd_scan_dir(root) {
2123
+ let roots;
2124
+ if (!_isDir(root)) {
2125
+ const legacy = path3.join(ROOT, ".agent-src.uncondensed");
2126
+ if (path3.resolve(root) === path3.resolve(legacy)) {
2127
+ roots = artefact_roots();
2128
+ if (roots.length === 0) {
2129
+ process.stderr.write("error: no artefact roots found (legacy or packages/*)\n");
2130
+ return 1;
2131
+ }
2132
+ } else {
2133
+ process.stderr.write(`error: not a directory: ${root}
2134
+ `);
2135
+ return 1;
2136
+ }
2137
+ } else {
2138
+ roots = [root];
2139
+ }
2140
+ const violations = [];
2141
+ let scanned = 0;
2142
+ for (const r of roots) {
2143
+ for (const md of _rglobMdSorted(r)) {
2144
+ scanned += 1;
2145
+ const text = fs3.readFileSync(md, "utf-8");
2146
+ const lines = _splitlines(text);
2147
+ for (let idx = 0; idx < lines.length; idx++) {
2148
+ const raw = lines[idx];
2149
+ const stripped = _strip_codespans(raw);
2150
+ if (OPTION_LINE_RE.test(stripped) && TAG_RE.test(stripped)) {
2151
+ violations.push([md, idx + 1, raw.trim()]);
2152
+ }
2153
+ }
2154
+ }
2155
+ }
2156
+ try {
2157
+ assertScanned({
2158
+ gate: "check_reply_consistency",
2159
+ scanned,
2160
+ units: "markdown file(s)",
2161
+ roots: roots.map((r) => _relToPosixOrAbs(r, ROOT))
2162
+ });
2163
+ } catch (exc) {
2164
+ if (exc instanceof DeadScopeError) {
2165
+ process.stderr.write(`\u274C ${exc.message}
2166
+ `);
2167
+ return 1;
2168
+ }
2169
+ throw exc;
2170
+ }
2171
+ if (violations.length > 0) {
2172
+ for (const [p, line, snippet] of violations) {
2173
+ process.stderr.write(` \u{1F534} ${p}:${String(line)} \u2014 inline-tag \u2014 ${snippet}
2174
+ `);
2175
+ }
2176
+ process.stderr.write(`
2177
+ \u274C ${String(violations.length)} legacy-pattern violation(s)
2178
+ `);
2179
+ return 2;
2180
+ }
2181
+ if (!QUIET) {
2182
+ const scanned2 = roots.map((r) => _relToPosixOrAbs(r, ROOT)).join(", ");
2183
+ process.stdout.write(`\u2705 No legacy (recommended) tags found under ${scanned2}
2184
+ `);
2185
+ }
2186
+ return 0;
2187
+ }
2188
+ var USAGE = "usage: check_reply_consistency [-h] (--stdin | --file FILE | --scan-dir SCAN_DIR)\n [-v] [--quiet]\n";
2189
+ function _usage_error(message) {
2190
+ process.stderr.write(USAGE);
2191
+ process.stderr.write(`check_reply_consistency: error: ${message}
2192
+ `);
2193
+ process.exit(1);
2194
+ }
2195
+ function _readStdin() {
2196
+ try {
2197
+ return fs3.readFileSync(0, "utf-8");
2198
+ } catch {
2199
+ return "";
2200
+ }
2201
+ }
2202
+ function parse_args(argv) {
2203
+ let stdin = false;
2204
+ let file = null;
2205
+ let scan_dir = null;
2206
+ let verbose = false;
2207
+ const groupSeen = [];
2208
+ const need = (i, name) => {
2209
+ const v = argv[i];
2210
+ if (v === void 0) {
2211
+ _usage_error(`argument ${name}: expected one argument`);
2212
+ }
2213
+ return v;
2214
+ };
2215
+ for (let i = 0; i < argv.length; i++) {
2216
+ const arg = argv[i];
2217
+ if (arg === "--stdin") {
2218
+ stdin = true;
2219
+ groupSeen.push("--stdin");
2220
+ } else if (arg === "--file") {
2221
+ file = need(++i, "--file");
2222
+ groupSeen.push("--file");
2223
+ } else if (arg.startsWith("--file=")) {
2224
+ file = arg.slice("--file=".length);
2225
+ groupSeen.push("--file");
2226
+ } else if (arg === "--scan-dir") {
2227
+ scan_dir = need(++i, "--scan-dir");
2228
+ groupSeen.push("--scan-dir");
2229
+ } else if (arg.startsWith("--scan-dir=")) {
2230
+ scan_dir = arg.slice("--scan-dir=".length);
2231
+ groupSeen.push("--scan-dir");
2232
+ } else if (arg === "-v" || arg === "--verbose") {
2233
+ verbose = true;
2234
+ } else if (arg === "--quiet") {
2235
+ } else if (arg === "-h" || arg === "--help") {
2236
+ process.stdout.write(USAGE);
2237
+ process.exit(0);
2238
+ } else {
2239
+ _usage_error(`unrecognized arguments: ${arg}`);
2240
+ }
2241
+ }
2242
+ if (groupSeen.length === 0) {
2243
+ _usage_error("one of the arguments --stdin --file --scan-dir is required");
2244
+ }
2245
+ if (groupSeen.length > 1) {
2246
+ _usage_error(`argument ${groupSeen[1]}: not allowed with argument ${groupSeen[0]}`);
2247
+ }
2248
+ return { stdin, file, scan_dir, verbose };
2249
+ }
2250
+ function main3(argv = process.argv.slice(2)) {
2251
+ const args = parse_args(argv);
2252
+ if (args.scan_dir !== null) {
2253
+ return cmd_scan_dir(args.scan_dir);
2254
+ }
2255
+ let text;
2256
+ try {
2257
+ text = args.stdin ? _readStdin() : fs3.readFileSync(args.file, "utf-8");
2258
+ } catch (e) {
2259
+ process.stderr.write(`error: ${String(e)}
2260
+ `);
2261
+ return 1;
2262
+ }
2263
+ const findings = check_reply(text);
2264
+ if (findings.length === 0) {
2265
+ if (args.verbose && !QUIET) {
2266
+ process.stdout.write("\u2705 reply consistent (every options block carries one adjacent recommendation)\n");
2267
+ }
2268
+ return 0;
2269
+ }
2270
+ for (const f of findings) {
2271
+ process.stderr.write(`\u274C line ${String(f.line)}: ${f.message}
2272
+ `);
2273
+ }
2274
+ return 2;
2275
+ }
2276
+ function _isCliEntry3() {
2277
+ if (true) {
2278
+ return false;
2279
+ }
2280
+ if (process.argv[1] === void 0) {
2281
+ return false;
2282
+ }
2283
+ const argvUrl = pathToFileURL3(path3.resolve(process.argv[1])).href;
2284
+ if (import.meta.url === argvUrl) {
2285
+ return true;
2286
+ }
2287
+ try {
2288
+ const here = fs3.realpathSync(fileURLToPath3(import.meta.url));
2289
+ const argv = fs3.realpathSync(path3.resolve(process.argv[1]));
2290
+ return here === argv;
2291
+ } catch {
2292
+ return false;
2293
+ }
2294
+ }
2295
+ var _IN_BUNDLE = true;
2296
+ if (!_IN_BUNDLE && (_isCliEntry3() || process.argv[1] === _HERE)) {
2297
+ process.exit(main3());
2298
+ }
2299
+
2300
+ // src/scripts/_lib/dropped_decision.ts
2301
+ function detectDroppedDecision(assistantTurnTexts, closingFromPayload = false) {
2302
+ if (assistantTurnTexts.length < 2) return null;
2303
+ const asksIn = (text) => {
2304
+ const blocks = find_option_blocks(text);
2305
+ if (blocks.length === 0) return blocks;
2306
+ const masked = splitAndMask(text);
2307
+ return blocks.filter((b) => recommendationsUnder(text, b, masked).length > 0);
2308
+ };
2309
+ const closing = assistantTurnTexts[assistantTurnTexts.length - 1];
2310
+ if (asksIn(closing).length > 0) return null;
2311
+ for (let i = assistantTurnTexts.length - 2; i >= 0; i -= 1) {
2312
+ const earlier = assistantTurnTexts[i];
2313
+ const blocks = asksIn(earlier);
2314
+ if (blocks.length === 0) continue;
2315
+ const block = blocks[blocks.length - 1];
2316
+ return {
2317
+ detector: "pending-decision",
2318
+ // The option NUMBERS and the line span, never the option text: the
2319
+ // evidence is quoted into a refusal that reaches the transcript, and
2320
+ // an options block can carry anything the reply carried.
2321
+ evidence: `options ${block.numbers.join("/")} at lines ${block.startLine}-${block.endLine} of an earlier reply this turn (closing reply read from ${closingFromPayload ? "the stop payload" : "the transcript"})`,
2322
+ reason: "an earlier reply in THIS turn put numbered options to the user and no user answer followed \u2014 this closing reply carries no options block, so the decision disappeared without being answered, cancelled or superseded. A hook nudge, a reviewer result or a task notification may ADD to a turn; it may not displace a question already asked (user-interaction Iron Law 3: a decision handed to the user outlives the turn). Re-present the block and its recommendation line at the end of this reply"
2323
+ };
2324
+ }
2325
+ return null;
2326
+ }
2327
+
2328
+ // src/scripts/hooks/end_review_nudge_hook.ts
2329
+ import { spawnSync as spawnSync2 } from "node:child_process";
2330
+ import * as crypto from "node:crypto";
2331
+ import * as fs5 from "node:fs";
2332
+ import * as os from "node:os";
2333
+ import * as path5 from "node:path";
2334
+ import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL4 } from "node:url";
2335
+
2336
+ // src/scripts/_lib/review_baseline.ts
2337
+ import { spawnSync } from "node:child_process";
2338
+ import * as fs4 from "node:fs";
2339
+ import * as path4 from "node:path";
2340
+ function currentHeadSha(cwd) {
2341
+ try {
2342
+ const r = spawnSync("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8" });
2343
+ if (r.status !== 0) return null;
2344
+ const out = (r.stdout ?? "").trim();
2345
+ return out === "" ? null : out;
2346
+ } catch {
2347
+ return null;
2348
+ }
2349
+ }
2350
+ var BASELINE_STATE_REL = path4.join("agents", "runtime", "state", "review-baseline");
2351
+ function baselineStateDir(workspaceRoot) {
2352
+ return path4.join(workspaceRoot, BASELINE_STATE_REL);
2353
+ }
2354
+ function baselineStateFile(workspaceRoot, sessionKey) {
2355
+ return path4.join(baselineStateDir(workspaceRoot), `${sessionKey}.json`);
2356
+ }
2357
+ function parseBaseline(raw) {
2358
+ let decoded;
2359
+ try {
2360
+ decoded = JSON.parse(raw);
2361
+ } catch {
2362
+ return null;
2363
+ }
2364
+ if (typeof decoded !== "object" || decoded === null || Array.isArray(decoded)) return null;
2365
+ const o = decoded;
2366
+ const lines = o["baseline_lines"];
2367
+ if (typeof lines !== "number" || !Number.isFinite(lines) || lines < 0) return null;
2368
+ const written = o["written_at"];
2369
+ if (typeof written !== "string") return null;
2370
+ const head = o["head_sha"];
2371
+ const measure = o["measure"];
2372
+ return {
2373
+ head_sha: typeof head === "string" && head !== "" ? head : null,
2374
+ baseline_lines: lines,
2375
+ ...measure === "exact" || measure === "capped_approximation" ? { measure } : {},
2376
+ written_at: written
2377
+ };
2378
+ }
2379
+ function readBaseline(workspaceRoot, sessionKey) {
2380
+ const file = baselineStateFile(workspaceRoot, sessionKey);
2381
+ let raw;
2382
+ try {
2383
+ raw = fs4.readFileSync(file, "utf-8");
2384
+ } catch (exc) {
2385
+ const code = exc?.code;
2386
+ return code === "ENOENT" ? "absent" : "unreadable";
2387
+ }
2388
+ return parseBaseline(raw) ?? "unreadable";
2389
+ }
2390
+ function applyBaseline(measuredLines, baseline, headSha, measuredMeasure = "exact") {
2391
+ if (baseline === "absent" || baseline === "unreadable") {
2392
+ return { applied: false, fallback: baseline, lines: measuredLines };
2393
+ }
2394
+ if (baseline.measure !== "exact" || measuredMeasure !== "exact") {
2395
+ return { applied: false, fallback: "mixed-measure", lines: measuredLines };
2396
+ }
2397
+ if (baseline.head_sha !== headSha()) {
2398
+ return { applied: false, fallback: "head-moved", lines: measuredLines };
2399
+ }
2400
+ return {
2401
+ applied: true,
2402
+ baseline,
2403
+ lines: Math.max(0, measuredLines - baseline.baseline_lines)
2404
+ };
2405
+ }
1954
2406
 
1955
2407
  // src/scripts/_lib/audit_field_provenance.ts
1956
2408
  var MAX_APPLIED_IDS = 32;
@@ -1966,6 +2418,13 @@ function appliedIds(values) {
1966
2418
  }
1967
2419
 
1968
2420
  // src/scripts/_lib/review_skipped_record.ts
2421
+ var BASELINE_APPLICATIONS = [
2422
+ "applied",
2423
+ "absent",
2424
+ "unreadable",
2425
+ "head_moved",
2426
+ "mixed_measure"
2427
+ ];
1969
2428
  var PRODUCER_PRIVACY_CLASS = "ids-only";
1970
2429
  function isNonNegInt(n) {
1971
2430
  return typeof n === "number" && Number.isFinite(n) && Number.isInteger(n) && n >= 0;
@@ -1981,6 +2440,9 @@ function buildReviewSkippedLine(input) {
1981
2440
  }
1982
2441
  if (!input.ts) errors.push("ts (ISO-8601 UTC) is required");
1983
2442
  if (!input.id) errors.push("id (ULID, UUID, or content hash) is required");
2443
+ if (input.baseline !== void 0 && !BASELINE_APPLICATIONS.includes(input.baseline)) {
2444
+ errors.push(`baseline must be one of ${BASELINE_APPLICATIONS.join(", ")}`);
2445
+ }
1984
2446
  if (errors.length) return { line: null, errors };
1985
2447
  const line = {
1986
2448
  schema_version: 1,
@@ -2007,7 +2469,14 @@ function buildReviewSkippedLine(input) {
2007
2469
  persona: null,
2008
2470
  input_kind: "prompt",
2009
2471
  type: "note",
2010
- review_skipped: { diff_lines: input.diff_lines, mutation_measure: input.mutation_measure }
2472
+ review_skipped: {
2473
+ diff_lines: input.diff_lines,
2474
+ mutation_measure: input.mutation_measure,
2475
+ // Omitted, not defaulted, when the producer recorded nothing —
2476
+ // audit-log-v1's absent-versus-present split is the same one
2477
+ // `skills_applied` uses above, for the same reason.
2478
+ ...input.baseline === void 0 ? {} : { baseline: input.baseline }
2479
+ }
2011
2480
  };
2012
2481
  return { line, errors: [] };
2013
2482
  }
@@ -2075,13 +2544,13 @@ function isSafeTranscriptPath(rawPath, opts = {}) {
2075
2544
  const homeDir = opts.homeDir ?? os.homedir();
2076
2545
  const maxBytes = opts.maxBytes ?? TRANSCRIPT_SCAN_MAX_BYTES;
2077
2546
  try {
2078
- const realHome = fs3.realpathSync(homeDir);
2079
- const realPath = fs3.realpathSync(rawPath);
2080
- const relative2 = path3.relative(realHome, realPath);
2081
- if (relative2 === "" || relative2.startsWith("..") || path3.isAbsolute(relative2)) {
2547
+ const realHome = fs5.realpathSync(homeDir);
2548
+ const realPath = fs5.realpathSync(rawPath);
2549
+ const relative3 = path5.relative(realHome, realPath);
2550
+ if (relative3 === "" || relative3.startsWith("..") || path5.isAbsolute(relative3)) {
2082
2551
  return false;
2083
2552
  }
2084
- const { size } = fs3.statSync(realPath);
2553
+ const { size } = fs5.statSync(realPath);
2085
2554
  return size <= maxBytes;
2086
2555
  } catch {
2087
2556
  return false;
@@ -2112,7 +2581,7 @@ function nonDocMutatedLines(rows) {
2112
2581
  }
2113
2582
  function gitNumstatRows(cwd) {
2114
2583
  try {
2115
- const r = spawnSync("git", ["diff", "--numstat", "HEAD"], {
2584
+ const r = spawnSync2("git", ["diff", "--numstat", "HEAD"], {
2116
2585
  cwd,
2117
2586
  encoding: "utf8",
2118
2587
  maxBuffer: 16 * 1024 * 1024
@@ -2125,7 +2594,7 @@ function gitNumstatRows(cwd) {
2125
2594
  }
2126
2595
  function untrackedNonDocFiles(cwd) {
2127
2596
  try {
2128
- const r = spawnSync("git", ["ls-files", "--others", "--exclude-standard"], {
2597
+ const r = spawnSync2("git", ["ls-files", "--others", "--exclude-standard"], {
2129
2598
  cwd,
2130
2599
  encoding: "utf8",
2131
2600
  maxBuffer: 16 * 1024 * 1024
@@ -2140,13 +2609,13 @@ var BINARY_PROBE_BYTES = 8e3;
2140
2609
  var UNTRACKED_FILE_READ_CAP_BYTES = 8 * 1024 * 1024;
2141
2610
  function untrackedFileLineCount(cwd, relPath) {
2142
2611
  try {
2143
- const abs = path3.resolve(cwd, relPath);
2144
- const size = fs3.statSync(abs).size;
2612
+ const abs = path5.resolve(cwd, relPath);
2613
+ const size = fs5.statSync(abs).size;
2145
2614
  if (size === 0) return 0;
2146
2615
  if (size > UNTRACKED_FILE_READ_CAP_BYTES) {
2147
2616
  return MUTATION_LINE_THRESHOLD + 1;
2148
2617
  }
2149
- const buf = fs3.readFileSync(abs);
2618
+ const buf = fs5.readFileSync(abs);
2150
2619
  if (buf.length === 0) return 0;
2151
2620
  const probe = buf.subarray(0, Math.min(buf.length, BINARY_PROBE_BYTES));
2152
2621
  if (probe.includes(0)) return 0;
@@ -2225,30 +2694,31 @@ function scanTranscriptForReviewer(transcriptText) {
2225
2694
  function buildAdvisoryLine(diffLines) {
2226
2695
  return `this session mutated ${diffLines} lines without a neutral review; spawn a cross-model reviewer before claiming done (delegation-policy / verify-budget)`;
2227
2696
  }
2228
- function appendReviewSkippedTelemetry(workspaceRoot, diffLines, mutationMeasure) {
2697
+ function appendReviewSkippedTelemetry(workspaceRoot, diffLines, mutationMeasure, baseline) {
2229
2698
  if (is_replay_mode()) return;
2230
2699
  const ts = (/* @__PURE__ */ new Date()).toISOString();
2231
2700
  const { line, errors } = buildReviewSkippedLine({
2232
2701
  diff_lines: diffLines,
2233
2702
  mutation_measure: mutationMeasure,
2234
2703
  ts,
2235
- id: crypto.randomUUID()
2704
+ id: crypto.randomUUID(),
2705
+ baseline
2236
2706
  });
2237
2707
  if (errors.length || line === null) return;
2238
2708
  try {
2239
- const dir = path3.join(workspaceRoot, "agents", "runtime", "state", "audit");
2240
- fs3.mkdirSync(dir, { recursive: true });
2241
- const file = path3.join(dir, `${ts.slice(0, 7)}.jsonl`);
2242
- fs3.appendFileSync(file, `${JSON.stringify(line)}
2709
+ const dir = path5.join(workspaceRoot, "agents", "runtime", "state", "audit");
2710
+ fs5.mkdirSync(dir, { recursive: true });
2711
+ const file = path5.join(dir, `${ts.slice(0, 7)}.jsonl`);
2712
+ fs5.appendFileSync(file, `${JSON.stringify(line)}
2243
2713
  `, "utf8");
2244
2714
  } catch {
2245
2715
  }
2246
2716
  }
2247
2717
  function sessionStateDir(workspaceRoot) {
2248
- return path3.join(workspaceRoot, "agents", "runtime", "state", "end-review-nudge");
2718
+ return path5.join(workspaceRoot, "agents", "runtime", "state", "end-review-nudge");
2249
2719
  }
2250
2720
  function sessionStateFile(workspaceRoot, sessionKey) {
2251
- return path3.join(sessionStateDir(workspaceRoot), `${sessionKey}.json`);
2721
+ return path5.join(sessionStateDir(workspaceRoot), `${sessionKey}.json`);
2252
2722
  }
2253
2723
  function deriveSessionKey2(envelope, payload) {
2254
2724
  const raw = str(envelope["session_id"]) || str(payload["transcript_path"] ?? payload["transcriptPath"]);
@@ -2257,7 +2727,7 @@ function deriveSessionKey2(envelope, payload) {
2257
2727
  }
2258
2728
  function hasFiredThisSession(workspaceRoot, sessionKey) {
2259
2729
  try {
2260
- return fs3.existsSync(sessionStateFile(workspaceRoot, sessionKey));
2730
+ return fs5.existsSync(sessionStateFile(workspaceRoot, sessionKey));
2261
2731
  } catch {
2262
2732
  return false;
2263
2733
  }
@@ -2271,26 +2741,45 @@ function markFiredThisSession(workspaceRoot, sessionKey, ts) {
2271
2741
  function _read_stdin() {
2272
2742
  return readHookStdin();
2273
2743
  }
2274
- function main3() {
2744
+ var FALLBACK_TO_TELEMETRY = {
2745
+ absent: "absent",
2746
+ unreadable: "unreadable",
2747
+ "head-moved": "head_moved",
2748
+ "mixed-measure": "mixed_measure"
2749
+ };
2750
+ function main4() {
2275
2751
  const [envelope, payload] = unwrap(_read_stdin(), "claude");
2276
2752
  const event = String(envelope["event"] ?? "");
2277
2753
  if (event !== "" && event !== "stop") {
2278
2754
  return 0;
2279
2755
  }
2280
2756
  const workspace_root = String(envelope["workspace_root"] ?? "").trim() || process.cwd();
2281
- let diffLines;
2757
+ let measuredLines;
2282
2758
  let mutationMeasure;
2283
2759
  try {
2284
2760
  const measured = totalNonDocMutatedLinesWithMeasure(workspace_root);
2285
- diffLines = measured.lines;
2761
+ measuredLines = measured.lines;
2286
2762
  mutationMeasure = measured.measure;
2287
2763
  } catch {
2288
2764
  return 0;
2289
2765
  }
2766
+ const sessionKey = deriveSessionKey2(envelope, payload);
2767
+ const baselineOutcome = applyBaseline(
2768
+ measuredLines,
2769
+ readBaseline(workspace_root, sessionKey),
2770
+ // A THUNK, not a value: on the `absent` and `unreadable` branches the
2771
+ // result is discarded, and those two are the steady state on every host
2772
+ // without this nudge and on every session before its first baseline
2773
+ // write. Passing the value eagerly spent an 11-14 ms `git rev-parse` on
2774
+ // each of those stops for nothing.
2775
+ () => currentHeadSha(workspace_root),
2776
+ mutationMeasure
2777
+ );
2778
+ const diffLines = baselineOutcome.lines;
2779
+ const baselineApplication = baselineOutcome.applied ? "applied" : FALLBACK_TO_TELEMETRY[baselineOutcome.fallback];
2290
2780
  if (diffLines <= MUTATION_LINE_THRESHOLD) {
2291
2781
  return 0;
2292
2782
  }
2293
- const sessionKey = deriveSessionKey2(envelope, payload);
2294
2783
  if (hasFiredThisSession(workspace_root, sessionKey)) {
2295
2784
  return 0;
2296
2785
  }
@@ -2300,7 +2789,7 @@ function main3() {
2300
2789
  let reviewerRan = false;
2301
2790
  if (transcriptPath && isSafeTranscriptPath(transcriptPath)) {
2302
2791
  try {
2303
- reviewerRan = scanTranscriptForReviewer(fs3.readFileSync(transcriptPath, "utf-8"));
2792
+ reviewerRan = scanTranscriptForReviewer(fs5.readFileSync(transcriptPath, "utf-8"));
2304
2793
  } catch {
2305
2794
  reviewerRan = false;
2306
2795
  }
@@ -2310,7 +2799,12 @@ function main3() {
2310
2799
  }
2311
2800
  markFiredThisSession(workspace_root, sessionKey, (/* @__PURE__ */ new Date()).toISOString());
2312
2801
  try {
2313
- appendReviewSkippedTelemetry(workspace_root, diffLines, mutationMeasure);
2802
+ appendReviewSkippedTelemetry(
2803
+ workspace_root,
2804
+ diffLines,
2805
+ mutationMeasure,
2806
+ baselineApplication
2807
+ );
2314
2808
  } catch {
2315
2809
  }
2316
2810
  process.stdout.write(
@@ -2323,34 +2817,34 @@ function main3() {
2323
2817
  );
2324
2818
  return EXIT_WARN2;
2325
2819
  }
2326
- function _isCliEntry3() {
2820
+ function _isCliEntry4() {
2327
2821
  if (true) {
2328
2822
  return false;
2329
2823
  }
2330
2824
  if (process.argv[1] === void 0) {
2331
2825
  return false;
2332
2826
  }
2333
- const argvUrl = pathToFileURL3(path3.resolve(process.argv[1])).href;
2827
+ const argvUrl = pathToFileURL4(path5.resolve(process.argv[1])).href;
2334
2828
  if (import.meta.url === argvUrl) {
2335
2829
  return true;
2336
2830
  }
2337
2831
  try {
2338
- const here = fs3.realpathSync(fileURLToPath3(import.meta.url));
2339
- const argv = fs3.realpathSync(path3.resolve(process.argv[1]));
2832
+ const here = fs5.realpathSync(fileURLToPath4(import.meta.url));
2833
+ const argv = fs5.realpathSync(path5.resolve(process.argv[1]));
2340
2834
  return here === argv;
2341
2835
  } catch {
2342
2836
  return false;
2343
2837
  }
2344
2838
  }
2345
- if (_isCliEntry3()) {
2346
- process.exit(main3());
2839
+ if (_isCliEntry4()) {
2840
+ process.exit(main4());
2347
2841
  }
2348
2842
 
2349
2843
  // src/scripts/hooks/subagent_ledger_hook.ts
2350
2844
  import * as crypto2 from "node:crypto";
2351
- import * as fs4 from "node:fs";
2352
- import * as path4 from "node:path";
2353
- import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL4 } from "node:url";
2845
+ import * as fs6 from "node:fs";
2846
+ import * as path6 from "node:path";
2847
+ import { fileURLToPath as fileURLToPath5, pathToFileURL as pathToFileURL5 } from "node:url";
2354
2848
 
2355
2849
  // src/scripts/_lib/subagent_response.ts
2356
2850
  var MAX_SUMMARY_CHARS = 2e3;
@@ -2456,7 +2950,7 @@ var EXIT_ALLOW3 = 0;
2456
2950
  function isObject2(v) {
2457
2951
  return typeof v === "object" && v !== null && !Array.isArray(v);
2458
2952
  }
2459
- var LEDGER_DIR = path4.join("agents", "runtime", "state", "subagent-ledger");
2953
+ var LEDGER_DIR = path6.join("agents", "runtime", "state", "subagent-ledger");
2460
2954
  var OPEN_SUBDIR = "open";
2461
2955
  var OPEN_RECORD_TTL_MS = 24 * 60 * 60 * 1e3;
2462
2956
  function refFor(agentId) {
@@ -2546,10 +3040,10 @@ function _jsonObjectCandidates(message) {
2546
3040
  return out;
2547
3041
  }
2548
3042
  function openDir(root) {
2549
- return path4.join(root, LEDGER_DIR, OPEN_SUBDIR);
3043
+ return path6.join(root, LEDGER_DIR, OPEN_SUBDIR);
2550
3044
  }
2551
3045
  function openFile(root, ref) {
2552
- return path4.join(openDir(root), `${ref}.json`);
3046
+ return path6.join(openDir(root), `${ref}.json`);
2553
3047
  }
2554
3048
  var DEPTH_BASES = /* @__PURE__ */ new Set(["observed", "asserted-parent", "assumed-root"]);
2555
3049
  function _asOpenRecord(value, expectedRef) {
@@ -2576,7 +3070,7 @@ function readOpenRecords(root) {
2576
3070
  const out = /* @__PURE__ */ new Map();
2577
3071
  let names;
2578
3072
  try {
2579
- names = fs4.readdirSync(openDir(root));
3073
+ names = fs6.readdirSync(openDir(root));
2580
3074
  } catch {
2581
3075
  return out;
2582
3076
  }
@@ -2584,7 +3078,7 @@ function readOpenRecords(root) {
2584
3078
  if (!name.endsWith(".json")) continue;
2585
3079
  const expectedRef = name.slice(0, -".json".length);
2586
3080
  try {
2587
- const raw = fs4.readFileSync(path4.join(openDir(root), name), "utf8");
3081
+ const raw = fs6.readFileSync(path6.join(openDir(root), name), "utf8");
2588
3082
  const rec = _asOpenRecord(JSON.parse(raw), expectedRef);
2589
3083
  if (rec) out.set(rec.ref, rec);
2590
3084
  } catch {
@@ -2599,13 +3093,13 @@ function resolveDepth(parentRef, open) {
2599
3093
  return { depth: parent.depth + 1, depth_basis: "observed" };
2600
3094
  }
2601
3095
  function ledgerFileFor2(root, ts) {
2602
- return path4.join(root, LEDGER_DIR, `${ts.slice(0, 7)}.jsonl`);
3096
+ return path6.join(root, LEDGER_DIR, `${ts.slice(0, 7)}.jsonl`);
2603
3097
  }
2604
3098
  function appendLedgerLine(root, ts, line) {
2605
3099
  if (is_replay_mode()) return;
2606
3100
  const file = ledgerFileFor2(root, ts);
2607
- fs4.mkdirSync(path4.dirname(file), { recursive: true });
2608
- fs4.appendFileSync(file, `${JSON.stringify(line)}
3101
+ fs6.mkdirSync(path6.dirname(file), { recursive: true });
3102
+ fs6.appendFileSync(file, `${JSON.stringify(line)}
2609
3103
  `, "utf8");
2610
3104
  }
2611
3105
  var WALL_CLOCK_ARMS_MS = [
@@ -2619,7 +3113,7 @@ function armsExceeded(elapsedMs) {
2619
3113
  return WALL_CLOCK_ARMS_MS.filter((a) => elapsedMs >= a.ms).map((a) => a.label);
2620
3114
  }
2621
3115
  function openRecordStats(root, nowMs = Date.now()) {
2622
- const ledgerPresent = fs4.existsSync(path4.join(root, LEDGER_DIR));
3116
+ const ledgerPresent = fs6.existsSync(path6.join(root, LEDGER_DIR));
2623
3117
  const open = readOpenRecords(root);
2624
3118
  let maxDepth = 0;
2625
3119
  let counted = 0;
@@ -2647,13 +3141,13 @@ function writeOpenRecord(root, rec) {
2647
3141
  function removeOpenRecord(root, ref) {
2648
3142
  if (is_replay_mode()) return;
2649
3143
  try {
2650
- fs4.unlinkSync(openFile(root, ref));
3144
+ fs6.unlinkSync(openFile(root, ref));
2651
3145
  } catch {
2652
3146
  }
2653
3147
  }
2654
3148
  function countOpen(root) {
2655
3149
  try {
2656
- return fs4.readdirSync(openDir(root)).filter((n) => n.endsWith(".json")).length;
3150
+ return fs6.readdirSync(openDir(root)).filter((n) => n.endsWith(".json")).length;
2657
3151
  } catch {
2658
3152
  return 0;
2659
3153
  }
@@ -2804,7 +3298,7 @@ function resolveConsumerRoot(envelope) {
2804
3298
  }
2805
3299
  return process.cwd();
2806
3300
  }
2807
- function main4() {
3301
+ function main5() {
2808
3302
  const raw = readHookStdin();
2809
3303
  let envelope = {};
2810
3304
  try {
@@ -2814,20 +3308,20 @@ function main4() {
2814
3308
  }
2815
3309
  return processEnvelope(envelope, resolveConsumerRoot(envelope));
2816
3310
  }
2817
- function _isCliEntry4() {
3311
+ function _isCliEntry5() {
2818
3312
  if (true) {
2819
3313
  return false;
2820
3314
  }
2821
3315
  if (process.argv[1] === void 0) return false;
2822
- const argvUrl = pathToFileURL4(path4.resolve(process.argv[1])).href;
3316
+ const argvUrl = pathToFileURL5(path6.resolve(process.argv[1])).href;
2823
3317
  if (import.meta.url === argvUrl) return true;
2824
3318
  try {
2825
- return fs4.realpathSync(fileURLToPath4(import.meta.url)) === fs4.realpathSync(path4.resolve(process.argv[1]));
3319
+ return fs6.realpathSync(fileURLToPath5(import.meta.url)) === fs6.realpathSync(path6.resolve(process.argv[1]));
2826
3320
  } catch {
2827
3321
  return false;
2828
3322
  }
2829
3323
  }
2830
- if (_isCliEntry4()) process.exit(main4());
3324
+ if (_isCliEntry5()) process.exit(main5());
2831
3325
 
2832
3326
  // src/scripts/hooks/turn_end_gate_hook.ts
2833
3327
  var EXIT_BLOCK = 1;
@@ -2936,7 +3430,7 @@ function detectPromissory(reply) {
2936
3430
  function readCiSettled(workspaceRoot, session_id) {
2937
3431
  if (!hasStableSessionId(session_id)) return { seen: false, settled: false };
2938
3432
  try {
2939
- const raw = fs5.readFileSync(path5.join(workspaceRoot, statePathFor(session_id)), "utf-8");
3433
+ const raw = fs7.readFileSync(path7.join(workspaceRoot, statePathFor(session_id)), "utf-8");
2940
3434
  const decoded = JSON.parse(raw);
2941
3435
  if (!owns_session_state(decoded, session_id)) return { seen: false, settled: false };
2942
3436
  if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
@@ -2972,8 +3466,8 @@ function detectCompletionClaim(reply, ci) {
2972
3466
  function readLanguagePin(workspaceRoot, session_id) {
2973
3467
  if (!hasStableSessionId(session_id)) return "und";
2974
3468
  try {
2975
- const raw = fs5.readFileSync(
2976
- path5.join(workspaceRoot, statePathFor2(session_id)),
3469
+ const raw = fs7.readFileSync(
3470
+ path7.join(workspaceRoot, statePathFor2(session_id)),
2977
3471
  "utf-8"
2978
3472
  );
2979
3473
  const decoded = JSON.parse(raw);
@@ -3024,12 +3518,37 @@ function detectUnverifiedEdit(toolCalls) {
3024
3518
  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)"
3025
3519
  };
3026
3520
  }
3521
+ var _SOURCE_RE = /\.(?:ts|tsx|js|jsx|mjs|cjs|vue|svelte|php|py|rb|go|rs|java|kt|swift|cs|scala|ex|exs)$/i;
3522
+ var _TEST_PATH_RE = /(?:^|\/)(?:tests?|specs?|__tests__|__specs__|e2e|cypress|playwright|features)\//i;
3523
+ var _TEST_FILE_RE = /(?:\.(?:test|spec)\.[a-z]+$)|(?:_test\.[a-z]+$)|(?:(?:^|\/)test_[^/]+$)|(?:Test\.php$)|(?:Spec\.php$)|(?:\.feature$)/i;
3524
+ function _isTestPath(p) {
3525
+ return _TEST_PATH_RE.test(p) || _TEST_FILE_RE.test(p);
3526
+ }
3527
+ function _isProductionSource(p) {
3528
+ return _SOURCE_RE.test(p) && !_isTestPath(p);
3529
+ }
3530
+ function detectUntestedChange(reply, toolCalls) {
3531
+ const edited = toolCalls.filter((c) => _EDIT_TOOLS.has(c.name) && c.path !== void 0).map((c) => c.path);
3532
+ const source = edited.filter(_isProductionSource);
3533
+ if (source.length === 0) return null;
3534
+ if (edited.some(_isTestPath)) return null;
3535
+ const prose = visibleProse(reply);
3536
+ const m = _COMPLETION_RE.exec(prose);
3537
+ if (!m) return null;
3538
+ if (_NEGATED_CLAIM_RE.test(_lineAround(prose, m.index))) return null;
3539
+ const shown = source.slice(0, 3).join(", ");
3540
+ return {
3541
+ detector: "untested",
3542
+ evidence: shown + (source.length > 3 ? ` (+${String(source.length - 3)} more)` : ""),
3543
+ reason: "a completion claim over production code this turn changed, with NO test file touched anywhere in the turn \u2014 running a linter is not evidence the change works. Write the test that would have caught the failure, and enumerate the states the change actually has (every view, every CRUD path, the empty and error states) rather than the happy one. If a test genuinely does not belong here, say which file carries the coverage instead"
3544
+ };
3545
+ }
3027
3546
  function sessionStateFile2(workspaceRoot, sessionKey) {
3028
3547
  return sessionRefusalFile(workspaceRoot, sessionKey);
3029
3548
  }
3030
3549
  function alreadyRefusedTurn(workspaceRoot, sessionKey, turnOrdinal) {
3031
3550
  try {
3032
- const raw = fs5.readFileSync(sessionStateFile2(workspaceRoot, sessionKey), "utf-8");
3551
+ const raw = fs7.readFileSync(sessionStateFile2(workspaceRoot, sessionKey), "utf-8");
3033
3552
  const decoded = JSON.parse(raw);
3034
3553
  if (typeof decoded === "object" && decoded !== null && !Array.isArray(decoded)) {
3035
3554
  return decoded["refused_turn"] === turnOrdinal;
@@ -3038,12 +3557,12 @@ function alreadyRefusedTurn(workspaceRoot, sessionKey, turnOrdinal) {
3038
3557
  }
3039
3558
  return false;
3040
3559
  }
3041
- function markRefusedTurn(workspaceRoot, sessionKey, turnOrdinal, detectors) {
3560
+ function markRefusedTurn(workspaceRoot, sessionKey, turnOrdinal, detectors, promptId) {
3042
3561
  if (is_replay_mode()) return;
3043
3562
  const file = sessionStateFile2(workspaceRoot, sessionKey);
3044
3563
  let prev = null;
3045
3564
  try {
3046
- prev = parseRecord(fs5.readFileSync(file, "utf-8"));
3565
+ prev = parseRecord(fs7.readFileSync(file, "utf-8"));
3047
3566
  } catch {
3048
3567
  }
3049
3568
  let version;
@@ -3059,27 +3578,34 @@ function markRefusedTurn(workspaceRoot, sessionKey, turnOrdinal, detectors) {
3059
3578
  detectors,
3060
3579
  turnOrdinal,
3061
3580
  at: (/* @__PURE__ */ new Date()).toISOString(),
3062
- version
3581
+ version,
3582
+ promptId
3063
3583
  })
3064
3584
  );
3065
3585
  } catch {
3066
3586
  }
3067
3587
  }
3068
3588
  function readTranscriptTail(transcriptPath, opts = {}) {
3069
- const empty = { lastAssistant: "", turnOrdinal: 0, toolCalls: [] };
3589
+ const empty = {
3590
+ lastAssistant: "",
3591
+ turnOrdinal: 0,
3592
+ toolCalls: [],
3593
+ assistantTurnTexts: []
3594
+ };
3070
3595
  if (!transcriptPath || !isSafeTranscriptPath(transcriptPath, opts)) return empty;
3071
3596
  let lines;
3072
3597
  try {
3073
- if (opts.maxBytes !== void 0 && fs5.statSync(transcriptPath).size > opts.maxBytes) {
3598
+ if (opts.maxBytes !== void 0 && fs7.statSync(transcriptPath).size > opts.maxBytes) {
3074
3599
  return empty;
3075
3600
  }
3076
- lines = fs5.readFileSync(transcriptPath, "utf-8").split("\n");
3601
+ lines = fs7.readFileSync(transcriptPath, "utf-8").split("\n");
3077
3602
  } catch {
3078
3603
  return empty;
3079
3604
  }
3080
3605
  let lastAssistant = "";
3081
3606
  let turnOrdinal = 0;
3082
3607
  let toolCalls = [];
3608
+ let assistantTurnTexts = [];
3083
3609
  for (const rawLine of lines) {
3084
3610
  const line = rawLine.trim();
3085
3611
  if (!line) continue;
@@ -3098,20 +3624,27 @@ function readTranscriptTail(transcriptPath, opts = {}) {
3098
3624
  if (typeof msg !== "object" || msg === null || Array.isArray(msg)) continue;
3099
3625
  const content = msg["content"];
3100
3626
  if (role === "assistant") {
3101
- toolCalls.push(..._toolCalls(content));
3627
+ toolCalls.push(...extractToolCalls(content));
3102
3628
  }
3103
3629
  const text = _messageText(content);
3104
3630
  if (text === null) continue;
3105
3631
  if (role === "assistant") {
3106
3632
  lastAssistant = text;
3633
+ assistantTurnTexts.push(text);
3107
3634
  } else if (!isSyntheticPrompt(text)) {
3108
3635
  turnOrdinal += 1;
3109
3636
  toolCalls = [];
3637
+ assistantTurnTexts = [];
3110
3638
  }
3111
3639
  }
3112
- return { lastAssistant: lastAssistant.trim(), turnOrdinal, toolCalls };
3640
+ return {
3641
+ lastAssistant: lastAssistant.trim(),
3642
+ turnOrdinal,
3643
+ toolCalls,
3644
+ assistantTurnTexts
3645
+ };
3113
3646
  }
3114
- function _toolCalls(content) {
3647
+ function extractToolCalls(content) {
3115
3648
  if (!Array.isArray(content)) return [];
3116
3649
  const out = [];
3117
3650
  for (const blk of content) {
@@ -3149,7 +3682,7 @@ function _messageText(content) {
3149
3682
  function str3(v) {
3150
3683
  return typeof v === "string" ? v : "";
3151
3684
  }
3152
- function main5() {
3685
+ function main6() {
3153
3686
  let envelope;
3154
3687
  let payload;
3155
3688
  try {
@@ -3167,10 +3700,19 @@ function main5() {
3167
3700
  const transcriptPath = str3(
3168
3701
  payload["transcript_path"] ?? payload["transcriptPath"]
3169
3702
  );
3170
- const { lastAssistant, turnOrdinal, toolCalls } = readTranscriptTail(transcriptPath, {
3171
- maxBytes: TRANSCRIPT_READ_MAX_BYTES
3172
- });
3703
+ const { lastAssistant, turnOrdinal, toolCalls, assistantTurnTexts } = readTranscriptTail(
3704
+ transcriptPath,
3705
+ { maxBytes: TRANSCRIPT_READ_MAX_BYTES }
3706
+ );
3173
3707
  if (!lastAssistant) return EXIT_ALLOW4;
3708
+ const payloadClosing = str3(
3709
+ payload["last_assistant_message"] ?? payload["lastAssistantMessage"]
3710
+ );
3711
+ const closingFromPayload = payloadClosing !== "" && !assistantTurnTexts.includes(payloadClosing);
3712
+ const turnTexts = closingFromPayload ? [...assistantTurnTexts, payloadClosing] : assistantTurnTexts;
3713
+ const promptId = str3(
3714
+ payload["prompt_id"] ?? payload["promptId"]
3715
+ );
3174
3716
  const rawSessionId = str3(envelope["session_id"]) || "";
3175
3717
  const sessionKey = deriveSessionKey(rawSessionId || "unknown-session");
3176
3718
  if (alreadyRefusedTurn(workspaceRoot, sessionKey, turnOrdinal)) return EXIT_ALLOW4;
@@ -3192,7 +3734,23 @@ function main5() {
3192
3734
  // gating is where the comment above says gating belongs — inside the
3193
3735
  // detector: no CI observed, or a settled read, or no completion claim
3194
3736
  // ⇒ no finding.
3195
- dispatchOpen ? null : detectCompletionClaim(lastAssistant, readCiSettled(workspaceRoot, rawSessionId))
3737
+ dispatchOpen ? null : detectCompletionClaim(lastAssistant, readCiSettled(workspaceRoot, rawSessionId)),
3738
+ // Detector E is UNCONDITIONAL, and that is the opposite choice from A
3739
+ // and D one line above rather than an oversight. An open dispatch
3740
+ // excuses a promissory closing because the work is genuinely still
3741
+ // running; it excuses nothing about a question the user was already
3742
+ // asked. Worse: a dispatch — or the `end-review-nudge` stop concern
3743
+ // that produced the measured failure — IS the continuation that drops
3744
+ // the decision, so narrowing E the same way would silence it in exactly
3745
+ // the case it exists for.
3746
+ detectDroppedDecision(turnTexts, closingFromPayload),
3747
+ // Detector F takes the OTHER side of that same question, and the two
3748
+ // sitting adjacent is the clearest place to say why. E fires on a
3749
+ // question already asked, which an open dispatch cannot excuse. F fires
3750
+ // on a completion CLAIM, and a turn waiting on a subagent has not
3751
+ // finished — so its closing is not the claim F is about. Same slot,
3752
+ // opposite trigger, opposite treatment of `dispatchOpen`.
3753
+ dispatchOpen ? null : detectUntestedChange(lastAssistant, toolCalls)
3196
3754
  ]) {
3197
3755
  if (f) findings.push(f);
3198
3756
  }
@@ -3201,7 +3759,8 @@ function main5() {
3201
3759
  workspaceRoot,
3202
3760
  sessionKey,
3203
3761
  turnOrdinal,
3204
- findings.map((f) => f.detector)
3762
+ findings.map((f) => f.detector),
3763
+ promptId
3205
3764
  );
3206
3765
  const lines = findings.map(
3207
3766
  (f) => ` \xB7 ${f.detector}: ${f.reason}
@@ -3210,43 +3769,43 @@ function main5() {
3210
3769
  process.stderr.write(
3211
3770
  `turn-end-gate: REFUSED \u2014 this turn is not finished.
3212
3771
  ${lines.join("\n")}
3213
- Do the promised work now, correct the language, run the verification the edit needs, or read the CI verdict before claiming it \u2014 then end the turn.
3772
+ Do the promised work now, correct the language, run the verification the edit needs, read the CI verdict before claiming it, or re-present the options block this turn dropped \u2014 then end the turn.
3214
3773
  This turn will not be refused a second time.
3215
3774
  `
3216
3775
  );
3217
3776
  return EXIT_BLOCK;
3218
3777
  }
3219
- function _isCliEntry5() {
3778
+ function _isCliEntry6() {
3220
3779
  if (true) {
3221
3780
  return false;
3222
3781
  }
3223
3782
  if (process.argv[1] === void 0) {
3224
3783
  return false;
3225
3784
  }
3226
- const argvUrl = pathToFileURL5(path5.resolve(process.argv[1])).href;
3785
+ const argvUrl = pathToFileURL6(path7.resolve(process.argv[1])).href;
3227
3786
  if (import.meta.url === argvUrl) {
3228
3787
  return true;
3229
3788
  }
3230
3789
  try {
3231
- const here = fs5.realpathSync(fileURLToPath5(import.meta.url));
3232
- const argv = fs5.realpathSync(path5.resolve(process.argv[1]));
3790
+ const here = fs7.realpathSync(fileURLToPath6(import.meta.url));
3791
+ const argv = fs7.realpathSync(path7.resolve(process.argv[1]));
3233
3792
  return here === argv;
3234
3793
  } catch {
3235
3794
  return false;
3236
3795
  }
3237
3796
  }
3238
- if (_isCliEntry5()) {
3239
- process.exit(main5());
3797
+ if (_isCliEntry6()) {
3798
+ process.exit(main6());
3240
3799
  }
3241
3800
 
3242
3801
  // src/scripts/hooks/evidence_independence.ts
3243
3802
  import crypto3 from "node:crypto";
3244
- import fs6 from "node:fs";
3245
- import path6 from "node:path";
3246
- import { fileURLToPath as fileURLToPath6, pathToFileURL as pathToFileURL6 } from "node:url";
3803
+ import fs8 from "node:fs";
3804
+ import path8 from "node:path";
3805
+ import { fileURLToPath as fileURLToPath7, pathToFileURL as pathToFileURL7 } from "node:url";
3247
3806
  var EXIT_ALLOW5 = 0;
3248
3807
  var EXIT_BLOCK2 = 1;
3249
- var STATE_FILE3 = path6.join("agents", "state", "evidence-dispatch.json");
3808
+ var STATE_FILE3 = path8.join("agents", "state", "evidence-dispatch.json");
3250
3809
  function _isObject5(v) {
3251
3810
  return typeof v === "object" && v !== null && !Array.isArray(v);
3252
3811
  }
@@ -3314,8 +3873,8 @@ function extractDispatch(envelope) {
3314
3873
  }
3315
3874
  function _ledgerStamp(consumer_root) {
3316
3875
  try {
3317
- const raw = fs6.readFileSync(
3318
- path6.join(consumer_root, "agents", "state", "git-authorization.json"),
3876
+ const raw = fs8.readFileSync(
3877
+ path8.join(consumer_root, "agents", "state", "git-authorization.json"),
3319
3878
  "utf8"
3320
3879
  );
3321
3880
  const d = JSON.parse(raw);
@@ -3326,7 +3885,7 @@ function _ledgerStamp(consumer_root) {
3326
3885
  }
3327
3886
  function _load(target) {
3328
3887
  try {
3329
- const decoded = JSON.parse(fs6.readFileSync(target, "utf8"));
3888
+ const decoded = JSON.parse(fs8.readFileSync(target, "utf8"));
3330
3889
  if (_isObject5(decoded) && Array.isArray(decoded["evaluations"])) {
3331
3890
  return decoded;
3332
3891
  }
@@ -3384,7 +3943,7 @@ function run3(stdin_text, options) {
3384
3943
  return EXIT_ALLOW5;
3385
3944
  }
3386
3945
  }
3387
- const target = path6.join(options.consumer_root, STATE_FILE3);
3946
+ const target = path8.join(options.consumer_root, STATE_FILE3);
3388
3947
  const state = _load(target);
3389
3948
  const session_id = typeof envelope["session_id"] === "string" ? envelope["session_id"] : "";
3390
3949
  const turnMarker = `${session_id}:${_ledgerStamp(options.consumer_root)}`;
@@ -3422,7 +3981,7 @@ function _errText3(err) {
3422
3981
  const t = err instanceof Error ? err.message : String(err);
3423
3982
  return t.replace(/\s+/g, " ").trim().slice(0, 200);
3424
3983
  }
3425
- function main6(argv) {
3984
+ function main7(argv) {
3426
3985
  const args = argv ?? process.argv.slice(2);
3427
3986
  let consumer_root = process.cwd();
3428
3987
  for (let i = 0; i < args.length; i += 1) {
@@ -3436,33 +3995,33 @@ function main6(argv) {
3436
3995
  }
3437
3996
  return run3(readHookStdin(), { consumer_root });
3438
3997
  }
3439
- function _isCliEntry6() {
3998
+ function _isCliEntry7() {
3440
3999
  if (true) {
3441
4000
  return false;
3442
4001
  }
3443
4002
  if (process.argv[1] === void 0) {
3444
4003
  return false;
3445
4004
  }
3446
- const argvUrl = pathToFileURL6(path6.resolve(process.argv[1])).href;
4005
+ const argvUrl = pathToFileURL7(path8.resolve(process.argv[1])).href;
3447
4006
  if (import.meta.url === argvUrl) {
3448
4007
  return true;
3449
4008
  }
3450
4009
  try {
3451
- const here = fs6.realpathSync(fileURLToPath6(import.meta.url));
3452
- const argv = fs6.realpathSync(path6.resolve(process.argv[1]));
4010
+ const here = fs8.realpathSync(fileURLToPath7(import.meta.url));
4011
+ const argv = fs8.realpathSync(path8.resolve(process.argv[1]));
3453
4012
  return here === argv;
3454
4013
  } catch {
3455
4014
  return false;
3456
4015
  }
3457
4016
  }
3458
- if (_isCliEntry6()) {
3459
- process.exit(main6());
4017
+ if (_isCliEntry7()) {
4018
+ process.exit(main7());
3460
4019
  }
3461
4020
 
3462
4021
  // src/scripts/hooks/delegation_nudge_hook.ts
3463
- import fs7 from "node:fs";
3464
- import path7 from "node:path";
3465
- import { fileURLToPath as fileURLToPath7, pathToFileURL as pathToFileURL7 } from "node:url";
4022
+ import fs9 from "node:fs";
4023
+ import path9 from "node:path";
4024
+ import { fileURLToPath as fileURLToPath8, pathToFileURL as pathToFileURL8 } from "node:url";
3466
4025
 
3467
4026
  // src/scripts/_lib/auto_dispatch.ts
3468
4027
  var SIZE_FLOOR = 1;
@@ -3917,7 +4476,7 @@ function _workspaceRoot(envelope) {
3917
4476
  }
3918
4477
  return process.cwd();
3919
4478
  }
3920
- function main7() {
4479
+ function main8() {
3921
4480
  let envelope = {};
3922
4481
  try {
3923
4482
  const raw = readHookStdin();
@@ -3956,31 +4515,31 @@ function main7() {
3956
4515
  );
3957
4516
  return EXIT_WARN3;
3958
4517
  }
3959
- function _isCliEntry7() {
4518
+ function _isCliEntry8() {
3960
4519
  if (true) {
3961
4520
  return false;
3962
4521
  }
3963
4522
  if (process.argv[1] === void 0) {
3964
4523
  return false;
3965
4524
  }
3966
- const argvUrl = pathToFileURL7(path7.resolve(process.argv[1])).href;
4525
+ const argvUrl = pathToFileURL8(path9.resolve(process.argv[1])).href;
3967
4526
  if (import.meta.url === argvUrl) {
3968
4527
  return true;
3969
4528
  }
3970
4529
  try {
3971
- const here = fs7.realpathSync(fileURLToPath7(import.meta.url));
3972
- const argv = fs7.realpathSync(path7.resolve(process.argv[1]));
4530
+ const here = fs9.realpathSync(fileURLToPath8(import.meta.url));
4531
+ const argv = fs9.realpathSync(path9.resolve(process.argv[1]));
3973
4532
  return here === argv;
3974
4533
  } catch {
3975
4534
  return false;
3976
4535
  }
3977
4536
  }
3978
- if (_isCliEntry7()) {
3979
- process.exit(main7());
4537
+ if (_isCliEntry8()) {
4538
+ process.exit(main8());
3980
4539
  }
3981
4540
 
3982
4541
  // src/scripts/conformance_scan.ts
3983
- var REPO_ROOT = path8.resolve(path8.dirname(fileURLToPath8(import.meta.url)), "..", "..");
4542
+ var REPO_ROOT = path10.resolve(path10.dirname(fileURLToPath9(import.meta.url)), "..", "..");
3984
4543
  var OBSERVED_BAND = { low: 9.1, high: 39.2 };
3985
4544
  var BAND_MIN_TURNS = 1978;
3986
4545
  var CARRIER_CHANGES = [
@@ -4346,7 +4905,7 @@ function scanSession(sessionId, lines) {
4346
4905
  closeWindow();
4347
4906
  return report;
4348
4907
  }
4349
- var DEFAULT_RATE_SERIES = path8.join(
4908
+ var DEFAULT_RATE_SERIES = path10.join(
4350
4909
  REPO_ROOT,
4351
4910
  "agents",
4352
4911
  "runtime",
@@ -4355,7 +4914,7 @@ var DEFAULT_RATE_SERIES = path8.join(
4355
4914
  );
4356
4915
  function defaultStore(projectDir) {
4357
4916
  const slug = projectStoreSlug(projectDir);
4358
- return path8.join(process.env["HOME"] ?? "", ".claude", "projects", slug);
4917
+ return path10.join(process.env["HOME"] ?? "", ".claude", "projects", slug);
4359
4918
  }
4360
4919
  function _tokens(chars) {
4361
4920
  return Math.round(chars / 4);
@@ -4366,13 +4925,13 @@ function measureDelivered(projectRulesDir, globalRulesDir) {
4366
4925
  return {
4367
4926
  project: {
4368
4927
  dir: projectRulesDir,
4369
- present: fs8.existsSync(projectRulesDir),
4928
+ present: fs10.existsSync(projectRulesDir),
4370
4929
  files: p.files,
4371
4930
  tokens: _tokens(p.chars)
4372
4931
  },
4373
4932
  global: {
4374
4933
  dir: globalRulesDir,
4375
- present: fs8.existsSync(globalRulesDir),
4934
+ present: fs10.existsSync(globalRulesDir),
4376
4935
  files: g.files,
4377
4936
  tokens: _tokens(g.chars)
4378
4937
  },
@@ -4380,13 +4939,13 @@ function measureDelivered(projectRulesDir, globalRulesDir) {
4380
4939
  };
4381
4940
  }
4382
4941
  function storeKey(store) {
4383
- return createHash3("sha256").update(path8.resolve(store)).digest("hex").slice(0, 12);
4942
+ return createHash3("sha256").update(path10.resolve(store)).digest("hex").slice(0, 12);
4384
4943
  }
4385
4944
  function scanStore(store, limit) {
4386
- 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);
4945
+ 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);
4387
4946
  const per_session = [];
4388
4947
  for (const f of files) {
4389
- const lines = fs8.readFileSync(path8.join(store, f), "utf8").split("\n");
4948
+ const lines = fs10.readFileSync(path10.join(store, f), "utf8").split("\n");
4390
4949
  const r = scanSession(f.replace(/\.jsonl$/, "").slice(0, 8), lines);
4391
4950
  if (r.assistant_turns > 0) {
4392
4951
  per_session.push(r);
@@ -4414,10 +4973,10 @@ function scanStore(store, limit) {
4414
4973
  const task_completeness_rate_pct = completeness_windows === 0 ? 0 : Number((100 * task_completeness / completeness_windows).toFixed(1));
4415
4974
  const era = spansCarrierChange(per_session.map((s) => s.first_at));
4416
4975
  const delivered = measureDelivered(
4417
- path8.join(REPO_ROOT, ".claude", "rules"),
4418
- path8.join(process.env["HOME"] ?? os2.homedir(), ".claude", "rules")
4976
+ path10.join(REPO_ROOT, ".claude", "rules"),
4977
+ path10.join(process.env["HOME"] ?? os2.homedir(), ".claude", "rules")
4419
4978
  );
4420
- const ownStore = path8.resolve(store) === path8.resolve(defaultStore(REPO_ROOT));
4979
+ const ownStore = path10.resolve(store) === path10.resolve(defaultStore(REPO_ROOT));
4421
4980
  return {
4422
4981
  scanned_at: (/* @__PURE__ */ new Date()).toISOString(),
4423
4982
  store,
@@ -4447,8 +5006,8 @@ function scanStore(store, limit) {
4447
5006
  };
4448
5007
  }
4449
5008
  function recordRate(file, scanned_at, rate) {
4450
- fs8.mkdirSync(path8.dirname(file), { recursive: true });
4451
- fs8.appendFileSync(file, `${JSON.stringify({ measured_at: scanned_at, ...rate })}
5009
+ fs10.mkdirSync(path10.dirname(file), { recursive: true });
5010
+ fs10.appendFileSync(file, `${JSON.stringify({ measured_at: scanned_at, ...rate })}
4452
5011
  `, "utf8");
4453
5012
  }
4454
5013
  function render(report) {
@@ -4547,7 +5106,7 @@ function render(report) {
4547
5106
  lines.push(" checkbox batching \u2014 measured NOWHERE. ~5 low-severity findings.");
4548
5107
  return lines.join("\n");
4549
5108
  }
4550
- function main8(argv) {
5109
+ function main9(argv) {
4551
5110
  const args = argv ?? process.argv.slice(2);
4552
5111
  let store = null;
4553
5112
  let limit = 30;
@@ -4579,14 +5138,14 @@ function main8(argv) {
4579
5138
  return 2;
4580
5139
  }
4581
5140
  const resolved = store ?? defaultStore(process.cwd());
4582
- if (!fs8.existsSync(resolved)) {
5141
+ if (!fs10.existsSync(resolved)) {
4583
5142
  process.stderr.write(`conformance:behavior: no transcript store at ${resolved}
4584
5143
  `);
4585
5144
  return 1;
4586
5145
  }
4587
5146
  const report = scanStore(resolved, Number.isFinite(limit) && limit > 0 ? limit : 30);
4588
5147
  if (out) {
4589
- fs8.writeFileSync(out, `${JSON.stringify(report, null, 2)}
5148
+ fs10.writeFileSync(out, `${JSON.stringify(report, null, 2)}
4590
5149
  `, "utf8");
4591
5150
  }
4592
5151
  if (record) {
@@ -4594,7 +5153,7 @@ function main8(argv) {
4594
5153
  }
4595
5154
  if (why !== null) {
4596
5155
  const id = why;
4597
- fs8.writeSync(
5156
+ fs10.writeSync(
4598
5157
  1,
4599
5158
  json ? `${JSON.stringify(
4600
5159
  {
@@ -4614,48 +5173,48 @@ function main8(argv) {
4614
5173
  );
4615
5174
  return 0;
4616
5175
  }
4617
- fs8.writeSync(1, json ? `${JSON.stringify(report, null, 2)}
5176
+ fs10.writeSync(1, json ? `${JSON.stringify(report, null, 2)}
4618
5177
  ` : `${render(report)}
4619
5178
  `);
4620
5179
  return 0;
4621
5180
  }
4622
- function _isCliEntry8() {
5181
+ function _isCliEntry9() {
4623
5182
  if (true) {
4624
5183
  return false;
4625
5184
  }
4626
5185
  if (process.argv[1] === void 0) {
4627
5186
  return false;
4628
5187
  }
4629
- const argvUrl = pathToFileURL8(path8.resolve(process.argv[1])).href;
5188
+ const argvUrl = pathToFileURL9(path10.resolve(process.argv[1])).href;
4630
5189
  if (import.meta.url === argvUrl) {
4631
5190
  return true;
4632
5191
  }
4633
5192
  try {
4634
- const here = fs8.realpathSync(fileURLToPath8(import.meta.url));
4635
- const argv = fs8.realpathSync(path8.resolve(process.argv[1]));
5193
+ const here = fs10.realpathSync(fileURLToPath9(import.meta.url));
5194
+ const argv = fs10.realpathSync(path10.resolve(process.argv[1]));
4636
5195
  return here === argv;
4637
5196
  } catch {
4638
5197
  return false;
4639
5198
  }
4640
5199
  }
4641
- if (_isCliEntry8()) {
4642
- process.exit(main8());
5200
+ if (_isCliEntry9()) {
5201
+ process.exit(main9());
4643
5202
  }
4644
5203
 
4645
5204
  // src/scripts/report_carrier_divergence.ts
4646
- import * as fs9 from "node:fs";
5205
+ import * as fs11 from "node:fs";
4647
5206
  import * as os3 from "node:os";
4648
- import * as path9 from "node:path";
5207
+ import * as path11 from "node:path";
4649
5208
  import process2 from "node:process";
4650
- import { fileURLToPath as fileURLToPath9, pathToFileURL as pathToFileURL9 } from "node:url";
4651
- var _HERE = fileURLToPath9(import.meta.url);
4652
- var REPO_ROOT2 = path9.resolve(path9.dirname(_HERE), "..", "..");
4653
- var PROJECT_RULES = path9.join(".claude", "rules");
4654
- var PROJECTION_SOURCE = path9.join("dist", "agent-src", "rules");
4655
- var GLOBAL_RULES = path9.join(".claude", "rules");
5209
+ import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL10 } from "node:url";
5210
+ var _HERE2 = fileURLToPath10(import.meta.url);
5211
+ var REPO_ROOT2 = path11.resolve(path11.dirname(_HERE2), "..", "..");
5212
+ var PROJECT_RULES = path11.join(".claude", "rules");
5213
+ var PROJECTION_SOURCE = path11.join("dist", "agent-src", "rules");
5214
+ var GLOBAL_RULES = path11.join(".claude", "rules");
4656
5215
  function _listRules(dir) {
4657
5216
  try {
4658
- return fs9.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
5217
+ return fs11.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
4659
5218
  } catch {
4660
5219
  return [];
4661
5220
  }
@@ -4663,7 +5222,7 @@ function _listRules(dir) {
4663
5222
  function _ruleType(file) {
4664
5223
  let text;
4665
5224
  try {
4666
- text = fs9.readFileSync(file, "utf-8");
5225
+ text = fs11.readFileSync(file, "utf-8");
4667
5226
  } catch {
4668
5227
  return "";
4669
5228
  }
@@ -4674,8 +5233,8 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
4674
5233
  const out = {
4675
5234
  projectDir,
4676
5235
  globalDir,
4677
- globalPresent: fs9.existsSync(globalDir),
4678
- projectPresent: fs9.existsSync(projectDir),
5236
+ globalPresent: fs11.existsSync(globalDir),
5237
+ projectPresent: fs11.existsSync(projectDir),
4679
5238
  shared: 0,
4680
5239
  identical: [],
4681
5240
  provenanceOnly: [],
@@ -4698,7 +5257,7 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
4698
5257
  }
4699
5258
  if (!inP && inG) {
4700
5259
  out.globalOnly.push(rule);
4701
- if (sourceDir !== void 0 && _ruleType(path9.join(sourceDir, rule)) === "manual") {
5260
+ if (sourceDir !== void 0 && _ruleType(path11.join(sourceDir, rule)) === "manual") {
4702
5261
  out.manualOnlyGlobal.push(rule);
4703
5262
  }
4704
5263
  continue;
@@ -4708,8 +5267,8 @@ function compareCarriers(projectDir, globalDir, sourceDir) {
4708
5267
  let projectCopy;
4709
5268
  let globalCopy;
4710
5269
  try {
4711
- projectCopy = fs9.readFileSync(path9.join(projectDir, rule));
4712
- globalCopy = fs9.readFileSync(path9.join(globalDir, rule));
5270
+ projectCopy = fs11.readFileSync(path11.join(projectDir, rule));
5271
+ globalCopy = fs11.readFileSync(path11.join(globalDir, rule));
4713
5272
  verdict = comparePair(projectCopy, globalCopy);
4714
5273
  } catch {
4715
5274
  out.shared -= 1;
@@ -4854,11 +5413,11 @@ function render2(d) {
4854
5413
  }
4855
5414
  return lines.join("\n");
4856
5415
  }
4857
- function main9(argv) {
5416
+ function main10(argv) {
4858
5417
  const args = argv ?? process2.argv.slice(2);
4859
- let projectDir = path9.join(REPO_ROOT2, PROJECT_RULES);
4860
- let globalDir = path9.join(os3.homedir(), GLOBAL_RULES);
4861
- let sourceDir = path9.join(REPO_ROOT2, PROJECTION_SOURCE);
5418
+ let projectDir = path11.join(REPO_ROOT2, PROJECT_RULES);
5419
+ let globalDir = path11.join(os3.homedir(), GLOBAL_RULES);
5420
+ let sourceDir = path11.join(REPO_ROOT2, PROJECTION_SOURCE);
4862
5421
  const value = (i) => {
4863
5422
  const v = args[i + 1];
4864
5423
  return v === void 0 || v.startsWith("-") ? null : v;
@@ -4872,7 +5431,7 @@ function main9(argv) {
4872
5431
  `);
4873
5432
  return 1;
4874
5433
  }
4875
- const resolved = path9.resolve(v);
5434
+ const resolved = path11.resolve(v);
4876
5435
  if (a === "--project") projectDir = resolved;
4877
5436
  else if (a === "--global") globalDir = resolved;
4878
5437
  else sourceDir = resolved;
@@ -4892,26 +5451,26 @@ function main9(argv) {
4892
5451
  `);
4893
5452
  return 0;
4894
5453
  }
4895
- function _isCliEntry9() {
5454
+ function _isCliEntry10() {
4896
5455
  if (process2.argv[1] === void 0) return false;
4897
- if (import.meta.url === pathToFileURL9(path9.resolve(process2.argv[1])).href) return true;
5456
+ if (import.meta.url === pathToFileURL10(path11.resolve(process2.argv[1])).href) return true;
4898
5457
  try {
4899
- return fs9.realpathSync(_HERE) === fs9.realpathSync(path9.resolve(process2.argv[1]));
5458
+ return fs11.realpathSync(_HERE2) === fs11.realpathSync(path11.resolve(process2.argv[1]));
4900
5459
  } catch {
4901
5460
  return false;
4902
5461
  }
4903
5462
  }
4904
- if (_isCliEntry9()) {
4905
- process2.exit(main9());
5463
+ if (_isCliEntry10()) {
5464
+ process2.exit(main10());
4906
5465
  }
4907
5466
 
4908
5467
  // src/scripts/report_skill_activation.ts
4909
- import * as fs10 from "node:fs";
5468
+ import * as fs12 from "node:fs";
4910
5469
  import * as os4 from "node:os";
4911
- import * as path10 from "node:path";
4912
- import { fileURLToPath as fileURLToPath10, pathToFileURL as pathToFileURL10 } from "node:url";
4913
- var _HERE2 = fileURLToPath10(import.meta.url);
4914
- var REPO_ROOT3 = path10.resolve(path10.dirname(_HERE2), "..", "..");
5470
+ import * as path12 from "node:path";
5471
+ import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL11 } from "node:url";
5472
+ var _HERE3 = fileURLToPath11(import.meta.url);
5473
+ var REPO_ROOT3 = path12.resolve(path12.dirname(_HERE3), "..", "..");
4915
5474
  var SKILLS_ROOT = "src/skills";
4916
5475
  var TRIGGER_KEYS = ["triggers:", "trigger_description:", "file_pattern:", "path_prefix:"];
4917
5476
  var DETERMINISTIC_RE = /^\s*(?:[-*]\s*)?(?:\*\*)?(MUST|NEVER|ALWAYS)\b/m;
@@ -4922,25 +5481,25 @@ function censusSkills(root) {
4922
5481
  withTriggerCorpus: [],
4923
5482
  withDeterministicObligation: []
4924
5483
  };
4925
- if (!fs10.existsSync(root)) {
5484
+ if (!fs12.existsSync(root)) {
4926
5485
  return out;
4927
5486
  }
4928
- for (const entry of fs10.readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
5487
+ for (const entry of fs12.readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
4929
5488
  if (!entry.isDirectory()) {
4930
5489
  continue;
4931
5490
  }
4932
- const file = path10.join(root, entry.name, "SKILL.md");
4933
- if (!fs10.existsSync(file)) {
5491
+ const file = path12.join(root, entry.name, "SKILL.md");
5492
+ if (!fs12.existsSync(file)) {
4934
5493
  continue;
4935
5494
  }
4936
5495
  out.total += 1;
4937
- const text = fs10.readFileSync(file, "utf8");
5496
+ const text = fs12.readFileSync(file, "utf8");
4938
5497
  const fmEnd = text.startsWith("---") ? text.indexOf("\n---", 3) : -1;
4939
5498
  const fm = fmEnd === -1 ? "" : text.slice(0, fmEnd);
4940
5499
  if (TRIGGER_KEYS.some((k) => new RegExp(`^${k}`, "m").test(fm))) {
4941
5500
  out.withTriggerKey.push(entry.name);
4942
5501
  }
4943
- if (fs10.existsSync(path10.join(root, entry.name, "evals", "triggers.json"))) {
5502
+ if (fs12.existsSync(path12.join(root, entry.name, "evals", "triggers.json"))) {
4944
5503
  out.withTriggerCorpus.push(entry.name);
4945
5504
  }
4946
5505
  const body = fmEnd === -1 ? text : text.slice(fmEnd + 4);
@@ -4951,17 +5510,17 @@ function censusSkills(root) {
4951
5510
  return out;
4952
5511
  }
4953
5512
  function defaultStore2(cwd) {
4954
- return path10.join(os4.homedir(), ".claude", "projects", projectStoreSlug(cwd));
5513
+ return path12.join(os4.homedir(), ".claude", "projects", projectStoreSlug(cwd));
4955
5514
  }
4956
5515
  function measureUsage(store, limit) {
4957
5516
  const rep = { store, sessions: 0, assistantTurns: 0, invocations: 0, bySkill: {} };
4958
- if (!fs10.existsSync(store)) {
5517
+ if (!fs12.existsSync(store)) {
4959
5518
  return rep;
4960
5519
  }
4961
- 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);
5520
+ 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);
4962
5521
  rep.sessions = files.length;
4963
5522
  for (const file of files) {
4964
- for (const line of fs10.readFileSync(file, "utf8").split("\n")) {
5523
+ for (const line of fs12.readFileSync(file, "utf8").split("\n")) {
4965
5524
  if (!line.trim()) {
4966
5525
  continue;
4967
5526
  }
@@ -5034,15 +5593,15 @@ function buildRecord(census, usage, today) {
5034
5593
  assistant_turns: usage.reduce((a, u) => a + u.assistantTurns, 0),
5035
5594
  invocations: usage.reduce((a, u) => a + u.invocations, 0),
5036
5595
  distinct_skills_invoked: distinct.size,
5037
- stores: usage.map((u) => path10.basename(u.store))
5596
+ stores: usage.map((u) => path12.basename(u.store))
5038
5597
  };
5039
5598
  }
5040
5599
  function readRecord(repoRoot) {
5041
- const file = path10.join(repoRoot, RECORD_PATH);
5042
- if (!fs10.existsSync(file)) {
5600
+ const file = path12.join(repoRoot, RECORD_PATH);
5601
+ if (!fs12.existsSync(file)) {
5043
5602
  return null;
5044
5603
  }
5045
- return JSON.parse(fs10.readFileSync(file, "utf8"));
5604
+ return JSON.parse(fs12.readFileSync(file, "utf8"));
5046
5605
  }
5047
5606
  function render3(census, usage, published = null) {
5048
5607
  const lines = [];
@@ -5077,7 +5636,7 @@ function render3(census, usage, published = null) {
5077
5636
  }
5078
5637
  totalInv += u.invocations;
5079
5638
  lines.push(
5080
- ` ${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)}`
5639
+ ` ${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)}`
5081
5640
  );
5082
5641
  }
5083
5642
  lines.push("");
@@ -5147,8 +5706,8 @@ function render3(census, usage, published = null) {
5147
5706
  lines.push(" catalogue once per session, then count descriptions against bare names.");
5148
5707
  return lines.join("\n");
5149
5708
  }
5150
- var USAGE = "usage: report_skill_activation [--root DIR] [--limit N] [--store PATH]... [--emit] [--allow-empty-store]\n";
5151
- function main10(argv) {
5709
+ var USAGE2 = "usage: report_skill_activation [--root DIR] [--limit N] [--store PATH]... [--emit] [--allow-empty-store]\n";
5710
+ function main11(argv) {
5152
5711
  let limit = 30;
5153
5712
  let emit = false;
5154
5713
  let allowEmpty = false;
@@ -5170,7 +5729,7 @@ function main10(argv) {
5170
5729
  } else if (a === "--allow-empty-store") {
5171
5730
  allowEmpty = true;
5172
5731
  } else if (a === "--help" || a === "-h") {
5173
- process.stdout.write(USAGE);
5732
+ process.stdout.write(USAGE2);
5174
5733
  return 0;
5175
5734
  }
5176
5735
  }
@@ -5181,7 +5740,7 @@ function main10(argv) {
5181
5740
  if (stores.length === 0) {
5182
5741
  stores.push(defaultStore2(REPO_ROOT3));
5183
5742
  }
5184
- const census = censusSkills(path10.join(root, SKILLS_ROOT));
5743
+ const census = censusSkills(path12.join(root, SKILLS_ROOT));
5185
5744
  const usage = stores.map((s) => measureUsage(s, limit));
5186
5745
  process.stdout.write(`${render3(census, usage, readRecord(root))}
5187
5746
  `);
@@ -5202,27 +5761,27 @@ function main10(argv) {
5202
5761
  return 1;
5203
5762
  }
5204
5763
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5205
- const file = path10.join(root, RECORD_PATH);
5206
- fs10.mkdirSync(path10.dirname(file), { recursive: true });
5207
- fs10.writeFileSync(file, `${JSON.stringify(buildRecord(census, usage, today), null, 2)}
5764
+ const file = path12.join(root, RECORD_PATH);
5765
+ fs12.mkdirSync(path12.dirname(file), { recursive: true });
5766
+ fs12.writeFileSync(file, `${JSON.stringify(buildRecord(census, usage, today), null, 2)}
5208
5767
  `);
5209
5768
  process.stdout.write(`
5210
5769
  wrote ${RECORD_PATH} (measured ${today})
5211
5770
  `);
5212
5771
  return 0;
5213
5772
  }
5214
- if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL10(path10.resolve(process.argv[1])).href) {
5215
- process.exit(main10(process.argv.slice(2)));
5773
+ if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL11(path12.resolve(process.argv[1])).href) {
5774
+ process.exit(main11(process.argv.slice(2)));
5216
5775
  }
5217
5776
 
5218
5777
  // src/scripts/report_skill_obligation_violations.ts
5219
- import * as fs11 from "node:fs";
5778
+ import * as fs13 from "node:fs";
5220
5779
  import * as os5 from "node:os";
5221
- import * as path11 from "node:path";
5780
+ import * as path13 from "node:path";
5222
5781
  import process3 from "node:process";
5223
- import { fileURLToPath as fileURLToPath11, pathToFileURL as pathToFileURL11 } from "node:url";
5224
- var _HERE3 = fileURLToPath11(import.meta.url);
5225
- var REPO_ROOT4 = path11.resolve(path11.dirname(_HERE3), "..", "..");
5782
+ import { fileURLToPath as fileURLToPath12, pathToFileURL as pathToFileURL12 } from "node:url";
5783
+ var _HERE4 = fileURLToPath12(import.meta.url);
5784
+ var REPO_ROOT4 = path13.resolve(path13.dirname(_HERE4), "..", "..");
5226
5785
  var OBLIGATION_LINE_RE = new RegExp(`${DETERMINISTIC_RE.source}.*`, "gm");
5227
5786
  var PATH_RE = /`([A-Za-z0-9_./-]*\/[A-Za-z0-9_.-]+\.[a-z]{2,6})`/g;
5228
5787
  var CMD_RE = /`([a-z][a-z0-9-]*(?: [a-z][a-z0-9:._-]*){1,3})`/g;
@@ -5260,7 +5819,7 @@ function _artefacts(line) {
5260
5819
  return out;
5261
5820
  }
5262
5821
  function extractObligations(repoRoot) {
5263
- const skillsRoot = path11.join(repoRoot, SKILLS_ROOT);
5822
+ const skillsRoot = path13.join(repoRoot, SKILLS_ROOT);
5264
5823
  const census = censusSkills(skillsRoot);
5265
5824
  const out = {
5266
5825
  skills: census.withDeterministicObligation,
@@ -5274,7 +5833,7 @@ function extractObligations(repoRoot) {
5274
5833
  for (const skill of census.withDeterministicObligation) {
5275
5834
  let text;
5276
5835
  try {
5277
- text = fs11.readFileSync(path11.join(skillsRoot, skill, "SKILL.md"), "utf-8");
5836
+ text = fs13.readFileSync(path13.join(skillsRoot, skill, "SKILL.md"), "utf-8");
5278
5837
  } catch {
5279
5838
  continue;
5280
5839
  }
@@ -5390,7 +5949,7 @@ function scanSessionForViolations(session, lines, forbidden, parsed) {
5390
5949
  return flags;
5391
5950
  }
5392
5951
  function defaultStore3(cwd) {
5393
- return path11.join(os5.homedir(), ".claude", "projects", projectStoreSlug(cwd));
5952
+ return path13.join(os5.homedir(), ".claude", "projects", projectStoreSlug(cwd));
5394
5953
  }
5395
5954
  function scanStore2(repoRoot, store, limit) {
5396
5955
  const census = extractObligations(repoRoot);
@@ -5403,14 +5962,14 @@ function scanStore2(repoRoot, store, limit) {
5403
5962
  };
5404
5963
  let files;
5405
5964
  try {
5406
- 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);
5965
+ 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);
5407
5966
  } catch {
5408
5967
  return report;
5409
5968
  }
5410
5969
  report.sessions = files.length;
5411
5970
  for (const file of files) {
5412
- const lines = fs11.readFileSync(file, "utf-8").split("\n");
5413
- const id = path11.basename(file).replace(/\.jsonl$/, "").slice(0, 8);
5971
+ const lines = fs13.readFileSync(file, "utf-8").split("\n");
5972
+ const id = path13.basename(file).replace(/\.jsonl$/, "").slice(0, 8);
5414
5973
  const entries = _parseSession(lines);
5415
5974
  if (loadedSkillsFrom(entries).size > 0) report.sessionsWithASkill += 1;
5416
5975
  report.flags.push(...scanSessionForViolations(id, lines, census.forbidden, entries));
@@ -5480,7 +6039,7 @@ function render4(r) {
5480
6039
  lines.push(" ships as detection-only, and this one says so.");
5481
6040
  return lines.join("\n");
5482
6041
  }
5483
- function main11(argv) {
6042
+ function main12(argv) {
5484
6043
  const args = argv ?? process3.argv.slice(2);
5485
6044
  let limit = 30;
5486
6045
  let json = false;
@@ -5533,35 +6092,35 @@ function main11(argv) {
5533
6092
  }
5534
6093
  return 0;
5535
6094
  }
5536
- function _isCliEntry10() {
6095
+ function _isCliEntry11() {
5537
6096
  if (process3.argv[1] === void 0) return false;
5538
- if (import.meta.url === pathToFileURL11(path11.resolve(process3.argv[1])).href) return true;
6097
+ if (import.meta.url === pathToFileURL12(path13.resolve(process3.argv[1])).href) return true;
5539
6098
  try {
5540
- return fs11.realpathSync(_HERE3) === fs11.realpathSync(path11.resolve(process3.argv[1]));
6099
+ return fs13.realpathSync(_HERE4) === fs13.realpathSync(path13.resolve(process3.argv[1]));
5541
6100
  } catch {
5542
6101
  return false;
5543
6102
  }
5544
6103
  }
5545
- if (_isCliEntry10()) {
5546
- process3.exit(main11());
6104
+ if (_isCliEntry11()) {
6105
+ process3.exit(main12());
5547
6106
  }
5548
6107
 
5549
6108
  // src/scripts/report_conformance_funnel.ts
5550
- var _HERE4 = fileURLToPath12(import.meta.url);
5551
- var REPO_ROOT5 = path12.resolve(path12.dirname(_HERE4), "..", "..");
6109
+ var _HERE5 = fileURLToPath13(import.meta.url);
6110
+ var REPO_ROOT5 = path14.resolve(path14.dirname(_HERE5), "..", "..");
5552
6111
  function buildFunnel(opts = {}) {
5553
6112
  const repoRoot = opts.repoRoot ?? REPO_ROOT5;
5554
- const projectRulesDir = opts.projectRulesDir ?? path12.join(repoRoot, PROJECT_RULES);
5555
- const globalRulesDir = opts.globalRulesDir ?? path12.join(os6.homedir(), GLOBAL_RULES);
5556
- const sourceDir = opts.sourceDir ?? path12.join(repoRoot, PROJECTION_SOURCE);
6113
+ const projectRulesDir = opts.projectRulesDir ?? path14.join(repoRoot, PROJECT_RULES);
6114
+ const globalRulesDir = opts.globalRulesDir ?? path14.join(os6.homedir(), GLOBAL_RULES);
6115
+ const sourceDir = opts.sourceDir ?? path14.join(repoRoot, PROJECTION_SOURCE);
5557
6116
  const store = opts.store ?? defaultStore(repoRoot);
5558
6117
  const limit = opts.limit ?? 30;
5559
6118
  return {
5560
6119
  delivered: measureDelivered(projectRulesDir, globalRulesDir),
5561
6120
  divergence: compareCarriers(projectRulesDir, globalRulesDir, sourceDir),
5562
- skills: censusSkills(path12.join(repoRoot, SKILLS_ROOT)),
6121
+ skills: censusSkills(path14.join(repoRoot, SKILLS_ROOT)),
5563
6122
  usage: measureUsage(store, limit),
5564
- storePresent: fs12.existsSync(store),
6123
+ storePresent: fs14.existsSync(store),
5565
6124
  sk2: scanStore2(repoRoot, store, limit)
5566
6125
  };
5567
6126
  }
@@ -5686,7 +6245,7 @@ function render5(r) {
5686
6245
  lines.push("workflow without a measured false-positive rate first (locked policy).");
5687
6246
  return lines.join("\n");
5688
6247
  }
5689
- function main12(argv) {
6248
+ function main13(argv) {
5690
6249
  const args = argv ?? process4.argv.slice(2);
5691
6250
  const opts = {};
5692
6251
  const value = (i) => {
@@ -5702,7 +6261,7 @@ function main12(argv) {
5702
6261
  `);
5703
6262
  return 1;
5704
6263
  }
5705
- const resolved = path12.resolve(v);
6264
+ const resolved = path14.resolve(v);
5706
6265
  if (a === "--store") opts.store = resolved;
5707
6266
  else if (a === "--project") opts.projectRulesDir = resolved;
5708
6267
  else if (a === "--global") opts.globalRulesDir = resolved;
@@ -5732,21 +6291,21 @@ function main12(argv) {
5732
6291
  `);
5733
6292
  return 0;
5734
6293
  }
5735
- function _isCliEntry11() {
6294
+ function _isCliEntry12() {
5736
6295
  if (process4.argv[1] === void 0) return false;
5737
- if (import.meta.url === pathToFileURL12(path12.resolve(process4.argv[1])).href) return true;
6296
+ if (import.meta.url === pathToFileURL13(path14.resolve(process4.argv[1])).href) return true;
5738
6297
  try {
5739
- return fs12.realpathSync(_HERE4) === fs12.realpathSync(path12.resolve(process4.argv[1]));
6298
+ return fs14.realpathSync(_HERE5) === fs14.realpathSync(path14.resolve(process4.argv[1]));
5740
6299
  } catch {
5741
6300
  return false;
5742
6301
  }
5743
6302
  }
5744
- if (_isCliEntry11()) {
5745
- process4.exit(main12());
6303
+ if (_isCliEntry12()) {
6304
+ process4.exit(main13());
5746
6305
  }
5747
6306
 
5748
6307
  // src/scripts/_cli/cmd_conformance.ts
5749
- var _HERE5 = fileURLToPath13(import.meta.url);
6308
+ var _HERE6 = fileURLToPath14(import.meta.url);
5750
6309
  var PACKAGE_ROOT = resolvePackageRoot(import.meta.url);
5751
6310
  var CONFORMANCE_CHECK_IDS = [
5752
6311
  "txlog-clean",
@@ -5769,17 +6328,17 @@ function conformanceLogPath() {
5769
6328
  if (override && override.trim().length > 0) {
5770
6329
  return override;
5771
6330
  }
5772
- return path13.join(os7.homedir(), ".event4u", "agent-config", "conformance-log.jsonl");
6331
+ return path15.join(os7.homedir(), ".event4u", "agent-config", "conformance-log.jsonl");
5773
6332
  }
5774
6333
  function installLogPath() {
5775
6334
  const override = process5.env["AGENT_CONFIG_INSTALL_LOG"];
5776
6335
  if (override && override.trim().length > 0) {
5777
6336
  return override;
5778
6337
  }
5779
- return path13.join(os7.homedir(), ".event4u", "agent-config", "install-log.jsonl");
6338
+ return path15.join(os7.homedir(), ".event4u", "agent-config", "install-log.jsonl");
5780
6339
  }
5781
6340
  function _check_txlog_clean(logPath = installLogPath()) {
5782
- if (!fs13.existsSync(logPath)) {
6341
+ if (!fs15.existsSync(logPath)) {
5783
6342
  return {
5784
6343
  id: "txlog-clean",
5785
6344
  status: "ok",
@@ -5813,11 +6372,11 @@ function _check_txlog_clean(logPath = installLogPath()) {
5813
6372
  };
5814
6373
  }
5815
6374
  function routeTargetPaths(target) {
5816
- return routeTargetPathsPosix(target).map((rel) => path13.join(...rel.split("/")));
6375
+ return routeTargetPathsPosix(target).map((rel) => path15.join(...rel.split("/")));
5817
6376
  }
5818
6377
  function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
5819
- const routerPath = path13.join(packageRoot, "dist", "router.json");
5820
- if (!fs13.existsSync(routerPath)) {
6378
+ const routerPath = path15.join(packageRoot, "dist", "router.json");
6379
+ if (!fs15.existsSync(routerPath)) {
5821
6380
  return {
5822
6381
  id: "router-pointers",
5823
6382
  status: "fail",
@@ -5827,7 +6386,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
5827
6386
  }
5828
6387
  let router;
5829
6388
  try {
5830
- router = JSON.parse(fs13.readFileSync(routerPath, "utf8"));
6389
+ router = JSON.parse(fs15.readFileSync(routerPath, "utf8"));
5831
6390
  } catch (exc) {
5832
6391
  return {
5833
6392
  id: "router-pointers",
@@ -5836,13 +6395,13 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
5836
6395
  remedy: "reinstall the package \u2014 dist/router.json is corrupt"
5837
6396
  };
5838
6397
  }
5839
- const rulesDir = path13.join(packageRoot, "dist", "agent-src", "rules");
6398
+ const rulesDir = path15.join(packageRoot, "dist", "agent-src", "rules");
5840
6399
  const broken = [];
5841
6400
  let ids = 0;
5842
6401
  let targets = 0;
5843
6402
  for (const kernelId of router["kernel"] ?? []) {
5844
6403
  ids += 1;
5845
- if (!fs13.existsSync(path13.join(rulesDir, `${kernelId}.md`))) {
6404
+ if (!fs15.existsSync(path15.join(rulesDir, `${kernelId}.md`))) {
5846
6405
  broken.push(`kernel:${kernelId} \u2192 rules/${kernelId}.md missing`);
5847
6406
  }
5848
6407
  }
@@ -5850,7 +6409,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
5850
6409
  for (const entry of router[tier] ?? []) {
5851
6410
  const ruleId = String(entry["id"] ?? "");
5852
6411
  ids += 1;
5853
- if (!fs13.existsSync(path13.join(rulesDir, `${ruleId}.md`))) {
6412
+ if (!fs15.existsSync(path15.join(rulesDir, `${ruleId}.md`))) {
5854
6413
  broken.push(`${tier}:${ruleId} \u2192 rules/${ruleId}.md missing`);
5855
6414
  }
5856
6415
  for (const target of entry["routes_to"] ?? []) {
@@ -5860,7 +6419,7 @@ function _check_router_pointers(packageRoot = PACKAGE_ROOT) {
5860
6419
  broken.push(`${ruleId} \u2192 unparseable routes_to ${JSON.stringify(target)}`);
5861
6420
  continue;
5862
6421
  }
5863
- if (!candidates.some((rel) => fs13.existsSync(path13.join(packageRoot, rel)))) {
6422
+ if (!candidates.some((rel) => fs15.existsSync(path15.join(packageRoot, rel)))) {
5864
6423
  broken.push(`${ruleId} \u2192 ${target} (${candidates[0]} missing)`);
5865
6424
  }
5866
6425
  }
@@ -5892,9 +6451,9 @@ function detectSmokePlatform(projectRoot) {
5892
6451
  return "claude";
5893
6452
  }
5894
6453
  function dispatcherRunner(packageRoot) {
5895
- const localTsx = path13.join(packageRoot, "node_modules", ".bin", "tsx");
5896
- const script = path13.join(packageRoot, "src", "scripts", "hooks", "dispatch_hook.ts");
5897
- if (fs13.existsSync(localTsx)) {
6454
+ const localTsx = path15.join(packageRoot, "node_modules", ".bin", "tsx");
6455
+ const script = path15.join(packageRoot, "src", "scripts", "hooks", "dispatch_hook.ts");
6456
+ if (fs15.existsSync(localTsx)) {
5898
6457
  return [localTsx, script];
5899
6458
  }
5900
6459
  return ["npx", "tsx", script];
@@ -5911,7 +6470,7 @@ function _check_hook_dispatcher(projectRoot, packageRoot = PACKAGE_ROOT, opts =
5911
6470
  ...event === "stop" ? { stop_reason: "conformance-smoke" } : { source: "startup" }
5912
6471
  });
5913
6472
  const argv = [...runner, "--platform", platform, "--event", event];
5914
- const proc = spawnSync2(argv[0], argv.slice(1), {
6473
+ const proc = spawnSync3(argv[0], argv.slice(1), {
5915
6474
  input: payload,
5916
6475
  cwd: projectRoot,
5917
6476
  encoding: "utf8",
@@ -5944,12 +6503,12 @@ function _check_hook_dispatcher(projectRoot, packageRoot = PACKAGE_ROOT, opts =
5944
6503
  };
5945
6504
  }
5946
6505
  function readSettingsMode(projectRoot) {
5947
- const settingsPath = path13.join(projectRoot, ".agent-settings.yml");
5948
- if (!fs13.existsSync(settingsPath)) {
6506
+ const settingsPath = path15.join(projectRoot, ".agent-settings.yml");
6507
+ if (!fs15.existsSync(settingsPath)) {
5949
6508
  return "eager-all";
5950
6509
  }
5951
6510
  try {
5952
- const parsed = YAML.parse(fs13.readFileSync(settingsPath, "utf8"));
6511
+ const parsed = YAML.parse(fs15.readFileSync(settingsPath, "utf8"));
5953
6512
  const lean = parsed?.["lean_projection"] ?? null;
5954
6513
  const mode = lean?.["mode"];
5955
6514
  return typeof mode === "string" && mode.length > 0 ? mode : "eager-all";
@@ -5960,7 +6519,7 @@ function readSettingsMode(projectRoot) {
5960
6519
  function kernelIdsFromRouter(packageRoot) {
5961
6520
  try {
5962
6521
  const router = JSON.parse(
5963
- fs13.readFileSync(path13.join(packageRoot, "dist", "router.json"), "utf8")
6522
+ fs15.readFileSync(path15.join(packageRoot, "dist", "router.json"), "utf8")
5964
6523
  );
5965
6524
  return new Set((router["kernel"] ?? []).map(String));
5966
6525
  } catch {
@@ -5977,8 +6536,8 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
5977
6536
  remedy: "set lean_projection.mode to 'eager-all' or 'thin' in .agent-settings.yml"
5978
6537
  };
5979
6538
  }
5980
- const rulesDir = projectedRulesDir ?? path13.join(projectRoot, ".augment", "rules");
5981
- if (!fs13.existsSync(rulesDir)) {
6539
+ const rulesDir = projectedRulesDir ?? path15.join(projectRoot, ".augment", "rules");
6540
+ if (!fs15.existsSync(rulesDir)) {
5982
6541
  return {
5983
6542
  id: "lean-projection",
5984
6543
  status: "skipped",
@@ -5987,7 +6546,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
5987
6546
  };
5988
6547
  }
5989
6548
  const kernel = kernelIdsFromRouter(packageRoot);
5990
- const files = fs13.readdirSync(rulesDir).filter((f) => f.endsWith(".md") && f !== "INDEX.md").sort();
6549
+ const files = fs15.readdirSync(rulesDir).filter((f) => f.endsWith(".md") && f !== "INDEX.md").sort();
5991
6550
  const nonKernel = files.filter((f) => !kernel.has(f.replace(/\.md$/, "")));
5992
6551
  if (nonKernel.length === 0) {
5993
6552
  return {
@@ -6001,7 +6560,7 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
6001
6560
  for (const f of nonKernel) {
6002
6561
  let text = "";
6003
6562
  try {
6004
- text = fs13.readFileSync(path13.join(rulesDir, f), "utf8");
6563
+ text = fs15.readFileSync(path15.join(rulesDir, f), "utf8");
6005
6564
  } catch {
6006
6565
  continue;
6007
6566
  }
@@ -6032,8 +6591,8 @@ function _check_lean_projection(projectRoot, packageRoot = PACKAGE_ROOT, project
6032
6591
  function _check_host_manifest(projectRoot) {
6033
6592
  const detected = Object.entries(detectToolPresence(projectRoot)).filter(([, v]) => v === true).map(([k]) => k);
6034
6593
  const detectedNote = detected.length > 0 ? `detected surfaces: ${detected.join(", ")}` : "no surfaces detected";
6035
- const settingsPath = path13.join(projectRoot, ".agent-settings.yml");
6036
- if (!fs13.existsSync(settingsPath)) {
6594
+ const settingsPath = path15.join(projectRoot, ".agent-settings.yml");
6595
+ if (!fs15.existsSync(settingsPath)) {
6037
6596
  return {
6038
6597
  id: "host-manifest",
6039
6598
  status: "ok",
@@ -6043,7 +6602,7 @@ function _check_host_manifest(projectRoot) {
6043
6602
  }
6044
6603
  let parsed = null;
6045
6604
  try {
6046
- parsed = YAML.parse(fs13.readFileSync(settingsPath, "utf8"));
6605
+ parsed = YAML.parse(fs15.readFileSync(settingsPath, "utf8"));
6047
6606
  } catch (exc) {
6048
6607
  return {
6049
6608
  id: "host-manifest",
@@ -6104,14 +6663,14 @@ function appendConformanceReport(checks, projectRoot, logPath = conformanceLogPa
6104
6663
  } catch {
6105
6664
  }
6106
6665
  }
6107
- var USAGE2 = "usage: agent-config conformance [-h] [--project PROJECT] [--json]\n [--skip-dispatcher] [--funnel]\n";
6666
+ var USAGE3 = "usage: agent-config conformance [-h] [--project PROJECT] [--json]\n [--skip-dispatcher] [--funnel]\n";
6108
6667
  function _parse(argv) {
6109
6668
  const opts = { project: null, json: false, skip_dispatcher: false, funnel: false };
6110
6669
  let i = 0;
6111
6670
  while (i < argv.length) {
6112
6671
  const a = argv[i];
6113
6672
  if (a === "-h" || a === "--help") {
6114
- process5.stdout.write(USAGE2);
6673
+ process5.stdout.write(USAGE3);
6115
6674
  throw new ArgparseExit(0);
6116
6675
  }
6117
6676
  if (a === "--json") {
@@ -6125,7 +6684,7 @@ function _parse(argv) {
6125
6684
  opts.project = a.slice(a.indexOf("=") + 1);
6126
6685
  } else {
6127
6686
  if (i + 1 >= argv.length) {
6128
- process5.stderr.write(USAGE2);
6687
+ process5.stderr.write(USAGE3);
6129
6688
  process5.stderr.write("agent-config conformance: error: --project expects a value\n");
6130
6689
  throw new ArgparseExit(2);
6131
6690
  }
@@ -6133,7 +6692,7 @@ function _parse(argv) {
6133
6692
  i += 1;
6134
6693
  }
6135
6694
  } else {
6136
- process5.stderr.write(USAGE2);
6695
+ process5.stderr.write(USAGE3);
6137
6696
  process5.stderr.write(`agent-config conformance: error: unrecognized argument ${a}
6138
6697
  `);
6139
6698
  throw new ArgparseExit(2);
@@ -6142,7 +6701,7 @@ function _parse(argv) {
6142
6701
  }
6143
6702
  return opts;
6144
6703
  }
6145
- function main13(argv = null) {
6704
+ function main14(argv = null) {
6146
6705
  const opts = _parse(argv !== null ? Array.from(argv) : process5.argv.slice(2));
6147
6706
  if (opts.funnel) {
6148
6707
  print(render5(buildFunnel()));
@@ -6213,25 +6772,25 @@ function main13(argv = null) {
6213
6772
  }
6214
6773
  return failed ? 1 : 0;
6215
6774
  }
6216
- function _isCliEntry12() {
6775
+ function _isCliEntry13() {
6217
6776
  if (process5.argv[1] === void 0) {
6218
6777
  return false;
6219
6778
  }
6220
- const argvUrl = pathToFileURL13(path13.resolve(process5.argv[1])).href;
6779
+ const argvUrl = pathToFileURL14(path15.resolve(process5.argv[1])).href;
6221
6780
  if (import.meta.url === argvUrl) {
6222
6781
  return true;
6223
6782
  }
6224
6783
  try {
6225
- const here = fs13.realpathSync(fileURLToPath13(import.meta.url));
6226
- const argv = fs13.realpathSync(path13.resolve(process5.argv[1]));
6784
+ const here = fs15.realpathSync(fileURLToPath14(import.meta.url));
6785
+ const argv = fs15.realpathSync(path15.resolve(process5.argv[1]));
6227
6786
  return here === argv;
6228
6787
  } catch {
6229
6788
  return false;
6230
6789
  }
6231
6790
  }
6232
- if (_isCliEntry12() || process5.argv[1] === _HERE5) {
6791
+ if (_isCliEntry13() || process5.argv[1] === _HERE6) {
6233
6792
  try {
6234
- process5.exitCode = main13(process5.argv.slice(2));
6793
+ process5.exitCode = main14(process5.argv.slice(2));
6235
6794
  } catch (e) {
6236
6795
  if (e instanceof ArgparseExit) {
6237
6796
  process5.exitCode = e.code;
@@ -6254,7 +6813,7 @@ export {
6254
6813
  conformanceLogPath,
6255
6814
  detectSmokePlatform,
6256
6815
  installLogPath,
6257
- main13 as main,
6816
+ main14 as main,
6258
6817
  routeTargetPaths,
6259
6818
  runConformanceChecks
6260
6819
  };