@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.46 → 0.1.48

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 (174) hide show
  1. package/bin/adl +1 -1
  2. package/bin/reconcile +7 -2
  3. package/package.json +1 -1
  4. package/packages/agent-hooks/src/rules/impl/git-branch.ts +1 -1
  5. package/packages/agent-skills/assets/write-feature/SKILL.md +13 -15
  6. package/bin/lean-ctx-observe-strip +0 -434
  7. package/bin/lib/lean-ctx-observe-hooks.sh +0 -634
  8. package/bin/update-azure-agent-pool +0 -29
  9. package/packages/agent-hooks/src/hooks/lean-ctx/handler.ts +0 -22
  10. package/packages/agent-hooks/src/hooks/lean-ctx/index.ts +0 -173
  11. package/packages/agent-hooks/src/hooks/lean-ctx/mapping.ts +0 -121
  12. package/packages/agent-hooks/src/hooks/lean-ctx/scope-rewrite.ts +0 -207
  13. package/packages/agent-hooks/src/lean-ctx/env.ts +0 -123
  14. package/packages/agent-hooks/src/lean-ctx/mcp.ts +0 -142
  15. package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +0 -51
  16. package/packages/agent-hooks/src/rules/impl/adl-session-required.ts +0 -403
  17. package/packages/agent-hooks/src/rules/impl/tool-lean-ctx-global.ts +0 -594
  18. package/packages/agent-settings/assets/GLOBAL-AGENTS.md +0 -112
  19. package/packages/agent-settings/assets/lean-ctx/config.toml +0 -42
  20. package/packages/agent-settings/assets/lean-ctx/gitignore +0 -10
  21. package/packages/agent-settings/assets/lean-ctx/layout.toml +0 -7
  22. package/packages/agent-settings/src/deploy/lean-ctx-deploy.ts +0 -230
  23. package/packages/agent-settings/src/deploy/lean-ctx-merge.ts +0 -580
  24. package/packages/agent-skills/assets/adl-mechanics/SKILL.md +0 -38
  25. package/packages/agent-skills/assets/codebase-design/SKILL.md +0 -98
  26. package/packages/agent-skills/assets/codebase-design/references/DEEPENING.md +0 -37
  27. package/packages/agent-skills/assets/codebase-design/references/DESIGN-IT-TWICE.md +0 -44
  28. package/packages/agent-skills/assets/codebase-design/references/TESTABILITY.md +0 -29
  29. package/packages/agent-skills/assets/debug-issue/SKILL.md +0 -41
  30. package/packages/agent-skills/assets/domain-modeling/SKILL.md +0 -86
  31. package/packages/agent-skills/assets/domain-modeling/references/ADR-FORMAT.md +0 -47
  32. package/packages/agent-skills/assets/domain-modeling/references/CONTEXT-FORMAT.md +0 -60
  33. package/packages/agent-skills/assets/implement/SKILL.md +0 -28
  34. package/packages/agent-skills/assets/review-changes/SKILL.md +0 -45
  35. package/packages/agent-skills/assets/tdd/SKILL.md +0 -49
  36. package/packages/agent-skills/assets/tdd/references/mocking.md +0 -59
  37. package/packages/agent-skills/assets/tdd/references/tests.md +0 -77
  38. package/packages/agent-skills/assets/testing/SKILL.md +0 -54
  39. package/packages/agent-skills/assets/testing/references/e2e.md +0 -37
  40. package/packages/agent-skills/assets/testing/references/integration.md +0 -37
  41. package/packages/agent-skills/assets/testing/references/unit.md +0 -32
  42. package/packages/agent-skills/assets/to-feature/SKILL.md +0 -91
  43. package/packages/agent-skills/assets/to-feature/references/FEATURE-SPEC-TEMPLATE.md +0 -88
  44. package/packages/agent-skills/assets/to-workitems/SKILL.md +0 -90
  45. package/packages/agent-skills/assets/to-workitems/references/AZURE-DEVOPS-HIERARCHY.md +0 -121
  46. package/packages/agent-skills/assets/to-workitems/references/TICKET-TEMPLATES.md +0 -70
  47. package/packages/azdo/src/workflow-rules-matrix.csv +0 -85
  48. package/packages/fleet/src/launch-agents.ts +0 -649
  49. package/packages/repo-controls/assets/GLOBAL-INVARIANTS.md +0 -21
  50. package/packages/repo-controls/assets/enable-integration-auto-complete.mjs +0 -79
  51. package/packages/repo-controls/assets/scaffold/docs/notes.md +0 -20
  52. package/packages/repo-controls/assets/scaffold/plans/GAPS-AND-FINDINGS.md +0 -12
  53. package/packages/repo-controls/azure-pipelines.yml +0 -274
  54. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +0 -1
  55. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/excluded/frontend/mobile/src/i18n/locales/zh-CN/strings.ts +0 -1
  56. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +0 -17
  57. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +0 -13
  58. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/product/stable-delivery.md +0 -10
  59. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/product/stable-recommendation.md +0 -12
  60. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/product/target-narration.md +0 -10
  61. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/frontend/packages/desktop/src/renderer/solo/item.ts +0 -1
  62. 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 +0 -1
  63. 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 +0 -1
  64. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/fresh/fresh.ts +0 -1
  65. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub1/only.ts +0 -1
  66. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub10/only.ts +0 -1
  67. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub11/only.ts +0 -1
  68. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub2/only.ts +0 -1
  69. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub3/only.ts +0 -1
  70. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub4/only.ts +0 -1
  71. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub5/only.ts +0 -1
  72. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub6/only.ts +0 -1
  73. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub7/only.ts +0 -1
  74. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub8/only.ts +0 -1
  75. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub9/only.ts +0 -1
  76. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/services/i18n/locales/de/common.json +0 -1
  77. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/solo/item.ts +0 -1
  78. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/vendored-crate/Cargo.toml +0 -2
  79. 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 +0 -1
  80. 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 +0 -1
  81. 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 +0 -1
  82. 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 +0 -1
  83. 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 +0 -1
  84. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/fresh/fresh.ts +0 -1
  85. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub1/only.ts +0 -1
  86. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub10/only.ts +0 -1
  87. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub11/only.ts +0 -1
  88. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub2/only.ts +0 -1
  89. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub3/only.ts +0 -1
  90. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub4/only.ts +0 -1
  91. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub5/only.ts +0 -1
  92. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub6/only.ts +0 -1
  93. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub7/only.ts +0 -1
  94. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub8/only.ts +0 -1
  95. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub9/only.ts +0 -1
  96. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/solo/item.ts +0 -1
  97. 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 +0 -1
  98. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/fixtures/open-work-cap-clean/plans/GAPS-AND-FINDINGS.md +0 -5
  99. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/fixtures/open-work-cap-clean/plans/features/az601-clean/spec.md +0 -10
  100. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/agent/crates/enact-providers/src/snapshots/README.md +0 -1
  101. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/backend/crates/enact-app/assets/builtin-assistants/avatars/assistant.jpg +0 -1
  102. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/backend/crates/enact-assets/assets/logos/tools/coding/tool.png +0 -1
  103. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/backend/crates/enact-session/src/backend/codex_init_prompt.md +0 -1
  104. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/mobile/assets/images/icon.png +0 -1
  105. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/packages/desktop/src/renderer/assets/logos/brand/app.png +0 -1
  106. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/packages/desktop/src/renderer/assets/themes/default-theme.png +0 -1
  107. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/public/pwa/icon-192.png +0 -1
  108. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/resources/product.png +0 -1
  109. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-stray/backend/crates/enact-session/src/backend/README.md +0 -1
  110. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/spec.md +0 -12
  111. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-violation/plans/features/az347-test-coverage/spec.md +0 -12
  112. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/__init__.py +0 -11
  113. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/check.py +0 -62
  114. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/NotAMigration.sql +0 -1
  115. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/0001_long_prefix.sql +0 -1
  116. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/001_init.sql +0 -1
  117. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/002_add_index.sql +0 -1
  118. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/003-dashed-slug.sql +0 -1
  119. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/004_MixedCase.sql +0 -1
  120. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/005_trailing space.sql +0 -1
  121. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/01_short_prefix.sql +0 -1
  122. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/not-a-migration.sql +0 -1
  123. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/test_check.py +0 -116
  124. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/docs/architecture/product/links.md +0 -20
  125. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/docs/architecture/product/route-target.md +0 -8
  126. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/docs/architecture/product/links.md +0 -20
  127. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/docs/architecture/product/route-target.md +0 -8
  128. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.changeset/declared.txt +0 -1
  129. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/INDEPENDENT-VERIFICATION.md +0 -3
  130. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/attribute-without-conversion/.gitattributes +0 -1
  131. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/attribute-without-conversion/large file.bin +0 -3
  132. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/clean/.gitattributes +0 -1
  133. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/clean/large file.bin +0 -3
  134. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/clean/small.txt +0 -1
  135. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/missing-filter/large file.bin +0 -0
  136. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/unmatched-extension/.gitattributes +0 -1
  137. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/unmatched-extension/payload.dat +0 -0
  138. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/__init__.py +0 -1
  139. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/__init__.py +0 -12
  140. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/check.py +0 -129
  141. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/fixtures/disjoint/gate-registry.yaml +0 -13
  142. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/fixtures/empty/gate-registry.yaml +0 -7
  143. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/fixtures/overlapping/gate-registry.yaml +0 -13
  144. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/test_check.py +0 -109
  145. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/__init__.py +0 -1
  146. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/__init__.py +0 -11
  147. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/check.py +0 -149
  148. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/fixtures/clean/docs/readme.md +0 -4
  149. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/fixtures/relevant/VERSION +0 -1
  150. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/test_check.py +0 -151
  151. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/__init__.py +0 -11
  152. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/check.py +0 -202
  153. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/.workflows/changesets/package.json +0 -5
  154. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/.workflows/package.json +0 -5
  155. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/CHANGELOG.md +0 -5
  156. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/VERSION +0 -1
  157. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/.workflows/changesets/package.json +0 -5
  158. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/.workflows/package.json +0 -5
  159. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/CHANGELOG.md +0 -5
  160. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/VERSION +0 -1
  161. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/test_check.py +0 -162
  162. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/check.py +0 -103
  163. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/Cargo.lock +0 -7
  164. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/Cargo.toml +0 -4
  165. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/rust-toolchain.toml +0 -3
  166. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/src/main.rs +0 -1
  167. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/frontend/bun.lock +0 -1
  168. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/Cargo.lock +0 -7
  169. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/Cargo.toml +0 -4
  170. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/rust-toolchain.toml +0 -3
  171. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/src/main.rs +0 -1
  172. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/frontend/bun.lock +0 -0
  173. package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/grants-registry.yaml +0 -112
  174. package/packages/repo-controls/workflows/scripts/release/verify-npm-artifact.ts +0 -119
@@ -1,142 +0,0 @@
1
- /**
2
- * `adl hook lean-ctx mcp` (work item A.1): a true stdio-passthrough spawn
3
- * of the global `lean-ctx mcp` server.
4
- *
5
- * This is fundamentally NOT a `HookHandler`: every other kind reads one JSON
6
- * payload off stdin, decides something, and writes one JSON/text result —
7
- * `main.ts`'s `run()` buffers stdin into a string and buffers a handler's
8
- * whole stdout/stderr into a `HookResult` for exactly that shape. `lean-ctx
9
- * mcp` is a long-running MCP server that speaks JSON-RPC continuously over
10
- * stdin/stdout for the lifetime of the process; buffering either stream
11
- * would break the protocol (and blocking on "read all of stdin first" would
12
- * simply hang forever, since an MCP client never closes stdin). So `main.ts`
13
- * dispatches `lean-ctx mcp` here directly, before it ever reads stdin as a
14
- * JSON payload or checks `--host` — see `main.ts`'s own dispatch for exactly
15
- * where this branches off.
16
- *
17
- * Two responsibilities:
18
- *
19
- * 1. `resolveLeanCtxMcpEnv` — walk from `cwd` to the git root and check for
20
- * `adl-config.toml` (`../gating/root.ts`'s `MARKER`), exactly
21
- * like every other kind's gating BUT with a different outcome on
22
- * failure: an unmanaged repo (no git root, or a git root with no
23
- * marker) still starts the MCP server — just with `lean-ctx`'s own
24
- * built-in defaults (no `LEAN_CTX_*` vars set at all) instead of this
25
- * repo's `.agents/lean-ctx/...` — plus a one-line stderr note. Every
26
- * other kind's gating treats "unmanaged" as "exit 0, do nothing"; that
27
- * is wrong here because an editor's MCP client expects the server it
28
- * just spawned to actually start, not silently exit.
29
- * 2. `runLeanCtxMcp` — the real spawn: `stdin`/`stdout`/`stderr` all set to
30
- * `'inherit'` (Bun.spawn's true fd-passthrough, not a piped-and-copied
31
- * stream — no buffering, no JS-side copy loop that could stall or
32
- * reorder JSON-RPC frames), `SIGINT`/`SIGTERM` forwarded from this
33
- * process to the child so the MCP client's own shutdown signal reaches
34
- * `lean-ctx` instead of being swallowed by `adl hook`, and the child's
35
- * own exit code propagated back out as `main.ts`'s process exit code.
36
- */
37
-
38
- import { join } from 'node:path'
39
- import { findGitRoot, MARKER, realRootIO, type RootIO } from '../gating/root.ts'
40
- import { LEAN_CTX_HEADLESS_ENV, leanCtxEnvFor } from './env.ts'
41
-
42
- export interface LeanCtxMcpEnvResult {
43
- readonly env: Readonly<Record<string, string | undefined>>
44
- /** Non-null only for an unmanaged repo — see this module's header. */
45
- readonly note: string | null
46
- }
47
-
48
- /**
49
- * Resolve the env `lean-ctx mcp` should run with, from `cwd` alone (there is
50
- * no JSON payload for this subcommand — see this module's header). Injected
51
- * `io` defaults to the real filesystem; tests supply a fake one, matching
52
- * `../gating/root.ts`'s own `RootIO` pattern.
53
- */
54
- export function resolveLeanCtxMcpEnv(
55
- cwd: string,
56
- baseEnv: Readonly<Record<string, string | undefined>>,
57
- io: RootIO = realRootIO,
58
- ): LeanCtxMcpEnvResult {
59
- const { root } = findGitRoot(io, cwd)
60
- const managed = root !== null && io.isFile(join(root, MARKER))
61
-
62
- if (!managed || root === null) {
63
- return {
64
- env: { ...baseEnv },
65
- note: `adl hook: lean-ctx mcp: no managed repo found from ${cwd} (missing ${MARKER}); starting lean-ctx with its own defaults\n`,
66
- }
67
- }
68
-
69
- return { env: leanCtxEnvFor(root, baseEnv), note: null }
70
- }
71
-
72
- /** The minimal shape of `Bun.spawn`'s return value this module needs — narrowed so a test can inject a fake. */
73
- export interface SpawnedProcess {
74
- readonly exited: Promise<number>
75
- kill(signal?: number | NodeJS.Signals): void
76
- }
77
-
78
- export type SpawnMcp = (
79
- cmd: readonly string[],
80
- opts: { readonly cwd: string; readonly env: Record<string, string | undefined> },
81
- ) => SpawnedProcess
82
-
83
- const defaultSpawn: SpawnMcp = (cmd, opts) =>
84
- Bun.spawn(cmd as string[], {
85
- cwd: opts.cwd,
86
- env: opts.env as Record<string, string>,
87
- stdin: 'inherit',
88
- stdout: 'inherit',
89
- stderr: 'inherit',
90
- }) as unknown as SpawnedProcess
91
-
92
- /**
93
- * Spawn `lean-ctx mcp` with fully inherited stdio, forward `SIGINT`/`SIGTERM`
94
- * to it, and resolve with its exit code (never throws for a normal child
95
- * exit — `main.ts` passes this straight to `process.exit`).
96
- */
97
- export async function runLeanCtxMcp(
98
- cwd: string,
99
- baseEnv: Readonly<Record<string, string | undefined>>,
100
- deps: {
101
- readonly spawn?: SpawnMcp
102
- readonly writeStderr?: (text: string) => void
103
- readonly signalTarget?: NodeJS.Process
104
- readonly io?: RootIO
105
- } = {},
106
- ): Promise<number> {
107
- const spawn = deps.spawn ?? defaultSpawn
108
- const writeStderr = deps.writeStderr ?? ((text: string) => process.stderr.write(text))
109
- const signalTarget = deps.signalTarget ?? process
110
-
111
- const { env, note } = resolveLeanCtxMcpEnv(cwd, baseEnv, deps.io ?? realRootIO)
112
- if (note) writeStderr(note)
113
-
114
- // Headless in an unmanaged folder too: see LEAN_CTX_HEADLESS_ENV — without
115
- // it this very start re-writes lean-ctx's hooks into the global settings.
116
- const child = spawn(['lean-ctx', 'mcp'], { cwd, env: { ...env, ...LEAN_CTX_HEADLESS_ENV } })
117
-
118
- const onSigint = () => {
119
- try {
120
- child.kill('SIGINT')
121
- } catch {
122
- // already dead
123
- }
124
- }
125
- const onSigterm = () => {
126
- try {
127
- child.kill('SIGTERM')
128
- } catch {
129
- // already dead
130
- }
131
- }
132
- signalTarget.on('SIGINT', onSigint)
133
- signalTarget.on('SIGTERM', onSigterm)
134
-
135
- try {
136
- const code = await child.exited
137
- return code
138
- } finally {
139
- signalTarget.off('SIGINT', onSigint)
140
- signalTarget.off('SIGTERM', onSigterm)
141
- }
142
- }
@@ -1,51 +0,0 @@
1
- /**
2
- * `adl.build-run-denied` — docs/operations/agent-permissions.md row 12 (build run):
3
- * denied for EVERY identity, unconditionally — "pipelines run on their own
4
- * triggers". Unlike the other role rules in this package, this one does not
5
- * branch on `ADL_AGENT_ID_AGENT` at all: the matrix's own hook-action column
6
- * shows ❌ for both `agent-tarun`/`agent-vivek` and `agent-reviewer`, so there
7
- * is no identity this tool is allowed for. With no identity at all,
8
- * `adl.run-required-for-writes` (registered ahead of this rule) reports
9
- * first with its own, more specific "no session" message; this rule is what
10
- * fires once an identity IS present, which is the case that rule leaves
11
- * alone.
12
- */
13
-
14
- import type { Invocation } from '../shell/invocation.ts'
15
- import type { Finding, MessageContext, RuleSpec } from '../spec.ts'
16
- import { noParams } from '../spec.ts'
17
- import { detailString } from './messages.ts'
18
- import { mcpToolName } from './mcp-tool.ts'
19
- import { toolCallFor } from './adl-mcp-cli.ts'
20
-
21
- const RULE_ID = 'adl.build-run-denied'
22
-
23
- export const adlBuildRunDenied: RuleSpec = {
24
- id: RULE_ID,
25
- category: 'tool-call',
26
- severity: 'deny',
27
- enabledByDefault: true,
28
- summary: 'Deny build_run for every identity (docs/operations/agent-permissions.md row 12) — the MCP tool AND its adl mcp cli equivalent.',
29
- params: noParams,
30
- match(inv: Invocation): Finding | null {
31
- // Also catch `adl mcp cli build-run` — same tool, same deny.
32
- const call = toolCallFor(inv)
33
- if (call === null) return null
34
- if (mcpToolName(call.tool) !== 'build_run') return null
35
- return { ruleId: RULE_ID, severity: 'deny', detail: { tool: call.tool } }
36
- },
37
- message(finding: Finding, ctx: MessageContext) {
38
- const tool = detailString(finding, 'tool')
39
- const user = 'pipelines run on their own triggers'
40
- return {
41
- user,
42
- agent:
43
- `DENIED ${tool}: ${user}. No agent identity may queue a build — use build_list_or_get to inspect an ` +
44
- `already-running or already-queued build instead. Blocked: ${ctx.snippet}`,
45
- }
46
- },
47
- corpus: {
48
- deny: [],
49
- allow: ['ls -la', 'git status'],
50
- },
51
- }
@@ -1,403 +0,0 @@
1
- /**
2
- * `adl.session-required-for-writes` — the managed baseline hook (docs/architecture/cli-design.md
3
- * §2/§3, item 10).
4
- *
5
- * WIDENED 2026-09-28 (STATUS.md 12p, "The
6
- * standard" / W2 build item 3): the name is kept for git-history continuity,
7
- * but this rule's job is no longer "writes only". Every Azure DevOps access
8
- * — reads included — needs a resolvable agent identity now: `adl run --as
9
- * <agent>`'s session env, the machine default-agent file
10
- * (`adl-identity.ts`'s `resolveFromEnvOrFile`, steps 2-3 of the standard),
11
- * or a valid inline `ADL_AGENT_ID_AGENT=<agent>` override on the command
12
- * itself (step 1, detected via `../shell/git-identity.ts`'s
13
- * `commandHasValidInlineIdentity` — see `checkResolvableIdentity` below). With
14
- * NONE of those present, this rule denies every identity-bearing command
15
- * class (git network reads/writes, the azdo MCP tools including their reads,
16
- * `adl mcp cli`/`adl repo doctor`/`adl repo controls azdo-push`/`adl id
17
- * token`/`adl-agent-id exec`, and curl/wget/httpie/xh to
18
- * dev.azure.com/*.visualstudio.com under any HTTP method) with the
19
- * standard's own message; every other command is left alone. Once an
20
- * identity resolves, this rule gets out of the way entirely — `git-ado`/
21
- * `adl`'s own rules, and the role rules, police what an authenticated
22
- * session may do.
23
- *
24
- * Four write surfaces, each inspected in the shape the shell/tool-call
25
- * classifier already hands every other rule:
26
- *
27
- * - `git push` (`../shell/invocation.ts`'s `'git'` kind). The hook cannot run
28
- * `git remote get-url` (it decides before the child runs, statically, off
29
- * argv alone) the way the deployed `bin/git` front controller can — so an
30
- * explicit `https://.../dev.azure.com/...` URL anywhere in the push's
31
- * arguments is authoritative, and otherwise the destination is UNRESOLVED
32
- * (a bare `git push`, or `git push origin main` naming a remote this rule
33
- * cannot look up) and fails closed: unresolved is treated exactly like
34
- * "proven Azure DevOps", because the rule cannot prove otherwise. Only an
35
- * explicit NON-Azure-DevOps URL is provably safe and lets a write through
36
- * without an identity. `git-verify.ts`'s `git.no-verify` corpus already
37
- * anticipates this: its own `allow` list deliberately never contains a bare
38
- * `git push` or `git push -n`, see the comment there and
39
- * `rules-corpus-executed.test.ts`'s "corrected corpus entries" check.
40
- * - `az devops|repos|pipelines|boards|artifacts ...` (the `'azure-devops'`
41
- * kind). `tool.azure-devops` (`./tool-azure-devops.ts`) already denies
42
- * EVERY direct invocation of this family outright, read or write,
43
- * identity or not, steering everything at the MCP server — and it is
44
- * registered ahead of this rule, so in the real engine it always reports
45
- * first. This rule's own az-CLI classification (read verbs `list`/`show`/
46
- * `get`/`query` vs. everything else, fail-closed to "write" when neither
47
- * matches) is therefore defense in depth for a repository that disables
48
- * `tool.azure-devops` (`[rules."tool.azure-devops"] enabled = false`), not
49
- * something reachable through `decide()` today — see
50
- * `tests/unit/rules-adl-session-required.test.ts`, which exercises it via
51
- * a direct `match()` call rather than the shared corpus (which runs
52
- * through the real engine and would otherwise always see `tool.azure-devops`
53
- * win first).
54
- * - `curl`/`wget`/httpie (`http`/`https`)/`xh` (the generic `'command'` kind)
55
- * with a non-GET method against a `dev.azure.com` URL. curl's method is
56
- * explicit (`-X`/`--request`) or implied by a data flag (`-d`/`--data*`,
57
- * `-F`/`--form`, `--json`); wget's by `--method=`/`--post-data`/
58
- * `--post-file`; httpie/xh's by an explicit leading method argument or a
59
- * request-item/`--form`/`--raw` implying a body (httpie's own semantics:
60
- * a request with data defaults to POST, one without defaults to GET).
61
- * - An Azure DevOps MCP write tool (the `'tool-call'` kind), named
62
- * `mcp__<prefix>__<tool>` where `<tool>` is one of the four mutating
63
- * tools `packages/azdo/src/mcp-server.ts` actually registers:
64
- * `pr_create_or_update`, `pr_review`, `build_run`, `workitem_create_or_update`. The
65
- * match is on the TOOL NAME alone, not the server prefix — the package is
66
- * `azdo`, P4 folds the server under `adl`, and Claude Code's plugin-scoped
67
- * form (`mcp__plugin_<plugin>_<server>__<tool>`) adds a third spelling —
68
- * so `mcp__azdo__...`, `mcp__adl__...`, `mcp__azure-devops-mcp__...` and
69
- * `mcp__plugin_adl_azdo__...` are all matched the same way. Its three read
70
- * tools (`pr_list_or_get`, `build_list_or_get`, `workitem_list_or_get`)
71
- * are left alone under every one of those prefixes too.
72
- */
73
-
74
- import type { Invocation } from '../shell/invocation.ts'
75
- import type { Token } from '../shell/token.ts'
76
- import { dynamicToken, tokenValue } from '../shell/token.ts'
77
- import { commandHasValidInlineIdentity, isNetworkGitInvocation } from '../shell/git-identity.ts'
78
- import type { EnvPort } from '../ports.ts'
79
- import type { Finding, MessageContext, RuleContext, RuleSpec } from '../spec.ts'
80
- import { noParams } from '../spec.ts'
81
- import {
82
- ADL_AGENT_ID_BINARY_NAMES,
83
- ADL_AGENT_ID_COMMAND_SHAPES,
84
- ADL_BINARY_NAMES,
85
- ADL_IDENTITY_COMMAND_SHAPES,
86
- classifyGitPushDestination,
87
- containsIdentityBearingToken,
88
- HTTP_CLIENT_BINARY_NAMES,
89
- httpClientMethod,
90
- isAdoUrl,
91
- isHelpOnlyInvocation,
92
- matchesIdentityShape,
93
- skipLeadingDashFlags,
94
- } from './git-helpers.ts'
95
- import { NO_AGENT_IDENTITY_MESSAGE, resolveFromEnvOrFile } from './adl-identity.ts'
96
- import { detailString } from './messages.ts'
97
- import { mcpToolName } from './mcp-tool.ts'
98
-
99
- const RULE_ID = 'adl.session-required-for-writes'
100
- const ENV_VAR = 'ADL_AGENT_ID_AGENT'
101
-
102
- /**
103
- * M7 (STATUS.md 12p): whether an identity is
104
- * resolvable for `command`, and if not, the EXACT message to show — the
105
- * one standard `NO_AGENT_IDENTITY_MESSAGE` when nothing is configured at
106
- * all, or the SPECIFIC named error when something IS configured but is
107
- * invalid (an unrecognized `ADL_AGENT_ID_AGENT` value, or a default-agent
108
- * file naming an agent outside `VALID_AGENTS`) — `resolveFromEnvOrFile`'s
109
- * own `UnresolvedIdentity.message` already carries exactly the right text
110
- * for either case (see `adl-identity.ts`'s `resolveFromEnvOrFile`: it is
111
- * `NO_AGENT_IDENTITY_MESSAGE` verbatim for `reason: 'none'`, and the named
112
- * `invalidAgentError` text for `reason: 'invalid'`), so this reads that
113
- * message through rather than reporting the SAME generic "run the fleet
114
- * reconcile" text regardless of which of the two actually happened — an
115
- * invalid identity is a materially different, more actionable diagnosis
116
- * than none configured at all, and reporting the generic text for both
117
- * hid that distinction from the agent.
118
- *
119
- * A valid inline `ADL_AGENT_ID_AGENT=<agent>` override anywhere on the
120
- * command line (step 1 of the standard — coarse, whole-command; see
121
- * `commandHasValidInlineIdentity`'s own doc for what that trades off)
122
- * resolves too, without needing the session env / machine default-agent
123
- * file (steps 2-3) at all.
124
- */
125
- type IdentityCheck = { readonly resolvable: true } | { readonly resolvable: false; readonly message: string }
126
-
127
- function checkResolvableIdentity(command: string, env: EnvPort): IdentityCheck {
128
- if (commandHasValidInlineIdentity(command)) return { resolvable: true }
129
- const resolution = resolveFromEnvOrFile(env)
130
- return resolution.ok ? { resolvable: true } : { resolvable: false, message: resolution.message }
131
- }
132
-
133
- const classifyPush = classifyGitPushDestination
134
-
135
- /**
136
- * az CLI verbs that only read. Fail-closed by design: anything NOT
137
- * recognized here (including a verb this list simply does not know about
138
- * yet) is treated as a write, never the reverse. Recognized against the
139
- * FULL args after `az` (the subcommand group included, e.g. `repos pr
140
- * list`) — a flag's VALUE (`--status active`) could in principle collide
141
- * with a verb spelling, an accepted heuristic risk given `tool.azure-devops`
142
- * denies the whole family outright regardless (see header).
143
- */
144
- const AZ_READ_VERBS: ReadonlySet<string> = new Set(['list', 'show', 'get', 'query'])
145
-
146
- function azCommandIsWrite(args: readonly Token[]): boolean {
147
- for (const token of args) {
148
- const value = tokenValue(token).toLowerCase()
149
- if (value.startsWith('-')) continue
150
- if (AZ_READ_VERBS.has(value)) return false
151
- }
152
- return true
153
- }
154
-
155
- /**
156
- * M10 (STATUS.md 12p): the name set and the
157
- * per-binary method detection both moved to `git-helpers.ts`'s
158
- * `HTTP_CLIENT_BINARY_NAMES`/`httpClientMethod` — shared with
159
- * `tool-azure-devops.ts`'s own new WRITE-outright deny (docs/operations/agent-permissions.md
160
- * row 13), so the two cannot classify the same command two different ways.
161
- */
162
- const HTTP_CLIENT_NAMES = HTTP_CLIENT_BINARY_NAMES
163
-
164
- /**
165
- * Azure DevOps MCP write tools, derived from `packages/azdo/src/mcp-server.ts`'s
166
- * `ListToolsRequestSchema` handler (re-grepped 2026-09-27 for C3) — the
167
- * complete tool roster there is `pr_list_or_get`/`pr_create_or_update`/
168
- * `pr_review`, `build_list_or_get`/`build_run`, `workitem_list_or_get`/
169
- * `workitem_create_or_update`; the three not in this set are the read half.
170
- * `pr_review` (C3, docs/operations/agent-permissions.md rows 6-8: comment + vote) joined
171
- * this set the same day `adl-pr-review-role.ts` started gating it by role —
172
- * a caller with no session identity at all must be denied here FIRST, the
173
- * same "no session, not merely the wrong role" ordering `adl-pr-role.ts`
174
- * documents for `pr_create_or_update`.
175
- */
176
- const ADO_MCP_WRITE_TOOLS: ReadonlySet<string> = new Set([
177
- 'pr_create_or_update',
178
- 'pr_review',
179
- 'build_run',
180
- 'workitem_create_or_update',
181
- ])
182
-
183
- /**
184
- * WIDENED 2026-09-28: the standard requires an identity for every Azure
185
- * DevOps MCP tool call, reads included — the read half no longer gets a
186
- * pass just because it cannot mutate anything. `mcp-server.ts`'s complete
187
- * roster: `pr_list_or_get`, `build_list_or_get`, `workitem_list_or_get`
188
- * (reads) alongside the four writes above.
189
- */
190
- const ADO_MCP_ALL_TOOLS: ReadonlySet<string> = new Set([...ADO_MCP_WRITE_TOOLS, 'pr_list_or_get', 'build_list_or_get', 'workitem_list_or_get'])
191
-
192
- /** `adl <...>` shapes that need an identity even with no HTTP client or git verb involved — see `git-helpers.ts`'s `ADL_IDENTITY_COMMAND_SHAPES`. */
193
- const ADL_BINARY_ALL_NAMES: ReadonlySet<string> = ADL_BINARY_NAMES
194
- const ADL_AGENT_ID_BINARY_ALL_NAMES: ReadonlySet<string> = ADL_AGENT_ID_BINARY_NAMES
195
-
196
- /**
197
- * R3 (STATUS.md 12p, re-review 2026-09-28 night): interpreter
198
- * one-liners whose `-c`/`-e`/`--eval` code string names an identity-bearing
199
- * operation — `../shell/invocation.ts`'s walker classifies these as a plain,
200
- * unclassified `'command'` Invocation (it only re-parses `-c` as shell for
201
- * `sh`/`bash`/`zsh`/`dash`/`ksh`/`fish`, never an interpreter's own code), so
202
- * `python3 -c "import subprocess; subprocess.run(['git','push'])"` was
203
- * previously invisible to this rule entirely. Deliberately coarse
204
- * (`containsIdentityBearingToken`, textual) — precise parsing of arbitrary
205
- * Python/JS/Perl/Ruby/AppleScript source is not this rule's job.
206
- */
207
- const INTERPRETER_ONE_LINER_NAMES: ReadonlySet<string> = new Set([
208
- 'python', 'python.exe', 'python2', 'python2.exe', 'python3', 'python3.exe',
209
- 'node', 'node.exe', 'perl', 'perl.exe', 'ruby', 'ruby.exe', 'bun', 'bun.exe',
210
- 'osascript', 'osascript.exe',
211
- ])
212
- const INTERPRETER_CODE_FLAGS: ReadonlySet<string> = new Set(['-c', '-e', '--eval'])
213
-
214
- /** Every code string passed via `-c`/`-e`/`--eval` among `args` — the token immediately following the flag. */
215
- function interpreterCodeStrings(args: readonly Token[]): readonly string[] {
216
- const codes: string[] = []
217
- for (let index = 0; index < args.length; index += 1) {
218
- if (!INTERPRETER_CODE_FLAGS.has(tokenValue(args[index] as Token))) continue
219
- const next = args[index + 1]
220
- if (next !== undefined) codes.push(tokenValue(next))
221
- }
222
- return codes
223
- }
224
-
225
- /**
226
- * Whether `inv` is a candidate this rule cares about at all, and if so, the
227
- * "reason" text for its Finding — computed WITHOUT ever resolving an
228
- * identity (see `match`'s own L4 comment for why the ordering matters). The
229
- * four surfaces are exactly the ones documented in this file's header.
230
- */
231
- /**
232
- * Exported for `../../pre-tool-use/handler.ts`'s own broader net (R3,
233
- * STATUS.md 12p): a walker-visible identity-bearing shape
234
- * the narrow `adl.git-identity` rewrite scanner does not recognize (buried
235
- * inside `if`/`!`/`for..do`/`xargs`/a heredoc or here-string/a piped-into
236
- * shell) still needs denying when the resolved identity cannot actually
237
- * reach THIS specific host/tool-class's child process — this rule alone
238
- * cannot make that call (it has no host/tool-class in its `RuleContext`),
239
- * but it IS the one place that already classifies every one of those shapes
240
- * correctly (see this file's header), so the handler reuses this function
241
- * rather than re-deriving the same walker-based classification a second
242
- * time.
243
- */
244
- export function identityBearingReason(inv: Invocation): string | null {
245
- if (inv.kind === 'git') {
246
- // F2 (independent review, 2026-09-29): widened from a plain
247
- // `NETWORK_GIT_VERBS.has(inv.subcommand)` gate — see
248
- // `isNetworkGitInvocation`'s own doc for the additional network-reaching
249
- // shapes now covered (git remote show/prune/update/set-head -a, git
250
- // maintenance run --task=prefetch, the remote-https/remote-http/
251
- // http-fetch transport helpers, git submodule update/sync --recursive,
252
- // git archive --remote).
253
- if (!isNetworkGitInvocation(inv.subcommand, inv.rest.map(tokenValue))) return null
254
- if (isHelpOnlyInvocation(inv.rest)) return null
255
- const risk = classifyPush(inv.rest)
256
- if (risk === 'non-ado') return null
257
- const verbLabel = inv.subcommand === 'push' ? 'git push' : `git ${inv.subcommand}`
258
- return risk === 'ado' ? `${verbLabel} against a dev.azure.com remote` : `${verbLabel} with an unresolved (implicit) remote destination`
259
- }
260
-
261
- if (inv.kind === 'azure-devops') {
262
- // Defense in depth only — tool.azure-devops (registered ahead of this
263
- // rule in ../registry.ts) already denies the whole `az devops|repos|
264
- // pipelines|boards|artifacts` family outright, read or write, identity
265
- // or not. See this file's header.
266
- return azCommandIsWrite(inv.args) ? 'az CLI Azure DevOps write' : null
267
- }
268
-
269
- if (inv.kind === 'command') {
270
- if (HTTP_CLIENT_NAMES.has(inv.name)) {
271
- const targetsAdo = inv.args.some((token) => isAdoUrl(tokenValue(token)))
272
- if (!targetsAdo) return null
273
- // WIDENED: every method now needs an identity, GET included — the
274
- // standard covers reads too, not only the mutating methods this rule
275
- // used to single out.
276
- const method = httpClientMethod(inv.name, inv.args)
277
- return `${inv.name} ${method} to dev.azure.com/visualstudio.com`
278
- }
279
- if (ADL_BINARY_ALL_NAMES.has(inv.name)) {
280
- const values = inv.args.map((token) => tokenValue(token))
281
- if (inv.args.some((token) => dynamicToken(token))) return null
282
- if (!matchesIdentityShape(values, ADL_IDENTITY_COMMAND_SHAPES)) return null
283
- return `${inv.name} ${values.slice(0, 3).join(' ')}`
284
- }
285
- if (ADL_AGENT_ID_BINARY_ALL_NAMES.has(inv.name)) {
286
- const values = inv.args.map((token) => tokenValue(token))
287
- if (inv.args.some((token) => dynamicToken(token))) return null
288
- // M5 (STATUS.md 12p): leading dash-prefixed
289
- // global flags are skipped before matching the `['exec']` shape —
290
- // see git-helpers.ts's skipLeadingDashFlags doc.
291
- if (!matchesIdentityShape(skipLeadingDashFlags(values), ADL_AGENT_ID_COMMAND_SHAPES)) return null
292
- return `${inv.name} ${values.slice(0, 3).join(' ')}`
293
- }
294
- if (INTERPRETER_ONE_LINER_NAMES.has(inv.name)) {
295
- const identityBearing = interpreterCodeStrings(inv.args).some((code) => containsIdentityBearingToken(code))
296
- return identityBearing ? `${inv.name} interpreter one-liner` : null
297
- }
298
- return null
299
- }
300
-
301
- if (inv.kind === 'tool-call') {
302
- const toolName = mcpToolName(inv.tool)
303
- if (toolName === null || !ADO_MCP_ALL_TOOLS.has(toolName)) return null
304
- return `Azure DevOps MCP tool ${inv.tool}`
305
- }
306
-
307
- return null
308
- }
309
-
310
- export const adlSessionRequiredForWrites: RuleSpec = {
311
- id: RULE_ID,
312
- category: 'tool-call',
313
- severity: 'deny',
314
- enabledByDefault: true,
315
- summary: 'Deny Azure DevOps access (git, az CLI, curl/wget/httpie, adl entry points, MCP tools) with no resolvable ADL agent identity.',
316
- params: noParams,
317
- match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
318
- // L4 (STATUS.md 12p): the shape check runs
319
- // FIRST, entirely without touching `ctx.env` — `checkResolvableIdentity`
320
- // can hit the real filesystem (the machine default-agent file) once
321
- // neither the command's own inline override nor the session env
322
- // resolves, so it must not run for every invocation this rule is asked
323
- // about. The vast majority (ls, cat, git status, an unrelated tool
324
- // call, …) are not identity-bearing at all and, with this ordering,
325
- // never reach `checkResolvableIdentity` — only a genuine candidate does.
326
- const reason = identityBearingReason(inv)
327
- if (reason === null) return null
328
-
329
- const identity = checkResolvableIdentity(ctx.command ?? '', ctx.env)
330
- if (identity.resolvable) return null
331
- // M7: the exact message this specific failure earns — NOT a fixed
332
- // generic string — carried in the Finding so message() reports it
333
- // faithfully instead of a constant that cannot distinguish "nothing
334
- // configured" from "something IS configured but it's wrong".
335
- return { ruleId: RULE_ID, severity: 'deny', detail: { reason, identityMessage: identity.message } }
336
- },
337
- message(finding: Finding, ctx: MessageContext) {
338
- const reason = detailString(finding, 'reason')
339
- const identityMessage = detailString(finding, 'identityMessage')
340
- // R8 (STATUS.md 12p, re-review 2026-09-28 night):
341
- // NO_AGENT_IDENTITY_MESSAGE (the "nothing configured at all" case) IS
342
- // ALREADY "prefix the command with ADL_AGENT_ID_AGENT=<agent>, or start
343
- // the session with `adl run <surface> --as <agent>`" — appending the
344
- // same advice a second time, in slightly different wording, said it
345
- // twice. The INVALID case (something IS configured, but names an agent
346
- // outside VALID_AGENTS) has no such text at all, so the "how to fix it"
347
- // sentence is the only place that advice appears for it and stays.
348
- const advice = identityMessage === NO_AGENT_IDENTITY_MESSAGE ? '' : ` Prefix the command with ${ENV_VAR}=<agent>, or start the session with adl run --as <agent>.`
349
- return {
350
- user: identityMessage,
351
- agent: `DENIED ${reason} without an ADL agent identity. ${identityMessage}${advice} Blocked: ${ctx.snippet}`,
352
- }
353
- },
354
- corpus: {
355
- deny: [
356
- 'git push https://dev.azure.com/org/project/_git/repo main',
357
- 'git push origin main',
358
- 'git push',
359
- // WIDENED (2026-09-28): git network READS now need an identity too —
360
- // every Azure DevOps access does, not only writes.
361
- 'git fetch origin main',
362
- 'git clone https://dev.azure.com/org/project/_git/repo',
363
- 'git ls-remote https://dev.azure.com/org/project/_git/repo',
364
- 'curl -X POST https://dev.azure.com/org/project/_apis/git/repositories',
365
- 'wget --method=POST https://dev.azure.com/org/project/_apis/git/repositories',
366
- // WIDENED: a plain GET to dev.azure.com now needs an identity too.
367
- 'curl https://dev.azure.com/org/project/_apis/git/repositories',
368
- 'wget https://dev.azure.com/org/project/_apis/git/repositories',
369
- // WIDENED: the adl entry points that reach Azure DevOps.
370
- 'adl mcp cli pr-list-or-get',
371
- 'adl repo doctor',
372
- 'adl repo controls azdo-push',
373
- 'adl id token agent-tarun',
374
- 'adl-agent-id exec --agent agent-tarun -- adl id token agent-tarun --json',
375
- // Already denied outright by tool.azure-devops (steers at the MCP server) —
376
- // kept here too so this rule's own corpus is non-empty and honest about
377
- // az CLI being a write surface it cares about; see the header for why
378
- // its OWN read/write split is exercised in a dedicated unit test instead.
379
- 'az repos pr create --title x',
380
- ],
381
- allow: [
382
- // Explicit non-ADO destination: provably safe without an identity.
383
- 'git push https://github.com/org/repo main',
384
- 'git fetch https://github.com/org/repo main',
385
- 'curl https://github.com/org/repo',
386
- 'wget https://github.com/org/repo',
387
- // Non-identity-bearing local commands and adl subcommands are untouched.
388
- 'git status',
389
- 'ls -la',
390
- 'adl run -- claude',
391
- 'adl repo controls compliance --repo .',
392
- // A valid inline override supplies its own identity. A feature-branch
393
- // destination (not `main`/`integration`) is used here so this stays a
394
- // clean example of THIS rule's own concern — since W2 build item 2
395
- // widened adl.git-push-branch-policy to grade the command's EFFECTIVE
396
- // identity too, an inline-only override no longer bypasses branch
397
- // protection: `ADL_AGENT_ID_AGENT=agent-tarun git push origin main`
398
- // is correctly denied by that rule now, not allowed by this one.
399
- 'ADL_AGENT_ID_AGENT=agent-tarun git push origin feat/x',
400
- 'ADL_AGENT_ID_AGENT=agent-tarun adl id token agent-tarun',
401
- ],
402
- },
403
- }