@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.12 → 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 (405) 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 +10 -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 +159 -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 +34 -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/src/azdo-pl.ts +2 -54
  140. package/packages/azdo/src/azdo-pr-review.ts +4 -4
  141. package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
  142. package/packages/azdo/src/azdo-wit.ts +41 -2
  143. package/packages/azdo/src/lib/agent-identity.ts +12 -14
  144. package/packages/azdo/src/lib/agent-token.ts +2 -2
  145. package/packages/azdo/src/lib/client.ts +0 -5
  146. package/packages/azdo/src/lib/graph-identity.ts +4 -4
  147. package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
  148. package/packages/azdo/src/workflow-rules.ts +128 -0
  149. package/packages/fleet/manifest.json +35 -11
  150. package/packages/fleet/manifest.schema.json +62 -10
  151. package/packages/fleet/src/default-agent-file.ts +3 -3
  152. package/packages/fleet/src/install-adl-package.ts +73 -15
  153. package/packages/fleet/src/install-embedding-model.ts +13 -13
  154. package/packages/fleet/src/managed-settings.ts +7 -7
  155. package/packages/fleet/src/repo-maintain.ts +91 -55
  156. package/packages/fleet/src/scratch-reap.ts +5 -5
  157. package/packages/fleet/src/vscode-settings.ts +5 -5
  158. package/packages/repo-controls/README.md +141 -43
  159. package/packages/repo-controls/assets/promote.ts +4 -4
  160. package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
  161. package/packages/repo-controls/assets/version-bump.sh +31 -84
  162. package/packages/repo-controls/bunfig.toml +6 -7
  163. package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
  164. package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
  165. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
  166. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
  167. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
  168. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
  169. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
  170. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
  171. 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
  172. 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
  173. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
  174. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
  175. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
  176. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
  177. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
  178. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
  179. 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
  180. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
  181. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
  182. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
  183. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
  184. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
  185. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
  186. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
  187. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
  188. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
  189. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
  190. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
  191. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
  192. 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
  193. 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
  194. 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
  195. 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
  196. 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
  197. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
  198. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
  199. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
  200. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
  201. 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
  202. 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
  203. 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
  204. 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
  205. 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
  206. 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
  207. 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
  208. 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
  209. 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
  210. 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
  211. 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
  212. 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
  213. 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
  214. 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
  215. 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
  216. 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
  217. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
  218. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
  219. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
  220. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
  221. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
  222. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
  223. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
  224. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
  225. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
  226. 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
  227. 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
  228. 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
  229. 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
  230. 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
  231. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
  232. 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
  233. 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
  234. 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
  235. 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
  236. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
  237. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
  238. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
  239. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
  240. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
  241. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
  242. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
  243. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
  244. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
  245. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
  246. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
  247. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
  248. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
  249. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
  250. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
  251. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
  252. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
  253. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
  254. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
  255. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
  256. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
  257. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
  258. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
  259. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
  260. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
  261. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
  262. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
  263. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
  264. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
  265. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
  266. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
  267. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
  268. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
  269. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
  270. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
  271. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
  272. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
  273. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
  274. 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
  275. 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
  276. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
  277. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
  278. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
  279. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
  280. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
  281. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
  282. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
  283. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
  284. 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
  285. 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
  286. 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
  287. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
  288. 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
  289. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
  290. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
  291. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
  292. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
  293. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
  294. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
  295. 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
  296. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
  297. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
  298. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
  299. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
  300. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
  301. 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
  302. 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
  303. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
  304. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
  305. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
  306. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
  307. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
  308. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
  309. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
  310. 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
  311. 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
  312. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
  313. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
  314. 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
  315. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
  316. 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
  317. 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
  318. 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
  319. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
  320. 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
  321. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
  322. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
  323. 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
  324. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
  325. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
  326. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
  327. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
  328. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
  329. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
  330. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +256 -0
  331. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
  332. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
  333. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +1 -1
  334. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
  335. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
  336. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
  337. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
  338. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
  339. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
  340. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
  341. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
  342. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
  343. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
  344. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
  345. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
  346. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
  347. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
  348. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
  349. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
  350. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
  351. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
  352. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
  353. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
  354. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
  355. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
  356. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
  357. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
  358. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
  359. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
  360. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
  361. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
  362. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
  363. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
  364. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
  365. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
  366. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
  367. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
  368. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
  369. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
  370. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
  371. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
  372. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
  373. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
  374. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
  375. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
  376. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
  377. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
  378. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
  379. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
  380. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
  381. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
  382. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
  383. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
  384. package/packages/repo-controls/package.json +2 -9
  385. package/packages/repo-controls/scripts/hooks/post-merge +13 -0
  386. package/packages/repo-controls/scripts/hooks/pre-push +3 -3
  387. package/packages/repo-controls/src/azdo-push.ts +64 -36
  388. package/packages/repo-controls/src/azure-devops-governance.ts +7 -9
  389. package/packages/repo-controls/src/azure-devops-remote.ts +1 -1
  390. package/packages/repo-controls/src/cli.ts +29 -8
  391. package/packages/repo-controls/src/compliance-config.ts +410 -2
  392. package/packages/repo-controls/src/config.ts +133 -60
  393. package/packages/repo-controls/src/constants.ts +13 -27
  394. package/packages/repo-controls/src/coverage-ratchet.ts +4 -4
  395. package/packages/repo-controls/src/doctor.ts +46 -19
  396. package/packages/repo-controls/src/gitignore-block.ts +5 -29
  397. package/packages/repo-controls/src/hook-log.ts +1 -2
  398. package/packages/repo-controls/src/hook.ts +201 -45
  399. package/packages/repo-controls/src/install.ts +14 -8
  400. package/packages/repo-controls/src/integrity.ts +3 -3
  401. package/packages/repo-controls/src/lfs.ts +111 -0
  402. package/packages/repo-controls/src/promote.ts +8 -8
  403. package/packages/repo-controls/src/runtime.ts +9 -1
  404. package/packages/repo-controls/src/workflows-drift.ts +4 -5
  405. package/packages/repo-controls/src/worktree-guard.ts +3 -3
@@ -1,5 +1,6 @@
1
1
  /**
2
- * `adl.human-azdo-bypass` — STATUS.md 12p decisions 1/1b/1c:
2
+ * `adl.human-azdo-bypass` — the human pass-through in `bin/git-ado` fails
3
+ * closed and the human opts in (Tarun, 2026-09-29):
3
4
  * `ADL_HUMAN_AZDO=1` marks Tarun's own interactive terminal (`bin/git-ado`'s
4
5
  * and `resolveAgentIdentity`'s shared human-pass-through check,
5
6
  * `packages/azdo/src/lib/agent-identity.ts`'s `isMarkedHumanAzdoCaller`:
@@ -11,17 +12,17 @@
11
12
  * the whole standard exists to close — just aimed at the marker itself
12
13
  * instead of at `ADL_AGENT_ID_AGENT`.
13
14
  *
14
- * F1 (independent review, 2026-09-29, HIGH, confirmed): a live bypass —
15
- * `export ADL_HUMAN_AZD''O=1; unset ADL_AGENT_ID_AGENT; script -q /dev/null
16
- * git push origin feat/x` — was ALLOWED and reached `bin/git-ado`'s human
17
- * pass-through via a faked pty. Fixed in three parts (a/b/c below).
15
+ * Three shapes are denied (a/b/c below). An independent review
16
+ * (2026-09-29) found the live bypass they close: `export ADL_HUMAN_AZD''O=1;
17
+ * unset ADL_AGENT_ID_AGENT; script -q /dev/null git push origin feat/x`
18
+ * reached `bin/git-ado`'s human pass-through via a faked pty.
18
19
  *
19
- * SECOND REVIEW (2026-09-29, same night): the first F1 fix over-matched —
20
- * `git commit -m "ADL_HUMAN_AZDO=1 is denied now"`, `git log -S
20
+ * Detection is POSITIONAL, not "any word anywhere", because a looser scan
21
+ * over-matched: `git commit -m "ADL_HUMAN_AZDO=1 is denied now"`, `git log -S
21
22
  * "ADL_HUMAN_AZDO=1"`, `declare -p ADL_HUMAN_AZDO` (a READ, not a set),
22
23
  * `grep -c '...'` (grep's COUNT flag, mistaken for shell `-c`), and `node -e
23
- * "console.log('pty')"` (a bare word 'pty' in unrelated code) were all
24
- * wrongly denied. Detection is now POSITIONAL, not "any word anywhere":
24
+ * "console.log('pty')"` (a bare word 'pty' in unrelated code) would all be
25
+ * wrongly denied:
25
26
  *
26
27
  * (a) A setter is recognized only in a real setter POSITION — a leading
27
28
  * `NAME=value` assignment before a piece's own command word, or the
@@ -48,7 +49,7 @@
48
49
  * (b) Clearing `ADL_AGENT_ID_AGENT` is denied in every named form: `unset
49
50
  * NAME` (as an operand of `unset`, the piece's own command), `env -u
50
51
  * NAME`/`--unset[=]NAME`, an empty leading assignment (`NAME=`),
51
- * `export -n NAME`, `declare +x NAME`/`typeset +x NAME` (P2: `+x`
52
+ * `export -n NAME`, `declare +x NAME`/`typeset +x NAME` (`+x`
52
53
  * removes the export attribute). `env -i`/`--ignore-environment`/bare
53
54
  * `env -` clears the WHOLE environment, but is denied ONLY when the
54
55
  * command it wraps is ITSELF identity-bearing (`isLikelyIdentityBearing`
@@ -62,8 +63,8 @@
62
63
  * `delete $ENV{X}` (perl) — same "-c/-e/--eval argument only" scoping
63
64
  * as the setter check.
64
65
  * (c) `script`/`unbuffer`/`expect`, `socat` with a `pty` argument, `tmux`/
65
- * `screen` starting a detached session with a command (P2:
66
- * `new-session`/`-dm`/`-dmS`), `zsh`'s `zpty` module command, a
66
+ * `screen` starting a detached session with a command
67
+ * (`new-session`/`-dm`/`-dmS`), `zsh`'s `zpty` module command, a
67
68
  * python/node/ruby/perl one-liner or flag that actually loads a pty
68
69
  * module (`import pty`/`pty.spawn(...)`, `require('pty'|'node-pty')`,
69
70
  * `-rpty`, `-MIO::Pty` — never a bare word), launching a real terminal
@@ -84,7 +85,7 @@
84
85
  * missed because the literal first word was a wrapper.
85
86
  *
86
87
  * Word collection deliberately does NOT walk into here-documents, here-
87
- * strings, or `$(...)`/backtick substitutions (out of scope for this fix);
88
+ * strings, or `$(...)`/backtick substitutions (out of scope for this rule);
88
89
  * it only reaches one level into a REAL shell's `-c`/`--command` script
89
90
  * string, depth-capped — matching this rule's own "coarse, not a precise
90
91
  * parser" contract.
@@ -98,8 +99,8 @@
98
99
  * managed repo's own normal rule pass — this rule fires the same way any
99
100
  * other enabled rule does, nothing baseline-specific about it.
100
101
  *
101
- * THE PTY-FAKING-WRAPPER CLASS IS UNBOUNDED (STATUS.md 12p item 15's threat
102
- * model; F4, fourth independent review, 2026-09-29, "bounded, then stop").
102
+ * THE PTY-FAKING-WRAPPER CLASS IS UNBOUNDED (independent review,
103
+ * 2026-09-29: widen once, then stop).
103
104
  * `pieceUsesPtyFakingWrapper` recognizes a widened but still FINITE list of
104
105
  * named tools (`script`/`unbuffer`/`expect`/`zpty`, `socat`, `tmux`/`screen`,
105
106
  * `ssh` to a loopback host, terminal-launching `open`/`osascript`, and a
@@ -109,12 +110,11 @@
109
110
  * helper, a language runtime this list does not name, a future terminal
110
111
  * emulator, a creative combination of otherwise-ordinary tools). Widening
111
112
  * this list further, one reported gap at a time, has a naturally
112
- * diminishing return: closing THIS session's known list here (this fix,
113
- * and the two before it in this file's own history) is the last widening
114
- * pass for the foreseeable future — the credential-level fix (removing the
113
+ * diminishing return: the list as it stands is the last widening pass for
114
+ * the foreseeable future — the credential-level fix (removing the
115
115
  * SHARED-machine TTY signal `bin/git-ado` relies on as a proxy for "is this
116
- * a human") is the orchestrator's own, separate track with Tarun, not
117
- * something this rule can substitute for by enumerating tools forever.
116
+ * a human") is a separate track with Tarun, not something this rule can
117
+ * substitute for by enumerating tools forever.
118
118
  */
119
119
 
120
120
  import type { Invocation } from '../shell/invocation.ts'
@@ -132,13 +132,13 @@ import { tokenize, tokenValue, type Token } from '../shell/token.ts'
132
132
  export const RULE_ID = 'adl.human-azdo-bypass'
133
133
 
134
134
  /**
135
- * The exact env var name STATUS.md 12p decisions 1b/1c name. Not exported as
135
+ * The exact env var name `bin/git-ado` checks for the human pass-through. Not exported as
136
136
  * a standalone string constant from `packages/azdo/src/lib/agent-identity.ts`
137
137
  * (only the combined TTY+value check, `isMarkedHumanAzdoCaller`, is) — this
138
138
  * is the one place in this package that spells it, rather than a second,
139
139
  * independent literal duplicated across detection helpers below.
140
140
  */
141
- export const ADL_HUMAN_AZDO_ENV_VAR = 'ADL_HUMAN_AZDO'
141
+ const ADL_HUMAN_AZDO_ENV_VAR = 'ADL_HUMAN_AZDO'
142
142
 
143
143
  /** `os.environ['ADL_HUMAN_AZDO'] = ...` / `os.environ.setdefault('ADL_HUMAN_AZDO', ...)` — Python. Checked against ONLY the `-c`/`-e`/`--eval` code argument (see this file's own header). */
144
144
  const PYTHON_HUMAN_AZDO_SET_RE = /os\.environ\s*(?:\[\s*['"]ADL_HUMAN_AZDO['"]\s*\]|\.setdefault\(\s*['"]ADL_HUMAN_AZDO['"])\s*[=(]/
@@ -161,7 +161,7 @@ const INTERPRETER_NAMES: ReadonlySet<string> = new Set(['python', 'python2', 'py
161
161
  const AZ_NAMES: ReadonlySet<string> = new Set(['az', 'az.exe'])
162
162
 
163
163
  /**
164
- * P2 (independent review, 2026-09-29, "dynamic names"): a strict leading
164
+ * Dynamic names (independent review, 2026-09-29): a strict leading
165
165
  * assignment shape (`^[A-Za-z_][A-Za-z0-9_]*=`), but permitting
166
166
  * `$`/backtick/`{`/`}` in the identifier portion too —
167
167
  * `ADL_HUMAN_AZ${EMPTY}DO=1` is one word after `tokenize` (confirmed
@@ -185,7 +185,7 @@ function isAssignmentTo(value: string, name: string): boolean {
185
185
  * know what such a word actually names — `v=ADL_HUMAN_AZDO; export "$v=1"`
186
186
  * and `X=ADL_AGENT_ID_AGENT; unset $X` both hide the real name behind a
187
187
  * variable this static scan never resolves — so any setter/clearer-shaped
188
- * position holding one is treated as a match (P2 "dynamic names",
188
+ * position holding one is treated as a match (dynamic names,
189
189
  * fail-closed) for whichever name the caller is checking.
190
190
  */
191
191
  function isNameOperandDynamic(value: string): boolean {
@@ -223,9 +223,8 @@ interface WordPiece {
223
223
  * (private) `isShellCommandOption` one-line check, kept in sync
224
224
  * deliberately rather than exported, to recognize a shell invoked with
225
225
  * combined flags (`zsh -ic '...'`, `bash -lc '...'`, `sh -ec '...'`) the
226
- * same way the rest of the engine already does (F2, third independent
227
- * review, 2026-09-29 — this rule's own exact-`-c`-only check let `zsh -ic
228
- * '...'` defeat it entirely).
226
+ * same way the rest of the engine already does (an exact-`-c`-only
227
+ * check would let `zsh -ic '...'` defeat this rule entirely).
229
228
  */
230
229
  function isShellScriptOption(value: string): boolean {
231
230
  return value === '-c' || /^-[^-]*c$/.test(value) || value === '--command' || value.startsWith('--command=')
@@ -235,9 +234,9 @@ function isShellScriptOption(value: string): boolean {
235
234
  * Every piece of `command` (one `WordPiece` per top-level piece), collected
236
235
  * into `out`. Recurses one level into a `-c`-shaped shell script string
237
236
  * ONLY when the piece's own RESOLVED command (past a leading assignment and
238
- * a chain of transparent wrappers — F2: `nohup bash -c '...'`/`FOO=1 bash
239
- * -c '...'` were invisible before, since only the piece's literal FIRST
240
- * word was checked) is a real shell (`SHELL_NAMES`) — never for an
237
+ * a chain of transparent wrappers: `nohup bash -c '...'`/`FOO=1 bash
238
+ * -c '...'` would be invisible if only the piece's literal FIRST
239
+ * word were checked) is a real shell (`SHELL_NAMES`) — never for an
241
240
  * unrelated `-c` flag on some other command (`grep -c`, `curl -c`, `ssh
242
241
  * -c`, …). Quote concatenation and backslash escapes are already resolved
243
242
  * by `tokenize`.
@@ -286,7 +285,7 @@ function interpreterInlineCode(args: readonly string[]): string | null {
286
285
  * begin — past a leading `NAME=value` assignment and a chain of transparent
287
286
  * wrappers (`sudo`/`env`/`timeout`/`nice`/`caffeinate`/`arch`/`exec`/`time`/
288
287
  * `stdbuf`/`setsid`/`command`/`doas`/`nohup`/`gtimeout`) and THEIR OWN
289
- * arguments (P2: "detect... by the walker's RESOLVED command"). Reuses
288
+ * arguments (detection is by the walker's RESOLVED command). Reuses
290
289
  * `../shell/prefixes.ts`'s own `skipPrefixes` — the SAME, already-tested
291
290
  * wrapper-argument-skipping logic every other rule's classification is
292
291
  * built on (`shell/invocation.ts`'s `walk()` calls it too) — rather than a
@@ -303,7 +302,7 @@ function resolvedCommand(piece: WordPiece): { readonly name: string | undefined;
303
302
  return { name: basenameOf(piece.values[index] as string).toLowerCase(), argsStart: index + 1 }
304
303
  }
305
304
 
306
- /** A network git verb, a curl/wget/httpie/xh call to Azure DevOps, `az`, or an `adl`/`adl-agent-id` entry point — the shapes `env -i`/bare `env -` is worth denying for (P1: clearing the WHOLE environment for a command that never needed an identity is harmless). Coarse, matching the same tradeoff every other check in this file makes. */
305
+ /** A network git verb, a curl/wget/httpie/xh call to Azure DevOps, `az`, or an `adl`/`adl-agent-id` entry point — the shapes `env -i`/bare `env -` is worth denying for (clearing the WHOLE environment for a command that never needed an identity is harmless). Coarse, matching the same tradeoff every other check in this file makes. */
307
306
  function isLikelyIdentityBearing(name: string, args: readonly string[]): boolean {
308
307
  if (name === 'git' || name === 'git.exe') {
309
308
  const subIndex = args.findIndex((value) => !value.startsWith('-'))
@@ -317,8 +316,7 @@ function isLikelyIdentityBearing(name: string, args: readonly string[]): boolean
317
316
  }
318
317
 
319
318
  /**
320
- * F3 (third independent review, 2026-09-29): a setter/clearer keyword is
321
- * still missed when it is NOT `values[0]` — `if true; then export
319
+ * A setter/clearer keyword can be missed when it is NOT `values[0]` — `if true; then export
322
320
  * ADL_HUMAN_AZDO=1; fi` splits (on `;`) into a piece whose first word is
323
321
  * the keyword `then`, not `export`; `builtin export …`/`command export …`
324
322
  * explicitly invoke the builtin/external form, bypassing any shell
@@ -356,7 +354,7 @@ function pieceSetsHumanAzdo(values: readonly string[], heredocs: readonly string
356
354
  const rest = resolved.slice(1)
357
355
  if (head === 'export') {
358
356
  // `-f` (functions) is unrelated; `-p` (print) is deliberately NOT
359
- // excluded here any more (F3) — `export -p ADL_HUMAN_AZDO=1` still
357
+ // excluded here — `export -p ADL_HUMAN_AZDO=1` still
360
358
  // carries an assignment and real bash still exports it, `-p` or not; a
361
359
  // bare `export -p ADL_HUMAN_AZDO` (no `=`, a genuine list/print with no
362
360
  // real effect) is a coarse, low-cost over-match this file already
@@ -387,8 +385,7 @@ function pieceSetsHumanAzdo(values: readonly string[], heredocs: readonly string
387
385
  return false
388
386
  }
389
387
  if (INTERPRETER_NAMES.has(head)) {
390
- // Third independent review (2026-09-29): "heredoc-fed interpreters"
391
- // (`python3 - <<'EOF' ... EOF`) have no `-c`/`-e`/`--eval` argument at
388
+ // Heredoc-fed interpreters (`python3 - <<'EOF' ... EOF`) have no `-c`/`-e`/`--eval` argument at
392
389
  // all — the real code is the heredoc BODY, passed in from `match()`
393
390
  // (computed once from the whole command, not per-piece).
394
391
  const inline = interpreterInlineCode(rest)
@@ -430,7 +427,7 @@ function pieceClearsAgentIdentity(piece: WordPiece, heredocs: readonly string[])
430
427
  return false
431
428
  }
432
429
  if (INTERPRETER_NAMES.has(head)) {
433
- // Third independent review (2026-09-29): heredoc-fed interpreters.
430
+ // Heredoc-fed interpreters.
434
431
  const inline = interpreterInlineCode(rest)
435
432
  const candidates = inline !== null ? [inline] : heredocs
436
433
  return candidates.some((code) => PYTHON_AGENT_ID_DELETE_RE.test(code) || NODE_AGENT_ID_DELETE_RE.test(code) || PERL_AGENT_ID_DELETE_RE.test(code))
@@ -441,7 +438,7 @@ function pieceClearsAgentIdentity(piece: WordPiece, heredocs: readonly string[])
441
438
  const LOOPBACK_EXACT: ReadonlySet<string> = new Set(['localhost', '::1', '0'])
442
439
 
443
440
  /**
444
- * F4 (fourth independent review, 2026-09-29): `user@host` (ssh's own
441
+ * `user@host` (ssh's own
445
442
  * `user@` prefix) is stripped before checking; `127.1`/`127.0.1` (partial
446
443
  * IPv4 notation — every major OS resolves these to the `127.0.0.1` range)
447
444
  * are accepted alongside the full four-octet form.
@@ -453,7 +450,7 @@ function isLoopbackHost(rawValue: string): boolean {
453
450
  return /^127(?:\.\d{1,3}){1,3}$/.test(lower)
454
451
  }
455
452
 
456
- /** An unresolved shell expansion in a host-shaped position (F4: `ssh -tt $(hostname) …`) — cannot be proven non-loopback, so treated as a match (fail-closed), the same "dynamic names" tradeoff this file already makes elsewhere. */
453
+ /** An unresolved shell expansion in a host-shaped position (`ssh -tt $(hostname) …`) — cannot be proven non-loopback, so treated as a match (fail-closed), the same "dynamic names" tradeoff this file already makes elsewhere. */
457
454
  const isDynamicHostCandidate = (value: string): boolean => /\$\(|`|\$\{/.test(value)
458
455
 
459
456
  function sshForcesTty(args: readonly string[]): boolean {
@@ -467,10 +464,10 @@ function sshForcesTty(args: readonly string[]): boolean {
467
464
  return false
468
465
  }
469
466
 
470
- /** No legitimate use on an agent surface — see this file's own F1(c) header. `zpty` is zsh's own pty module command — invoked as `zsh -c 'zpty ...'`, this scanner's own `-c` recursion (real shells only) makes `zpty` the RESOLVED command of the nested piece, not merely an argument to `zsh`. */
467
+ /** No legitimate use on an agent surface — see this file's own header, part (c). `zpty` is zsh's own pty module command — invoked as `zsh -c 'zpty ...'`, this scanner's own `-c` recursion (real shells only) makes `zpty` the RESOLVED command of the nested piece, not merely an argument to `zsh`. */
471
468
  const UNCONDITIONAL_PTY_WRAPPERS: ReadonlySet<string> = new Set(['script', 'unbuffer', 'expect', 'zpty'])
472
469
 
473
- /** True when `args` is nothing but `--help`/`-h`/`--version`/`-V` — a string-value mirror of `shell/invocation.ts`'s own (Token-based) `isHelpOrVersionOnly`. F7 (fourth independent review, 2026-09-29): `expect --version` has no script to run at all — harmless. */
470
+ /** True when `args` is nothing but `--help`/`-h`/`--version`/`-V` — a string-value mirror of `shell/invocation.ts`'s own (Token-based) `isHelpOrVersionOnly`. `expect --version` has no script to run at all — harmless. */
474
471
  function isHelpOrVersionOnlyValues(args: readonly string[]): boolean {
475
472
  let sawHelp = false
476
473
  for (const arg of args) {
@@ -485,7 +482,7 @@ function isHelpOrVersionOnlyValues(args: readonly string[]): boolean {
485
482
  return sawHelp
486
483
  }
487
484
 
488
- /** Every `-e CODE` occurrence (F4: `osascript` accepts MULTIPLE `-e` flags, each one a line of the same script — reading only the first, as `interpreterInlineCode` does, missed a script split across several). */
485
+ /** Every `-e CODE` occurrence (`osascript` accepts MULTIPLE `-e` flags, each one a line of the same script — reading only the first, as `interpreterInlineCode` does, missed a script split across several). */
489
486
  function allDashEArgs(args: readonly string[]): readonly string[] {
490
487
  const values: string[] = []
491
488
  for (let index = 0; index < args.length; index += 1) {
@@ -495,7 +492,7 @@ function allDashEArgs(args: readonly string[]): readonly string[] {
495
492
  }
496
493
 
497
494
  const TMUX_ACTIONS: ReadonlySet<string> = new Set(['new-session', 'new', 'new-window', 'split-window', 'send-keys'])
498
- /** Bundle IDs for `open -b <id>` — F4: the app-name check (`open -a Terminal`) has no bundle-id equivalent to match against. */
495
+ /** Bundle IDs for `open -b <id>`: the app-name check (`open -a Terminal`) has no bundle-id equivalent to match against. */
499
496
  const TERMINAL_BUNDLE_IDS: ReadonlySet<string> = new Set([
500
497
  'com.apple.terminal',
501
498
  'com.googlecode.iterm2',
@@ -505,10 +502,10 @@ const TERMINAL_BUNDLE_IDS: ReadonlySet<string> = new Set([
505
502
  'org.alacritty',
506
503
  'com.github.wez.wezterm',
507
504
  ])
508
- /** Terminal-app names `open -a`/AppleScript/JXA name by — F4: widened past Terminal/iTerm to every terminal emulator the finding named. */
505
+ /** Terminal-app names `open -a`/AppleScript/JXA name by — covers every common terminal emulator, not only Terminal/iTerm. */
509
506
  const TERMINAL_APP_NAME_RE = /\b(?:terminal|iterm|ghostty|warp|kitty|alacritty|wezterm)\b/i
510
507
 
511
- /** True when `piece` (one piece's words) invokes a pty-faking wrapper, resolved past a leading assignment and a chain of transparent wrappers. See this file's own F1(c) header for which shapes are unconditional vs. narrowed to a loopback host. */
508
+ /** True when `piece` (one piece's words) invokes a pty-faking wrapper, resolved past a leading assignment and a chain of transparent wrappers. See this file's own header, part (c), for which shapes are unconditional vs. narrowed to a loopback host. */
512
509
  function pieceUsesPtyFakingWrapper(piece: WordPiece): boolean {
513
510
  const resolved = resolvedCommand(piece)
514
511
  const name = resolved.name
@@ -530,7 +527,7 @@ function pieceUsesPtyFakingWrapper(piece: WordPiece): boolean {
530
527
  if (INTERPRETER_NAMES.has(name)) {
531
528
  const code = interpreterInlineCode(args)
532
529
  if (code === null) return false
533
- // F4: comma-form imports (`import os, pty`) and `__import__('pty')`.
530
+ // Comma-form imports (`import os, pty`) and `__import__('pty')`.
534
531
  if (name.startsWith('python')) {
535
532
  return (
536
533
  /(?:^|[\s;])import\s+(?:[\w.]+\s*,\s*)*pty\b|\bfrom\s+pty\s+import\b|\bpty\.(?:spawn|fork|openpty)\s*\(|__import__\(\s*['"]pty['"]\s*\)/.test(
@@ -549,7 +546,7 @@ function pieceUsesPtyFakingWrapper(piece: WordPiece): boolean {
549
546
  if (name === 'open') {
550
547
  for (let index = 0; index < args.length; index += 1) {
551
548
  const value = args[index] as string
552
- // F4: combined flags (`-na` = -n new-instance + -a app) — any
549
+ // Combined flags (`-na` = -n new-instance + -a app) — any
553
550
  // combined short-flag string containing `a`/`b` still takes the
554
551
  // NEXT word as the app name / bundle id, same as the bare flag.
555
552
  if (/^-[a-zA-Z]*a[a-zA-Z]*$/.test(value) && TERMINAL_APP_NAME_RE.test(args[index + 1] ?? '')) return true
@@ -562,7 +559,7 @@ function pieceUsesPtyFakingWrapper(piece: WordPiece): boolean {
562
559
  if (codes.length === 0) return false
563
560
  const combined = codes.join('\n')
564
561
  if (!TERMINAL_APP_NAME_RE.test(combined)) return false
565
- // F4: AppleScript's `do script` and JXA's (`-l JavaScript`) `.doScript(`
562
+ // AppleScript's `do script` and JXA's (`-l JavaScript`) `.doScript(`
566
563
  // are the same operation in the two languages osascript accepts.
567
564
  return /\bdo script\b/i.test(combined) || /\.\s*doScript\s*\(/i.test(combined)
568
565
  }
@@ -577,7 +574,7 @@ export const adlHumanAzdoBypass: RuleSpec = {
577
574
  severity: 'deny',
578
575
  enabledByDefault: true,
579
576
  summary:
580
- "Deny an agent command that sets/exports/assigns ADL_HUMAN_AZDO, clears ADL_AGENT_ID_AGENT, or fakes a TTY to defeat bin/git-ado's human/agent decision (STATUS.md 12p decisions 1/1b/1c; F1).",
577
+ "Deny an agent command that sets/exports/assigns ADL_HUMAN_AZDO, clears ADL_AGENT_ID_AGENT, or fakes a TTY to defeat bin/git-ado's human/agent decision.",
581
578
  params: noParams,
582
579
  match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
583
580
  // A tool-call payload (a real MCP call) carries no shell command text
@@ -586,7 +583,7 @@ export const adlHumanAzdoBypass: RuleSpec = {
586
583
  const command = ctx.command ?? ''
587
584
  if (command.trim().length === 0) return null
588
585
  const pieces = wordPiecesFor(command)
589
- // Third independent review (2026-09-29): heredoc-fed interpreters
586
+ // Heredoc-fed interpreters
590
587
  // (`python3 - <<'EOF' ... EOF`) have no `-c`/`-e`/`--eval` argument at
591
588
  // all — computed once from the whole command, not per-piece.
592
589
  const heredocs = heredocBodies(command)
@@ -623,7 +620,7 @@ export const adlHumanAzdoBypass: RuleSpec = {
623
620
  agent:
624
621
  `DENIED ${user}. unset/env -u/env -i (wrapping an identity-bearing command)/an empty inline assignment/export -n/` +
625
622
  `declare or typeset +x on ${ADL_AGENT_ID_ENV_VAR} removes the one thing that routes a network git command as this ` +
626
- `agent instead of falling through to bin/git-ado's own default (F1, STATUS.md 12p). Never clear it; prefix the ` +
623
+ `agent instead of falling through to bin/git-ado's own default. Never clear it; prefix the ` +
627
624
  `command with ${ADL_AGENT_ID_ENV_VAR}=<agent> instead. Blocked: ${ctx.snippet}`,
628
625
  }
629
626
  }
@@ -634,7 +631,7 @@ export const adlHumanAzdoBypass: RuleSpec = {
634
631
  user,
635
632
  agent:
636
633
  `DENIED ${user}. These tools exist to make a program's isatty() check pass when nothing real is attached to it — ` +
637
- "bin/git-ado's own human-vs-agent decision is exactly such a check, and faking it (F1, STATUS.md 12p) is how a " +
634
+ "bin/git-ado's own human-vs-agent decision is exactly such a check, and faking it is how a " +
638
635
  'session with no agent identity reaches the human credential path undetected. There is no legitimate use of a ' +
639
636
  `pty-faking wrapper on an agent surface; run the command directly instead. Blocked: ${ctx.snippet}`,
640
637
  }
@@ -645,7 +642,7 @@ export const adlHumanAzdoBypass: RuleSpec = {
645
642
  agent:
646
643
  `DENIED ${user}. ${ADL_HUMAN_AZDO_ENV_VAR}=1 tells bin/git-ado this is Tarun's own interactive terminal - setting, exporting, ` +
647
644
  `or assigning it from an agent surface (inline, export, env, declare/typeset -x, printf -v, read, a nested REAL shell — ` +
648
- `quote-split or backslash-escaped included, F1 — or an interpreter's own os.environ/process.env/$ENV) would let ` +
645
+ `quote-split or backslash-escaped included — or an interpreter's own os.environ/process.env/$ENV) would let ` +
649
646
  `git-ado's human pass-through apply with no agent identity involved. Unset it (or use \`env -u ${ADL_HUMAN_AZDO_ENV_VAR}\`) ` +
650
647
  `if you need it absent; prefix the command with ADL_AGENT_ID_AGENT=<agent-tarun|agent-vivek|agent-reviewer> instead. ` +
651
648
  `Blocked: ${ctx.snippet}`,
@@ -664,7 +661,7 @@ export const adlHumanAzdoBypass: RuleSpec = {
664
661
  `python3 -c "import os; os.environ['ADL_HUMAN_AZDO'] = '1'"`,
665
662
  `node -e "process.env.ADL_HUMAN_AZDO = '1'"`,
666
663
  `node -e "process.env['ADL_HUMAN_AZDO'] = '1'"`,
667
- // F1(a): shell quote-splitting / backslash-escaping cannot defeat the
664
+ // Shell quote-splitting / backslash-escaping cannot defeat the
668
665
  // check any more — the tokenizer resolves both before matching.
669
666
  `export ADL_HUMAN_AZD''O=1`,
670
667
  `export ADL_HUMAN_AZ\\DO=1`,
@@ -675,7 +672,7 @@ export const adlHumanAzdoBypass: RuleSpec = {
675
672
  // also what makes the loop run at all.
676
673
  `printf -v ADL_HUMAN_AZDO '1'; git push origin main`,
677
674
  'read ADL_HUMAN_AZDO',
678
- // F1(b): clearing ADL_AGENT_ID_AGENT in any form.
675
+ // Clearing ADL_AGENT_ID_AGENT in any form.
679
676
  'unset ADL_AGENT_ID_AGENT',
680
677
  'unset ADL_AGENT_ID_AGENT; git push origin feat/x',
681
678
  'env -u ADL_AGENT_ID_AGENT git push origin feat/x',
@@ -686,7 +683,7 @@ export const adlHumanAzdoBypass: RuleSpec = {
686
683
  'ADL_AGENT_ID_AGENT= git push origin feat/x',
687
684
  'export -n ADL_AGENT_ID_AGENT',
688
685
  'declare +x ADL_AGENT_ID_AGENT',
689
- // F1(c): pty-faking wrappers, unconditional.
686
+ // Pty-faking wrappers, unconditional.
690
687
  'script -q /dev/null git push origin feat/x',
691
688
  'unbuffer git push origin feat/x',
692
689
  'expect -c "spawn git push origin feat/x"',
@@ -694,7 +691,7 @@ export const adlHumanAzdoBypass: RuleSpec = {
694
691
  `python3 -c "import pty; pty.spawn(['git','push','origin','feat/x'])"`,
695
692
  'ssh -t localhost git push origin feat/x',
696
693
  'ssh -t 127.0.0.1 git push origin feat/x',
697
- // The live F1 incident, combined.
694
+ // The live bypass found by the independent review, combined.
698
695
  "export ADL_HUMAN_AZD''O=1; unset ADL_AGENT_ID_AGENT; script -q /dev/null git push origin feat/x",
699
696
  ],
700
697
  allow: [
@@ -712,7 +709,7 @@ export const adlHumanAzdoBypass: RuleSpec = {
712
709
  'socat TCP:example.com:80 -',
713
710
  // A bare python/node one-liner naming neither variable: untouched.
714
711
  `python3 -c "print('hello')"`,
715
- // SECOND REVIEW (2026-09-29): the false positives that broke normal
712
+ // False positives a looser scan produced on normal
716
713
  // agent work — a mention of the name in an unrelated command's
717
714
  // argument, a read (not a set), an unrelated `-c` flag mistaken for
718
715
  // shell `-c`, a bare 'pty' word, and env -i clearing the WHOLE
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * `ADL_AGENT_ID_AGENT`, read the same way by every rule that keys behaviour
3
- * off the session's agent identity (docs/operations/agent-permissions.md, docs/architecture/cli-design.md
4
- * decision 2).
3
+ * off the session's agent identity (docs/operations/agent-permissions.md,
4
+ * docs/architecture/cli-design.md §1c).
5
5
  *
6
- * The one-agent-identity standard (STATUS.md 12p)
7
- * makes `packages/azdo/src/lib/agent-identity.ts` the ONE Azure DevOps
8
- * identity resolver in this repo; this file no longer keeps its own copy of
6
+ * The one-agent-identity standard (Tarun, 2026-09-28) makes
7
+ * `packages/azdo/src/lib/agent-identity.ts` the ONE Azure DevOps identity
8
+ * resolver in this repo; this file keeps no copy of
9
9
  * `VALID_AGENTS`/`NO_AGENT_IDENTITY_MESSAGE`/the default-agent-file read — it
10
10
  * imports them, and `BUILDER_AGENTS` derives from `VALID_AGENTS` rather than
11
11
  * naming `AGENT_TARUN`/`AGENT_VIVEK` a second time.
@@ -15,16 +15,13 @@ import {
15
15
  NO_AGENT_IDENTITY_MESSAGE,
16
16
  resolveAgentIdentity,
17
17
  VALID_AGENTS,
18
- type ValidAgent,
19
18
  } from '../../../../azdo/src/lib/agent-identity.ts'
20
19
  import type { EnvPort } from '../ports.ts'
21
20
 
22
- export { isValidAgent, NO_AGENT_IDENTITY_MESSAGE, VALID_AGENTS, type ValidAgent }
21
+ export { isValidAgent, NO_AGENT_IDENTITY_MESSAGE }
23
22
 
24
23
  export const ADL_AGENT_ID_ENV_VAR = 'ADL_AGENT_ID_AGENT'
25
24
  export const AGENT_REVIEWER = 'agent-reviewer'
26
- export const AGENT_TARUN = 'agent-tarun'
27
- export const AGENT_VIVEK = 'agent-vivek'
28
25
 
29
26
  /** The two-branch standard's builders (docs/specs/two-branch-standard-2026-09-27.md §1b.1): cut a feature branch from `integration`, create their own PRs into it. Every VALID_AGENTS member except agent-reviewer. */
30
27
  export const BUILDER_AGENTS: ReadonlySet<string> = new Set(VALID_AGENTS.filter((name) => name !== AGENT_REVIEWER))
@@ -38,21 +35,18 @@ export const BUILDER_AGENTS: ReadonlySet<string> = new Set(VALID_AGENTS.filter((
38
35
  * set it to a path that does not exist -- see `resolveFromEnvOrFile`'s doc.
39
36
  * Never the real system path (AGENTS.md: tests are hermetic).
40
37
  */
41
- export const DEFAULT_AGENT_FILE_OVERRIDE_ENV = 'ADL_DEFAULT_AGENT_FILE'
38
+ const DEFAULT_AGENT_FILE_OVERRIDE_ENV = 'ADL_DEFAULT_AGENT_FILE'
42
39
 
43
- // L3 (STATUS.md 12p): `currentAgent` — the
44
- // session-env-only read this file used to export for
45
- // `../../hooks/lean-ctx/scope-rewrite.ts`'s `sessionIdentityOf` — was
46
- // removed here (not merely superseded) once that caller switched to
40
+ // There is deliberately no session-env-only `currentAgent` read here:
41
+ // `../../hooks/lean-ctx/scope-rewrite.ts`'s `sessionIdentityOf` calls
47
42
  // `resolveFromEnvOrFile` (steps 2-3 of the standard: env, THEN the machine
48
- // default-agent file). It had no other caller left, so it stayed as dead,
49
- // uncovered code rather than a function this file's own contract still
50
- // needs — bunfig.toml's coverage policy has no ignore-list for exactly this
43
+ // default-agent file), so a function that read the env alone would have no
44
+ // caller. bunfig.toml's coverage policy has no ignore-list for exactly this
51
45
  // reason: a function nothing calls gets deleted, not exempted.
52
46
 
53
- export type IdentitySource = 'env' | 'default-file'
47
+ type IdentitySource = 'env' | 'default-file'
54
48
 
55
- export interface ResolvedIdentity {
49
+ interface ResolvedIdentity {
56
50
  readonly ok: true
57
51
  readonly agent: string
58
52
  readonly source: IdentitySource
@@ -68,7 +62,7 @@ export interface ResolvedIdentity {
68
62
  * identity, here is how to set one" is a different problem from "an agent
69
63
  * identity IS configured and it is wrong."
70
64
  */
71
- export interface UnresolvedIdentity {
65
+ interface UnresolvedIdentity {
72
66
  readonly ok: false
73
67
  readonly reason: 'none' | 'invalid'
74
68
  readonly message: string
@@ -77,9 +71,8 @@ export interface UnresolvedIdentity {
77
71
  export type IdentityResolution = ResolvedIdentity | UnresolvedIdentity
78
72
 
79
73
  /**
80
- * Steps 2-3 of the standard (STATUS.md 12p, "The
81
- * standard"): `ADL_AGENT_ID_AGENT` from the session environment, else the
82
- * machine default-agent file, else unresolved. Step 1 (an inline
74
+ * Steps 2-3 of the standard: `ADL_AGENT_ID_AGENT` from the session
75
+ * environment, else the machine default-agent file, else unresolved. Step 1 (an inline
83
76
  * `ADL_AGENT_ID_AGENT=<agent>` prefix on the command itself) is NOT this
84
77
  * function's job — that is a property of the command text, resolved by
85
78
  * `../shell/git-identity.ts`'s scanner, which calls this function only for
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * `adl mcp cli <command> [options]` → the equivalent MCP tool call, for the
3
- * role rules that must grade it EXACTLY like the real MCP tool call (M4,
4
- * STATUS.md 12p): `docs/operations/agent-permissions.md`
3
+ * role rules that must grade it EXACTLY like the real MCP tool call.
4
+ * MCP is the primary route to Azure DevOps operations and `adl mcp cli` is
5
+ * the fallback for when MCP is not working, so both surfaces share one grade:
6
+ * `docs/operations/agent-permissions.md`
5
7
  * gates the tool, not the surface it was invoked through, and `adl mcp cli`
6
8
  * (`packages/azdo/src/cli.ts`'s `runCli`) dispatches to the SAME
7
9
  * `dispatchTool` the MCP server itself calls — a caller who runs
@@ -134,7 +136,7 @@ export function adlMcpCliCall(inv: Invocation): AdlMcpCliCall | null {
134
136
 
135
137
  /**
136
138
  * The `{tool, input}` pair for `inv`, whether it is a real MCP tool-call
137
- * payload or an equivalent `adl mcp cli <command>` shell invocation (M4) —
139
+ * payload or an equivalent `adl mcp cli <command>` shell invocation —
138
140
  * or `null` when `inv` is neither. Every role rule that used to check only
139
141
  * `inv.kind === 'tool-call'` calls this instead, so a caller cannot route
140
142
  * around role grading just by using the CLI form of the same tool.
@@ -145,19 +147,20 @@ export function toolCallFor(inv: Invocation): AdlMcpCliCall | null {
145
147
  }
146
148
 
147
149
  /**
148
- * R5 (STATUS.md 12p, re-review 2026-09-28 night): the
149
- * EFFECTIVE identity for THIS specific `adl mcp cli <command>` invocation —
150
- * the same M2/M3 correlation `impl/adl-git-push-policy.ts`'s
151
- * `effectiveIdentityForPush` already gives `git push`, extended to this
152
- * command class. Before this fix, `adl-workitem-role.ts`/`adl-pr-role.ts`/
153
- * `adl-pr-review-role.ts` graded `resolveFromEnvOrFile(ctx.env)` alone —
154
- * ignoring a valid inline `ADL_AGENT_ID_AGENT=` override on the very piece
155
- * being graded, so a reviewer session's own inline `agent-tarun` override on
156
- * `adl mcp cli workitem-create-or-update` was denied as `agent-reviewer`
157
- * regardless (a false deny), and — the more dangerous direction R5 actually
158
- * names — a `agent-tarun` SESSION with an inline `ADL_AGENT_ID_AGENT=agent-
159
- * reviewer` override was graded as `agent-tarun` (a false ALLOW: the piece
160
- * that will actually run is `agent-reviewer`'s).
150
+ * The EFFECTIVE identity for THIS specific `adl mcp cli <command>`
151
+ * invocation — the same per-piece correlation
152
+ * `impl/adl-git-push-policy.ts`'s `effectiveIdentityForPush` gives
153
+ * `git push`, extended to this command class. The role rules
154
+ * (`adl-workitem-role.ts`/`adl-pr-role.ts`/`adl-pr-review-role.ts`) grade this
155
+ * value, not `resolveFromEnvOrFile(ctx.env)` alone, because a valid inline
156
+ * `ADL_AGENT_ID_AGENT=` override on the very piece being graded wins. Grading
157
+ * the session identity alone would be wrong in both directions: a reviewer
158
+ * session's own inline `agent-tarun` override on
159
+ * `adl mcp cli workitem-create-or-update` would be denied as `agent-reviewer`
160
+ * (a false deny), and — the more dangerous direction — an `agent-tarun`
161
+ * SESSION with an inline `ADL_AGENT_ID_AGENT=agent-reviewer` override would be
162
+ * graded as `agent-tarun` (a false ALLOW: the piece that will actually run is
163
+ * `agent-reviewer`'s).
161
164
  *
162
165
  * A `tool-call`-kind `inv` (a real MCP tool call, not the CLI shell form)
163
166
  * carries no command text at all — no inline override is possible for it —
@@ -36,10 +36,10 @@ export const adlPrCompletePendingDecision: RuleSpec = {
36
36
  severity: 'deny',
37
37
  enabledByDefault: true,
38
38
  summary:
39
- 'Deny PR completion / auto-complete for every identity — open decision (docs/operations/agent-permissions.md row 9) — the MCP tool AND its adl mcp cli equivalent (M4).',
39
+ 'Deny PR completion / auto-complete for every identity — open decision (docs/operations/agent-permissions.md row 9) — the MCP tool AND its adl mcp cli equivalent.',
40
40
  params: noParams,
41
41
  match(inv: Invocation): Finding | null {
42
- // M4 (STATUS.md 12p): `adl mcp cli
42
+ // `adl mcp cli
43
43
  // pr-create-or-update` is the SAME tool `adl.pr-create-update-role`
44
44
  // steps aside for on this shape — without this, the CLI form of a
45
45
  // completion call would sail through both rules.
@@ -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