@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
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # `sudo adl reconcile --host NAME [--mode plan|apply]` -- one full pass of what
5
+ # the 12-hourly job does (the job's program is `adl reconcile`, which runs this),
6
+ # also run on demand:
7
+ #
8
+ # 1. tools: this package's bin/sync-and-reconcile (run through bash, never
9
+ # executed directly: bun leaves every shipped file but the `bin` targets
10
+ # without an exec bit) with `--source npm --device NAME --owner OWNER`
11
+ # (package update with bun, then tools reconcile). `--source npm` names
12
+ # the registry the package comes from, not the installer. The owner is the
13
+ # device's `administrator` in this package's
14
+ # manifest (bin/lib/fleet-host.sh, the lookup bin/setup shares). --mode is
15
+ # forwarded only when given, so the default is apply.
16
+ # 2. repositories: `adl maintain --location <repo_location> --expect-user
17
+ # OWNER`, the package's own bin/adl, run AS THE ADMINISTRATOR -- never as
18
+ # root. sudo resets PATH to its secure_path, which has neither Homebrew nor
19
+ # /usr/local/bin, so PATH is always handed over explicitly with `env PATH=`
20
+ # (every sudo -u call that ends up running adl, git or bun must); the
21
+ # owner's bun bin directory (~/.bun/bin) is on it, after /usr/local/bin.
22
+ # --mode plan becomes --dry-run.
23
+ #
24
+ # Both steps always run (a failed tools step does not hide a repository problem,
25
+ # and vice versa); the exit code is the first failure's, and each failure is
26
+ # reported as an ERROR line. A host that declares no repo_location skips step 2
27
+ # with a log line.
28
+ #
29
+ # ADL_SETUP_TEST_ROOT is the same single test switch bin/setup has: unset in
30
+ # every real run; when set it only keeps the caller's PATH so `id`, `uname` and
31
+ # `sudo` can be stubbed (packages/fleet/tests/reconcile-host.test.ts).
32
+
33
+ if [[ -n "${ADL_SETUP_TEST_ROOT:-}" ]]; then
34
+ export PATH="${PATH:-/usr/bin:/bin}"
35
+ else
36
+ export PATH="/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
37
+ fi
38
+
39
+ host=""
40
+ mode=""
41
+ while [[ "$#" -gt 0 ]]; do
42
+ case "$1" in
43
+ --host) host="${2:-}"; shift 2 ;;
44
+ --mode) mode="${2:-}"; shift 2 ;;
45
+ *) echo "ERROR unknown argument: $1" >&2; exit 2 ;;
46
+ esac
47
+ done
48
+ [[ -n "$host" ]] || { echo "ERROR usage: sudo adl reconcile --host NAME [--mode plan|apply]" >&2; exit 2; }
49
+ if [[ -n "$mode" && "$mode" != plan && "$mode" != apply ]]; then
50
+ echo "ERROR unsupported mode: $mode (expected plan or apply)" >&2
51
+ exit 2
52
+ fi
53
+ [[ "$(id -u)" -eq 0 ]] || { echo "ERROR adl reconcile must run as root: sudo adl reconcile --host $host" >&2; exit 1; }
54
+
55
+ script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
56
+ package_dir="$(cd -- "$script_dir/.." && pwd)"
57
+ # shellcheck source=lib/fleet-host.sh
58
+ source "$script_dir/lib/fleet-host.sh"
59
+ fleet_host_resolve "adl reconcile" "$package_dir/packages/fleet/manifest.json" "$host" || exit $?
60
+ owner="$fleet_host_owner"
61
+ repo_location="$fleet_host_repo_location"
62
+ branch_max_age_days="$fleet_host_branch_max_age_days"
63
+
64
+ # shellcheck source=lib/adl-package.sh
65
+ source "$script_dir/lib/adl-package.sh"
66
+ [[ -f "$script_dir/sync-and-reconcile" ]] || { echo "ERROR adl reconcile: package scheduler script is missing: $script_dir/sync-and-reconcile" >&2; exit 1; }
67
+
68
+ # One lock around both steps: an on-demand run overlapping the timer must not
69
+ # run a second repository pass after its tools step lost sync's own lock.
70
+ if [[ -n "${ADL_SETUP_TEST_ROOT:-}" ]]; then
71
+ lock_dir="${ADL_SETUP_TEST_ROOT%/}/adl-reconcile.lock"
72
+ else
73
+ lock_dir=/var/run/adl-reconcile.lock
74
+ fi
75
+ adl_lock_acquire "$lock_dir" "adl reconcile: another reconcile is running" || exit 1
76
+ trap 'rm -rf -- "$lock_dir"' EXIT
77
+
78
+ # 1. tools
79
+ sync_args=(--source npm --device "$host" --owner "$owner")
80
+ if [[ -n "$mode" ]]; then sync_args+=(--mode "$mode"); fi
81
+ tools_rc=0
82
+ bash "$script_dir/sync-and-reconcile" "${sync_args[@]}" || tools_rc=$?
83
+ if [[ "$tools_rc" -ne 0 ]]; then
84
+ echo "ERROR global-tools: tools reconcile failed (exit $tools_rc)" >&2
85
+ fi
86
+
87
+ # 2. repositories
88
+ repos_rc=0
89
+ if [[ -z "$repo_location" ]]; then
90
+ echo "global-tools: repo maintenance skipped: $host declares no repo_location"
91
+ else
92
+ adl_bin="$package_dir/bin/adl"
93
+ if [[ ! -x "$adl_bin" ]]; then
94
+ echo "ERROR global-tools: package adl is missing or not executable: $adl_bin" >&2
95
+ repos_rc=1
96
+ else
97
+ case "$fleet_host_platform" in
98
+ mac) repo_os=Darwin ;;
99
+ *) repo_os=Linux ;;
100
+ esac
101
+ if ! owner_home="$(adl_owner_home "$owner")"; then
102
+ echo "ERROR global-tools: cannot resolve the home directory of $owner" >&2
103
+ exit 1
104
+ fi
105
+ owner_path="$(adl_owner_path "$repo_os" "$owner_home")"
106
+ maintain_args=(maintain --location "$repo_location" --expect-user "$owner")
107
+ # config.repo_maintain.branch_max_age_days in this package's manifest, never an environment variable.
108
+ if [[ -n "$branch_max_age_days" ]]; then maintain_args+=(--branch-max-age-days "$branch_max_age_days"); fi
109
+ if [[ "$mode" == plan ]]; then maintain_args+=(--dry-run); fi
110
+ # /usr/local/bin first (see adl_owner_path): git must resolve to the managed
111
+ # controller, which routes Azure DevOps traffic through the agent identity;
112
+ # Homebrew's git would bypass it.
113
+ sudo -u "$owner" -H env PATH="$owner_path" "$adl_bin" "${maintain_args[@]}" || repos_rc=$?
114
+ if [[ "$repos_rc" -ne 0 ]]; then
115
+ echo "ERROR global-tools: repository maintenance failed (exit $repos_rc)" >&2
116
+ fi
117
+ fi
118
+ fi
119
+
120
+ if [[ "$tools_rc" -ne 0 ]]; then exit "$tools_rc"; fi
121
+ exit "$repos_rc"
package/bin/setup ADDED
@@ -0,0 +1,219 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # `sudo adl setup --host NAME` -- the whole onboarding of a host after
5
+ # `bun install -g @amsterdamdatalabs/adl-agent-control` (run as the device's
6
+ # administrator):
7
+ #
8
+ # 1. check this is THE package the job manages (the one in the owner's bun
9
+ # global directory), that its bin/adl is there, and that the `adl` the
10
+ # owner gets on PATH is this package and not a different one that shadows it
11
+ # 2. run the first reconcile: `<this package>/bin/adl reconcile --host NAME`
12
+ # 3. only if that succeeded, arm the job that re-runs the same command every
13
+ # 12 hours
14
+ #
15
+ # A host that cannot reconcile is never left with a timer that fails unseen.
16
+ # The job's program is the package's own bin/adl, not a shell script: on macOS
17
+ # the one-time Full Disk Access grant (needed to read the repositories under the
18
+ # host's repo_location) goes to that binary, and the launchd/systemd job and
19
+ # `sudo adl reconcile --host NAME` are then literally the same command.
20
+ #
21
+ # Everything comes from this package: it locates itself from its own path and
22
+ # reads packages/fleet/manifest.json beside it (no git checkout, no source
23
+ # flag -- the published package is the only source). The account the job runs
24
+ # bun as is the device's `administrator` in that manifest; there is no owner
25
+ # flag. The package's scripts are run through bash, never executed directly:
26
+ # bun leaves every shipped file but the `bin` targets without an exec bit.
27
+ #
28
+ # ADL_SETUP_TEST_ROOT is the one test switch (packages/fleet/tests/setup.test.ts):
29
+ # unset in every real run. When set it relocates the system paths under that
30
+ # directory and keeps the caller's PATH so the system commands can be stubbed.
31
+
32
+ if [[ -n "${ADL_SETUP_TEST_ROOT:-}" ]]; then
33
+ export PATH="${PATH:-/usr/bin:/bin}"
34
+ # The sourced sync-and-reconcile has its own test switch; one switch here
35
+ # drives both, so a test sets only ADL_SETUP_TEST_ROOT.
36
+ export SYNC_AND_RECONCILE_TEST_ROOT="$ADL_SETUP_TEST_ROOT"
37
+ else
38
+ export PATH="/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
39
+ fi
40
+
41
+ host=""
42
+ while [[ "$#" -gt 0 ]]; do
43
+ case "$1" in
44
+ --host) host="${2:-}"; shift 2 ;;
45
+ *) echo "ERROR unknown argument: $1" >&2; exit 2 ;;
46
+ esac
47
+ done
48
+ [[ -n "$host" ]] || { echo "ERROR usage: sudo adl setup --host NAME" >&2; exit 2; }
49
+ [[ "$(id -u)" -eq 0 ]] || { echo "ERROR adl setup must run as root: sudo adl setup --host $host" >&2; exit 1; }
50
+
51
+ script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
52
+ package_dir="$(cd -- "$script_dir/.." && pwd)"
53
+ package_dir_real="$(cd -P -- "$script_dir/.." && pwd -P)"
54
+ # shellcheck source=lib/fleet-host.sh
55
+ source "$script_dir/lib/fleet-host.sh"
56
+ fleet_host_resolve "adl setup" "$package_dir/packages/fleet/manifest.json" "$host" || exit $?
57
+ owner="$fleet_host_owner"
58
+ minute="$fleet_host_minute"
59
+
60
+ # The job keeps THE package installed in the owner's bun global directory up to
61
+ # date and reconciles from it. This must be that package, or the host would be
62
+ # armed to manage a different copy than the one the operator just ran. Ask for
63
+ # the location the way the job does (bin/lib/adl-package.sh, shared with
64
+ # sync-and-reconcile), and compare real paths.
65
+ # shellcheck source=lib/adl-package.sh
66
+ source "$script_dir/lib/adl-package.sh"
67
+ os_name="$(uname -s)"
68
+ owner_home="$(adl_owner_home "$owner")" || {
69
+ echo "ERROR adl setup: cannot resolve the home directory of $owner" >&2
70
+ exit 1
71
+ }
72
+ managed_dir="$(adl_platform_package_dir "$(adl_global_node_modules "$owner_home")" "$os_name" "$(uname -m)")" || exit 1
73
+ managed_real="$(cd -P -- "$managed_dir" 2>/dev/null && pwd -P)" || managed_real=""
74
+ if [[ -z "$managed_real" || "$package_dir_real" != "$managed_real" ]]; then
75
+ {
76
+ echo "ERROR adl setup: this package ($package_dir_real) is not the package the scheduled job manages ($managed_dir)."
77
+ echo "ERROR adl setup: install it where the job looks, as $owner, then run setup again:"
78
+ echo "ERROR adl setup: bun install -g @amsterdamdatalabs/adl-agent-control"
79
+ } >&2
80
+ exit 1
81
+ fi
82
+
83
+ adl_bin="$package_dir_real/bin/adl"
84
+ [[ -x "$adl_bin" ]] || { echo "ERROR adl setup: the package adl is missing or not executable: $package_dir/bin/adl" >&2; exit 1; }
85
+ adl_check_adl_not_shadowed "$owner" "$os_name" "$owner_home" "$package_dir_real" "adl setup" || exit 1
86
+
87
+ if [[ -n "${ADL_SETUP_TEST_ROOT:-}" ]]; then
88
+ system_root="${ADL_SETUP_TEST_ROOT%/}"
89
+ else
90
+ system_root=""
91
+ fi
92
+ legacy_adl_sync="$system_root/usr/local/libexec/adl-sync"
93
+ launch_daemons_dir="$system_root/Library/LaunchDaemons"
94
+ systemd_dir="$system_root/etc/systemd/system"
95
+ brew_prefix="$system_root/home/linuxbrew/.linuxbrew"
96
+
97
+ # Preflight that must hold before the first reconcile: the Linux job runs
98
+ # Homebrew as a non-root owner, and that owner needs git's safe.directory for
99
+ # the brew repositories or every `brew update` inside the reconcile fails.
100
+ if [[ "$fleet_host_platform" == linux ]]; then
101
+ if [[ -d "$brew_prefix" ]]; then
102
+ brew_owner="$(stat -c '%U' "$brew_prefix")"
103
+ [[ "$brew_owner" != root ]] || {
104
+ echo "ERROR Homebrew prefix must be owned by a non-root account: /home/linuxbrew/.linuxbrew" >&2
105
+ exit 1
106
+ }
107
+ else
108
+ echo "ERROR Homebrew prefix missing: /home/linuxbrew/.linuxbrew" >&2
109
+ exit 1
110
+ fi
111
+ for brew_repo in \
112
+ "$brew_prefix/Homebrew" \
113
+ "$brew_prefix/Homebrew/Library/Taps/adl-tan-theta/homebrew-tap"; do
114
+ [[ -d "$brew_repo/.git" ]] || continue
115
+ if ! (cd /tmp && sudo -u "$brew_owner" -H git config --global --get-all safe.directory 2>/dev/null) | grep -Fxq "$brew_repo"; then
116
+ (cd /tmp && sudo -u "$brew_owner" -H git config --global --add safe.directory "$brew_repo")
117
+ fi
118
+ done
119
+ fi
120
+
121
+ mkdir -p "$system_root/var/lib/adl" "$system_root/var/log/adl"
122
+
123
+ echo "adl setup: first reconcile for $host (owner $owner)"
124
+ reconcile_rc=0
125
+ "$adl_bin" reconcile --host "$host" || reconcile_rc=$?
126
+ if [[ "$reconcile_rc" -ne 0 ]]; then
127
+ echo "ERROR adl setup: first reconcile failed (exit $reconcile_rc); scheduler NOT armed. Fix the failure and re-run: sudo adl setup --host $host" >&2
128
+ exit "$reconcile_rc"
129
+ fi
130
+
131
+ case "$fleet_host_platform" in
132
+ mac)
133
+ mkdir -p "$launch_daemons_dir"
134
+ plist="$launch_daemons_dir/com.adl.global-tools.plist"
135
+ {
136
+ printf '%s\n' '<?xml version="1.0" encoding="UTF-8"?>'
137
+ printf '%s\n' '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
138
+ printf '%s\n' '<plist version="1.0"><dict>'
139
+ printf '%s\n' '<key>Label</key><string>com.adl.global-tools</string>'
140
+ printf '%s\n' '<key>ProgramArguments</key><array>'
141
+ printf '<string>%s</string>\n' "$adl_bin"
142
+ printf '%s\n' '<string>reconcile</string>'
143
+ printf '<string>--host</string><string>%s</string>\n' "$host"
144
+ printf '%s\n' '</array>'
145
+ printf '%s\n' '<key>StartCalendarInterval</key><array>'
146
+ for hour in 0 12; do printf '<dict><key>Hour</key><integer>%s</integer><key>Minute</key><integer>%s</integer></dict>\n' "$hour" "$minute"; done
147
+ printf '%s\n' '</array><key>ProcessType</key><string>Background</string>'
148
+ printf '%s\n' '<key>StandardOutPath</key><string>/var/log/adl/stdout.log</string>'
149
+ printf '%s\n' '<key>StandardErrorPath</key><string>/var/log/adl/stderr.log</string>'
150
+ printf '%s\n' '</dict></plist>'
151
+ } >"$plist"
152
+ chown root:wheel "$plist"
153
+ chmod 0644 "$plist"
154
+ plutil -lint "$plist"
155
+ # bootout fails when the job is not loaded, so ask first instead of
156
+ # swallowing the error: a bootout that fails on a loaded job must stop us.
157
+ if launchctl print system/com.adl.global-tools >/dev/null 2>&1; then
158
+ launchctl bootout system/com.adl.global-tools
159
+ # bootout returns before launchd has finished unloading, and a
160
+ # bootstrap in that window fails with an I/O error. Wait until the
161
+ # label is really gone, bounded, and fail loud if it is not.
162
+ unloaded=0
163
+ for _ in 1 2 3 4 5 6 7 8 9 10; do
164
+ if ! launchctl print system/com.adl.global-tools >/dev/null 2>&1; then unloaded=1; break; fi
165
+ sleep 0.5
166
+ done
167
+ [[ "$unloaded" -eq 1 ]] || {
168
+ echo "ERROR adl setup: com.adl.global-tools is still loaded after bootout (waited 5s); not bootstrapping. Run: sudo launchctl bootout system/com.adl.global-tools" >&2
169
+ exit 1
170
+ }
171
+ fi
172
+ launchctl bootstrap system "$plist"
173
+ ;;
174
+ linux)
175
+ mkdir -p "$systemd_dir"
176
+ cat > "$systemd_dir/adl-global-tools.service" <<EOF
177
+ [Unit]
178
+ Description=Reconcile Adl global tools and repositories (adl reconcile)
179
+ After=network-online.target
180
+ Wants=network-online.target
181
+
182
+ [Service]
183
+ Type=oneshot
184
+ ExecStart=$adl_bin reconcile --host $host
185
+ StandardOutput=append:/var/log/adl/stdout.log
186
+ StandardError=append:/var/log/adl/stderr.log
187
+ Nice=10
188
+ IOSchedulingClass=best-effort
189
+ IOSchedulingPriority=7
190
+ TimeoutStartSec=3h
191
+ EOF
192
+ cat > "$systemd_dir/adl-global-tools.timer" <<EOF
193
+ [Unit]
194
+ Description=Run Adl global-tool reconciliation every 12 hours
195
+
196
+ [Timer]
197
+ OnCalendar=*-*-* 00,12:$minute:00
198
+ Persistent=true
199
+ Unit=adl-global-tools.service
200
+
201
+ [Install]
202
+ WantedBy=timers.target
203
+ EOF
204
+ systemctl daemon-reload
205
+ systemctl enable --now adl-global-tools.timer
206
+ # enable --now leaves an already-active timer on its old schedule.
207
+ systemctl restart adl-global-tools.timer
208
+ ;;
209
+ esac
210
+
211
+ # The job used to run a copy of bin/sync-and-reconcile installed here. Its
212
+ # definition now points at the package's adl, so the copy is dead weight that
213
+ # would keep running stale update logic if anyone invoked it.
214
+ if [[ -e "$legacy_adl_sync" ]]; then
215
+ rm -f -- "$legacy_adl_sync"
216
+ echo "adl setup: removed the legacy scheduler copy $legacy_adl_sync"
217
+ fi
218
+
219
+ echo "adl setup: $host reconciled and armed (every 12 hours at minute $minute); run on demand with: sudo adl reconcile --host $host"
@@ -1,9 +1,15 @@
1
1
  #!/usr/bin/env bash
2
2
  # Managed by adl global-tools.
3
3
  # Keep /usr/local/bin first in interactive shells so manifest-owned front
4
- # controllers win over Homebrew and system executables on every host.
4
+ # controllers win over Homebrew and system executables on every host. The
5
+ # administrator's bun bin directory comes right after it (Tarun, 2026-10-01):
6
+ # hosts install the adl package with `bun install -g`, which links `adl` into
7
+ # $HOME/.bun/bin, and humans and agents must be able to run it (root on Linux:
8
+ # /root/.bun/bin). It stays behind /usr/local/bin so the managed git wins.
5
9
  set -euo pipefail
6
10
 
11
+ managed_path_line='export PATH="/usr/local/bin:$HOME/.bun/bin${PATH:+:$PATH}"'
12
+
7
13
  usage() {
8
14
  echo 'usage: shell-path-policy --home ABSOLUTE_PATH --platform mac|linux --mode plan|apply [--owner USER]' >&2
9
15
  exit 2
@@ -35,10 +41,14 @@ upsert_block() {
35
41
  mkdir -p -- "$(dirname -- "$file")"
36
42
  temp="$file.adl-new"
37
43
  if [[ -e "$file" ]]; then
44
+ # Trailing blank lines are dropped with the block: the append below puts one
45
+ # blank line back in front of it, so a re-run is byte-identical, not one line longer.
38
46
  awk -v begin="$begin" -v end="$end" '
39
47
  $0 == begin { inside = 1; next }
40
48
  $0 == end { inside = 0; next }
41
- !inside { print }
49
+ inside { next }
50
+ /^$/ { blanks++; next }
51
+ { while (blanks > 0) { print ""; blanks-- } print }
42
52
  ' "$file" >"$temp"
43
53
  else
44
54
  : >"$temp"
@@ -50,14 +60,14 @@ upsert_block() {
50
60
 
51
61
  if [[ "$platform" == mac ]]; then
52
62
  upsert_block "$home/.zshenv" '# BEGIN ADL GLOBAL PATH' '# END ADL GLOBAL PATH' \
53
- 'export PATH="/usr/local/bin${PATH:+:$PATH}"'
63
+ "$managed_path_line"
54
64
  exit 0
55
65
  fi
56
66
 
57
67
  upsert_block "$home/.bashenv" '# BEGIN ADL GLOBAL PATH ENV' '# END ADL GLOBAL PATH ENV' \
58
- 'export PATH="/usr/local/bin${PATH:+:$PATH}"'
68
+ "$managed_path_line"
59
69
  upsert_block "$home/.zshenv" '# BEGIN ADL GLOBAL PATH ENV' '# END ADL GLOBAL PATH ENV' \
60
- 'export PATH="/usr/local/bin${PATH:+:$PATH}"'
70
+ "$managed_path_line"
61
71
  for shell_file in "$home/.bashrc" "$home/.bash_profile" "$home/.profile"; do
62
72
  upsert_block "$shell_file" '# BEGIN ADL GLOBAL PATH SOURCE' '# END ADL GLOBAL PATH SOURCE' \
63
73
  'if [[ -r "$HOME/.bashenv" ]]; then . "$HOME/.bashenv"; fi'
@@ -7,20 +7,26 @@ else
7
7
  export PATH="/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
8
8
  fi
9
9
 
10
- # Scheduled sync downloads the ADL platform package and executes its own
11
- # reconcile command. Checkout mode is an explicit developer-only bypass.
10
+ # Scheduled sync installs the published ADL package with bun (as the device's
11
+ # administrator) and runs that package's own reconcile. Checkout mode is an
12
+ # explicit developer-only bypass. Package layout and owner lookups are in
13
+ # lib/adl-package.sh, shared with bin/setup and bin/reconcile.
14
+ _sync_and_reconcile_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
15
+ # shellcheck source=lib/adl-package.sh
16
+ source "$_sync_and_reconcile_dir/lib/adl-package.sh"
17
+
12
18
  sync_and_reconcile_platform() {
13
19
  case "$(uname -s)" in
14
20
  Darwin) printf '%s\n' mac ;;
15
21
  Linux) printf '%s\n' linux ;;
16
- *) echo "unsupported operating system for scheduled sync: $(uname -s)" >&2; return 1 ;;
22
+ *) echo "ERROR unsupported operating system for scheduled sync: $(uname -s)" >&2; return 1 ;;
17
23
  esac
18
24
  }
19
25
 
20
26
  require_linux_automation_root() {
21
27
  local platform="$1" owner="$2"
22
28
  if [[ "$platform" == linux && "$owner" != root ]]; then
23
- echo "global-tools: Linux scheduled sync must run as root; got --owner $owner" >&2
29
+ echo "ERROR global-tools: Linux scheduled sync must run as root; got --owner $owner" >&2
24
30
  return 1
25
31
  fi
26
32
  }
@@ -35,35 +41,25 @@ parse_sync_source() {
35
41
  done
36
42
  case "$sync_source" in
37
43
  npm|checkout) ;;
38
- *) echo "unsupported source: $sync_source" >&2; return 2 ;;
44
+ *) echo "ERROR unsupported source: $sync_source" >&2; return 2 ;;
39
45
  esac
40
46
  }
41
47
 
42
- npm_package_spec() {
48
+ adl_package_spec() {
43
49
  local policy="$1" version="${2:-}"
44
50
  case "$policy" in
45
51
  latest-stable) printf '%s@latest\n' '@amsterdamdatalabs/adl-agent-control' ;;
46
52
  pinned)
47
53
  [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$ ]] || {
48
- echo "pinned update_policy requires a valid installed package version" >&2
54
+ echo "ERROR pinned update_policy requires a valid installed package version" >&2
49
55
  return 1
50
56
  }
51
57
  printf '%s@%s\n' '@amsterdamdatalabs/adl-agent-control' "$version"
52
58
  ;;
53
- *) echo "unsupported update_policy: $policy" >&2; return 1 ;;
59
+ *) echo "ERROR unsupported update_policy: $policy" >&2; return 1 ;;
54
60
  esac
55
61
  }
56
62
 
57
- npm_platform_package_dir() {
58
- local npm_root="$1" os="$2" arch="$3" platform
59
- case "$os:$arch" in
60
- Darwin:arm64) platform=darwin-arm64 ;;
61
- Linux:x86_64) platform=linux-x64 ;;
62
- *) echo "unsupported platform for npm package: $os $arch" >&2; return 1 ;;
63
- esac
64
- printf '%s/@amsterdamdatalabs/adl-agent-control-%s\n' "${npm_root%/}" "$platform"
65
- }
66
-
67
63
  prepare_adl_npm_migration() {
68
64
  local applied_manifest="$1" device="$2" platform="$3" legacy_adl="$4" hash_file="$5"
69
65
  local previous_manager previous_executable
@@ -72,12 +68,12 @@ prepare_adl_npm_migration() {
72
68
  previous_executable="$(jq -r --arg platform "$platform" --arg device "$device" '(.[$platform].common.tools // {}) * (.[$platform].devices[$device].tools // {}) | .adl.executable // empty' "$applied_manifest")" || return 1
73
69
  [[ "$previous_manager" == bun-compile && "$previous_executable" == /usr/local/bin/adl ]] || return 0
74
70
  [[ -f "$legacy_adl" && ! -L "$legacy_adl" ]] || {
75
- echo "prior manifest proves adl was a Bun binary, but the expected regular file is missing or is a symlink: $legacy_adl" >&2
71
+ echo "ERROR prior manifest proves adl was a Bun binary, but the expected regular file is missing or is a symlink: $legacy_adl" >&2
76
72
  return 1
77
73
  }
78
74
  rm -f -- "$legacy_adl"
79
75
  rm -f -- "$hash_file"
80
- echo "global-tools: removed prior Bun adl binary before npm install: $legacy_adl"
76
+ echo "global-tools: removed prior Bun adl binary before the package install: $legacy_adl"
81
77
  }
82
78
 
83
79
  if [[ "${SYNC_AND_RECONCILE_SOURCE_ONLY:-0}" == 1 ]]; then
@@ -96,94 +92,84 @@ while [[ "$#" -gt 0 ]]; do
96
92
  --repo) repo="${2:-}"; shift 2 ;;
97
93
  --owner) owner="${2:-}"; shift 2 ;;
98
94
  --mode) mode="${2:-}"; shift 2 ;;
99
- *) echo "unknown argument: $1" >&2; exit 2 ;;
95
+ *) echo "ERROR unknown argument: $1" >&2; exit 2 ;;
100
96
  esac
101
97
  done
102
98
  case "$sync_source" in
103
99
  npm|checkout) ;;
104
- *) echo "unsupported source: $sync_source" >&2; exit 2 ;;
100
+ *) echo "ERROR unsupported source: $sync_source" >&2; exit 2 ;;
105
101
  esac
106
102
  [[ -n "$device" && -n "$owner" ]] || {
107
- echo "usage: sync-and-reconcile [--source npm|checkout] --device NAME --owner USER [--repo PATH] [--mode audit|plan|apply]" >&2
103
+ echo "ERROR usage: sync-and-reconcile [--source npm|checkout] --device NAME --owner USER [--repo PATH] [--mode audit|plan|apply]" >&2
108
104
  exit 2
109
105
  }
110
106
  [[ "$mode" == audit || "$mode" == plan || "$mode" == apply ]] || {
111
- echo "unsupported reconcile mode: $mode" >&2
107
+ echo "ERROR unsupported reconcile mode: $mode" >&2
112
108
  exit 2
113
109
  }
114
110
  if [[ "$sync_source" == checkout && -z "$repo" ]]; then
115
- echo "checkout source requires --repo PATH" >&2
111
+ echo "ERROR checkout source requires --repo PATH" >&2
116
112
  exit 2
117
113
  fi
118
114
  if [[ "$sync_source" == npm && -n "$repo" ]]; then
119
- echo "npm source does not accept --repo; use --source checkout for a checkout path" >&2
115
+ echo "ERROR npm source does not accept --repo; use --source checkout for a checkout path" >&2
120
116
  exit 2
121
117
  fi
122
118
 
123
119
  if [[ -n "${SYNC_AND_RECONCILE_TEST_ROOT:-}" ]]; then
124
120
  lock_dir="${SYNC_AND_RECONCILE_TEST_ROOT%/}/adl-sync.lock"
125
- scheduler_path="${SYNC_AND_RECONCILE_TEST_ROOT%/}/scheduler"
126
121
  else
127
122
  lock_dir=/var/run/adl-sync.lock
128
- scheduler_path=/usr/local/libexec/adl-sync
129
- fi
130
- if ! mkdir "$lock_dir" 2>/dev/null; then
131
- echo "global-tools: another reconciliation is running (lock: $lock_dir)" >&2
132
- exit 1
133
123
  fi
134
- trap 'rmdir "$lock_dir" 2>/dev/null || true' EXIT
124
+ adl_lock_acquire "$lock_dir" "global-tools: another reconciliation is running" || exit 1
125
+ trap 'rm -rf -- "$lock_dir"' EXIT
135
126
 
136
127
  host_platform="$(sync_and_reconcile_platform)"
137
128
  require_linux_automation_root "$host_platform" "$owner" || exit 1
138
129
 
139
130
  if [[ "$sync_source" == checkout ]]; then
140
- [[ -e "$repo/.git" ]] || { echo "developer checkout missing: $repo" >&2; exit 1; }
131
+ [[ -e "$repo/.git" ]] || { echo "ERROR developer checkout missing: $repo" >&2; exit 1; }
141
132
  manifest="$repo/packages/fleet/manifest.json"
142
- [[ -f "$manifest" ]] || { echo "developer checkout manifest missing: $manifest" >&2; exit 1; }
143
- [[ -x "$repo/bin/reconcile" ]] || { echo "developer checkout reconcile is missing: $repo/bin/reconcile" >&2; exit 1; }
133
+ [[ -f "$manifest" ]] || { echo "ERROR developer checkout manifest missing: $manifest" >&2; exit 1; }
134
+ [[ -f "$repo/bin/reconcile" ]] || { echo "ERROR developer checkout reconcile is missing: $repo/bin/reconcile" >&2; exit 1; }
144
135
  echo "global-tools: source=checkout (developer mode)"
145
136
  reconcile_dir="$repo/bin"
146
137
  else
147
138
  os="$(uname -s)"
148
139
  arch="$(uname -m)"
149
- case "$os" in
150
- Darwin) npm_path=/opt/homebrew/bin:/usr/bin:/bin ;;
151
- Linux) npm_path=/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin ;;
152
- *) echo "unsupported operating system for npm package: $os" >&2; exit 1 ;;
153
- esac
154
- npm_env=(PATH="$npm_path")
155
- if [[ "$os" == Linux ]]; then npm_env=(npm_config_prefix=/usr/local PATH="$npm_path"); fi
156
- npm_root="$(sudo -u "$owner" -H env "${npm_env[@]}" npm root -g)" || {
157
- echo "cannot resolve the global npm root as $owner" >&2
158
- exit 1
159
- }
160
- [[ "$npm_root" == /*/lib/node_modules ]] || {
161
- echo "global npm root has an unsupported path: $npm_root" >&2
140
+ owner_home="$(adl_owner_home "$owner")" || {
141
+ echo "ERROR cannot resolve the home directory of $owner" >&2
162
142
  exit 1
163
143
  }
164
- npm_prefix="${npm_root%/lib/node_modules}"
165
- platform_dir="$(npm_platform_package_dir "$npm_root" "$os" "$arch")" || exit 1
144
+ global_node_modules="$(adl_global_node_modules "$owner_home")"
145
+ platform_dir="$(adl_platform_package_dir "$global_node_modules" "$os" "$arch")" || exit 1
166
146
  installed_manifest="$platform_dir/packages/fleet/manifest.json"
167
147
  package_spec=""
148
+ update_policy=""
149
+ installed_version=""
168
150
  if [[ -f "$installed_manifest" ]]; then
151
+ [[ -f "$platform_dir/package.json" ]] && installed_version="$(jq -er '.version | select(type == "string")' "$platform_dir/package.json")" || {
152
+ echo "ERROR installed adl package has no readable version: $platform_dir/package.json" >&2
153
+ exit 1
154
+ }
169
155
  update_policy="$(jq -er '.config.update_policy | select(type == "string")' "$installed_manifest")" || {
170
- echo "installed adl package manifest has no config.update_policy: $installed_manifest" >&2
156
+ echo "ERROR installed adl package manifest has no config.update_policy: $installed_manifest" >&2
171
157
  exit 1
172
158
  }
173
159
  case "$update_policy" in
174
- latest-stable) package_spec="$(npm_package_spec latest-stable)" ;;
160
+ latest-stable) package_spec="$(adl_package_spec latest-stable)" ;;
175
161
  pinned)
176
162
  pinned_version="$(jq -er --arg platform "$host_platform" '.[$platform].common.tools.adl.version | select(type == "string")' "$installed_manifest")" || {
177
- echo "installed adl package manifest requires a version for pinned update_policy: $installed_manifest" >&2
163
+ echo "ERROR installed adl package manifest requires a version for pinned update_policy: $installed_manifest" >&2
178
164
  exit 1
179
165
  }
180
- package_spec="$(npm_package_spec pinned "$pinned_version")" || exit 1
166
+ package_spec="$(adl_package_spec pinned "$pinned_version")" || exit 1
181
167
  ;;
182
- *) package_spec="$(npm_package_spec "$update_policy")" || exit 1 ;;
168
+ *) package_spec="$(adl_package_spec "$update_policy")" || exit 1 ;;
183
169
  esac
184
170
  else
185
- package_spec="$(npm_package_spec latest-stable)"
186
- echo "global-tools: bootstrapping adl package from npm latest tag"
171
+ package_spec="$(adl_package_spec latest-stable)"
172
+ echo "global-tools: bootstrapping adl package from the registry latest tag"
187
173
  fi
188
174
 
189
175
  if [[ -n "${SYNC_AND_RECONCILE_TEST_ROOT:-}" ]]; then
@@ -198,18 +184,43 @@ else
198
184
  fi
199
185
  prepare_adl_npm_migration "$applied_manifest" "$device" "$host_platform" "$legacy_adl" "$legacy_hash"
200
186
 
201
- sudo -u "$owner" -H env "${npm_env[@]}" npm install --global --prefix "$npm_prefix" --no-audit --no-fund "$package_spec"
202
- [[ -d "$platform_dir" ]] || { echo "npm install did not create the platform package: $platform_dir" >&2; exit 1; }
187
+ # NEVER DOWNGRADE (Tarun, 2026-10-01): under latest-stable the installed package is
188
+ # compared with the registry's `latest` first. Newer installed (a local pre-release
189
+ # build) and equal are kept; only an older one is updated. A lookup that fails stops
190
+ # the run loudly. A first install has nothing to compare, and a pinned policy installs
191
+ # exactly its pin.
192
+ skip_install=0
193
+ if [[ -n "$installed_version" && "$update_policy" == latest-stable ]]; then
194
+ registry_latest="$(adl_registry_latest "$owner" "$os" "$owner_home")" || {
195
+ echo "ERROR cannot read the registry latest of $adl_wrapper_package; not updating and not reconciling (run again when the registry is reachable)" >&2
196
+ exit 1
197
+ }
198
+ version_order="$(adl_semver_compare "$installed_version" "$registry_latest")" || exit 1
199
+ case "$version_order" in
200
+ 1)
201
+ echo "global-tools: installed $installed_version is newer than registry latest $registry_latest; keeping it"
202
+ skip_install=1
203
+ ;;
204
+ 0)
205
+ echo "global-tools: installed $installed_version is already the registry latest; no update needed"
206
+ skip_install=1
207
+ ;;
208
+ *) echo "global-tools: updating adl package $installed_version -> $registry_latest" ;;
209
+ esac
210
+ fi
211
+ if [[ "$skip_install" -eq 0 ]]; then
212
+ adl_bun_add_global "$owner" "$os" "$owner_home" "$package_spec"
213
+ fi
214
+ [[ -d "$platform_dir" ]] || { echo "ERROR bun add did not create the platform package: $platform_dir" >&2; exit 1; }
203
215
  installed_manifest="$platform_dir/packages/fleet/manifest.json"
204
- [[ -f "$installed_manifest" ]] || { echo "installed adl package manifest missing: $installed_manifest" >&2; exit 1; }
205
- [[ -x "$platform_dir/bin/reconcile" ]] || { echo "installed adl package reconcile is missing: $platform_dir/bin/reconcile" >&2; exit 1; }
206
- [[ -x "$platform_dir/bin/sync-and-reconcile" ]] || { echo "installed adl package scheduler is missing: $platform_dir/bin/sync-and-reconcile" >&2; exit 1; }
207
- [[ -x "$platform_dir/bin/validate-manifest" ]] || { echo "installed adl package manifest validator is missing: $platform_dir/bin/validate-manifest" >&2; exit 1; }
208
- "$platform_dir/bin/validate-manifest" "$installed_manifest"
209
- install -m 0755 "$platform_dir/bin/sync-and-reconcile" "$scheduler_path.new"
210
- mv "$scheduler_path.new" "$scheduler_path"
216
+ [[ -f "$installed_manifest" ]] || { echo "ERROR installed adl package manifest missing: $installed_manifest" >&2; exit 1; }
217
+ # bun leaves every shipped file but the `bin` targets 0644, so the package's
218
+ # scripts are checked with -f and run through bash, never executed directly.
219
+ [[ -f "$platform_dir/bin/reconcile" ]] || { echo "ERROR installed adl package reconcile is missing: $platform_dir/bin/reconcile" >&2; exit 1; }
220
+ [[ -f "$platform_dir/bin/validate-manifest" ]] || { echo "ERROR installed adl package manifest validator is missing: $platform_dir/bin/validate-manifest" >&2; exit 1; }
221
+ bash "$platform_dir/bin/validate-manifest" "$installed_manifest"
211
222
  reconcile_dir="$platform_dir/bin"
212
223
  fi
213
224
 
214
- PATH="$reconcile_dir:$PATH" "$reconcile_dir/reconcile" \
225
+ PATH="$reconcile_dir:$PATH" bash "$reconcile_dir/reconcile" \
215
226
  --device "$device" --source "$sync_source" --mode "$mode"