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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. package/bin/adl +2 -2
  2. package/bin/git +17 -18
  3. package/bin/git-ado +27 -26
  4. package/bin/git-defaults +173 -0
  5. package/bin/health-check +8 -1
  6. package/bin/kimi-hooks +1 -1
  7. package/bin/lib/adl-package.sh +257 -0
  8. package/bin/lib/bun-compile-build.sh +1 -1
  9. package/bin/lib/fleet-host.sh +62 -0
  10. package/bin/lib/lean-ctx-observe-hooks.sh +9 -9
  11. package/bin/reconcile +693 -470
  12. package/bin/reconcile-host +121 -0
  13. package/bin/setup +219 -0
  14. package/bin/shell-path-policy +15 -5
  15. package/bin/sync-and-reconcile +79 -68
  16. package/bin/validate-manifest +46 -51
  17. package/package.json +2 -12
  18. package/packages/agent-hooks/README.md +14 -9
  19. package/packages/agent-hooks/assets/hooks.json +0 -20
  20. package/packages/agent-hooks/package.json +1 -2
  21. package/packages/agent-hooks/src/cli/args.ts +1 -1
  22. package/packages/agent-hooks/src/cli/doctor.ts +6 -58
  23. package/packages/agent-hooks/src/deploy/deploy.ts +12 -41
  24. package/packages/agent-hooks/src/deploy/doctor.ts +8 -11
  25. package/packages/agent-hooks/src/deploy/index.ts +14 -14
  26. package/packages/agent-hooks/src/deploy/json-merge.ts +7 -8
  27. package/packages/agent-hooks/src/deploy/legacy-lock.ts +2 -2
  28. package/packages/agent-hooks/src/deploy/list.ts +1 -1
  29. package/packages/agent-hooks/src/deploy/lock.ts +31 -12
  30. package/packages/agent-hooks/src/deploy/profile.ts +3 -4
  31. package/packages/agent-hooks/src/deploy/source.ts +1 -1
  32. package/packages/agent-hooks/src/gating/config.ts +10 -24
  33. package/packages/agent-hooks/src/gating/root.ts +3 -3
  34. package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
  35. package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
  36. package/packages/agent-hooks/src/hooks/contract.ts +17 -17
  37. package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
  38. package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
  39. package/packages/agent-hooks/src/hooks/log.ts +8 -10
  40. package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
  41. package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
  42. package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
  43. package/packages/agent-hooks/src/hosts/registry.ts +1 -1
  44. package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
  45. package/packages/agent-hooks/src/log/writer.ts +16 -2
  46. package/packages/agent-hooks/src/main.ts +7 -41
  47. package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
  48. package/packages/agent-hooks/src/rules/engine.ts +13 -17
  49. package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
  50. package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
  51. package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
  52. package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
  53. package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
  54. package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
  55. package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
  56. package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
  57. package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
  58. package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
  59. package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
  60. package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
  61. package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
  62. package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
  63. package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +159 -0
  64. package/packages/agent-hooks/src/rules/impl/fs-trash.ts +2 -2
  65. package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
  66. package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
  67. package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
  68. package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
  69. package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
  70. package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
  71. package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
  72. package/packages/agent-hooks/src/rules/impl/tool-grep.ts +34 -12
  73. package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
  74. package/packages/agent-hooks/src/rules/ports.ts +5 -7
  75. package/packages/agent-hooks/src/rules/registry.ts +4 -6
  76. package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
  77. package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
  78. package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
  79. package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
  80. package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
  81. package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
  82. package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
  83. package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
  84. package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
  85. package/packages/agent-hooks/src/rules/spec.ts +2 -2
  86. package/packages/agent-settings/README.md +287 -0
  87. package/packages/agent-settings/assets/GLOBAL-AGENTS.md +18 -18
  88. package/packages/agent-settings/assets/agents/architect.toml +2 -0
  89. package/packages/agent-settings/assets/agents/code-reviewer.toml +2 -0
  90. package/packages/agent-settings/assets/agents/executor.toml +2 -0
  91. package/packages/agent-settings/assets/agents/explore.toml +2 -0
  92. package/packages/agent-settings/assets/agents/planner.toml +2 -0
  93. package/packages/agent-settings/assets/mcp.json +0 -4
  94. package/packages/agent-settings/deploy-profile.json +139 -0
  95. package/packages/agent-settings/deploy-profile.schema.json +147 -0
  96. package/packages/agent-settings/managed/README.md +29 -30
  97. package/packages/agent-settings/managed/codex-requirements.toml +9 -9
  98. package/packages/agent-settings/package.json +20 -0
  99. package/packages/agent-settings/src/deploy/agent-render.ts +2 -2
  100. package/packages/agent-settings/src/deploy/agent-toml.ts +1 -1
  101. package/packages/agent-settings/src/deploy/agents-deploy.ts +17 -3
  102. package/packages/agent-settings/src/deploy/doctor.ts +3 -83
  103. package/packages/agent-settings/src/deploy/index.ts +6 -33
  104. package/packages/agent-settings/src/deploy/legacy-lock.ts +6 -6
  105. package/packages/agent-settings/src/deploy/list.ts +5 -19
  106. package/packages/agent-settings/src/deploy/lock.ts +8 -18
  107. package/packages/agent-settings/src/deploy/mcp-deploy.ts +10 -5
  108. package/packages/agent-settings/src/deploy/mcp-merge.ts +22 -3
  109. package/packages/agent-settings/src/deploy/mcp-source.ts +1 -1
  110. package/packages/agent-settings/src/deploy/profile.ts +11 -35
  111. package/packages/agent-settings/src/deploy/retire-lean-ctx.ts +184 -0
  112. package/packages/agent-settings/src/deploy/settings.ts +17 -22
  113. package/packages/agent-settings/src/global-surface-sweep.ts +5 -17
  114. package/packages/agent-settings/src/kimi-hooks.ts +339 -192
  115. package/packages/agent-settings/src/opencode-hooks.ts +1 -1
  116. package/packages/agent-settings/tsconfig.json +23 -0
  117. package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +120 -0
  118. package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +276 -0
  119. package/packages/agent-skills/assets/debug-issue/SKILL.md +8 -7
  120. package/packages/agent-skills/assets/explore-codebase/SKILL.md +13 -13
  121. package/packages/agent-skills/assets/refactor-safely/SKILL.md +12 -11
  122. package/packages/agent-skills/assets/review-changes/SKILL.md +7 -7
  123. package/packages/agent-skills/assets/testing/references/e2e.md +37 -0
  124. package/packages/agent-skills/assets/testing/references/integration.md +37 -0
  125. package/packages/agent-skills/assets/testing/references/unit.md +32 -0
  126. package/packages/agent-skills/dist/deploy.d.ts +2 -0
  127. package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
  128. package/packages/agent-skills/dist/deploy.js +27 -1
  129. package/packages/agent-skills/dist/deploy.js.map +1 -1
  130. package/packages/agent-skills/dist/doctor.d.ts +0 -2
  131. package/packages/agent-skills/dist/doctor.d.ts.map +1 -1
  132. package/packages/agent-skills/dist/doctor.js +1 -1
  133. package/packages/agent-skills/dist/doctor.js.map +1 -1
  134. package/packages/agent-skills/dist/fs-utils.d.ts +0 -1
  135. package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -1
  136. package/packages/agent-skills/dist/fs-utils.js +1 -1
  137. package/packages/agent-skills/dist/fs-utils.js.map +1 -1
  138. package/packages/agent-skills/package.json +1 -1
  139. package/packages/agent-skills/src/deploy.ts +29 -1
  140. package/packages/agent-skills/src/doctor.ts +1 -1
  141. package/packages/agent-skills/src/fs-utils.ts +1 -1
  142. package/packages/azdo/README.md +10 -9
  143. package/packages/azdo/package.json +2 -5
  144. package/packages/azdo/src/azdo-pl.ts +2 -54
  145. package/packages/azdo/src/azdo-pr-review.ts +4 -4
  146. package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
  147. package/packages/azdo/src/azdo-wit.ts +41 -2
  148. package/packages/azdo/src/lib/agent-identity.ts +12 -14
  149. package/packages/azdo/src/lib/agent-token.ts +2 -2
  150. package/packages/azdo/src/lib/client.ts +0 -5
  151. package/packages/azdo/src/lib/graph-identity.ts +4 -4
  152. package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
  153. package/packages/azdo/src/workflow-rules.ts +128 -0
  154. package/packages/fleet/manifest.json +38 -33
  155. package/packages/fleet/manifest.schema.json +67 -65
  156. package/packages/fleet/src/default-agent-file.ts +3 -3
  157. package/packages/fleet/src/install-adl-package.ts +73 -15
  158. package/packages/fleet/src/install-embedding-model.ts +14 -14
  159. package/packages/fleet/src/managed-settings.ts +7 -7
  160. package/packages/fleet/src/repo-maintain.ts +439 -0
  161. package/packages/fleet/src/scratch-reap.ts +6 -6
  162. package/packages/fleet/src/vscode-settings.ts +5 -5
  163. package/packages/repo-controls/README.md +141 -43
  164. package/packages/repo-controls/assets/promote.ts +4 -4
  165. package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
  166. package/packages/repo-controls/assets/version-bump.sh +31 -84
  167. package/packages/repo-controls/bunfig.toml +6 -7
  168. package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
  169. package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
  170. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
  171. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
  172. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
  173. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
  174. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
  175. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
  176. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/c.md +1 -0
  177. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/d.md +1 -0
  178. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
  179. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
  180. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
  181. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
  182. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
  183. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
  184. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/sub/nested.md +1 -0
  185. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
  186. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
  187. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
  188. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
  189. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
  190. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
  191. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
  192. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
  193. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
  194. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
  195. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
  196. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
  197. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-001-tenancy.md +1 -0
  198. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-002-carrier.md +1 -0
  199. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-003-cli.md +1 -0
  200. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-old.md +1 -0
  201. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-older.md +1 -0
  202. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
  203. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
  204. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
  205. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
  206. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-01.md +1 -0
  207. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-02.md +1 -0
  208. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-03.md +1 -0
  209. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-04.md +1 -0
  210. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-05.md +1 -0
  211. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-06.md +1 -0
  212. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-07.md +1 -0
  213. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-08.md +1 -0
  214. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-09.md +1 -0
  215. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-10.md +1 -0
  216. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-11.md +1 -0
  217. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-12.md +1 -0
  218. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-13.md +1 -0
  219. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-14.md +1 -0
  220. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-15.md +1 -0
  221. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-16.md +1 -0
  222. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
  223. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
  224. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
  225. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
  226. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
  227. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
  228. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
  229. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
  230. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
  231. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/a.md +1 -0
  232. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/b.md +1 -0
  233. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/c.md +1 -0
  234. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/d.md +1 -0
  235. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/e.md +1 -0
  236. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
  237. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/a.md +1 -0
  238. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/b.md +1 -0
  239. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/c.md +1 -0
  240. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/short/only.md +1 -0
  241. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
  242. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
  243. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
  244. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
  245. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
  246. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
  247. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
  248. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
  249. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
  250. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
  251. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
  252. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
  253. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
  254. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
  255. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
  256. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
  257. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
  258. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
  259. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
  260. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
  261. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
  262. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
  263. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
  264. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
  265. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
  266. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
  267. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
  268. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
  269. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
  270. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
  271. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
  272. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
  273. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
  274. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
  275. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
  276. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
  277. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
  278. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
  279. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-legacy/docs/compliance/index.md +10 -0
  280. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-type/docs/compliance/index.md +10 -0
  281. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
  282. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
  283. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
  284. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
  285. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
  286. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
  287. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
  288. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
  289. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/no-type.md +9 -0
  290. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-experiment.md +10 -0
  291. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-research.md +10 -0
  292. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
  293. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs/architecture/bad-status.md +0 -1
  294. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
  295. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
  296. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
  297. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
  298. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
  299. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
  300. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-last-update.md +11 -0
  301. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
  302. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
  303. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
  304. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
  305. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
  306. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/created-date.md +21 -0
  307. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/research-shaped.md +19 -0
  308. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
  309. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
  310. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
  311. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
  312. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
  313. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
  314. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
  315. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/a.ts +1 -0
  316. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/b.ts +1 -0
  317. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
  318. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
  319. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
  320. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
  321. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/a.ts +1 -0
  322. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/b.ts +1 -0
  323. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/c.ts +1 -0
  324. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
  325. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
  326. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
  327. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
  328. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
  329. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
  330. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
  331. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
  332. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
  333. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
  334. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
  335. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +256 -0
  336. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
  337. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
  338. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +1 -1
  339. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
  340. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
  341. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
  342. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
  343. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
  344. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
  345. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
  346. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
  347. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
  348. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
  349. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
  350. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
  351. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
  352. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
  353. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
  354. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
  355. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
  356. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
  357. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
  358. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
  359. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
  360. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
  361. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
  362. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
  363. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
  364. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
  365. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
  366. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
  367. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
  368. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
  369. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
  370. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
  371. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
  372. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
  373. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
  374. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
  375. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
  376. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
  377. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
  378. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
  379. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
  380. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
  381. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
  382. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
  383. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
  384. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
  385. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
  386. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
  387. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
  388. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
  389. package/packages/repo-controls/package.json +2 -10
  390. package/packages/repo-controls/scripts/hooks/post-merge +13 -0
  391. package/packages/repo-controls/scripts/hooks/pre-push +3 -3
  392. package/packages/repo-controls/src/azdo-push.ts +64 -36
  393. package/packages/repo-controls/src/azure-devops-governance.ts +7 -9
  394. package/packages/repo-controls/src/azure-devops-remote.ts +1 -1
  395. package/packages/repo-controls/src/cli.ts +29 -8
  396. package/packages/repo-controls/src/compliance-config.ts +410 -2
  397. package/packages/repo-controls/src/config.ts +133 -60
  398. package/packages/repo-controls/src/constants.ts +13 -27
  399. package/packages/repo-controls/src/coverage-ratchet.ts +4 -4
  400. package/packages/repo-controls/src/doctor.ts +46 -19
  401. package/packages/repo-controls/src/gitignore-block.ts +5 -29
  402. package/packages/repo-controls/src/hook-log.ts +1 -2
  403. package/packages/repo-controls/src/hook.ts +201 -45
  404. package/packages/repo-controls/src/install.ts +14 -8
  405. package/packages/repo-controls/src/integrity.ts +3 -3
  406. package/packages/repo-controls/src/lfs.ts +111 -0
  407. package/packages/repo-controls/src/promote.ts +8 -8
  408. package/packages/repo-controls/src/runtime.ts +9 -1
  409. package/packages/repo-controls/src/workflows-drift.ts +4 -5
  410. package/packages/repo-controls/src/worktree-guard.ts +3 -3
  411. package/packages/fleet/jobs/git-maintain/src/main.ts +0 -848
  412. package/packages/fleet/systemd/adl-azure-agent-update.service +0 -13
  413. package/packages/fleet/systemd/adl-azure-agent-update.timer +0 -10
@@ -44,14 +44,13 @@
44
44
  * position; adl's slot is restored separately, right there — never
45
45
  * deleted, never duplicated.
46
46
  *
47
- * A lock recording no hashes at all (`ownedEntries` absent — every repo
48
- * enrolled before this fix; closes (a)) falls back, for exactly this one
49
- * transitional deploy, to command-anywhere matching against the lock's OLD
50
- * `ownedCommands` — the only signal that data has — via the SAME
51
- * `legacyOwnedCommands` channel the pre-agent-hooks engine's own takeover
52
- * already used (both are "we have no better proof than an exact command
53
- * string" signals). This run then persists real content hashes
54
- * (`ownedEntries`), so every later deploy uses the full contract.
47
+ * The `legacyOwnedCommands` channel ("command text is the only proof we
48
+ * have") is fed ONLY by the pre-agent-hooks engine's own hash-verified
49
+ * takeover (legacy-lock.ts). It used to ALSO carry a one-deploy transitional
50
+ * fallback for a lock with no hashes at all (`ownedEntries` absent — every
51
+ * repo enrolled before this fix; closed (a)); that transition is over
52
+ * (Tarun, 2026-10-01): lock.ts's `readLock` now refuses such an entry
53
+ * outright, so every deploy here uses the full content-addressed contract.
55
54
  *
56
55
  * THIRD independent review (2026-09-30) found the fallback ITSELF still
57
56
  * leaked through raw array position, in two ways:
@@ -61,13 +61,13 @@ export function stableStringify(value: unknown): string {
61
61
  /** Content hash of a JSON value, exactly as the legacy engine recorded it. */
62
62
  export const legacyValueHash = (value: unknown): string => sha256Hex(stableStringify(value))
63
63
 
64
- export interface LegacyJsonMergeEntry {
64
+ interface LegacyJsonMergeEntry {
65
65
  readonly type: string
66
66
  readonly path: readonly (string | number)[]
67
67
  readonly sha256: string
68
68
  }
69
69
 
70
- export interface LegacyMergedRecord {
70
+ interface LegacyMergedRecord {
71
71
  readonly entries?: readonly LegacyJsonMergeEntry[]
72
72
  }
73
73
 
@@ -10,7 +10,7 @@ import { type HookLockEntry, readLock } from './lock.ts'
10
10
  import { type HookDeployProfile, type HookSurface, loadProfile } from './profile.ts'
11
11
  import { flattenSourceHooks, hookLabel, loadHooksSource, type CanonicalHooksDoc } from './source.ts'
12
12
 
13
- export type HookOwner = 'adl' | 'user' | 'conflict' | '-'
13
+ type HookOwner = 'adl' | 'user' | 'conflict' | '-'
14
14
 
15
15
  export interface HookListingEntry {
16
16
  readonly name: string
@@ -7,8 +7,12 @@
7
7
  * read it to report ownership.
8
8
  *
9
9
  * For a json-hooks surface (claude-settings / codex-hooks / cursor-hooks-v1),
10
- * "owned" is recorded per surface event name as the exact rendered command
11
- * strings (already carrying --host=<surface>) this deploy wrote there. For
10
+ * "owned" is recorded per surface event name as content-addressed hook
11
+ * entries (`ownedEntries`: hash + command + matcher), alongside the exact
12
+ * rendered command strings (`ownedCommands`, already carrying
13
+ * --host=<surface>; informational, read by list.ts). `readLock` refuses an
14
+ * entry without `ownedEntries` (the older `ownedCommands`-only shape is no
15
+ * longer migrated — Tarun, 2026-10-01). For
12
16
  * the opencode-plugin surface, the whole file is wholly adl-owned (H3) —
13
17
  * `owned: true` records that fact rather than a per-command breakdown.
14
18
  */
@@ -29,7 +33,7 @@ export const LOCK_RELATIVE_PATH = '.agents/agent-hooks.lock.json'
29
33
  * never by array position/index, which the second independent review
30
34
  * already ruled unreliable.
31
35
  */
32
- export interface OwnedHookEntry {
36
+ interface OwnedHookEntry {
33
37
  readonly hash: string
34
38
  readonly command: string
35
39
  readonly matcher?: string
@@ -37,7 +41,7 @@ export interface OwnedHookEntry {
37
41
 
38
42
  export interface JsonHooksLockEntry {
39
43
  readonly format: 'claude-settings' | 'codex-hooks' | 'cursor-hooks-v1'
40
- /** Surface event name -> the exact command strings (with --host) this deploy wrote into that event's array — informational only (list.ts); ownership itself is `ownedEntries`, below. */
44
+ /** Surface event name -> the exact command strings (with --host) this deploy wrote into that event's array — informational only (list.ts reads it to label what is adl's); ownership itself is `ownedEntries`, below. */
41
45
  readonly ownedCommands: Readonly<Record<string, readonly string[]>>
42
46
  /**
43
47
  * Surface event name -> this deploy's own written hooks, content-
@@ -45,16 +49,14 @@ export interface JsonHooksLockEntry {
45
49
  * pure array-index tracking, broke the moment a user inserted or
46
50
  * removed an entry before adl's own block, and could not express
47
51
  * "split a group" when a user hook was appended inside one — see
48
- * json-merge.ts's header for the corrected rule). Absent on a lock
49
- * written before EITHER ownership fix existed (every repo enrolled
50
- * before this one) — every reader treats that as "derive ownership
51
- * once from `ownedCommands` by exact command match, then persist real
52
- * entries here," never as malformed.
52
+ * json-merge.ts's header for the corrected rule). Required: `readLock`
53
+ * refuses an entry without it (Tarun, 2026-10-01: the transitional
54
+ * rewrite of the older `ownedCommands`-only shape is gone).
53
55
  */
54
- readonly ownedEntries?: Readonly<Record<string, readonly OwnedHookEntry[]>>
56
+ readonly ownedEntries: Readonly<Record<string, readonly OwnedHookEntry[]>>
55
57
  }
56
58
 
57
- export interface OpencodePluginLockEntry {
59
+ interface OpencodePluginLockEntry {
58
60
  readonly format: 'opencode-plugin'
59
61
  readonly owned: true
60
62
  }
@@ -86,7 +88,24 @@ export function readLock(targetRepo: string): HookLock {
86
88
  if (typeof record !== 'object' || record === null || record.version !== 1 || typeof record.entries !== 'object' || record.entries === null) {
87
89
  throw new Error(`agent-hooks lock has an unrecognized shape: ${path}`)
88
90
  }
89
- return { version: 1, entries: record.entries as Record<string, HookLockEntry> }
91
+ const entries = record.entries as Record<string, HookLockEntry>
92
+ // Tarun, 2026-10-01: the legacy (`ownedCommands` without `ownedEntries`) ->
93
+ // content-addressed migration is over. Reading such an entry as "owns
94
+ // nothing" would duplicate every adl hook already in the file, and
95
+ // guessing ownership from command text is the very thing content-
96
+ // addressing replaced — so refuse, loudly, and say how to recover.
97
+ for (const [file, entry] of Object.entries(entries)) {
98
+ if (typeof entry !== 'object' || entry === null || entry.format === 'opencode-plugin') continue
99
+ const ownedEntries: unknown = (entry as { ownedEntries?: unknown }).ownedEntries
100
+ if (typeof ownedEntries !== 'object' || ownedEntries === null || Array.isArray(ownedEntries)) {
101
+ throw new Error(
102
+ `agent-hooks lock entry for ${file} has no usable \`ownedEntries\` (the older \`ownedCommands\`-only shape is no longer migrated): ${path}. ` +
103
+ `Recover by removing the adl-written hook commands listed under that entry's \`ownedCommands\` from ${file}, deleting that entry from the lock (or deleting the lock file), ` +
104
+ `then running \`adl hooks deploy --repo ${targetRepo}\` to re-enrol.`,
105
+ )
106
+ }
107
+ }
108
+ return { version: 1, entries }
90
109
  }
91
110
 
92
111
  /** Skips the write entirely when the serialized content is already byte-identical (independent review, 2026-09-29, finding 8: a genuine no-op run must not touch the lock file's mtime either). */
@@ -16,11 +16,10 @@ import Ajv, { type ErrorObject, type ValidateFunction } from 'ajv'
16
16
  import { readFileSync } from 'node:fs'
17
17
  import { fileURLToPath } from 'node:url'
18
18
 
19
- export type HookWireFormat = 'claude-settings' | 'codex-hooks' | 'cursor-hooks-v1' | 'opencode-plugin'
20
- export const HOOK_WIRE_FORMATS: readonly HookWireFormat[] = ['claude-settings', 'codex-hooks', 'cursor-hooks-v1', 'opencode-plugin']
19
+ type HookWireFormat = 'claude-settings' | 'codex-hooks' | 'cursor-hooks-v1' | 'opencode-plugin'
21
20
 
22
- export type UnmappedMatcherPolicy = 'keep' | 'drop'
23
- export type TimeoutUnit = 's' | 'ms'
21
+ type UnmappedMatcherPolicy = 'keep' | 'drop'
22
+ type TimeoutUnit = 's' | 'ms'
24
23
 
25
24
  export interface HookSurface {
26
25
  readonly name: string
@@ -23,7 +23,7 @@ export interface CanonicalHookGroup {
23
23
 
24
24
  export type CanonicalHooksDoc = ReadonlyMap<string, readonly CanonicalHookGroup[]>
25
25
 
26
- export const DEFAULT_HOOKS_SOURCE_PATH = fileURLToPath(new URL('../../assets/hooks.json', import.meta.url))
26
+ const DEFAULT_HOOKS_SOURCE_PATH = fileURLToPath(new URL('../../assets/hooks.json', import.meta.url))
27
27
 
28
28
  function isHookCommand(value: unknown): value is CanonicalHookCommand {
29
29
  if (typeof value !== 'object' || value === null) return false
@@ -10,8 +10,9 @@
10
10
  * `adl-config.toml` is shared with other tools at the same root: adl hook
11
11
  * owns `[hooks]`, `[rules]`, and `[repo]`; `adl-repo-controls` owns
12
12
  * `[controls]`; `adl-extensions` owns `[extensions]` (and, before its
13
- * HARDCUT, `[skills]`). `[controls]` and `[skills]` are recognized root tables
14
- * this module accepts and never reads into.
13
+ * HARDCUT, `[skills]`). `[azdo]` is reserved for shared Azure DevOps
14
+ * configuration. `[controls]`, `[skills]`, and `[azdo]` are recognized root
15
+ * tables this module accepts and never reads into.
15
16
  *
16
17
  * `[extensions]` is the one exception, and a deliberate one: its sub-table
17
18
  * KEYS are decoded into `AdlRepoConfig.extensions`. Since adl-extensions
@@ -27,13 +28,6 @@
27
28
  * # (pre-tool-use, user-prompt-submit, briefing,
28
29
  * # crg) for this repo: exit 0, empty stdout/stderr.
29
30
  * skills_dir = ".agents/skills" # optional; see src/hooks/user-prompt-submit
30
- * lean_ctx_dir = ".agents/lean-ctx" # optional; repo-relative root for
31
- * # lean-ctx's own config/data/state/cache dirs
32
- * # (see src/lean-ctx/env.ts). A throwaway repo
33
- * # — a binary test fixture, say — sets this so
34
- * # lean-ctx's state, and any daemon it starts
35
- * # off that state, lands somewhere disposable
36
- * # instead of the default.
37
31
  *
38
32
  * [rules]
39
33
  * default = "on" # "on" | "off"; baseline for rules with no
@@ -69,7 +63,7 @@
69
63
 
70
64
  import { MARKER } from './root.ts'
71
65
 
72
- export interface RuleSection {
66
+ interface RuleSection {
73
67
  readonly enabled: boolean
74
68
  }
75
69
 
@@ -79,11 +73,9 @@ export interface RulesConfig {
79
73
  readonly byId: Readonly<Record<string, RuleSection>>
80
74
  }
81
75
 
82
- export interface HooksConfig {
76
+ interface HooksConfig {
83
77
  readonly enabled: boolean
84
78
  readonly skillsDir: string | undefined
85
- /** Repo-relative root for lean-ctx's config/data/state/cache; see `../lean-ctx/env.ts`. */
86
- readonly leanCtxDir: string | undefined
87
79
  }
88
80
 
89
81
  /**
@@ -185,7 +177,7 @@ const DEFAULT_AGENT: AgentSection = {
185
177
  }
186
178
 
187
179
  const DEFAULT_CONFIG: AdlRepoConfig = {
188
- hooks: { enabled: true, skillsDir: undefined, leanCtxDir: undefined },
180
+ hooks: { enabled: true, skillsDir: undefined },
189
181
  rules: { default: 'on', unsafeAllowUncertain: false, byId: {} },
190
182
  repo: DEFAULT_REPO,
191
183
  agent: DEFAULT_AGENT,
@@ -222,13 +214,13 @@ function rejectUnknownKeys(
222
214
  * Top-level keys `decodeConfig` recognizes. `version` is accepted (and
223
215
  * ignored) only so the marker file's own minimal `version = 1\n` convention
224
216
  * stays valid — this package has no schema migrations to gate on it.
225
- * controls/skills: see module header for ownership.
217
+ * controls/skills/azdo: see module header for ownership.
226
218
  */
227
219
  /**
228
220
  * Root tables this module accepts. It owns `version`/`hooks`/`rules`/`repo`
229
221
  * and never reads the rest — they belong to the other tools sharing this file:
230
- * `controls` to adl-repo-controls, and `extensions` (formerly `skills`) to
231
- * adl-extensions.
222
+ * `controls` to adl-repo-controls, `extensions` (formerly `skills`) to
223
+ * adl-extensions, and `azdo` to shared Azure DevOps configuration.
232
224
  *
233
225
  * `skills` is retained alongside `extensions` on purpose. adl-extensions
234
226
  * HARDCUT to `[extensions]` because an extension owns its skills rather than
@@ -237,7 +229,7 @@ function rejectUnknownKeys(
237
229
  * here would fail exactly those repos, the ones nobody has touched yet.
238
230
  */
239
231
  const KNOWN_ROOT_KEYS: ReadonlySet<string> = new Set([
240
- 'version', 'hooks', 'rules', 'repo', 'agent', 'controls', 'skills', 'extensions',
232
+ 'version', 'hooks', 'rules', 'repo', 'agent', 'controls', 'skills', 'extensions', 'azdo',
241
233
  ])
242
234
 
243
235
  /**
@@ -314,17 +306,11 @@ function decodeHooks(value: unknown): { ok: true; value: HooksConfig } | { ok: f
314
306
  return { ok: false, issue: { pointer: '/hooks/skills_dir', message: 'expected a string' } }
315
307
  }
316
308
 
317
- const leanCtxDirRaw = value.lean_ctx_dir
318
- if (leanCtxDirRaw !== undefined && typeof leanCtxDirRaw !== 'string') {
319
- return { ok: false, issue: { pointer: '/hooks/lean_ctx_dir', message: 'expected a string' } }
320
- }
321
-
322
309
  return {
323
310
  ok: true,
324
311
  value: {
325
312
  enabled: enabledRaw ?? true,
326
313
  skillsDir: skillsDirRaw,
327
- leanCtxDir: leanCtxDirRaw,
328
314
  },
329
315
  }
330
316
  }
@@ -28,7 +28,7 @@ import { dirname, join } from 'node:path'
28
28
  import { statSync } from 'node:fs'
29
29
 
30
30
  /** Guard against a symlink loop or a pathological mount turning the walk into a hang. */
31
- export const MAX_WALK_DEPTH = 128
31
+ const MAX_WALK_DEPTH = 128
32
32
 
33
33
  /** The repo marker + settings file (docs/architecture/adl-config.md). Hard cut (Tarun, 2026-09-27): no fallback read of the old `adl-config.toml` name. */
34
34
  export const MARKER = 'adl-config.toml'
@@ -40,7 +40,7 @@ export interface RootIO {
40
40
  readonly cwd: () => string
41
41
  }
42
42
 
43
- export interface GitRootResult {
43
+ interface GitRootResult {
44
44
  readonly root: string | null
45
45
  readonly searched: readonly string[]
46
46
  }
@@ -50,7 +50,7 @@ export interface GitRootResult {
50
50
  * Stops at the first one found, at the filesystem root, or after
51
51
  * `MAX_WALK_DEPTH` levels — whichever comes first.
52
52
  */
53
- export function findGitRoot(io: RootIO, startDir: string): GitRootResult {
53
+ function findGitRoot(io: RootIO, startDir: string): GitRootResult {
54
54
  const searched: string[] = []
55
55
  let current = startDir
56
56
 
@@ -13,9 +13,9 @@
13
13
  */
14
14
 
15
15
  import type { HookInvocation, HookResult } from '../contract.ts'
16
- import { bunRunner, createBriefingHandler } from './index.ts'
16
+ import { createBriefingHandler } from './index.ts'
17
17
 
18
- const briefingHandler = createBriefingHandler({ run: bunRunner })
18
+ const briefingHandler = createBriefingHandler()
19
19
 
20
20
  export async function handleBriefing(inv: HookInvocation): Promise<HookResult> {
21
21
  return briefingHandler(inv)
@@ -1,320 +1,60 @@
1
- /**
2
- * The `briefing` hook kind.
3
- *
4
- * Ports `enact-m5/.agents/hooks/session-briefing/`
5
- * (`session-briefing.mjs` + `src/render.mjs` + `src/warmup.mjs`) onto the
6
- * `HookHandler` contract in `../contract.ts`.
7
- *
8
- * Two subprocess calls into `lean-ctx`, both behind the injected `Runner` so
9
- * tests never touch a real binary:
10
- *
11
- * 1. `hook codex-session-start` — the base lean-ctx session briefing text,
12
- * read out of its `hookSpecificOutput.additionalContext` JSON.
13
- * 2. `overview [task]` and `knowledge status` — the PROJECT WARMUP appendix,
14
- * always emitted (even with no lean-ctx at all) because its static
15
- * workflow block does not depend on either call succeeding.
16
- *
17
- * `lean-ctx` is a GLOBAL binary installed fleet-wide on `PATH` by
18
- * global-tools (see its `manifest.json`'s `"lean-ctx"` entry) — unlike the
19
- * reference tree, there is no repo-local `.agents/bin/lean-ctx-local`
20
- * wrapper here, so every call below resolves `lean-ctx` off the ambient
21
- * `PATH` directly. What stays repo-local is lean-ctx's own state: every call
22
- * still sets `LEAN_CTX_CONFIG_DIR`/`LEAN_CTX_DATA_DIR`/`LEAN_CTX_STATE_DIR`/
23
- * `LEAN_CTX_CACHE_DIR` rooted at `<root>/.agents/lean-ctx/<config/lean-ctx|data|state|cache>`
24
- * (`../../lean-ctx/env.ts`'s `leanCtxEnv` — shared with the `lean-ctx`
25
- * pre/post-tool-use hook kind, `../lean-ctx/index.ts`), so lean-ctx's
26
- * config/data/state/cache stay per-repository even though the binary itself
27
- * is now shared.
28
- *
29
- * HARDCUT (work item A.3): this used to set the plain `XDG_CONFIG_HOME`/
30
- * `XDG_DATA_HOME`/`XDG_STATE_HOME`/`XDG_CACHE_HOME` vars, mirroring what the
31
- * reference's wrapper script exported before exec'ing its own repo-local
32
- * binary. `../../lean-ctx/env.ts`'s header records the live verification
33
- * (this session, 2026-09-14) that the real v3.9.20 binary does not actually
34
- * key its config/data/state/cache resolution on those XDG vars at all — only
35
- * on the four `LEAN_CTX_*` ones now used here.
36
- *
37
- * lean-ctx missing or failing is advisory, never fatal: the warmup section
38
- * still goes out and the failure is named on stderr, but this never returns
39
- * exitCode 2 — a briefing hook has no host-visible "block" channel, and the
40
- * reference script's own header says the same ("Advises only — never block
41
- * the session or prompt"). A spawn that never exits (gap #1) degrades the
42
- * same way: the injected `Runner` is timeout-enforcing (see
43
- * `../../lib/spawn-with-timeout.ts`), so a hung `lean-ctx` child is killed
44
- * and reported exactly like a failed/ENOENT spawn — `status: null` — rather
45
- * than hanging the calling agent host.
46
- *
47
- * `deploy.mjs`-level concerns from the reference tree — wiring the hook into
48
- * each host's config, `--self-test`/`--host=`/`--event=` argv parsing, the
49
- * five-surface deploy fixture in `tests/test-wiring.mjs` — are out of scope
50
- * here: `src/hosts/*` and `src/main.ts`'s dispatch own that, per this task's
51
- * boundary.
52
- */
53
-
1
+ /** Static session-orientation briefing for supported agent hosts. */
54
2
  import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
55
3
  import { join } from 'node:path'
56
-
57
4
  import type { HookHandler, HookInvocation, HookResult, HostId } from '../contract.ts'
58
5
  import { spawnWithTimeout } from '../../lib/spawn-with-timeout.ts'
59
- import { leanCtxEnvFor } from '../../lean-ctx/env.ts'
60
-
61
- /** The marker lean-ctx's own `hook codex-session-start` output carries, when present. */
62
- export const MARKER = 'lean-ctx SESSION BRIEFING'
63
- export const WARMUP_MARKER = 'PROJECT WARMUP'
64
-
65
- const LEAN_CTX_BIN = 'lean-ctx'
66
6
 
67
- const OVERVIEW_MAX_LINES = 28
68
- const OVERVIEW_TIMEOUT_MS = 12_000
69
- const DEFAULT_TIMEOUT_MS = 8_000
70
-
71
- export interface RunResult {
72
- readonly status: number | null
73
- readonly stdout: string
74
- readonly stderr: string
75
- /** `true` only when the spawn was killed for exceeding `timeoutMs` — see gap #1. */
76
- readonly timedOut?: boolean
77
- }
78
-
79
- export interface RunOptions {
80
- readonly cwd: string
81
- readonly env: Readonly<Record<string, string | undefined>>
82
- readonly input?: string
83
- /** Wall-clock spawn timeout in ms; overridable per call, defaults per call site below. */
84
- readonly timeoutMs?: number
85
- }
86
-
87
- /** Process spawning, injected so tests never need a real `lean-ctx` binary. */
7
+ interface RunResult { readonly status: number | null; readonly stdout: string; readonly stderr: string; readonly timedOut?: boolean }
8
+ interface RunOptions { readonly cwd: string; readonly env: Readonly<Record<string, string | undefined>>; readonly input?: string; readonly timeoutMs?: number }
88
9
  export type Runner = (cmd: string, args: readonly string[], opts: RunOptions) => Promise<RunResult>
89
-
90
- function deliveredStateDir(root: string): string {
91
- return join(root, '.agents/lean-ctx/state/session-briefing-delivered')
92
- }
93
-
94
- function sessionId(payload: Record<string, unknown>): string {
95
- const raw = payload['session_id'] ?? payload['conversation_id']
96
- return typeof raw === 'string' && raw.trim().length > 0 ? raw.trim() : 'unknown'
97
- }
98
-
99
- /** Cursor and Kimi have no host-native "fire once at SessionStart" channel; gate on a marker file instead. */
100
- function usesPromptGate(host: HostId): boolean {
101
- return host === 'cursor' || host === 'kimi'
10
+ /** Kept for the shared subprocess-runner contract used by focused tests. */
11
+ export const bunRunner: Runner = async (cmd, args, opts) => {
12
+ try {
13
+ const result = await spawnWithTimeout(cmd, args, { cwd: opts.cwd, env: opts.env, timeoutMs: opts.timeoutMs ?? 8_000, ...(opts.input === undefined ? {} : { stdin: opts.input }) })
14
+ return result.timedOut ? { status: null, stdout: result.stdout, stderr: result.stderr.trim() || `${cmd} timed out after ${opts.timeoutMs ?? 8_000}ms`, timedOut: true } : { status: result.exitCode, stdout: result.stdout, stderr: result.stderr }
15
+ } catch (error) { return { status: null, stdout: '', stderr: error instanceof Error ? error.message : String(error) } }
102
16
  }
103
17
 
104
- function deliveredPath(root: string, host: HostId, session: string): string {
105
- return join(deliveredStateDir(root), `${host}-${session}.done`)
106
- }
18
+ const WARMUP_MARKER = 'PROJECT WARMUP'
107
19
 
108
- function alreadyDelivered(root: string, host: HostId, session: string): boolean {
109
- if (!usesPromptGate(host)) return false
110
- return existsSync(deliveredPath(root, host, session))
20
+ function deliveredStateDir(root: string): string { return join(root, '.adl', 'state', 'session-briefing-delivered') }
21
+ function sessionId(payload: Record<string, unknown>): string {
22
+ const raw = payload.session_id ?? payload.conversation_id
23
+ return typeof raw === 'string' && raw.trim() ? raw.trim() : 'unknown'
111
24
  }
112
-
25
+ function usesPromptGate(host: HostId): boolean { return host === 'cursor' || host === 'kimi' }
26
+ function deliveredPath(root: string, host: HostId, session: string): string { return join(deliveredStateDir(root), `${host}-${session}.done`) }
27
+ function alreadyDelivered(root: string, host: HostId, session: string): boolean { return usesPromptGate(host) && existsSync(deliveredPath(root, host, session)) }
113
28
  function markDelivered(root: string, host: HostId, session: string): void {
114
29
  if (!usesPromptGate(host)) return
115
30
  mkdirSync(deliveredStateDir(root), { recursive: true })
116
31
  writeFileSync(deliveredPath(root, host, session), `${new Date().toISOString()}\n`)
117
32
  }
118
-
119
- function runLeanCtx(
120
- run: Runner,
121
- root: string,
122
- env: Readonly<Record<string, string | undefined>>,
123
- args: readonly string[],
124
- timeoutMs = DEFAULT_TIMEOUT_MS,
125
- ): Promise<RunResult> {
126
- return run(LEAN_CTX_BIN, args, { cwd: root, env: leanCtxEnvFor(root, env), timeoutMs })
127
- }
128
-
129
- function truncateLines(text: string, maxLines: number): string {
130
- const lines = text.split('\n')
131
- if (lines.length <= maxLines) return text
132
- return `${lines.slice(0, maxLines).join('\n')}\n… (${lines.length - maxLines} more lines; call ctx_overview for full map)`
133
- }
134
-
135
- function taskFromPayload(payload: Record<string, unknown>): string {
136
- const prompt = payload['prompt']
137
- const trimmed = typeof prompt === 'string' ? prompt.trim() : ''
138
- if (trimmed.length < 8) return ''
139
- return trimmed.length > 120 ? `${trimmed.slice(0, 117)}…` : trimmed
140
- }
141
-
142
- function workflowBlock(): string {
33
+ function briefingText(): string {
143
34
  return [
144
- WARMUP_MARKER,
145
- '',
146
- 'Start every session (ctx_* or lean-ctx; use ctx_call when not advertised):',
147
- '• ctx_overview / lean-ctx overview ["task"] — project map; FIRST on unfamiliar work',
35
+ WARMUP_MARKER, '',
36
+ 'Start every session with ctx_overview when it is available; use ctx_call when it is not advertised.',
148
37
  '• ctx_knowledge(action="wakeup") — cross-session facts and decisions',
149
- '• ctx_session(action="status") — last session findings in this repo',
150
- '',
151
- 'Knowledge: ctx_knowledge or lean-ctx knowledge — status | recall | search | remember | consolidate',
152
- 'Checkpoints: ctx_session(action="task"|"decision", …) after significant progress',
153
- '',
38
+ '• ctx_session(action="status") — last session findings in this repository', '',
154
39
  'After orientation: ctx_compose → ctx_read/ctx_search → ctx_shell (verify) → persist.',
155
40
  ].join('\n')
156
41
  }
157
-
158
- /**
159
- * The PROJECT WARMUP appendix. Always non-empty — its static workflow block
160
- * does not depend on `lean-ctx` at all — so a briefing is never fully silent
161
- * just because the binary is missing.
162
- */
163
- async function projectWarmupAppendix(
164
- run: Runner,
165
- root: string,
166
- env: Readonly<Record<string, string | undefined>>,
167
- payload: Record<string, unknown>,
168
- ): Promise<string> {
169
- const parts = [workflowBlock()]
170
-
171
- const task = taskFromPayload(payload)
172
- const overviewArgs = task ? ['overview', task] : ['overview']
173
- const overview = await runLeanCtx(run, root, env, overviewArgs, OVERVIEW_TIMEOUT_MS)
174
- if (overview.status === 0 && overview.stdout.trim()) {
175
- parts.push('', '--- ctx_overview (cached snapshot) ---', truncateLines(overview.stdout.trim(), OVERVIEW_MAX_LINES))
176
- }
177
-
178
- const knowledge = await runLeanCtx(run, root, env, ['knowledge', 'status'])
179
- if (knowledge.status === 0 && knowledge.stdout.trim()) {
180
- parts.push('', '--- ctx_knowledge status ---', knowledge.stdout.trim())
181
- }
182
-
183
- return parts.join('\n')
184
- }
185
-
186
- function composeBriefing(base: string, warmup: string): string {
187
- const b = base.trim()
188
- const w = warmup.trim()
189
- if (b && w) return `${b}\n\n${w}`
190
- return b || w
191
- }
192
-
193
- interface BaseBriefing {
194
- readonly text: string
195
- readonly failureNote: string
196
- readonly outcome: 'ok' | 'timeout' | 'error'
197
- }
198
-
199
- /** Runs `lean-ctx hook codex-session-start`; failure degrades to an empty base text plus a stderr note. */
200
- async function baseBriefing(
201
- run: Runner,
202
- root: string,
203
- env: Readonly<Record<string, string | undefined>>,
204
- payload: Record<string, unknown>,
205
- ): Promise<BaseBriefing> {
206
- const result = await run(LEAN_CTX_BIN, ['hook', 'codex-session-start'], {
207
- cwd: root,
208
- env: leanCtxEnvFor(root, env),
209
- input: JSON.stringify(payload),
210
- timeoutMs: DEFAULT_TIMEOUT_MS,
211
- })
212
-
213
- if (result.status !== 0 || !result.stdout.trim()) {
214
- const reason = result.stderr.trim() || `lean-ctx exited with status ${String(result.status)}`
215
- return {
216
- text: '',
217
- failureNote: `session-briefing: lean-ctx hook codex-session-start failed — ${reason}\n`,
218
- outcome: result.timedOut ? 'timeout' : 'error',
219
- }
220
- }
221
-
222
- try {
223
- const parsed = JSON.parse(result.stdout) as { hookSpecificOutput?: { additionalContext?: unknown } }
224
- const text = parsed.hookSpecificOutput?.additionalContext
225
- return { text: typeof text === 'string' ? text : '', failureNote: '', outcome: 'ok' }
226
- } catch (error) {
227
- const message = error instanceof Error ? error.message : String(error)
228
- return {
229
- text: '',
230
- failureNote: `session-briefing: lean-ctx hook codex-session-start returned invalid JSON — ${message}\n`,
231
- outcome: 'error',
232
- }
233
- }
234
- }
235
-
236
- /**
237
- * Wrap briefing text in a host's native envelope.
238
- *
239
- * Per official docs where they differ from the reference tree:
240
- * - Claude / Codex SessionStart (and any other event): `hookSpecificOutput.additionalContext`.
241
- * - Cursor: flat `additional_context` — the reference's nested
242
- * `hookSpecificOutput` shape for Cursor `UserPromptSubmit` is not part of
243
- * Cursor's documented hook contract, so it is not ported here.
244
- * - Kimi: bare stdout text (its `UserPromptSubmit` hook has no JSON envelope).
245
- * - OpenCode: `{"advice": "..."}`, consumed by this repo's own OpenCode plugin.
246
- */
247
42
  function renderBriefing(host: HostId, event: string, text: string): string {
248
- if (!text) return ''
249
43
  if (host === 'kimi') return `${text}\n`
250
44
  if (host === 'opencode') return JSON.stringify({ advice: text })
251
45
  if (host === 'cursor') return JSON.stringify({ additional_context: text })
252
46
  return JSON.stringify({ hookSpecificOutput: { hookEventName: event, additionalContext: text } })
253
47
  }
254
48
 
255
- export function createBriefingHandler(deps: { run: Runner }): HookHandler {
49
+ export function createBriefingHandler(): HookHandler {
256
50
  return async (inv: HookInvocation): Promise<HookResult> => {
257
- const { host, root, env } = inv
258
- const payload = inv.payload
259
- const event = inv.event ?? 'SessionStart'
260
- const session = sessionId(payload)
261
-
262
- if (alreadyDelivered(root, host, session)) {
51
+ const session = sessionId(inv.payload)
52
+ if (alreadyDelivered(inv.root, inv.host, session)) {
263
53
  inv.record?.({ reason: 'SKIP already delivered this session' })
264
54
  return { stdout: '', stderr: '', exitCode: 0 }
265
55
  }
266
-
267
- const { text: base, failureNote, outcome } = await baseBriefing(deps.run, root, env, payload)
268
- const warmup = await projectWarmupAppendix(deps.run, root, env, payload)
269
- const text = composeBriefing(base, warmup)
270
-
271
- markDelivered(root, host, session)
272
- const reasons = { ok: 'PASS', timeout: 'TIMEOUT lean-ctx hook codex-session-start', error: 'ERROR lean-ctx hook codex-session-start' }
273
- inv.record?.({
274
- reason: reasons[outcome],
275
- message: failureNote.trim(),
276
- downstream: 'lean-ctx hook codex-session-start, lean-ctx overview, lean-ctx knowledge status',
277
- })
278
-
279
- return {
280
- stdout: renderBriefing(host, event, text),
281
- stderr: failureNote,
282
- exitCode: 0,
283
- }
56
+ markDelivered(inv.root, inv.host, session)
57
+ inv.record?.({ reason: 'PASS', downstream: 'static session briefing' })
58
+ return { stdout: renderBriefing(inv.host, inv.event ?? 'SessionStart', briefingText()), stderr: '', exitCode: 0 }
284
59
  }
285
60
  }
286
-
287
- /**
288
- * The production `Runner`: a real, timeout-enforcing subprocess via
289
- * `spawnWithTimeout` (see `../../lib/spawn-with-timeout.ts`) — replaces the
290
- * reference tree's `Bun.spawnSync`, which had no timeout and could hang the
291
- * calling agent host forever on a stuck `lean-ctx` child (gap #1). A timeout
292
- * degrades exactly like an ENOENT/failed spawn: `status: null` with the
293
- * reason on stderr, plus `timedOut: true` so callers can tell the two apart.
294
- */
295
- export const bunRunner: Runner = async (cmd, args, opts) => {
296
- const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS
297
- try {
298
- const result = await spawnWithTimeout(cmd, args, {
299
- cwd: opts.cwd,
300
- env: opts.env,
301
- timeoutMs,
302
- ...(opts.input !== undefined ? { stdin: opts.input } : {}),
303
- })
304
- if (result.timedOut) {
305
- return {
306
- status: null,
307
- stdout: result.stdout,
308
- stderr: result.stderr.trim() || `${cmd} timed out after ${timeoutMs}ms`,
309
- timedOut: true,
310
- }
311
- }
312
- return { status: result.exitCode, stdout: result.stdout, stderr: result.stderr }
313
- } catch (error) {
314
- const message = error instanceof Error ? error.message : String(error)
315
- return { status: null, stdout: '', stderr: message }
316
- }
317
- }
318
-
319
- export const handleBriefing: HookHandler = createBriefingHandler({ run: bunRunner })
320
- export default handleBriefing