@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
@@ -49,12 +49,12 @@ export function toolNameEndingWithKnownSuffix(tool: string, knownSuffixes: Reado
49
49
  * exactly on `<tool>`.
50
50
  *
51
51
  * Shared by every rule that gates an Azure DevOps MCP tool by name
52
- * (adl-session-required.ts, adl-pr-role.ts, adl-pr-complete-pending.ts,
52
+ * (adl-run-required.ts, adl-pr-role.ts, adl-pr-complete-pending.ts,
53
53
  * adl-workitem-role.ts, adl-build-run-denied.ts) so the parsing cannot drift
54
54
  * between them.
55
55
  *
56
- * WIDENED 2026-09-28 (STATUS.md 12p, W2 build item
57
- * 4): OpenCode's and Kimi's own MCP tool-call naming has never actually been
56
+ * Prefix-less fallback (added 2026-09-28 with the one-agent-identity
57
+ * standard): OpenCode's and Kimi's own MCP tool-call naming has never actually been
58
58
  * observed in production (`.adl/logs/hooks.log` shows only `mcp__`-prefixed
59
59
  * calls, from Claude/Codex/Cursor) — they MAY call an azdo tool with no
60
60
  * `mcp__` prefix at all, spelled `<server>_<tool>` / `<server>.<tool>` /
@@ -39,7 +39,7 @@ export function detailString(finding: Finding, key: string): string {
39
39
  * that there is no sanctioned workaround, name the recovery commands that
40
40
  * ARE allowed, and otherwise send the agent back to the user.
41
41
  */
42
- export const GIT_NO_WORKAROUND_GUIDANCE =
42
+ const GIT_NO_WORKAROUND_GUIDANCE =
43
43
  'Do NOT work around this block: no git plumbing (update-ref, symbolic-ref, read-tree, update-index, ' +
44
44
  'reflog, replace, prune) and no editing, moving, copying over, or deleting anything under .git. If you ' +
45
45
  'are stuck in an in-progress rebase/merge/cherry-pick/revert/am and a recovery command is what is ' +
@@ -18,7 +18,7 @@
18
18
  * description, no completion fields), are both untouched by row 9.
19
19
  */
20
20
 
21
- export interface PrCreateOrUpdateInput {
21
+ interface PrCreateOrUpdateInput {
22
22
  readonly action?: unknown
23
23
  readonly autoComplete?: unknown
24
24
  readonly mergeStrategy?: unknown
@@ -6,14 +6,13 @@
6
6
  * classification time (shell/invocation.ts's `walkToolCommand`); this rule
7
7
  * only ever sees the denied subset.
8
8
  *
9
- * WIDENED 2026-09-28 (STATUS.md 12p, W3 build item
10
- * 5): `az account get-access-token` and `az rest` targeting Azure DevOps are
9
+ * `az account get-access-token` and `az rest` targeting Azure DevOps are
11
10
  * NOT in `azureDevopsSubcommands` (`../shell/invocation.ts`), so they fall
12
11
  * through to the generic `'command'` kind (name `az`) rather than the
13
- * `'azure-devops'` kind this rule used to match exclusively — that let an
14
- * agent mint a bearer token from the HUMAN's own `az login` session and call
15
- * the Azure DevOps REST API directly, entirely outside the agent-identity
16
- * standard. Both are now denied here too, steering at the same MCP server /
12
+ * `'azure-devops'` kind — without a dedicated check an agent could mint a
13
+ * bearer token from the HUMAN's own `az login` session and call the Azure
14
+ * DevOps REST API directly, entirely outside the agent-identity standard.
15
+ * Both are denied here too, steering at the same MCP server /
17
16
  * `adl id token` path. `az account show` and every other `az account`
18
17
  * subcommand, and `az rest` against a non-Azure-DevOps host, are untouched.
19
18
  */
@@ -32,8 +31,8 @@ const AZ_NAMES: ReadonlySet<string> = new Set(['az', 'az.exe'])
32
31
  /**
33
32
  * Interpreter-ADO risk (independent review, 2026-09-29): python
34
33
  * requests/urllib, node fetch, ruby net/http, and perl LWP one-liners hitting
35
- * Azure DevOps directly are the SAME structural problem R6 closed for
36
- * curl/wget/httpie/xh — none of them can carry the resolved agent identity,
34
+ * Azure DevOps directly are the SAME structural problem as curl/wget/httpie/xh
35
+ * (denied outright in `match` below) — none of them can carry the resolved agent identity,
37
36
  * and any one can read `~/.netrc` or an ambient token exactly like curl's
38
37
  * `-n`/`--netrc*` does. `python`/`python3`/`ruby`/`perl`/`node`/`nodejs` (and
39
38
  * the Windows `.exe` spellings) are `inv.kind === 'command'` (unclassified by
@@ -41,18 +40,17 @@ const AZ_NAMES: ReadonlySet<string> = new Set(['az', 'az.exe'])
41
40
  * already sees them, it just never inspected their text for an Azure DevOps
42
41
  * host.
43
42
  *
44
- * P1 (second independent review, 2026-09-29): the FIRST version of this
45
- * check scanned `ctx.command` (the whole raw command line) for the ADO
46
- * host substring — matching it in ARGV too, not only inline code, which
47
- * wrongly denied `python3 -m pip install -i https://pkgs.dev.azure.com/...`
43
+ * The check deliberately does NOT scan `ctx.command` (the whole raw command line) for the ADO
44
+ * host substring: matching it in ARGV too, not only inline code, would
45
+ * wrongly deny `python3 -m pip install -i https://pkgs.dev.azure.com/...`
48
46
  * (an Azure Artifacts feed) and `node scripts/x.js --remote
49
47
  * https://dev.azure.com/...` (a flag on a script FILE run, not inline
50
- * code at all). Narrowed to `interpreterInlineCode`'s own `-c`/`-e`/
48
+ * code at all). It reads `interpreterInlineCode`'s own `-c`/`-e`/
51
49
  * `--eval[=]` argument value ONLY — coarse within that scope (a literal
52
50
  * `dev.azure.com`/`visualstudio.com` substring in the INLINE code is
53
51
  * enough, no attempt to verify a real HTTP call is actually made, matching
54
- * R6's own "curl to the URL is enough" coarseness), but no longer coarse
55
- * about WHERE it looks. `pkgs.dev.azure.com` (Azure Artifacts) stays IN
52
+ * the HTTP-client deny's "curl to the URL is enough" coarseness), but not
53
+ * coarse about WHERE it looks. `pkgs.dev.azure.com` (Azure Artifacts) stays IN
56
54
  * SCOPE when it DOES appear in inline code — `isAdoUrl`'s existing
57
55
  * `dev.azure.com` substring check already matches it.
58
56
  */
@@ -60,7 +58,7 @@ const AZ_NAMES: ReadonlySet<string> = new Set(['az', 'az.exe'])
60
58
  * The `-c`/`-e`/`--eval[=]` argument value for an interpreter invocation, or
61
59
  * null when the piece runs a script FILE or a module (`-m pip ...`) — argv
62
60
  * a script or module sees (a pip index URL, a `--remote` flag) is NOT this
63
- * rule's to inspect (P1, second independent review, 2026-09-29): only the
61
+ * rule's to inspect: only the
64
62
  * interpreter's own INLINE code can reach a host directly through that
65
63
  * interpreter's HTTP client; a script file's own argv is opaque to this
66
64
  * hook and denying on a mere URL-shaped argument would deny an ordinary
@@ -73,7 +71,7 @@ const AZ_NAMES: ReadonlySet<string> = new Set(['az', 'az.exe'])
73
71
  */
74
72
  /**
75
73
  * `name`-specific inline-code shapes beyond the common `-c`/`-e`/`--eval[=]`
76
- * (P2, independent review, 2026-09-29): php's own inline-eval flag is `-r`
74
+ * php's own inline-eval flag is `-r`
77
75
  * (not `-e`), and Deno's is a POSITIONAL argument after its `eval`
78
76
  * subcommand, no flag at all — neither fits the shared scan below.
79
77
  */
@@ -113,7 +111,6 @@ const INTERPRETER_NAMES: ReadonlySet<string> = new Set([
113
111
  'node.exe',
114
112
  'nodejs',
115
113
  'nodejs.exe',
116
- // P2 (independent review, 2026-09-29).
117
114
  'bun',
118
115
  'bun.exe',
119
116
  'deno',
@@ -129,13 +126,12 @@ export const toolAzureDevops: RuleSpec = {
129
126
  severity: 'deny',
130
127
  enabledByDefault: true,
131
128
  summary:
132
- 'Deny direct az devops/repos/pipelines/boards/artifacts, az account get-access-token, az rest to Azure DevOps, and curl/wget/httpie/xh to Azure DevOps under every method (R6: reads included — curl cannot carry the agent identity); steer at adl mcp serve/cli.',
129
+ 'Deny direct az devops/repos/pipelines/boards/artifacts, az account get-access-token, az rest to Azure DevOps, and curl/wget/httpie/xh to Azure DevOps under every method (reads included — curl cannot carry the agent identity); steer at adl mcp serve/cli.',
133
130
  params: noParams,
134
131
  match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
135
132
  if (inv.kind === 'command' && INTERPRETER_NAMES.has(inv.name)) {
136
133
  const code = interpreterInlineCode(inv.name, inv.args)
137
- // Third independent review (2026-09-29): "heredoc-fed interpreters"
138
- // (`python3 - <<'EOF' ... EOF`) have no -c/-e/--eval argument at all
134
+ // Heredoc-fed interpreters (`python3 - <<'EOF' ... EOF`) have no -c/-e/--eval argument at all
139
135
  // — the real code is the heredoc BODY, only visible in `ctx.command`.
140
136
  const candidates = code !== null ? [code] : heredocBodies(ctx.command ?? '')
141
137
  if (candidates.some((candidate) => isAdoUrl(candidate))) {
@@ -146,7 +142,7 @@ export const toolAzureDevops: RuleSpec = {
146
142
  return { ruleId: 'tool.azure-devops', severity: 'deny', detail: { reason: 'az-devops-family' } }
147
143
  }
148
144
  if (inv.kind === 'command' && AZ_NAMES.has(inv.name)) {
149
- // M6 (STATUS.md 12p): a global flag
145
+ // A global flag
150
146
  // (`az --output json account get-access-token`) must not hide the
151
147
  // real subcommand from this check either — same skip
152
148
  // shell/invocation.ts's own `azureDevopsSubcommands` classification
@@ -160,23 +156,18 @@ export const toolAzureDevops: RuleSpec = {
160
156
  return { ruleId: 'tool.azure-devops', severity: 'deny', detail: { reason: 'az-rest-ado' } }
161
157
  }
162
158
  }
163
- // R6 (STATUS.md 12p, re-review 2026-09-28 night,
164
- // WIDENING M10/docs/operations/agent-permissions.md row 13 — a deliberate SPEC
165
- // CHANGE, not a weakening: row 13 read "writes"; Tarun's own standard
166
- // ("reads included") requires every Azure DevOps access to go through
167
- // the resolved agent identity, and curl/wget/httpie/xh categorically
159
+ // Every curl/wget/httpie/xh call to Azure DevOps is denied, every method
160
+ // included (docs/operations/agent-permissions.md row 13). Tarun's
161
+ // standard ("reads included") requires every Azure DevOps access to go
162
+ // through the resolved agent identity, and these clients categorically
168
163
  // cannot carry one — the request authenticates with whatever the HUMAN
169
164
  // environment already supplies (`-n`/`--netrc*` reads `~/.netrc`, `-u`
170
165
  // is a literal credential on the command line, `-H Authorization`/`-K
171
166
  // <config-file>` read a header or config a human set up, a cached
172
- // credential helper, …), regardless of `ADL_AGENT_ID_AGENT`. A GET was
173
- // previously exempted here ("row 13 names writes specifically") on the
174
- // theory that a plain read is harmless; R6's point is narrower and
175
- // structural — it is not that a read is dangerous, it is that curl
176
- // cannot prove WHICH identity performed it at all, so it is denied
177
- // outright, identity or not, exactly like a write): every
178
- // curl/wget/httpie/xh call to Azure DevOps is denied now, every method
179
- // included. `adl.session-required-for-writes` already denies every
167
+ // credential helper, …), regardless of `ADL_AGENT_ID_AGENT`. The point
168
+ // is structural, not that a read is dangerous: the client cannot prove
169
+ // WHICH identity performed the call, so a GET is denied outright,
170
+ // identity or not, exactly like a write. `adl.run-required-for-writes` already denies every
180
171
  // method with NO identity at all; this is the unconditional net once an
181
172
  // identity IS present — a raw HTTP call cannot be rewritten to an exact
182
173
  // `adl` equivalent, so it is denied rather than routed, same as az CLI
@@ -198,11 +189,11 @@ export const toolAzureDevops: RuleSpec = {
198
189
  : reason === 'az-rest-ado'
199
190
  ? 'Blocked `az rest` against Azure DevOps: it authenticates as the human `az` login, not the resolved agent identity.'
200
191
  : reason === 'http-client-ado'
201
- ? // L2/M10/R6: names the actual method and binary, and steers at
192
+ ? // Names the actual method and binary, and steers at
202
193
  // the real, current entry points — `adl mcp serve` (the MCP
203
194
  // server folded into the `adl` binary) and its `adl mcp cli`
204
- // direct-CLI form — never a path that no longer exists. R6:
205
- // every method, reads included — curl/wget/httpie/xh cannot
195
+ // direct-CLI form — never a path that no longer exists.
196
+ // Every method, reads included — curl/wget/httpie/xh cannot
206
197
  // carry the agent identity at all (any auth it uses, `-n`/
207
198
  // `--netrc*`, `-u`, `-H Authorization`, `-K`, is the human's).
208
199
  `Blocked \`${detailString(finding, 'name')} ${detailString(finding, 'method')}\` to Azure DevOps: a raw HTTP call cannot be translated exactly, and it authenticates outside the agent-identity standard entirely (this client cannot carry the resolved agent identity for any method, reads included).`
@@ -235,23 +226,22 @@ export const toolAzureDevops: RuleSpec = {
235
226
  'az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798',
236
227
  'az rest --method get --url https://dev.azure.com/org/_apis/projects',
237
228
  'az rest --url https://vssps.dev.azure.com/org/_apis/profile/profiles/me',
238
- // M6 (STATUS.md 12p): a real az CLI global
229
+ // A real az CLI global
239
230
  // flag before the subcommand group must not hide it from this rule.
240
231
  'az --output json devops project list',
241
232
  'az -o table repos pr list --status active',
242
233
  'az --verbose account get-access-token',
243
234
  'az --output json rest --method get --url https://dev.azure.com/org/_apis/projects',
244
- // M10 (STATUS.md 12p, docs/operations/agent-permissions.md
245
- // row 13): curl/wget/httpie/xh WRITES to Azure DevOps, denied
235
+ // docs/operations/agent-permissions.md
236
+ // row 13: curl/wget/httpie/xh WRITES to Azure DevOps, denied
246
237
  // outright regardless of identity.
247
238
  'curl -X POST https://dev.azure.com/org/project/_apis/git/repositories',
248
239
  'curl -d "{}" https://dev.azure.com/org/project/_apis/git/repositories',
249
240
  'wget --method=POST https://dev.azure.com/org/project/_apis/git/repositories',
250
241
  'http POST https://dev.azure.com/org/project/_apis/git/repositories name=x',
251
242
  'xh PUT https://vssps.dev.azure.com/org/_apis/profile/profiles/me',
252
- // R6 (STATUS.md 12p, re-review 2026-09-28 night):
253
- // a plain GET/HEAD is now denied too — SPEC CHANGE from row 13's
254
- // "writes" wording, not a weakening; see this file's own R6 comment.
243
+ // A plain GET/HEAD is denied too (reads included, not only writes);
244
+ // see the HTTP-client comment in `match` above.
255
245
  'curl https://dev.azure.com/org/project/_apis/git/repositories',
256
246
  'curl -X GET https://dev.azure.com/org/project/_apis/git/repositories',
257
247
  'wget https://dev.azure.com/org/project/_apis/git/repositories',
@@ -274,8 +264,7 @@ export const toolAzureDevops: RuleSpec = {
274
264
  'az storage account list',
275
265
  'az rest --method get --url https://management.azure.com/subscriptions',
276
266
  `python3 -c "print('hello')"`,
277
- // P1 (second independent review, 2026-09-29): the ADO host in ARGV,
278
- // not inline code, is not this rule's to inspect.
267
+ // The ADO host in ARGV, not inline code, is not this rule's to inspect.
279
268
  'python3 -m pip install -i https://pkgs.dev.azure.com/org/_packaging/feed/pypi/simple/',
280
269
  'node scripts/x.js --remote https://dev.azure.com/org/project',
281
270
  ],
@@ -8,18 +8,33 @@
8
8
  * is caught: at the start, after a pipe, after `&&`/`||`/`;`, inside
9
9
  * `$()`/backticks, after xargs, after sudo, and via a leading path — all of
10
10
  * that classification lives in shell/invocation.ts, not here.
11
+ *
12
+ * DENY TEXT (2026-10-03, after research-2026-10-02-search-tool-usage-across-surfaces
13
+ * finding #1):
14
+ *
15
+ * - Earlier this text pointed every `find` denial at `search query "<text>"`,
16
+ * but every `find` denial that day was a path pattern (`find -name '*.md'
17
+ * -newermt '2026-10-01'`, `find ~/Documents -name 'code-review-graph*'`),
18
+ * never a content search. The right tool for path patterns is `rg --files
19
+ * -g '<glob>'`. `search` only answers when the doc-tree case
20
+ * is the question — and `find` can't tell which case it is, so we lead
21
+ * with `rg --files -g '<glob>'` (the most common case) and put `search`
22
+ * behind it as the docs/plans fallback.
23
+ * - Recommendation rows come from `./deny-allowlist.ts` so the three
24
+ * search-tool deny texts cannot drift from each other.
11
25
  */
12
26
 
13
27
  import type { Invocation } from '../shell/invocation.ts'
14
28
  import type { Finding, MessageContext, RuleSpec } from '../spec.ts'
15
29
  import { noParams } from '../spec.ts'
30
+ import { recommendationBlock } from './deny-allowlist.ts'
16
31
 
17
32
  export const toolFind: RuleSpec = {
18
33
  id: 'tool.find',
19
34
  category: 'tool',
20
35
  severity: 'deny',
21
36
  enabledByDefault: true,
22
- summary: 'Deny find unconditionally; steer at `search query "<text>"`.',
37
+ summary: 'Deny find unconditionally; steer at rg --files -g for path patterns and `search query "<text>"` only for docs/plans.',
23
38
  params: noParams,
24
39
  match(inv: Invocation): Finding | null {
25
40
  if (inv.kind !== 'find') return null
@@ -27,16 +42,23 @@ export const toolFind: RuleSpec = {
27
42
  },
28
43
  message(_finding: Finding, ctx: MessageContext) {
29
44
  return {
30
- user: 'Blocked find. It matches file PATHS/names only, never file contents, so piping it to grep filters filenames, not text - use `search query "<text>"` instead (/usr/local/bin/search; subcommands: index, prepare, query, doctor).',
45
+ user: 'Blocked find. It emits PATHS, never contents — pipe it to grep and you filter filenames. Use instead: `rg --files -g "<glob>"` for path patterns, or `search query "<text>"` only when the path is `docs/`, `plans/`, or `.scratchpad/`.',
31
46
  agent:
32
47
  'DENIED find. `find` emits PATHS, so piping it to grep (or any other text tool) filters FILENAMES, never ' +
33
- 'file contents - that produces confidently wrong answers, not merely incomplete ones. For example, ' +
48
+ 'file contents — that produces confidently wrong answers, not merely incomplete ones. For example, ' +
34
49
  "`find docs -name '*.md' | grep -iE 'kernel|ontology|metric'` matched only files whose NAME contained " +
35
50
  'those words; it missed docs/semantica-cleanup/superset-setup.md, the one document that actually ' +
36
- 'described the subject, while counting name-matches whose contents were irrelevant. ' +
37
- 'Use `search query "<text>"` instead - the machine-wide docs-search CLI shim at /usr/local/bin/search ' +
38
- '(subcommands: index, prepare, query, doctor; e.g. `search query "how do I author a metric"`), which is ' +
39
- `real content/hybrid search. Blocked command: ${ctx.snippet}`,
51
+ 'described the subject, while counting name-matches whose contents were irrelevant.\n' +
52
+ 'Match the tool to the question:\n' +
53
+ ' rg --files -g "<glob>" -g "!node_modules/**" path patterns (default)\n' +
54
+ ' search query "<text>" only when the path is docs/, plans/, or .scratchpad/ and the doc TALKS about X\n' +
55
+ ' crg search "<text>" --kind File code-graph search by name or text\n' +
56
+ 'Worked example: `search query "how do I author a metric"` (correct subcommand form).\n' +
57
+ 'The full replacement table from `./deny-allowlist.ts`:\n' +
58
+ recommendationBlock(
59
+ (row) => row.binary === 'rg' || row.binary === 'search' || row.binary === 'crg',
60
+ ) +
61
+ `Blocked command: ${ctx.snippet}`,
40
62
  }
41
63
  },
42
64
  corpus: {
@@ -77,6 +99,11 @@ export const toolFind: RuleSpec = {
77
99
  'rg -e find file.txt',
78
100
  'python3 -c "print(s.find(\'x\'))"',
79
101
  'node -e "str.find(\'x\')"',
102
+ // The replacements stay allowed.
103
+ 'rg --files -g "*.md" -g "!node_modules/**"',
104
+ 'rg --files -g "*.test.ts"',
105
+ 'crg search "term" --kind File',
106
+
80
107
  ],
81
108
  },
82
109
  }
@@ -2,13 +2,14 @@
2
2
  * `grep`, unconditionally.
3
3
  *
4
4
  * Owner decision, 2026-09-15: ban the grep family outright and steer at
5
- * `rg` / `ast-grep` / `search` / `ctx_search`. Every replacement was measured
6
- * present and already passing the allowlist before the ban was written:
5
+ * `rg` / `ast-grep` / `search` / `crg`. Every replacement is
6
+ * measured present and passing its respective allowlist:
7
7
  *
8
8
  * rg /opt/homebrew/bin/rg stdin filter AND tree search
9
9
  * fd 10.4.2 replaces find
10
10
  * ast-grep 0.45.3 structural search neither ever did
11
11
  * search /usr/local/bin/search hybrid semantic + keyword
12
+ * crg /usr/local/bin/crg code-graph: callers/callees/impact
12
13
  *
13
14
  * BLANKET, including a pure stdin filter. An earlier proposal carved out
14
15
  * `npm test 2>&1 | grep -E '…'` as "reading output, not searching code". That
@@ -26,18 +27,35 @@
26
27
  * `ls` is deliberately NOT denied. It shares `find`'s weakness — it answers
27
28
  * about names, never contents — but it is far more load-bearing for ordinary
28
29
  * work than the search tools this replaces.
30
+ *
31
+ * DENY TEXT (2026-10-03, after research-2026-10-02-search-tool-usage-across-surfaces
32
+ * finding #4):
33
+ *
34
+ * - Earlier this text claimed "rg / ast-grep / search / crg / ctx_search
35
+ * — all on PATH and already allowed". `search` and `crg` are NOT in
36
+ * lean-ctx's default allowlist — they only pass on repos whose
37
+ * `.agents/lean-ctx/config/lean-ctx/config.toml` declares them under
38
+ * `shell_allowlist_extra`. The new text is honest about that and points
39
+ * at per-repo config when relevant.
40
+ * - The recommendation rows come from `./deny-allowlist.ts` so a single
41
+ * edit to the allowed-tools table updates this text and `tool.find.ts`
42
+ * and `tool.native-search.ts` at once. Adding `--glob '!'` advice at
43
+ * the top of the block (per research §2) keeps the kimi-style
44
+ * `rg -rg -v Y1 | grep -v Y2` chains from re-emerging as a "let me
45
+ * refine my filter" behaviour.
29
46
  */
30
47
 
31
48
  import type { Invocation } from '../shell/invocation.ts'
32
49
  import type { Finding, MessageContext, RuleSpec } from '../spec.ts'
33
50
  import { noParams } from '../spec.ts'
51
+ import { recommendationBlock } from './deny-allowlist.ts'
34
52
 
35
53
  export const toolGrep: RuleSpec = {
36
54
  id: 'tool.grep',
37
55
  category: 'tool',
38
56
  severity: 'deny',
39
57
  enabledByDefault: true,
40
- summary: 'Deny the grep family; steer at ast-grep / search / crg / rg / ctx_search.',
58
+ summary: 'Deny the grep family; steer at ast-grep / search / crg / rg (per-repo allowlist).',
41
59
  params: noParams,
42
60
  match(inv: Invocation): Finding | null {
43
61
  if (inv.kind !== 'grep') return null
@@ -45,15 +63,14 @@ export const toolGrep: RuleSpec = {
45
63
  },
46
64
  message(_finding: Finding, ctx: MessageContext) {
47
65
  return {
48
- user: 'Blocked grep. Pick the tool for the question: `ast-grep` for code shapes, `search` for docs by meaning, `crg` for callers and impact, `rg` for literal text, `ctx_search` for the indexed code search.',
66
+ user: 'Blocked grep. Pick the tool for the question, in this order: `ast-grep` for code shapes, `search` for docs/plans by meaning, `crg` for code-graph, `rg` for literal text (incl. stdin).',
49
67
  agent:
50
- 'DENIED grep. Match the tool to the question - in this order, all on PATH and already allowed:\n' +
51
- ' ast-grep code STRUCTURE: shapes rather than strings (`ast-grep -p "foo($A)" -l ts`)\n' +
52
- ' search docs and plans by MEANING: hybrid semantic + keyword (`search query "<text>"`)\n' +
53
- ' crg the code GRAPH: callers, callees, impact (`crg query callers_of <fn>`, `crg impact`)\n' +
54
- ' rg LITERAL text or regex, including stdin: `npm test 2>&1 | rg "pass|fail"`\n' +
55
- ' ctx_search the indexed code search (action=symbol for an exact symbol)\n' +
56
- 'A pure output filter is no exception: `rg` reads stdin exactly as grep does. ' +
68
+ 'DENIED grep. A pure `something | grep -v <X>` is still a grep — refine the upstream command with ' +
69
+ '`--glob \'!<X>\'` or `--type-not` instead of piping. Match the tool to the question - in this order:\n' +
70
+ recommendationBlock(
71
+ (row) => row.binary !== 'ctx_glob' && row.binary !== 'ctx_read' && row.binary !== 'ctx_compose' && row.binary !== 'ctx_search',
72
+ ) +
73
+ '\nA pure output filter is no exception: ripgrep filters stdin exactly as grep does. ' +
57
74
  `Blocked command: ${ctx.snippet}`,
58
75
  }
59
76
  },
@@ -76,11 +93,15 @@ export const toolGrep: RuleSpec = {
76
93
  ],
77
94
  allow: [
78
95
  // The replacements must keep working — a ban with no escape route is a trap.
96
+ // Mirrors `ALLOWED_SEARCH_TOOLS` in `./deny-allowlist.ts`; adding a row
97
+ // there should land here too.
79
98
  'rg TODO src/',
80
99
  "npm test 2>&1 | rg 'pass|fail'",
100
+ "rg -n TODO src/ -g '!node_modules/**'",
81
101
  'fd -e ts src/',
82
102
  'ast-grep --version',
83
- 'search query "how do I author a metric"',
103
+ 'search how do I author a metric',
104
+ 'crg search TODO --kind File',
84
105
  'ls -la',
85
106
  // The word `grep` is not the command `grep`.
86
107
  'rg grep src/',
@@ -19,6 +19,20 @@
19
19
  * not hand-rolled search, and it is the tool `ctx_read` redirects through.
20
20
  * Edit/Write are untouched — this rule is about search surfaces only.
21
21
  *
22
+ * DENY TEXT (2026-10-03, after research-2026-10-02-search-tool-usage-across-surfaces
23
+ * found a 3/95 pivot rate and zero pivots to `search` / `crg`):
24
+ *
25
+ * - Earlier this text recommended `ctx_search`/`ctx_compose`/`ctx_callgraph`
26
+ * and `rg / ast-grep` only. The model took the lean-ctx MCP path (3/3
27
+ * pivots went there) and never reached for `search` (the enoted-search
28
+ * binary that IS the right tool for `docs/`, `plans/`, `.scratchpad/`).
29
+ * - The new text leads with the docs/plans case (the most common
30
+ * search-tool denial in the kimi data: 11 of 25 were docs/plans) and
31
+ * then names `crg search` (the graph tool) for code-graph queries,
32
+ * then falls back to the lean-ctx MCP and rg/ast-grep.
33
+ * - The recommendations come from `./deny-allowlist.ts` so a single edit
34
+ * updates every rule's deny text.
35
+ *
22
36
  * Tool names are matched exactly and case-sensitively against each host's own
23
37
  * vocabulary, the same way `../../hooks/lean-ctx/mapping.ts` matches them —
24
38
  * Claude spells them `Grep`/`Glob`, and lowercase spellings appear in the
@@ -29,6 +43,7 @@ import type { Invocation } from '../shell/invocation.ts'
29
43
  import type { Finding, MessageContext, RuleSpec } from '../spec.ts'
30
44
  import { noParams } from '../spec.ts'
31
45
  import { loadSurfacePolicy } from '../../surface-policy.ts'
46
+ import { ALLOWED_SEARCH_TOOLS, DOC_TREES, recommendationBlock } from './deny-allowlist.ts'
32
47
 
33
48
  /**
34
49
  * Search-shaped native tools. Mirrors the search half of the `redirect` route
@@ -41,25 +56,53 @@ export const toolNativeSearch: RuleSpec = {
41
56
  category: 'tool-call',
42
57
  severity: 'deny',
43
58
  enabledByDefault: true,
44
- summary: 'Deny the native Grep/Glob/Search tools; steer at ctx_search and rg.',
59
+ summary: 'Deny the native Grep/Glob/Search tools; steer at search <semantic query | keywords> (docs/plans), crg (code graph), rg, ast-grep.',
45
60
  params: noParams,
46
61
  match(inv: Invocation): Finding | null {
47
62
  if (inv.kind !== 'tool-call') return null
48
63
  if (!new Set(loadSurfacePolicy().deny.nativeTools).has(inv.tool)) return null
49
- return { ruleId: 'tool.native-search', severity: 'deny', detail: { tool: inv.tool } }
64
+ // Surface the tool input's path-ish field for the message so it can
65
+ // recommend `search` (the right tool for docs/plans/.scratchpad) over
66
+ // `crg` (the right tool for code-graph queries). Different hosts name
67
+ // this field differently — Claude uses `path`, Codex uses `path`,
68
+ // Cursor uses `target_file` / `target_directory` for Write. The
69
+ // engine normalises nothing here, so we read every common spelling.
70
+ const detail: Record<string, string> = { tool: inv.tool }
71
+ const input = inv.input as Record<string, unknown>
72
+ const candidate = input.path ?? input.directory ?? input.target_directory ?? input.target_file
73
+ if (typeof candidate === 'string') {
74
+ detail.path = candidate
75
+ }
76
+ return { ruleId: 'tool.native-search', severity: 'deny', detail }
50
77
  },
51
78
  message(finding: Finding, ctx: MessageContext) {
52
79
  const tool = typeof finding.detail.tool === 'string' ? finding.detail.tool : 'this tool'
80
+ // Path-aware recommendation. Native Grep on docs/plans/.scratchpad ->
81
+ // lead with `search`; everywhere else -> lead with `crg`.
82
+ const path = typeof finding.detail.path === 'string' ? finding.detail.path : ''
83
+ const isDoc = DOC_TREES.some((prefix) => path.startsWith(prefix))
84
+
85
+ const leadTool = isDoc ? 'search' : 'crg'
86
+ const leadExamples = ALLOWED_SEARCH_TOOLS.find((row) => row.binary === leadTool)?.examples ?? []
87
+
88
+ const leadLines = leadExamples.map((e) => ` ${e}`).join('\n')
89
+
90
+ const tail = recommendationBlock(
91
+ (row) => row.binary !== leadTool,
92
+ )
93
+
53
94
  return {
54
- user: `Blocked the native ${tool} tool. Use ctx_search (indexed), or rg / ast-grep in a shell.`,
95
+ user: isDoc
96
+ ? `Blocked the native ${tool} tool on \`${path}\` (a docs/plans/.scratchpad tree). The right answer is \`search <semantic query | keywords>\` — semantic + keyword, finds the doc that *talks* about X. \`rg\`/\`crg\` are the wrong tools here.`
97
+ : `Blocked the native ${tool} tool. Lead with \`crg search "<text>"\` for code-graph queries, fall back to \`rg\`/\`ast-grep\` for literal text, \`search <semantic query | keywords>\` only when the path is docs/plans/.scratchpad.`,
55
98
  agent:
56
99
  `DENIED the native ${tool} tool. It is routed through the lean-ctx hook but NOT converted — ` +
57
100
  'the call still runs natively — so it is a way around the shell search ban rather than an ' +
58
- 'alternative to it. Use instead:\n' +
59
- ' ctx_search indexed search; action=symbol for an exact symbol\n' +
60
- ' ctx_compose orient on a task without reading whole files\n' +
61
- ' ctx_callgraph callers/impact, which no text search answers\n' +
62
- ' rg / ast-grep in Bash when you genuinely need raw text or structural search\n' +
101
+ 'alternative to it.\n' +
102
+ `Lead with the right tool for the surface:\n` +
103
+ `${leadLines}\n` +
104
+ `Then fall back as needed:\n` +
105
+ `${tail}\n` +
63
106
  `Blocked call: ${ctx.snippet}`,
64
107
  }
65
108
  },
@@ -74,4 +117,4 @@ export const toolNativeSearch: RuleSpec = {
74
117
  'cat src/index.ts',
75
118
  ],
76
119
  },
77
- }
120
+ }
@@ -53,16 +53,14 @@ export interface RepoIndexPort {
53
53
  /** Expand Git URL rewrite rules for an explicit remote URL without contacting it. */
54
54
  resolveRemoteUrl(url: string, direction: 'fetch' | 'push'): string | null
55
55
  /**
56
- * R4 (STATUS.md 12p, re-review 2026-09-28 night): the
57
- * repo-configured value of `alias.<verb>` (`git config --get
56
+ * The repo-configured value of `alias.<verb>` (`git config --get
58
57
  * alias.<verb>`), or `null` when unset or unreadable — `adl.git-
59
58
  * credential-bypass` resolves an UNKNOWN git verb (not a built-in one this
60
59
  * repo's own classifier already recognizes) this way to see whether it is
61
- * actually a network/credential operation in disguise, the same way
62
- * `bin/git-ado` cannot: it routes on the literal argv verb, never
63
- * resolving repo config itself. Optional — a fixture that predates this
64
- * finding, or one that has no reason to exercise it, is not forced to
65
- * implement it; a rule reading it treats `undefined` (the method itself
60
+ * actually a network/credential operation in disguise, because the
61
+ * `bin/git` front controller routes on the literal argv verb and never
62
+ * resolves repo config itself. Optional — a fixture with no reason to
63
+ * exercise it is not forced to implement it; a rule reading it treats `undefined` (the method itself
66
64
  * absent) the same as `null` (present, resolved to nothing).
67
65
  */
68
66
  configuredAlias?(verb: string): string | null
@@ -53,7 +53,7 @@ import { fsTrash } from './impl/fs-trash.ts'
53
53
  import { toolCargo } from './impl/tool-cargo.ts'
54
54
  import { toolBunTest } from './impl/tool-bun-test.ts'
55
55
  import { toolAzureDevops } from './impl/tool-azure-devops.ts'
56
- import { adlSessionRequiredForWrites } from './impl/adl-session-required.ts'
56
+ import { adlRunRequiredForWrites } from './impl/adl-run-required.ts'
57
57
  import { adlHumanAzdoBypass } from './impl/adl-human-azdo-bypass.ts'
58
58
  import { adlGitCredentialBypass, adlSecurityKeychainAdo } from './impl/adl-git-credential-bypass.ts'
59
59
  import { adlGitPushBranchPolicy } from './impl/adl-git-push-policy.ts'
@@ -69,7 +69,6 @@ import { toolGrep } from './impl/tool-grep.ts'
69
69
  import { toolNativeSearch } from './impl/tool-native-search.ts'
70
70
  import { toolFrontend } from './impl/tool-frontend.ts'
71
71
  import { toolChmodHookDisarm } from './impl/tool-chmod-hook.ts'
72
- import { toolLeanCtxGlobalState } from './impl/tool-lean-ctx-global.ts'
73
72
  import { shellRemoteScriptExec } from './impl/shell-remote-script-exec.ts'
74
73
  import { parseUncertain } from './impl/parse-uncertain.ts'
75
74
  import { advisoryFinder } from './impl/advisory-finder.ts'
@@ -124,21 +123,20 @@ export const TOOL_RULES: readonly AnyRuleSpec[] = [
124
123
  toolNativeSearch,
125
124
  toolFrontend,
126
125
  toolChmodHookDisarm,
127
- toolLeanCtxGlobalState,
128
126
  shellRemoteScriptExec,
129
127
  // Before everything else identity-related: an agent setting the human
130
128
  // pass-through marker itself is the most fundamental problem (decisions
131
129
  // 1/1b/1c) — it gets its own specific message rather than being shadowed
132
130
  // by a "no identity"/"protected branch"/credential-bypass one.
133
131
  adlHumanAzdoBypass,
134
- // Before adl.session-required-for-writes: an absolute-binary/remote-
132
+ // Before adl.run-required-for-writes: an absolute-binary/remote-
135
133
  // update/submodule/credential-helper bypass is the more fundamental
136
134
  // problem (it sidesteps bin/git-ado's routing regardless of whether an
137
135
  // identity would otherwise resolve), so it gets its own specific message
138
136
  // rather than being shadowed by the generic "no identity" one.
139
137
  adlGitCredentialBypass,
140
138
  adlSecurityKeychainAdo,
141
- adlSessionRequiredForWrites,
139
+ adlRunRequiredForWrites,
142
140
  adlGitPushBranchPolicy,
143
141
  // After the push policies: it rewrites what they allow, and denies the
144
142
  // identity conflicts (inline override / sudo wrapper) those rules ignore.
@@ -172,7 +170,7 @@ export const ADVISORY_RULES: readonly AnyRuleSpec[] = [advisoryFinder, advisoryC
172
170
  * `AGENT_VAULT_*` env triad) was removed. It gated Azure DevOps access
173
171
  * unconditionally on `AGENT_VAULT_VAULT`, ran BEFORE every `adl.*` rule in
174
172
  * `BUILTIN_RULES`, and did not know about adl's own identity mechanism
175
- * (`ADL_AGENT_ID_AGENT`, `adl.session-required-for-writes`,
173
+ * (`ADL_AGENT_ID_AGENT`, `adl.run-required-for-writes`,
176
174
  * `adl.git-push-branch-policy`) — the two mechanisms conflicted and the
177
175
  * Agent-Vault one intercepted first, regressing adl's tested behaviour. Only
178
176
  * `agent.secrets-stay-unread` and `agent.tamper-protection` survive; neither