@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.10 → 0.1.26

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 (413) hide show
  1. package/bin/adl +2 -2
  2. package/bin/git +17 -18
  3. package/bin/git-ado +27 -26
  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/bun-compile-build.sh +1 -1
  9. package/bin/lib/fleet-host.sh +62 -0
  10. package/bin/lib/lean-ctx-observe-hooks.sh +9 -9
  11. package/bin/reconcile +693 -470
  12. package/bin/reconcile-host +121 -0
  13. package/bin/setup +219 -0
  14. package/bin/shell-path-policy +15 -5
  15. package/bin/sync-and-reconcile +79 -68
  16. package/bin/validate-manifest +46 -51
  17. package/package.json +2 -12
  18. package/packages/agent-hooks/README.md +14 -9
  19. package/packages/agent-hooks/assets/hooks.json +0 -20
  20. package/packages/agent-hooks/package.json +1 -2
  21. package/packages/agent-hooks/src/cli/args.ts +1 -1
  22. package/packages/agent-hooks/src/cli/doctor.ts +6 -58
  23. package/packages/agent-hooks/src/deploy/deploy.ts +12 -41
  24. package/packages/agent-hooks/src/deploy/doctor.ts +8 -11
  25. package/packages/agent-hooks/src/deploy/index.ts +14 -14
  26. package/packages/agent-hooks/src/deploy/json-merge.ts +7 -8
  27. package/packages/agent-hooks/src/deploy/legacy-lock.ts +2 -2
  28. package/packages/agent-hooks/src/deploy/list.ts +1 -1
  29. package/packages/agent-hooks/src/deploy/lock.ts +31 -12
  30. package/packages/agent-hooks/src/deploy/profile.ts +3 -4
  31. package/packages/agent-hooks/src/deploy/source.ts +1 -1
  32. package/packages/agent-hooks/src/gating/config.ts +10 -24
  33. package/packages/agent-hooks/src/gating/root.ts +3 -3
  34. package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
  35. package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
  36. package/packages/agent-hooks/src/hooks/contract.ts +17 -17
  37. package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
  38. package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
  39. package/packages/agent-hooks/src/hooks/log.ts +8 -10
  40. package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
  41. package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
  42. package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
  43. package/packages/agent-hooks/src/hosts/registry.ts +1 -1
  44. package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
  45. package/packages/agent-hooks/src/log/writer.ts +16 -2
  46. package/packages/agent-hooks/src/main.ts +7 -41
  47. package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
  48. package/packages/agent-hooks/src/rules/engine.ts +13 -17
  49. package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
  50. package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
  51. package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
  52. package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
  53. package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
  54. package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
  55. package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
  56. package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
  57. package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
  58. package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
  59. package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
  60. package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
  61. package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
  62. package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
  63. package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +159 -0
  64. package/packages/agent-hooks/src/rules/impl/fs-trash.ts +2 -2
  65. package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
  66. package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
  67. package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
  68. package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
  69. package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
  70. package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
  71. package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
  72. package/packages/agent-hooks/src/rules/impl/tool-grep.ts +34 -12
  73. package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
  74. package/packages/agent-hooks/src/rules/ports.ts +5 -7
  75. package/packages/agent-hooks/src/rules/registry.ts +4 -6
  76. package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
  77. package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
  78. package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
  79. package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
  80. package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
  81. package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
  82. package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
  83. package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
  84. package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
  85. package/packages/agent-hooks/src/rules/spec.ts +2 -2
  86. package/packages/agent-settings/README.md +287 -0
  87. package/packages/agent-settings/assets/GLOBAL-AGENTS.md +18 -18
  88. package/packages/agent-settings/assets/agents/architect.toml +2 -0
  89. package/packages/agent-settings/assets/agents/code-reviewer.toml +2 -0
  90. package/packages/agent-settings/assets/agents/executor.toml +2 -0
  91. package/packages/agent-settings/assets/agents/explore.toml +2 -0
  92. package/packages/agent-settings/assets/agents/planner.toml +2 -0
  93. package/packages/agent-settings/assets/mcp.json +0 -4
  94. package/packages/agent-settings/deploy-profile.json +139 -0
  95. package/packages/agent-settings/deploy-profile.schema.json +147 -0
  96. package/packages/agent-settings/managed/README.md +29 -30
  97. package/packages/agent-settings/managed/codex-requirements.toml +9 -9
  98. package/packages/agent-settings/package.json +20 -0
  99. package/packages/agent-settings/src/deploy/agent-render.ts +2 -2
  100. package/packages/agent-settings/src/deploy/agent-toml.ts +1 -1
  101. package/packages/agent-settings/src/deploy/agents-deploy.ts +17 -3
  102. package/packages/agent-settings/src/deploy/doctor.ts +3 -83
  103. package/packages/agent-settings/src/deploy/index.ts +6 -33
  104. package/packages/agent-settings/src/deploy/legacy-lock.ts +6 -6
  105. package/packages/agent-settings/src/deploy/list.ts +5 -19
  106. package/packages/agent-settings/src/deploy/lock.ts +8 -18
  107. package/packages/agent-settings/src/deploy/mcp-deploy.ts +10 -5
  108. package/packages/agent-settings/src/deploy/mcp-merge.ts +22 -3
  109. package/packages/agent-settings/src/deploy/mcp-source.ts +1 -1
  110. package/packages/agent-settings/src/deploy/profile.ts +11 -35
  111. package/packages/agent-settings/src/deploy/retire-lean-ctx.ts +184 -0
  112. package/packages/agent-settings/src/deploy/settings.ts +17 -22
  113. package/packages/agent-settings/src/global-surface-sweep.ts +5 -17
  114. package/packages/agent-settings/src/kimi-hooks.ts +339 -192
  115. package/packages/agent-settings/src/opencode-hooks.ts +1 -1
  116. package/packages/agent-settings/tsconfig.json +23 -0
  117. package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +120 -0
  118. package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +276 -0
  119. package/packages/agent-skills/assets/debug-issue/SKILL.md +8 -7
  120. package/packages/agent-skills/assets/explore-codebase/SKILL.md +13 -13
  121. package/packages/agent-skills/assets/refactor-safely/SKILL.md +12 -11
  122. package/packages/agent-skills/assets/review-changes/SKILL.md +7 -7
  123. package/packages/agent-skills/assets/testing/references/e2e.md +37 -0
  124. package/packages/agent-skills/assets/testing/references/integration.md +37 -0
  125. package/packages/agent-skills/assets/testing/references/unit.md +32 -0
  126. package/packages/agent-skills/dist/deploy.d.ts +2 -0
  127. package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
  128. package/packages/agent-skills/dist/deploy.js +27 -1
  129. package/packages/agent-skills/dist/deploy.js.map +1 -1
  130. package/packages/agent-skills/dist/doctor.d.ts +0 -2
  131. package/packages/agent-skills/dist/doctor.d.ts.map +1 -1
  132. package/packages/agent-skills/dist/doctor.js +1 -1
  133. package/packages/agent-skills/dist/doctor.js.map +1 -1
  134. package/packages/agent-skills/dist/fs-utils.d.ts +0 -1
  135. package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -1
  136. package/packages/agent-skills/dist/fs-utils.js +1 -1
  137. package/packages/agent-skills/dist/fs-utils.js.map +1 -1
  138. package/packages/agent-skills/package.json +1 -1
  139. package/packages/agent-skills/src/deploy.ts +29 -1
  140. package/packages/agent-skills/src/doctor.ts +1 -1
  141. package/packages/agent-skills/src/fs-utils.ts +1 -1
  142. package/packages/azdo/README.md +10 -9
  143. package/packages/azdo/package.json +2 -5
  144. package/packages/azdo/src/azdo-pl.ts +2 -54
  145. package/packages/azdo/src/azdo-pr-review.ts +4 -4
  146. package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
  147. package/packages/azdo/src/azdo-wit.ts +41 -2
  148. package/packages/azdo/src/lib/agent-identity.ts +12 -14
  149. package/packages/azdo/src/lib/agent-token.ts +2 -2
  150. package/packages/azdo/src/lib/client.ts +0 -5
  151. package/packages/azdo/src/lib/graph-identity.ts +4 -4
  152. package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
  153. package/packages/azdo/src/workflow-rules.ts +128 -0
  154. package/packages/fleet/manifest.json +38 -33
  155. package/packages/fleet/manifest.schema.json +67 -65
  156. package/packages/fleet/src/default-agent-file.ts +3 -3
  157. package/packages/fleet/src/install-adl-package.ts +73 -15
  158. package/packages/fleet/src/install-embedding-model.ts +14 -14
  159. package/packages/fleet/src/managed-settings.ts +7 -7
  160. package/packages/fleet/src/repo-maintain.ts +439 -0
  161. package/packages/fleet/src/scratch-reap.ts +6 -6
  162. package/packages/fleet/src/vscode-settings.ts +5 -5
  163. package/packages/repo-controls/README.md +141 -43
  164. package/packages/repo-controls/assets/promote.ts +4 -4
  165. package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
  166. package/packages/repo-controls/assets/version-bump.sh +31 -84
  167. package/packages/repo-controls/bunfig.toml +6 -7
  168. package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
  169. package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
  170. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
  171. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
  172. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
  173. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
  174. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
  175. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
  176. 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
  177. 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
  178. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
  179. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
  180. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
  181. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
  182. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
  183. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
  184. 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
  185. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
  186. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
  187. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
  188. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
  189. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
  190. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
  191. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
  192. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
  193. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
  194. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
  195. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
  196. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
  197. 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
  198. 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
  199. 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
  200. 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
  201. 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
  202. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
  203. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
  204. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
  205. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
  206. 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
  207. 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
  208. 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
  209. 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
  210. 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
  211. 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
  212. 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
  213. 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
  214. 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
  215. 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
  216. 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
  217. 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
  218. 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
  219. 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
  220. 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
  221. 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
  222. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
  223. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
  224. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
  225. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
  226. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
  227. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
  228. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
  229. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
  230. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
  231. 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
  232. 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
  233. 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
  234. 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
  235. 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
  236. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
  237. 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
  238. 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
  239. 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
  240. 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
  241. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
  242. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
  243. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
  244. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
  245. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
  246. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
  247. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
  248. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
  249. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
  250. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
  251. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
  252. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
  253. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
  254. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
  255. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
  256. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
  257. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
  258. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
  259. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
  260. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
  261. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
  262. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
  263. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
  264. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
  265. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
  266. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
  267. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
  268. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
  269. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
  270. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
  271. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
  272. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
  273. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
  274. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
  275. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
  276. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
  277. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
  278. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
  279. 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
  280. 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
  281. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
  282. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
  283. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
  284. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
  285. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
  286. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
  287. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
  288. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
  289. 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
  290. 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
  291. 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
  292. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
  293. 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
  294. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
  295. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
  296. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
  297. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
  298. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
  299. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
  300. 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
  301. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
  302. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
  303. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
  304. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
  305. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
  306. 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
  307. 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
  308. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
  309. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
  310. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
  311. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
  312. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
  313. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
  314. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
  315. 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
  316. 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
  317. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
  318. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
  319. 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
  320. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
  321. 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
  322. 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
  323. 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
  324. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
  325. 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
  326. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
  327. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
  328. 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
  329. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
  330. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
  331. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
  332. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
  333. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
  334. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
  335. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +256 -0
  336. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
  337. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
  338. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +1 -1
  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 -10
  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
  411. package/packages/fleet/jobs/git-maintain/src/main.ts +0 -848
  412. package/packages/fleet/systemd/adl-azure-agent-update.service +0 -13
  413. package/packages/fleet/systemd/adl-azure-agent-update.timer +0 -10
@@ -2,7 +2,7 @@
2
2
  * `adl.pr-review-role` — docs/operations/agent-permissions.md rows 6-8 (PR comment; PR
3
3
  * vote on `main`; PR vote on `integration`), the sibling `adl-pr-role.ts`'s
4
4
  * own header named as PENDING until `packages/azdo` shipped a comment/vote
5
- * tool (C3, `pr_review`). Gates the ONE MCP tool that ships that shape,
5
+ * tool (`pr_review`). Gates the ONE MCP tool that ships that shape,
6
6
  * `pr_review({ pullRequestId, comment?, vote?, targetBranch?, repository? })`
7
7
  * — see `packages/azdo/src/azdo-pr-review.ts`.
8
8
  *
@@ -31,7 +31,7 @@
31
31
  * caller cannot route around by skipping the hook.
32
32
  *
33
33
  * Requires an identity to already be present (`ADL_AGENT_ID_AGENT`
34
- * non-blank) — with no identity at all, `adl.session-required-for-writes`
34
+ * non-blank) — with no identity at all, `adl.run-required-for-writes`
35
35
  * denies the call first (a different problem: no session, not the wrong
36
36
  * role or branch), so this rule returns null when the env var is absent or
37
37
  * blank, matching `adl-pr-role.ts`'s own convention exactly.
@@ -72,16 +72,14 @@ export const adlPrReviewRole: RuleSpec = {
72
72
  'Gate pr_review: comment for a builder or agent-reviewer (row 6); vote for agent-reviewer only, main only, fail-closed without a declared target (rows 7-8).',
73
73
  params: noParams,
74
74
  match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
75
- // M4 (STATUS.md 12p): `adl mcp cli
76
- // pr-review` dispatches to the same tool the MCP server calls.
75
+ // `adl mcp cli pr-review` dispatches to the same tool the MCP server calls.
77
76
  const call = toolCallFor(inv)
78
77
  if (call === null) return null
79
78
  if (mcpToolName(call.tool) !== 'pr_review') return null
80
79
 
81
- // R5 (STATUS.md 12p, re-review 2026-09-28 night):
82
- // grade the EFFECTIVE identity for THIS specific piece — a valid inline
80
+ // Grade the EFFECTIVE identity for THIS specific piece — a valid inline
83
81
  // `ADL_AGENT_ID_AGENT=` override on the same `adl mcp cli` invocation
84
- // still wins, exactly like M3 already does for `git push` (see
82
+ // still wins, exactly like it does for `git push` (see
85
83
  // `effectiveIdentityForMcpCli`'s own doc). A real MCP tool-call payload
86
84
  // carries no command text at all (no inline override possible), so this
87
85
  // still resolves to the plain session identity for that shape — env,
@@ -90,19 +88,18 @@ export const adlPrReviewRole: RuleSpec = {
90
88
  const resolution = resolveFromEnvOrFile(ctx.env)
91
89
  const fallback = resolution.ok ? resolution.agent : null
92
90
  const agent = effectiveIdentityForMcpCli(inv, ctx.command ?? '', fallback)
93
- if (agent === null) return null // no identity at all: adl.session-required-for-writes's job
91
+ if (agent === null) return null // no identity at all: adl.run-required-for-writes's job
94
92
 
95
93
  const input = call.input as PrReviewInput
96
94
 
97
95
  // Row 6: comment — the more fundamental restriction when present, same
98
96
  // allow-set as row 5, checked first regardless of whether a vote is ALSO
99
- // on this call. W2 build item 2 (2026-09-28): `agent` is now guaranteed
97
+ // on this call. `agent` is guaranteed
100
98
  // a VALID_AGENTS member whenever it is non-null (resolveFromEnvOrFile
101
99
  // validates it), and BUILDER_AGENTS ∪ {agent-reviewer} already IS all of
102
100
  // VALID_AGENTS for this row — so `!isAllowedToComment(agent)` can never
103
- // be true through any real resolved identity any more (same fact
104
- // adl-pr-role.ts's sibling check already lived with, one line, before
105
- // this widening). Kept as defense in depth for a future VALID_AGENTS
101
+ // be true through any real resolved identity (same fact
102
+ // adl-pr-role.ts's sibling check already lives with). Kept as defense in depth for a future VALID_AGENTS
106
103
  // member this allow-set does not name, in the same single-physical-line
107
104
  // shape adl-pr-role.ts already uses for its own now-unreachable check —
108
105
  // see rules-adl-pr-role.test.ts's "denial message is exact" describe
@@ -41,7 +41,7 @@
41
41
  * matching a guessed tool name now.
42
42
  *
43
43
  * Requires an identity to already be present (`ADL_AGENT_ID_AGENT`
44
- * non-blank) — with no identity at all, `adl.session-required-for-writes`
44
+ * non-blank) — with no identity at all, `adl.run-required-for-writes`
45
45
  * denies the call first (a different problem: no session, not the wrong
46
46
  * role), so this rule returns null when the env var is absent or blank.
47
47
  */
@@ -70,16 +70,14 @@ export const adlPrCreateUpdateRole: RuleSpec = {
70
70
  'Deny pr_create_or_update for any identity other than a builder (agent-tarun/agent-vivek) or agent-reviewer (docs/operations/agent-permissions.md row 5).',
71
71
  params: noParams,
72
72
  match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
73
- // M4 (STATUS.md 12p): `adl mcp cli
74
- // pr-create-or-update` dispatches to the same tool the MCP server calls.
73
+ // `adl mcp cli pr-create-or-update` dispatches to the same tool the MCP server calls.
75
74
  const call = toolCallFor(inv)
76
75
  if (call === null) return null
77
76
  if (mcpToolName(call.tool) !== 'pr_create_or_update') return null
78
77
 
79
- // R5 (STATUS.md 12p, re-review 2026-09-28 night):
80
- // grade the EFFECTIVE identity for THIS specific piece — a valid inline
78
+ // Grade the EFFECTIVE identity for THIS specific piece — a valid inline
81
79
  // `ADL_AGENT_ID_AGENT=` override on the same `adl mcp cli` invocation
82
- // still wins, exactly like M3 already does for `git push` (see
80
+ // still wins, exactly like it does for `git push` (see
83
81
  // `effectiveIdentityForMcpCli`'s own doc). A real MCP tool-call payload
84
82
  // carries no command text at all (no inline override possible), so this
85
83
  // still resolves to the plain session identity for that shape — env,
@@ -88,7 +86,7 @@ export const adlPrCreateUpdateRole: RuleSpec = {
88
86
  const resolution = resolveFromEnvOrFile(ctx.env)
89
87
  const fallback = resolution.ok ? resolution.agent : null
90
88
  const agent = effectiveIdentityForMcpCli(inv, ctx.command ?? '', fallback)
91
- if (agent === null) return null // no identity at all: adl.session-required-for-writes's job
89
+ if (agent === null) return null // no identity at all: adl.run-required-for-writes's job
92
90
 
93
91
  // Not a builder and not agent-reviewer: denied regardless of shape — this
94
92
  // is the more fundamental restriction, so it reports even for a call that
@@ -0,0 +1,411 @@
1
+ /**
2
+ * `adl.run-required-for-writes` — the managed baseline hook (docs/architecture/cli-design.md
3
+ * §2/§3).
4
+ *
5
+ * Widened 2026-09-28 by the one-agent-identity standard (Tarun): the rule id
6
+ * is kept stable, but this rule's job is no longer "writes only". Every Azure DevOps access
7
+ * — reads included — needs a resolvable agent identity now: the session env
8
+ * (set by the surface's managed default), the machine default-agent file
9
+ * (`adl-identity.ts`'s `resolveFromEnvOrFile`, steps 2-3 of the standard),
10
+ * or a valid inline `ADL_AGENT_ID_AGENT=<agent>` override on the command
11
+ * itself (step 1, detected via `../shell/git-identity.ts`'s
12
+ * `commandHasValidInlineIdentity` — see `checkResolvableIdentity` below). With
13
+ * NONE of those present, this rule denies every identity-bearing command
14
+ * class (git network reads/writes, the azdo MCP tools including their reads,
15
+ * `adl mcp cli`/`adl repo doctor`/`adl repo controls azdo-push`/`adl id
16
+ * token`/`adl-agent-id exec`, and curl/wget/httpie/xh to
17
+ * dev.azure.com/*.visualstudio.com under any HTTP method) with the
18
+ * standard's own message; every other command is left alone. Once an
19
+ * identity resolves, this rule gets out of the way entirely — `git-ado`/
20
+ * `adl`'s own rules, and the role rules, police what an authenticated
21
+ * run may do.
22
+ *
23
+ * Four write surfaces, each inspected in the shape the shell/tool-call
24
+ * classifier already hands every other rule:
25
+ *
26
+ * - `git push` (`../shell/invocation.ts`'s `'git'` kind). The hook cannot run
27
+ * `git remote get-url` (it decides before the child runs, statically, off
28
+ * argv alone) the way the deployed `bin/git` front controller can — so an
29
+ * explicit `https://.../dev.azure.com/...` URL anywhere in the push's
30
+ * arguments is authoritative, and otherwise the destination is UNRESOLVED
31
+ * (a bare `git push`, or `git push origin main` naming a remote this rule
32
+ * cannot look up) and fails closed: unresolved is treated exactly like
33
+ * "proven Azure DevOps", because the rule cannot prove otherwise. Only an
34
+ * explicit NON-Azure-DevOps URL is provably safe and lets a write through
35
+ * without an identity. `git-verify.ts`'s `git.no-verify` corpus already
36
+ * anticipates this: its own `allow` list deliberately never contains a bare
37
+ * `git push` or `git push -n`, see the comment there and
38
+ * `rules-corpus-executed.test.ts`'s "corrected corpus entries" check.
39
+ * - `az devops|repos|pipelines|boards|artifacts ...` (the `'azure-devops'`
40
+ * kind). `tool.azure-devops` (`./tool-azure-devops.ts`) already denies
41
+ * EVERY direct invocation of this family outright, read or write,
42
+ * identity or not, steering everything at the MCP server — and it is
43
+ * registered ahead of this rule, so in the real engine it always reports
44
+ * first. This rule's own az-CLI classification (read verbs `list`/`show`/
45
+ * `get`/`query` vs. everything else, fail-closed to "write" when neither
46
+ * matches) is therefore defense in depth for a repository that disables
47
+ * `tool.azure-devops` (`[rules."tool.azure-devops"] enabled = false`), not
48
+ * something reachable through `decide()` today — see
49
+ * `tests/unit/rules-adl-run-required.test.ts`, which exercises it via
50
+ * a direct `match()` call rather than the shared corpus (which runs
51
+ * through the real engine and would otherwise always see `tool.azure-devops`
52
+ * win first).
53
+ * - `curl`/`wget`/httpie (`http`/`https`)/`xh` (the generic `'command'` kind)
54
+ * with a non-GET method against a `dev.azure.com` URL. curl's method is
55
+ * explicit (`-X`/`--request`) or implied by a data flag (`-d`/`--data*`,
56
+ * `-F`/`--form`, `--json`); wget's by `--method=`/`--post-data`/
57
+ * `--post-file`; httpie/xh's by an explicit leading method argument or a
58
+ * request-item/`--form`/`--raw` implying a body (httpie's own semantics:
59
+ * a request with data defaults to POST, one without defaults to GET).
60
+ * - An Azure DevOps MCP write tool (the `'tool-call'` kind), named
61
+ * `mcp__<prefix>__<tool>` where `<tool>` is one of the four mutating
62
+ * tools `packages/azdo/src/mcp-server.ts` actually registers:
63
+ * `pr_create_or_update`, `pr_review`, `build_run`, `workitem_create_or_update`. The
64
+ * match is on the TOOL NAME alone, not the server prefix — the package is
65
+ * `azdo`, P4 folds the server under `adl`, and Claude Code's plugin-scoped
66
+ * form (`mcp__plugin_<plugin>_<server>__<tool>`) adds a third spelling —
67
+ * so `mcp__azdo__...`, `mcp__adl__...`, `mcp__azure-devops-mcp__...` and
68
+ * `mcp__plugin_adl_azdo__...` are all matched the same way. Its three read
69
+ * tools (`pr_list_or_get`, `build_list_or_get`, `workitem_list_or_get`)
70
+ * are left alone under every one of those prefixes too.
71
+ */
72
+
73
+ import type { Invocation } from '../shell/invocation.ts'
74
+ import type { Token } from '../shell/token.ts'
75
+ import { dynamicToken, tokenValue } from '../shell/token.ts'
76
+ import { commandHasValidInlineIdentity, isNetworkGitInvocation } from '../shell/git-identity.ts'
77
+ import type { EnvPort } from '../ports.ts'
78
+ import type { Finding, MessageContext, RuleContext, RuleSpec } from '../spec.ts'
79
+ import { noParams } from '../spec.ts'
80
+ import {
81
+ ADL_AGENT_ID_BINARY_NAMES,
82
+ ADL_AGENT_ID_COMMAND_SHAPES,
83
+ ADL_BINARY_NAMES,
84
+ ADL_IDENTITY_COMMAND_SHAPES,
85
+ classifyGitPushDestination,
86
+ containsIdentityBearingToken,
87
+ HTTP_CLIENT_BINARY_NAMES,
88
+ httpClientMethod,
89
+ isAdoUrl,
90
+ isHelpOnlyInvocation,
91
+ matchesIdentityShape,
92
+ skipLeadingDashFlags,
93
+ } from './git-helpers.ts'
94
+ import { NO_AGENT_IDENTITY_MESSAGE, resolveFromEnvOrFile } from './adl-identity.ts'
95
+ import { detailString } from './messages.ts'
96
+ import { mcpToolName } from './mcp-tool.ts'
97
+
98
+ const RULE_ID = 'adl.run-required-for-writes'
99
+ const ENV_VAR = 'ADL_AGENT_ID_AGENT'
100
+
101
+ /**
102
+ * Whether an identity is
103
+ * resolvable for `command`, and if not, the EXACT message to show — the
104
+ * one standard `NO_AGENT_IDENTITY_MESSAGE` when nothing is configured at
105
+ * all, or the SPECIFIC named error when something IS configured but is
106
+ * invalid (an unrecognized `ADL_AGENT_ID_AGENT` value, or a default-agent
107
+ * file naming an agent outside `VALID_AGENTS`) — `resolveFromEnvOrFile`'s
108
+ * own `UnresolvedIdentity.message` already carries exactly the right text
109
+ * for either case (see `adl-identity.ts`'s `resolveFromEnvOrFile`: it is
110
+ * `NO_AGENT_IDENTITY_MESSAGE` verbatim for `reason: 'none'`, and the named
111
+ * `invalidAgentError` text for `reason: 'invalid'`), so this reads that
112
+ * message through rather than reporting the SAME generic "run the fleet
113
+ * reconcile" text regardless of which of the two actually happened — an
114
+ * invalid identity is a materially different, more actionable diagnosis
115
+ * than none configured at all, and reporting the generic text for both
116
+ * hid that distinction from the agent.
117
+ *
118
+ * A valid inline `ADL_AGENT_ID_AGENT=<agent>` override anywhere on the
119
+ * command line (step 1 of the standard — coarse, whole-command; see
120
+ * `commandHasValidInlineIdentity`'s own doc for what that trades off)
121
+ * resolves too, without needing the session env / machine default-agent
122
+ * file (steps 2-3) at all.
123
+ */
124
+ type IdentityCheck = { readonly resolvable: true } | { readonly resolvable: false; readonly message: string }
125
+
126
+ function checkResolvableIdentity(command: string, env: EnvPort): IdentityCheck {
127
+ if (commandHasValidInlineIdentity(command)) return { resolvable: true }
128
+ const resolution = resolveFromEnvOrFile(env)
129
+ return resolution.ok ? { resolvable: true } : { resolvable: false, message: resolution.message }
130
+ }
131
+
132
+ const classifyPush = classifyGitPushDestination
133
+
134
+ /**
135
+ * az CLI verbs that only read. Fail-closed by design: anything NOT
136
+ * recognized here (including a verb this list simply does not know about
137
+ * yet) is treated as a write, never the reverse. Recognized against the
138
+ * FULL args after `az` (the subcommand group included, e.g. `repos pr
139
+ * list`) — a flag's VALUE (`--status active`) could in principle collide
140
+ * with a verb spelling, an accepted heuristic risk given `tool.azure-devops`
141
+ * denies the whole family outright regardless (see header).
142
+ */
143
+ const AZ_READ_VERBS: ReadonlySet<string> = new Set(['list', 'show', 'get', 'query'])
144
+
145
+ function azCommandIsWrite(args: readonly Token[]): boolean {
146
+ for (const token of args) {
147
+ const value = tokenValue(token).toLowerCase()
148
+ if (value.startsWith('-')) continue
149
+ if (AZ_READ_VERBS.has(value)) return false
150
+ }
151
+ return true
152
+ }
153
+
154
+ /**
155
+ * The name set and the per-binary method detection live in
156
+ * `git-helpers.ts`'s `HTTP_CLIENT_BINARY_NAMES`/`httpClientMethod` — shared
157
+ * with `tool-azure-devops.ts`'s WRITE-outright deny
158
+ * (docs/operations/agent-permissions.md row 13), so the two cannot classify
159
+ * the same command two different ways.
160
+ */
161
+ const HTTP_CLIENT_NAMES = HTTP_CLIENT_BINARY_NAMES
162
+
163
+ /**
164
+ * Azure DevOps MCP write tools, derived from `packages/azdo/src/mcp-server.ts`'s
165
+ * `ListToolsRequestSchema` handler (re-checked 2026-10-01) — the
166
+ * complete tool roster there is `pr_list_or_get`/`pr_create_or_update`/
167
+ * `pr_review`, `build_list_or_get`/`build_run`, `workitem_list_or_get`/
168
+ * `workitem_create_or_update`; the three not in this set are the read half.
169
+ * `pr_review` (docs/operations/agent-permissions.md rows 6-8: comment + vote) is
170
+ * in this set because `adl-pr-review-role.ts` gates it by role —
171
+ * a caller with no run identity at all must be denied here FIRST, the
172
+ * same "no session, not merely the wrong role" ordering `adl-pr-role.ts`
173
+ * documents for `pr_create_or_update`.
174
+ */
175
+ const ADO_MCP_WRITE_TOOLS: ReadonlySet<string> = new Set([
176
+ 'pr_create_or_update',
177
+ 'pr_review',
178
+ 'build_run',
179
+ 'workitem_create_or_update',
180
+ ])
181
+
182
+ /**
183
+ * The standard requires an identity for every Azure
184
+ * DevOps MCP tool call, reads included — the read half gets no
185
+ * pass just because it cannot mutate anything. `mcp-server.ts`'s complete
186
+ * roster: `pr_list_or_get`, `build_list_or_get`, `workitem_list_or_get`
187
+ * (reads) alongside the four writes above.
188
+ */
189
+ /** The leading words of the `identityBearingReason` for an Azure DevOps MCP tool call — `message()` keys the MCP-only CLI advice off it. */
190
+ const MCP_REASON_PREFIX = 'Azure DevOps MCP tool'
191
+
192
+ const ADO_MCP_ALL_TOOLS: ReadonlySet<string> = new Set([...ADO_MCP_WRITE_TOOLS, 'pr_list_or_get', 'build_list_or_get', 'workitem_list_or_get'])
193
+
194
+ /** `adl <...>` shapes that need an identity even with no HTTP client or git verb involved — see `git-helpers.ts`'s `ADL_IDENTITY_COMMAND_SHAPES`. */
195
+ const ADL_BINARY_ALL_NAMES: ReadonlySet<string> = ADL_BINARY_NAMES
196
+ const ADL_AGENT_ID_BINARY_ALL_NAMES: ReadonlySet<string> = ADL_AGENT_ID_BINARY_NAMES
197
+
198
+ /**
199
+ * Interpreter one-liners whose `-c`/`-e`/`--eval` code string names an
200
+ * identity-bearing operation — `../shell/invocation.ts`'s walker classifies
201
+ * these as a plain, unclassified `'command'` Invocation (it only re-parses
202
+ * `-c` as shell for `sh`/`bash`/`zsh`/`dash`/`ksh`/`fish`, never an
203
+ * interpreter's own code), so
204
+ * `python3 -c "import subprocess; subprocess.run(['git','push'])"` would be
205
+ * invisible to this rule without this check. Deliberately coarse
206
+ * (`containsIdentityBearingToken`, textual) — precise parsing of arbitrary
207
+ * Python/JS/Perl/Ruby/AppleScript source is not this rule's job.
208
+ */
209
+ const INTERPRETER_ONE_LINER_NAMES: ReadonlySet<string> = new Set([
210
+ 'python', 'python.exe', 'python2', 'python2.exe', 'python3', 'python3.exe',
211
+ 'node', 'node.exe', 'perl', 'perl.exe', 'ruby', 'ruby.exe', 'bun', 'bun.exe',
212
+ 'osascript', 'osascript.exe',
213
+ ])
214
+ const INTERPRETER_CODE_FLAGS: ReadonlySet<string> = new Set(['-c', '-e', '--eval'])
215
+
216
+ /** Every code string passed via `-c`/`-e`/`--eval` among `args` — the token immediately following the flag. */
217
+ function interpreterCodeStrings(args: readonly Token[]): readonly string[] {
218
+ const codes: string[] = []
219
+ for (let index = 0; index < args.length; index += 1) {
220
+ if (!INTERPRETER_CODE_FLAGS.has(tokenValue(args[index] as Token))) continue
221
+ const next = args[index + 1]
222
+ if (next !== undefined) codes.push(tokenValue(next))
223
+ }
224
+ return codes
225
+ }
226
+
227
+ /**
228
+ * Whether `inv` is a candidate this rule cares about at all, and if so, the
229
+ * "reason" text for its Finding — computed WITHOUT ever resolving an
230
+ * identity (see `match`'s own comment on resolution order for why the ordering matters). The
231
+ * four surfaces are exactly the ones documented in this file's header.
232
+ */
233
+ /**
234
+ * Exported for `../../pre-tool-use/handler.ts`'s own broader net: a
235
+ * walker-visible identity-bearing shape the narrow `adl.git-identity` rewrite scanner does not recognize (buried
236
+ * inside `if`/`!`/`for..do`/`xargs`/a heredoc or here-string/a piped-into
237
+ * shell) still needs denying when the resolved identity cannot actually
238
+ * reach THIS specific host/tool-class's child process — this rule alone
239
+ * cannot make that call (it has no host/tool-class in its `RuleContext`),
240
+ * but it IS the one place that already classifies every one of those shapes
241
+ * correctly (see this file's header), so the handler reuses this function
242
+ * rather than re-deriving the same walker-based classification a second
243
+ * time.
244
+ */
245
+ export function identityBearingReason(inv: Invocation): string | null {
246
+ if (inv.kind === 'git') {
247
+ // Wider than a plain
248
+ // `NETWORK_GIT_VERBS.has(inv.subcommand)` gate — see
249
+ // `isNetworkGitInvocation`'s own doc for the additional network-reaching
250
+ // shapes now covered (git remote show/prune/update/set-head -a, git
251
+ // maintenance run --task=prefetch, the remote-https/remote-http/
252
+ // http-fetch transport helpers, git submodule update/sync --recursive,
253
+ // git archive --remote).
254
+ if (!isNetworkGitInvocation(inv.subcommand, inv.rest.map(tokenValue))) return null
255
+ if (isHelpOnlyInvocation(inv.rest)) return null
256
+ const risk = classifyPush(inv.rest)
257
+ if (risk === 'non-ado') return null
258
+ const verbLabel = inv.subcommand === 'push' ? 'git push' : `git ${inv.subcommand}`
259
+ return risk === 'ado' ? `${verbLabel} against a dev.azure.com remote` : `${verbLabel} with an unresolved (implicit) remote destination`
260
+ }
261
+
262
+ if (inv.kind === 'azure-devops') {
263
+ // Defense in depth only — tool.azure-devops (registered ahead of this
264
+ // rule in ../registry.ts) already denies the whole `az devops|repos|
265
+ // pipelines|boards|artifacts` family outright, read or write, identity
266
+ // or not. See this file's header.
267
+ return azCommandIsWrite(inv.args) ? 'az CLI Azure DevOps write' : null
268
+ }
269
+
270
+ if (inv.kind === 'command') {
271
+ if (HTTP_CLIENT_NAMES.has(inv.name)) {
272
+ const targetsAdo = inv.args.some((token) => isAdoUrl(tokenValue(token)))
273
+ if (!targetsAdo) return null
274
+ // Every method needs an identity, GET included — the standard covers
275
+ // reads too, not only the mutating methods.
276
+ const method = httpClientMethod(inv.name, inv.args)
277
+ return `${inv.name} ${method} to dev.azure.com/visualstudio.com`
278
+ }
279
+ if (ADL_BINARY_ALL_NAMES.has(inv.name)) {
280
+ const values = inv.args.map((token) => tokenValue(token))
281
+ if (inv.args.some((token) => dynamicToken(token))) return null
282
+ if (!matchesIdentityShape(values, ADL_IDENTITY_COMMAND_SHAPES)) return null
283
+ return `${inv.name} ${values.slice(0, 3).join(' ')}`
284
+ }
285
+ if (ADL_AGENT_ID_BINARY_ALL_NAMES.has(inv.name)) {
286
+ const values = inv.args.map((token) => tokenValue(token))
287
+ if (inv.args.some((token) => dynamicToken(token))) return null
288
+ // Leading dash-prefixed
289
+ // global flags are skipped before matching the `['exec']` shape —
290
+ // see git-helpers.ts's skipLeadingDashFlags doc.
291
+ if (!matchesIdentityShape(skipLeadingDashFlags(values), ADL_AGENT_ID_COMMAND_SHAPES)) return null
292
+ return `${inv.name} ${values.slice(0, 3).join(' ')}`
293
+ }
294
+ if (INTERPRETER_ONE_LINER_NAMES.has(inv.name)) {
295
+ const identityBearing = interpreterCodeStrings(inv.args).some((code) => containsIdentityBearingToken(code))
296
+ return identityBearing ? `${inv.name} interpreter one-liner` : null
297
+ }
298
+ return null
299
+ }
300
+
301
+ if (inv.kind === 'tool-call') {
302
+ const toolName = mcpToolName(inv.tool)
303
+ if (toolName === null || !ADO_MCP_ALL_TOOLS.has(toolName)) return null
304
+ return `${MCP_REASON_PREFIX} ${inv.tool}`
305
+ }
306
+
307
+ return null
308
+ }
309
+
310
+ export const adlRunRequiredForWrites: RuleSpec = {
311
+ id: RULE_ID,
312
+ category: 'tool-call',
313
+ severity: 'deny',
314
+ enabledByDefault: true,
315
+ summary: 'Deny Azure DevOps access (git, az CLI, curl/wget/httpie, adl entry points, MCP tools) with no resolvable ADL agent identity.',
316
+ params: noParams,
317
+ match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
318
+ // The shape check runs
319
+ // FIRST, entirely without touching `ctx.env` — `checkResolvableIdentity`
320
+ // can hit the real filesystem (the machine default-agent file) once
321
+ // neither the command's own inline override nor the session env
322
+ // resolves, so it must not run for every invocation this rule is asked
323
+ // about. The vast majority (ls, cat, git status, an unrelated tool
324
+ // call, …) are not identity-bearing at all and, with this ordering,
325
+ // never reach `checkResolvableIdentity` — only a genuine candidate does.
326
+ const reason = identityBearingReason(inv)
327
+ if (reason === null) return null
328
+
329
+ const identity = checkResolvableIdentity(ctx.command ?? '', ctx.env)
330
+ if (identity.resolvable) return null
331
+ // The exact message this specific failure earns — NOT a fixed
332
+ // generic string — carried in the Finding so message() reports it
333
+ // faithfully instead of a constant that cannot distinguish "nothing
334
+ // configured" from "something IS configured but it's wrong".
335
+ return { ruleId: RULE_ID, severity: 'deny', detail: { reason, identityMessage: identity.message } }
336
+ },
337
+ message(finding: Finding, ctx: MessageContext) {
338
+ const reason = detailString(finding, 'reason')
339
+ const identityMessage = detailString(finding, 'identityMessage')
340
+ // NO_AGENT_IDENTITY_MESSAGE (the "nothing configured at all" case) IS
341
+ // ALREADY "prefix the command with ADL_AGENT_ID_AGENT=<agent-...>" —
342
+ // appending the same advice a second time, in slightly different
343
+ // wording, would say it twice. The INVALID case (something IS configured, but names an agent
344
+ // outside VALID_AGENTS) has no such text at all, so the "how to fix it"
345
+ // sentence is the only place that advice appears for it and stays.
346
+ const advice = identityMessage === NO_AGENT_IDENTITY_MESSAGE ? '' : ` Prefix the command with ${ENV_VAR}=<agent>.`
347
+ // An MCP tool call carries no command text, so "prefix the command"
348
+ // cannot apply to it (Tarun, 2026-10-01): its identity comes from the
349
+ // environment or the machine default-agent file. MCP stays the primary
350
+ // route; `adl mcp cli <command>` is the FALLBACK when no identity
351
+ // resolves for the MCP server, and it takes the inline prefix like any
352
+ // command. Never `adl run` / "start the session" — see
353
+ // docs/operations/agent-permissions.md.
354
+ const cliAdvice = reason.startsWith(MCP_REASON_PREFIX)
355
+ ? ` An MCP tool call cannot carry an inline prefix; its identity comes from the environment or the machine default-agent file. Until one resolves, use the fallback: ${ENV_VAR}=<agent> adl mcp cli <command>.`
356
+ : ''
357
+ return {
358
+ user: `${identityMessage}${cliAdvice}`,
359
+ agent: `DENIED ${reason} without an ADL agent identity. ${identityMessage}${advice}${cliAdvice} Blocked: ${ctx.snippet}`,
360
+ }
361
+ },
362
+ corpus: {
363
+ deny: [
364
+ 'git push https://dev.azure.com/org/project/_git/repo main',
365
+ 'git push origin main',
366
+ 'git push',
367
+ // Git network READS need an identity too — every Azure DevOps access
368
+ // does, not only writes.
369
+ 'git fetch origin main',
370
+ 'git clone https://dev.azure.com/org/project/_git/repo',
371
+ 'git ls-remote https://dev.azure.com/org/project/_git/repo',
372
+ 'curl -X POST https://dev.azure.com/org/project/_apis/git/repositories',
373
+ 'wget --method=POST https://dev.azure.com/org/project/_apis/git/repositories',
374
+ // A plain GET to dev.azure.com needs an identity too.
375
+ 'curl https://dev.azure.com/org/project/_apis/git/repositories',
376
+ 'wget https://dev.azure.com/org/project/_apis/git/repositories',
377
+ // The adl entry points that reach Azure DevOps.
378
+ 'adl mcp cli pr-list-or-get',
379
+ 'adl repo doctor',
380
+ 'adl repo controls azdo-push',
381
+ 'adl id token agent-tarun',
382
+ 'adl-agent-id exec --agent agent-tarun -- adl id token agent-tarun --json',
383
+ // Already denied outright by tool.azure-devops (steers at the MCP server) —
384
+ // kept here too so this rule's own corpus is non-empty and honest about
385
+ // az CLI being a write surface it cares about; see the header for why
386
+ // its OWN read/write split is exercised in a dedicated unit test instead.
387
+ 'az repos pr create --title x',
388
+ ],
389
+ allow: [
390
+ // Explicit non-ADO destination: provably safe without an identity.
391
+ 'git push https://github.com/org/repo main',
392
+ 'git fetch https://github.com/org/repo main',
393
+ 'curl https://github.com/org/repo',
394
+ 'wget https://github.com/org/repo',
395
+ // Non-identity-bearing local commands and adl subcommands are untouched.
396
+ 'git status',
397
+ 'ls -la',
398
+ 'adl run -- claude',
399
+ 'adl repo controls compliance --repo .',
400
+ // A valid inline override supplies its own identity. A feature-branch
401
+ // destination (not `main`/`integration`) is used here so this stays a
402
+ // clean example of THIS rule's own concern — adl.git-push-branch-policy
403
+ // grades the command's EFFECTIVE identity too, so an inline-only
404
+ // override does not bypass branch protection:
405
+ // `ADL_AGENT_ID_AGENT=agent-tarun git push origin main` is denied by
406
+ // that rule, not allowed by this one.
407
+ 'ADL_AGENT_ID_AGENT=agent-tarun git push origin feat/x',
408
+ 'ADL_AGENT_ID_AGENT=agent-tarun adl id token agent-tarun',
409
+ ],
410
+ },
411
+ }
@@ -1,6 +1,5 @@
1
1
  /**
2
- * `adl.token-minting-role` — W2 build item 1
3
- * (STATUS.md 12p): an agent may mint a bearer
2
+ * `adl.token-minting-role` — one-agent-identity standard: an agent may mint a bearer
4
3
  * token, or exec as an agent identity, only for its OWN effective identity —
5
4
  * never for a different agent whose passport happens to be installed on the
6
5
  * same machine. Covers the two token-minting entry points the standard
@@ -12,7 +11,7 @@
12
11
  * `ADL_AGENT_ID_AGENT=<value>` on the command wins (step 1); otherwise the
13
12
  * session's resolved identity, env then the machine default-agent file
14
13
  * (`adl-identity.ts`'s `resolveFromEnvOrFile`, steps 2-3). With no identity
15
- * at all, this rule stays silent — `adl.session-required-for-writes` denies
14
+ * at all, this rule stays silent — `adl.run-required-for-writes` denies
16
15
  * the call first (no session, not the wrong agent); with an invalid/empty
17
16
  * inline override or an unrewritable sudo/doas wrapper, `adl.git-identity`
18
17
  * denies first (registered ahead of this rule — see `../registry.ts`). This
@@ -56,7 +55,7 @@ export const adlTokenMintingRole: RuleSpec = {
56
55
  if (scanGitIdentityConflicts(command, fallback) !== null) return null
57
56
 
58
57
  for (const piece of scanTokenMintingPieces(command, fallback)) {
59
- if (piece.effectiveAgent === null) continue // adl.session-required-for-writes's job
58
+ if (piece.effectiveAgent === null) continue // adl.run-required-for-writes's job
60
59
  if (piece.effectiveAgent === piece.requestedAgent) continue
61
60
  return {
62
61
  ruleId: RULE_ID,
@@ -84,7 +83,7 @@ export const adlTokenMintingRole: RuleSpec = {
84
83
  // adl.git-identity / adl.git-push-branch-policy — the shared corpus
85
84
  // fixture (tests/fixtures/decide.ts) is hermetically identity-less, so
86
85
  // even a bare `adl id token`/`adl-agent-id exec` there is denied by
87
- // adl.session-required-for-writes first, not usable as an allow entry
86
+ // adl.run-required-for-writes first, not usable as an allow entry
88
87
  // here. Real coverage is tests/unit/rules-adl-token-minting-role.test.ts.
89
88
  deny: [],
90
89
  allow: ['ls -la', 'git status'],
@@ -12,7 +12,7 @@
12
12
  * order"); `tool.azure-devops` keeps denying the raw `az` form unchanged.
13
13
  *
14
14
  * Requires an identity to already be present (`ADL_AGENT_ID_AGENT`
15
- * non-blank) — with no identity at all, `adl.session-required-for-writes`
15
+ * non-blank) — with no identity at all, `adl.run-required-for-writes`
16
16
  * denies the call first, so this rule returns null when the env var is
17
17
  * absent or blank.
18
18
  */
@@ -32,20 +32,19 @@ export const adlWorkitemRequiresTarunOrVivek: RuleSpec = {
32
32
  category: 'tool-call',
33
33
  severity: 'deny',
34
34
  enabledByDefault: true,
35
- summary: 'Deny workitem_create_or_update for agent-reviewer (docs/operations/agent-permissions.md row 10) — the MCP tool AND its adl mcp cli equivalent (M4).',
35
+ summary: 'Deny workitem_create_or_update for agent-reviewer (docs/operations/agent-permissions.md row 10) — the MCP tool AND its adl mcp cli equivalent.',
36
36
  params: noParams,
37
37
  match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
38
- // M4 (STATUS.md 12p): `adl mcp cli
38
+ // `adl mcp cli
39
39
  // workitem-create-or-update` dispatches to the same tool the MCP server
40
40
  // calls — graded identically, not only the tool-call payload shape.
41
41
  const call = toolCallFor(inv)
42
42
  if (call === null) return null
43
43
  if (mcpToolName(call.tool) !== 'workitem_create_or_update') return null
44
44
 
45
- // R5 (STATUS.md 12p, re-review 2026-09-28 night):
46
- // grade the EFFECTIVE identity for THIS specific piece — a valid inline
45
+ // Grade the EFFECTIVE identity for THIS specific piece — a valid inline
47
46
  // `ADL_AGENT_ID_AGENT=` override on the same `adl mcp cli` invocation
48
- // still wins, exactly like M3 already does for `git push`
47
+ // still wins, exactly like it does for `git push`
49
48
  // (effectiveIdentityForMcpCli's own doc has the full "why"). A real MCP
50
49
  // tool-call payload carries no command text at all (no inline override
51
50
  // possible), so this still resolves to the plain session identity for
@@ -54,7 +53,7 @@ export const adlWorkitemRequiresTarunOrVivek: RuleSpec = {
54
53
  const resolution = resolveFromEnvOrFile(ctx.env)
55
54
  const fallback = resolution.ok ? resolution.agent : null
56
55
  const agent = effectiveIdentityForMcpCli(inv, ctx.command ?? '', fallback)
57
- if (agent === null) return null // no identity at all: adl.session-required-for-writes's job
56
+ if (agent === null) return null // no identity at all: adl.run-required-for-writes's job
58
57
  if (agent !== AGENT_REVIEWER) return null
59
58
 
60
59
  return { ruleId: RULE_ID, severity: 'deny', detail: { tool: call.tool } }