@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,46 +1,48 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Editing the files that wire the host's hooks
|
|
2
|
+
* Editing the files that wire the host's hooks.
|
|
3
3
|
*
|
|
4
4
|
* Handoff 5, rule 5: deny Write/Edit/MultiEdit/NotebookEdit on
|
|
5
|
-
* `.claude/settings.json`, `.claude/settings.local.json`,
|
|
6
|
-
* `.codex/config.toml
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* gate in this repo (`adl-config.toml`'s `[hooks] enabled = false`
|
|
10
|
-
* silently no-ops every kind — see `main.ts`'s `runHook`). Editing any
|
|
11
|
-
* of them is a way to switch the gate off without anyone noticing.
|
|
5
|
+
* `.claude/settings.json`, `.claude/settings.local.json`, or
|
|
6
|
+
* `.codex/config.toml`. These are the files that install the hook into the
|
|
7
|
+
* host (including the `.local.json` overrides). Editing any of them is a way
|
|
8
|
+
* to switch the gate off without anyone noticing.
|
|
12
9
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* `adl-config.toml` was the fourth file until 2026-10-01 (Tarun: "nobody
|
|
11
|
+
* should stop editing adl-config.toml"). It is no longer on the list, so an
|
|
12
|
+
* agent can edit, move or delete it. Two things follow, both accepted by the
|
|
13
|
+
* owner: (1) every hook run re-reads it, so `[hooks] enabled = false` (a
|
|
14
|
+
* silent no-op, `main.ts`'s `runHook`) or a `[rules."<id>"] enabled = false`
|
|
15
|
+
* takes effect on the agent's next tool call, ahead of any commit — the
|
|
16
|
+
* commit-time layers (`git.protected-tree-commit`, repo-controls' integrity
|
|
17
|
+
* gate) are the only review left; (2) the carriers that stayed on the list
|
|
18
|
+
* below are only as strong as that file, since it can also switch THIS rule
|
|
19
|
+
* off.
|
|
20
|
+
*
|
|
21
|
+
* Hooks are local-repo-first (Tarun, 2026-09-29): there is no managed-hooks
|
|
22
|
+
* lock and no global carrier, so these per-repo carrier files are the ONLY
|
|
15
23
|
* enforcement layer for the hosts that read them — three more joined the
|
|
16
24
|
* set for exactly that reason: `.codex/hooks.json`, `.cursor/hooks.json`,
|
|
17
25
|
* and `.opencode/plugins/adl-repo.ts` (the generated OpenCode plugin IS
|
|
18
|
-
* its own carrier; there is no separate settings file for that host).
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* original four's own control case (`.claude/settings.json`) already had
|
|
23
|
-
* `blocked: true`.
|
|
26
|
+
* its own carrier; there is no separate settings file for that host). The
|
|
27
|
+
* single source of the list is `PROTECTED_CARRIER_PATHS` in
|
|
28
|
+
* `../shell/protected-carriers.ts`, which also names Kimi's one global
|
|
29
|
+
* carrier, `~/.kimi-code/config.toml`.
|
|
24
30
|
*
|
|
25
|
-
* The list is hard-coded here on purpose
|
|
26
|
-
* `
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* legitimately needs a different allowlist should patch this file in a
|
|
30
|
-
* PR, not in a session.
|
|
31
|
+
* The list is hard-coded here on purpose: a per-repo allowlist in
|
|
32
|
+
* `adl-config.toml` would be one more switch in a file the repo controls.
|
|
33
|
+
* A repo that legitimately needs a different allowlist should patch this
|
|
34
|
+
* file in a PR, not in a session.
|
|
31
35
|
*
|
|
32
36
|
* The file names match against the FULL path and against the basename so
|
|
33
37
|
* `Write .claude/settings.json` AND `Write /Users/x/repo/.claude/settings.json`
|
|
34
38
|
* both fire, but `Write .claude/SETTINGS.json.bak` does NOT (the
|
|
35
39
|
* case-sensitive suffix check rejects it).
|
|
36
40
|
*
|
|
37
|
-
* Shell-write coverage
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* measured directly against the real engine before this fix. Closed via
|
|
43
|
-
* three additional match() branches:
|
|
41
|
+
* Shell-write coverage: the tool-call gate above never sees a shell
|
|
42
|
+
* command, so `echo x > .cursor/hooks.json`, `tee`, `mv`/`cp`/`install`/
|
|
43
|
+
* `ln -sf`, `sed -i`/`perl -pi`, `truncate`, `trash`/`rm`/`unlink`/`shred`,
|
|
44
|
+
* and `dd of=` against a protected file are covered by three additional
|
|
45
|
+
* match() branches:
|
|
44
46
|
* - `inv.kind === 'protected-carrier-write'` — the generic-command half
|
|
45
47
|
* (redirection/tee/mv/cp/install/ln/sed/perl/truncate/trash/rm/unlink/
|
|
46
48
|
* shred/dd), classified by `shell/protected-carrier-writes.ts` and wired
|
|
@@ -88,14 +90,14 @@ function logicalToolName(tool: string): string {
|
|
|
88
90
|
/**
|
|
89
91
|
* Tools whose `input.file_path` / `input.notebook_path` / `input.path` /
|
|
90
92
|
* `input.filePath` decides what the edit targets — matched case-insensitively
|
|
91
|
-
* (
|
|
93
|
+
* (independent review, 2026-09-29): OpenCode's own plugin
|
|
92
94
|
* (`.opencode/plugins/adl-repo.ts`'s `tool.execute.before`) sends its OWN
|
|
93
95
|
* lowercase tool names (`edit`, `write`), not Claude/Codex/Kimi's
|
|
94
96
|
* capitalized ones, and its `tool_input` (`output.args`) carries the target
|
|
95
97
|
* as camelCase `filePath`, not `file_path`.
|
|
96
98
|
*/
|
|
97
99
|
/**
|
|
98
|
-
*
|
|
100
|
+
* Widened beyond Claude/Codex/Kimi's
|
|
99
101
|
* own capitalized names — one normalized (lowercase) list covering every
|
|
100
102
|
* edit-tool spelling a supported host actually sends:
|
|
101
103
|
* - `strreplace`/`str_replace_editor`/`edit_file`/`str_replace`/
|
|
@@ -139,7 +141,7 @@ function readStringField(input: Readonly<Record<string, unknown>>, key: string):
|
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
/**
|
|
142
|
-
* Codex's `apply_patch
|
|
144
|
+
* Codex's `apply_patch`: its patch body lives in `input.command`
|
|
143
145
|
* (`handler.ts`'s `toDecideInput` special-cases this tool to a `tool-call`
|
|
144
146
|
* precisely so it reaches here instead of being walked as shell text), and
|
|
145
147
|
* the path it targets is named in a `*** Add File:`/`*** Update File:`/
|
|
@@ -161,13 +163,13 @@ function toolCallTarget(inv: Invocation & { kind: 'tool-call' }): string | null
|
|
|
161
163
|
const name = logicalToolName(inv.tool).toLowerCase()
|
|
162
164
|
// apply_patch / OpenCode's own `patch` tool: the patch body is
|
|
163
165
|
// `input.command` (Codex) or `input.patchText` (OpenCode's own field
|
|
164
|
-
// name for the same shape
|
|
166
|
+
// name for the same shape) — never a `file_path`-shaped field.
|
|
165
167
|
if (name === 'apply_patch' || name === 'patch') {
|
|
166
168
|
const body = readStringField(inv.input, 'command') + readStringField(inv.input, 'patchText')
|
|
167
169
|
if (body.length > 0) return applyPatchTarget(body)
|
|
168
170
|
}
|
|
169
171
|
if (!EDIT_TOOL_NAMES.has(name)) return null
|
|
170
|
-
//
|
|
172
|
+
// Cursor's real `edit_file`
|
|
171
173
|
// schema names its path argument `target_file` (confirmed via Cursor's
|
|
172
174
|
// own published tool schema/system-prompt documentation).
|
|
173
175
|
const filePath =
|
|
@@ -194,8 +196,8 @@ function nonOptionValues(rest: readonly Token[]): readonly string[] {
|
|
|
194
196
|
/**
|
|
195
197
|
* `git checkout` ALWAYS restores the WORKTREE for a named path — there is no
|
|
196
198
|
* staged-only variant (that is `git restore --staged`'s job) — so every
|
|
197
|
-
* shape is checked: `git checkout -- <path>` and
|
|
198
|
-
*
|
|
199
|
+
* shape is checked: `git checkout -- <path>` and the equally real
|
|
200
|
+
* `git checkout <rev> <path>` form
|
|
199
201
|
* with no `--` at all (>= 2 non-option operands; the LAST one is the path).
|
|
200
202
|
*/
|
|
201
203
|
function checkoutTarget(rest: readonly Token[]): string | null {
|
|
@@ -215,7 +217,7 @@ function checkoutTarget(rest: readonly Token[]): string | null {
|
|
|
215
217
|
/**
|
|
216
218
|
* `git restore` touches the WORKTREE by default; `--staged`/`-S` makes it an
|
|
217
219
|
* index-only unstage UNLESS `--worktree`/`-W` is ALSO given (both flags
|
|
218
|
-
* together restore both).
|
|
220
|
+
* together restore both). A
|
|
219
221
|
* plain `git restore --staged -- <path>` must be ALLOWED — it never
|
|
220
222
|
* touches the file this rule exists to protect from being overwritten.
|
|
221
223
|
*/
|
|
@@ -242,8 +244,7 @@ function restoreTarget(rest: readonly Token[]): string | null {
|
|
|
242
244
|
* `--hard`/`--merge`/`--keep`, none of which accepts a pathspec in real
|
|
243
245
|
* git (a bare `git reset --hard` with no path at all is `git.reset`'s own
|
|
244
246
|
* unconditional deny to catch, not this rule's — there is no specific
|
|
245
|
-
* carrier PATH for this function to find there).
|
|
246
|
-
* review, 2026-09-29): `git reset -- <path>` and `git reset HEAD --
|
|
247
|
+
* carrier PATH for this function to find there). `git reset -- <path>` and `git reset HEAD --
|
|
247
248
|
* <path>` must be ALLOWED — they only unstage.
|
|
248
249
|
*/
|
|
249
250
|
function resetTouchesWorktree(rest: readonly Token[]): boolean {
|
|
@@ -267,7 +268,7 @@ function anyOperandTarget(rest: readonly Token[]): string | null {
|
|
|
267
268
|
for (const token of rest) {
|
|
268
269
|
const value = tokenValue(token)
|
|
269
270
|
if (value === '--' || value.startsWith('-')) continue
|
|
270
|
-
//
|
|
271
|
+
// `git mv .claude
|
|
271
272
|
// .claude-old` moves the WHOLE carrier directory away — file-level
|
|
272
273
|
// `protectedCarrierMatch` alone never saw this.
|
|
273
274
|
const hit = protectedCarrierMatch(value) ?? protectedCarrierDirMatch(value)
|
|
@@ -277,13 +278,13 @@ function anyOperandTarget(rest: readonly Token[]): string | null {
|
|
|
277
278
|
}
|
|
278
279
|
|
|
279
280
|
function gitTarget(inv: Invocation & { kind: 'git' }): string | null {
|
|
280
|
-
//
|
|
281
|
+
// `git mv` of a carrier (either
|
|
281
282
|
// operand — moving it away, or overwriting it with something else).
|
|
282
283
|
if (inv.subcommand === 'rm' || inv.subcommand === 'mv') return anyOperandTarget(inv.rest)
|
|
283
284
|
if (inv.subcommand === 'checkout') return checkoutTarget(inv.rest)
|
|
284
285
|
if (inv.subcommand === 'restore') return restoreTarget(inv.rest)
|
|
285
286
|
if (inv.subcommand === 'reset') return resetTarget(inv.rest)
|
|
286
|
-
//
|
|
287
|
+
// `git checkout-index` writes working-tree files from the index for
|
|
287
288
|
// named paths — the plumbing sibling of `git checkout -- <path>`. `-a`/
|
|
288
289
|
// `--all` (every staged file, no specific path named) is a known,
|
|
289
290
|
// documented gap — not handled here.
|
|
@@ -292,8 +293,7 @@ function gitTarget(inv: Invocation & { kind: 'git' }): string | null {
|
|
|
292
293
|
}
|
|
293
294
|
|
|
294
295
|
/**
|
|
295
|
-
* `git apply`/the standalone `patch` utility
|
|
296
|
-
* 2026-09-29): the path a patch actually modifies lives INSIDE the patch
|
|
296
|
+
* `git apply`/the standalone `patch` utility: the path a patch actually modifies lives INSIDE the patch
|
|
297
297
|
* file's own headers, not (usually) as a command-line operand at all —
|
|
298
298
|
* `git apply some.patch` names the PATCH FILE, never its target. Coarse,
|
|
299
299
|
* whole-command (same tradeoff `interpreterTarget`/`coarsePathMention`
|
|
@@ -303,29 +303,38 @@ function gitTarget(inv: Invocation & { kind: 'git' }): string | null {
|
|
|
303
303
|
* static, pre-execution hook (it would need to read the file from disk,
|
|
304
304
|
* which this hook does not do for any other check either).
|
|
305
305
|
*/
|
|
306
|
-
/** `git apply` flags that inspect a patch without applying anything
|
|
306
|
+
/** `git apply` flags that inspect a patch without applying anything. */
|
|
307
307
|
const DRY_RUN_GIT_APPLY_FLAGS: ReadonlySet<string> = new Set(['--check', '--stat', '--numstat', '--summary'])
|
|
308
308
|
|
|
309
|
+
/**
|
|
310
|
+
* `name` as a whole file name: not glued to a longer name on either side. A bare
|
|
311
|
+
* substring test matched `config.toml` inside `adl-config.toml`,
|
|
312
|
+
* `enact-config.toml` and `my.config.toml`, denying any `git apply`/`patch`
|
|
313
|
+
* that named them as "rewriting .codex/config.toml".
|
|
314
|
+
*/
|
|
315
|
+
function mentionsWholeName(command: string, name: string): boolean {
|
|
316
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
317
|
+
return new RegExp(`(?<![\\w.-])${escaped}(?![\\w.-])`).test(command)
|
|
318
|
+
}
|
|
319
|
+
|
|
309
320
|
function coarsePathMention(command: string): string | null {
|
|
310
321
|
for (const protectedPath of PROTECTED_CARRIER_PATHS) {
|
|
311
322
|
if (command.includes(protectedPath)) return protectedPath
|
|
312
323
|
const base = protectedPath.slice(protectedPath.lastIndexOf('/') + 1)
|
|
313
|
-
if (command
|
|
324
|
+
if (mentionsWholeName(command, base)) return protectedPath
|
|
314
325
|
}
|
|
315
326
|
return null
|
|
316
327
|
}
|
|
317
328
|
|
|
318
329
|
/**
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
330
|
+
* Correlated detection, not two independent checks. Pairing "some write call
|
|
331
|
+
* anywhere in the command" with "a carrier path anywhere in the command
|
|
332
|
+
* text" (`coarsePathMention`) was a live false positive (independent review,
|
|
333
|
+
* 2026-09-29): a heredoc-fed `python3 - <<'EOF'` writing an unrelated file
|
|
334
|
+
* (e.g. `notes.md`) whose own written TEXT merely mentioned
|
|
324
335
|
* `.codex/config.toml` (a docstring, a log line, a commit message) was
|
|
325
336
|
* wrongly denied — the mention and the write had nothing to do with each
|
|
326
|
-
* other.
|
|
327
|
-
*
|
|
328
|
-
* Replaced with CORRELATED detection: each pattern below captures the
|
|
337
|
+
* other. So each pattern below captures the
|
|
329
338
|
* WRITE-CALL'S OWN TARGET ARGUMENT specifically (group 1) — `open(TARGET,
|
|
330
339
|
* 'w'|'a'|'x'…)`, `Path(TARGET).write_text/write_bytes(...)`,
|
|
331
340
|
* `os.remove/unlink(TARGET)`, `os.rename(SRC, TARGET)`,
|
|
@@ -344,7 +353,7 @@ function coarsePathMention(command: string): string | null {
|
|
|
344
353
|
* expression (neither a literal nor a bare identifier — string
|
|
345
354
|
* concatenation, a function call, …) cannot be correlated at all and is
|
|
346
355
|
* left alone (allowed), the same "cannot resolve, so cannot deny" stance
|
|
347
|
-
* `adl.
|
|
356
|
+
* `adl.run-required-for-writes`'s own destination classification takes
|
|
348
357
|
* for an unresolved git push remote.
|
|
349
358
|
*
|
|
350
359
|
* `ARG` allows one level of nested parens (`os.path.join(a, b)` as a
|
|
@@ -354,7 +363,7 @@ function coarsePathMention(command: string): string | null {
|
|
|
354
363
|
const ARG = `((?:[^,()]|\\([^()]*\\))+)`
|
|
355
364
|
/** `fs.X(...)`, `require('fs').X(...)`, or `require('fs').promises.X(...)` (no literal `fs.` substring exists in the `require(...)` forms — `'fs')` breaks it — so all three are matched explicitly rather than relying on a bare `fs\.` prefix). Required (not optional) for the async, non-Sync names below — `rename`/`unlink`/`rm` are common-enough verbs that an UNqualified bare call risks a real collision with an unrelated same-named function. */
|
|
356
365
|
const FS_QUALIFIED_PREFIX = `(?:\\bfs|require\\(\\s*['"]fs['"]\\s*\\))\\s*\\.\\s*(?:promises\\s*\\.\\s*)?`
|
|
357
|
-
/** The SAME prefix, but OPTIONAL
|
|
366
|
+
/** The SAME prefix, but OPTIONAL: `const { writeFileSync } = require('fs'); writeFileSync(...)` calls it BARE, with no qualifying prefix on the call site itself. Only for the `*Sync` names, distinctive enough on their own that an unqualified bare call is still almost certainly this Node API. */
|
|
358
367
|
const FS_SYNC_OPTIONAL_PREFIX = `(?:${FS_QUALIFIED_PREFIX})?`
|
|
359
368
|
const WRITE_TARGET_PATTERNS: readonly RegExp[] = [
|
|
360
369
|
new RegExp(`\\bopen\\s*\\(\\s*${ARG}\\s*,\\s*['"][wax]`, 'g'),
|
|
@@ -364,7 +373,7 @@ const WRITE_TARGET_PATTERNS: readonly RegExp[] = [
|
|
|
364
373
|
new RegExp(`\\bshutil\\.(?:move|copy2?|copyfile)\\s*\\(\\s*${ARG}\\s*,\\s*${ARG}\\s*\\)`, 'g'),
|
|
365
374
|
new RegExp(`${FS_SYNC_OPTIONAL_PREFIX}(?:writeFileSync|appendFileSync|rmSync|unlinkSync|copyFileSync|truncateSync)\\s*\\(\\s*${ARG}`, 'g'),
|
|
366
375
|
new RegExp(`${FS_SYNC_OPTIONAL_PREFIX}renameSync\\s*\\(\\s*${ARG}\\s*,\\s*${ARG}`, 'g'),
|
|
367
|
-
//
|
|
376
|
+
// The async (non-Sync) forms, prefix REQUIRED.
|
|
368
377
|
new RegExp(`${FS_QUALIFIED_PREFIX}(?:writeFile|appendFile|rm|unlink|copyFile)\\s*\\(\\s*${ARG}`, 'g'),
|
|
369
378
|
new RegExp(`${FS_QUALIFIED_PREFIX}rename\\s*\\(\\s*${ARG}\\s*,\\s*${ARG}`, 'g'),
|
|
370
379
|
new RegExp(`\\bBun\\.write\\s*\\(\\s*${ARG}`, 'g'),
|
|
@@ -414,7 +423,7 @@ export const agentTamperProtection: RuleSpec = {
|
|
|
414
423
|
category: 'tool-call',
|
|
415
424
|
severity: 'deny',
|
|
416
425
|
enabledByDefault: true,
|
|
417
|
-
summary:
|
|
426
|
+
summary: "Deny edits (tool, shell write, or git rewrite) to the files that wire a host's hooks.",
|
|
418
427
|
params: noParams,
|
|
419
428
|
match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
|
|
420
429
|
if (inv.kind === 'tool-call') {
|
|
@@ -431,10 +440,10 @@ export const agentTamperProtection: RuleSpec = {
|
|
|
431
440
|
if (target !== null) {
|
|
432
441
|
return { ruleId: 'agent.tamper-protection', severity: 'deny', detail: { path: target, via: 'git', command: `git ${inv.subcommand}` } }
|
|
433
442
|
}
|
|
434
|
-
//
|
|
443
|
+
// `git apply` — coarse, whole-command (see `coarsePathMention`'s
|
|
435
444
|
// own doc for why: the target path is inside the patch's own
|
|
436
445
|
// headers, not an operand `gitTarget`'s per-operand scan would see).
|
|
437
|
-
//
|
|
446
|
+
// A dry-run/inspection
|
|
438
447
|
// flag applies NOTHING — `git apply --check/--stat/--numstat/
|
|
439
448
|
// --summary` never touches the working tree, so naming a carrier is
|
|
440
449
|
// harmless.
|
|
@@ -444,7 +453,7 @@ export const agentTamperProtection: RuleSpec = {
|
|
|
444
453
|
}
|
|
445
454
|
return null
|
|
446
455
|
}
|
|
447
|
-
//
|
|
456
|
+
// The standalone `patch` utility — same coarse, whole-command
|
|
448
457
|
// reasoning as `git apply` above.
|
|
449
458
|
if (inv.kind === 'command' && inv.name === 'patch') {
|
|
450
459
|
const hit = coarsePathMention(ctx.command ?? '')
|
|
@@ -469,21 +478,19 @@ export const agentTamperProtection: RuleSpec = {
|
|
|
469
478
|
? 'an interpreter one-liner writing'
|
|
470
479
|
: 'editing'
|
|
471
480
|
return {
|
|
472
|
-
user: `Blocked ${via === 'tool-call' ? 'editing' : verb} ${path}. This file wires the host's hooks
|
|
481
|
+
user: `Blocked ${via === 'tool-call' ? 'editing' : verb} ${path}. This file wires the host's hooks; ask the user to change it.`,
|
|
473
482
|
agent:
|
|
474
483
|
`DENIED ${verb} ${path}. This file is one of the tamper-protected files: ` +
|
|
475
484
|
'`.claude/settings.json`, `.claude/settings.local.json`, `.codex/config.toml`, ' +
|
|
476
485
|
'`.codex/hooks.json`, `.cursor/hooks.json`, `.opencode/plugins/adl-repo.ts`, ' +
|
|
477
|
-
"`~/.kimi-code/config.toml
|
|
478
|
-
"
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
"own gate marker (`[hooks] enabled = false` silently no-ops every hook kind — see " +
|
|
482
|
-
'`main.ts`). Editing, overwriting, moving over, truncating, ' +
|
|
486
|
+
"or `~/.kimi-code/config.toml`. Each installs or overrides a host's own hook contract " +
|
|
487
|
+
"(directly, or — for `.opencode/plugins/adl-repo.ts` — as the generated plugin THAT IS " +
|
|
488
|
+
"the carrier; `~/.kimi-code/config.toml` is Kimi's own single, globally-installed " +
|
|
489
|
+
'carrier — Kimi has no per-repo one). Editing, overwriting, moving over, truncating, ' +
|
|
483
490
|
'deleting, or rewriting any of them — by a tool call, a shell write, or a git checkout/ ' +
|
|
484
491
|
'restore/reset/rm — is a way to switch the gate off without anyone noticing, the ONLY ' +
|
|
485
|
-
'enforcement layer for the hosts that read them (
|
|
486
|
-
`
|
|
492
|
+
'enforcement layer for the hosts that read them (there is no managed-hooks lock). ' +
|
|
493
|
+
`If a legitimate change is needed, file a PR or ask the user to make it themselves. ` +
|
|
487
494
|
`Blocked call: ${ctx.snippet}`,
|
|
488
495
|
}
|
|
489
496
|
},
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for "which commands actually pass the lean-ctx
|
|
3
|
+
* shell allowlist", so the three search-tool deny rules (tool.grep,
|
|
4
|
+
* tool.find, tool.native-search) cannot lie about what's available.
|
|
5
|
+
*
|
|
6
|
+
* History (2026-10-02 research `research-2026-10-02-search-tool-usage-across-surfaces.md`
|
|
7
|
+
* finding #4):
|
|
8
|
+
*
|
|
9
|
+
* - `tool.grep`'s deny text claimed "search is allowed". It is not — the
|
|
10
|
+
* default lean-ctx allowlist has 223 commands and no `search` unless the
|
|
11
|
+
* repo's `.agents/lean-ctx/config/lean-ctx/config.toml` declares it under
|
|
12
|
+
* `shell_allowlist_extra`. Only a per-repo deploy with the seed list lands
|
|
13
|
+
* `search`/`crg`/etc. into the actual runtime allowlist.
|
|
14
|
+
* - `tool.find`'s deny text pointed at `search query "<text>"` for every
|
|
15
|
+
* path-pattern request, which is the wrong recommendation — `search`
|
|
16
|
+
* searches CONTENT, not paths; the right tool for `find -name '*.md'` is
|
|
17
|
+
* `rg --files -g '<glob>'` or `ctx_glob`.
|
|
18
|
+
* - `tool.native-search`'s deny text pointed at `ctx_search` /
|
|
19
|
+
* `ctx_compose` / `ctx_callgraph` / `rg / ast-grep`, never at `search
|
|
20
|
+
* query` — the docs-and-plans case that 11 of 25 kimi denials actually were.
|
|
21
|
+
*
|
|
22
|
+
* Every entry here is the canonical name (matches the binary on PATH); the
|
|
23
|
+
* rules import this and reference its shape from their deny messages, so a
|
|
24
|
+
* command added here appears in every deny message that recommends it, and a
|
|
25
|
+
* command removed here stops being recommended everywhere at once.
|
|
26
|
+
*
|
|
27
|
+
* The list is consumed by:
|
|
28
|
+
*
|
|
29
|
+
* - `tool.grep.ts` (Bash shape): pipe stdin filter / literal text search
|
|
30
|
+
* - `tool.find.ts` (Bash shape): path-pattern search
|
|
31
|
+
* - `tool.native-search.ts` (host-native tool shape): Grep / Glob / Search
|
|
32
|
+
*
|
|
33
|
+
* Each rule still owns its own denial text, but the recommendation rows are
|
|
34
|
+
* generated from `ALLOWED` so the texts cannot drift from the truth here.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
export interface AllowedTool {
|
|
38
|
+
/** The binary name as it appears on PATH (no path prefix). */
|
|
39
|
+
readonly binary: string
|
|
40
|
+
/** A one-line description used by the deny rules' recommendation table. */
|
|
41
|
+
readonly purpose: string
|
|
42
|
+
/**
|
|
43
|
+
* A concrete command shape the model can copy verbatim. Used by the rules'
|
|
44
|
+
* deny messages so the message reads like documentation, not a hint.
|
|
45
|
+
* Multiple commands because some tools have multiple shapes (e.g. rg grep vs
|
|
46
|
+
* rg tree).
|
|
47
|
+
*/
|
|
48
|
+
readonly examples: readonly string[]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The tools the deny messages recommend. Each row carries a single source of
|
|
53
|
+
* truth so the three rules' text cannot drift.
|
|
54
|
+
*
|
|
55
|
+
* Only the surface that's relevant to search-tool use is here. Bash itself
|
|
56
|
+
* is not "allowed" in this sense — it's the substrate the tools run in. `ls`,
|
|
57
|
+
* `cat`, `git`, etc. are not in this table because they are not search
|
|
58
|
+
* replacements.
|
|
59
|
+
*/
|
|
60
|
+
export const ALLOWED_SEARCH_TOOLS: readonly AllowedTool[] = [
|
|
61
|
+
// Order matters — `rules-grep-message-order.test.ts` pins it as
|
|
62
|
+
// ast-grep, search, crg, rg, ctx_search, … (Tarun, 2026-09-30).
|
|
63
|
+
{
|
|
64
|
+
binary: 'ast-grep',
|
|
65
|
+
purpose: 'code STRUCTURE: shapes rather than strings',
|
|
66
|
+
examples: [
|
|
67
|
+
'ast-grep -p "foo($A)" -l ts',
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
binary: 'search',
|
|
72
|
+
purpose:
|
|
73
|
+
'docs and plans by MEANING: hybrid semantic + keyword (enoted-search@0.2.2 at /usr/local/bin/search)',
|
|
74
|
+
examples: [
|
|
75
|
+
'search query "how do I author a metric" # hybrid (default)',
|
|
76
|
+
'search query "<text>" --mode keyword # when you only want literal matches',
|
|
77
|
+
'search query "<text>" --mode semantic # when the doc talks about it, not the word',
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
binary: 'crg',
|
|
82
|
+
purpose: 'the code GRAPH: callers, callees, impact (code-review-graph)',
|
|
83
|
+
examples: [
|
|
84
|
+
'crg search "<text>" --kind File # find files matching a name/text',
|
|
85
|
+
'crg query callers_of <fn> # who calls this function?',
|
|
86
|
+
'crg query callees_of <fn> # what does this function call?',
|
|
87
|
+
'crg impact # blast radius of staged changes',
|
|
88
|
+
'crg architecture # module/structure overview',
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
binary: 'rg',
|
|
93
|
+
purpose: 'literal text or regex, including stdin (`npm test 2>&1 | rg "pass|fail"`)',
|
|
94
|
+
examples: [
|
|
95
|
+
'rg "TODO" src/',
|
|
96
|
+
'rg --files -g "<glob>" # path patterns, NOT find',
|
|
97
|
+
'rg "pass|fail" # stdin filter, NOT grep',
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
binary: 'ctx_search',
|
|
102
|
+
purpose: 'lean-ctx MCP indexed code search (action=symbol for an exact symbol)',
|
|
103
|
+
examples: [
|
|
104
|
+
'ctx_search(action=symbol, handle="path#name@Lstart")',
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
binary: 'ctx_glob',
|
|
109
|
+
purpose: 'lean-ctx MCP indexed file search (path patterns only, not content)',
|
|
110
|
+
examples: ['ctx_glob(pattern, path)'],
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
binary: 'ctx_read',
|
|
114
|
+
purpose: 'lean-ctx MCP indexed file read (compressed output, no token tax)',
|
|
115
|
+
examples: ['ctx_read(path, mode)'],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
binary: 'ctx_compose',
|
|
119
|
+
purpose: 'lean-ctx MCP context compose (orient on a task without reading whole files)',
|
|
120
|
+
examples: ['ctx_compose(task)'],
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
binary: 'ctx_callgraph',
|
|
124
|
+
purpose: 'lean-ctx MCP callers/impact for callers and engines (crg also answers these, but via shell)',
|
|
125
|
+
examples: ['ctx_callgraph(symbol)'],
|
|
126
|
+
},
|
|
127
|
+
] as const
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* The rule's deny text needs to point at the right tool for the right
|
|
131
|
+
* surface. This helper produces a single recommendation block from
|
|
132
|
+
* `ALLOWED_SEARCH_TOOLS`, formatted as a multi-line bullet list the rules
|
|
133
|
+
* can paste into their `agent:` field. `filter` lets a rule narrow to the
|
|
134
|
+
* subset of tools that apply (e.g. only tools that work in a docs/plans
|
|
135
|
+
* tree).
|
|
136
|
+
*/
|
|
137
|
+
export function recommendationBlock(filter?: (tool: AllowedTool) => boolean): string {
|
|
138
|
+
const rows = ALLOWED_SEARCH_TOOLS.filter(filter ?? (() => true))
|
|
139
|
+
return rows
|
|
140
|
+
.map((row) => {
|
|
141
|
+
const examples = row.examples.map((e) => ` ${e}`).join('\n')
|
|
142
|
+
return ` ${row.binary.padEnd(11)} ${row.purpose}\n${examples}`
|
|
143
|
+
})
|
|
144
|
+
.join('\n')
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* The set of paths where `search` (semantic + keyword) is the right tool
|
|
149
|
+
* over `rg`/`crg`/`ctx_search`. A native `Grep` whose `tool_input.path`
|
|
150
|
+
* starts with one of these should redirect to `search`, not to `rg` — the
|
|
151
|
+
* model is searching for the document that *talks* about X, not for the
|
|
152
|
+
* literal text X.
|
|
153
|
+
*/
|
|
154
|
+
export const DOC_TREES: readonly string[] = [
|
|
155
|
+
'docs/',
|
|
156
|
+
'plans/',
|
|
157
|
+
'.scratchpad/',
|
|
158
|
+
] as const
|
|
159
|
+
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* The original's eighth predicate -- any path with an `.agents` segment --
|
|
9
9
|
* was dropped by owner decision on 2026-09-15. `.agents/` is reconciled
|
|
10
|
-
* centrally every
|
|
11
|
-
* surfaces in every managed repo), so a trashed copy is restored rather than
|
|
10
|
+
* centrally every 12 hours (`adl reconcile`'s repository step runs `adl install --repo`,
|
|
11
|
+
* which refreshes repo-local surfaces in every managed repo), so a trashed copy is restored rather than
|
|
12
12
|
* lost, and `trash(1)` is itself recoverable from ~/.Trash. Protecting it here
|
|
13
13
|
* blocked routine work to guard against something the fleet already repairs.
|
|
14
14
|
*
|
|
@@ -90,7 +90,7 @@ export function flipsCoreBare(tokens: readonly Token[]): boolean {
|
|
|
90
90
|
return tokens.some((token) => /core\.bare/i.test(tokenValue(token)))
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
function pathIsInProtectedTree(rawPath: string, protectedTrees: readonly string[]): boolean {
|
|
94
94
|
const path = `/${rawPath.replace(/^\.\//, '').replace(/\/+$/, '')}/`
|
|
95
95
|
return protectedTrees.some((tree) => path.includes(`/${tree}`))
|
|
96
96
|
}
|
|
@@ -107,7 +107,7 @@ export function moveEscapesRepo(rest: readonly Token[], protectedTrees: readonly
|
|
|
107
107
|
|
|
108
108
|
const WHOLE_TREE_PATHSPEC = new Set(['.', './', '..', '../', '*', ':', ':/', ':/*', ':(top)'])
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
function namedPathspecs(tokens: readonly Token[]): readonly string[] {
|
|
111
111
|
const paths: string[] = []
|
|
112
112
|
for (let index = 0; index < tokens.length; index += 1) {
|
|
113
113
|
const value = tokenValue(tokens[index] as Token)
|
|
@@ -121,7 +121,7 @@ export function namedPathspecs(tokens: readonly Token[]): readonly string[] {
|
|
|
121
121
|
return paths
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
function isNamedPathspecOnly(tokens: readonly Token[]): boolean {
|
|
125
125
|
const paths = namedPathspecs(tokens)
|
|
126
126
|
if (paths.length === 0) return false
|
|
127
127
|
return paths.every((value) => !WHOLE_TREE_PATHSPEC.has(value))
|
|
@@ -152,23 +152,22 @@ export function updateIndexIsUnstageOnly(rest: readonly Token[]): boolean {
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
|
-
* `git push` destination classification shared by `adl.
|
|
156
|
-
* and `adl.git-push-branch-policy` —
|
|
157
|
-
*
|
|
155
|
+
* `git push` destination classification shared by `adl.run-required-for-writes`
|
|
156
|
+
* and `adl.git-push-branch-policy` — kept here (docs/architecture/cli-design.md §2 /
|
|
157
|
+
* docs/operations/agent-permissions.md) so the two rules cannot drift on what
|
|
158
158
|
* counts as an Azure DevOps push. Both decide statically, off argv alone: no
|
|
159
159
|
* `git remote get-url` subprocess (the deployed `bin/git` front controller can
|
|
160
160
|
* do that; a pre-tool-use hook decides before the child runs).
|
|
161
161
|
*/
|
|
162
|
-
|
|
162
|
+
const ADO_HOST = 'dev.azure.com'
|
|
163
163
|
|
|
164
164
|
/**
|
|
165
165
|
* The second Azure DevOps host the one-agent-identity standard names
|
|
166
|
-
* (
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
* `isAdoUrl` used to check `dev.azure.com` alone.
|
|
166
|
+
* (REST: curl/wget/httpie/xh to `dev.azure.com` / `*.visualstudio.com`);
|
|
167
|
+
* `isAdoUrl` checks both, alongside the identity-bearing command classes
|
|
168
|
+
* below.
|
|
170
169
|
*/
|
|
171
|
-
|
|
170
|
+
const ADO_VISUALSTUDIO_HOST = 'visualstudio.com'
|
|
172
171
|
|
|
173
172
|
export function isAdoUrl(value: string): boolean {
|
|
174
173
|
const lower = value.toLowerCase()
|
|
@@ -177,13 +176,12 @@ export function isAdoUrl(value: string): boolean {
|
|
|
177
176
|
|
|
178
177
|
/**
|
|
179
178
|
* Identity-bearing `adl <...>` subcommand shapes
|
|
180
|
-
* (
|
|
181
|
-
* item 1): every one of these reaches Azure DevOps and needs the resolved
|
|
179
|
+
* (one-agent-identity standard): every one of these reaches Azure DevOps and needs the resolved
|
|
182
180
|
* agent identity, exactly like a network git command. Matched positionally
|
|
183
181
|
* against the words/tokens right after `adl` itself (case-insensitively,
|
|
184
182
|
* dynamic values excluded by the caller) — shared by the shell scanner
|
|
185
183
|
* (`../shell/git-identity.ts`, which needs the raw source span to rewrite)
|
|
186
|
-
* and the ordinary invocation-based rules (`adl-
|
|
184
|
+
* and the ordinary invocation-based rules (`adl-run-required.ts`, which
|
|
187
185
|
* only needs a yes/no match) so the two classifications cannot drift apart.
|
|
188
186
|
*/
|
|
189
187
|
export const ADL_IDENTITY_COMMAND_SHAPES: readonly (readonly string[])[] = [
|
|
@@ -202,7 +200,7 @@ export const ADL_AGENT_ID_BINARY_NAMES: ReadonlySet<string> = new Set(['adl-agen
|
|
|
202
200
|
|
|
203
201
|
/**
|
|
204
202
|
* curl/wget/httpie(`http`/`https`)/xh — the REST client family the standard
|
|
205
|
-
* names. Shared with `adl-
|
|
203
|
+
* names. Shared with `adl-run-required.ts`'s own `HTTP_CLIENT_NAMES` so
|
|
206
204
|
* the two classifications (this file's shape matcher vs. that rule's method
|
|
207
205
|
* inspection) cannot name a different set of binaries.
|
|
208
206
|
*/
|
|
@@ -309,8 +307,8 @@ function httpieMethod(args: readonly Token[]): string {
|
|
|
309
307
|
/**
|
|
310
308
|
* The effective HTTP method for an `HTTP_CLIENT_BINARY_NAMES` invocation,
|
|
311
309
|
* dispatched by binary name — curl/wget/httpie(`http`/`https`)/xh each spell
|
|
312
|
-
* their method differently.
|
|
313
|
-
* by `adl-
|
|
310
|
+
* their method differently. Shared
|
|
311
|
+
* by `adl-run-required.ts` (deny with no identity, every method) and
|
|
314
312
|
* `tool-azure-devops.ts` (deny a WRITE method outright, identity or not —
|
|
315
313
|
* docs/operations/agent-permissions.md row 13) so the method-detection logic
|
|
316
314
|
* cannot drift between the two.
|
|
@@ -334,8 +332,8 @@ export function matchesIdentityShape(values: readonly string[], shapes: readonly
|
|
|
334
332
|
}
|
|
335
333
|
|
|
336
334
|
/**
|
|
337
|
-
* Drop leading dash-prefixed words
|
|
338
|
-
*
|
|
335
|
+
* Drop leading dash-prefixed words:
|
|
336
|
+
* `adl-agent-id`'s own global flags (e.g. `--verbose`/`--quiet`)
|
|
339
337
|
* ahead of its `exec` subcommand, which `ADL_AGENT_ID_COMMAND_SHAPES`
|
|
340
338
|
* (`[['exec']]`) would otherwise require sitting at position 0 exactly —
|
|
341
339
|
* `adl-agent-id --verbose exec --agent agent-tarun -- ...` would not match
|
|
@@ -344,7 +342,7 @@ export function matchesIdentityShape(values: readonly string[], shapes: readonly
|
|
|
344
342
|
* global flag is not a documented `adl-agent-id` shape today, so this does
|
|
345
343
|
* not try to consume one — a bare `-` (stdin marker) is not treated as a
|
|
346
344
|
* flag either. Shared by `../shell/git-identity.ts` (the rewrite scanner)
|
|
347
|
-
* and `adl-
|
|
345
|
+
* and `adl-run-required.ts` so the two classifications cannot drift on
|
|
348
346
|
* this.
|
|
349
347
|
*/
|
|
350
348
|
export function skipLeadingDashFlags(values: readonly string[]): readonly string[] {
|
|
@@ -380,9 +378,9 @@ export function classifyGitPushDestination(rest: readonly Token[]): GitPushDesti
|
|
|
380
378
|
}
|
|
381
379
|
|
|
382
380
|
/**
|
|
383
|
-
*
|
|
381
|
+
* A coarse, TEXTUAL (not
|
|
384
382
|
* shell-parsed) signal that some string holds an identity-bearing token —
|
|
385
|
-
* used by `adl-
|
|
383
|
+
* used by `adl-run-required.ts`'s `identityBearingReason` for the two
|
|
386
384
|
* shapes the shell walker (`../shell/invocation.ts`) cannot see INTO at all:
|
|
387
385
|
* an interpreter one-liner's `-c`/`-e` code string (`python3 -c
|
|
388
386
|
* "...subprocess.run(['git','push'])..."` — the walker only re-parses
|