@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.12 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adl +2 -2
- package/bin/git +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 +10 -24
- package/packages/agent-hooks/src/gating/root.ts +3 -3
- package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
- package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
- package/packages/agent-hooks/src/hooks/contract.ts +17 -17
- package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
- package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
- package/packages/agent-hooks/src/hooks/log.ts +8 -10
- package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
- package/packages/agent-hooks/src/hosts/registry.ts +1 -1
- package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
- package/packages/agent-hooks/src/log/writer.ts +16 -2
- package/packages/agent-hooks/src/main.ts +7 -41
- package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
- package/packages/agent-hooks/src/rules/engine.ts +13 -17
- package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
- package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
- package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
- package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
- package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
- package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
- package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
- package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
- package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
- package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
- package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
- package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +159 -0
- package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
- package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
- package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
- package/packages/agent-hooks/src/rules/impl/tool-grep.ts +34 -12
- package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
- package/packages/agent-hooks/src/rules/ports.ts +5 -7
- package/packages/agent-hooks/src/rules/registry.ts +4 -6
- package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
- package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
- package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
- package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
- package/packages/agent-hooks/src/rules/spec.ts +2 -2
- package/packages/agent-settings/README.md +287 -0
- package/packages/agent-settings/assets/GLOBAL-AGENTS.md +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/src/azdo-pl.ts +2 -54
- package/packages/azdo/src/azdo-pr-review.ts +4 -4
- package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
- package/packages/azdo/src/azdo-wit.ts +41 -2
- package/packages/azdo/src/lib/agent-identity.ts +12 -14
- package/packages/azdo/src/lib/agent-token.ts +2 -2
- package/packages/azdo/src/lib/client.ts +0 -5
- package/packages/azdo/src/lib/graph-identity.ts +4 -4
- package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
- package/packages/azdo/src/workflow-rules.ts +128 -0
- package/packages/fleet/manifest.json +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 +256 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
- package/packages/repo-controls/package.json +2 -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 @@
|
|
|
1
|
+
c
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
only
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
b
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
b
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
b
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
c
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"""DOC-012 — the page-count cap for every directory directly under docs/.
|
|
2
|
+
|
|
3
|
+
Ten committed corpora, the runner-driven shape LAY-004's test uses:
|
|
4
|
+
`docs-size-clean` (every directory within the engine-default cap of 15),
|
|
5
|
+
`docs-size-default-cap` (sixteen pages in one directory, no declared cap —
|
|
6
|
+
DIR-004 names the default; the old-style register beside it proves a register
|
|
7
|
+
without a `docs_pages` section is no exemption), `docs-size-over-cap` (DIR-004
|
|
8
|
+
with an in-cap control beside it), `docs-size-exempt` (a baseline entry
|
|
9
|
+
exempts its directory up to the recorded number), `docs-size-grew` (DIR-005,
|
|
10
|
+
a directory past its recorded exemption), `docs-size-stale` (DIR-006's two
|
|
11
|
+
kept cases, shrunk-under-cap and directory-gone, with a still-valid baseline
|
|
12
|
+
entry beside them), `docs-size-no-section` (an old-style register holds no
|
|
13
|
+
exemptions, so the cap is enforced bare over its five-page directory),
|
|
14
|
+
`docs-size-decisions` (the flat ADR log is exempt by rule at any depth, with
|
|
15
|
+
an over-cap directory beside it proving the corpus is not silent by
|
|
16
|
+
accident), `docs-size-assets` (non-`.md` assets, dot-prefixed pages, and
|
|
17
|
+
paths outside docs/ are not counted, at the runner level and — reading the
|
|
18
|
+
check directly, the way DOC-011's test does — at the check level), and
|
|
19
|
+
`docs-size-unusable` (a register that exists but is not valid YAML —
|
|
20
|
+
could-not-run, the ruling's kept exception).
|
|
21
|
+
|
|
22
|
+
V2 (owner ruling 2026-10-02, replacing v1 the same day): the cap lives in
|
|
23
|
+
`[controls.compliance.limits].docs_pages_per_directory` (engine default 15),
|
|
24
|
+
NOT in the register. The register is exemptions ONLY — a `docs_pages.baseline`
|
|
25
|
+
entry exempts its directory up to the recorded number; no entry means no
|
|
26
|
+
exemption, so an ABSENT register or a register without a `docs_pages` section
|
|
27
|
+
grades STRICTER (the widening input's normal contract — v1's "ratchets sit
|
|
28
|
+
ON TOP" absence-is-clean exception belonged to LAY-004, whose configuration
|
|
29
|
+
IS the register; DOC-012's configuration is the declared limit). Two tests
|
|
30
|
+
below are the v1 tests reworked for the flip, and say so. At zero exemptions
|
|
31
|
+
the register file has no meaning and is deleted — adl-azdo's own was.
|
|
32
|
+
|
|
33
|
+
Each fixture carries its own `grants.yaml` at its own root, passed as the
|
|
34
|
+
`register` input override — the same mechanism LAY-004's test uses. The cap
|
|
35
|
+
travels as the `docs-pages-per-directory` declaration, the same channel
|
|
36
|
+
LAY-014's tests use for `scripts-direct-files`. `docs_root` needs no
|
|
37
|
+
override: the corpora are laid out in the fixture tree shape and
|
|
38
|
+
`conftest.py` declares it once for the suite.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
from __future__ import annotations
|
|
42
|
+
|
|
43
|
+
import pathlib
|
|
44
|
+
|
|
45
|
+
from adl_compliance import runner
|
|
46
|
+
from adl_compliance.checks.docs.directory_size import DocsDirectorySize
|
|
47
|
+
from adl_compliance.core.context import Context, FileSet
|
|
48
|
+
from adl_compliance.core.finding import Finding
|
|
49
|
+
from adl_compliance.core.verdict import Outcome
|
|
50
|
+
from adl_compliance.policy.registry import load
|
|
51
|
+
|
|
52
|
+
FIXTURES = pathlib.Path(__file__).parent / "fixtures"
|
|
53
|
+
ROW = load().by_id("DOC-012")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def corpus_files(root: pathlib.Path) -> tuple[str, ...]:
|
|
57
|
+
return tuple(
|
|
58
|
+
sorted(
|
|
59
|
+
str(path.relative_to(root))
|
|
60
|
+
for path in root.rglob("*")
|
|
61
|
+
if path.is_file() and path.name != "grants.yaml"
|
|
62
|
+
)
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def run(case: str, *, register: str = "grants.yaml", cap: str | None = None) -> object:
|
|
67
|
+
directory = FIXTURES / case
|
|
68
|
+
declarations = {} if cap is None else {DocsDirectorySize.PAGES_DECLARATION: cap}
|
|
69
|
+
return runner.run(
|
|
70
|
+
ROW, directory, corpus_files(directory),
|
|
71
|
+
inputs={ROW.id: {"register": directory / register}},
|
|
72
|
+
declarations=declarations,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def findings_for(
|
|
77
|
+
root: pathlib.Path, given: tuple[str, ...], *, cap: str | None = None
|
|
78
|
+
) -> tuple[Finding, ...]:
|
|
79
|
+
"""The check read directly, bypassing row-scope narrowing — the honest way
|
|
80
|
+
to prove the CHECK's own filters (prefix, `.md`, dot-components,
|
|
81
|
+
liveness), which the runner's scope intersection could otherwise be
|
|
82
|
+
mistaken for."""
|
|
83
|
+
declarations = {} if cap is None else {DocsDirectorySize.PAGES_DECLARATION: cap}
|
|
84
|
+
ctx = Context(
|
|
85
|
+
root=root, row=ROW,
|
|
86
|
+
inputs={"register": root / "grants.yaml", "docs_root": root / "docs"},
|
|
87
|
+
declarations=declarations,
|
|
88
|
+
)
|
|
89
|
+
return tuple(DocsDirectorySize().run(ctx, FileSet(paths=given)))
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# ------------------------------------------------------------------ the cap
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_a_tree_within_the_default_cap_passes() -> None:
|
|
96
|
+
"""No declaration, cap 15, every directory well under it."""
|
|
97
|
+
verdict = run("docs-size-clean")
|
|
98
|
+
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
99
|
+
assert not verdict.findings
|
|
100
|
+
assert not verdict.advisories
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def test_a_directory_over_the_default_cap_is_dir_004() -> None:
|
|
104
|
+
verdict = run("docs-size-default-cap")
|
|
105
|
+
assert verdict.outcome is Outcome.FINDINGS
|
|
106
|
+
findings = [f for f in verdict.findings if f.rule == "DIR-004"]
|
|
107
|
+
assert len(findings) == 1, tuple(f.render() for f in verdict.findings)
|
|
108
|
+
finding = findings[0]
|
|
109
|
+
assert finding.path == "docs/guide"
|
|
110
|
+
assert finding.message == "16 pages (max 15), no ratchet entry"
|
|
111
|
+
assert finding.fix == (
|
|
112
|
+
"add a docs_pages baseline entry for docs/guide to the ratchet "
|
|
113
|
+
"register, or split the directory"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_a_declared_cap_wins_over_the_default() -> None:
|
|
118
|
+
"""The same three-page corpus is clean under a declared cap of 3 and
|
|
119
|
+
reported under a declared cap of 2 — the declaration, not the default,
|
|
120
|
+
is the limit in force (no down-only ratchet, same as LAY-014)."""
|
|
121
|
+
assert run("docs-size-over-cap", cap="3").outcome is Outcome.CLEAN
|
|
122
|
+
assert run("docs-size-over-cap", cap="2").outcome is Outcome.FINDINGS
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def test_a_malformed_cap_declaration_is_could_not_run() -> None:
|
|
126
|
+
"""Mirrors LAY-014's `direct_file_limit`: a value that is not a base-10
|
|
127
|
+
positive integer is could-not-run naming
|
|
128
|
+
`[controls.compliance.limits].docs_pages_per_directory`, never a quiet
|
|
129
|
+
fall back to the default."""
|
|
130
|
+
verdict = run("docs-size-over-cap", cap="banana")
|
|
131
|
+
assert verdict.outcome is Outcome.COULD_NOT_RUN
|
|
132
|
+
assert "docs_pages_per_directory" in verdict.message
|
|
133
|
+
verdict = run("docs-size-over-cap", cap="0")
|
|
134
|
+
assert verdict.outcome is Outcome.COULD_NOT_RUN
|
|
135
|
+
assert "docs_pages_per_directory" in verdict.message
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# -------------------------------------------- the register is exemptions only
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def test_an_absent_register_enforces_the_cap_bare() -> None:
|
|
142
|
+
"""REWORKED from v1's `test_an_absent_register_means_nothing_is_ratcheted`,
|
|
143
|
+
which asserted the opposite. Owner ruling 2026-10-02 (v2): the register
|
|
144
|
+
holds EXEMPTIONS, not configuration — if it is not there, no exemptions
|
|
145
|
+
are allowed, so the cap is enforced bare and the over-cap directory
|
|
146
|
+
reports. (v1's "ratchets sit ON TOP" absence-is-clean reading belonged to
|
|
147
|
+
LAY-004, whose configuration IS the register; DOC-012's configuration is
|
|
148
|
+
the declared limit, so absence here grades STRICTER — the widening
|
|
149
|
+
input's normal contract.)"""
|
|
150
|
+
verdict = run("docs-size-over-cap", register="does-not-exist.yaml", cap="2")
|
|
151
|
+
assert verdict.outcome is Outcome.FINDINGS
|
|
152
|
+
findings = [f for f in verdict.findings if f.rule == "DIR-004"]
|
|
153
|
+
assert len(findings) == 1, tuple(f.render() for f in verdict.findings)
|
|
154
|
+
assert findings[0].path == "docs/guide"
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_a_register_without_a_docs_pages_section_enforces_the_cap_bare() -> None:
|
|
158
|
+
"""REWORKED from v1's `test_a_register_without_a_docs_pages_section_passes_clean`,
|
|
159
|
+
which asserted the opposite under the v1 ruling. Same v2 reasoning as the
|
|
160
|
+
absent-register case, one step milder: the register EXISTS and parses —
|
|
161
|
+
it just names no exemptions, so the five-page directory reports against a
|
|
162
|
+
declared cap of 3."""
|
|
163
|
+
verdict = run("docs-size-no-section", cap="3")
|
|
164
|
+
assert verdict.outcome is Outcome.FINDINGS
|
|
165
|
+
findings = [f for f in verdict.findings if f.rule == "DIR-004"]
|
|
166
|
+
assert len(findings) == 1, tuple(f.render() for f in verdict.findings)
|
|
167
|
+
assert findings[0].path == "docs/guide"
|
|
168
|
+
assert findings[0].message == "5 pages (max 3), no ratchet entry"
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def test_a_baseline_entry_exempts_its_directory_up_to_the_recorded_number() -> None:
|
|
172
|
+
"""The exemption channel itself: three pages against a declared cap of 2
|
|
173
|
+
are CLEAN because the register records `docs/guide: 3` — the entry
|
|
174
|
+
forgives the directory up to the count it was recorded at (growing past
|
|
175
|
+
it is DIR-005, reported separately)."""
|
|
176
|
+
verdict = run("docs-size-exempt", cap="2")
|
|
177
|
+
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
178
|
+
assert not verdict.findings
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
# ------------------------------------------------------------------ DIR-004
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def test_an_over_cap_directory_with_no_entry_is_dir_004() -> None:
|
|
185
|
+
verdict = run("docs-size-over-cap", cap="2")
|
|
186
|
+
assert verdict.outcome is Outcome.FINDINGS
|
|
187
|
+
findings = [f for f in verdict.findings if f.rule == "DIR-004"]
|
|
188
|
+
assert len(findings) == 1, tuple(f.render() for f in verdict.findings)
|
|
189
|
+
finding = findings[0]
|
|
190
|
+
assert finding.path == "docs/guide"
|
|
191
|
+
assert finding.message == "3 pages (max 2), no ratchet entry"
|
|
192
|
+
assert finding.fix == (
|
|
193
|
+
"add a docs_pages baseline entry for docs/guide to the ratchet "
|
|
194
|
+
"register, or split the directory"
|
|
195
|
+
)
|
|
196
|
+
assert "docs/short" not in {f.path for f in verdict.findings}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def test_the_register_is_not_a_grant_catalogue() -> None:
|
|
200
|
+
"""`structural_grant = True` forces the allowance to 0 regardless of the
|
|
201
|
+
row's `grants:` field — the same arithmetic LAY-004 pins: the register is
|
|
202
|
+
spent BEFORE counting, never subtracted after."""
|
|
203
|
+
verdict = run("docs-size-over-cap", cap="2")
|
|
204
|
+
assert verdict.granted == 0
|
|
205
|
+
assert verdict.outcome is Outcome.FINDINGS
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# ------------------------------------------------------------------ DIR-005
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def test_a_directory_that_grew_past_its_baseline_is_dir_005() -> None:
|
|
212
|
+
verdict = run("docs-size-grew", cap="2")
|
|
213
|
+
assert verdict.outcome is Outcome.FINDINGS
|
|
214
|
+
findings = [f for f in verdict.findings if f.rule == "DIR-005"]
|
|
215
|
+
assert len(findings) == 1, tuple(f.render() for f in verdict.findings)
|
|
216
|
+
finding = findings[0]
|
|
217
|
+
assert finding.path == "docs/guide"
|
|
218
|
+
assert finding.message == "3 pages (baseline 2)"
|
|
219
|
+
assert finding.fix == (
|
|
220
|
+
"reduce docs/guide back to at most 2 pages, or raise its "
|
|
221
|
+
"docs_pages baseline entry"
|
|
222
|
+
)
|
|
223
|
+
# The entry exists, so DIR-004 must NOT fire alongside DIR-005.
|
|
224
|
+
assert not [f for f in verdict.findings if f.rule == "DIR-004"]
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# ------------------------------------------------------------------ DIR-006
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def test_a_baseline_entry_shrunk_under_the_cap_is_dir_006() -> None:
|
|
231
|
+
verdict = run("docs-size-stale", cap="3")
|
|
232
|
+
stale = [f for f in verdict.findings if f.rule == "DIR-006"]
|
|
233
|
+
assert len(stale) == 2, tuple(f.render() for f in verdict.findings)
|
|
234
|
+
by_path = {f.path: f for f in stale}
|
|
235
|
+
shrunk = by_path["docs/shrunk"]
|
|
236
|
+
assert shrunk.message == "ratchet entry is no longer required"
|
|
237
|
+
assert shrunk.fix == (
|
|
238
|
+
"delete docs/shrunk's stale docs_pages baseline entry from the "
|
|
239
|
+
"ratchet register"
|
|
240
|
+
)
|
|
241
|
+
# The directory-gone case: the entry names a directory the tree no
|
|
242
|
+
# longer holds. Grading ABSENCE, exactly like LAY-004's DIR-003.
|
|
243
|
+
assert "docs/gone" in by_path
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def test_a_still_valid_baseline_entry_is_not_reported() -> None:
|
|
247
|
+
"""`docs/held` holds 4 pages over the declared cap of 3 with a recorded
|
|
248
|
+
baseline of 4 — over the cap but AT its recorded number, so neither
|
|
249
|
+
DIR-004 (the entry exists) nor DIR-005 (it did not grow) fires, and
|
|
250
|
+
DIR-006 must not either (4 is still over the cap, so the entry is
|
|
251
|
+
load-bearing)."""
|
|
252
|
+
verdict = run("docs-size-stale", cap="3")
|
|
253
|
+
assert "docs/held" not in {f.path for f in verdict.findings}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
# ------------------------------------------------------- unusable registers
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def test_a_register_that_exists_but_is_unusable_is_could_not_run() -> None:
|
|
260
|
+
"""The kept exception through both ruling shapes: a register that exists
|
|
261
|
+
but cannot be parsed may be mid-edit; grading it as "no exemptions" would
|
|
262
|
+
silently drop every baseline it names. Could-not-run either way."""
|
|
263
|
+
verdict = run("docs-size-unusable", cap="2")
|
|
264
|
+
assert verdict.outcome is Outcome.COULD_NOT_RUN
|
|
265
|
+
assert "unusable" in verdict.message
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def test_a_register_that_exists_but_is_not_a_file_is_could_not_run() -> None:
|
|
269
|
+
directory = FIXTURES / "docs-size-over-cap"
|
|
270
|
+
verdict = runner.run(
|
|
271
|
+
ROW, directory, corpus_files(directory),
|
|
272
|
+
inputs={ROW.id: {"register": directory}},
|
|
273
|
+
declarations={DocsDirectorySize.PAGES_DECLARATION: "2"},
|
|
274
|
+
)
|
|
275
|
+
assert verdict.outcome is Outcome.COULD_NOT_RUN
|
|
276
|
+
assert "exists but is not a file" in verdict.message
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
# --------------------------------------------------------- the rule's filters
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def test_decisions_is_exempt_at_any_depth() -> None:
|
|
283
|
+
"""The flat ADR log is exempt by rule (owner ruling 2026-10-02, flat by
|
|
284
|
+
design per the docs convention), at the log root and below it. `guide` is
|
|
285
|
+
over the same cap and MUST be reported — without it the corpus would be
|
|
286
|
+
silent by accident."""
|
|
287
|
+
verdict = run("docs-size-decisions", cap="2")
|
|
288
|
+
assert verdict.outcome is Outcome.FINDINGS
|
|
289
|
+
assert {f.path for f in verdict.findings} == {"docs/guide"}
|
|
290
|
+
assert all(f.rule == "DIR-004" for f in verdict.findings)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def test_assets_dotfiles_and_outside_paths_are_not_counted() -> None:
|
|
294
|
+
"""Through the runner: `guide` holds 2 visible pages beside 3 non-`.md`
|
|
295
|
+
assets; counting assets would report it (5 over the declared cap of 3).
|
|
296
|
+
`plans/` and the root `docs.md` never reach the check — the row's scope
|
|
297
|
+
is the runner's business — but they are in the given set, so a check that
|
|
298
|
+
counted them would say so here."""
|
|
299
|
+
verdict = run("docs-size-assets", cap="3")
|
|
300
|
+
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
301
|
+
assert not verdict.findings
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def test_the_check_itself_skips_assets_dotfiles_and_outside_paths() -> None:
|
|
305
|
+
"""Read directly, with the dot-prefixed files the runner may or may not
|
|
306
|
+
hand over: the counted set is `a.md`, `b.md`, `sub/nested.md` — the
|
|
307
|
+
dot-prefixed pages, the assets, the `plans/` tree and the root `docs.md`
|
|
308
|
+
lookalike are all invisible to the rule. Counting any of them would push
|
|
309
|
+
`guide` over the declared cap of 3 and report it."""
|
|
310
|
+
directory = FIXTURES / "docs-size-assets"
|
|
311
|
+
findings = findings_for(directory, corpus_files(directory), cap="3")
|
|
312
|
+
assert findings == (), tuple(f.render() for f in findings)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def test_a_deleted_file_is_not_counted() -> None:
|
|
316
|
+
"""The `is_file` liveness check, LAY-004's discipline: a set may name a
|
|
317
|
+
file this commit deleted. Handed the two live paths and one ghost under a
|
|
318
|
+
declared cap of 2, the count stays at the cap — no finding."""
|
|
319
|
+
directory = FIXTURES / "docs-size-over-cap"
|
|
320
|
+
given = (
|
|
321
|
+
"docs/guide/a.md",
|
|
322
|
+
"docs/guide/b.md",
|
|
323
|
+
"docs/guide/ghost.md", # in the set, deleted from disk
|
|
324
|
+
"docs/short/only.md",
|
|
325
|
+
)
|
|
326
|
+
findings = findings_for(directory, given, cap="2")
|
|
327
|
+
assert findings == (), tuple(f.render() for f in findings)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def test_an_empty_set_grades_nothing() -> None:
|
|
331
|
+
findings = findings_for(FIXTURES / "docs-size-over-cap", (), cap="2")
|
|
332
|
+
assert findings == ()
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
# --------------------------------------------------------------- the wiring
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def test_the_register_is_not_packaged_data() -> None:
|
|
339
|
+
"""The regression guard, same shape as LAY-004's: re-adding a `resources`
|
|
340
|
+
entry here would ship one repository's exemption register to every other
|
|
341
|
+
repository (the K-42 defect)."""
|
|
342
|
+
assert "register" in DocsDirectorySize.inputs
|
|
343
|
+
assert "register" not in DocsDirectorySize.resources
|
|
344
|
+
assert DocsDirectorySize.inputs["register"].startswith("<")
|
|
345
|
+
assert "docs_root" in DocsDirectorySize.inputs
|
|
@@ -190,15 +190,28 @@ class DocsEnglishOnly(Check):
|
|
|
190
190
|
|
|
191
191
|
# ------------------------------------------------------ subject-matter scope
|
|
192
192
|
|
|
193
|
-
def _i18n_owner(self, ctx: Context) -> str:
|
|
194
|
-
|
|
193
|
+
def _i18n_owner(self, ctx: Context) -> str | None:
|
|
194
|
+
# Decision for a tree declared absent (`frontend = ""`, which drops
|
|
195
|
+
# `frontend_src` from the resolved inputs): this input only contributes
|
|
196
|
+
# the i18n OWNER exemption, an extra path that excuses translated strings
|
|
197
|
+
# beneath it. A repository with no frontend tree has no such directory, so
|
|
198
|
+
# there is no exemption to grant -- Han text anywhere is graded by the rule
|
|
199
|
+
# as written, and the generic locale-directory exemption below still
|
|
200
|
+
# applies. This read `ctx.inputs['frontend_src']` unguarded -- a `KeyError`
|
|
201
|
+
# traceback (exit 1), not a verdict, on any file.
|
|
202
|
+
frontend_src = ctx.inputs.get("frontend_src")
|
|
203
|
+
if frontend_src is None:
|
|
204
|
+
return None
|
|
205
|
+
return f"{ctx.relative(frontend_src)}/mobile/src/i18n"
|
|
195
206
|
|
|
196
|
-
def _excluded(self, relative: str, i18n_owner: str) -> bool:
|
|
207
|
+
def _excluded(self, relative: str, i18n_owner: str | None) -> bool:
|
|
197
208
|
# 1. Hidden paths, by decision. Every component is tested.
|
|
198
209
|
if any(part.startswith(".") for part in relative.split("/")):
|
|
199
210
|
return True
|
|
200
|
-
# 2. The one named i18n owner exemption.
|
|
201
|
-
if
|
|
211
|
+
# 2. The one named i18n owner exemption (absent when the frontend tree is).
|
|
212
|
+
if i18n_owner is not None and (
|
|
213
|
+
relative == i18n_owner or relative.startswith(i18n_owner + "/")
|
|
214
|
+
):
|
|
202
215
|
return True
|
|
203
216
|
# 3. Any locale-named data directory, anywhere.
|
|
204
217
|
if self.LOCALE_DIR.search(relative):
|
|
@@ -191,3 +191,38 @@ def test_an_unreadable_office_archive_is_reported_not_silently_skipped(
|
|
|
191
191
|
verdict = graded_directly(tmp_path, ("broken.docx",))
|
|
192
192
|
assert verdict.outcome is Outcome.FINDINGS, verdict.render()
|
|
193
193
|
assert verdict.findings[0].message == "unreadable Office archive on this line"
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def test_a_frontend_tree_declared_absent_leaves_only_the_locale_directory_exemption(
|
|
197
|
+
tmp_path: pathlib.Path,
|
|
198
|
+
) -> None:
|
|
199
|
+
"""`frontend = ""` drops `frontend_src` from the resolved inputs. It only
|
|
200
|
+
contributes the i18n OWNER exemption (an extra path), so absent that
|
|
201
|
+
exemption does not exist -- but the generic locale-directory exemption
|
|
202
|
+
still does, and Han text elsewhere is still reported. This was a
|
|
203
|
+
`KeyError: 'frontend_src'` traceback (exit 1) on any file, measured against
|
|
204
|
+
enact-combined with `--tree rust= --tree frontend=`."""
|
|
205
|
+
(tmp_path / "src").mkdir()
|
|
206
|
+
(tmp_path / "src" / "page.ts").write_text("const label = '一'\n", encoding="utf-8")
|
|
207
|
+
(tmp_path / "web" / "mobile" / "src" / "i18n").mkdir(parents=True)
|
|
208
|
+
(tmp_path / "web" / "mobile" / "src" / "i18n" / "strings.ts").write_text(
|
|
209
|
+
"export const label = '一'\n", encoding="utf-8"
|
|
210
|
+
)
|
|
211
|
+
(tmp_path / "web" / "i18n" / "locales" / "zh-CN").mkdir(parents=True)
|
|
212
|
+
(tmp_path / "web" / "i18n" / "locales" / "zh-CN" / "strings.ts").write_text(
|
|
213
|
+
"export const label = '一'\n", encoding="utf-8"
|
|
214
|
+
)
|
|
215
|
+
ctx = Context(root=tmp_path, row=ROW)
|
|
216
|
+
findings = tuple(
|
|
217
|
+
DocsEnglishOnly().graded(
|
|
218
|
+
ctx,
|
|
219
|
+
FileSet(
|
|
220
|
+
paths=(
|
|
221
|
+
"src/page.ts",
|
|
222
|
+
"web/mobile/src/i18n/strings.ts",
|
|
223
|
+
"web/i18n/locales/zh-CN/strings.ts",
|
|
224
|
+
)
|
|
225
|
+
),
|
|
226
|
+
)
|
|
227
|
+
)
|
|
228
|
+
assert sorted(f.path for f in findings) == ["src/page.ts", "web/mobile/src/i18n/strings.ts"], findings
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""DOC-011 -- every Markdown page under `docs/` has a lower-kebab stem.
|
|
2
|
+
|
|
3
|
+
The rule this gate grades, stated in full:
|
|
4
|
+
|
|
5
|
+
For every `.md` file in scope, the filename stem must full-match
|
|
6
|
+
`^[a-z0-9]+(-[a-z0-9]+)*$` -- lower-kebab: runs of `[a-z0-9]` joined by
|
|
7
|
+
single hyphens, nothing else. Exact-name exemptions: `AGENTS.md` and
|
|
8
|
+
`CLAUDE.md`, the standing tree-guide names the other docs gates exclude
|
|
9
|
+
from grading too (DOC-006's scope carries them; `layout.agents-layout`
|
|
10
|
+
governs them). Non-`.md` files are NOT graded: docs trees legitimately
|
|
11
|
+
hold `.png`/`.html`/`.csv`/`.yaml` assets, and the rule is about page
|
|
12
|
+
names, not asset names -- a `UI-CONTRACT.png` beside a fixed
|
|
13
|
+
`UI-CONTRACT.md` is not a finding.
|
|
14
|
+
|
|
15
|
+
The row's scope mirrors DOC-006 (`docs.okf-profile`) exactly -- `<docs>/**`
|
|
16
|
+
with the same `proposals/`, `compliance/`, guide, and `index.md` excludes --
|
|
17
|
+
so both docs/ content gates walk the same tree (see the registry row's
|
|
18
|
+
comment for the carried-over rationale).
|
|
19
|
+
|
|
20
|
+
SCOPE OF THE RULE, DECIDED 2026-10-02 (orchestrator correction): an earlier
|
|
21
|
+
shape of this gate enforced ADR naming (`adr-<NNN>-<slug>.md`) over
|
|
22
|
+
`<docs>/decisions/**`; that reading invented a rule the brief did not carry.
|
|
23
|
+
This gate is the kebab-stem rule above; ADR naming may become its own gate
|
|
24
|
+
later and is deliberately not graded here -- every well-formed ADR name
|
|
25
|
+
(`adr-001-organization-workspace-tenancy.md`) is kebab-conforming anyway,
|
|
26
|
+
so the two rules only diverge on legacy prose names, which this gate reports
|
|
27
|
+
by the kebab rule wherever they sit under docs/.
|
|
28
|
+
|
|
29
|
+
There is no `structural` half, the same call DOC-010 (`docs.closed-set`)
|
|
30
|
+
makes: every rule here is answered from the GIVEN SET, and a repository
|
|
31
|
+
whose docs/ tree holds no `.md` page is permitted, not failing.
|
|
32
|
+
|
|
33
|
+
The check-level filters, in order: the path must sit under the resolved
|
|
34
|
+
`docs_root` (a lookalike `docs.md` beside the tree is outside it), the file
|
|
35
|
+
must be `.md`, and the basename must not be one of the two exempt guide
|
|
36
|
+
names. The row's scope excludes (`proposals/`, `compliance/`, guides,
|
|
37
|
+
`index.md`) are the runner's narrowing; the guide-name exemption is repeated
|
|
38
|
+
here because it is a property of the RULE (a name may not be lower-kebab and
|
|
39
|
+
still be correct), not of one scope.
|
|
40
|
+
|
|
41
|
+
Like DOC-010, `docs_root` is read straight from `ctx.inputs` -- a missing
|
|
42
|
+
docs tree is a misconfiguration this gate has no lenient mode for, and
|
|
43
|
+
adl-azdo declares `docs = "docs"`.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
from __future__ import annotations
|
|
47
|
+
|
|
48
|
+
import re
|
|
49
|
+
from collections.abc import Iterable
|
|
50
|
+
from typing import ClassVar
|
|
51
|
+
|
|
52
|
+
from ....core.check import Check
|
|
53
|
+
from ....core.context import Context, FileSet
|
|
54
|
+
from ....core.finding import Report
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class DocsFilename(Check):
|
|
58
|
+
id: ClassVar[str] = "DOC-011"
|
|
59
|
+
rule: ClassVar[str] = "DOC-011"
|
|
60
|
+
|
|
61
|
+
inputs: ClassVar[dict[str, str]] = {"docs_root": "<docs>"}
|
|
62
|
+
"""The same named input DOC-001 and DOC-010 declare for the same reason
|
|
63
|
+
(K-42: a hardcoded `"docs"` literal silently drops every page when a
|
|
64
|
+
repository names its documentation tree something else)."""
|
|
65
|
+
|
|
66
|
+
KEBAB: ClassVar[re.Pattern[str]] = re.compile(r"[a-z0-9]+(?:-[a-z0-9]+)*")
|
|
67
|
+
"""The stem grammar, anchored by `fullmatch`: one or more runs of
|
|
68
|
+
`[a-z0-9]`, single-hyphen joined. Uppercase, underscores, spaces,
|
|
69
|
+
leading/trailing/double hyphens all fail the full match."""
|
|
70
|
+
|
|
71
|
+
GUIDE_NAMES: ClassVar[frozenset[str]] = frozenset({"AGENTS.md", "CLAUDE.md"})
|
|
72
|
+
"""The standing tree-guide names, exempt by exact basename at any depth
|
|
73
|
+
-- the rule-level pair to the scope excludes the row carries."""
|
|
74
|
+
|
|
75
|
+
def graded(self, ctx: Context, files: FileSet) -> Iterable[Report]:
|
|
76
|
+
docs_root = ctx.relative(ctx.inputs["docs_root"])
|
|
77
|
+
prefix = f"{docs_root}/"
|
|
78
|
+
for path in files:
|
|
79
|
+
if not path.startswith(prefix):
|
|
80
|
+
continue
|
|
81
|
+
name = path.rsplit("/", 1)[-1]
|
|
82
|
+
if not name.endswith(".md") or name in self.GUIDE_NAMES:
|
|
83
|
+
continue
|
|
84
|
+
stem = name[: -len(".md")]
|
|
85
|
+
if not self.KEBAB.fullmatch(stem):
|
|
86
|
+
yield self.report(
|
|
87
|
+
path,
|
|
88
|
+
f"{stem} is not lower-kebab ([a-z0-9]+(-[a-z0-9]+)*)",
|
|
89
|
+
f"rename {path} so the stem is lower-kebab -- words of "
|
|
90
|
+
"[a-z0-9] joined by single hyphens",
|
|
91
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
PNG asset placeholder; non-Markdown files are not graded.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<!doctype html><title>reference</title>
|