@event4u/agent-config 14.20.0 → 14.22.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 (242) 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 +441 -0
  5. package/CREDITS.md +37 -0
  6. package/README.md +1 -1
  7. package/agents/templates/.ai-council.yml.example +10 -0
  8. package/dist/agent-src/commands/analyze/inbox.md +381 -6
  9. package/dist/agent-src/commands/analyze/{reference-repo.md → repo.md} +251 -34
  10. package/dist/agent-src/commands/analyze/roadmap-repos.md +129 -0
  11. package/dist/agent-src/commands/analyze.md +12 -7
  12. package/dist/agent-src/commands/feature/plan.md +55 -16
  13. package/dist/agent-src/commands/feature/refactor.md +8 -3
  14. package/dist/agent-src/commands/humanize.md +48 -4
  15. package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +69 -0
  16. package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -5
  17. package/dist/agent-src/contexts/execution/contract-decision-sheet.md +22 -1
  18. package/dist/agent-src/contexts/execution/host-capability-manifest.md +4 -1
  19. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +35 -2
  20. package/dist/agent-src/contexts/execution/terminal-states.md +4 -1
  21. package/dist/agent-src/rules/evaluator-independence.md +4 -4
  22. package/dist/agent-src/rules/external-code-graph-interop.md +19 -14
  23. package/dist/agent-src/rules/external-reference-deep-dive.md +2 -2
  24. package/dist/agent-src/rules/token-efficiency.md +26 -3
  25. package/dist/agent-src/scripts/_cli_entry.ts +51 -0
  26. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +14 -23
  27. package/dist/agent-src/scripts/roadmap_gates.ts +4 -20
  28. package/dist/agent-src/scripts/roadmap_set_step.ts +5 -2
  29. package/dist/agent-src/scripts/stubs_due.ts +4 -18
  30. package/dist/agent-src/scripts/update_roadmap_progress.ts +7 -24
  31. package/dist/agent-src/skills/code-intelligence/SKILL.md +25 -0
  32. package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
  33. package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +27 -11
  34. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +1 -1
  35. package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
  36. package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
  37. package/dist/agent-src/skills/roadmap-writing/SKILL.md +17 -0
  38. package/dist/agent-src/skills/technical-specification/SKILL.md +4 -0
  39. package/dist/agent-src/templates/agent-settings.md +0 -1
  40. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  41. package/dist/agent-src/templates/features.md +5 -0
  42. package/dist/agent-src/templates/roadmaps.md +15 -0
  43. package/dist/cli-delegate/_cli_entry.js +8 -0
  44. package/dist/cli-delegate/_lib/pin_resolver.js +170 -0
  45. package/dist/cli-delegate/archival_sweep.js +8 -0
  46. package/dist/cli-delegate/archive_completed_roadmaps.js +494 -0
  47. package/dist/cli-delegate/check_update_banner.js +923 -0
  48. package/dist/cli-delegate/{chunk-KPBWFOPZ.js → chunk-2FTMENJL.js} +194 -37
  49. package/dist/cli-delegate/{chunk-PI2GU3DP.js → chunk-2TAQ2K4V.js} +4 -1
  50. package/dist/cli-delegate/chunk-5EK5WQN6.js +28 -0
  51. package/dist/cli-delegate/chunk-7XGD2OEU.js +96 -0
  52. package/dist/cli-delegate/{chunk-C6IPZRDA.js → chunk-BIXEDQPZ.js} +7 -1
  53. package/dist/cli-delegate/chunk-DBH4AHDK.js +155 -0
  54. package/dist/cli-delegate/{chunk-NUMQHLS5.js → chunk-J3RFNKG4.js} +21 -2
  55. package/dist/cli-delegate/chunk-JO25G5H7.js +20 -0
  56. package/dist/cli-delegate/chunk-LTYVIY76.js +7961 -0
  57. package/dist/cli-delegate/chunk-QAJS5YWY.js +999 -0
  58. package/dist/cli-delegate/{chunk-ZVBOHSVF.js → chunk-TGIPZBCW.js} +1 -1
  59. package/dist/cli-delegate/{chunk-YS6XTLEK.js → chunk-TYSY33MD.js} +56 -6
  60. package/dist/cli-delegate/chunk-ULET4BYS.js +328 -0
  61. package/dist/cli-delegate/chunk-YDQSHTD7.js +187 -0
  62. package/dist/cli-delegate/chunk-YWVXLR44.js +48 -0
  63. package/dist/cli-delegate/chunk-ZZQBUHFK.js +273 -0
  64. package/dist/cli-delegate/cmd_conformance.js +19 -5
  65. package/dist/cli-delegate/cmd_doctor.js +3 -3
  66. package/dist/cli-delegate/cmd_export.js +2 -2
  67. package/dist/cli-delegate/cmd_handoff.js +27 -3
  68. package/dist/cli-delegate/cmd_prune.js +2 -2
  69. package/dist/cli-delegate/cmd_session_recycle.js +2 -2
  70. package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
  71. package/dist/cli-delegate/cmd_sync.js +2 -2
  72. package/dist/cli-delegate/cmd_uninstall.js +2 -2
  73. package/dist/cli-delegate/cmd_validate.js +2 -2
  74. package/dist/cli-delegate/dashboard_mode.js +16 -0
  75. package/dist/cli-delegate/gate_budget.js +24 -0
  76. package/dist/cli-delegate/gate_execute.js +25 -0
  77. package/dist/cli-delegate/guarded_baseline.js +18 -0
  78. package/dist/cli-delegate/resume_probe.js +22 -0
  79. package/dist/cli-delegate/roadmap_gates.js +638 -0
  80. package/dist/cli-delegate/roadmap_set_step.js +173 -0
  81. package/dist/cli-delegate/stub_queue.js +47 -0
  82. package/dist/cli-delegate/stubs_due.js +38 -0
  83. package/dist/cli-delegate/ticket_bundles.js +59 -0
  84. package/dist/cli-delegate/update_roadmap_progress.js +60 -0
  85. package/dist/discovery/deprecation-report.md +1 -1
  86. package/dist/discovery/discovery-manifest.json +60 -29
  87. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  88. package/dist/discovery/discovery-manifest.summary.md +3 -3
  89. package/dist/discovery/dormancy-report.md +1 -1
  90. package/dist/discovery/orphan-report.md +1 -1
  91. package/dist/discovery/packs.json +7 -6
  92. package/dist/discovery/trust-report.md +2 -2
  93. package/dist/discovery/workspaces.json +6 -5
  94. package/dist/hooks/dispatch.js +1522 -1008
  95. package/dist/install/claudeLayerCarriage.js +237 -0
  96. package/dist/install/claudePathsPlan.js +79 -0
  97. package/dist/install/hostLayerFingerprint.js +1 -1
  98. package/dist/install/install.mjs +10 -1
  99. package/dist/install/partitionEligibility.js +231 -117
  100. package/dist/install/ruleLayerPartition.js +10 -7
  101. package/dist/mcp/registry-manifest.json +3 -3
  102. package/dist/mcp/server.json +2 -2
  103. package/dist/mcp/server.mjs +39376 -38902
  104. package/dist/scripts/ai_council/content_ceiling.js +63 -0
  105. package/dist/scripts/ai_council/seat_policy.js +106 -0
  106. package/dist/scripts/ai_council/transport_resolver.js +21 -0
  107. package/dist/scripts/condense.js +32 -25
  108. package/docs/MIGRATION.md +49 -1
  109. package/docs/contracts/settings-classes.md +1 -1
  110. package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +73 -0
  111. package/llms.txt +14 -14
  112. package/package.json +7 -4
  113. package/src/agent-src/scripts/_cli_entry.ts +51 -0
  114. package/src/agent-src/scripts/archive_completed_roadmaps.ts +14 -23
  115. package/src/agent-src/scripts/roadmap_gates.ts +4 -20
  116. package/src/agent-src/scripts/roadmap_set_step.ts +5 -2
  117. package/src/agent-src/scripts/stubs_due.ts +4 -18
  118. package/src/agent-src/scripts/update_roadmap_progress.ts +7 -24
  119. package/src/config/continuity-surface.json +509 -0
  120. package/src/config/estate-count-budget.json +1 -1
  121. package/src/config/gate-coverage.yml +29 -8
  122. package/src/config/gate-violation-baselines.json +8 -8
  123. package/src/config/gitignore-block.txt +19 -0
  124. package/src/config/host-injection-effect.json +73 -0
  125. package/src/config/packed-binary-manifest.json +33 -0
  126. package/src/config/preamble-payload-budget.json +112 -105
  127. package/src/config/publish-surface.json +4 -2
  128. package/src/config/release-gate-locality.yml +4 -3
  129. package/src/install/claudeLayerCarriage.ts +273 -0
  130. package/src/install/claudePathsPlan.ts +76 -0
  131. package/src/install/hostLayerFingerprint.ts +1 -1
  132. package/src/install/partitionEligibility.ts +261 -127
  133. package/src/install/ruleLayerPartition.ts +19 -23
  134. package/src/scripts/_dispatch.bash +77 -27
  135. package/src/scripts/_lib/auto_dispatch.ts +2 -2
  136. package/src/scripts/_lib/blocked_by_marker.ts +189 -0
  137. package/src/scripts/_lib/catalogue_layer_parity.ts +146 -0
  138. package/src/scripts/_lib/continuity_surface.ts +296 -0
  139. package/src/scripts/_lib/corpus_manifest.ts +26 -9
  140. package/src/scripts/_lib/hook_settings.ts +1 -1
  141. package/src/scripts/_lib/host_capability.ts +38 -1
  142. package/src/scripts/_lib/injection_effect.ts +151 -0
  143. package/src/scripts/_lib/layer_overlap_notice.ts +50 -6
  144. package/src/scripts/_lib/packed_binary_predicate.ts +225 -0
  145. package/src/scripts/_lib/pin_resolver.ts +13 -0
  146. package/src/scripts/_lib/regression_neighbourhood.ts +1 -1
  147. package/src/scripts/_lib/release_highlights.ts +19 -211
  148. package/src/scripts/_lib/release_material.ts +27 -77
  149. package/src/scripts/_lib/retired_status.ts +74 -0
  150. package/src/scripts/_lib/skill_catalogue.ts +156 -21
  151. package/src/scripts/_lib/structured_ask.ts +117 -0
  152. package/src/scripts/_lib/subagent_capsule.ts +117 -8
  153. package/src/scripts/_lib/tty_prompt.ts +76 -0
  154. package/src/scripts/ai_council/api_transport.ts +168 -0
  155. package/src/scripts/ai_council/clients.ts +58 -63
  156. package/src/scripts/ai_council/config.ts +13 -0
  157. package/src/scripts/ai_council/content_ceiling.ts +79 -0
  158. package/src/scripts/ai_council/deliberation_metrics.ts +353 -0
  159. package/src/scripts/ai_council/jury_aggregate.ts +178 -0
  160. package/src/scripts/ai_council/prompts.ts +9 -0
  161. package/src/scripts/ai_council/seat_policy.ts +137 -0
  162. package/src/scripts/ai_council/status_surface.ts +79 -0
  163. package/src/scripts/ai_council/synthesis_disagreement.ts +206 -0
  164. package/src/scripts/ai_council/transport_resolver.ts +59 -1
  165. package/src/scripts/ai_tells_rules.ts +446 -5
  166. package/src/scripts/ask_block_census.ts +499 -0
  167. package/src/scripts/bench_humanizer_eval.ts +264 -40
  168. package/src/scripts/bench_prose_tells_fp.ts +198 -0
  169. package/src/scripts/capture_skill_catalogue.ts +24 -11
  170. package/src/scripts/check_branch_work_committed.ts +234 -0
  171. package/src/scripts/check_candidate_lines.ts +499 -0
  172. package/src/scripts/check_continuity_surface.ts +475 -0
  173. package/src/scripts/check_dependency_floors.ts +13 -6
  174. package/src/scripts/check_estate_count.ts +40 -79
  175. package/src/scripts/check_pack_size.ts +263 -24
  176. package/src/scripts/check_release_highlights.ts +0 -157
  177. package/src/scripts/check_roadmap_trackable.ts +19 -16
  178. package/src/scripts/check_rule_layer_partition.ts +54 -34
  179. package/src/scripts/check_single_delivery.ts +97 -31
  180. package/src/scripts/check_update_banner.ts +13 -0
  181. package/src/scripts/code_graph/build.ts +138 -15
  182. package/src/scripts/code_graph/cli.ts +76 -8
  183. package/src/scripts/code_graph/extract.ts +11 -0
  184. package/src/scripts/code_graph/grammar_probe.ts +43 -0
  185. package/src/scripts/code_graph/loader.ts +88 -14
  186. package/src/scripts/code_graph/query.ts +121 -11
  187. package/src/scripts/code_graph/resolution_tiers.ts +238 -0
  188. package/src/scripts/code_graph/sqlite_store.ts +247 -6
  189. package/src/scripts/code_graph/types.ts +66 -1
  190. package/src/scripts/code_graph/validate.ts +23 -0
  191. package/src/scripts/condense.ts +34 -22
  192. package/src/scripts/corpus_manifest.ts +5 -5
  193. package/src/scripts/council_cli.ts +29 -39
  194. package/src/scripts/count_intent_disagreement.ts +426 -0
  195. package/src/scripts/detect_ai_tells.ts +142 -20
  196. package/src/scripts/handoff_context_hook.ts +79 -0
  197. package/src/scripts/harvest_reference_tokens.ts +698 -0
  198. package/src/scripts/hook_effect_doctor.ts +82 -1
  199. package/src/scripts/hook_manifest.json +1 -1
  200. package/src/scripts/hook_manifest.yaml +94 -12
  201. package/src/scripts/hooks/chain_nudge_hook.ts +282 -0
  202. package/src/scripts/hooks/code_graph_context_hook.ts +212 -0
  203. package/src/scripts/hooks/concern_registry.ts +6 -2
  204. package/src/scripts/hooks/delegation_nudge_hook.ts +45 -1
  205. package/src/scripts/hooks/host_semantics.ts +1 -1
  206. package/src/scripts/hooks/one_question_per_ask_hook.ts +191 -0
  207. package/src/scripts/hooks/orchestration_record_hook.ts +2 -2
  208. package/src/scripts/hooks/rule_inject_hook.ts +1 -1
  209. package/src/scripts/hooks/skill_route_hook.ts +11 -4
  210. package/src/scripts/inbox_source_census.ts +322 -0
  211. package/src/scripts/install-hooks.sh +134 -0
  212. package/src/scripts/{lint_carrier_integrity.ts → lint_deferral_integrity.ts} +60 -214
  213. package/src/scripts/lint_plan_risk_register.ts +13 -17
  214. package/src/scripts/lint_roadmap_blockers.ts +51 -1
  215. package/src/scripts/mcp_server/suggest_skill.ts +72 -0
  216. package/src/scripts/mcp_server/tools.ts +2 -56
  217. package/src/scripts/media/lib/adapter-contract.md +7 -2
  218. package/src/scripts/media/lib/fixtures/flux/asset-0001.png +0 -0
  219. package/src/scripts/media/lib/fixtures/gemini-image/asset-0001.png +0 -0
  220. package/src/scripts/media/lib/fixtures/ideogram/asset-0001.png +0 -0
  221. package/src/scripts/migrate_command_suggestions.ts +1 -1
  222. package/src/scripts/probe_unblocked_ask.ts +135 -2
  223. package/src/scripts/rdp_candidates_delta.ts +276 -0
  224. package/src/scripts/rdp_quality_eval.ts +217 -19
  225. package/src/scripts/release.ts +26 -71
  226. package/src/scripts/release_drill.ts +6 -10
  227. package/src/scripts/release_env.ts +1 -0
  228. package/src/scripts/release_mix_taxonomy.json +3 -2
  229. package/src/scripts/release_publication.ts +34 -29
  230. package/src/scripts/report_host_injection_effect.ts +189 -0
  231. package/src/scripts/report_layer_overlap.ts +41 -0
  232. package/src/scripts/report_skill_menu_census.ts +341 -0
  233. package/src/scripts/self_review_gate.ts +409 -15
  234. package/src/scripts/skill_tools/score_skill_relevance.ts +70 -6
  235. package/src/scripts/skill_tools/suggest_skill_for_task.ts +37 -3
  236. package/src/vendor/grammars/README.md +61 -0
  237. package/src/vendor/grammars/tree-sitter-javascript.wasm +0 -0
  238. package/src/vendor/grammars/tree-sitter-php.wasm +0 -0
  239. package/src/vendor/grammars/tree-sitter-typescript.wasm +0 -0
  240. package/src/scripts/_lib/carrier_status.ts +0 -118
  241. package/src/scripts/_lib/estate_carrier_cases.ts +0 -72
  242. package/src/scripts/hooks/code_graph_nudge_hook.ts +0 -191
@@ -30,6 +30,18 @@ if [ -n "${AGENT_CONFIG_HOOKS_DIR+set}" ]; then
30
30
  exit 2
31
31
  fi
32
32
  HOOKS_DIR="$AGENT_CONFIG_HOOKS_DIR"
33
+ elif CONFIGURED_HOOKS_PATH="$(git -C "$PROJECT_ROOT" config --get core.hooksPath 2>/dev/null)" \
34
+ && [ -n "$CONFIGURED_HOOKS_PATH" ]; then
35
+ # core.hooksPath wins over .git/hooks WHEREVER IT IS SET — git stops looking
36
+ # in the common dir entirely once it is configured. Installing into
37
+ # .git/hooks while git reads somewhere else writes six hooks that never run,
38
+ # and the freshness gate would then compare the copy nothing executes.
39
+ # Resolved relative to PROJECT_ROOT because git interprets a relative
40
+ # core.hooksPath against the top level of the working tree, not against CWD.
41
+ case "$CONFIGURED_HOOKS_PATH" in
42
+ /*) HOOKS_DIR="$CONFIGURED_HOOKS_PATH" ;;
43
+ *) HOOKS_DIR="$PROJECT_ROOT/$CONFIGURED_HOOKS_PATH" ;;
44
+ esac
33
45
  elif COMMON_GIT_DIR="$(git -C "$PROJECT_ROOT" rev-parse --git-common-dir 2>/dev/null)"; then
34
46
  case "$COMMON_GIT_DIR" in /*) : ;; *) COMMON_GIT_DIR="$PROJECT_ROOT/$COMMON_GIT_DIR" ;; esac
35
47
  HOOKS_DIR="$COMMON_GIT_DIR/hooks"
@@ -152,6 +164,58 @@ elif ! ./scripts-run src/scripts/check_branch_freshness --quiet; then
152
164
  exit 1
153
165
  fi
154
166
 
167
+ # BRANCH WORK COMMITTED — after base freshness, before everything else.
168
+ #
169
+ # Ordering is deliberate in BOTH directions. It runs AFTER base freshness
170
+ # because the remedy there (`task push-ready`) merges, and a merge changes the
171
+ # working tree this gate reads — checking first would answer against a tree the
172
+ # operator is about to replace. It runs BEFORE the remaining gates because they
173
+ # all answer against the working tree, and a tree carrying unfinished work
174
+ # makes their verdicts describe something that is not being pushed.
175
+ #
176
+ # Measured twice, and both placements were wrong for a different reason.
177
+ # Placing it FIRST reded tests/scripts/prepush_base_freshness.test.ts, which
178
+ # executes the whole hook and asserts the freshness block is reached. Placing
179
+ # it between the next block's comment header and that block's `echo` reded
180
+ # check_installed_hooks_fresh's advisory pin, whose extraction runs from that
181
+ # header to the following task-availability check and so swallowed this block's
182
+ # `exit 1`. A block goes BEFORE a neighbour's comment header, never between the
183
+ # header and its code.
184
+ #
185
+ # And this paragraph may NOT name that header literally: the pin locates it with
186
+ # a plain indexOf over the rendered hook, so a comment quoting the string
187
+ # becomes the first match and truncates the block to nothing. An anchor that is
188
+ # also content is not an anchor — spelled out here because the obvious edit to
189
+ # this comment is to put the string back in for clarity.
190
+ #
191
+ # The defect it exists for, measured 2026-09-07: a reconciled baseline was
192
+ # written into gate-violation-baselines.json AFTER `git add`, so
193
+ # `git commit --no-edit` captured the staged side, the edit stayed in the tree,
194
+ # and the push shipped a branch whose commits contradicted it. CI cannot see
195
+ # this class at all — it checks out the commit, not the tree the edit is in.
196
+ #
197
+ # It blocks only what it can attribute to THIS branch (staged paths, and dirty
198
+ # paths this branch's own commits touch). A gate script's report output and a
199
+ # parallel session's edit are named and waved through, which is what keeps this
200
+ # from becoming the blanket clean-tree rule that would train the operator to
201
+ # set the skip variable.
202
+ echo "🔍 Branch work committed — is any of this branch's own work still uncommitted?"
203
+ if [ "${AGENT_CONFIG_SKIP_PREPUSH_WORKTREE:-}" = "1" ]; then
204
+ echo "⏭️ skipped via AGENT_CONFIG_SKIP_PREPUSH_WORKTREE=1"
205
+ elif [ ! -x ./scripts-run ]; then
206
+ echo "⚠️ ./scripts-run not found — skipping the worktree check for this push."
207
+ elif ! ./scripts-run src/scripts/check_branch_work_committed --quiet; then
208
+ echo ""
209
+ echo " Push blocked — this branch's own work is not all committed, so the"
210
+ echo " pushed branch would carry commits its own tree contradicts."
211
+ echo ""
212
+ echo " Commit them, or 'git restore' whatever was not meant to land."
213
+ echo ""
214
+ echo " This hook refuses; it never commits for you. Bypass a genuine WIP"
215
+ echo " push with AGENT_CONFIG_SKIP_PREPUSH_WORKTREE=1."
216
+ exit 1
217
+ fi
218
+
155
219
  # INSTALLED-HOOK FRESHNESS — ADVISORY, and deliberately AFTER base freshness.
156
220
  #
157
221
  # What it answers: are the hooks in .git/hooks still what THIS checkout's
@@ -522,3 +586,73 @@ EOF
522
586
  append_auto_sync_block "post-merge" "1"
523
587
  append_auto_sync_block "post-checkout" "3"
524
588
  echo "✅ Auto-sync block appended to post-merge / post-checkout hooks." >&2
589
+
590
+ # Code-graph freshness, from git, with no daemon ----------------------------
591
+ #
592
+ # road-to-a-graph-that-is-shipped 1.3. A code graph goes stale the moment a
593
+ # commit lands, and the only thing that knew were the reader — after it had
594
+ # already answered from a stale index. These two hooks close that without a
595
+ # resident process: git tells us HEAD moved, and a detached child rebuilds.
596
+ #
597
+ # Four properties, each load-bearing:
598
+ #
599
+ # · BACKGROUND. The refresh is `&`-detached with stdout/stderr closed, so a
600
+ # commit never waits on a parse. Git's own runtime is unchanged.
601
+ # · SINGLE-FLIGHT. `mkdir` is atomic on every POSIX filesystem, so of two
602
+ # concurrent commits exactly one creates the lock and exactly one refresh
603
+ # runs. This is Risk 3 in the roadmap's register — "git hooks pile up
604
+ # rebuilds" — and a lock file written with `>` would not have closed it,
605
+ # because two processes can both truncate-and-write the same path.
606
+ # · BUDGETED. `--budget-seconds` is the engine's own wall-clock ceiling; a
607
+ # child that exceeds it is SIGKILLed and the OLD cache is left untouched
608
+ # (cli.ts's refresh contract). Kill register K7 — never block on a stale
609
+ # graph — holds by construction here, since nothing waits at all.
610
+ # · NEVER BUILDS ONE UNBIDDEN. The block is a no-op unless a cache already
611
+ # exists. Building a graph for someone who never asked for one is the pure
612
+ # cost Risk 1 names; refreshing one they built is the service.
613
+ #
614
+ # The lock is a directory under the gitignored runtime state, so a crashed
615
+ # child leaves a stale lock that the next refresh clears by age rather than
616
+ # blocking forever.
617
+
618
+ append_code_graph_refresh_block() {
619
+ local name="$1"
620
+ cat >> "$HOOKS_DIR/$name" << EOF
621
+
622
+ # --- code-graph background refresh ------------------------------------------
623
+ EOF
624
+ if [ "$name" = "post-checkout" ]; then
625
+ cat >> "$HOOKS_DIR/$name" << 'EOF'
626
+ # A file-checkout ($3 = 0) moves no commits, so there is nothing to be behind.
627
+ if [ "${3:-1}" = "0" ]; then
628
+ exit 0
629
+ fi
630
+ EOF
631
+ fi
632
+ cat >> "$HOOKS_DIR/$name" << 'EOF'
633
+ cg_cache="agents/runtime/state/code-graph-v1.json"
634
+ cg_lock="agents/runtime/state/code-graph-refresh.lock"
635
+ if [ -f "$cg_cache" ] && [ -x ./agent-config ]; then
636
+ # Clear a lock left by a killed child: older than the largest budget any
637
+ # caller passes, so it cannot race a refresh that is legitimately running.
638
+ if [ -d "$cg_lock" ]; then
639
+ if [ -z "$(find "$cg_lock" -maxdepth 0 -mmin -5 2>/dev/null)" ]; then
640
+ rmdir "$cg_lock" 2>/dev/null || true
641
+ fi
642
+ fi
643
+ # Atomic: exactly one of N concurrent hooks wins this, and the losers do
644
+ # nothing rather than queueing a second rebuild behind the first.
645
+ if mkdir "$cg_lock" 2>/dev/null; then
646
+ (
647
+ trap 'rmdir "$cg_lock" 2>/dev/null || true' EXIT
648
+ ./agent-config code-graph refresh --budget-seconds 60 >/dev/null 2>&1 || true
649
+ ) >/dev/null 2>&1 &
650
+ fi
651
+ fi
652
+ exit 0
653
+ EOF
654
+ }
655
+
656
+ append_code_graph_refresh_block "post-commit"
657
+ append_code_graph_refresh_block "post-checkout"
658
+ echo "✅ Code-graph refresh block appended to post-commit / post-checkout hooks." >&2
@@ -37,16 +37,16 @@
37
37
  * three are red here, deliberately, until a disposition vocabulary exists to
38
38
  * express them.
39
39
  *
40
- * A SECOND ENUMERATION runs beside the first, over the live carriers rather
41
- * than over the archived parents, and it exists because the walk direction that
42
- * makes whole-file deletion detectable also makes a self-declared carrier
43
- * invisible. `status: carrier` buys exclusion from the active count, from
44
- * trackability and from the plan risk register; enumerating only archived
45
- * parents means a file nobody carried anything to wears the status for free.
46
- * So every live carrier must be named by some dead roadmap's `carried-to=`
47
- * annotation, and one that is not is a hard failure like any other lost
48
- * obligation — the status is legitimate for a receiver of a real carry, and for
49
- * nothing else.
40
+ * A SECOND ENUMERATION used to run beside this one, over the live roadmaps that
41
+ * declared `status: carrier`, reddening any that no archived parent named. It
42
+ * existed only to police the three exemptions that status bought — from the
43
+ * active roadmap count, from `check_roadmap_trackable` and from the plan risk
44
+ * register — so that a file nobody carried anything to could not wear them for
45
+ * free. ADR-262 deleted the status and all three exemptions, leaving nothing to
46
+ * police: a file that would once have been an unjustified carrier is now
47
+ * ordinary estate, caught by those gates for present-tense reasons rather than
48
+ * for its ancestry. The reciprocal direction — every carry names a destination
49
+ * that exists and back-links — is this enumeration, and it is untouched.
50
50
  *
51
51
  * Exit codes: 0 = every carry resolves, 1 = at least one does not.
52
52
  */
@@ -102,12 +102,12 @@ const EXCLUDE_NAMES: ReadonlySet<string> = new Set([
102
102
  * is an obligation that had a recorded home and lost it. Deleting a live
103
103
  * receiver produces this class, not the other one.
104
104
  */
105
- export type CarrierProblemClass = 'unannotated' | 'broken-destination';
105
+ export type DeferralProblemClass = 'unannotated' | 'broken-destination';
106
106
 
107
- export interface CarrierProblem {
107
+ export interface DeferralProblem {
108
108
  /** Repo-relative path of the archived roadmap whose carry is broken. */
109
109
  source: string;
110
- cls: CarrierProblemClass;
110
+ cls: DeferralProblemClass;
111
111
  detail: string;
112
112
  }
113
113
 
@@ -197,7 +197,6 @@ function _locate(root: string, slug: string): { file: string; dir: 'active' | 'l
197
197
  const OPEN_STEP_RE = /^[ \t]*[-*][ \t]*\[[ ][ \t]*\][ \t]/;
198
198
  /** A fenced block's delimiter, in either of the two fence styles in use here. */
199
199
  const FENCE_RE = /^[ \t]*(?:```|~~~)/;
200
- const CARRIER_STATUS_RE = /^status:[ \t]*carrier[ \t]*$/m;
201
200
 
202
201
  /**
203
202
  * True when an OPEN step appears OUTSIDE every fenced block.
@@ -222,11 +221,6 @@ export function hasOpenStep(text: string): boolean {
222
221
  return false;
223
222
  }
224
223
 
225
- /** True when the frontmatter — not the body — declares `status: carrier`. */
226
- export function declaresCarrier(text: string): boolean {
227
- return CARRIER_STATUS_RE.test(frontmatter(text));
228
- }
229
-
230
224
  /**
231
225
  * The standing carry policy for one archived roadmap. See the module header for
232
226
  * why this is not `deferralProblems`.
@@ -235,23 +229,22 @@ export function carryProblems(
235
229
  root: string,
236
230
  sourceSlug: string,
237
231
  text: string,
238
- ): Array<{ cls: CarrierProblemClass; detail: string }> {
232
+ ): Array<{ cls: DeferralProblemClass; detail: string }> {
239
233
  return carryProblemsFor(root, sourceSlug, parseDeferredItems(text));
240
234
  }
241
235
 
242
236
  /**
243
237
  * The same policy over an ALREADY-PARSED item list.
244
238
  *
245
- * Split out so the walk parses each candidate once and reuses the result for
246
- * both this check and the destination census the live-carrier enumeration
247
- * needs, rather than parsing the same file twice per run.
239
+ * Split out so the walk parses each candidate once and hands the item list to
240
+ * this check, rather than parsing the same file twice per run.
248
241
  */
249
242
  export function carryProblemsFor(
250
243
  root: string,
251
244
  sourceSlug: string,
252
245
  items: readonly DeferredItem[],
253
- ): Array<{ cls: CarrierProblemClass; detail: string }> {
254
- const problems: Array<{ cls: CarrierProblemClass; detail: string }> = [];
246
+ ): Array<{ cls: DeferralProblemClass; detail: string }> {
247
+ const problems: Array<{ cls: DeferralProblemClass; detail: string }> = [];
255
248
  for (const item of items) {
256
249
  const label = item.text === '' ? '(unnamed step)' : item.text;
257
250
  if (item.kind === null || item.destination === null) {
@@ -289,20 +282,6 @@ export function carryProblemsFor(
289
282
  continue;
290
283
  }
291
284
  const destText = fs.readFileSync(found.file, 'utf-8');
292
- // A carrier exists to stay live. Archiving one is the terminal-archival
293
- // transition that has no vocabulary yet, and it strands every item the
294
- // carrier itself holds — none of which is an OPEN step, so the check
295
- // below would not see it.
296
- if (found.dir === 'archive' && declaresCarrier(destText)) {
297
- problems.push({
298
- cls: 'broken-destination',
299
- detail:
300
- `destination \`${item.destination}\` is a \`status: carrier\` roadmap that has been ` +
301
- 'archived — a carrier holds obligations whose triggers are unmet, so archiving it ' +
302
- 'strands them. Terminal archival of a live carrier is not expressible yet and fails closed.',
303
- });
304
- continue;
305
- }
306
285
  if (found.dir === 'archive' && hasOpenStep(destText)) {
307
286
  problems.push({
308
287
  cls: 'broken-destination',
@@ -322,67 +301,20 @@ export function carryProblemsFor(
322
301
  return problems;
323
302
  }
324
303
 
325
- /** The live locations a carrier may occupy — both are live per `_locate`. */
326
- const LIVE_SUBDIRS: readonly string[] = ['', 'later'];
327
-
328
304
  /**
329
- * Every roadmap that DECLARES `status: carrier` and is still live.
330
- *
331
- * The enumeration the walk-from-the-archive direction cannot produce. Sorted,
332
- * repo-relative, and `later/` is included because `_locate` treats a parked
333
- * receiver as live — a carrier parked there is equally excluded from the active
334
- * count, so it needs the same justification.
335
- */
336
- export function liveCarriers(root: string): string[] {
337
- const out: string[] = [];
338
- for (const sub of LIVE_SUBDIRS) {
339
- const abs = path.join(root, 'agents', 'roadmaps', sub);
340
- let entries: string[];
341
- try {
342
- entries = fs.readdirSync(abs);
343
- } catch {
344
- continue;
345
- }
346
- for (const name of entries.sort()) {
347
- if (!name.endsWith('.md') || EXCLUDE_NAMES.has(name)) {
348
- continue;
349
- }
350
- const full = path.join(abs, name);
351
- let text: string;
352
- try {
353
- if (!fs.statSync(full).isFile()) {
354
- continue;
355
- }
356
- text = fs.readFileSync(full, 'utf-8');
357
- } catch {
358
- continue;
359
- }
360
- if (declaresCarrier(text)) {
361
- out.push(path.posix.join('agents/roadmaps', sub, name));
362
- }
363
- }
364
- }
365
- return out;
366
- }
367
-
368
- /**
369
- * Validate every carry annotation in the dead directories, then every live
370
- * carrier against the destinations those annotations actually name.
305
+ * Validate every carry annotation in the dead directories.
371
306
  *
372
307
  * @param walked the dead-roadmap list, when the caller already has it. The walk
373
308
  * `statSync`s every file in the archive, so taking it as a parameter is what
374
309
  * stops the run doing that twice — once for the ledger's plan and once here.
375
- * @returns the problems found, how many dead roadmaps were read, and how many
376
- * live carriers were checked.
310
+ * @returns the problems found and how many dead roadmaps were read.
377
311
  */
378
312
  export function auditCarries(
379
313
  root: string,
380
314
  walked: readonly string[] = deadRoadmaps(root),
381
- ): { problems: CarrierProblem[]; scanned: number; carriers: string[] } {
382
- const problems: CarrierProblem[] = [];
315
+ ): { problems: DeferralProblem[]; scanned: number } {
316
+ const problems: DeferralProblem[] = [];
383
317
  let scanned = 0;
384
- /** Every slug some dead roadmap named with `carried-to=`. */
385
- const carriedTo = new Set<string>();
386
318
  for (const rel of walked) {
387
319
  let text: string;
388
320
  try {
@@ -395,39 +327,15 @@ export function auditCarries(
395
327
  continue;
396
328
  }
397
329
  const items = parseDeferredItems(text);
398
- for (const item of items) {
399
- if (item.kind === 'carried-to' && item.destination !== null) {
400
- carriedTo.add(item.destination);
401
- }
402
- }
403
330
  const sourceSlug = path.basename(rel).replace(/\.md$/, '');
404
331
  for (const found of carryProblemsFor(root, sourceSlug, items)) {
405
332
  problems.push({ source: rel, ...found });
406
333
  }
407
334
  }
408
- const carriers = liveCarriers(root);
409
- for (const rel of carriers) {
410
- const slug = path.basename(rel).replace(/\.md$/, '');
411
- if (carriedTo.has(slug)) {
412
- continue;
413
- }
414
- problems.push({
415
- source: rel,
416
- cls: 'broken-destination',
417
- detail:
418
- 'declares `status: carrier`, but no roadmap under `agents/roadmaps/archive/` or ' +
419
- '`agents/roadmaps/skipped/` names it with a `<!-- deferred-resolution: ' +
420
- `carried-to=${slug} -->\` annotation. That status is only legitimate for the ` +
421
- 'RECEIVER of a real carry: it buys exclusion from the active roadmap count, from ' +
422
- '`check_roadmap_trackable` and from the plan risk register, so a file no archived ' +
423
- 'parent carried anything to would take all three exclusions for nothing. Either ' +
424
- 'record the carry in the parent that deferred the work, or drop `status: carrier`.',
425
- });
426
- }
427
- return { problems, scanned, carriers };
335
+ return { problems, scanned };
428
336
  }
429
337
 
430
- const USAGE = `usage: lint_carrier_integrity [--root <dir>] [--self-test] [--quiet]
338
+ const USAGE = `usage: lint_deferral_integrity [--root <dir>] [--self-test] [--quiet]
431
339
 
432
340
  --root <dir> audit another checkout (default: this repository)
433
341
  --self-test run the built-in discrimination suite and exit
@@ -454,19 +362,15 @@ Body.
454
362
  }
455
363
 
456
364
  /**
457
- * A body that DOCUMENTS roadmap syntax inside a fence. Both structural tests
458
- * used to match it, so this fixture is the one that fails in two ways at once.
365
+ * A body that DOCUMENTS roadmap syntax inside a fence rather than declaring it.
366
+ * `hasOpenStep` used to match the `- [ ]` line inside it and red an archived
367
+ * receiver that had completed its work.
459
368
  */
460
- const FENCED_SYNTAX_DOC = 'Syntax this file documents rather than declares:\n\n```markdown\n---\nstatus: carrier\n---\n- [ ] **1.1 An example open step.**\n```\n';
369
+ const FENCED_SYNTAX_DOC = 'Syntax this file documents rather than declares:\n\n```markdown\n---\nstatus: draft\n---\n- [ ] **1.1 An example open step.**\n```\n';
461
370
 
462
371
  /** A back-link that exists only in the body — a mention, never a declaration. */
463
372
  const FENCED_BODY_BACKLINK = 'What a back-link looks like, quoted:\n\n```yaml\nparent_roadmap: road-to-parent\nrelates:\n - slug: road-to-parent\n relation: extends\n```\n';
464
373
 
465
- /** A receiver that declares itself a carrier — used only where that is the point. */
466
- function _carrierReceiver(backlink: string): string {
467
- return _receiver(backlink).replace('---\n# Receiver', 'status: carrier\n---\n# Receiver');
468
- }
469
-
470
374
  /**
471
375
  * Each case builds a throwaway tree, runs the real CLI against it with
472
376
  * `--root`, and asserts the exit code. Shelling out rather than calling
@@ -488,7 +392,7 @@ export function selfTestCases(root: string): SelfTestCase[] {
488
392
  plant(dir);
489
393
  return runGateCli(
490
394
  root,
491
- 'src/scripts/lint_carrier_integrity.ts',
395
+ 'src/scripts/lint_deferral_integrity.ts',
492
396
  ['--root', dir, '--quiet'],
493
397
  root,
494
398
  );
@@ -503,7 +407,7 @@ export function selfTestCases(root: string): SelfTestCase[] {
503
407
  {
504
408
  name: 'a live receiver with a back-link is accepted',
505
409
  expect: 'accept',
506
- run: build('carrier-ok-', (dir) => {
410
+ run: build('deferral-ok-', (dir) => {
507
411
  parent(dir);
508
412
  _writeFixture(
509
413
  dir,
@@ -515,7 +419,7 @@ export function selfTestCases(root: string): SelfTestCase[] {
515
419
  {
516
420
  name: 'a receiver parked under later/ is equally live and is accepted',
517
421
  expect: 'accept',
518
- run: build('carrier-later-', (dir) => {
422
+ run: build('deferral-later-', (dir) => {
519
423
  parent(dir);
520
424
  _writeFixture(
521
425
  dir,
@@ -527,7 +431,7 @@ export function selfTestCases(root: string): SelfTestCase[] {
527
431
  {
528
432
  name: 'a receiver that completed its work and archived is accepted — fulfilment, not loss',
529
433
  expect: 'accept',
530
- run: build('carrier-done-', (dir) => {
434
+ run: build('deferral-done-', (dir) => {
531
435
  parent(dir);
532
436
  _writeFixture(
533
437
  dir,
@@ -539,7 +443,7 @@ export function selfTestCases(root: string): SelfTestCase[] {
539
443
  {
540
444
  name: 'a back-link supplied as a relates: row instead of parent_roadmap is accepted',
541
445
  expect: 'accept',
542
- run: build('carrier-relates-', (dir) => {
446
+ run: build('deferral-relates-', (dir) => {
543
447
  parent(dir);
544
448
  _writeFixture(
545
449
  dir,
@@ -548,22 +452,10 @@ export function selfTestCases(root: string): SelfTestCase[] {
548
452
  );
549
453
  }),
550
454
  },
551
- {
552
- name: 'a live carrier an archived parent actually names is accepted',
553
- expect: 'accept',
554
- run: build('carrier-named-', (dir) => {
555
- parent(dir);
556
- _writeFixture(
557
- dir,
558
- 'agents/roadmaps/road-to-receiver.md',
559
- _carrierReceiver('parent_roadmap: road-to-parent'),
560
- );
561
- }),
562
- },
563
455
  {
564
456
  name: 'an archived receiver that only documents roadmap syntax in a fence is accepted',
565
457
  expect: 'accept',
566
- run: build('carrier-fenced-', (dir) => {
458
+ run: build('deferral-fenced-', (dir) => {
567
459
  parent(dir);
568
460
  _writeFixture(
569
461
  dir,
@@ -572,44 +464,10 @@ export function selfTestCases(root: string): SelfTestCase[] {
572
464
  );
573
465
  }),
574
466
  },
575
- {
576
- name: 'a live carrier no archived parent names is rejected — the status is not free',
577
- expect: 'reject',
578
- run: build('carrier-orphan-', (dir) => {
579
- parent(dir);
580
- _writeFixture(
581
- dir,
582
- 'agents/roadmaps/road-to-receiver.md',
583
- _receiver('parent_roadmap: road-to-parent'),
584
- );
585
- _writeFixture(
586
- dir,
587
- 'agents/roadmaps/road-to-self-declared.md',
588
- _carrierReceiver('owner: maintainer'),
589
- );
590
- }),
591
- },
592
- {
593
- name: 'an orphan carrier parked under later/ is rejected too',
594
- expect: 'reject',
595
- run: build('carrier-orphan-later-', (dir) => {
596
- parent(dir);
597
- _writeFixture(
598
- dir,
599
- 'agents/roadmaps/road-to-receiver.md',
600
- _receiver('parent_roadmap: road-to-parent'),
601
- );
602
- _writeFixture(
603
- dir,
604
- 'agents/roadmaps/later/road-to-self-declared.md',
605
- _carrierReceiver('owner: maintainer'),
606
- );
607
- }),
608
- },
609
467
  {
610
468
  name: 'an archived receiver with an asterisk-bulleted OPEN step is rejected',
611
469
  expect: 'reject',
612
- run: build('carrier-asterisk-', (dir) => {
470
+ run: build('deferral-asterisk-', (dir) => {
613
471
  parent(dir);
614
472
  _writeFixture(
615
473
  dir,
@@ -621,7 +479,7 @@ export function selfTestCases(root: string): SelfTestCase[] {
621
479
  {
622
480
  name: 'a back-link that only appears in the body, not the frontmatter, is rejected',
623
481
  expect: 'reject',
624
- run: build('carrier-bodylink-', (dir) => {
482
+ run: build('deferral-bodylink-', (dir) => {
625
483
  parent(dir);
626
484
  _writeFixture(
627
485
  dir,
@@ -630,27 +488,15 @@ export function selfTestCases(root: string): SelfTestCase[] {
630
488
  );
631
489
  }),
632
490
  },
633
- {
634
- name: 'a receiver that is itself a carrier and has been archived is rejected',
635
- expect: 'reject',
636
- run: build('carrier-archived-carrier-', (dir) => {
637
- parent(dir);
638
- _writeFixture(
639
- dir,
640
- 'agents/roadmaps/archive/road-to-receiver.md',
641
- _carrierReceiver('parent_roadmap: road-to-parent'),
642
- );
643
- }),
644
- },
645
491
  {
646
492
  name: 'the receiver deleted entirely is rejected',
647
493
  expect: 'reject',
648
- run: build('carrier-deleted-', parent),
494
+ run: build('deferral-deleted-', parent),
649
495
  },
650
496
  {
651
497
  name: 'a receiver archived while still carrying OPEN steps is rejected — stranded, not completed',
652
498
  expect: 'reject',
653
- run: build('carrier-stranded-', (dir) => {
499
+ run: build('deferral-stranded-', (dir) => {
654
500
  parent(dir);
655
501
  _writeFixture(
656
502
  dir,
@@ -662,7 +508,7 @@ export function selfTestCases(root: string): SelfTestCase[] {
662
508
  {
663
509
  name: 'a receiver under skipped/ is rejected — skipping is not fulfilling',
664
510
  expect: 'reject',
665
- run: build('carrier-skipped-', (dir) => {
511
+ run: build('deferral-skipped-', (dir) => {
666
512
  parent(dir);
667
513
  _writeFixture(
668
514
  dir,
@@ -674,7 +520,7 @@ export function selfTestCases(root: string): SelfTestCase[] {
674
520
  {
675
521
  name: 'the back-link removed is rejected — the link must verify from both ends',
676
522
  expect: 'reject',
677
- run: build('carrier-nolink-', (dir) => {
523
+ run: build('deferral-nolink-', (dir) => {
678
524
  parent(dir);
679
525
  _writeFixture(
680
526
  dir,
@@ -686,7 +532,7 @@ export function selfTestCases(root: string): SelfTestCase[] {
686
532
  {
687
533
  name: 'a back-link naming a different parent is rejected',
688
534
  expect: 'reject',
689
- run: build('carrier-reparent-', (dir) => {
535
+ run: build('deferral-reparent-', (dir) => {
690
536
  parent(dir);
691
537
  _writeFixture(
692
538
  dir,
@@ -711,34 +557,36 @@ export function main(argv: string[]): number {
711
557
  } else if (arg === '--root') {
712
558
  const next = argv[i + 1];
713
559
  if (next === undefined) {
714
- process.stderr.write('lint_carrier_integrity: --root needs a directory\n');
560
+ process.stderr.write('lint_deferral_integrity: --root needs a directory\n');
715
561
  return 2;
716
562
  }
717
563
  root = path.resolve(next);
718
564
  i += 1;
719
565
  } else if (arg === '--self-test') {
720
566
  return runSelfTest({
721
- gate: 'lint_carrier_integrity',
567
+ gate: 'lint_deferral_integrity',
722
568
  cases: selfTestCases(_DEFAULT_ROOT),
723
- minCases: 16,
724
- minRejectCases: 10,
569
+ // 16/10 before ADR-262 deleted `status: carrier`, which took one
570
+ // accept case (a named live carrier) and three reject cases (two
571
+ // orphan carriers, one archived carrier destination) with it.
572
+ minCases: 12,
573
+ minRejectCases: 7,
725
574
  });
726
575
  } else {
727
- process.stderr.write(`lint_carrier_integrity: unknown argument ${JSON.stringify(arg)}\n`);
576
+ process.stderr.write(`lint_deferral_integrity: unknown argument ${JSON.stringify(arg)}\n`);
728
577
  process.stderr.write(USAGE);
729
578
  return 2;
730
579
  }
731
580
  }
732
581
 
733
- const ledger = new GateLedger('lint_carrier_integrity');
582
+ const ledger = new GateLedger('lint_deferral_integrity');
734
583
  const walked = deadRoadmaps(root);
735
- // Walked ONCE and handed to the audit. The two enumerations used to each
736
- // call `deadRoadmaps`, so a run cost two readdirs and two `statSync` per
737
- // archived file for one reading.
738
- const { problems, scanned, carriers } = auditCarries(root, walked);
739
- ledger.plan([...walked, ...carriers]);
584
+ // Walked ONCE and handed to the audit, so the run does not readdir and
585
+ // `statSync` every archived file twice for one reading.
586
+ const { problems, scanned } = auditCarries(root, walked);
587
+ ledger.plan([...walked]);
740
588
  const failed = new Set(problems.map((p) => p.source));
741
- for (const rel of [...walked, ...carriers]) {
589
+ for (const rel of walked) {
742
590
  if (failed.has(rel)) {
743
591
  ledger.fail(rel, problems.find((p) => p.source === rel)?.detail ?? 'broken carry');
744
592
  } else {
@@ -747,7 +595,7 @@ export function main(argv: string[]): number {
747
595
  }
748
596
  try {
749
597
  reportScanned({
750
- gate: 'lint_carrier_integrity',
598
+ gate: 'lint_deferral_integrity',
751
599
  scanned,
752
600
  units: 'archived roadmap(s)',
753
601
  roots: DEAD_DIRS.map((d) => `agents/roadmaps/${d}`),
@@ -779,16 +627,14 @@ export function main(argv: string[]): number {
779
627
  process.stderr.write(
780
628
  '\n Restore the receiver, restore its `parent_roadmap:` back-link, or move the\n' +
781
629
  ' carried items back to open in the archived parent. A rename or a re-parent is\n' +
782
- ' not expressible yet and fails closed on purpose.\n' +
783
- ' A file listed for declaring `status: carrier` needs neither: record the carry\n' +
784
- ' in the archived parent, or drop the status and let the file be ordinary estate.\n',
630
+ ' not expressible yet and fails closed on purpose.\n',
785
631
  );
786
632
  ledger.report();
787
633
  return 1;
788
634
  }
789
635
 
790
636
  const verdict = checkRatchet({
791
- gate: 'lint_carrier_integrity',
637
+ gate: 'lint_deferral_integrity',
792
638
  actual: unannotated.length,
793
639
  repoRoot: _DEFAULT_ROOT,
794
640
  });
@@ -807,8 +653,8 @@ export function main(argv: string[]): number {
807
653
  if (!quiet) {
808
654
  process.stdout.write(`✅ ${verdict.message}\n`);
809
655
  process.stdout.write(
810
- `✅ lint_carrier_integrity: ${String(scanned)} dead roadmap(s) scanned, ` +
811
- `${String(carriers.length)} live carrier(s) justified, every annotated carry resolves.\n`,
656
+ `✅ lint_deferral_integrity: ${String(scanned)} dead roadmap(s) scanned, ` +
657
+ 'every annotated carry resolves.\n',
812
658
  );
813
659
  }
814
660
  ledger.report();