@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.10 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adl +2 -2
- package/bin/git +17 -18
- package/bin/git-ado +27 -26
- package/bin/git-defaults +173 -0
- package/bin/health-check +8 -1
- package/bin/kimi-hooks +1 -1
- package/bin/lib/adl-package.sh +257 -0
- package/bin/lib/bun-compile-build.sh +1 -1
- package/bin/lib/fleet-host.sh +62 -0
- package/bin/lib/lean-ctx-observe-hooks.sh +9 -9
- package/bin/reconcile +693 -470
- package/bin/reconcile-host +121 -0
- package/bin/setup +219 -0
- package/bin/shell-path-policy +15 -5
- package/bin/sync-and-reconcile +79 -68
- package/bin/validate-manifest +46 -51
- package/package.json +2 -12
- package/packages/agent-hooks/README.md +14 -9
- package/packages/agent-hooks/assets/hooks.json +0 -20
- package/packages/agent-hooks/package.json +1 -2
- package/packages/agent-hooks/src/cli/args.ts +1 -1
- package/packages/agent-hooks/src/cli/doctor.ts +6 -58
- package/packages/agent-hooks/src/deploy/deploy.ts +12 -41
- package/packages/agent-hooks/src/deploy/doctor.ts +8 -11
- package/packages/agent-hooks/src/deploy/index.ts +14 -14
- package/packages/agent-hooks/src/deploy/json-merge.ts +7 -8
- package/packages/agent-hooks/src/deploy/legacy-lock.ts +2 -2
- package/packages/agent-hooks/src/deploy/list.ts +1 -1
- package/packages/agent-hooks/src/deploy/lock.ts +31 -12
- package/packages/agent-hooks/src/deploy/profile.ts +3 -4
- package/packages/agent-hooks/src/deploy/source.ts +1 -1
- package/packages/agent-hooks/src/gating/config.ts +10 -24
- package/packages/agent-hooks/src/gating/root.ts +3 -3
- package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
- package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
- package/packages/agent-hooks/src/hooks/contract.ts +17 -17
- package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
- package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
- package/packages/agent-hooks/src/hooks/log.ts +8 -10
- package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
- package/packages/agent-hooks/src/hosts/registry.ts +1 -1
- package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
- package/packages/agent-hooks/src/log/writer.ts +16 -2
- package/packages/agent-hooks/src/main.ts +7 -41
- package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
- package/packages/agent-hooks/src/rules/engine.ts +13 -17
- package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
- package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
- package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
- package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
- package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
- package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
- package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
- package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
- package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
- package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
- package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
- package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +159 -0
- package/packages/agent-hooks/src/rules/impl/fs-trash.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
- package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
- package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
- package/packages/agent-hooks/src/rules/impl/tool-grep.ts +34 -12
- package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
- package/packages/agent-hooks/src/rules/ports.ts +5 -7
- package/packages/agent-hooks/src/rules/registry.ts +4 -6
- package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
- package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
- package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
- package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
- package/packages/agent-hooks/src/rules/spec.ts +2 -2
- package/packages/agent-settings/README.md +287 -0
- package/packages/agent-settings/assets/GLOBAL-AGENTS.md +18 -18
- package/packages/agent-settings/assets/agents/architect.toml +2 -0
- package/packages/agent-settings/assets/agents/code-reviewer.toml +2 -0
- package/packages/agent-settings/assets/agents/executor.toml +2 -0
- package/packages/agent-settings/assets/agents/explore.toml +2 -0
- package/packages/agent-settings/assets/agents/planner.toml +2 -0
- package/packages/agent-settings/assets/mcp.json +0 -4
- package/packages/agent-settings/deploy-profile.json +139 -0
- package/packages/agent-settings/deploy-profile.schema.json +147 -0
- package/packages/agent-settings/managed/README.md +29 -30
- package/packages/agent-settings/managed/codex-requirements.toml +9 -9
- package/packages/agent-settings/package.json +20 -0
- package/packages/agent-settings/src/deploy/agent-render.ts +2 -2
- package/packages/agent-settings/src/deploy/agent-toml.ts +1 -1
- package/packages/agent-settings/src/deploy/agents-deploy.ts +17 -3
- package/packages/agent-settings/src/deploy/doctor.ts +3 -83
- package/packages/agent-settings/src/deploy/index.ts +6 -33
- package/packages/agent-settings/src/deploy/legacy-lock.ts +6 -6
- package/packages/agent-settings/src/deploy/list.ts +5 -19
- package/packages/agent-settings/src/deploy/lock.ts +8 -18
- package/packages/agent-settings/src/deploy/mcp-deploy.ts +10 -5
- package/packages/agent-settings/src/deploy/mcp-merge.ts +22 -3
- package/packages/agent-settings/src/deploy/mcp-source.ts +1 -1
- package/packages/agent-settings/src/deploy/profile.ts +11 -35
- package/packages/agent-settings/src/deploy/retire-lean-ctx.ts +184 -0
- package/packages/agent-settings/src/deploy/settings.ts +17 -22
- package/packages/agent-settings/src/global-surface-sweep.ts +5 -17
- package/packages/agent-settings/src/kimi-hooks.ts +339 -192
- package/packages/agent-settings/src/opencode-hooks.ts +1 -1
- package/packages/agent-settings/tsconfig.json +23 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +120 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +276 -0
- package/packages/agent-skills/assets/debug-issue/SKILL.md +8 -7
- package/packages/agent-skills/assets/explore-codebase/SKILL.md +13 -13
- package/packages/agent-skills/assets/refactor-safely/SKILL.md +12 -11
- package/packages/agent-skills/assets/review-changes/SKILL.md +7 -7
- package/packages/agent-skills/assets/testing/references/e2e.md +37 -0
- package/packages/agent-skills/assets/testing/references/integration.md +37 -0
- package/packages/agent-skills/assets/testing/references/unit.md +32 -0
- package/packages/agent-skills/dist/deploy.d.ts +2 -0
- package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
- package/packages/agent-skills/dist/deploy.js +27 -1
- package/packages/agent-skills/dist/deploy.js.map +1 -1
- package/packages/agent-skills/dist/doctor.d.ts +0 -2
- package/packages/agent-skills/dist/doctor.d.ts.map +1 -1
- package/packages/agent-skills/dist/doctor.js +1 -1
- package/packages/agent-skills/dist/doctor.js.map +1 -1
- package/packages/agent-skills/dist/fs-utils.d.ts +0 -1
- package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -1
- package/packages/agent-skills/dist/fs-utils.js +1 -1
- package/packages/agent-skills/dist/fs-utils.js.map +1 -1
- package/packages/agent-skills/package.json +1 -1
- package/packages/agent-skills/src/deploy.ts +29 -1
- package/packages/agent-skills/src/doctor.ts +1 -1
- package/packages/agent-skills/src/fs-utils.ts +1 -1
- package/packages/azdo/README.md +10 -9
- package/packages/azdo/package.json +2 -5
- package/packages/azdo/src/azdo-pl.ts +2 -54
- package/packages/azdo/src/azdo-pr-review.ts +4 -4
- package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
- package/packages/azdo/src/azdo-wit.ts +41 -2
- package/packages/azdo/src/lib/agent-identity.ts +12 -14
- package/packages/azdo/src/lib/agent-token.ts +2 -2
- package/packages/azdo/src/lib/client.ts +0 -5
- package/packages/azdo/src/lib/graph-identity.ts +4 -4
- package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
- package/packages/azdo/src/workflow-rules.ts +128 -0
- package/packages/fleet/manifest.json +38 -33
- package/packages/fleet/manifest.schema.json +67 -65
- package/packages/fleet/src/default-agent-file.ts +3 -3
- package/packages/fleet/src/install-adl-package.ts +73 -15
- package/packages/fleet/src/install-embedding-model.ts +14 -14
- package/packages/fleet/src/managed-settings.ts +7 -7
- package/packages/fleet/src/repo-maintain.ts +439 -0
- package/packages/fleet/src/scratch-reap.ts +6 -6
- package/packages/fleet/src/vscode-settings.ts +5 -5
- package/packages/repo-controls/README.md +141 -43
- package/packages/repo-controls/assets/promote.ts +4 -4
- package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
- package/packages/repo-controls/assets/version-bump.sh +31 -84
- package/packages/repo-controls/bunfig.toml +6 -7
- package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
- package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
- 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
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
- 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
- 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
- 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
- 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
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
- 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
- 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
- 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
- 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
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
- 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
- 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
- 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
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
- 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
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
- 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
- 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
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
- 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
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
- 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
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
- 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
- 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
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
- 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
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +256 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
- package/packages/repo-controls/package.json +2 -10
- package/packages/repo-controls/scripts/hooks/post-merge +13 -0
- package/packages/repo-controls/scripts/hooks/pre-push +3 -3
- package/packages/repo-controls/src/azdo-push.ts +64 -36
- package/packages/repo-controls/src/azure-devops-governance.ts +7 -9
- package/packages/repo-controls/src/azure-devops-remote.ts +1 -1
- package/packages/repo-controls/src/cli.ts +29 -8
- package/packages/repo-controls/src/compliance-config.ts +410 -2
- package/packages/repo-controls/src/config.ts +133 -60
- package/packages/repo-controls/src/constants.ts +13 -27
- package/packages/repo-controls/src/coverage-ratchet.ts +4 -4
- package/packages/repo-controls/src/doctor.ts +46 -19
- package/packages/repo-controls/src/gitignore-block.ts +5 -29
- package/packages/repo-controls/src/hook-log.ts +1 -2
- package/packages/repo-controls/src/hook.ts +201 -45
- package/packages/repo-controls/src/install.ts +14 -8
- package/packages/repo-controls/src/integrity.ts +3 -3
- package/packages/repo-controls/src/lfs.ts +111 -0
- package/packages/repo-controls/src/promote.ts +8 -8
- package/packages/repo-controls/src/runtime.ts +9 -1
- package/packages/repo-controls/src/workflows-drift.ts +4 -5
- package/packages/repo-controls/src/worktree-guard.ts +3 -3
- package/packages/fleet/jobs/git-maintain/src/main.ts +0 -848
- package/packages/fleet/systemd/adl-azure-agent-update.service +0 -13
- package/packages/fleet/systemd/adl-azure-agent-update.timer +0 -10
|
@@ -35,7 +35,7 @@ import { gitIdentityNeedsIdentityMessage, hostCannotRewriteMessage, RULE_ID as G
|
|
|
35
35
|
import { RULE_ID as GIT_CREDENTIAL_BYPASS_RULE_ID, SECURITY_RULE_ID as SECURITY_KEYCHAIN_ADO_RULE_ID } from '../rules/impl/adl-git-credential-bypass.ts'
|
|
36
36
|
import { RULE_ID as HUMAN_AZDO_BYPASS_RULE_ID } from '../rules/impl/adl-human-azdo-bypass.ts'
|
|
37
37
|
import { resolveFromEnvOrFile } from '../rules/impl/adl-identity.ts'
|
|
38
|
-
import { identityBearingReason } from '../rules/impl/adl-
|
|
38
|
+
import { identityBearingReason } from '../rules/impl/adl-run-required.ts'
|
|
39
39
|
import { commandHasValidInlineIdentity, effectiveIdentityForCommand } from '../rules/shell/git-identity.ts'
|
|
40
40
|
import { invocations } from '../rules/shell/invocation.ts'
|
|
41
41
|
import { KNOWN_MCP_TOOL_NAMES, mcpToolName, toolNameEndingWithKnownSuffix } from '../rules/impl/mcp-tool.ts'
|
|
@@ -82,7 +82,7 @@ const RULES = requireRegistered(BUILTIN_RULES)
|
|
|
82
82
|
export function toDecideInput(payload: Record<string, unknown>): DecideInput | null {
|
|
83
83
|
const toolInput = (payload.tool_input ?? {}) as Record<string, unknown>
|
|
84
84
|
|
|
85
|
-
//
|
|
85
|
+
// Codex's `apply_patch` names its
|
|
86
86
|
// patch body `tool_input.command` — the same key name a real shell tool
|
|
87
87
|
// call uses. Checked BEFORE the generic loop below, which would otherwise
|
|
88
88
|
// read that patch TEXT as if it were a shell command and walk it through
|
|
@@ -167,13 +167,11 @@ function classifyCommandTool(payload: Record<string, unknown>): CommandToolClass
|
|
|
167
167
|
if (typeof tool !== 'string' || tool.length === 0) return 'native-shell'
|
|
168
168
|
if (tool.startsWith('mcp__') || tool.startsWith('MCP:')) return 'mcp'
|
|
169
169
|
if (NATIVE_SHELL_TOOL_NAMES.has(tool)) return 'native-shell'
|
|
170
|
-
// ASSUMPTION (unverified
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
// `<server>.ctx_shell` / `<server>:ctx_shell` (or the ctx_execute
|
|
176
|
-
// sibling). Treated as MCP-class defensively: an unrewritten push through
|
|
170
|
+
// ASSUMPTION (unverified): OpenCode's and Kimi's own MCP tool-call naming
|
|
171
|
+
// has not been confirmed against a live capture (the tests use synthetic names) — they may
|
|
172
|
+
// carry no mcp__/MCP: prefix at all, spelling the lean-ctx shell tool
|
|
173
|
+
// `<server>_ctx_shell` / `<server>.ctx_shell` / `<server>:ctx_shell` (or
|
|
174
|
+
// the ctx_execute sibling). Treated as MCP-class defensively: an unrewritten push through
|
|
177
175
|
// such a call would otherwise silently fall through to 'other' and reach
|
|
178
176
|
// git-ado's human pass-through unrewritten — the exact incident this
|
|
179
177
|
// module exists to close (see this file's own header).
|
|
@@ -229,7 +227,7 @@ export async function handlePreToolUse(inv: HookInvocation): Promise<HookResult>
|
|
|
229
227
|
|
|
230
228
|
// The invocation's own environment, not the handler process's ambient one:
|
|
231
229
|
// `main.ts` passes `process.env` here in production, and the identity rules
|
|
232
|
-
// (`adl.
|
|
230
|
+
// (`adl.run-required-for-writes`, `adl.git-push-branch-policy`,
|
|
233
231
|
// `adl.git-identity`'s rewrite) must read the environment the caller handed
|
|
234
232
|
// the invocation — tests inject it explicitly, and a host that scrubs its
|
|
235
233
|
// hook child's environment must not inherit the hook wrapper's own identity.
|
|
@@ -257,24 +255,21 @@ export async function handlePreToolUse(inv: HookInvocation): Promise<HookResult>
|
|
|
257
255
|
}
|
|
258
256
|
|
|
259
257
|
/**
|
|
260
|
-
* The identity rule ids — used below
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
258
|
+
* The identity rule ids — used below purely to tell `denyIdentity`/
|
|
259
|
+
* `passIdentity` which decisions in a MANAGED repo's own normal rule pass
|
|
260
|
+
* are identity decisions worth logging `identity_source`/`identityAgent`
|
|
261
|
+
* for, as opposed to an unrelated deny (`fs.rm`, `git.no-verify`, …) that
|
|
262
|
+
* made no identity decision at all.
|
|
265
263
|
*
|
|
266
|
-
*
|
|
267
|
-
* config.toml`
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
* calls anything for either of those cases but a strict, silent no-op — see
|
|
273
|
-
* its own header and `silentNoop`. The rule ids themselves stay meaningful
|
|
274
|
-
* only for the logging purpose above, in the repos where hooks already run.
|
|
264
|
+
* This is NOT a baseline that runs anywhere else: hooks run only in a repo
|
|
265
|
+
* with its own `adl-config.toml` where `adl hooks deploy` has run
|
|
266
|
+
* (Tarun, 2026-09-29: "the repos where `adl-config.toml` does not exist have
|
|
267
|
+
* no business running hooks"). `main.ts` calls nothing but a strict, silent
|
|
268
|
+
* no-op for an unmanaged repo or one with `[hooks] enabled = false` — see its
|
|
269
|
+
* own header and `silentNoop`.
|
|
275
270
|
*/
|
|
276
271
|
const IDENTITY_RULE_IDS: ReadonlySet<RuleId> = new Set([
|
|
277
|
-
'adl.
|
|
272
|
+
'adl.run-required-for-writes',
|
|
278
273
|
'adl.git-identity',
|
|
279
274
|
'adl.token-minting-role',
|
|
280
275
|
'tool.azure-devops',
|
|
@@ -285,18 +280,17 @@ const IDENTITY_RULE_IDS: ReadonlySet<RuleId> = new Set([
|
|
|
285
280
|
])
|
|
286
281
|
|
|
287
282
|
/**
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
* `adl.
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
* would have been without the role mismatch.
|
|
283
|
+
* The four role-gate rules that deny a SPECIFIC Azure DevOps MCP tool call by
|
|
284
|
+
* the caller's identity (`adl.workitem-requires-tarun-or-vivek`,
|
|
285
|
+
* `adl.pr-create-update-role`, `adl.pr-review-role`,
|
|
286
|
+
* `adl.build-run-denied`). None of these are in `IDENTITY_RULE_IDS` above —
|
|
287
|
+
* that set covers the rules that fire when no identity is resolved or
|
|
288
|
+
* carried, never a rule that denies WITH an identity already resolved, on the
|
|
289
|
+
* strength of who that identity is. Each of them can only fire on the same
|
|
290
|
+
* Azure DevOps MCP tool-call shape the PASS-side logging covers
|
|
291
|
+
* (`isAdoMcpToolCall`, below), so a role-gate deny is just as much an
|
|
292
|
+
* identity decision as the PASS it would have been without the role
|
|
293
|
+
* mismatch, and its deny log line carries `identity_source` too.
|
|
300
294
|
*/
|
|
301
295
|
const ROLE_GATE_RULE_IDS: ReadonlySet<RuleId> = new Set([
|
|
302
296
|
'adl.workitem-requires-tarun-or-vivek',
|
|
@@ -314,23 +308,23 @@ interface EffectiveIdentity {
|
|
|
314
308
|
}
|
|
315
309
|
|
|
316
310
|
/**
|
|
317
|
-
* Where the effective agent identity for THIS decision came from
|
|
318
|
-
*
|
|
319
|
-
* actually names (M8, STATUS.md 12p) — a valid
|
|
311
|
+
* Where the effective agent identity for THIS decision came from
|
|
312
|
+
* (`identity_source` in the log), AND the agent it actually names: a valid
|
|
320
313
|
* inline `ADL_AGENT_ID_AGENT=` on the command itself (step 1 of the
|
|
321
|
-
*
|
|
322
|
-
* 2-3, `resolveFromEnvOrFile`'s own `source`/`agent`), else
|
|
323
|
-
* A tool-call input carries no command text at all, so it
|
|
324
|
-
*
|
|
325
|
-
*
|
|
314
|
+
* resolution order), else the session env or the machine default-agent file
|
|
315
|
+
* (steps 2-3, `resolveFromEnvOrFile`'s own `source`/`agent`), else
|
|
316
|
+
* `none`/no agent. A tool-call input carries no command text at all, so it
|
|
317
|
+
* can never be `inline`: its identity is the session env or the machine
|
|
318
|
+
* default-agent file. MCP is the primary route to Azure DevOps operations;
|
|
319
|
+
* `ADL_AGENT_ID_AGENT=<agent> adl mcp cli <command>` (which does carry an
|
|
320
|
+
* inline prefix) is the fallback when MCP is not working.
|
|
326
321
|
*
|
|
327
322
|
* The AGENT half matters because it can differ from the session's own
|
|
328
323
|
* `ADL_AGENT_ID_AGENT`: `ADL_AGENT_ID_AGENT=agent-vivek git push …` run in
|
|
329
324
|
* an agent-tarun session is agent-vivek's push, not agent-tarun's — the
|
|
330
|
-
* override, not the session env, is what actually acted, and
|
|
331
|
-
* reads THIS agent for the log's `agent` column
|
|
332
|
-
*
|
|
333
|
-
* column shows the session agent" even on an overridden command).
|
|
325
|
+
* override, not the session env, is what actually acted, and
|
|
326
|
+
* `../hooks/log.ts` reads THIS agent for the log's `agent` column rather
|
|
327
|
+
* than the session env var.
|
|
334
328
|
*/
|
|
335
329
|
function effectiveIdentityFor(input: DecideInput, engineCtx: EngineContext): EffectiveIdentity {
|
|
336
330
|
const resolution = resolveFromEnvOrFile(engineCtx.env)
|
|
@@ -344,10 +338,10 @@ function effectiveIdentityFor(input: DecideInput, engineCtx: EngineContext): Eff
|
|
|
344
338
|
}
|
|
345
339
|
|
|
346
340
|
/**
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
341
|
+
* The resolved FALLBACK identity alone (steps 2-3 of the resolution order:
|
|
342
|
+
* env, else the machine default-agent file) — never the coarse,
|
|
343
|
+
* whole-command "any inline override anywhere on the line"
|
|
344
|
+
* `effectiveIdentityFor` also reports.
|
|
351
345
|
*
|
|
352
346
|
* `adl.git-identity`'s REWRITE stage (`decision.rewrite`) and its own
|
|
353
347
|
* fallback-based DENY reasons (`identity-mismatch`'s hint, `unrewritable-
|
|
@@ -393,11 +387,10 @@ function decideAndRespond(inv: HookInvocation, engineCtx: EngineContext): HookRe
|
|
|
393
387
|
//
|
|
394
388
|
// Every branch below decided an identity (the rewrite ALWAYS comes from
|
|
395
389
|
// adl.git-identity), so every inv.record?.() call here carries
|
|
396
|
-
// identitySource/identityAgent
|
|
397
|
-
//
|
|
398
|
-
//
|
|
399
|
-
//
|
|
400
|
-
// elsewhere on a chained command.
|
|
390
|
+
// identitySource/identityAgent — the FALLBACK identity specifically, not
|
|
391
|
+
// `effectiveIdentityFor`'s coarse whole-command value (see
|
|
392
|
+
// `fallbackIdentity`'s own doc for why a rewrite is always about the
|
|
393
|
+
// fallback, never an inline override elsewhere on a chained command).
|
|
401
394
|
if (!decision.blocked && decision.rewrite) {
|
|
402
395
|
const identity = fallbackIdentity(engineCtx)
|
|
403
396
|
const identitySource = identity.source
|
|
@@ -413,7 +406,7 @@ function decideAndRespond(inv: HookInvocation, engineCtx: EngineContext): HookRe
|
|
|
413
406
|
inv.record?.({ reason: `REWRITE ${decision.rewrite.ruleId}`, ...identityFields(identity) })
|
|
414
407
|
return { stdout: `${JSON.stringify(rendered)}\n`, stderr: '', exitCode: 0 }
|
|
415
408
|
}
|
|
416
|
-
//
|
|
409
|
+
// `native-shell` here is only reached when the host could not
|
|
417
410
|
// render a rewrite for this payload shape (Kimi has none at all;
|
|
418
411
|
// Cursor's beforeShellExecution has no tool_input to replace) — SKIP
|
|
419
412
|
// (allow unchanged) is only safe when `ADL_AGENT_ID_AGENT` is actually
|
|
@@ -434,7 +427,7 @@ function decideAndRespond(inv: HookInvocation, engineCtx: EngineContext): HookRe
|
|
|
434
427
|
return denyHostCannotRewrite(spec, inv.host, message)
|
|
435
428
|
}
|
|
436
429
|
|
|
437
|
-
//
|
|
430
|
+
// Walker-found identity-bearing shapes the rewrite scanner missed: the
|
|
438
431
|
// branch above only runs when `adl.git-identity`'s own narrow, offset-
|
|
439
432
|
// based scanner recognized the command as identity-bearing at all
|
|
440
433
|
// (`decision.rewrite` set) — it does not walk into `if`/`!`/`for..do`/
|
|
@@ -444,11 +437,11 @@ function decideAndRespond(inv: HookInvocation, engineCtx: EngineContext): HookRe
|
|
|
444
437
|
// backstop for a shape THIS scanner misses on a REWRITING host's native
|
|
445
438
|
// shell). But `../rules/shell/invocation.ts`'s walker (reused here via
|
|
446
439
|
// `identityBearingReason`, already proven against every one of those
|
|
447
|
-
// shapes for `adl.
|
|
440
|
+
// shapes for `adl.run-required-for-writes`'s own deny) DOES find them
|
|
448
441
|
// — and once found, there is no rewritten command to offer at all (this
|
|
449
442
|
// scanner never computed one), so the only safe outcomes are: a
|
|
450
443
|
// native-shell tool with an ENV-sourced identity (its child inherits it
|
|
451
|
-
// regardless of any rewrite, exactly like the
|
|
444
|
+
// regardless of any rewrite, exactly like the native-shell SKIP in the rewrite branch above), or an
|
|
452
445
|
// inline override already on the command text (travels with the text
|
|
453
446
|
// itself, no env inheritance needed) — anything else must be denied
|
|
454
447
|
// rather than run with no identity anyone can prove reached the child.
|
|
@@ -476,13 +469,11 @@ function decideAndRespond(inv: HookInvocation, engineCtx: EngineContext): HookRe
|
|
|
476
469
|
// unrelated deny (fs.rm, git.no-verify, …) made no identity decision at
|
|
477
470
|
// all. A PASS made one too when the command is identity-bearing but
|
|
478
471
|
// needed no rewrite because it ALREADY carried a valid inline override
|
|
479
|
-
// (
|
|
480
|
-
//
|
|
481
|
-
//
|
|
482
|
-
//
|
|
483
|
-
//
|
|
484
|
-
// R7 (STATUS.md 12p, re-review 2026-09-28 night): a
|
|
485
|
-
// `adl.git-identity` deny (identity-mismatch/unrewritable-wrapper/
|
|
472
|
+
// (the override's PASS line): `rewriteGitNetworkCommands`'s `unchanged`
|
|
473
|
+
// outcome covers BOTH "not identity-bearing at all" and "fully covered by
|
|
474
|
+
// an inline override already", and only `commandHasValidInlineIdentity`
|
|
475
|
+
// tells those two apart from here.
|
|
476
|
+
// An `adl.git-identity` deny (identity-mismatch/unrewritable-wrapper/
|
|
486
477
|
// network-alias-redefinition/dynamic-agent/unsafe-identity) is ALWAYS
|
|
487
478
|
// about the piece LACKING a valid override — the same fallback-only
|
|
488
479
|
// reasoning `fallbackIdentity`'s doc gives the rewrite branch, and
|
|
@@ -490,15 +481,13 @@ function decideAndRespond(inv: HookInvocation, engineCtx: EngineContext): HookRe
|
|
|
490
481
|
// hint ("your session's own resolved identity is X"). The coarse
|
|
491
482
|
// `effectiveIdentityFor` could otherwise report an unrelated, valid
|
|
492
483
|
// override sitting on a DIFFERENT piece of the same chained command. The
|
|
493
|
-
// other
|
|
494
|
-
//
|
|
495
|
-
//
|
|
496
|
-
// token-minting-role`/`tool.azure-devops` are not piece-correlated
|
|
497
|
-
//
|
|
498
|
-
//
|
|
499
|
-
//
|
|
500
|
-
// can also test it — a role-gate deny of an Azure DevOps MCP call is the
|
|
501
|
-
// same shape as its PASS, just with the wrong identity.
|
|
484
|
+
// other identity rules keep the coarse helper: `adl.run-required-for-writes`
|
|
485
|
+
// only ever denies when `commandHasValidInlineIdentity` is ALSO false (so
|
|
486
|
+
// the two never actually disagree for it), and
|
|
487
|
+
// `adl.token-minting-role`/`tool.azure-devops` are not piece-correlated.
|
|
488
|
+
// `isAdoMcpToolCall` is computed ahead of `denyIdentity` because the
|
|
489
|
+
// DENY-side computation tests it too: a role-gate deny of an Azure DevOps
|
|
490
|
+
// MCP call is the same shape as its PASS, just with the wrong identity.
|
|
502
491
|
const isAdoMcpToolCall = input.kind === 'tool-call' && KNOWN_MCP_TOOL_NAMES.has(mcpToolName(input.tool) ?? '')
|
|
503
492
|
const denyIdentity =
|
|
504
493
|
decision.blocked && (IDENTITY_RULE_IDS.has(decision.ruleId) || (isAdoMcpToolCall && ROLE_GATE_RULE_IDS.has(decision.ruleId)))
|
|
@@ -506,7 +495,7 @@ function decideAndRespond(inv: HookInvocation, engineCtx: EngineContext): HookRe
|
|
|
506
495
|
? fallbackIdentity(engineCtx)
|
|
507
496
|
: effectiveIdentityFor(input, engineCtx)
|
|
508
497
|
: undefined
|
|
509
|
-
//
|
|
498
|
+
// An ALLOWED Azure DevOps MCP
|
|
510
499
|
// tool call — reads included (workitem_list_or_get/pr_list_or_get/
|
|
511
500
|
// build_list_or_get, not only the four writes) — logs `identitySource`/
|
|
512
501
|
// `identityAgent` too, the SAME field names the shell path already uses
|
|
@@ -515,11 +504,11 @@ function decideAndRespond(inv: HookInvocation, engineCtx: EngineContext): HookRe
|
|
|
515
504
|
// tool-call branch already reflects that, unchanged), so this is exactly
|
|
516
505
|
// the session's resolved identity (env, else the machine default-agent
|
|
517
506
|
// file). Every one of these calls ALREADY required a resolvable identity
|
|
518
|
-
// to reach this PASS line at all (`adl.
|
|
507
|
+
// to reach this PASS line at all (`adl.run-required-for-writes` denies
|
|
519
508
|
// otherwise) — this only makes that already-decided identity visible in
|
|
520
509
|
// the log, the same way the shell path's own inline-override PASS line
|
|
521
|
-
// does
|
|
522
|
-
//
|
|
510
|
+
// does. Tarun, 2026-09-29: every Azure DevOps MCP call logs
|
|
511
|
+
// `identity_source`, reads included.
|
|
523
512
|
const passIdentity = !decision.blocked && ((input.kind === 'command' && commandHasValidInlineIdentity(input.command)) || isAdoMcpToolCall) ? effectiveIdentityFor(input, engineCtx) : undefined
|
|
524
513
|
inv.record?.(
|
|
525
514
|
decision.blocked
|
|
@@ -87,14 +87,14 @@ export type DecideInput =
|
|
|
87
87
|
| { readonly kind: 'command'; readonly command: string }
|
|
88
88
|
| { readonly kind: 'tool-call'; readonly tool: string; readonly input: Readonly<Record<string, unknown>> }
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
interface DenyDecision {
|
|
91
91
|
readonly blocked: true
|
|
92
92
|
readonly ruleId: RuleId
|
|
93
93
|
readonly userMessage: string
|
|
94
94
|
readonly agentMessage: string
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
interface AdviceDecision {
|
|
98
98
|
readonly blocked: false
|
|
99
99
|
readonly advice?: { readonly ruleId: RuleId; readonly userMessage: string; readonly agentMessage: string }
|
|
100
100
|
/**
|
|
@@ -205,9 +205,8 @@ function decideCommand(command: string, ctx: EngineContext): Decision {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
// adl.git-identity's REWRITE stage (docs/architecture/cli-design.md §1a;
|
|
208
|
-
//
|
|
209
|
-
// every
|
|
210
|
-
// passed — carry the resolved identity (steps 2-3: session env, else the
|
|
208
|
+
// it covers every identity-bearing command class, not only network git):
|
|
209
|
+
// every rule passed — carry the resolved identity (steps 2-3: session env, else the
|
|
211
210
|
// machine default-agent file) into every identity-bearing invocation in
|
|
212
211
|
// the command. A VALID inline override (step 1) is honoured as-is
|
|
213
212
|
// (`kind: 'unchanged'`, handled inside `rewriteGitNetworkCommands` itself,
|
|
@@ -216,19 +215,16 @@ function decideCommand(command: string, ctx: EngineContext): Decision {
|
|
|
216
215
|
// rule can be disabled per-repo; an unsafe identity is never the rule's to
|
|
217
216
|
// see).
|
|
218
217
|
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
//
|
|
222
|
-
//
|
|
223
|
-
// command earlier in the rule pass — a separate classification (the
|
|
218
|
+
// `needs-identity` (an identity-bearing command with no inline override
|
|
219
|
+
// and no resolvable fallback) is denied HERE, directly, rather than left
|
|
220
|
+
// to `adl.run-required-for-writes` having already denied the SAME command
|
|
221
|
+
// earlier in the rule pass: that rule is a separate classification (the
|
|
224
222
|
// shared shell/invocation.ts walker) that can be disabled per repo
|
|
225
|
-
// (`[rules."adl.
|
|
226
|
-
//
|
|
227
|
-
//
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
// L4 (STATUS.md 12p): resolve the fallback
|
|
231
|
-
// identity — which can read the REAL machine default-agent file
|
|
223
|
+
// (`[rules."adl.run-required-for-writes"] enabled = false`) or simply not
|
|
224
|
+
// recognize a shape this scanner does, and nothing else here would stand
|
|
225
|
+
// between an unidentified network git command and a plain allow.
|
|
226
|
+
//
|
|
227
|
+
// The fallback identity — which can read the REAL machine default-agent file
|
|
232
228
|
// (`resolveFromEnvOrFile`) — ONLY when the command actually has an
|
|
233
229
|
// identity-bearing piece that would use it. A probe scan with
|
|
234
230
|
// `fallback: null` is fallback-INDEPENDENT for every outcome except
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* branch on `ADL_AGENT_ID_AGENT` at all: the matrix's own hook-action column
|
|
6
6
|
* shows ❌ for both `agent-tarun`/`agent-vivek` and `agent-reviewer`, so there
|
|
7
7
|
* is no identity this tool is allowed for. With no identity at all,
|
|
8
|
-
* `adl.
|
|
8
|
+
* `adl.run-required-for-writes` (registered ahead of this rule) reports
|
|
9
9
|
* first with its own, more specific "no session" message; this rule is what
|
|
10
10
|
* fires once an identity IS present, which is the case that rule leaves
|
|
11
11
|
* alone.
|
|
@@ -25,10 +25,10 @@ export const adlBuildRunDenied: RuleSpec = {
|
|
|
25
25
|
category: 'tool-call',
|
|
26
26
|
severity: 'deny',
|
|
27
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
|
|
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
29
|
params: noParams,
|
|
30
30
|
match(inv: Invocation): Finding | null {
|
|
31
|
-
//
|
|
31
|
+
// Also catch `adl mcp cli build-run` — same tool, same deny.
|
|
32
32
|
const call = toolCallFor(inv)
|
|
33
33
|
if (call === null) return null
|
|
34
34
|
if (mcpToolName(call.tool) !== 'build_run') return null
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `adl.git-credential-bypass` —
|
|
2
|
+
* `adl.git-credential-bypass` — deny, for agents, every
|
|
3
3
|
* shell shape that reaches Azure DevOps credentials or bypasses
|
|
4
4
|
* `bin/git-ado`'s routing entirely, without touching any of the specific
|
|
5
|
-
* verbs `adl.
|
|
5
|
+
* verbs `adl.run-required-for-writes`/`adl.git-identity` already police:
|
|
6
6
|
*
|
|
7
7
|
* - An absolute git binary other than the managed front controller
|
|
8
8
|
* `/usr/local/bin/git` (that IS the path `bin/git-ado` installs itself
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* untouched.
|
|
14
14
|
* - `git remote update` — fetches every configured remote, the same
|
|
15
15
|
* network operation as `git fetch`, but not a verb
|
|
16
|
-
* `adl.
|
|
16
|
+
* `adl.run-required-for-writes`'s `NETWORK_GIT_VERBS` recognizes.
|
|
17
17
|
* - `git submodule update/sync/foreach` — `update`/`sync` can fetch a
|
|
18
18
|
* submodule's own remote; `foreach` runs an arbitrary shell command once
|
|
19
19
|
* per submodule, unauditable by this hook.
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* credential directly, sidestepping the front controller entirely.
|
|
22
22
|
*
|
|
23
23
|
* `security find-generic-password`/`find-internet-password` naming Azure
|
|
24
|
-
* DevOps (
|
|
24
|
+
* DevOps (a macOS Keychain read, not a git operation at
|
|
25
25
|
* all) is `adl.security-keychain-ado` below, in the same file since it
|
|
26
26
|
* shares `namesAzureDevops`, but registered as its own `category: 'tool'`
|
|
27
27
|
* rule: `tests/unit/rules-git-deny-guidance.test.ts` requires every
|
|
@@ -33,14 +33,13 @@
|
|
|
33
33
|
* an intentional, heavily-tested feature — `tests/unit/rules-git-worktree.
|
|
34
34
|
* test.ts`'s dozens of `git -c alias.wt=worktree`-shaped corpus entries SEE
|
|
35
35
|
* THROUGH a non-network inline alias on purpose). Two narrower, resolved
|
|
36
|
-
* pieces of that space ARE covered
|
|
37
|
-
* "BLOCKED" note (STATUS.md 12p):
|
|
36
|
+
* pieces of that space ARE covered:
|
|
38
37
|
* - a SELF-referential inline `-c alias.<verb>=<value>`/`--config-env`
|
|
39
38
|
* naming the LITERAL subcommand this invocation runs, where `<value>`'s
|
|
40
39
|
* own verb is network/credential — `adl.git-identity`'s own
|
|
41
40
|
* `network-alias-redefinition` reason (`../shell/git-identity.ts`), not
|
|
42
41
|
* this rule.
|
|
43
|
-
* -
|
|
42
|
+
* - a REPO-CONFIGURED alias (`.git/config`,
|
|
44
43
|
* invisible to the walker's own inline/env-var-only resolution) whose
|
|
45
44
|
* value's verb is network/credential — `repo-alias-network-verb` below,
|
|
46
45
|
* resolved via the injectable `ctx.index.configuredAlias` port
|
|
@@ -48,7 +47,7 @@
|
|
|
48
47
|
* stay hermetic. Still narrower than a blanket deny: a non-network
|
|
49
48
|
* repo-configured alias (`git st` → `alias.st=status`) is untouched.
|
|
50
49
|
*
|
|
51
|
-
*
|
|
50
|
+
* Three more front-controller bypasses are denied here, all sharing the
|
|
52
51
|
* same reasoning: `/usr/local/bin/git` (`bin/git-ado`) routes on the
|
|
53
52
|
* LITERAL verb/binary an agent typed — it does not resolve `PATH`
|
|
54
53
|
* overrides, `command -p`'s own default `$PATH`, or `xcrun`'s tool
|
|
@@ -130,7 +129,7 @@ const CREDENTIAL_HELPER_BINARY_PREFIX = 'credential-'
|
|
|
130
129
|
* that holds a credential for a short-lived window and exits — `git
|
|
131
130
|
* credential-cache exit` merely stops it); it never reads or writes a
|
|
132
131
|
* platform secret store the way `credential-osxkeychain`/`credential-
|
|
133
|
-
* manager`/… do, and this exact allow case
|
|
132
|
+
* manager`/… do, and this exact allow case is part of this rule's own corpus.
|
|
134
133
|
* Excluded from the deny by name rather than widened into a blanket
|
|
135
134
|
* "every credential-* helper", to avoid regressing that settled behaviour.
|
|
136
135
|
*/
|
|
@@ -143,9 +142,8 @@ function isDeniedCredentialHelper(subcommandOrName: string): boolean {
|
|
|
143
142
|
|
|
144
143
|
/**
|
|
145
144
|
* Git's own real subcommand vocabulary (porcelain and common plumbing),
|
|
146
|
-
* lower-cased —
|
|
147
|
-
*
|
|
148
|
-
* only, per this finding's own text ("resolve unknown git verbs"), so an
|
|
145
|
+
* lower-cased — gates the repo-configured-alias lookup
|
|
146
|
+
* (`ctx.index.configuredAlias`) to an UNKNOWN verb only, so an
|
|
149
147
|
* ordinary `git status`/`git log`/… never pays for a `git config --get`
|
|
150
148
|
* shell-out. Not exhaustive — an obscure real git verb missing here only
|
|
151
149
|
* costs one harmless extra (correctness-preserving) lookup that resolves to
|
|
@@ -163,8 +161,8 @@ const KNOWN_GIT_VERBS: ReadonlySet<string> = new Set([
|
|
|
163
161
|
/**
|
|
164
162
|
* `PATH=`/`export PATH=` anywhere in `command`, co-occurring with a `git`
|
|
165
163
|
* invocation this rule is already deciding — coarse (whole-command, not
|
|
166
|
-
* piece-scoped) by design, matching
|
|
167
|
-
* package: a PATH override ahead of `git` ANYWHERE on the line is suspicious
|
|
164
|
+
* piece-scoped) by design, matching the other coarse textual checks in this
|
|
165
|
+
* package (see `containsIdentityBearingToken` in `git-helpers.ts`): a PATH override ahead of `git` ANYWHERE on the line is suspicious
|
|
168
166
|
* enough on its own that over-denial costs nothing legitimate.
|
|
169
167
|
*/
|
|
170
168
|
function pathOverridePresent(command: string): boolean {
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
* `adl run -- codex` session ran `git push -u origin feat/adl-m3-finish`
|
|
9
9
|
* through the lean-ctx MCP tool `mcp__lean_ctx__ctx_shell`; Codex gives
|
|
10
10
|
* `ADL_AGENT_ID_AGENT` only to its own shell tool, so the push executed with
|
|
11
|
-
* no identity and `bin/git-ado`
|
|
12
|
-
*
|
|
11
|
+
* no identity and `bin/git-ado` (which then passed an unset identity through
|
|
12
|
+
* to the human's credential helper; it now fails closed unless a real TTY and
|
|
13
|
+
* `ADL_HUMAN_AZDO=1`) pushed with Tarun's own credential. The hook knew the session
|
|
13
14
|
* identity — it is in the hook's own environment — but passed the command
|
|
14
15
|
* through unchanged. This module is the fix: the command is REWRITTEN to
|
|
15
16
|
* carry the identity (`git push …` → `ADL_AGENT_ID_AGENT=agent-tarun git
|
|
@@ -25,9 +26,9 @@
|
|
|
25
26
|
* into the human credential), or a `sudo`/`doas` wrapper, which strips
|
|
26
27
|
* the environment the identity travels in. Both are denies rather than
|
|
27
28
|
* rewrites: an inexact rewrite is a deny (cli-design.md §1a's rule). With
|
|
28
|
-
* no
|
|
29
|
-
* `adl.
|
|
30
|
-
*
|
|
29
|
+
* no agent identity at all this rule stays silent —
|
|
30
|
+
* `adl.run-required-for-writes` denies the write with the
|
|
31
|
+
* inline-prefix hint first.
|
|
31
32
|
*
|
|
32
33
|
* 2. The REWRITE stage, computed in `../engine.ts`'s `decideCommand` after
|
|
33
34
|
* every rule passed: `../shell/git-identity.ts` rewrites the command
|
|
@@ -67,7 +68,7 @@ import { NETWORK_GIT_VERBS, scanGitIdentityConflicts, type GitIdentityDenyReason
|
|
|
67
68
|
|
|
68
69
|
export const RULE_ID = 'adl.git-identity'
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
type GitIdentityRuleReason = Extract<
|
|
71
72
|
GitIdentityDenyReason,
|
|
72
73
|
'identity-mismatch' | 'unrewritable-wrapper' | 'network-alias-redefinition' | 'dynamic-agent'
|
|
73
74
|
>
|
|
@@ -75,14 +76,13 @@ export type GitIdentityRuleReason = Extract<
|
|
|
75
76
|
/** Messages for the rule's two deny reasons and for the engine rewrite-stage nets (unsafe identity). */
|
|
76
77
|
export function gitIdentityDenyMessage(reason: GitIdentityDenyReason, ctx: MessageContext, identity: string | undefined): RuleMessage {
|
|
77
78
|
if (reason === 'identity-mismatch') {
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
// true behavior and was actively misleading about what to actually fix.
|
|
79
|
+
// Under the one-agent-identity standard (Tarun, 2026-09-28) this reason
|
|
80
|
+
// means ONLY "empty or not a recognized agent": a valid inline override
|
|
81
|
+
// that merely NAMES A DIFFERENT agent than the session's own is not a
|
|
82
|
+
// conflict at all (see applyIdentityOutcome's doc in
|
|
83
|
+
// ../shell/git-identity.ts) — it is the override, and it wins. The
|
|
84
|
+
// message therefore says what to fix (an empty or unrecognized value),
|
|
85
|
+
// not that another agent "conflicts with this session".
|
|
86
86
|
const user = 'the inline ADL_AGENT_ID_AGENT override on this command is empty or not a recognized agent'
|
|
87
87
|
const hint = identity !== undefined ? ` Your session's own resolved identity is ${identity}; remove the override to use it,` : ' Remove the override,'
|
|
88
88
|
return {
|
|
@@ -124,22 +124,22 @@ export function gitIdentityDenyMessage(reason: GitIdentityDenyReason, ctx: Messa
|
|
|
124
124
|
`directly instead of aliasing it inline. Blocked: ${ctx.snippet}`,
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
|
-
const user =
|
|
127
|
+
const user = 'the agent identity is not a safe shell word'
|
|
128
128
|
return {
|
|
129
129
|
user,
|
|
130
130
|
agent:
|
|
131
|
-
`DENIED ${user}:
|
|
132
|
-
|
|
131
|
+
`DENIED ${user}: the ${ADL_AGENT_ID_ENV_VAR} value in this environment contains characters outside [A-Za-z0-9_-], ` +
|
|
132
|
+
`so the hook cannot place it on a command line. Prefix the command with ${ADL_AGENT_ID_ENV_VAR}=<agent-tarun|agent-vivek|agent-reviewer> instead. ` +
|
|
133
133
|
`Blocked: ${ctx.snippet}`,
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
138
|
+
* The deny rendered by `../engine.ts`'s rewrite stage itself for a
|
|
139
|
+
* `needs-identity` outcome —
|
|
140
140
|
* an identity-bearing command with no valid inline override and no
|
|
141
141
|
* resolvable fallback (steps 2-3 of the standard). This is defense in
|
|
142
|
-
* depth: `adl.
|
|
142
|
+
* depth: `adl.run-required-for-writes` is expected to have already
|
|
143
143
|
* denied the same command with this same standard message earlier in the
|
|
144
144
|
* rule pass, but it is a SEPARATE classification that can be disabled per
|
|
145
145
|
* repo or simply miss a shape this scanner recognizes — see engine.ts's own
|
|
@@ -159,14 +159,14 @@ export function gitIdentityNeedsIdentityMessage(ctx: MessageContext): RuleMessag
|
|
|
159
159
|
* tool input, and the identity is not otherwise present in THIS invocation's
|
|
160
160
|
* own environment: an MCP-class tool (Kimi has no `renderRewrite` at all),
|
|
161
161
|
* or a native-shell tool whose identity resolved from the machine
|
|
162
|
-
* default-agent file rather than the session env (
|
|
162
|
+
* default-agent file rather than the session env (the hook process
|
|
163
163
|
* read that file itself; a child process this shell tool spawns never sees
|
|
164
164
|
* `ADL_AGENT_ID_AGENT`, so it would reach Azure DevOps as the human, which
|
|
165
165
|
* is the exact incident this module exists to close). `agent` is the
|
|
166
166
|
* resolved fallback identity (steps 2-3 of the standard) when one resolved
|
|
167
167
|
* — always the case at both call sites, since a `rewrite` decision only
|
|
168
168
|
* exists once a fallback resolved — so the message can name the EXACT
|
|
169
|
-
* prefix to add
|
|
169
|
+
* prefix to add, not just point at "an agent" in the abstract.
|
|
170
170
|
*/
|
|
171
171
|
export function hostCannotRewriteMessage(host: string, ctx: MessageContext, agent: string | undefined): RuleMessage {
|
|
172
172
|
const prefix = `${ADL_AGENT_ID_ENV_VAR}=${agent ?? '<agent>'}`
|
|
@@ -174,7 +174,7 @@ export function hostCannotRewriteMessage(host: string, ctx: MessageContext, agen
|
|
|
174
174
|
// OpenCode's fail-closed path) writes `message.user`, not `message.agent`,
|
|
175
175
|
// to stderr (see ../../pre-tool-use/handler.ts's `denyHostCannotRewrite`),
|
|
176
176
|
// and that stream is what the agent itself reads on those hosts.
|
|
177
|
-
const user = `this agent surface (${host}) cannot carry the
|
|
177
|
+
const user = `this agent surface (${host}) cannot carry the agent identity into this command; prefix it with \`${prefix}\` and retry`
|
|
178
178
|
return {
|
|
179
179
|
user,
|
|
180
180
|
agent:
|
|
@@ -193,16 +193,16 @@ export const adlGitIdentity: RuleSpec = {
|
|
|
193
193
|
summary: 'Deny an identity-bearing command whose inline ADL_AGENT_ID_AGENT is invalid/empty, or that runs through sudo/doas.',
|
|
194
194
|
params: noParams,
|
|
195
195
|
match(inv, ctx): Finding | null {
|
|
196
|
-
//
|
|
197
|
-
//
|
|
196
|
+
// Every identity-bearing command class, not only network git
|
|
197
|
+
// (widened 2026-09-28 by the one-agent-identity standard) —
|
|
198
198
|
// `adl mcp cli`/`adl repo doctor`/`adl repo controls azdo-push`/`adl id
|
|
199
199
|
// token`, `adl-agent-id exec`, and curl/wget/httpie/xh to
|
|
200
200
|
// dev.azure.com/*.visualstudio.com. This rule no longer requires a
|
|
201
201
|
// resolved fallback identity to run (`identity === null` used to skip
|
|
202
|
-
// straight to
|
|
202
|
+
// straight to run-required) — an invalid/empty INLINE override is a
|
|
203
203
|
// real problem independent of whether a fallback exists; the two rules
|
|
204
204
|
// still cannot both win for the same invocation because the registry
|
|
205
|
-
// orders
|
|
205
|
+
// orders run-required first (`../registry.ts`) and the engine's
|
|
206
206
|
// `firstFinding` stops at the first rule that reports anything at all.
|
|
207
207
|
let isIdentityBearing = false
|
|
208
208
|
if (inv.kind === 'git') {
|
|
@@ -213,7 +213,7 @@ export const adlGitIdentity: RuleSpec = {
|
|
|
213
213
|
if (ADL_BINARY_NAMES.has(inv.name)) {
|
|
214
214
|
isIdentityBearing = !dynamic && matchesIdentityShape(values, ADL_IDENTITY_COMMAND_SHAPES)
|
|
215
215
|
} else if (ADL_AGENT_ID_BINARY_NAMES.has(inv.name)) {
|
|
216
|
-
//
|
|
216
|
+
// Leading dash-prefixed
|
|
217
217
|
// global flags (`adl-agent-id --verbose exec …`) are skipped before
|
|
218
218
|
// matching the `['exec']` shape — see skipLeadingDashFlags's doc.
|
|
219
219
|
isIdentityBearing = !dynamic && matchesIdentityShape(skipLeadingDashFlags(values), ADL_AGENT_ID_COMMAND_SHAPES)
|