@event4u/agent-config 14.6.0 → 14.8.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 (258) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +255 -145
  3. package/README.md +1 -1
  4. package/dist/agent-src/commands/analyze/inbox.md +264 -10
  5. package/dist/agent-src/commands/analyze.md +1 -1
  6. package/dist/agent-src/commands/evals/git-pr-merge.json +13 -0
  7. package/dist/agent-src/commands/evals/roadmap.json +17 -1
  8. package/dist/agent-src/commands/pr/create.md +14 -2
  9. package/dist/agent-src/commands/pr/merge.md +379 -0
  10. package/dist/agent-src/commands/roadmap/process-full.md +272 -32
  11. package/dist/agent-src/commands/roadmap.md +1 -1
  12. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +46 -36
  13. package/dist/agent-src/contexts/execution/autonomy-mechanics.md +37 -2
  14. package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +95 -2
  15. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +289 -106
  16. package/dist/agent-src/rules/artifact-drafting-protocol.md +5 -1
  17. package/dist/agent-src/rules/context-hygiene.md +2 -0
  18. package/dist/agent-src/rules/decision-revisit-gate.md +67 -32
  19. package/dist/agent-src/rules/fix-what-you-see.md +108 -0
  20. package/dist/agent-src/rules/no-roadmap-references.md +0 -5
  21. package/dist/agent-src/rules/recurring-criticism.md +110 -0
  22. package/dist/agent-src/rules/roadmap-progress-sync.md +20 -1
  23. package/dist/agent-src/rules/rule-type-governance.md +0 -2
  24. package/dist/agent-src/rules/self-repair-loop.md +17 -0
  25. package/dist/agent-src/rules/skill-quality.md +0 -2
  26. package/dist/agent-src/rules/source-confidentiality.md +37 -7
  27. package/dist/agent-src/scripts/archival_sweep.ts +117 -0
  28. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +26 -7
  29. package/dist/agent-src/scripts/dashboard_mode.ts +212 -0
  30. package/dist/agent-src/scripts/gate_budget.ts +282 -0
  31. package/dist/agent-src/scripts/gate_execute.ts +72 -31
  32. package/dist/agent-src/scripts/roadmap_gates.ts +74 -3
  33. package/dist/agent-src/scripts/update_roadmap_progress.ts +296 -53
  34. package/dist/agent-src/skills/adr-create/SKILL.md +124 -5
  35. package/dist/agent-src/skills/ai-council/SKILL.md +48 -807
  36. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +320 -0
  37. package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +99 -0
  38. package/dist/agent-src/skills/ai-council/references/execution-modes.md +162 -0
  39. package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +125 -0
  40. package/dist/agent-src/skills/ai-council/references/procedure.md +143 -0
  41. package/dist/agent-src/skills/decision-record/SKILL.md +61 -3
  42. package/dist/agent-src/skills/decision-review/SKILL.md +65 -0
  43. package/dist/agent-src/skills/merge-conflicts/SKILL.md +26 -0
  44. package/dist/agent-src/skills/quality-tools/SKILL.md +34 -326
  45. package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +113 -0
  46. package/dist/agent-src/skills/quality-tools/references/php-tools.md +222 -0
  47. package/dist/agent-src/skills/roadmap-management/SKILL.md +15 -409
  48. package/dist/agent-src/skills/roadmap-management/references/archival.md +226 -0
  49. package/dist/agent-src/skills/roadmap-management/references/authoring.md +107 -0
  50. package/dist/agent-src/skills/roadmap-management/references/dashboard.md +47 -0
  51. package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +58 -0
  52. package/dist/agent-src/skills/security/SKILL.md +8 -0
  53. package/dist/agent-src/skills/security-audit/SKILL.md +12 -1
  54. package/dist/agent-src/skills/skill-writing/SKILL.md +34 -570
  55. package/dist/agent-src/skills/skill-writing/references/procedure.md +275 -0
  56. package/dist/agent-src/skills/skill-writing/references/read-only-scripts.md +18 -0
  57. package/dist/agent-src/skills/skill-writing/references/section-patterns.md +298 -0
  58. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  59. package/dist/agent-src/templates/roadmaps.md +65 -4
  60. package/dist/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
  61. package/dist/agent-src/templates/scripts/telemetry/remote.ts +160 -7
  62. package/dist/agent-src/templates/scripts/telemetry/transport.ts +169 -0
  63. package/dist/cli/registry.js +2 -1
  64. package/dist/cli/registry.js.map +1 -1
  65. package/dist/cli-delegate/chunk-2GNWGMAL.js +172 -0
  66. package/dist/cli-delegate/{chunk-P6LQDIWK.js → chunk-7PRE6ZV2.js} +338 -0
  67. package/dist/cli-delegate/{chunk-BKO2AZ7Z.js → chunk-B2ERU2VA.js} +1 -1
  68. package/dist/cli-delegate/chunk-E4XIZDIB.js +402 -0
  69. package/dist/cli-delegate/{chunk-3UCJWMMP.js → chunk-EEJUMCDZ.js} +16 -16
  70. package/dist/cli-delegate/{chunk-NXFWFAYV.js → chunk-G23AT6GD.js} +1 -0
  71. package/dist/cli-delegate/{chunk-XURJ4AQC.js → chunk-H4VIVD4C.js} +385 -284
  72. package/dist/cli-delegate/chunk-I3EIN2YG.js +36 -0
  73. package/dist/cli-delegate/{chunk-RLN73PR5.js → chunk-LPPWO5CE.js} +12 -8
  74. package/dist/cli-delegate/chunk-MWRD5YOH.js +100 -0
  75. package/dist/cli-delegate/{chunk-UEZ7D35A.js → chunk-N7CDDGI3.js} +4 -23
  76. package/dist/cli-delegate/{chunk-63WSP6YZ.js → chunk-PMEKGDED.js} +74 -167
  77. package/dist/cli-delegate/{chunk-GRRPEPRN.js → chunk-T7L2QK3K.js} +24 -5
  78. package/dist/cli-delegate/{chunk-EVTY7ISR.js → chunk-YM4GZDJG.js} +9 -1
  79. package/dist/cli-delegate/cmd_adr_effective.js +1162 -0
  80. package/dist/cli-delegate/cmd_conformance.js +466 -716
  81. package/dist/cli-delegate/cmd_converge.js +3 -3
  82. package/dist/cli-delegate/cmd_doctor.js +10 -10
  83. package/dist/cli-delegate/cmd_explain.js +1 -1
  84. package/dist/cli-delegate/cmd_export.js +10 -9
  85. package/dist/cli-delegate/cmd_handoff.js +10 -9
  86. package/dist/cli-delegate/cmd_memory_get.js +2 -1
  87. package/dist/cli-delegate/cmd_migrate.js +2 -2
  88. package/dist/cli-delegate/cmd_packs_active.js +1 -1
  89. package/dist/cli-delegate/cmd_preflight.js +5 -5
  90. package/dist/cli-delegate/cmd_prune.js +11 -10
  91. package/dist/cli-delegate/cmd_route_audit.js +6 -5
  92. package/dist/cli-delegate/cmd_route_explain.js +3 -3
  93. package/dist/cli-delegate/cmd_session_recycle.js +840 -30
  94. package/dist/cli-delegate/cmd_settings_get.js +3 -3
  95. package/dist/cli-delegate/cmd_settings_migrate.js +10 -9
  96. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  97. package/dist/cli-delegate/cmd_sync.js +11 -10
  98. package/dist/cli-delegate/cmd_uninstall.js +13 -11
  99. package/dist/cli-delegate/cmd_update.js +4 -4
  100. package/dist/cli-delegate/cmd_upgrade.js +4 -4
  101. package/dist/cli-delegate/cmd_validate.js +11 -10
  102. package/dist/cli-delegate/cmd_versions.js +3 -3
  103. package/dist/discovery/deprecation-report.md +1 -1
  104. package/dist/discovery/discovery-manifest.json +111 -37
  105. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  106. package/dist/discovery/discovery-manifest.summary.md +5 -5
  107. package/dist/discovery/dormancy-report.md +1 -1
  108. package/dist/discovery/orphan-report.md +1 -1
  109. package/dist/discovery/packs.json +15 -12
  110. package/dist/discovery/trust-report.md +3 -3
  111. package/dist/discovery/workspaces.json +11 -8
  112. package/dist/hooks/dispatch.js +3165 -2192
  113. package/dist/install/claudePathsPlan.js +187 -0
  114. package/dist/install/claudePathsPlan.js.map +1 -0
  115. package/dist/install/globalRuleLayers.js +169 -0
  116. package/dist/install/globalRuleLayers.js.map +1 -0
  117. package/dist/install/hostLayerFingerprint.js +136 -0
  118. package/dist/install/hostLayerFingerprint.js.map +1 -0
  119. package/dist/install/install.mjs +553 -425
  120. package/dist/install/partitionEligibility.js +432 -0
  121. package/dist/install/partitionEligibility.js.map +1 -0
  122. package/dist/install/ruleLayerPartition.js +157 -0
  123. package/dist/install/ruleLayerPartition.js.map +1 -0
  124. package/dist/mcp/registry-manifest.json +3 -3
  125. package/dist/mcp/server.json +2 -2
  126. package/dist/mcp/server.mjs +1863 -1234
  127. package/dist/router.json +1 -1
  128. package/dist/scripts/_lib/agent_src.js +41 -0
  129. package/dist/scripts/_lib/agent_src.js.map +1 -1
  130. package/dist/scripts/_lib/install_layout.js +83 -0
  131. package/dist/scripts/_lib/install_layout.js.map +1 -0
  132. package/dist/scripts/_lib/installed_lock.js +444 -0
  133. package/dist/scripts/_lib/installed_lock.js.map +1 -0
  134. package/dist/scripts/_lib/prune_empty_dirs.js +85 -0
  135. package/dist/scripts/_lib/prune_empty_dirs.js.map +1 -0
  136. package/dist/scripts/condense.js +63 -251
  137. package/dist/scripts/condense.js.map +1 -1
  138. package/dist/server/schemas/settings.js +4 -0
  139. package/dist/server/schemas/settings.js.map +1 -1
  140. package/docs/contracts/settings-classes.md +12 -6
  141. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +8 -3
  142. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +45 -1
  143. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +26 -0
  144. package/docs/guidelines/agent-infra/false-green.md +47 -1
  145. package/docs/guidelines/agent-infra/memory-access.md +17 -0
  146. package/docs/guidelines/agent-infra/recurring-criticism-mechanics.md +96 -0
  147. package/package.json +1 -1
  148. package/src/agent-src/scripts/archival_sweep.ts +117 -0
  149. package/src/agent-src/scripts/archive_completed_roadmaps.ts +26 -7
  150. package/src/agent-src/scripts/dashboard_mode.ts +212 -0
  151. package/src/agent-src/scripts/gate_budget.ts +282 -0
  152. package/src/agent-src/scripts/gate_execute.ts +72 -31
  153. package/src/agent-src/scripts/roadmap_gates.ts +74 -3
  154. package/src/agent-src/scripts/update_roadmap_progress.ts +296 -53
  155. package/src/agent-src/templates/scripts/telemetry/flush_sender.mjs +163 -0
  156. package/src/agent-src/templates/scripts/telemetry/remote.ts +160 -7
  157. package/src/agent-src/templates/scripts/telemetry/transport.ts +169 -0
  158. package/src/config/agent-settings.template.yml +27 -2
  159. package/src/config/ci-local-parity.yml +39 -0
  160. package/src/config/estate-count-budget.json +612 -3
  161. package/src/config/evaluator-budgets.json +3 -3
  162. package/src/config/gate-coverage.yml +220 -12
  163. package/src/config/gate-violation-baselines.json +73 -63
  164. package/src/config/gitignore-block.txt +15 -2
  165. package/src/config/hook-latency-budget.json +5 -0
  166. package/src/config/rule-activation-census.json +14 -6
  167. package/src/config/rule-stub-ceilings.json +34 -7
  168. package/src/install/claudePathsPlan.ts +196 -0
  169. package/src/install/globalRuleLayers.ts +197 -0
  170. package/src/install/hostLayerFingerprint.ts +145 -0
  171. package/src/install/partitionEligibility.ts +502 -0
  172. package/src/install/ruleLayerPartition.ts +212 -0
  173. package/src/scripts/_cli/cmd_adr_effective.ts +484 -0
  174. package/src/scripts/_cli/cmd_session_recycle.ts +9 -1
  175. package/src/scripts/_dispatch.bash +17 -1
  176. package/src/scripts/_lib/ac_heading.ts +30 -0
  177. package/src/scripts/_lib/adr_frontmatter.test.ts +365 -0
  178. package/src/scripts/_lib/adr_frontmatter.ts +459 -0
  179. package/src/scripts/_lib/agent_src.ts +42 -0
  180. package/src/scripts/_lib/bench_ab_pinned_repo.ts +162 -0
  181. package/src/scripts/_lib/bench_ab_workspace.ts +10 -1
  182. package/src/scripts/_lib/envelope_grounding.ts +49 -9
  183. package/src/scripts/_lib/installed_lock.ts +50 -5
  184. package/src/scripts/_lib/layer_overlap_notice.ts +11 -2
  185. package/src/scripts/_lib/md_section.ts +129 -0
  186. package/src/scripts/_lib/prune_empty_dirs.ts +80 -0
  187. package/src/scripts/_lib/scope_guard.sh +26 -3
  188. package/src/scripts/_lib/self_repair.ts +19 -0
  189. package/src/scripts/_lib/self_repair_class_b.ts +171 -0
  190. package/src/scripts/adr/evidence_census.ts +899 -0
  191. package/src/scripts/adr/regenerate_index.ts +12 -32
  192. package/src/scripts/adr_cite_check.ts +540 -39
  193. package/src/scripts/ai_council/cli_help.ts +55 -0
  194. package/src/scripts/audit_adr_coverage.ts +103 -17
  195. package/src/scripts/before_complete_hook.ts +153 -28
  196. package/src/scripts/bench_ab_v2_complexity.ts +27 -7
  197. package/src/scripts/bench_hook_latency.ts +204 -0
  198. package/src/scripts/build_archive_index.ts +34 -0
  199. package/src/scripts/check_adr_frontmatter.ts +574 -39
  200. package/src/scripts/check_hook_bundle_content.ts +219 -0
  201. package/src/scripts/check_new_adr_evidence.ts +529 -0
  202. package/src/scripts/check_references.ts +78 -0
  203. package/src/scripts/check_release_published.ts +32 -11
  204. package/src/scripts/check_rule_layer_partition.ts +531 -0
  205. package/src/scripts/check_single_delivery.ts +194 -17
  206. package/src/scripts/check_standing_rule_delivery.ts +8 -2
  207. package/src/scripts/ci_settle.ts +170 -0
  208. package/src/scripts/condense.ts +79 -259
  209. package/src/scripts/council_cli.ts +3 -3
  210. package/src/scripts/dispatch_r2_reviewer.ts +6 -14
  211. package/src/scripts/external_sources_denylist.json +4 -1
  212. package/src/scripts/hook_manifest.json +1 -1
  213. package/src/scripts/hook_manifest.yaml +77 -14
  214. package/src/scripts/hooks/block_no_verify.ts +61 -10
  215. package/src/scripts/hooks/block_unauthorized_git.ts +21 -1
  216. package/src/scripts/hooks/concern_registry.ts +4 -0
  217. package/src/scripts/hooks/dispatch_hook.ts +154 -187
  218. package/src/scripts/hooks/dispatch_issues.ts +38 -19
  219. package/src/scripts/hooks/fallback_yaml.ts +66 -0
  220. package/src/scripts/hooks/host_semantics.ts +21 -0
  221. package/src/scripts/hooks/injection_budget.ts +13 -3
  222. package/src/scripts/hooks/py_json_dumps.ts +103 -0
  223. package/src/scripts/hooks/rtk_wrap_hook.ts +8 -3
  224. package/src/scripts/hooks/run_continuation_hook.ts +8 -5
  225. package/src/scripts/hooks/ship_diff_volume_hook.ts +81 -15
  226. package/src/scripts/hooks/source_first_gate_hook.ts +464 -0
  227. package/src/scripts/hooks/state_io.ts +870 -21
  228. package/src/scripts/hooks/stdin_failure_policy.ts +96 -0
  229. package/src/scripts/hooks/subagent_ledger_hook.ts +44 -15
  230. package/src/scripts/hooks/telemetry_flush_hook.ts +139 -0
  231. package/src/scripts/hooks/telemetry_self_repair.ts +128 -0
  232. package/src/scripts/hooks/telemetry_usage_hook.ts +22 -4
  233. package/src/scripts/hooks/turn_end_gate_hook.ts +81 -15
  234. package/src/scripts/injection_scan_hook.ts +137 -5
  235. package/src/scripts/install.ts +16 -11
  236. package/src/scripts/language_mirror_hook.ts +561 -25
  237. package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
  238. package/src/scripts/lint_hook_manifest.ts +49 -0
  239. package/src/scripts/lint_plan_risk_register.ts +4 -3
  240. package/src/scripts/lint_provenance_vocabulary.ts +472 -4
  241. package/src/scripts/lint_skill_router_head.ts +4 -4
  242. package/src/scripts/mcp_server/tools.ts +2 -2
  243. package/src/scripts/new_roadmap.ts +136 -0
  244. package/src/scripts/pack_mcp_content.ts +20 -5
  245. package/src/scripts/release.ts +37 -38
  246. package/src/scripts/report_layer_overlap.ts +6 -0
  247. package/src/scripts/routing_doctor.ts +5 -1
  248. package/src/scripts/self_repair_hook.ts +37 -5
  249. package/src/scripts/session_register_hook.ts +11 -0
  250. package/src/scripts/skill_usage_collect.ts +11 -1
  251. package/src/scripts/skill_usage_report.ts +278 -8
  252. package/src/scripts/sync_pr_branch.ts +170 -20
  253. package/src/server/schemas/settings.ts +8 -0
  254. package/dist/cli-delegate/chunk-EJITJBJX.js +0 -172
  255. package/dist/cli-delegate/chunk-PZWRPRWP.js +0 -38
  256. package/dist/cli-delegate/{chunk-PPQO4NGR.js → chunk-6RJA2F5A.js} +3 -3
  257. package/dist/cli-delegate/{chunk-RYNADUFG.js → chunk-LWTYTX6F.js} +0 -0
  258. package/dist/cli-delegate/{chunk-FBKL6JWT.js → chunk-MMSGVZKV.js} +3 -3
@@ -230,6 +230,159 @@ export function benchEvent(
230
230
  };
231
231
  }
232
232
 
233
+ /**
234
+ * One dispatcher invocation that reads stdin, parses it, and exits — the
235
+ * transport-isolation cell of the § 2 matrix.
236
+ *
237
+ * `b-payload-read-parse-dominates`, option (a), council 2026-08-20 (2/2
238
+ * quorum). Phase 1 removed ten of eleven envelope stringifies and moved
239
+ * nothing; Phase 2 removed the body from six of eleven concerns and moved
240
+ * nothing. What is left between the small and large cells happens ONCE per
241
+ * event, before any concern runs: `readFd0ToEnd` drains the pipe and
242
+ * `_build_envelope` parses it. This measures exactly that, through the SAME
243
+ * bundle, interpreter and spawn as the slot reading it is a share of — so the
244
+ * constant terms cancel in the delta.
245
+ *
246
+ * Deliberately the real bundle with `--read-exit` rather than a standalone
247
+ * probe: a probe would re-implement the audited retrying reader, and that copy
248
+ * is the drift `hook_stdin` exists to prevent.
249
+ */
250
+ export function benchReadExit(
251
+ event: string,
252
+ runs: number,
253
+ workspace: string,
254
+ ): EventResult {
255
+ const durations: number[] = [];
256
+ const payload = syntheticPayload(event, workspace);
257
+ for (let i = 0; i < runs; i += 1) {
258
+ const started = performance.now();
259
+ const proc = spawnSync(
260
+ process.execPath,
261
+ [
262
+ BUNDLE_OVERRIDE ?? BUNDLE,
263
+ '--platform',
264
+ 'claude',
265
+ '--event',
266
+ event,
267
+ '--project-dir',
268
+ workspace,
269
+ '--read-exit',
270
+ ],
271
+ {
272
+ input: payload,
273
+ encoding: 'utf-8',
274
+ env: { ...process.env, AGENT_CONFIG_REPLAY: '1', CLAUDE_PROJECT_DIR: workspace },
275
+ timeout: 60000,
276
+ },
277
+ );
278
+ const elapsed = performance.now() - started;
279
+ if (proc.error) {
280
+ throw new Error(`read-exit failed on ${event}: ${proc.error.message}`);
281
+ }
282
+ if (!(proc.stderr ?? '').includes('--read-exit ok')) {
283
+ // A silent no-op here would report the fastest possible number and
284
+ // measure nothing — the failure mode this whole cell exists to avoid
285
+ // in the OTHER direction. Refuse instead of publishing it.
286
+ throw new Error(
287
+ `read-exit produced no confirmation on ${event}; the flag may not be ` +
288
+ `wired in the measured bundle (${BUNDLE_OVERRIDE ?? BUNDLE}). ` +
289
+ `stderr: ${(proc.stderr ?? '').trim().slice(0, 200)}`,
290
+ );
291
+ }
292
+ durations.push(elapsed);
293
+ }
294
+ durations.sort((a, b) => a - b);
295
+ return {
296
+ event: `read_exit:${event}`,
297
+ runs,
298
+ p50_ms: Math.round(percentile(durations, 50)),
299
+ p95_ms: Math.round(percentile(durations, 95)),
300
+ max_ms: Math.round(durations[durations.length - 1] as number),
301
+ };
302
+ }
303
+
304
+ /** One row of the transport-share decomposition. */
305
+ export interface ReadExitCell {
306
+ event: string;
307
+ payload_bytes: number;
308
+ slot_small_p50_ms: number;
309
+ slot_large_p50_ms: number;
310
+ read_exit_small_p50_ms: number;
311
+ read_exit_large_p50_ms: number;
312
+ /** Large-minus-small on the full dispatch. */
313
+ slot_delta_ms: number;
314
+ /** Large-minus-small on read + parse alone. */
315
+ transport_delta_ms: number;
316
+ /**
317
+ * `transport_delta / slot_delta`, as a percentage, or `null` when the slot
318
+ * delta is not positive.
319
+ *
320
+ * `null` is a real answer and must not be rendered as 0: a run whose large
321
+ * cell is no slower than its small one says the fixture did not reproduce
322
+ * the gap on this machine, which is different from saying transport is free.
323
+ */
324
+ transport_share_pct: number | null;
325
+ }
326
+
327
+ /**
328
+ * The four measurements the option asks for, in one invocation.
329
+ *
330
+ * Both payload sizes are needed for the SHARE, and taking them in one run is
331
+ * the point: two separate runs would compare across whatever else the machine
332
+ * was doing, which is the cross-runner shape § 2 of the roadmap refuses as a
333
+ * repo fact. Arms alternate per repetition for the same reason.
334
+ */
335
+ export function benchReadExitCell(
336
+ event: string,
337
+ runs: number,
338
+ workspace: string,
339
+ payloadBytes: number,
340
+ ): ReadExitCell {
341
+ const saved = PAYLOAD_BYTES;
342
+ try {
343
+ PAYLOAD_BYTES = 0;
344
+ const slotSmall = benchEvent(event, runs, workspace, 'bundle');
345
+ const probeSmall = benchReadExit(event, runs, workspace);
346
+ PAYLOAD_BYTES = payloadBytes;
347
+ const slotLarge = benchEvent(event, runs, workspace, 'bundle');
348
+ const probeLarge = benchReadExit(event, runs, workspace);
349
+ const slot_delta_ms = slotLarge.p50_ms - slotSmall.p50_ms;
350
+ const transport_delta_ms = probeLarge.p50_ms - probeSmall.p50_ms;
351
+ return {
352
+ event,
353
+ payload_bytes: payloadBytes,
354
+ slot_small_p50_ms: slotSmall.p50_ms,
355
+ slot_large_p50_ms: slotLarge.p50_ms,
356
+ read_exit_small_p50_ms: probeSmall.p50_ms,
357
+ read_exit_large_p50_ms: probeLarge.p50_ms,
358
+ slot_delta_ms,
359
+ transport_delta_ms,
360
+ transport_share_pct:
361
+ slot_delta_ms > 0
362
+ ? Math.round((transport_delta_ms / slot_delta_ms) * 100)
363
+ : null,
364
+ };
365
+ } finally {
366
+ PAYLOAD_BYTES = saved;
367
+ }
368
+ }
369
+
370
+ /** Human-readable decomposition, one line per fact. */
371
+ export function renderReadExitCell(cell: ReadExitCell): string {
372
+ const share =
373
+ cell.transport_share_pct === null
374
+ ? 'n/a — the large cell was not slower than the small one in this run'
375
+ : `${String(cell.transport_share_pct)}%`;
376
+ return (
377
+ `read-exit cell · ${cell.event} · payload ${String(cell.payload_bytes)}B\n` +
378
+ ` full dispatch small ${String(cell.slot_small_p50_ms).padStart(5)} ms · ` +
379
+ `large ${String(cell.slot_large_p50_ms).padStart(5)} ms · delta ${String(cell.slot_delta_ms)} ms\n` +
380
+ ` read + parse small ${String(cell.read_exit_small_p50_ms).padStart(5)} ms · ` +
381
+ `large ${String(cell.read_exit_large_p50_ms).padStart(5)} ms · delta ${String(cell.transport_delta_ms)} ms\n` +
382
+ ` transport share of the large-payload delta: ${share}\n`
383
+ );
384
+ }
385
+
233
386
  /**
234
387
  * Same-run control: a bare `node -e 0`, measured through the identical
235
388
  * spawnSync harness the slots use.
@@ -486,6 +639,37 @@ export function main(argv: string[] = process.argv.slice(2)): number {
486
639
  PAYLOAD_BYTES = parsed;
487
640
  }
488
641
 
642
+ // `--read-exit-cell <bytes>`: the transport-isolation cell. Measurement-only
643
+ // for the same reason `--payload-bytes` is — it PADS the payload, so it must
644
+ // never write a budget row or a regression baseline.
645
+ const readExitIdx = argv.indexOf('--read-exit-cell');
646
+ let readExitBytes: number | null = null;
647
+ if (readExitIdx >= 0) {
648
+ const raw = argv[readExitIdx + 1];
649
+ const parsed = raw === undefined ? Number.NaN : Number.parseInt(raw, 10);
650
+ if (!Number.isFinite(parsed) || parsed <= 0) {
651
+ process.stderr.write(
652
+ 'bench_hook_latency: --read-exit-cell requires a positive integer byte count\n',
653
+ );
654
+ return 2;
655
+ }
656
+ if (gate || update || baselineIdx >= 0) {
657
+ process.stderr.write(
658
+ 'bench_hook_latency: --read-exit-cell is measurement-only — a padded payload must ' +
659
+ "never write this tree's budget row or regression baseline\n",
660
+ );
661
+ return 2;
662
+ }
663
+ if (viaCli) {
664
+ process.stderr.write(
665
+ 'bench_hook_latency: --read-exit-cell drives the bundle directly and does not use ' +
666
+ 'the --via-cli shim path — pick one\n',
667
+ );
668
+ return 2;
669
+ }
670
+ readExitBytes = parsed;
671
+ }
672
+
489
673
  const bundleIdx = argv.indexOf('--bundle');
490
674
  if (bundleIdx >= 0) {
491
675
  const raw = argv[bundleIdx + 1];
@@ -539,6 +723,26 @@ export function main(argv: string[] = process.argv.slice(2)): number {
539
723
  return 2;
540
724
  }
541
725
 
726
+ if (readExitBytes !== null) {
727
+ // Its own mode: the cell alternates two payload sizes internally, so
728
+ // running it alongside the ordinary sweep would report a padded number
729
+ // under an unpadded label.
730
+ const cellWorkspace = fs.mkdtempSync(path.join(os.tmpdir(), 'ac-hook-readexit-'));
731
+ try {
732
+ // `post_tool_use` only. That is where the large cell lives: a
733
+ // `tool_response` does not exist on a `PreToolUse` payload, which is
734
+ // the same objection `syntheticPayload` raises against padding `stop`.
735
+ const cell = benchReadExitCell('post_tool_use', runs, cellWorkspace, readExitBytes);
736
+ process.stdout.write(renderReadExitCell(cell));
737
+ process.stdout.write(
738
+ 'ℹ️ measurement only (no gate) — this cell never writes a budget row\n',
739
+ );
740
+ } finally {
741
+ fs.rmSync(cellWorkspace, { recursive: true, force: true });
742
+ }
743
+ return 0;
744
+ }
745
+
542
746
  const workspace = fs.mkdtempSync(path.join(os.tmpdir(), 'ac-hook-bench-'));
543
747
  const results: EventResult[] = [];
544
748
  let control: EventResult | null = null;
@@ -45,6 +45,7 @@ import * as path from 'node:path';
45
45
  import process from 'node:process';
46
46
  import { fileURLToPath, pathToFileURL } from 'node:url';
47
47
 
48
+ import { evaluateDashboardOnDisk, parseModeToken, type DashboardMode } from '../agent-src/scripts/dashboard_mode.js';
48
49
  import { GateLedger } from './_lib/gate_ledger.js';
49
50
  import { DeadScopeError, reportScanned } from './_lib/scan_scope.js';
50
51
  import { parse_frontmatter } from './validate_frontmatter.js';
@@ -390,6 +391,39 @@ export function main(argv: readonly string[]): number {
390
391
  const json = renderJson(entries);
391
392
 
392
393
  if (argv.includes('--check')) {
394
+ // `--untracked-mode` is the same three-state table the dashboard's
395
+ // `--check` already runs, on a second generated artefact: in-index is a
396
+ // failure, absent is the declared state, present is still compared
397
+ // against a fresh render. Untracked never means unchecked. The table
398
+ // itself lives in `dashboard_mode.ts` and is imported rather than
399
+ // restated, so the two artefacts cannot drift into different verdicts
400
+ // for the same observable state.
401
+ const mode: DashboardMode =
402
+ argv.map(parseModeToken).find((m) => m !== null) ?? 'tracked';
403
+ if (mode === 'untracked') {
404
+ let failed = false;
405
+ for (const [abs, rel, rendered] of [
406
+ [mdPath, `${ARCHIVE_REL}/${INDEX_MD}`, md],
407
+ [jsonPath, `${ARCHIVE_REL}/${INDEX_JSON}`, json],
408
+ ] as const) {
409
+ const v = evaluateDashboardOnDisk({
410
+ mode,
411
+ target: abs,
412
+ repo_root: ROOT,
413
+ rendered,
414
+ rel,
415
+ regen: 'Run `task build-archive-index` to regenerate.',
416
+ noun: 'archive index',
417
+ });
418
+ if (v.stale) {
419
+ failed = true;
420
+ process.stderr.write(v.error ?? '');
421
+ } else if (!quiet && v.ok !== null) {
422
+ process.stdout.write(v.ok);
423
+ }
424
+ }
425
+ return failed ? 1 : 0;
426
+ }
393
427
  const stale = [
394
428
  _read(mdPath) === md ? null : `${ARCHIVE_REL}/${INDEX_MD}`,
395
429
  _read(jsonPath) === json ? null : `${ARCHIVE_REL}/${INDEX_JSON}`,