@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.30 → 0.1.33
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/adl-git-push-policy.ts +5 -4
- 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-hooks/src/rules/shell/protected-carriers.ts +19 -5
- package/packages/agent-settings/assets/GLOBAL-AGENTS.md +1 -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/azdo/src/lib/commit-types.ts +8 -0
- package/packages/azdo/src/lib/validate-pr-metadata.ts +4 -1
- package/packages/fleet/manifest.json +2 -1
- package/packages/fleet/src/repo-maintain.ts +5 -2
- package/packages/repo-controls/AGENTS.md +8 -5
- package/packages/repo-controls/README.md +348 -58
- 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/commit-msg +1 -1
- 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 +62 -52
- 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
- package/packages/repo-controls/src/integrity.ts +5 -18
|
@@ -1,52 +1,8 @@
|
|
|
1
|
-
// Managed by adl-repo-controls
|
|
2
|
-
// Regenerate with: adl-repo-controls install --repo .
|
|
3
|
-
//
|
|
4
|
-
// Vendored into `.workflows/` byte-for-byte so CI depends on nothing: no
|
|
5
|
-
// adl-repo-controls on PATH, no MCP client, no package install. A pipeline
|
|
6
|
-
// agent is a cold environment, and a promotion that needs a global npm binary
|
|
7
|
-
// fails there for reasons that have nothing to do with the promotion.
|
|
8
|
-
//
|
|
9
|
-
// Byte-identical in every repository, deliberately. Refs come from the
|
|
10
|
-
// environment, never baked in — otherwise each consumer's copy would hash
|
|
11
|
-
// differently and one published hash could not verify any of them.
|
|
1
|
+
// Managed by adl-repo-controls, do not edit; regenerate with: adl-repo-controls install --repo . (README "Managed workflow scripts").
|
|
12
2
|
|
|
13
|
-
/**
|
|
14
|
-
* Promote one branch to another through an Azure DevOps pull request.
|
|
15
|
-
*
|
|
16
|
-
* Standard, not repo-local: every repository in this estate is on Azure DevOps,
|
|
17
|
-
* and promoting a branch to its trunk is find-or-reuse a PR, then set
|
|
18
|
-
* auto-complete. Ported from enact-m5's `workflows/scripts/release/
|
|
19
|
-
* promote-main.ts`, where the mechanism was already injectable — fetch,
|
|
20
|
-
* collection, project, repository and token were all parameters — and only
|
|
21
|
-
* three module-scoped literals made it that repository's:
|
|
22
|
-
*
|
|
23
|
-
* SOURCE_REF = 'refs/heads/integration'
|
|
24
|
-
* TARGET_REF = 'refs/heads/main'
|
|
25
|
-
* title = 'release: promote integration to main'
|
|
26
|
-
*
|
|
27
|
-
* The refs are declared as `[controls.release].source` / `.target`. The title is
|
|
28
|
-
* DERIVED from them rather than being a third key: a title that can disagree
|
|
29
|
-
* with the refs it describes is a bug waiting for someone to change one and
|
|
30
|
-
* forget the other, and the derived form satisfies this package's own
|
|
31
|
-
* commit-msg grammar for any pair.
|
|
32
|
-
*
|
|
33
|
-
* The target branch's gate is Tarun's approval alone (Tarun, 2026-09-30): the
|
|
34
|
-
* promotion PR gets NO build validation and CD runs after the merge into the
|
|
35
|
-
* target. The pre-flight proves the minimum-reviewer policy (>=1 approver,
|
|
36
|
-
* resetOnSourcePush=true) and does not require a build policy.
|
|
37
|
-
*
|
|
38
|
-
* There is no default pair. Defaulting to integration -> main would put one
|
|
39
|
-
* repository's branch names back into the package by the back door.
|
|
40
|
-
*/
|
|
3
|
+
/** Promote one branch to another through an Azure DevOps pull request; see README "Managed workflow scripts". */
|
|
41
4
|
|
|
42
|
-
/**
|
|
43
|
-
* Azure DevOps' `GitPullRequestCompletionOptions.mergeStrategy`, by name.
|
|
44
|
-
* The REST API's wire values are the camelCase strings below (confirmed
|
|
45
|
-
* against a live PR: sending the numeric `GitPullRequestMergeStrategy` enum
|
|
46
|
-
* ordinal here is silently accepted by the type system but is not what the
|
|
47
|
-
* API expects — PR 1477, 2026-09-27, armed auto-complete with `rebase`
|
|
48
|
-
* although "no-fast-forward" was intended). `squash` is the standard.
|
|
49
|
-
*/
|
|
5
|
+
/** Azure DevOps' `mergeStrategy` by name; see README "Managed workflow scripts". */
|
|
50
6
|
export const MERGE_STRATEGIES = {
|
|
51
7
|
squash: 'squash',
|
|
52
8
|
rebase: 'rebase',
|
|
@@ -68,12 +24,7 @@ export interface PromotionRequest {
|
|
|
68
24
|
/** Declared branch names, WITHOUT the `refs/heads/` prefix. */
|
|
69
25
|
source?: string
|
|
70
26
|
target?: string
|
|
71
|
-
/**
|
|
72
|
-
* Azure's `GitPullRequestMergeStrategy`. Defaults to the standard the MCP
|
|
73
|
-
* server defines -- its PR tool admits `enum: ['Squash']` and nothing else.
|
|
74
|
-
* A repository wanting something else declares it, so the deviation is
|
|
75
|
-
* visible instead of welded into this file.
|
|
76
|
-
*/
|
|
27
|
+
/** Azure's `GitPullRequestMergeStrategy`; see README "Managed workflow scripts". */
|
|
77
28
|
mergeStrategy?: MergeStrategy
|
|
78
29
|
}
|
|
79
30
|
|
|
@@ -192,26 +143,7 @@ export interface PromotionPolicyReceipts {
|
|
|
192
143
|
build: PolicyConfiguration | null
|
|
193
144
|
}
|
|
194
145
|
|
|
195
|
-
/**
|
|
196
|
-
* The one policy contract used by both promotion and doctor. A configuration
|
|
197
|
-
* only counts when it is enabled, blocking, and scoped exactly to the target
|
|
198
|
-
* branch; a project-wide or path-filtered lookalike cannot guard a promotion.
|
|
199
|
-
*
|
|
200
|
-
* The target's gate is the minimum-reviewer policy ONLY (Tarun, 2026-09-30):
|
|
201
|
-
* the integration -> main promotion PR gets no build validation, Tarun's
|
|
202
|
-
* approval is the only gate, and CD runs after the merge into main. Promotion
|
|
203
|
-
* therefore never requires a build policy. `build` is still reported so a
|
|
204
|
-
* caller can show one that happens to be present, but nothing here demands it.
|
|
205
|
-
*
|
|
206
|
-
* No named-reviewer policy is checked here, deliberately (Tarun,
|
|
207
|
-
* 2026-09-27): the two-branch standard's `main` gate is "exactly one human
|
|
208
|
-
* reviewer, author's vote excluded" via the minimum-reviewer policy below —
|
|
209
|
-
* never a specific named individual. A required-reviewer-by-identity policy
|
|
210
|
-
* on `main` was PR 1477's second live bug: it named the person who pushed to
|
|
211
|
-
* `integration` as a mandatory approver, which both self-approves (that
|
|
212
|
-
* person is usually the change's author) and contradicts "agent-reviewer is
|
|
213
|
-
* optional, never required".
|
|
214
|
-
*/
|
|
146
|
+
/** The one policy contract used by promotion and doctor (see README "Managed workflow scripts"). */
|
|
215
147
|
export function promotionPolicyReceipts(
|
|
216
148
|
policies: readonly PolicyConfiguration[],
|
|
217
149
|
{ repositoryId, targetRef }: PromotionPolicyRequirement,
|
|
@@ -326,11 +258,7 @@ export async function ensurePromotionPullRequest({
|
|
|
326
258
|
status = 'created'
|
|
327
259
|
}
|
|
328
260
|
|
|
329
|
-
// No reviewer is named
|
|
330
|
-
// typically the person who pushed to `integration` — is a self-approval
|
|
331
|
-
// risk and contradicts "agent-reviewer is optional, never required". The
|
|
332
|
-
// gate is the target branch's own minimum-reviewer policy (verified above),
|
|
333
|
-
// which excludes the author's own vote.
|
|
261
|
+
// No reviewer is named: see README "Managed workflow scripts".
|
|
334
262
|
await azureRequest(fetchImpl, `${repositoryUrl}/pullrequests/${pullRequest.pullRequestId}?api-version=7.1`, authToken, {
|
|
335
263
|
method: 'PATCH',
|
|
336
264
|
body: JSON.stringify({
|
|
@@ -347,13 +275,7 @@ export async function ensurePromotionPullRequest({
|
|
|
347
275
|
}
|
|
348
276
|
|
|
349
277
|
|
|
350
|
-
/**
|
|
351
|
-
* Standalone entry point. Reads the refs from the ENVIRONMENT, not from config:
|
|
352
|
-
* this file is vendored into `.workflows/` byte-for-byte, so its content must
|
|
353
|
-
* be identical in every repository or a single published hash cannot verify
|
|
354
|
-
* any of them. The pipeline supplies the repository-specific values through
|
|
355
|
-
* environment variables while the managed implementation stays identical.
|
|
356
|
-
*/
|
|
278
|
+
/** Standalone entry point; refs come from the environment (see README "Managed workflow scripts"). */
|
|
357
279
|
export async function main(env: Record<string, string | undefined> = process.env): Promise<void> {
|
|
358
280
|
const result = await ensurePromotionPullRequest({
|
|
359
281
|
collectionUri: env.AZURE_DEVOPS_COLLECTION_URI,
|
|
@@ -1,20 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
|
-
# Stage 1
|
|
5
|
-
# runs the tests). It forces the PR author, usually an agent, to reconcile with
|
|
6
|
-
# integration before anything merges:
|
|
7
|
-
#
|
|
8
|
-
# the PR source branch contains integration's tip
|
|
9
|
-
#
|
|
10
|
-
# That is the only check. The version bump is not a PR concern any more: the
|
|
11
|
-
# integration-merge pipeline bumps after the merge (Tarun, 2026-10-01).
|
|
12
|
-
#
|
|
13
|
-
# Read-only: this script only fetches and reads. It never pushes, and the only
|
|
14
|
-
# refs it writes are the two remote-tracking refs it fetches.
|
|
15
|
-
|
|
16
|
-
# CI never carries an agent identity. Never set one here, and never inherit
|
|
17
|
-
# one from the caller.
|
|
4
|
+
# Stage 1 PR guard; see README "Managed workflow scripts".
|
|
18
5
|
unset ADL_AGENT_ID_AGENT
|
|
19
6
|
|
|
20
7
|
die() {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# docs/ — what belongs here
|
|
2
|
+
|
|
3
|
+
Reference documentation for this repository: how it works and why it is shaped
|
|
4
|
+
the way it is.
|
|
5
|
+
|
|
6
|
+
## Layout
|
|
7
|
+
|
|
8
|
+
- Standing reference pages live directly under this directory, one topic per
|
|
9
|
+
page.
|
|
10
|
+
- Sub-directories group related pages (for example `decisions/` for
|
|
11
|
+
architecture decision records, `research/` for dated investigations). Add one
|
|
12
|
+
only when it has pages to hold.
|
|
13
|
+
- `notes.md` is the repository's task ledger: one line when an agent starts a
|
|
14
|
+
task and one when it finishes.
|
|
15
|
+
|
|
16
|
+
## Conventions
|
|
17
|
+
|
|
18
|
+
- Every page carries YAML frontmatter with at least `type`, `title`,
|
|
19
|
+
`description`, `status` and `last_update` (ISO-8601 UTC,
|
|
20
|
+
`YYYY-MM-DDTHH:MM:SSZ`).
|
|
21
|
+
- `notes.md` is append-only: newest line at the bottom, earlier lines are never
|
|
22
|
+
rewritten. Format `YYYY-MM-DD HH:MM <surface> <note>`, at most 100
|
|
23
|
+
characters per line.
|
|
24
|
+
- A page that is catalogued in an index stays listed there; add the entry in
|
|
25
|
+
the same change that adds or renames the page.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
last_update: '2026-10-08T00:00:00Z'
|
|
3
|
+
title: Architecture decision records
|
|
4
|
+
description: The index of this repository's architecture decision records, one adr-<slug>.md page per decision.
|
|
5
|
+
type: Reference
|
|
6
|
+
status: stable
|
|
7
|
+
sources: the repository's documentation conventions (decision records)
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Architecture decision records
|
|
11
|
+
|
|
12
|
+
One page per decision, named `adr-<slug>.md`. Each carries an inline
|
|
13
|
+
`**Status:**` line (OPEN, DECIDED or STABLE) and the backlinks that state owes.
|
|
14
|
+
|
|
15
|
+
## Decisions
|
|
16
|
+
|
|
17
|
+
None yet. List each new record here in the same change that adds it.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
last_update: '2026-10-08T00:00:00Z'
|
|
3
|
+
title: Agent notes ledger
|
|
4
|
+
description: One append-only ledger per repository for every agent, one line when you start a task and one when you finish it.
|
|
5
|
+
type: Operations
|
|
6
|
+
status: stable
|
|
7
|
+
sources: the repository's agent rules (task ledger convention)
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Agent notes ledger
|
|
11
|
+
|
|
12
|
+
A short, append-only log so anyone landing in the repository can see at a glance
|
|
13
|
+
what every agent is doing. Every line is at most 100 characters, format
|
|
14
|
+
`YYYY-MM-DD HH:MM <surface> <note>` (for example
|
|
15
|
+
`2026-10-08 13:30 claude start: add retry to the uploader`). Agents append one
|
|
16
|
+
line when they start a task and one when they finish it. The ledger is never
|
|
17
|
+
edited or sorted; earlier lines are never rewritten, only appended to, newest
|
|
18
|
+
at the bottom.
|
|
19
|
+
|
|
20
|
+
## Lines
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# plans/ — what belongs here
|
|
2
|
+
|
|
3
|
+
Work items: Features, and the PBIs/Bugs that hang under them. The work-item
|
|
4
|
+
board is the only place status lives; the files here describe the work.
|
|
5
|
+
|
|
6
|
+
## Layout
|
|
7
|
+
|
|
8
|
+
- `plans/features/az<id>-<slug>/spec.md` — one Feature, one file, for its whole
|
|
9
|
+
life. Frontmatter: `type: feature`, `title`, `status` (the board state),
|
|
10
|
+
`epic:` (the parent Epic's board URL), `work_item:` (this Feature's own board
|
|
11
|
+
URL), `last_update`. The Feature's own `## Items` table is the one place it
|
|
12
|
+
may list its children.
|
|
13
|
+
- `plans/features/az<id>-<slug>/items/az<item-id>-<slug>.md` — one PBI or Bug.
|
|
14
|
+
Frontmatter: `type: pbi` or `type: bug`, `title`, `status`, `feature:` (the
|
|
15
|
+
parent Feature's slug), `work_item:`, `last_update`.
|
|
16
|
+
- `plans/GAPS-AND-FINDINGS.md` — a register of gaps found while planning or
|
|
17
|
+
building something else. A row is deleted, not marked done, once its linked
|
|
18
|
+
item closes.
|
|
19
|
+
- `plans/LEDGER.md` — the plan-event ledger, a Markdown table, newest entry
|
|
20
|
+
first.
|
|
21
|
+
|
|
22
|
+
## Conventions
|
|
23
|
+
|
|
24
|
+
- The board is the only place status lives. A file's `status:` mirrors the
|
|
25
|
+
board state.
|
|
26
|
+
- An item is allocated on the board first; the file is named `az<id>-<slug>`
|
|
27
|
+
only once that id exists. Files never move between directories.
|
|
28
|
+
- `epic:` and `feature:` are authored by hand, never tool-generated.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Gaps and findings
|
|
2
|
+
|
|
3
|
+
Anything found while planning or building that is not the work in hand. Each row
|
|
4
|
+
becomes an item file with `item_type: bug`, parented under the same Feature as
|
|
5
|
+
the plan it was found from, so the fix stays attached to the effort that
|
|
6
|
+
surfaced it.
|
|
7
|
+
|
|
8
|
+
Each row states how it was verified, because a finding nobody can re-check is a
|
|
9
|
+
rumour. A row is deleted, not marked done, once it stops being a gap.
|
|
10
|
+
|
|
11
|
+
| Found | Finding | From plan | Item file | Work item |
|
|
12
|
+
| --- | --- | --- | --- | --- |
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Ledger
|
|
2
|
+
|
|
3
|
+
Plan events, newest first. Each row has a kebab-case unique `Id`, an ISO `Date`,
|
|
4
|
+
an `Area`, a short `Event`, and `Refs` (repository-relative paths that exist).
|
|
5
|
+
|
|
6
|
+
| Date | Id | Area | Event | Refs |
|
|
7
|
+
| --- | --- | --- | --- | --- |
|
|
8
|
+
| 2026-10-08 | plans-tree-bootstrapped | plans | Plans tree scaffolded by adl repo controls install | — |
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Agent entry point
|
|
2
|
+
|
|
3
|
+
This is the first file a human or agent should read on arriving at this
|
|
4
|
+
repository. Edit it to describe what this repository is; the sections below
|
|
5
|
+
describe the layout the adl repo controls enforce.
|
|
6
|
+
|
|
7
|
+
## Layout
|
|
8
|
+
|
|
9
|
+
| Path | What lives there |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| `docs/` | reference documentation, see `docs/AGENTS.md` |
|
|
12
|
+
| `plans/` | Features and the PBIs/Bugs under them, see `plans/AGENTS.md` |
|
|
13
|
+
| `workflows/` | CI pipelines and build/release scripts, see `workflows/AGENTS.md` |
|
|
14
|
+
| `.workflows/` | managed hook stubs and lock, rebuilt by `adl repo controls install`; never hand-edit |
|
|
15
|
+
|
|
16
|
+
## Rules
|
|
17
|
+
|
|
18
|
+
- This repository is graded by `adl-compliance` on every commit; the enabled
|
|
19
|
+
gates are `[controls.compliance].enabled` in `adl-config.toml`. A failing
|
|
20
|
+
gate is fixed, not skipped.
|
|
21
|
+
- `INVARIANTS.md` lists what this repository must never regress.
|
|
22
|
+
- Work-item status lives on the board, never in a file.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# workflows/ — what belongs here
|
|
2
|
+
|
|
3
|
+
The CI tree: pipeline definitions and the scripts they run.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
- `workflows/pipelines/` — pipeline definitions and their shared templates.
|
|
8
|
+
- `workflows/scripts/` — the scripts the pipelines invoke, grouped in
|
|
9
|
+
sub-directories by purpose (for example `build/`, `release/`).
|
|
10
|
+
|
|
11
|
+
## Conventions
|
|
12
|
+
|
|
13
|
+
- A script here is invoked by a pipeline, never by a git hook.
|
|
14
|
+
- Keep each scripts directory small; split by purpose before it grows past a
|
|
15
|
+
screenful of files.
|
|
16
|
+
- A pipeline and the scripts it references must resolve: move them together.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
File without changes
|
|
File without changes
|
|
@@ -1,26 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
|
-
#
|
|
5
|
-
|
|
6
|
-
# build-validation policy ignores `[skip ci]`, so a bump pushed from PR CI
|
|
7
|
-
# re-queued itself; a push to a branch honours it). After a merge lands on
|
|
8
|
-
# `integration` this sets the manifest to that commit's version + patch 1:
|
|
9
|
-
#
|
|
10
|
-
# version-bump.sh --file package.json --integration --push
|
|
11
|
-
#
|
|
12
|
-
# The Azure Pipelines build checks out the detached commit that triggered the
|
|
13
|
-
# run with persisted credentials, so `git push` authenticates as the project
|
|
14
|
-
# build service (which needs Contribute + "Bypass policies when pushing" on
|
|
15
|
-
# `integration`). The bump commit is created on that checkout, carries
|
|
16
|
-
# `[skip ci]` so the push does not trigger this pipeline again, and is pushed
|
|
17
|
-
# with a plain fast-forward -- never forced. If integration moved since the
|
|
18
|
-
# checkout the push is rejected and the script fails loud; the newer merge's
|
|
19
|
-
# own run bumps. No npm query, no PR.
|
|
20
|
-
|
|
21
|
-
# CI never carries an agent identity: the push below authenticates as the
|
|
22
|
-
# project build service through the checkout's persisted System.AccessToken.
|
|
23
|
-
# Never set an agent identity here, and never inherit one from the caller.
|
|
4
|
+
# Rationale: packages/repo-controls/README.md, "Managed workflow scripts", version-bump.sh.
|
|
5
|
+
|
|
24
6
|
unset ADL_AGENT_ID_AGENT
|
|
25
7
|
|
|
26
8
|
die() {
|
|
@@ -82,13 +64,6 @@ node -e '
|
|
|
82
64
|
fs.writeFileSync(file, `${JSON.stringify(manifest, null, 2)}\n`)
|
|
83
65
|
' "$version_file" "$next_version"
|
|
84
66
|
|
|
85
|
-
# `[controls.release].pre_bump` (adl-config.toml, repo root): ordered,
|
|
86
|
-
# repository-relative scripts a multi-language repo runs before the bump
|
|
87
|
-
# commit — e.g. agent-identities updates a Go version constant nothing about
|
|
88
|
-
# package.json can reach. No file, or no `pre_bump` key: no scripts, and
|
|
89
|
-
# everything below this comment is a no-op, so the resulting commit is
|
|
90
|
-
# byte-identical to the behaviour before this feature existed (see
|
|
91
|
-
# packages/repo-controls/tests/version-bump-integration-pre-bump.test.ts).
|
|
92
67
|
config_path="$repo_root/adl-config.toml"
|
|
93
68
|
pre_bump_list=''
|
|
94
69
|
if [[ -f "$config_path" ]]; then
|
|
@@ -129,31 +104,17 @@ if [[ -n "$pre_bump_list" ]]; then
|
|
|
129
104
|
fi
|
|
130
105
|
|
|
131
106
|
if [[ ${#pre_bump_scripts[@]} -gt 0 ]]; then
|
|
132
|
-
# Validated before any of them run, so a bad declaration fails clearly
|
|
133
|
-
# instead of leaving the repo half-way through a partial run.
|
|
134
107
|
for script in "${pre_bump_scripts[@]}"; do
|
|
135
108
|
[[ -f "$repo_root/$script" ]] || die "pre_bump script not found: $script"
|
|
136
109
|
done
|
|
137
110
|
|
|
138
|
-
# Every var whose name ends _TOKEN/_PAT/_SECRET/_PASSWORD, plus the two
|
|
139
|
-
# Azure DevOps credentials by their exact names (SYSTEM_ACCESSTOKEN does
|
|
140
|
-
# not end in "_TOKEN"), is stripped from each script's environment. A
|
|
141
|
-
# pre_bump script is repo-authored, unreviewed by this package, and has no
|
|
142
|
-
# business ever seeing the pipeline's push/PR credentials.
|
|
143
111
|
unset_flags=(-u SYSTEM_ACCESSTOKEN -u AZURE_DEVOPS_EXT_PAT -u AZURE_DEVOPS_TOKEN -u AZURE_DEVOPS_PAT)
|
|
144
112
|
while IFS= read -r var_name; do
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
# diffs against — so this is a separate, explicit check. There is no
|
|
151
|
-
# equivalent check for a script writing to an absolute path OUTSIDE the
|
|
152
|
-
# repository entirely: a plain shell script has no sandbox to enforce
|
|
153
|
-
# that, so this refuses `.git` tampering only, honestly, rather than
|
|
154
|
-
# claiming a guarantee this script cannot keep. Changes INSIDE the repo
|
|
155
|
-
# tree are never "outside the repo" by construction: every add below is
|
|
156
|
-
# scoped to `$repo_root`, so nothing beyond it can ever be staged.
|
|
113
|
+
if [[ "$var_name" =~ _([Tt][Oo][Kk][Ee][Nn]|[Pp][Aa][Tt]|[Ss][Ee][Cc][Rr][Ee][Tt]|[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd])$ ]]; then
|
|
114
|
+
unset_flags+=(-u "$var_name")
|
|
115
|
+
fi
|
|
116
|
+
done < <(compgen -v)
|
|
117
|
+
|
|
157
118
|
git_marker="$(mktemp)"
|
|
158
119
|
for script in "${pre_bump_scripts[@]}"; do
|
|
159
120
|
if ! ( cd "$repo_root" && env "${unset_flags[@]}" \
|
|
@@ -172,8 +133,6 @@ fi
|
|
|
172
133
|
|
|
173
134
|
git -C "$repo_root" add -A
|
|
174
135
|
git diff --cached --quiet && die "version bump produced no staged change (expected at least $version_file)"
|
|
175
|
-
# `[skip ci]` (Azure DevOps: a push whose commits contain it does not trigger CI
|
|
176
|
-
# pipelines) keeps this push from re-running the promote pipeline that made it.
|
|
177
136
|
git commit -m "chore: bump version $current_version to $next_version [skip ci]"
|
|
178
137
|
if ! git push origin "HEAD:refs/heads/integration"; then
|
|
179
138
|
die "push to integration rejected: integration moved since checkout, so this bump is stale; the next merge's run bumps"
|
|
@@ -98,15 +98,15 @@ the rest, so ast-grep's next release does not fail a gate.
|
|
|
98
98
|
|
|
99
99
|
## The consumer's layout arrives
|
|
100
100
|
|
|
101
|
-
A row names a logical tree; `
|
|
101
|
+
A row names a logical tree; the consumer's `[controls.compliance.trees]` says where it lives (`policy/config.toml` ships no defaults).
|
|
102
102
|
|
|
103
103
|
```yaml
|
|
104
104
|
scope:
|
|
105
|
-
- <
|
|
106
|
-
- <
|
|
105
|
+
- <docs>/guides/**/*.md # documentation/guides/**/*.md
|
|
106
|
+
- <plans>/features/**/spec.md
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
Most of the registry's scope entries are placeholders, and named-input
|
|
110
110
|
defaults and `grants:` paths resolve through the same table — so no consumer path
|
|
111
111
|
is written in this package's rows, and moving a tree is one line. `<name>`, not
|
|
112
112
|
`{name}`: braces are already glob alternation and eleven rows use it. An unknown
|
|
@@ -125,8 +125,8 @@ never enter a set and no row needs to exclude `node_modules/`.
|
|
|
125
125
|
## Running
|
|
126
126
|
|
|
127
127
|
```bash
|
|
128
|
-
uv run adl-compliance
|
|
129
|
-
uv run adl-compliance
|
|
128
|
+
uv run adl-compliance layout.references
|
|
129
|
+
uv run adl-compliance DOC-001 --files changed.list
|
|
130
130
|
uv run adl-compliance # every row
|
|
131
131
|
```
|
|
132
132
|
|
|
@@ -150,7 +150,7 @@ it. `tests/core/` is the one exception, for the spine (`Check`, `scope`,
|
|
|
150
150
|
|
|
151
151
|
## Status
|
|
152
152
|
|
|
153
|
-
Every row of the registry is implemented —
|
|
153
|
+
Every row of the registry is implemented — 29 of 29, counted by importing
|
|
154
154
|
`adl_compliance.checks` and measuring `len(CHECKS)` (`checks/__init__.py`'s
|
|
155
155
|
explicit registry tuple), not by re-reading this paragraph. The shell
|
|
156
156
|
`compliance_new/` tree this package ported from is gone, not frozen: a row
|
|
@@ -160,3 +160,21 @@ never a silent pass, and today no row reaches that.
|
|
|
160
160
|
[`docs/operations/adl-compliance-invariants.md`](../../../../docs/operations/adl-compliance-invariants.md)
|
|
161
161
|
records what is not true yet, including two rows that do not
|
|
162
162
|
trigger on their own named inputs and one whose register does not exist.
|
|
163
|
+
|
|
164
|
+
## Rationale moved out of code comments (Bug 602)
|
|
165
|
+
|
|
166
|
+
- A check that subscripts an input dropped because its tree is declared `""`
|
|
167
|
+
(`[controls.compliance.trees] <tree> = ""`) is could-not-run, never clean: a
|
|
168
|
+
clean verdict would read as a pass for a gate that graded nothing (Bug 597).
|
|
169
|
+
Checks that can honestly narrow (LAY-006/008/013, DOC-002) guard the read.
|
|
170
|
+
Any other `KeyError` is a plain crash, reported as that row's could-not-run so
|
|
171
|
+
it cannot erase the other rows' verdicts.
|
|
172
|
+
- A widening input (a register of grants) whose tree is unknown is "no register",
|
|
173
|
+
never an error: its absence can only grade stricter (PBI 599).
|
|
174
|
+
- Central root trees are only adl's own or language-neutral ones (`compliance`,
|
|
175
|
+
`workflows`, `bin`, `packages`, `scripts`, `src`, `tests`); any other layout is
|
|
176
|
+
declared under `[controls.compliance.root] dirs` (PBI 601).
|
|
177
|
+
- `.workflows/` is deliberately not in the root-Markdown guide list: it is
|
|
178
|
+
machine-managed, written wholesale by `adl-repo-controls install`.
|
|
179
|
+
- `markdown_trees` root names come from `[controls.compliance.root] files` and
|
|
180
|
+
match exactly; a glob is refused by `declared_root_files`.
|
|
@@ -36,16 +36,16 @@ from .layout.root_closed_set import RootClosedSet
|
|
|
36
36
|
from .layout.root_markdown_allowlist import RootMarkdownAllowlist
|
|
37
37
|
from .layout.scripts_size_depth import ScriptsSizeDepth
|
|
38
38
|
from .lfs.integrity import Integrity
|
|
39
|
-
from .pipeline.phase_disjoint import PhaseDisjoint
|
|
40
|
-
from .repository.banned_commands import BannedCommands
|
|
41
39
|
from .repository.ignored_paths import IgnoredPaths
|
|
40
|
+
from .repository.legacy_search import LegacySearch
|
|
42
41
|
from .repository.license_declared import LicenseDeclared
|
|
43
42
|
from .repository.lockfile_integrity import LockfileIntegrity
|
|
43
|
+
from .repository.no_multiline_comments import NoMultilineComments
|
|
44
|
+
from .repository.vcs_in_scripts import VcsInScripts
|
|
44
45
|
|
|
45
46
|
CHECKS: tuple[type[Check], ...] = (
|
|
46
47
|
AdrLifecycle,
|
|
47
48
|
AgentsLayout,
|
|
48
|
-
BannedCommands,
|
|
49
49
|
CiPaths,
|
|
50
50
|
DirectoryRatchet,
|
|
51
51
|
DocsClosedSet,
|
|
@@ -59,18 +59,20 @@ CHECKS: tuple[type[Check], ...] = (
|
|
|
59
59
|
Indexes,
|
|
60
60
|
Integrity,
|
|
61
61
|
LicenseDeclared,
|
|
62
|
+
LegacySearch,
|
|
62
63
|
LockfileIntegrity,
|
|
63
64
|
MarkdownAst,
|
|
64
65
|
MarkdownTrees,
|
|
66
|
+
NoMultilineComments,
|
|
65
67
|
OkfProfile,
|
|
66
68
|
OpenWorkCap,
|
|
67
|
-
PhaseDisjoint,
|
|
68
69
|
Placement,
|
|
69
70
|
PlansLayout,
|
|
70
71
|
References,
|
|
71
72
|
RootClosedSet,
|
|
72
73
|
RootMarkdownAllowlist,
|
|
73
74
|
ScriptsSizeDepth,
|
|
75
|
+
VcsInScripts,
|
|
74
76
|
)
|
|
75
77
|
|
|
76
78
|
_BY_ID: dict[str, type[Check]] = {check.id: check for check in CHECKS}
|
|
@@ -7,7 +7,7 @@ owes a different set of backlinks.
|
|
|
7
7
|
docs/architecture/decisions/ entirely would pass in silence.
|
|
8
8
|
graded the ADRs, which are the given set.
|
|
9
9
|
|
|
10
|
-
BACKLINK TARGETS ARE RESOLVED, NOT GRADED. `.
|
|
10
|
+
BACKLINK TARGETS ARE RESOLVED, NOT GRADED. `.plans/` and
|
|
11
11
|
`docs/architecture/` references are read from disk even though the row's scope
|
|
12
12
|
excludes them. That is not a second discovery pass: the set says which ADRs are
|
|
13
13
|
graded, and whether an ADR's own link resolves is a property OF that ADR.
|
|
@@ -54,7 +54,7 @@ def test_a_linked_plan_is_no_longer_graded_on_the_directory_it_sits_in() -> None
|
|
|
54
54
|
So whether a linked plan is active is no longer answerable from disk, and this
|
|
55
55
|
gate does not try. What remains is the backlink itself, asserted below. The rule
|
|
56
56
|
survived the tree's deletion by eighteen months of nobody writing a DECIDED ADR —
|
|
57
|
-
DOC-001 was armed and green on
|
|
57
|
+
DOC-001 was armed and green on a managed repository the whole time."""
|
|
58
58
|
verdict = verdict_for("DOC-001", CORPORA / "adr-lifecycle-inactive-plan")
|
|
59
59
|
assert "requires a linked active plan" not in verdict.render()
|
|
60
60
|
|
|
@@ -35,12 +35,10 @@ One finding per (path, line, kind), not per matched character or codepoint —
|
|
|
35
35
|
the matched value (a two-character Han word on one line is one finding, not
|
|
36
36
|
two).
|
|
37
37
|
|
|
38
|
-
The row's `engine.scope` (`policy/gate-registry.yaml`, `DOC-002`)
|
|
39
|
-
|
|
40
|
-
check. `scan_excluded`'s three rules below are a different thing: SUBJECT-MATTER
|
|
38
|
+
The row's `engine.scope` (`policy/gate-registry.yaml`, `DOC-002`) decides
|
|
39
|
+
SCOPE, not this check. `scan_excluded`'s rules below are a different thing: SUBJECT-MATTER
|
|
41
40
|
exclusions this gate owns, because they say what kind of content Han text is
|
|
42
|
-
allowed to be (hidden paths,
|
|
43
|
-
data directory), not where in the tree it lives.
|
|
41
|
+
allowed to be (hidden paths, any locale-named data directory), not where in the tree it lives.
|
|
44
42
|
"""
|
|
45
43
|
|
|
46
44
|
from __future__ import annotations
|
|
@@ -124,19 +122,6 @@ class DocsEnglishOnly(Check):
|
|
|
124
122
|
and `.../i18n/locales/<locale>/...` — where non-English text is the point,
|
|
125
123
|
not a defect. Mirrors check.sh's `scan_excluded` rule 3."""
|
|
126
124
|
|
|
127
|
-
inputs: ClassVar[dict[str, str]] = {"frontend_src": "<frontend>"}
|
|
128
|
-
"""FIXED 2026-09-16 (K-42 sweep, LOUD form, approved): `I18N_OWNER` was a
|
|
129
|
-
hardcoded `frontend/mobile/src/i18n` literal, matched against the given
|
|
130
|
-
set with `==`/`startswith` inside `_excluded` -- a rule 2 EXEMPTION, not a
|
|
131
|
-
filter over what gets scanned. A repository whose frontend root is not the
|
|
132
|
-
packaged default had its real i18n directory fail this match, so its
|
|
133
|
-
genuinely-translated strings were no longer exempt -- every one of them
|
|
134
|
-
became a false "raw Han text" finding. LOUD, not silent: the wrong path
|
|
135
|
-
does not go quiet, it makes real translated content look like a defect.
|
|
136
|
-
`mobile/src/i18n` stays literal below the resolved root: the settled
|
|
137
|
-
platform path, not a resolvable one, the same call TS-001's `MOBILE_SRC`
|
|
138
|
-
fix already made."""
|
|
139
|
-
|
|
140
125
|
FIX_BY_KIND: ClassVar[dict[str, str]] = {
|
|
141
126
|
"Han Unicode escape": "replace the \\u/\\U escape with the equivalent English text",
|
|
142
127
|
"raw Han text": "translate this Han-script text into English",
|
|
@@ -172,15 +157,14 @@ class DocsEnglishOnly(Check):
|
|
|
172
157
|
# it still exists on disk — check.sh's ALL_RELPATHS is filled before
|
|
173
158
|
# its own `[ -f "$rel" ]` guard, because a Han PATH is the finding
|
|
174
159
|
# there, distinct from Han CONTENT, which a deleted file no longer has.
|
|
175
|
-
i18n_owner = self._i18n_owner(ctx)
|
|
176
160
|
for relative in files:
|
|
177
|
-
if self._excluded(relative
|
|
161
|
+
if self._excluded(relative):
|
|
178
162
|
continue
|
|
179
163
|
if self.HAN_PATTERN.search(relative):
|
|
180
164
|
yield self._finding(relative, "Han filename")
|
|
181
165
|
|
|
182
166
|
for relative in files.existing(ctx.root):
|
|
183
|
-
if self._excluded(relative
|
|
167
|
+
if self._excluded(relative):
|
|
184
168
|
continue
|
|
185
169
|
suffix = self._path_suffix(relative).lower()
|
|
186
170
|
if suffix in self.OFFICE_SUFFIXES:
|
|
@@ -190,30 +174,11 @@ class DocsEnglishOnly(Check):
|
|
|
190
174
|
|
|
191
175
|
# ------------------------------------------------------ subject-matter scope
|
|
192
176
|
|
|
193
|
-
def
|
|
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"
|
|
206
|
-
|
|
207
|
-
def _excluded(self, relative: str, i18n_owner: str | None) -> bool:
|
|
177
|
+
def _excluded(self, relative: str) -> bool:
|
|
208
178
|
# 1. Hidden paths, by decision. Every component is tested.
|
|
209
179
|
if any(part.startswith(".") for part in relative.split("/")):
|
|
210
180
|
return True
|
|
211
|
-
# 2.
|
|
212
|
-
if i18n_owner is not None and (
|
|
213
|
-
relative == i18n_owner or relative.startswith(i18n_owner + "/")
|
|
214
|
-
):
|
|
215
|
-
return True
|
|
216
|
-
# 3. Any locale-named data directory, anywhere.
|
|
181
|
+
# 2. Any locale-named data directory, anywhere.
|
|
217
182
|
if self.LOCALE_DIR.search(relative):
|
|
218
183
|
return True
|
|
219
184
|
return False
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const strings = { greeting: "你好" };
|