@event4u/agent-config 14.20.0 → 14.21.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 (100) 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 +243 -0
  5. package/README.md +1 -1
  6. package/agents/templates/.ai-council.yml.example +10 -0
  7. package/dist/agent-src/commands/analyze/inbox.md +1 -1
  8. package/dist/agent-src/commands/analyze/{reference-repo.md → repo.md} +247 -32
  9. package/dist/agent-src/commands/analyze/roadmap-repos.md +129 -0
  10. package/dist/agent-src/commands/analyze.md +12 -7
  11. package/dist/agent-src/commands/feature/plan.md +55 -16
  12. package/dist/agent-src/commands/feature/refactor.md +8 -3
  13. package/dist/agent-src/commands/humanize.md +48 -4
  14. package/dist/agent-src/contexts/execution/contract-decision-sheet.md +22 -1
  15. package/dist/agent-src/contexts/execution/host-capability-manifest.md +4 -1
  16. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +35 -2
  17. package/dist/agent-src/contexts/execution/terminal-states.md +4 -1
  18. package/dist/agent-src/rules/evaluator-independence.md +4 -4
  19. package/dist/agent-src/rules/external-reference-deep-dive.md +2 -2
  20. package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
  21. package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +27 -11
  22. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +1 -1
  23. package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
  24. package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
  25. package/dist/agent-src/skills/technical-specification/SKILL.md +4 -0
  26. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  27. package/dist/agent-src/templates/features.md +5 -0
  28. package/dist/agent-src/templates/roadmaps.md +15 -0
  29. package/dist/cli-delegate/{chunk-KPBWFOPZ.js → chunk-2FTMENJL.js} +194 -37
  30. package/dist/cli-delegate/{chunk-PI2GU3DP.js → chunk-2TAQ2K4V.js} +4 -1
  31. package/dist/cli-delegate/{chunk-C6IPZRDA.js → chunk-643Z7FIC.js} +1 -1
  32. package/dist/cli-delegate/{chunk-NUMQHLS5.js → chunk-J3RFNKG4.js} +21 -2
  33. package/dist/cli-delegate/cmd_conformance.js +17 -3
  34. package/dist/cli-delegate/cmd_doctor.js +3 -3
  35. package/dist/cli-delegate/cmd_export.js +2 -2
  36. package/dist/cli-delegate/cmd_handoff.js +1 -1
  37. package/dist/cli-delegate/cmd_prune.js +2 -2
  38. package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
  39. package/dist/cli-delegate/cmd_sync.js +2 -2
  40. package/dist/cli-delegate/cmd_uninstall.js +2 -2
  41. package/dist/cli-delegate/cmd_validate.js +2 -2
  42. package/dist/discovery/deprecation-report.md +1 -1
  43. package/dist/discovery/discovery-manifest.json +56 -25
  44. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  45. package/dist/discovery/discovery-manifest.summary.md +3 -3
  46. package/dist/discovery/dormancy-report.md +1 -1
  47. package/dist/discovery/orphan-report.md +1 -1
  48. package/dist/discovery/packs.json +7 -6
  49. package/dist/discovery/trust-report.md +2 -2
  50. package/dist/discovery/workspaces.json +6 -5
  51. package/dist/hooks/dispatch.js +479 -241
  52. package/dist/install/install.mjs +4 -1
  53. package/dist/mcp/registry-manifest.json +2 -2
  54. package/dist/mcp/server.json +2 -2
  55. package/dist/mcp/server.mjs +313 -63
  56. package/dist/scripts/ai_council/content_ceiling.js +63 -0
  57. package/dist/scripts/ai_council/seat_policy.js +106 -0
  58. package/dist/scripts/ai_council/transport_resolver.js +21 -0
  59. package/llms.txt +14 -14
  60. package/package.json +1 -1
  61. package/src/config/gate-violation-baselines.json +3 -3
  62. package/src/config/release-gate-locality.yml +4 -3
  63. package/src/scripts/_lib/blocked_by_marker.ts +189 -0
  64. package/src/scripts/_lib/host_capability.ts +38 -1
  65. package/src/scripts/_lib/release_highlights.ts +19 -211
  66. package/src/scripts/_lib/release_material.ts +27 -77
  67. package/src/scripts/_lib/structured_ask.ts +117 -0
  68. package/src/scripts/_lib/tty_prompt.ts +76 -0
  69. package/src/scripts/ai_council/api_transport.ts +163 -0
  70. package/src/scripts/ai_council/clients.ts +58 -63
  71. package/src/scripts/ai_council/config.ts +13 -0
  72. package/src/scripts/ai_council/content_ceiling.ts +79 -0
  73. package/src/scripts/ai_council/jury_aggregate.ts +178 -0
  74. package/src/scripts/ai_council/seat_policy.ts +137 -0
  75. package/src/scripts/ai_council/status_surface.ts +79 -0
  76. package/src/scripts/ai_council/transport_resolver.ts +59 -1
  77. package/src/scripts/ai_tells_rules.ts +446 -5
  78. package/src/scripts/ask_block_census.ts +499 -0
  79. package/src/scripts/bench_humanizer_eval.ts +264 -40
  80. package/src/scripts/bench_prose_tells_fp.ts +198 -0
  81. package/src/scripts/check_branch_work_committed.ts +234 -0
  82. package/src/scripts/check_pack_size.ts +1 -1
  83. package/src/scripts/check_release_highlights.ts +0 -157
  84. package/src/scripts/council_cli.ts +18 -27
  85. package/src/scripts/detect_ai_tells.ts +142 -20
  86. package/src/scripts/harvest_reference_tokens.ts +698 -0
  87. package/src/scripts/hook_manifest.json +1 -1
  88. package/src/scripts/hook_manifest.yaml +31 -1
  89. package/src/scripts/hooks/concern_registry.ts +2 -0
  90. package/src/scripts/hooks/delegation_nudge_hook.ts +45 -1
  91. package/src/scripts/hooks/one_question_per_ask_hook.ts +191 -0
  92. package/src/scripts/install-hooks.sh +52 -0
  93. package/src/scripts/lint_roadmap_blockers.ts +51 -1
  94. package/src/scripts/migrate_command_suggestions.ts +1 -1
  95. package/src/scripts/probe_unblocked_ask.ts +135 -2
  96. package/src/scripts/release.ts +26 -71
  97. package/src/scripts/release_drill.ts +6 -10
  98. package/src/scripts/release_env.ts +1 -0
  99. package/src/scripts/release_publication.ts +34 -29
  100. package/src/scripts/self_review_gate.ts +409 -15
@@ -7364,7 +7364,7 @@ var require_dist = __commonJS({
7364
7364
 
7365
7365
  // src/scripts/hooks/dispatch_entry.ts
7366
7366
  import * as path108 from "node:path";
7367
- import { fileURLToPath as fileURLToPath69 } from "node:url";
7367
+ import { fileURLToPath as fileURLToPath70 } from "node:url";
7368
7368
 
7369
7369
  // src/scripts/hooks/dispatch_hook.ts
7370
7370
  var import_yaml7 = __toESM(require_dist(), 1);
@@ -7372,7 +7372,7 @@ import { spawnSync as spawnSync11 } from "node:child_process";
7372
7372
  import fs105 from "node:fs";
7373
7373
  import path107 from "node:path";
7374
7374
  import * as tty2 from "node:tty";
7375
- import { fileURLToPath as fileURLToPath68, pathToFileURL as pathToFileURL59 } from "node:url";
7375
+ import { fileURLToPath as fileURLToPath69, pathToFileURL as pathToFileURL60 } from "node:url";
7376
7376
 
7377
7377
  // src/scripts/_lib/spawn_env.ts
7378
7378
  var DENY_EXACT = /* @__PURE__ */ new Set([
@@ -9675,10 +9675,10 @@ function scan_encoding_findings(s) {
9675
9675
  });
9676
9676
  }
9677
9677
  for (const m of s.matchAll(TOKEN_RE)) {
9678
- const verdict = classifyToken(m[0]);
9679
- if (verdict !== null) {
9680
- const script = verdict.startsWith("latin+greek") ? "greek" : "cyrillic";
9681
- out.push({ channel: `confusable-${script}`, detail: `${m[0]} \u2014 ${verdict}` });
9678
+ const verdict2 = classifyToken(m[0]);
9679
+ if (verdict2 !== null) {
9680
+ const script = verdict2.startsWith("latin+greek") ? "greek" : "cyrillic";
9681
+ out.push({ channel: `confusable-${script}`, detail: `${m[0]} \u2014 ${verdict2}` });
9682
9682
  }
9683
9683
  }
9684
9684
  for (const m of s.matchAll(/\bxn--[a-z0-9-]+/gi)) {
@@ -11109,14 +11109,14 @@ function aggregate(signals, nowMs) {
11109
11109
  const corroborations = top.origins.size;
11110
11110
  if (corroborations < MIN_CORROBORATIONS) continue;
11111
11111
  const secondCorroborated = claims.slice(1).some((c) => c.origins.size >= MIN_CORROBORATIONS);
11112
- let verdict;
11113
- if (secondCorroborated) verdict = "contested";
11114
- else if (top.polarity === "dead_end") verdict = "dead_end";
11115
- else verdict = "preferred";
11112
+ let verdict2;
11113
+ if (secondCorroborated) verdict2 = "contested";
11114
+ else if (top.polarity === "dead_end") verdict2 = "dead_end";
11115
+ else verdict2 = "preferred";
11116
11116
  lessons.push({
11117
11117
  entry_type: g.entryType,
11118
11118
  path: g.path,
11119
- verdict,
11119
+ verdict: verdict2,
11120
11120
  score: Math.round(top.score * 1e3) / 1e3,
11121
11121
  corroborations,
11122
11122
  last_ts: top.lastTs,
@@ -16787,6 +16787,63 @@ function _isExecutable(p) {
16787
16787
  }
16788
16788
  }
16789
16789
 
16790
+ // src/scripts/ai_council/content_ceiling.ts
16791
+ var CONTENT_CLASSES = ["public-artifact", "project-content"];
16792
+ var DEFAULT_CONTENT_CLASS = "project-content";
16793
+ var DEFAULT_SEAT_CEILING = "project-content";
16794
+ var _SET = new Set(CONTENT_CLASSES);
16795
+ function classifyContentClass(raw, fallback = DEFAULT_CONTENT_CLASS) {
16796
+ if (typeof raw === "string" && _SET.has(raw)) {
16797
+ return raw;
16798
+ }
16799
+ return fallback;
16800
+ }
16801
+
16802
+ // src/scripts/ai_council/seat_policy.ts
16803
+ var POLICY_EXCLUSIONS = [
16804
+ /** The provider's terms forbid this use of the route. */
16805
+ "policy_terms",
16806
+ /** A privacy constraint forbids sending to this route. */
16807
+ "policy_privacy",
16808
+ /** The route's cost property is asserted rather than proven. */
16809
+ "policy_unproven_cost",
16810
+ /** The route serves a model other than the one requested. */
16811
+ "policy_model_mismatch",
16812
+ /** 2.2 — the payload's content class exceeds the seat's ceiling. */
16813
+ "policy_content_ceiling",
16814
+ /** The config named an exclusion this build does not understand. */
16815
+ "policy_unknown"
16816
+ ];
16817
+ var _SET2 = new Set(POLICY_EXCLUSIONS);
16818
+ function isPolicyExclusion(v) {
16819
+ return typeof v === "string" && _SET2.has(v);
16820
+ }
16821
+ function classifyPolicyExclusion(raw) {
16822
+ if (raw === void 0 || raw === null) {
16823
+ return null;
16824
+ }
16825
+ return isPolicyExclusion(raw) ? raw : "policy_unknown";
16826
+ }
16827
+ function parseSeatFields(name, raw) {
16828
+ const dr = raw["disabled_reason"];
16829
+ let disabled_reason = null;
16830
+ if (dr !== void 0 && dr !== null) {
16831
+ if (typeof dr !== "string" || dr.trim() === "") {
16832
+ return {
16833
+ error: `members.${name}.disabled_reason must be a non-empty string when set (got ${JSON.stringify(dr)}).`
16834
+ };
16835
+ }
16836
+ disabled_reason = dr.trim();
16837
+ }
16838
+ return {
16839
+ fields: {
16840
+ disabled_reason,
16841
+ policy_exclusion: classifyPolicyExclusion(raw["policy_exclusion"]),
16842
+ content_ceiling: classifyContentClass(raw["content_ceiling"], DEFAULT_SEAT_CEILING)
16843
+ }
16844
+ };
16845
+ }
16846
+
16790
16847
  // src/scripts/ai_council/fallback_config.ts
16791
16848
  var SECOND_MODEL_PROVIDERS = /* @__PURE__ */ new Set([
16792
16849
  "anthropic",
@@ -17971,6 +18028,10 @@ function _build_member(name, cfg, default_mode = "auto", ignored = []) {
17971
18028
  }
17972
18029
  verified_at = coerced;
17973
18030
  }
18031
+ const seat = parseSeatFields(name, cfg);
18032
+ if ("error" in seat) {
18033
+ throw new CouncilConfigError(seat.error);
18034
+ }
17974
18035
  const prompt_cache_raw = _get(cfg, "prompt_cache", null);
17975
18036
  let prompt_cache_ttl = "5m";
17976
18037
  if (prompt_cache_raw !== null && prompt_cache_raw !== void 0 && !_isBool(prompt_cache_raw)) {
@@ -17998,7 +18059,8 @@ function _build_member(name, cfg, default_mode = "auto", ignored = []) {
17998
18059
  participate_low_impact: participate_raw,
17999
18060
  tier,
18000
18061
  prompt_cache_ttl,
18001
- verified_at
18062
+ verified_at,
18063
+ ...seat.fields
18002
18064
  };
18003
18065
  }
18004
18066
  function resolve_cli_call_caps(raw) {
@@ -23864,10 +23926,10 @@ function format_gate_ledger_line(entry) {
23864
23926
  function record_gate_verdict(opts) {
23865
23927
  const config = opts.config ?? _load_config_fail_open();
23866
23928
  const bound = config.review_gate.max_consecutive_blocks;
23867
- const verdict = opts.verdict ?? parse_gate_verdict(opts.transcript_text);
23929
+ const verdict2 = opts.verdict ?? parse_gate_verdict(opts.transcript_text);
23868
23930
  if (!config.review_gate.managed) {
23869
23931
  return {
23870
- verdict,
23932
+ verdict: verdict2,
23871
23933
  consecutive_blocks: 0,
23872
23934
  bound,
23873
23935
  counted: false,
@@ -23891,7 +23953,7 @@ function record_gate_verdict(opts) {
23891
23953
  };
23892
23954
  if (dedupe_key !== "" && session.last_dedupe_key === dedupe_key) {
23893
23955
  return {
23894
- verdict,
23956
+ verdict: verdict2,
23895
23957
  consecutive_blocks: session.consecutive_blocks,
23896
23958
  bound,
23897
23959
  counted: false,
@@ -23902,11 +23964,11 @@ function record_gate_verdict(opts) {
23902
23964
  }
23903
23965
  let counted = false;
23904
23966
  let notice = null;
23905
- if (verdict === "ALLOW") {
23967
+ if (verdict2 === "ALLOW") {
23906
23968
  session.consecutive_blocks = 0;
23907
23969
  session.notice_emitted = false;
23908
23970
  counted = true;
23909
- } else if (verdict === "BLOCK") {
23971
+ } else if (verdict2 === "BLOCK") {
23910
23972
  session.consecutive_blocks += 1;
23911
23973
  counted = true;
23912
23974
  if (session.consecutive_blocks >= bound && !session.notice_emitted) {
@@ -23919,18 +23981,18 @@ function record_gate_verdict(opts) {
23919
23981
  state.sessions[session_key] = session;
23920
23982
  _prune_sessions(state);
23921
23983
  atomic_write_json(state_path, state);
23922
- const counter = verdict === "ALLOW" ? "reset" : `${session.consecutive_blocks}/${bound}`;
23984
+ const counter = verdict2 === "ALLOW" ? "reset" : `${session.consecutive_blocks}/${bound}`;
23923
23985
  const entry = {
23924
23986
  schema_version: 1,
23925
23987
  ts_utc: session.updated_utc,
23926
23988
  kind: GATE_LEDGER_KIND,
23927
23989
  session_id: session_key,
23928
- verdict,
23990
+ verdict: verdict2,
23929
23991
  counter
23930
23992
  };
23931
23993
  const written = _append_ledger_line(ledger_path, entry);
23932
23994
  return {
23933
- verdict,
23995
+ verdict: verdict2,
23934
23996
  consecutive_blocks: session.consecutive_blocks,
23935
23997
  bound,
23936
23998
  counted,
@@ -29008,9 +29070,9 @@ function main37() {
29008
29070
  }
29009
29071
  }
29010
29072
  for (const v of candidates) {
29011
- const verdict = verdictFor(v, (p) => fs64.existsSync(p), repoRoot);
29012
- if (verdict.block && verdict.dir !== null) {
29013
- process.stderr.write(denyMessage(verdict.dir));
29073
+ const verdict2 = verdictFor(v, (p) => fs64.existsSync(p), repoRoot);
29074
+ if (verdict2.block && verdict2.dir !== null) {
29075
+ process.stderr.write(denyMessage(verdict2.dir));
29014
29076
  return 1;
29015
29077
  }
29016
29078
  }
@@ -29036,10 +29098,169 @@ if (_isCliEntry29()) {
29036
29098
  process.exit(main37());
29037
29099
  }
29038
29100
 
29101
+ // src/scripts/hooks/one_question_per_ask_hook.ts
29102
+ import { fileURLToPath as fileURLToPath42, pathToFileURL as pathToFileURL33 } from "node:url";
29103
+
29104
+ // src/scripts/_lib/structured_ask.ts
29105
+ var STRUCTURED_ASK_SHAPES = {};
29106
+ function structuredAskShape(hostId) {
29107
+ if (hostId === null || hostId === void 0) {
29108
+ return void 0;
29109
+ }
29110
+ return STRUCTURED_ASK_SHAPES[hostId];
29111
+ }
29112
+ var STRUCTURED_ASK_TOOL_NAME_RE = /^(ask[_-]?user[_-]?question|user[_-]?question|ask[_-]?question)s?$/i;
29113
+ function isStructuredAskTool(name, hostId) {
29114
+ const shape = structuredAskShape(hostId);
29115
+ if (shape !== void 0) {
29116
+ return name === shape.tool;
29117
+ }
29118
+ return STRUCTURED_ASK_TOOL_NAME_RE.test(name);
29119
+ }
29120
+ function countStructuredAskQuestions(input) {
29121
+ if (input === null || typeof input !== "object" || Array.isArray(input)) {
29122
+ return -1;
29123
+ }
29124
+ const src = input;
29125
+ for (const key of ["questions", "question_list", "items", "prompts"]) {
29126
+ const v = src[key];
29127
+ if (Array.isArray(v)) {
29128
+ return v.length;
29129
+ }
29130
+ }
29131
+ for (const key of ["question", "prompt", "header"]) {
29132
+ if (typeof src[key] === "string" && src[key].trim() !== "") {
29133
+ return 1;
29134
+ }
29135
+ }
29136
+ return -1;
29137
+ }
29138
+
29139
+ // src/scripts/hooks/one_question_per_ask_hook.ts
29140
+ var _HERE8 = fileURLToPath42(import.meta.url);
29141
+ function _isObject13(v) {
29142
+ return typeof v === "object" && v !== null && !Array.isArray(v);
29143
+ }
29144
+ function extractAskCall(envelope) {
29145
+ const payload = _isObject13(envelope["payload"]) ? envelope["payload"] : envelope;
29146
+ const nameVal = payload["tool_name"] ?? payload["toolName"] ?? payload["tool"] ?? envelope["tool_name"] ?? envelope["tool"];
29147
+ const tool = typeof nameVal === "string" ? nameVal : "";
29148
+ const ti = _isObject13(payload["tool_input"]) ? payload["tool_input"] : _isObject13(envelope["tool_input"]) ? envelope["tool_input"] : null;
29149
+ return { tool, questions: ti === null ? -1 : countStructuredAskQuestions(ti) };
29150
+ }
29151
+ function verdict(call) {
29152
+ if (call.tool === "" || !isStructuredAskTool(call.tool)) {
29153
+ return { block: false, reason: "not a structured-ask call" };
29154
+ }
29155
+ if (call.questions < 0) {
29156
+ return { block: false, reason: "payload shape not recognised \u2014 allowed, never guessed" };
29157
+ }
29158
+ if (call.questions <= 1) {
29159
+ return { block: false, reason: "one question" };
29160
+ }
29161
+ return {
29162
+ block: true,
29163
+ reason: `${call.tool} carries ${String(call.questions)} questions in one call. One decision per ask: put the first question, wait for the answer, then the next. The call is denied rather than truncated \u2014 dropping the extra questions would hide the decisions the user is owed.`
29164
+ };
29165
+ }
29166
+ function main38(argv) {
29167
+ const args = argv ?? process.argv.slice(2);
29168
+ for (const a of args) {
29169
+ if (a === "--self-test") {
29170
+ return selfTest();
29171
+ }
29172
+ }
29173
+ const raw = readHookStdin();
29174
+ if (!raw.trim()) {
29175
+ return 0;
29176
+ }
29177
+ let envelope;
29178
+ try {
29179
+ const parsed = JSON.parse(raw);
29180
+ envelope = _isObject13(parsed) ? parsed : {};
29181
+ } catch {
29182
+ return 0;
29183
+ }
29184
+ const v = verdict(extractAskCall(envelope));
29185
+ if (v.block) {
29186
+ process.stderr.write(`one-question-per-ask: BLOCKED \u2014 ${v.reason}
29187
+ `);
29188
+ return 1;
29189
+ }
29190
+ return 0;
29191
+ }
29192
+ function selfTest() {
29193
+ const cases = [
29194
+ [
29195
+ "two questions in one call is denied",
29196
+ { tool_name: "AskUserQuestion", tool_input: { questions: [{}, {}] } },
29197
+ true
29198
+ ],
29199
+ [
29200
+ "four questions is denied",
29201
+ { tool_name: "AskUserQuestion", tool_input: { questions: [{}, {}, {}, {}] } },
29202
+ true
29203
+ ],
29204
+ [
29205
+ "one question passes",
29206
+ { tool_name: "AskUserQuestion", tool_input: { questions: [{}] } },
29207
+ false
29208
+ ],
29209
+ [
29210
+ "a single-question field passes",
29211
+ { tool_name: "ask_user_question", tool_input: { question: "which one?" } },
29212
+ false
29213
+ ],
29214
+ [
29215
+ "an empty ask passes \u2014 malformed, but not this guard's failure",
29216
+ { tool_name: "AskUserQuestion", tool_input: { questions: [] } },
29217
+ false
29218
+ ],
29219
+ [
29220
+ "an unrecognised payload shape passes rather than wedging the session",
29221
+ { tool_name: "AskUserQuestion", tool_input: { something: "else" } },
29222
+ false
29223
+ ],
29224
+ ["an ordinary tool is never seen", { tool_name: "Bash", tool_input: { command: "ls" } }, false],
29225
+ [
29226
+ "a Write with two questions in its body is not an ask call",
29227
+ { tool_name: "Write", tool_input: { questions: [{}, {}] } },
29228
+ false
29229
+ ],
29230
+ ["an empty envelope passes", {}, false]
29231
+ ];
29232
+ let failed = 0;
29233
+ for (const [name, envelope, want] of cases) {
29234
+ const got = verdict(extractAskCall(envelope)).block;
29235
+ const ok = got === want;
29236
+ process.stdout.write(
29237
+ `${ok ? "\u2705" : "\u274C"} ${name} \u2014 block=${String(got)}` + (ok ? "\n" : ` (wanted ${String(want)})
29238
+ `)
29239
+ );
29240
+ if (!ok) failed += 1;
29241
+ }
29242
+ const positives = cases.filter((c) => c[2]).length;
29243
+ if (positives < 2) {
29244
+ process.stderr.write(
29245
+ "\u274C one_question_per_ask --self-test: fewer than 2 deny cases \u2014 a guard never seen refuse has unknown sensitivity.\n"
29246
+ );
29247
+ return 1;
29248
+ }
29249
+ process.stdout.write(
29250
+ `
29251
+ one_question_per_ask --self-test: ${String(cases.length - failed)}/${String(cases.length)} case(s) behaved (${String(positives)} deny, ${String(cases.length - positives)} allow)
29252
+ `
29253
+ );
29254
+ return failed > 0 ? 1 : 0;
29255
+ }
29256
+ if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL33(process.argv[1]).href) {
29257
+ process.exit(main38());
29258
+ }
29259
+
29039
29260
  // src/scripts/hooks/rtk_wrap_hook.ts
29040
29261
  import fs65 from "node:fs";
29041
29262
  import path64 from "node:path";
29042
- import { fileURLToPath as fileURLToPath42, pathToFileURL as pathToFileURL33 } from "node:url";
29263
+ import { fileURLToPath as fileURLToPath43, pathToFileURL as pathToFileURL34 } from "node:url";
29043
29264
 
29044
29265
  // src/install/rtkDetection.ts
29045
29266
  import { spawnSync as spawnSync6 } from "node:child_process";
@@ -29177,7 +29398,7 @@ var _RTK_PROGRAMS = /* @__PURE__ */ new Set([
29177
29398
  "kubectl",
29178
29399
  "terraform"
29179
29400
  ]);
29180
- function _isObject13(v) {
29401
+ function _isObject14(v) {
29181
29402
  return typeof v === "object" && v !== null && !Array.isArray(v);
29182
29403
  }
29183
29404
  function _enabled2(root) {
@@ -29236,8 +29457,8 @@ function rtk_available(env = process.env) {
29236
29457
  return false;
29237
29458
  }
29238
29459
  function _extract_command4(envelope) {
29239
- const payload = _isObject13(envelope["payload"]) ? envelope["payload"] : {};
29240
- const tool_input = _isObject13(payload["tool_input"]) ? payload["tool_input"] : {};
29460
+ const payload = _isObject14(envelope["payload"]) ? envelope["payload"] : {};
29461
+ const tool_input = _isObject14(payload["tool_input"]) ? payload["tool_input"] : {};
29241
29462
  for (const src of [tool_input["command"], payload["command"], envelope["command"]]) {
29242
29463
  if (typeof src === "string") return src;
29243
29464
  }
@@ -29332,7 +29553,7 @@ function _readStdin13() {
29332
29553
  function _jsonReason(reason) {
29333
29554
  return JSON.stringify({ decision: "warn", reason });
29334
29555
  }
29335
- function main38() {
29556
+ function main39() {
29336
29557
  let envelope;
29337
29558
  try {
29338
29559
  const raw = _readStdin13();
@@ -29340,7 +29561,7 @@ function main38() {
29340
29561
  } catch {
29341
29562
  return EXIT_ALLOW14;
29342
29563
  }
29343
- if (!_isObject13(envelope)) return EXIT_ALLOW14;
29564
+ if (!_isObject14(envelope)) return EXIT_ALLOW14;
29344
29565
  const cwd = envelope["cwd"];
29345
29566
  const projectRoot = envelope["workspace_root"] ?? envelope["project_root"];
29346
29567
  const root = typeof cwd === "string" && cwd ? cwd : typeof projectRoot === "string" && projectRoot ? projectRoot : ".";
@@ -29348,8 +29569,8 @@ function main38() {
29348
29569
  const command = _extract_command4(envelope);
29349
29570
  if (!command) return EXIT_ALLOW14;
29350
29571
  if (rtk_available() && detectRtkCached().identity === "token-killer") {
29351
- const verdict = classify2(command);
29352
- if (verdict.eligible) {
29572
+ const verdict2 = classify2(command);
29573
+ if (verdict2.eligible) {
29353
29574
  const reason = `rtk is installed and wraps verbose CLI output (upstream reports 60\u201390% fewer output tokens). Re-run wrapped: \`rtk ${command.trim()}\`. (Skip for completeness-critical output like \`git diff\`.)`;
29354
29575
  process.stdout.write(`${_jsonReason(reason)}
29355
29576
  `);
@@ -29372,12 +29593,12 @@ function _isCliEntry30() {
29372
29593
  if (process.argv[1] === void 0) {
29373
29594
  return false;
29374
29595
  }
29375
- const argvUrl = pathToFileURL33(path64.resolve(process.argv[1])).href;
29596
+ const argvUrl = pathToFileURL34(path64.resolve(process.argv[1])).href;
29376
29597
  if (import.meta.url === argvUrl) {
29377
29598
  return true;
29378
29599
  }
29379
29600
  try {
29380
- const here = fs65.realpathSync(fileURLToPath42(import.meta.url));
29601
+ const here = fs65.realpathSync(fileURLToPath43(import.meta.url));
29381
29602
  const argv = fs65.realpathSync(path64.resolve(process.argv[1]));
29382
29603
  return here === argv;
29383
29604
  } catch {
@@ -29385,13 +29606,13 @@ function _isCliEntry30() {
29385
29606
  }
29386
29607
  }
29387
29608
  if (_isCliEntry30()) {
29388
- process.exit(main38());
29609
+ process.exit(main39());
29389
29610
  }
29390
29611
 
29391
29612
  // src/scripts/hooks/design_pass_hook.ts
29392
29613
  import fs67 from "node:fs";
29393
29614
  import path66 from "node:path";
29394
- import { fileURLToPath as fileURLToPath43, pathToFileURL as pathToFileURL34 } from "node:url";
29615
+ import { fileURLToPath as fileURLToPath44, pathToFileURL as pathToFileURL35 } from "node:url";
29395
29616
 
29396
29617
  // src/scripts/_lib/ui_surface.ts
29397
29618
  var UI_EXTENSIONS = [
@@ -30066,7 +30287,7 @@ function scanFile(content, relPath, ctx) {
30066
30287
  }
30067
30288
  return out;
30068
30289
  }
30069
- function main39() {
30290
+ function main40() {
30070
30291
  const args = process.argv.slice(2);
30071
30292
  const jsonMode = args.includes("--json");
30072
30293
  const quiet = args.includes("--quiet");
@@ -30143,7 +30364,7 @@ lint_design_slop: ${findings.length} tell(s) flagged (rebuttable \u2014 declare
30143
30364
  process.exit(overThreshold.length > 0 ? 2 : 0);
30144
30365
  }
30145
30366
  var invokedDirectly = process.argv[1] !== void 0 && /lint_design_slop\.ts$/.test(process.argv[1]);
30146
- if (invokedDirectly) main39();
30367
+ if (invokedDirectly) main40();
30147
30368
 
30148
30369
  // src/scripts/hooks/design_pass_hook.ts
30149
30370
  var EXIT_ALLOW15 = 0;
@@ -30262,7 +30483,7 @@ function render(result) {
30262
30483
  if (result.degradation_reason) lines.push(`degradation_reason: ${result.degradation_reason}`);
30263
30484
  return lines.join("\n");
30264
30485
  }
30265
- function main40() {
30486
+ function main41() {
30266
30487
  const root = process.env["CLAUDE_PROJECT_DIR"] ?? process.cwd();
30267
30488
  if (!enabled2(root)) return EXIT_ALLOW15;
30268
30489
  const slotArg = process.argv.includes("--slot") ? process.argv[process.argv.indexOf("--slot") + 1] : void 0;
@@ -30321,15 +30542,15 @@ function main40() {
30321
30542
  `);
30322
30543
  return EXIT_WARN7;
30323
30544
  }
30324
- if (process.argv[1] && pathToFileURL34(process.argv[1]).href === import.meta.url) {
30325
- process.exit(main40());
30545
+ if (process.argv[1] && pathToFileURL35(process.argv[1]).href === import.meta.url) {
30546
+ process.exit(main41());
30326
30547
  }
30327
- var _HERE8 = fileURLToPath43(import.meta.url);
30548
+ var _HERE9 = fileURLToPath44(import.meta.url);
30328
30549
 
30329
30550
  // src/scripts/hooks/design_slop_hook.ts
30330
30551
  import fs68 from "node:fs";
30331
30552
  import path67 from "node:path";
30332
- import { fileURLToPath as fileURLToPath44, pathToFileURL as pathToFileURL35 } from "node:url";
30553
+ import { fileURLToPath as fileURLToPath45, pathToFileURL as pathToFileURL36 } from "node:url";
30333
30554
  var SETTINGS_FILE8 = ".agent-settings.yml";
30334
30555
  var EXIT_ALLOW16 = 0;
30335
30556
  var EXIT_WARN8 = 2;
@@ -30406,7 +30627,7 @@ function writeState2(root, state) {
30406
30627
  function readStdin() {
30407
30628
  return readHookStdin();
30408
30629
  }
30409
- function main41() {
30630
+ function main42() {
30410
30631
  let envelope;
30411
30632
  try {
30412
30633
  const raw = readStdin();
@@ -30457,12 +30678,12 @@ function _isCliEntry31() {
30457
30678
  if (process.argv[1] === void 0) {
30458
30679
  return false;
30459
30680
  }
30460
- const argvUrl = pathToFileURL35(path67.resolve(process.argv[1])).href;
30681
+ const argvUrl = pathToFileURL36(path67.resolve(process.argv[1])).href;
30461
30682
  if (import.meta.url === argvUrl) {
30462
30683
  return true;
30463
30684
  }
30464
30685
  try {
30465
- const here = fs68.realpathSync(fileURLToPath44(import.meta.url));
30686
+ const here = fs68.realpathSync(fileURLToPath45(import.meta.url));
30466
30687
  const argv = fs68.realpathSync(path67.resolve(process.argv[1]));
30467
30688
  return here === argv;
30468
30689
  } catch {
@@ -30470,12 +30691,12 @@ function _isCliEntry31() {
30470
30691
  }
30471
30692
  }
30472
30693
  var isCliEntry11 = _isCliEntry31();
30473
- if (isCliEntry11) process.exit(main41());
30694
+ if (isCliEntry11) process.exit(main42());
30474
30695
 
30475
30696
  // src/scripts/hooks/code_graph_nudge_hook.ts
30476
30697
  import fs70 from "node:fs";
30477
30698
  import path69 from "node:path";
30478
- import { fileURLToPath as fileURLToPath45, pathToFileURL as pathToFileURL36 } from "node:url";
30699
+ import { fileURLToPath as fileURLToPath46, pathToFileURL as pathToFileURL37 } from "node:url";
30479
30700
 
30480
30701
  // src/scripts/code_graph/detect.ts
30481
30702
  import { execFileSync as execFileSync4 } from "node:child_process";
@@ -30710,7 +30931,7 @@ function nudgeReason(root) {
30710
30931
  }
30711
30932
  return "A fresh code-graph is present \u2014 for structure questions run `agent-config code-graph query|affected <symbol>` first; grep is the fallback (say which answered).";
30712
30933
  }
30713
- function main42() {
30934
+ function main43() {
30714
30935
  let envelope;
30715
30936
  try {
30716
30937
  const raw = readHookStdin();
@@ -30743,20 +30964,20 @@ function isCliEntry12() {
30743
30964
  return false;
30744
30965
  }
30745
30966
  if (process.argv[1] === void 0) return false;
30746
- const argvUrl = pathToFileURL36(path69.resolve(process.argv[1])).href;
30967
+ const argvUrl = pathToFileURL37(path69.resolve(process.argv[1])).href;
30747
30968
  if (import.meta.url === argvUrl) return true;
30748
30969
  try {
30749
- return fs70.realpathSync(fileURLToPath45(import.meta.url)) === fs70.realpathSync(path69.resolve(process.argv[1]));
30970
+ return fs70.realpathSync(fileURLToPath46(import.meta.url)) === fs70.realpathSync(path69.resolve(process.argv[1]));
30750
30971
  } catch {
30751
30972
  return false;
30752
30973
  }
30753
30974
  }
30754
- if (isCliEntry12()) process.exit(main42());
30975
+ if (isCliEntry12()) process.exit(main43());
30755
30976
 
30756
30977
  // src/scripts/hooks/suggestion_capture_hook.ts
30757
30978
  import fs71 from "node:fs";
30758
30979
  import path70 from "node:path";
30759
- import { fileURLToPath as fileURLToPath46, pathToFileURL as pathToFileURL37 } from "node:url";
30980
+ import { fileURLToPath as fileURLToPath47, pathToFileURL as pathToFileURL38 } from "node:url";
30760
30981
  var EXIT_ALLOW18 = 0;
30761
30982
  var SETTINGS_FILE10 = ".agent-settings.yml";
30762
30983
  var SINK_REL = path70.join("agents", "runtime", "state", "audit", "suggestion-capture.jsonl");
@@ -30893,7 +31114,7 @@ function eventOf(envelope, payload) {
30893
31114
  if (raw === "userpromptsubmit" || raw === "user_prompt_submit") return "user_prompt_submit";
30894
31115
  return raw;
30895
31116
  }
30896
- function main43(_argv2 = [], now = /* @__PURE__ */ new Date()) {
31117
+ function main44(_argv2 = [], now = /* @__PURE__ */ new Date()) {
30897
31118
  let envelope;
30898
31119
  let payload;
30899
31120
  try {
@@ -30947,20 +31168,20 @@ function main43(_argv2 = [], now = /* @__PURE__ */ new Date()) {
30947
31168
  function isCliEntry13() {
30948
31169
  if (true) return false;
30949
31170
  if (process.argv[1] === void 0) return false;
30950
- const argvUrl = pathToFileURL37(path70.resolve(process.argv[1])).href;
31171
+ const argvUrl = pathToFileURL38(path70.resolve(process.argv[1])).href;
30951
31172
  if (import.meta.url === argvUrl) return true;
30952
31173
  try {
30953
- return fs71.realpathSync(fileURLToPath46(import.meta.url)) === fs71.realpathSync(path70.resolve(process.argv[1]));
31174
+ return fs71.realpathSync(fileURLToPath47(import.meta.url)) === fs71.realpathSync(path70.resolve(process.argv[1]));
30954
31175
  } catch {
30955
31176
  return false;
30956
31177
  }
30957
31178
  }
30958
- if (isCliEntry13()) process.exit(main43());
31179
+ if (isCliEntry13()) process.exit(main44());
30959
31180
 
30960
31181
  // src/scripts/hooks/ui_route_nudge_hook.ts
30961
31182
  import * as fs73 from "node:fs";
30962
31183
  import * as path72 from "node:path";
30963
- import { fileURLToPath as fileURLToPath47, pathToFileURL as pathToFileURL38 } from "node:url";
31184
+ import { fileURLToPath as fileURLToPath48, pathToFileURL as pathToFileURL39 } from "node:url";
30964
31185
 
30965
31186
  // src/scripts/_lib/hook_settings.ts
30966
31187
  import * as fs72 from "node:fs";
@@ -31117,7 +31338,7 @@ function stateChanged(before, after) {
31117
31338
  function nudgeReason2(file) {
31118
31339
  return `Non-trivial UI write to ${file} with no design consultation this session. Run \`existing-ui-audit\` first, then the fe-design loop (brief \u2192 inventory, if an artifact was provided \u2192 build \u2192 review). Skip only if this is ui-trivial: <=1 file, <=5 lines, no new component, no new state, no new dependency.`;
31119
31340
  }
31120
- function main44() {
31341
+ function main45() {
31121
31342
  let envelope;
31122
31343
  try {
31123
31344
  const raw = readHookStdin();
@@ -31147,16 +31368,16 @@ function main44() {
31147
31368
  function isCliEntry14() {
31148
31369
  const entry = process.argv[1];
31149
31370
  if (!entry) return false;
31150
- return pathToFileURL38(path72.resolve(entry)).href === import.meta.url;
31371
+ return pathToFileURL39(path72.resolve(entry)).href === import.meta.url;
31151
31372
  }
31152
- if (isCliEntry14()) process.exit(main44());
31153
- var _HOOK_FILE = fileURLToPath47(import.meta.url);
31373
+ if (isCliEntry14()) process.exit(main45());
31374
+ var _HOOK_FILE = fileURLToPath48(import.meta.url);
31154
31375
 
31155
31376
  // src/scripts/hooks/orchestration_record_hook.ts
31156
31377
  import * as crypto8 from "node:crypto";
31157
31378
  import * as fs75 from "node:fs";
31158
31379
  import * as path74 from "node:path";
31159
- import { fileURLToPath as fileURLToPath48, pathToFileURL as pathToFileURL40 } from "node:url";
31380
+ import { fileURLToPath as fileURLToPath49, pathToFileURL as pathToFileURL41 } from "node:url";
31160
31381
 
31161
31382
  // src/scripts/_lib/audit_field_provenance.ts
31162
31383
  var MAX_APPLIED_IDS = 32;
@@ -31418,7 +31639,7 @@ function buildOrchestrationLine(input) {
31418
31639
  import * as crypto7 from "node:crypto";
31419
31640
  import * as fs74 from "node:fs";
31420
31641
  import * as path73 from "node:path";
31421
- import { pathToFileURL as pathToFileURL39 } from "node:url";
31642
+ import { pathToFileURL as pathToFileURL40 } from "node:url";
31422
31643
  var DEFAULT_DIR = "agents/runtime/state/audit";
31423
31644
  function parseFlags(argv) {
31424
31645
  const flags = {};
@@ -31468,7 +31689,7 @@ function contentHashId(input) {
31468
31689
  });
31469
31690
  return crypto7.createHash("sha256").update(canonical2).digest("hex").slice(0, 26).toUpperCase();
31470
31691
  }
31471
- function main45(argv = process.argv.slice(2)) {
31692
+ function main46(argv = process.argv.slice(2)) {
31472
31693
  const flags = parseFlags(argv);
31473
31694
  const dir = str4(flags, "dir") ?? DEFAULT_DIR;
31474
31695
  const dryRun = flags["dry-run"] === true;
@@ -31559,8 +31780,8 @@ function main45(argv = process.argv.slice(2)) {
31559
31780
  return 0;
31560
31781
  }
31561
31782
  if (process.argv[1] !== void 0) {
31562
- const invokedUrl = pathToFileURL39(path73.resolve(process.argv[1])).href;
31563
- if (import.meta.url === invokedUrl) process.exit(main45());
31783
+ const invokedUrl = pathToFileURL40(path73.resolve(process.argv[1])).href;
31784
+ if (import.meta.url === invokedUrl) process.exit(main46());
31564
31785
  }
31565
31786
 
31566
31787
  // src/scripts/hooks/orchestration_record_hook.ts
@@ -31691,7 +31912,7 @@ function _resolveRoot2(envelope) {
31691
31912
  }
31692
31913
  return process.cwd();
31693
31914
  }
31694
- function main46() {
31915
+ function main47() {
31695
31916
  const raw = readHookStdin();
31696
31917
  let envelope = {};
31697
31918
  try {
@@ -31706,25 +31927,25 @@ function _isCliEntry32() {
31706
31927
  return false;
31707
31928
  }
31708
31929
  if (process.argv[1] === void 0) return false;
31709
- const argvUrl = pathToFileURL40(path74.resolve(process.argv[1])).href;
31930
+ const argvUrl = pathToFileURL41(path74.resolve(process.argv[1])).href;
31710
31931
  if (import.meta.url === argvUrl) return true;
31711
31932
  try {
31712
- return fs75.realpathSync(fileURLToPath48(import.meta.url)) === fs75.realpathSync(path74.resolve(process.argv[1]));
31933
+ return fs75.realpathSync(fileURLToPath49(import.meta.url)) === fs75.realpathSync(path74.resolve(process.argv[1]));
31713
31934
  } catch {
31714
31935
  return false;
31715
31936
  }
31716
31937
  }
31717
- if (_isCliEntry32()) process.exit(main46());
31938
+ if (_isCliEntry32()) process.exit(main47());
31718
31939
 
31719
31940
  // src/scripts/hooks/telemetry_flush_hook.ts
31720
31941
  import * as fs76 from "node:fs";
31721
31942
  import * as path75 from "node:path";
31722
- import { fileURLToPath as fileURLToPath49, pathToFileURL as pathToFileURL41 } from "node:url";
31943
+ import { fileURLToPath as fileURLToPath50, pathToFileURL as pathToFileURL42 } from "node:url";
31723
31944
  var EXIT_ALLOW21 = 0;
31724
31945
  var SENDER_REL = "../../agent-src/templates/scripts/telemetry/flush_sender.mjs";
31725
31946
  function resolveSenderScript() {
31726
31947
  try {
31727
- const here = path75.dirname(fileURLToPath49(import.meta.url));
31948
+ const here = path75.dirname(fileURLToPath50(import.meta.url));
31728
31949
  const candidate = path75.resolve(here, SENDER_REL);
31729
31950
  return fs76.statSync(candidate).isFile() ? candidate : null;
31730
31951
  } catch {
@@ -31752,7 +31973,7 @@ function flushFor(consumer_root, sender = resolveSenderScript()) {
31752
31973
  return { result: "inactive" };
31753
31974
  }
31754
31975
  }
31755
- function main47() {
31976
+ function main48() {
31756
31977
  const raw = readHookStdin();
31757
31978
  let envelope = {};
31758
31979
  try {
@@ -31768,20 +31989,20 @@ function _isCliEntry33() {
31768
31989
  return false;
31769
31990
  }
31770
31991
  if (process.argv[1] === void 0) return false;
31771
- const argvUrl = pathToFileURL41(path75.resolve(process.argv[1])).href;
31992
+ const argvUrl = pathToFileURL42(path75.resolve(process.argv[1])).href;
31772
31993
  if (import.meta.url === argvUrl) return true;
31773
31994
  try {
31774
- return fs76.realpathSync(fileURLToPath49(import.meta.url)) === fs76.realpathSync(path75.resolve(process.argv[1]));
31995
+ return fs76.realpathSync(fileURLToPath50(import.meta.url)) === fs76.realpathSync(path75.resolve(process.argv[1]));
31775
31996
  } catch {
31776
31997
  return false;
31777
31998
  }
31778
31999
  }
31779
- if (_isCliEntry33()) process.exit(main47());
32000
+ if (_isCliEntry33()) process.exit(main48());
31780
32001
 
31781
32002
  // src/scripts/hooks/delegation_nudge_hook.ts
31782
32003
  import fs77 from "node:fs";
31783
32004
  import path76 from "node:path";
31784
- import { fileURLToPath as fileURLToPath50, pathToFileURL as pathToFileURL42 } from "node:url";
32005
+ import { fileURLToPath as fileURLToPath51, pathToFileURL as pathToFileURL43 } from "node:url";
31785
32006
 
31786
32007
  // src/scripts/_lib/host_capability.ts
31787
32008
  import process12 from "node:process";
@@ -31793,6 +32014,7 @@ var SAFE_DEFAULT = {
31793
32014
  separate_quota_pool: false,
31794
32015
  agent_teams: false,
31795
32016
  worker_respawn: false,
32017
+ structured_ask: false,
31796
32018
  reads_project_mcp_config: false,
31797
32019
  // `true` because the safe answer here is "there is still a step", not
31798
32020
  // "there is nothing to do" — see the field's own note.
@@ -31814,6 +32036,7 @@ function normalizeHostManifest(input) {
31814
32036
  separate_quota_pool: asBool(src.separate_quota_pool),
31815
32037
  agent_teams: asBool(src.agent_teams),
31816
32038
  worker_respawn: asBool(src.worker_respawn),
32039
+ structured_ask: asBool(src.structured_ask),
31817
32040
  reads_project_mcp_config: asBool(src.reads_project_mcp_config),
31818
32041
  // Inverted coercion, matching the inverted default: only an explicit
31819
32042
  // `false` clears the residual, so an absent or malformed value keeps
@@ -31822,7 +32045,7 @@ function normalizeHostManifest(input) {
31822
32045
  };
31823
32046
  }
31824
32047
  var HOST_CAPABILITY_REGISTRY = {
31825
- claude: { subagent_spawn: true, parallel_spawn: true }
32048
+ claude: { subagent_spawn: true, parallel_spawn: true, structured_ask: false }
31826
32049
  };
31827
32050
  function resolveHostCapabilities(hostId, override) {
31828
32051
  if (override !== void 0 && override !== null && typeof override === "object" && !Array.isArray(override)) {
@@ -32121,7 +32344,7 @@ function resolveSubagentRouting(inp) {
32121
32344
  // src/scripts/hooks/delegation_nudge_hook.ts
32122
32345
  var EXIT_ALLOW22 = 0;
32123
32346
  var EXIT_WARN11 = 2;
32124
- function _isObject14(v) {
32347
+ function _isObject15(v) {
32125
32348
  return typeof v === "object" && v !== null && !Array.isArray(v);
32126
32349
  }
32127
32350
  var FILE_TOKEN_RE = /`?\b[\w][\w.\-]{0,80}\.(ts|tsx|js|jsx|mjs|cjs|py|php|rb|go|rs|java|kt|swift|md|mdx|json|ya?ml|css|scss|less|html|vue|svelte|sql|sh|bash|c|cpp|h|hpp|cs|toml|xml)\b`?/gi;
@@ -32230,6 +32453,12 @@ function buildNudgeLine(rung, classification, sliceCount, tier) {
32230
32453
  if (rung === 0.5) {
32231
32454
  return `<delegation-nudge>rung-0.5: ask, est. <1k tokens. This is a single bounded question \u2014 answer it via ONE completion (\`./scripts-run src/scripts/ask_transport "<question>"\`) instead of a subagent spawn (measured spawn floor: ~251k tokens) \u2014 ${classification.reason}.</delegation-nudge>`;
32232
32455
  }
32456
+ if (rung === 4) {
32457
+ return `<delegation-nudge>rung-4: council. This is contested judgment, not a slice to dispatch \u2014 route it to the council yourself via \`./scripts-run src/scripts/council_cli run --input <file>\` (check reachability first with \`agent-config council:status\`; the file path is the input, never an inline question). Not a spawn, and not run for you \u2014 ${classification.reason}.</delegation-nudge>`;
32458
+ }
32459
+ if (rung === 3) {
32460
+ return `<delegation-nudge>rung-3: team. These slices must see each other's state during the run, so a set of independent subagent spawns cannot express it \u2014 use the host teams primitive, or fall back to \`./scripts-run src/scripts/ask_transport "<question>"\` for a bounded sub-question. Not a spawn, and not run for you \u2014 ${classification.reason}.</delegation-nudge>`;
32461
+ }
32233
32462
  const modeLabel = classification.mode ?? "single-slice";
32234
32463
  return `<delegation-nudge>${rungLabel}: dispatch ${modeLabel} (${sliceCount} ${unit}, ${tier} tier recommended). Consider dispatching via subagent-orchestration instead of doing every slice in-session \u2014 ${classification.reason}.</delegation-nudge>`;
32235
32464
  }
@@ -32248,6 +32477,14 @@ function classifyPrompt(prompt, workspace_root, hostId) {
32248
32477
  agentTeams,
32249
32478
  insideSubagentSession: sessionRole !== "orchestrator"
32250
32479
  });
32480
+ if (ladder2.verdict === "team" || ladder2.verdict === "council") {
32481
+ return {
32482
+ classification: { delegable: false, action: "ask", mode: null, reason: ladder2.reason },
32483
+ sliceCount: 0,
32484
+ tier: recommendSliceTier(downshift, separate_quota_pool),
32485
+ rung: ladder2.rung
32486
+ };
32487
+ }
32251
32488
  if (ladder2.verdict !== "subagent") {
32252
32489
  return null;
32253
32490
  }
@@ -32280,7 +32517,7 @@ function _workspaceRoot4(envelope) {
32280
32517
  }
32281
32518
  return process.cwd();
32282
32519
  }
32283
- function main48() {
32520
+ function main49() {
32284
32521
  let envelope = {};
32285
32522
  try {
32286
32523
  const raw = readHookStdin();
@@ -32288,13 +32525,13 @@ function main48() {
32288
32525
  } catch {
32289
32526
  return EXIT_ALLOW22;
32290
32527
  }
32291
- const env = _isObject14(envelope) ? envelope : {};
32528
+ const env = _isObject15(envelope) ? envelope : {};
32292
32529
  const event = env["event"];
32293
32530
  const slot = typeof event === "string" && event !== "" ? event : "user_prompt_submit";
32294
32531
  if (slot !== "user_prompt_submit") {
32295
32532
  return EXIT_ALLOW22;
32296
32533
  }
32297
- const payload = _isObject14(env["payload"]) ? env["payload"] : env;
32534
+ const payload = _isObject15(env["payload"]) ? env["payload"] : env;
32298
32535
  const prompt = _extractPrompt2(payload);
32299
32536
  if (!prompt) {
32300
32537
  return EXIT_ALLOW22;
@@ -32326,12 +32563,12 @@ function _isCliEntry34() {
32326
32563
  if (process.argv[1] === void 0) {
32327
32564
  return false;
32328
32565
  }
32329
- const argvUrl = pathToFileURL42(path76.resolve(process.argv[1])).href;
32566
+ const argvUrl = pathToFileURL43(path76.resolve(process.argv[1])).href;
32330
32567
  if (import.meta.url === argvUrl) {
32331
32568
  return true;
32332
32569
  }
32333
32570
  try {
32334
- const here = fs77.realpathSync(fileURLToPath50(import.meta.url));
32571
+ const here = fs77.realpathSync(fileURLToPath51(import.meta.url));
32335
32572
  const argv = fs77.realpathSync(path76.resolve(process.argv[1]));
32336
32573
  return here === argv;
32337
32574
  } catch {
@@ -32339,13 +32576,13 @@ function _isCliEntry34() {
32339
32576
  }
32340
32577
  }
32341
32578
  if (_isCliEntry34()) {
32342
- process.exit(main48());
32579
+ process.exit(main49());
32343
32580
  }
32344
32581
 
32345
32582
  // src/scripts/hooks/skill_route_hook.ts
32346
32583
  import fs80 from "node:fs";
32347
32584
  import path79 from "node:path";
32348
- import { fileURLToPath as fileURLToPath52, pathToFileURL as pathToFileURL44 } from "node:url";
32585
+ import { fileURLToPath as fileURLToPath53, pathToFileURL as pathToFileURL45 } from "node:url";
32349
32586
 
32350
32587
  // src/scripts/_lib/skill_catalogue.ts
32351
32588
  import * as fs78 from "node:fs";
@@ -32418,7 +32655,7 @@ function knownBareNames(records, host) {
32418
32655
  // src/scripts/skill_tools/score_skill_relevance.ts
32419
32656
  import * as fs79 from "node:fs";
32420
32657
  import * as path78 from "node:path";
32421
- import { fileURLToPath as fileURLToPath51, pathToFileURL as pathToFileURL43 } from "node:url";
32658
+ import { fileURLToPath as fileURLToPath52, pathToFileURL as pathToFileURL44 } from "node:url";
32422
32659
 
32423
32660
  // src/shared/skillRanking.ts
32424
32661
  var TOKEN_RE2 = /[a-z][a-z0-9]+/g;
@@ -32549,8 +32786,8 @@ function scoreSkill(taskTerms, skill, terms) {
32549
32786
  }
32550
32787
 
32551
32788
  // src/scripts/skill_tools/score_skill_relevance.ts
32552
- var _HERE9 = fileURLToPath51(import.meta.url);
32553
- var ROOT2 = path78.resolve(path78.dirname(_HERE9), "..", "..", "..");
32789
+ var _HERE10 = fileURLToPath52(import.meta.url);
32790
+ var ROOT2 = path78.resolve(path78.dirname(_HERE10), "..", "..", "..");
32554
32791
  var DEFAULT_SKILLS_DIR = resolveSkillsRoot(ROOT2);
32555
32792
  function pyLen2(s) {
32556
32793
  let n = 0;
@@ -32872,7 +33109,7 @@ function catalogueDeficit(dir) {
32872
33109
  }
32873
33110
  return null;
32874
33111
  }
32875
- function main49(argv = null) {
33112
+ function main50(argv = null) {
32876
33113
  const args = parse_args8(argv ?? process.argv.slice(2));
32877
33114
  const task = args.sample ? _SAMPLE.task : args.task;
32878
33115
  if (!task) {
@@ -32915,12 +33152,12 @@ function _isCliEntry35() {
32915
33152
  if (process.argv[1] === void 0) {
32916
33153
  return false;
32917
33154
  }
32918
- const argvUrl = pathToFileURL43(path78.resolve(process.argv[1])).href;
33155
+ const argvUrl = pathToFileURL44(path78.resolve(process.argv[1])).href;
32919
33156
  if (import.meta.url === argvUrl) {
32920
33157
  return true;
32921
33158
  }
32922
33159
  try {
32923
- const here = fs79.realpathSync(fileURLToPath51(import.meta.url));
33160
+ const here = fs79.realpathSync(fileURLToPath52(import.meta.url));
32924
33161
  const argv = fs79.realpathSync(path78.resolve(process.argv[1]));
32925
33162
  return here === argv;
32926
33163
  } catch {
@@ -32929,7 +33166,7 @@ function _isCliEntry35() {
32929
33166
  }
32930
33167
  var _isMain5 = _isCliEntry35();
32931
33168
  if (_isMain5) {
32932
- process.exitCode = main49();
33169
+ process.exitCode = main50();
32933
33170
  }
32934
33171
 
32935
33172
  // src/scripts/hooks/skill_route_hook.ts
@@ -32938,7 +33175,7 @@ var EXIT_WARN12 = 2;
32938
33175
  var MIN_TOP_SCORE = 31;
32939
33176
  var MIN_TASK_TERMS = 3;
32940
33177
  var TOP_K = 3;
32941
- function _isObject15(v) {
33178
+ function _isObject16(v) {
32942
33179
  return typeof v === "object" && v !== null && !Array.isArray(v);
32943
33180
  }
32944
33181
  function knownBareForHost(workspaceRoot3, host) {
@@ -32996,7 +33233,7 @@ function _workspaceRoot5(envelope) {
32996
33233
  const v = envelope["workspace_root"];
32997
33234
  return typeof v === "string" && v ? v : process.cwd();
32998
33235
  }
32999
- function main50() {
33236
+ function main51() {
33000
33237
  let envelope = {};
33001
33238
  try {
33002
33239
  const raw = readHookStdin();
@@ -33004,11 +33241,11 @@ function main50() {
33004
33241
  } catch {
33005
33242
  return EXIT_ALLOW23;
33006
33243
  }
33007
- const env = _isObject15(envelope) ? envelope : {};
33244
+ const env = _isObject16(envelope) ? envelope : {};
33008
33245
  const event = env["event"];
33009
33246
  const slot = typeof event === "string" && event !== "" ? event : "user_prompt_submit";
33010
33247
  if (slot !== "user_prompt_submit") return EXIT_ALLOW23;
33011
- const payload = _isObject15(env["payload"]) ? env["payload"] : env;
33248
+ const payload = _isObject16(env["payload"]) ? env["payload"] : env;
33012
33249
  const prompt = _extractPrompt3(payload);
33013
33250
  if (!prompt) return EXIT_ALLOW23;
33014
33251
  if (isSyntheticPrompt(prompt)) return EXIT_ALLOW23;
@@ -33036,10 +33273,10 @@ function main50() {
33036
33273
  function _isCliEntry36() {
33037
33274
  if (true) return false;
33038
33275
  if (process.argv[1] === void 0) return false;
33039
- const argvUrl = pathToFileURL44(path79.resolve(process.argv[1])).href;
33276
+ const argvUrl = pathToFileURL45(path79.resolve(process.argv[1])).href;
33040
33277
  if (import.meta.url === argvUrl) return true;
33041
33278
  try {
33042
- const here = fs80.realpathSync(fileURLToPath52(import.meta.url));
33279
+ const here = fs80.realpathSync(fileURLToPath53(import.meta.url));
33043
33280
  const argv = fs80.realpathSync(path79.resolve(process.argv[1]));
33044
33281
  return here === argv;
33045
33282
  } catch {
@@ -33047,14 +33284,14 @@ function _isCliEntry36() {
33047
33284
  }
33048
33285
  }
33049
33286
  if (_isCliEntry36()) {
33050
- process.exit(main50());
33287
+ process.exit(main51());
33051
33288
  }
33052
33289
 
33053
33290
  // src/scripts/hooks/rule_inject_hook.ts
33054
33291
  import * as fs82 from "node:fs";
33055
33292
  import * as path81 from "node:path";
33056
33293
  import process13 from "node:process";
33057
- import { fileURLToPath as fileURLToPath53, pathToFileURL as pathToFileURL45 } from "node:url";
33294
+ import { fileURLToPath as fileURLToPath54, pathToFileURL as pathToFileURL46 } from "node:url";
33058
33295
 
33059
33296
  // src/scripts/_lib/lean_projection_mode.ts
33060
33297
  var DEFAULT_LEAN_PROJECTION_MODE = "eager-all";
@@ -33421,7 +33658,7 @@ function gateOpen(root, cliEntry) {
33421
33658
  if (hookSectionEnabled(root, "rule_inject")) return true;
33422
33659
  return cliEntry && process13.env["AGENT_CONFIG_REPLAY"] !== "1";
33423
33660
  }
33424
- function main51(argv = process13.argv.slice(2)) {
33661
+ function main52(argv = process13.argv.slice(2)) {
33425
33662
  let eventOverride = null;
33426
33663
  for (let i = 0; i < argv.length; i += 1) {
33427
33664
  if (argv[i] === "--event") {
@@ -33480,16 +33717,16 @@ function main51(argv = process13.argv.slice(2)) {
33480
33717
  function _isCliEntry37() {
33481
33718
  if (true) return false;
33482
33719
  if (process13.argv[1] === void 0) return false;
33483
- const argvUrl = pathToFileURL45(path81.resolve(process13.argv[1])).href;
33720
+ const argvUrl = pathToFileURL46(path81.resolve(process13.argv[1])).href;
33484
33721
  if (import.meta.url === argvUrl) return true;
33485
33722
  try {
33486
- return fs82.realpathSync(fileURLToPath53(import.meta.url)) === fs82.realpathSync(path81.resolve(process13.argv[1]));
33723
+ return fs82.realpathSync(fileURLToPath54(import.meta.url)) === fs82.realpathSync(path81.resolve(process13.argv[1]));
33487
33724
  } catch {
33488
33725
  return false;
33489
33726
  }
33490
33727
  }
33491
33728
  if (_isCliEntry37()) {
33492
- process13.exit(main51());
33729
+ process13.exit(main52());
33493
33730
  }
33494
33731
 
33495
33732
  // src/scripts/hooks/end_review_nudge_hook.ts
@@ -33498,7 +33735,7 @@ import * as crypto9 from "node:crypto";
33498
33735
  import * as fs83 from "node:fs";
33499
33736
  import * as os10 from "node:os";
33500
33737
  import * as path82 from "node:path";
33501
- import { fileURLToPath as fileURLToPath54, pathToFileURL as pathToFileURL46 } from "node:url";
33738
+ import { fileURLToPath as fileURLToPath55, pathToFileURL as pathToFileURL47 } from "node:url";
33502
33739
 
33503
33740
  // src/scripts/_lib/review_skipped_record.ts
33504
33741
  var PRODUCER_PRIVACY_CLASS2 = "ids-only";
@@ -33752,7 +33989,7 @@ function markFiredThisSession(workspaceRoot3, sessionKey, ts) {
33752
33989
  function _read_stdin3() {
33753
33990
  return readHookStdin();
33754
33991
  }
33755
- function main52() {
33992
+ function main53() {
33756
33993
  const [envelope, payload] = unwrap(_read_stdin3(), "claude");
33757
33994
  const event = String(envelope["event"] ?? "");
33758
33995
  if (event !== "" && event !== "stop") {
@@ -33811,12 +34048,12 @@ function _isCliEntry38() {
33811
34048
  if (process.argv[1] === void 0) {
33812
34049
  return false;
33813
34050
  }
33814
- const argvUrl = pathToFileURL46(path82.resolve(process.argv[1])).href;
34051
+ const argvUrl = pathToFileURL47(path82.resolve(process.argv[1])).href;
33815
34052
  if (import.meta.url === argvUrl) {
33816
34053
  return true;
33817
34054
  }
33818
34055
  try {
33819
- const here = fs83.realpathSync(fileURLToPath54(import.meta.url));
34056
+ const here = fs83.realpathSync(fileURLToPath55(import.meta.url));
33820
34057
  const argv = fs83.realpathSync(path82.resolve(process.argv[1]));
33821
34058
  return here === argv;
33822
34059
  } catch {
@@ -33824,19 +34061,19 @@ function _isCliEntry38() {
33824
34061
  }
33825
34062
  }
33826
34063
  if (_isCliEntry38()) {
33827
- process.exit(main52());
34064
+ process.exit(main53());
33828
34065
  }
33829
34066
 
33830
34067
  // src/scripts/hooks/turn_end_gate_hook.ts
33831
34068
  import * as fs85 from "node:fs";
33832
34069
  import * as path84 from "node:path";
33833
- import { fileURLToPath as fileURLToPath56, pathToFileURL as pathToFileURL48 } from "node:url";
34070
+ import { fileURLToPath as fileURLToPath57, pathToFileURL as pathToFileURL49 } from "node:url";
33834
34071
 
33835
34072
  // src/scripts/hooks/subagent_ledger_hook.ts
33836
34073
  import * as crypto10 from "node:crypto";
33837
34074
  import * as fs84 from "node:fs";
33838
34075
  import * as path83 from "node:path";
33839
- import { fileURLToPath as fileURLToPath55, pathToFileURL as pathToFileURL47 } from "node:url";
34076
+ import { fileURLToPath as fileURLToPath56, pathToFileURL as pathToFileURL48 } from "node:url";
33840
34077
 
33841
34078
  // src/scripts/_lib/subagent_response.ts
33842
34079
  var MAX_SUMMARY_CHARS = 2e3;
@@ -34290,7 +34527,7 @@ function resolveConsumerRoot(envelope) {
34290
34527
  }
34291
34528
  return process.cwd();
34292
34529
  }
34293
- function main53() {
34530
+ function main54() {
34294
34531
  const raw = readHookStdin();
34295
34532
  let envelope = {};
34296
34533
  try {
@@ -34305,15 +34542,15 @@ function _isCliEntry39() {
34305
34542
  return false;
34306
34543
  }
34307
34544
  if (process.argv[1] === void 0) return false;
34308
- const argvUrl = pathToFileURL47(path83.resolve(process.argv[1])).href;
34545
+ const argvUrl = pathToFileURL48(path83.resolve(process.argv[1])).href;
34309
34546
  if (import.meta.url === argvUrl) return true;
34310
34547
  try {
34311
- return fs84.realpathSync(fileURLToPath55(import.meta.url)) === fs84.realpathSync(path83.resolve(process.argv[1]));
34548
+ return fs84.realpathSync(fileURLToPath56(import.meta.url)) === fs84.realpathSync(path83.resolve(process.argv[1]));
34312
34549
  } catch {
34313
34550
  return false;
34314
34551
  }
34315
34552
  }
34316
- if (_isCliEntry39()) process.exit(main53());
34553
+ if (_isCliEntry39()) process.exit(main54());
34317
34554
 
34318
34555
  // src/scripts/hooks/turn_end_gate_hook.ts
34319
34556
  var EXIT_BLOCK3 = 1;
@@ -34475,13 +34712,13 @@ function readLanguagePin(workspaceRoot3, session_id) {
34475
34712
  function detectLanguage(reply, pinned) {
34476
34713
  if (pinned !== "de" && pinned !== "en") return null;
34477
34714
  const prose = visibleProse(reply);
34478
- const verdict = classify(prose);
34479
- if (verdict.language === "und") return null;
34480
- if (verdict.language === pinned) return null;
34715
+ const verdict2 = classify(prose);
34716
+ if (verdict2.language === "und") return null;
34717
+ if (verdict2.language === pinned) return null;
34481
34718
  return {
34482
34719
  detector: "language",
34483
34720
  evidence: prose.trim().slice(0, 120),
34484
- reason: `the pinned reply language is "${pinned}" but the reply classifies as "${verdict.language}" (${verdict.de_markers} de / ${verdict.en_markers} en markers; code, quotes, tables, URLs and paths excluded, then scored lead-first by the same classifier that sets the pin)`
34721
+ reason: `the pinned reply language is "${pinned}" but the reply classifies as "${verdict2.language}" (${verdict2.de_markers} de / ${verdict2.en_markers} en markers; code, quotes, tables, URLs and paths excluded, then scored lead-first by the same classifier that sets the pin)`
34485
34722
  };
34486
34723
  }
34487
34724
  var _EDIT_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
@@ -34635,7 +34872,7 @@ function _messageText(content) {
34635
34872
  function str8(v) {
34636
34873
  return typeof v === "string" ? v : "";
34637
34874
  }
34638
- function main54() {
34875
+ function main55() {
34639
34876
  let envelope;
34640
34877
  let payload;
34641
34878
  try {
@@ -34709,12 +34946,12 @@ function _isCliEntry40() {
34709
34946
  if (process.argv[1] === void 0) {
34710
34947
  return false;
34711
34948
  }
34712
- const argvUrl = pathToFileURL48(path84.resolve(process.argv[1])).href;
34949
+ const argvUrl = pathToFileURL49(path84.resolve(process.argv[1])).href;
34713
34950
  if (import.meta.url === argvUrl) {
34714
34951
  return true;
34715
34952
  }
34716
34953
  try {
34717
- const here = fs85.realpathSync(fileURLToPath56(import.meta.url));
34954
+ const here = fs85.realpathSync(fileURLToPath57(import.meta.url));
34718
34955
  const argv = fs85.realpathSync(path84.resolve(process.argv[1]));
34719
34956
  return here === argv;
34720
34957
  } catch {
@@ -34722,7 +34959,7 @@ function _isCliEntry40() {
34722
34959
  }
34723
34960
  }
34724
34961
  if (_isCliEntry40()) {
34725
- process.exit(main54());
34962
+ process.exit(main55());
34726
34963
  }
34727
34964
 
34728
34965
  // src/scripts/hooks/edit_shape_hook.ts
@@ -34730,7 +34967,7 @@ import { spawnSync as spawnSync8 } from "node:child_process";
34730
34967
  import * as crypto11 from "node:crypto";
34731
34968
  import * as fs86 from "node:fs";
34732
34969
  import * as path85 from "node:path";
34733
- import { fileURLToPath as fileURLToPath57, pathToFileURL as pathToFileURL49 } from "node:url";
34970
+ import { fileURLToPath as fileURLToPath58, pathToFileURL as pathToFileURL50 } from "node:url";
34734
34971
  var EXIT_ALLOW27 = 0;
34735
34972
  var EXIT_WARN15 = 2;
34736
34973
  var MIN_FILE_LINES = 50;
@@ -34825,7 +35062,7 @@ function extractFilePath2(payload) {
34825
35062
  if (!isObject13(ti)) return "";
34826
35063
  return str9(ti["file_path"] ?? ti["path"] ?? ti["filePath"]);
34827
35064
  }
34828
- function main55() {
35065
+ function main56() {
34829
35066
  try {
34830
35067
  const [envelope, payload] = unwrap(readHookStdin(), "claude");
34831
35068
  const event = str9(envelope["event"]);
@@ -34866,12 +35103,12 @@ function _isCliEntry41() {
34866
35103
  if (process.argv[1] === void 0) {
34867
35104
  return false;
34868
35105
  }
34869
- const argvUrl = pathToFileURL49(path85.resolve(process.argv[1])).href;
35106
+ const argvUrl = pathToFileURL50(path85.resolve(process.argv[1])).href;
34870
35107
  if (import.meta.url === argvUrl) {
34871
35108
  return true;
34872
35109
  }
34873
35110
  try {
34874
- const here = fs86.realpathSync(fileURLToPath57(import.meta.url));
35111
+ const here = fs86.realpathSync(fileURLToPath58(import.meta.url));
34875
35112
  const argv = fs86.realpathSync(path85.resolve(process.argv[1]));
34876
35113
  return here === argv;
34877
35114
  } catch {
@@ -34879,13 +35116,13 @@ function _isCliEntry41() {
34879
35116
  }
34880
35117
  }
34881
35118
  if (_isCliEntry41()) {
34882
- process.exit(main55());
35119
+ process.exit(main56());
34883
35120
  }
34884
35121
 
34885
35122
  // src/scripts/hooks/comment_discipline_hook.ts
34886
35123
  import * as fs88 from "node:fs";
34887
35124
  import * as path88 from "node:path";
34888
- import { fileURLToPath as fileURLToPath59, pathToFileURL as pathToFileURL50 } from "node:url";
35125
+ import { fileURLToPath as fileURLToPath60, pathToFileURL as pathToFileURL51 } from "node:url";
34889
35126
 
34890
35127
  // src/scripts/lint_code_comments.ts
34891
35128
  import { spawnSync as spawnSync10 } from "node:child_process";
@@ -34893,7 +35130,7 @@ import * as fs87 from "node:fs";
34893
35130
  import * as os11 from "node:os";
34894
35131
  import * as path87 from "node:path";
34895
35132
  import process15 from "node:process";
34896
- import { fileURLToPath as fileURLToPath58 } from "node:url";
35133
+ import { fileURLToPath as fileURLToPath59 } from "node:url";
34897
35134
 
34898
35135
  // src/scripts/_lib/gate_self_test.ts
34899
35136
  import { spawnSync as spawnSync9 } from "node:child_process";
@@ -34958,7 +35195,7 @@ ${opts.gate} --self-test: ${String(opts.cases.length - failed)}/${String(opts.ca
34958
35195
  }
34959
35196
 
34960
35197
  // src/scripts/lint_code_comments.ts
34961
- var _HERE10 = fileURLToPath58(import.meta.url);
35198
+ var _HERE11 = fileURLToPath59(import.meta.url);
34962
35199
  var SCANNED_EXTENSIONS = /* @__PURE__ */ new Set([
34963
35200
  ".ts",
34964
35201
  ".tsx",
@@ -35395,8 +35632,8 @@ var COMMENT_CASES = [
35395
35632
  flags: ["de-comment"]
35396
35633
  }
35397
35634
  ];
35398
- function selfTest() {
35399
- const repoRoot = path87.resolve(path87.dirname(_HERE10), "..", "..");
35635
+ function selfTest2() {
35636
+ const repoRoot = path87.resolve(path87.dirname(_HERE11), "..", "..");
35400
35637
  const dir = fs87.mkdtempSync(path87.join(os11.tmpdir(), "lcc-selftest-"));
35401
35638
  const exercise = (testCase, index) => {
35402
35639
  const file = path87.join(dir, `case-${String(index)}.ts`);
@@ -35430,7 +35667,7 @@ Classes: de-comment \xB7 report-comment \xB7 provenance-comment
35430
35667
  Escape: code-comment-allow <class|*> -- <reason> (per line)
35431
35668
  code-comment-allow-file -- <reason> (first 2000 chars)
35432
35669
  `;
35433
- function main56(argv) {
35670
+ function main57(argv) {
35434
35671
  if (argv.includes("--help") || argv.includes("-h")) {
35435
35672
  process15.stdout.write(HELP);
35436
35673
  return 0;
@@ -35440,10 +35677,10 @@ function main56(argv) {
35440
35677
  process15.stderr.write("lint_code_comments: refusing to nest --self-test inside a self-test child\n");
35441
35678
  return 2;
35442
35679
  }
35443
- return selfTest();
35680
+ return selfTest2();
35444
35681
  }
35445
35682
  let base = "origin/main";
35446
- let root = path87.resolve(path87.dirname(_HERE10), "..", "..");
35683
+ let root = path87.resolve(path87.dirname(_HERE11), "..", "..");
35447
35684
  let reportOnly = false;
35448
35685
  const explicit = [];
35449
35686
  for (let i = 0; i < argv.length; i++) {
@@ -35537,12 +35774,12 @@ var _isMain6 = (() => {
35537
35774
  const entry = process15.argv[1];
35538
35775
  if (!entry) return false;
35539
35776
  try {
35540
- return fs87.realpathSync(entry) === fs87.realpathSync(_HERE10);
35777
+ return fs87.realpathSync(entry) === fs87.realpathSync(_HERE11);
35541
35778
  } catch {
35542
35779
  return false;
35543
35780
  }
35544
35781
  })();
35545
- if (_isMain6) process15.exit(main56(process15.argv.slice(2)));
35782
+ if (_isMain6) process15.exit(main57(process15.argv.slice(2)));
35546
35783
 
35547
35784
  // src/scripts/hooks/comment_discipline_hook.ts
35548
35785
  var EXIT_ALLOW28 = 0;
@@ -35569,7 +35806,7 @@ function buildAdvisoryLine3(file, findings) {
35569
35806
  const more = findings.length > MAX_REPORTED ? `, +${findings.length - MAX_REPORTED} more` : "";
35570
35807
  return `comment-discipline: the text just written to ${file} carries ${summary} \u2014 ${named}${more}. A comment states a WHY or a constraint the code cannot show, in English; evidence for a roadmap step belongs in that roadmap, not in a second copy in the source. Rewrite or delete those lines now, before the next write \u2014 \`lint_code_comments\` refuses them at the gate.`;
35571
35808
  }
35572
- function main57() {
35809
+ function main58() {
35573
35810
  try {
35574
35811
  const [envelope, payload] = unwrap(readHookStdin(), "claude");
35575
35812
  const event = str10(envelope["event"]);
@@ -35606,21 +35843,21 @@ function main57() {
35606
35843
  function _isCliEntry42() {
35607
35844
  if (true) return false;
35608
35845
  if (process.argv[1] === void 0) return false;
35609
- const argvUrl = pathToFileURL50(path88.resolve(process.argv[1])).href;
35846
+ const argvUrl = pathToFileURL51(path88.resolve(process.argv[1])).href;
35610
35847
  if (import.meta.url === argvUrl) return true;
35611
35848
  try {
35612
- return fs88.realpathSync(fileURLToPath59(import.meta.url)) === fs88.realpathSync(path88.resolve(process.argv[1]));
35849
+ return fs88.realpathSync(fileURLToPath60(import.meta.url)) === fs88.realpathSync(path88.resolve(process.argv[1]));
35613
35850
  } catch {
35614
35851
  return false;
35615
35852
  }
35616
35853
  }
35617
- if (_isCliEntry42()) process.exit(main57());
35854
+ if (_isCliEntry42()) process.exit(main58());
35618
35855
 
35619
35856
  // src/scripts/hooks/reread_guard_hook.ts
35620
35857
  import * as crypto12 from "node:crypto";
35621
35858
  import * as fs89 from "node:fs";
35622
35859
  import * as path89 from "node:path";
35623
- import { fileURLToPath as fileURLToPath60, pathToFileURL as pathToFileURL51 } from "node:url";
35860
+ import { fileURLToPath as fileURLToPath61, pathToFileURL as pathToFileURL52 } from "node:url";
35624
35861
  var EXIT_ALLOW29 = 0;
35625
35862
  var EXIT_WARN17 = 2;
35626
35863
  var EXEMPT_PATH_PATTERNS2 = [
@@ -35701,7 +35938,7 @@ function buildDuplicateReadLine(relPath, earlierTs) {
35701
35938
  function buildPostEditReadLine(relPath) {
35702
35939
  return `re-read guard: this session just edited ${relPath} \u2014 a full-file re-read re-pays for content you already have; a ranged Read (offset/limit) over the edited hunk is enough to verify the change.`;
35703
35940
  }
35704
- function main58() {
35941
+ function main59() {
35705
35942
  try {
35706
35943
  const [envelope, payload] = unwrap(readHookStdin(), "claude");
35707
35944
  const event = str11(envelope["event"]);
@@ -35771,12 +36008,12 @@ function _isCliEntry43() {
35771
36008
  if (process.argv[1] === void 0) {
35772
36009
  return false;
35773
36010
  }
35774
- const argvUrl = pathToFileURL51(path89.resolve(process.argv[1])).href;
36011
+ const argvUrl = pathToFileURL52(path89.resolve(process.argv[1])).href;
35775
36012
  if (import.meta.url === argvUrl) {
35776
36013
  return true;
35777
36014
  }
35778
36015
  try {
35779
- const here = fs89.realpathSync(fileURLToPath60(import.meta.url));
36016
+ const here = fs89.realpathSync(fileURLToPath61(import.meta.url));
35780
36017
  const argv = fs89.realpathSync(path89.resolve(process.argv[1]));
35781
36018
  return here === argv;
35782
36019
  } catch {
@@ -35784,14 +36021,14 @@ function _isCliEntry43() {
35784
36021
  }
35785
36022
  }
35786
36023
  if (_isCliEntry43()) {
35787
- process.exit(main58());
36024
+ process.exit(main59());
35788
36025
  }
35789
36026
 
35790
36027
  // src/scripts/hooks/session_eol_hook.ts
35791
36028
  import * as fs94 from "node:fs";
35792
36029
  import * as path95 from "node:path";
35793
36030
  import process16 from "node:process";
35794
- import { fileURLToPath as fileURLToPath61, pathToFileURL as pathToFileURL52 } from "node:url";
36031
+ import { fileURLToPath as fileURLToPath62, pathToFileURL as pathToFileURL53 } from "node:url";
35795
36032
 
35796
36033
  // src/config/recycle-threshold-budget.json
35797
36034
  var recycle_threshold_budget_default = {
@@ -36275,7 +36512,7 @@ function writeContextFill(workspaceRoot3, tokens, threshold, ts) {
36275
36512
  } catch {
36276
36513
  }
36277
36514
  }
36278
- function main59() {
36515
+ function main60() {
36279
36516
  const [envelope, payload] = unwrap(readHookStdin(), "claude");
36280
36517
  const event = String(envelope["event"] ?? "");
36281
36518
  if (event !== "" && event !== "stop") {
@@ -36369,12 +36606,12 @@ function _isCliEntry44() {
36369
36606
  if (process16.argv[1] === void 0) {
36370
36607
  return false;
36371
36608
  }
36372
- const argvUrl = pathToFileURL52(path95.resolve(process16.argv[1])).href;
36609
+ const argvUrl = pathToFileURL53(path95.resolve(process16.argv[1])).href;
36373
36610
  if (import.meta.url === argvUrl) {
36374
36611
  return true;
36375
36612
  }
36376
36613
  try {
36377
- const here = fs94.realpathSync(fileURLToPath61(import.meta.url));
36614
+ const here = fs94.realpathSync(fileURLToPath62(import.meta.url));
36378
36615
  const argv = fs94.realpathSync(path95.resolve(process16.argv[1]));
36379
36616
  return here === argv;
36380
36617
  } catch {
@@ -36382,13 +36619,13 @@ function _isCliEntry44() {
36382
36619
  }
36383
36620
  }
36384
36621
  if (_isCliEntry44()) {
36385
- process16.exit(main59());
36622
+ process16.exit(main60());
36386
36623
  }
36387
36624
 
36388
36625
  // src/scripts/hooks/tool_result_bytes_hook.ts
36389
36626
  import * as fs95 from "node:fs";
36390
36627
  import * as path96 from "node:path";
36391
- import { fileURLToPath as fileURLToPath62, pathToFileURL as pathToFileURL53 } from "node:url";
36628
+ import { fileURLToPath as fileURLToPath63, pathToFileURL as pathToFileURL54 } from "node:url";
36392
36629
  var EXIT_ALLOW30 = 0;
36393
36630
  function isObject16(v) {
36394
36631
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -36465,7 +36702,7 @@ function resolveConsumerRoot2(envelope) {
36465
36702
  }
36466
36703
  return process.cwd();
36467
36704
  }
36468
- function main60() {
36705
+ function main61() {
36469
36706
  const raw = readHookStdin();
36470
36707
  let envelope = {};
36471
36708
  try {
@@ -36480,20 +36717,20 @@ function _isCliEntry45() {
36480
36717
  return false;
36481
36718
  }
36482
36719
  if (process.argv[1] === void 0) return false;
36483
- const argvUrl = pathToFileURL53(path96.resolve(process.argv[1])).href;
36720
+ const argvUrl = pathToFileURL54(path96.resolve(process.argv[1])).href;
36484
36721
  if (import.meta.url === argvUrl) return true;
36485
36722
  try {
36486
- return fs95.realpathSync(fileURLToPath62(import.meta.url)) === fs95.realpathSync(path96.resolve(process.argv[1]));
36723
+ return fs95.realpathSync(fileURLToPath63(import.meta.url)) === fs95.realpathSync(path96.resolve(process.argv[1]));
36487
36724
  } catch {
36488
36725
  return false;
36489
36726
  }
36490
36727
  }
36491
- if (_isCliEntry45()) process.exit(main60());
36728
+ if (_isCliEntry45()) process.exit(main61());
36492
36729
 
36493
36730
  // src/scripts/hooks/spawn_guard_shadow_hook.ts
36494
36731
  import * as fs96 from "node:fs";
36495
36732
  import * as path97 from "node:path";
36496
- import { fileURLToPath as fileURLToPath63, pathToFileURL as pathToFileURL54 } from "node:url";
36733
+ import { fileURLToPath as fileURLToPath64, pathToFileURL as pathToFileURL55 } from "node:url";
36497
36734
  var EXIT_ALLOW31 = 0;
36498
36735
  function isObject17(v) {
36499
36736
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -36557,7 +36794,7 @@ function processEnvelope5(envelope, consumerRoot) {
36557
36794
  }
36558
36795
  return EXIT_ALLOW31;
36559
36796
  }
36560
- function main61() {
36797
+ function main62() {
36561
36798
  const raw = readHookStdin();
36562
36799
  let envelope = {};
36563
36800
  try {
@@ -36570,20 +36807,20 @@ function main61() {
36570
36807
  function _isCliEntry46() {
36571
36808
  if (true) return false;
36572
36809
  if (process.argv[1] === void 0) return false;
36573
- const argvUrl = pathToFileURL54(path97.resolve(process.argv[1])).href;
36810
+ const argvUrl = pathToFileURL55(path97.resolve(process.argv[1])).href;
36574
36811
  if (import.meta.url === argvUrl) return true;
36575
36812
  try {
36576
- return fs96.realpathSync(fileURLToPath63(import.meta.url)) === fs96.realpathSync(path97.resolve(process.argv[1]));
36813
+ return fs96.realpathSync(fileURLToPath64(import.meta.url)) === fs96.realpathSync(path97.resolve(process.argv[1]));
36577
36814
  } catch {
36578
36815
  return false;
36579
36816
  }
36580
36817
  }
36581
- if (_isCliEntry46()) process.exit(main61());
36818
+ if (_isCliEntry46()) process.exit(main62());
36582
36819
 
36583
36820
  // src/scripts/hooks/source_first_gate_hook.ts
36584
36821
  import * as fs97 from "node:fs";
36585
36822
  import * as path98 from "node:path";
36586
- import { fileURLToPath as fileURLToPath64, pathToFileURL as pathToFileURL55 } from "node:url";
36823
+ import { fileURLToPath as fileURLToPath65, pathToFileURL as pathToFileURL56 } from "node:url";
36587
36824
  var EXIT_ALLOW32 = 0;
36588
36825
  var MAX_SHADOW_WARNS = 2;
36589
36826
  var SHADOW_LOG = path98.join("agents", "runtime", "state", "source-first-gate.jsonl");
@@ -36780,7 +37017,7 @@ function processEnvelope6(envelope, consumerRoot, session) {
36780
37017
  }
36781
37018
  return EXIT_ALLOW32;
36782
37019
  }
36783
- function main62() {
37020
+ function main63() {
36784
37021
  const raw = readHookStdin();
36785
37022
  let envelope = {};
36786
37023
  try {
@@ -36795,20 +37032,20 @@ function main62() {
36795
37032
  function _isCliEntry47() {
36796
37033
  if (true) return false;
36797
37034
  if (process.argv[1] === void 0) return false;
36798
- const argvUrl = pathToFileURL55(path98.resolve(process.argv[1])).href;
37035
+ const argvUrl = pathToFileURL56(path98.resolve(process.argv[1])).href;
36799
37036
  if (import.meta.url === argvUrl) return true;
36800
37037
  try {
36801
- return fs97.realpathSync(fileURLToPath64(import.meta.url)) === fs97.realpathSync(path98.resolve(process.argv[1]));
37038
+ return fs97.realpathSync(fileURLToPath65(import.meta.url)) === fs97.realpathSync(path98.resolve(process.argv[1]));
36802
37039
  } catch {
36803
37040
  return false;
36804
37041
  }
36805
37042
  }
36806
- if (_isCliEntry47()) process.exit(main62());
37043
+ if (_isCliEntry47()) process.exit(main63());
36807
37044
 
36808
37045
  // src/scripts/hooks/interruption_ledger_hook.ts
36809
37046
  import * as fs98 from "node:fs";
36810
37047
  import * as path99 from "node:path";
36811
- import { fileURLToPath as fileURLToPath65, pathToFileURL as pathToFileURL56 } from "node:url";
37048
+ import { fileURLToPath as fileURLToPath66, pathToFileURL as pathToFileURL57 } from "node:url";
36812
37049
  var EXIT_OK2 = 0;
36813
37050
  var TRANSCRIPT_READ_MAX_BYTES2 = 2 * 1024 * 1024;
36814
37051
  var LEDGER_RELPATH = path99.join("agents", "runtime", "state", "interruptions.jsonl");
@@ -36872,7 +37109,7 @@ function alreadyRecorded(ledgerPath, runId, turn) {
36872
37109
  function str14(v) {
36873
37110
  return typeof v === "string" ? v : "";
36874
37111
  }
36875
- function main63() {
37112
+ function main64() {
36876
37113
  let envelope;
36877
37114
  let payload;
36878
37115
  try {
@@ -36899,12 +37136,12 @@ function main63() {
36899
37136
  const runId = sessionId2 ? derive_session_tag(sessionId2) : "unknown";
36900
37137
  const ledgerPath = path99.join(workspaceRoot3, LEDGER_RELPATH);
36901
37138
  if (alreadyRecorded(ledgerPath, runId, turnOrdinal)) return EXIT_OK2;
36902
- const verdict = classifyReply(lastAssistant);
37139
+ const verdict2 = classifyReply(lastAssistant);
36903
37140
  const record = {
36904
37141
  run_id: runId,
36905
37142
  turn: turnOrdinal,
36906
- kind: verdict.kind,
36907
- class: verdict.class,
37143
+ kind: verdict2.kind,
37144
+ class: verdict2.class,
36908
37145
  roadmap: readClaimedRoadmap(workspaceRoot3, sessionId2),
36909
37146
  at: (/* @__PURE__ */ new Date()).toISOString()
36910
37147
  };
@@ -36920,12 +37157,12 @@ function _isCliEntry48() {
36920
37157
  if (process.argv[1] === void 0) {
36921
37158
  return false;
36922
37159
  }
36923
- const argvUrl = pathToFileURL56(path99.resolve(process.argv[1])).href;
37160
+ const argvUrl = pathToFileURL57(path99.resolve(process.argv[1])).href;
36924
37161
  if (import.meta.url === argvUrl) {
36925
37162
  return true;
36926
37163
  }
36927
37164
  try {
36928
- const here = fs98.realpathSync(fileURLToPath65(import.meta.url));
37165
+ const here = fs98.realpathSync(fileURLToPath66(import.meta.url));
36929
37166
  const argv = fs98.realpathSync(path99.resolve(process.argv[1]));
36930
37167
  return here === argv;
36931
37168
  } catch {
@@ -36933,7 +37170,7 @@ function _isCliEntry48() {
36933
37170
  }
36934
37171
  }
36935
37172
  if (_isCliEntry48()) {
36936
- process.exit(main63());
37173
+ process.exit(main64());
36937
37174
  }
36938
37175
 
36939
37176
  // src/scripts/hooks/run_continuation_hook.ts
@@ -36960,7 +37197,7 @@ function revokeBillingGrant(repoRoot, runId) {
36960
37197
 
36961
37198
  // src/scripts/hooks/run_continuation_hook.ts
36962
37199
  import * as path101 from "node:path";
36963
- import { fileURLToPath as fileURLToPath66, pathToFileURL as pathToFileURL57 } from "node:url";
37200
+ import { fileURLToPath as fileURLToPath67, pathToFileURL as pathToFileURL58 } from "node:url";
36964
37201
 
36965
37202
  // src/scripts/_lib/outcome_vocabularies.ts
36966
37203
  var RUN_TERMINAL_STATES = [
@@ -37320,7 +37557,7 @@ function refusedThisTurn(workspaceRoot3, sessionId2, turnOrdinal) {
37320
37557
  function str15(v) {
37321
37558
  return typeof v === "string" ? v : "";
37322
37559
  }
37323
- function main64() {
37560
+ function main65() {
37324
37561
  if (is_replay_mode()) return EXIT_ALLOW33;
37325
37562
  if (process.env["AGENT_CONFIG_NO_RUN_CONTINUATION"] === "1") return EXIT_ALLOW33;
37326
37563
  let envelope;
@@ -37553,10 +37790,10 @@ function _isCliEntry49() {
37553
37790
  return false;
37554
37791
  }
37555
37792
  if (process.argv[1] === void 0) return false;
37556
- const argvUrl = pathToFileURL57(path101.resolve(process.argv[1])).href;
37793
+ const argvUrl = pathToFileURL58(path101.resolve(process.argv[1])).href;
37557
37794
  if (import.meta.url === argvUrl) return true;
37558
37795
  try {
37559
- const here = fs100.realpathSync(fileURLToPath66(import.meta.url));
37796
+ const here = fs100.realpathSync(fileURLToPath67(import.meta.url));
37560
37797
  const argv = fs100.realpathSync(path101.resolve(process.argv[1]));
37561
37798
  return here === argv;
37562
37799
  } catch {
@@ -37564,13 +37801,13 @@ function _isCliEntry49() {
37564
37801
  }
37565
37802
  }
37566
37803
  if (_isCliEntry49()) {
37567
- process.exit(main64());
37804
+ process.exit(main65());
37568
37805
  }
37569
37806
 
37570
37807
  // src/scripts/hooks/journal_record_hook.ts
37571
37808
  import * as fs102 from "node:fs";
37572
37809
  import * as path103 from "node:path";
37573
- import { fileURLToPath as fileURLToPath67, pathToFileURL as pathToFileURL58 } from "node:url";
37810
+ import { fileURLToPath as fileURLToPath68, pathToFileURL as pathToFileURL59 } from "node:url";
37574
37811
 
37575
37812
  // src/scripts/_lib/surface.ts
37576
37813
  var SURFACES = ["ide", "cli", "cloud", "unknown"];
@@ -38068,7 +38305,7 @@ function processEnvelope7(envelope, consumerRoot) {
38068
38305
  }
38069
38306
  return EXIT_ALLOW34;
38070
38307
  }
38071
- function main65() {
38308
+ function main66() {
38072
38309
  const raw = readHookStdin();
38073
38310
  let envelope = {};
38074
38311
  try {
@@ -38083,15 +38320,15 @@ function _isCliEntry50() {
38083
38320
  return false;
38084
38321
  }
38085
38322
  if (process.argv[1] === void 0) return false;
38086
- const argvUrl = pathToFileURL58(path103.resolve(process.argv[1])).href;
38323
+ const argvUrl = pathToFileURL59(path103.resolve(process.argv[1])).href;
38087
38324
  if (import.meta.url === argvUrl) return true;
38088
38325
  try {
38089
- return fs102.realpathSync(fileURLToPath67(import.meta.url)) === fs102.realpathSync(path103.resolve(process.argv[1]));
38326
+ return fs102.realpathSync(fileURLToPath68(import.meta.url)) === fs102.realpathSync(path103.resolve(process.argv[1]));
38090
38327
  } catch {
38091
38328
  return false;
38092
38329
  }
38093
38330
  }
38094
- if (_isCliEntry50()) process.exit(main65());
38331
+ if (_isCliEntry50()) process.exit(main66());
38095
38332
 
38096
38333
  // src/scripts/hooks/concern_registry.ts
38097
38334
  var CONCERN_REGISTRY = {
@@ -38125,31 +38362,32 @@ var CONCERN_REGISTRY = {
38125
38362
  "src/scripts/hooks/block_kernel_rule_writes.ts": main35,
38126
38363
  "src/scripts/hooks/block_config_weakening.ts": main36,
38127
38364
  "src/scripts/hooks/block_speaking_inbox_dir.ts": main37,
38128
- "src/scripts/hooks/rtk_wrap_hook.ts": main38,
38129
- "src/scripts/hooks/design_pass_hook.ts": main40,
38130
- "src/scripts/hooks/design_slop_hook.ts": main41,
38131
- "src/scripts/hooks/code_graph_nudge_hook.ts": main42,
38132
- "src/scripts/hooks/suggestion_capture_hook.ts": main43,
38133
- "src/scripts/hooks/ui_route_nudge_hook.ts": main44,
38134
- "src/scripts/hooks/orchestration_record_hook.ts": main46,
38365
+ "src/scripts/hooks/one_question_per_ask_hook.ts": main38,
38366
+ "src/scripts/hooks/rtk_wrap_hook.ts": main39,
38367
+ "src/scripts/hooks/design_pass_hook.ts": main41,
38368
+ "src/scripts/hooks/design_slop_hook.ts": main42,
38369
+ "src/scripts/hooks/code_graph_nudge_hook.ts": main43,
38370
+ "src/scripts/hooks/suggestion_capture_hook.ts": main44,
38371
+ "src/scripts/hooks/ui_route_nudge_hook.ts": main45,
38372
+ "src/scripts/hooks/orchestration_record_hook.ts": main47,
38135
38373
  "src/scripts/hooks/telemetry_usage_hook.ts": main28,
38136
- "src/scripts/hooks/telemetry_flush_hook.ts": main47,
38137
- "src/scripts/hooks/delegation_nudge_hook.ts": main48,
38138
- "src/scripts/hooks/skill_route_hook.ts": main50,
38139
- "src/scripts/hooks/rule_inject_hook.ts": main51,
38140
- "src/scripts/hooks/end_review_nudge_hook.ts": main52,
38141
- "src/scripts/hooks/turn_end_gate_hook.ts": main54,
38142
- "src/scripts/hooks/edit_shape_hook.ts": main55,
38143
- "src/scripts/hooks/comment_discipline_hook.ts": main57,
38144
- "src/scripts/hooks/reread_guard_hook.ts": main58,
38145
- "src/scripts/hooks/session_eol_hook.ts": main59,
38146
- "src/scripts/hooks/subagent_ledger_hook.ts": main53,
38147
- "src/scripts/hooks/tool_result_bytes_hook.ts": main60,
38148
- "src/scripts/hooks/spawn_guard_shadow_hook.ts": main61,
38149
- "src/scripts/hooks/source_first_gate_hook.ts": main62,
38150
- "src/scripts/hooks/interruption_ledger_hook.ts": main63,
38151
- "src/scripts/hooks/run_continuation_hook.ts": main64,
38152
- "src/scripts/hooks/journal_record_hook.ts": main65
38374
+ "src/scripts/hooks/telemetry_flush_hook.ts": main48,
38375
+ "src/scripts/hooks/delegation_nudge_hook.ts": main49,
38376
+ "src/scripts/hooks/skill_route_hook.ts": main51,
38377
+ "src/scripts/hooks/rule_inject_hook.ts": main52,
38378
+ "src/scripts/hooks/end_review_nudge_hook.ts": main53,
38379
+ "src/scripts/hooks/turn_end_gate_hook.ts": main55,
38380
+ "src/scripts/hooks/edit_shape_hook.ts": main56,
38381
+ "src/scripts/hooks/comment_discipline_hook.ts": main58,
38382
+ "src/scripts/hooks/reread_guard_hook.ts": main59,
38383
+ "src/scripts/hooks/session_eol_hook.ts": main60,
38384
+ "src/scripts/hooks/subagent_ledger_hook.ts": main54,
38385
+ "src/scripts/hooks/tool_result_bytes_hook.ts": main61,
38386
+ "src/scripts/hooks/spawn_guard_shadow_hook.ts": main62,
38387
+ "src/scripts/hooks/source_first_gate_hook.ts": main63,
38388
+ "src/scripts/hooks/interruption_ledger_hook.ts": main64,
38389
+ "src/scripts/hooks/run_continuation_hook.ts": main65,
38390
+ "src/scripts/hooks/journal_record_hook.ts": main66
38153
38391
  };
38154
38392
 
38155
38393
  // src/scripts/hooks/category_a.ts
@@ -38423,26 +38661,26 @@ function isCategoryA(toolName2, toolInput, workingTree) {
38423
38661
  }
38424
38662
 
38425
38663
  // src/scripts/hooks/permission_gate.ts
38426
- function _isObject16(v) {
38664
+ function _isObject17(v) {
38427
38665
  return typeof v === "object" && v !== null && !Array.isArray(v);
38428
38666
  }
38429
38667
  var EXIT_ALLOW35 = 0;
38430
38668
  var EXIT_BLOCK5 = 1;
38431
38669
  function _payload_tool_name(envelope) {
38432
38670
  const payload = envelope["payload"];
38433
- if (!_isObject16(payload)) return "";
38671
+ if (!_isObject17(payload)) return "";
38434
38672
  const raw = payload["tool_name"];
38435
38673
  return typeof raw === "string" ? raw : "";
38436
38674
  }
38437
38675
  function _payload_tool_input(envelope) {
38438
38676
  const payload = envelope["payload"];
38439
- if (!_isObject16(payload)) return {};
38677
+ if (!_isObject17(payload)) return {};
38440
38678
  const raw = payload["tool_input"];
38441
- return _isObject16(raw) ? raw : {};
38679
+ return _isObject17(raw) ? raw : {};
38442
38680
  }
38443
38681
  function _working_tree_root(envelope) {
38444
38682
  const payload = envelope["payload"];
38445
- if (_isObject16(payload) && typeof payload["cwd"] === "string" && payload["cwd"].trim()) {
38683
+ if (_isObject17(payload) && typeof payload["cwd"] === "string" && payload["cwd"].trim()) {
38446
38684
  return payload["cwd"];
38447
38685
  }
38448
38686
  const workspace = envelope["workspace_root"];
@@ -38829,7 +39067,7 @@ function spoolRecord(record, userRoot) {
38829
39067
  // src/scripts/hooks/dispatch_hook.ts
38830
39068
  var _IN_BUNDLE2 = true;
38831
39069
  var REPO_ROOT = path107.resolve(
38832
- path107.dirname(fileURLToPath68(import.meta.url)),
39070
+ path107.dirname(fileURLToPath69(import.meta.url)),
38833
39071
  ..._IN_BUNDLE2 ? ["..", ".."] : ["..", "..", ".."]
38834
39072
  );
38835
39073
  var MANIFEST_PATH = path107.join(REPO_ROOT, "src", "scripts", "hook_manifest.yaml");
@@ -38853,7 +39091,7 @@ var _SEVERITY_BY_EXIT = {
38853
39091
  [EXIT_BLOCK6]: "block",
38854
39092
  [EXIT_WARN19]: "warn"
38855
39093
  };
38856
- function _isObject17(v) {
39094
+ function _isObject18(v) {
38857
39095
  return typeof v === "object" && v !== null && !Array.isArray(v);
38858
39096
  }
38859
39097
  function _severity_for(rc) {
@@ -38883,7 +39121,7 @@ function _parse_concern_stdout(stdout_text) {
38883
39121
  } catch {
38884
39122
  return { _raw_stdout: text.slice(0, 500) };
38885
39123
  }
38886
- return _isObject17(parsed) ? parsed : { _raw: parsed };
39124
+ return _isObject18(parsed) ? parsed : { _raw: parsed };
38887
39125
  }
38888
39126
  function _manifest_fingerprint(text) {
38889
39127
  let h = 2166136261;
@@ -38899,14 +39137,14 @@ function _load_yaml3(p) {
38899
39137
  if (compiled !== p) {
38900
39138
  try {
38901
39139
  const raw = JSON.parse(fs105.readFileSync(compiled, "utf-8"));
38902
- if (_isObject17(raw) && raw["fingerprint"] === _manifest_fingerprint(text) && _isObject17(raw["manifest"])) {
39140
+ if (_isObject18(raw) && raw["fingerprint"] === _manifest_fingerprint(text) && _isObject18(raw["manifest"])) {
38903
39141
  return raw["manifest"];
38904
39142
  }
38905
39143
  } catch {
38906
39144
  }
38907
39145
  }
38908
39146
  const data = (0, import_yaml7.parse)(text, { version: "1.1" });
38909
- return _isObject17(data) ? data : {};
39147
+ return _isObject18(data) ? data : {};
38910
39148
  }
38911
39149
  function _concern_matches_tool(concern, tool_name) {
38912
39150
  const raw = concern["tools"];
@@ -38930,8 +39168,8 @@ function _role_drop_set(manifest, role, event) {
38930
39168
  return /* @__PURE__ */ new Set();
38931
39169
  }
38932
39170
  const rolesRaw = manifest["roles"];
38933
- const roleSpec = _isObject17(rolesRaw) ? rolesRaw[role] : void 0;
38934
- if (!_isObject17(roleSpec)) {
39171
+ const roleSpec = _isObject18(rolesRaw) ? rolesRaw[role] : void 0;
39172
+ if (!_isObject18(roleSpec)) {
38935
39173
  return /* @__PURE__ */ new Set();
38936
39174
  }
38937
39175
  const drop = roleSpec["drop"];
@@ -38944,9 +39182,9 @@ function _is_refusal_retry(event, payload_text) {
38944
39182
  if (event !== "stop") return false;
38945
39183
  try {
38946
39184
  const parsed = JSON.parse(payload_text);
38947
- if (!_isObject17(parsed)) return false;
39185
+ if (!_isObject18(parsed)) return false;
38948
39186
  const payload = parsed["payload"];
38949
- const source = _isObject17(payload) ? payload : parsed;
39187
+ const source = _isObject18(payload) ? payload : parsed;
38950
39188
  return source["stop_hook_active"] === true;
38951
39189
  } catch {
38952
39190
  return false;
@@ -38954,28 +39192,28 @@ function _is_refusal_retry(event, payload_text) {
38954
39192
  }
38955
39193
  function _resolve_concerns(manifest, platform, event, role = "orchestrator", opts = {}) {
38956
39194
  const platformsRaw = manifest["platforms"];
38957
- const platforms = _isObject17(platformsRaw) ? platformsRaw : {};
39195
+ const platforms = _isObject18(platformsRaw) ? platformsRaw : {};
38958
39196
  const block = platforms[platform];
38959
39197
  if (!block) {
38960
39198
  return [];
38961
39199
  }
38962
- if (_isObject17(block) && block["fallback_only"]) {
39200
+ if (_isObject18(block) && block["fallback_only"]) {
38963
39201
  return [];
38964
39202
  }
38965
- const names = _isObject17(block) ? block[event] : null;
39203
+ const names = _isObject18(block) ? block[event] : null;
38966
39204
  if (!Array.isArray(names)) {
38967
39205
  return [];
38968
39206
  }
38969
39207
  const dropped = _role_drop_set(manifest, role, event);
38970
39208
  const concernsRaw = manifest["concerns"];
38971
- const concerns_def = _isObject17(concernsRaw) ? concernsRaw : {};
39209
+ const concerns_def = _isObject18(concernsRaw) ? concernsRaw : {};
38972
39210
  const out = [];
38973
39211
  for (const name of names) {
38974
39212
  if (typeof name === "string" && dropped.has(name)) {
38975
39213
  continue;
38976
39214
  }
38977
39215
  const spec = typeof name === "string" ? concerns_def[name] : void 0;
38978
- if (!spec || !_isObject17(spec)) {
39216
+ if (!spec || !_isObject18(spec)) {
38979
39217
  process.stderr.write(
38980
39218
  `dispatch_hook: unknown concern '${String(name)}' in manifest
38981
39219
  `
@@ -39033,7 +39271,7 @@ function _build_envelope(args, payload_text) {
39033
39271
  let payload;
39034
39272
  try {
39035
39273
  payload = payload_text.trim() ? JSON.parse(payload_text) : {};
39036
- if (!_isObject17(payload)) {
39274
+ if (!_isObject18(payload)) {
39037
39275
  payload = { _raw: payload };
39038
39276
  }
39039
39277
  } catch {
@@ -39069,7 +39307,7 @@ function _resolve_tsx_invocation2(scriptPath, scriptArgs) {
39069
39307
  dir = parent;
39070
39308
  }
39071
39309
  };
39072
- const tsx = walkUp(path107.dirname(scriptPath)) ?? walkUp(path107.dirname(fileURLToPath68(import.meta.url)));
39310
+ const tsx = walkUp(path107.dirname(scriptPath)) ?? walkUp(path107.dirname(fileURLToPath69(import.meta.url)));
39073
39311
  if (tsx !== null) {
39074
39312
  return { command: tsx, args: [scriptPath, ...scriptArgs] };
39075
39313
  }
@@ -39325,11 +39563,11 @@ function _record_rule_trips(envelope, entries) {
39325
39563
  update_json_under_lock(target, (loaded) => {
39326
39564
  const doc = { schema_version: 1, concerns: {}, ...loaded };
39327
39565
  const concernsRaw = doc["concerns"];
39328
- const concerns = _isObject17(concernsRaw) ? concernsRaw : {};
39566
+ const concerns = _isObject18(concernsRaw) ? concernsRaw : {};
39329
39567
  for (const e of tripped) {
39330
39568
  const name = String(e["concern"]);
39331
39569
  const prevRaw = concerns[name];
39332
- const prev = _isObject17(prevRaw) ? prevRaw : { block: 0, warn: 0 };
39570
+ const prev = _isObject18(prevRaw) ? prevRaw : { block: 0, warn: 0 };
39333
39571
  concerns[name] = {
39334
39572
  block: (Number(prev["block"]) || 0) + (e["exit_code"] === EXIT_BLOCK6 ? 1 : 0),
39335
39573
  warn: (Number(prev["warn"]) || 0) + (e["exit_code"] === EXIT_WARN19 ? 1 : 0),
@@ -39425,7 +39663,7 @@ function _parse_args(argv) {
39425
39663
  }
39426
39664
  return args;
39427
39665
  }
39428
- function main66(argv) {
39666
+ function main67(argv) {
39429
39667
  const args = _parse_args(argv ?? process.argv.slice(2));
39430
39668
  if (args.project_dir) {
39431
39669
  const project_dir = _expanduser3(args.project_dir);
@@ -39447,7 +39685,7 @@ function main66(argv) {
39447
39685
  }
39448
39686
  const envelope2 = _build_envelope(args, probe.text);
39449
39687
  process.stderr.write(
39450
- `dispatch_hook: --read-exit ok (${probe.text.length} chars, ${Object.keys(_isObject17(envelope2["payload"]) ? envelope2["payload"] : {}).length} payload keys)
39688
+ `dispatch_hook: --read-exit ok (${probe.text.length} chars, ${Object.keys(_isObject18(envelope2["payload"]) ? envelope2["payload"] : {}).length} payload keys)
39451
39689
  `
39452
39690
  );
39453
39691
  return EXIT_ALLOW36;
@@ -39649,12 +39887,12 @@ function _isCliEntry51() {
39649
39887
  if (process.argv[1] === void 0) {
39650
39888
  return false;
39651
39889
  }
39652
- const argvUrl = pathToFileURL59(path107.resolve(process.argv[1])).href;
39890
+ const argvUrl = pathToFileURL60(path107.resolve(process.argv[1])).href;
39653
39891
  if (import.meta.url === argvUrl) {
39654
39892
  return true;
39655
39893
  }
39656
39894
  try {
39657
- const here = fs105.realpathSync(fileURLToPath68(import.meta.url));
39895
+ const here = fs105.realpathSync(fileURLToPath69(import.meta.url));
39658
39896
  const argv = fs105.realpathSync(path107.resolve(process.argv[1]));
39659
39897
  return here === argv;
39660
39898
  } catch {
@@ -39663,15 +39901,15 @@ function _isCliEntry51() {
39663
39901
  }
39664
39902
  var isCliEntry15 = _isCliEntry51();
39665
39903
  if (isCliEntry15) {
39666
- process.exit(main66(process.argv.slice(2)));
39904
+ process.exit(main67(process.argv.slice(2)));
39667
39905
  }
39668
39906
 
39669
39907
  // src/scripts/hooks/dispatch_entry.ts
39670
- var _selfPath = fileURLToPath69(import.meta.url);
39908
+ var _selfPath = fileURLToPath70(import.meta.url);
39671
39909
  var _invokedDirectly2 = globalThis.__AC_HOOKS_BUNDLE_DIRECT === true || process.argv[1] !== void 0 && path108.resolve(process.argv[1]) === path108.resolve(_selfPath);
39672
39910
  if (_invokedDirectly2) {
39673
- process.exitCode = main66(process.argv.slice(2));
39911
+ process.exitCode = main67(process.argv.slice(2));
39674
39912
  }
39675
39913
  export {
39676
- main66 as main
39914
+ main67 as main
39677
39915
  };