@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.12 → 0.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adl +2 -2
- package/bin/git +16 -17
- package/bin/git-ado +25 -24
- package/bin/git-defaults +173 -0
- package/bin/health-check +8 -1
- package/bin/kimi-hooks +1 -1
- package/bin/lib/adl-package.sh +257 -0
- package/bin/lib/fleet-host.sh +8 -5
- package/bin/reconcile +482 -232
- package/bin/reconcile-host +30 -20
- package/bin/setup +20 -17
- package/bin/shell-path-policy +15 -5
- package/bin/sync-and-reconcile +62 -64
- package/bin/validate-manifest +33 -9
- package/package.json +2 -10
- package/packages/agent-hooks/README.md +14 -9
- package/packages/agent-hooks/assets/hooks.json +0 -20
- package/packages/agent-hooks/src/cli/args.ts +1 -1
- package/packages/agent-hooks/src/cli/doctor.ts +6 -58
- package/packages/agent-hooks/src/deploy/deploy.ts +12 -41
- package/packages/agent-hooks/src/deploy/doctor.ts +8 -11
- package/packages/agent-hooks/src/deploy/index.ts +14 -14
- package/packages/agent-hooks/src/deploy/json-merge.ts +7 -8
- package/packages/agent-hooks/src/deploy/legacy-lock.ts +2 -2
- package/packages/agent-hooks/src/deploy/list.ts +1 -1
- package/packages/agent-hooks/src/deploy/lock.ts +31 -12
- package/packages/agent-hooks/src/deploy/profile.ts +3 -4
- package/packages/agent-hooks/src/deploy/source.ts +1 -1
- package/packages/agent-hooks/src/gating/config.ts +12 -24
- package/packages/agent-hooks/src/gating/root.ts +3 -3
- package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
- package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
- package/packages/agent-hooks/src/hooks/contract.ts +17 -17
- package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
- package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
- package/packages/agent-hooks/src/hooks/log.ts +8 -10
- package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
- package/packages/agent-hooks/src/hosts/registry.ts +1 -1
- package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
- package/packages/agent-hooks/src/log/writer.ts +16 -2
- package/packages/agent-hooks/src/main.ts +7 -41
- package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
- package/packages/agent-hooks/src/rules/engine.ts +13 -17
- package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
- package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
- package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
- package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
- package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
- package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
- package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
- package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
- package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
- package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
- package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
- package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +131 -0
- package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
- package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
- package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
- package/packages/agent-hooks/src/rules/impl/tool-grep.ts +33 -12
- package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
- package/packages/agent-hooks/src/rules/ports.ts +5 -7
- package/packages/agent-hooks/src/rules/registry.ts +4 -6
- package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
- package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
- package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
- package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
- package/packages/agent-hooks/src/rules/spec.ts +2 -2
- package/packages/agent-settings/README.md +287 -0
- package/packages/agent-settings/assets/GLOBAL-AGENTS.md +14 -16
- package/packages/agent-settings/assets/agents/architect.toml +2 -0
- package/packages/agent-settings/assets/agents/code-reviewer.toml +2 -0
- package/packages/agent-settings/assets/agents/executor.toml +2 -0
- package/packages/agent-settings/assets/agents/explore.toml +2 -0
- package/packages/agent-settings/assets/agents/planner.toml +2 -0
- package/packages/agent-settings/assets/mcp.json +0 -4
- package/packages/agent-settings/deploy-profile.json +139 -0
- package/packages/agent-settings/deploy-profile.schema.json +147 -0
- package/packages/agent-settings/managed/README.md +29 -30
- package/packages/agent-settings/managed/codex-requirements.toml +9 -9
- package/packages/agent-settings/package.json +20 -0
- package/packages/agent-settings/src/deploy/agent-render.ts +2 -2
- package/packages/agent-settings/src/deploy/agent-toml.ts +1 -1
- package/packages/agent-settings/src/deploy/agents-deploy.ts +17 -3
- package/packages/agent-settings/src/deploy/doctor.ts +3 -83
- package/packages/agent-settings/src/deploy/index.ts +6 -33
- package/packages/agent-settings/src/deploy/legacy-lock.ts +6 -6
- package/packages/agent-settings/src/deploy/list.ts +5 -19
- package/packages/agent-settings/src/deploy/lock.ts +8 -18
- package/packages/agent-settings/src/deploy/mcp-deploy.ts +10 -5
- package/packages/agent-settings/src/deploy/mcp-merge.ts +22 -3
- package/packages/agent-settings/src/deploy/mcp-source.ts +1 -1
- package/packages/agent-settings/src/deploy/profile.ts +11 -35
- package/packages/agent-settings/src/deploy/retire-lean-ctx.ts +184 -0
- package/packages/agent-settings/src/deploy/settings.ts +17 -22
- package/packages/agent-settings/src/global-surface-sweep.ts +0 -2
- package/packages/agent-settings/src/kimi-hooks.ts +339 -192
- package/packages/agent-settings/src/opencode-hooks.ts +1 -1
- package/packages/agent-settings/tsconfig.json +23 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +120 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +276 -0
- package/packages/agent-skills/assets/debug-issue/SKILL.md +8 -7
- package/packages/agent-skills/assets/explore-codebase/SKILL.md +13 -13
- package/packages/agent-skills/assets/refactor-safely/SKILL.md +12 -11
- package/packages/agent-skills/assets/review-changes/SKILL.md +7 -7
- package/packages/agent-skills/assets/testing/references/e2e.md +37 -0
- package/packages/agent-skills/assets/testing/references/integration.md +37 -0
- package/packages/agent-skills/assets/testing/references/unit.md +32 -0
- package/packages/agent-skills/dist/deploy.d.ts +2 -0
- package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
- package/packages/agent-skills/dist/deploy.js +27 -1
- package/packages/agent-skills/dist/deploy.js.map +1 -1
- package/packages/agent-skills/dist/doctor.d.ts +0 -2
- package/packages/agent-skills/dist/doctor.d.ts.map +1 -1
- package/packages/agent-skills/dist/doctor.js +1 -1
- package/packages/agent-skills/dist/doctor.js.map +1 -1
- package/packages/agent-skills/dist/fs-utils.d.ts +0 -1
- package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -1
- package/packages/agent-skills/dist/fs-utils.js +1 -1
- package/packages/agent-skills/dist/fs-utils.js.map +1 -1
- package/packages/agent-skills/src/deploy.ts +29 -1
- package/packages/agent-skills/src/doctor.ts +1 -1
- package/packages/agent-skills/src/fs-utils.ts +1 -1
- package/packages/azdo/README.md +10 -9
- package/packages/azdo/package.json +1 -3
- package/packages/azdo/scripts/probe-ado-rules.ts +311 -0
- package/packages/azdo/src/azdo-pl.ts +2 -54
- package/packages/azdo/src/azdo-pr-review.ts +4 -4
- package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
- package/packages/azdo/src/azdo-wit.ts +44 -2
- package/packages/azdo/src/lib/agent-identity.ts +12 -14
- package/packages/azdo/src/lib/agent-token.ts +2 -2
- package/packages/azdo/src/lib/client.ts +0 -5
- package/packages/azdo/src/lib/graph-identity.ts +4 -4
- package/packages/azdo/src/workflow-ladder.csv +241 -0
- package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
- package/packages/azdo/src/workflow-rules.ts +194 -0
- package/packages/fleet/manifest.json +35 -11
- package/packages/fleet/manifest.schema.json +62 -10
- package/packages/fleet/src/default-agent-file.ts +3 -3
- package/packages/fleet/src/install-adl-package.ts +73 -15
- package/packages/fleet/src/install-embedding-model.ts +13 -13
- package/packages/fleet/src/managed-settings.ts +7 -7
- package/packages/fleet/src/repo-maintain.ts +91 -55
- package/packages/fleet/src/scratch-reap.ts +5 -5
- package/packages/fleet/src/vscode-settings.ts +5 -5
- package/packages/repo-controls/README.md +141 -43
- package/packages/repo-controls/assets/promote.ts +4 -4
- package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
- package/packages/repo-controls/assets/version-bump.sh +31 -84
- package/packages/repo-controls/bunfig.toml +6 -7
- package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
- package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/sub/nested.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-001-tenancy.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-002-carrier.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-003-cli.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-old.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-older.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-01.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-02.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-03.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-04.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-05.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-06.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-07.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-08.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-09.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-10.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-11.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-12.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-13.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-14.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-15.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-16.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/e.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/short/only.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-legacy/docs/compliance/index.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-type/docs/compliance/index.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/no-type.md +9 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-experiment.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-research.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs/architecture/bad-status.md +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-last-update.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/created-date.md +21 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/research-shaped.md +19 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/a.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/b.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/a.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/b.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/c.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +258 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plan_metadata.py +9 -4
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/items/az351-restore-entrypoint.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +3 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
- package/packages/repo-controls/package.json +2 -9
- package/packages/repo-controls/scripts/hooks/post-merge +13 -0
- package/packages/repo-controls/scripts/hooks/pre-push +3 -3
- package/packages/repo-controls/src/azdo-push.ts +64 -36
- package/packages/repo-controls/src/azure-devops-governance.ts +7 -9
- package/packages/repo-controls/src/azure-devops-remote.ts +1 -1
- package/packages/repo-controls/src/cli.ts +29 -8
- package/packages/repo-controls/src/compliance-config.ts +410 -2
- package/packages/repo-controls/src/config.ts +133 -60
- package/packages/repo-controls/src/constants.ts +13 -27
- package/packages/repo-controls/src/coverage-ratchet.ts +4 -4
- package/packages/repo-controls/src/doctor.ts +46 -19
- package/packages/repo-controls/src/gitignore-block.ts +5 -29
- package/packages/repo-controls/src/hook-log.ts +1 -2
- package/packages/repo-controls/src/hook.ts +201 -45
- package/packages/repo-controls/src/install.ts +14 -8
- package/packages/repo-controls/src/integrity.ts +3 -3
- package/packages/repo-controls/src/lfs.ts +111 -0
- package/packages/repo-controls/src/promote.ts +8 -8
- package/packages/repo-controls/src/runtime.ts +9 -1
- package/packages/repo-controls/src/workflows-drift.ts +4 -5
- package/packages/repo-controls/src/worktree-guard.ts +3 -3
|
@@ -22,12 +22,20 @@
|
|
|
22
22
|
* integration/main/master/develop and HEAD are never deleted, the KEEP
|
|
23
23
|
* most recent branches are kept, and only "[gone]" upstreams (-D) or
|
|
24
24
|
* branches merged into the baseline (-d) are deleted;
|
|
25
|
-
* 4.
|
|
25
|
+
* 4. the stale-branch prune (only when `branchMaxAgeDays` is configured, from
|
|
26
|
+
* the manifest's `config.repo_maintain.branch_max_age_days`): every local
|
|
27
|
+
* branch whose TIP commit is older than that many days is deleted with
|
|
28
|
+
* `git branch -D` -- never integration/main/master/develop, the checked-out
|
|
29
|
+
* HEAD, or a branch checked out in any worktree. Each deletion is a
|
|
30
|
+
* `WARN repo-maintain: <repo>: deleted stale branch <name> at <sha> (last
|
|
31
|
+
* commit <date>)` line, which is how a deleted branch is recovered from the
|
|
32
|
+
* log (`git branch <name> <sha>`); a dry run lists them without deleting;
|
|
33
|
+
* 5. `adl install --repo <repo>` -- the existing per-repo enrolment.
|
|
26
34
|
*
|
|
27
35
|
* This runs as the device administrator, never root (the caller,
|
|
28
36
|
* bin/reconcile-host, drops privileges and `adl maintain --expect-user`
|
|
29
|
-
* refuses otherwise). It never migrates enact-config.toml:
|
|
30
|
-
* both markers
|
|
37
|
+
* refuses otherwise). It never reads, migrates or modifies enact-config.toml:
|
|
38
|
+
* a repo may carry both markers, and adl-config.toml alone decides scope.
|
|
31
39
|
*
|
|
32
40
|
* Reporting: plain progress lines go to `out`; every warning and failure goes
|
|
33
41
|
* to `err` as `WARN repo-maintain: ...` / `ERROR repo-maintain: ...` (the
|
|
@@ -42,9 +50,7 @@ import { NO_AGENT_IDENTITY_MESSAGE, resolveAgentIdentity } from '../../azdo/src/
|
|
|
42
50
|
export const TCC_DENIED_MARKER = 'TCC denied'
|
|
43
51
|
|
|
44
52
|
/** The file whose presence puts a repository in this step's scope. */
|
|
45
|
-
|
|
46
|
-
/** The retired marker; a repo with both is ambiguous and fails loud. */
|
|
47
|
-
const LEGACY_MARKER = 'enact-config.toml'
|
|
53
|
+
const MARKER = 'adl-config.toml'
|
|
48
54
|
|
|
49
55
|
/** Branches fast-forwarded, in this order. */
|
|
50
56
|
const SYNCED_BRANCHES = ['integration', 'main'] as const
|
|
@@ -65,6 +71,14 @@ export interface MaintainOptions {
|
|
|
65
71
|
readonly keep?: number
|
|
66
72
|
/** Report only: fetches, but never moves a ref, deletes a branch or runs install. */
|
|
67
73
|
readonly dryRun?: boolean
|
|
74
|
+
/**
|
|
75
|
+
* Delete local branches whose tip commit is older than this many days (a
|
|
76
|
+
* positive whole number). Unset: no age-based deletion. The manifest's
|
|
77
|
+
* `config.repo_maintain.branch_max_age_days`, never an environment variable.
|
|
78
|
+
*/
|
|
79
|
+
readonly branchMaxAgeDays?: number
|
|
80
|
+
/** The clock, injectable for tests. Default: the current time. */
|
|
81
|
+
readonly now?: () => Date
|
|
68
82
|
/** Environment for identity resolution and every child. Default process.env. */
|
|
69
83
|
readonly env?: NodeJS.ProcessEnv
|
|
70
84
|
readonly out?: (line: string) => void
|
|
@@ -87,15 +101,18 @@ export function listFailureLines(root: string, error: unknown, executable: strin
|
|
|
87
101
|
const code = (error as { code?: unknown } | null)?.code
|
|
88
102
|
if (code === 'ENOTDIR') return [`${root}: ${message}`]
|
|
89
103
|
const lines = [`${root}: cannot list: ${message}`]
|
|
90
|
-
if (code === 'EPERM')
|
|
91
|
-
lines.push(
|
|
92
|
-
`${root}: ${TCC_DENIED_MARKER}: macOS privacy protection blocked ${executable}; ` +
|
|
93
|
-
`one-time fix: System Settings › Privacy & Security › Full Disk Access › + › add ${executable}`,
|
|
94
|
-
)
|
|
95
|
-
}
|
|
104
|
+
if (code === 'EPERM') lines.push(tccDeniedLine(root, executable))
|
|
96
105
|
return lines
|
|
97
106
|
}
|
|
98
107
|
|
|
108
|
+
/** The one Full Disk Access hint, for a refused readdir and for a git child refused the same way. */
|
|
109
|
+
function tccDeniedLine(path: string, executable: string): string {
|
|
110
|
+
return (
|
|
111
|
+
`${path}: ${TCC_DENIED_MARKER}: macOS privacy protection blocked ${executable}; ` +
|
|
112
|
+
`one-time fix: System Settings › Privacy & Security › Full Disk Access › + › add ${executable}`
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
99
116
|
interface GitResult {
|
|
100
117
|
readonly ok: boolean
|
|
101
118
|
readonly stdout: string
|
|
@@ -120,29 +137,6 @@ function isForbiddenAzurePipelinesPath(path: string): boolean {
|
|
|
120
137
|
}
|
|
121
138
|
}
|
|
122
139
|
|
|
123
|
-
/** `packages/<name>/enact-config.toml` -- the per-package copies of the retired marker. */
|
|
124
|
-
function legacyMarkers(repo: string): string[] {
|
|
125
|
-
const found: string[] = []
|
|
126
|
-
const tryStat = (relative: string): void => {
|
|
127
|
-
try {
|
|
128
|
-
if (statSync(join(repo, relative)).isFile()) found.push(relative)
|
|
129
|
-
} catch (error) {
|
|
130
|
-
if (errorCode(error) !== 'ENOENT' && errorCode(error) !== 'ENOTDIR') throw error
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
tryStat(LEGACY_MARKER)
|
|
134
|
-
let packages: Dirent[] = []
|
|
135
|
-
try {
|
|
136
|
-
packages = readdirSync(join(repo, 'packages'), { withFileTypes: true })
|
|
137
|
-
} catch (error) {
|
|
138
|
-
if (errorCode(error) !== 'ENOENT' && errorCode(error) !== 'ENOTDIR') throw error
|
|
139
|
-
}
|
|
140
|
-
for (const entry of packages.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
141
|
-
if (entry.isDirectory()) tryStat(join('packages', entry.name, LEGACY_MARKER))
|
|
142
|
-
}
|
|
143
|
-
return found
|
|
144
|
-
}
|
|
145
|
-
|
|
146
140
|
export function maintainRepositories(options: MaintainOptions): MaintainResult {
|
|
147
141
|
const env = options.env ?? process.env
|
|
148
142
|
const keep = options.keep ?? DEFAULT_KEEP
|
|
@@ -165,6 +159,13 @@ export function maintainRepositories(options: MaintainOptions): MaintainResult {
|
|
|
165
159
|
return { ok: result.status === 0, stdout: result.stdout, stderr: result.stderr ?? '' }
|
|
166
160
|
}
|
|
167
161
|
|
|
162
|
+
const maxAgeDays = options.branchMaxAgeDays
|
|
163
|
+
if (maxAgeDays !== undefined && (!Number.isInteger(maxAgeDays) || maxAgeDays < 1)) {
|
|
164
|
+
fail(`branch max age must be a positive whole number of days: ${maxAgeDays}`, 'branch-max-age-days')
|
|
165
|
+
return { ok: false, repositories: 0, failures }
|
|
166
|
+
}
|
|
167
|
+
const now = options.now ?? ((): Date => new Date())
|
|
168
|
+
|
|
168
169
|
const { location } = options
|
|
169
170
|
if (!isAbsolute(location)) {
|
|
170
171
|
fail(`location must be an absolute path: ${location}`, location)
|
|
@@ -196,7 +197,7 @@ export function maintainRepositories(options: MaintainOptions): MaintainResult {
|
|
|
196
197
|
}
|
|
197
198
|
if (agent !== undefined) identityEnv = { ADL_AGENT_ID_AGENT: agent }
|
|
198
199
|
|
|
199
|
-
info(`start location=${location} keep=${keep} dry=${dry ? 1 : 0}`)
|
|
200
|
+
info(`start location=${location} keep=${keep} dry=${dry ? 1 : 0}${maxAgeDays === undefined ? '' : ` branch_max_age_days=${maxAgeDays}`}`)
|
|
200
201
|
|
|
201
202
|
let entries: Dirent[]
|
|
202
203
|
let locationReal: string
|
|
@@ -242,19 +243,10 @@ export function maintainRepositories(options: MaintainOptions): MaintainResult {
|
|
|
242
243
|
}
|
|
243
244
|
seen.add(real)
|
|
244
245
|
|
|
245
|
-
// 3. In scope from here on.
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
} catch (error) {
|
|
250
|
-
fail(`${real}: cannot read: ${error instanceof Error ? error.message : String(error)}`, real)
|
|
251
|
-
continue
|
|
252
|
-
}
|
|
253
|
-
if (legacy.length > 0) {
|
|
254
|
-
fail(`${real}: duplicate markers: ${MARKER} and ${LEGACY_MARKER} (${legacy.join(', ')}); migrate or remove one`, real)
|
|
255
|
-
continue
|
|
256
|
-
}
|
|
257
|
-
if (!isGitToplevel(real)) {
|
|
246
|
+
// 3. In scope from here on. enact-config.toml may sit beside the marker; it is never read.
|
|
247
|
+
const toplevel = gitToplevelState(real)
|
|
248
|
+
if (toplevel === 'failed') continue
|
|
249
|
+
if (toplevel === 'not-toplevel') {
|
|
258
250
|
warn(`${real}: ${MARKER} but not a git top-level; skipped`)
|
|
259
251
|
continue
|
|
260
252
|
}
|
|
@@ -265,13 +257,33 @@ export function maintainRepositories(options: MaintainOptions): MaintainResult {
|
|
|
265
257
|
info(`done (${repositories} repositories, ${failures.length} failed)`)
|
|
266
258
|
return { ok: failures.length === 0, repositories, failures }
|
|
267
259
|
|
|
268
|
-
|
|
260
|
+
/**
|
|
261
|
+
* 'not-toplevel' only on git's own "not a git repository" answer (exit 128) or
|
|
262
|
+
* a toplevel that is a different directory. Anything else (spawn error, other
|
|
263
|
+
* exit status, unresolvable toplevel) is reported here as a failure naming the
|
|
264
|
+
* directory, and the repo is not maintained: it may hide an in-scope repository.
|
|
265
|
+
*/
|
|
266
|
+
function gitToplevelState(directory: string): 'toplevel' | 'not-toplevel' | 'failed' {
|
|
267
|
+
const command = 'git rev-parse --show-toplevel'
|
|
269
268
|
const top = spawnSync('git', ['-C', directory, 'rev-parse', '--show-toplevel'], { encoding: 'utf8', env: childEnv() })
|
|
270
|
-
if (top.error !== undefined
|
|
269
|
+
if (top.error !== undefined) {
|
|
270
|
+
fail(`${directory}: cannot run ${command}: ${top.error.message}`, directory)
|
|
271
|
+
return 'failed'
|
|
272
|
+
}
|
|
273
|
+
const stderr = (top.stderr ?? '').trim()
|
|
274
|
+
if (top.status === 128 && stderr.includes('not a git repository')) return 'not-toplevel'
|
|
275
|
+
if (top.status !== 0) {
|
|
276
|
+
const shown = stderr.split('\n').slice(0, 3).join(' | ')
|
|
277
|
+
fail(`${directory}: ${command} exited ${top.status ?? `by signal ${top.signal}`}: ${shown}`, directory)
|
|
278
|
+
// git's "Operation not permitted" is TCC refusing the files to this job's responsible process (adl).
|
|
279
|
+
if (stderr.includes('Operation not permitted')) errOut(`ERROR repo-maintain: ${tccDeniedLine(directory, options.executable)}`)
|
|
280
|
+
return 'failed'
|
|
281
|
+
}
|
|
271
282
|
try {
|
|
272
|
-
return realpathSync(top.stdout.trim()) === directory
|
|
273
|
-
} catch {
|
|
274
|
-
|
|
283
|
+
return realpathSync(top.stdout.trim()) === directory ? 'toplevel' : 'not-toplevel'
|
|
284
|
+
} catch (error) {
|
|
285
|
+
fail(`${directory}: cannot resolve git toplevel ${top.stdout.trim()}: ${error instanceof Error ? error.message : String(error)}`, directory)
|
|
286
|
+
return 'failed'
|
|
275
287
|
}
|
|
276
288
|
}
|
|
277
289
|
|
|
@@ -312,7 +324,10 @@ export function maintainRepositories(options: MaintainOptions): MaintainResult {
|
|
|
312
324
|
// 3. guarded prune.
|
|
313
325
|
prune(repo, name, current)
|
|
314
326
|
|
|
315
|
-
// 4. the
|
|
327
|
+
// 4. stale-branch prune: by the tip commit's age.
|
|
328
|
+
if (maxAgeDays !== undefined) pruneStale(repo, name, current, maxAgeDays)
|
|
329
|
+
|
|
330
|
+
// 5. the per-repo enrolment.
|
|
316
331
|
const argv = [...options.install.leadingArgs, 'install', '--repo', repo]
|
|
317
332
|
const shown = `adl install --repo ${repo}`
|
|
318
333
|
if (dry) {
|
|
@@ -368,6 +383,27 @@ export function maintainRepositories(options: MaintainOptions): MaintainResult {
|
|
|
368
383
|
}
|
|
369
384
|
}
|
|
370
385
|
|
|
386
|
+
function pruneStale(repo: string, name: string, current: string, days: number): void {
|
|
387
|
+
const cutoff = now().getTime() / 1000 - days * 86_400
|
|
388
|
+
// %1f (unit separator) cannot appear in a ref name, unlike `|`.
|
|
389
|
+
const format = '%(refname:short)%1f%(objectname)%1f%(committerdate:unix)%1f%(worktreepath)'
|
|
390
|
+
for (const line of lines(git(repo, 'for-each-ref', 'refs/heads/', `--format=${format}`).stdout)) {
|
|
391
|
+
const [branch = '', sha = '', committed = '', worktree = ''] = line.split('\x1f')
|
|
392
|
+
if (branch === '' || PROTECTED.has(branch) || branch === current) continue
|
|
393
|
+
const tip = Number(committed)
|
|
394
|
+
if (!Number.isFinite(tip) || tip >= cutoff) continue
|
|
395
|
+
// A branch checked out in any worktree (the main one included) is in use.
|
|
396
|
+
if (worktree !== '') {
|
|
397
|
+
info(`${name}: kept stale branch ${branch} (checked out in ${worktree})`)
|
|
398
|
+
continue
|
|
399
|
+
}
|
|
400
|
+
const described = `stale branch ${branch} at ${sha} (last commit ${new Date(tip * 1000).toISOString().slice(0, 10)})`
|
|
401
|
+
if (dry) info(`${name}: [dry] would delete ${described}`)
|
|
402
|
+
else if (git(repo, 'branch', '-D', branch).ok) warn(`${name}: deleted ${described}`)
|
|
403
|
+
else warn(`${name}: could not delete ${described}`)
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
371
407
|
function prune(repo: string, name: string, current: string): void {
|
|
372
408
|
const base = baselineFor(repo)
|
|
373
409
|
const keptRecent = new Set(
|
|
@@ -34,12 +34,12 @@ import { defaultAgentFilePath, type FleetPlatform } from './default-agent-file.t
|
|
|
34
34
|
// apps/cli/src/commands/mcp.ts's own cross-package import of packages/azdo:
|
|
35
35
|
// this workspace has no node_modules/@adl/* symlinks without `bun install`.
|
|
36
36
|
// packages/azdo/src/lib/agent-identity.ts is now THE one place the
|
|
37
|
-
// default-agent file is READ from
|
|
38
|
-
//
|
|
39
|
-
//
|
|
37
|
+
// default-agent file is READ from; this package's own default-agent-file.ts
|
|
38
|
+
// keeps only the WRITE side (`reconcileDefaultAgentFile`) plus the path
|
|
39
|
+
// computation both sides need.
|
|
40
40
|
import { NO_AGENT_IDENTITY_MESSAGE, resolveAgentIdentity } from '../../azdo/src/lib/agent-identity.ts'
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
type Mode = 'plan' | 'apply'
|
|
43
43
|
|
|
44
44
|
export type GitResult = { ok: boolean; stdout: string; stderr: string }
|
|
45
45
|
export type Git = (args: string[], cwd: string) => GitResult
|
|
@@ -530,7 +530,7 @@ function usage(): never {
|
|
|
530
530
|
process.exit(2)
|
|
531
531
|
}
|
|
532
532
|
|
|
533
|
-
|
|
533
|
+
function main(argv: string[]): number {
|
|
534
534
|
const repos: string[] = []
|
|
535
535
|
let mode: Mode = 'plan'
|
|
536
536
|
let idleDays = 1
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* format and default/named-profile directory shape, under its own
|
|
22
22
|
* `Application Support`/`.config` folder name (`Cursor` instead of `Code`) —
|
|
23
23
|
* this is the standard, well-known Cursor Application Support location
|
|
24
|
-
* (docs/
|
|
24
|
+
* (docs/research/research-2026-09-27-worktree-controls-per-surface.md confirms
|
|
25
25
|
* `~/.cursor/worktrees/<repo>/` for worktree storage and that
|
|
26
26
|
* `cursor.worktreeMaxCount` lives in "the regular Cursor settings.json (user
|
|
27
27
|
* or workspace scope, VS Code-style)", but does not separately spell out the
|
|
@@ -51,14 +51,14 @@ import { basename, dirname, isAbsolute, join } from 'node:path'
|
|
|
51
51
|
export type VscodePlatform = 'mac' | 'linux'
|
|
52
52
|
|
|
53
53
|
/** A managed setting's value: VS Code's two owned keys are boolean; Cursor's `worktreeMaxCount` is numeric. */
|
|
54
|
-
|
|
54
|
+
type SettingValue = boolean | number
|
|
55
55
|
|
|
56
56
|
export const REQUIRED_VSCODE_SETTINGS = {
|
|
57
57
|
'git.detectWorktrees': true,
|
|
58
58
|
'scm.alwaysShowRepositories': true,
|
|
59
59
|
} as const
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
const APPLY_TO_ALL_PROFILES_SETTING = 'workbench.settings.applyToAllProfiles'
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* `cursor.worktreeMaxCount` — docs/operations/worktree-guard.md L0. Deployed as a
|
|
@@ -75,7 +75,7 @@ export const REQUIRED_CURSOR_SETTINGS = {
|
|
|
75
75
|
'cursor.worktreeMaxCount': 3,
|
|
76
76
|
} as const
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
interface EditorSettingsSpec {
|
|
79
79
|
readonly requiredSettings: Readonly<Record<string, SettingValue>>
|
|
80
80
|
/** VS Code only: the setting id that collects a profile-wide apply-to-all list. Omit for editors with no confirmed equivalent (Cursor). */
|
|
81
81
|
readonly applyToAllProfilesSetting?: string
|
|
@@ -90,7 +90,7 @@ const CURSOR_SPEC: EditorSettingsSpec = {
|
|
|
90
90
|
requiredSettings: REQUIRED_CURSOR_SETTINGS,
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
interface VscodeSettingsFileResult {
|
|
94
94
|
readonly path: string
|
|
95
95
|
readonly changed: boolean
|
|
96
96
|
readonly missing: boolean
|
|
@@ -16,7 +16,8 @@ target repo (committed) adl (fleet-installed; see below)
|
|
|
16
16
|
.workflows/hooks/commit-msg ├─ sh stub ──▶ ├─ validates adl-config.toml [controls]
|
|
17
17
|
.workflows/hooks/pre-push │ exec ├─ checks bash >= 4
|
|
18
18
|
.workflows/hooks/post-commit │ └─ runs scripts/hooks/<name>
|
|
19
|
-
.workflows/hooks/post-checkout
|
|
19
|
+
.workflows/hooks/post-checkout │
|
|
20
|
+
.workflows/hooks/post-merge ─┘
|
|
20
21
|
adl-config.toml [controls] (config, shared file — see below) (package-owned script, config via env)
|
|
21
22
|
.workflows/repo-controls.lock.json (hashes)
|
|
22
23
|
local .git/config: core.hooksPath = .workflows/hooks
|
|
@@ -25,9 +26,9 @@ local .git/config: core.hooksPath = .workflows/hooks
|
|
|
25
26
|
- **Stubs** are POSIX `sh`, contain no paths, and fail loudly (with the install
|
|
26
27
|
command) when `adl` is not on `PATH` — never a silent skip. This package is
|
|
27
28
|
folded into the `adl` binary's `repo controls` namespace
|
|
28
|
-
(docs/architecture/cli-design.md §6
|
|
29
|
+
(docs/architecture/cli-design.md §6); it is never itself a
|
|
29
30
|
standalone global command — hard cut, no `adl-repo-controls` compat shim
|
|
30
|
-
(
|
|
31
|
+
(2026-09-27).
|
|
31
32
|
- **Bundled scripts** in `scripts/hooks/` are package-owned implementations.
|
|
32
33
|
They originated in enact-m5; commit `20ec790` removed the former byte-copy
|
|
33
34
|
tree and manifest when mechanism moved into this package. Their current
|
|
@@ -77,6 +78,53 @@ a release-configured pre-commit commits successfully with no network-capable
|
|
|
77
78
|
binary on `PATH` at all, and pre-push blocks by name when the token mint
|
|
78
79
|
fails and permits the push once it succeeds.
|
|
79
80
|
|
|
81
|
+
## Git LFS chaining (`pre-push`, `post-checkout`, `post-commit`, `post-merge`)
|
|
82
|
+
|
|
83
|
+
Installed repositories set `core.hooksPath=.workflows/hooks`, so git never runs
|
|
84
|
+
the `.git/hooks/{pre-push,post-checkout,post-commit,post-merge}` that
|
|
85
|
+
`git lfs install` writes. Before 2026-10-01 nothing in adl called git-lfs, so a
|
|
86
|
+
push of a commit carrying an LFS pointer succeeded **without uploading the
|
|
87
|
+
object** and left a broken pointer on the remote (live, enact-combined: a
|
|
88
|
+
broken WebM pointer had to be deleted by hand). `runHook` (`src/hook.ts`) now
|
|
89
|
+
chains each of those four hooks to `git lfs <hook> "$@"` (`src/lfs.ts`):
|
|
90
|
+
|
|
91
|
+
- **Only when the repository uses LFS:** a `filter=lfs` attribute in any
|
|
92
|
+
`.gitattributes` (tracked or untracked, nested included) or in
|
|
93
|
+
`.git/info/attributes`, a `.lfsconfig`, or `lfs.*` in the repository's own git
|
|
94
|
+
config. A repository without LFS never calls `git lfs`.
|
|
95
|
+
- **Fail loud, never skip:** LFS in use and no `git-lfs` on `PATH` is a hard
|
|
96
|
+
failure with the install command in the message; a failing `git lfs <hook>`
|
|
97
|
+
fails the hook (for `pre-push`, the push). A FAIL row is also written to the
|
|
98
|
+
hook log, because the bundled script has already logged its PASS by then.
|
|
99
|
+
- **`pre-push` order and stdin:** git writes the pushed ref lines once. `runHook`
|
|
100
|
+
reads them once and feeds the same bytes to the bundled script (branch rules)
|
|
101
|
+
and to `git lfs pre-push`. The LFS upload is the LAST step, after every adl
|
|
102
|
+
check passed, so a refused push uploads nothing. `post-merge` is a new hook
|
|
103
|
+
(`HOOK_NAMES`) whose only job is this chain; `doctor` therefore reports
|
|
104
|
+
`hook:post-merge`, and an already-installed repository needs `adl repo
|
|
105
|
+
controls install --repo .` once to project the stub.
|
|
106
|
+
- **Credentials — one boundary, no second path.** `bin/git-ado` authenticates an
|
|
107
|
+
agent's `git push` by exporting `GIT_CONFIG_COUNT` and a
|
|
108
|
+
`GIT_CONFIG_KEY_n=http.https://<host>/.extraHeader` /
|
|
109
|
+
`GIT_CONFIG_VALUE_n=Authorization: Bearer <token>` pair (`bin/git-ado`, the
|
|
110
|
+
two `exec env ... GIT_CONFIG_COUNT=` blocks); git passes its environment to
|
|
111
|
+
the hook. `runBundled` strips every `GIT_CONFIG_*` (`childEnv`) so adl's own
|
|
112
|
+
checks never hold the token, which is why the chain is TypeScript and not
|
|
113
|
+
bash: `runHook` still has the unstripped environment, and the one
|
|
114
|
+
`git lfs` spawn (`spawnGitLfs`) is the only child given it. git-lfs therefore
|
|
115
|
+
authenticates with exactly the pairs the parent `git push` had: same
|
|
116
|
+
mechanism, no second token mint, never the human's credential helper.
|
|
117
|
+
`tests/lfs-credential-boundary.test.ts` is the proof (real git-lfs, a local
|
|
118
|
+
LFS endpoint that requires the Bearer token and answers 401 otherwise, a
|
|
119
|
+
credential helper that records every call): every request carried the header,
|
|
120
|
+
the helper was never called, and with the header absent the helper IS called
|
|
121
|
+
(the control that makes the first claim falsifiable).
|
|
122
|
+
- **Explicit `git lfs push|pull|fetch` for agents** was refused in `bin/git-ado`
|
|
123
|
+
until that proof existed; it now takes the ordinary agent path. The refusal
|
|
124
|
+
must come back if `lfs-credential-boundary.test.ts` ever goes red. No agent-hooks
|
|
125
|
+
rule mentions LFS, so `git push` -> hook -> `git lfs pre-push` is not a
|
|
126
|
+
command an agent types and is not intercepted by any rule.
|
|
127
|
+
|
|
80
128
|
## Worktree-count backstop (`post-checkout`)
|
|
81
129
|
|
|
82
130
|
`MAX_WORKTREES` (`src/constants.ts`) is `3` — a repository may have at most 3
|
|
@@ -144,7 +192,7 @@ or a `Task`/`Agent` launch with `isolation: "worktree"`) — see
|
|
|
144
192
|
|
|
145
193
|
### Why bun (and not node)
|
|
146
194
|
|
|
147
|
-
This package is never distributed standalone (
|
|
195
|
+
This package is never distributed standalone (since 2026-09-27):
|
|
148
196
|
`adl repo controls <command>` folds it into the one `adl` binary
|
|
149
197
|
(docs/architecture/cli-design.md §6), which the fleet installs via `bin/reconcile`'s
|
|
150
198
|
`bun-compile` manager; `apps/cli/src/commands/repo-controls.ts` resolves this
|
|
@@ -186,7 +234,7 @@ centralization are documented in
|
|
|
186
234
|
adl-repo-controls install --repo <path> [--dry-run]
|
|
187
235
|
adl-repo-controls uninstall --repo <path> [--dry-run]
|
|
188
236
|
adl-repo-controls doctor --repo <path> [--json]
|
|
189
|
-
adl-repo-controls hook <pre-commit|commit-msg|pre-push|post-commit> [git hook args]
|
|
237
|
+
adl-repo-controls hook <pre-commit|commit-msg|pre-push|post-commit|post-checkout|post-merge> [git hook args]
|
|
190
238
|
adl-repo-controls log <hook-name> <reason> [context] [message] (internal — called by the bundled hooks)
|
|
191
239
|
adl-repo-controls promote --repo <path>
|
|
192
240
|
adl-repo-controls run <azdo-push|coverage|repo-hygiene|validate-pr-metadata> --repo <path> [-- args]
|
|
@@ -229,21 +277,56 @@ merge into `integration`) runs.
|
|
|
229
277
|
**doctor** is read-only and exits 1 on any failure: bash >= 4, bun, binary on
|
|
230
278
|
PATH, the bundled compliance package present at its packaged path, repository
|
|
231
279
|
root, `[controls]` config validity, (warning) `coverage/coverage-summary.json`
|
|
232
|
-
exists whenever `pre_push.coverage_ratchet` is enabled
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
coverage
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
280
|
+
exists whenever `pre_push.coverage_ratchet` is enabled (`coverage_ratchet`
|
|
281
|
+
defaults ON; the gate is a no-op until the file lands, so this is informational
|
|
282
|
+
rather than blocking), (warning) `pre_push.coverage_produce` enabled with no
|
|
283
|
+
`[controls.coverage].produce_push` declared (the push gate fails loud there, so
|
|
284
|
+
doctor names it first), `[controls.compliance]` config validity, `uv` on PATH
|
|
285
|
+
(only checked once `[controls.compliance].enabled` is non-empty; otherwise
|
|
286
|
+
reported ok unconditionally, same on-by-default posture as the coverage-summary
|
|
287
|
+
check), (warning only, same conditioning) `ast-grep` on PATH, lock, each stub
|
|
288
|
+
(present, unedited, executable), `core.hooksPath`, `.gitignore` lines, and
|
|
289
|
+
(warning) lock version skew. When `[controls.release]` is declared, it also
|
|
290
|
+
derives the configured `origin` remote, loads the validated canonical Agent
|
|
291
|
+
Vault file before reading Azure DevOps, and records separate fail-closed
|
|
292
|
+
receipts for the HTTPS handle, required owner reviewer, minimum-review reset,
|
|
293
|
+
and (only when one is present) build policy.
|
|
241
294
|
|
|
242
295
|
**run** executes a bundled enact-m5 tool against the repository with the config
|
|
243
296
|
exported: `azdo-push` (Azure DevOps push with push lock + behind-origin refusal),
|
|
244
297
|
`coverage <check-push|prewarm-push|status|unlock|...>`, `repo-hygiene` (CI
|
|
245
298
|
entrypoint), `validate-pr-metadata` (Azure PR title/description policy).
|
|
246
299
|
|
|
300
|
+
#### azdo-push: one credential boundary
|
|
301
|
+
|
|
302
|
+
`azdo-push` mints and injects **no credential** (Tarun, 2026-10-01). Its git
|
|
303
|
+
children run through the managed front controller (`/usr/local/bin/git` ->
|
|
304
|
+
`bin/git-ado`), the only place a token is minted and a header added. What
|
|
305
|
+
`azdo-push` does contribute is `ADL_AGENT_ID_AGENT=<resolved agent>` on every
|
|
306
|
+
git spawn (so the controller mints for the right agent) and the removal of any
|
|
307
|
+
inherited `ADL_HUMAN_AZDO`. It refuses, before any network call, when no agent
|
|
308
|
+
identity resolves, and when the `git` on `PATH` does not carry the
|
|
309
|
+
`# Managed by adl global-tools.` marker (a plain git would fall to the human
|
|
310
|
+
credential helper).
|
|
311
|
+
|
|
312
|
+
**Verify on the wire** that a request carries exactly one `Authorization`
|
|
313
|
+
header. Git redacts the value by default (`GIT_TRACE_REDACT`, on unless set to
|
|
314
|
+
`0` -- never set it), so the trace is safe to read and to paste:
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
GIT_TRACE_CURL=1 GIT_TRACE_CURL_NO_DATA=1 git ls-remote origin HEAD 2>&1 \
|
|
318
|
+
| rg '=> Send header: (GET|POST|Authorization)'
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Expect each `GET`/`POST` line to be followed by exactly one
|
|
322
|
+
`=> Send header: Authorization: Bearer <redacted>` line. Count them with
|
|
323
|
+
`... | rg -c '=> Send header: Authorization'` -- 1 for the single request of
|
|
324
|
+
`ls-remote`. Two per request means a second credential path is back (the old
|
|
325
|
+
behaviour was a global `http.extraheader` from `azdo-push` plus git-ado's own
|
|
326
|
+
URL-scoped header). `ls-remote` is read-only; to trace the push path itself, run
|
|
327
|
+
`GIT_TRACE_CURL=1 GIT_TRACE_CURL_NO_DATA=1 adl repo controls azdo-push` on a
|
|
328
|
+
branch you mean to push.
|
|
329
|
+
|
|
247
330
|
**run compliance** runs the bundled `adl-compliance` Python engine (via `uv`)
|
|
248
331
|
against the repository. `--root <repo>` is always injected first from `--repo`;
|
|
249
332
|
once `[controls.compliance].enabled` is non-empty, `--only <the enabled list, comma-joined>`
|
|
@@ -285,41 +368,47 @@ an inline table is one attribute, because editing inside one means rewriting byt
|
|
|
285
368
|
you own. Nothing is parsed and re-serialized; text is spliced into the table's span.
|
|
286
369
|
|
|
287
370
|
`[controls]` is strictly validated: unknown keys and wrong types are errors. An
|
|
288
|
-
**absent**
|
|
371
|
+
**absent** key takes its documented default, never an error. Most gates default
|
|
372
|
+
ON; the matching `[controls.<gate>]` keys are what configure them. A gate whose
|
|
373
|
+
wrapper is ON but whose configuration is missing is a no-op at hook time and a
|
|
374
|
+
*warning* at `doctor` time — informational, never blocking.
|
|
289
375
|
|
|
290
376
|
| Key | Seeded by install | Default when absent | enact-m5 | Effect |
|
|
291
377
|
|---|---|---|---|---|
|
|
292
378
|
| `branches.protected` | yes | *required* | `["main", "integration"]` | pre-push refuses while on these branches |
|
|
293
379
|
| `branches.prefixes` | yes | *required* | `["feat", "fix", "docs", "chore"]` | pre-push / azdo-push branch pattern `<prefix>/<kebab>` |
|
|
294
380
|
| `pre_push.remote` | yes | *required* | `"origin"` | remote azdo-push pushes to and reads status from |
|
|
295
|
-
| `pre_commit.
|
|
296
|
-
| `pre_commit.
|
|
297
|
-
| `pre_commit.
|
|
298
|
-
| `pre_push.coverage_ratchet` | no | `
|
|
299
|
-
| `pre_push.
|
|
381
|
+
| `pre_commit.staged_coverage` | no | `true` | `true` | enact-m5-only staged coverage measurement (no-op until `[controls.coverage].produce` is declared) |
|
|
382
|
+
| `pre_commit.doc_freshness` | no | `true` | opt in | a staged `docs/` or `plans/` `.md` carries a `last_update` stamped within 5h (no-op when no docs are staged) |
|
|
383
|
+
| `pre_commit.compliance` | no | `true` | `true` | staged adl-compliance gates (no-op until `[controls.compliance].enabled` is non-empty) |
|
|
384
|
+
| `pre_push.coverage_ratchet` | no | `true` | `true` | per outgoing commit, `coverage/coverage-summary.json` must exist and not regress (no-op until the file lands) |
|
|
385
|
+
| `pre_push.coverage_produce` | no | `false` | opt in | run the coverage MEASUREMENT at push via `[controls.coverage].produce_push` (fails the push when armed with no command declared) |
|
|
386
|
+
| `pre_push.findings_ratchet` | no | `true` | opt in | per outgoing commit, every declared static-analysis counter's findings must not exceed the committed floor (no-op until `[controls.findings].counters` is declared and the floor file lands) |
|
|
300
387
|
| `pre_push.static_checks` | no | `[]` | tsc, knip, svelte-check | `{ label, run }` commands run on an export of HEAD, pass cached per tree OID |
|
|
301
388
|
| `release.source` | no | `""` | `"integration"` | source branch for the managed promotion PR; no branch pair is guessed |
|
|
302
389
|
| `release.target` | no | `""` | `"main"` | target branch for the managed promotion PR |
|
|
303
390
|
| `release.merge_strategy` | no | `"squash"` | `"no-fast-forward"` | one of `squash`, `rebase`, `rebase-merge`, or `no-fast-forward` — sent to Azure DevOps as the matching wire value (`squash`, `rebase`, `rebaseMerge`, `noFastForward`) |
|
|
304
|
-
| `release.pre_bump` | no | `[]` | — | ordered, repository-relative script paths `version-bump.sh` runs from the repo root before the bump commit (the
|
|
305
|
-
|
|
306
|
-
### Release scripts —
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
integration
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
`integration`'s
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
391
|
+
| `release.pre_bump` | no | `[]` | — | ordered, repository-relative script paths `version-bump.sh` runs from the repo root before the bump commit (the Promote pipeline's Bump stage, on the checkout of the `integration` commit that triggered it) |
|
|
392
|
+
|
|
393
|
+
### Release scripts — Guard and Bump (Tarun, 2026-09-30; bump moved 2026-10-01)
|
|
394
|
+
|
|
395
|
+
Three pipelines (CI on PRs into `integration`, Promote on `integration`, CD on
|
|
396
|
+
`main`; `docs/architecture/cli-design.md` §6a). Two managed scripts:
|
|
397
|
+
|
|
398
|
+
- **`.workflows/reconcile-guard.sh --pr-source <source> --base integration`**
|
|
399
|
+
(CI pipeline, Guard stage) is read-only and fails, printing the reconcile
|
|
400
|
+
command (`git pull origin integration, then push`), unless the source
|
|
401
|
+
contains `integration`'s tip. It checks no version: PR CI bumps nothing,
|
|
402
|
+
because a PR's build-validation policy ignores `[skip ci]`.
|
|
403
|
+
- **`.workflows/version-bump.sh --file package.json --integration --push`**
|
|
404
|
+
(Promote pipeline, Bump stage) sets the manifest to the checked-out
|
|
405
|
+
`integration` commit's version + 1 patch, runs `release.pre_bump` scripts in
|
|
406
|
+
the same commit, commits `chore: bump version A to B [skip ci]` and pushes
|
|
407
|
+
`HEAD:refs/heads/integration` (a plain fast-forward as the build service,
|
|
408
|
+
which needs Contribute and "Bypass policies when pushing" there; never an
|
|
409
|
+
agent identity, never force). If `integration` moved since the checkout the
|
|
410
|
+
push is rejected and the script fails loud; the next merge's run bumps. The
|
|
411
|
+
old `--pr-source` mode is gone: it is an unknown argument.
|
|
323
412
|
|
|
324
413
|
### `release.pre_bump` — multi-language version bumps
|
|
325
414
|
|
|
@@ -395,10 +484,9 @@ sed -i.bak -E "s/^const Version = \".*\"/const Version = \"${ADL_NEXT_VERSION}\"
|
|
|
395
484
|
rm -f "${file}.bak"
|
|
396
485
|
```
|
|
397
486
|
|
|
398
|
-
`install` copies
|
|
487
|
+
`install` copies three package-owned standalone CI assets byte-for-byte:
|
|
399
488
|
|
|
400
489
|
- `.workflows/promote.ts`
|
|
401
|
-
- `.workflows/scripts/enable-integration-auto-complete.mjs`
|
|
402
490
|
- `.workflows/version-bump.sh`
|
|
403
491
|
- `.workflows/reconcile-guard.sh`
|
|
404
492
|
|
|
@@ -469,6 +557,13 @@ Note: with `coverage_ratchet = true` every pushed commit and its parent must
|
|
|
469
557
|
contain `coverage/coverage-summary.json` (Istanbul json-summary); commit a
|
|
470
558
|
baseline first or set it to `false`.
|
|
471
559
|
|
|
560
|
+
Note: with `coverage_produce = true` the coverage MEASUREMENT runs at push too,
|
|
561
|
+
through `[controls.coverage].produce_push` — measurement at push, grading at
|
|
562
|
+
push, so commits stay fast. `produce_push` is the push-appropriate command: it
|
|
563
|
+
runs against immutable HEAD before the push, so a check-mode run that never
|
|
564
|
+
mutates the index is the shape. Armed with no command declared, the gate fails
|
|
565
|
+
the push by name — a step that measures nothing is not a pass.
|
|
566
|
+
|
|
472
567
|
Note: with `findings_ratchet = true`, `[controls.findings]` says where the
|
|
473
568
|
floor lives (`floor`, default `compliance/ratchets/static-analysis-findings.yaml`)
|
|
474
569
|
and `[controls.findings.counters]` names the repository's own static-analysis
|
|
@@ -512,6 +607,9 @@ non-empty string.
|
|
|
512
607
|
| `enabled` | `[]` | gate ids (`RST-001`) or `domain.name` addresses (`rust.acp-boundary`) to grade; empty = installed, nothing runs |
|
|
513
608
|
| `registry` | `"default"` | forward-compatible; today both values point at the same packaged registry YAML |
|
|
514
609
|
| `[controls.compliance.trees]` | `{}` (no entries) | per-key path overrides; a key absent here keeps the packaged (source-shaped) default for that key |
|
|
610
|
+
| `[controls.compliance.limits]` | absent (engine defaults) | per-repository engine limits, strictly validated. `scripts_direct_files` (positive integer) replaces LAY-014's default of 15 direct files per scripts directory and reaches the engine as `--declare scripts-direct-files=N`; a value the engine cannot read as a positive integer is could-not-run, never a fall back to 15. The depth limit is not configurable. `open_gaps` and `open_plans` (each a positive integer) replace LAY-016's default cap of 10 open gaps and 10 open plans, independently, and reach the engine as `--declare open-gaps=N` / `--declare open-plans=N`; the same could-not-run rule applies to each, and a finding names the effective cap as `N open gaps, cap is M`. The engine default stays 10: a repository declares today's measured count and ratchets it down |
|
|
611
|
+
| `[controls.compliance.markdown]` | absent (no extra Markdown roots) | extra Markdown roots for LAY-006 (`layout.markdown-trees`), strictly validated. `roots` is an array of repository-relative directories whose Markdown is site or application content rather than documentation (an Astro site's `src/content/**/*.md`); LAY-006 admits `.md` and `.mdx` beneath each, in addition to the docs trees, so a declared root only ever widens the allowlist and absent is the stricter grade. Reaches the engine as one `--declare markdown-roots=a,b`. An entry that is empty, absolute, contains `,` or `=`, or has a `.`, `..` or empty path segment is rejected when the config loads (a trailing `/` is dropped); the engine refuses the same values as could-not-run (exit 2) |
|
|
612
|
+
| `[controls.compliance.lockfiles]` | absent (REP-002 keeps its tree-derived scope) | exactly which manifest and lockfile paths REP-002 (`repository.lockfile-integrity`) scans and grades, strictly validated. Four arrays: `bun_manifests` / `bun_lockfiles` and `cargo_manifests` / `cargo_lockfiles`. A manifest entry is a repository-relative path or glob ending in `package.json` (`Cargo.toml`), such as `package.json` or `apps/*/package.json`; a lockfile entry is a literal path (a missing one is reported by name). An ecosystem is declared as a pair, and a declared pair replaces that ecosystem's default (`<typescript>/package.json` + `<typescript>/bun.lock`, the `<rust>` pair) in both what selects the gate and what it grades; an undeclared ecosystem is unchanged. Reaches the engine as `--declare bun-manifests=a,b`, `bun-lockfiles=`, `cargo-manifests=`, `cargo-lockfiles=` (a list is omitted when empty); a declared manifest that matches no file is could-not-run naming it. An entry that is empty, absolute, duplicated, contains `,` `=` `\` `<` `>` `{` `}`, starts with `!`, has a `.`, `..` or empty path segment, ends in the wrong file name, or (for a lockfile) is a glob, an ecosystem with only one of its two lists, and a `REP-002:bun_lock` / `cargo_lock` / `cargo_manifest` / `workspace` input beside the pair it supersedes are all rejected when the config loads; the engine refuses the same values as could-not-run (exit 2) |
|
|
515
613
|
|
|
516
614
|
### Registry curation
|
|
517
615
|
|
|
@@ -534,5 +632,5 @@ bun test --coverage # 100% lines + functions gate (bunfig.toml)
|
|
|
534
632
|
```
|
|
535
633
|
|
|
536
634
|
Tests run real git in temporary repositories under `.scratchpad/test-tmp/`
|
|
537
|
-
(gitignored), exercising the installed stubs end to end. CI
|
|
538
|
-
|
|
635
|
+
(gitignored), exercising the installed stubs end to end. CI runs them through
|
|
636
|
+
the repository's root pipelines under `workflows/pipelines/`.
|
|
@@ -90,7 +90,7 @@ interface PullRequestList {
|
|
|
90
90
|
value?: PullRequest[]
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
interface PolicyScope {
|
|
94
94
|
repositoryId?: string
|
|
95
95
|
refName?: string
|
|
96
96
|
matchKind?: string
|
|
@@ -111,12 +111,12 @@ export interface PolicyConfiguration {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
interface PolicyConfigurationList {
|
|
115
115
|
value?: PolicyConfiguration[]
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
const MINIMUM_REVIEWER_POLICY_TYPE = 'fa4e907d-c16b-4a4c-9dfa-4906e5d171dd'
|
|
119
|
+
const BUILD_POLICY_TYPE = '0609b952-1397-4640-95ec-e00a01b2c241'
|
|
120
120
|
|
|
121
121
|
/** `release: promote <source> to <target>` — derived, never declared. */
|
|
122
122
|
export function promotionTitle(source: string, target: string): string {
|