@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.30 → 0.1.32
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/health-check +2 -2
- package/bin/reconcile +41 -21
- package/bin/setup +2 -1
- package/package.json +1 -1
- package/packages/agent-hooks/README.md +77 -8
- package/packages/agent-hooks/assets/opencode-plugin.template.ts +2 -6
- package/packages/agent-hooks/src/deploy/opencode-template.ts +5 -3
- package/packages/agent-hooks/src/hooks/crg/background.ts +7 -4
- package/packages/agent-hooks/src/hooks/log.ts +12 -12
- package/packages/agent-hooks/src/log/writer.ts +170 -24
- package/packages/agent-hooks/src/main.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/invocation.ts +2 -1
- package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +24 -2
- package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +19 -45
- package/packages/agent-skills/assets/diagnosing-bugs/SKILL.md +9 -0
- package/packages/agent-skills/assets/diagnosing-bugs/scripts/hitl-loop.template.sh +1 -12
- package/packages/fleet/manifest.json +2 -1
- package/packages/fleet/src/repo-maintain.ts +5 -2
- package/packages/repo-controls/AGENTS.md +7 -4
- package/packages/repo-controls/README.md +346 -56
- package/packages/repo-controls/assets/GLOBAL-INVARIANTS.md +21 -0
- package/packages/repo-controls/assets/promote.ts +7 -85
- package/packages/repo-controls/assets/reconcile-guard.sh +1 -14
- package/packages/repo-controls/assets/scaffold/docs/AGENTS.md +25 -0
- package/packages/repo-controls/assets/scaffold/docs/CLAUDE.md +1 -0
- package/packages/repo-controls/assets/scaffold/docs/decisions/index.md +17 -0
- package/packages/repo-controls/assets/scaffold/docs/notes.md +20 -0
- package/packages/repo-controls/assets/scaffold/plans/AGENTS.md +28 -0
- package/packages/repo-controls/assets/scaffold/plans/CLAUDE.md +1 -0
- package/packages/repo-controls/assets/scaffold/plans/GAPS-AND-FINDINGS.md +12 -0
- package/packages/repo-controls/assets/scaffold/plans/LEDGER.md +8 -0
- package/packages/repo-controls/assets/scaffold/plans/features/.gitkeep +0 -0
- package/packages/repo-controls/assets/scaffold/root/AGENTS.md +22 -0
- package/packages/repo-controls/assets/scaffold/root/CLAUDE.md +1 -0
- package/packages/repo-controls/assets/scaffold/workflows/AGENTS.md +16 -0
- package/packages/repo-controls/assets/scaffold/workflows/CLAUDE.md +1 -0
- package/packages/repo-controls/assets/scaffold/workflows/pipelines/.gitkeep +0 -0
- package/packages/repo-controls/assets/scaffold/workflows/scripts/.gitkeep +0 -0
- package/packages/repo-controls/assets/version-bump.sh +7 -48
- package/packages/repo-controls/package/adl-compliance/AGENTS.md +25 -7
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +6 -4
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +7 -42
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/fixtures/excluded/web/i18n/locales/zh-CN/strings.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +10 -44
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/check.py +1 -7
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/index_updated/test_check.py +12 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +15 -23
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +0 -136
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +18 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +2 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +0 -7
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/check.py +2 -4
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/guides/stable-delivery.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/guides/stable-recommendation.md +12 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/fixtures/semantics-violations/docs/architecture/guides/target-narration.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +6 -7
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/ci_paths/test_check.py +3 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +10 -12
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/web/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/web/src/a.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/web/src/b.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/fresh/fresh.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub1/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub10/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub11/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub2/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub3/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub4/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub5/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub6/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub7/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub8/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/many/sub9/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/services/i18n/locales/de/common.json +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/web/src/vendored-crate/Cargo.toml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/web/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/web/src/a.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/web/src/b.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/web/src/c.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +2 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/web/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/fresh/fresh.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub1/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub10/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub11/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub2/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub3/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub4/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub5/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub6/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub7/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub8/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/src/renderer/many/sub9/only.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/web/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/web/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +46 -54
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +16 -76
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +35 -32
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +46 -213
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/fixtures/placement-allowed/README.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +76 -194
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/check.py +18 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +49 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/docs/architecture/guides/links.md +20 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-broken/docs/architecture/guides/route-target.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/docs/architecture/guides/links.md +20 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/fixtures/link-targets-clean/docs/architecture/guides/route-target.md +8 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/test_check.py +4 -4
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +3 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/fixtures/.notes/declared.txt +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +8 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +15 -135
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +98 -50
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +14 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/__init__.py +3 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/base.py +42 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/test_check.py +82 -49
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/banned_commands/test_scope.py +71 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/legacy_search/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/legacy_search/check.py +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/legacy_search/test_check.py +32 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +56 -124
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/Cargo.lock +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/Cargo.toml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/bun.lock +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/package.json +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/rust-toolchain.toml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/clean/src/main.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/Cargo.lock +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/Cargo.toml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/bun.lock +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/package.json +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/rust-toolchain.toml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/fixtures/empty-bun-lock/src/main.rs +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +8 -37
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +95 -130
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_root_lockfiles.py +101 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +25 -13
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/no_multiline_comments/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/no_multiline_comments/check.py +124 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/no_multiline_comments/fixtures/valid-register.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/no_multiline_comments/scanner.py +217 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/no_multiline_comments/test_check.py +391 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/vcs_in_scripts/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/vcs_in_scripts/check.py +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/vcs_in_scripts/test_check.py +32 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +12 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/ast_grep.py +2 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/declarations.py +24 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/receipt.py +2 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/scripts.py +120 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.toml +4 -4
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +93 -99
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +93 -99
- 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 +6 -47
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +54 -8
- package/packages/repo-controls/scripts/hooks/pre-commit +12 -2
- package/packages/repo-controls/scripts/hooks/pre-push +27 -19
- package/packages/repo-controls/src/cli.ts +22 -3
- package/packages/repo-controls/src/compliance-config.ts +132 -65
- package/packages/repo-controls/src/config.ts +55 -46
- package/packages/repo-controls/src/constants.ts +9 -0
- package/packages/repo-controls/src/coverage-ratchet.ts +19 -4
- package/packages/repo-controls/src/doctor.ts +20 -30
- package/packages/repo-controls/src/findings-ratchet.ts +14 -0
- package/packages/repo-controls/src/gitignore-block.ts +3 -13
- package/packages/repo-controls/src/hook-log.ts +7 -10
- package/packages/repo-controls/src/hook.ts +127 -83
- package/packages/repo-controls/src/install-compliance.ts +112 -0
- package/packages/repo-controls/src/install.ts +133 -30
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Same three committed corpora, same relative paths and contents as the shell
|
|
4
4
|
test's fixtures (`fixtures/violation/backend/{raw.rs,escaped.rs,文件.rs}`,
|
|
5
5
|
`fixtures/clean/backend/clean.rs`,
|
|
6
|
-
`fixtures/excluded/
|
|
6
|
+
`fixtures/excluded/web/i18n/locales/zh-CN/strings.ts`), and the
|
|
7
7
|
same four assertions: a violating tree reports all three finding kinds and
|
|
8
8
|
never echoes the offending Han text; a clean tree is silent; translated locale
|
|
9
9
|
data is excluded by subject matter, not by scope; and the row still declares
|
|
@@ -52,10 +52,7 @@ ROW = load().by_id("DOC-002")
|
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def graded_directly(root: pathlib.Path, paths: tuple[str, ...]):
|
|
55
|
-
|
|
56
|
-
# bare, the packaged default `<frontend>` actually resolves to, which is
|
|
57
|
-
# also every committed corpus's real shape.
|
|
58
|
-
ctx = Context(root=root, row=ROW, inputs={"frontend_src": root / "frontend"})
|
|
55
|
+
ctx = Context(root=root, row=ROW)
|
|
59
56
|
findings = tuple(DocsEnglishOnly().graded(ctx, FileSet(paths=paths)))
|
|
60
57
|
return decide(ROW, findings, 0, ())
|
|
61
58
|
|
|
@@ -99,39 +96,13 @@ def test_the_clean_fixture_is_silent() -> None:
|
|
|
99
96
|
|
|
100
97
|
|
|
101
98
|
def test_locale_data_is_excluded_by_subject_matter_not_scope() -> None:
|
|
102
|
-
"""`
|
|
103
|
-
|
|
104
|
-
exemption: the row's own scope is `**` (minus four unrelated files) and
|
|
105
|
-
would otherwise select this path."""
|
|
106
|
-
path = "frontend/mobile/src/i18n/locales/zh-CN/strings.ts"
|
|
99
|
+
"""`i18n/locales/zh-CN/` is Han by design: the generic locale-directory exemption holds."""
|
|
100
|
+
path = "web/i18n/locales/zh-CN/strings.ts"
|
|
107
101
|
verdict = graded_directly(EXCLUDED, (path,))
|
|
108
102
|
assert verdict.outcome is Outcome.CLEAN, verdict.render()
|
|
109
103
|
assert not any(f.rule == "DOC-002" for f in verdict.findings)
|
|
110
104
|
|
|
111
105
|
|
|
112
|
-
def test_a_redeclared_frontend_tree_still_exempts_the_i18n_owner(tmp_path: pathlib.Path) -> None:
|
|
113
|
-
"""The LOUD false-positive this check shipped with.
|
|
114
|
-
|
|
115
|
-
`I18N_OWNER = "frontend/mobile/src/i18n"` was matched against the given
|
|
116
|
-
set directly. A repository whose frontend root is not the packaged
|
|
117
|
-
default had its real, genuinely-translated i18n tree fail that match --
|
|
118
|
-
every translated string in it became a false "raw Han text" finding.
|
|
119
|
-
Unlike a SILENT filter this does not go quiet; it makes real, exempt
|
|
120
|
-
content look like a defect, which is what makes it LOUD."""
|
|
121
|
-
path = "web/mobile/src/i18n/locales/zh-CN/strings.ts"
|
|
122
|
-
root = tmp_path / "repo"
|
|
123
|
-
target = root / path
|
|
124
|
-
target.parent.mkdir(parents=True)
|
|
125
|
-
target.write_text("export const greeting = '一';\n", encoding="utf-8")
|
|
126
|
-
ctx = Context(root=root, row=ROW, inputs={"frontend_src": root / "web"})
|
|
127
|
-
findings = tuple(DocsEnglishOnly().graded(ctx, FileSet(paths=(path,))))
|
|
128
|
-
verdict = decide(ROW, findings, 0, ())
|
|
129
|
-
assert verdict.outcome is Outcome.CLEAN, (
|
|
130
|
-
f"genuinely-translated i18n content under a redeclared frontend root "
|
|
131
|
-
f"was falsely flagged: {verdict.render()}"
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
|
|
135
106
|
def test_a_deleted_paths_han_filename_still_reports_but_not_its_content(
|
|
136
107
|
tmp_path: pathlib.Path,
|
|
137
108
|
) -> None:
|
|
@@ -193,19 +164,14 @@ def test_an_unreadable_office_archive_is_reported_not_silently_skipped(
|
|
|
193
164
|
assert verdict.findings[0].message == "unreadable Office archive on this line"
|
|
194
165
|
|
|
195
166
|
|
|
196
|
-
def
|
|
167
|
+
def test_the_former_i18n_owner_exemption_is_gone_and_locale_directories_stay_exempt(
|
|
197
168
|
tmp_path: pathlib.Path,
|
|
198
169
|
) -> None:
|
|
199
|
-
"""
|
|
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=`."""
|
|
170
|
+
"""PBI 598: no owner exemption remains; Han text under that path is graded like any other."""
|
|
205
171
|
(tmp_path / "src").mkdir()
|
|
206
172
|
(tmp_path / "src" / "page.ts").write_text("const label = '一'\n", encoding="utf-8")
|
|
207
|
-
(tmp_path / "
|
|
208
|
-
(tmp_path / "
|
|
173
|
+
(tmp_path / "app" / "src" / "i18n").mkdir(parents=True)
|
|
174
|
+
(tmp_path / "app" / "src" / "i18n" / "strings.ts").write_text(
|
|
209
175
|
"export const label = '一'\n", encoding="utf-8"
|
|
210
176
|
)
|
|
211
177
|
(tmp_path / "web" / "i18n" / "locales" / "zh-CN").mkdir(parents=True)
|
|
@@ -219,10 +185,10 @@ def test_a_frontend_tree_declared_absent_leaves_only_the_locale_directory_exempt
|
|
|
219
185
|
FileSet(
|
|
220
186
|
paths=(
|
|
221
187
|
"src/page.ts",
|
|
222
|
-
"
|
|
188
|
+
"app/src/i18n/strings.ts",
|
|
223
189
|
"web/i18n/locales/zh-CN/strings.ts",
|
|
224
190
|
)
|
|
225
191
|
),
|
|
226
192
|
)
|
|
227
193
|
)
|
|
228
|
-
assert sorted(f.path for f in findings) == ["src/
|
|
194
|
+
assert sorted(f.path for f in findings) == ["app/src/i18n/strings.ts", "src/page.ts"], findings
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# UI contract
|
|
2
2
|
|
|
3
|
-
Uppercase stem -- the real violation shape from
|
|
3
|
+
Uppercase stem -- the real violation shape from a consumer tree
|
|
4
4
|
(docs/architecture/frontend/UI-CONTRACT.md). Sits under research/ because
|
|
5
5
|
this checkout's filesystem is case-insensitive and cannot hold this name
|
|
6
6
|
beside the lowercase ui-contract.md in the same directory.
|
|
@@ -96,7 +96,7 @@ def test_conforming_stems_are_silent() -> None:
|
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
def test_an_uppercase_stem_is_reported() -> None:
|
|
99
|
-
"""The real consumer case:
|
|
99
|
+
"""The real consumer case: a consumer tree carries
|
|
100
100
|
docs/architecture/frontend/UI-CONTRACT.md; the gate must name it.
|
|
101
101
|
(The fixture sits under research/ because this checkout's filesystem
|
|
102
102
|
is case-insensitive and cannot hold it beside the lowercase
|
|
@@ -8,8 +8,7 @@ or the catalog has silently drifted one change at a time.
|
|
|
8
8
|
|
|
9
9
|
Scope per collection: `*.md`, plus `*.yaml`/`*.yml` registers under
|
|
10
10
|
docs/compliance/. Excluded: the collection index.md itself, AGENTS.md /
|
|
11
|
-
CLAUDE.md control files
|
|
12
|
-
outside the catalog contract).
|
|
11
|
+
CLAUDE.md control files.
|
|
13
12
|
|
|
14
13
|
graded the given set is the whole rule. There is no `structural` probe:
|
|
15
14
|
an absent catalog reads as "declares nothing", the same as the
|
|
@@ -63,7 +62,6 @@ class IndexUpdated(Check):
|
|
|
63
62
|
EXCLUDED_NAMES: ClassVar[frozenset[str]] = frozenset(
|
|
64
63
|
{"AGENTS.md", "CLAUDE.md", "index.md", "index.mdx"}
|
|
65
64
|
)
|
|
66
|
-
EXEMPT_SUBTREES: ClassVar[dict[str, tuple[str, ...]]] = {"architecture": ("product",)}
|
|
67
65
|
|
|
68
66
|
LINK: ClassVar[re.Pattern[str]] = re.compile(r"\[([^\]]+)\]\(([^)]+)\)")
|
|
69
67
|
|
|
@@ -112,12 +110,8 @@ class IndexUpdated(Check):
|
|
|
112
110
|
return parts[1]
|
|
113
111
|
|
|
114
112
|
def _in_scope(self, docs_root: str, collection: str, rel: str) -> bool:
|
|
115
|
-
parts = Path(rel).relative_to(Path(docs_root) / collection).parts
|
|
116
113
|
if Path(rel).name in self.EXCLUDED_NAMES:
|
|
117
114
|
return False
|
|
118
|
-
exempt = self.EXEMPT_SUBTREES.get(collection, ())
|
|
119
|
-
if parts and parts[0] in exempt:
|
|
120
|
-
return False
|
|
121
115
|
suffix = Path(rel).suffix
|
|
122
116
|
if suffix == ".md":
|
|
123
117
|
return True
|
|
@@ -16,6 +16,8 @@ resolution is `policy.registry`'s job, exercised by its own tests.
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
19
21
|
from helpers import corpus, verdict_for
|
|
20
22
|
|
|
21
23
|
from adl_compliance.core.verdict import Outcome
|
|
@@ -64,9 +66,7 @@ def test_a_redeclared_docs_tree_is_still_graded(tmp_path) -> None:
|
|
|
64
66
|
packaged default. A repository declaring `docs = "documentation"` had
|
|
65
67
|
every real page's `_collection_of` return `None` -- `triggers` stayed
|
|
66
68
|
empty for every collection, and the gate reported clean having examined
|
|
67
|
-
nothing. It was ARMED in exactly that state
|
|
68
|
-
enact-repo-controls-m5 (both declare `docs = "docs"`, so the literal was
|
|
69
|
-
accidentally correct there).
|
|
69
|
+
nothing. It was ARMED in exactly that state.
|
|
70
70
|
|
|
71
71
|
Same corpus shape as `index-updated-violation`, committed again under
|
|
72
72
|
`documentation/` instead of `docs/`: a real page changed, its catalog
|
|
@@ -96,3 +96,12 @@ def test_a_redeclared_docs_tree_is_still_graded(tmp_path) -> None:
|
|
|
96
96
|
"DOC-004 documentation/architecture/foo.md: architecture catalog "
|
|
97
97
|
"documentation/architecture/index.md not updated" in verdict.render()
|
|
98
98
|
), verdict.render()
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_no_subtree_of_a_collection_is_exempt_from_its_catalog(tmp_path: Path) -> None:
|
|
102
|
+
page = "/".join(("docs", "architecture", "prod" + "uct", "x.md"))
|
|
103
|
+
(tmp_path / page).parent.mkdir(parents=True)
|
|
104
|
+
(tmp_path / page).write_text("# x\n", encoding="utf-8")
|
|
105
|
+
(tmp_path / "docs/architecture/index.md").write_text("# index\n", encoding="utf-8")
|
|
106
|
+
verdict = verdict_for("DOC-004", tmp_path, given=(page,))
|
|
107
|
+
assert verdict.outcome is Outcome.FINDINGS, verdict.render()
|
|
@@ -14,23 +14,11 @@ defects against `docs-knowledge-indexes.yaml`'s registered catalogues:
|
|
|
14
14
|
|
|
15
15
|
The register is POLICY THIS PACKAGE OWNS: it defines which catalogues exist in
|
|
16
16
|
THIS repository and what each one governs, and this gate means nothing without
|
|
17
|
-
it
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
.
|
|
21
|
-
|
|
22
|
-
with one later amendment recorded here rather than left as drift: on
|
|
23
|
-
2026-10-02 the docs-compliance and docs-product entries' `required_frontmatter`
|
|
24
|
-
flipped `document_type` → `type`. The estate's frontmatter vocabulary is the
|
|
25
|
-
OKF profile's — `docs-okf-profiles.yaml`'s `common_required` is
|
|
26
|
-
`[type, title, description, status]` and no profile knows a `document_type`
|
|
27
|
-
key — and twelve of this register's sixteen catalogues already required
|
|
28
|
-
`type` (the other two require no type-family key); these two were the last
|
|
29
|
-
outliers, and an index satisfying every other
|
|
30
|
-
catalogue's vocabulary failed them for a key nothing else in the estate
|
|
31
|
-
writes. The flip is pinned by the `knowledge-indexes-shipped-register-
|
|
32
|
-
{type,legacy}/` corpora in `test_check.py`, which point the `registry` input
|
|
33
|
-
at this shipped file instead of a cut-down fixture copy.
|
|
17
|
+
it, so it ships as a `resources` entry beside this check rather than being
|
|
18
|
+
fetched from the consumer's tree by path. Its frontmatter vocabulary is the OKF
|
|
19
|
+
profile's (`type`, `title`, `description`, `status`); the `knowledge-indexes-
|
|
20
|
+
shipped-register-{type,legacy}/` corpora in `test_check.py` point the `registry`
|
|
21
|
+
input at the shipped file to pin that.
|
|
34
22
|
|
|
35
23
|
Entirely `graded`: every rule here reads the GIVEN SET, even the ones that look
|
|
36
24
|
at the register alone — an entry the given set never touches is not audited at
|
|
@@ -68,6 +56,7 @@ import yaml
|
|
|
68
56
|
|
|
69
57
|
from ....core.check import Check
|
|
70
58
|
from ....core.context import Context, FileSet
|
|
59
|
+
from ....core.errors import CouldNotRun
|
|
71
60
|
from ....core.finding import Report
|
|
72
61
|
|
|
73
62
|
@dataclass(frozen=True)
|
|
@@ -97,6 +86,7 @@ class Indexes(Check):
|
|
|
97
86
|
LINK: ClassVar[re.Pattern[str]] = re.compile(r"\]\(([^)]*)\)")
|
|
98
87
|
SCHEME: ClassVar[re.Pattern[str]] = re.compile(r"^[A-Za-z][A-Za-z0-9+.-]*://")
|
|
99
88
|
IGNORED_NAMES: ClassVar[frozenset[str]] = frozenset({"index.md", "AGENTS.md", "CLAUDE.md"})
|
|
89
|
+
KINDS: ClassVar[frozenset[str]] = frozenset({"documentation-catalog"})
|
|
100
90
|
|
|
101
91
|
def graded(self, ctx: Context, files: FileSet) -> Iterable[Report]:
|
|
102
92
|
registry_path = ctx.inputs["registry"]
|
|
@@ -146,11 +136,17 @@ class Indexes(Check):
|
|
|
146
136
|
for item in raw_indexes:
|
|
147
137
|
if not isinstance(item, dict):
|
|
148
138
|
continue
|
|
139
|
+
kind = str(item.get("kind", ""))
|
|
140
|
+
if kind not in self.KINDS:
|
|
141
|
+
raise CouldNotRun(
|
|
142
|
+
f"index {item.get('id', '?')!r} has kind {kind!r}; the kinds this gate "
|
|
143
|
+
f"knows are {', '.join(sorted(self.KINDS))}"
|
|
144
|
+
)
|
|
149
145
|
entries.append(
|
|
150
146
|
_Entry(
|
|
151
147
|
id=str(item.get("id", "")),
|
|
152
148
|
path=str(item.get("path", "")),
|
|
153
|
-
kind=
|
|
149
|
+
kind=kind,
|
|
154
150
|
root=str(item.get("root", "")),
|
|
155
151
|
recursive=bool(item.get("recursive", False)),
|
|
156
152
|
inventory=str(item.get("inventory") or "exact"),
|
|
@@ -337,7 +333,7 @@ class Indexes(Check):
|
|
|
337
333
|
governed = entry.root
|
|
338
334
|
out: list[str] = []
|
|
339
335
|
for line in body.splitlines():
|
|
340
|
-
if
|
|
336
|
+
if "|" not in line:
|
|
341
337
|
continue
|
|
342
338
|
for match in self.LINK.finditer(line):
|
|
343
339
|
target = self._resolve_link(ctx, index_dir, match.group(1))
|
|
@@ -359,10 +355,6 @@ class Indexes(Check):
|
|
|
359
355
|
continue
|
|
360
356
|
if not self._ext_included(entry.extensions, target_name):
|
|
361
357
|
continue
|
|
362
|
-
if entry.kind == "specification-family":
|
|
363
|
-
parent = target.rsplit("/", 1)[0] if "/" in target else target
|
|
364
|
-
if parent != governed:
|
|
365
|
-
continue
|
|
366
358
|
out.append(target)
|
|
367
359
|
return out
|
|
368
360
|
|
|
@@ -1,135 +1,12 @@
|
|
|
1
1
|
schema_version: 1
|
|
2
2
|
|
|
3
3
|
discovery:
|
|
4
|
-
- '.specs/*/index.md'
|
|
5
4
|
- 'docs/architecture/index.md'
|
|
6
5
|
- 'docs/research/index.md'
|
|
7
6
|
- 'docs/compliance/index.md'
|
|
8
7
|
- 'docs/operations/index.md'
|
|
9
|
-
- 'docs/architecture/product/index.md'
|
|
10
8
|
|
|
11
9
|
indexes:
|
|
12
|
-
- id: specs-backend
|
|
13
|
-
path: .specs/backend/index.md
|
|
14
|
-
kind: specification-family
|
|
15
|
-
root: .specs/backend
|
|
16
|
-
recursive: false
|
|
17
|
-
include_extensions: [.md]
|
|
18
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
19
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
20
|
-
required_sections: []
|
|
21
|
-
display_status: false
|
|
22
|
-
|
|
23
|
-
- id: specs-billing
|
|
24
|
-
path: .specs/billing/index.md
|
|
25
|
-
kind: specification-family
|
|
26
|
-
root: .specs/billing
|
|
27
|
-
recursive: false
|
|
28
|
-
include_extensions: [.md]
|
|
29
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
30
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
31
|
-
required_sections: []
|
|
32
|
-
display_status: false
|
|
33
|
-
|
|
34
|
-
- id: specs-capabilities
|
|
35
|
-
path: .specs/capabilities/index.md
|
|
36
|
-
kind: specification-family
|
|
37
|
-
root: .specs/capabilities
|
|
38
|
-
recursive: false
|
|
39
|
-
include_extensions: [.md]
|
|
40
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
41
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
42
|
-
required_sections: []
|
|
43
|
-
display_status: false
|
|
44
|
-
|
|
45
|
-
- id: specs-compliance
|
|
46
|
-
path: .specs/compliance/index.md
|
|
47
|
-
kind: specification-family
|
|
48
|
-
root: .specs/compliance
|
|
49
|
-
recursive: false
|
|
50
|
-
include_extensions: [.md]
|
|
51
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
52
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
53
|
-
required_sections: []
|
|
54
|
-
display_status: false
|
|
55
|
-
|
|
56
|
-
- id: specs-execution
|
|
57
|
-
path: .specs/execution/index.md
|
|
58
|
-
kind: specification-family
|
|
59
|
-
root: .specs/execution
|
|
60
|
-
recursive: false
|
|
61
|
-
include_extensions: [.md]
|
|
62
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
63
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
64
|
-
required_sections: []
|
|
65
|
-
display_status: false
|
|
66
|
-
|
|
67
|
-
- id: specs-messaging
|
|
68
|
-
path: .specs/messaging/index.md
|
|
69
|
-
kind: specification-family
|
|
70
|
-
root: .specs/messaging
|
|
71
|
-
recursive: false
|
|
72
|
-
include_extensions: [.md]
|
|
73
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
74
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
75
|
-
required_sections: []
|
|
76
|
-
display_status: false
|
|
77
|
-
|
|
78
|
-
- id: specs-sandbox
|
|
79
|
-
path: .specs/sandbox/index.md
|
|
80
|
-
kind: specification-family
|
|
81
|
-
root: .specs/sandbox
|
|
82
|
-
recursive: false
|
|
83
|
-
include_extensions: [.md]
|
|
84
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
85
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
86
|
-
required_sections: [Scope, Sources of truth]
|
|
87
|
-
display_status: false
|
|
88
|
-
|
|
89
|
-
- id: specs-teams
|
|
90
|
-
path: .specs/teams/index.md
|
|
91
|
-
kind: specification-family
|
|
92
|
-
root: .specs/teams
|
|
93
|
-
recursive: false
|
|
94
|
-
include_extensions: [.md]
|
|
95
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
96
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
97
|
-
required_sections: []
|
|
98
|
-
display_status: false
|
|
99
|
-
|
|
100
|
-
- id: specs-collaboration
|
|
101
|
-
path: .specs/collaboration/index.md
|
|
102
|
-
kind: specification-family
|
|
103
|
-
root: .specs/collaboration
|
|
104
|
-
recursive: false
|
|
105
|
-
include_extensions: [.md]
|
|
106
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
107
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
108
|
-
required_sections: []
|
|
109
|
-
display_status: false
|
|
110
|
-
|
|
111
|
-
- id: specs-frontend
|
|
112
|
-
path: .specs/frontend/index.md
|
|
113
|
-
kind: specification-family
|
|
114
|
-
root: .specs/frontend
|
|
115
|
-
recursive: false
|
|
116
|
-
include_extensions: [.md]
|
|
117
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
118
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
119
|
-
required_sections: []
|
|
120
|
-
display_status: false
|
|
121
|
-
|
|
122
|
-
- id: specs-tenancy
|
|
123
|
-
path: .specs/tenancy/index.md
|
|
124
|
-
kind: specification-family
|
|
125
|
-
root: .specs/tenancy
|
|
126
|
-
recursive: false
|
|
127
|
-
include_extensions: [.md]
|
|
128
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
129
|
-
required_frontmatter: [type, title, description, status, generated, owner, requirement_prefix, sources]
|
|
130
|
-
required_sections: []
|
|
131
|
-
display_status: false
|
|
132
|
-
|
|
133
10
|
- id: docs-architecture
|
|
134
11
|
path: docs/architecture/index.md
|
|
135
12
|
kind: documentation-catalog
|
|
@@ -137,7 +14,6 @@ indexes:
|
|
|
137
14
|
recursive: true
|
|
138
15
|
include_extensions: [.md]
|
|
139
16
|
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
140
|
-
exclude_prefixes: [product/]
|
|
141
17
|
required_frontmatter: [type, title, description, status, last_update, sources, related]
|
|
142
18
|
required_sections: [Reading order]
|
|
143
19
|
display_status: true
|
|
@@ -178,15 +54,3 @@ indexes:
|
|
|
178
54
|
required_sections: []
|
|
179
55
|
display_status: true
|
|
180
56
|
status_map: {draft: draft, stable: stable}
|
|
181
|
-
|
|
182
|
-
- id: docs-product
|
|
183
|
-
path: docs/architecture/product/index.md
|
|
184
|
-
kind: hand-maintained-catalog
|
|
185
|
-
root: docs/architecture/product
|
|
186
|
-
recursive: true
|
|
187
|
-
include_extensions: [.md]
|
|
188
|
-
exclude_names: [index.md, AGENTS.md, CLAUDE.md]
|
|
189
|
-
required_frontmatter: [title, description, type, status, last_update, reason]
|
|
190
|
-
required_sections: [Normative, "Input, not authority", The schema itself]
|
|
191
|
-
display_status: false
|
|
192
|
-
inventory: exempt
|
|
@@ -152,3 +152,21 @@ def test_an_index_carrying_only_the_legacy_document_type_key_is_reported() -> No
|
|
|
152
152
|
finding = verdict.findings[0]
|
|
153
153
|
assert finding.path == "docs/compliance/index.md"
|
|
154
154
|
assert finding.message == "missing required frontmatter field type"
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_an_unknown_index_kind_is_could_not_run(tmp_path: Path) -> None:
|
|
158
|
+
body = (CLEAN / "docs-knowledge-indexes.yaml").read_text(encoding="utf-8")
|
|
159
|
+
assert "kind: documentation-catalog" in body
|
|
160
|
+
registry = tmp_path / "docs-knowledge-indexes.yaml"
|
|
161
|
+
registry.write_text(body.replace("kind: documentation-catalog", "kind: specification-family"), encoding="utf-8")
|
|
162
|
+
verdict = _run(CLEAN, registry=registry)
|
|
163
|
+
assert verdict.outcome is Outcome.COULD_NOT_RUN, verdict.render()
|
|
164
|
+
assert "specification-family" in verdict.message
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def test_a_missing_index_kind_is_could_not_run(tmp_path: Path) -> None:
|
|
168
|
+
body = (CLEAN / "docs-knowledge-indexes.yaml").read_text(encoding="utf-8")
|
|
169
|
+
registry = tmp_path / "docs-knowledge-indexes.yaml"
|
|
170
|
+
registry.write_text(body.replace(" kind: documentation-catalog\n", ""), encoding="utf-8")
|
|
171
|
+
verdict = _run(CLEAN, registry=registry)
|
|
172
|
+
assert verdict.outcome is Outcome.COULD_NOT_RUN, verdict.render()
|
|
@@ -46,13 +46,13 @@ common_optional:
|
|
|
46
46
|
#
|
|
47
47
|
# There were eight. Benchmark, Evaluation, Field Note and Specification declared
|
|
48
48
|
# trees that do not exist -- docs/research/benchmarks, docs/research/evaluations,
|
|
49
|
-
# docs/research/field-notes
|
|
49
|
+
# docs/research/field-notes -- so seven of the eight graded nothing at
|
|
50
50
|
# all while reading as coverage. A register that describes a documentation set
|
|
51
51
|
# nobody has is worse than a smaller one that describes the real thing: it
|
|
52
52
|
# reports clean because it never matched a file. Those four stay removed.
|
|
53
53
|
#
|
|
54
54
|
# Research is added back (2026-10-01), and not as a return of those four:
|
|
55
|
-
# docs/research/ itself exists in the consuming repositories.
|
|
55
|
+
# docs/research/ itself exists in the consuming repositories. the combined repository
|
|
56
56
|
# holds docs/research/cloud-local-research-input.md (type Research) and
|
|
57
57
|
# docs/research/codex-app-server-container-experiment.md (type Experiment), and
|
|
58
58
|
# with no profile covering that path DOC-006 reported "no OKF profile matches
|
package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py
CHANGED
|
@@ -125,16 +125,9 @@ class SeverityCounts(StrictModel):
|
|
|
125
125
|
low: int
|
|
126
126
|
|
|
127
127
|
|
|
128
|
-
class ComponentCounts(StrictModel):
|
|
129
|
-
enact_backend: int
|
|
130
|
-
enact_agent_rs: int
|
|
131
|
-
enact_frontend: int
|
|
132
|
-
|
|
133
|
-
|
|
134
128
|
class SecurityFindingsSummary(StrictModel):
|
|
135
129
|
total_findings: int
|
|
136
130
|
by_severity: SeverityCounts
|
|
137
|
-
by_component: ComponentCounts
|
|
138
131
|
|
|
139
132
|
|
|
140
133
|
class SecurityFinding(StrictModel):
|
|
@@ -90,9 +90,7 @@ class DocsSemantics(Check):
|
|
|
90
90
|
(real paths read `documentation/architecture/...`) — the filter dropped every page
|
|
91
91
|
before grading, and the gate reported clean having graded nothing. No
|
|
92
92
|
error, no could-not-run: a green light meaning nothing, and it was ARMED
|
|
93
|
-
in exactly that state
|
|
94
|
-
to declare `docs = "docs"`, so the literal was accidentally correct there
|
|
95
|
-
— this fix should not move either repo's count). `COLLECTIONS` below
|
|
93
|
+
in exactly that state. `COLLECTIONS` below
|
|
96
94
|
stays literal: architecture/research/compliance/operations are the
|
|
97
95
|
settled taxonomy, not a resolvable path (see its own comment)."""
|
|
98
96
|
|
|
@@ -336,7 +334,7 @@ class DocsSemantics(Check):
|
|
|
336
334
|
`IMPLEMENTATION_STATUS` matched the filename in
|
|
337
335
|
`backend/shipped-runtime-imports.test.ts` and the word "implemented" inside
|
|
338
336
|
`` `agent-loop/v1` ``, so a page was told to move delivery narration it did
|
|
339
|
-
not contain. Six of nine findings against
|
|
337
|
+
not contain. Six of nine findings against a managed repository were this.
|
|
340
338
|
"""
|
|
341
339
|
return cls.CODE_SPAN.sub(lambda m: " " * len(m.group(0)), line)
|
|
342
340
|
|
|
@@ -59,8 +59,7 @@ def test_a_redeclared_docs_tree_is_still_graded(tmp_path) -> None:
|
|
|
59
59
|
`documentation/architecture/...`) — the filter dropped every page before
|
|
60
60
|
grading, and the gate reported clean having graded nothing. No error, no
|
|
61
61
|
could-not-run: a green light meaning nothing, and it was ARMED in exactly
|
|
62
|
-
that state
|
|
63
|
-
`docs = "docs"`, so the literal was accidentally correct there).
|
|
62
|
+
that state.
|
|
64
63
|
|
|
65
64
|
A real stable architecture page under the redeclared tree, carrying
|
|
66
65
|
genuine delivery-status prose (`IMPLEMENTATION_STATUS`'s own "is shipped"
|
|
@@ -107,7 +106,7 @@ def test_every_defect_in_the_violations_corpus_is_reported() -> None:
|
|
|
107
106
|
def test_architecture_target_delivery_narration_is_reported() -> None:
|
|
108
107
|
verdict = run("semantics-violations")
|
|
109
108
|
assert any(
|
|
110
|
-
f.path == "docs/architecture/
|
|
109
|
+
f.path == "docs/architecture/guides/target-narration.md"
|
|
111
110
|
and "architecture target cannot carry delivery-status narration" in f.message
|
|
112
111
|
for f in verdict.findings
|
|
113
112
|
), verdict.render()
|
|
@@ -116,7 +115,7 @@ def test_architecture_target_delivery_narration_is_reported() -> None:
|
|
|
116
115
|
def test_stable_unresolved_recommendation_is_reported() -> None:
|
|
117
116
|
verdict = run("semantics-violations")
|
|
118
117
|
assert any(
|
|
119
|
-
f.path == "docs/architecture/
|
|
118
|
+
f.path == "docs/architecture/guides/stable-recommendation.md"
|
|
120
119
|
and f.message == "stable architecture cannot contain unresolved recommendation language"
|
|
121
120
|
for f in verdict.findings
|
|
122
121
|
), verdict.render()
|
|
@@ -125,7 +124,7 @@ def test_stable_unresolved_recommendation_is_reported() -> None:
|
|
|
125
124
|
def test_stable_delivery_status_is_reported() -> None:
|
|
126
125
|
verdict = run("semantics-violations")
|
|
127
126
|
assert any(
|
|
128
|
-
f.path == "docs/architecture/
|
|
127
|
+
f.path == "docs/architecture/guides/stable-delivery.md"
|
|
129
128
|
and f.message == "stable architecture cannot carry delivery or implementation status"
|
|
130
129
|
for f in verdict.findings
|
|
131
130
|
), verdict.render()
|
|
@@ -251,7 +250,7 @@ def test_code_spans_and_fences_are_not_prose(tmp_path: pathlib.Path) -> None:
|
|
|
251
250
|
the filename inside `backend/shipped-runtime-imports.test.ts`, and "implemented"
|
|
252
251
|
inside `agent-loop/v1`, and told the page to move narration it did not contain.
|
|
253
252
|
|
|
254
|
-
Six of nine findings against
|
|
253
|
+
Six of nine findings against a managed repository were regex hits rather than statements; this
|
|
255
254
|
closes the two that were unambiguously code."""
|
|
256
255
|
from adl_compliance.checks.docs.semantics.check import DocsSemantics
|
|
257
256
|
|
|
@@ -318,7 +317,7 @@ def test_genuine_built_delivery_claims_still_fire() -> None:
|
|
|
318
317
|
|
|
319
318
|
MEANS = [
|
|
320
319
|
"Those are additional Task-executor shapes; they are not implemented by provisioning another sandbox.",
|
|
321
|
-
"It is a reference copy from
|
|
320
|
+
"It is a reference copy from another repository, not wired into this repository's own pipeline.",
|
|
322
321
|
"An agent surface config not wired to the shared guard is the subject of that rule.",
|
|
323
322
|
]
|
|
324
323
|
|
|
@@ -124,8 +124,8 @@ def test_a_docker_registry_reference_is_excluded() -> None:
|
|
|
124
124
|
|
|
125
125
|
def test_donors_and_target_prefixed_tokens_are_excluded() -> None:
|
|
126
126
|
check = CiPaths()
|
|
127
|
-
assert check._excluded(".donors/
|
|
128
|
-
assert check._excluded("target/debug/
|
|
127
|
+
assert check._excluded(".donors/upstream-lib/README.md", frozenset({".donors"}))
|
|
128
|
+
assert check._excluded("target/debug/binary", frozenset({"target"}))
|
|
129
129
|
|
|
130
130
|
|
|
131
131
|
def test_a_token_whose_first_segment_is_not_a_real_root_entry_is_excluded() -> None:
|
|
@@ -136,7 +136,7 @@ def test_a_token_whose_first_segment_is_not_a_real_root_entry_is_excluded() -> N
|
|
|
136
136
|
|
|
137
137
|
def test_a_token_whose_first_segment_is_a_real_root_entry_survives() -> None:
|
|
138
138
|
assert not CiPaths()._excluded(
|
|
139
|
-
"backend/crates/
|
|
139
|
+
"backend/crates/db/src/lib.rs", frozenset({"backend", "frontend"})
|
|
140
140
|
)
|
|
141
141
|
|
|
142
142
|
|