@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.12 → 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 (405) hide show
  1. package/bin/adl +2 -2
  2. package/bin/git +16 -17
  3. package/bin/git-ado +25 -24
  4. package/bin/git-defaults +173 -0
  5. package/bin/health-check +8 -1
  6. package/bin/kimi-hooks +1 -1
  7. package/bin/lib/adl-package.sh +257 -0
  8. package/bin/lib/fleet-host.sh +8 -5
  9. package/bin/reconcile +482 -232
  10. package/bin/reconcile-host +30 -20
  11. package/bin/setup +20 -17
  12. package/bin/shell-path-policy +15 -5
  13. package/bin/sync-and-reconcile +62 -64
  14. package/bin/validate-manifest +33 -9
  15. package/package.json +2 -10
  16. package/packages/agent-hooks/README.md +14 -9
  17. package/packages/agent-hooks/assets/hooks.json +0 -20
  18. package/packages/agent-hooks/src/cli/args.ts +1 -1
  19. package/packages/agent-hooks/src/cli/doctor.ts +6 -58
  20. package/packages/agent-hooks/src/deploy/deploy.ts +12 -41
  21. package/packages/agent-hooks/src/deploy/doctor.ts +8 -11
  22. package/packages/agent-hooks/src/deploy/index.ts +14 -14
  23. package/packages/agent-hooks/src/deploy/json-merge.ts +7 -8
  24. package/packages/agent-hooks/src/deploy/legacy-lock.ts +2 -2
  25. package/packages/agent-hooks/src/deploy/list.ts +1 -1
  26. package/packages/agent-hooks/src/deploy/lock.ts +31 -12
  27. package/packages/agent-hooks/src/deploy/profile.ts +3 -4
  28. package/packages/agent-hooks/src/deploy/source.ts +1 -1
  29. package/packages/agent-hooks/src/gating/config.ts +10 -24
  30. package/packages/agent-hooks/src/gating/root.ts +3 -3
  31. package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
  32. package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
  33. package/packages/agent-hooks/src/hooks/contract.ts +17 -17
  34. package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
  35. package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
  36. package/packages/agent-hooks/src/hooks/log.ts +8 -10
  37. package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
  38. package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
  39. package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
  40. package/packages/agent-hooks/src/hosts/registry.ts +1 -1
  41. package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
  42. package/packages/agent-hooks/src/log/writer.ts +16 -2
  43. package/packages/agent-hooks/src/main.ts +7 -41
  44. package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
  45. package/packages/agent-hooks/src/rules/engine.ts +13 -17
  46. package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
  47. package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
  48. package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
  49. package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
  50. package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
  51. package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
  52. package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
  53. package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
  54. package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
  55. package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
  56. package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
  57. package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
  58. package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
  59. package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
  60. package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +159 -0
  61. package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
  62. package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
  63. package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
  64. package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
  65. package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
  66. package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
  67. package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
  68. package/packages/agent-hooks/src/rules/impl/tool-grep.ts +34 -12
  69. package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
  70. package/packages/agent-hooks/src/rules/ports.ts +5 -7
  71. package/packages/agent-hooks/src/rules/registry.ts +4 -6
  72. package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
  73. package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
  74. package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
  75. package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
  76. package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
  77. package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
  78. package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
  79. package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
  80. package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
  81. package/packages/agent-hooks/src/rules/spec.ts +2 -2
  82. package/packages/agent-settings/README.md +287 -0
  83. package/packages/agent-settings/assets/GLOBAL-AGENTS.md +14 -16
  84. package/packages/agent-settings/assets/agents/architect.toml +2 -0
  85. package/packages/agent-settings/assets/agents/code-reviewer.toml +2 -0
  86. package/packages/agent-settings/assets/agents/executor.toml +2 -0
  87. package/packages/agent-settings/assets/agents/explore.toml +2 -0
  88. package/packages/agent-settings/assets/agents/planner.toml +2 -0
  89. package/packages/agent-settings/assets/mcp.json +0 -4
  90. package/packages/agent-settings/deploy-profile.json +139 -0
  91. package/packages/agent-settings/deploy-profile.schema.json +147 -0
  92. package/packages/agent-settings/managed/README.md +29 -30
  93. package/packages/agent-settings/managed/codex-requirements.toml +9 -9
  94. package/packages/agent-settings/package.json +20 -0
  95. package/packages/agent-settings/src/deploy/agent-render.ts +2 -2
  96. package/packages/agent-settings/src/deploy/agent-toml.ts +1 -1
  97. package/packages/agent-settings/src/deploy/agents-deploy.ts +17 -3
  98. package/packages/agent-settings/src/deploy/doctor.ts +3 -83
  99. package/packages/agent-settings/src/deploy/index.ts +6 -33
  100. package/packages/agent-settings/src/deploy/legacy-lock.ts +6 -6
  101. package/packages/agent-settings/src/deploy/list.ts +5 -19
  102. package/packages/agent-settings/src/deploy/lock.ts +8 -18
  103. package/packages/agent-settings/src/deploy/mcp-deploy.ts +10 -5
  104. package/packages/agent-settings/src/deploy/mcp-merge.ts +22 -3
  105. package/packages/agent-settings/src/deploy/mcp-source.ts +1 -1
  106. package/packages/agent-settings/src/deploy/profile.ts +11 -35
  107. package/packages/agent-settings/src/deploy/retire-lean-ctx.ts +184 -0
  108. package/packages/agent-settings/src/deploy/settings.ts +17 -22
  109. package/packages/agent-settings/src/global-surface-sweep.ts +0 -2
  110. package/packages/agent-settings/src/kimi-hooks.ts +339 -192
  111. package/packages/agent-settings/src/opencode-hooks.ts +1 -1
  112. package/packages/agent-settings/tsconfig.json +23 -0
  113. package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +120 -0
  114. package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +276 -0
  115. package/packages/agent-skills/assets/debug-issue/SKILL.md +8 -7
  116. package/packages/agent-skills/assets/explore-codebase/SKILL.md +13 -13
  117. package/packages/agent-skills/assets/refactor-safely/SKILL.md +12 -11
  118. package/packages/agent-skills/assets/review-changes/SKILL.md +7 -7
  119. package/packages/agent-skills/assets/testing/references/e2e.md +37 -0
  120. package/packages/agent-skills/assets/testing/references/integration.md +37 -0
  121. package/packages/agent-skills/assets/testing/references/unit.md +32 -0
  122. package/packages/agent-skills/dist/deploy.d.ts +2 -0
  123. package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
  124. package/packages/agent-skills/dist/deploy.js +27 -1
  125. package/packages/agent-skills/dist/deploy.js.map +1 -1
  126. package/packages/agent-skills/dist/doctor.d.ts +0 -2
  127. package/packages/agent-skills/dist/doctor.d.ts.map +1 -1
  128. package/packages/agent-skills/dist/doctor.js +1 -1
  129. package/packages/agent-skills/dist/doctor.js.map +1 -1
  130. package/packages/agent-skills/dist/fs-utils.d.ts +0 -1
  131. package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -1
  132. package/packages/agent-skills/dist/fs-utils.js +1 -1
  133. package/packages/agent-skills/dist/fs-utils.js.map +1 -1
  134. package/packages/agent-skills/src/deploy.ts +29 -1
  135. package/packages/agent-skills/src/doctor.ts +1 -1
  136. package/packages/agent-skills/src/fs-utils.ts +1 -1
  137. package/packages/azdo/README.md +10 -9
  138. package/packages/azdo/package.json +1 -3
  139. package/packages/azdo/src/azdo-pl.ts +2 -54
  140. package/packages/azdo/src/azdo-pr-review.ts +4 -4
  141. package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
  142. package/packages/azdo/src/azdo-wit.ts +41 -2
  143. package/packages/azdo/src/lib/agent-identity.ts +12 -14
  144. package/packages/azdo/src/lib/agent-token.ts +2 -2
  145. package/packages/azdo/src/lib/client.ts +0 -5
  146. package/packages/azdo/src/lib/graph-identity.ts +4 -4
  147. package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
  148. package/packages/azdo/src/workflow-rules.ts +128 -0
  149. package/packages/fleet/manifest.json +35 -11
  150. package/packages/fleet/manifest.schema.json +62 -10
  151. package/packages/fleet/src/default-agent-file.ts +3 -3
  152. package/packages/fleet/src/install-adl-package.ts +73 -15
  153. package/packages/fleet/src/install-embedding-model.ts +13 -13
  154. package/packages/fleet/src/managed-settings.ts +7 -7
  155. package/packages/fleet/src/repo-maintain.ts +91 -55
  156. package/packages/fleet/src/scratch-reap.ts +5 -5
  157. package/packages/fleet/src/vscode-settings.ts +5 -5
  158. package/packages/repo-controls/README.md +141 -43
  159. package/packages/repo-controls/assets/promote.ts +4 -4
  160. package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
  161. package/packages/repo-controls/assets/version-bump.sh +31 -84
  162. package/packages/repo-controls/bunfig.toml +6 -7
  163. package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
  164. package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
  165. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
  166. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
  167. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
  168. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
  169. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
  170. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
  171. 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
  172. 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
  173. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
  174. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
  175. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
  176. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
  177. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
  178. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
  179. 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
  180. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
  181. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
  182. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
  183. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
  184. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
  185. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
  186. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
  187. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
  188. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
  189. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
  190. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
  191. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
  192. 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
  193. 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
  194. 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
  195. 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
  196. 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
  197. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
  198. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
  199. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
  200. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
  201. 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
  202. 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
  203. 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
  204. 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
  205. 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
  206. 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
  207. 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
  208. 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
  209. 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
  210. 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
  211. 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
  212. 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
  213. 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
  214. 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
  215. 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
  216. 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
  217. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
  218. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
  219. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
  220. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
  221. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
  222. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
  223. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
  224. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
  225. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
  226. 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
  227. 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
  228. 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
  229. 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
  230. 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
  231. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
  232. 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
  233. 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
  234. 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
  235. 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
  236. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
  237. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
  238. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
  239. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
  240. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
  241. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
  242. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
  243. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
  244. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
  245. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
  246. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
  247. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
  248. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
  249. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
  250. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
  251. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
  252. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
  253. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
  254. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
  255. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
  256. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
  257. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
  258. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
  259. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
  260. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
  261. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
  262. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
  263. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
  264. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
  265. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
  266. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
  267. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
  268. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
  269. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
  270. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
  271. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
  272. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
  273. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
  274. 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
  275. 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
  276. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
  277. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
  278. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
  279. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
  280. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
  281. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
  282. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
  283. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
  284. 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
  285. 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
  286. 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
  287. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
  288. 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
  289. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
  290. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
  291. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
  292. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
  293. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
  294. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
  295. 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
  296. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
  297. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
  298. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
  299. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
  300. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
  301. 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
  302. 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
  303. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
  304. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
  305. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
  306. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
  307. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
  308. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
  309. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
  310. 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
  311. 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
  312. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
  313. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
  314. 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
  315. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
  316. 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
  317. 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
  318. 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
  319. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
  320. 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
  321. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
  322. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
  323. 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
  324. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
  325. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
  326. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
  327. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
  328. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
  329. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
  330. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +256 -0
  331. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
  332. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
  333. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +1 -1
  334. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
  335. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
  336. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
  337. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
  338. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
  339. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
  340. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
  341. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
  342. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
  343. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
  344. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
  345. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
  346. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
  347. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
  348. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
  349. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
  350. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
  351. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
  352. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
  353. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
  354. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
  355. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
  356. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
  357. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
  358. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
  359. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
  360. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
  361. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
  362. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
  363. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
  364. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
  365. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
  366. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
  367. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
  368. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
  369. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
  370. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
  371. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
  372. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
  373. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
  374. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
  375. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
  376. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
  377. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
  378. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
  379. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
  380. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
  381. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
  382. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
  383. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
  384. package/packages/repo-controls/package.json +2 -9
  385. package/packages/repo-controls/scripts/hooks/post-merge +13 -0
  386. package/packages/repo-controls/scripts/hooks/pre-push +3 -3
  387. package/packages/repo-controls/src/azdo-push.ts +64 -36
  388. package/packages/repo-controls/src/azure-devops-governance.ts +7 -9
  389. package/packages/repo-controls/src/azure-devops-remote.ts +1 -1
  390. package/packages/repo-controls/src/cli.ts +29 -8
  391. package/packages/repo-controls/src/compliance-config.ts +410 -2
  392. package/packages/repo-controls/src/config.ts +133 -60
  393. package/packages/repo-controls/src/constants.ts +13 -27
  394. package/packages/repo-controls/src/coverage-ratchet.ts +4 -4
  395. package/packages/repo-controls/src/doctor.ts +46 -19
  396. package/packages/repo-controls/src/gitignore-block.ts +5 -29
  397. package/packages/repo-controls/src/hook-log.ts +1 -2
  398. package/packages/repo-controls/src/hook.ts +201 -45
  399. package/packages/repo-controls/src/install.ts +14 -8
  400. package/packages/repo-controls/src/integrity.ts +3 -3
  401. package/packages/repo-controls/src/lfs.ts +111 -0
  402. package/packages/repo-controls/src/promote.ts +8 -8
  403. package/packages/repo-controls/src/runtime.ts +9 -1
  404. package/packages/repo-controls/src/workflows-drift.ts +4 -5
  405. package/packages/repo-controls/src/worktree-guard.ts +3 -3
@@ -1,33 +1,6 @@
1
- export { deployMcp, type DeployMcpOptions, type DeployMcpResult, type McpFileConflict } from "./mcp-deploy.js";
2
- export { deployAgents, type DeployAgentsOptions, type DeployAgentsResult, type AgentConflict } from "./agents-deploy.js";
3
- export { deployLeanCtx, type DeployLeanCtxOptions, type DeployLeanCtxResult, type LeanCtxConflict } from "./lean-ctx-deploy.js";
4
- export {
5
- doctorMcp,
6
- doctorAgents,
7
- doctorLeanCtx,
8
- mergeDoctorResults,
9
- type DoctorIssue,
10
- type DoctorResult,
11
- type DoctorMcpOptions,
12
- type DoctorAgentsOptions,
13
- type DoctorLeanCtxOptions,
14
- } from "./doctor.js";
15
- export { listSettings, type ListOptions, type ListResult, type ListEntry, type ItemOwner } from "./list.js";
16
- export { deploySettings, doctorSettings, type SettingsTargetOptions, type DeploySettingsResult } from "./settings.js";
17
- export { lockPathFor, readLock, writeLock, mcpServerOwned, agentOwned, leanCtxOwned, LOCK_RELATIVE_PATH, type SettingsLock, type McpLockEntry } from "./lock.js";
18
- export {
19
- DEFAULT_PROFILE_PATH,
20
- DEFAULT_PROFILE_SCHEMA_PATH,
21
- loadProfile,
22
- validateProfileDocument,
23
- type DeployProfile,
24
- type McpSurface,
25
- type AgentSurface,
26
- type LeanCtxFile,
27
- type LeanCtxProfileSection,
28
- type ProfileIssue,
29
- } from "./profile.js";
30
- export { loadMcpSource, DEFAULT_MCP_SOURCE_PATH, type McpServerSpec } from "./mcp-source.js";
31
- export { loadAgentSources, parseAgentToml, type AgentDef } from "./agent-toml.js";
32
- export { renderAgent, extensionFor } from "./agent-render.js";
33
- export { stringifyPretty } from "./json-pretty.js";
1
+ export { type DoctorResult } from "./doctor.js";
2
+ export { listSettings } from "./list.js";
3
+ export { deploySettings, doctorSettings, type DeploySettingsResult } from "./settings.js";
4
+ export { loadProfile } from "./profile.js";
5
+ export { loadMcpSource, type McpServerSpec } from "./mcp-source.js";
6
+ export { loadAgentSources, type AgentDef } from "./agent-toml.js";
@@ -65,7 +65,7 @@ export const sha256Hex = (input: string | Buffer): string => createHash("sha256"
65
65
  * legacy lock's `merged` section. An entry's identity must not change just
66
66
  * because a host or a user rewrote the file and reordered its keys.
67
67
  */
68
- export function stableStringify(value: unknown): string {
68
+ function stableStringify(value: unknown): string {
69
69
  if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
70
70
  if (value && typeof value === "object") {
71
71
  return `{${Object.keys(value as Record<string, unknown>)
@@ -81,18 +81,18 @@ export const legacyValueHash = (value: unknown): string => sha256Hex(stableStrin
81
81
 
82
82
  export type LegacyJsonPath = readonly (string | number)[];
83
83
 
84
- export interface LegacyJsonMergeEntry {
84
+ interface LegacyJsonMergeEntry {
85
85
  readonly type: string;
86
86
  readonly path: LegacyJsonPath;
87
87
  readonly sha256: string;
88
88
  }
89
89
 
90
- export interface LegacyMergedRecord {
90
+ interface LegacyMergedRecord {
91
91
  readonly entries?: readonly LegacyJsonMergeEntry[];
92
92
  readonly [key: string]: unknown;
93
93
  }
94
94
 
95
- export interface LegacyGitignoreRecord {
95
+ interface LegacyGitignoreRecord {
96
96
  readonly created?: boolean;
97
97
  readonly lines?: readonly string[];
98
98
  readonly appended?: string;
@@ -126,7 +126,7 @@ export function readLegacyLock(path: string): LegacyLockDoc | undefined {
126
126
  }
127
127
 
128
128
  /** The legacy lock's recorded whole-file sha256 for `file` under `files`, or `undefined` when unrecorded. */
129
- export function legacyFileHash(doc: LegacyLockDoc | undefined, file: string): string | undefined {
129
+ function legacyFileHash(doc: LegacyLockDoc | undefined, file: string): string | undefined {
130
130
  return doc?.files?.[file]?.sha256;
131
131
  }
132
132
 
@@ -207,7 +207,7 @@ export function legacyTakeoverForGitignore(content: string, doc: LegacyLockDoc |
207
207
  return false;
208
208
  }
209
209
 
210
- export interface LegacyMergedRemoval {
210
+ interface LegacyMergedRemoval {
211
211
  readonly file: string;
212
212
  readonly paths: readonly LegacyJsonPath[];
213
213
  }
@@ -6,18 +6,18 @@
6
6
  * (mirrors packages/agent-skills/src/list.ts's shape).
7
7
  */
8
8
  import { existsSync, readdirSync } from "node:fs";
9
- import { basename, join } from "node:path";
9
+ import { join } from "node:path";
10
10
  import { extensionFor } from "./agent-render.js";
11
11
  import { loadAgentSources, type AgentDef } from "./agent-toml.js";
12
- import { agentOwned, leanCtxOwned, mcpServerOwned, readLock } from "./lock.js";
12
+ import { agentOwned, mcpServerOwned, readLock } from "./lock.js";
13
13
  import { readDeployedMcpServerNames } from "./mcp-inspect.js";
14
14
  import { loadMcpSource, type McpServerSpec } from "./mcp-source.js";
15
15
  import { type DeployProfile, loadProfile } from "./profile.js";
16
16
 
17
- export type ItemOwner = "adl" | "user" | "conflict" | "-";
17
+ type ItemOwner = "adl" | "user" | "conflict" | "-";
18
18
 
19
- export interface ListEntry {
20
- readonly kind: "mcp" | "agent" | "lean-ctx";
19
+ interface ListEntry {
20
+ readonly kind: "mcp" | "agent";
21
21
  readonly name: string;
22
22
  readonly available: boolean;
23
23
  readonly deployedIn: readonly string[];
@@ -117,19 +117,5 @@ export function listSettings(options: ListOptions): ListResult {
117
117
  entries.push({ ...base, line: formatLine(`agent:${name}`, base) });
118
118
  }
119
119
 
120
- // --- lean-ctx ---
121
- if (profile.leanCtx !== undefined) {
122
- const leanCtxAssetsDir = join(options.assetsRoot, profile.leanCtx.source);
123
- for (const file of profile.leanCtx.files) {
124
- const targetAbs = join(options.targetRepo, file.target);
125
- const deployed = existsSync(targetAbs);
126
- const owned = leanCtxOwned(lock, file.target);
127
- const available = existsSync(join(leanCtxAssetsDir, file.asset));
128
- const owner: ItemOwner = deployed ? (owned ? "adl" : "conflict") : "-";
129
- const base = { kind: "lean-ctx" as const, name: file.target, available, deployedIn: deployed ? [file.target] : [], owner };
130
- entries.push({ ...base, line: formatLine(`lean-ctx:${basename(file.target)}`, base) });
131
- }
132
- }
133
-
134
120
  return { entries, lines: entries.map((e) => e.line) };
135
121
  }
@@ -13,32 +13,27 @@
13
13
  * breakdown is needed.
14
14
  * - `agents`: target folder -> the agent NAMES this deploy wrote as files
15
15
  * in that folder (one file per agent, so this is the removal unit).
16
- * - `leanCtx`: target path -> `true` for each repo-local lean-ctx file
17
- * (config.toml, layout.toml, .agents/.gitignore) this deploy wrote —
18
- * one whole file is the removal unit, same as agents but keyed directly
19
- * by target path since there is no per-file "container".
20
16
  *
21
17
  * A name/file missing from a later run's lock (because it fell out of
22
18
  * assets/) is removed from the target on that run; anything not recorded
23
19
  * here was never written by us and is never touched.
24
20
  *
25
- * `leanCtx` is optional on read: a lock written before this section existed
26
- * has no `leanCtx` key, and is treated as owning nothing yet (`{}`), not as
27
- * a malformed lock.
21
+ * The optional `leanCtx` field remains readable only so deploy can retire
22
+ * paths recorded by older releases. New locks never write it.
28
23
  */
29
24
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
30
25
  import { dirname, join } from "node:path";
31
26
 
32
- export const LOCK_RELATIVE_PATH = ".agents/agent-settings.lock.json";
27
+ const LOCK_RELATIVE_PATH = ".agents/agent-settings.lock.json";
33
28
  const LOCK_SCHEMA = 1;
34
29
 
35
- export interface McpJsonLockEntry {
30
+ interface McpJsonLockEntry {
36
31
  readonly kind: "json";
37
32
  /** MCP server names this deploy owns in this file's server map. */
38
33
  readonly servers: readonly string[];
39
34
  }
40
35
 
41
- export interface McpBlockLockEntry {
36
+ interface McpBlockLockEntry {
42
37
  readonly kind: "block";
43
38
  readonly owned: true;
44
39
  }
@@ -49,10 +44,10 @@ export interface SettingsLock {
49
44
  readonly schema: number;
50
45
  readonly mcp: Readonly<Record<string, McpLockEntry>>;
51
46
  readonly agents: Readonly<Record<string, readonly string[]>>;
52
- readonly leanCtx: Readonly<Record<string, boolean>>;
47
+ readonly leanCtx?: Readonly<Record<string, boolean>>;
53
48
  }
54
49
 
55
- const EMPTY_LOCK: SettingsLock = { schema: LOCK_SCHEMA, mcp: {}, agents: {}, leanCtx: {} };
50
+ const EMPTY_LOCK: SettingsLock = { schema: LOCK_SCHEMA, mcp: {}, agents: {} };
56
51
 
57
52
  export function lockPathFor(targetRepo: string): string {
58
53
  return join(targetRepo, LOCK_RELATIVE_PATH);
@@ -92,7 +87,7 @@ export function readLock(targetRepo: string): SettingsLock {
92
87
  /** 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). */
93
88
  export function writeLock(targetRepo: string, lock: SettingsLock): void {
94
89
  const path = lockPathFor(targetRepo);
95
- const next = `${JSON.stringify({ schema: LOCK_SCHEMA, mcp: lock.mcp, agents: lock.agents, leanCtx: lock.leanCtx }, null, 2)}\n`;
90
+ const next = `${JSON.stringify({ schema: LOCK_SCHEMA, mcp: lock.mcp, agents: lock.agents }, null, 2)}\n`;
96
91
  if (existsSync(path) && readFileSync(path, "utf8") === next) return;
97
92
  mkdirSync(dirname(path), { recursive: true });
98
93
  writeFileSync(path, next);
@@ -108,8 +103,3 @@ export function mcpServerOwned(lock: SettingsLock, file: string, serverName: str
108
103
  export function agentOwned(lock: SettingsLock, folder: string, agentName: string): boolean {
109
104
  return (lock.agents[folder] ?? []).includes(agentName);
110
105
  }
111
-
112
- /** True iff the lock records `targetPath` as an adl-owned lean-ctx file. */
113
- export function leanCtxOwned(lock: SettingsLock, targetPath: string): boolean {
114
- return lock.leanCtx[targetPath] === true;
115
- }
@@ -24,7 +24,7 @@ import {
24
24
  readLegacyLock,
25
25
  stripLegacyOwnership,
26
26
  } from "./legacy-lock.js";
27
- import { type SettingsLock, type McpLockEntry, readLock, writeLock } from "./lock.js";
27
+ import { type McpLockEntry, readLock, writeLock } from "./lock.js";
28
28
  import { hasForeignTopLevelTable, mergeCodexBlock, mergeServerMap } from "./mcp-merge.js";
29
29
  import { renderCodexManagedBlock, renderMcpJsonEntry } from "./mcp-render.js";
30
30
  import { loadMcpSource, type McpServerSpec } from "./mcp-source.js";
@@ -40,7 +40,7 @@ export interface DeployMcpOptions {
40
40
  readonly dryRun?: boolean;
41
41
  }
42
42
 
43
- export interface McpFileConflict {
43
+ interface McpFileConflict {
44
44
  readonly file: string;
45
45
  readonly server: string;
46
46
  readonly reason: string;
@@ -50,6 +50,8 @@ export interface DeployMcpResult {
50
50
  readonly written: readonly string[];
51
51
  readonly unchanged: readonly string[];
52
52
  readonly conflicts: readonly McpFileConflict[];
53
+ /** Same-name entries not in the lock whose value was identical to what deploy renders: taken over, locked, never a conflict. */
54
+ readonly adopted: readonly { readonly file: string; readonly server: string }[];
53
55
  readonly lockPath: string;
54
56
  }
55
57
 
@@ -95,6 +97,7 @@ export function deployMcp(options: DeployMcpOptions): DeployMcpResult {
95
97
  const written: string[] = [];
96
98
  const unchanged: string[] = [];
97
99
  const conflicts: McpFileConflict[] = [];
100
+ const adopted: { file: string; server: string }[] = [];
98
101
  const legacyMergedRemovals: { file: string; paths: LegacyJsonPath[] }[] = [];
99
102
  const legacyTomlRemovals: string[] = [];
100
103
  let anyLegacyTakeover = false;
@@ -147,15 +150,16 @@ export function deployMcp(options: DeployMcpOptions): DeployMcpResult {
147
150
  const effectivePreviousOwned = legacyTakeover.matched ? [...new Set([...previousOwned, ...legacyTakeover.ownedServers])] : previousOwned;
148
151
  const desired = new Map<string, unknown>(servers.map((spec) => [spec.name, renderMcpJsonEntry(surface.entry, spec)]));
149
152
 
150
- const { fileContent, ownedServers, conflicts: serverConflicts, changed } = mergeServerMap(existingRaw, topKey, desired, effectivePreviousOwned);
153
+ const { fileContent, ownedServers, conflicts: serverConflicts, adopted: serverAdopted, changed } = mergeServerMap(existingRaw, topKey, desired, effectivePreviousOwned);
151
154
  for (const c of serverConflicts) conflicts.push({ file: surface.file, server: c.server, reason: c.reason });
155
+ for (const server of serverAdopted) adopted.push({ file: surface.file, server });
152
156
 
153
157
  writeIfChanged(targetAbs, `${serializeJsonStyle(surface.jsonStyle as "width-aware" | "expanded", fileContent)}\n`, changed, dryRun);
154
158
  (changed ? written : unchanged).push(surface.file);
155
159
  newMcpEntries[surface.file] = { kind: "json", servers: ownedServers };
156
160
  }
157
161
 
158
- if (!dryRun) writeLock(targetRepo, { schema: 1, mcp: newMcpEntries, agents: lock.agents, leanCtx: lock.leanCtx });
162
+ if (!dryRun) writeLock(targetRepo, { schema: 1, mcp: newMcpEntries, agents: lock.agents });
159
163
 
160
164
  // Once anything was actually taken over, this package's own footprint in
161
165
  // the legacy lock (the four MCP `merged` sections and the codex `toml`
@@ -171,8 +175,9 @@ export function deployMcp(options: DeployMcpOptions): DeployMcpResult {
171
175
  written: written.sort(),
172
176
  unchanged: unchanged.sort(),
173
177
  conflicts: conflicts.sort((a, b) => `${a.file}/${a.server}`.localeCompare(`${b.file}/${b.server}`)),
178
+ adopted: adopted.sort((a, b) => `${a.file}/${a.server}`.localeCompare(`${b.file}/${b.server}`)),
174
179
  lockPath: join(targetRepo, ".agents/agent-settings.lock.json"),
175
180
  };
176
181
  }
177
182
 
178
- export type { SettingsLock };
183
+ ;
@@ -22,7 +22,9 @@
22
22
  * `.cursor/mcp.json` / `.kimi-code/mcp.json` / the `mcp` key of
23
23
  * `opencode.json` / the codex block (up to its marker line) byte-for-byte.
24
24
  */
25
- export interface McpServerConflict {
25
+ import { isDeepStrictEqual } from "node:util";
26
+
27
+ interface McpServerConflict {
26
28
  readonly server: string;
27
29
  readonly reason: string;
28
30
  }
@@ -32,6 +34,8 @@ export interface JsonServerMergeResult {
32
34
  /** New lock contents: the MCP server names this deploy now owns in this file's server map. */
33
35
  readonly ownedServers: readonly string[];
34
36
  readonly conflicts: readonly McpServerConflict[];
37
+ /** Same-name servers not recorded as ours whose value is deep-equal to what deploy renders: adopted into `ownedServers`, never a conflict. */
38
+ readonly adopted: readonly string[];
35
39
  readonly changed: boolean;
36
40
  }
37
41
 
@@ -40,7 +44,11 @@ export interface JsonServerMergeResult {
40
44
  * `desired` must be provided in the exact order a fresh file should list
41
45
  * servers in. A same-name server already present and NOT recorded as ours
42
46
  * in a previous run (`previousOwned`) is a conflict: left untouched,
43
- * reported, never claimed in `ownedServers` (M4/D5-equivalent for MCP).
47
+ * reported, never claimed in `ownedServers` (M4/D5-equivalent for MCP) —
48
+ * unless its value is deep-equal to the desired one, in which case it holds
49
+ * no user content and is ADOPTED (Tarun, 2026-10-01): recorded in
50
+ * `ownedServers` and named in `adopted`, same rule as lean-ctx's
51
+ * `adoptUnmarkedManagedText`. Any difference at all stays a conflict.
44
52
  */
45
53
  export function mergeServerMap(
46
54
  existing: Record<string, unknown> | undefined,
@@ -64,8 +72,19 @@ export function mergeServerMap(
64
72
 
65
73
  const conflicts: McpServerConflict[] = [];
66
74
  const owned: string[] = [];
75
+ const adopted: string[] = [];
67
76
  for (const [name, value] of desired) {
68
77
  if (Object.prototype.hasOwnProperty.call(newServers, name)) {
78
+ if (isDeepStrictEqual(newServers[name], value)) {
79
+ // Identical to what we would write: take it over. Re-added below at
80
+ // the desired position, exactly like an entry we already owned, so
81
+ // the next run's drop-and-re-add sees the same order (no-op).
82
+ delete newServers[name];
83
+ newServers[name] = value;
84
+ owned.push(name);
85
+ adopted.push(name);
86
+ continue;
87
+ }
69
88
  conflicts.push({ server: name, reason: "a user-owned MCP server already exists with this name; deploy left it untouched" });
70
89
  continue; // never overwrite it, never claim it in the lock
71
90
  }
@@ -76,7 +95,7 @@ export function mergeServerMap(
76
95
  base[topKey] = newServers;
77
96
  const changed = existing === undefined || JSON.stringify(existingServers) !== JSON.stringify(newServers);
78
97
 
79
- return { fileContent: base, ownedServers: owned, conflicts, changed };
98
+ return { fileContent: base, ownedServers: owned, conflicts, adopted, changed };
80
99
  }
81
100
 
82
101
  export interface CodexBlockMergeResult {
@@ -14,7 +14,7 @@ export interface McpServerSpec {
14
14
  readonly args: readonly string[];
15
15
  }
16
16
 
17
- export const DEFAULT_MCP_SOURCE_PATH = fileURLToPath(new URL("../../assets/mcp.json", import.meta.url));
17
+ const DEFAULT_MCP_SOURCE_PATH = fileURLToPath(new URL("../../assets/mcp.json", import.meta.url));
18
18
 
19
19
  function isServerSpec(value: unknown): value is { command: string; args: readonly string[] } {
20
20
  if (typeof value !== "object" || value === null) return false;
@@ -34,13 +34,13 @@ import Ajv, { type ErrorObject, type ValidateFunction } from "ajv";
34
34
  import { readFileSync } from "node:fs";
35
35
  import { fileURLToPath } from "node:url";
36
36
 
37
- export type McpSurfaceFormat = "json" | "toml-block";
38
- export type AgentSurfaceFormat = "md" | "toml";
39
- export type McpJsonStyle = "width-aware" | "expanded";
37
+ type McpSurfaceFormat = "json" | "toml-block";
38
+ type AgentSurfaceFormat = "md" | "toml";
39
+ type McpJsonStyle = "width-aware" | "expanded";
40
40
  export type McpFromToken = "command" | "args" | "commandArgs";
41
41
  /** The full set a `from` token may name across BOTH front-matter fields and TOML fields; which subset is valid for which is enforced by the schema's two separate enums (agentFrontMatterField vs agentTomlField). */
42
42
  export type AgentFromToken = "name" | "description" | "model" | "claude_model" | "cursor_model" | "tools" | "model_reasoning_effort" | "sandbox_mode";
43
- export type AgentFieldStyle = "plain" | "csv-list";
43
+ type AgentFieldStyle = "plain" | "csv-list";
44
44
 
45
45
  export interface McpEntryField {
46
46
  readonly key: string;
@@ -49,7 +49,7 @@ export interface McpEntryField {
49
49
  }
50
50
 
51
51
  /** A static (non-per-server) field in a `topLevel` TOML table — always a constant, since there is no per-server spec to draw `from`. */
52
- export interface McpTopLevelField {
52
+ interface McpTopLevelField {
53
53
  readonly key: string;
54
54
  readonly const: string | boolean | number;
55
55
  }
@@ -103,40 +103,28 @@ export interface AgentSurface {
103
103
  readonly bodyField?: "developer_instructions";
104
104
  }
105
105
 
106
- export interface McpProfileSection {
106
+ interface McpProfileSection {
107
107
  readonly source: string;
108
108
  readonly marker?: string;
109
109
  readonly surfaces: readonly McpSurface[];
110
110
  }
111
111
 
112
- export interface AgentProfileSection {
112
+ interface AgentProfileSection {
113
113
  readonly source: string;
114
114
  readonly surfaces: readonly AgentSurface[];
115
115
  }
116
116
 
117
- export interface LeanCtxFile {
118
- readonly asset: string;
119
- readonly target: string;
120
- }
121
-
122
- export interface LeanCtxProfileSection {
123
- readonly source: string;
124
- readonly files: readonly LeanCtxFile[];
125
- }
126
-
127
117
  export interface DeployProfile {
128
118
  readonly mcp: McpProfileSection;
129
119
  readonly agents: AgentProfileSection;
130
- /** Optional: absent in older/fixture profiles (e.g. tests/fixtures/two-surface-profile.json), which cover only mcp/agents. deployLeanCtx/doctorLeanCtx throw if called against a profile without this section. */
131
- readonly leanCtx?: LeanCtxProfileSection;
132
120
  /** Repo-relative path to the pre-agent-settings engine's own install lock, if this repo may still carry one (see deploy-profile.schema.json and legacy-lock.ts). */
133
121
  readonly legacyLock?: string;
134
122
  }
135
123
 
136
- export const DEFAULT_PROFILE_PATH = fileURLToPath(new URL("../../deploy-profile.json", import.meta.url));
137
- export const DEFAULT_PROFILE_SCHEMA_PATH = fileURLToPath(new URL("../../deploy-profile.schema.json", import.meta.url));
124
+ const DEFAULT_PROFILE_PATH = fileURLToPath(new URL("../../deploy-profile.json", import.meta.url));
125
+ const DEFAULT_PROFILE_SCHEMA_PATH = fileURLToPath(new URL("../../deploy-profile.schema.json", import.meta.url));
138
126
 
139
- export interface ProfileIssue {
127
+ interface ProfileIssue {
140
128
  readonly path: string;
141
129
  readonly message: string;
142
130
  }
@@ -250,18 +238,6 @@ function crossFieldChecks(doc: DeployProfile): readonly ProfileIssue[] {
250
238
  }
251
239
  });
252
240
 
253
- if (doc.leanCtx !== undefined) {
254
- const leanCtxTargets = new Set<string>();
255
- const leanCtxAssets = new Set<string>();
256
- doc.leanCtx.files.forEach((file, index) => {
257
- const p = `/leanCtx/files/${index}`;
258
- if (leanCtxTargets.has(file.target)) issues.push({ path: `${p}/target`, message: `duplicate leanCtx target: ${file.target}` });
259
- leanCtxTargets.add(file.target);
260
- if (leanCtxAssets.has(file.asset)) issues.push({ path: `${p}/asset`, message: `duplicate leanCtx asset: ${file.asset}` });
261
- leanCtxAssets.add(file.asset);
262
- });
263
- }
264
-
265
241
  return issues;
266
242
  }
267
243
 
@@ -271,7 +247,7 @@ function crossFieldChecks(doc: DeployProfile): readonly ProfileIssue[] {
271
247
  * comment). Pure: never throws for a structurally-wrong `doc` (returns
272
248
  * issues instead); only a missing/malformed `schemaPath` throws.
273
249
  */
274
- export function validateProfileDocument(doc: unknown, schemaPath: string = DEFAULT_PROFILE_SCHEMA_PATH): readonly ProfileIssue[] {
250
+ function validateProfileDocument(doc: unknown, schemaPath: string = DEFAULT_PROFILE_SCHEMA_PATH): readonly ProfileIssue[] {
275
251
  const validate = compileValidator(schemaPath);
276
252
  if (!validate(doc)) {
277
253
  return (validate.errors ?? []).map(formatAjvError);
@@ -0,0 +1,184 @@
1
+ /** Remove repo-local lean-ctx artifacts recorded by older agent-settings locks. */
2
+ import { existsSync, lstatSync, readFileSync, rmSync, rmdirSync, unlinkSync, writeFileSync } from "node:fs";
3
+ import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
4
+ import {
5
+ legacyFileTakeover,
6
+ legacyTakeoverForGitignore,
7
+ readLegacyLock,
8
+ stripLegacyOwnership,
9
+ type LegacyLockDoc,
10
+ } from "./legacy-lock.js";
11
+ import { readLock, writeLock } from "./lock.js";
12
+
13
+ const LOCKED_LEAN_CTX_ROOT = ".agents/lean-ctx";
14
+ const AGENTS_GITIGNORE = ".agents/.gitignore";
15
+ const RETIRED_GITIGNORE_LINE = /^\/(?:lean-ctx\/(?:data|cache|state|bin)\/|lean-ctx\/config\/lean-ctx\/workspace-trust\.toml)$/;
16
+
17
+ export interface RetireLeanCtxOptions {
18
+ readonly targetRepo: string;
19
+ readonly legacyLockPath?: string;
20
+ readonly dryRun?: boolean;
21
+ }
22
+
23
+ export interface RetireLeanCtxResult {
24
+ readonly removed: readonly string[];
25
+ }
26
+
27
+ function isWithin(root: string, path: string): boolean {
28
+ const rel = relative(root, path);
29
+ return rel !== "" && rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
30
+ }
31
+
32
+ function assertOwnedTarget(targetRepo: string, target: string): string {
33
+ if (target !== AGENTS_GITIGNORE && !target.startsWith(`${LOCKED_LEAN_CTX_ROOT}/`)) {
34
+ throw new Error(`agent-settings retirement lock contains an unexpected lean-ctx path: ${target}`);
35
+ }
36
+ const absolute = resolve(targetRepo, target);
37
+ if (!isWithin(resolve(targetRepo), absolute)) {
38
+ throw new Error(`agent-settings retirement path escapes target repo: ${target}`);
39
+ }
40
+ return absolute;
41
+ }
42
+
43
+ function assertRegularFile(path: string): void {
44
+ const stat = lstatSync(path);
45
+ if (!stat.isFile()) throw new Error(`agent-settings retirement target is not a regular file: ${path}`);
46
+ }
47
+
48
+ function removeLegacyGitignore(content: string, record: NonNullable<LegacyLockDoc["gitignore"]>[string]): string | undefined {
49
+ if (record.created === true) return undefined;
50
+ const owned = record.appended ?? (record.lines === undefined ? undefined : `${record.lines.join("\n")}\n`);
51
+ if (owned === undefined || !content.endsWith(owned)) {
52
+ throw new Error("agent-settings retirement could not isolate the legacy lean-ctx .agents/.gitignore addition");
53
+ }
54
+ const remaining = content.slice(0, -owned.length);
55
+ return remaining.length === 0 ? undefined : remaining;
56
+ }
57
+
58
+ function removeManagedGitignoreBlock(content: string): string | undefined {
59
+ const lines = content.match(/[^\n]*\n|[^\n]+$/g) ?? [];
60
+ const open = "# >>> adl managed (do not edit within this block) >>>\n";
61
+ const close = "# <<< adl managed <<<\n";
62
+ const starts = lines.flatMap((line, index) => line === open ? [index] : []);
63
+ const ends = lines.flatMap((line, index) => line === close ? [index] : []);
64
+ if (starts.length !== ends.length || starts.length > 1 || (starts.length === 1 && (ends[0] as number) < (starts[0] as number))) {
65
+ throw new Error("agent-settings retirement found malformed managed markers in .agents/.gitignore");
66
+ }
67
+ if (starts.length === 1) lines.splice(starts[0] as number, (ends[0] as number) - (starts[0] as number) + 1);
68
+ const remaining = lines
69
+ .filter((line) => !RETIRED_GITIGNORE_LINE.test(line.replace(/\r?\n$/, "")))
70
+ .join("");
71
+ return remaining.length === 0 ? undefined : remaining;
72
+ }
73
+
74
+ function pruneEmptyDirectories(targetRepo: string, start: string, dryRun: boolean): void {
75
+ const stop = resolve(targetRepo, LOCKED_LEAN_CTX_ROOT);
76
+ let current = dirname(start);
77
+ while (current === stop || isWithin(stop, current)) {
78
+ if (!dryRun) {
79
+ try {
80
+ rmdirSync(current);
81
+ } catch (error) {
82
+ const code = (error as NodeJS.ErrnoException).code;
83
+ if (code === "ENOENT") {
84
+ current = dirname(current);
85
+ continue;
86
+ }
87
+ if (code === "ENOTEMPTY" || code === "EEXIST") return;
88
+ throw error;
89
+ }
90
+ }
91
+ if (current === stop) return;
92
+ current = dirname(current);
93
+ }
94
+ }
95
+
96
+ /**
97
+ * One-time migration for the leanCtx lock field and the legacy installer
98
+ * records. It removes only lock-owned paths; new locks omit the retired field.
99
+ */
100
+ export function retireLeanCtx(options: RetireLeanCtxOptions): RetireLeanCtxResult {
101
+ const { targetRepo, dryRun = false } = options;
102
+ const lock = readLock(targetRepo);
103
+ const legacy = options.legacyLockPath === undefined ? undefined : readLegacyLock(options.legacyLockPath);
104
+ const targets = new Set(Object.entries(lock.leanCtx ?? {}).filter(([, owned]) => owned === true).map(([target]) => target));
105
+ const legacyFiles: string[] = [];
106
+ const legacyGitignore: string[] = [];
107
+ const legacyReplacements = new Map<string, string | undefined>();
108
+
109
+ for (const target of Object.keys(legacy?.files ?? {})) {
110
+ if (!target.startsWith(`${LOCKED_LEAN_CTX_ROOT}/`)) continue;
111
+ const absolute = assertOwnedTarget(targetRepo, target);
112
+ if (!existsSync(absolute)) continue;
113
+ assertRegularFile(absolute);
114
+ if (legacyFileTakeover(readFileSync(absolute), legacy, target)) {
115
+ targets.add(target);
116
+ legacyFiles.push(target);
117
+ }
118
+ }
119
+
120
+ const legacyGitignoreRecord = legacy?.gitignore?.[AGENTS_GITIGNORE];
121
+ const gitignoreAbs = targets.has(AGENTS_GITIGNORE) || legacyGitignoreRecord !== undefined
122
+ ? assertOwnedTarget(targetRepo, AGENTS_GITIGNORE)
123
+ : undefined;
124
+ if (legacyGitignoreRecord !== undefined && gitignoreAbs !== undefined && existsSync(gitignoreAbs)) {
125
+ assertRegularFile(gitignoreAbs);
126
+ const current = readFileSync(gitignoreAbs, "utf8");
127
+ if (legacyTakeoverForGitignore(current, legacy, AGENTS_GITIGNORE)) {
128
+ legacyReplacements.set(AGENTS_GITIGNORE, removeLegacyGitignore(current, legacyGitignoreRecord));
129
+ legacyGitignore.push(AGENTS_GITIGNORE);
130
+ targets.add(AGENTS_GITIGNORE);
131
+ }
132
+ }
133
+
134
+ for (const target of targets) {
135
+ const absolute = assertOwnedTarget(targetRepo, target);
136
+ if (!existsSync(absolute) || target === AGENTS_GITIGNORE) continue;
137
+ assertRegularFile(absolute);
138
+ }
139
+
140
+ const removed: string[] = [];
141
+ const ownsRepoTree = [...targets].some((target) => target.startsWith(`${LOCKED_LEAN_CTX_ROOT}/`));
142
+ const repoTreeAbs = resolve(targetRepo, LOCKED_LEAN_CTX_ROOT);
143
+ if (ownsRepoTree && existsSync(repoTreeAbs)) {
144
+ const treeStat = lstatSync(repoTreeAbs);
145
+ if (!treeStat.isDirectory() || treeStat.isSymbolicLink()) {
146
+ throw new Error(`agent-settings retirement tree is not a real directory: ${repoTreeAbs}`);
147
+ }
148
+ if (!dryRun) rmSync(repoTreeAbs, { recursive: true });
149
+ removed.push(LOCKED_LEAN_CTX_ROOT);
150
+ }
151
+ for (const target of targets) {
152
+ const absolute = assertOwnedTarget(targetRepo, target);
153
+ if (target.startsWith(`${LOCKED_LEAN_CTX_ROOT}/`)) continue;
154
+ if (!existsSync(absolute)) {
155
+ if (target !== AGENTS_GITIGNORE) pruneEmptyDirectories(targetRepo, absolute, dryRun);
156
+ continue;
157
+ }
158
+ if (target === AGENTS_GITIGNORE) {
159
+ assertRegularFile(absolute);
160
+ const current = readFileSync(absolute, "utf8");
161
+ const replacement = legacyReplacements.has(target)
162
+ ? legacyReplacements.get(target)
163
+ : removeManagedGitignoreBlock(current);
164
+ if (replacement === undefined || replacement.length === 0) {
165
+ if (!dryRun) unlinkSync(absolute);
166
+ } else if (replacement !== current && !dryRun) {
167
+ writeFileSync(absolute, replacement);
168
+ }
169
+ removed.push(target);
170
+ continue;
171
+ }
172
+ if (!dryRun) unlinkSync(absolute);
173
+ removed.push(target);
174
+ pruneEmptyDirectories(targetRepo, absolute, dryRun);
175
+ }
176
+
177
+ if (!dryRun) {
178
+ if (lock.leanCtx !== undefined) writeLock(targetRepo, { schema: 1, mcp: lock.mcp, agents: lock.agents });
179
+ if (legacy !== undefined && options.legacyLockPath !== undefined && (legacyFiles.length > 0 || legacyGitignore.length > 0)) {
180
+ stripLegacyOwnership(legacy, options.legacyLockPath, { files: legacyFiles, gitignore: legacyGitignore });
181
+ }
182
+ }
183
+ return { removed: removed.sort() };
184
+ }