@event4u/agent-config 14.5.0 → 14.7.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 (203) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +384 -3
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/analyze/decision.md +7 -0
  5. package/dist/agent-src/commands/analyze/inbox.md +264 -10
  6. package/dist/agent-src/commands/analyze.md +1 -1
  7. package/dist/agent-src/commands/optimize/project.md +10 -0
  8. package/dist/agent-src/commands/roadmap/process-full.md +132 -4
  9. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +31 -0
  10. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +161 -1
  11. package/dist/agent-src/rules/context-hygiene.md +2 -0
  12. package/dist/agent-src/rules/decision-revisit-gate.md +111 -7
  13. package/dist/agent-src/rules/fix-what-you-see.md +108 -0
  14. package/dist/agent-src/rules/no-roadmap-references.md +0 -5
  15. package/dist/agent-src/rules/recurring-criticism.md +110 -0
  16. package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
  17. package/dist/agent-src/rules/rule-type-governance.md +0 -2
  18. package/dist/agent-src/rules/self-repair-loop.md +17 -0
  19. package/dist/agent-src/rules/skill-quality.md +0 -2
  20. package/dist/agent-src/rules/source-confidentiality.md +37 -7
  21. package/dist/agent-src/scripts/archival_sweep.ts +117 -0
  22. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
  23. package/dist/agent-src/scripts/gate_budget.ts +282 -0
  24. package/dist/agent-src/scripts/gate_execute.ts +72 -31
  25. package/dist/agent-src/scripts/roadmap_gates.ts +74 -3
  26. package/dist/agent-src/scripts/update_roadmap_progress.ts +251 -7
  27. package/dist/agent-src/skills/adr-create/SKILL.md +25 -3
  28. package/dist/agent-src/skills/ai-council/SKILL.md +48 -807
  29. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +320 -0
  30. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +99 -0
  31. package/dist/agent-src/skills/ai-council/references/execution-modes.md +162 -0
  32. package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +125 -0
  33. package/dist/agent-src/skills/ai-council/references/procedure.md +143 -0
  34. package/dist/agent-src/skills/decision-review/SKILL.md +18 -0
  35. package/dist/agent-src/skills/quality-tools/SKILL.md +34 -326
  36. package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +113 -0
  37. package/dist/agent-src/skills/quality-tools/references/php-tools.md +222 -0
  38. package/dist/agent-src/skills/roadmap-management/SKILL.md +15 -409
  39. package/dist/agent-src/skills/roadmap-management/references/archival.md +226 -0
  40. package/dist/agent-src/skills/roadmap-management/references/authoring.md +107 -0
  41. package/dist/agent-src/skills/roadmap-management/references/dashboard.md +47 -0
  42. package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +58 -0
  43. package/dist/agent-src/skills/skill-writing/SKILL.md +34 -570
  44. package/dist/agent-src/skills/skill-writing/references/procedure.md +275 -0
  45. package/dist/agent-src/skills/skill-writing/references/read-only-scripts.md +18 -0
  46. package/dist/agent-src/skills/skill-writing/references/section-patterns.md +298 -0
  47. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  48. package/dist/agent-src/templates/roadmaps.md +45 -2
  49. package/dist/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
  50. package/dist/agent-src/templates/scripts/telemetry/remote.ts +160 -7
  51. package/dist/agent-src/templates/scripts/telemetry/transport.ts +169 -0
  52. package/dist/cli/registry.js +1 -1
  53. package/dist/cli/registry.js.map +1 -1
  54. package/dist/cli-delegate/chunk-2GNWGMAL.js +172 -0
  55. package/dist/cli-delegate/{chunk-RLN73PR5.js → chunk-4VR4ORQ6.js} +10 -7
  56. package/dist/cli-delegate/chunk-6EOCNQAM.js +402 -0
  57. package/dist/cli-delegate/{chunk-XURJ4AQC.js → chunk-74E3TKWV.js} +381 -280
  58. package/dist/cli-delegate/{chunk-3UCJWMMP.js → chunk-7F3VYSM2.js} +4 -4
  59. package/dist/cli-delegate/{chunk-BKO2AZ7Z.js → chunk-B2ERU2VA.js} +1 -1
  60. package/dist/cli-delegate/{chunk-NXFWFAYV.js → chunk-G23AT6GD.js} +1 -0
  61. package/dist/cli-delegate/{chunk-63WSP6YZ.js → chunk-GJ5BVHXM.js} +72 -165
  62. package/dist/cli-delegate/{chunk-ZPSXJTLI.js → chunk-JZ4NR2TW.js} +353 -1
  63. package/dist/cli-delegate/chunk-MWRD5YOH.js +100 -0
  64. package/dist/cli-delegate/{chunk-GRRPEPRN.js → chunk-T7L2QK3K.js} +24 -5
  65. package/dist/cli-delegate/{chunk-EVTY7ISR.js → chunk-YM4GZDJG.js} +9 -1
  66. package/dist/cli-delegate/cmd_conformance.js +459 -709
  67. package/dist/cli-delegate/cmd_doctor.js +6 -6
  68. package/dist/cli-delegate/cmd_explain.js +1 -1
  69. package/dist/cli-delegate/cmd_export.js +7 -6
  70. package/dist/cli-delegate/cmd_handoff.js +6 -6
  71. package/dist/cli-delegate/cmd_packs_active.js +1 -1
  72. package/dist/cli-delegate/cmd_preflight.js +2 -2
  73. package/dist/cli-delegate/cmd_prune.js +7 -6
  74. package/dist/cli-delegate/cmd_session_recycle.js +840 -30
  75. package/dist/cli-delegate/cmd_settings_migrate.js +7 -6
  76. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  77. package/dist/cli-delegate/cmd_sync.js +7 -6
  78. package/dist/cli-delegate/cmd_uninstall.js +9 -7
  79. package/dist/cli-delegate/cmd_update.js +1 -1
  80. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  81. package/dist/cli-delegate/cmd_validate.js +7 -6
  82. package/dist/discovery/deprecation-report.md +1 -1
  83. package/dist/discovery/discovery-manifest.json +72 -29
  84. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  85. package/dist/discovery/discovery-manifest.summary.md +4 -4
  86. package/dist/discovery/dormancy-report.md +1 -1
  87. package/dist/discovery/orphan-report.md +1 -1
  88. package/dist/discovery/packs.json +10 -8
  89. package/dist/discovery/trust-report.md +3 -3
  90. package/dist/discovery/workspaces.json +8 -6
  91. package/dist/hooks/dispatch.js +3127 -2022
  92. package/dist/install/claudePathsPlan.js +187 -0
  93. package/dist/install/claudePathsPlan.js.map +1 -0
  94. package/dist/install/hostLayerFingerprint.js +136 -0
  95. package/dist/install/hostLayerFingerprint.js.map +1 -0
  96. package/dist/install/install.mjs +553 -425
  97. package/dist/install/partitionEligibility.js +276 -0
  98. package/dist/install/partitionEligibility.js.map +1 -0
  99. package/dist/mcp/registry-manifest.json +3 -3
  100. package/dist/mcp/server.json +2 -2
  101. package/dist/mcp/server.mjs +1744 -1191
  102. package/dist/router.json +1 -1
  103. package/dist/scripts/_lib/agent_src.js +41 -0
  104. package/dist/scripts/_lib/agent_src.js.map +1 -1
  105. package/dist/scripts/_lib/install_layout.js +83 -0
  106. package/dist/scripts/_lib/install_layout.js.map +1 -0
  107. package/dist/scripts/_lib/installed_lock.js +444 -0
  108. package/dist/scripts/_lib/installed_lock.js.map +1 -0
  109. package/dist/scripts/condense.js +13 -164
  110. package/dist/scripts/condense.js.map +1 -1
  111. package/dist/server/schemas/settings.js +4 -0
  112. package/dist/server/schemas/settings.js.map +1 -1
  113. package/docs/contracts/settings-classes.md +12 -6
  114. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +8 -3
  115. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +26 -0
  116. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +49 -0
  117. package/docs/guidelines/agent-infra/memory-access.md +17 -0
  118. package/docs/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
  119. package/package.json +1 -1
  120. package/src/agent-src/scripts/archival_sweep.ts +117 -0
  121. package/src/agent-src/scripts/archive_completed_roadmaps.ts +19 -3
  122. package/src/agent-src/scripts/gate_budget.ts +282 -0
  123. package/src/agent-src/scripts/gate_execute.ts +72 -31
  124. package/src/agent-src/scripts/roadmap_gates.ts +74 -3
  125. package/src/agent-src/scripts/update_roadmap_progress.ts +251 -7
  126. package/src/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
  127. package/src/agent-src/templates/scripts/telemetry/remote.ts +160 -7
  128. package/src/agent-src/templates/scripts/telemetry/transport.ts +169 -0
  129. package/src/config/agent-settings.template.yml +27 -2
  130. package/src/config/ci-local-parity.yml +18 -0
  131. package/src/config/estate-count-budget.json +367 -3
  132. package/src/config/gate-violation-baselines.json +41 -41
  133. package/src/config/pack-size-budget.json +3 -2
  134. package/src/config/rule-activation-census.json +14 -6
  135. package/src/config/rule-stub-ceilings.json +19 -6
  136. package/src/install/claudePathsPlan.ts +196 -0
  137. package/src/install/hostLayerFingerprint.ts +145 -0
  138. package/src/install/partitionEligibility.ts +325 -0
  139. package/src/scripts/_cli/cmd_session_recycle.ts +9 -1
  140. package/src/scripts/_dispatch.bash +6 -1
  141. package/src/scripts/_lib/ac_heading.ts +30 -0
  142. package/src/scripts/_lib/agent_src.ts +42 -0
  143. package/src/scripts/_lib/bench_ab_pinned_repo.ts +162 -0
  144. package/src/scripts/_lib/bench_ab_workspace.ts +10 -1
  145. package/src/scripts/_lib/envelope_grounding.ts +38 -8
  146. package/src/scripts/_lib/installed_lock.ts +50 -5
  147. package/src/scripts/_lib/layer_overlap_notice.ts +85 -0
  148. package/src/scripts/_lib/md_section.ts +129 -0
  149. package/src/scripts/_lib/scope_guard.sh +86 -4
  150. package/src/scripts/_lib/self_repair.ts +19 -0
  151. package/src/scripts/_lib/self_repair_class_b.ts +171 -0
  152. package/src/scripts/_lib/subagent_capsule.ts +81 -1
  153. package/src/scripts/adr/regenerate_index.ts +13 -2
  154. package/src/scripts/adr_cite_check.ts +424 -0
  155. package/src/scripts/ai_council/cli_help.ts +55 -0
  156. package/src/scripts/before_complete_hook.ts +153 -28
  157. package/src/scripts/bench_ab_v2_complexity.ts +27 -7
  158. package/src/scripts/check_adr_frontmatter.ts +187 -1
  159. package/src/scripts/check_references.ts +60 -0
  160. package/src/scripts/check_release_published.ts +32 -11
  161. package/src/scripts/check_single_delivery.ts +517 -0
  162. package/src/scripts/ci_settle.ts +170 -0
  163. package/src/scripts/condense.ts +20 -170
  164. package/src/scripts/council_cli.ts +3 -3
  165. package/src/scripts/dispatch_r2_reviewer.ts +6 -14
  166. package/src/scripts/hook_manifest.json +1 -1
  167. package/src/scripts/hook_manifest.yaml +77 -14
  168. package/src/scripts/hooks/block_no_verify.ts +61 -10
  169. package/src/scripts/hooks/block_unauthorized_git.ts +1 -1
  170. package/src/scripts/hooks/concern_registry.ts +4 -0
  171. package/src/scripts/hooks/rtk_wrap_hook.ts +8 -3
  172. package/src/scripts/hooks/run_continuation_hook.ts +887 -68
  173. package/src/scripts/hooks/ship_diff_volume_hook.ts +81 -15
  174. package/src/scripts/hooks/source_first_gate_hook.ts +464 -0
  175. package/src/scripts/hooks/state_io.ts +782 -20
  176. package/src/scripts/hooks/subagent_ledger_hook.ts +44 -15
  177. package/src/scripts/hooks/telemetry_flush_hook.ts +139 -0
  178. package/src/scripts/hooks/telemetry_self_repair.ts +128 -0
  179. package/src/scripts/hooks/telemetry_usage_hook.ts +22 -4
  180. package/src/scripts/hooks/turn_end_gate_hook.ts +81 -15
  181. package/src/scripts/install.sh +12 -2
  182. package/src/scripts/install.ts +16 -11
  183. package/src/scripts/language_mirror_hook.ts +561 -25
  184. package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
  185. package/src/scripts/lint_plan_risk_register.ts +4 -3
  186. package/src/scripts/lint_skill_router_head.ts +4 -4
  187. package/src/scripts/mcp_server/tools.ts +2 -2
  188. package/src/scripts/memory_consolidation.ts +189 -0
  189. package/src/scripts/memory_eviction.ts +384 -0
  190. package/src/scripts/new_roadmap.ts +136 -0
  191. package/src/scripts/pack_mcp_content.ts +20 -5
  192. package/src/scripts/release.ts +37 -38
  193. package/src/scripts/report_layer_overlap.ts +78 -0
  194. package/src/scripts/report_memory_pointers.ts +622 -0
  195. package/src/scripts/self_repair_hook.ts +37 -5
  196. package/src/scripts/session_register_hook.ts +115 -15
  197. package/src/scripts/skill_usage_collect.ts +11 -1
  198. package/src/scripts/skill_usage_report.ts +278 -8
  199. package/src/scripts/sync_pr_branch.ts +7 -0
  200. package/src/server/schemas/settings.ts +8 -0
  201. package/dist/cli-delegate/chunk-EJITJBJX.js +0 -172
  202. package/dist/cli-delegate/chunk-PZWRPRWP.js +0 -38
  203. /package/dist/cli-delegate/{chunk-RYNADUFG.js → chunk-LWTYTX6F.js} +0 -0
@@ -38,7 +38,9 @@ import { substitutionPayloads } from './block_unauthorized_git.js';
38
38
 
39
39
  const _HERE = fileURLToPath(import.meta.url);
40
40
 
41
- const _SHELL_SEPARATORS: ReadonlySet<string> = new Set(['&&', '||', ';', '|']);
41
+ const _SHELL_SEPARATORS: ReadonlySet<string> = new Set(['&&', '||', ';', '|', '&']);
42
+ /** Characters that begin a shell separator, for `shlexSplit(s, true)`. */
43
+ const _OPERATOR_CHARS = ';|&';
42
44
  const _NO_VERIFY_FLAGS: ReadonlySet<string> = new Set(['--no-verify']);
43
45
  const _NO_VERIFY_SHORT: ReadonlySet<string> = new Set(['-n']);
44
46
  const _HOOKS_PATH_RE = /^core\.hooksPath\s*=/i;
@@ -78,14 +80,36 @@ type JsonObject = { [k: string]: JsonValue };
78
80
  * Faithful port of `shlex.split(s, comments=False, posix=True)` for the
79
81
  * subset block_no_verify needs: whitespace tokenisation, single + double
80
82
  * quotes, backslash escaping (POSIX), and a `ValueError("No closing
81
- * quotation")` on an unterminated quote. `&&` / `|` / `;` are ordinary word
82
- * characters here (no `punctuation_chars`), so they survive as embedded
83
- * tokens exactly as CPython's shlex returns them — the separator split below
84
- * matches them as whole tokens.
83
+ * quotation")` on an unterminated quote.
84
+ *
85
+ * `splitOperators` (default OFF, so the port stays faithful for
86
+ * `rtk_wrap_hook`, its other caller) additionally emits an UNQUOTED shell
87
+ * separator as its own token, maximal-munch for `&&` and `||`.
88
+ *
89
+ * WHY IT EXISTS. Without it, POSIX shlex leaves a separator attached to the
90
+ * preceding word — `git status; sed -n 1,5p f` tokenises as
91
+ * `['git','status;','sed','-n',...]`, one token, no separator. This docstring
92
+ * previously asserted the opposite ("they survive as embedded tokens ... the
93
+ * separator split below matches them as whole tokens"); that holds only when
94
+ * the separator is surrounded by whitespace, and the guard's segmentation is
95
+ * built on it. Measured 2026-08-20, the mistake had TWO faces and the second
96
+ * is the serious one:
97
+ *
98
+ * git status; sed -n 1,5p f → REFUSED (false positive: the `-n`
99
+ * of `sed` is read as git's)
100
+ * echo hi; git commit --no-verify → ALLOWED (BYPASS: the group starts
101
+ * with `echo`, so `_git_base` returns
102
+ * null and the git command is never
103
+ * scanned at all)
104
+ *
105
+ * Quote- and escape-safe by construction: the operator check lives in the
106
+ * unquoted word path only, so `git commit -m "a;b"` and `git commit -m a\;b`
107
+ * keep their semicolon inside one token and cannot be split into a group that
108
+ * no longer starts with `git`.
85
109
  */
86
110
  class ShlexError extends Error {}
87
111
 
88
- function shlexSplit(s: string): string[] {
112
+ function shlexSplit(s: string, splitOperators = false): string[] {
89
113
  const whitespace = ' \t\r\n\f\v';
90
114
  const quotes = '\'"';
91
115
  const escape = '\\';
@@ -159,6 +183,25 @@ function shlexSplit(s: string): string[] {
159
183
  }
160
184
  continue;
161
185
  }
186
+ if (splitOperators && _OPERATOR_CHARS.includes(c)) {
187
+ // Unquoted separator: close the word in progress, then emit the
188
+ // operator as its own token. Maximal munch so `&&` and `||` stay
189
+ // one token rather than two, matching _SHELL_SEPARATORS.
190
+ if (token !== null) {
191
+ tokens.push(token);
192
+ token = null;
193
+ }
194
+ const nxt = i + 1 < n ? (s[i + 1] as string) : null;
195
+ if (nxt === c && (c === '&' || c === '|')) {
196
+ tokens.push(c + c);
197
+ i += 2;
198
+ } else {
199
+ tokens.push(c);
200
+ i += 1;
201
+ }
202
+ state = 'ws';
203
+ continue;
204
+ }
162
205
  if (escape.includes(c)) {
163
206
  // POSIX escape outside quotes: backslash preserves the next char.
164
207
  const nxt = i + 1 < n ? (s[i + 1] as string) : null;
@@ -293,19 +336,22 @@ function _is_blocked(git_tokens: string[]): [boolean, string] {
293
336
  while (i < git_tokens.length) {
294
337
  const tok = git_tokens[i] as string;
295
338
  if (_NO_VERIFY_FLAGS.has(tok)) {
296
- return [true, `'${tok}' bypasses git hooks (git-history-discipline)`];
339
+ return [true, `'${tok}' bypasses git hooks (git-history-discipline).`
340
+ + ' Let the hooks run and fix what they report; that is the only path this guard leaves open.'];
297
341
  }
298
342
  if (_NO_VERIFY_SHORT.has(tok)) {
299
343
  return [
300
344
  true,
301
- `'${tok}' is short for --no-verify and bypasses git hooks (git-history-discipline)`,
345
+ `'${tok}' is short for --no-verify and bypasses git hooks (git-history-discipline).`
346
+ + ' Let the hooks run and fix what they report; that is the only path this guard leaves open.',
302
347
  ];
303
348
  }
304
349
  // Short flag bundles containing 'n': -nm, -mn, etc.
305
350
  if (/^-[a-zA-Z]*n[a-zA-Z]*$/.test(tok) && !tok.startsWith('--')) {
306
351
  return [
307
352
  true,
308
- `'${tok}' contains -n (--no-verify) and bypasses git hooks (git-history-discipline)`,
353
+ `'${tok}' contains -n (--no-verify) and bypasses git hooks (git-history-discipline).`
354
+ + ' Let the hooks run and fix what they report; that is the only path this guard leaves open.',
309
355
  ];
310
356
  }
311
357
  if (tok === '-c') {
@@ -492,7 +538,12 @@ function _check_command(cmd: string, depth = 0): [boolean, string] {
492
538
  }
493
539
  let tokens: string[];
494
540
  try {
495
- tokens = shlexSplit(stripped);
541
+ // splitOperators: an unquoted `;` / `&&` / `||` / `|` / `&` becomes its
542
+ // own token, so _split_subcommands can see it. Without it a separator
543
+ // attached to the preceding word (`status;`) kept the whole line in one
544
+ // group — refusing `git status; sed -n 1,5p f` and, in the other
545
+ // direction, never scanning `echo hi; git commit --no-verify` at all.
546
+ tokens = shlexSplit(stripped, true);
496
547
  } catch (e) {
497
548
  if (e instanceof ShlexError) {
498
549
  // Tested against the string that actually failed to parse. Round 7
@@ -486,7 +486,7 @@ export function commandOp(command: string): GitOp | null {
486
486
  }
487
487
 
488
488
  /** A ledger older than this is not "this turn" under any reading. */
489
- export const LEDGER_MAX_AGE_MS = 30 * 60 * 1000;
489
+ export const LEDGER_MAX_AGE_MS = 6 * 60 * 60 * 1000; // TEMP: PR-drain run, revert after
490
490
 
491
491
  /**
492
492
  * Load the ledger, and refuse one that does not belong to THIS session and
@@ -59,6 +59,7 @@ import { main as codeGraphNudgeMain } from './code_graph_nudge_hook.js';
59
59
  import { main as uiRouteNudgeMain } from './ui_route_nudge_hook.js';
60
60
  import { main as orchestrationRecordMain } from './orchestration_record_hook.js';
61
61
  import { main as telemetryUsageMain } from './telemetry_usage_hook.js';
62
+ import { main as telemetryFlushMain } from './telemetry_flush_hook.js';
62
63
  import { main as delegationNudgeMain } from './delegation_nudge_hook.js';
63
64
  import { main as skillRouteMain } from './skill_route_hook.js';
64
65
  import { main as endReviewNudgeMain } from './end_review_nudge_hook.js';
@@ -69,6 +70,7 @@ import { main as sessionEolMain } from './session_eol_hook.js';
69
70
  import { main as subagentLedgerMain } from './subagent_ledger_hook.js';
70
71
  import { main as toolResultBytesMain } from './tool_result_bytes_hook.js';
71
72
  import { main as spawnGuardShadowMain } from './spawn_guard_shadow_hook.js';
73
+ import { main as sourceFirstGateMain } from './source_first_gate_hook.js';
72
74
  import { main as interruptionLedgerMain } from './interruption_ledger_hook.js';
73
75
  import { main as runContinuationMain } from './run_continuation_hook.js';
74
76
 
@@ -112,6 +114,7 @@ export const CONCERN_REGISTRY: Readonly<Record<string, ConcernMain>> = {
112
114
  'src/scripts/hooks/ui_route_nudge_hook.ts': uiRouteNudgeMain as ConcernMain,
113
115
  'src/scripts/hooks/orchestration_record_hook.ts': orchestrationRecordMain as ConcernMain,
114
116
  'src/scripts/hooks/telemetry_usage_hook.ts': telemetryUsageMain as ConcernMain,
117
+ 'src/scripts/hooks/telemetry_flush_hook.ts': telemetryFlushMain as ConcernMain,
115
118
  'src/scripts/hooks/delegation_nudge_hook.ts': delegationNudgeMain as ConcernMain,
116
119
  'src/scripts/hooks/skill_route_hook.ts': skillRouteMain as ConcernMain,
117
120
  'src/scripts/hooks/end_review_nudge_hook.ts': endReviewNudgeMain as ConcernMain,
@@ -122,6 +125,7 @@ export const CONCERN_REGISTRY: Readonly<Record<string, ConcernMain>> = {
122
125
  'src/scripts/hooks/subagent_ledger_hook.ts': subagentLedgerMain as ConcernMain,
123
126
  'src/scripts/hooks/tool_result_bytes_hook.ts': toolResultBytesMain as ConcernMain,
124
127
  'src/scripts/hooks/spawn_guard_shadow_hook.ts': spawnGuardShadowMain as ConcernMain,
128
+ 'src/scripts/hooks/source_first_gate_hook.ts': sourceFirstGateMain as ConcernMain,
125
129
  'src/scripts/hooks/interruption_ledger_hook.ts': interruptionLedgerMain as ConcernMain,
126
130
  'src/scripts/hooks/run_continuation_hook.ts': runContinuationMain as ConcernMain,
127
131
  };
@@ -155,14 +155,19 @@ export function classify(command: string): Eligibility {
155
155
 
156
156
  let tokens: string[];
157
157
  try {
158
- tokens = shlexSplit(cmd);
158
+ tokens = shlexSplit(cmd, true);
159
159
  } catch (e) {
160
160
  if (e instanceof ShlexError) return { eligible: false, reason_skip: "parse-error" };
161
161
  throw e;
162
162
  }
163
163
 
164
164
  // Compound / piped → don't wrap (rtk wraps a single command). `_split_subcommands`
165
- // splits on && || ; | — more than one group means a pipeline/chain.
165
+ // splits on && || ; | & — more than one group means a pipeline/chain.
166
+ // `splitOperators` is REQUIRED here: POSIX shlex leaves a separator attached
167
+ // to the preceding word, so `foo; bar` tokenised to one group and read as a
168
+ // single command. Same construct as the block_no_verify defect measured
169
+ // 2026-08-20; found by the sibling search for that fix, 2 call sites, both
170
+ // in this file.
166
171
  const groups = _split_subcommands(tokens);
167
172
  if (groups.length !== 1) return { eligible: false, reason_skip: "compound-or-piped" };
168
173
 
@@ -256,7 +261,7 @@ export function classifyCap(
256
261
  if (!cmd) return null;
257
262
  let tokens: string[];
258
263
  try {
259
- tokens = shlexSplit(cmd);
264
+ tokens = shlexSplit(cmd, true);
260
265
  } catch (e) {
261
266
  if (e instanceof ShlexError) return null;
262
267
  throw e;