@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
|
@@ -1,40 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `git.worktree` — worktree policy (
|
|
2
|
+
* `git.worktree` — worktree policy (layers L2/L3 of
|
|
3
3
|
* docs/operations/worktree-guard.md; docs/operations/agent-permissions.md "route, don't block").
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* blanket deny-all is replaced by a ROUTE-when-possible, cap-aware policy:
|
|
5
|
+
* Decided 2026-09-27 (Tarun): a ROUTE-when-possible, cap-aware policy, not a
|
|
6
|
+
* blanket deny of every worktree action:
|
|
8
7
|
*
|
|
9
8
|
* - `git worktree list|remove|prune|repair` — ALLOW outright (`match`
|
|
10
9
|
* returns `null`). These are needed to RECONCILE existing worktrees
|
|
11
10
|
* (docs/operations/worktree-guard.md L6, and this cap's own remove hint), and none
|
|
12
11
|
* of them creates a new checkout, so none of them can push a repository
|
|
13
12
|
* over the 3-checkout cap.
|
|
14
|
-
* - `git worktree add` —
|
|
15
|
-
* silent
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* `../
|
|
21
|
-
* `
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* exactly one subsystem that does this at all: `../../hooks/lean-ctx/
|
|
26
|
-
* scope-rewrite.ts`, a DIFFERENT hook (`lean-ctx hook rewrite`) with its
|
|
27
|
-
* own envelope, unrelated to `adl hook`'s `pre-tool-use` engine this
|
|
28
|
-
* rule runs in. Building real rewrite support means extending
|
|
29
|
-
* `Severity`/`Finding`/`Decision`/`HostSpec` and all four host adapters —
|
|
30
|
-
* files this rule's write scope does not include (git-worktree.ts + its
|
|
31
|
-
* tests/fixtures/README only). Reported as a blocker rather than faked;
|
|
32
|
-
* see this task's final report for the flag. Until that engine work
|
|
33
|
-
* lands, `add` gets the fallback docs/operations/agent-permissions.md's own
|
|
34
|
-
* Principles section already names for this exact situation: "An
|
|
35
|
-
* inexact rewrite is a deny with the `adl` command to use. The hook
|
|
36
|
-
* never guesses." — DENY, with the precise `adl worktree add` command to
|
|
37
|
-
* run instead.
|
|
13
|
+
* - `git worktree add` — DENIED, with the precise `adl worktree add` command
|
|
14
|
+
* to run instead. A silent rewrite to that command is not available to a
|
|
15
|
+
* rule: `Severity` (`../spec.ts`) is only `'deny' | 'advise'` and
|
|
16
|
+
* `Finding` carries no replacement-command field. The one rewrite the
|
|
17
|
+
* engine does render (`Decision.rewrite` in `../engine.ts`, carrying the
|
|
18
|
+
* session identity into network git commands) is computed by
|
|
19
|
+
* `../shell/git-identity.ts`, not by a rule, and `../../hooks/lean-ctx/
|
|
20
|
+
* scope-rewrite.ts` is a different hook (`lean-ctx hook rewrite`) with its
|
|
21
|
+
* own envelope. So `add` gets the fallback docs/operations/agent-permissions.md's
|
|
22
|
+
* Principles section names for an inexact rewrite: "An inexact rewrite is
|
|
23
|
+
* a deny with the `adl` command to use. The hook never guesses."
|
|
38
24
|
* - `git worktree move|lock|unlock` — still DENIED: each mutates a
|
|
39
25
|
* worktree's registration or lock state without checking the cap or
|
|
40
26
|
* reconciling anything, and none is needed to reconcile toward the cap
|
|
@@ -49,12 +49,12 @@ export function toolNameEndingWithKnownSuffix(tool: string, knownSuffixes: Reado
|
|
|
49
49
|
* exactly on `<tool>`.
|
|
50
50
|
*
|
|
51
51
|
* Shared by every rule that gates an Azure DevOps MCP tool by name
|
|
52
|
-
* (adl-
|
|
52
|
+
* (adl-run-required.ts, adl-pr-role.ts, adl-pr-complete-pending.ts,
|
|
53
53
|
* adl-workitem-role.ts, adl-build-run-denied.ts) so the parsing cannot drift
|
|
54
54
|
* between them.
|
|
55
55
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
56
|
+
* Prefix-less fallback (added 2026-09-28 with the one-agent-identity
|
|
57
|
+
* standard): OpenCode's and Kimi's own MCP tool-call naming has never actually been
|
|
58
58
|
* observed in production (`.adl/logs/hooks.log` shows only `mcp__`-prefixed
|
|
59
59
|
* calls, from Claude/Codex/Cursor) — they MAY call an azdo tool with no
|
|
60
60
|
* `mcp__` prefix at all, spelled `<server>_<tool>` / `<server>.<tool>` /
|
|
@@ -39,7 +39,7 @@ export function detailString(finding: Finding, key: string): string {
|
|
|
39
39
|
* that there is no sanctioned workaround, name the recovery commands that
|
|
40
40
|
* ARE allowed, and otherwise send the agent back to the user.
|
|
41
41
|
*/
|
|
42
|
-
|
|
42
|
+
const GIT_NO_WORKAROUND_GUIDANCE =
|
|
43
43
|
'Do NOT work around this block: no git plumbing (update-ref, symbolic-ref, read-tree, update-index, ' +
|
|
44
44
|
'reflog, replace, prune) and no editing, moving, copying over, or deleting anything under .git. If you ' +
|
|
45
45
|
'are stuck in an in-progress rebase/merge/cherry-pick/revert/am and a recovery command is what is ' +
|
|
@@ -6,14 +6,13 @@
|
|
|
6
6
|
* classification time (shell/invocation.ts's `walkToolCommand`); this rule
|
|
7
7
|
* only ever sees the denied subset.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
* 5): `az account get-access-token` and `az rest` targeting Azure DevOps are
|
|
9
|
+
* `az account get-access-token` and `az rest` targeting Azure DevOps are
|
|
11
10
|
* NOT in `azureDevopsSubcommands` (`../shell/invocation.ts`), so they fall
|
|
12
11
|
* through to the generic `'command'` kind (name `az`) rather than the
|
|
13
|
-
* `'azure-devops'` kind
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* `'azure-devops'` kind — without a dedicated check an agent could mint a
|
|
13
|
+
* bearer token from the HUMAN's own `az login` session and call the Azure
|
|
14
|
+
* DevOps REST API directly, entirely outside the agent-identity standard.
|
|
15
|
+
* Both are denied here too, steering at the same MCP server /
|
|
17
16
|
* `adl id token` path. `az account show` and every other `az account`
|
|
18
17
|
* subcommand, and `az rest` against a non-Azure-DevOps host, are untouched.
|
|
19
18
|
*/
|
|
@@ -32,8 +31,8 @@ const AZ_NAMES: ReadonlySet<string> = new Set(['az', 'az.exe'])
|
|
|
32
31
|
/**
|
|
33
32
|
* Interpreter-ADO risk (independent review, 2026-09-29): python
|
|
34
33
|
* requests/urllib, node fetch, ruby net/http, and perl LWP one-liners hitting
|
|
35
|
-
* Azure DevOps directly are the SAME structural problem
|
|
36
|
-
*
|
|
34
|
+
* Azure DevOps directly are the SAME structural problem as curl/wget/httpie/xh
|
|
35
|
+
* (denied outright in `match` below) — none of them can carry the resolved agent identity,
|
|
37
36
|
* and any one can read `~/.netrc` or an ambient token exactly like curl's
|
|
38
37
|
* `-n`/`--netrc*` does. `python`/`python3`/`ruby`/`perl`/`node`/`nodejs` (and
|
|
39
38
|
* the Windows `.exe` spellings) are `inv.kind === 'command'` (unclassified by
|
|
@@ -41,18 +40,17 @@ const AZ_NAMES: ReadonlySet<string> = new Set(['az', 'az.exe'])
|
|
|
41
40
|
* already sees them, it just never inspected their text for an Azure DevOps
|
|
42
41
|
* host.
|
|
43
42
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* wrongly denied `python3 -m pip install -i https://pkgs.dev.azure.com/...`
|
|
43
|
+
* The check deliberately does NOT scan `ctx.command` (the whole raw command line) for the ADO
|
|
44
|
+
* host substring: matching it in ARGV too, not only inline code, would
|
|
45
|
+
* wrongly deny `python3 -m pip install -i https://pkgs.dev.azure.com/...`
|
|
48
46
|
* (an Azure Artifacts feed) and `node scripts/x.js --remote
|
|
49
47
|
* https://dev.azure.com/...` (a flag on a script FILE run, not inline
|
|
50
|
-
* code at all).
|
|
48
|
+
* code at all). It reads `interpreterInlineCode`'s own `-c`/`-e`/
|
|
51
49
|
* `--eval[=]` argument value ONLY — coarse within that scope (a literal
|
|
52
50
|
* `dev.azure.com`/`visualstudio.com` substring in the INLINE code is
|
|
53
51
|
* enough, no attempt to verify a real HTTP call is actually made, matching
|
|
54
|
-
*
|
|
55
|
-
* about WHERE it looks. `pkgs.dev.azure.com` (Azure Artifacts) stays IN
|
|
52
|
+
* the HTTP-client deny's "curl to the URL is enough" coarseness), but not
|
|
53
|
+
* coarse about WHERE it looks. `pkgs.dev.azure.com` (Azure Artifacts) stays IN
|
|
56
54
|
* SCOPE when it DOES appear in inline code — `isAdoUrl`'s existing
|
|
57
55
|
* `dev.azure.com` substring check already matches it.
|
|
58
56
|
*/
|
|
@@ -60,7 +58,7 @@ const AZ_NAMES: ReadonlySet<string> = new Set(['az', 'az.exe'])
|
|
|
60
58
|
* The `-c`/`-e`/`--eval[=]` argument value for an interpreter invocation, or
|
|
61
59
|
* null when the piece runs a script FILE or a module (`-m pip ...`) — argv
|
|
62
60
|
* a script or module sees (a pip index URL, a `--remote` flag) is NOT this
|
|
63
|
-
* rule's to inspect
|
|
61
|
+
* rule's to inspect: only the
|
|
64
62
|
* interpreter's own INLINE code can reach a host directly through that
|
|
65
63
|
* interpreter's HTTP client; a script file's own argv is opaque to this
|
|
66
64
|
* hook and denying on a mere URL-shaped argument would deny an ordinary
|
|
@@ -73,7 +71,7 @@ const AZ_NAMES: ReadonlySet<string> = new Set(['az', 'az.exe'])
|
|
|
73
71
|
*/
|
|
74
72
|
/**
|
|
75
73
|
* `name`-specific inline-code shapes beyond the common `-c`/`-e`/`--eval[=]`
|
|
76
|
-
*
|
|
74
|
+
* php's own inline-eval flag is `-r`
|
|
77
75
|
* (not `-e`), and Deno's is a POSITIONAL argument after its `eval`
|
|
78
76
|
* subcommand, no flag at all — neither fits the shared scan below.
|
|
79
77
|
*/
|
|
@@ -113,7 +111,6 @@ const INTERPRETER_NAMES: ReadonlySet<string> = new Set([
|
|
|
113
111
|
'node.exe',
|
|
114
112
|
'nodejs',
|
|
115
113
|
'nodejs.exe',
|
|
116
|
-
// P2 (independent review, 2026-09-29).
|
|
117
114
|
'bun',
|
|
118
115
|
'bun.exe',
|
|
119
116
|
'deno',
|
|
@@ -129,13 +126,12 @@ export const toolAzureDevops: RuleSpec = {
|
|
|
129
126
|
severity: 'deny',
|
|
130
127
|
enabledByDefault: true,
|
|
131
128
|
summary:
|
|
132
|
-
'Deny direct az devops/repos/pipelines/boards/artifacts, az account get-access-token, az rest to Azure DevOps, and curl/wget/httpie/xh to Azure DevOps under every method (
|
|
129
|
+
'Deny direct az devops/repos/pipelines/boards/artifacts, az account get-access-token, az rest to Azure DevOps, and curl/wget/httpie/xh to Azure DevOps under every method (reads included — curl cannot carry the agent identity); steer at adl mcp serve/cli.',
|
|
133
130
|
params: noParams,
|
|
134
131
|
match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
|
|
135
132
|
if (inv.kind === 'command' && INTERPRETER_NAMES.has(inv.name)) {
|
|
136
133
|
const code = interpreterInlineCode(inv.name, inv.args)
|
|
137
|
-
//
|
|
138
|
-
// (`python3 - <<'EOF' ... EOF`) have no -c/-e/--eval argument at all
|
|
134
|
+
// Heredoc-fed interpreters (`python3 - <<'EOF' ... EOF`) have no -c/-e/--eval argument at all
|
|
139
135
|
// — the real code is the heredoc BODY, only visible in `ctx.command`.
|
|
140
136
|
const candidates = code !== null ? [code] : heredocBodies(ctx.command ?? '')
|
|
141
137
|
if (candidates.some((candidate) => isAdoUrl(candidate))) {
|
|
@@ -146,7 +142,7 @@ export const toolAzureDevops: RuleSpec = {
|
|
|
146
142
|
return { ruleId: 'tool.azure-devops', severity: 'deny', detail: { reason: 'az-devops-family' } }
|
|
147
143
|
}
|
|
148
144
|
if (inv.kind === 'command' && AZ_NAMES.has(inv.name)) {
|
|
149
|
-
//
|
|
145
|
+
// A global flag
|
|
150
146
|
// (`az --output json account get-access-token`) must not hide the
|
|
151
147
|
// real subcommand from this check either — same skip
|
|
152
148
|
// shell/invocation.ts's own `azureDevopsSubcommands` classification
|
|
@@ -160,23 +156,18 @@ export const toolAzureDevops: RuleSpec = {
|
|
|
160
156
|
return { ruleId: 'tool.azure-devops', severity: 'deny', detail: { reason: 'az-rest-ado' } }
|
|
161
157
|
}
|
|
162
158
|
}
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
//
|
|
166
|
-
//
|
|
167
|
-
// the resolved agent identity, and curl/wget/httpie/xh categorically
|
|
159
|
+
// Every curl/wget/httpie/xh call to Azure DevOps is denied, every method
|
|
160
|
+
// included (docs/operations/agent-permissions.md row 13). Tarun's
|
|
161
|
+
// standard ("reads included") requires every Azure DevOps access to go
|
|
162
|
+
// through the resolved agent identity, and these clients categorically
|
|
168
163
|
// cannot carry one — the request authenticates with whatever the HUMAN
|
|
169
164
|
// environment already supplies (`-n`/`--netrc*` reads `~/.netrc`, `-u`
|
|
170
165
|
// is a literal credential on the command line, `-H Authorization`/`-K
|
|
171
166
|
// <config-file>` read a header or config a human set up, a cached
|
|
172
|
-
// credential helper, …), regardless of `ADL_AGENT_ID_AGENT`.
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
// cannot prove WHICH identity performed it at all, so it is denied
|
|
177
|
-
// outright, identity or not, exactly like a write): every
|
|
178
|
-
// curl/wget/httpie/xh call to Azure DevOps is denied now, every method
|
|
179
|
-
// included. `adl.session-required-for-writes` already denies every
|
|
167
|
+
// credential helper, …), regardless of `ADL_AGENT_ID_AGENT`. The point
|
|
168
|
+
// is structural, not that a read is dangerous: the client cannot prove
|
|
169
|
+
// WHICH identity performed the call, so a GET is denied outright,
|
|
170
|
+
// identity or not, exactly like a write. `adl.run-required-for-writes` already denies every
|
|
180
171
|
// method with NO identity at all; this is the unconditional net once an
|
|
181
172
|
// identity IS present — a raw HTTP call cannot be rewritten to an exact
|
|
182
173
|
// `adl` equivalent, so it is denied rather than routed, same as az CLI
|
|
@@ -198,11 +189,11 @@ export const toolAzureDevops: RuleSpec = {
|
|
|
198
189
|
: reason === 'az-rest-ado'
|
|
199
190
|
? 'Blocked `az rest` against Azure DevOps: it authenticates as the human `az` login, not the resolved agent identity.'
|
|
200
191
|
: reason === 'http-client-ado'
|
|
201
|
-
? //
|
|
192
|
+
? // Names the actual method and binary, and steers at
|
|
202
193
|
// the real, current entry points — `adl mcp serve` (the MCP
|
|
203
194
|
// server folded into the `adl` binary) and its `adl mcp cli`
|
|
204
|
-
// direct-CLI form — never a path that no longer exists.
|
|
205
|
-
//
|
|
195
|
+
// direct-CLI form — never a path that no longer exists.
|
|
196
|
+
// Every method, reads included — curl/wget/httpie/xh cannot
|
|
206
197
|
// carry the agent identity at all (any auth it uses, `-n`/
|
|
207
198
|
// `--netrc*`, `-u`, `-H Authorization`, `-K`, is the human's).
|
|
208
199
|
`Blocked \`${detailString(finding, 'name')} ${detailString(finding, 'method')}\` to Azure DevOps: a raw HTTP call cannot be translated exactly, and it authenticates outside the agent-identity standard entirely (this client cannot carry the resolved agent identity for any method, reads included).`
|
|
@@ -235,23 +226,22 @@ export const toolAzureDevops: RuleSpec = {
|
|
|
235
226
|
'az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798',
|
|
236
227
|
'az rest --method get --url https://dev.azure.com/org/_apis/projects',
|
|
237
228
|
'az rest --url https://vssps.dev.azure.com/org/_apis/profile/profiles/me',
|
|
238
|
-
//
|
|
229
|
+
// A real az CLI global
|
|
239
230
|
// flag before the subcommand group must not hide it from this rule.
|
|
240
231
|
'az --output json devops project list',
|
|
241
232
|
'az -o table repos pr list --status active',
|
|
242
233
|
'az --verbose account get-access-token',
|
|
243
234
|
'az --output json rest --method get --url https://dev.azure.com/org/_apis/projects',
|
|
244
|
-
//
|
|
245
|
-
// row 13
|
|
235
|
+
// docs/operations/agent-permissions.md
|
|
236
|
+
// row 13: curl/wget/httpie/xh WRITES to Azure DevOps, denied
|
|
246
237
|
// outright regardless of identity.
|
|
247
238
|
'curl -X POST https://dev.azure.com/org/project/_apis/git/repositories',
|
|
248
239
|
'curl -d "{}" https://dev.azure.com/org/project/_apis/git/repositories',
|
|
249
240
|
'wget --method=POST https://dev.azure.com/org/project/_apis/git/repositories',
|
|
250
241
|
'http POST https://dev.azure.com/org/project/_apis/git/repositories name=x',
|
|
251
242
|
'xh PUT https://vssps.dev.azure.com/org/_apis/profile/profiles/me',
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
// "writes" wording, not a weakening; see this file's own R6 comment.
|
|
243
|
+
// A plain GET/HEAD is denied too (reads included, not only writes);
|
|
244
|
+
// see the HTTP-client comment in `match` above.
|
|
255
245
|
'curl https://dev.azure.com/org/project/_apis/git/repositories',
|
|
256
246
|
'curl -X GET https://dev.azure.com/org/project/_apis/git/repositories',
|
|
257
247
|
'wget https://dev.azure.com/org/project/_apis/git/repositories',
|
|
@@ -274,8 +264,7 @@ export const toolAzureDevops: RuleSpec = {
|
|
|
274
264
|
'az storage account list',
|
|
275
265
|
'az rest --method get --url https://management.azure.com/subscriptions',
|
|
276
266
|
`python3 -c "print('hello')"`,
|
|
277
|
-
//
|
|
278
|
-
// not inline code, is not this rule's to inspect.
|
|
267
|
+
// The ADO host in ARGV, not inline code, is not this rule's to inspect.
|
|
279
268
|
'python3 -m pip install -i https://pkgs.dev.azure.com/org/_packaging/feed/pypi/simple/',
|
|
280
269
|
'node scripts/x.js --remote https://dev.azure.com/org/project',
|
|
281
270
|
],
|
|
@@ -8,18 +8,33 @@
|
|
|
8
8
|
* is caught: at the start, after a pipe, after `&&`/`||`/`;`, inside
|
|
9
9
|
* `$()`/backticks, after xargs, after sudo, and via a leading path — all of
|
|
10
10
|
* that classification lives in shell/invocation.ts, not here.
|
|
11
|
+
*
|
|
12
|
+
* DENY TEXT (2026-10-03, after research-2026-10-02-search-tool-usage-across-surfaces
|
|
13
|
+
* finding #1):
|
|
14
|
+
*
|
|
15
|
+
* - Earlier this text pointed every `find` denial at `search query "<text>"`,
|
|
16
|
+
* but every `find` denial that day was a path pattern (`find -name '*.md'
|
|
17
|
+
* -newermt '2026-10-01'`, `find ~/Documents -name 'code-review-graph*'`),
|
|
18
|
+
* never a content search. The right tool for path patterns is `rg --files
|
|
19
|
+
* -g '<glob>'` or `ctx_glob`. `search` only answers when the doc-tree case
|
|
20
|
+
* is the question — and `find` can't tell which case it is, so we lead
|
|
21
|
+
* with `rg --files -g '<glob>'` (the most common case) and put `search`
|
|
22
|
+
* behind it as the docs/plans fallback.
|
|
23
|
+
* - Recommendation rows come from `./deny-allowlist.ts` so the three
|
|
24
|
+
* search-tool deny texts cannot drift from each other.
|
|
11
25
|
*/
|
|
12
26
|
|
|
13
27
|
import type { Invocation } from '../shell/invocation.ts'
|
|
14
28
|
import type { Finding, MessageContext, RuleSpec } from '../spec.ts'
|
|
15
29
|
import { noParams } from '../spec.ts'
|
|
30
|
+
import { recommendationBlock } from './deny-allowlist.ts'
|
|
16
31
|
|
|
17
32
|
export const toolFind: RuleSpec = {
|
|
18
33
|
id: 'tool.find',
|
|
19
34
|
category: 'tool',
|
|
20
35
|
severity: 'deny',
|
|
21
36
|
enabledByDefault: true,
|
|
22
|
-
summary: 'Deny find unconditionally; steer at `search query "<text>"
|
|
37
|
+
summary: 'Deny find unconditionally; steer at rg --files -g for path patterns and `search query "<text>"` only for docs/plans.',
|
|
23
38
|
params: noParams,
|
|
24
39
|
match(inv: Invocation): Finding | null {
|
|
25
40
|
if (inv.kind !== 'find') return null
|
|
@@ -27,16 +42,23 @@ export const toolFind: RuleSpec = {
|
|
|
27
42
|
},
|
|
28
43
|
message(_finding: Finding, ctx: MessageContext) {
|
|
29
44
|
return {
|
|
30
|
-
user: 'Blocked find. It
|
|
45
|
+
user: 'Blocked find. It emits PATHS, never contents — pipe it to grep and you filter filenames. Use instead: `rg --files -g "<glob>"` for path patterns, `ctx_glob` for indexed file search, or `search query "<text>"` only when the path is `docs/`, `plans/`, or `.scratchpad/`.',
|
|
31
46
|
agent:
|
|
32
47
|
'DENIED find. `find` emits PATHS, so piping it to grep (or any other text tool) filters FILENAMES, never ' +
|
|
33
|
-
'file contents
|
|
48
|
+
'file contents — that produces confidently wrong answers, not merely incomplete ones. For example, ' +
|
|
34
49
|
"`find docs -name '*.md' | grep -iE 'kernel|ontology|metric'` matched only files whose NAME contained " +
|
|
35
50
|
'those words; it missed docs/semantica-cleanup/superset-setup.md, the one document that actually ' +
|
|
36
|
-
'described the subject, while counting name-matches whose contents were irrelevant
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
|
|
51
|
+
'described the subject, while counting name-matches whose contents were irrelevant.\n' +
|
|
52
|
+
'Match the tool to the question:\n' +
|
|
53
|
+
' rg --files -g "<glob>" -g "!node_modules/**" path patterns (default)\n' +
|
|
54
|
+
' ctx_glob(pattern, path) indexed file search\n' +
|
|
55
|
+
' search query "<text>" only when the path is docs/, plans/, or .scratchpad/ and the doc TALKS about X\n' +
|
|
56
|
+
' crg search "<text>" --kind File code-graph search by name or text\n' +
|
|
57
|
+
'The full replacement table from `./deny-allowlist.ts`:\n' +
|
|
58
|
+
recommendationBlock(
|
|
59
|
+
(row) => row.binary === 'rg' || row.binary === 'search' || row.binary === 'crg' || row.binary === 'ctx_glob',
|
|
60
|
+
) +
|
|
61
|
+
`Blocked command: ${ctx.snippet}`,
|
|
40
62
|
}
|
|
41
63
|
},
|
|
42
64
|
corpus: {
|
|
@@ -77,6 +99,11 @@ export const toolFind: RuleSpec = {
|
|
|
77
99
|
'rg -e find file.txt',
|
|
78
100
|
'python3 -c "print(s.find(\'x\'))"',
|
|
79
101
|
'node -e "str.find(\'x\')"',
|
|
102
|
+
// The replacements stay allowed.
|
|
103
|
+
'rg --files -g "*.md" -g "!node_modules/**"',
|
|
104
|
+
'rg --files -g "*.test.ts"',
|
|
105
|
+
'crg search "term" --kind File',
|
|
106
|
+
'ctx_glob "*.md"',
|
|
80
107
|
],
|
|
81
108
|
},
|
|
82
109
|
}
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
* `grep`, unconditionally.
|
|
3
3
|
*
|
|
4
4
|
* Owner decision, 2026-09-15: ban the grep family outright and steer at
|
|
5
|
-
* `rg` / `ast-grep` / `search` / `ctx_search`. Every replacement
|
|
6
|
-
* present and
|
|
5
|
+
* `rg` / `ast-grep` / `search` / `crg` / `ctx_search`. Every replacement is
|
|
6
|
+
* measured present and passing its respective allowlist:
|
|
7
7
|
*
|
|
8
8
|
* rg /opt/homebrew/bin/rg stdin filter AND tree search
|
|
9
9
|
* fd 10.4.2 replaces find
|
|
10
10
|
* ast-grep 0.45.3 structural search neither ever did
|
|
11
|
-
* search /usr/local/bin/search hybrid semantic + keyword
|
|
11
|
+
* search /usr/local/bin/search hybrid semantic + keyword (per-repo allowlist)
|
|
12
|
+
* crg /usr/local/bin/crg code-graph: callers/callees/impact
|
|
13
|
+
* ctx_search / ctx_glob / ctx_read lean-ctx MCP (per-repo allowlist)
|
|
12
14
|
*
|
|
13
15
|
* BLANKET, including a pure stdin filter. An earlier proposal carved out
|
|
14
16
|
* `npm test 2>&1 | grep -E '…'` as "reading output, not searching code". That
|
|
@@ -26,18 +28,35 @@
|
|
|
26
28
|
* `ls` is deliberately NOT denied. It shares `find`'s weakness — it answers
|
|
27
29
|
* about names, never contents — but it is far more load-bearing for ordinary
|
|
28
30
|
* work than the search tools this replaces.
|
|
31
|
+
*
|
|
32
|
+
* DENY TEXT (2026-10-03, after research-2026-10-02-search-tool-usage-across-surfaces
|
|
33
|
+
* finding #4):
|
|
34
|
+
*
|
|
35
|
+
* - Earlier this text claimed "rg / ast-grep / search / crg / ctx_search
|
|
36
|
+
* — all on PATH and already allowed". `search` and `crg` are NOT in
|
|
37
|
+
* lean-ctx's default allowlist — they only pass on repos whose
|
|
38
|
+
* `.agents/lean-ctx/config/lean-ctx/config.toml` declares them under
|
|
39
|
+
* `shell_allowlist_extra`. The new text is honest about that and points
|
|
40
|
+
* at per-repo config when relevant.
|
|
41
|
+
* - The recommendation rows come from `./deny-allowlist.ts` so a single
|
|
42
|
+
* edit to the allowed-tools table updates this text and `tool.find.ts`
|
|
43
|
+
* and `tool.native-search.ts` at once. Adding `--glob '!'` advice at
|
|
44
|
+
* the top of the block (per research §2) keeps the kimi-style
|
|
45
|
+
* `rg -rg -v Y1 | grep -v Y2` chains from re-emerging as a "let me
|
|
46
|
+
* refine my filter" behaviour.
|
|
29
47
|
*/
|
|
30
48
|
|
|
31
49
|
import type { Invocation } from '../shell/invocation.ts'
|
|
32
50
|
import type { Finding, MessageContext, RuleSpec } from '../spec.ts'
|
|
33
51
|
import { noParams } from '../spec.ts'
|
|
52
|
+
import { recommendationBlock } from './deny-allowlist.ts'
|
|
34
53
|
|
|
35
54
|
export const toolGrep: RuleSpec = {
|
|
36
55
|
id: 'tool.grep',
|
|
37
56
|
category: 'tool',
|
|
38
57
|
severity: 'deny',
|
|
39
58
|
enabledByDefault: true,
|
|
40
|
-
summary: 'Deny the grep family; steer at ast-grep / search / crg / rg / ctx_search.',
|
|
59
|
+
summary: 'Deny the grep family; steer at ast-grep / search / crg / rg / ctx_search (per-repo allowlist).',
|
|
41
60
|
params: noParams,
|
|
42
61
|
match(inv: Invocation): Finding | null {
|
|
43
62
|
if (inv.kind !== 'grep') return null
|
|
@@ -45,15 +64,14 @@ export const toolGrep: RuleSpec = {
|
|
|
45
64
|
},
|
|
46
65
|
message(_finding: Finding, ctx: MessageContext) {
|
|
47
66
|
return {
|
|
48
|
-
user: 'Blocked grep. Pick the tool for the question: `ast-grep` for code shapes, `search` for docs by meaning, `crg` for
|
|
67
|
+
user: 'Blocked grep. Pick the tool for the question, in this order: `ast-grep` for code shapes, `search` for docs/plans by meaning, `crg` for code-graph, `rg` for literal text (incl. stdin), `ctx_search` for the indexed code search.',
|
|
49
68
|
agent:
|
|
50
|
-
'DENIED grep.
|
|
51
|
-
'
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
'
|
|
56
|
-
'A pure output filter is no exception: `rg` reads stdin exactly as grep does. ' +
|
|
69
|
+
'DENIED grep. A pure `something | grep -v <X>` is still a grep — refine the upstream command with ' +
|
|
70
|
+
'`--glob \'!<X>\'` or `--type-not` instead of piping. Match the tool to the question - in this order:\n' +
|
|
71
|
+
recommendationBlock(
|
|
72
|
+
(row) => row.binary !== 'ctx_glob' && row.binary !== 'ctx_read' && row.binary !== 'ctx_compose',
|
|
73
|
+
) +
|
|
74
|
+
'\nA pure output filter is no exception: ripgrep filters stdin exactly as grep does. ' +
|
|
57
75
|
`Blocked command: ${ctx.snippet}`,
|
|
58
76
|
}
|
|
59
77
|
},
|
|
@@ -76,11 +94,15 @@ export const toolGrep: RuleSpec = {
|
|
|
76
94
|
],
|
|
77
95
|
allow: [
|
|
78
96
|
// The replacements must keep working — a ban with no escape route is a trap.
|
|
97
|
+
// Mirrors `ALLOWED_SEARCH_TOOLS` in `./deny-allowlist.ts`; adding a row
|
|
98
|
+
// there should land here too.
|
|
79
99
|
'rg TODO src/',
|
|
80
100
|
"npm test 2>&1 | rg 'pass|fail'",
|
|
101
|
+
"rg -n TODO src/ -g '!node_modules/**'",
|
|
81
102
|
'fd -e ts src/',
|
|
82
103
|
'ast-grep --version',
|
|
83
104
|
'search query "how do I author a metric"',
|
|
105
|
+
'crg search TODO --kind File',
|
|
84
106
|
'ls -la',
|
|
85
107
|
// The word `grep` is not the command `grep`.
|
|
86
108
|
'rg grep src/',
|
|
@@ -19,6 +19,20 @@
|
|
|
19
19
|
* not hand-rolled search, and it is the tool `ctx_read` redirects through.
|
|
20
20
|
* Edit/Write are untouched — this rule is about search surfaces only.
|
|
21
21
|
*
|
|
22
|
+
* DENY TEXT (2026-10-03, after research-2026-10-02-search-tool-usage-across-surfaces
|
|
23
|
+
* found a 3/95 pivot rate and zero pivots to `search query` / `crg`):
|
|
24
|
+
*
|
|
25
|
+
* - Earlier this text recommended `ctx_search`/`ctx_compose`/`ctx_callgraph`
|
|
26
|
+
* and `rg / ast-grep` only. The model took the lean-ctx MCP path (3/3
|
|
27
|
+
* pivots went there) and never reached for `search` (the enoted-search
|
|
28
|
+
* binary that IS the right tool for `docs/`, `plans/`, `.scratchpad/`).
|
|
29
|
+
* - The new text leads with the docs/plans case (the most common
|
|
30
|
+
* search-tool denial in the kimi data: 11 of 25 were docs/plans) and
|
|
31
|
+
* then names `crg search` (the graph tool) for code-graph queries,
|
|
32
|
+
* then falls back to the lean-ctx MCP and rg/ast-grep.
|
|
33
|
+
* - The recommendations come from `./deny-allowlist.ts` so a single edit
|
|
34
|
+
* updates every rule's deny text.
|
|
35
|
+
*
|
|
22
36
|
* Tool names are matched exactly and case-sensitively against each host's own
|
|
23
37
|
* vocabulary, the same way `../../hooks/lean-ctx/mapping.ts` matches them —
|
|
24
38
|
* Claude spells them `Grep`/`Glob`, and lowercase spellings appear in the
|
|
@@ -29,6 +43,7 @@ import type { Invocation } from '../shell/invocation.ts'
|
|
|
29
43
|
import type { Finding, MessageContext, RuleSpec } from '../spec.ts'
|
|
30
44
|
import { noParams } from '../spec.ts'
|
|
31
45
|
import { loadSurfacePolicy } from '../../surface-policy.ts'
|
|
46
|
+
import { ALLOWED_SEARCH_TOOLS, DOC_TREES, recommendationBlock } from './deny-allowlist.ts'
|
|
32
47
|
|
|
33
48
|
/**
|
|
34
49
|
* Search-shaped native tools. Mirrors the search half of the `redirect` route
|
|
@@ -41,25 +56,53 @@ export const toolNativeSearch: RuleSpec = {
|
|
|
41
56
|
category: 'tool-call',
|
|
42
57
|
severity: 'deny',
|
|
43
58
|
enabledByDefault: true,
|
|
44
|
-
summary: 'Deny the native Grep/Glob/Search tools; steer at ctx_search
|
|
59
|
+
summary: 'Deny the native Grep/Glob/Search tools; steer at search query (docs/plans), crg (code graph), ctx_search, rg, ast-grep.',
|
|
45
60
|
params: noParams,
|
|
46
61
|
match(inv: Invocation): Finding | null {
|
|
47
62
|
if (inv.kind !== 'tool-call') return null
|
|
48
63
|
if (!new Set(loadSurfacePolicy().deny.nativeTools).has(inv.tool)) return null
|
|
49
|
-
|
|
64
|
+
// Surface the tool input's path-ish field for the message so it can
|
|
65
|
+
// recommend `search` (the right tool for docs/plans/.scratchpad) over
|
|
66
|
+
// `crg` (the right tool for code-graph queries). Different hosts name
|
|
67
|
+
// this field differently — Claude uses `path`, Codex uses `path`,
|
|
68
|
+
// Cursor uses `target_file` / `target_directory` for Write. The
|
|
69
|
+
// engine normalises nothing here, so we read every common spelling.
|
|
70
|
+
const detail: Record<string, string> = { tool: inv.tool }
|
|
71
|
+
const input = inv.input as Record<string, unknown>
|
|
72
|
+
const candidate = input.path ?? input.directory ?? input.target_directory ?? input.target_file
|
|
73
|
+
if (typeof candidate === 'string') {
|
|
74
|
+
detail.path = candidate
|
|
75
|
+
}
|
|
76
|
+
return { ruleId: 'tool.native-search', severity: 'deny', detail }
|
|
50
77
|
},
|
|
51
78
|
message(finding: Finding, ctx: MessageContext) {
|
|
52
79
|
const tool = typeof finding.detail.tool === 'string' ? finding.detail.tool : 'this tool'
|
|
80
|
+
// Path-aware recommendation. Native Grep on docs/plans/.scratchpad ->
|
|
81
|
+
// lead with `search`; everywhere else -> lead with `crg`/`ctx_search`.
|
|
82
|
+
const path = typeof finding.detail.path === 'string' ? finding.detail.path : ''
|
|
83
|
+
const isDoc = DOC_TREES.some((prefix) => path.startsWith(prefix))
|
|
84
|
+
|
|
85
|
+
const leadTool = isDoc ? 'search' : 'crg'
|
|
86
|
+
const leadExamples = ALLOWED_SEARCH_TOOLS.find((row) => row.binary === leadTool)?.examples ?? []
|
|
87
|
+
|
|
88
|
+
const leadLines = leadExamples.map((e) => ` ${e}`).join('\n')
|
|
89
|
+
|
|
90
|
+
const tail = recommendationBlock(
|
|
91
|
+
(row) => row.binary !== leadTool && row.binary !== 'ctx_compose' && row.binary !== 'ctx_callgraph',
|
|
92
|
+
)
|
|
93
|
+
|
|
53
94
|
return {
|
|
54
|
-
user:
|
|
95
|
+
user: isDoc
|
|
96
|
+
? `Blocked the native ${tool} tool on \`${path}\` (a docs/plans/.scratchpad tree). The right answer is \`search query "<text>"\` — semantic + keyword, finds the doc that *talks* about X. \`rg\`/\`crg\`/\`ctx_search\` are the wrong tools here.`
|
|
97
|
+
: `Blocked the native ${tool} tool. Lead with \`crg search "<text>"\` for code-graph queries, fall back to \`rg\`/\`ast-grep\` for literal text, \`ctx_search\` for indexed code, \`search query "<text>"\` only when the path is docs/plans/.scratchpad.`,
|
|
55
98
|
agent:
|
|
56
99
|
`DENIED the native ${tool} tool. It is routed through the lean-ctx hook but NOT converted — ` +
|
|
57
100
|
'the call still runs natively — so it is a way around the shell search ban rather than an ' +
|
|
58
|
-
'alternative to it
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
101
|
+
'alternative to it.\n' +
|
|
102
|
+
`Lead with the right tool for the surface:\n` +
|
|
103
|
+
`${leadLines}\n` +
|
|
104
|
+
`Then fall back as needed:\n` +
|
|
105
|
+
`${tail}\n` +
|
|
63
106
|
`Blocked call: ${ctx.snippet}`,
|
|
64
107
|
}
|
|
65
108
|
},
|
|
@@ -74,4 +117,4 @@ export const toolNativeSearch: RuleSpec = {
|
|
|
74
117
|
'cat src/index.ts',
|
|
75
118
|
],
|
|
76
119
|
},
|
|
77
|
-
}
|
|
120
|
+
}
|
|
@@ -53,16 +53,14 @@ export interface RepoIndexPort {
|
|
|
53
53
|
/** Expand Git URL rewrite rules for an explicit remote URL without contacting it. */
|
|
54
54
|
resolveRemoteUrl(url: string, direction: 'fetch' | 'push'): string | null
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
57
|
-
* repo-configured value of `alias.<verb>` (`git config --get
|
|
56
|
+
* The repo-configured value of `alias.<verb>` (`git config --get
|
|
58
57
|
* alias.<verb>`), or `null` when unset or unreadable — `adl.git-
|
|
59
58
|
* credential-bypass` resolves an UNKNOWN git verb (not a built-in one this
|
|
60
59
|
* repo's own classifier already recognizes) this way to see whether it is
|
|
61
|
-
* actually a network/credential operation in disguise, the
|
|
62
|
-
* `bin/git
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* implement it; a rule reading it treats `undefined` (the method itself
|
|
60
|
+
* actually a network/credential operation in disguise, because the
|
|
61
|
+
* `bin/git` front controller routes on the literal argv verb and never
|
|
62
|
+
* resolves repo config itself. Optional — a fixture with no reason to
|
|
63
|
+
* exercise it is not forced to implement it; a rule reading it treats `undefined` (the method itself
|
|
66
64
|
* absent) the same as `null` (present, resolved to nothing).
|
|
67
65
|
*/
|
|
68
66
|
configuredAlias?(verb: string): string | null
|