@amsterdamdatalabs/adl-agent-control-linux-x64 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,731 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `adl.human-azdo-bypass` — STATUS.md 12p decisions 1/1b/1c:
|
|
3
|
+
* `ADL_HUMAN_AZDO=1` marks Tarun's own interactive terminal (`bin/git-ado`'s
|
|
4
|
+
* and `resolveAgentIdentity`'s shared human-pass-through check,
|
|
5
|
+
* `packages/azdo/src/lib/agent-identity.ts`'s `isMarkedHumanAzdoCaller`:
|
|
6
|
+
* stdin is a real TTY AND `ADL_HUMAN_AZDO === '1'`, exactly — never a
|
|
7
|
+
* near-miss value, never trimmed or case-insensitive). An agent must never
|
|
8
|
+
* set it at all: doing so from an agent surface would let a LATER command
|
|
9
|
+
* on the same persistent shell (where one exists) fall through git-ado's
|
|
10
|
+
* human pass-through with no agent identity involved, exactly the incident
|
|
11
|
+
* the whole standard exists to close — just aimed at the marker itself
|
|
12
|
+
* instead of at `ADL_AGENT_ID_AGENT`.
|
|
13
|
+
*
|
|
14
|
+
* F1 (independent review, 2026-09-29, HIGH, confirmed): a live bypass —
|
|
15
|
+
* `export ADL_HUMAN_AZD''O=1; unset ADL_AGENT_ID_AGENT; script -q /dev/null
|
|
16
|
+
* git push origin feat/x` — was ALLOWED and reached `bin/git-ado`'s human
|
|
17
|
+
* pass-through via a faked pty. Fixed in three parts (a/b/c below).
|
|
18
|
+
*
|
|
19
|
+
* SECOND REVIEW (2026-09-29, same night): the first F1 fix over-matched —
|
|
20
|
+
* `git commit -m "ADL_HUMAN_AZDO=1 is denied now"`, `git log -S
|
|
21
|
+
* "ADL_HUMAN_AZDO=1"`, `declare -p ADL_HUMAN_AZDO` (a READ, not a set),
|
|
22
|
+
* `grep -c '...'` (grep's COUNT flag, mistaken for shell `-c`), and `node -e
|
|
23
|
+
* "console.log('pty')"` (a bare word 'pty' in unrelated code) were all
|
|
24
|
+
* wrongly denied. Detection is now POSITIONAL, not "any word anywhere":
|
|
25
|
+
*
|
|
26
|
+
* (a) A setter is recognized only in a real setter POSITION — a leading
|
|
27
|
+
* `NAME=value` assignment before a piece's own command word, or the
|
|
28
|
+
* piece's OWN command word being `export`/`declare -x`/`typeset -x`/
|
|
29
|
+
* `printf -v`/`read`/`env NAME=value` with the name as ITS operand
|
|
30
|
+
* (checked against `values[0]`, the piece's actual command, never an
|
|
31
|
+
* unrelated word buried inside some OTHER command's arguments — a git
|
|
32
|
+
* commit message, a `-S`/`-m` operand, are never inspected for this at
|
|
33
|
+
* all). `declare`/`typeset` require the `-x` flag to be present
|
|
34
|
+
* (`-p`/bare prints or lists, never sets); `printf` requires `-v`;
|
|
35
|
+
* `export -p` (list, not set) does not count either. Word values are
|
|
36
|
+
* already quote/escape-resolved by `../shell/token.ts`'s `tokenize`
|
|
37
|
+
* before any of this runs, closing the original quote-splitting/
|
|
38
|
+
* backslash-escaping bypass without needing a second, looser check.
|
|
39
|
+
* A `-c`/`--command` argument is only re-scanned as a nested shell
|
|
40
|
+
* script when the piece's OWN command is a REAL shell
|
|
41
|
+
* (`bash`/`sh`/`zsh`/`dash`/`ksh`/`fish`) — `grep -c PATTERN`'s count
|
|
42
|
+
* flag is never mistaken for one.
|
|
43
|
+
* Interpreter one-liners (python/node/ruby/perl) are matched by their
|
|
44
|
+
* OWN coarse setter pattern (`os.environ[...]=`/`.setdefault(...)`,
|
|
45
|
+
* `process.env.X=`/`['X']=`, `$ENV{X}=`) against ONLY the `-c`/`-e`/
|
|
46
|
+
* `--eval` code argument's value — never a bare word anywhere in the
|
|
47
|
+
* command.
|
|
48
|
+
* (b) Clearing `ADL_AGENT_ID_AGENT` is denied in every named form: `unset
|
|
49
|
+
* NAME` (as an operand of `unset`, the piece's own command), `env -u
|
|
50
|
+
* NAME`/`--unset[=]NAME`, an empty leading assignment (`NAME=`),
|
|
51
|
+
* `export -n NAME`, `declare +x NAME`/`typeset +x NAME` (P2: `+x`
|
|
52
|
+
* removes the export attribute). `env -i`/`--ignore-environment`/bare
|
|
53
|
+
* `env -` clears the WHOLE environment, but is denied ONLY when the
|
|
54
|
+
* command it wraps is ITSELF identity-bearing (`isLikelyIdentityBearing`
|
|
55
|
+
* below: a network git verb, a curl/wget/httpie/xh call to Azure
|
|
56
|
+
* DevOps, `az`, or an `adl`/`adl-agent-id` entry point) — `env -i PATH=
|
|
57
|
+
* /usr/bin ls` clears the environment for a command that never needed
|
|
58
|
+
* an identity in the first place, and denying it would only cost a
|
|
59
|
+
* falsely-blocked, ordinary command for no security gain.
|
|
60
|
+
* Interpreter one-liners: `del os.environ[...]`/`.pop(...)`/
|
|
61
|
+
* `os.unsetenv(...)` (python), `delete process.env.X`/`['X']` (node),
|
|
62
|
+
* `delete $ENV{X}` (perl) — same "-c/-e/--eval argument only" scoping
|
|
63
|
+
* as the setter check.
|
|
64
|
+
* (c) `script`/`unbuffer`/`expect`, `socat` with a `pty` argument, `tmux`/
|
|
65
|
+
* `screen` starting a detached session with a command (P2:
|
|
66
|
+
* `new-session`/`-dm`/`-dmS`), `zsh`'s `zpty` module command, a
|
|
67
|
+
* python/node/ruby/perl one-liner or flag that actually loads a pty
|
|
68
|
+
* module (`import pty`/`pty.spawn(...)`, `require('pty'|'node-pty')`,
|
|
69
|
+
* `-rpty`, `-MIO::Pty` — never a bare word), launching a real terminal
|
|
70
|
+
* app (`open -a Terminal|iTerm...`, `open *.command`, an `osascript`
|
|
71
|
+
* `do script ... "Terminal"|"iTerm"`) are denied UNCONDITIONALLY — none
|
|
72
|
+
* has a legitimate purpose on an agent surface, and narrowing to
|
|
73
|
+
* "wraps an identity-bearing command" would require parsing what each
|
|
74
|
+
* one wraps, fragile and trivially evaded by one more layer of
|
|
75
|
+
* indirection. `ssh -t|-tt|-o RequestTTY=force` is the one shape
|
|
76
|
+
* narrowed to a loopback host (`localhost`, `127.0.0.0/8`, `::1`, the
|
|
77
|
+
* shorthand `0`) — forcing a PTY on a genuine remote admin session is
|
|
78
|
+
* ordinary usage unrelated to faking a LOCAL pty.
|
|
79
|
+
* All of (c) resolves the piece's REAL command first — past a leading
|
|
80
|
+
* `NAME=value`, and past a chain of `env`/`timeout`/`nice`/`nohup`/
|
|
81
|
+
* `command`/`exec` wrappers and their own flags (`resolvedCommand`,
|
|
82
|
+
* below) — so `env ADL_AGENT_ID_AGENT=agent-tarun nohup script -q
|
|
83
|
+
* /dev/null git push origin feat/x` is still caught as `script`, not
|
|
84
|
+
* missed because the literal first word was a wrapper.
|
|
85
|
+
*
|
|
86
|
+
* Word collection deliberately does NOT walk into here-documents, here-
|
|
87
|
+
* strings, or `$(...)`/backtick substitutions (out of scope for this fix);
|
|
88
|
+
* it only reaches one level into a REAL shell's `-c`/`--command` script
|
|
89
|
+
* string, depth-capped — matching this rule's own "coarse, not a precise
|
|
90
|
+
* parser" contract.
|
|
91
|
+
*
|
|
92
|
+
* Unconditional — this fires regardless of whether an agent identity is
|
|
93
|
+
* otherwise resolvable. `IDENTITY_RULE_IDS` (`../../pre-tool-use/handler.ts`)
|
|
94
|
+
* no longer names a baseline this rule "rides" — Tarun's rule (2026-09-29)
|
|
95
|
+
* removed the global identity baseline entirely (hooks run only in a repo
|
|
96
|
+
* with its own `adl-config.toml`, never unmanaged), so `IDENTITY_RULE_IDS`
|
|
97
|
+
* now serves `identity_source` LOGGING classification only, inside a
|
|
98
|
+
* managed repo's own normal rule pass — this rule fires the same way any
|
|
99
|
+
* other enabled rule does, nothing baseline-specific about it.
|
|
100
|
+
*
|
|
101
|
+
* THE PTY-FAKING-WRAPPER CLASS IS UNBOUNDED (STATUS.md 12p item 15's threat
|
|
102
|
+
* model; F4, fourth independent review, 2026-09-29, "bounded, then stop").
|
|
103
|
+
* `pieceUsesPtyFakingWrapper` recognizes a widened but still FINITE list of
|
|
104
|
+
* named tools (`script`/`unbuffer`/`expect`/`zpty`, `socat`, `tmux`/`screen`,
|
|
105
|
+
* `ssh` to a loopback host, terminal-launching `open`/`osascript`, and a
|
|
106
|
+
* `pty`-module reference from python/node/ruby/perl) — it is not, and
|
|
107
|
+
* cannot be made, a complete enumeration of every way a same-OS-user
|
|
108
|
+
* process can attach to or fake a controlling terminal (a custom compiled
|
|
109
|
+
* helper, a language runtime this list does not name, a future terminal
|
|
110
|
+
* emulator, a creative combination of otherwise-ordinary tools). Widening
|
|
111
|
+
* this list further, one reported gap at a time, has a naturally
|
|
112
|
+
* diminishing return: closing THIS session's known list here (this fix,
|
|
113
|
+
* and the two before it in this file's own history) is the last widening
|
|
114
|
+
* pass for the foreseeable future — the credential-level fix (removing the
|
|
115
|
+
* SHARED-machine TTY signal `bin/git-ado` relies on as a proxy for "is this
|
|
116
|
+
* a human") is the orchestrator's own, separate track with Tarun, not
|
|
117
|
+
* something this rule can substitute for by enumerating tools forever.
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
import type { Invocation } from '../shell/invocation.ts'
|
|
121
|
+
import type { Finding, MessageContext, RuleContext, RuleSpec } from '../spec.ts'
|
|
122
|
+
import { noParams } from '../spec.ts'
|
|
123
|
+
import { isMarkedHumanAzdoCaller } from '../../../../azdo/src/lib/agent-identity.ts'
|
|
124
|
+
import { ADL_AGENT_ID_ENV_VAR } from './adl-identity.ts'
|
|
125
|
+
import { ADL_AGENT_ID_BINARY_NAMES, ADL_BINARY_NAMES, HTTP_CLIENT_BINARY_NAMES, isAdoUrl } from './git-helpers.ts'
|
|
126
|
+
import { isNetworkGitInvocation } from '../shell/git-identity.ts'
|
|
127
|
+
import { skipPrefixes } from '../shell/prefixes.ts'
|
|
128
|
+
import { heredocBodies } from '../shell/substitution.ts'
|
|
129
|
+
import { splitShell } from '../shell/split.ts'
|
|
130
|
+
import { tokenize, tokenValue, type Token } from '../shell/token.ts'
|
|
131
|
+
|
|
132
|
+
export const RULE_ID = 'adl.human-azdo-bypass'
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The exact env var name STATUS.md 12p decisions 1b/1c name. Not exported as
|
|
136
|
+
* a standalone string constant from `packages/azdo/src/lib/agent-identity.ts`
|
|
137
|
+
* (only the combined TTY+value check, `isMarkedHumanAzdoCaller`, is) — this
|
|
138
|
+
* is the one place in this package that spells it, rather than a second,
|
|
139
|
+
* independent literal duplicated across detection helpers below.
|
|
140
|
+
*/
|
|
141
|
+
export const ADL_HUMAN_AZDO_ENV_VAR = 'ADL_HUMAN_AZDO'
|
|
142
|
+
|
|
143
|
+
/** `os.environ['ADL_HUMAN_AZDO'] = ...` / `os.environ.setdefault('ADL_HUMAN_AZDO', ...)` — Python. Checked against ONLY the `-c`/`-e`/`--eval` code argument (see this file's own header). */
|
|
144
|
+
const PYTHON_HUMAN_AZDO_SET_RE = /os\.environ\s*(?:\[\s*['"]ADL_HUMAN_AZDO['"]\s*\]|\.setdefault\(\s*['"]ADL_HUMAN_AZDO['"])\s*[=(]/
|
|
145
|
+
/** `process.env.ADL_HUMAN_AZDO = ...` / `process.env['ADL_HUMAN_AZDO'] = ...` — Node. */
|
|
146
|
+
const NODE_HUMAN_AZDO_SET_RE = /process\.env\s*(?:\.\s*ADL_HUMAN_AZDO\b|\[\s*['"]ADL_HUMAN_AZDO['"]\s*\])\s*=/
|
|
147
|
+
/** `$ENV{ADL_HUMAN_AZDO} = ...` — Perl. */
|
|
148
|
+
const PERL_HUMAN_AZDO_SET_RE = /\$ENV\{\s*['"]?ADL_HUMAN_AZDO['"]?\s*\}\s*=/
|
|
149
|
+
|
|
150
|
+
/** `del os.environ['ADL_AGENT_ID_AGENT']` / `os.environ.pop(...)` / `os.unsetenv(...)` — Python. */
|
|
151
|
+
const PYTHON_AGENT_ID_DELETE_RE = /\bdel\s+os\.environ\s*\[\s*['"]ADL_AGENT_ID_AGENT['"]\s*\]|\bos\.environ\.pop\(\s*['"]ADL_AGENT_ID_AGENT['"]|\bos\.unsetenv\(\s*['"]ADL_AGENT_ID_AGENT['"]/
|
|
152
|
+
/** `delete process.env.ADL_AGENT_ID_AGENT` / `delete process.env['ADL_AGENT_ID_AGENT']` — Node. */
|
|
153
|
+
const NODE_AGENT_ID_DELETE_RE = /\bdelete\s+process\.env\s*(?:\.\s*ADL_AGENT_ID_AGENT\b|\[\s*['"]ADL_AGENT_ID_AGENT['"]\s*\])/
|
|
154
|
+
/** `delete $ENV{ADL_AGENT_ID_AGENT}` — Perl. */
|
|
155
|
+
const PERL_AGENT_ID_DELETE_RE = /\bdelete\s*\$ENV\{\s*['"]?ADL_AGENT_ID_AGENT['"]?\s*\}/
|
|
156
|
+
|
|
157
|
+
/** Real shells only — a `-c`/`--command` word is re-scanned as a nested script only when the piece's OWN command is one of these (never `grep -c PATTERN`'s unrelated count flag). */
|
|
158
|
+
const SHELL_NAMES: ReadonlySet<string> = new Set(['sh', 'bash', 'zsh', 'dash', 'ksh', 'fish'])
|
|
159
|
+
/** python/node/ruby/perl — interpreters whose `-c`/`-e`/`--eval` inline code is inspected by the coarse patterns above. */
|
|
160
|
+
const INTERPRETER_NAMES: ReadonlySet<string> = new Set(['python', 'python2', 'python3', 'node', 'nodejs', 'ruby', 'perl'])
|
|
161
|
+
const AZ_NAMES: ReadonlySet<string> = new Set(['az', 'az.exe'])
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* P2 (independent review, 2026-09-29, "dynamic names"): a strict leading
|
|
165
|
+
* assignment shape (`^[A-Za-z_][A-Za-z0-9_]*=`), but permitting
|
|
166
|
+
* `$`/backtick/`{`/`}` in the identifier portion too —
|
|
167
|
+
* `ADL_HUMAN_AZ${EMPTY}DO=1` is one word after `tokenize` (confirmed
|
|
168
|
+
* directly), and a real shell WOULD expand `${EMPTY}` before checking
|
|
169
|
+
* assignment shape, so this is a genuine bypass of a strict identifier
|
|
170
|
+
* check, not merely cosmetic. Used only to recognize the SHAPE (so a scan
|
|
171
|
+
* keeps walking past it); `isNameOperandDynamic` below decides whether the
|
|
172
|
+
* identifier portion is actually dynamic.
|
|
173
|
+
*/
|
|
174
|
+
const ASSIGNMENT_SHAPE_RE = /^[A-Za-z_][\w$`{}]*=/
|
|
175
|
+
|
|
176
|
+
function isAssignmentTo(value: string, name: string): boolean {
|
|
177
|
+
return value === `${name}=` || value.startsWith(`${name}=`)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* True when `value` — a bare operand (`unset NAME`, `read NAME`, `printf -v
|
|
182
|
+
* NAME`) or an assignment word (`NAME=value`) — has an unresolved shell
|
|
183
|
+
* expansion (`$VAR`, `${VAR}`, `$(...)`, backtick) in the NAME portion
|
|
184
|
+
* (before the first `=`, or the whole word when there is none). We cannot
|
|
185
|
+
* know what such a word actually names — `v=ADL_HUMAN_AZDO; export "$v=1"`
|
|
186
|
+
* and `X=ADL_AGENT_ID_AGENT; unset $X` both hide the real name behind a
|
|
187
|
+
* variable this static scan never resolves — so any setter/clearer-shaped
|
|
188
|
+
* position holding one is treated as a match (P2 "dynamic names",
|
|
189
|
+
* fail-closed) for whichever name the caller is checking.
|
|
190
|
+
*/
|
|
191
|
+
function isNameOperandDynamic(value: string): boolean {
|
|
192
|
+
const equals = value.indexOf('=')
|
|
193
|
+
const namePart = equals < 0 ? value : value.slice(0, equals)
|
|
194
|
+
return /[$`]/.test(namePart)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function basenameOf(value: string): string {
|
|
198
|
+
const index = value.lastIndexOf('/')
|
|
199
|
+
return index < 0 ? value : value.slice(index + 1)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** Nested `-c`/`--command` shell script strings are re-tokenized at most this deep. */
|
|
203
|
+
const MAX_WORD_SCAN_DEPTH = 8
|
|
204
|
+
|
|
205
|
+
/** One piece of a command: its raw tokens (for `skipPrefixes`, which needs a real `Token[]`) alongside their already quote/escape-resolved string values. */
|
|
206
|
+
interface WordPiece {
|
|
207
|
+
readonly tokens: readonly Token[]
|
|
208
|
+
readonly values: readonly string[]
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Every piece of `command` (one `WordPiece` per top-level piece), collected
|
|
213
|
+
* into `out`. Recurses one level into a `-c`/`--command` shell script string
|
|
214
|
+
* ONLY when the piece's own command is a real shell (`SHELL_NAMES`) — never
|
|
215
|
+
* for an unrelated `-c` flag on some other command (`grep -c`, `curl -c`,
|
|
216
|
+
* `ssh -c`, …). Quote concatenation and backslash escapes are already
|
|
217
|
+
* resolved by `tokenize`.
|
|
218
|
+
*/
|
|
219
|
+
/**
|
|
220
|
+
* `-c`, a combined short flag ENDING in `c` (`-ic`, `-lc`, `-ec` — an
|
|
221
|
+
* interactive/login/errexit shell still reads its script from the SAME
|
|
222
|
+
* `-c` operand), or `--command[=]` — mirrors `shell/invocation.ts`'s own
|
|
223
|
+
* (private) `isShellCommandOption` one-line check, kept in sync
|
|
224
|
+
* deliberately rather than exported, to recognize a shell invoked with
|
|
225
|
+
* combined flags (`zsh -ic '...'`, `bash -lc '...'`, `sh -ec '...'`) the
|
|
226
|
+
* same way the rest of the engine already does (F2, third independent
|
|
227
|
+
* review, 2026-09-29 — this rule's own exact-`-c`-only check let `zsh -ic
|
|
228
|
+
* '...'` defeat it entirely).
|
|
229
|
+
*/
|
|
230
|
+
function isShellScriptOption(value: string): boolean {
|
|
231
|
+
return value === '-c' || /^-[^-]*c$/.test(value) || value === '--command' || value.startsWith('--command=')
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Every piece of `command` (one `WordPiece` per top-level piece), collected
|
|
236
|
+
* into `out`. Recurses one level into a `-c`-shaped shell script string
|
|
237
|
+
* ONLY when the piece's own RESOLVED command (past a leading assignment and
|
|
238
|
+
* a chain of transparent wrappers — F2: `nohup bash -c '...'`/`FOO=1 bash
|
|
239
|
+
* -c '...'` were invisible before, since only the piece's literal FIRST
|
|
240
|
+
* word was checked) is a real shell (`SHELL_NAMES`) — never for an
|
|
241
|
+
* unrelated `-c` flag on some other command (`grep -c`, `curl -c`, `ssh
|
|
242
|
+
* -c`, …). Quote concatenation and backslash escapes are already resolved
|
|
243
|
+
* by `tokenize`.
|
|
244
|
+
*/
|
|
245
|
+
function collectWordPieces(command: string, depth: number, out: WordPiece[]): void {
|
|
246
|
+
if (depth > MAX_WORD_SCAN_DEPTH) return
|
|
247
|
+
const split = splitShell(command)
|
|
248
|
+
if (split.invalid) return
|
|
249
|
+
for (const piece of split.pieces) {
|
|
250
|
+
const tokenized = tokenize(piece)
|
|
251
|
+
if (tokenized.invalid) continue
|
|
252
|
+
const values = tokenized.tokens.map(tokenValue)
|
|
253
|
+
const wordPiece: WordPiece = { tokens: tokenized.tokens, values }
|
|
254
|
+
out.push(wordPiece)
|
|
255
|
+
const resolved = resolvedCommand(wordPiece)
|
|
256
|
+
if (resolved.name === undefined || !SHELL_NAMES.has(resolved.name)) continue
|
|
257
|
+
for (let index = resolved.argsStart; index < values.length; index += 1) {
|
|
258
|
+
const value = values[index] as string
|
|
259
|
+
if (isShellScriptOption(value) && !value.startsWith('--command=')) {
|
|
260
|
+
if (values[index + 1] !== undefined) collectWordPieces(values[index + 1] as string, depth + 1, out)
|
|
261
|
+
} else if (value.startsWith('--command=')) {
|
|
262
|
+
collectWordPieces(value.slice('--command='.length), depth + 1, out)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function wordPiecesFor(command: string): readonly WordPiece[] {
|
|
269
|
+
const out: WordPiece[] = []
|
|
270
|
+
collectWordPieces(command, 0, out)
|
|
271
|
+
return out
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** The `-c`/`-e`/`--eval[=]` argument value for an interpreter invocation, or null when the piece runs a script FILE (nothing inline to inspect). */
|
|
275
|
+
function interpreterInlineCode(args: readonly string[]): string | null {
|
|
276
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
277
|
+
const value = args[index] as string
|
|
278
|
+
if (value === '-c' || value === '-e' || value === '--eval') return args[index + 1] ?? null
|
|
279
|
+
if (value.startsWith('--eval=')) return value.slice('--eval='.length)
|
|
280
|
+
}
|
|
281
|
+
return null
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Find the REAL command a piece resolves to, and where ITS OWN arguments
|
|
286
|
+
* begin — past a leading `NAME=value` assignment and a chain of transparent
|
|
287
|
+
* wrappers (`sudo`/`env`/`timeout`/`nice`/`caffeinate`/`arch`/`exec`/`time`/
|
|
288
|
+
* `stdbuf`/`setsid`/`command`/`doas`/`nohup`/`gtimeout`) and THEIR OWN
|
|
289
|
+
* arguments (P2: "detect... by the walker's RESOLVED command"). Reuses
|
|
290
|
+
* `../shell/prefixes.ts`'s own `skipPrefixes` — the SAME, already-tested
|
|
291
|
+
* wrapper-argument-skipping logic every other rule's classification is
|
|
292
|
+
* built on (`shell/invocation.ts`'s `walk()` calls it too) — rather than a
|
|
293
|
+
* second, narrower reimplementation: an earlier version of this function
|
|
294
|
+
* had its own generic "skip one flag at a time" loop, which mishandled a
|
|
295
|
+
* wrapper's own POSITIONAL argument (`timeout 90 script ...` — `90` is
|
|
296
|
+
* `timeout`'s duration, not a flag, and a generic dash-flag skipper does
|
|
297
|
+
* not know to skip it) — `skipPrefixes` already has a specific handler for
|
|
298
|
+
* exactly that (`skipTimeoutFlags`).
|
|
299
|
+
*/
|
|
300
|
+
function resolvedCommand(piece: WordPiece): { readonly name: string | undefined; readonly argsStart: number } {
|
|
301
|
+
const index = skipPrefixes(piece.tokens)
|
|
302
|
+
if (index >= piece.tokens.length) return { name: undefined, argsStart: index }
|
|
303
|
+
return { name: basenameOf(piece.values[index] as string).toLowerCase(), argsStart: index + 1 }
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** A network git verb, a curl/wget/httpie/xh call to Azure DevOps, `az`, or an `adl`/`adl-agent-id` entry point — the shapes `env -i`/bare `env -` is worth denying for (P1: clearing the WHOLE environment for a command that never needed an identity is harmless). Coarse, matching the same tradeoff every other check in this file makes. */
|
|
307
|
+
function isLikelyIdentityBearing(name: string, args: readonly string[]): boolean {
|
|
308
|
+
if (name === 'git' || name === 'git.exe') {
|
|
309
|
+
const subIndex = args.findIndex((value) => !value.startsWith('-'))
|
|
310
|
+
if (subIndex < 0) return false
|
|
311
|
+
return isNetworkGitInvocation((args[subIndex] as string).toLowerCase(), args.slice(subIndex + 1))
|
|
312
|
+
}
|
|
313
|
+
if (HTTP_CLIENT_BINARY_NAMES.has(name)) return args.some((value) => isAdoUrl(value))
|
|
314
|
+
if (AZ_NAMES.has(name)) return true
|
|
315
|
+
if (ADL_BINARY_NAMES.has(name) || ADL_AGENT_ID_BINARY_NAMES.has(name)) return true
|
|
316
|
+
return false
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* F3 (third independent review, 2026-09-29): a setter/clearer keyword is
|
|
321
|
+
* still missed when it is NOT `values[0]` — `if true; then export
|
|
322
|
+
* ADL_HUMAN_AZDO=1; fi` splits (on `;`) into a piece whose first word is
|
|
323
|
+
* the keyword `then`, not `export`; `builtin export …`/`command export …`
|
|
324
|
+
* explicitly invoke the builtin/external form, bypassing any shell
|
|
325
|
+
* function or alias named `export` but still meaning the same thing. Strip
|
|
326
|
+
* a leading run of these — pure syntax markers or explicit-invocation
|
|
327
|
+
* prefixes, none of which take a flag/operand of their own to skip past —
|
|
328
|
+
* to find the actual setter/clearer keyword underneath. `command` is
|
|
329
|
+
* ALSO one of `shell/prefixes.ts`'s own `COMMAND_PREFIXES` (so
|
|
330
|
+
* `resolvedCommand`'s wrapper-chain resolution already skips it too); kept
|
|
331
|
+
* here as well since this strip runs on plain string VALUES, before (and
|
|
332
|
+
* independently of) any Token-based `resolvedCommand` call.
|
|
333
|
+
*/
|
|
334
|
+
const HEAD_SKIP_WORDS: ReadonlySet<string> = new Set(['then', 'do', 'else', 'elif', 'builtin', 'command'])
|
|
335
|
+
|
|
336
|
+
function afterHeadSkipWords(values: readonly string[]): readonly string[] {
|
|
337
|
+
let rest = values
|
|
338
|
+
while (rest.length > 0 && HEAD_SKIP_WORDS.has(basenameOf(rest[0] as string).toLowerCase())) {
|
|
339
|
+
rest = rest.slice(1)
|
|
340
|
+
}
|
|
341
|
+
return rest
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/** True when `values` (one piece's words) sets/exports/declares/reads-into/printf-v's `ADL_HUMAN_AZDO` in a real setter POSITION, or an interpreter's inline code writes it via `os.environ`/`process.env`/`$ENV`. */
|
|
345
|
+
function pieceSetsHumanAzdo(values: readonly string[], heredocs: readonly string[]): boolean {
|
|
346
|
+
const name = ADL_HUMAN_AZDO_ENV_VAR
|
|
347
|
+
let index = 0
|
|
348
|
+
while (index < values.length && ASSIGNMENT_SHAPE_RE.test(values[index] as string)) {
|
|
349
|
+
const word = values[index] as string
|
|
350
|
+
if (isAssignmentTo(word, name) || isNameOperandDynamic(word)) return true
|
|
351
|
+
index += 1
|
|
352
|
+
}
|
|
353
|
+
const resolved = afterHeadSkipWords(values)
|
|
354
|
+
if (resolved.length === 0) return false
|
|
355
|
+
const head = basenameOf(resolved[0] as string).toLowerCase()
|
|
356
|
+
const rest = resolved.slice(1)
|
|
357
|
+
if (head === 'export') {
|
|
358
|
+
// `-f` (functions) is unrelated; `-p` (print) is deliberately NOT
|
|
359
|
+
// excluded here any more (F3) — `export -p ADL_HUMAN_AZDO=1` still
|
|
360
|
+
// carries an assignment and real bash still exports it, `-p` or not; a
|
|
361
|
+
// bare `export -p ADL_HUMAN_AZDO` (no `=`, a genuine list/print with no
|
|
362
|
+
// real effect) is a coarse, low-cost over-match this file already
|
|
363
|
+
// accepts elsewhere (documented "dynamic names" tradeoff, same file).
|
|
364
|
+
if (rest.includes('-f')) return false
|
|
365
|
+
return rest.some((value) => value === name || isAssignmentTo(value, name) || isNameOperandDynamic(value))
|
|
366
|
+
}
|
|
367
|
+
if (head === 'declare' || head === 'typeset' || head === 'local') {
|
|
368
|
+
if (!rest.some((value) => value === '-x' || /^-[a-zA-Z]*x[a-zA-Z]*$/.test(value))) return false
|
|
369
|
+
return rest.some((value) => value === name || isAssignmentTo(value, name) || isNameOperandDynamic(value))
|
|
370
|
+
}
|
|
371
|
+
if (head === 'read') {
|
|
372
|
+
const target = rest.find((value) => !value.startsWith('-'))
|
|
373
|
+
return target !== undefined && (target === name || isNameOperandDynamic(target))
|
|
374
|
+
}
|
|
375
|
+
if (head === 'printf') {
|
|
376
|
+
const vIndex = rest.indexOf('-v')
|
|
377
|
+
if (vIndex < 0) return false
|
|
378
|
+
const target = rest[vIndex + 1]
|
|
379
|
+
return target !== undefined && (target === name || isNameOperandDynamic(target))
|
|
380
|
+
}
|
|
381
|
+
if (head === 'env') {
|
|
382
|
+
for (const value of rest) {
|
|
383
|
+
if (value.startsWith('-')) continue
|
|
384
|
+
if (!ASSIGNMENT_SHAPE_RE.test(value)) break
|
|
385
|
+
if (isAssignmentTo(value, name) || isNameOperandDynamic(value)) return true
|
|
386
|
+
}
|
|
387
|
+
return false
|
|
388
|
+
}
|
|
389
|
+
if (INTERPRETER_NAMES.has(head)) {
|
|
390
|
+
// Third independent review (2026-09-29): "heredoc-fed interpreters"
|
|
391
|
+
// (`python3 - <<'EOF' ... EOF`) have no `-c`/`-e`/`--eval` argument at
|
|
392
|
+
// all — the real code is the heredoc BODY, passed in from `match()`
|
|
393
|
+
// (computed once from the whole command, not per-piece).
|
|
394
|
+
const inline = interpreterInlineCode(rest)
|
|
395
|
+
const candidates = inline !== null ? [inline] : heredocs
|
|
396
|
+
return candidates.some((code) => PYTHON_HUMAN_AZDO_SET_RE.test(code) || NODE_HUMAN_AZDO_SET_RE.test(code) || PERL_HUMAN_AZDO_SET_RE.test(code))
|
|
397
|
+
}
|
|
398
|
+
return false
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/** True when `piece` (one piece's words) clears `ADL_AGENT_ID_AGENT` — `unset`/`env -u`/`export -n`/`declare +x`/`typeset +x` in a real clearer POSITION, an empty leading assignment, `env -i` wrapping an identity-bearing command, or an interpreter's inline code deleting it. */
|
|
402
|
+
function pieceClearsAgentIdentity(piece: WordPiece, heredocs: readonly string[]): boolean {
|
|
403
|
+
const values = piece.values
|
|
404
|
+
const name = ADL_AGENT_ID_ENV_VAR
|
|
405
|
+
let index = 0
|
|
406
|
+
while (index < values.length && ASSIGNMENT_SHAPE_RE.test(values[index] as string)) {
|
|
407
|
+
const word = values[index] as string
|
|
408
|
+
if (word === `${name}=`) return true
|
|
409
|
+
if (isNameOperandDynamic(word) && word.endsWith('=')) return true
|
|
410
|
+
index += 1
|
|
411
|
+
}
|
|
412
|
+
const afterKeywords = afterHeadSkipWords(values)
|
|
413
|
+
if (afterKeywords.length === 0) return false
|
|
414
|
+
const head = basenameOf(afterKeywords[0] as string).toLowerCase()
|
|
415
|
+
const rest = afterKeywords.slice(1)
|
|
416
|
+
if (head === 'unset') return rest.some((value) => value === name || isNameOperandDynamic(value))
|
|
417
|
+
if (head === 'export') return rest.includes('-n') && rest.some((value) => value === name || isNameOperandDynamic(value))
|
|
418
|
+
if (head === 'declare' || head === 'typeset' || head === 'local') return rest.includes('+x') && rest.some((value) => value === name || isNameOperandDynamic(value))
|
|
419
|
+
if (head === 'env') {
|
|
420
|
+
for (let look = 0; look < rest.length; look += 1) {
|
|
421
|
+
const flag = rest[look] as string
|
|
422
|
+
if ((flag === '-u' || flag === '--unset') && rest[look + 1] !== undefined && (rest[look + 1] === name || isNameOperandDynamic(rest[look + 1] as string))) return true
|
|
423
|
+
if (flag.startsWith('--unset=') && (flag.slice('--unset='.length) === name || isNameOperandDynamic(flag.slice('--unset='.length)))) return true
|
|
424
|
+
if (flag === '-i' || flag === '--ignore-environment' || flag === '-') {
|
|
425
|
+
const resolved = resolvedCommand(piece)
|
|
426
|
+
return resolved.name !== undefined && isLikelyIdentityBearing(resolved.name, values.slice(resolved.argsStart))
|
|
427
|
+
}
|
|
428
|
+
if (!flag.startsWith('-') && !ASSIGNMENT_SHAPE_RE.test(flag)) break
|
|
429
|
+
}
|
|
430
|
+
return false
|
|
431
|
+
}
|
|
432
|
+
if (INTERPRETER_NAMES.has(head)) {
|
|
433
|
+
// Third independent review (2026-09-29): heredoc-fed interpreters.
|
|
434
|
+
const inline = interpreterInlineCode(rest)
|
|
435
|
+
const candidates = inline !== null ? [inline] : heredocs
|
|
436
|
+
return candidates.some((code) => PYTHON_AGENT_ID_DELETE_RE.test(code) || NODE_AGENT_ID_DELETE_RE.test(code) || PERL_AGENT_ID_DELETE_RE.test(code))
|
|
437
|
+
}
|
|
438
|
+
return false
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const LOOPBACK_EXACT: ReadonlySet<string> = new Set(['localhost', '::1', '0'])
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* F4 (fourth independent review, 2026-09-29): `user@host` (ssh's own
|
|
445
|
+
* `user@` prefix) is stripped before checking; `127.1`/`127.0.1` (partial
|
|
446
|
+
* IPv4 notation — every major OS resolves these to the `127.0.0.1` range)
|
|
447
|
+
* are accepted alongside the full four-octet form.
|
|
448
|
+
*/
|
|
449
|
+
function isLoopbackHost(rawValue: string): boolean {
|
|
450
|
+
const value = rawValue.includes('@') ? rawValue.slice(rawValue.lastIndexOf('@') + 1) : rawValue
|
|
451
|
+
const lower = value.toLowerCase()
|
|
452
|
+
if (LOOPBACK_EXACT.has(lower)) return true
|
|
453
|
+
return /^127(?:\.\d{1,3}){1,3}$/.test(lower)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/** An unresolved shell expansion in a host-shaped position (F4: `ssh -tt $(hostname) …`) — cannot be proven non-loopback, so treated as a match (fail-closed), the same "dynamic names" tradeoff this file already makes elsewhere. */
|
|
457
|
+
const isDynamicHostCandidate = (value: string): boolean => /\$\(|`|\$\{/.test(value)
|
|
458
|
+
|
|
459
|
+
function sshForcesTty(args: readonly string[]): boolean {
|
|
460
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
461
|
+
const value = args[index] as string
|
|
462
|
+
if (value === '-t' || value === '-tt' || /^-[a-zA-Z]*t{1,2}[a-zA-Z]*$/.test(value)) return true
|
|
463
|
+
const next = args[index + 1]
|
|
464
|
+
if ((value === '-o' || value === '--') && next !== undefined && /^requesttty=force$/i.test(next)) return true
|
|
465
|
+
if (/^-o?requesttty=force$/i.test(value.replace(/\s+/g, ''))) return true
|
|
466
|
+
}
|
|
467
|
+
return false
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/** No legitimate use on an agent surface — see this file's own F1(c) header. `zpty` is zsh's own pty module command — invoked as `zsh -c 'zpty ...'`, this scanner's own `-c` recursion (real shells only) makes `zpty` the RESOLVED command of the nested piece, not merely an argument to `zsh`. */
|
|
471
|
+
const UNCONDITIONAL_PTY_WRAPPERS: ReadonlySet<string> = new Set(['script', 'unbuffer', 'expect', 'zpty'])
|
|
472
|
+
|
|
473
|
+
/** True when `args` is nothing but `--help`/`-h`/`--version`/`-V` — a string-value mirror of `shell/invocation.ts`'s own (Token-based) `isHelpOrVersionOnly`. F7 (fourth independent review, 2026-09-29): `expect --version` has no script to run at all — harmless. */
|
|
474
|
+
function isHelpOrVersionOnlyValues(args: readonly string[]): boolean {
|
|
475
|
+
let sawHelp = false
|
|
476
|
+
for (const arg of args) {
|
|
477
|
+
if (arg === '--') return false
|
|
478
|
+
if (!arg.startsWith('-')) return false
|
|
479
|
+
if (arg === '--help' || arg === '-h' || arg === '--version' || arg === '-V') {
|
|
480
|
+
sawHelp = true
|
|
481
|
+
continue
|
|
482
|
+
}
|
|
483
|
+
return false
|
|
484
|
+
}
|
|
485
|
+
return sawHelp
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/** Every `-e CODE` occurrence (F4: `osascript` accepts MULTIPLE `-e` flags, each one a line of the same script — reading only the first, as `interpreterInlineCode` does, missed a script split across several). */
|
|
489
|
+
function allDashEArgs(args: readonly string[]): readonly string[] {
|
|
490
|
+
const values: string[] = []
|
|
491
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
492
|
+
if (args[index] === '-e' && args[index + 1] !== undefined) values.push(args[index + 1] as string)
|
|
493
|
+
}
|
|
494
|
+
return values
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const TMUX_ACTIONS: ReadonlySet<string> = new Set(['new-session', 'new', 'new-window', 'split-window', 'send-keys'])
|
|
498
|
+
/** Bundle IDs for `open -b <id>` — F4: the app-name check (`open -a Terminal`) has no bundle-id equivalent to match against. */
|
|
499
|
+
const TERMINAL_BUNDLE_IDS: ReadonlySet<string> = new Set([
|
|
500
|
+
'com.apple.terminal',
|
|
501
|
+
'com.googlecode.iterm2',
|
|
502
|
+
'com.mitchellh.ghostty',
|
|
503
|
+
'dev.warp.warp-stable',
|
|
504
|
+
'net.kovidgoyal.kitty',
|
|
505
|
+
'org.alacritty',
|
|
506
|
+
'com.github.wez.wezterm',
|
|
507
|
+
])
|
|
508
|
+
/** Terminal-app names `open -a`/AppleScript/JXA name by — F4: widened past Terminal/iTerm to every terminal emulator the finding named. */
|
|
509
|
+
const TERMINAL_APP_NAME_RE = /\b(?:terminal|iterm|ghostty|warp|kitty|alacritty|wezterm)\b/i
|
|
510
|
+
|
|
511
|
+
/** True when `piece` (one piece's words) invokes a pty-faking wrapper, resolved past a leading assignment and a chain of transparent wrappers. See this file's own F1(c) header for which shapes are unconditional vs. narrowed to a loopback host. */
|
|
512
|
+
function pieceUsesPtyFakingWrapper(piece: WordPiece): boolean {
|
|
513
|
+
const resolved = resolvedCommand(piece)
|
|
514
|
+
const name = resolved.name
|
|
515
|
+
if (name === undefined) return false
|
|
516
|
+
const args = piece.values.slice(resolved.argsStart)
|
|
517
|
+
if (UNCONDITIONAL_PTY_WRAPPERS.has(name)) return !isHelpOrVersionOnlyValues(args)
|
|
518
|
+
if (name === 'socat') return args.some((value) => /\bpty\b/i.test(value))
|
|
519
|
+
if (name === 'tmux') return args.some((value) => TMUX_ACTIONS.has(value) || value === '-dm' || value === '-dmS')
|
|
520
|
+
if (name === 'screen') {
|
|
521
|
+
if (args.some((value) => value === '-dm' || value === '-dmS')) return true
|
|
522
|
+
return args.includes('-d') && args.includes('-m')
|
|
523
|
+
}
|
|
524
|
+
if (name === 'ruby') {
|
|
525
|
+
if (args.includes('-rpty')) return true
|
|
526
|
+
const code = interpreterInlineCode(args)
|
|
527
|
+
return code !== null && /require\s+['"]pty['"]/.test(code)
|
|
528
|
+
}
|
|
529
|
+
if (name === 'perl' && args.includes('-MIO::Pty')) return true
|
|
530
|
+
if (INTERPRETER_NAMES.has(name)) {
|
|
531
|
+
const code = interpreterInlineCode(args)
|
|
532
|
+
if (code === null) return false
|
|
533
|
+
// F4: comma-form imports (`import os, pty`) and `__import__('pty')`.
|
|
534
|
+
if (name.startsWith('python')) {
|
|
535
|
+
return (
|
|
536
|
+
/(?:^|[\s;])import\s+(?:[\w.]+\s*,\s*)*pty\b|\bfrom\s+pty\s+import\b|\bpty\.(?:spawn|fork|openpty)\s*\(|__import__\(\s*['"]pty['"]\s*\)/.test(
|
|
537
|
+
code,
|
|
538
|
+
)
|
|
539
|
+
)
|
|
540
|
+
}
|
|
541
|
+
if (name.startsWith('node')) return /\brequire\(\s*['"](?:node-)?pty['"]\s*\)/.test(code)
|
|
542
|
+
return false
|
|
543
|
+
}
|
|
544
|
+
if (name === 'ssh') {
|
|
545
|
+
if (!sshForcesTty(args)) return false
|
|
546
|
+
if (args.some(isLoopbackHost)) return true
|
|
547
|
+
return args.some((value) => !value.startsWith('-') && isDynamicHostCandidate(value))
|
|
548
|
+
}
|
|
549
|
+
if (name === 'open') {
|
|
550
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
551
|
+
const value = args[index] as string
|
|
552
|
+
// F4: combined flags (`-na` = -n new-instance + -a app) — any
|
|
553
|
+
// combined short-flag string containing `a`/`b` still takes the
|
|
554
|
+
// NEXT word as the app name / bundle id, same as the bare flag.
|
|
555
|
+
if (/^-[a-zA-Z]*a[a-zA-Z]*$/.test(value) && TERMINAL_APP_NAME_RE.test(args[index + 1] ?? '')) return true
|
|
556
|
+
if (/^-[a-zA-Z]*b[a-zA-Z]*$/.test(value) && TERMINAL_BUNDLE_IDS.has((args[index + 1] ?? '').toLowerCase())) return true
|
|
557
|
+
}
|
|
558
|
+
return args.some((value) => value.toLowerCase().endsWith('.command'))
|
|
559
|
+
}
|
|
560
|
+
if (name === 'osascript') {
|
|
561
|
+
const codes = allDashEArgs(args)
|
|
562
|
+
if (codes.length === 0) return false
|
|
563
|
+
const combined = codes.join('\n')
|
|
564
|
+
if (!TERMINAL_APP_NAME_RE.test(combined)) return false
|
|
565
|
+
// F4: AppleScript's `do script` and JXA's (`-l JavaScript`) `.doScript(`
|
|
566
|
+
// are the same operation in the two languages osascript accepts.
|
|
567
|
+
return /\bdo script\b/i.test(combined) || /\.\s*doScript\s*\(/i.test(combined)
|
|
568
|
+
}
|
|
569
|
+
return false
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
type BypassReason = 'sets-human-azdo' | 'clears-agent-identity' | 'pty-faking-wrapper'
|
|
573
|
+
|
|
574
|
+
export const adlHumanAzdoBypass: RuleSpec = {
|
|
575
|
+
id: RULE_ID,
|
|
576
|
+
category: 'tool',
|
|
577
|
+
severity: 'deny',
|
|
578
|
+
enabledByDefault: true,
|
|
579
|
+
summary:
|
|
580
|
+
"Deny an agent command that sets/exports/assigns ADL_HUMAN_AZDO, clears ADL_AGENT_ID_AGENT, or fakes a TTY to defeat bin/git-ado's human/agent decision (STATUS.md 12p decisions 1/1b/1c; F1).",
|
|
581
|
+
params: noParams,
|
|
582
|
+
match(inv: Invocation, ctx: RuleContext<Record<string, never>>): Finding | null {
|
|
583
|
+
// A tool-call payload (a real MCP call) carries no shell command text
|
|
584
|
+
// at all — nothing for this word-level scan to see.
|
|
585
|
+
if (inv.kind === 'tool-call') return null
|
|
586
|
+
const command = ctx.command ?? ''
|
|
587
|
+
if (command.trim().length === 0) return null
|
|
588
|
+
const pieces = wordPiecesFor(command)
|
|
589
|
+
// Third independent review (2026-09-29): heredoc-fed interpreters
|
|
590
|
+
// (`python3 - <<'EOF' ... EOF`) have no `-c`/`-e`/`--eval` argument at
|
|
591
|
+
// all — computed once from the whole command, not per-piece.
|
|
592
|
+
const heredocs = heredocBodies(command)
|
|
593
|
+
let reason: BypassReason | null = null
|
|
594
|
+
for (const piece of pieces) {
|
|
595
|
+
if (pieceSetsHumanAzdo(piece.values, heredocs)) {
|
|
596
|
+
reason = 'sets-human-azdo'
|
|
597
|
+
break
|
|
598
|
+
}
|
|
599
|
+
if (pieceClearsAgentIdentity(piece, heredocs)) {
|
|
600
|
+
reason = 'clears-agent-identity'
|
|
601
|
+
break
|
|
602
|
+
}
|
|
603
|
+
if (pieceUsesPtyFakingWrapper(piece)) {
|
|
604
|
+
reason = 'pty-faking-wrapper'
|
|
605
|
+
break
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
if (reason === null) return null
|
|
609
|
+
// Reuse the ONE shared human-pass-through check rather than asserting
|
|
610
|
+
// the same fact independently: a pre-tool-use hook invocation reads a
|
|
611
|
+
// JSON payload from its host, never an interactive TTY, so this can
|
|
612
|
+
// never legitimately be a marked-human session — `stdinIsTTY` is
|
|
613
|
+
// explicitly `false` here, by construction, not merely assumed.
|
|
614
|
+
const consideredHuman = isMarkedHumanAzdoCaller({ [ADL_HUMAN_AZDO_ENV_VAR]: ctx.env.get(ADL_HUMAN_AZDO_ENV_VAR) } as NodeJS.ProcessEnv, false)
|
|
615
|
+
return { ruleId: RULE_ID, severity: 'deny', detail: { consideredHuman: String(consideredHuman), reason } }
|
|
616
|
+
},
|
|
617
|
+
message(finding: Finding, ctx: MessageContext) {
|
|
618
|
+
const reason = (typeof finding.detail.reason === 'string' ? finding.detail.reason : 'sets-human-azdo') as BypassReason
|
|
619
|
+
if (reason === 'clears-agent-identity') {
|
|
620
|
+
const user = `clearing ${ADL_AGENT_ID_ENV_VAR} is not allowed — an agent must always carry its identity`
|
|
621
|
+
return {
|
|
622
|
+
user,
|
|
623
|
+
agent:
|
|
624
|
+
`DENIED ${user}. unset/env -u/env -i (wrapping an identity-bearing command)/an empty inline assignment/export -n/` +
|
|
625
|
+
`declare or typeset +x on ${ADL_AGENT_ID_ENV_VAR} removes the one thing that routes a network git command as this ` +
|
|
626
|
+
`agent instead of falling through to bin/git-ado's own default (F1, STATUS.md 12p). Never clear it; prefix the ` +
|
|
627
|
+
`command with ${ADL_AGENT_ID_ENV_VAR}=<agent> instead. Blocked: ${ctx.snippet}`,
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
if (reason === 'pty-faking-wrapper') {
|
|
631
|
+
const user =
|
|
632
|
+
'faking a TTY (script/unbuffer/expect, socat/tmux/screen/zsh zpty, a pty-module interpreter one-liner, ssh -t to a loopback host, or launching a real terminal app) is not allowed'
|
|
633
|
+
return {
|
|
634
|
+
user,
|
|
635
|
+
agent:
|
|
636
|
+
`DENIED ${user}. These tools exist to make a program's isatty() check pass when nothing real is attached to it — ` +
|
|
637
|
+
"bin/git-ado's own human-vs-agent decision is exactly such a check, and faking it (F1, STATUS.md 12p) is how a " +
|
|
638
|
+
'session with no agent identity reaches the human credential path undetected. There is no legitimate use of a ' +
|
|
639
|
+
`pty-faking wrapper on an agent surface; run the command directly instead. Blocked: ${ctx.snippet}`,
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
const user = `${ADL_HUMAN_AZDO_ENV_VAR} marks a human terminal; an agent may never set it — use ADL_AGENT_ID_AGENT=<agent>`
|
|
643
|
+
return {
|
|
644
|
+
user,
|
|
645
|
+
agent:
|
|
646
|
+
`DENIED ${user}. ${ADL_HUMAN_AZDO_ENV_VAR}=1 tells bin/git-ado this is Tarun's own interactive terminal - setting, exporting, ` +
|
|
647
|
+
`or assigning it from an agent surface (inline, export, env, declare/typeset -x, printf -v, read, a nested REAL shell — ` +
|
|
648
|
+
`quote-split or backslash-escaped included, F1 — or an interpreter's own os.environ/process.env/$ENV) would let ` +
|
|
649
|
+
`git-ado's human pass-through apply with no agent identity involved. Unset it (or use \`env -u ${ADL_HUMAN_AZDO_ENV_VAR}\`) ` +
|
|
650
|
+
`if you need it absent; prefix the command with ADL_AGENT_ID_AGENT=<agent-tarun|agent-vivek|agent-reviewer> instead. ` +
|
|
651
|
+
`Blocked: ${ctx.snippet}`,
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
corpus: {
|
|
655
|
+
deny: [
|
|
656
|
+
'ADL_HUMAN_AZDO=1 git push origin main',
|
|
657
|
+
'export ADL_HUMAN_AZDO=1',
|
|
658
|
+
'export ADL_HUMAN_AZDO=1 && git push origin main',
|
|
659
|
+
'env ADL_HUMAN_AZDO=1 git push origin main',
|
|
660
|
+
'declare -x ADL_HUMAN_AZDO=1',
|
|
661
|
+
'typeset -x ADL_HUMAN_AZDO=1',
|
|
662
|
+
'export ADL_HUMAN_AZDO',
|
|
663
|
+
"bash -c 'export ADL_HUMAN_AZDO=1 && git push origin main'",
|
|
664
|
+
`python3 -c "import os; os.environ['ADL_HUMAN_AZDO'] = '1'"`,
|
|
665
|
+
`node -e "process.env.ADL_HUMAN_AZDO = '1'"`,
|
|
666
|
+
`node -e "process.env['ADL_HUMAN_AZDO'] = '1'"`,
|
|
667
|
+
// F1(a): shell quote-splitting / backslash-escaping cannot defeat the
|
|
668
|
+
// check any more — the tokenizer resolves both before matching.
|
|
669
|
+
`export ADL_HUMAN_AZD''O=1`,
|
|
670
|
+
`export ADL_HUMAN_AZ\\DO=1`,
|
|
671
|
+
// A bare `printf ...` line alone produces no Invocation at all
|
|
672
|
+
// (`printf` is in shell/invocation.ts's own `introspectionNames`, so
|
|
673
|
+
// `decideCommand`'s per-invocation loop never runs) — realistic usage
|
|
674
|
+
// always chains it with the command it is trying to unlock, which is
|
|
675
|
+
// also what makes the loop run at all.
|
|
676
|
+
`printf -v ADL_HUMAN_AZDO '1'; git push origin main`,
|
|
677
|
+
'read ADL_HUMAN_AZDO',
|
|
678
|
+
// F1(b): clearing ADL_AGENT_ID_AGENT in any form.
|
|
679
|
+
'unset ADL_AGENT_ID_AGENT',
|
|
680
|
+
'unset ADL_AGENT_ID_AGENT; git push origin feat/x',
|
|
681
|
+
'env -u ADL_AGENT_ID_AGENT git push origin feat/x',
|
|
682
|
+
'env --unset ADL_AGENT_ID_AGENT git push origin feat/x',
|
|
683
|
+
'env --unset=ADL_AGENT_ID_AGENT git push origin feat/x',
|
|
684
|
+
'env -i git push origin feat/x',
|
|
685
|
+
'env --ignore-environment git push origin feat/x',
|
|
686
|
+
'ADL_AGENT_ID_AGENT= git push origin feat/x',
|
|
687
|
+
'export -n ADL_AGENT_ID_AGENT',
|
|
688
|
+
'declare +x ADL_AGENT_ID_AGENT',
|
|
689
|
+
// F1(c): pty-faking wrappers, unconditional.
|
|
690
|
+
'script -q /dev/null git push origin feat/x',
|
|
691
|
+
'unbuffer git push origin feat/x',
|
|
692
|
+
'expect -c "spawn git push origin feat/x"',
|
|
693
|
+
"socat exec:'git push origin feat/x',pty stdio",
|
|
694
|
+
`python3 -c "import pty; pty.spawn(['git','push','origin','feat/x'])"`,
|
|
695
|
+
'ssh -t localhost git push origin feat/x',
|
|
696
|
+
'ssh -t 127.0.0.1 git push origin feat/x',
|
|
697
|
+
// The live F1 incident, combined.
|
|
698
|
+
"export ADL_HUMAN_AZD''O=1; unset ADL_AGENT_ID_AGENT; script -q /dev/null git push origin feat/x",
|
|
699
|
+
],
|
|
700
|
+
allow: [
|
|
701
|
+
'git status',
|
|
702
|
+
'ADL_AGENT_ID_AGENT=agent-tarun git push origin feat/x',
|
|
703
|
+
// Unsetting HUMAN_AZDO is explicitly fine — only SETTING it is denied.
|
|
704
|
+
'env -u ADL_HUMAN_AZDO git status',
|
|
705
|
+
'unset ADL_HUMAN_AZDO',
|
|
706
|
+
// Unsetting an unrelated variable, or exporting one, is untouched.
|
|
707
|
+
'unset SOME_OTHER_VAR',
|
|
708
|
+
'export PATH=/usr/bin:$PATH',
|
|
709
|
+
// ssh -t to a genuine remote host: ordinary, common usage.
|
|
710
|
+
'ssh -t build-host.example.com uptime',
|
|
711
|
+
// socat without a pty argument: unrelated.
|
|
712
|
+
'socat TCP:example.com:80 -',
|
|
713
|
+
// A bare python/node one-liner naming neither variable: untouched.
|
|
714
|
+
`python3 -c "print('hello')"`,
|
|
715
|
+
// SECOND REVIEW (2026-09-29): the false positives that broke normal
|
|
716
|
+
// agent work — a mention of the name in an unrelated command's
|
|
717
|
+
// argument, a read (not a set), an unrelated `-c` flag mistaken for
|
|
718
|
+
// shell `-c`, a bare 'pty' word, and env -i clearing the WHOLE
|
|
719
|
+
// environment for a command that never needed an identity.
|
|
720
|
+
'git commit -m "ADL_HUMAN_AZDO=1 is denied now"',
|
|
721
|
+
'git log -S "ADL_HUMAN_AZDO=1"',
|
|
722
|
+
'declare -p ADL_HUMAN_AZDO',
|
|
723
|
+
// `rg`, not `grep` — `tool.grep` denies grep outright, unrelated to
|
|
724
|
+
// this rule; the point here is `-c` (rg's own count flag) not being
|
|
725
|
+
// mistaken for shell `-c`.
|
|
726
|
+
"bun -e '1' && rg -c 'unset ADL_AGENT_ID_AGENT' STATUS.md",
|
|
727
|
+
`node -e "console.log('pty')"`,
|
|
728
|
+
'env -i PATH=/usr/bin ls',
|
|
729
|
+
],
|
|
730
|
+
},
|
|
731
|
+
}
|