@amsterdamdatalabs/adl-agent-control-darwin-arm64 0.1.4
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 +4 -0
- package/bin/cursor-settings +14 -0
- package/bin/default-agent-file +14 -0
- package/bin/git +670 -0
- package/bin/git-ado +425 -0
- package/bin/global-agents +14 -0
- package/bin/global-surface-sweep +14 -0
- package/bin/health-check +38 -0
- package/bin/kimi-hooks +14 -0
- package/bin/lean-ctx-observe-strip +361 -0
- package/bin/lib/bun-compile-build.sh +34 -0
- package/bin/lib/lean-ctx-observe-hooks.sh +634 -0
- package/bin/managed-settings +14 -0
- package/bin/opencode-hooks +14 -0
- package/bin/reconcile +2648 -0
- package/bin/scratch-reap +14 -0
- package/bin/shell-path-policy +64 -0
- package/bin/surface-policy +14 -0
- package/bin/sync-and-reconcile +215 -0
- package/bin/update-azure-agent-pool +29 -0
- package/bin/validate-manifest +171 -0
- package/bin/vscode-settings +14 -0
- package/package.json +44 -0
- package/packages/agent-hooks/README.md +411 -0
- package/packages/agent-hooks/assets/hooks.json +97 -0
- package/packages/agent-hooks/assets/opencode-plugin.template.ts +224 -0
- package/packages/agent-hooks/bunfig.toml +27 -0
- package/packages/agent-hooks/deploy-profile.json +53 -0
- package/packages/agent-hooks/deploy-profile.schema.json +120 -0
- package/packages/agent-hooks/package.json +23 -0
- package/packages/agent-hooks/src/cli/args.ts +99 -0
- package/packages/agent-hooks/src/cli/doctor.ts +241 -0
- package/packages/agent-hooks/src/cli/rules.ts +133 -0
- package/packages/agent-hooks/src/deploy/deploy.ts +181 -0
- package/packages/agent-hooks/src/deploy/doctor.ts +158 -0
- package/packages/agent-hooks/src/deploy/index.ts +17 -0
- package/packages/agent-hooks/src/deploy/json-merge.ts +115 -0
- package/packages/agent-hooks/src/deploy/legacy-lock.ts +213 -0
- package/packages/agent-hooks/src/deploy/list.ts +117 -0
- package/packages/agent-hooks/src/deploy/lock.ts +65 -0
- package/packages/agent-hooks/src/deploy/opencode-template.ts +74 -0
- package/packages/agent-hooks/src/deploy/profile.ts +117 -0
- package/packages/agent-hooks/src/deploy/render.ts +162 -0
- package/packages/agent-hooks/src/deploy/source.ts +84 -0
- package/packages/agent-hooks/src/gating/config.ts +514 -0
- package/packages/agent-hooks/src/gating/root.ts +117 -0
- package/packages/agent-hooks/src/hooks/briefing/handler.ts +22 -0
- package/packages/agent-hooks/src/hooks/briefing/index.ts +320 -0
- package/packages/agent-hooks/src/hooks/contract.ts +112 -0
- package/packages/agent-hooks/src/hooks/crg/handler.ts +22 -0
- package/packages/agent-hooks/src/hooks/crg/index.ts +209 -0
- package/packages/agent-hooks/src/hooks/lean-ctx/handler.ts +22 -0
- package/packages/agent-hooks/src/hooks/lean-ctx/index.ts +173 -0
- package/packages/agent-hooks/src/hooks/lean-ctx/mapping.ts +121 -0
- package/packages/agent-hooks/src/hooks/lean-ctx/scope-rewrite.ts +207 -0
- package/packages/agent-hooks/src/hooks/log.ts +233 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/config.ts +58 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/constants.ts +149 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/handler.ts +72 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/index.ts +203 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +212 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/skill-roots.ts +73 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/skills.ts +98 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +115 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +174 -0
- package/packages/agent-hooks/src/hosts/impl/claude.ts +47 -0
- package/packages/agent-hooks/src/hosts/impl/codex.ts +47 -0
- package/packages/agent-hooks/src/hosts/impl/cursor.ts +40 -0
- package/packages/agent-hooks/src/hosts/impl/kimi.ts +47 -0
- package/packages/agent-hooks/src/hosts/impl/opencode.ts +54 -0
- package/packages/agent-hooks/src/hosts/registry.ts +29 -0
- package/packages/agent-hooks/src/hosts/spec.ts +113 -0
- package/packages/agent-hooks/src/lean-ctx/env.ts +106 -0
- package/packages/agent-hooks/src/lean-ctx/mcp.ts +140 -0
- package/packages/agent-hooks/src/lib/spawn-with-timeout.ts +120 -0
- package/packages/agent-hooks/src/log/writer.ts +230 -0
- package/packages/agent-hooks/src/main.ts +269 -0
- package/packages/agent-hooks/src/pre-tool-use/handler.ts +549 -0
- package/packages/agent-hooks/src/rules/engine.ts +293 -0
- package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +51 -0
- package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +320 -0
- package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +249 -0
- package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +258 -0
- package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +731 -0
- package/packages/agent-hooks/src/rules/impl/adl-identity.ts +128 -0
- package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +179 -0
- package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +65 -0
- package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +156 -0
- package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +121 -0
- package/packages/agent-hooks/src/rules/impl/adl-session-required.ts +403 -0
- package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +92 -0
- package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +74 -0
- package/packages/agent-hooks/src/rules/impl/advisory-coverage.ts +43 -0
- package/packages/agent-hooks/src/rules/impl/advisory-finder.ts +62 -0
- package/packages/agent-hooks/src/rules/impl/agent-secrets-stay-unread.ts +173 -0
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +508 -0
- package/packages/agent-hooks/src/rules/impl/fs-canonical-checkout.ts +86 -0
- package/packages/agent-hooks/src/rules/impl/fs-git-internals.ts +75 -0
- package/packages/agent-hooks/src/rules/impl/fs-mv.ts +66 -0
- package/packages/agent-hooks/src/rules/impl/fs-rm.ts +83 -0
- package/packages/agent-hooks/src/rules/impl/fs-trash.ts +140 -0
- package/packages/agent-hooks/src/rules/impl/git-core.ts +101 -0
- package/packages/agent-hooks/src/rules/impl/git-helpers.ts +408 -0
- package/packages/agent-hooks/src/rules/impl/git-history.ts +77 -0
- package/packages/agent-hooks/src/rules/impl/git-paths.ts +139 -0
- package/packages/agent-hooks/src/rules/impl/git-plumbing.ts +167 -0
- package/packages/agent-hooks/src/rules/impl/git-protected-tree.ts +132 -0
- package/packages/agent-hooks/src/rules/impl/git-transitions.ts +292 -0
- package/packages/agent-hooks/src/rules/impl/git-verify.ts +95 -0
- package/packages/agent-hooks/src/rules/impl/git-worktree.ts +265 -0
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +76 -0
- package/packages/agent-hooks/src/rules/impl/messages.ts +128 -0
- package/packages/agent-hooks/src/rules/impl/parse-uncertain.ts +143 -0
- package/packages/agent-hooks/src/rules/impl/pr-completion.ts +35 -0
- package/packages/agent-hooks/src/rules/impl/shell-remote-script-exec.ts +63 -0
- package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +283 -0
- package/packages/agent-hooks/src/rules/impl/tool-bun-test.ts +81 -0
- package/packages/agent-hooks/src/rules/impl/tool-cargo.ts +66 -0
- package/packages/agent-hooks/src/rules/impl/tool-chmod-hook.ts +42 -0
- package/packages/agent-hooks/src/rules/impl/tool-find.ts +82 -0
- package/packages/agent-hooks/src/rules/impl/tool-frontend.ts +83 -0
- package/packages/agent-hooks/src/rules/impl/tool-grep.ts +93 -0
- package/packages/agent-hooks/src/rules/impl/tool-lean-ctx-global.ts +594 -0
- package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +77 -0
- package/packages/agent-hooks/src/rules/ports.ts +178 -0
- package/packages/agent-hooks/src/rules/registry.ts +233 -0
- package/packages/agent-hooks/src/rules/shell/git-identity.ts +1415 -0
- package/packages/agent-hooks/src/rules/shell/git-internals.ts +186 -0
- package/packages/agent-hooks/src/rules/shell/invocation.ts +1083 -0
- package/packages/agent-hooks/src/rules/shell/piped-script.ts +201 -0
- package/packages/agent-hooks/src/rules/shell/prefixes.ts +214 -0
- package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +108 -0
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +149 -0
- package/packages/agent-hooks/src/rules/shell/split.ts +179 -0
- package/packages/agent-hooks/src/rules/shell/substitution.ts +394 -0
- package/packages/agent-hooks/src/rules/shell/token.ts +180 -0
- package/packages/agent-hooks/src/rules/shell/xargs.ts +81 -0
- package/packages/agent-hooks/src/rules/spec.ts +152 -0
- package/packages/agent-hooks/src/surface-policy.ts +37 -0
- package/packages/agent-hooks/tsconfig.json +23 -0
- package/packages/agent-settings/assets/GLOBAL-AGENTS.md +107 -0
- package/packages/agent-settings/assets/agents/architect.toml +30 -0
- package/packages/agent-settings/assets/agents/code-reviewer.toml +27 -0
- package/packages/agent-settings/assets/agents/critic.toml +35 -0
- package/packages/agent-settings/assets/agents/executor.toml +28 -0
- package/packages/agent-settings/assets/agents/explore.toml +25 -0
- package/packages/agent-settings/assets/agents/planner.toml +29 -0
- package/packages/agent-settings/assets/lean-ctx/config.toml +39 -0
- package/packages/agent-settings/assets/lean-ctx/gitignore +6 -0
- package/packages/agent-settings/assets/lean-ctx/layout.toml +5 -0
- package/packages/agent-settings/assets/mcp.json +20 -0
- package/packages/agent-settings/managed/README.md +331 -0
- package/packages/agent-settings/managed/claude-managed-settings.json +150 -0
- package/packages/agent-settings/managed/codex-requirements.toml +105 -0
- package/packages/agent-settings/protected.json +470 -0
- package/packages/agent-settings/src/deploy/agent-render.ts +94 -0
- package/packages/agent-settings/src/deploy/agent-toml.ts +76 -0
- package/packages/agent-settings/src/deploy/agents-deploy.ts +129 -0
- package/packages/agent-settings/src/deploy/doctor.ts +201 -0
- package/packages/agent-settings/src/deploy/index.ts +33 -0
- package/packages/agent-settings/src/deploy/json-pretty.ts +66 -0
- package/packages/agent-settings/src/deploy/lean-ctx-deploy.ts +138 -0
- package/packages/agent-settings/src/deploy/legacy-lock.ts +286 -0
- package/packages/agent-settings/src/deploy/list.ts +135 -0
- package/packages/agent-settings/src/deploy/lock.ts +112 -0
- package/packages/agent-settings/src/deploy/mcp-deploy.ts +175 -0
- package/packages/agent-settings/src/deploy/mcp-inspect.ts +56 -0
- package/packages/agent-settings/src/deploy/mcp-merge.ts +164 -0
- package/packages/agent-settings/src/deploy/mcp-render.ts +80 -0
- package/packages/agent-settings/src/deploy/mcp-source.ts +43 -0
- package/packages/agent-settings/src/deploy/profile.ts +296 -0
- package/packages/agent-settings/src/deploy/settings.ts +65 -0
- package/packages/agent-settings/src/global-agents.ts +230 -0
- package/packages/agent-settings/src/global-surface-sweep.ts +2179 -0
- package/packages/agent-settings/src/kimi-hooks.ts +455 -0
- package/packages/agent-settings/src/opencode-hooks.ts +76 -0
- package/packages/agent-settings/src/surface-policy.ts +441 -0
- package/packages/agent-settings/surface-policy.json +20 -0
- package/packages/agent-skills/assets/code-review/SKILL.md +100 -0
- package/packages/agent-skills/assets/codebase-design/SKILL.md +98 -0
- package/packages/agent-skills/assets/codebase-design/references/DEEPENING.md +37 -0
- package/packages/agent-skills/assets/codebase-design/references/DESIGN-IT-TWICE.md +44 -0
- package/packages/agent-skills/assets/codebase-design/references/TESTABILITY.md +29 -0
- package/packages/agent-skills/assets/debug-issue/SKILL.md +40 -0
- package/packages/agent-skills/assets/diagnosing-bugs/SKILL.md +100 -0
- package/packages/agent-skills/assets/diagnosing-bugs/references/FEEDBACK-LOOP-TACTICS.md +34 -0
- package/packages/agent-skills/assets/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
- package/packages/agent-skills/assets/domain-modeling/SKILL.md +86 -0
- package/packages/agent-skills/assets/domain-modeling/references/ADR-FORMAT.md +47 -0
- package/packages/agent-skills/assets/domain-modeling/references/CONTEXT-FORMAT.md +60 -0
- package/packages/agent-skills/assets/explore-codebase/SKILL.md +41 -0
- package/packages/agent-skills/assets/handoff/SKILL.md +28 -0
- package/packages/agent-skills/assets/implement/SKILL.md +28 -0
- package/packages/agent-skills/assets/refactor-safely/SKILL.md +44 -0
- package/packages/agent-skills/assets/review-changes/SKILL.md +45 -0
- package/packages/agent-skills/assets/tdd/SKILL.md +49 -0
- package/packages/agent-skills/assets/tdd/references/mocking.md +59 -0
- package/packages/agent-skills/assets/tdd/references/tests.md +77 -0
- package/packages/agent-skills/assets/testing/SKILL.md +54 -0
- package/packages/agent-skills/assets/to-feature/SKILL.md +91 -0
- package/packages/agent-skills/assets/to-feature/references/FEATURE-SPEC-TEMPLATE.md +88 -0
- package/packages/agent-skills/assets/to-workitems/SKILL.md +90 -0
- package/packages/agent-skills/assets/to-workitems/references/AZURE-DEVOPS-HIERARCHY.md +118 -0
- package/packages/agent-skills/assets/to-workitems/references/TICKET-TEMPLATES.md +70 -0
- package/packages/agent-skills/assets/wayfinder/SKILL.md +100 -0
- package/packages/agent-skills/assets/wayfinder/references/TEMPLATES.md +35 -0
- package/packages/agent-skills/assets/wayfinder/references/TICKET-TYPES.md +8 -0
- package/packages/agent-skills/deploy-profile.json +9 -0
- package/packages/agent-skills/deploy-profile.schema.json +45 -0
- package/packages/agent-skills/dist/deploy.d.ts +27 -0
- package/packages/agent-skills/dist/deploy.d.ts.map +1 -0
- package/packages/agent-skills/dist/deploy.js +186 -0
- package/packages/agent-skills/dist/deploy.js.map +1 -0
- package/packages/agent-skills/dist/doctor.d.ts +24 -0
- package/packages/agent-skills/dist/doctor.d.ts.map +1 -0
- package/packages/agent-skills/dist/doctor.js +141 -0
- package/packages/agent-skills/dist/doctor.js.map +1 -0
- package/packages/agent-skills/dist/fs-utils.d.ts +8 -0
- package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -0
- package/packages/agent-skills/dist/fs-utils.js +40 -0
- package/packages/agent-skills/dist/fs-utils.js.map +1 -0
- package/packages/agent-skills/dist/index.d.ts +8 -0
- package/packages/agent-skills/dist/index.d.ts.map +1 -0
- package/packages/agent-skills/dist/index.js +8 -0
- package/packages/agent-skills/dist/index.js.map +1 -0
- package/packages/agent-skills/dist/legacy-lock.d.ts +44 -0
- package/packages/agent-skills/dist/legacy-lock.d.ts.map +1 -0
- package/packages/agent-skills/dist/legacy-lock.js +121 -0
- package/packages/agent-skills/dist/legacy-lock.js.map +1 -0
- package/packages/agent-skills/dist/list.d.ts +23 -0
- package/packages/agent-skills/dist/list.d.ts.map +1 -0
- package/packages/agent-skills/dist/list.js +75 -0
- package/packages/agent-skills/dist/list.js.map +1 -0
- package/packages/agent-skills/dist/manifest.d.ts +15 -0
- package/packages/agent-skills/dist/manifest.d.ts.map +1 -0
- package/packages/agent-skills/dist/manifest.js +57 -0
- package/packages/agent-skills/dist/manifest.js.map +1 -0
- package/packages/agent-skills/dist/profile.d.ts +41 -0
- package/packages/agent-skills/dist/profile.d.ts.map +1 -0
- package/packages/agent-skills/dist/profile.js +86 -0
- package/packages/agent-skills/dist/profile.js.map +1 -0
- package/packages/agent-skills/dist/skill-config.d.ts +24 -0
- package/packages/agent-skills/dist/skill-config.d.ts.map +1 -0
- package/packages/agent-skills/dist/skill-config.js +68 -0
- package/packages/agent-skills/dist/skill-config.js.map +1 -0
- package/packages/agent-skills/dist/skill-meta.d.ts +17 -0
- package/packages/agent-skills/dist/skill-meta.d.ts.map +1 -0
- package/packages/agent-skills/dist/skill-meta.js +67 -0
- package/packages/agent-skills/dist/skill-meta.js.map +1 -0
- package/packages/agent-skills/package.json +31 -0
- package/packages/agent-skills/src/deploy.ts +222 -0
- package/packages/agent-skills/src/doctor.ts +178 -0
- package/packages/agent-skills/src/fs-utils.ts +40 -0
- package/packages/agent-skills/src/index.ts +29 -0
- package/packages/agent-skills/src/legacy-lock.ts +152 -0
- package/packages/agent-skills/src/list.ts +94 -0
- package/packages/agent-skills/src/manifest.ts +66 -0
- package/packages/agent-skills/src/profile.ts +128 -0
- package/packages/agent-skills/src/skill-config.ts +75 -0
- package/packages/agent-skills/src/skill-meta.ts +78 -0
- package/packages/agent-skills/tsconfig.build.json +13 -0
- package/packages/agent-skills/tsconfig.json +23 -0
- package/packages/azdo/README.md +111 -0
- package/packages/azdo/package.json +21 -0
- package/packages/azdo/src/azdo-pl.ts +275 -0
- package/packages/azdo/src/azdo-pr-review.ts +160 -0
- package/packages/azdo/src/azdo-pr.ts +289 -0
- package/packages/azdo/src/azdo-repo-doctor.ts +839 -0
- package/packages/azdo/src/azdo-wit.ts +145 -0
- package/packages/azdo/src/cli.ts +251 -0
- package/packages/azdo/src/lib/agent-identity.ts +198 -0
- package/packages/azdo/src/lib/agent-token.ts +167 -0
- package/packages/azdo/src/lib/client.ts +259 -0
- package/packages/azdo/src/lib/graph-identity.ts +153 -0
- package/packages/azdo/src/lib/validate-pr-metadata.ts +57 -0
- package/packages/azdo/src/mcp-server.ts +209 -0
- package/packages/azdo/src/tool-dispatch.ts +204 -0
- package/packages/azdo/tsconfig.json +13 -0
- package/packages/fleet/jobs/git-maintain/src/main.ts +588 -0
- package/packages/fleet/manifest.json +207 -0
- package/packages/fleet/manifest.schema.json +283 -0
- package/packages/fleet/src/default-agent-file.ts +144 -0
- package/packages/fleet/src/install-adl-package.ts +178 -0
- package/packages/fleet/src/install-embedding-model.ts +412 -0
- package/packages/fleet/src/launch-agents.ts +649 -0
- package/packages/fleet/src/managed-settings.ts +278 -0
- package/packages/fleet/src/scratch-reap.ts +601 -0
- package/packages/fleet/src/vscode-settings.ts +705 -0
- package/packages/fleet/systemd/adl-azure-agent-update.service +13 -0
- package/packages/fleet/systemd/adl-azure-agent-update.timer +10 -0
- package/packages/repo-controls/AGENTS.md +96 -0
- package/packages/repo-controls/CLAUDE.md +1 -0
- package/packages/repo-controls/LICENSE +20 -0
- package/packages/repo-controls/README.md +493 -0
- package/packages/repo-controls/assets/enable-integration-auto-complete.mjs +79 -0
- package/packages/repo-controls/assets/promote.ts +371 -0
- package/packages/repo-controls/assets/version-bump.sh +189 -0
- package/packages/repo-controls/azure-pipelines.yml +274 -0
- package/packages/repo-controls/bin/adl-repo-controls.ts +10 -0
- package/packages/repo-controls/bunfig.toml +58 -0
- package/packages/repo-controls/package/adl-compliance/AGENTS.md +163 -0
- package/packages/repo-controls/package/adl-compliance/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/conftest.py +78 -0
- package/packages/repo-controls/package/adl-compliance/pyproject.toml +31 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/__init__.py +50 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +98 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/check.py +210 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-bad-status/docs/architecture/overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-bad-status/docs/decisions/adr-901-proposed.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-broken-backlink/docs/decisions/adr-902-dangling.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-clean/docs/architecture/overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-clean/docs/decisions/adr-900-example.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-frontmatter-mismatch/.plans/b_committed/26-08-08-lifecycle-fixture.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-frontmatter-mismatch/.specs/demo/lifecycle.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-frontmatter-mismatch/docs/decisions/adr-903-frontmatter-mismatch.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-inactive-plan/.plans/c_done/26-08-08-completed-fixture.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-inactive-plan/.specs/demo/lifecycle.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-inactive-plan/docs/decisions/adr-904-completed-plan.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +127 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/check.py +91 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/architecture/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/compliance/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/decisions/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/index.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/operations/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/research/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/stray-root-file.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/totally-made-up/nonsense.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +106 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +291 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/clean/backend/clean.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/excluded/frontend/mobile/src/i18n/locales/zh-CN/strings.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/violation/backend/escaped.rs +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/violation/backend/raw.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/violation/backend//346/226/207/344/273/266.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +193 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/check.py +140 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/fixtures/index-updated-clean/docs/architecture/foo.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/fixtures/index-updated-clean/docs/architecture/index.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/fixtures/index-updated-violation/docs/architecture/foo.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/fixtures/index-updated-violation/docs/architecture/index.md +9 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/test_check.py +98 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +378 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +192 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-clean/docs/index.md +14 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-clean/docs/one.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-clean/docs/two.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-clean/docs-knowledge-indexes.yaml +20 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-duplicate/docs/index.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-duplicate/docs/one.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-duplicate/docs/two.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-duplicate/docs-knowledge-indexes.yaml +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-missing-entry/docs/index.md +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-missing-entry/docs/one.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-missing-entry/docs/two.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-missing-entry/docs-knowledge-indexes.yaml +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +102 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/check.py +387 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/fixtures/ledger-bad-date/plans/LEDGER.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/fixtures/ledger-clean/plans/LEDGER.md +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/fixtures/ledger-empty-table/plans/LEDGER.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/fixtures/ledger-long-event/plans/LEDGER.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/fixtures/ledger-violation/plans/LEDGER.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +427 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/check.py +84 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/fixtures/markdown-structure-bad-fence/docs/bad-fence.md +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/fixtures/markdown-structure-bad-fence/docs/valid.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/fixtures/markdown-structure-bad-frontmatter/docs/bad-front-matter.md +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/fixtures/markdown-structure-bad-frontmatter/docs/valid.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/fixtures/markdown-structure-clean/docs/valid.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/test_check.py +126 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +210 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +119 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs/architecture/bad-status.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +49 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +159 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/check.py +578 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-clean/docs/architecture/backend/crate-overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-clean/docs/architecture/team/team-overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-clean/docs/compliance/controls/control-matrix.md +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-clean/docs/compliance/controls/control-matrix.yaml +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-clean/docs/research/benchmarks/note.md +24 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/backend/crate-overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/product/stable-delivery.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/product/stable-recommendation.md +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/product/target-narration.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/team/team-overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/compliance/controls/control-matrix.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/compliance/controls/control-matrix.yaml +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/research/benchmarks/bad-research.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +461 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/check.py +124 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/.workflows/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/.workflows/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/CLAUDE.md +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/INVARIANTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/bad-pointer/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/bad-pointer/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/docs/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/docs/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/missing-pair/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/owned/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/owned/CLAUDE.md +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/test_check.py +116 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/ci_paths/__init__.py +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/ci_paths/check.py +380 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/ci_paths/fixtures/redeclared-workflows-tree/automation/pipelines/pr-validation.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/ci_paths/test_check.py +274 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +227 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/fresh/fresh.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub1/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub10/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub11/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub2/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub3/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub4/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub5/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub6/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub7/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub8/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub9/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/services/i18n/locales/de/common.json +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/vendored-crate/Cargo.toml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/fresh/fresh.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub1/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub10/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub11/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub2/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub3/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub4/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub5/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub6/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub7/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub8/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub9/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +138 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +240 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/fixtures/markdown-trees-clean/.plans/a_new/plan.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/fixtures/markdown-trees-clean/backend/AGENTS.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/fixtures/markdown-trees-clean/docs/page.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/fixtures/markdown-trees-stray/backend/notes.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/fixtures/markdown-trees-stray/docs/page.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +220 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/__init__.py +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +225 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/fixtures/open-work-cap-clean/plans/GAPS-AND-FINDINGS.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/fixtures/open-work-cap-clean/plans/features/az601-clean/spec.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +330 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +240 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/agent/crates/enact-providers/src/snapshots/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/backend/crates/enact-app/assets/builtin-assistants/avatars/assistant.jpg +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/backend/crates/enact-assets/assets/logos/tools/coding/tool.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/backend/crates/enact-session/src/backend/codex_init_prompt.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/mobile/assets/images/icon.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/packages/desktop/src/renderer/assets/logos/brand/app.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/packages/desktop/src/renderer/assets/themes/default-theme.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/public/pwa/icon-192.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/resources/product.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-stray/apps/legacy/file.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-stray/backend/crates/enact-session/src/backend/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-stray/frontend/unapproved/screenshot.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +230 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plan_metadata.py +53 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/check.py +438 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/items/az351-restore-entrypoint.md +9 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/spec.md +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/templates/feature.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-violation/plans/features/az347-test-coverage/items/az351-restore-entrypoint.md +9 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-violation/plans/features/az347-test-coverage/spec.md +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +461 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/check.py +62 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/NotAMigration.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/0001_long_prefix.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/001_init.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/002_add_index.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/003-dashed-slug.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/004_MixedCase.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/005_trailing space.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/01_short_prefix.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/not-a-migration.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/test_check.py +116 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +188 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/.plans/c_done/26-07-27-history.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/docs/README.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/docs/architecture/product/links.md +20 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/docs/architecture/product/route-target.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/.plans/c_done/26-07-27-history.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/docs/README.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/docs/architecture/product/links.md +20 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/docs/architecture/product/route-target.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/test_check.py +166 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +135 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.agents/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.changeset/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.claude/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.code-review-graph/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.code-review-graph_old/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.codex/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.cursor/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.cursorrules +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.dockerignore +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.docs/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.donors/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.gitattributes +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.kimi-code/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.lfsconfig +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.mcp.json +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.opencode/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.workflows/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/CHANGELOG.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/CLAUDE-INVARIANTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/INDEPENDENT-VERIFICATION.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/INVARIANTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/LICENSE +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/NOTICE +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/RELEASE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/VERSION +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/backend/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/compliance/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/dev/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/docker/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/docs/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/frontend/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/infra/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/justfile +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/opencode.jsonc +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/rule-tests/undeclared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/rules/undeclared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/unapproved-root/undeclared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/undeclared-root-file.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +122 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +290 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/.changeset/some-change.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/.plans/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/.specs/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/.workflows/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/CHANGELOG.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/CLAUDE.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/INDEPENDENT-VERIFICATION.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/INVARIANTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/README.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/RELEASE.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/STRAY.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/docs/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/docs/architecture/note.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/frontend/README.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-missing-guide/.workflows/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-missing-guide/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-missing-guide/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-missing-guide/docs/overview.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-missing-guide/plans/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +329 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +127 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/a/b/c/d/at-limit.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/a/b/c/d/e/too-deep.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-01.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-02.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-03.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-04.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-05.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-06.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-07.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-08.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-09.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-10.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-11.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-12.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-13.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-14.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-15.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-16.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +163 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +169 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/attribute-without-conversion/.gitattributes +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/attribute-without-conversion/large file.bin +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/clean/.gitattributes +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/clean/large file.bin +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/clean/small.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/missing-filter/large file.bin +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/unmatched-extension/.gitattributes +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/unmatched-extension/payload.dat +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +133 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/check.py +129 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/fixtures/disjoint/gate-registry.yaml +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/fixtures/empty/gate-registry.yaml +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/fixtures/overlapping/gate-registry.yaml +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/test_check.py +109 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/check.py +149 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/fixtures/clean/docs/readme.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/fixtures/relevant/VERSION +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/test_check.py +151 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/check.py +202 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/.workflows/changesets/package.json +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/.workflows/package.json +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/CHANGELOG.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/VERSION +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/.workflows/changesets/package.json +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/.workflows/package.json +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/CHANGELOG.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/VERSION +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/test_check.py +162 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/check.py +103 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/git-bad.sh +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/git-note.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/good.sh +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/grep-bad.sh +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/grep-note.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/grep-trailing.sh +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/notes.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/elsewhere/loose-git.sh +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/elsewhere/loose-grep.sh +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/test_check.py +117 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/__init__.py +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +265 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/fixtures/ignored-paths/keep.log +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/fixtures/ignored-paths/src/main.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +180 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/check.py +84 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/fixtures/license-declared-clean/LICENSE +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/fixtures/license-declared-mismatch/LICENSE +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/fixtures/license-declared-missing/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/test_check.py +66 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +167 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/Cargo.lock +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/Cargo.toml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/rust-toolchain.toml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/src/main.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/frontend/bun.lock +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/Cargo.lock +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/Cargo.toml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/rust-toolchain.toml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/src/main.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/frontend/bun.lock +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +109 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +483 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/ast_grep.py +199 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/batch.py +52 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +303 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +106 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +99 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/errors.py +32 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/finding.py +65 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/models.py +40 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/receipt.py +63 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/scope.py +82 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/verdict.py +161 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +131 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.toml +30 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +65 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +791 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.schema.yaml +176 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +791 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/grants-registry.yaml +112 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/grants.py +129 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +281 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +250 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/severity-policy.yaml +114 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/providers/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +371 -0
- package/packages/repo-controls/package/adl-compliance/uv.lock +199 -0
- package/packages/repo-controls/package.json +33 -0
- package/packages/repo-controls/scripts/hooks/commit-msg +63 -0
- package/packages/repo-controls/scripts/hooks/lib/hook-log.sh +62 -0
- package/packages/repo-controls/scripts/hooks/post-checkout +15 -0
- package/packages/repo-controls/scripts/hooks/post-commit +18 -0
- package/packages/repo-controls/scripts/hooks/pre-commit +82 -0
- package/packages/repo-controls/scripts/hooks/pre-push +144 -0
- package/packages/repo-controls/src/azdo-push.ts +463 -0
- package/packages/repo-controls/src/azure-devops-governance.ts +248 -0
- package/packages/repo-controls/src/azure-devops-remote.ts +61 -0
- package/packages/repo-controls/src/cli.ts +188 -0
- package/packages/repo-controls/src/compliance-config.ts +200 -0
- package/packages/repo-controls/src/config.ts +690 -0
- package/packages/repo-controls/src/constants.ts +97 -0
- package/packages/repo-controls/src/coverage-ratchet.ts +153 -0
- package/packages/repo-controls/src/doc-freshness.ts +172 -0
- package/packages/repo-controls/src/doctor.ts +304 -0
- package/packages/repo-controls/src/findings-ratchet.ts +163 -0
- package/packages/repo-controls/src/gitignore-block.ts +253 -0
- package/packages/repo-controls/src/hook-log.ts +72 -0
- package/packages/repo-controls/src/hook.ts +694 -0
- package/packages/repo-controls/src/install.ts +506 -0
- package/packages/repo-controls/src/integrity.ts +104 -0
- package/packages/repo-controls/src/promote.ts +25 -0
- package/packages/repo-controls/src/runtime.ts +110 -0
- package/packages/repo-controls/src/workflows-drift.ts +106 -0
- package/packages/repo-controls/src/worktree-guard.ts +272 -0
- package/packages/repo-controls/src/worktree-limit.ts +11 -0
- package/packages/repo-controls/tsconfig.json +14 -0
- package/packages/repo-controls/workflows/scripts/release/verify-npm-artifact.ts +119 -0
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editing the files that wire the host's hooks or un-manage this repo.
|
|
3
|
+
*
|
|
4
|
+
* Handoff 5, rule 5: deny Write/Edit/MultiEdit/NotebookEdit on
|
|
5
|
+
* `.claude/settings.json`, `.claude/settings.local.json`,
|
|
6
|
+
* `.codex/config.toml`, or `adl-config.toml`. These are the files that
|
|
7
|
+
* either install the hook into the host (`.claude/settings.json`,
|
|
8
|
+
* `.codex/config.toml`, including the `.local.json` overrides) or arm the
|
|
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.
|
|
12
|
+
*
|
|
13
|
+
* Decision 13 (STATUS.md 12p, 2026-09-29): the managed-
|
|
14
|
+
* hooks lock is off, so these per-repo carrier files are now the ONLY
|
|
15
|
+
* enforcement layer for the hosts that read them — three more joined the
|
|
16
|
+
* set for exactly that reason: `.codex/hooks.json`, `.cursor/hooks.json`,
|
|
17
|
+
* 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
|
+
* Measured against the real engine before this fix: Write
|
|
20
|
+
* `.codex/hooks.json` / Edit `.cursor/hooks.json` / Write
|
|
21
|
+
* `.opencode/plugins/adl-repo.ts` all had `blocked: false`, while the
|
|
22
|
+
* original four's own control case (`.claude/settings.json`) already had
|
|
23
|
+
* `blocked: true`.
|
|
24
|
+
*
|
|
25
|
+
* The list is hard-coded here on purpose. `adl-config.toml`'s own
|
|
26
|
+
* `[hooks] enabled` already lets a repo switch the whole hook system
|
|
27
|
+
* off; allowing `[rules."agent.tamper-protection"] enabled = false` in
|
|
28
|
+
* the same file is the same switch wearing a different hat. A repo that
|
|
29
|
+
* legitimately needs a different allowlist should patch this file in a
|
|
30
|
+
* PR, not in a session.
|
|
31
|
+
*
|
|
32
|
+
* The file names match against the FULL path and against the basename so
|
|
33
|
+
* `Write .claude/settings.json` AND `Write /Users/x/repo/.claude/settings.json`
|
|
34
|
+
* both fire, but `Write .claude/SETTINGS.json.bak` does NOT (the
|
|
35
|
+
* case-sensitive suffix check rejects it).
|
|
36
|
+
*
|
|
37
|
+
* Shell-write coverage (STATUS.md 12p, decision 13 follow-up, 2026-09-29):
|
|
38
|
+
* the tool-call gate above never saw a shell command at all — `echo x >
|
|
39
|
+
* .cursor/hooks.json`, `tee`, `mv`/`cp`/`install`/`ln -sf`, `sed -i`/
|
|
40
|
+
* `perl -pi`, `truncate`, `trash`/`rm`/`unlink`/`shred`, and `dd of=` were
|
|
41
|
+
* every one of them `{blocked: false}` against all seven protected files,
|
|
42
|
+
* measured directly against the real engine before this fix. Closed via
|
|
43
|
+
* three additional match() branches:
|
|
44
|
+
* - `inv.kind === 'protected-carrier-write'` — the generic-command half
|
|
45
|
+
* (redirection/tee/mv/cp/install/ln/sed/perl/truncate/trash/rm/unlink/
|
|
46
|
+
* shred/dd), classified by `shell/protected-carrier-writes.ts` and wired
|
|
47
|
+
* into `shell/invocation.ts`'s `walk()` exactly like `git-internals-write`
|
|
48
|
+
* — which is what makes nested `bash -c`/`sh -c` covered for free (that
|
|
49
|
+
* detection runs on every walked piece, top-level or nested).
|
|
50
|
+
* - `inv.kind === 'git'` with subcommand `rm`, or `checkout`/`restore`/
|
|
51
|
+
* `reset` with a protected path after `--` — `git rm`/`checkout --`/etc.
|
|
52
|
+
* on one of these files IS already blocked today by generic, target-
|
|
53
|
+
* independent rules (`git.rm` bans every `git rm`; `git.checkout-dashdash`
|
|
54
|
+
* bans every `git checkout --`), but neither is protecting THESE files
|
|
55
|
+
* specifically and neither would survive being disabled on its own —
|
|
56
|
+
* this rule (AGENT_RULES, evaluated before GIT_RULES — see registry.ts)
|
|
57
|
+
* now claims the protected-path case with its own message before either
|
|
58
|
+
* generic rule gets a turn.
|
|
59
|
+
* - A coarse textual check on `ctx.command` (the same pattern as
|
|
60
|
+
* `adl.human-azdo-bypass`'s `os.environ`/`process.env` detection) for an
|
|
61
|
+
* interpreter one-liner writing a protected path — `python3 -c
|
|
62
|
+
* "open('.codex/hooks.json','w')..."`, `node -e
|
|
63
|
+
* "fs.writeFileSync('.cursor/hooks.json', ...)"`. Not a parser: a
|
|
64
|
+
* write-shaped call plus a protected path's text anywhere in the command
|
|
65
|
+
* is enough to deny, same tradeoff `adl.human-azdo-bypass` already makes.
|
|
66
|
+
*
|
|
67
|
+
* A write whose target is a dynamic command substitution
|
|
68
|
+
* (`$(git rev-parse --show-toplevel)/…`) is not this rule's to classify at
|
|
69
|
+
* all — `shell/invocation.ts`'s existing, target-agnostic
|
|
70
|
+
* `unresolvableRedirectionWriteTargets`/`unresolvableOperandWriteTargets`
|
|
71
|
+
* checks already fail closed on ANY dynamic write target via
|
|
72
|
+
* `parse.uncertain`, protected carrier or not.
|
|
73
|
+
*/
|
|
74
|
+
import type { Token } from '../shell/token.ts'
|
|
75
|
+
import { tokenValue } from '../shell/token.ts'
|
|
76
|
+
import type { Invocation } from '../shell/invocation.ts'
|
|
77
|
+
import { PROTECTED_CARRIER_PATHS, protectedCarrierDirMatch, protectedCarrierMatch } from '../shell/protected-carriers.ts'
|
|
78
|
+
import { mcpToolName } from './mcp-tool.ts'
|
|
79
|
+
import type { Finding, MessageContext, RuleContext, RuleSpec } from '../spec.ts'
|
|
80
|
+
import { noParams } from '../spec.ts'
|
|
81
|
+
|
|
82
|
+
/** The tool name a host actually sends, past an `mcp__<server>__` prefix (e.g. `mcp__lean_ctx__ctx_patch` → `ctx_patch`) — unprefixed names (Claude/Codex/Kimi/Cursor/OpenCode's own tool names) pass through unchanged. */
|
|
83
|
+
function logicalToolName(tool: string): string {
|
|
84
|
+
if (!tool.startsWith('mcp__')) return tool
|
|
85
|
+
return mcpToolName(tool) ?? tool
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Tools whose `input.file_path` / `input.notebook_path` / `input.path` /
|
|
90
|
+
* `input.filePath` decides what the edit targets — matched case-insensitively
|
|
91
|
+
* (F4, independent review, 2026-09-29): OpenCode's own plugin
|
|
92
|
+
* (`.opencode/plugins/adl-repo.ts`'s `tool.execute.before`) sends its OWN
|
|
93
|
+
* lowercase tool names (`edit`, `write`), not Claude/Codex/Kimi's
|
|
94
|
+
* capitalized ones, and its `tool_input` (`output.args`) carries the target
|
|
95
|
+
* as camelCase `filePath`, not `file_path`.
|
|
96
|
+
*/
|
|
97
|
+
/**
|
|
98
|
+
* P2 (independent review, 2026-09-29): widened beyond Claude/Codex/Kimi's
|
|
99
|
+
* own capitalized names — one normalized (lowercase) list covering every
|
|
100
|
+
* edit-tool spelling a supported host actually sends:
|
|
101
|
+
* - `strreplace`/`str_replace_editor`/`edit_file`/`str_replace`/
|
|
102
|
+
* `replace_in_file`/`create_file`/`write_file` — Cursor's own matcher
|
|
103
|
+
* regex names every one of these (`deploy-profile.json`'s
|
|
104
|
+
* `surfaces[].matchers` entry for cursor, line ~33) as an alias its
|
|
105
|
+
* generated carrier maps onto `Write`; this rule reads the SAME source
|
|
106
|
+
* list rather than a second, hand-copied one.
|
|
107
|
+
* - `delete` — Cursor's own delete-file tool.
|
|
108
|
+
* - `writefile`/`strreplacefile` — Kimi's own tool names (`WriteFile`/
|
|
109
|
+
* `StrReplaceFile`), lower-cased same as every other host's.
|
|
110
|
+
* - `ctx_patch`/`ctx_edit` — the lean-ctx MCP server's own edit tools
|
|
111
|
+
* (`mcp__lean_ctx__ctx_patch`/`ctx_edit`); their target field is `path`,
|
|
112
|
+
* already read below alongside `file_path`/`notebook_path`/`filePath`.
|
|
113
|
+
* `apply_patch` stays a SEPARATE branch (its own patch-header parsing, not
|
|
114
|
+
* a `file_path`-shaped field) — see `applyPatchTarget`.
|
|
115
|
+
*/
|
|
116
|
+
const EDIT_TOOL_NAMES = new Set([
|
|
117
|
+
'write',
|
|
118
|
+
'edit',
|
|
119
|
+
'multiedit',
|
|
120
|
+
'notebookedit',
|
|
121
|
+
'patch',
|
|
122
|
+
'strreplace',
|
|
123
|
+
'str_replace_editor',
|
|
124
|
+
'edit_file',
|
|
125
|
+
'str_replace',
|
|
126
|
+
'replace_in_file',
|
|
127
|
+
'create_file',
|
|
128
|
+
'write_file',
|
|
129
|
+
'delete',
|
|
130
|
+
'writefile',
|
|
131
|
+
'strreplacefile',
|
|
132
|
+
'ctx_patch',
|
|
133
|
+
'ctx_edit',
|
|
134
|
+
])
|
|
135
|
+
|
|
136
|
+
function readStringField(input: Readonly<Record<string, unknown>>, key: string): string {
|
|
137
|
+
const value = input[key]
|
|
138
|
+
return typeof value === 'string' ? value : ''
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Codex's `apply_patch` (F4): its patch body lives in `input.command`
|
|
143
|
+
* (`handler.ts`'s `toDecideInput` special-cases this tool to a `tool-call`
|
|
144
|
+
* precisely so it reaches here instead of being walked as shell text), and
|
|
145
|
+
* the path it targets is named in a `*** Add File:`/`*** Update File:`/
|
|
146
|
+
* `*** Delete File:`/`*** Move to:` header — never a `file_path`-shaped
|
|
147
|
+
* field. Coarse (no real patch parser): any one of those headers naming a
|
|
148
|
+
* protected path is enough to deny.
|
|
149
|
+
*/
|
|
150
|
+
const PATCH_HEADER_RE = /^\*\*\* (?:Add File|Update File|Delete File|Move to): (.+)$/gm
|
|
151
|
+
|
|
152
|
+
function applyPatchTarget(patchBody: string): string | null {
|
|
153
|
+
for (const match of patchBody.matchAll(PATCH_HEADER_RE)) {
|
|
154
|
+
const path = (match[1] ?? '').trim()
|
|
155
|
+
if (protectedCarrierMatch(path) !== null) return path
|
|
156
|
+
}
|
|
157
|
+
return null
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function toolCallTarget(inv: Invocation & { kind: 'tool-call' }): string | null {
|
|
161
|
+
const name = logicalToolName(inv.tool).toLowerCase()
|
|
162
|
+
// apply_patch / OpenCode's own `patch` tool: the patch body is
|
|
163
|
+
// `input.command` (Codex) or `input.patchText` (OpenCode's own field
|
|
164
|
+
// name for the same shape, P2) — never a `file_path`-shaped field.
|
|
165
|
+
if (name === 'apply_patch' || name === 'patch') {
|
|
166
|
+
const body = readStringField(inv.input, 'command') + readStringField(inv.input, 'patchText')
|
|
167
|
+
if (body.length > 0) return applyPatchTarget(body)
|
|
168
|
+
}
|
|
169
|
+
if (!EDIT_TOOL_NAMES.has(name)) return null
|
|
170
|
+
// F8 (fourth independent review, 2026-09-29): Cursor's real `edit_file`
|
|
171
|
+
// schema names its path argument `target_file` (confirmed via Cursor's
|
|
172
|
+
// own published tool schema/system-prompt documentation).
|
|
173
|
+
const filePath =
|
|
174
|
+
readStringField(inv.input, 'file_path') + readStringField(inv.input, 'notebook_path') + readStringField(inv.input, 'filePath') + readStringField(inv.input, 'target_file')
|
|
175
|
+
const path = readStringField(inv.input, 'path')
|
|
176
|
+
for (const candidate of [filePath, path]) {
|
|
177
|
+
if (candidate.length === 0) continue
|
|
178
|
+
if (protectedCarrierMatch(candidate) !== null) return candidate
|
|
179
|
+
}
|
|
180
|
+
return null
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** The path operands after a `--` in `rest` (git's own pathspec separator). */
|
|
184
|
+
function pathsAfterDashDash(rest: readonly Token[]): readonly string[] {
|
|
185
|
+
const index = rest.findIndex((token) => tokenValue(token) === '--')
|
|
186
|
+
return index < 0 ? [] : rest.slice(index + 1).map(tokenValue)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** The non-option operands (`--` itself excluded) — used for the no-`--` positional path forms below. */
|
|
190
|
+
function nonOptionValues(rest: readonly Token[]): readonly string[] {
|
|
191
|
+
return rest.map(tokenValue).filter((value) => value !== '--' && (!value.startsWith('-') || value === '-'))
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* `git checkout` ALWAYS restores the WORKTREE for a named path — there is no
|
|
196
|
+
* staged-only variant (that is `git restore --staged`'s job) — so every
|
|
197
|
+
* shape is checked: `git checkout -- <path>` and, P1 (second independent
|
|
198
|
+
* review, 2026-09-29), the equally real `git checkout <rev> <path>` form
|
|
199
|
+
* with no `--` at all (>= 2 non-option operands; the LAST one is the path).
|
|
200
|
+
*/
|
|
201
|
+
function checkoutTarget(rest: readonly Token[]): string | null {
|
|
202
|
+
const afterDashDash = pathsAfterDashDash(rest)
|
|
203
|
+
if (afterDashDash.length > 0) {
|
|
204
|
+
for (const value of afterDashDash) {
|
|
205
|
+
if (protectedCarrierMatch(value) !== null) return value
|
|
206
|
+
}
|
|
207
|
+
return null
|
|
208
|
+
}
|
|
209
|
+
const operands = nonOptionValues(rest)
|
|
210
|
+
if (operands.length < 2) return null
|
|
211
|
+
const path = operands[operands.length - 1] as string
|
|
212
|
+
return protectedCarrierMatch(path) !== null ? path : null
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* `git restore` touches the WORKTREE by default; `--staged`/`-S` makes it an
|
|
217
|
+
* index-only unstage UNLESS `--worktree`/`-W` is ALSO given (both flags
|
|
218
|
+
* together restore both). P1 (second independent review, 2026-09-29): a
|
|
219
|
+
* plain `git restore --staged -- <path>` must be ALLOWED — it never
|
|
220
|
+
* touches the file this rule exists to protect from being overwritten.
|
|
221
|
+
*/
|
|
222
|
+
function restoreTouchesWorktree(rest: readonly Token[]): boolean {
|
|
223
|
+
const values = rest.map(tokenValue)
|
|
224
|
+
const staged = values.some((value) => value === '--staged' || value === '-S')
|
|
225
|
+
if (!staged) return true
|
|
226
|
+
return values.some((value) => value === '--worktree' || value === '-W')
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function restoreTarget(rest: readonly Token[]): string | null {
|
|
230
|
+
if (!restoreTouchesWorktree(rest)) return null
|
|
231
|
+
const afterDashDash = pathsAfterDashDash(rest)
|
|
232
|
+
const candidates = afterDashDash.length > 0 ? afterDashDash : nonOptionValues(rest)
|
|
233
|
+
for (const value of candidates) {
|
|
234
|
+
if (protectedCarrierMatch(value) !== null) return value
|
|
235
|
+
}
|
|
236
|
+
return null
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* `git reset [<tree>] [--] <paths>...` only ever updates the INDEX for
|
|
241
|
+
* those paths — never the worktree — regardless of any flag other than
|
|
242
|
+
* `--hard`/`--merge`/`--keep`, none of which accepts a pathspec in real
|
|
243
|
+
* git (a bare `git reset --hard` with no path at all is `git.reset`'s own
|
|
244
|
+
* unconditional deny to catch, not this rule's — there is no specific
|
|
245
|
+
* carrier PATH for this function to find there). P1 (second independent
|
|
246
|
+
* review, 2026-09-29): `git reset -- <path>` and `git reset HEAD --
|
|
247
|
+
* <path>` must be ALLOWED — they only unstage.
|
|
248
|
+
*/
|
|
249
|
+
function resetTouchesWorktree(rest: readonly Token[]): boolean {
|
|
250
|
+
return rest.some((token) => {
|
|
251
|
+
const value = tokenValue(token)
|
|
252
|
+
return value === '--hard' || value === '--merge' || value === '--keep'
|
|
253
|
+
})
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function resetTarget(rest: readonly Token[]): string | null {
|
|
257
|
+
if (!resetTouchesWorktree(rest)) return null
|
|
258
|
+
for (const value of pathsAfterDashDash(rest)) {
|
|
259
|
+
if (protectedCarrierMatch(value) !== null) return value
|
|
260
|
+
}
|
|
261
|
+
return null
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** `git rm <protected>` (any form), or `git checkout|restore|reset` in a WORKTREE-changing form naming `<protected>`. */
|
|
265
|
+
/** `git rm`/`git mv`: every non-option operand is a candidate (for `mv`, moving a carrier away OR overwriting one with something else are both tamper). */
|
|
266
|
+
function anyOperandTarget(rest: readonly Token[]): string | null {
|
|
267
|
+
for (const token of rest) {
|
|
268
|
+
const value = tokenValue(token)
|
|
269
|
+
if (value === '--' || value.startsWith('-')) continue
|
|
270
|
+
// F5 (fourth independent review, 2026-09-29): `git mv .claude
|
|
271
|
+
// .claude-old` moves the WHOLE carrier directory away — file-level
|
|
272
|
+
// `protectedCarrierMatch` alone never saw this.
|
|
273
|
+
const hit = protectedCarrierMatch(value) ?? protectedCarrierDirMatch(value)
|
|
274
|
+
if (hit !== null) return value
|
|
275
|
+
}
|
|
276
|
+
return null
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function gitTarget(inv: Invocation & { kind: 'git' }): string | null {
|
|
280
|
+
// P2 (independent review, 2026-09-29): `git mv` of a carrier (either
|
|
281
|
+
// operand — moving it away, or overwriting it with something else).
|
|
282
|
+
if (inv.subcommand === 'rm' || inv.subcommand === 'mv') return anyOperandTarget(inv.rest)
|
|
283
|
+
if (inv.subcommand === 'checkout') return checkoutTarget(inv.rest)
|
|
284
|
+
if (inv.subcommand === 'restore') return restoreTarget(inv.rest)
|
|
285
|
+
if (inv.subcommand === 'reset') return resetTarget(inv.rest)
|
|
286
|
+
// P2: `git checkout-index` writes working-tree files from the index for
|
|
287
|
+
// named paths — the plumbing sibling of `git checkout -- <path>`. `-a`/
|
|
288
|
+
// `--all` (every staged file, no specific path named) is a known,
|
|
289
|
+
// documented gap — not handled here.
|
|
290
|
+
if (inv.subcommand === 'checkout-index') return anyOperandTarget(inv.rest)
|
|
291
|
+
return null
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* `git apply`/the standalone `patch` utility (P2, independent review,
|
|
296
|
+
* 2026-09-29): the path a patch actually modifies lives INSIDE the patch
|
|
297
|
+
* file's own headers, not (usually) as a command-line operand at all —
|
|
298
|
+
* `git apply some.patch` names the PATCH FILE, never its target. Coarse,
|
|
299
|
+
* whole-command (same tradeoff `interpreterTarget`/`coarsePathMention`
|
|
300
|
+
* already make elsewhere in this file): a protected path's text ANYWHERE
|
|
301
|
+
* on the line is enough to deny — reading the patch file's own content to
|
|
302
|
+
* parse its `--- a/<path>`/`+++ b/<path>` headers is out of scope for a
|
|
303
|
+
* static, pre-execution hook (it would need to read the file from disk,
|
|
304
|
+
* which this hook does not do for any other check either).
|
|
305
|
+
*/
|
|
306
|
+
/** `git apply` flags that inspect a patch without applying anything (F7, fourth independent review, 2026-09-29). */
|
|
307
|
+
const DRY_RUN_GIT_APPLY_FLAGS: ReadonlySet<string> = new Set(['--check', '--stat', '--numstat', '--summary'])
|
|
308
|
+
|
|
309
|
+
function coarsePathMention(command: string): string | null {
|
|
310
|
+
for (const protectedPath of PROTECTED_CARRIER_PATHS) {
|
|
311
|
+
if (command.includes(protectedPath)) return protectedPath
|
|
312
|
+
const base = protectedPath.slice(protectedPath.lastIndexOf('/') + 1)
|
|
313
|
+
if (command.includes(base)) return protectedPath
|
|
314
|
+
}
|
|
315
|
+
return null
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Live false positive (third independent review, 2026-09-29): the OLD check
|
|
320
|
+
* paired "some write call anywhere in the command" (`WRITE_CALL_RE.test`)
|
|
321
|
+
* with "a carrier path anywhere in the command text" (`coarsePathMention`)
|
|
322
|
+
* — two UNCORRELATED checks. A heredoc-fed `python3 - <<'EOF'` writing an
|
|
323
|
+
* unrelated file (e.g. `STATUS.md`) whose own written TEXT merely mentioned
|
|
324
|
+
* `.codex/config.toml` (a docstring, a log line, a commit message) was
|
|
325
|
+
* 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
|
|
329
|
+
* WRITE-CALL'S OWN TARGET ARGUMENT specifically (group 1) — `open(TARGET,
|
|
330
|
+
* 'w'|'a'|'x'…)`, `Path(TARGET).write_text/write_bytes(...)`,
|
|
331
|
+
* `os.remove/unlink(TARGET)`, `os.rename(SRC, TARGET)`,
|
|
332
|
+
* `shutil.move/copy/copy2/copyfile(SRC, TARGET)`,
|
|
333
|
+
* `fs.writeFileSync|appendFileSync|rmSync|unlinkSync|copyFileSync|truncateSync(TARGET, …)`,
|
|
334
|
+
* `fs.renameSync(SRC, TARGET)`, `Bun.write(TARGET, …)`, `File.write(TARGET,
|
|
335
|
+
* …)` (Ruby), `open(FH, '>'|'>>', TARGET)` (Perl 3-arg open) — a carrier
|
|
336
|
+
* path is only a match when it appears THERE. `writeCallTargets` extracts
|
|
337
|
+
* every captured target; `targetNamesCarrierPath` decides each one: a
|
|
338
|
+
* quoted string literal (or f-string) is checked directly
|
|
339
|
+
* (`protectedCarrierMatch`); a bare, unresolvable identifier/expression is
|
|
340
|
+
* fail-closed ONLY when that EXACT identifier is separately assigned a
|
|
341
|
+
* carrier-path string literal earlier in the same code (`p = '.codex/
|
|
342
|
+
* config.toml'; open(p, 'w')`) — an unrelated variable, or one assigned
|
|
343
|
+
* something else, is not a match. A capture that is a more complex
|
|
344
|
+
* expression (neither a literal nor a bare identifier — string
|
|
345
|
+
* concatenation, a function call, …) cannot be correlated at all and is
|
|
346
|
+
* left alone (allowed), the same "cannot resolve, so cannot deny" stance
|
|
347
|
+
* `adl.session-required-for-writes`'s own destination classification takes
|
|
348
|
+
* for an unresolved git push remote.
|
|
349
|
+
*
|
|
350
|
+
* `ARG` allows one level of nested parens (`os.path.join(a, b)` as a
|
|
351
|
+
* target) but otherwise stops at the next comma/paren — coarse, matching
|
|
352
|
+
* every other regex-based check in this file, not a real expression parser.
|
|
353
|
+
*/
|
|
354
|
+
const ARG = `((?:[^,()]|\\([^()]*\\))+)`
|
|
355
|
+
/** `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
|
+
const FS_QUALIFIED_PREFIX = `(?:\\bfs|require\\(\\s*['"]fs['"]\\s*\\))\\s*\\.\\s*(?:promises\\s*\\.\\s*)?`
|
|
357
|
+
/** The SAME prefix, but OPTIONAL — F6 (fourth independent review, 2026-09-29): `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
|
+
const FS_SYNC_OPTIONAL_PREFIX = `(?:${FS_QUALIFIED_PREFIX})?`
|
|
359
|
+
const WRITE_TARGET_PATTERNS: readonly RegExp[] = [
|
|
360
|
+
new RegExp(`\\bopen\\s*\\(\\s*${ARG}\\s*,\\s*['"][wax]`, 'g'),
|
|
361
|
+
new RegExp(`\\bPath\\s*\\(\\s*${ARG}\\s*\\)\\s*\\.\\s*write_(?:text|bytes)\\s*\\(`, 'g'),
|
|
362
|
+
new RegExp(`\\bos\\.(?:remove|unlink)\\s*\\(\\s*${ARG}\\s*\\)`, 'g'),
|
|
363
|
+
new RegExp(`\\bos\\.rename\\s*\\(\\s*${ARG}\\s*,\\s*${ARG}\\s*\\)`, 'g'),
|
|
364
|
+
new RegExp(`\\bshutil\\.(?:move|copy2?|copyfile)\\s*\\(\\s*${ARG}\\s*,\\s*${ARG}\\s*\\)`, 'g'),
|
|
365
|
+
new RegExp(`${FS_SYNC_OPTIONAL_PREFIX}(?:writeFileSync|appendFileSync|rmSync|unlinkSync|copyFileSync|truncateSync)\\s*\\(\\s*${ARG}`, 'g'),
|
|
366
|
+
new RegExp(`${FS_SYNC_OPTIONAL_PREFIX}renameSync\\s*\\(\\s*${ARG}\\s*,\\s*${ARG}`, 'g'),
|
|
367
|
+
// F6: the async (non-Sync) forms, prefix REQUIRED.
|
|
368
|
+
new RegExp(`${FS_QUALIFIED_PREFIX}(?:writeFile|appendFile|rm|unlink|copyFile)\\s*\\(\\s*${ARG}`, 'g'),
|
|
369
|
+
new RegExp(`${FS_QUALIFIED_PREFIX}rename\\s*\\(\\s*${ARG}\\s*,\\s*${ARG}`, 'g'),
|
|
370
|
+
new RegExp(`\\bBun\\.write\\s*\\(\\s*${ARG}`, 'g'),
|
|
371
|
+
new RegExp(`\\bFile\\.write\\s*\\(\\s*${ARG}`, 'g'),
|
|
372
|
+
new RegExp(`\\bopen\\s*\\(\\s*${ARG}\\s*,\\s*['"]>{1,2}['"]\\s*,\\s*${ARG}\\s*\\)`, 'g'),
|
|
373
|
+
]
|
|
374
|
+
/** Position (from the end) of the TARGET capture group for each pattern above, in the same order — `os.rename`/`shutil.*`/the async `rename`/perl `open` capture 2 groups (source, target); every other pattern captures 1 (the target itself). */
|
|
375
|
+
const TARGET_IS_LAST_GROUP: readonly boolean[] = [false, false, false, true, true, false, true, false, true, false, false, true]
|
|
376
|
+
|
|
377
|
+
function writeCallTargets(command: string): readonly string[] {
|
|
378
|
+
const targets: string[] = []
|
|
379
|
+
for (let index = 0; index < WRITE_TARGET_PATTERNS.length; index += 1) {
|
|
380
|
+
const pattern = WRITE_TARGET_PATTERNS[index] as RegExp
|
|
381
|
+
const takeLast = TARGET_IS_LAST_GROUP[index]
|
|
382
|
+
for (const match of command.matchAll(pattern)) {
|
|
383
|
+
const value = takeLast ? match[2] : match[1]
|
|
384
|
+
if (value !== undefined) targets.push(value.trim())
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return targets
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const QUOTED_LITERAL_RE = /^f?(['"])([\s\S]*)\1$/
|
|
391
|
+
const BARE_IDENTIFIER_RE = /^[A-Za-z_]\w*$/
|
|
392
|
+
|
|
393
|
+
/** Whether `target` (a captured write-call argument) names a protected carrier — directly (a quoted literal) or, fail-closed, via a same-code assignment to a carrier-path literal when `target` is an unresolvable bare identifier. */
|
|
394
|
+
function targetNamesCarrierPath(target: string, command: string): string | null {
|
|
395
|
+
const literal = QUOTED_LITERAL_RE.exec(target)
|
|
396
|
+
if (literal !== null) return protectedCarrierMatch(literal[2] ?? '')
|
|
397
|
+
if (!BARE_IDENTIFIER_RE.test(target)) return null
|
|
398
|
+
const escaped = target.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
399
|
+
const assignment = new RegExp(`\\b${escaped}\\s*=\\s*f?(['"])([\\s\\S]*?)\\1`).exec(command)
|
|
400
|
+
if (assignment === null) return null
|
|
401
|
+
return protectedCarrierMatch(assignment[2] ?? '')
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function interpreterTarget(command: string): string | null {
|
|
405
|
+
for (const target of writeCallTargets(command)) {
|
|
406
|
+
const hit = targetNamesCarrierPath(target, command)
|
|
407
|
+
if (hit !== null) return hit
|
|
408
|
+
}
|
|
409
|
+
return null
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
export const agentTamperProtection: RuleSpec = {
|
|
413
|
+
id: 'agent.tamper-protection',
|
|
414
|
+
category: 'tool-call',
|
|
415
|
+
severity: 'deny',
|
|
416
|
+
enabledByDefault: true,
|
|
417
|
+
summary: 'Deny edits (tool, shell write, or git rewrite) to the host hook config or the repo gate marker.',
|
|
418
|
+
params: noParams,
|
|
419
|
+
match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
|
|
420
|
+
if (inv.kind === 'tool-call') {
|
|
421
|
+
const target = toolCallTarget(inv)
|
|
422
|
+
return target === null ? null : { ruleId: 'agent.tamper-protection', severity: 'deny', detail: { path: target, via: 'tool-call' } }
|
|
423
|
+
}
|
|
424
|
+
if (inv.kind === 'protected-carrier-write') {
|
|
425
|
+
// `targets` is never empty here: shell/invocation.ts only ever emits
|
|
426
|
+
// this kind when `protectedCarrierWriteTargets(...).length > 0`.
|
|
427
|
+
return { ruleId: 'agent.tamper-protection', severity: 'deny', detail: { path: inv.targets[0] ?? '', via: 'shell', command: inv.name || 'a redirection' } }
|
|
428
|
+
}
|
|
429
|
+
if (inv.kind === 'git') {
|
|
430
|
+
const target = gitTarget(inv)
|
|
431
|
+
if (target !== null) {
|
|
432
|
+
return { ruleId: 'agent.tamper-protection', severity: 'deny', detail: { path: target, via: 'git', command: `git ${inv.subcommand}` } }
|
|
433
|
+
}
|
|
434
|
+
// P2: `git apply` — coarse, whole-command (see `coarsePathMention`'s
|
|
435
|
+
// own doc for why: the target path is inside the patch's own
|
|
436
|
+
// headers, not an operand `gitTarget`'s per-operand scan would see).
|
|
437
|
+
// F7 (fourth independent review, 2026-09-29): a dry-run/inspection
|
|
438
|
+
// flag applies NOTHING — `git apply --check/--stat/--numstat/
|
|
439
|
+
// --summary` never touches the working tree, so naming a carrier is
|
|
440
|
+
// harmless.
|
|
441
|
+
if (inv.subcommand === 'apply' && !inv.rest.some((token) => DRY_RUN_GIT_APPLY_FLAGS.has(tokenValue(token)))) {
|
|
442
|
+
const hit = coarsePathMention(ctx.command ?? '')
|
|
443
|
+
if (hit !== null) return { ruleId: 'agent.tamper-protection', severity: 'deny', detail: { path: hit, via: 'git', command: 'git apply' } }
|
|
444
|
+
}
|
|
445
|
+
return null
|
|
446
|
+
}
|
|
447
|
+
// P2: the standalone `patch` utility — same coarse, whole-command
|
|
448
|
+
// reasoning as `git apply` above.
|
|
449
|
+
if (inv.kind === 'command' && inv.name === 'patch') {
|
|
450
|
+
const hit = coarsePathMention(ctx.command ?? '')
|
|
451
|
+
if (hit !== null) return { ruleId: 'agent.tamper-protection', severity: 'deny', detail: { path: hit, via: 'shell', command: 'patch' } }
|
|
452
|
+
}
|
|
453
|
+
const interpreter = interpreterTarget(ctx.command ?? '')
|
|
454
|
+
if (interpreter !== null) {
|
|
455
|
+
return { ruleId: 'agent.tamper-protection', severity: 'deny', detail: { path: interpreter, via: 'interpreter' } }
|
|
456
|
+
}
|
|
457
|
+
return null
|
|
458
|
+
},
|
|
459
|
+
message(finding: Finding, ctx: MessageContext) {
|
|
460
|
+
const path = typeof finding.detail.path === 'string' ? finding.detail.path : 'this file'
|
|
461
|
+
const via = typeof finding.detail.via === 'string' ? finding.detail.via : 'tool-call'
|
|
462
|
+
const command = typeof finding.detail.command === 'string' ? finding.detail.command : ''
|
|
463
|
+
const verb =
|
|
464
|
+
via === 'shell'
|
|
465
|
+
? `${command} writing`
|
|
466
|
+
: via === 'git'
|
|
467
|
+
? `${command} rewriting`
|
|
468
|
+
: via === 'interpreter'
|
|
469
|
+
? 'an interpreter one-liner writing'
|
|
470
|
+
: 'editing'
|
|
471
|
+
return {
|
|
472
|
+
user: `Blocked ${via === 'tool-call' ? 'editing' : verb} ${path}. This file wires the host's hooks or un-manages this repo; ask the user to change it.`,
|
|
473
|
+
agent:
|
|
474
|
+
`DENIED ${verb} ${path}. This file is one of the tamper-protected files: ` +
|
|
475
|
+
'`.claude/settings.json`, `.claude/settings.local.json`, `.codex/config.toml`, ' +
|
|
476
|
+
'`.codex/hooks.json`, `.cursor/hooks.json`, `.opencode/plugins/adl-repo.ts`, ' +
|
|
477
|
+
"`~/.kimi-code/config.toml`, or `adl-config.toml`. The first six install or override a " +
|
|
478
|
+
"host's own hook contract (directly, or — for `.opencode/plugins/adl-repo.ts` — as the " +
|
|
479
|
+
'generated plugin THAT IS the carrier; `~/.kimi-code/config.toml` is Kimi\'s own single, ' +
|
|
480
|
+
"globally-installed carrier — Kimi has no per-repo one); `adl-config.toml` is the repo's " +
|
|
481
|
+
"own gate marker (`[hooks] enabled = false` silently no-ops every hook kind — see " +
|
|
482
|
+
'`main.ts`). Editing, overwriting, moving over, truncating, ' +
|
|
483
|
+
'deleting, or rewriting any of them — by a tool call, a shell write, or a git checkout/ ' +
|
|
484
|
+
'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 (decision 13: the managed-hooks lock is ' +
|
|
486
|
+
`off). If a legitimate change is needed, file a PR or ask the user to make it themselves. ` +
|
|
487
|
+
`Blocked call: ${ctx.snippet}`,
|
|
488
|
+
}
|
|
489
|
+
},
|
|
490
|
+
corpus: {
|
|
491
|
+
// Tool-call and shell-command shapes are both exercised directly by
|
|
492
|
+
// `tests/unit/rules-agent-tamper-protection.test.ts` (through
|
|
493
|
+
// `decide({kind:'tool-call'})` and `decideCommand`); this corpus only
|
|
494
|
+
// has to prove reads stay allowed and unrelated commands don't trip it.
|
|
495
|
+
deny: [],
|
|
496
|
+
allow: [
|
|
497
|
+
'ls -la .claude',
|
|
498
|
+
'cat .claude/settings.json',
|
|
499
|
+
'cat adl-config.toml',
|
|
500
|
+
'rg "enabled" .claude/',
|
|
501
|
+
'cat .codex/hooks.json',
|
|
502
|
+
'cat .cursor/hooks.json',
|
|
503
|
+
'cat .opencode/plugins/adl-repo.ts',
|
|
504
|
+
'jq . .codex/hooks.json',
|
|
505
|
+
'sed -n "1,5p" .codex/hooks.json',
|
|
506
|
+
],
|
|
507
|
+
},
|
|
508
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `~/enact-vps` — the canonical checkout — is off-limits to agents.
|
|
3
|
+
*
|
|
4
|
+
* Owner decision, 2026-09-15. It is the tree the fleet reconciler builds every
|
|
5
|
+
* global binary from (`/Library/LaunchDaemons/com.adl.global-tools.plist` →
|
|
6
|
+
* `--repo /Users/ranahome/enact-vps`), and
|
|
7
|
+
* `/usr/local/libexec/adl-global-tools-sync` refuses the ENTIRE
|
|
8
|
+
* reconciliation while that tree is dirty (labels/binary confirmed already
|
|
9
|
+
* renamed fleet-side: `packages/fleet/README.md` documents
|
|
10
|
+
* `com.adl.global-tools`; this comment had drifted):
|
|
11
|
+
*
|
|
12
|
+
* canonical checkout is dirty; refusing pull and reconciliation
|
|
13
|
+
*
|
|
14
|
+
* So a single stray write there does not inconvenience one repo — it silently
|
|
15
|
+
* stops every machine in the fleet from updating, with no signal beyond a line
|
|
16
|
+
* in a log nobody reads. That had been happening for an unknown number of
|
|
17
|
+
* cycles before it was found.
|
|
18
|
+
*
|
|
19
|
+
* Nothing needs to touch that path to ship: agents work in a clone and push to
|
|
20
|
+
* `main`, and the reconciler does its own `git pull --ff-only origin main`.
|
|
21
|
+
*
|
|
22
|
+
* WHY THIS LAYER. `~/.claude/settings.json` cannot express it. Permission rules
|
|
23
|
+
* match Bash by command PREFIX (`Bash(git *)`), never by path, so
|
|
24
|
+
* `rg foo ~/enact-vps` is invisible to them — and a hand-added `permissions.deny`
|
|
25
|
+
* entry is itself a global-surface-sweep candidate, so it would be removed
|
|
26
|
+
* again later. Path-aware denial exists only here.
|
|
27
|
+
*
|
|
28
|
+
* The classifier carries the path (see `shell/invocation.ts`'s `denied-path`):
|
|
29
|
+
* `cat`/`ls` and the other read-only consumers return `[]` from classification
|
|
30
|
+
* and are invisible to rules, and `read-only` carries only a name, so without
|
|
31
|
+
* that kind there would be nothing for this rule to inspect.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import type { Invocation } from '../shell/invocation.ts'
|
|
35
|
+
import type { Finding, MessageContext, RuleSpec } from '../spec.ts'
|
|
36
|
+
import { noParams } from '../spec.ts'
|
|
37
|
+
import { detailString } from './messages.ts'
|
|
38
|
+
|
|
39
|
+
export const fsCanonicalCheckout: RuleSpec = {
|
|
40
|
+
id: 'fs.canonical-checkout',
|
|
41
|
+
category: 'filesystem',
|
|
42
|
+
severity: 'deny',
|
|
43
|
+
enabledByDefault: true,
|
|
44
|
+
summary: 'Deny any command reaching into ~/enact-vps, the canonical checkout the fleet builds from.',
|
|
45
|
+
params: noParams,
|
|
46
|
+
match(inv: Invocation): Finding | null {
|
|
47
|
+
if (inv.kind !== 'denied-path') return null
|
|
48
|
+
return { ruleId: 'fs.canonical-checkout', severity: 'deny', detail: { path: inv.path, name: inv.name } }
|
|
49
|
+
},
|
|
50
|
+
message(finding: Finding, ctx: MessageContext) {
|
|
51
|
+
const path = detailString(finding, 'path')
|
|
52
|
+
return {
|
|
53
|
+
user: `Blocked: ${path} is inside ~/enact-vps, the canonical checkout. Work in a clone and push to main — the reconciler pulls from origin itself.`,
|
|
54
|
+
agent:
|
|
55
|
+
`DENIED ${path}. That is inside ~/enact-vps, the canonical checkout the fleet reconciler builds every ` +
|
|
56
|
+
'global binary from. It refuses the whole reconciliation while that tree is dirty ("canonical checkout ' +
|
|
57
|
+
'is dirty; refusing pull and reconciliation"), so a stray write there stops every machine updating.\n' +
|
|
58
|
+
'Nothing needs to touch it to ship: work in a clone (e.g. ~/Documents/enact-vps-m5), commit, and push to ' +
|
|
59
|
+
'`main`. The reconciler runs its own `git pull --ff-only origin main` before building, so your change ' +
|
|
60
|
+
'reaches /usr/local/bin without that path ever being written by an agent.\n' +
|
|
61
|
+
`Blocked command: ${ctx.snippet}`,
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
corpus: {
|
|
65
|
+
// $HOME is /Users/tester in the rule fixtures (test/fixtures/decide.ts).
|
|
66
|
+
deny: [
|
|
67
|
+
'cat /Users/tester/enact-vps/adl-config.toml',
|
|
68
|
+
'rg TODO /Users/tester/enact-vps/adl-hook/src',
|
|
69
|
+
'ls /Users/tester/enact-vps',
|
|
70
|
+
'cp /Users/tester/enact-vps/x.ts /tmp/x.ts',
|
|
71
|
+
'ls -la && cat /Users/tester/enact-vps/adl-config.toml',
|
|
72
|
+
'echo hi; cat /Users/tester/enact-vps/adl-config.toml',
|
|
73
|
+
],
|
|
74
|
+
allow: [
|
|
75
|
+
// A clone whose name merely starts with the denied one is a different repo.
|
|
76
|
+
'cat /Users/tester/enact-vps-m5/adl-config.toml',
|
|
77
|
+
'rg TODO /Users/tester/enact-vps-m5/adl-hook/src',
|
|
78
|
+
// Same name, different place.
|
|
79
|
+
'cat /Users/tester/Documents/enact-vps/adl-config.toml',
|
|
80
|
+
// The word is not the path.
|
|
81
|
+
'echo "see enact-vps for details"',
|
|
82
|
+
'rg TODO src/',
|
|
83
|
+
'ls -la',
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem writes into `.git` — the non-plumbing half of "manual git
|
|
3
|
+
* surgery".
|
|
4
|
+
*
|
|
5
|
+
* Added after an incident: an agent denied `git rebase --abort` trashed
|
|
6
|
+
* `.git/rebase-merge` and rewrote HEAD by hand. `fs.trash` refused only
|
|
7
|
+
* `.git` itself; `mv`, `cp`, `tee`, `>`, `sed -i`, `perl -pi`, `truncate`,
|
|
8
|
+
* `chmod`, `ln -sf`, `rsync` into `.git` were never inspected at all. The
|
|
9
|
+
* detection (which verbs, which operand is the written path) lives in
|
|
10
|
+
* shell/git-internals.ts; this rule only denies what it classified. Reading
|
|
11
|
+
* `.git/*` is never classified and stays allowed.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { Invocation } from '../shell/invocation.ts'
|
|
15
|
+
import type { Finding, MessageContext, RuleSpec } from '../spec.ts'
|
|
16
|
+
import { noParams } from '../spec.ts'
|
|
17
|
+
import { detailString, gitAgentTail } from './messages.ts'
|
|
18
|
+
|
|
19
|
+
export const fsGitInternals: RuleSpec = {
|
|
20
|
+
id: 'fs.git-internals',
|
|
21
|
+
category: 'filesystem',
|
|
22
|
+
severity: 'deny',
|
|
23
|
+
enabledByDefault: true,
|
|
24
|
+
summary: 'Deny any filesystem write (rm/trash/mv/cp/ln/rsync/truncate/redirect/tee/sed -i/perl -i/chmod/find -delete) into a .git directory or gitdir file.',
|
|
25
|
+
params: noParams,
|
|
26
|
+
match(inv: Invocation): Finding | null {
|
|
27
|
+
if (inv.kind !== 'git-internals-write') return null
|
|
28
|
+
return {
|
|
29
|
+
ruleId: 'fs.git-internals',
|
|
30
|
+
severity: 'deny',
|
|
31
|
+
detail: { command: inv.name || 'a redirection', target: inv.targets[0] ?? '' },
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
message(finding: Finding, ctx: MessageContext) {
|
|
35
|
+
const command = detailString(finding, 'command')
|
|
36
|
+
const target = detailString(finding, 'target')
|
|
37
|
+
return {
|
|
38
|
+
user: `Blocked ${command} writing inside .git (${target}). Hand-editing git internals can corrupt the repository; use git's own commands, or do it yourself.`,
|
|
39
|
+
agent:
|
|
40
|
+
`DENIED ${command} writing inside .git (${target}). Deleting, moving, overwriting, truncating, ` +
|
|
41
|
+
're-permissioning, or in-place editing anything in a .git directory (refs, HEAD, the index, ' +
|
|
42
|
+
'rebase-merge/rebase-apply, MERGE_HEAD, objects, a worktree or submodule gitdir file) bypasses every ' +
|
|
43
|
+
"safety check git has and can leave the repository corrupt or silently lose commits. Reading .git " +
|
|
44
|
+
`is fine (cat, ls, grep). ${gitAgentTail(ctx.snippet)}`,
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
corpus: {
|
|
48
|
+
deny: [
|
|
49
|
+
'trash .git/rebase-merge',
|
|
50
|
+
'rm -rf .git/rebase-merge',
|
|
51
|
+
'mv .git/rebase-merge ~/.Trash/',
|
|
52
|
+
'cp -f /tmp/HEAD .git/HEAD',
|
|
53
|
+
'echo ref: refs/heads/main > .git/HEAD',
|
|
54
|
+
'echo abc | tee .git/ORIG_HEAD',
|
|
55
|
+
"sed -i 's/feat/main/' .git/HEAD",
|
|
56
|
+
"perl -pi -e 's/feat/main/' .git/HEAD",
|
|
57
|
+
'truncate -s 0 .git/index',
|
|
58
|
+
'ln -sf refs/heads/main .git/HEAD',
|
|
59
|
+
'rsync -a --delete backup/ .git/',
|
|
60
|
+
'chmod 000 .git/index',
|
|
61
|
+
'find .git/rebase-merge -delete',
|
|
62
|
+
'cd repo && trash sub/.git/rebase-apply',
|
|
63
|
+
"bash <<'EOF'\nrm -rf .git\nEOF",
|
|
64
|
+
"sh <<EOF\nrm -rf .git\nEOF",
|
|
65
|
+
],
|
|
66
|
+
allow: [
|
|
67
|
+
'cat .git/HEAD',
|
|
68
|
+
'ls -la .git/rebase-merge',
|
|
69
|
+
"sed -n '1,5p' .git/config",
|
|
70
|
+
'cp .git/config /tmp/git-config',
|
|
71
|
+
'trash .gitignore',
|
|
72
|
+
"cat <<'EOF' > notes.md\nrm -rf .git\nEOF",
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
}
|