@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.12 → 0.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adl +2 -2
- package/bin/git +16 -17
- package/bin/git-ado +25 -24
- package/bin/git-defaults +173 -0
- package/bin/health-check +8 -1
- package/bin/kimi-hooks +1 -1
- package/bin/lib/adl-package.sh +257 -0
- package/bin/lib/fleet-host.sh +8 -5
- package/bin/reconcile +482 -232
- package/bin/reconcile-host +30 -20
- package/bin/setup +20 -17
- package/bin/shell-path-policy +15 -5
- package/bin/sync-and-reconcile +62 -64
- package/bin/validate-manifest +33 -9
- package/package.json +2 -10
- package/packages/agent-hooks/README.md +14 -9
- package/packages/agent-hooks/assets/hooks.json +0 -20
- package/packages/agent-hooks/src/cli/args.ts +1 -1
- package/packages/agent-hooks/src/cli/doctor.ts +6 -58
- package/packages/agent-hooks/src/deploy/deploy.ts +12 -41
- package/packages/agent-hooks/src/deploy/doctor.ts +8 -11
- package/packages/agent-hooks/src/deploy/index.ts +14 -14
- package/packages/agent-hooks/src/deploy/json-merge.ts +7 -8
- package/packages/agent-hooks/src/deploy/legacy-lock.ts +2 -2
- package/packages/agent-hooks/src/deploy/list.ts +1 -1
- package/packages/agent-hooks/src/deploy/lock.ts +31 -12
- package/packages/agent-hooks/src/deploy/profile.ts +3 -4
- package/packages/agent-hooks/src/deploy/source.ts +1 -1
- package/packages/agent-hooks/src/gating/config.ts +12 -24
- package/packages/agent-hooks/src/gating/root.ts +3 -3
- package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
- package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
- package/packages/agent-hooks/src/hooks/contract.ts +17 -17
- package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
- package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
- package/packages/agent-hooks/src/hooks/log.ts +8 -10
- package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
- package/packages/agent-hooks/src/hosts/registry.ts +1 -1
- package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
- package/packages/agent-hooks/src/log/writer.ts +16 -2
- package/packages/agent-hooks/src/main.ts +7 -41
- package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
- package/packages/agent-hooks/src/rules/engine.ts +13 -17
- package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
- package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
- package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
- package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
- package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
- package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
- package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
- package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
- package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
- package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
- package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
- package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +131 -0
- package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
- package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
- package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
- package/packages/agent-hooks/src/rules/impl/tool-grep.ts +33 -12
- package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
- package/packages/agent-hooks/src/rules/ports.ts +5 -7
- package/packages/agent-hooks/src/rules/registry.ts +4 -6
- package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
- package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
- package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
- package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
- package/packages/agent-hooks/src/rules/spec.ts +2 -2
- package/packages/agent-settings/README.md +287 -0
- package/packages/agent-settings/assets/GLOBAL-AGENTS.md +14 -16
- package/packages/agent-settings/assets/agents/architect.toml +2 -0
- package/packages/agent-settings/assets/agents/code-reviewer.toml +2 -0
- package/packages/agent-settings/assets/agents/executor.toml +2 -0
- package/packages/agent-settings/assets/agents/explore.toml +2 -0
- package/packages/agent-settings/assets/agents/planner.toml +2 -0
- package/packages/agent-settings/assets/mcp.json +0 -4
- package/packages/agent-settings/deploy-profile.json +139 -0
- package/packages/agent-settings/deploy-profile.schema.json +147 -0
- package/packages/agent-settings/managed/README.md +29 -30
- package/packages/agent-settings/managed/codex-requirements.toml +9 -9
- package/packages/agent-settings/package.json +20 -0
- package/packages/agent-settings/src/deploy/agent-render.ts +2 -2
- package/packages/agent-settings/src/deploy/agent-toml.ts +1 -1
- package/packages/agent-settings/src/deploy/agents-deploy.ts +17 -3
- package/packages/agent-settings/src/deploy/doctor.ts +3 -83
- package/packages/agent-settings/src/deploy/index.ts +6 -33
- package/packages/agent-settings/src/deploy/legacy-lock.ts +6 -6
- package/packages/agent-settings/src/deploy/list.ts +5 -19
- package/packages/agent-settings/src/deploy/lock.ts +8 -18
- package/packages/agent-settings/src/deploy/mcp-deploy.ts +10 -5
- package/packages/agent-settings/src/deploy/mcp-merge.ts +22 -3
- package/packages/agent-settings/src/deploy/mcp-source.ts +1 -1
- package/packages/agent-settings/src/deploy/profile.ts +11 -35
- package/packages/agent-settings/src/deploy/retire-lean-ctx.ts +184 -0
- package/packages/agent-settings/src/deploy/settings.ts +17 -22
- package/packages/agent-settings/src/global-surface-sweep.ts +0 -2
- package/packages/agent-settings/src/kimi-hooks.ts +339 -192
- package/packages/agent-settings/src/opencode-hooks.ts +1 -1
- package/packages/agent-settings/tsconfig.json +23 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +120 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +276 -0
- package/packages/agent-skills/assets/debug-issue/SKILL.md +8 -7
- package/packages/agent-skills/assets/explore-codebase/SKILL.md +13 -13
- package/packages/agent-skills/assets/refactor-safely/SKILL.md +12 -11
- package/packages/agent-skills/assets/review-changes/SKILL.md +7 -7
- package/packages/agent-skills/assets/testing/references/e2e.md +37 -0
- package/packages/agent-skills/assets/testing/references/integration.md +37 -0
- package/packages/agent-skills/assets/testing/references/unit.md +32 -0
- package/packages/agent-skills/dist/deploy.d.ts +2 -0
- package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
- package/packages/agent-skills/dist/deploy.js +27 -1
- package/packages/agent-skills/dist/deploy.js.map +1 -1
- package/packages/agent-skills/dist/doctor.d.ts +0 -2
- package/packages/agent-skills/dist/doctor.d.ts.map +1 -1
- package/packages/agent-skills/dist/doctor.js +1 -1
- package/packages/agent-skills/dist/doctor.js.map +1 -1
- package/packages/agent-skills/dist/fs-utils.d.ts +0 -1
- package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -1
- package/packages/agent-skills/dist/fs-utils.js +1 -1
- package/packages/agent-skills/dist/fs-utils.js.map +1 -1
- package/packages/agent-skills/src/deploy.ts +29 -1
- package/packages/agent-skills/src/doctor.ts +1 -1
- package/packages/agent-skills/src/fs-utils.ts +1 -1
- package/packages/azdo/README.md +10 -9
- package/packages/azdo/package.json +1 -3
- package/packages/azdo/scripts/probe-ado-rules.ts +311 -0
- package/packages/azdo/src/azdo-pl.ts +2 -54
- package/packages/azdo/src/azdo-pr-review.ts +4 -4
- package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
- package/packages/azdo/src/azdo-wit.ts +44 -2
- package/packages/azdo/src/lib/agent-identity.ts +12 -14
- package/packages/azdo/src/lib/agent-token.ts +2 -2
- package/packages/azdo/src/lib/client.ts +0 -5
- package/packages/azdo/src/lib/graph-identity.ts +4 -4
- package/packages/azdo/src/workflow-ladder.csv +241 -0
- package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
- package/packages/azdo/src/workflow-rules.ts +194 -0
- package/packages/fleet/manifest.json +35 -11
- package/packages/fleet/manifest.schema.json +62 -10
- package/packages/fleet/src/default-agent-file.ts +3 -3
- package/packages/fleet/src/install-adl-package.ts +73 -15
- package/packages/fleet/src/install-embedding-model.ts +13 -13
- package/packages/fleet/src/managed-settings.ts +7 -7
- package/packages/fleet/src/repo-maintain.ts +91 -55
- package/packages/fleet/src/scratch-reap.ts +5 -5
- package/packages/fleet/src/vscode-settings.ts +5 -5
- package/packages/repo-controls/README.md +141 -43
- package/packages/repo-controls/assets/promote.ts +4 -4
- package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
- package/packages/repo-controls/assets/version-bump.sh +31 -84
- package/packages/repo-controls/bunfig.toml +6 -7
- package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
- package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/sub/nested.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-001-tenancy.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-002-carrier.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-003-cli.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-old.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-older.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-01.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-02.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-03.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-04.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-05.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-06.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-07.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-08.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-09.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-10.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-11.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-12.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-13.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-14.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-15.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-16.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/e.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/short/only.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-legacy/docs/compliance/index.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-type/docs/compliance/index.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/no-type.md +9 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-experiment.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-research.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs/architecture/bad-status.md +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-last-update.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/created-date.md +21 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/research-shaped.md +19 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/a.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/b.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/a.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/b.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/c.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +258 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plan_metadata.py +9 -4
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/check.py +1 -1
- 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 +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +3 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
- package/packages/repo-controls/package.json +2 -9
- package/packages/repo-controls/scripts/hooks/post-merge +13 -0
- package/packages/repo-controls/scripts/hooks/pre-push +3 -3
- package/packages/repo-controls/src/azdo-push.ts +64 -36
- package/packages/repo-controls/src/azure-devops-governance.ts +7 -9
- package/packages/repo-controls/src/azure-devops-remote.ts +1 -1
- package/packages/repo-controls/src/cli.ts +29 -8
- package/packages/repo-controls/src/compliance-config.ts +410 -2
- package/packages/repo-controls/src/config.ts +133 -60
- package/packages/repo-controls/src/constants.ts +13 -27
- package/packages/repo-controls/src/coverage-ratchet.ts +4 -4
- package/packages/repo-controls/src/doctor.ts +46 -19
- package/packages/repo-controls/src/gitignore-block.ts +5 -29
- package/packages/repo-controls/src/hook-log.ts +1 -2
- package/packages/repo-controls/src/hook.ts +201 -45
- package/packages/repo-controls/src/install.ts +14 -8
- package/packages/repo-controls/src/integrity.ts +3 -3
- package/packages/repo-controls/src/lfs.ts +111 -0
- package/packages/repo-controls/src/promote.ts +8 -8
- package/packages/repo-controls/src/runtime.ts +9 -1
- package/packages/repo-controls/src/workflows-drift.ts +4 -5
- package/packages/repo-controls/src/worktree-guard.ts +3 -3
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
"""REP-002 grades the manifest and lockfile paths a repository DECLARES.
|
|
2
|
+
|
|
3
|
+
`[controls.compliance.lockfiles]` in `adl-config.toml` reaches the engine as four
|
|
4
|
+
comma-list declarations, a half (Bun, Cargo) being declared by a manifests list
|
|
5
|
+
and a lockfiles list together:
|
|
6
|
+
|
|
7
|
+
bun-manifests / bun-lockfiles `package.json` paths or globs / `bun.lock` paths
|
|
8
|
+
cargo-manifests / cargo-lockfiles `Cargo.toml` paths or globs / `Cargo.lock` paths
|
|
9
|
+
|
|
10
|
+
Why this exists, measured on enact-combined (2026-10-01): its `typescript` tree is
|
|
11
|
+
a brace union of directories, and its manifests sit at the repository ROOT and
|
|
12
|
+
under `apps/*/` and `packages/*/`. The registry scope `<typescript>/package.json`
|
|
13
|
+
expands to `{apps,packages,...}/package.json`, a ONE-level path that matches
|
|
14
|
+
nothing, so the whole-tree run was could-not-run while a narrowed run passed. The
|
|
15
|
+
declaration restates the scope (which files select the gate) and the grade (which
|
|
16
|
+
lockfiles must exist) from the same lists.
|
|
17
|
+
|
|
18
|
+
This file is separate from `test_check.py` on purpose: that module carries a
|
|
19
|
+
module-level cargo skip and an autouse patch of `runner.lookup`, and nothing in it
|
|
20
|
+
is edited here. Every test below that needs a real `cargo` says so.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import shutil
|
|
26
|
+
from collections.abc import Mapping
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
|
|
29
|
+
import pytest
|
|
30
|
+
from fixture_trees import fixture_trees
|
|
31
|
+
from helpers import corpus, corpus_files
|
|
32
|
+
|
|
33
|
+
from adl_compliance import runner
|
|
34
|
+
from adl_compliance.checks.repository.lockfile_integrity import LockfileIntegrity
|
|
35
|
+
from adl_compliance.core.context import Context, FileSet
|
|
36
|
+
from adl_compliance.core.errors import CouldNotRun
|
|
37
|
+
from adl_compliance.core.verdict import Outcome, Verdict
|
|
38
|
+
from adl_compliance.policy.registry import load, policy_text
|
|
39
|
+
|
|
40
|
+
ROW = load().by_id("REP-002")
|
|
41
|
+
CLEAN_CORPUS = corpus("repository", "lockfile-integrity") / "clean"
|
|
42
|
+
|
|
43
|
+
requires_cargo = pytest.mark.skipif(shutil.which("cargo") is None, reason="cargo is not installed")
|
|
44
|
+
|
|
45
|
+
# enact-combined's declared trees, as `adl-config.toml` states them.
|
|
46
|
+
ENACT_TREES = {
|
|
47
|
+
"rust": "",
|
|
48
|
+
"frontend": "",
|
|
49
|
+
"typescript": "{apps,packages,workflows,infra,tests,dev,live-probes}",
|
|
50
|
+
}
|
|
51
|
+
# The declaration enact-combined needs (see .scratchpad/rep002-scope/enact-combined-patch.toml).
|
|
52
|
+
BUN = {
|
|
53
|
+
"bun-manifests": "package.json,apps/*/package.json,packages/*/package.json",
|
|
54
|
+
"bun-lockfiles": "bun.lock",
|
|
55
|
+
}
|
|
56
|
+
CARGO = {
|
|
57
|
+
"cargo-manifests": "backend/Cargo.toml",
|
|
58
|
+
"cargo-lockfiles": "backend/Cargo.lock",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
ENACT_FILES = {
|
|
62
|
+
"README.md": "# repo\n",
|
|
63
|
+
"package.json": "{}\n",
|
|
64
|
+
"bun.lock": "lock\n",
|
|
65
|
+
"apps/web/package.json": "{}\n",
|
|
66
|
+
"apps/server/package.json": "{}\n",
|
|
67
|
+
"packages/x/package.json": "{}\n",
|
|
68
|
+
}
|
|
69
|
+
IN_SCOPE = 5 # package.json, bun.lock, and the three nested package.json files
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def write(root: Path, files: Mapping[str, str]) -> tuple[str, ...]:
|
|
73
|
+
for relative, body in files.items():
|
|
74
|
+
target = root / relative
|
|
75
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
76
|
+
target.write_text(body, encoding="utf-8")
|
|
77
|
+
return tuple(sorted(files))
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def grade(
|
|
81
|
+
root: Path,
|
|
82
|
+
files: tuple[str, ...],
|
|
83
|
+
*,
|
|
84
|
+
trees: Mapping[str, str],
|
|
85
|
+
declarations: Mapping[str, str],
|
|
86
|
+
given: tuple[str, ...] | None = None,
|
|
87
|
+
exhaustive: bool = True,
|
|
88
|
+
**kwargs: object,
|
|
89
|
+
) -> Verdict:
|
|
90
|
+
"""The real dispatch path. With `given`, a NARROWED run over the complete
|
|
91
|
+
`files` universe; without it, the hook's shape (the whole tree, exhaustive)."""
|
|
92
|
+
return runner.run(
|
|
93
|
+
ROW,
|
|
94
|
+
root,
|
|
95
|
+
files if given is None else given,
|
|
96
|
+
exhaustive=exhaustive and given is None,
|
|
97
|
+
universe=files,
|
|
98
|
+
declarations=declarations,
|
|
99
|
+
trees=trees,
|
|
100
|
+
declared_trees=trees,
|
|
101
|
+
**kwargs, # type: ignore[arg-type]
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# ------------------------------------------------------------ the enact-combined shape
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def test_undeclared_the_enact_shape_is_still_could_not_run_on_a_whole_tree(tmp_path: Path) -> None:
|
|
109
|
+
"""The default is unchanged: no declaration, no new behaviour. This is the
|
|
110
|
+
verdict that was measured live, kept as the pin that declaring nothing does
|
|
111
|
+
not move it."""
|
|
112
|
+
files = write(tmp_path, ENACT_FILES)
|
|
113
|
+
verdict = grade(tmp_path, files, trees=ENACT_TREES, declarations={})
|
|
114
|
+
assert verdict.outcome is Outcome.COULD_NOT_RUN, verdict.render()
|
|
115
|
+
assert "engine.scope matches no file on disk" in verdict.message
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_declared_the_enact_shape_is_clean_on_a_whole_tree(tmp_path: Path) -> None:
|
|
119
|
+
files = write(tmp_path, ENACT_FILES)
|
|
120
|
+
verdict = grade(tmp_path, files, trees=ENACT_TREES, declarations=BUN)
|
|
121
|
+
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
122
|
+
assert verdict.units == IN_SCOPE
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_declared_the_enact_shape_is_clean_on_a_narrowed_run(tmp_path: Path) -> None:
|
|
126
|
+
"""One changed manifest selects the gate, and the gate is graded over every
|
|
127
|
+
declared path in the complete universe."""
|
|
128
|
+
files = write(tmp_path, ENACT_FILES)
|
|
129
|
+
verdict = grade(
|
|
130
|
+
tmp_path, files, trees=ENACT_TREES, declarations=BUN, given=("apps/web/package.json",)
|
|
131
|
+
)
|
|
132
|
+
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
133
|
+
assert verdict.units == IN_SCOPE
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def test_declared_a_changed_lockfile_alone_selects_the_gate(tmp_path: Path) -> None:
|
|
137
|
+
files = write(tmp_path, ENACT_FILES)
|
|
138
|
+
verdict = grade(tmp_path, files, trees=ENACT_TREES, declarations=BUN, given=("bun.lock",))
|
|
139
|
+
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
140
|
+
assert verdict.units == IN_SCOPE
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_declared_a_change_outside_every_declared_path_does_not_select_the_gate(
|
|
144
|
+
tmp_path: Path,
|
|
145
|
+
) -> None:
|
|
146
|
+
"""Selection follows the declaration. With nothing declared changed, the gate
|
|
147
|
+
does not apply: the missing lockfile below is not probed on this run."""
|
|
148
|
+
files = write(tmp_path, {**ENACT_FILES, "bun.lock": ""})
|
|
149
|
+
verdict = grade(tmp_path, files, trees=ENACT_TREES, declarations=BUN, given=("README.md",))
|
|
150
|
+
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
151
|
+
assert verdict.findings == ()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def test_declared_the_lockfile_input_is_not_consulted(tmp_path: Path) -> None:
|
|
155
|
+
"""The declaration drives the grade: a per-gate `bun_lock` input pointing at
|
|
156
|
+
nothing cannot fail a repository whose declared lockfile is present."""
|
|
157
|
+
files = write(tmp_path, ENACT_FILES)
|
|
158
|
+
verdict = grade(
|
|
159
|
+
tmp_path,
|
|
160
|
+
files,
|
|
161
|
+
trees=ENACT_TREES,
|
|
162
|
+
declarations=BUN,
|
|
163
|
+
inputs={"REP-002": {"bun_lock": tmp_path / "nowhere" / "bun.lock"}},
|
|
164
|
+
)
|
|
165
|
+
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# ----------------------------------------------------------------- the lockfile grade
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@pytest.mark.parametrize("body", [None, ""], ids=["missing", "empty"])
|
|
172
|
+
def test_declared_a_missing_or_empty_lockfile_is_the_same_finding(
|
|
173
|
+
tmp_path: Path, body: str | None
|
|
174
|
+
) -> None:
|
|
175
|
+
files = dict(ENACT_FILES)
|
|
176
|
+
if body is None:
|
|
177
|
+
del files["bun.lock"]
|
|
178
|
+
else:
|
|
179
|
+
files["bun.lock"] = body
|
|
180
|
+
verdict = grade(tmp_path, write(tmp_path, files), trees=ENACT_TREES, declarations=BUN)
|
|
181
|
+
assert verdict.outcome is Outcome.FINDINGS, verdict.render()
|
|
182
|
+
[finding] = verdict.findings
|
|
183
|
+
assert finding.rule == "LCK-001"
|
|
184
|
+
assert finding.path == "bun.lock"
|
|
185
|
+
assert finding.message == "missing bun.lock"
|
|
186
|
+
assert "(cd . && bun install)" in finding.fix
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def test_declared_and_undeclared_report_a_missing_lockfile_identically(tmp_path: Path) -> None:
|
|
190
|
+
"""Same corpus, graded once through the tree default and once through the
|
|
191
|
+
declaration (with the tree pointed elsewhere, so only the declaration can
|
|
192
|
+
reach the file): the finding is equal, field for field."""
|
|
193
|
+
files = write(tmp_path, {"frontend/package.json": "{}\n", "frontend/bun.lock": ""})
|
|
194
|
+
undeclared = grade(
|
|
195
|
+
tmp_path, files, trees={"rust": "", "typescript": "frontend"}, declarations={}
|
|
196
|
+
)
|
|
197
|
+
declared = grade(
|
|
198
|
+
tmp_path,
|
|
199
|
+
files,
|
|
200
|
+
trees={"rust": "", "typescript": "elsewhere"},
|
|
201
|
+
declarations={"bun-manifests": "frontend/package.json", "bun-lockfiles": "frontend/bun.lock"},
|
|
202
|
+
)
|
|
203
|
+
assert undeclared.outcome is Outcome.FINDINGS, undeclared.render()
|
|
204
|
+
assert declared.findings == undeclared.findings
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def test_declared_two_present_lockfiles_are_clean(tmp_path: Path) -> None:
|
|
208
|
+
declarations = {
|
|
209
|
+
"bun-manifests": "package.json,infra/docker/opencode-stack/package.json",
|
|
210
|
+
"bun-lockfiles": "bun.lock,infra/docker/opencode-stack/bun.lock",
|
|
211
|
+
}
|
|
212
|
+
both = {
|
|
213
|
+
**ENACT_FILES,
|
|
214
|
+
"infra/docker/opencode-stack/package.json": "{}\n",
|
|
215
|
+
"infra/docker/opencode-stack/bun.lock": "lock\n",
|
|
216
|
+
}
|
|
217
|
+
verdict = grade(tmp_path, write(tmp_path, both), trees=ENACT_TREES, declarations=declarations)
|
|
218
|
+
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def test_declared_the_second_lockfile_missing_is_reported_by_its_own_path(tmp_path: Path) -> None:
|
|
222
|
+
declarations = {
|
|
223
|
+
"bun-manifests": "package.json,infra/docker/opencode-stack/package.json",
|
|
224
|
+
"bun-lockfiles": "bun.lock,infra/docker/opencode-stack/bun.lock",
|
|
225
|
+
}
|
|
226
|
+
files = {**ENACT_FILES, "infra/docker/opencode-stack/package.json": "{}\n"}
|
|
227
|
+
verdict = grade(tmp_path, write(tmp_path, files), trees=ENACT_TREES, declarations=declarations)
|
|
228
|
+
[finding] = verdict.findings
|
|
229
|
+
assert finding.path == "infra/docker/opencode-stack/bun.lock"
|
|
230
|
+
assert finding.message == "missing infra/docker/opencode-stack/bun.lock"
|
|
231
|
+
assert "(cd infra/docker/opencode-stack && bun install)" in finding.fix
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def test_declared_both_lockfiles_missing_reports_only_the_first(tmp_path: Path) -> None:
|
|
235
|
+
"""check.sh's shape: the first problem ends the run."""
|
|
236
|
+
declarations = {
|
|
237
|
+
"bun-manifests": "package.json,infra/docker/opencode-stack/package.json",
|
|
238
|
+
"bun-lockfiles": "bun.lock,infra/docker/opencode-stack/bun.lock",
|
|
239
|
+
}
|
|
240
|
+
files = {k: v for k, v in ENACT_FILES.items() if k != "bun.lock"}
|
|
241
|
+
files["infra/docker/opencode-stack/package.json"] = "{}\n"
|
|
242
|
+
verdict = grade(tmp_path, write(tmp_path, files), trees=ENACT_TREES, declarations=declarations)
|
|
243
|
+
assert [f.path for f in verdict.findings] == ["bun.lock"]
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
# ------------------------------------------------------ a declared glob that matches nothing
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
@pytest.mark.parametrize("narrowed", [False, True], ids=["whole tree", "narrowed run"])
|
|
250
|
+
@pytest.mark.parametrize("dead", ["tools/*/package.json", "nope/package.json"])
|
|
251
|
+
def test_a_declared_manifest_matching_no_file_is_could_not_run_naming_it(
|
|
252
|
+
tmp_path: Path, dead: str, narrowed: bool
|
|
253
|
+
) -> None:
|
|
254
|
+
files = write(tmp_path, ENACT_FILES)
|
|
255
|
+
declarations = {**BUN, "bun-manifests": f"package.json,{dead}"}
|
|
256
|
+
verdict = grade(
|
|
257
|
+
tmp_path,
|
|
258
|
+
files,
|
|
259
|
+
trees=ENACT_TREES,
|
|
260
|
+
declarations=declarations,
|
|
261
|
+
given=("package.json",) if narrowed else None,
|
|
262
|
+
)
|
|
263
|
+
assert verdict.outcome is Outcome.COULD_NOT_RUN, verdict.render()
|
|
264
|
+
assert "`bun-manifests`" in verdict.message
|
|
265
|
+
assert dead in verdict.message
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def test_a_dead_declaration_is_loud_even_though_other_declared_paths_match(
|
|
269
|
+
tmp_path: Path,
|
|
270
|
+
) -> None:
|
|
271
|
+
"""The scope is non-empty (the live entries match), so the runner's own
|
|
272
|
+
empty-scope guard is silent; only the per-declaration check can see it."""
|
|
273
|
+
files = write(tmp_path, ENACT_FILES)
|
|
274
|
+
verdict = grade(
|
|
275
|
+
tmp_path,
|
|
276
|
+
files,
|
|
277
|
+
trees=ENACT_TREES,
|
|
278
|
+
declarations={**BUN, "bun-manifests": "package.json,services/*/package.json"},
|
|
279
|
+
)
|
|
280
|
+
assert verdict.outcome is Outcome.COULD_NOT_RUN, verdict.render()
|
|
281
|
+
assert "services/*/package.json" in verdict.message
|
|
282
|
+
assert "matches no file on disk" not in verdict.message
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def test_the_check_itself_refuses_a_dead_declaration_given_a_complete_set(tmp_path: Path) -> None:
|
|
286
|
+
"""Not only through the runner: a caller building a Context by hand gets the
|
|
287
|
+
same refusal, because the check is what knows what it was told to scan."""
|
|
288
|
+
ctx = Context(root=tmp_path, row=ROW, declarations=BUN | {"bun-manifests": "app/*/package.json"})
|
|
289
|
+
write(tmp_path, ENACT_FILES)
|
|
290
|
+
with pytest.raises(CouldNotRun) as raised:
|
|
291
|
+
tuple(LockfileIntegrity().run(ctx, FileSet(paths=tuple(sorted(ENACT_FILES)))))
|
|
292
|
+
assert "`bun-manifests`" in str(raised.value)
|
|
293
|
+
assert "app/*/package.json" in str(raised.value)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
# ------------------------------------------------------------- malformed declarations
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def bun(manifests: str = "package.json", lockfiles: str = "bun.lock") -> dict[str, str]:
|
|
300
|
+
return {"bun-manifests": manifests, "bun-lockfiles": lockfiles}
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def cargo(manifests: str = "backend/Cargo.toml", lockfiles: str = "backend/Cargo.lock") -> dict[str, str]:
|
|
304
|
+
return {"cargo-manifests": manifests, "cargo-lockfiles": lockfiles}
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
MALFORMED = [
|
|
308
|
+
pytest.param(bun("/etc/package.json"), "bun-manifests", id="manifest absolute"),
|
|
309
|
+
pytest.param(bun("../x/package.json"), "bun-manifests", id="manifest leading .."),
|
|
310
|
+
pytest.param(bun("apps/../package.json"), "bun-manifests", id="manifest embedded .."),
|
|
311
|
+
pytest.param(bun("./package.json"), "bun-manifests", id="manifest leading ."),
|
|
312
|
+
pytest.param(bun("apps//web/package.json"), "bun-manifests", id="manifest empty segment"),
|
|
313
|
+
pytest.param(bun("apps\\web\\package.json"), "bun-manifests", id="manifest backslash"),
|
|
314
|
+
pytest.param(bun(""), "bun-manifests", id="manifest empty value"),
|
|
315
|
+
pytest.param(bun("package.json,"), "bun-manifests", id="manifest trailing comma"),
|
|
316
|
+
pytest.param(bun(",package.json"), "bun-manifests", id="manifest leading comma"),
|
|
317
|
+
pytest.param(bun("package.json, ,apps/*/package.json"), "bun-manifests", id="manifest blank entry"),
|
|
318
|
+
pytest.param(bun("package.json,package.json"), "bun-manifests", id="manifest duplicate"),
|
|
319
|
+
pytest.param(bun("!apps/web/package.json"), "bun-manifests", id="manifest negation"),
|
|
320
|
+
pytest.param(bun("<typescript>/package.json"), "bun-manifests", id="manifest placeholder"),
|
|
321
|
+
pytest.param(bun("apps/{web,x}/package.json"), "bun-manifests", id="manifest brace union"),
|
|
322
|
+
pytest.param(bun("apps/web/README.md"), "bun-manifests", id="manifest wrong file name"),
|
|
323
|
+
pytest.param(bun("apps/web/"), "bun-manifests", id="manifest directory"),
|
|
324
|
+
pytest.param(bun(lockfiles="/abs/bun.lock"), "bun-lockfiles", id="lockfile absolute"),
|
|
325
|
+
pytest.param(bun(lockfiles="../bun.lock"), "bun-lockfiles", id="lockfile .."),
|
|
326
|
+
pytest.param(bun(lockfiles="a\\bun.lock"), "bun-lockfiles", id="lockfile backslash"),
|
|
327
|
+
pytest.param(bun(lockfiles=""), "bun-lockfiles", id="lockfile empty value"),
|
|
328
|
+
pytest.param(bun(lockfiles="bun.lock,bun.lock"), "bun-lockfiles", id="lockfile duplicate"),
|
|
329
|
+
pytest.param(bun(lockfiles="*.lock"), "bun-lockfiles", id="lockfile glob"),
|
|
330
|
+
pytest.param(bun(lockfiles="apps/*/bun.lock"), "bun-lockfiles", id="lockfile nested glob"),
|
|
331
|
+
pytest.param(cargo("/abs/Cargo.toml"), "cargo-manifests", id="cargo manifest absolute"),
|
|
332
|
+
pytest.param(cargo("backend/Cargo.json"), "cargo-manifests", id="cargo manifest wrong file name"),
|
|
333
|
+
pytest.param(cargo(lockfiles="../Cargo.lock"), "cargo-lockfiles", id="cargo lockfile .."),
|
|
334
|
+
pytest.param(cargo(lockfiles="backend/*/Cargo.lock"), "cargo-lockfiles", id="cargo lockfile glob"),
|
|
335
|
+
pytest.param({"bun-manifests": "package.json"}, "bun-lockfiles", id="bun manifests without lockfiles"),
|
|
336
|
+
pytest.param({"bun-lockfiles": "bun.lock"}, "bun-manifests", id="bun lockfiles without manifests"),
|
|
337
|
+
pytest.param({"cargo-manifests": "backend/Cargo.toml"}, "cargo-lockfiles", id="cargo manifests alone"),
|
|
338
|
+
pytest.param({"cargo-lockfiles": "backend/Cargo.lock"}, "cargo-manifests", id="cargo lockfiles alone"),
|
|
339
|
+
]
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
@pytest.mark.parametrize(("declarations", "named"), MALFORMED)
|
|
343
|
+
def test_a_malformed_declaration_is_could_not_run_naming_it(
|
|
344
|
+
tmp_path: Path, declarations: dict[str, str], named: str
|
|
345
|
+
) -> None:
|
|
346
|
+
files = write(tmp_path, ENACT_FILES)
|
|
347
|
+
verdict = grade(tmp_path, files, trees=ENACT_TREES, declarations=declarations)
|
|
348
|
+
assert verdict.outcome is Outcome.COULD_NOT_RUN, verdict.render()
|
|
349
|
+
assert f"`{named}`" in verdict.message, verdict.message
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
@pytest.mark.parametrize(("declarations", "named"), MALFORMED)
|
|
353
|
+
def test_the_check_refuses_a_malformed_declaration_without_the_runner(
|
|
354
|
+
tmp_path: Path, declarations: dict[str, str], named: str
|
|
355
|
+
) -> None:
|
|
356
|
+
files = write(tmp_path, ENACT_FILES)
|
|
357
|
+
ctx = Context(root=tmp_path, row=ROW, declarations=declarations)
|
|
358
|
+
with pytest.raises(CouldNotRun) as raised:
|
|
359
|
+
tuple(LockfileIntegrity().run(ctx, FileSet(paths=files)))
|
|
360
|
+
assert f"`{named}`" in str(raised.value), str(raised.value)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
# ----------------------------------------------------------------- the scope hook
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def test_an_absent_declaration_restates_nothing() -> None:
|
|
367
|
+
assert LockfileIntegrity.declared_scope(ROW.engine.scope, {}) is None
|
|
368
|
+
assert LockfileIntegrity.declared_scope(ROW.engine.scope, {"license": "Proprietary"}) is None
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def test_a_declared_bun_half_replaces_only_the_typescript_entries() -> None:
|
|
372
|
+
assert LockfileIntegrity.declared_scope(ROW.engine.scope, BUN) == (
|
|
373
|
+
"<rust>/Cargo.toml",
|
|
374
|
+
"<rust>/Cargo.lock",
|
|
375
|
+
"package.json",
|
|
376
|
+
"apps/*/package.json",
|
|
377
|
+
"packages/*/package.json",
|
|
378
|
+
"bun.lock",
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def test_a_declared_cargo_half_replaces_only_the_rust_entries() -> None:
|
|
383
|
+
assert LockfileIntegrity.declared_scope(ROW.engine.scope, CARGO) == (
|
|
384
|
+
"<typescript>/package.json",
|
|
385
|
+
"<typescript>/bun.lock",
|
|
386
|
+
"backend/Cargo.toml",
|
|
387
|
+
"backend/Cargo.lock",
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def test_both_halves_declared_leave_no_tree_default() -> None:
|
|
392
|
+
assert LockfileIntegrity.declared_scope(ROW.engine.scope, {**BUN, **CARGO}) == (
|
|
393
|
+
"backend/Cargo.toml",
|
|
394
|
+
"backend/Cargo.lock",
|
|
395
|
+
"package.json",
|
|
396
|
+
"apps/*/package.json",
|
|
397
|
+
"packages/*/package.json",
|
|
398
|
+
"bun.lock",
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def test_the_registry_scope_the_hook_replaces_is_two_entries_per_tree() -> None:
|
|
403
|
+
"""The hook drops a declared half's defaults by their tree prefix, so a row
|
|
404
|
+
that grew an entry under a prefix would be dropped by a declaration without
|
|
405
|
+
anyone deciding it. This pins the shape the replacement relies on."""
|
|
406
|
+
scope = ROW.engine.scope
|
|
407
|
+
assert sorted(scope) == sorted(
|
|
408
|
+
["<rust>/Cargo.toml", "<rust>/Cargo.lock", "<typescript>/package.json", "<typescript>/bun.lock"]
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def test_both_registry_files_carry_the_same_text() -> None:
|
|
413
|
+
assert policy_text("gate-registry.yaml") == policy_text("gate-registry.alt.yaml")
|
|
414
|
+
assert load("gate-registry.alt.yaml").by_id("REP-002").engine.scope == ROW.engine.scope
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
# ------------------------------------------------------------------- the Cargo half
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
@requires_cargo
|
|
421
|
+
def test_declared_cargo_paths_are_graded_instead_of_the_rust_tree(tmp_path: Path) -> None:
|
|
422
|
+
shutil.copytree(CLEAN_CORPUS, tmp_path, dirs_exist_ok=True)
|
|
423
|
+
files = corpus_files(tmp_path)
|
|
424
|
+
trees = {**fixture_trees(), "rust": "somewhere-else"}
|
|
425
|
+
|
|
426
|
+
undeclared = grade(tmp_path, files, trees=trees, declarations={})
|
|
427
|
+
assert [f.path for f in undeclared.findings] == ["somewhere-else/Cargo.lock"]
|
|
428
|
+
|
|
429
|
+
declared = grade(tmp_path, files, trees=trees, declarations=CARGO)
|
|
430
|
+
assert declared.outcome is Outcome.CLEAN, declared.render()
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
@requires_cargo
|
|
434
|
+
def test_declared_cargo_missing_lockfile_is_the_missing_finding(tmp_path: Path) -> None:
|
|
435
|
+
shutil.copytree(CLEAN_CORPUS, tmp_path, dirs_exist_ok=True)
|
|
436
|
+
(tmp_path / "backend" / "Cargo.lock").unlink()
|
|
437
|
+
verdict = grade(
|
|
438
|
+
tmp_path,
|
|
439
|
+
corpus_files(tmp_path),
|
|
440
|
+
trees={**fixture_trees(), "rust": "somewhere-else"},
|
|
441
|
+
declarations=CARGO,
|
|
442
|
+
)
|
|
443
|
+
[finding] = verdict.findings
|
|
444
|
+
assert finding.rule == "LCK-001"
|
|
445
|
+
assert finding.path == "backend/Cargo.lock"
|
|
446
|
+
assert finding.message == "missing backend/Cargo.lock"
|
|
447
|
+
assert "(cd backend && cargo generate-lockfile)" in finding.fix
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
def test_declared_cargo_rejection_is_lck_002_against_the_lockfiles_own_directory(
|
|
451
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
452
|
+
) -> None:
|
|
453
|
+
"""The cargo command, not cargo's opinion, is what this pins.
|
|
454
|
+
|
|
455
|
+
`cargo metadata --locked --offline --no-deps` (the command this row has always
|
|
456
|
+
run, unchanged here) accepts every lock body measured -- `version = 4` alone,
|
|
457
|
+
garbage, `version = 99` -- so a real stale lockfile cannot be built to make it
|
|
458
|
+
fail. What can be asserted is what the declaration changes: the workspace is the
|
|
459
|
+
declared lockfile's directory (cwd), the manifest is `<that directory>/Cargo.toml`
|
|
460
|
+
(`--manifest-path`), and a non-zero exit is the LCK-002 finding naming both.
|
|
461
|
+
"""
|
|
462
|
+
from adl_compliance.checks.repository.lockfile_integrity import check as module
|
|
463
|
+
|
|
464
|
+
write(tmp_path, {"nested/ws/Cargo.toml": "[package]\n", "nested/ws/Cargo.lock": "lock\n", "frontend/bun.lock": "lock\n"})
|
|
465
|
+
calls: list[tuple[list[str], Path]] = []
|
|
466
|
+
|
|
467
|
+
def fake_run(argv: list[str], *, cwd: Path, **_: object) -> object:
|
|
468
|
+
calls.append((argv, cwd))
|
|
469
|
+
return type("Done", (), {"returncode": 0 if argv[1] == "--version" else 101})()
|
|
470
|
+
|
|
471
|
+
monkeypatch.setattr(module.shutil, "which", lambda name: "/fake/cargo")
|
|
472
|
+
monkeypatch.setattr(module.subprocess, "run", fake_run)
|
|
473
|
+
verdict = grade(
|
|
474
|
+
tmp_path,
|
|
475
|
+
corpus_files(tmp_path),
|
|
476
|
+
trees=fixture_trees(),
|
|
477
|
+
declarations=cargo("nested/*/Cargo.toml", "nested/ws/Cargo.lock"),
|
|
478
|
+
)
|
|
479
|
+
[finding] = verdict.findings
|
|
480
|
+
assert finding.rule == "LCK-002"
|
|
481
|
+
assert finding.path == "nested/ws/Cargo.lock"
|
|
482
|
+
assert finding.message == "nested/ws/Cargo.lock does not satisfy nested/ws/Cargo.toml"
|
|
483
|
+
assert "(cd nested/ws && cargo update)" in finding.fix
|
|
484
|
+
assert [cwd for _, cwd in calls] == [tmp_path / "nested" / "ws"] * 2
|
|
485
|
+
metadata = calls[1][0]
|
|
486
|
+
assert metadata[:3] == ["cargo", "metadata", "--locked"]
|
|
487
|
+
assert metadata[metadata.index("--manifest-path") + 1] == str(tmp_path / "nested" / "ws" / "Cargo.toml")
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
@requires_cargo
|
|
491
|
+
def test_declared_cargo_workspace_is_the_lockfiles_directory(tmp_path: Path) -> None:
|
|
492
|
+
"""A workspace nested where no tree points: cargo is driven from the lock's
|
|
493
|
+
own directory, so the rust-toolchain override beside it applies."""
|
|
494
|
+
shutil.copytree(CLEAN_CORPUS / "backend", tmp_path / "crates" / "ws")
|
|
495
|
+
write(tmp_path, {"frontend/bun.lock": "lock\n"})
|
|
496
|
+
verdict = grade(
|
|
497
|
+
tmp_path,
|
|
498
|
+
corpus_files(tmp_path),
|
|
499
|
+
trees=fixture_trees(),
|
|
500
|
+
declarations=cargo("crates/*/Cargo.toml", "crates/ws/Cargo.lock"),
|
|
501
|
+
)
|
|
502
|
+
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
@requires_cargo
|
|
506
|
+
def test_an_undeclared_half_keeps_its_tree_defaults_beside_a_declared_one(tmp_path: Path) -> None:
|
|
507
|
+
"""Bun declared, Cargo not: the Rust tree still supplies the Cargo half."""
|
|
508
|
+
shutil.copytree(CLEAN_CORPUS, tmp_path, dirs_exist_ok=True)
|
|
509
|
+
write(tmp_path, ENACT_FILES)
|
|
510
|
+
files = corpus_files(tmp_path)
|
|
511
|
+
trees = {"rust": "backend", "typescript": ENACT_TREES["typescript"]}
|
|
512
|
+
|
|
513
|
+
clean = grade(tmp_path, files, trees=trees, declarations=BUN)
|
|
514
|
+
assert clean.outcome is Outcome.CLEAN, clean.render()
|
|
515
|
+
assert clean.units == IN_SCOPE + 2 # + backend/Cargo.toml and backend/Cargo.lock
|
|
516
|
+
|
|
517
|
+
(tmp_path / "bun.lock").unlink()
|
|
518
|
+
broken = grade(tmp_path, corpus_files(tmp_path), trees=trees, declarations=BUN)
|
|
519
|
+
assert [f.path for f in broken.findings] == ["bun.lock"]
|
|
520
|
+
|
|
521
|
+
(tmp_path / "backend" / "Cargo.lock").unlink()
|
|
522
|
+
both = grade(tmp_path, corpus_files(tmp_path), trees=trees, declarations=BUN)
|
|
523
|
+
assert [f.path for f in both.findings] == ["backend/Cargo.lock"], "the Cargo half is reported first, as before"
|