@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
@@ -0,0 +1,194 @@
1
+ """DOC-011 — every Markdown page under docs/ has a lower-kebab stem.
2
+
3
+ The rule being tested, restated from the gate's own docstring:
4
+
5
+ for every `.md` file in scope, the filename stem must full-match
6
+ `^[a-z0-9]+(-[a-z0-9]+)*$`, with exact-name exemptions for the standing
7
+ tree guides `AGENTS.md` and `CLAUDE.md`. Non-`.md` files are not graded
8
+ at all -- docs trees legitimately hold .png/.html/.csv/.yaml assets, and
9
+ the rule is about page names, not asset names.
10
+
11
+ Ported in the same shape `docs/closed_set/test_check.py` uses: ONE corpus,
12
+ and the clean case is the same tree with the violating entries left out of
13
+ the given set -- exactly what a commit touching nothing violating looks like
14
+ in production.
15
+
16
+ Every test calls `DocsFilename` directly rather than through `runner.run`/
17
+ `decide`, bypassing row-scope narrowing and registry lookup; the row is still
18
+ loaded from the real registry because it is the Context's `row`. The row's
19
+ scope excludes (`proposals/`, `compliance/`, guides, `index.md`) are the
20
+ runner's business and are proven by the end-to-end CLI runs recorded in
21
+ `docs/operations/repo-controls-copy-notes.md`, not replayed here -- this
22
+ corpus deliberately carries no fixture for them.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ from helpers import corpus, corpus_files
28
+
29
+ from adl_compliance.checks.docs.filename import DocsFilename
30
+ from adl_compliance.core.context import Context, FileSet
31
+ from adl_compliance.core.finding import Finding
32
+ from adl_compliance.policy.registry import load
33
+
34
+ CORPUS = corpus("docs", "filename")
35
+ ROW = load().by_id("DOC-011")
36
+
37
+ # Every violation shape the rule names, kept out of the clean set.
38
+ VIOLATING = (
39
+ "docs/research/UI-CONTRACT.md",
40
+ "docs/architecture/user_profile.md",
41
+ "docs/architecture/getting started.md",
42
+ "docs/architecture/-leading-hyphen.md",
43
+ "docs/architecture/trailing-hyphen-.md",
44
+ "docs/architecture/double--hyphen.md",
45
+ )
46
+
47
+ # In the corpus, never findings: exempt guide names (root and nested),
48
+ # the standing catalog/ledger names, non-Markdown assets (including one
49
+ # with a deliberately violating stem), and a path that merely lookalikes
50
+ # the docs/ prefix.
51
+ NOT_FINDINGS = (
52
+ "docs.md",
53
+ "docs/AGENTS.md",
54
+ "docs/CLAUDE.md",
55
+ "docs/architecture/AGENTS.md",
56
+ "docs/index.md",
57
+ "docs/notes.md",
58
+ "docs/reference.html",
59
+ "docs/assets/diagram.png",
60
+ "docs/assets/UI-CONTRACT.png",
61
+ )
62
+
63
+ CONFORMING = (
64
+ "docs/architecture/ui-contract.md",
65
+ "docs/architecture/nested/page-here.md",
66
+ "docs/research/2026-10-experiment.md",
67
+ )
68
+
69
+
70
+ def clean_set() -> tuple[str, ...]:
71
+ return tuple(p for p in corpus_files(CORPUS) if p not in VIOLATING)
72
+
73
+
74
+ def findings_for(given: tuple[str, ...]) -> tuple[Finding, ...]:
75
+ ctx = Context(root=CORPUS, row=ROW, inputs={"docs_root": CORPUS / "docs"})
76
+ return tuple(DocsFilename().run(ctx, FileSet(paths=given)))
77
+
78
+
79
+ def messages_for(given: tuple[str, ...]) -> tuple[str, ...]:
80
+ return tuple(f.render() for f in findings_for(given))
81
+
82
+
83
+ def test_the_premise_holds() -> None:
84
+ """Asserted, not assumed: a mistyped path would leave the clean set
85
+ identical to the full corpus and every case below would agree for
86
+ nothing."""
87
+ all_files = corpus_files(CORPUS)
88
+ for path in (*VIOLATING, *NOT_FINDINGS, *CONFORMING):
89
+ assert path in all_files, path
90
+ assert len(clean_set()) == len(all_files) - len(VIOLATING)
91
+
92
+
93
+ def test_conforming_stems_are_silent() -> None:
94
+ findings = findings_for(clean_set())
95
+ assert findings == (), tuple(f.render() for f in findings)
96
+
97
+
98
+ def test_an_uppercase_stem_is_reported() -> None:
99
+ """The real consumer case: the Enact tree carries
100
+ docs/architecture/frontend/UI-CONTRACT.md; the gate must name it.
101
+ (The fixture sits under research/ because this checkout's filesystem
102
+ is case-insensitive and cannot hold it beside the lowercase
103
+ ui-contract.md in the same directory.)"""
104
+ messages = messages_for(corpus_files(CORPUS))
105
+ assert any(
106
+ "docs/research/UI-CONTRACT.md" in m and "is not lower-kebab" in m
107
+ for m in messages
108
+ ), messages
109
+
110
+
111
+ def test_an_underscored_stem_is_reported() -> None:
112
+ messages = messages_for(corpus_files(CORPUS))
113
+ assert any("user_profile.md" in m for m in messages), messages
114
+
115
+
116
+ def test_a_spaced_stem_is_reported() -> None:
117
+ messages = messages_for(corpus_files(CORPUS))
118
+ assert any("getting started.md" in m for m in messages), messages
119
+
120
+
121
+ def test_a_leading_hyphen_is_reported() -> None:
122
+ """A leading hyphen makes the first run empty; full-match fails."""
123
+ messages = messages_for(corpus_files(CORPUS))
124
+ assert any("-leading-hyphen.md" in m for m in messages), messages
125
+
126
+
127
+ def test_a_trailing_hyphen_is_reported() -> None:
128
+ """A trailing hyphen makes the last run empty; full-match fails."""
129
+ messages = messages_for(corpus_files(CORPUS))
130
+ assert any("trailing-hyphen-.md" in m for m in messages), messages
131
+
132
+
133
+ def test_a_double_hyphen_is_reported() -> None:
134
+ """A double hyphen leaves an empty segment between the dashes; the
135
+ `(?:-[a-z0-9]+)*` repeat cannot cross it."""
136
+ messages = messages_for(corpus_files(CORPUS))
137
+ assert any("double--hyphen.md" in m for m in messages), messages
138
+
139
+
140
+ def test_guide_names_are_exempt_at_any_depth() -> None:
141
+ """AGENTS.md and CLAUDE.md are the standing tree-guide names the other
142
+ docs gates exclude too; the exemption is by exact name, so it holds in
143
+ nested directories as well as at the docs root."""
144
+ text = "\n".join(messages_for(corpus_files(CORPUS)))
145
+ assert "docs/AGENTS.md" not in text
146
+ assert "docs/CLAUDE.md" not in text
147
+ assert "docs/architecture/AGENTS.md" not in text
148
+
149
+
150
+ def test_the_standing_page_names_are_silent() -> None:
151
+ """`index.md` (the standing catalog name, also scope-excluded) and
152
+ `notes.md` (the task ledger) carry conforming stems; both stay silent."""
153
+ text = "\n".join(messages_for(corpus_files(CORPUS)))
154
+ assert "docs/index.md" not in text
155
+ assert "docs/notes.md" not in text
156
+
157
+
158
+ def test_non_markdown_files_are_not_graded() -> None:
159
+ """The rule grades `.md` pages only. `docs/assets/UI-CONTRACT.png` pins
160
+ the sharp edge: a violating STEM in a non-Markdown file is not a
161
+ finding, or every diagram beside a UI contract page would fail."""
162
+ text = "\n".join(messages_for(corpus_files(CORPUS)))
163
+ assert "docs/reference.html" not in text
164
+ assert "docs/assets/diagram.png" not in text
165
+ assert "docs/assets/UI-CONTRACT.png" not in text
166
+
167
+
168
+ def test_every_finding_is_tagged_doc_011() -> None:
169
+ findings = findings_for(corpus_files(CORPUS))
170
+ assert findings
171
+ assert all(f.rule == "DOC-011" for f in findings), tuple(
172
+ f.render() for f in findings
173
+ )
174
+
175
+
176
+ def test_a_lookalike_prefix_is_ignored() -> None:
177
+ """`docs.md` is a root-level file whose name is the tree name plus the
178
+ extension; the gate's prefix carries a trailing slash, so it is outside
179
+ docs/ entirely."""
180
+ assert "docs.md" in corpus_files(CORPUS)
181
+ text = "\n".join(messages_for(corpus_files(CORPUS)))
182
+ assert "docs.md" not in text
183
+
184
+
185
+ def test_an_empty_set_grades_nothing() -> None:
186
+ """Every violating stem is still on disk. A check that grades only what
187
+ it is handed must report none of them against an empty given set."""
188
+ findings = findings_for(())
189
+ assert findings == ()
190
+
191
+
192
+ def test_a_path_outside_docs_is_ignored() -> None:
193
+ findings = findings_for(("documentation/UI-CONTRACT.md",))
194
+ assert findings == ()
@@ -17,8 +17,20 @@ THIS repository and what each one governs, and this gate means nothing without
17
17
  it — so it ships as a `resources` entry beside this check (co-located with the
18
18
  gate, per `compliance_new/AGENTS.md`'s "a named input lives in the gate's own
19
19
  folder"), not fetched from the consumer's tree by path. `docs-knowledge-indexes
20
- .yaml` here is transcribed byte-for-byte from
21
- `compliance_new/checks/docs/indexes/docs-knowledge-indexes.yaml` (2026-08-29).
20
+ .yaml` was transcribed byte-for-byte from
21
+ `compliance_new/checks/docs/indexes/docs-knowledge-indexes.yaml` (2026-08-29),
22
+ with one later amendment recorded here rather than left as drift: on
23
+ 2026-10-02 the docs-compliance and docs-product entries' `required_frontmatter`
24
+ flipped `document_type` → `type`. The estate's frontmatter vocabulary is the
25
+ OKF profile's — `docs-okf-profiles.yaml`'s `common_required` is
26
+ `[type, title, description, status]` and no profile knows a `document_type`
27
+ key — and twelve of this register's sixteen catalogues already required
28
+ `type` (the other two require no type-family key); these two were the last
29
+ outliers, and an index satisfying every other
30
+ catalogue's vocabulary failed them for a key nothing else in the estate
31
+ writes. The flip is pinned by the `knowledge-indexes-shipped-register-
32
+ {type,legacy}/` corpora in `test_check.py`, which point the `registry` input
33
+ at this shipped file instead of a cut-down fixture copy.
22
34
 
23
35
  Entirely `graded`: every rule here reads the GIVEN SET, even the ones that look
24
36
  at the register alone — an entry the given set never touches is not audited at
@@ -138,7 +138,7 @@ indexes:
138
138
  include_extensions: [.md]
139
139
  exclude_names: [index.md, AGENTS.md, CLAUDE.md]
140
140
  exclude_prefixes: [product/]
141
- required_frontmatter: [title, description, document_type, status, last_update, reason]
141
+ required_frontmatter: [type, title, description, status, last_update, sources, related]
142
142
  required_sections: [Reading order]
143
143
  display_status: true
144
144
  status_map: {draft: draft, stable: stable}
@@ -150,7 +150,7 @@ indexes:
150
150
  recursive: true
151
151
  include_extensions: [.md]
152
152
  exclude_names: [index.md, AGENTS.md, CLAUDE.md]
153
- required_frontmatter: [title, description, document_type, status, last_update, reason]
153
+ required_frontmatter: [title, description, status, last_update, sources, created]
154
154
  required_sections: []
155
155
  display_status: true
156
156
  status_map: {draft: draft, canonical: canonical, stable: stable}
@@ -162,7 +162,7 @@ indexes:
162
162
  recursive: true
163
163
  include_extensions: [.md, .yaml, .yml]
164
164
  exclude_names: [index.md, AGENTS.md, CLAUDE.md]
165
- required_frontmatter: [title, description, document_type, status, last_update, reason]
165
+ required_frontmatter: [title, description, type, status, last_update, reason]
166
166
  required_sections: []
167
167
  display_status: true
168
168
  status_map: {canonical: stable, draft: draft, '-': metadata}
@@ -174,7 +174,7 @@ indexes:
174
174
  recursive: false
175
175
  include_extensions: [.md]
176
176
  exclude_names: [index.md, AGENTS.md, CLAUDE.md]
177
- required_frontmatter: [title, description, document_type, status, last_update, reason]
177
+ required_frontmatter: [type, title, description, status, last_update, sources, related]
178
178
  required_sections: []
179
179
  display_status: true
180
180
  status_map: {draft: draft, stable: stable}
@@ -186,7 +186,7 @@ indexes:
186
186
  recursive: true
187
187
  include_extensions: [.md]
188
188
  exclude_names: [index.md, AGENTS.md, CLAUDE.md]
189
- required_frontmatter: [title, description, document_type, status, last_update, reason]
189
+ required_frontmatter: [title, description, type, status, last_update, reason]
190
190
  required_sections: [Normative, "Input, not authority", The schema itself]
191
191
  display_status: false
192
192
  inventory: exempt
@@ -0,0 +1,10 @@
1
+ ---
2
+ title: Compliance
3
+ description: Fixture catalogue for the shipped-register frontmatter tests.
4
+ document_type: compliance
5
+ status: stable
6
+ last_update: 2026-10-02
7
+ reason: fixture for the shipped-register vocabulary tests, not a graded page
8
+ ---
9
+
10
+ # Compliance
@@ -0,0 +1,10 @@
1
+ ---
2
+ title: Compliance
3
+ description: Fixture catalogue for the shipped-register frontmatter tests.
4
+ type: compliance
5
+ status: stable
6
+ last_update: 2026-10-02
7
+ reason: fixture for the shipped-register vocabulary tests, not a graded page
8
+ ---
9
+
10
+ # Compliance
@@ -1,12 +1,20 @@
1
1
  """DOC-008 — ported from `compliance_new/checks/docs/indexes/test.sh`.
2
2
 
3
- Three committed corpora, same scenario names and same file content as the
4
- shell fixtures under
3
+ Five committed corpora. Three share the shell fixtures' scenario names and
4
+ file content under
5
5
  `compliance_new/checks/docs/indexes/fixtures/knowledge-indexes-{clean,
6
6
  missing-entry,duplicate}/` — only the registry input is flattened to the
7
7
  fixture root rather than nested under the shell tree's own `compliance/
8
8
  checks/docs/indexes/` path (see `knowledge-indexes-clean/
9
- docs-knowledge-indexes.yaml`'s own comment).
9
+ docs-knowledge-indexes.yaml`'s own comment). The remaining two
10
+ (`knowledge-indexes-shipped-register-{type,legacy}/`) hold one
11
+ `docs/compliance/index.md` each and point the `registry` input at the GATE'S
12
+ OWN shipped `docs-knowledge-indexes.yaml` rather than a cut-down fixture
13
+ registry: the first three corpora grade the check's mechanics, but only the
14
+ shipped register's own vocabulary can say whether `type` is required — the
15
+ flip of 2026-10-02 (`document_type` → `type` in the docs-compliance and
16
+ docs-product entries, recorded in `check.py`'s module docstring) is pinned
17
+ by these two.
10
18
 
11
19
  This wave's checks are wired into `checks/__init__.py` in a later, single pass
12
20
  (see the folder's own docstring / the dispatch instructions), so `Indexes` is
@@ -44,16 +52,34 @@ FIXTURES = corpus("docs", "indexes")
44
52
  CLEAN = FIXTURES / "knowledge-indexes-clean"
45
53
  MISSING_ENTRY = FIXTURES / "knowledge-indexes-missing-entry"
46
54
  DUPLICATE = FIXTURES / "knowledge-indexes-duplicate"
55
+ SHIPPED_TYPE = FIXTURES / "knowledge-indexes-shipped-register-type"
56
+ SHIPPED_LEGACY = FIXTURES / "knowledge-indexes-shipped-register-legacy"
47
57
 
48
58
  ROW = load().by_id("DOC-008")
49
59
 
60
+ # The register the package ships beside this check — the policy whose
61
+ # vocabulary the two shipped-register corpora grade.
62
+ SHIPPED_REGISTER = FIXTURES.parent / "docs-knowledge-indexes.yaml"
50
63
 
51
- def _run(root: Path, *, given: Sequence[str] | None = None) -> Verdict:
64
+
65
+ def _run(
66
+ root: Path,
67
+ *,
68
+ given: Sequence[str] | None = None,
69
+ registry: Path | None = None,
70
+ ) -> Verdict:
52
71
  """`runner.run`'s scope-narrow-then-decide, against this check directly —
53
- the same bypass `CON-003`'s test uses for an unwired check."""
72
+ the same bypass `CON-003`'s test uses for an unwired check.
73
+
74
+ `registry` defaults to the corpus's own flattened copy; the
75
+ shipped-register corpora pass the gate folder's own yaml instead."""
54
76
  raw = corpus_files(root) if given is None else tuple(given)
55
77
  narrowed = FileSet(paths=scope.intersect(ROW.resolved_scope(), raw))
56
- ctx = Context(root=root, row=ROW, inputs={"registry": root / "docs-knowledge-indexes.yaml"})
78
+ ctx = Context(
79
+ root=root,
80
+ row=ROW,
81
+ inputs={"registry": registry if registry is not None else root / "docs-knowledge-indexes.yaml"},
82
+ )
57
83
  try:
58
84
  findings = tuple(Indexes().run(ctx, narrowed))
59
85
  except CouldNotRun as exc:
@@ -100,3 +126,29 @@ def test_the_omitted_page_outside_the_given_set_is_not_reported() -> None:
100
126
  in the given set this time — so there is nothing to compare it against."""
101
127
  verdict = _run(MISSING_ENTRY, given=("docs/index.md", "docs/one.md"))
102
128
  assert verdict.outcome is Outcome.CLEAN, verdict.render()
129
+
130
+
131
+ # ------------------------------------------- the shipped register's vocabulary
132
+
133
+ def test_an_index_satisfying_the_shipped_register_with_type_is_clean() -> None:
134
+ """The gate's OWN register, not a fixture copy, grades a compliance index
135
+ carrying the OKF `type` key clean. Decision of 2026-10-02: the
136
+ docs-compliance and docs-product entries' `required_frontmatter` flipped
137
+ `document_type` → `type` (see `check.py`'s module docstring) — before the
138
+ flip this corpus was reported as missing `document_type`."""
139
+ verdict = _run(SHIPPED_TYPE, registry=SHIPPED_REGISTER)
140
+ assert verdict.outcome is Outcome.CLEAN, verdict.render()
141
+ assert verdict.findings == ()
142
+
143
+
144
+ def test_an_index_carrying_only_the_legacy_document_type_key_is_reported() -> None:
145
+ """The flip's converse: an index that still carries `document_type` and no
146
+ `type` fails the shipped register. Before 2026-10-02 this corpus graded
147
+ CLEAN, which is exactly the drift the flip removes — the OKF profile
148
+ (`docs-okf-profiles.yaml`'s `common_required`) knows `type` only."""
149
+ verdict = _run(SHIPPED_LEGACY, registry=SHIPPED_REGISTER)
150
+ assert verdict.outcome is Outcome.FINDINGS, verdict.render()
151
+ assert verdict.rules == ["KNW-001"]
152
+ finding = verdict.findings[0]
153
+ assert finding.path == "docs/compliance/index.md"
154
+ assert finding.message == "missing required frontmatter field type"
@@ -24,7 +24,6 @@ import pathlib
24
24
  import shutil
25
25
  from datetime import date, timedelta
26
26
 
27
- import pytest
28
27
  import yaml
29
28
 
30
29
  from adl_compliance import runner
@@ -2,17 +2,36 @@
2
2
 
3
3
  Google Cloud's Open Knowledge Format v0.2. The profile register declares the
4
4
  common required fields, and then one profile per document kind: which paths it
5
- covers, the `type` and `document_type` those documents must declare, the extra
6
- fields they must carry, and the headings they must contain.
5
+ covers, the `type` those documents must declare (optional: a profile that names
6
+ none leaves the value unconstrained), the extra fields they must carry, and the
7
+ headings they must contain.
7
8
 
8
9
  Six rules, one rule id, because they are one contract:
9
10
 
10
11
  * the file has parseable YAML frontmatter at all;
11
12
  * some profile covers its path;
12
- * `type` and `document_type` match that profile;
13
+ * `type` matches that profile, where it declares one;
13
14
  * every common and profile-specific required field is present;
14
15
  * `status` is `draft` or `stable`;
15
- * each declared heading group has at least one of its headings present.
16
+ * each declared heading group has at least one of its headings present;
17
+ * the frontmatter key set is CLOSED (2026-10-02): a document may carry only
18
+ the keys its profile admits — `common_required`, `common_optional`, and
19
+ the profile's own `required` — and every other key is reported by name.
20
+
21
+ The closed set is the same contract `core/models.py`'s `extra="forbid"`
22
+ grades this package's own policy documents with, applied at the frontmatter
23
+ layer. Required-only grading had the hole in reverse: keys nobody admitted
24
+ accumulated in real documents because nothing rejected them, and the register's
25
+ `common_optional` list — until this rule — was read by no check at all. The
26
+ root agent rule names the workflow the finding drives: admit a new key by
27
+ editing `docs-okf-profiles.yaml` (into `common_optional`, or a profile's
28
+ `required` when every document of that kind must carry it), never ad-hoc in a
29
+ document. The set is closed PER PROFILE, not per register: `created` is in the
30
+ vocabulary because the Research profile requires it, but an architecture page
31
+ carrying it is reported — otherwise every profile's `required` list would leak
32
+ into every other profile by construction. `last_update` sits in
33
+ `common_optional` (not any profile's `required`) because every document kind
34
+ carries it while no document kind must.
16
35
 
17
36
  The `plan_state`-agrees-with-its-directory rule is gone. It existed because a
18
37
  plan's lifecycle state was mirrored in a directory name (`a_new`,
@@ -51,12 +70,14 @@ from ....core.scope import matches
51
70
 
52
71
 
53
72
  class Profile(StrictModel):
54
- type: str
73
+ type: str | None = None
74
+ """Optional per profile. The Research profile declares none because the
75
+ pages under `docs/research/` legitimately differ in `type` (Research,
76
+ Experiment). A profile that names no `type` asserts nothing about its
77
+ VALUE; the field must still be present, because `common_required` lists
78
+ it."""
79
+
55
80
  paths: Annotated[tuple[str, ...], Field(min_length=1, strict=False)]
56
- document_type: str | None = None
57
- """Optional per profile. Two of the shipped profiles — Specification and
58
- Change Plan — declare none, and a profile that does not name one is not
59
- asserting anything about the field."""
60
81
 
61
82
  required: Annotated[tuple[str, ...], Field(strict=False)] = ()
62
83
 
@@ -159,18 +180,11 @@ class OkfProfile(Check):
159
180
  return
160
181
 
161
182
  declared_type = frontmatter.get("type")
162
- if declared_type != profile.type:
183
+ if profile.type is not None and declared_type != profile.type:
163
184
  yield self.report(
164
185
  relative, f"type must be '{profile.type}' (got {declared_type!r})",
165
186
  f"set frontmatter type: {profile.type}",
166
187
  )
167
- declared_document = frontmatter.get("document_type")
168
- if profile.document_type is not None and declared_document != profile.document_type:
169
- yield self.report(
170
- relative,
171
- f"document_type must be '{profile.document_type}' (got {declared_document!r})",
172
- f"set frontmatter document_type: {profile.document_type}",
173
- )
174
188
 
175
189
  for field in register.common_required:
176
190
  if not frontmatter.get(field):
@@ -185,6 +199,8 @@ class OkfProfile(Check):
185
199
  f"add the {field} field required by this document's OKF profile",
186
200
  )
187
201
 
202
+ yield from self._admitted_keys(relative, frontmatter, register, profile)
203
+
188
204
  status = frontmatter.get("status")
189
205
  if status not in self.STATUSES:
190
206
  yield self.report(
@@ -194,6 +210,37 @@ class OkfProfile(Check):
194
210
 
195
211
  yield from self._headings(relative, body, profile)
196
212
 
213
+ def _admitted_keys(
214
+ self,
215
+ relative: str,
216
+ frontmatter: Mapping[str, object],
217
+ register: ProfileRegister,
218
+ profile: Profile,
219
+ ) -> Iterable[Report]:
220
+ """The closed key set: common_required, common_optional, and the
221
+ profile's own required. Anything else is reported by name, in key
222
+ order, so a document with three stray keys reports three findings and
223
+ the fix list reads the same way every time.
224
+
225
+ Keys are compared as a SET, not by truthiness: an admitted key with an
226
+ empty value is the required-fields rule's subject, not this one's.
227
+ Non-string YAML keys cannot be in the vocabulary and are reported
228
+ rather than crashing the sort."""
229
+ admitted = (
230
+ set(register.common_required)
231
+ | set(register.common_optional)
232
+ | set(profile.required)
233
+ )
234
+ for key in sorted(frontmatter, key=str):
235
+ if key in admitted:
236
+ continue
237
+ yield self.report(
238
+ relative, f"unknown OKF frontmatter key {key!r}",
239
+ "remove the key, or admit it in docs-okf-profiles.yaml: add it "
240
+ "to common_optional, or to this profile's required if every "
241
+ "document of this kind must carry it",
242
+ )
243
+
197
244
  def _headings(self, relative: str, body: str, profile: Profile) -> Iterable[Report]:
198
245
  present = [
199
246
  line.lstrip("#").strip()
@@ -5,7 +5,6 @@ version: "0.2"
5
5
  # |--------------------------|-----------------------------------------------------|
6
6
  # | status | unquoted bare scalar: draft | stable (status: draft) |
7
7
  # | last_update | quoted ISO-8601 UTC : '2026-08-22T00:00:00Z' |
8
- # | document_type | unquoted bare scalar (same rule as status) |
9
8
  # | created, decision_date, …| unquoted bare YYYY-MM-DD dates where present |
10
9
 
11
10
  # `generated: {by, at}` used to be here. It was machine provenance nobody
@@ -19,25 +18,55 @@ common_required:
19
18
  - description
20
19
  - status
21
20
 
21
+ # common_optional is the closed key set's safety valve (DOC-006, 2026-10-02):
22
+ # a key here is admitted on every document kind but required of none. The
23
+ # closed-set rule reads this list; nothing else ever did — it existed in the
24
+ # register for a year with no check enforcing it.
25
+ #
26
+ # last_update is admitted here, not in any profile's required: every document
27
+ # kind carries it (it is a frontmatter convention above, and all 25 documents
28
+ # in the adl-azdo corpus have it) while no document kind must — required
29
+ # belongs to fields a profile's headings cannot be written without.
30
+ #
31
+ # related is admitted the same way and for the measured reason: 24 of those 25
32
+ # documents carry it, across every kind — the Architecture and Operations
33
+ # profiles already REQUIRE it, and research pages carry it without their
34
+ # profile requiring it (see test_check.py: the research fixtures deliberately
35
+ # have none). A key the whole corpus conventionally carries but one kind
36
+ # legitimately omits is the definition of optional.
22
37
  common_optional:
23
38
  - verified
24
39
  - resource
25
40
  - tags
26
41
  - stale_after
42
+ - last_update
43
+ - related
27
44
 
28
- # Four profiles, deliberately.
45
+ # Five profiles, deliberately (Compliance is disabled, see below).
29
46
  #
30
47
  # There were eight. Benchmark, Evaluation, Field Note and Specification declared
31
48
  # trees that do not exist -- docs/research/benchmarks, docs/research/evaluations,
32
49
  # docs/research/field-notes, .specs -- so seven of the eight graded nothing at
33
50
  # all while reading as coverage. A register that describes a documentation set
34
51
  # nobody has is worse than a smaller one that describes the real thing: it
35
- # reports clean because it never matched a file.
52
+ # reports clean because it never matched a file. Those four stay removed.
53
+ #
54
+ # Research is added back (2026-10-01), and not as a return of those four:
55
+ # docs/research/ itself exists in the consuming repositories. enact-combined
56
+ # holds docs/research/cloud-local-research-input.md (type Research) and
57
+ # docs/research/codex-app-server-container-experiment.md (type Experiment), and
58
+ # with no profile covering that path DOC-006 reported "no OKF profile matches
59
+ # this path" for both. The profile is minimal on purpose: one entry for
60
+ # docs/research/**, requiring what both pages carry -- title, description and
61
+ # status through common_required, then last_update and sources -- and nothing else. It declares no `type`, because the two pages
62
+ # differ in it, and no headings, because they share no section structure.
36
63
  #
37
64
  # Architecture what the system is docs/architecture/**
38
65
  # ADR why it is that way docs/architecture/decisions/**, docs/decisions/**
39
- # Compliance what we must show docs/compliance/**
40
66
  # Operations how it is operated docs/operations/**
67
+ # Task ledger what each agent task did docs/notes.md
68
+ # Research what is being found out docs/research/**
69
+ # (Compliance what we must show docs/compliance/** -- disabled, see below)
41
70
  #
42
71
  # plans/ is NOT here. Its frontmatter answers to the Azure DevOps board, not to
43
72
  # OKF, and LAY-009 owns it.
@@ -46,7 +75,6 @@ profiles:
46
75
  - type: Architecture
47
76
  paths:
48
77
  - docs/architecture/**
49
- document_type: architecture
50
78
  required:
51
79
  - sources
52
80
  - related
@@ -60,7 +88,6 @@ profiles:
60
88
  paths:
61
89
  - docs/architecture/decisions/**
62
90
  - docs/decisions/**
63
- document_type: adr
64
91
  required:
65
92
  - decision_id
66
93
  - decision_date
@@ -84,8 +111,7 @@ profiles:
84
111
  # - type: Compliance Assessment
85
112
  # paths:
86
113
  # - docs/compliance/**
87
- # document_type: compliance
88
- # required:
114
+ # required:
89
115
  # - control_ids
90
116
  # - owner
91
117
  # - review_frequency
@@ -107,7 +133,6 @@ profiles:
107
133
  - type: Operations
108
134
  paths:
109
135
  - docs/operations/**
110
- document_type: operations
111
136
  required:
112
137
  - sources
113
138
  - related
@@ -117,3 +142,29 @@ profiles:
117
142
  - ["Credentials", "Access", "Sign"]
118
143
  - ["Verification", "Evidence", "Check"]
119
144
 
145
+ # The task ledger: one append-only list of dated lines, one per task start
146
+ # and finish, that the global agent rule requires in every repository
147
+ # (docs/notes.md, declared in policy/docs_shape.py). It is an operations
148
+ # document, but not a procedure: it has no Purpose/Procedure/Credentials
149
+ # sections and no `related` field, so it gets its own profile rather than
150
+ # the Operations one above. It is graded for what it really has: OKF
151
+ # frontmatter with `sources`, and its `## Lines` section.
152
+ - type: Operations
153
+ paths:
154
+ - docs/notes.md
155
+ required:
156
+ - sources
157
+ headings:
158
+ - ["Lines"]
159
+
160
+ # Research: inputs, findings and experiment plans under docs/research/. No
161
+ # `type` -- the pages there differ (Research, Experiment) -- and no headings;
162
+ # see the header. Title, description and status come from common_required.
163
+ # Research pages are dated: `created` (bare YYYY-MM-DD) records when the work
164
+ # was done -- the date is part of what a research page is.
165
+ - paths:
166
+ - docs/research/**
167
+ required:
168
+ - created
169
+ - last_update
170
+ - sources
@@ -0,0 +1,17 @@
1
+ ---
2
+ last_update: 2026-09-28T15:10:00Z
3
+ title: Agent notes ledger
4
+ description: Fixture task ledger, one append-only line per task start and finish.
5
+ type: Operations
6
+ status: stable
7
+ sources: packages/agent-settings/assets/GLOBAL-AGENTS.md
8
+ ---
9
+
10
+ # Agent notes ledger
11
+
12
+ An append-only log; one line when an agent starts a task and one when it finishes.
13
+
14
+ ## Lines
15
+
16
+ 2026-09-28 05:31 claude start: fixture task
17
+ 2026-09-28 05:40 claude finish: fixture task