@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
@@ -9,9 +9,13 @@ nothing to contribute.
9
9
  Four rules, evaluated independently per path (a single path can trip more than
10
10
  one):
11
11
 
12
- 1. root allowlist a file with no `/` must be on the enumerated allowlist
13
- of files legitimately committed at the repository root.
14
- 2. apps/ retired any path under the retired `apps/` tree.
12
+ 1. root allowlist a file with no `/` must be on the allowlist of files
13
+ legitimately committed at the repository root: the
14
+ central set in `policy/root_shape.py` plus whatever the
15
+ repository itself declares (`root-files`).
16
+ 2. apps/ retired any path under the retired `apps/` tree -- unless the
17
+ repository declares `apps` among its root directories
18
+ (`root-dirs`), which says `apps/` is live there.
15
19
  3. stray artifacts a throwaway extension (`.log`/`.tmp`/`.bak`/`.swp`,
16
20
  checked STRICTLY, everywhere) or a screenshot/image
17
21
  basename outside the enumerated asset directories.
@@ -45,7 +49,12 @@ from typing import ClassVar
45
49
  from ....core.check import Check
46
50
  from ....core.context import Context, FileSet
47
51
  from ....core.finding import Report
48
- from ....policy.root_shape import ALLOWED_ROOT_FILES
52
+ from ....policy.root_shape import (
53
+ ALLOWED_ROOT_FILES,
54
+ ROOT_DIRS_DECLARATION,
55
+ allowed_root_files,
56
+ declared_root_names,
57
+ )
49
58
 
50
59
 
51
60
  class Placement(Check):
@@ -62,6 +71,10 @@ class Placement(Check):
62
71
  # `.attributes` and `.ignore`, which LAY-012 had long since corrected to
63
72
  # `.gitattributes` and `.gitignore` — so the same file was permitted by one
64
73
  # gate and reported by the other.
74
+ #
75
+ # This is the CENTRAL default only. What is actually graded is the effective
76
+ # set, `allowed_root_files(ctx.declarations)`: this plus the names the
77
+ # repository declares under `[controls.compliance.root] files`.
65
78
  ROOT_ALLOWLIST: ClassVar[frozenset[str]] = ALLOWED_ROOT_FILES
66
79
 
67
80
  THROWAWAY_SUFFIXES: ClassVar[tuple[str, ...]] = (
@@ -139,24 +152,34 @@ class Placement(Check):
139
152
  )
140
153
 
141
154
  def _md_src_trees(self, ctx: Context) -> tuple[str, ...]:
142
- return self.MD_SRC_TREES_LITERAL + (f"{ctx.relative(ctx.inputs['rust_root'])}/",)
155
+ # Decision for a tree declared absent (`rust = ""`, which drops
156
+ # `rust_root` from the resolved inputs): the rust root only contributes
157
+ # an extra PREFIX to the trees whose `src/` Markdown is reported, so a
158
+ # repository with no Rust tree has nothing under it to report and
159
+ # contributes nothing. The literal `agent/` tree still governs. This read
160
+ # `ctx.inputs['rust_root']` unguarded -- a `KeyError` traceback (exit 1),
161
+ # not a verdict, on any `.md` path.
162
+ rust_root = ctx.inputs.get("rust_root")
163
+ if rust_root is None:
164
+ return self.MD_SRC_TREES_LITERAL
165
+ return self.MD_SRC_TREES_LITERAL + (f"{ctx.relative(rust_root)}/",)
143
166
 
144
167
  def graded(self, ctx: Context, files: FileSet) -> Iterable[Report]:
145
168
  # `LC_ALL=C sort` in the shell is a byte-order sort; Python's default
146
169
  # string ordering matches it for the ASCII repository-relative paths
147
170
  # this row ever sees.
148
171
  for relative in sorted(files):
149
- yield from self._root_allowlist(relative)
150
- yield from self._apps_retired(relative)
172
+ yield from self._root_allowlist(ctx, relative)
173
+ yield from self._apps_retired(ctx, relative)
151
174
  yield from self._stray_artifact(ctx, relative)
152
175
  yield from self._md_sprawl(ctx, relative)
153
176
 
154
177
  # -- Rule 1: root-level allowlist ---------------------------------------
155
178
 
156
- def _root_allowlist(self, relative: str) -> Iterable[Report]:
179
+ def _root_allowlist(self, ctx: Context, relative: str) -> Iterable[Report]:
157
180
  if "/" in relative:
158
181
  return
159
- if relative in self.ROOT_ALLOWLIST:
182
+ if relative in allowed_root_files(ctx.declarations):
160
183
  return
161
184
  # The allowlist is ~60 entries. Printing all of them per finding buries
162
185
  # the one fact the line is reporting, and five findings produced three
@@ -164,13 +187,18 @@ class Placement(Check):
164
187
  yield self.report(
165
188
  relative,
166
189
  f"root: '{relative}' is not on the root allowlist",
167
- f"move '{relative}' into an owning subdirectory, or add it to "
168
- "policy/root_shape.py if it genuinely belongs at the root",
190
+ f"move '{relative}' into an owning subdirectory, or declare it under "
191
+ "[controls.compliance.root] files in this repository's adl-config.toml "
192
+ "if it genuinely belongs at the root",
169
193
  )
170
194
 
171
195
  # -- Rule 2 (numbered 4 in check.sh): apps/ is retired ------------------
172
196
 
173
- def _apps_retired(self, relative: str) -> Iterable[Report]:
197
+ def _apps_retired(self, ctx: Context, relative: str) -> Iterable[Report]:
198
+ # A repository that declares `apps` as a root directory has said `apps/`
199
+ # is live there; "apps is retired" would contradict its own declaration.
200
+ if "apps" in declared_root_names(ctx.declarations, ROOT_DIRS_DECLARATION):
201
+ return
174
202
  if relative.startswith("apps/"):
175
203
  yield self.report(
176
204
  relative,
@@ -228,3 +228,111 @@ def test_a_redeclared_rust_root_still_catches_md_sprawl(tmp_path: pathlib.Path)
228
228
  f"real markdown sprawl under a redeclared rust root went "
229
229
  f"unreported: {findings}"
230
230
  )
231
+
232
+
233
+ # ---------------------------------------------- per-repository root declarations
234
+ def graded_declaring(
235
+ declarations: dict[str, str], paths: tuple[str, ...], root: pathlib.Path = ALLOWED
236
+ ) -> Verdict:
237
+ """`graded_directly`, plus what the repository declared about its own root
238
+ (`[controls.compliance.root]` arrives as the `root-files` / `root-dirs`
239
+ declarations)."""
240
+ ctx = Context(
241
+ root=root, row=ROW, declarations=declarations,
242
+ inputs={
243
+ "docs_root": root / "docs",
244
+ "rust_root": root / "backend",
245
+ "frontend_root": root / "frontend",
246
+ "specs_root": root / ".specs",
247
+ },
248
+ )
249
+ findings = tuple(Placement().graded(ctx, FileSet(paths=paths)))
250
+ return decide(ROW, findings, 0, ())
251
+
252
+
253
+ def test_a_non_standard_root_file_is_reported_without_a_declaration() -> None:
254
+ """STATUS.md is not on the central list any more: without the repository
255
+ declaring it, it is an undeclared root file."""
256
+ verdict = graded_declaring({}, ("STATUS.md",))
257
+ assert verdict.outcome is Outcome.FINDINGS, verdict.render()
258
+ assert [f.path for f in verdict.findings] == ["STATUS.md"]
259
+ assert "root allowlist" in verdict.findings[0].message
260
+
261
+
262
+ def test_a_declared_root_file_is_accepted() -> None:
263
+ verdict = graded_declaring({"root-files": "STATUS.md,DRIFT.md"}, ("STATUS.md", "DRIFT.md"))
264
+ assert verdict.outcome is Outcome.CLEAN, verdict.render()
265
+
266
+
267
+ def test_a_declaration_admits_only_the_names_it_lists() -> None:
268
+ """Without this, the case above also passes against a gate that stops
269
+ grading the root as soon as any declaration is present."""
270
+ verdict = graded_declaring({"root-files": "STATUS.md"}, ("STATUS.md", "DRIFT.md"))
271
+ assert [f.path for f in verdict.findings] == ["DRIFT.md"], verdict.render()
272
+
273
+
274
+ def test_a_root_dirs_declaration_does_not_admit_a_root_file() -> None:
275
+ verdict = graded_declaring({"root-dirs": "STATUS.md"}, ("STATUS.md",))
276
+ assert [f.path for f in verdict.findings] == ["STATUS.md"], verdict.render()
277
+
278
+
279
+ def test_the_root_file_remedy_points_at_the_declaration_not_at_source() -> None:
280
+ """The old remedy sent a reader to edit `policy/root_shape.py` in the shared
281
+ package. The repository owns the declaration, so the remedy names it."""
282
+ finding = graded_declaring({}, ("STATUS.md",)).findings[0]
283
+ assert "[controls.compliance.root]" in finding.fix, finding.fix
284
+ assert "adl-config.toml" in finding.fix, finding.fix
285
+ assert "root_shape.py" not in finding.fix, finding.fix
286
+
287
+
288
+ def test_apps_stays_retired_unless_the_repository_declares_it() -> None:
289
+ """The retired-`apps/` rule is active by default, and declaring a DIFFERENT
290
+ directory does not switch it off."""
291
+ for declarations in ({}, {"root-dirs": "packaging"}, {"root-files": "apps"}):
292
+ verdict = graded_declaring(declarations, ("apps/legacy/file.ts",))
293
+ assert [f.path for f in verdict.findings] == ["apps/legacy/file.ts"], declarations
294
+ assert "apps-retired" in verdict.findings[0].message
295
+
296
+
297
+ def test_a_declared_apps_directory_is_not_retired() -> None:
298
+ """A declared `apps/` contradicts "apps is retired", so the rule stands down."""
299
+ for declarations in ({"root-dirs": "apps"}, {"root-dirs": "packaging, apps"}):
300
+ verdict = graded_declaring(declarations, ("apps/legacy/file.ts", "apps/cli/src/main.ts"))
301
+ assert verdict.outcome is Outcome.CLEAN, (declarations, verdict.render())
302
+
303
+
304
+ def test_enact_config_is_a_built_in_root_file_beside_adl_config() -> None:
305
+ """Owner decision (Tarun, 2026-10-01): an adl-controlled Enact repository
306
+ carries BOTH `adl-config.toml` and `enact-config.toml` at its root,
307
+ permanently. Neither is declared by hand under `[controls.compliance.root]`."""
308
+ verdict = graded_declaring({}, ("adl-config.toml", "enact-config.toml"))
309
+ assert verdict.outcome is Outcome.CLEAN, verdict.render()
310
+
311
+
312
+ def test_an_unknown_root_toml_still_fails_beside_enact_config() -> None:
313
+ """Without this, the case above also passes against a gate that admits
314
+ every root `.toml`."""
315
+ verdict = graded_declaring({}, ("enact-config.toml", "random.toml"))
316
+ assert [f.path for f in verdict.findings] == ["random.toml"], verdict.render()
317
+
318
+
319
+ # ------------------------------------------------- a tree declared absent
320
+ def test_a_rust_tree_declared_absent_contributes_nothing_to_md_sprawl(
321
+ tmp_path: pathlib.Path,
322
+ ) -> None:
323
+ """`rust = ""` (the repository states it has no Rust tree) drops `rust_root`
324
+ from the resolved inputs. In `_md_src_trees` that input only ever ADDS a
325
+ prefix to the trees whose `src/` Markdown is reported, so absent it
326
+ contributes nothing and the literal `agent/` tree still governs. This was a
327
+ `KeyError: 'rust_root'` traceback (exit 1, not could-not-run) on any `.md`
328
+ path, measured against enact-combined with `--tree rust= --tree frontend=`.
329
+ The rule is not switched off: `agent/**/src/*.md` is still reported."""
330
+ ctx = Context(root=tmp_path, row=ROW, inputs={"docs_root": tmp_path / "docs"})
331
+ findings = tuple(
332
+ Placement().graded(
333
+ ctx,
334
+ FileSet(paths=("notes/overview.md", "backend/crates/x/src/n.md", "agent/crates/x/src/n.md")),
335
+ )
336
+ )
337
+ assert [f.path for f in findings] == ["agent/crates/x/src/n.md"], findings
338
+ assert "md-sprawl" in findings[0].message
@@ -14,7 +14,7 @@ from __future__ import annotations
14
14
 
15
15
  import pathlib
16
16
 
17
- from helpers import corpus, corpus_files
17
+ from helpers import corpus
18
18
 
19
19
  from adl_compliance.checks.layout.plans_layout import PlansLayout
20
20
  from adl_compliance.core.context import Context, FileSet
@@ -62,9 +62,8 @@ class References(Check):
62
62
  # Was "LAY-010" — the neighbouring gate's id, so every broken-link finding printed
63
63
  # under `layout.profile-data` and sent a reader chasing a Rust migration-filename
64
64
  # rule. Third instance of the defect 58866d2 fixed for LAY-008, and its test pinned
65
- # it the same way. (`layout/profile_data` carries the same shape DELIBERATELY: its
66
- # docstring explains it is a faithful carry of a shell-source mismatch whose own
67
- # test.sh asserts LAY-009. This one had no such justification anywhere in the file.)
65
+ # it the same way. (The gate that owned LAY-010, `layout.profile-data`, was retired
66
+ # 2026-10-01, so no gate answers to that id now.)
68
67
  rule: ClassVar[str] = "LAY-011"
69
68
 
70
69
  # This gate's own values, and no other module's business. Shared values are
@@ -23,8 +23,13 @@ line:
23
23
  which skips it for the same reason (not restated there beyond
24
24
  the `continue`).
25
25
 
26
- ALLOWED_FILES and ALLOWED_DIRS are the closed set itself: named requirements,
27
- not scope, and the list cannot grow with the tree.
26
+ ALLOWED_FILES and ALLOWED_DIRS are the CENTRAL closed set: named requirements,
27
+ not scope, and the list cannot grow with the tree. What is graded is the
28
+ effective set -- the central one plus the names the repository declares under
29
+ `[controls.compliance.root]` in its own adl-config.toml (`files`, `dirs`), which
30
+ reach this gate as `Context.declarations["root-files" | "root-dirs"]`. A
31
+ non-standard root entry is declared by the repository that has it, never added
32
+ here.
28
33
 
29
34
  Ported from `compliance_new/checks/layout/root-closed-set/check.sh` with one
30
35
  correction verified against that script's own fixture and against this
@@ -58,6 +63,8 @@ from ....policy.root_shape import (
58
63
  ALLOWED_ROOT_DIRS,
59
64
  ALLOWED_ROOT_FILES,
60
65
  REQUIRED_ROOT_FILES,
66
+ allowed_root_dirs,
67
+ allowed_root_files,
61
68
  )
62
69
 
63
70
 
@@ -86,12 +93,18 @@ class RootClosedSet(Check):
86
93
  # config module states the principle these lists were breaking: "a path
87
94
  # outside this package, written inside it, is a dependency on this
88
95
  # particular checkout's shape."
96
+ #
97
+ # The CENTRAL default. The effective set is
98
+ # `allowed_root_files(ctx.declarations)`, computed at grade time.
89
99
  ALLOWED_FILES: ClassVar[frozenset[str]] = ALLOWED_ROOT_FILES
90
100
 
91
101
  # PERMITTED at the root, same as the files above: present is fine, absent
92
102
  # is fine. Several entries here name trees no longer in use anywhere
93
103
  # (`.code-review-graph_old`, `.plans`, `.specs`) and they cost nothing while
94
104
  # they only permit; under the old manifest reading, each was a finding.
105
+ #
106
+ # The CENTRAL default. The effective set is
107
+ # `allowed_root_dirs(ctx.declarations)`, computed at grade time.
95
108
  ALLOWED_DIRS: ClassVar[frozenset[str]] = ALLOWED_ROOT_DIRS
96
109
 
97
110
  # What a repository must actually HAVE at its root, as opposed to what it
@@ -121,15 +134,19 @@ class RootClosedSet(Check):
121
134
  else:
122
135
  root_files.add(path)
123
136
 
137
+ allowed_dirs = allowed_root_dirs(ctx.declarations)
138
+ allowed_files = allowed_root_files(ctx.declarations)
124
139
  for name in sorted(dirs):
125
- if name not in self.ALLOWED_DIRS:
140
+ if name not in allowed_dirs:
126
141
  yield self.report(
127
142
  name, "undeclared top-level directory",
128
- f"declare {name}/ in ALLOWED_DIRS, or move it into an owning tree",
143
+ f"declare {name} under [controls.compliance.root] dirs in this "
144
+ "repository's adl-config.toml, or move it into an owning tree",
129
145
  )
130
146
  for name in sorted(root_files):
131
- if name not in self.ALLOWED_FILES:
147
+ if name not in allowed_files:
132
148
  yield self.report(
133
149
  name, "undeclared top-level file",
134
- f"declare {name} in ALLOWED_FILES, or move it into an owning tree",
150
+ f"declare {name} under [controls.compliance.root] files in this "
151
+ "repository's adl-config.toml, or move it into an owning tree",
135
152
  )
@@ -120,3 +120,79 @@ def test_the_structural_half_still_runs_on_an_empty_set() -> None:
120
120
  still a clean verdict."""
121
121
  verdict = verdict_for(())
122
122
  assert verdict.outcome is Outcome.CLEAN, verdict.render()
123
+
124
+
125
+ # ---------------------------------------------- per-repository root declarations
126
+ def verdict_declaring(declarations: dict[str, str], given: tuple[str, ...]) -> Verdict:
127
+ """`verdict_for`, plus what the repository declared about its own root
128
+ (`[controls.compliance.root]` arrives as the `root-files` / `root-dirs`
129
+ declarations)."""
130
+ ctx = Context(root=CORPUS, row=ROW, declarations=declarations)
131
+ findings = tuple(
132
+ r for r in RootClosedSet().run(ctx, FileSet(paths=given)) if isinstance(r, Finding)
133
+ )
134
+ return decide(ROW, findings, 0, ())
135
+
136
+
137
+ def test_a_non_standard_root_directory_is_undeclared_without_a_declaration() -> None:
138
+ """`apps/` and `packaging/` are not on the central list any more."""
139
+ for name in ("apps", "packaging"):
140
+ verdict = verdict_declaring({}, (f"{name}/cli/main.ts",))
141
+ assert verdict.outcome is Outcome.FINDINGS, verdict.render()
142
+ assert [f.path for f in verdict.findings] == [name], verdict.render()
143
+ assert f"{name}: undeclared top-level directory" in verdict.render()
144
+
145
+
146
+ def test_a_declared_root_directory_is_accepted() -> None:
147
+ verdict = verdict_declaring(
148
+ {"root-dirs": "apps,packaging"}, ("apps/cli/main.ts", "packaging/npm/package.json"),
149
+ )
150
+ assert verdict.outcome is Outcome.CLEAN, verdict.render()
151
+
152
+
153
+ def test_a_non_standard_root_file_is_undeclared_without_a_declaration() -> None:
154
+ """STATUS.md and DRIFT.md are not on the central list any more."""
155
+ for name in ("STATUS.md", "DRIFT.md"):
156
+ verdict = verdict_declaring({}, (name,))
157
+ assert [f.path for f in verdict.findings] == [name], verdict.render()
158
+ assert f"{name}: undeclared top-level file" in verdict.render()
159
+
160
+
161
+ def test_a_declared_root_file_is_accepted() -> None:
162
+ verdict = verdict_declaring({"root-files": "STATUS.md, DRIFT.md"}, ("STATUS.md", "DRIFT.md"))
163
+ assert verdict.outcome is Outcome.CLEAN, verdict.render()
164
+
165
+
166
+ def test_a_declaration_does_not_silence_the_rest_of_the_root() -> None:
167
+ """Without this, the accept cases above also pass against a gate that stops
168
+ grading the root once any declaration is present."""
169
+ verdict = verdict_declaring(
170
+ {"root-dirs": "apps", "root-files": "STATUS.md"},
171
+ ("apps/cli/main.ts", "STATUS.md", "unapproved-root/x.md", "undeclared-root-file.txt"),
172
+ )
173
+ assert sorted(f.path for f in verdict.findings) == [
174
+ "unapproved-root", "undeclared-root-file.txt",
175
+ ], verdict.render()
176
+
177
+
178
+ def test_the_files_and_dirs_declarations_do_not_cross() -> None:
179
+ """A name declared as a directory does not admit a file of that name, and
180
+ the other way round."""
181
+ dirs_only = verdict_declaring({"root-dirs": "thing"}, ("thing",))
182
+ assert [f.path for f in dirs_only.findings] == ["thing"], dirs_only.render()
183
+ files_only = verdict_declaring({"root-files": "thing"}, ("thing/x.ts",))
184
+ assert [f.path for f in files_only.findings] == ["thing"], files_only.render()
185
+
186
+
187
+ def test_the_remedies_point_at_the_declaration_not_at_source() -> None:
188
+ """The old remedies said "declare X in ALLOWED_DIRS/ALLOWED_FILES" -- a
189
+ constant in the shared package. The repository owns the declaration."""
190
+ by_path = {
191
+ f.path: f for f in verdict_declaring({}, ("apps/cli/main.ts", "STATUS.md")).findings
192
+ }
193
+ directory, file = by_path["apps"], by_path["STATUS.md"]
194
+ for finding, key in ((directory, "dirs"), (file, "files")):
195
+ assert "[controls.compliance.root]" in finding.fix, finding.fix
196
+ assert "adl-config.toml" in finding.fix, finding.fix
197
+ assert key in finding.fix, finding.fix
198
+ assert "ALLOWED_" not in finding.fix, finding.fix
@@ -32,7 +32,13 @@ from typing import ClassVar
32
32
  from ....core.check import Check
33
33
  from ....core.context import Context, FileSet
34
34
  from ....core.finding import Report
35
- from ....policy.root_shape import GOVERNANCE, GUIDES, REGISTERS
35
+ from ....policy.root_shape import (
36
+ GOVERNANCE,
37
+ GUIDES,
38
+ REGISTERS,
39
+ ROOT_FILES_DECLARATION,
40
+ declared_root_names,
41
+ )
36
42
 
37
43
 
38
44
  class RootMarkdownAllowlist(Check):
@@ -64,7 +70,12 @@ class RootMarkdownAllowlist(Check):
64
70
  # that does exist at `plans/AGENTS.md` went unseen while a phantom one was
65
71
  # demanded. The rule is about trees being documented, not about these exact
66
72
  # paths being present.
67
- GUIDED_TREES: ClassVar[tuple[str, ...]] = (".workflows", "plans", "specs", "docs")
73
+ #
74
+ # `.workflows/` is deliberately not listed (owner decision, 2026-10-01): it is
75
+ # a machine-managed tree, written wholesale by `adl-repo-controls install` and
76
+ # never hand-authored, so it does not need a guide of its own. A guide that
77
+ # does exist there is still admitted by `_allowed_markdown`.
78
+ GUIDED_TREES: ClassVar[tuple[str, ...]] = ("plans", "specs", "docs")
68
79
 
69
80
  # Trees whose Markdown this repository does not author: vendored provider
70
81
  # documentation, and archives kept for reference. Renaming a README inside
@@ -199,8 +210,10 @@ class RootMarkdownAllowlist(Check):
199
210
  path,
200
211
  "tracked Markdown is outside the root allowlist",
201
212
  f"move {path} under an allowed tree (docs/, plans/, .specs/, "
202
- ".changeset/, etc.), or add an explicit exception in "
203
- "check.py if it is a legitimate case",
213
+ ".changeset/, etc.), or, if it is a root-level Markdown file "
214
+ "this repository genuinely carries, declare it under "
215
+ "[controls.compliance.root] files in this repository's "
216
+ "adl-config.toml",
204
217
  )
205
218
 
206
219
  def _allowed_markdown(self, ctx: Context, path: str) -> bool:
@@ -209,17 +222,27 @@ class RootMarkdownAllowlist(Check):
209
222
  # ADR-095 admits this one root-relative verification contract by
210
223
  # literal name.
211
224
  #
212
- # `policy/root_shape.py` is THE list of what may sit at a repository's
225
+ # `policy/root_shape.py` is THE list of what may sit at EVERY repository's
213
226
  # root — GUIDES (AGENTS.md/CLAUDE.md/INVARIANTS.md/…), GOVERNANCE
214
227
  # (CONTRIBUTING.md/SECURITY.md/…) and REGISTERS (GAPS-AND-FINDINGS.md,
215
- # OPEN-ITEMS.md, STATUS.md, DRIFT.md). This gate used to carry its own
216
- # copy of that same set, hardcoded here, and the two had already
217
- # drifted apart once (STATUS.md/DRIFT.md were on neither copy). Import
228
+ # OPEN-ITEMS.md). This gate used to carry its own copy of that same set,
229
+ # hardcoded here, and the copies had already drifted apart once. Import
218
230
  # rather than duplicate, exactly as `layout.markdown-trees` and
219
231
  # `layout.placement` already do — one policy, not a fourth copy of it.
220
232
  # (Tarun, 2026-09-27.)
233
+ #
234
+ # Root Markdown that is NOT standard (a repository's own STATUS.md,
235
+ # DRIFT.md) is not on that list: the repository declares it under
236
+ # `[controls.compliance.root] files`, and it arrives below as the
237
+ # `root-files` declaration. That lookup must stay AFTER this short-circuit —
238
+ # the central names are answered without a Context at all
239
+ # (tests/core/test_root_shape.py passes `ctx=None`).
221
240
  if path in (GUIDES | GOVERNANCE | REGISTERS):
222
241
  return True
242
+ if "/" not in path and path in declared_root_names(
243
+ ctx.declarations, ROOT_FILES_DECLARATION
244
+ ):
245
+ return True
223
246
  # Ported from check-markdown-placement.py: any AGENTS.md/CLAUDE.md
224
247
  # guide file is allowed regardless of folder — the AGENTS.md/CLAUDE.md
225
248
  # hierarchy is governed separately by layout.agents-layout.
@@ -260,11 +283,25 @@ class RootMarkdownAllowlist(Check):
260
283
  # above).
261
284
  if path in self.GOVERNANCE_FILES or path in self.RETAINED_MARKDOWN_FILES:
262
285
  return True
263
- rust_root = ctx.relative(ctx.inputs["rust_root"])
264
- frontend_root = ctx.relative(ctx.inputs["frontend_root"])
265
- if path in {f"{rust_root}/{suffix}" for suffix in self.RUST_GOVERNANCE_SUFFIXES}:
286
+ # Decision for a tree declared absent (`rust = ""` / `frontend = ""`, which
287
+ # drops `rust_root` / `frontend_root` from the resolved inputs): both only
288
+ # ever ADD allowlist entries -- the governance suffixes and code-asset
289
+ # roots beneath the tree -- so a repository with no such tree has nothing
290
+ # there to admit and they contribute nothing. Strictly stricter, never a
291
+ # silent pass. These were read unguarded (`ctx.inputs["rust_root"]`): a
292
+ # stray root Markdown file, which every allowance above declines, reached
293
+ # them and raised `KeyError` -- a traceback with exit 1, not a verdict.
294
+ rust_input = ctx.inputs.get("rust_root")
295
+ rust_root = None if rust_input is None else ctx.relative(rust_input)
296
+ frontend_input = ctx.inputs.get("frontend_root")
297
+ frontend_root = None if frontend_input is None else ctx.relative(frontend_input)
298
+ if rust_root is not None and path in {
299
+ f"{rust_root}/{suffix}" for suffix in self.RUST_GOVERNANCE_SUFFIXES
300
+ }:
266
301
  return True
267
- if path in {f"{frontend_root}/{suffix}" for suffix in self.FRONTEND_GOVERNANCE_SUFFIXES}:
302
+ if frontend_root is not None and path in {
303
+ f"{frontend_root}/{suffix}" for suffix in self.FRONTEND_GOVERNANCE_SUFFIXES
304
+ }:
268
305
  return True
269
306
  if path in {f"{workflows_root}/{suffix}" for suffix in self.WORKFLOWS_GOVERNANCE_SUFFIXES}:
270
307
  return True
@@ -272,19 +309,23 @@ class RootMarkdownAllowlist(Check):
272
309
  return True
273
310
  if any(path.startswith(code_root) for code_root in self.CODE_ASSET_ROOTS):
274
311
  return True
275
- if any(
312
+ if rust_root is not None and any(
276
313
  path.startswith(f"{rust_root}/{suffix}") for suffix in self.RUST_CODE_ASSET_SUFFIXES
277
314
  ):
278
315
  return True
279
- if any(
316
+ if frontend_root is not None and any(
280
317
  path.startswith(f"{frontend_root}/{suffix}")
281
318
  for suffix in self.FRONTEND_CODE_ASSET_SUFFIXES
282
319
  ):
283
320
  return True
284
321
  name = path.rsplit("/", 1)[-1]
285
- if name in self.FRONTEND_LOCAL_DOC_NAMES and any(
286
- path.startswith(f"{frontend_root}/{suffix}")
287
- for suffix in self.FRONTEND_LOCAL_DOC_SUFFIXES
322
+ if (
323
+ frontend_root is not None
324
+ and name in self.FRONTEND_LOCAL_DOC_NAMES
325
+ and any(
326
+ path.startswith(f"{frontend_root}/{suffix}")
327
+ for suffix in self.FRONTEND_LOCAL_DOC_SUFFIXES
328
+ )
288
329
  ):
289
330
  return True
290
331
  return False