@amsterdamdatalabs/adl-agent-control-darwin-arm64 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adl +4 -0
- package/bin/cursor-settings +14 -0
- package/bin/default-agent-file +14 -0
- package/bin/git +670 -0
- package/bin/git-ado +425 -0
- package/bin/global-agents +14 -0
- package/bin/global-surface-sweep +14 -0
- package/bin/health-check +38 -0
- package/bin/kimi-hooks +14 -0
- package/bin/lean-ctx-observe-strip +361 -0
- package/bin/lib/bun-compile-build.sh +34 -0
- package/bin/lib/lean-ctx-observe-hooks.sh +634 -0
- package/bin/managed-settings +14 -0
- package/bin/opencode-hooks +14 -0
- package/bin/reconcile +2648 -0
- package/bin/scratch-reap +14 -0
- package/bin/shell-path-policy +64 -0
- package/bin/surface-policy +14 -0
- package/bin/sync-and-reconcile +215 -0
- package/bin/update-azure-agent-pool +29 -0
- package/bin/validate-manifest +171 -0
- package/bin/vscode-settings +14 -0
- package/package.json +44 -0
- package/packages/agent-hooks/README.md +411 -0
- package/packages/agent-hooks/assets/hooks.json +97 -0
- package/packages/agent-hooks/assets/opencode-plugin.template.ts +224 -0
- package/packages/agent-hooks/bunfig.toml +27 -0
- package/packages/agent-hooks/deploy-profile.json +53 -0
- package/packages/agent-hooks/deploy-profile.schema.json +120 -0
- package/packages/agent-hooks/package.json +23 -0
- package/packages/agent-hooks/src/cli/args.ts +99 -0
- package/packages/agent-hooks/src/cli/doctor.ts +241 -0
- package/packages/agent-hooks/src/cli/rules.ts +133 -0
- package/packages/agent-hooks/src/deploy/deploy.ts +181 -0
- package/packages/agent-hooks/src/deploy/doctor.ts +158 -0
- package/packages/agent-hooks/src/deploy/index.ts +17 -0
- package/packages/agent-hooks/src/deploy/json-merge.ts +115 -0
- package/packages/agent-hooks/src/deploy/legacy-lock.ts +213 -0
- package/packages/agent-hooks/src/deploy/list.ts +117 -0
- package/packages/agent-hooks/src/deploy/lock.ts +65 -0
- package/packages/agent-hooks/src/deploy/opencode-template.ts +74 -0
- package/packages/agent-hooks/src/deploy/profile.ts +117 -0
- package/packages/agent-hooks/src/deploy/render.ts +162 -0
- package/packages/agent-hooks/src/deploy/source.ts +84 -0
- package/packages/agent-hooks/src/gating/config.ts +514 -0
- package/packages/agent-hooks/src/gating/root.ts +117 -0
- package/packages/agent-hooks/src/hooks/briefing/handler.ts +22 -0
- package/packages/agent-hooks/src/hooks/briefing/index.ts +320 -0
- package/packages/agent-hooks/src/hooks/contract.ts +112 -0
- package/packages/agent-hooks/src/hooks/crg/handler.ts +22 -0
- package/packages/agent-hooks/src/hooks/crg/index.ts +209 -0
- package/packages/agent-hooks/src/hooks/lean-ctx/handler.ts +22 -0
- package/packages/agent-hooks/src/hooks/lean-ctx/index.ts +173 -0
- package/packages/agent-hooks/src/hooks/lean-ctx/mapping.ts +121 -0
- package/packages/agent-hooks/src/hooks/lean-ctx/scope-rewrite.ts +207 -0
- package/packages/agent-hooks/src/hooks/log.ts +233 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/config.ts +58 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/constants.ts +149 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/handler.ts +72 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/index.ts +203 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +212 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/skill-roots.ts +73 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/skills.ts +98 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +115 -0
- package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +174 -0
- package/packages/agent-hooks/src/hosts/impl/claude.ts +47 -0
- package/packages/agent-hooks/src/hosts/impl/codex.ts +47 -0
- package/packages/agent-hooks/src/hosts/impl/cursor.ts +40 -0
- package/packages/agent-hooks/src/hosts/impl/kimi.ts +47 -0
- package/packages/agent-hooks/src/hosts/impl/opencode.ts +54 -0
- package/packages/agent-hooks/src/hosts/registry.ts +29 -0
- package/packages/agent-hooks/src/hosts/spec.ts +113 -0
- package/packages/agent-hooks/src/lean-ctx/env.ts +106 -0
- package/packages/agent-hooks/src/lean-ctx/mcp.ts +140 -0
- package/packages/agent-hooks/src/lib/spawn-with-timeout.ts +120 -0
- package/packages/agent-hooks/src/log/writer.ts +230 -0
- package/packages/agent-hooks/src/main.ts +269 -0
- package/packages/agent-hooks/src/pre-tool-use/handler.ts +549 -0
- package/packages/agent-hooks/src/rules/engine.ts +293 -0
- package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +51 -0
- package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +320 -0
- package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +249 -0
- package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +258 -0
- package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +731 -0
- package/packages/agent-hooks/src/rules/impl/adl-identity.ts +128 -0
- package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +179 -0
- package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +65 -0
- package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +156 -0
- package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +121 -0
- package/packages/agent-hooks/src/rules/impl/adl-session-required.ts +403 -0
- package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +92 -0
- package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +74 -0
- package/packages/agent-hooks/src/rules/impl/advisory-coverage.ts +43 -0
- package/packages/agent-hooks/src/rules/impl/advisory-finder.ts +62 -0
- package/packages/agent-hooks/src/rules/impl/agent-secrets-stay-unread.ts +173 -0
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +508 -0
- package/packages/agent-hooks/src/rules/impl/fs-canonical-checkout.ts +86 -0
- package/packages/agent-hooks/src/rules/impl/fs-git-internals.ts +75 -0
- package/packages/agent-hooks/src/rules/impl/fs-mv.ts +66 -0
- package/packages/agent-hooks/src/rules/impl/fs-rm.ts +83 -0
- package/packages/agent-hooks/src/rules/impl/fs-trash.ts +140 -0
- package/packages/agent-hooks/src/rules/impl/git-core.ts +101 -0
- package/packages/agent-hooks/src/rules/impl/git-helpers.ts +408 -0
- package/packages/agent-hooks/src/rules/impl/git-history.ts +77 -0
- package/packages/agent-hooks/src/rules/impl/git-paths.ts +139 -0
- package/packages/agent-hooks/src/rules/impl/git-plumbing.ts +167 -0
- package/packages/agent-hooks/src/rules/impl/git-protected-tree.ts +132 -0
- package/packages/agent-hooks/src/rules/impl/git-transitions.ts +292 -0
- package/packages/agent-hooks/src/rules/impl/git-verify.ts +95 -0
- package/packages/agent-hooks/src/rules/impl/git-worktree.ts +265 -0
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +76 -0
- package/packages/agent-hooks/src/rules/impl/messages.ts +128 -0
- package/packages/agent-hooks/src/rules/impl/parse-uncertain.ts +143 -0
- package/packages/agent-hooks/src/rules/impl/pr-completion.ts +35 -0
- package/packages/agent-hooks/src/rules/impl/shell-remote-script-exec.ts +63 -0
- package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +283 -0
- package/packages/agent-hooks/src/rules/impl/tool-bun-test.ts +81 -0
- package/packages/agent-hooks/src/rules/impl/tool-cargo.ts +66 -0
- package/packages/agent-hooks/src/rules/impl/tool-chmod-hook.ts +42 -0
- package/packages/agent-hooks/src/rules/impl/tool-find.ts +82 -0
- package/packages/agent-hooks/src/rules/impl/tool-frontend.ts +83 -0
- package/packages/agent-hooks/src/rules/impl/tool-grep.ts +93 -0
- package/packages/agent-hooks/src/rules/impl/tool-lean-ctx-global.ts +594 -0
- package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +77 -0
- package/packages/agent-hooks/src/rules/ports.ts +178 -0
- package/packages/agent-hooks/src/rules/registry.ts +233 -0
- package/packages/agent-hooks/src/rules/shell/git-identity.ts +1415 -0
- package/packages/agent-hooks/src/rules/shell/git-internals.ts +186 -0
- package/packages/agent-hooks/src/rules/shell/invocation.ts +1083 -0
- package/packages/agent-hooks/src/rules/shell/piped-script.ts +201 -0
- package/packages/agent-hooks/src/rules/shell/prefixes.ts +214 -0
- package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +108 -0
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +149 -0
- package/packages/agent-hooks/src/rules/shell/split.ts +179 -0
- package/packages/agent-hooks/src/rules/shell/substitution.ts +394 -0
- package/packages/agent-hooks/src/rules/shell/token.ts +180 -0
- package/packages/agent-hooks/src/rules/shell/xargs.ts +81 -0
- package/packages/agent-hooks/src/rules/spec.ts +152 -0
- package/packages/agent-hooks/src/surface-policy.ts +37 -0
- package/packages/agent-hooks/tsconfig.json +23 -0
- package/packages/agent-settings/assets/GLOBAL-AGENTS.md +107 -0
- package/packages/agent-settings/assets/agents/architect.toml +30 -0
- package/packages/agent-settings/assets/agents/code-reviewer.toml +27 -0
- package/packages/agent-settings/assets/agents/critic.toml +35 -0
- package/packages/agent-settings/assets/agents/executor.toml +28 -0
- package/packages/agent-settings/assets/agents/explore.toml +25 -0
- package/packages/agent-settings/assets/agents/planner.toml +29 -0
- package/packages/agent-settings/assets/lean-ctx/config.toml +39 -0
- package/packages/agent-settings/assets/lean-ctx/gitignore +6 -0
- package/packages/agent-settings/assets/lean-ctx/layout.toml +5 -0
- package/packages/agent-settings/assets/mcp.json +20 -0
- package/packages/agent-settings/managed/README.md +331 -0
- package/packages/agent-settings/managed/claude-managed-settings.json +150 -0
- package/packages/agent-settings/managed/codex-requirements.toml +105 -0
- package/packages/agent-settings/protected.json +470 -0
- package/packages/agent-settings/src/deploy/agent-render.ts +94 -0
- package/packages/agent-settings/src/deploy/agent-toml.ts +76 -0
- package/packages/agent-settings/src/deploy/agents-deploy.ts +129 -0
- package/packages/agent-settings/src/deploy/doctor.ts +201 -0
- package/packages/agent-settings/src/deploy/index.ts +33 -0
- package/packages/agent-settings/src/deploy/json-pretty.ts +66 -0
- package/packages/agent-settings/src/deploy/lean-ctx-deploy.ts +138 -0
- package/packages/agent-settings/src/deploy/legacy-lock.ts +286 -0
- package/packages/agent-settings/src/deploy/list.ts +135 -0
- package/packages/agent-settings/src/deploy/lock.ts +112 -0
- package/packages/agent-settings/src/deploy/mcp-deploy.ts +175 -0
- package/packages/agent-settings/src/deploy/mcp-inspect.ts +56 -0
- package/packages/agent-settings/src/deploy/mcp-merge.ts +164 -0
- package/packages/agent-settings/src/deploy/mcp-render.ts +80 -0
- package/packages/agent-settings/src/deploy/mcp-source.ts +43 -0
- package/packages/agent-settings/src/deploy/profile.ts +296 -0
- package/packages/agent-settings/src/deploy/settings.ts +65 -0
- package/packages/agent-settings/src/global-agents.ts +230 -0
- package/packages/agent-settings/src/global-surface-sweep.ts +2179 -0
- package/packages/agent-settings/src/kimi-hooks.ts +455 -0
- package/packages/agent-settings/src/opencode-hooks.ts +76 -0
- package/packages/agent-settings/src/surface-policy.ts +441 -0
- package/packages/agent-settings/surface-policy.json +20 -0
- package/packages/agent-skills/assets/code-review/SKILL.md +100 -0
- package/packages/agent-skills/assets/codebase-design/SKILL.md +98 -0
- package/packages/agent-skills/assets/codebase-design/references/DEEPENING.md +37 -0
- package/packages/agent-skills/assets/codebase-design/references/DESIGN-IT-TWICE.md +44 -0
- package/packages/agent-skills/assets/codebase-design/references/TESTABILITY.md +29 -0
- package/packages/agent-skills/assets/debug-issue/SKILL.md +40 -0
- package/packages/agent-skills/assets/diagnosing-bugs/SKILL.md +100 -0
- package/packages/agent-skills/assets/diagnosing-bugs/references/FEEDBACK-LOOP-TACTICS.md +34 -0
- package/packages/agent-skills/assets/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
- package/packages/agent-skills/assets/domain-modeling/SKILL.md +86 -0
- package/packages/agent-skills/assets/domain-modeling/references/ADR-FORMAT.md +47 -0
- package/packages/agent-skills/assets/domain-modeling/references/CONTEXT-FORMAT.md +60 -0
- package/packages/agent-skills/assets/explore-codebase/SKILL.md +41 -0
- package/packages/agent-skills/assets/handoff/SKILL.md +28 -0
- package/packages/agent-skills/assets/implement/SKILL.md +28 -0
- package/packages/agent-skills/assets/refactor-safely/SKILL.md +44 -0
- package/packages/agent-skills/assets/review-changes/SKILL.md +45 -0
- package/packages/agent-skills/assets/tdd/SKILL.md +49 -0
- package/packages/agent-skills/assets/tdd/references/mocking.md +59 -0
- package/packages/agent-skills/assets/tdd/references/tests.md +77 -0
- package/packages/agent-skills/assets/testing/SKILL.md +54 -0
- package/packages/agent-skills/assets/to-feature/SKILL.md +91 -0
- package/packages/agent-skills/assets/to-feature/references/FEATURE-SPEC-TEMPLATE.md +88 -0
- package/packages/agent-skills/assets/to-workitems/SKILL.md +90 -0
- package/packages/agent-skills/assets/to-workitems/references/AZURE-DEVOPS-HIERARCHY.md +118 -0
- package/packages/agent-skills/assets/to-workitems/references/TICKET-TEMPLATES.md +70 -0
- package/packages/agent-skills/assets/wayfinder/SKILL.md +100 -0
- package/packages/agent-skills/assets/wayfinder/references/TEMPLATES.md +35 -0
- package/packages/agent-skills/assets/wayfinder/references/TICKET-TYPES.md +8 -0
- package/packages/agent-skills/deploy-profile.json +9 -0
- package/packages/agent-skills/deploy-profile.schema.json +45 -0
- package/packages/agent-skills/dist/deploy.d.ts +27 -0
- package/packages/agent-skills/dist/deploy.d.ts.map +1 -0
- package/packages/agent-skills/dist/deploy.js +186 -0
- package/packages/agent-skills/dist/deploy.js.map +1 -0
- package/packages/agent-skills/dist/doctor.d.ts +24 -0
- package/packages/agent-skills/dist/doctor.d.ts.map +1 -0
- package/packages/agent-skills/dist/doctor.js +141 -0
- package/packages/agent-skills/dist/doctor.js.map +1 -0
- package/packages/agent-skills/dist/fs-utils.d.ts +8 -0
- package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -0
- package/packages/agent-skills/dist/fs-utils.js +40 -0
- package/packages/agent-skills/dist/fs-utils.js.map +1 -0
- package/packages/agent-skills/dist/index.d.ts +8 -0
- package/packages/agent-skills/dist/index.d.ts.map +1 -0
- package/packages/agent-skills/dist/index.js +8 -0
- package/packages/agent-skills/dist/index.js.map +1 -0
- package/packages/agent-skills/dist/legacy-lock.d.ts +44 -0
- package/packages/agent-skills/dist/legacy-lock.d.ts.map +1 -0
- package/packages/agent-skills/dist/legacy-lock.js +121 -0
- package/packages/agent-skills/dist/legacy-lock.js.map +1 -0
- package/packages/agent-skills/dist/list.d.ts +23 -0
- package/packages/agent-skills/dist/list.d.ts.map +1 -0
- package/packages/agent-skills/dist/list.js +75 -0
- package/packages/agent-skills/dist/list.js.map +1 -0
- package/packages/agent-skills/dist/manifest.d.ts +15 -0
- package/packages/agent-skills/dist/manifest.d.ts.map +1 -0
- package/packages/agent-skills/dist/manifest.js +57 -0
- package/packages/agent-skills/dist/manifest.js.map +1 -0
- package/packages/agent-skills/dist/profile.d.ts +41 -0
- package/packages/agent-skills/dist/profile.d.ts.map +1 -0
- package/packages/agent-skills/dist/profile.js +86 -0
- package/packages/agent-skills/dist/profile.js.map +1 -0
- package/packages/agent-skills/dist/skill-config.d.ts +24 -0
- package/packages/agent-skills/dist/skill-config.d.ts.map +1 -0
- package/packages/agent-skills/dist/skill-config.js +68 -0
- package/packages/agent-skills/dist/skill-config.js.map +1 -0
- package/packages/agent-skills/dist/skill-meta.d.ts +17 -0
- package/packages/agent-skills/dist/skill-meta.d.ts.map +1 -0
- package/packages/agent-skills/dist/skill-meta.js +67 -0
- package/packages/agent-skills/dist/skill-meta.js.map +1 -0
- package/packages/agent-skills/package.json +31 -0
- package/packages/agent-skills/src/deploy.ts +222 -0
- package/packages/agent-skills/src/doctor.ts +178 -0
- package/packages/agent-skills/src/fs-utils.ts +40 -0
- package/packages/agent-skills/src/index.ts +29 -0
- package/packages/agent-skills/src/legacy-lock.ts +152 -0
- package/packages/agent-skills/src/list.ts +94 -0
- package/packages/agent-skills/src/manifest.ts +66 -0
- package/packages/agent-skills/src/profile.ts +128 -0
- package/packages/agent-skills/src/skill-config.ts +75 -0
- package/packages/agent-skills/src/skill-meta.ts +78 -0
- package/packages/agent-skills/tsconfig.build.json +13 -0
- package/packages/agent-skills/tsconfig.json +23 -0
- package/packages/azdo/README.md +111 -0
- package/packages/azdo/package.json +21 -0
- package/packages/azdo/src/azdo-pl.ts +275 -0
- package/packages/azdo/src/azdo-pr-review.ts +160 -0
- package/packages/azdo/src/azdo-pr.ts +289 -0
- package/packages/azdo/src/azdo-repo-doctor.ts +839 -0
- package/packages/azdo/src/azdo-wit.ts +145 -0
- package/packages/azdo/src/cli.ts +251 -0
- package/packages/azdo/src/lib/agent-identity.ts +198 -0
- package/packages/azdo/src/lib/agent-token.ts +167 -0
- package/packages/azdo/src/lib/client.ts +259 -0
- package/packages/azdo/src/lib/graph-identity.ts +153 -0
- package/packages/azdo/src/lib/validate-pr-metadata.ts +57 -0
- package/packages/azdo/src/mcp-server.ts +209 -0
- package/packages/azdo/src/tool-dispatch.ts +204 -0
- package/packages/azdo/tsconfig.json +13 -0
- package/packages/fleet/jobs/git-maintain/src/main.ts +588 -0
- package/packages/fleet/manifest.json +207 -0
- package/packages/fleet/manifest.schema.json +283 -0
- package/packages/fleet/src/default-agent-file.ts +144 -0
- package/packages/fleet/src/install-adl-package.ts +178 -0
- package/packages/fleet/src/install-embedding-model.ts +412 -0
- package/packages/fleet/src/launch-agents.ts +649 -0
- package/packages/fleet/src/managed-settings.ts +278 -0
- package/packages/fleet/src/scratch-reap.ts +601 -0
- package/packages/fleet/src/vscode-settings.ts +705 -0
- package/packages/fleet/systemd/adl-azure-agent-update.service +13 -0
- package/packages/fleet/systemd/adl-azure-agent-update.timer +10 -0
- package/packages/repo-controls/AGENTS.md +96 -0
- package/packages/repo-controls/CLAUDE.md +1 -0
- package/packages/repo-controls/LICENSE +20 -0
- package/packages/repo-controls/README.md +493 -0
- package/packages/repo-controls/assets/enable-integration-auto-complete.mjs +79 -0
- package/packages/repo-controls/assets/promote.ts +371 -0
- package/packages/repo-controls/assets/version-bump.sh +189 -0
- package/packages/repo-controls/azure-pipelines.yml +274 -0
- package/packages/repo-controls/bin/adl-repo-controls.ts +10 -0
- package/packages/repo-controls/bunfig.toml +58 -0
- package/packages/repo-controls/package/adl-compliance/AGENTS.md +163 -0
- package/packages/repo-controls/package/adl-compliance/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/conftest.py +78 -0
- package/packages/repo-controls/package/adl-compliance/pyproject.toml +31 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/__init__.py +50 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +98 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/check.py +210 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-bad-status/docs/architecture/overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-bad-status/docs/decisions/adr-901-proposed.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-broken-backlink/docs/decisions/adr-902-dangling.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-clean/docs/architecture/overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-clean/docs/decisions/adr-900-example.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-frontmatter-mismatch/.plans/b_committed/26-08-08-lifecycle-fixture.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-frontmatter-mismatch/.specs/demo/lifecycle.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-frontmatter-mismatch/docs/decisions/adr-903-frontmatter-mismatch.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-inactive-plan/.plans/c_done/26-08-08-completed-fixture.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-inactive-plan/.specs/demo/lifecycle.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/fixtures/adr-lifecycle-inactive-plan/docs/decisions/adr-904-completed-plan.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +127 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/check.py +91 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/architecture/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/compliance/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/decisions/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/index.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/operations/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/research/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/stray-root-file.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/totally-made-up/nonsense.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +106 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +291 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/clean/backend/clean.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/excluded/frontend/mobile/src/i18n/locales/zh-CN/strings.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/violation/backend/escaped.rs +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/violation/backend/raw.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/violation/backend//346/226/207/344/273/266.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +193 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/check.py +140 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/fixtures/index-updated-clean/docs/architecture/foo.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/fixtures/index-updated-clean/docs/architecture/index.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/fixtures/index-updated-violation/docs/architecture/foo.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/fixtures/index-updated-violation/docs/architecture/index.md +9 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/test_check.py +98 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +378 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +192 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-clean/docs/index.md +14 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-clean/docs/one.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-clean/docs/two.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-clean/docs-knowledge-indexes.yaml +20 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-duplicate/docs/index.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-duplicate/docs/one.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-duplicate/docs/two.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-duplicate/docs-knowledge-indexes.yaml +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-missing-entry/docs/index.md +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-missing-entry/docs/one.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-missing-entry/docs/two.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-missing-entry/docs-knowledge-indexes.yaml +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +102 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/check.py +387 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/fixtures/ledger-bad-date/plans/LEDGER.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/fixtures/ledger-clean/plans/LEDGER.md +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/fixtures/ledger-empty-table/plans/LEDGER.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/fixtures/ledger-long-event/plans/LEDGER.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/fixtures/ledger-violation/plans/LEDGER.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +427 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/check.py +84 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/fixtures/markdown-structure-bad-fence/docs/bad-fence.md +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/fixtures/markdown-structure-bad-fence/docs/valid.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/fixtures/markdown-structure-bad-frontmatter/docs/bad-front-matter.md +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/fixtures/markdown-structure-bad-frontmatter/docs/valid.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/fixtures/markdown-structure-clean/docs/valid.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/markdown_ast/test_check.py +126 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +210 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +119 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs/architecture/bad-status.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +49 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +159 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/check.py +578 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-clean/docs/architecture/backend/crate-overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-clean/docs/architecture/team/team-overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-clean/docs/compliance/controls/control-matrix.md +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-clean/docs/compliance/controls/control-matrix.yaml +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-clean/docs/research/benchmarks/note.md +24 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/backend/crate-overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/product/stable-delivery.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/product/stable-recommendation.md +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/product/target-narration.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/team/team-overview.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/compliance/controls/control-matrix.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/compliance/controls/control-matrix.yaml +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/research/benchmarks/bad-research.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +461 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/check.py +124 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/.workflows/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/.workflows/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/CLAUDE.md +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/INVARIANTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/bad-pointer/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/bad-pointer/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/docs/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/docs/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/missing-pair/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/owned/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/fixtures/owned/CLAUDE.md +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/agents_layout/test_check.py +116 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/ci_paths/__init__.py +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/ci_paths/check.py +380 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/ci_paths/fixtures/redeclared-workflows-tree/automation/pipelines/pr-validation.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/ci_paths/test_check.py +274 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +227 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/fresh/fresh.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub1/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub10/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub11/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub2/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub3/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub4/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub5/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub6/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub7/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub8/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/many/sub9/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/services/i18n/locales/de/common.json +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/frontend/packages/desktop/src/vendored-crate/Cargo.toml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/fresh/fresh.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub1/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub10/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub11/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub2/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub3/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub4/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub5/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub6/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub7/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub8/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/many/sub9/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +138 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +240 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/fixtures/markdown-trees-clean/.plans/a_new/plan.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/fixtures/markdown-trees-clean/backend/AGENTS.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/fixtures/markdown-trees-clean/docs/page.md +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/fixtures/markdown-trees-stray/backend/notes.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/fixtures/markdown-trees-stray/docs/page.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +220 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/__init__.py +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +225 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/fixtures/open-work-cap-clean/plans/GAPS-AND-FINDINGS.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/fixtures/open-work-cap-clean/plans/features/az601-clean/spec.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +330 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +240 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/agent/crates/enact-providers/src/snapshots/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/backend/crates/enact-app/assets/builtin-assistants/avatars/assistant.jpg +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/backend/crates/enact-assets/assets/logos/tools/coding/tool.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/backend/crates/enact-session/src/backend/codex_init_prompt.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/mobile/assets/images/icon.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/packages/desktop/src/renderer/assets/logos/brand/app.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/packages/desktop/src/renderer/assets/themes/default-theme.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/public/pwa/icon-192.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/frontend/resources/product.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-stray/apps/legacy/file.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-stray/backend/crates/enact-session/src/backend/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-stray/frontend/unapproved/screenshot.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +230 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plan_metadata.py +53 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/check.py +438 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/items/az351-restore-entrypoint.md +9 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/spec.md +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/templates/feature.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-violation/plans/features/az347-test-coverage/items/az351-restore-entrypoint.md +9 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-violation/plans/features/az347-test-coverage/spec.md +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +461 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/check.py +62 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/NotAMigration.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/0001_long_prefix.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/001_init.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/002_add_index.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/003-dashed-slug.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/004_MixedCase.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/005_trailing space.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/01_short_prefix.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/fixtures/migration-filenames/backend/crates/demo/migrations/not-a-migration.sql +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/profile_data/test_check.py +116 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +188 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/.plans/c_done/26-07-27-history.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/docs/README.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/docs/architecture/product/links.md +20 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/docs/architecture/product/route-target.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/.plans/c_done/26-07-27-history.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/docs/README.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/docs/architecture/product/links.md +20 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/docs/architecture/product/route-target.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/test_check.py +166 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +135 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.agents/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.changeset/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.claude/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.code-review-graph/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.code-review-graph_old/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.codex/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.cursor/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.cursorrules +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.dockerignore +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.docs/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.donors/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.gitattributes +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.kimi-code/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.lfsconfig +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.mcp.json +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.opencode/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.workflows/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/CHANGELOG.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/CLAUDE-INVARIANTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/CLAUDE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/INDEPENDENT-VERIFICATION.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/INVARIANTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/LICENSE +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/NOTICE +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/RELEASE.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/VERSION +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/backend/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/compliance/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/dev/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/docker/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/docs/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/frontend/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/infra/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/justfile +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/opencode.jsonc +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/rule-tests/undeclared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/rules/undeclared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/unapproved-root/undeclared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/undeclared-root-file.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +122 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +290 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/.changeset/some-change.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/.plans/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/.specs/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/.workflows/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/CHANGELOG.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/CLAUDE.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/INDEPENDENT-VERIFICATION.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/INVARIANTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/README.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/RELEASE.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/STRAY.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/docs/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/docs/architecture/note.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-clean/frontend/README.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-missing-guide/.workflows/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-missing-guide/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-missing-guide/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-missing-guide/docs/overview.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/fixtures/root-markdown-missing-guide/plans/AGENTS.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +329 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +127 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/a/b/c/d/at-limit.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/a/b/c/d/e/too-deep.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-01.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-02.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-03.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-04.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-05.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-06.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-07.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-08.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-09.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-10.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-11.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-12.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-13.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-14.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-15.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/fixtures/scripts-layout/.workflows/scripts/direct-16.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +163 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +169 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/attribute-without-conversion/.gitattributes +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/attribute-without-conversion/large file.bin +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/clean/.gitattributes +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/clean/large file.bin +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/clean/small.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/missing-filter/large file.bin +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/unmatched-extension/.gitattributes +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/unmatched-extension/payload.dat +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +133 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/check.py +129 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/fixtures/disjoint/gate-registry.yaml +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/fixtures/empty/gate-registry.yaml +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/fixtures/overlapping/gate-registry.yaml +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/pipeline/phase_disjoint/test_check.py +109 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/check.py +149 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/fixtures/clean/docs/readme.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/fixtures/relevant/VERSION +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/changeset_plan/test_check.py +151 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/check.py +202 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/.workflows/changesets/package.json +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/.workflows/package.json +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/CHANGELOG.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/aligned/VERSION +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/.workflows/changesets/package.json +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/.workflows/package.json +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/CHANGELOG.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/fixtures/mismatched/VERSION +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/release/version_release/test_check.py +162 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/check.py +103 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/git-bad.sh +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/git-note.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/good.sh +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/grep-bad.sh +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/grep-note.sh +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/grep-trailing.sh +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/compliance_py/checks/notes.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/elsewhere/loose-git.sh +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/fixtures/no-banned-commands/elsewhere/loose-grep.sh +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/test_check.py +117 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/__init__.py +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +265 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/fixtures/ignored-paths/keep.log +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/fixtures/ignored-paths/src/main.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +180 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/__init__.py +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/check.py +84 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/fixtures/license-declared-clean/LICENSE +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/fixtures/license-declared-mismatch/LICENSE +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/fixtures/license-declared-missing/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/license_declared/test_check.py +66 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +167 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/Cargo.lock +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/Cargo.toml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/rust-toolchain.toml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/backend/src/main.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/frontend/bun.lock +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/Cargo.lock +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/Cargo.toml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/rust-toolchain.toml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/backend/src/main.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/frontend/bun.lock +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +109 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +483 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/ast_grep.py +199 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/batch.py +52 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +303 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +106 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +99 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/errors.py +32 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/finding.py +65 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/models.py +40 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/receipt.py +63 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/scope.py +82 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/verdict.py +161 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/__init__.py +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +131 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.toml +30 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +65 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +791 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.schema.yaml +176 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +791 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/grants-registry.yaml +112 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/grants.py +129 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +281 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +250 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/severity-policy.yaml +114 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/providers/__init__.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +371 -0
- package/packages/repo-controls/package/adl-compliance/uv.lock +199 -0
- package/packages/repo-controls/package.json +33 -0
- package/packages/repo-controls/scripts/hooks/commit-msg +63 -0
- package/packages/repo-controls/scripts/hooks/lib/hook-log.sh +62 -0
- package/packages/repo-controls/scripts/hooks/post-checkout +15 -0
- package/packages/repo-controls/scripts/hooks/post-commit +18 -0
- package/packages/repo-controls/scripts/hooks/pre-commit +82 -0
- package/packages/repo-controls/scripts/hooks/pre-push +144 -0
- package/packages/repo-controls/src/azdo-push.ts +463 -0
- package/packages/repo-controls/src/azure-devops-governance.ts +248 -0
- package/packages/repo-controls/src/azure-devops-remote.ts +61 -0
- package/packages/repo-controls/src/cli.ts +188 -0
- package/packages/repo-controls/src/compliance-config.ts +200 -0
- package/packages/repo-controls/src/config.ts +690 -0
- package/packages/repo-controls/src/constants.ts +97 -0
- package/packages/repo-controls/src/coverage-ratchet.ts +153 -0
- package/packages/repo-controls/src/doc-freshness.ts +172 -0
- package/packages/repo-controls/src/doctor.ts +304 -0
- package/packages/repo-controls/src/findings-ratchet.ts +163 -0
- package/packages/repo-controls/src/gitignore-block.ts +253 -0
- package/packages/repo-controls/src/hook-log.ts +72 -0
- package/packages/repo-controls/src/hook.ts +694 -0
- package/packages/repo-controls/src/install.ts +506 -0
- package/packages/repo-controls/src/integrity.ts +104 -0
- package/packages/repo-controls/src/promote.ts +25 -0
- package/packages/repo-controls/src/runtime.ts +110 -0
- package/packages/repo-controls/src/workflows-drift.ts +106 -0
- package/packages/repo-controls/src/worktree-guard.ts +272 -0
- package/packages/repo-controls/src/worktree-limit.ts +11 -0
- package/packages/repo-controls/tsconfig.json +14 -0
- package/packages/repo-controls/workflows/scripts/release/verify-npm-artifact.ts +119 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Azure DevOps agent-identity TOKEN MINTING (split out of ./agent-identity.ts
|
|
2
|
+
// 2026-09-28: packages/agent-hooks imports agent-identity.ts's resolution
|
|
3
|
+
// exports for its `adl-identity` rule, and agent-hooks' `check` gate requires
|
|
4
|
+
// 100% funcs/lines with no ignore patterns. bun instruments the whole
|
|
5
|
+
// imported file, so `getAccessToken`/`resolveAgentIdBinary`/
|
|
6
|
+
// `resetAccessTokenCacheForTests` -- never called by the hook -- made
|
|
7
|
+
// agent-hooks' gate fail on code it never exercises. Moving minting here
|
|
8
|
+
// keeps agent-identity.ts to pure resolution, which the hook's own tests
|
|
9
|
+
// cover completely.
|
|
10
|
+
//
|
|
11
|
+
// Token flow, mirroring bin/git-ado's agent path exactly (same two pinned
|
|
12
|
+
// addresses, same two-hop exec):
|
|
13
|
+
//
|
|
14
|
+
// adl-agent-id exec --agent <agent> -- adl id token <agent> --json
|
|
15
|
+
//
|
|
16
|
+
// (docs/architecture/cli-design.md §7 P4 folded the standalone `ado-token`
|
|
17
|
+
// binary into `adl id token`, byte-for-byte the same contract: the agent is
|
|
18
|
+
// positional and comes first, `--json` is a flag after it; see
|
|
19
|
+
// apps/cli/src/ado-token.ts, which is now the single implementation `adl id
|
|
20
|
+
// token` and this module both rely on -- this module cannot call it
|
|
21
|
+
// in-process because the proxy env (HTTPS_PROXY / NODE_EXTRA_CA_CERTS) is
|
|
22
|
+
// set by agent-vault for the SPAWNED child only, never for this process.)
|
|
23
|
+
//
|
|
24
|
+
// adl-agent-id mints a short-lived, proxy-only Agent Vault session for
|
|
25
|
+
// <agent> and execs `adl id token <agent> --json` inside it; that prints
|
|
26
|
+
// {"access_token":...,"expires_in":...} on stdout. This process never sees
|
|
27
|
+
// the vault proxy, the CA, or a client secret -- only the finished bearer
|
|
28
|
+
// token, read from the child's stdout PIPE (never argv, never logged).
|
|
29
|
+
//
|
|
30
|
+
// ADL_AGENT_ID_ADDR and ADL_AGENT_ID_VAULT_ADDR are PINNED to the same two
|
|
31
|
+
// constants bin/git-ado pins, for the same reason stated there: a caller
|
|
32
|
+
// that could redirect either one could redirect the signed broker request
|
|
33
|
+
// or the minted token to a server of its choosing. They are fixed constants
|
|
34
|
+
// here too, not read from the environment -- see
|
|
35
|
+
// tests/agent-id-constants-pinned.test.ts, which fails if the two copies
|
|
36
|
+
// drift.
|
|
37
|
+
|
|
38
|
+
export const ADL_AGENT_ID_ADDR_CONST = 'https://agentid.amsterdamdatalabs.com';
|
|
39
|
+
export const ADL_AGENT_ID_VAULT_ADDR_CONST = 'https://agentid-vault.walrus-morray.ts.net';
|
|
40
|
+
|
|
41
|
+
function resolveAgentIdBinary(env: NodeJS.ProcessEnv): string {
|
|
42
|
+
const resolved = Bun.which('adl-agent-id', { PATH: env.PATH ?? '' });
|
|
43
|
+
if (!resolved) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
'adl-agent-id not found on PATH: reconcile the global-tools manifest before running Azure DevOps tools',
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return resolved;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface CachedToken {
|
|
52
|
+
accessToken: string;
|
|
53
|
+
expiresAt: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** One cache entry per agent name, for the life of this process. */
|
|
57
|
+
const tokenCache = new Map<string, CachedToken>();
|
|
58
|
+
|
|
59
|
+
/** Test seam: forget every cached token. */
|
|
60
|
+
export function resetAccessTokenCacheForTests(): void {
|
|
61
|
+
tokenCache.clear();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* OVERRIDING whatever the caller's environment carried -- adl-agent-id
|
|
66
|
+
* resolves both only from the environment (there is no --broker/--vault
|
|
67
|
+
* flag), so this is the one place that decides where the signed request and
|
|
68
|
+
* the vault session go, exactly as bin/git-ado does for the git path. Shared
|
|
69
|
+
* by both the async and sync mint below -- one pinned pair, not two copies.
|
|
70
|
+
*/
|
|
71
|
+
function mintEnv(env: NodeJS.ProcessEnv): Record<string, string | undefined> {
|
|
72
|
+
return {
|
|
73
|
+
...env,
|
|
74
|
+
ADL_AGENT_ID_ADDR: ADL_AGENT_ID_ADDR_CONST,
|
|
75
|
+
ADL_AGENT_ID_VAULT_ADDR: ADL_AGENT_ID_VAULT_ADDR_CONST,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const MINT_COMMAND = (agentIdBin: string, agent: string): string[] => [
|
|
80
|
+
agentIdBin,
|
|
81
|
+
'exec',
|
|
82
|
+
'--agent',
|
|
83
|
+
agent,
|
|
84
|
+
'--',
|
|
85
|
+
'adl',
|
|
86
|
+
'id',
|
|
87
|
+
'token',
|
|
88
|
+
agent,
|
|
89
|
+
'--json',
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
/** Parses and validates `adl id token --json`'s stdout; shared by both mints. */
|
|
93
|
+
function parseMintedToken(stdout: string): { accessToken: string; expiresAt: number } {
|
|
94
|
+
let parsed: { access_token?: string; expires_in?: number };
|
|
95
|
+
try {
|
|
96
|
+
parsed = JSON.parse(stdout.trim());
|
|
97
|
+
} catch {
|
|
98
|
+
throw new Error('ado-token --json produced unparseable output');
|
|
99
|
+
}
|
|
100
|
+
if (!parsed.access_token || !Number.isFinite(parsed.expires_in) || (parsed.expires_in as number) <= 0) {
|
|
101
|
+
throw new Error('ado-token --json response is missing a valid access_token or expires_in');
|
|
102
|
+
}
|
|
103
|
+
return { accessToken: parsed.access_token, expiresAt: Date.now() + (parsed.expires_in! - 60) * 1000 };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* The bearer token for `agent`, minted through
|
|
108
|
+
* `adl-agent-id exec --agent <agent> -- adl id token <agent> --json` and
|
|
109
|
+
* cached in memory until `expires_in - 60s`. The JSON is parsed straight off
|
|
110
|
+
* the child's stdout pipe; nothing here logs it.
|
|
111
|
+
*/
|
|
112
|
+
export async function getAccessToken(agent: string): Promise<string> {
|
|
113
|
+
const cached = tokenCache.get(agent);
|
|
114
|
+
if (cached && Date.now() < cached.expiresAt) {
|
|
115
|
+
return cached.accessToken;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const agentIdBin = resolveAgentIdBinary(process.env);
|
|
119
|
+
const proc = Bun.spawn(MINT_COMMAND(agentIdBin, agent), { env: mintEnv(process.env), stdout: 'pipe', stderr: 'pipe' });
|
|
120
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
121
|
+
new Response(proc.stdout).text(),
|
|
122
|
+
new Response(proc.stderr).text(),
|
|
123
|
+
proc.exited,
|
|
124
|
+
]);
|
|
125
|
+
if (exitCode !== 0) {
|
|
126
|
+
throw new Error(`adl-agent-id exec -- adl id token --json failed (exit ${exitCode}): ${stderr.trim()}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const { accessToken, expiresAt } = parseMintedToken(stdout);
|
|
130
|
+
tokenCache.set(agent, { accessToken, expiresAt });
|
|
131
|
+
return accessToken;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Synchronous counterpart to `getAccessToken`, same command/parsing/pinned
|
|
136
|
+
* addresses and the same in-memory cache -- for callers whose call sites are
|
|
137
|
+
* all sync (packages/repo-controls' doctor/hook checks), where importing the
|
|
138
|
+
* async mint across the package boundary would mean threading `await`
|
|
139
|
+
* through code that has none today. STATUS.md 12p finding M9: this is the
|
|
140
|
+
* ONE mint every surface uses now; packages/repo-controls/src/azure-devops-governance.ts
|
|
141
|
+
* no longer keeps its own copy.
|
|
142
|
+
*
|
|
143
|
+
* `env` defaults to `process.env` (matching `getAccessToken`) but is
|
|
144
|
+
* threaded through UNMERGED -- not layered on top of `process.env` -- so a
|
|
145
|
+
* caller that resolves its own hermetic env (governance.ts's doctor/hook
|
|
146
|
+
* requests, and their tests) gets that exact env for both the
|
|
147
|
+
* `adl-agent-id` PATH lookup and the spawned child, never a silent fallback
|
|
148
|
+
* to the real machine's environment.
|
|
149
|
+
*/
|
|
150
|
+
export function getAccessTokenSync(agent: string, env: NodeJS.ProcessEnv = process.env): string {
|
|
151
|
+
const cached = tokenCache.get(agent);
|
|
152
|
+
if (cached && Date.now() < cached.expiresAt) {
|
|
153
|
+
return cached.accessToken;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const agentIdBin = resolveAgentIdBinary(env);
|
|
157
|
+
const proc = Bun.spawnSync(MINT_COMMAND(agentIdBin, agent), { env: mintEnv(env), stdout: 'pipe', stderr: 'pipe' });
|
|
158
|
+
const stdout = proc.stdout.toString();
|
|
159
|
+
const stderr = proc.stderr.toString();
|
|
160
|
+
if (proc.exitCode !== 0) {
|
|
161
|
+
throw new Error(`adl-agent-id exec -- adl id token --json failed (exit ${proc.exitCode}): ${stderr.trim()}`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const { accessToken, expiresAt } = parseMintedToken(stdout);
|
|
165
|
+
tokenCache.set(agent, { accessToken, expiresAt });
|
|
166
|
+
return accessToken;
|
|
167
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
// Azure DevOps client. Authenticates as the SESSION's own agent identity
|
|
2
|
+
// (ADL_AGENT_ID_AGENT) via lib/agent-identity.ts -- see that file for the
|
|
3
|
+
// token flow. P2 (2026-09-27, Tarun) replaced the earlier Agent Vault
|
|
4
|
+
// client-credentials binding this file used to hold directly.
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { resolveAgentIdentity } from './agent-identity.ts';
|
|
7
|
+
import { getAccessToken } from './agent-token.ts';
|
|
8
|
+
|
|
9
|
+
export interface AdoClientConfig {
|
|
10
|
+
/** Full `.../_apis` base URL override. Defaults to the real Azure DevOps
|
|
11
|
+
* REST base built from org/project; set directly (or via
|
|
12
|
+
* AZURE_DEVOPS_BASE_URL) to point at a different Azure DevOps Server
|
|
13
|
+
* instance, or at a local stub in tests. */
|
|
14
|
+
baseUrl?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The Azure DevOps organization and project every tool in this package
|
|
19
|
+
* addresses, and the ONLY place their defaults are written.
|
|
20
|
+
*
|
|
21
|
+
* `enact-webview` is a REPOSITORY inside the `Enact` project, not a project —
|
|
22
|
+
* `azdo-wit.ts` used to default the project to it, so work-item calls hit a
|
|
23
|
+
* different URL than the PR and build calls in the same process. Anything
|
|
24
|
+
* needing these values imports from here rather than restating them.
|
|
25
|
+
*/
|
|
26
|
+
export const DEFAULT_ORG = 'amsterdamdatalabs';
|
|
27
|
+
export const DEFAULT_PROJECT = 'Enact';
|
|
28
|
+
/** The one PR target this opinionated tool opens against. */
|
|
29
|
+
export const PR_TARGET_BRANCH = 'integration';
|
|
30
|
+
|
|
31
|
+
/** Current checkout branch, or undefined when git cannot determine it. */
|
|
32
|
+
export function currentBranch(cwd?: string): string | undefined {
|
|
33
|
+
const result = spawnSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
|
34
|
+
...(cwd === undefined ? {} : { cwd }),
|
|
35
|
+
encoding: 'utf8',
|
|
36
|
+
timeout: 5000,
|
|
37
|
+
});
|
|
38
|
+
return result.status === 0 ? configured(result.stdout) : undefined;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Treat blank and whitespace-only env values as unset, never as an empty path segment. */
|
|
42
|
+
function configured(value: string | undefined): string | undefined {
|
|
43
|
+
const trimmed = value?.trim();
|
|
44
|
+
return trimmed ? trimmed : undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface AzureRemote {
|
|
48
|
+
readonly org: string;
|
|
49
|
+
readonly project: string;
|
|
50
|
+
readonly repository: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Pull org/project/repository out of an Azure DevOps remote URL.
|
|
55
|
+
*
|
|
56
|
+
* git@ssh.dev.azure.com:v3/<org>/<project>/<repo>
|
|
57
|
+
* https://dev.azure.com/<org>/<project>/_git/<repo>[.git]
|
|
58
|
+
* https://<org>.visualstudio.com/<project>/_git/<repo>
|
|
59
|
+
*
|
|
60
|
+
* Returns null for anything else rather than guessing — a GitHub remote must
|
|
61
|
+
* not silently yield an Azure target.
|
|
62
|
+
*/
|
|
63
|
+
export function parseAzureRemote(url: string): AzureRemote | null {
|
|
64
|
+
const decode = (value: string) => {
|
|
65
|
+
try {
|
|
66
|
+
return decodeURIComponent(value);
|
|
67
|
+
} catch {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const build = (org: string, project: string, repo: string): AzureRemote | null => {
|
|
72
|
+
const parts = [org, project, repo.replace(/\.git$/, '')].map(decode);
|
|
73
|
+
return parts.every((p) => p.length > 0) ? { org: parts[0]!, project: parts[1]!, repository: parts[2]! } : null;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const ssh = /^(?:ssh:\/\/)?git@(?:ssh\.)?dev\.azure\.com[:/]v3\/([^/]+)\/([^/]+)\/([^/]+?)\/?$/.exec(url.trim());
|
|
77
|
+
if (ssh) return build(ssh[1]!, ssh[2]!, ssh[3]!);
|
|
78
|
+
|
|
79
|
+
const https = /^https?:\/\/(?:[^@/]+@)?dev\.azure\.com\/([^/]+)\/([^/]+)\/_git\/([^/]+?)\/?$/.exec(url.trim());
|
|
80
|
+
if (https) return build(https[1]!, https[2]!, https[3]!);
|
|
81
|
+
|
|
82
|
+
const legacy = /^https?:\/\/(?:[^@/]+@)?([^./]+)\.visualstudio\.com\/([^/]+)\/_git\/([^/]+?)\/?$/.exec(url.trim());
|
|
83
|
+
if (legacy) return build(legacy[1]!, legacy[2]!, legacy[3]!);
|
|
84
|
+
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The Azure coordinates of the checkout this process is running in, read once
|
|
90
|
+
* from `git remote get-url origin`.
|
|
91
|
+
*
|
|
92
|
+
* This is why no environment variable is needed: the working directory already
|
|
93
|
+
* knows which repository it is. Before this, an unset `AZURE_DEVOPS_REPO` fell
|
|
94
|
+
* through to `enact-webview`, so a PR call made from any other repo was aimed
|
|
95
|
+
* at enact-webview and Azure answered TF401398 "branch does not exist" — a
|
|
96
|
+
* truthful error about the wrong target, which is the expensive kind.
|
|
97
|
+
*
|
|
98
|
+
* Cached: the remote cannot change under a running server, and this sits on
|
|
99
|
+
* every tool call.
|
|
100
|
+
*/
|
|
101
|
+
let remoteCache: AzureRemote | null | undefined;
|
|
102
|
+
export function currentRemote(cwd?: string): AzureRemote | null {
|
|
103
|
+
if (cwd !== undefined) {
|
|
104
|
+
const probe = spawnSync('git', ['remote', 'get-url', 'origin'], { cwd, encoding: 'utf8', timeout: 5000 });
|
|
105
|
+
return probe.status === 0 ? parseAzureRemote(probe.stdout ?? '') : null;
|
|
106
|
+
}
|
|
107
|
+
if (remoteCache !== undefined) return remoteCache;
|
|
108
|
+
const result = spawnSync('git', ['remote', 'get-url', 'origin'], { encoding: 'utf8', timeout: 5000 });
|
|
109
|
+
remoteCache = result.status === 0 ? parseAzureRemote(result.stdout ?? '') : null;
|
|
110
|
+
return remoteCache;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Test seam: forget the cached remote. */
|
|
114
|
+
export function resetRemoteCache(): void {
|
|
115
|
+
remoteCache = undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function resolveOrg(cwd?: string): string {
|
|
119
|
+
return configured(process.env.AZURE_DEVOPS_ORG) ?? currentRemote(cwd)?.org ?? DEFAULT_ORG;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function resolveProject(cwd?: string): string {
|
|
123
|
+
return configured(process.env.AZURE_DEVOPS_PROJECT) ?? currentRemote(cwd)?.project ?? DEFAULT_PROJECT;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Which repository a call addresses: the explicit per-call argument first (one
|
|
128
|
+
* session can span repos), then `AZURE_DEVOPS_REPO` as an override, then the
|
|
129
|
+
* checkout's own git remote.
|
|
130
|
+
*
|
|
131
|
+
* There is deliberately NO default. A fallback constant is what made this fail
|
|
132
|
+
* silently: with `DEFAULT_REPO = 'enact-webview'` in place, every call from a
|
|
133
|
+
* repo that was not enact-webview was confidently aimed at enact-webview, and
|
|
134
|
+
* the only symptom was Azure answering TF401398 "branch does not exist" — a
|
|
135
|
+
* truthful error about a target nobody chose. Throwing names the real problem
|
|
136
|
+
* at the point it occurs.
|
|
137
|
+
*
|
|
138
|
+
* org/project keep their defaults: unlike the repository, they are constant
|
|
139
|
+
* across this fleet, and a wrong one fails visibly at the URL rather than
|
|
140
|
+
* writing somewhere real.
|
|
141
|
+
*/
|
|
142
|
+
export function resolveRepository(repository?: string, cwd?: string): string {
|
|
143
|
+
const resolved = configured(repository) ?? configured(process.env.AZURE_DEVOPS_REPO) ?? currentRemote(cwd)?.repository;
|
|
144
|
+
if (resolved === undefined) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
'Cannot determine the Azure DevOps repository: no `repository` argument, no AZURE_DEVOPS_REPO, ' +
|
|
147
|
+
'and `git remote get-url origin` in this working directory is not an Azure DevOps remote. ' +
|
|
148
|
+
'Pass `repository` explicitly or run from a checkout of the target repo.',
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
return resolved;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* `https://dev.azure.com/{org}/{project}` — the ONE place the host and both
|
|
156
|
+
* segments are written. The REST base appends `/_apis`; human-facing links
|
|
157
|
+
* append `/_git/...`. Two builders restating this shape can disagree about
|
|
158
|
+
* where a project lives just as easily as two default constants could.
|
|
159
|
+
*/
|
|
160
|
+
export function adoProjectUrl(): string {
|
|
161
|
+
return `https://dev.azure.com/${resolveOrg()}/${resolveProject()}`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export class AdoClient {
|
|
165
|
+
private config: Required<AdoClientConfig>;
|
|
166
|
+
|
|
167
|
+
constructor(config: AdoClientConfig = {}) {
|
|
168
|
+
this.config = {
|
|
169
|
+
baseUrl: config.baseUrl ?? process.env.AZURE_DEVOPS_BASE_URL ?? '',
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private get baseUrl(): string {
|
|
174
|
+
if (this.config.baseUrl) return this.config.baseUrl;
|
|
175
|
+
return `${adoProjectUrl()}/_apis`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// No proxy, no CA override, no vault: the session's own bearer token goes
|
|
179
|
+
// straight to Azure DevOps (or, in tests, to AZURE_DEVOPS_BASE_URL's local
|
|
180
|
+
// stub). See lib/agent-identity.ts for where the token comes from and why.
|
|
181
|
+
private async acquireAccessToken(): Promise<string> {
|
|
182
|
+
return getAccessToken(resolveAgentIdentity().agent);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async request<T>(
|
|
186
|
+
path: string,
|
|
187
|
+
options: {
|
|
188
|
+
method?: string;
|
|
189
|
+
body?: any;
|
|
190
|
+
queryParams?: Record<string, string>;
|
|
191
|
+
contentType?: string;
|
|
192
|
+
} = {}
|
|
193
|
+
): Promise<T> {
|
|
194
|
+
const token = await this.acquireAccessToken();
|
|
195
|
+
const method = options.method ?? 'GET';
|
|
196
|
+
const contentType = options.contentType ?? 'application/json';
|
|
197
|
+
|
|
198
|
+
let url = `${this.baseUrl}${path}`;
|
|
199
|
+
if (options.queryParams) {
|
|
200
|
+
const params = new URLSearchParams(options.queryParams);
|
|
201
|
+
url += `?${params.toString()}`;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const headers: Record<string, string> = {
|
|
205
|
+
Authorization: `Bearer ${token}`,
|
|
206
|
+
'Content-Type': contentType,
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const resp = await fetch(url, {
|
|
210
|
+
redirect: 'error',
|
|
211
|
+
method,
|
|
212
|
+
headers,
|
|
213
|
+
body: options.body ? JSON.stringify(options.body) : undefined,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
if (!resp.ok) {
|
|
217
|
+
const text = await resp.text();
|
|
218
|
+
throw new Error(`Azure DevOps API error: ${resp.status} ${text}`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return resp.json() as Promise<T>;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async get<T>(path: string, queryParams?: Record<string, string>): Promise<T> {
|
|
225
|
+
return this.request<T>(path, { ...(queryParams === undefined ? {} : { queryParams }) });
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async post<T>(path: string, body: any, queryParams?: Record<string, string>, contentType?: string): Promise<T> {
|
|
229
|
+
return this.request<T>(path, {
|
|
230
|
+
method: 'POST',
|
|
231
|
+
body,
|
|
232
|
+
...(queryParams === undefined ? {} : { queryParams }),
|
|
233
|
+
...(contentType === undefined ? {} : { contentType }),
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async patch<T>(path: string, body: any, queryParams?: Record<string, string>, contentType?: string): Promise<T> {
|
|
238
|
+
return this.request<T>(path, {
|
|
239
|
+
method: 'PATCH',
|
|
240
|
+
body,
|
|
241
|
+
...(queryParams === undefined ? {} : { queryParams }),
|
|
242
|
+
...(contentType === undefined ? {} : { contentType }),
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** Pull Request Reviewers — Create Pull Request Reviewer (add a reviewer or cast a vote) uses PUT; nothing else in this package needed it until azdo-pr-review.ts. */
|
|
247
|
+
async put<T>(path: string, body: any, queryParams?: Record<string, string>, contentType?: string): Promise<T> {
|
|
248
|
+
return this.request<T>(path, {
|
|
249
|
+
method: 'PUT',
|
|
250
|
+
body,
|
|
251
|
+
...(queryParams === undefined ? {} : { queryParams }),
|
|
252
|
+
...(contentType === undefined ? {} : { contentType }),
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async delete<T>(path: string): Promise<T> {
|
|
257
|
+
return this.request<T>(path, { method: 'DELETE' });
|
|
258
|
+
}
|
|
259
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// Azure DevOps Graph identity resolution: turn one of this fleet's three
|
|
2
|
+
// agent display names ("agent-tarun" / "agent-vivek" / "agent-reviewer" —
|
|
3
|
+
// verified live against the Graph service by azdo-repo-doctor.ts, which
|
|
4
|
+
// posts each name as-is to the Subject Query below and expects an EXACT
|
|
5
|
+
// `displayName` match) into the legacy GUID identity id that the Git REST
|
|
6
|
+
// APIs use everywhere else (`createdBy.id`, `reviewers[].id`, the
|
|
7
|
+
// `autoCompleteSetBy.id` this package already sends in azdo-pr.ts).
|
|
8
|
+
//
|
|
9
|
+
// Two REST calls, both against the org-scoped Graph host (a different host
|
|
10
|
+
// from `dev.azure.com/{org}/{project}`, same as azdo-repo-doctor.ts already
|
|
11
|
+
// established for the same reason):
|
|
12
|
+
//
|
|
13
|
+
// 1. Graph — Subject Query (display name -> Graph descriptor)
|
|
14
|
+
// POST https://vssps.dev.azure.com/{org}/_apis/graph/subjectquery?api-version=7.1-preview.1
|
|
15
|
+
// body: { query: <displayName>, subjectKind: ['User'] }
|
|
16
|
+
// https://learn.microsoft.com/en-us/rest/api/azure/devops/graph/subject-query/query
|
|
17
|
+
//
|
|
18
|
+
// 2. Graph — Storage Keys — Get (descriptor -> legacy GUID identity id)
|
|
19
|
+
// GET https://vssps.dev.azure.com/{org}/_apis/graph/storagekeys/{subjectDescriptor}?api-version=7.1
|
|
20
|
+
// https://learn.microsoft.com/en-us/rest/api/azure/devops/graph/storage-keys/get
|
|
21
|
+
// response: { value: "<guid>" } — this IS the same identity-id shape as
|
|
22
|
+
// the Git PR APIs' `id`/`reviewerId`/`createdBy.id` (the well-known
|
|
23
|
+
// "storage key" / legacy VSID bridge the official az CLI extension uses
|
|
24
|
+
// to resolve "who am I" into an identity a Git API will accept).
|
|
25
|
+
//
|
|
26
|
+
// Extracted out of azdo-repo-doctor.ts (2026-09-27, C3): that file resolves
|
|
27
|
+
// descriptors for its own read-only ACL checks and had this exact
|
|
28
|
+
// vsspsBaseUrl()/fetchJson()/postJson()/resolveAgentDescriptor() quartet
|
|
29
|
+
// private to itself. azdo-pr-review.ts (C3, docs/operations/agent-permissions.md rows
|
|
30
|
+
// 6-8) needs the SAME descriptor lookup plus the storage-key hop the doctor
|
|
31
|
+
// never needed, so the shared half moved here rather than being copied a
|
|
32
|
+
// second time — repo-doctor.ts now imports it instead of defining its own.
|
|
33
|
+
import { resolveAgentIdentity } from './agent-identity.ts';
|
|
34
|
+
import { getAccessToken } from './agent-token.ts';
|
|
35
|
+
import { resolveOrg } from './client.ts';
|
|
36
|
+
|
|
37
|
+
/** Treat blank and whitespace-only env overrides as unset, like lib/client.ts's own `configured()`. */
|
|
38
|
+
function configured(value: string | undefined): string | undefined {
|
|
39
|
+
const trimmed = value?.trim();
|
|
40
|
+
return trimmed ? trimmed : undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The Graph service host — a different host from dev.azure.com entirely. */
|
|
44
|
+
export function vsspsBaseUrl(): string {
|
|
45
|
+
return configured(process.env.AZURE_DEVOPS_VSSPS_BASE_URL) ?? `https://vssps.dev.azure.com/${resolveOrg()}`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function fetchJson<T>(url: string, label: string): Promise<T> {
|
|
49
|
+
const token = await getAccessToken(resolveAgentIdentity().agent);
|
|
50
|
+
const resp = await fetch(url, { headers: { Authorization: `Bearer ${token}` }, redirect: 'error' });
|
|
51
|
+
if (!resp.ok) {
|
|
52
|
+
throw new Error(`Azure DevOps API error (${label}): ${resp.status} ${(await resp.text()).slice(0, 300)}`);
|
|
53
|
+
}
|
|
54
|
+
return resp.json() as Promise<T>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function postJson<T>(url: string, body: unknown, label: string): Promise<T> {
|
|
58
|
+
const token = await getAccessToken(resolveAgentIdentity().agent);
|
|
59
|
+
const resp = await fetch(url, {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
|
|
62
|
+
body: JSON.stringify(body),
|
|
63
|
+
redirect: 'error',
|
|
64
|
+
});
|
|
65
|
+
if (!resp.ok) {
|
|
66
|
+
throw new Error(`Azure DevOps API error (${label}): ${resp.status} ${(await resp.text()).slice(0, 300)}`);
|
|
67
|
+
}
|
|
68
|
+
return resp.json() as Promise<T>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface GraphSubjectQueryResponse {
|
|
72
|
+
value?: Array<{ displayName?: string; descriptor?: string }>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Resolve `displayName` to its Graph descriptor, or undefined when the Subject Query finds no exact match. */
|
|
76
|
+
export async function resolveAgentDescriptor(displayName: string): Promise<string | undefined> {
|
|
77
|
+
const result = await postJson<GraphSubjectQueryResponse>(
|
|
78
|
+
`${vsspsBaseUrl()}/_apis/graph/subjectquery?api-version=7.1-preview.1`,
|
|
79
|
+
{ query: displayName, subjectKind: ['User'] },
|
|
80
|
+
'Graph subject query',
|
|
81
|
+
);
|
|
82
|
+
return (result.value ?? []).find((subject) => subject.displayName === displayName)?.descriptor;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface GraphStorageKeyResponse {
|
|
86
|
+
value?: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Resolve a Graph `descriptor` to its legacy GUID storage key, or undefined when Graph has none on file. */
|
|
90
|
+
export async function resolveIdentityStorageKey(descriptor: string): Promise<string | undefined> {
|
|
91
|
+
const result = await fetchJson<GraphStorageKeyResponse>(
|
|
92
|
+
`${vsspsBaseUrl()}/_apis/graph/storagekeys/${encodeURIComponent(descriptor)}?api-version=7.1`,
|
|
93
|
+
'Graph storage key',
|
|
94
|
+
);
|
|
95
|
+
return result.value;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface IdentitiesResponse {
|
|
99
|
+
count?: number;
|
|
100
|
+
value?: Array<{ descriptor?: string; providerDisplayName?: string; customDisplayName?: string }>;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Resolve a LEGACY/SERVICE identity (a build service, not a Graph 'User' or
|
|
105
|
+
* 'Group' subject — `resolveAgentDescriptor()` above cannot find these) by
|
|
106
|
+
* its exact display name, via Identities - Read Identities on the vssps
|
|
107
|
+
* host — NOT Graph subjectquery:
|
|
108
|
+
* GET https://vssps.dev.azure.com/{org}/_apis/identities?searchFilter=General&filterValue=<name>&queryMembership=None&api-version=7.1
|
|
109
|
+
* https://learn.microsoft.com/en-us/rest/api/azure/devops/ims/identities/read-identities
|
|
110
|
+
* Returns the identity's `descriptor` (accepted by the same
|
|
111
|
+
* `accesscontrollists` `descriptors` filter every other lookup in this
|
|
112
|
+
* package uses).
|
|
113
|
+
*
|
|
114
|
+
* Verified live 2026-09-29 against amsterdamdatalabs/Infrastructure-AzDo's
|
|
115
|
+
* real project build service: for a SERVICE identity, `providerDisplayName`
|
|
116
|
+
* is the raw provider-side id (e.g. the project GUID, "a20912fc-..."), NOT
|
|
117
|
+
* the friendly Security-tab name — the friendly name Azure DevOps shows in
|
|
118
|
+
* the UI comes back in `customDisplayName` instead. Matching only on
|
|
119
|
+
* `providerDisplayName` (the field the REST docs describe as "the display
|
|
120
|
+
* name") silently missed a real, correctly-permissioned identity — the
|
|
121
|
+
* General search itself already found it (count: 1); the exact-match gate
|
|
122
|
+
* was reading the wrong field. Match whichever of the two is the friendly
|
|
123
|
+
* name; returns undefined only when NEITHER equals `displayName` exactly.
|
|
124
|
+
*/
|
|
125
|
+
export async function resolveIdentityByDisplayName(displayName: string): Promise<string | undefined> {
|
|
126
|
+
const url = `${vsspsBaseUrl()}/_apis/identities?searchFilter=General&filterValue=${encodeURIComponent(displayName)}&queryMembership=None&api-version=7.1`;
|
|
127
|
+
const result = await fetchJson<IdentitiesResponse>(url, 'Read identities');
|
|
128
|
+
return (result.value ?? []).find(
|
|
129
|
+
(identity) => identity.customDisplayName === displayName || identity.providerDisplayName === displayName,
|
|
130
|
+
)?.descriptor;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* `agent` (one of "agent-tarun" / "agent-vivek" / "agent-reviewer") -> the
|
|
135
|
+
* GUID identity id a Git PR API call accepts as `reviewers/{reviewerId}` or
|
|
136
|
+
* expects back as `createdBy.id`. Throws — never returns a partial or guessed
|
|
137
|
+
* id — when either hop finds nothing, naming which hop failed.
|
|
138
|
+
*/
|
|
139
|
+
export async function resolveAgentIdentityId(agent: string): Promise<string> {
|
|
140
|
+
const descriptor = await resolveAgentDescriptor(agent);
|
|
141
|
+
if (!descriptor) {
|
|
142
|
+
throw new Error(
|
|
143
|
+
`could not resolve an Azure DevOps identity for '${agent}': Graph subject query returned no exact display-name match`,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
const storageKey = await resolveIdentityStorageKey(descriptor);
|
|
147
|
+
if (!storageKey) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`could not resolve an Azure DevOps identity for '${agent}': Graph returned a descriptor but no storage key for it`,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return storageKey;
|
|
153
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const TITLE_PATTERN = /^(feat|fix|docs|refactor|perf|chore)(\([a-z0-9][a-z0-9-]*\))?: .+$/
|
|
2
|
+
const REQUIRED_SECTIONS = ['Summary', 'Why', 'Changes']
|
|
3
|
+
|
|
4
|
+
export function validatePullRequestMetadata(title: string, description: string): string[] {
|
|
5
|
+
return [...validatePullRequestTitle(title), ...validatePullRequestDescription(description)]
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function validatePullRequestTitle(title: string): string[] {
|
|
9
|
+
const errors: string[] = []
|
|
10
|
+
const subject = title.slice(title.indexOf(':') + 1).trim()
|
|
11
|
+
|
|
12
|
+
if (title.length > 80) errors.push('title exceeds 80 characters')
|
|
13
|
+
if (!TITLE_PATTERN.test(title)) errors.push('title must use <type>(<scope>): <subject>')
|
|
14
|
+
if (subject !== subject.toLowerCase()) errors.push('title subject must be lowercase')
|
|
15
|
+
if (subject.endsWith('.')) errors.push('title must not end with a period')
|
|
16
|
+
|
|
17
|
+
return errors
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function validatePullRequestDescription(description: string): string[] {
|
|
21
|
+
const errors: string[] = []
|
|
22
|
+
for (const section of REQUIRED_SECTIONS) {
|
|
23
|
+
const match = description.match(new RegExp(`(?:^|\\n)## ${section}[ \\t]*\\n([\\s\\S]*?)(?=\\n## |$)`, 'i'))
|
|
24
|
+
if (!match?.[1]?.trim()) errors.push(`description requires a non-empty ## ${section} section`)
|
|
25
|
+
}
|
|
26
|
+
return errors
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function loadPullRequest() {
|
|
30
|
+
const collection = required('SYSTEM_COLLECTIONURI')
|
|
31
|
+
const project = required('SYSTEM_TEAMPROJECTID')
|
|
32
|
+
const repository = required('BUILD_REPOSITORY_ID')
|
|
33
|
+
const pullRequest = required('SYSTEM_PULLREQUEST_PULLREQUESTID')
|
|
34
|
+
const token = required('SYSTEM_ACCESSTOKEN')
|
|
35
|
+
const url = `${collection}${project}/_apis/git/repositories/${repository}/pullRequests/${pullRequest}?api-version=7.1`
|
|
36
|
+
const response = await fetch(url, {
|
|
37
|
+
headers: { Authorization: `Basic ${btoa(`:${token}`)}` },
|
|
38
|
+
})
|
|
39
|
+
if (!response.ok) throw new Error(`Azure DevOps PR lookup failed: ${response.status} ${response.statusText}`)
|
|
40
|
+
return response.json() as Promise<{ title?: string; description?: string }>
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function required(name: string) {
|
|
44
|
+
const value = process.env[name]
|
|
45
|
+
if (!value) throw new Error(`missing ${name}`)
|
|
46
|
+
return value
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (import.meta.main) {
|
|
50
|
+
const pullRequest = await loadPullRequest()
|
|
51
|
+
const errors = validatePullRequestMetadata(pullRequest.title ?? '', pullRequest.description ?? '')
|
|
52
|
+
if (errors.length > 0) {
|
|
53
|
+
for (const error of errors) console.error(`pr-policy: FAIL — ${error}`)
|
|
54
|
+
process.exit(1)
|
|
55
|
+
}
|
|
56
|
+
console.log('pr-policy: PASS')
|
|
57
|
+
}
|