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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (410) hide show
  1. package/bin/adl +2 -2
  2. package/bin/git +16 -17
  3. package/bin/git-ado +25 -24
  4. package/bin/git-defaults +173 -0
  5. package/bin/health-check +8 -1
  6. package/bin/kimi-hooks +1 -1
  7. package/bin/lib/adl-package.sh +257 -0
  8. package/bin/lib/fleet-host.sh +8 -5
  9. package/bin/reconcile +482 -232
  10. package/bin/reconcile-host +30 -20
  11. package/bin/setup +20 -17
  12. package/bin/shell-path-policy +15 -5
  13. package/bin/sync-and-reconcile +62 -64
  14. package/bin/validate-manifest +33 -9
  15. package/package.json +2 -10
  16. package/packages/agent-hooks/README.md +14 -9
  17. package/packages/agent-hooks/assets/hooks.json +0 -20
  18. package/packages/agent-hooks/src/cli/args.ts +1 -1
  19. package/packages/agent-hooks/src/cli/doctor.ts +6 -58
  20. package/packages/agent-hooks/src/deploy/deploy.ts +12 -41
  21. package/packages/agent-hooks/src/deploy/doctor.ts +8 -11
  22. package/packages/agent-hooks/src/deploy/index.ts +14 -14
  23. package/packages/agent-hooks/src/deploy/json-merge.ts +7 -8
  24. package/packages/agent-hooks/src/deploy/legacy-lock.ts +2 -2
  25. package/packages/agent-hooks/src/deploy/list.ts +1 -1
  26. package/packages/agent-hooks/src/deploy/lock.ts +31 -12
  27. package/packages/agent-hooks/src/deploy/profile.ts +3 -4
  28. package/packages/agent-hooks/src/deploy/source.ts +1 -1
  29. package/packages/agent-hooks/src/gating/config.ts +12 -24
  30. package/packages/agent-hooks/src/gating/root.ts +3 -3
  31. package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
  32. package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
  33. package/packages/agent-hooks/src/hooks/contract.ts +17 -17
  34. package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
  35. package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
  36. package/packages/agent-hooks/src/hooks/log.ts +8 -10
  37. package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
  38. package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
  39. package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
  40. package/packages/agent-hooks/src/hosts/registry.ts +1 -1
  41. package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
  42. package/packages/agent-hooks/src/log/writer.ts +16 -2
  43. package/packages/agent-hooks/src/main.ts +7 -41
  44. package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
  45. package/packages/agent-hooks/src/rules/engine.ts +13 -17
  46. package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
  47. package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
  48. package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
  49. package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
  50. package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
  51. package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
  52. package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
  53. package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
  54. package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
  55. package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
  56. package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
  57. package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
  58. package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
  59. package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
  60. package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +131 -0
  61. package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
  62. package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
  63. package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
  64. package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
  65. package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
  66. package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
  67. package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
  68. package/packages/agent-hooks/src/rules/impl/tool-grep.ts +33 -12
  69. package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
  70. package/packages/agent-hooks/src/rules/ports.ts +5 -7
  71. package/packages/agent-hooks/src/rules/registry.ts +4 -6
  72. package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
  73. package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
  74. package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
  75. package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
  76. package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
  77. package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
  78. package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
  79. package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
  80. package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
  81. package/packages/agent-hooks/src/rules/spec.ts +2 -2
  82. package/packages/agent-settings/README.md +287 -0
  83. package/packages/agent-settings/assets/GLOBAL-AGENTS.md +14 -16
  84. package/packages/agent-settings/assets/agents/architect.toml +2 -0
  85. package/packages/agent-settings/assets/agents/code-reviewer.toml +2 -0
  86. package/packages/agent-settings/assets/agents/executor.toml +2 -0
  87. package/packages/agent-settings/assets/agents/explore.toml +2 -0
  88. package/packages/agent-settings/assets/agents/planner.toml +2 -0
  89. package/packages/agent-settings/assets/mcp.json +0 -4
  90. package/packages/agent-settings/deploy-profile.json +139 -0
  91. package/packages/agent-settings/deploy-profile.schema.json +147 -0
  92. package/packages/agent-settings/managed/README.md +29 -30
  93. package/packages/agent-settings/managed/codex-requirements.toml +9 -9
  94. package/packages/agent-settings/package.json +20 -0
  95. package/packages/agent-settings/src/deploy/agent-render.ts +2 -2
  96. package/packages/agent-settings/src/deploy/agent-toml.ts +1 -1
  97. package/packages/agent-settings/src/deploy/agents-deploy.ts +17 -3
  98. package/packages/agent-settings/src/deploy/doctor.ts +3 -83
  99. package/packages/agent-settings/src/deploy/index.ts +6 -33
  100. package/packages/agent-settings/src/deploy/legacy-lock.ts +6 -6
  101. package/packages/agent-settings/src/deploy/list.ts +5 -19
  102. package/packages/agent-settings/src/deploy/lock.ts +8 -18
  103. package/packages/agent-settings/src/deploy/mcp-deploy.ts +10 -5
  104. package/packages/agent-settings/src/deploy/mcp-merge.ts +22 -3
  105. package/packages/agent-settings/src/deploy/mcp-source.ts +1 -1
  106. package/packages/agent-settings/src/deploy/profile.ts +11 -35
  107. package/packages/agent-settings/src/deploy/retire-lean-ctx.ts +184 -0
  108. package/packages/agent-settings/src/deploy/settings.ts +17 -22
  109. package/packages/agent-settings/src/global-surface-sweep.ts +0 -2
  110. package/packages/agent-settings/src/kimi-hooks.ts +339 -192
  111. package/packages/agent-settings/src/opencode-hooks.ts +1 -1
  112. package/packages/agent-settings/tsconfig.json +23 -0
  113. package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +120 -0
  114. package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +276 -0
  115. package/packages/agent-skills/assets/debug-issue/SKILL.md +8 -7
  116. package/packages/agent-skills/assets/explore-codebase/SKILL.md +13 -13
  117. package/packages/agent-skills/assets/refactor-safely/SKILL.md +12 -11
  118. package/packages/agent-skills/assets/review-changes/SKILL.md +7 -7
  119. package/packages/agent-skills/assets/testing/references/e2e.md +37 -0
  120. package/packages/agent-skills/assets/testing/references/integration.md +37 -0
  121. package/packages/agent-skills/assets/testing/references/unit.md +32 -0
  122. package/packages/agent-skills/dist/deploy.d.ts +2 -0
  123. package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
  124. package/packages/agent-skills/dist/deploy.js +27 -1
  125. package/packages/agent-skills/dist/deploy.js.map +1 -1
  126. package/packages/agent-skills/dist/doctor.d.ts +0 -2
  127. package/packages/agent-skills/dist/doctor.d.ts.map +1 -1
  128. package/packages/agent-skills/dist/doctor.js +1 -1
  129. package/packages/agent-skills/dist/doctor.js.map +1 -1
  130. package/packages/agent-skills/dist/fs-utils.d.ts +0 -1
  131. package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -1
  132. package/packages/agent-skills/dist/fs-utils.js +1 -1
  133. package/packages/agent-skills/dist/fs-utils.js.map +1 -1
  134. package/packages/agent-skills/src/deploy.ts +29 -1
  135. package/packages/agent-skills/src/doctor.ts +1 -1
  136. package/packages/agent-skills/src/fs-utils.ts +1 -1
  137. package/packages/azdo/README.md +10 -9
  138. package/packages/azdo/package.json +1 -3
  139. package/packages/azdo/scripts/probe-ado-rules.ts +311 -0
  140. package/packages/azdo/src/azdo-pl.ts +2 -54
  141. package/packages/azdo/src/azdo-pr-review.ts +4 -4
  142. package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
  143. package/packages/azdo/src/azdo-wit.ts +44 -2
  144. package/packages/azdo/src/lib/agent-identity.ts +12 -14
  145. package/packages/azdo/src/lib/agent-token.ts +2 -2
  146. package/packages/azdo/src/lib/client.ts +0 -5
  147. package/packages/azdo/src/lib/graph-identity.ts +4 -4
  148. package/packages/azdo/src/workflow-ladder.csv +241 -0
  149. package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
  150. package/packages/azdo/src/workflow-rules.ts +194 -0
  151. package/packages/fleet/manifest.json +35 -11
  152. package/packages/fleet/manifest.schema.json +62 -10
  153. package/packages/fleet/src/default-agent-file.ts +3 -3
  154. package/packages/fleet/src/install-adl-package.ts +73 -15
  155. package/packages/fleet/src/install-embedding-model.ts +13 -13
  156. package/packages/fleet/src/managed-settings.ts +7 -7
  157. package/packages/fleet/src/repo-maintain.ts +91 -55
  158. package/packages/fleet/src/scratch-reap.ts +5 -5
  159. package/packages/fleet/src/vscode-settings.ts +5 -5
  160. package/packages/repo-controls/README.md +141 -43
  161. package/packages/repo-controls/assets/promote.ts +4 -4
  162. package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
  163. package/packages/repo-controls/assets/version-bump.sh +31 -84
  164. package/packages/repo-controls/bunfig.toml +6 -7
  165. package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
  166. package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
  167. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
  168. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
  169. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
  170. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
  171. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
  172. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
  173. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/c.md +1 -0
  174. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/d.md +1 -0
  175. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
  176. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
  177. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
  178. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
  179. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
  180. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
  181. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/sub/nested.md +1 -0
  182. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
  183. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
  184. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
  185. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
  186. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
  187. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
  188. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
  189. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
  190. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
  191. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
  192. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
  193. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
  194. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-001-tenancy.md +1 -0
  195. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-002-carrier.md +1 -0
  196. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-003-cli.md +1 -0
  197. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-old.md +1 -0
  198. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-older.md +1 -0
  199. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
  200. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
  201. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
  202. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
  203. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-01.md +1 -0
  204. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-02.md +1 -0
  205. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-03.md +1 -0
  206. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-04.md +1 -0
  207. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-05.md +1 -0
  208. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-06.md +1 -0
  209. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-07.md +1 -0
  210. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-08.md +1 -0
  211. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-09.md +1 -0
  212. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-10.md +1 -0
  213. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-11.md +1 -0
  214. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-12.md +1 -0
  215. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-13.md +1 -0
  216. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-14.md +1 -0
  217. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-15.md +1 -0
  218. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-16.md +1 -0
  219. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
  220. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
  221. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
  222. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
  223. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
  224. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
  225. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
  226. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
  227. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
  228. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/a.md +1 -0
  229. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/b.md +1 -0
  230. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/c.md +1 -0
  231. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/d.md +1 -0
  232. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/e.md +1 -0
  233. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
  234. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/a.md +1 -0
  235. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/b.md +1 -0
  236. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/c.md +1 -0
  237. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/short/only.md +1 -0
  238. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
  239. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
  240. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
  241. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
  242. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
  243. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
  244. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
  245. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
  246. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
  247. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
  248. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
  249. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
  250. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
  251. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
  252. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
  253. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
  254. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
  255. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
  256. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
  257. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
  258. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
  259. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
  260. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
  261. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
  262. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
  263. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
  264. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
  265. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
  266. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
  267. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
  268. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
  269. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
  270. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
  271. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
  272. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
  273. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
  274. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
  275. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
  276. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-legacy/docs/compliance/index.md +10 -0
  277. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-type/docs/compliance/index.md +10 -0
  278. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
  279. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
  280. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
  281. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
  282. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
  283. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
  284. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
  285. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
  286. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/no-type.md +9 -0
  287. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-experiment.md +10 -0
  288. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-research.md +10 -0
  289. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
  290. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs/architecture/bad-status.md +0 -1
  291. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
  292. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
  293. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
  294. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
  295. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
  296. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
  297. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-last-update.md +11 -0
  298. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
  299. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
  300. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
  301. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
  302. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
  303. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/created-date.md +21 -0
  304. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/research-shaped.md +19 -0
  305. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
  306. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
  307. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
  308. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
  309. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
  310. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
  311. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
  312. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/a.ts +1 -0
  313. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/b.ts +1 -0
  314. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
  315. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
  316. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
  317. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
  318. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/a.ts +1 -0
  319. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/b.ts +1 -0
  320. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/c.ts +1 -0
  321. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
  322. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
  323. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
  324. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
  325. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
  326. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
  327. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
  328. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
  329. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
  330. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
  331. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
  332. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +258 -2
  333. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
  334. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
  335. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plan_metadata.py +9 -4
  336. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/check.py +1 -1
  337. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/items/az351-restore-entrypoint.md +1 -1
  338. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +3 -3
  339. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
  340. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
  341. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
  342. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
  343. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
  344. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
  345. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
  346. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
  347. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
  348. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
  349. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
  350. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
  351. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
  352. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
  353. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
  354. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
  355. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
  356. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
  357. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
  358. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
  359. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
  360. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
  361. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
  362. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
  363. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
  364. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
  365. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
  366. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
  367. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
  368. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
  369. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
  370. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
  371. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
  372. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
  373. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
  374. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
  375. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
  376. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
  377. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
  378. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
  379. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
  380. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
  381. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
  382. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
  383. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
  384. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
  385. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
  386. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
  387. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
  388. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
  389. package/packages/repo-controls/package.json +2 -9
  390. package/packages/repo-controls/scripts/hooks/post-merge +13 -0
  391. package/packages/repo-controls/scripts/hooks/pre-push +3 -3
  392. package/packages/repo-controls/src/azdo-push.ts +64 -36
  393. package/packages/repo-controls/src/azure-devops-governance.ts +7 -9
  394. package/packages/repo-controls/src/azure-devops-remote.ts +1 -1
  395. package/packages/repo-controls/src/cli.ts +29 -8
  396. package/packages/repo-controls/src/compliance-config.ts +410 -2
  397. package/packages/repo-controls/src/config.ts +133 -60
  398. package/packages/repo-controls/src/constants.ts +13 -27
  399. package/packages/repo-controls/src/coverage-ratchet.ts +4 -4
  400. package/packages/repo-controls/src/doctor.ts +46 -19
  401. package/packages/repo-controls/src/gitignore-block.ts +5 -29
  402. package/packages/repo-controls/src/hook-log.ts +1 -2
  403. package/packages/repo-controls/src/hook.ts +201 -45
  404. package/packages/repo-controls/src/install.ts +14 -8
  405. package/packages/repo-controls/src/integrity.ts +3 -3
  406. package/packages/repo-controls/src/lfs.ts +111 -0
  407. package/packages/repo-controls/src/promote.ts +8 -8
  408. package/packages/repo-controls/src/runtime.ts +9 -1
  409. package/packages/repo-controls/src/workflows-drift.ts +4 -5
  410. package/packages/repo-controls/src/worktree-guard.ts +3 -3
@@ -17,6 +17,115 @@ export interface ComplianceConfig {
17
17
  * outright until this key existed.
18
18
  */
19
19
  declarations: Record<string, string>
20
+ /**
21
+ * Root-level names this repository adds to the engine's standard root allow-list,
22
+ * from `[controls.compliance.root]`. OMITTED (not `undefined`-valued, not empty)
23
+ * when the repository declares no `root` table, so a repository that declares
24
+ * nothing parses to exactly the shape it always did. `hook.ts` turns each
25
+ * non-empty list into one `--declare root-files=a,b` / `root-dirs=x,y` flag.
26
+ */
27
+ root?: RootDeclaration
28
+ /**
29
+ * Engine limits this repository sets for itself, from `[controls.compliance.limits]`.
30
+ * OMITTED (not `undefined`-valued) when the repository declares no `limits` table,
31
+ * for the same whole-object-shape reason as `root`. A key absent inside the table
32
+ * keeps the engine's own default. `hook.ts` turns a set `scripts_direct_files`,
33
+ * `open_gaps` and `open_plans` into `--declare scripts-direct-files=<n>`,
34
+ * `--declare open-gaps=<n>` and `--declare open-plans=<n>`.
35
+ */
36
+ limits?: LimitsDeclaration
37
+ /**
38
+ * Extra Markdown roots this repository declares, from `[controls.compliance.markdown]`.
39
+ * OMITTED (not `undefined`-valued) when the repository declares no `markdown` table,
40
+ * for the same whole-object-shape reason as `root` and `limits`. `hook.ts` turns a
41
+ * non-empty `roots` into one `--declare markdown-roots=a,b` flag.
42
+ */
43
+ markdown?: MarkdownDeclaration
44
+ /**
45
+ * The manifest and lockfile paths REP-002 scans and grades, from
46
+ * `[controls.compliance.lockfiles]`. OMITTED (not `undefined`-valued) when the
47
+ * repository declares no `lockfiles` table, for the same whole-object-shape reason
48
+ * as `root`, `limits` and `markdown`. `hook.ts` turns each non-empty list into one
49
+ * `--declare bun-manifests=a,b` (and `bun-lockfiles`, `cargo-manifests`,
50
+ * `cargo-lockfiles`) flag.
51
+ */
52
+ lockfiles?: LockfilesDeclaration
53
+ /**
54
+ * LAY-004's per-tree direct-file ceilings, from `[controls.compliance.directory-ratchet]`.
55
+ * OMITTED (not `undefined`-valued) when the repository declares no
56
+ * `directory-ratchet` table, for the same whole-object-shape reason as `root`,
57
+ * `limits`, `markdown` and `lockfiles`. `hook.ts` turns a non-empty `max_children`
58
+ * into one `--declare directory-ceilings=<path>:<n>,<path>:<n>` flag, entries sorted
59
+ * for deterministic argv.
60
+ */
61
+ directory_ratchet?: DirectoryRatchetDeclaration
62
+ }
63
+
64
+ /**
65
+ * `[controls.compliance.directory-ratchet]`: LAY-004's RULE — the per-tree
66
+ * direct-file ceilings, configuration the generic ratchet principle
67
+ * (2026-10-02) moved out of the register, which records state (exemption
68
+ * baselines) only. A ceiling is `max_children.<path> = <n>`: every directory
69
+ * at or below `<path>` (measured per directory) may hold at most `<n>` direct
70
+ * files unless the register records an exemption. Defaults to empty (nothing
71
+ * configured: the gate is inert, the same "no configuration = nothing to
72
+ * enforce" reading DOC-012's cap has).
73
+ */
74
+ interface DirectoryRatchetDeclaration {
75
+ /** Repo-relative tree path -> its direct-file ceiling (a positive integer). */
76
+ max_children: Record<string, number>
77
+ }
78
+
79
+ /**
80
+ * `[controls.compliance.lockfiles]`: exactly which paths REP-002 scans and grades. An
81
+ * ecosystem (Bun, Cargo) is declared as a PAIR, a manifests list and a lockfiles list,
82
+ * and a declared pair REPLACES that ecosystem's tree-derived default, in what selects the
83
+ * gate and in what it grades. All four default to empty (nothing declared: the default).
84
+ */
85
+ interface LockfilesDeclaration {
86
+ /** `package.json` paths or globs, e.g. `package.json`, `apps/*\/package.json`. */
87
+ bun_manifests: string[]
88
+ /** Literal `bun.lock` paths; each must exist and be non-empty. */
89
+ bun_lockfiles: string[]
90
+ /** `Cargo.toml` paths or globs. */
91
+ cargo_manifests: string[]
92
+ /** Literal `Cargo.lock` paths; each one's directory is the cargo workspace graded. */
93
+ cargo_lockfiles: string[]
94
+ }
95
+
96
+ /** The four keys, in the order `hook.ts` sends them: the Bun pair, then the Cargo pair. */
97
+ export const LOCKFILE_KEYS = ['bun_manifests', 'bun_lockfiles', 'cargo_manifests', 'cargo_lockfiles'] as const
98
+
99
+ /**
100
+ * `[controls.compliance.markdown]`: directories whose Markdown is site or application
101
+ * content rather than documentation (an Astro site's `src/content/**\/*.md`). LAY-006
102
+ * admits Markdown beneath each in addition to the docs trees, so a declared root only
103
+ * ever widens its allowlist. Defaults to empty.
104
+ */
105
+ interface MarkdownDeclaration {
106
+ /** Repository-relative directories, trailing `/` normalised away. */
107
+ roots: string[]
108
+ }
109
+
110
+ /** `[controls.compliance.root]`: names directly under the repository root. Both lists default to empty. */
111
+ interface RootDeclaration {
112
+ files: string[]
113
+ dirs: string[]
114
+ }
115
+
116
+ /**
117
+ * `[controls.compliance.limits]`: engine limits a repository overrides. Every key
118
+ * is optional and, absent, leaves the engine default in force.
119
+ */
120
+ interface LimitsDeclaration {
121
+ /** LAY-014's direct-file limit per scripts directory. The engine default is 15. */
122
+ scripts_direct_files?: number
123
+ /** LAY-016's cap on open gaps in the gap register. The engine default is 10. */
124
+ open_gaps?: number
125
+ /** LAY-016's cap on open plans (Features). Independent of `open_gaps`. The engine default is 10. */
126
+ open_plans?: number
127
+ /** DOC-012's page cap per docs/ directory. The engine default is 15. */
128
+ docs_pages_per_directory?: number
20
129
  }
21
130
 
22
131
  /**
@@ -36,7 +145,7 @@ const ENABLED_SEED_COMMENT = `# Nothing is graded until a gate is named here. A
36
145
  # the packaged defaults are shaped after the repo these checks were authored
37
146
  # against, so an enabled row with unpointed trees grades the wrong files.`
38
147
 
39
- export const SEEDED_COMPLIANCE_ATTRIBUTES: SeededAttribute[] = [
148
+ const SEEDED_COMPLIANCE_ATTRIBUTES: SeededAttribute[] = [
40
149
  {
41
150
  key: 'enabled',
42
151
  text: `${ENABLED_SEED_COMMENT}
@@ -105,7 +214,11 @@ export function parseComplianceConfig(text: string): ComplianceConfig {
105
214
  const compliance = controls.compliance
106
215
 
107
216
  const problems = new Problems()
108
- problems.unknownKeys(compliance, ['enabled', 'registry', 'trees', 'inputs', 'license'], '')
217
+ problems.unknownKeys(
218
+ compliance,
219
+ ['enabled', 'registry', 'trees', 'inputs', 'license', 'root', 'limits', 'markdown', 'lockfiles', 'directory-ratchet'],
220
+ '',
221
+ )
109
222
 
110
223
  // Absent is the documented default, never an error: install seeds only `version`
111
224
  // and `enabled`, and `registry`/`trees` both have working defaults. Present but the
@@ -127,6 +240,18 @@ export function parseComplianceConfig(text: string): ComplianceConfig {
127
240
  }
128
241
 
129
242
  const config: ComplianceConfig = { enabled, registry, trees, inputs, declarations }
243
+ // Assigned only when declared: an `undefined`-valued key would still change the
244
+ // shape every whole-object comparison of a root-less repository sees.
245
+ if (compliance.root !== undefined) config.root = parseRoot(compliance.root, problems)
246
+ if (compliance.limits !== undefined) config.limits = parseLimits(compliance.limits, problems)
247
+ if (compliance.markdown !== undefined) config.markdown = parseMarkdown(compliance.markdown, problems)
248
+ if (compliance.lockfiles !== undefined) {
249
+ config.lockfiles = parseLockfiles(compliance.lockfiles, problems)
250
+ rejectSupersededInputs(config.lockfiles, inputs, problems)
251
+ }
252
+ if (compliance['directory-ratchet'] !== undefined) {
253
+ config.directory_ratchet = parseDirectoryRatchet(compliance['directory-ratchet'], problems)
254
+ }
130
255
  if (problems.list.length > 0) {
131
256
  throw new Error(`${CONFIG_REL} is invalid:\n - ${problems.list.join('\n - ')}`)
132
257
  }
@@ -193,6 +318,289 @@ function parseTrees(
193
318
  return trees
194
319
  }
195
320
 
321
+ /**
322
+ * A root entry is a NAME directly under the repository root, and the whole list
323
+ * travels to the engine as ONE comma-separated `--declare root-files=a,b` value.
324
+ * So a name may not contain `,` (it would split into two names), `=` (it collides
325
+ * with `--declare name=value`'s own separator) or `/` and `..` (a root name is not
326
+ * a path: either would escape the root or reach below it). Empty and
327
+ * whitespace-only names are refused because the engine rejects an empty item.
328
+ */
329
+ const ROOT_NAME_FORBIDDEN = /[,/=]|\.\./
330
+
331
+ function parseRoot(value: unknown, problems: Problems): RootDeclaration {
332
+ const root: RootDeclaration = { files: [], dirs: [] }
333
+ if (!isTable(value)) {
334
+ problems.add('root must be a table')
335
+ return root
336
+ }
337
+ problems.unknownKeys(value, ['files', 'dirs'], 'root.')
338
+ for (const key of ['files', 'dirs'] as const) {
339
+ const list = value[key]
340
+ if (list === undefined) continue
341
+ if (!Array.isArray(list)) {
342
+ problems.add(`root.${key} must be an array of strings`)
343
+ continue
344
+ }
345
+ list.forEach((item: unknown, index) => {
346
+ const label = `root.${key}[${index}]`
347
+ if (typeof item !== 'string') problems.add(`${label} must be a string`)
348
+ else if (item.trim() === '') problems.add(`${label} must not be empty`)
349
+ else if (ROOT_NAME_FORBIDDEN.test(item)) problems.add(`${label} must not contain ',', '/', '=' or '..'`)
350
+ else root[key].push(item)
351
+ })
352
+ }
353
+ return root
354
+ }
355
+
356
+ const LIMIT_KEYS = ['scripts_direct_files', 'open_gaps', 'open_plans', 'docs_pages_per_directory'] as const
357
+
358
+ /**
359
+ * Each limit travels to the engine as `--declare <name>=N` (`scripts-direct-files`,
360
+ * `open-gaps`, `open-plans`, `docs-pages-per-directory`) and the engine refuses
361
+ * anything but a base-10 positive integer, so the same set is refused here,
362
+ * naming the key. A TOML float with an integral value (`20.0`) reaches this
363
+ * point as the number 20 — the parser does not keep the distinction — and is
364
+ * accepted as 20.
365
+ */
366
+ function parseLimits(value: unknown, problems: Problems): LimitsDeclaration {
367
+ const limits: LimitsDeclaration = {}
368
+ if (!isTable(value)) {
369
+ problems.add('limits must be a table')
370
+ return limits
371
+ }
372
+ problems.unknownKeys(value, [...LIMIT_KEYS], 'limits.')
373
+ for (const key of LIMIT_KEYS) {
374
+ const limit = value[key]
375
+ if (limit === undefined) continue
376
+ if (typeof limit !== 'number' || !Number.isSafeInteger(limit) || limit < 1) {
377
+ problems.add(`limits.${key} must be a positive integer`)
378
+ } else {
379
+ limits[key] = limit
380
+ }
381
+ }
382
+ return limits
383
+ }
384
+
385
+ /**
386
+ * A markdown root is a repository-relative DIRECTORY, and the whole list travels to the
387
+ * engine as ONE comma-separated `--declare markdown-roots=a,b` value. So an entry may not
388
+ * contain `,` (it would split into two roots) or `=` (it collides with `--declare
389
+ * name=value`'s own separator), may not be absolute, and may not carry a `.`, `..` or
390
+ * empty path segment -- none of those names a directory this repository owns, and the
391
+ * engine refuses them as could-not-run because a declared root can only WIDEN LAY-006's
392
+ * allowlist. Surrounding whitespace and trailing `/` are normalised away, the same way
393
+ * the engine reads the comma list.
394
+ */
395
+ const MARKDOWN_ROOT_FORBIDDEN = /[,=]/
396
+
397
+ function parseMarkdown(value: unknown, problems: Problems): MarkdownDeclaration {
398
+ const markdown: MarkdownDeclaration = { roots: [] }
399
+ if (!isTable(value)) {
400
+ problems.add('markdown must be a table')
401
+ return markdown
402
+ }
403
+ problems.unknownKeys(value, ['roots'], 'markdown.')
404
+ const list = value.roots
405
+ if (list === undefined) return markdown
406
+ if (!Array.isArray(list)) {
407
+ problems.add('markdown.roots must be an array of strings')
408
+ return markdown
409
+ }
410
+ list.forEach((item: unknown, index) => {
411
+ const label = `markdown.roots[${index}]`
412
+ if (typeof item !== 'string') {
413
+ problems.add(`${label} must be a string`)
414
+ return
415
+ }
416
+ const trimmed = item.trim()
417
+ if (trimmed === '') {
418
+ problems.add(`${label} must not be empty`)
419
+ return
420
+ }
421
+ const root = trimmed.replace(/\/+$/, '')
422
+ const notADirectory = trimmed.startsWith('/') || root.split('/').some((part) => part === '' || part === '.' || part === '..')
423
+ if (MARKDOWN_ROOT_FORBIDDEN.test(root) || notADirectory) {
424
+ problems.add(
425
+ `${label} must be a repository-relative directory without a leading '/', a '.', '..' or empty segment, ',' or '='`,
426
+ )
427
+ return
428
+ }
429
+ markdown.roots.push(root)
430
+ })
431
+ return markdown
432
+ }
433
+
434
+ /**
435
+ * The two ecosystems REP-002 grades, with the file name every manifest entry must end in
436
+ * and the per-gate inputs a declared pair supersedes.
437
+ */
438
+ const LOCKFILE_HALVES = [
439
+ {
440
+ manifests: 'bun_manifests',
441
+ lockfiles: 'bun_lockfiles',
442
+ manifestName: 'package.json',
443
+ inputs: ['REP-002:bun_lock'],
444
+ },
445
+ {
446
+ manifests: 'cargo_manifests',
447
+ lockfiles: 'cargo_lockfiles',
448
+ manifestName: 'Cargo.toml',
449
+ inputs: ['REP-002:cargo_lock', 'REP-002:cargo_manifest', 'REP-002:workspace'],
450
+ },
451
+ ] as const
452
+
453
+ /**
454
+ * Entries travel to the engine as ONE comma-separated `--declare` value, so `,` would split
455
+ * one path in two and `=` collides with `--declare name=value`'s own separator. A backslash,
456
+ * `<`, `>`, `{` and `}` are not path characters here: a `<tree>` placeholder, a brace union
457
+ * and a leading `!` negation are scope SYNTAX, and an entry that carried one would mean more
458
+ * or less than the repository wrote. The engine refuses the same set as could-not-run.
459
+ */
460
+ const LOCKFILE_ENTRY_FORBIDDEN = /[,=\\<>{}]/
461
+ const LOCKFILE_GLOB_CHARS = /[*?[\]]/
462
+
463
+ /** Is `entry` NOT a path REP-002 can scan? `manifestName` is null for a lockfile entry (a literal path). */
464
+ function lockfileEntryRefused(entry: string, manifestName: string | null): boolean {
465
+ if (LOCKFILE_ENTRY_FORBIDDEN.test(entry) || entry.startsWith('/') || entry.startsWith('!')) return true
466
+ const segments = entry.split('/')
467
+ if (segments.some((part) => part === '' || part === '.' || part === '..')) return true
468
+ if (manifestName !== null) return segments[segments.length - 1] !== manifestName
469
+ return LOCKFILE_GLOB_CHARS.test(entry)
470
+ }
471
+
472
+ // A ceiling path is repository-relative and travels to the engine INSIDE one
473
+ // comma-separated `--declare directory-ceilings=<path>:<n>,...` value, so it
474
+ // may not contain `,` (the list separator), `:` or `=` (collisions with the
475
+ // entry and declare separators), a leading `/` or `!`, or a `.`, `..` or empty
476
+ // segment — none of those names a tree this repository owns, and the engine
477
+ // refuses them as could-not-run.
478
+ const CEILING_PATH_FORBIDDEN = /[,:=]/
479
+
480
+ /**
481
+ * `[controls.compliance.directory-ratchet]`: LAY-004's configured ceilings.
482
+ * The engine reads each `<path>:<n>` entry with the same base-10 positive
483
+ * integer rule as the limits, so the same set is refused here, naming the
484
+ * path.
485
+ */
486
+ function parseDirectoryRatchet(value: unknown, problems: Problems): DirectoryRatchetDeclaration {
487
+ const ratchet: DirectoryRatchetDeclaration = { max_children: {} }
488
+ if (!isTable(value)) {
489
+ problems.add('directory-ratchet must be a table')
490
+ return ratchet
491
+ }
492
+ problems.unknownKeys(value, ['max_children'], 'directory-ratchet.')
493
+ const ceilings = value.max_children
494
+ if (ceilings === undefined) return ratchet
495
+ if (!isTable(ceilings)) {
496
+ problems.add('directory-ratchet.max_children must be a table')
497
+ return ratchet
498
+ }
499
+ for (const [path, ceiling] of Object.entries(ceilings)) {
500
+ const label = `directory-ratchet.max_children.${path}`
501
+ if (typeof ceiling !== 'number' || !Number.isSafeInteger(ceiling) || ceiling < 1) {
502
+ problems.add(`${label} must be a positive integer`)
503
+ continue
504
+ }
505
+ if (CEILING_PATH_FORBIDDEN.test(path) || path.startsWith('/') || path.startsWith('!')) {
506
+ problems.add(`${label} must be a repository-relative path without a leading '/' or '!', or any of ',', ':', '='`)
507
+ continue
508
+ }
509
+ if (path.split('/').some((part) => part === '' || part === '.' || part === '..')) {
510
+ problems.add(`${label} must be a repository-relative path without a '.', '..' or empty segment`)
511
+ continue
512
+ }
513
+ ratchet.max_children[path] = ceiling
514
+ }
515
+ return ratchet
516
+ }
517
+
518
+ function parseLockfiles(value: unknown, problems: Problems): LockfilesDeclaration {
519
+ const lockfiles: LockfilesDeclaration = { bun_manifests: [], bun_lockfiles: [], cargo_manifests: [], cargo_lockfiles: [] }
520
+ if (!isTable(value)) {
521
+ problems.add('lockfiles must be a table')
522
+ return lockfiles
523
+ }
524
+ problems.unknownKeys(value, [...LOCKFILE_KEYS], 'lockfiles.')
525
+ for (const half of LOCKFILE_HALVES) {
526
+ const broken = new Set<string>()
527
+ for (const [key, manifestName] of [
528
+ [half.manifests, half.manifestName],
529
+ [half.lockfiles, null],
530
+ ] as const) {
531
+ const list = value[key]
532
+ if (list === undefined) continue
533
+ if (!Array.isArray(list)) {
534
+ problems.add(`lockfiles.${key} must be an array of strings`)
535
+ broken.add(key)
536
+ continue
537
+ }
538
+ const seen = new Map<string, number>()
539
+ list.forEach((item: unknown, index) => {
540
+ const label = `lockfiles.${key}[${index}]`
541
+ if (typeof item !== 'string') {
542
+ problems.add(`${label} must be a string`)
543
+ broken.add(key)
544
+ return
545
+ }
546
+ const entry = item.trim()
547
+ if (entry === '') {
548
+ problems.add(`${label} must not be empty`)
549
+ broken.add(key)
550
+ return
551
+ }
552
+ if (lockfileEntryRefused(entry, manifestName)) {
553
+ problems.add(
554
+ manifestName === null
555
+ ? `${label} must be a literal repository-relative file path without a leading '/' or '!', a '.', '..' or empty segment, a glob character ('*', '?', '[', ']'), or any of ',', '=', '\\', '<', '>', '{', '}'`
556
+ : `${label} must be a repository-relative path or glob ending in ${manifestName}, without a leading '/' or '!', a '.', '..' or empty segment, or any of ',', '=', '\\', '<', '>', '{', '}'`,
557
+ )
558
+ broken.add(key)
559
+ return
560
+ }
561
+ const first = seen.get(entry)
562
+ if (first !== undefined) {
563
+ problems.add(`${label} duplicates lockfiles.${key}[${first}]`)
564
+ broken.add(key)
565
+ return
566
+ }
567
+ seen.set(entry, index)
568
+ lockfiles[key].push(entry)
569
+ })
570
+ }
571
+ // A half is declared as a pair. One list without the other would leave the engine
572
+ // guessing which default the missing list takes, and the engine refuses it too. Skipped
573
+ // when either list already has a problem: that is the one to fix first.
574
+ const hasManifests = lockfiles[half.manifests].length > 0
575
+ const hasLockfiles = lockfiles[half.lockfiles].length > 0
576
+ if (hasManifests !== hasLockfiles && !broken.has(half.manifests) && !broken.has(half.lockfiles)) {
577
+ const [present, missing] = hasManifests ? [half.manifests, half.lockfiles] : [half.lockfiles, half.manifests]
578
+ problems.add(`lockfiles.${present} is declared without lockfiles.${missing}: a half is declared as a pair`)
579
+ }
580
+ }
581
+ return lockfiles
582
+ }
583
+
584
+ /**
585
+ * `REP-002:<name>` inputs are the per-gate overrides a declared pair supersedes: the engine
586
+ * grades a declared half from its declaration and never consults them. Left in place they
587
+ * would be silently ignored, so the combination is refused.
588
+ */
589
+ function rejectSupersededInputs(
590
+ lockfiles: LockfilesDeclaration,
591
+ inputs: Record<string, string>,
592
+ problems: Problems,
593
+ ): void {
594
+ for (const half of LOCKFILE_HALVES) {
595
+ if (lockfiles[half.manifests].length === 0 || lockfiles[half.lockfiles].length === 0) continue
596
+ for (const input of half.inputs) {
597
+ if (input in inputs) {
598
+ problems.add(`inputs.${input} is superseded by lockfiles.${half.lockfiles}; remove the input`)
599
+ }
600
+ }
601
+ }
602
+ }
603
+
196
604
  export function loadComplianceConfig(repo: string): ComplianceConfig {
197
605
  const path = join(repo, CONFIG_REL)
198
606
  if (!existsSync(path)) throw new Error(`${CONFIG_REL} is missing — ${INSTALL_HINT}`)