@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.12 → 0.1.28

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 (410) hide show
  1. package/bin/adl +2 -2
  2. package/bin/git +16 -17
  3. package/bin/git-ado +25 -24
  4. package/bin/git-defaults +173 -0
  5. package/bin/health-check +8 -1
  6. package/bin/kimi-hooks +1 -1
  7. package/bin/lib/adl-package.sh +257 -0
  8. package/bin/lib/fleet-host.sh +8 -5
  9. package/bin/reconcile +482 -232
  10. package/bin/reconcile-host +30 -20
  11. package/bin/setup +20 -17
  12. package/bin/shell-path-policy +15 -5
  13. package/bin/sync-and-reconcile +62 -64
  14. package/bin/validate-manifest +33 -9
  15. package/package.json +2 -10
  16. package/packages/agent-hooks/README.md +14 -9
  17. package/packages/agent-hooks/assets/hooks.json +0 -20
  18. package/packages/agent-hooks/src/cli/args.ts +1 -1
  19. package/packages/agent-hooks/src/cli/doctor.ts +6 -58
  20. package/packages/agent-hooks/src/deploy/deploy.ts +12 -41
  21. package/packages/agent-hooks/src/deploy/doctor.ts +8 -11
  22. package/packages/agent-hooks/src/deploy/index.ts +14 -14
  23. package/packages/agent-hooks/src/deploy/json-merge.ts +7 -8
  24. package/packages/agent-hooks/src/deploy/legacy-lock.ts +2 -2
  25. package/packages/agent-hooks/src/deploy/list.ts +1 -1
  26. package/packages/agent-hooks/src/deploy/lock.ts +31 -12
  27. package/packages/agent-hooks/src/deploy/profile.ts +3 -4
  28. package/packages/agent-hooks/src/deploy/source.ts +1 -1
  29. package/packages/agent-hooks/src/gating/config.ts +12 -24
  30. package/packages/agent-hooks/src/gating/root.ts +3 -3
  31. package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
  32. package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
  33. package/packages/agent-hooks/src/hooks/contract.ts +17 -17
  34. package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
  35. package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
  36. package/packages/agent-hooks/src/hooks/log.ts +8 -10
  37. package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
  38. package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
  39. package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
  40. package/packages/agent-hooks/src/hosts/registry.ts +1 -1
  41. package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
  42. package/packages/agent-hooks/src/log/writer.ts +16 -2
  43. package/packages/agent-hooks/src/main.ts +7 -41
  44. package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
  45. package/packages/agent-hooks/src/rules/engine.ts +13 -17
  46. package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
  47. package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
  48. package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
  49. package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
  50. package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
  51. package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
  52. package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
  53. package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
  54. package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
  55. package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
  56. package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
  57. package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
  58. package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
  59. package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
  60. package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +131 -0
  61. package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
  62. package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
  63. package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
  64. package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
  65. package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
  66. package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
  67. package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
  68. package/packages/agent-hooks/src/rules/impl/tool-grep.ts +33 -12
  69. package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
  70. package/packages/agent-hooks/src/rules/ports.ts +5 -7
  71. package/packages/agent-hooks/src/rules/registry.ts +4 -6
  72. package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
  73. package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
  74. package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
  75. package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
  76. package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
  77. package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
  78. package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
  79. package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
  80. package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
  81. package/packages/agent-hooks/src/rules/spec.ts +2 -2
  82. package/packages/agent-settings/README.md +287 -0
  83. package/packages/agent-settings/assets/GLOBAL-AGENTS.md +14 -16
  84. package/packages/agent-settings/assets/agents/architect.toml +2 -0
  85. package/packages/agent-settings/assets/agents/code-reviewer.toml +2 -0
  86. package/packages/agent-settings/assets/agents/executor.toml +2 -0
  87. package/packages/agent-settings/assets/agents/explore.toml +2 -0
  88. package/packages/agent-settings/assets/agents/planner.toml +2 -0
  89. package/packages/agent-settings/assets/mcp.json +0 -4
  90. package/packages/agent-settings/deploy-profile.json +139 -0
  91. package/packages/agent-settings/deploy-profile.schema.json +147 -0
  92. package/packages/agent-settings/managed/README.md +29 -30
  93. package/packages/agent-settings/managed/codex-requirements.toml +9 -9
  94. package/packages/agent-settings/package.json +20 -0
  95. package/packages/agent-settings/src/deploy/agent-render.ts +2 -2
  96. package/packages/agent-settings/src/deploy/agent-toml.ts +1 -1
  97. package/packages/agent-settings/src/deploy/agents-deploy.ts +17 -3
  98. package/packages/agent-settings/src/deploy/doctor.ts +3 -83
  99. package/packages/agent-settings/src/deploy/index.ts +6 -33
  100. package/packages/agent-settings/src/deploy/legacy-lock.ts +6 -6
  101. package/packages/agent-settings/src/deploy/list.ts +5 -19
  102. package/packages/agent-settings/src/deploy/lock.ts +8 -18
  103. package/packages/agent-settings/src/deploy/mcp-deploy.ts +10 -5
  104. package/packages/agent-settings/src/deploy/mcp-merge.ts +22 -3
  105. package/packages/agent-settings/src/deploy/mcp-source.ts +1 -1
  106. package/packages/agent-settings/src/deploy/profile.ts +11 -35
  107. package/packages/agent-settings/src/deploy/retire-lean-ctx.ts +184 -0
  108. package/packages/agent-settings/src/deploy/settings.ts +17 -22
  109. package/packages/agent-settings/src/global-surface-sweep.ts +0 -2
  110. package/packages/agent-settings/src/kimi-hooks.ts +339 -192
  111. package/packages/agent-settings/src/opencode-hooks.ts +1 -1
  112. package/packages/agent-settings/tsconfig.json +23 -0
  113. package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +120 -0
  114. package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +276 -0
  115. package/packages/agent-skills/assets/debug-issue/SKILL.md +8 -7
  116. package/packages/agent-skills/assets/explore-codebase/SKILL.md +13 -13
  117. package/packages/agent-skills/assets/refactor-safely/SKILL.md +12 -11
  118. package/packages/agent-skills/assets/review-changes/SKILL.md +7 -7
  119. package/packages/agent-skills/assets/testing/references/e2e.md +37 -0
  120. package/packages/agent-skills/assets/testing/references/integration.md +37 -0
  121. package/packages/agent-skills/assets/testing/references/unit.md +32 -0
  122. package/packages/agent-skills/dist/deploy.d.ts +2 -0
  123. package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
  124. package/packages/agent-skills/dist/deploy.js +27 -1
  125. package/packages/agent-skills/dist/deploy.js.map +1 -1
  126. package/packages/agent-skills/dist/doctor.d.ts +0 -2
  127. package/packages/agent-skills/dist/doctor.d.ts.map +1 -1
  128. package/packages/agent-skills/dist/doctor.js +1 -1
  129. package/packages/agent-skills/dist/doctor.js.map +1 -1
  130. package/packages/agent-skills/dist/fs-utils.d.ts +0 -1
  131. package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -1
  132. package/packages/agent-skills/dist/fs-utils.js +1 -1
  133. package/packages/agent-skills/dist/fs-utils.js.map +1 -1
  134. package/packages/agent-skills/src/deploy.ts +29 -1
  135. package/packages/agent-skills/src/doctor.ts +1 -1
  136. package/packages/agent-skills/src/fs-utils.ts +1 -1
  137. package/packages/azdo/README.md +10 -9
  138. package/packages/azdo/package.json +1 -3
  139. package/packages/azdo/scripts/probe-ado-rules.ts +311 -0
  140. package/packages/azdo/src/azdo-pl.ts +2 -54
  141. package/packages/azdo/src/azdo-pr-review.ts +4 -4
  142. package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
  143. package/packages/azdo/src/azdo-wit.ts +44 -2
  144. package/packages/azdo/src/lib/agent-identity.ts +12 -14
  145. package/packages/azdo/src/lib/agent-token.ts +2 -2
  146. package/packages/azdo/src/lib/client.ts +0 -5
  147. package/packages/azdo/src/lib/graph-identity.ts +4 -4
  148. package/packages/azdo/src/workflow-ladder.csv +241 -0
  149. package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
  150. package/packages/azdo/src/workflow-rules.ts +194 -0
  151. package/packages/fleet/manifest.json +35 -11
  152. package/packages/fleet/manifest.schema.json +62 -10
  153. package/packages/fleet/src/default-agent-file.ts +3 -3
  154. package/packages/fleet/src/install-adl-package.ts +73 -15
  155. package/packages/fleet/src/install-embedding-model.ts +13 -13
  156. package/packages/fleet/src/managed-settings.ts +7 -7
  157. package/packages/fleet/src/repo-maintain.ts +91 -55
  158. package/packages/fleet/src/scratch-reap.ts +5 -5
  159. package/packages/fleet/src/vscode-settings.ts +5 -5
  160. package/packages/repo-controls/README.md +141 -43
  161. package/packages/repo-controls/assets/promote.ts +4 -4
  162. package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
  163. package/packages/repo-controls/assets/version-bump.sh +31 -84
  164. package/packages/repo-controls/bunfig.toml +6 -7
  165. package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
  166. package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
  167. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
  168. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
  169. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
  170. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
  171. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
  172. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
  173. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/c.md +1 -0
  174. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/d.md +1 -0
  175. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
  176. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
  177. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
  178. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
  179. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
  180. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
  181. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/sub/nested.md +1 -0
  182. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
  183. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
  184. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
  185. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
  186. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
  187. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
  188. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
  189. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
  190. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
  191. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
  192. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
  193. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
  194. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-001-tenancy.md +1 -0
  195. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-002-carrier.md +1 -0
  196. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-003-cli.md +1 -0
  197. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-old.md +1 -0
  198. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-older.md +1 -0
  199. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
  200. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
  201. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
  202. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
  203. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-01.md +1 -0
  204. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-02.md +1 -0
  205. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-03.md +1 -0
  206. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-04.md +1 -0
  207. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-05.md +1 -0
  208. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-06.md +1 -0
  209. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-07.md +1 -0
  210. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-08.md +1 -0
  211. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-09.md +1 -0
  212. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-10.md +1 -0
  213. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-11.md +1 -0
  214. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-12.md +1 -0
  215. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-13.md +1 -0
  216. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-14.md +1 -0
  217. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-15.md +1 -0
  218. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-16.md +1 -0
  219. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
  220. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
  221. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
  222. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
  223. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
  224. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
  225. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
  226. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
  227. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
  228. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/a.md +1 -0
  229. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/b.md +1 -0
  230. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/c.md +1 -0
  231. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/d.md +1 -0
  232. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/e.md +1 -0
  233. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
  234. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/a.md +1 -0
  235. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/b.md +1 -0
  236. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/c.md +1 -0
  237. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/short/only.md +1 -0
  238. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
  239. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
  240. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
  241. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
  242. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
  243. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
  244. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
  245. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
  246. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
  247. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
  248. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
  249. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
  250. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
  251. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
  252. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
  253. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
  254. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
  255. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
  256. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
  257. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
  258. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
  259. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
  260. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
  261. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
  262. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
  263. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
  264. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
  265. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
  266. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
  267. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
  268. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
  269. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
  270. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
  271. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
  272. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
  273. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
  274. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
  275. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
  276. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-legacy/docs/compliance/index.md +10 -0
  277. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-type/docs/compliance/index.md +10 -0
  278. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
  279. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
  280. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
  281. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
  282. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
  283. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
  284. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
  285. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
  286. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/no-type.md +9 -0
  287. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-experiment.md +10 -0
  288. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-research.md +10 -0
  289. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
  290. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs/architecture/bad-status.md +0 -1
  291. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
  292. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
  293. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
  294. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
  295. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
  296. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
  297. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-last-update.md +11 -0
  298. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
  299. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
  300. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
  301. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
  302. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
  303. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/created-date.md +21 -0
  304. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/research-shaped.md +19 -0
  305. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
  306. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
  307. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
  308. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
  309. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
  310. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
  311. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
  312. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/a.ts +1 -0
  313. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/b.ts +1 -0
  314. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
  315. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
  316. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
  317. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
  318. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/a.ts +1 -0
  319. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/b.ts +1 -0
  320. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/c.ts +1 -0
  321. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
  322. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
  323. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
  324. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
  325. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
  326. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
  327. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
  328. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
  329. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
  330. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
  331. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
  332. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +258 -2
  333. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
  334. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
  335. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plan_metadata.py +9 -4
  336. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/check.py +1 -1
  337. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/items/az351-restore-entrypoint.md +1 -1
  338. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +3 -3
  339. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
  340. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
  341. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
  342. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
  343. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
  344. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
  345. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
  346. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
  347. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
  348. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
  349. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
  350. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
  351. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
  352. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
  353. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
  354. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
  355. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
  356. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
  357. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
  358. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
  359. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
  360. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
  361. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
  362. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
  363. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
  364. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
  365. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
  366. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
  367. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
  368. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
  369. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
  370. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
  371. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
  372. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
  373. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
  374. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
  375. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
  376. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
  377. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
  378. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
  379. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
  380. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
  381. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
  382. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
  383. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
  384. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
  385. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
  386. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
  387. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
  388. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
  389. package/packages/repo-controls/package.json +2 -9
  390. package/packages/repo-controls/scripts/hooks/post-merge +13 -0
  391. package/packages/repo-controls/scripts/hooks/pre-push +3 -3
  392. package/packages/repo-controls/src/azdo-push.ts +64 -36
  393. package/packages/repo-controls/src/azure-devops-governance.ts +7 -9
  394. package/packages/repo-controls/src/azure-devops-remote.ts +1 -1
  395. package/packages/repo-controls/src/cli.ts +29 -8
  396. package/packages/repo-controls/src/compliance-config.ts +410 -2
  397. package/packages/repo-controls/src/config.ts +133 -60
  398. package/packages/repo-controls/src/constants.ts +13 -27
  399. package/packages/repo-controls/src/coverage-ratchet.ts +4 -4
  400. package/packages/repo-controls/src/doctor.ts +46 -19
  401. package/packages/repo-controls/src/gitignore-block.ts +5 -29
  402. package/packages/repo-controls/src/hook-log.ts +1 -2
  403. package/packages/repo-controls/src/hook.ts +201 -45
  404. package/packages/repo-controls/src/install.ts +14 -8
  405. package/packages/repo-controls/src/integrity.ts +3 -3
  406. package/packages/repo-controls/src/lfs.ts +111 -0
  407. package/packages/repo-controls/src/promote.ts +8 -8
  408. package/packages/repo-controls/src/runtime.ts +9 -1
  409. package/packages/repo-controls/src/workflows-drift.ts +4 -5
  410. package/packages/repo-controls/src/worktree-guard.ts +3 -3
@@ -13,13 +13,10 @@
13
13
  * signal for that lives now, since UserPromptSubmit only WARNS -- an
14
14
  * empty corpus has an innocent explanation once it is per-host and
15
15
  * per-extension, and a dead prompt is worse than a missing hint);
16
- * `lean-ctx` not on PATH or `--version` failing (briefing and the
17
- * lean-ctx hooks shell out to it); `code-review-graph` not on PATH
18
- * (the crg hooks shell out to it).
16
+ * `code-review-graph` not on PATH (the crg hooks shell out to it).
19
17
  * warn — unmanaged repo (hooks no-op by design); `[hooks] enabled = false`;
20
18
  * embedding model missing/corrupt (user-prompt-submit falls back to
21
- * BM25-only, never fatal); vector half disabled; lean-ctx allowlist
22
- * count not readable.
19
+ * BM25-only, never fatal); vector half disabled.
23
20
  *
24
21
  * The vector half is "effectively disabled by cosineFloor" when the floor
25
22
  * exceeds 1: a vector hit must reach `cosine >= cosineFloor` to enter fusion
@@ -36,8 +33,6 @@ import { scanSkills } from '../hooks/user-prompt-submit/skills.ts'
36
33
  import { loadTokenizer } from '../hooks/user-prompt-submit/tokenizer.ts'
37
34
  import { loadVectorHalf, resolveGlobalArtifactDir } from '../hooks/user-prompt-submit/vector.ts'
38
35
  import { HOOKS_DENY_LOG_REL, HOOKS_LOG_REL } from '../hooks/log.ts'
39
- import { DEFAULT_LEAN_CTX_DIR, leanCtxEnv } from '../lean-ctx/env.ts'
40
- import { spawnWithTimeout } from '../lib/spawn-with-timeout.ts'
41
36
  import { buildEngineContext } from '../rules/engine.ts'
42
37
  import { liveEnv, liveRepoIndex } from '../rules/ports.ts'
43
38
  import { BUILTIN_RULES, requireRegistered } from '../rules/registry.ts'
@@ -46,6 +41,9 @@ import { type CliResult, type LoadedRepo, cliError, loadRepo, parseArgs, unmanag
46
41
  type Status = 'ok' | 'warn' | 'FAIL' | 'skip' | 'info'
47
42
  type Env = Readonly<Record<string, string | undefined>>
48
43
 
44
+ /** Reserved for callers that previously supplied process-check timeouts. */
45
+ export interface DoctorOptions { readonly timeoutMs?: number }
46
+
49
47
  interface Check {
50
48
  readonly status: Status
51
49
  readonly text: string
@@ -53,13 +51,6 @@ interface Check {
53
51
 
54
52
  const check = (status: Status, name: string, detail: string): Check => ({ status, text: `${name}: ${detail}` })
55
53
 
56
- export interface DoctorOptions {
57
- /** Per-subprocess timeout for `lean-ctx --version` / `lean-ctx doctor --json`. */
58
- readonly timeoutMs?: number
59
- }
60
-
61
- const DEFAULT_TIMEOUT_MS = 10_000
62
-
63
54
  /** Config + rule resolution, and the config the downstream checks use (null when unusable). */
64
55
  function repoChecks(loaded: LoadedRepo): { readonly checks: Check[]; readonly config: AdlRepoConfig | null } {
65
56
  const { state } = loaded
@@ -148,48 +139,6 @@ function modelAndVector(env: Env): Check[] {
148
139
  return [model, vector]
149
140
  }
150
141
 
151
- async function leanCtxChecks(
152
- loaded: LoadedRepo,
153
- config: AdlRepoConfig | null,
154
- env: Env,
155
- timeoutMs: number,
156
- ): Promise<Check[]> {
157
- const path = Bun.which('lean-ctx', { PATH: env.PATH ?? '' })
158
- const skipAllowlist = check('skip', 'lean-ctx allowlist', 'lean-ctx not usable')
159
- if (path === null) return [check('FAIL', 'lean-ctx', `not found on PATH (${env.PATH ?? ''})`), skipAllowlist]
160
- const version = await spawnWithTimeout(path, ['--version'], { env, timeoutMs })
161
- if (version.exitCode !== 0) {
162
- const reason = version.timedOut ? `timed out after ${timeoutMs}ms` : `exited ${version.exitCode}: ${version.stderr.trim()}`
163
- return [check('FAIL', 'lean-ctx', `${path} --version ${reason}`), skipAllowlist]
164
- }
165
- const binary = check('ok', 'lean-ctx', `${path} (${version.stdout.trim().split('\n')[0]})`)
166
-
167
- // Same env the hooks give lean-ctx: repo-rooted LEAN_CTX_* in a managed repo, lean-ctx's own defaults otherwise (mcp.ts).
168
- // `config` is the value `repoChecks` already decoded — reusing it keeps an invalid
169
- // `adl-config.toml` reported by the `config` check above rather than thrown from here.
170
- const root = loaded.state.managed && config !== null ? (loaded.state.root as string) : null
171
- const childEnv = root === null ? { ...env } : leanCtxEnv(root, env, config?.hooks.leanCtxDir ?? DEFAULT_LEAN_CTX_DIR)
172
- const scope = root === null ? 'lean-ctx defaults; LEAN_CTX_CONFIG_DIR unset' : `LEAN_CTX_CONFIG_DIR=${childEnv.LEAN_CTX_CONFIG_DIR}`
173
- const unavailable = (reason: string): Check[] => [binary, check('warn', 'lean-ctx allowlist', `unavailable (${reason})`)]
174
- const doctor = await spawnWithTimeout(path, ['doctor', '--json'], { env: childEnv, timeoutMs, ...(root === null ? {} : { cwd: root }) })
175
- if (doctor.timedOut) return unavailable(`lean-ctx doctor --json timed out after ${timeoutMs}ms`)
176
- // A non-zero exit alone is not a failure: lean-ctx 3.10.1 exits 1 whenever any of its OWN checks fail
177
- // (e.g. no shell aliases) while still printing the full report. Only a report we cannot read is.
178
- let parsed: { readonly checks?: readonly { readonly name?: string }[] }
179
- try {
180
- parsed = JSON.parse(doctor.stdout) as typeof parsed
181
- } catch {
182
- return unavailable(
183
- doctor.exitCode === 0
184
- ? 'lean-ctx doctor --json printed invalid JSON'
185
- : `lean-ctx doctor --json exited ${doctor.exitCode}: ${doctor.stderr.trim()}`,
186
- )
187
- }
188
- const count = (parsed.checks ?? []).map((entry) => /Shell allowlist\s+(\d+) command/.exec(entry.name ?? '')?.[1]).find((n) => n !== undefined)
189
- if (count === undefined) return unavailable('no "Shell allowlist" check in lean-ctx doctor --json')
190
- return [binary, check('ok', 'lean-ctx allowlist', `${count} command(s) enforced (${scope})`)]
191
- }
192
-
193
142
  /** Both hook logs: path, row count, and for the deny log its last 5 rows. JSON Lines (docs/architecture/cli-design.md §5a): every line is a record, there is no header row to skip. */
194
143
  function logChecks(loaded: LoadedRepo): Check[] {
195
144
  if (!loaded.state.managed) return [check('skip', 'logs', 'not a managed repo (hooks log nothing here)')]
@@ -216,7 +165,7 @@ function crgCheck(env: Env): Check {
216
165
  }
217
166
 
218
167
  /** `argv` is everything after `doctor`. */
219
- export async function runDoctor(argv: readonly string[], cwd: string, env: Env, options: DoctorOptions = {}): Promise<CliResult> {
168
+ export async function runDoctor(argv: readonly string[], cwd: string, env: Env, _options: DoctorOptions = {}): Promise<CliResult> {
220
169
  const parsed = parseArgs(argv, false)
221
170
  if ('error' in parsed) return cliError(parsed.error)
222
171
  if (parsed.positionals.length > 0) return cliError(`unexpected argument '${parsed.positionals[0]}'`)
@@ -228,7 +177,6 @@ export async function runDoctor(argv: readonly string[], cwd: string, env: Env,
228
177
  ...repo.checks,
229
178
  ...hooksAndSkills(loaded, repo.config),
230
179
  ...modelAndVector(env),
231
- ...(await leanCtxChecks(loaded, repo.config, env, options.timeoutMs ?? DEFAULT_TIMEOUT_MS)),
232
180
  crgCheck(env),
233
181
  ...logChecks(loaded),
234
182
  ]
@@ -23,7 +23,6 @@ import {
23
23
  readLegacyLock,
24
24
  sha256Hex,
25
25
  stripLegacyOwnership,
26
- unionOwnedCommands,
27
26
  } from './legacy-lock.ts'
28
27
  import { type HookLockEntry, lockPathFor, readLock, writeLock } from './lock.ts'
29
28
  import { type HookDeployProfile, type HookSurface, loadProfile } from './profile.ts'
@@ -51,13 +50,13 @@ export interface DeployHooksOptions {
51
50
  readonly dryRun?: boolean
52
51
  }
53
52
 
54
- export interface HookConflict {
53
+ interface HookConflict {
55
54
  readonly file: string
56
55
  readonly reason: string
57
56
  }
58
57
 
59
58
  /** One hook healed via the PAIR fallback (not hash, not the legacy channel) this run — see json-merge.ts's `RestoredHook` for the full rationale (2026-09-30, round 5, finding 2). */
60
- export interface RestoredHookReport {
59
+ interface RestoredHookReport {
61
60
  readonly file: string
62
61
  readonly event: string
63
62
  readonly command: string
@@ -78,17 +77,6 @@ export interface DeployHooksResult {
78
77
  readonly unchanged: readonly string[]
79
78
  readonly conflicts: readonly HookConflict[]
80
79
  readonly lockPath: string
81
- /**
82
- * Surface files whose lock entry moved from the legacy
83
- * (`ownedCommands`-only) shape to the content-addressed one
84
- * (`ownedEntries`) on THIS run (independent review, 2026-09-30, finding
85
- * 7). This can be non-empty even when the surface's own `written`/
86
- * `unchanged` outcome looks like nothing happened — the deployed JSON
87
- * file can stay byte-identical while the LOCK itself is rewritten, and
88
- * that rewrite deserves its own truthful line in the CLI's output
89
- * rather than being folded silently into "unchanged".
90
- */
91
- readonly lockMigrated: readonly string[]
92
80
  /** Hooks healed via the pair fallback this run, named explicitly (round 5, finding 2) so deploy's own output, doctor's preview, and `adl install` can all say "restored adl hook <event>/<matcher>/<command> — local changes to it were replaced". */
93
81
  readonly restored: readonly RestoredHookReport[]
94
82
  }
@@ -134,12 +122,11 @@ export function deployHooks(options: DeployHooksOptions): DeployHooksResult {
134
122
  const written: string[] = []
135
123
  const unchanged: string[] = []
136
124
  const conflicts: HookConflict[] = []
137
- const lockMigrated: string[] = []
138
125
  const restored: RestoredHookReport[] = []
139
126
  const takeover = { any: false }
140
127
 
141
128
  for (const surface of profile.surfaces) {
142
- deploySurface(surface, { assetsDir, targetRepo, hooksDoc, lock, legacyDoc, takeover, newEntries, written, unchanged, conflicts, lockMigrated, restored, dryRun })
129
+ deploySurface(surface, { assetsDir, targetRepo, hooksDoc, lock, legacyDoc, takeover, newEntries, written, unchanged, conflicts, restored, dryRun })
143
130
  }
144
131
 
145
132
  if (!dryRun) writeLock(targetRepo, { version: 1, entries: newEntries })
@@ -158,7 +145,6 @@ export function deployHooks(options: DeployHooksOptions): DeployHooksResult {
158
145
  unchanged: unchanged.sort(),
159
146
  conflicts: conflicts.sort((a, b) => a.file.localeCompare(b.file)),
160
147
  lockPath: lockPathFor(targetRepo),
161
- lockMigrated: lockMigrated.sort(),
162
148
  restored,
163
149
  }
164
150
  }
@@ -176,7 +162,6 @@ interface DeploySurfaceContext {
176
162
  readonly written: string[]
177
163
  readonly unchanged: string[]
178
164
  readonly conflicts: HookConflict[]
179
- readonly lockMigrated: string[]
180
165
  readonly restored: RestoredHookReport[]
181
166
  readonly dryRun: boolean
182
167
  }
@@ -212,38 +197,24 @@ function deploySurface(surface: HookSurface, ctx: DeploySurfaceContext): void {
212
197
  // Ownership is content-addressed (json-merge.ts's own header, second
213
198
  // independent review 2026-09-29): `recordedEntries` is THIS package's own
214
199
  // prior write, read straight from the lock as hash+command pairs, never
215
- // derived from command text alone. A lock with no `ownedEntries` at all
216
- // (every repo enrolled before this fix) has no hashes to give — for
217
- // exactly this one transitional deploy, its OLD `ownedCommands` feeds the
218
- // command-anywhere fallback channel instead, unioned with
219
- // `legacyTakeover.ownedByEvent` (the pre-agent-hooks engine's own
220
- // hash-verified takeover signal — a different legacy source, same
221
- // "command text is the only proof we have" shape).
200
+ // derived from command text alone. `readLock` (lock.ts) has already
201
+ // refused any entry without `ownedEntries` (Tarun, 2026-10-01: the legacy
202
+ // `ownedCommands`-only shape is no longer migrated). The command-anywhere
203
+ // channel below is fed ONLY by `legacyTakeover.ownedByEvent` — the
204
+ // pre-agent-hooks engine's own hash-verified takeover signal, a different
205
+ // legacy source that is deliberately kept.
222
206
  const sameFormatPrev = prevEntry !== undefined && prevEntry.format === surface.format ? prevEntry : undefined
223
- const isLegacyShapedLock = sameFormatPrev !== undefined && sameFormatPrev.ownedEntries === undefined
224
- // Independent review, 2026-09-30, finding 7: this transitional deploy
225
- // rewrites the LOCK from the legacy (`ownedCommands`-only) shape to the
226
- // content-addressed one — report it, since the deployed JSON file can
227
- // stay byte-identical while that rewrite happens underneath it.
228
- if (isLegacyShapedLock) ctx.lockMigrated.push(surface.file)
229
207
  const recordedEntries = sameFormatPrev?.ownedEntries ?? {}
230
- const ownCommandsLegacyFallback = isLegacyShapedLock ? sameFormatPrev.ownedCommands : {}
231
208
  const existingRaw = readExistingJson(targetAbs)
232
209
  const legacyTakeover = legacyTakeoverForJsonHooksSurface(existingRaw, ctx.legacyDoc, surface.file)
233
210
  if (legacyTakeover.matched) ctx.takeover.any = true
234
- const legacyCommandsAnywhere = unionOwnedCommands(ownCommandsLegacyFallback, legacyTakeover.ownedByEvent)
211
+ const legacyCommandsAnywhere = legacyTakeover.ownedByEvent
235
212
 
236
213
  if (surface.format === 'cursor-hooks-v1') {
237
214
  const desired = renderCursorEntries(ctx.hooksDoc, surface)
238
215
  const { fileContent, ownedCommands, ownedEntries, changed, restored, ambiguousConflicts } = mergeCursorHooksFile(existingRaw, desired, recordedEntries, legacyCommandsAnywhere)
239
216
  writeJsonIfChanged(targetAbs, fileContent, changed, ctx.dryRun)
240
- // Independent review, 2026-09-30, round 5, finding 4: a legacy lock
241
- // migration rewrites the LOCK for real even when this surface's own
242
- // deployed content stays byte-identical — count that as "written",
243
- // not "unchanged", so a caller reading these two arrays (which is
244
- // exactly what "up to date (no changes)" and "written: N" do) never
245
- // reports a pure no-op when something real did change on disk.
246
- ;(changed || isLegacyShapedLock ? ctx.written : ctx.unchanged).push(surface.file)
217
+ ;(changed ? ctx.written : ctx.unchanged).push(surface.file)
247
218
  ctx.newEntries[surface.file] = { format: 'cursor-hooks-v1', ownedCommands, ownedEntries }
248
219
  for (const hook of restored) ctx.restored.push(makeRestoredReport(surface.file, hook))
249
220
  for (const conflict of ambiguousConflicts) ctx.conflicts.push({ file: surface.file, reason: ambiguousConflictReason(conflict) })
@@ -254,7 +225,7 @@ function deploySurface(surface: HookSurface, ctx: DeploySurfaceContext): void {
254
225
  const desired = renderJsonHooksGroups(ctx.hooksDoc, surface)
255
226
  const { fileContent, ownedCommands, ownedEntries, changed, restored, ambiguousConflicts } = mergeJsonHooksFile(existingRaw, desired, recordedEntries, legacyCommandsAnywhere)
256
227
  writeJsonIfChanged(targetAbs, fileContent, changed, ctx.dryRun)
257
- ;(changed || isLegacyShapedLock ? ctx.written : ctx.unchanged).push(surface.file)
228
+ ;(changed ? ctx.written : ctx.unchanged).push(surface.file)
258
229
  ctx.newEntries[surface.file] = { format: surface.format, ownedCommands, ownedEntries }
259
230
  for (const hook of restored) ctx.restored.push(makeRestoredReport(surface.file, hook))
260
231
  for (const conflict of ambiguousConflicts) ctx.conflicts.push({ file: surface.file, reason: ambiguousConflictReason(conflict) })
@@ -29,7 +29,7 @@ import {
29
29
  import { renderCursorEntries, renderJsonHooksGroups } from './render.ts'
30
30
  import { type CanonicalHooksDoc, loadHooksSource } from './source.ts'
31
31
 
32
- export interface DoctorIssue {
32
+ interface DoctorIssue {
33
33
  readonly severity: 'error' | 'info'
34
34
  readonly path: string
35
35
  readonly reason: string
@@ -44,7 +44,7 @@ function toResult(issues: readonly DoctorIssue[]): DoctorResult {
44
44
  return { ok: issues.every((issue) => issue.severity !== 'error'), issues }
45
45
  }
46
46
 
47
- export { validateProfileDocument }
47
+
48
48
 
49
49
  export interface DoctorDeploymentOptions {
50
50
  readonly assetsDir: string
@@ -71,13 +71,10 @@ function doctorJsonSurface(surface: HookSurface, targetRepo: string, hooksDoc: C
71
71
  const targetAbs = join(targetRepo, surface.file)
72
72
  const exists = existsSync(targetAbs)
73
73
  const lockEntry = lock.entries[surface.file]?.format === surface.format ? (lock.entries[surface.file] as JsonHooksLockEntry) : undefined
74
- // Same fallback deploy.ts itself uses: a lock with no ownedEntries at all
75
- // (every repo enrolled before the content-hash fix) has no hashes to
76
- // give, so its OLD ownedCommands feeds the command-anywhere channel
77
- // instead -- otherwise doctor would report drift for every currently-
78
- // enrolled repo's untouched content that deploy itself recognizes fine.
74
+ // `readLock` has already refused any entry without `ownedEntries`
75
+ // (Tarun, 2026-10-01: the legacy `ownedCommands`-only shape is no longer
76
+ // migrated), so ownership here is always the content-addressed record.
79
77
  const recordedEntries = lockEntry?.ownedEntries ?? {}
80
- const legacyCommandsAnywhere = lockEntry !== undefined && lockEntry.ownedEntries === undefined ? lockEntry.ownedCommands : {}
81
78
 
82
79
  let parseFailed = false
83
80
  if (exists) {
@@ -92,8 +89,8 @@ function doctorJsonSurface(surface: HookSurface, targetRepo: string, hooksDoc: C
92
89
  const existingRaw = readExistingJson(targetAbs)
93
90
  const merged =
94
91
  surface.format === 'cursor-hooks-v1'
95
- ? mergeCursorHooksFile(existingRaw, renderCursorEntries(hooksDoc, surface), recordedEntries, legacyCommandsAnywhere)
96
- : mergeJsonHooksFile(existingRaw, renderJsonHooksGroups(hooksDoc, surface), recordedEntries, legacyCommandsAnywhere)
92
+ ? mergeCursorHooksFile(existingRaw, renderCursorEntries(hooksDoc, surface), recordedEntries)
93
+ : mergeJsonHooksFile(existingRaw, renderJsonHooksGroups(hooksDoc, surface), recordedEntries)
97
94
 
98
95
  if (!exists) {
99
96
  return [{ severity: 'error', path: surface.file, reason: 'expected hook wiring has not been deployed' }]
@@ -144,7 +141,7 @@ function doctorJsonSurface(surface: HookSurface, targetRepo: string, hooksDoc: C
144
141
  severity: 'error' as const,
145
142
  path: `${surface.file}#${event}`,
146
143
  reason:
147
- recordedEntries[event] !== undefined || legacyCommandsAnywhere[event] !== undefined
144
+ recordedEntries[event] !== undefined
148
145
  ? 'deploy-written hook entries were modified since deploy, or assets/hooks.json changed since; run deploy to update'
149
146
  : 'expected hook wiring for this event has not been deployed',
150
147
  }
@@ -1,17 +1,17 @@
1
- export { deployHooks, type DeployHooksOptions, type DeployHooksResult, type HookConflict } from './deploy.ts'
2
- export { doctorDeployment, type DoctorDeploymentOptions, type DoctorIssue, type DoctorResult } from './doctor.ts'
3
- export { formatHookLine, listHooks, type HookListing, type HookListingEntry, type HookOwner, type ListHooksOptions } from './list.ts'
4
- export { type HookLock, type HookLockEntry, LOCK_RELATIVE_PATH, lockPathFor, readLock, writeLock } from './lock.ts'
1
+ export { deployHooks, type DeployHooksResult, } from './deploy.ts'
2
+ export { doctorDeployment, type DoctorResult } from './doctor.ts'
3
+ export { formatHookLine, listHooks, } from './list.ts'
4
+
5
5
  export {
6
- DEFAULT_PROFILE_PATH,
7
- DEFAULT_PROFILE_SCHEMA_PATH,
8
- type HookDeployProfile,
9
- HOOK_WIRE_FORMATS,
10
- type HookSurface,
11
- type HookWireFormat,
6
+
7
+
8
+
9
+
10
+
11
+
12
12
  loadProfile,
13
- type ProfileIssue,
14
- validateProfileDocument,
13
+
14
+
15
15
  } from './profile.ts'
16
- export { renderCursorEntries, renderJsonHooksGroups, renderOpencodeSlots } from './render.ts'
17
- export { DEFAULT_HOOKS_SOURCE_PATH, flattenSourceHooks, hookLabel, loadHooksSource, type CanonicalHooksDoc } from './source.ts'
16
+
17
+
@@ -44,14 +44,13 @@
44
44
  * position; adl's slot is restored separately, right there — never
45
45
  * deleted, never duplicated.
46
46
  *
47
- * A lock recording no hashes at all (`ownedEntries` absent — every repo
48
- * enrolled before this fix; closes (a)) falls back, for exactly this one
49
- * transitional deploy, to command-anywhere matching against the lock's OLD
50
- * `ownedCommands` — the only signal that data has — via the SAME
51
- * `legacyOwnedCommands` channel the pre-agent-hooks engine's own takeover
52
- * already used (both are "we have no better proof than an exact command
53
- * string" signals). This run then persists real content hashes
54
- * (`ownedEntries`), so every later deploy uses the full contract.
47
+ * The `legacyOwnedCommands` channel ("command text is the only proof we
48
+ * have") is fed ONLY by the pre-agent-hooks engine's own hash-verified
49
+ * takeover (legacy-lock.ts). It used to ALSO carry a one-deploy transitional
50
+ * fallback for a lock with no hashes at all (`ownedEntries` absent — every
51
+ * repo enrolled before this fix; closed (a)); that transition is over
52
+ * (Tarun, 2026-10-01): lock.ts's `readLock` now refuses such an entry
53
+ * outright, so every deploy here uses the full content-addressed contract.
55
54
  *
56
55
  * THIRD independent review (2026-09-30) found the fallback ITSELF still
57
56
  * leaked through raw array position, in two ways:
@@ -61,13 +61,13 @@ export function stableStringify(value: unknown): string {
61
61
  /** Content hash of a JSON value, exactly as the legacy engine recorded it. */
62
62
  export const legacyValueHash = (value: unknown): string => sha256Hex(stableStringify(value))
63
63
 
64
- export interface LegacyJsonMergeEntry {
64
+ interface LegacyJsonMergeEntry {
65
65
  readonly type: string
66
66
  readonly path: readonly (string | number)[]
67
67
  readonly sha256: string
68
68
  }
69
69
 
70
- export interface LegacyMergedRecord {
70
+ interface LegacyMergedRecord {
71
71
  readonly entries?: readonly LegacyJsonMergeEntry[]
72
72
  }
73
73
 
@@ -10,7 +10,7 @@ import { type HookLockEntry, readLock } from './lock.ts'
10
10
  import { type HookDeployProfile, type HookSurface, loadProfile } from './profile.ts'
11
11
  import { flattenSourceHooks, hookLabel, loadHooksSource, type CanonicalHooksDoc } from './source.ts'
12
12
 
13
- export type HookOwner = 'adl' | 'user' | 'conflict' | '-'
13
+ type HookOwner = 'adl' | 'user' | 'conflict' | '-'
14
14
 
15
15
  export interface HookListingEntry {
16
16
  readonly name: string
@@ -7,8 +7,12 @@
7
7
  * read it to report ownership.
8
8
  *
9
9
  * For a json-hooks surface (claude-settings / codex-hooks / cursor-hooks-v1),
10
- * "owned" is recorded per surface event name as the exact rendered command
11
- * strings (already carrying --host=<surface>) this deploy wrote there. For
10
+ * "owned" is recorded per surface event name as content-addressed hook
11
+ * entries (`ownedEntries`: hash + command + matcher), alongside the exact
12
+ * rendered command strings (`ownedCommands`, already carrying
13
+ * --host=<surface>; informational, read by list.ts). `readLock` refuses an
14
+ * entry without `ownedEntries` (the older `ownedCommands`-only shape is no
15
+ * longer migrated — Tarun, 2026-10-01). For
12
16
  * the opencode-plugin surface, the whole file is wholly adl-owned (H3) —
13
17
  * `owned: true` records that fact rather than a per-command breakdown.
14
18
  */
@@ -29,7 +33,7 @@ export const LOCK_RELATIVE_PATH = '.agents/agent-hooks.lock.json'
29
33
  * never by array position/index, which the second independent review
30
34
  * already ruled unreliable.
31
35
  */
32
- export interface OwnedHookEntry {
36
+ interface OwnedHookEntry {
33
37
  readonly hash: string
34
38
  readonly command: string
35
39
  readonly matcher?: string
@@ -37,7 +41,7 @@ export interface OwnedHookEntry {
37
41
 
38
42
  export interface JsonHooksLockEntry {
39
43
  readonly format: 'claude-settings' | 'codex-hooks' | 'cursor-hooks-v1'
40
- /** Surface event name -> the exact command strings (with --host) this deploy wrote into that event's array — informational only (list.ts); ownership itself is `ownedEntries`, below. */
44
+ /** Surface event name -> the exact command strings (with --host) this deploy wrote into that event's array — informational only (list.ts reads it to label what is adl's); ownership itself is `ownedEntries`, below. */
41
45
  readonly ownedCommands: Readonly<Record<string, readonly string[]>>
42
46
  /**
43
47
  * Surface event name -> this deploy's own written hooks, content-
@@ -45,16 +49,14 @@ export interface JsonHooksLockEntry {
45
49
  * pure array-index tracking, broke the moment a user inserted or
46
50
  * removed an entry before adl's own block, and could not express
47
51
  * "split a group" when a user hook was appended inside one — see
48
- * json-merge.ts's header for the corrected rule). Absent on a lock
49
- * written before EITHER ownership fix existed (every repo enrolled
50
- * before this one) — every reader treats that as "derive ownership
51
- * once from `ownedCommands` by exact command match, then persist real
52
- * entries here," never as malformed.
52
+ * json-merge.ts's header for the corrected rule). Required: `readLock`
53
+ * refuses an entry without it (Tarun, 2026-10-01: the transitional
54
+ * rewrite of the older `ownedCommands`-only shape is gone).
53
55
  */
54
- readonly ownedEntries?: Readonly<Record<string, readonly OwnedHookEntry[]>>
56
+ readonly ownedEntries: Readonly<Record<string, readonly OwnedHookEntry[]>>
55
57
  }
56
58
 
57
- export interface OpencodePluginLockEntry {
59
+ interface OpencodePluginLockEntry {
58
60
  readonly format: 'opencode-plugin'
59
61
  readonly owned: true
60
62
  }
@@ -86,7 +88,24 @@ export function readLock(targetRepo: string): HookLock {
86
88
  if (typeof record !== 'object' || record === null || record.version !== 1 || typeof record.entries !== 'object' || record.entries === null) {
87
89
  throw new Error(`agent-hooks lock has an unrecognized shape: ${path}`)
88
90
  }
89
- return { version: 1, entries: record.entries as Record<string, HookLockEntry> }
91
+ const entries = record.entries as Record<string, HookLockEntry>
92
+ // Tarun, 2026-10-01: the legacy (`ownedCommands` without `ownedEntries`) ->
93
+ // content-addressed migration is over. Reading such an entry as "owns
94
+ // nothing" would duplicate every adl hook already in the file, and
95
+ // guessing ownership from command text is the very thing content-
96
+ // addressing replaced — so refuse, loudly, and say how to recover.
97
+ for (const [file, entry] of Object.entries(entries)) {
98
+ if (typeof entry !== 'object' || entry === null || entry.format === 'opencode-plugin') continue
99
+ const ownedEntries: unknown = (entry as { ownedEntries?: unknown }).ownedEntries
100
+ if (typeof ownedEntries !== 'object' || ownedEntries === null || Array.isArray(ownedEntries)) {
101
+ throw new Error(
102
+ `agent-hooks lock entry for ${file} has no usable \`ownedEntries\` (the older \`ownedCommands\`-only shape is no longer migrated): ${path}. ` +
103
+ `Recover by removing the adl-written hook commands listed under that entry's \`ownedCommands\` from ${file}, deleting that entry from the lock (or deleting the lock file), ` +
104
+ `then running \`adl hooks deploy --repo ${targetRepo}\` to re-enrol.`,
105
+ )
106
+ }
107
+ }
108
+ return { version: 1, entries }
90
109
  }
91
110
 
92
111
  /** Skips the write entirely when the serialized content is already byte-identical (independent review, 2026-09-29, finding 8: a genuine no-op run must not touch the lock file's mtime either). */
@@ -16,11 +16,10 @@ import Ajv, { type ErrorObject, type ValidateFunction } from 'ajv'
16
16
  import { readFileSync } from 'node:fs'
17
17
  import { fileURLToPath } from 'node:url'
18
18
 
19
- export type HookWireFormat = 'claude-settings' | 'codex-hooks' | 'cursor-hooks-v1' | 'opencode-plugin'
20
- export const HOOK_WIRE_FORMATS: readonly HookWireFormat[] = ['claude-settings', 'codex-hooks', 'cursor-hooks-v1', 'opencode-plugin']
19
+ type HookWireFormat = 'claude-settings' | 'codex-hooks' | 'cursor-hooks-v1' | 'opencode-plugin'
21
20
 
22
- export type UnmappedMatcherPolicy = 'keep' | 'drop'
23
- export type TimeoutUnit = 's' | 'ms'
21
+ type UnmappedMatcherPolicy = 'keep' | 'drop'
22
+ type TimeoutUnit = 's' | 'ms'
24
23
 
25
24
  export interface HookSurface {
26
25
  readonly name: string
@@ -23,7 +23,7 @@ export interface CanonicalHookGroup {
23
23
 
24
24
  export type CanonicalHooksDoc = ReadonlyMap<string, readonly CanonicalHookGroup[]>
25
25
 
26
- export const DEFAULT_HOOKS_SOURCE_PATH = fileURLToPath(new URL('../../assets/hooks.json', import.meta.url))
26
+ const DEFAULT_HOOKS_SOURCE_PATH = fileURLToPath(new URL('../../assets/hooks.json', import.meta.url))
27
27
 
28
28
  function isHookCommand(value: unknown): value is CanonicalHookCommand {
29
29
  if (typeof value !== 'object' || value === null) return false
@@ -10,8 +10,9 @@
10
10
  * `adl-config.toml` is shared with other tools at the same root: adl hook
11
11
  * owns `[hooks]`, `[rules]`, and `[repo]`; `adl-repo-controls` owns
12
12
  * `[controls]`; `adl-extensions` owns `[extensions]` (and, before its
13
- * HARDCUT, `[skills]`). `[controls]` and `[skills]` are recognized root tables
14
- * this module accepts and never reads into.
13
+ * HARDCUT, `[skills]`). `[azdo]` is reserved for shared Azure DevOps
14
+ * configuration. `[controls]`, `[skills]`, and `[azdo]` are recognized root
15
+ * tables this module accepts and never reads into.
15
16
  *
16
17
  * `[extensions]` is the one exception, and a deliberate one: its sub-table
17
18
  * KEYS are decoded into `AdlRepoConfig.extensions`. Since adl-extensions
@@ -27,13 +28,6 @@
27
28
  * # (pre-tool-use, user-prompt-submit, briefing,
28
29
  * # crg) for this repo: exit 0, empty stdout/stderr.
29
30
  * skills_dir = ".agents/skills" # optional; see src/hooks/user-prompt-submit
30
- * lean_ctx_dir = ".agents/lean-ctx" # optional; repo-relative root for
31
- * # lean-ctx's own config/data/state/cache dirs
32
- * # (see src/lean-ctx/env.ts). A throwaway repo
33
- * # — a binary test fixture, say — sets this so
34
- * # lean-ctx's state, and any daemon it starts
35
- * # off that state, lands somewhere disposable
36
- * # instead of the default.
37
31
  *
38
32
  * [rules]
39
33
  * default = "on" # "on" | "off"; baseline for rules with no
@@ -69,7 +63,7 @@
69
63
 
70
64
  import { MARKER } from './root.ts'
71
65
 
72
- export interface RuleSection {
66
+ interface RuleSection {
73
67
  readonly enabled: boolean
74
68
  }
75
69
 
@@ -79,11 +73,9 @@ export interface RulesConfig {
79
73
  readonly byId: Readonly<Record<string, RuleSection>>
80
74
  }
81
75
 
82
- export interface HooksConfig {
76
+ interface HooksConfig {
83
77
  readonly enabled: boolean
84
78
  readonly skillsDir: string | undefined
85
- /** Repo-relative root for lean-ctx's config/data/state/cache; see `../lean-ctx/env.ts`. */
86
- readonly leanCtxDir: string | undefined
87
79
  }
88
80
 
89
81
  /**
@@ -185,7 +177,7 @@ const DEFAULT_AGENT: AgentSection = {
185
177
  }
186
178
 
187
179
  const DEFAULT_CONFIG: AdlRepoConfig = {
188
- hooks: { enabled: true, skillsDir: undefined, leanCtxDir: undefined },
180
+ hooks: { enabled: true, skillsDir: undefined },
189
181
  rules: { default: 'on', unsafeAllowUncertain: false, byId: {} },
190
182
  repo: DEFAULT_REPO,
191
183
  agent: DEFAULT_AGENT,
@@ -222,13 +214,15 @@ function rejectUnknownKeys(
222
214
  * Top-level keys `decodeConfig` recognizes. `version` is accepted (and
223
215
  * ignored) only so the marker file's own minimal `version = 1\n` convention
224
216
  * stays valid — this package has no schema migrations to gate on it.
225
- * controls/skills: see module header for ownership.
217
+ * controls/skills/azdo: see module header for ownership.
226
218
  */
227
219
  /**
228
220
  * Root tables this module accepts. It owns `version`/`hooks`/`rules`/`repo`
229
221
  * and never reads the rest — they belong to the other tools sharing this file:
230
- * `controls` to adl-repo-controls, and `extensions` (formerly `skills`) to
231
- * adl-extensions.
222
+ * `controls` to adl-repo-controls, `extensions` (formerly `skills`) to
223
+ * adl-extensions, `azdo` to shared Azure DevOps configuration, and `dispatch`
224
+ * to adl-dispatcher (the integration-base ref + per-checkout selector the
225
+ * dispatcher reads; this package neither reads nor validates its schema).
232
226
  *
233
227
  * `skills` is retained alongside `extensions` on purpose. adl-extensions
234
228
  * HARDCUT to `[extensions]` because an extension owns its skills rather than
@@ -237,7 +231,7 @@ function rejectUnknownKeys(
237
231
  * here would fail exactly those repos, the ones nobody has touched yet.
238
232
  */
239
233
  const KNOWN_ROOT_KEYS: ReadonlySet<string> = new Set([
240
- 'version', 'hooks', 'rules', 'repo', 'agent', 'controls', 'skills', 'extensions',
234
+ 'version', 'hooks', 'rules', 'repo', 'agent', 'controls', 'skills', 'extensions', 'azdo', 'dispatch',
241
235
  ])
242
236
 
243
237
  /**
@@ -314,17 +308,11 @@ function decodeHooks(value: unknown): { ok: true; value: HooksConfig } | { ok: f
314
308
  return { ok: false, issue: { pointer: '/hooks/skills_dir', message: 'expected a string' } }
315
309
  }
316
310
 
317
- const leanCtxDirRaw = value.lean_ctx_dir
318
- if (leanCtxDirRaw !== undefined && typeof leanCtxDirRaw !== 'string') {
319
- return { ok: false, issue: { pointer: '/hooks/lean_ctx_dir', message: 'expected a string' } }
320
- }
321
-
322
311
  return {
323
312
  ok: true,
324
313
  value: {
325
314
  enabled: enabledRaw ?? true,
326
315
  skillsDir: skillsDirRaw,
327
- leanCtxDir: leanCtxDirRaw,
328
316
  },
329
317
  }
330
318
  }
@@ -28,7 +28,7 @@ import { dirname, join } from 'node:path'
28
28
  import { statSync } from 'node:fs'
29
29
 
30
30
  /** Guard against a symlink loop or a pathological mount turning the walk into a hang. */
31
- export const MAX_WALK_DEPTH = 128
31
+ const MAX_WALK_DEPTH = 128
32
32
 
33
33
  /** The repo marker + settings file (docs/architecture/adl-config.md). Hard cut (Tarun, 2026-09-27): no fallback read of the old `adl-config.toml` name. */
34
34
  export const MARKER = 'adl-config.toml'
@@ -40,7 +40,7 @@ export interface RootIO {
40
40
  readonly cwd: () => string
41
41
  }
42
42
 
43
- export interface GitRootResult {
43
+ interface GitRootResult {
44
44
  readonly root: string | null
45
45
  readonly searched: readonly string[]
46
46
  }
@@ -50,7 +50,7 @@ export interface GitRootResult {
50
50
  * Stops at the first one found, at the filesystem root, or after
51
51
  * `MAX_WALK_DEPTH` levels — whichever comes first.
52
52
  */
53
- export function findGitRoot(io: RootIO, startDir: string): GitRootResult {
53
+ function findGitRoot(io: RootIO, startDir: string): GitRootResult {
54
54
  const searched: string[] = []
55
55
  let current = startDir
56
56
 
@@ -13,9 +13,9 @@
13
13
  */
14
14
 
15
15
  import type { HookInvocation, HookResult } from '../contract.ts'
16
- import { bunRunner, createBriefingHandler } from './index.ts'
16
+ import { createBriefingHandler } from './index.ts'
17
17
 
18
- const briefingHandler = createBriefingHandler({ run: bunRunner })
18
+ const briefingHandler = createBriefingHandler()
19
19
 
20
20
  export async function handleBriefing(inv: HookInvocation): Promise<HookResult> {
21
21
  return briefingHandler(inv)