@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
package/bin/adl
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: package/bin/adl
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 82912736 bytes
|
|
4
|
+
sha256: 1a2ae55423977502b4d00c4c8ba08eac8d3c2d4d9388c934b0ea1f7ff80efe72
|
package/bin/git
CHANGED
|
@@ -117,7 +117,7 @@ done
|
|
|
117
117
|
(( command_index >= 0 )) || exec "$real_git" ${args[@]+"${args[@]}"}
|
|
118
118
|
command_name="${args[command_index]}"
|
|
119
119
|
|
|
120
|
-
# L1 worktree guard (
|
|
120
|
+
# L1 worktree guard (docs/operations/worktree-guard.md): refuse
|
|
121
121
|
# `git worktree add` when the repository already has 3 checkouts, including
|
|
122
122
|
# the main folder. Runs BEFORE the network-command routing below because it
|
|
123
123
|
# applies to every command line, not only Azure DevOps ones, and to humans
|
|
@@ -567,22 +567,21 @@ case "$command_name" in
|
|
|
567
567
|
done
|
|
568
568
|
;;
|
|
569
569
|
lfs)
|
|
570
|
-
# GAP (second independent review, 2026-09-29)
|
|
571
|
-
#
|
|
572
|
-
#
|
|
573
|
-
#
|
|
574
|
-
# through
|
|
575
|
-
#
|
|
576
|
-
#
|
|
577
|
-
#
|
|
578
|
-
# human
|
|
579
|
-
#
|
|
580
|
-
#
|
|
581
|
-
#
|
|
582
|
-
#
|
|
583
|
-
#
|
|
584
|
-
#
|
|
585
|
-
# refuses, exactly as for every other verb.
|
|
570
|
+
# GAP (second independent review, 2026-09-29): `git lfs push|pull|fetch`
|
|
571
|
+
# against an Azure DevOps remote reaches the real `git-lfs` binary (a
|
|
572
|
+
# SEPARATE executable git dispatches to via PATH, never through THIS
|
|
573
|
+
# controller's own real_git exec) with no identity at all, so it is routed
|
|
574
|
+
# through git-ado like every other network verb. git-ado applies the one
|
|
575
|
+
# policy: human (TTY+marker) passes through unchanged; an agent identity
|
|
576
|
+
# authenticates with the same `http.<url>.extraHeader` GIT_CONFIG_*
|
|
577
|
+
# mechanism as `git push` (proved to be honored by git-lfs, with no fallback
|
|
578
|
+
# to the human credential helper, in packages/repo-controls/tests/
|
|
579
|
+
# lfs-credential-boundary.test.ts -- it was refused for agents until that
|
|
580
|
+
# proof existed); no identity and no human marker is refused, as for every
|
|
581
|
+
# other verb. Other `git lfs` subcommands -- notably `pre-push`,
|
|
582
|
+
# `post-checkout`, `post-commit` and `post-merge`, which the projected hooks
|
|
583
|
+
# run inside a `git push` that already carries the header -- never reach
|
|
584
|
+
# the network through here and are not routed.
|
|
586
585
|
lfs_sub=''
|
|
587
586
|
lfs_sub_index=-1
|
|
588
587
|
for ((index = command_index + 1; index < ${#args[@]}; index += 1)); do
|
package/bin/git-ado
CHANGED
|
@@ -15,16 +15,17 @@
|
|
|
15
15
|
# three Entra service principals: agent-tarun, agent-vivek, agent-reviewer.
|
|
16
16
|
# Agents never see a secret.
|
|
17
17
|
#
|
|
18
|
-
# HUMAN PATH (
|
|
18
|
+
# HUMAN PATH (fail closed: the human opts in; Tarun, 2026-09-29).
|
|
19
19
|
# An unset/empty ADL_AGENT_ID_AGENT is passed through to the human's own
|
|
20
20
|
# credential helper (Git Credential Manager, etc.) ONLY when BOTH stdin is
|
|
21
21
|
# a real terminal AND ADL_HUMAN_AZDO is the exact string "1" -- Tarun
|
|
22
|
-
# exports it from his own `.zshrc` (
|
|
23
|
-
#
|
|
24
|
-
#
|
|
22
|
+
# exports it from his own `.zshrc` ("its not only git, its azdo": the
|
|
23
|
+
# marker governs every human Azure DevOps path, not only this script;
|
|
24
|
+
# `adl run` strips it from a child's environment and the adl hook denies
|
|
25
|
+
# any agent command that sets it). Otherwise this script refuses outright, by name, before
|
|
25
26
|
# touching git at all: the earlier "unset means human" rule relied
|
|
26
27
|
# entirely on the adl hook denying an agent's Azure DevOps network git
|
|
27
|
-
# command that omits ADL_AGENT_ID_AGENT
|
|
28
|
+
# command that omits ADL_AGENT_ID_AGENT -- a host the hook
|
|
28
29
|
# cannot rewrite on, or a chained/opaque shell shape the hook's walker
|
|
29
30
|
# misses, reached THIS script with no agent identity and no TTY, and used
|
|
30
31
|
# to be treated as human regardless. `adl id whoami`
|
|
@@ -311,10 +312,10 @@ ado_host="$(printf '%s' "$remote_url" | tr '[:upper:]' '[:lower:]')"
|
|
|
311
312
|
ado_host="${ado_host#https://}"
|
|
312
313
|
ado_host="${ado_host%%/*}"
|
|
313
314
|
|
|
314
|
-
# HUMAN PASS-THROUGH (
|
|
315
|
-
#
|
|
315
|
+
# HUMAN PASS-THROUGH (fail closed: the human opts in; Tarun, 2026-09-29).
|
|
316
|
+
# Unset or empty ADL_AGENT_ID_AGENT passes through to the real git
|
|
316
317
|
# UNCHANGED only when this is also a marked human terminal: stdin is a real
|
|
317
|
-
# tty AND ADL_HUMAN_AZDO is the exact string "1"
|
|
318
|
+
# tty AND ADL_HUMAN_AZDO is the exact string "1". Anything
|
|
318
319
|
# else with no agent identity -- no marker, no tty, or both -- is refused
|
|
319
320
|
# outright, by name, before touching git at all. This is the ONE place that
|
|
320
321
|
# check is made in bash; `isMarkedHumanAzdoCaller` in
|
|
@@ -333,22 +334,22 @@ fi
|
|
|
333
334
|
# AGENT PATH.
|
|
334
335
|
require_agent_identity "$ADL_AGENT_ID_AGENT" || exit 1
|
|
335
336
|
|
|
336
|
-
#
|
|
337
|
-
#
|
|
338
|
-
#
|
|
339
|
-
# credential resolution
|
|
340
|
-
# `http.<url>.extraHeader` mechanism
|
|
341
|
-
#
|
|
342
|
-
#
|
|
343
|
-
#
|
|
344
|
-
#
|
|
345
|
-
#
|
|
346
|
-
#
|
|
347
|
-
#
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
337
|
+
# `git lfs push|pull|fetch` reaches here too (`is_network_command_name`
|
|
338
|
+
# includes `lfs`) and takes the SAME agent path as every other verb. It used to
|
|
339
|
+
# be refused (independent review, 2026-09-29, item 3) because git-lfs is a
|
|
340
|
+
# SEPARATE binary whose HTTP credential resolution had never been verified to
|
|
341
|
+
# honor the `http.<url>.extraHeader` mechanism below; if it ignored the header
|
|
342
|
+
# it would fall back to `git credential fill`, i.e. Git Credential Manager,
|
|
343
|
+
# i.e. the HUMAN. That doubt is settled by a test, not an assumption:
|
|
344
|
+
# packages/repo-controls/tests/lfs-credential-boundary.test.ts runs real
|
|
345
|
+
# git-lfs (3.8.0) against a local LFS endpoint that requires the Bearer token
|
|
346
|
+
# and a credential helper that records every call, with exactly this
|
|
347
|
+
# GIT_CONFIG_COUNT/KEY_n/VALUE_n mechanism: every request carried the header
|
|
348
|
+
# and the helper was never called (and, as the control, was called when the
|
|
349
|
+
# header was absent). The same proof covers the pre-push hook's
|
|
350
|
+
# `git lfs pre-push` (packages/repo-controls/src/lfs.ts), which inherits this
|
|
351
|
+
# environment from the `git push` this script runs. Had it failed, this would
|
|
352
|
+
# still be a refusal; it must become one again if that test ever goes red.
|
|
352
353
|
|
|
353
354
|
# adl-agent-id mints the session and runs `agent-vault run -- <child>`. The
|
|
354
355
|
# child asks `adl id token` for this agent's Entra token over the proxy
|
package/bin/git-defaults
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Managed by adl global-tools.
|
|
3
|
+
#
|
|
4
|
+
# Every host's human git setup is identical and kept that way by the 12-hourly
|
|
5
|
+
# reconcile (Tarun, 2026-10-01): no manual `git config` on any machine. This
|
|
6
|
+
# script sets the administrator's GLOBAL git config from the manifest:
|
|
7
|
+
#
|
|
8
|
+
# config.git_global_config shared by every host
|
|
9
|
+
# <platform>.common.git_global_config added for that platform only
|
|
10
|
+
# <platform>.devices.<device>.git_user user.name / user.email
|
|
11
|
+
#
|
|
12
|
+
# A value is a string (single-valued key) or an ordered array of strings
|
|
13
|
+
# (multi-valued key: the empty-reset-then-helper pattern of credential.helper).
|
|
14
|
+
# A key is rewritten only when its current values differ from the declared
|
|
15
|
+
# ordered list: single-valued via `git config --global KEY VALUE`, multi-valued
|
|
16
|
+
# via `--unset-all` then `--add` for each value in order. Keys the manifest does
|
|
17
|
+
# not declare (including any GitHub or gist credential helper a human set) are
|
|
18
|
+
# never read, changed or removed.
|
|
19
|
+
#
|
|
20
|
+
# Git Credential Manager is installed by the human (macOS: `brew install --cask
|
|
21
|
+
# git-credential-manager`; Linux: the .deb or tarball) -- reconcile never
|
|
22
|
+
# installs it. The one placeholder a value may carry, {git-credential-manager},
|
|
23
|
+
# is resolved at run time as the administrator (`command -v` on the explicit
|
|
24
|
+
# PATH below, which covers /usr/local/bin, /usr/local/share/gcm-core and the
|
|
25
|
+
# Homebrew/linuxbrew bins). When it is not installed, every key that needs it is
|
|
26
|
+
# skipped and left as it is, with one loud WARN; the next reconcile after the
|
|
27
|
+
# install sets it. Nothing is ever written that points at a missing executable.
|
|
28
|
+
#
|
|
29
|
+
# Headless Linux has no keychain, so the manifest's Linux common config sets
|
|
30
|
+
# GCM's credentialStore=cache (an in-memory credential cache daemon) with a
|
|
31
|
+
# one-week timeout instead of the macOS keychain.
|
|
32
|
+
#
|
|
33
|
+
# Git runs as the administrator (`sudo -u ADMIN -H env PATH=... git ...`) so
|
|
34
|
+
# ~/.gitconfig stays user-owned. Apply is invoked by bin/reconcile as root. Plan
|
|
35
|
+
# mode only reads, through sudo when run as root and as the caller otherwise.
|
|
36
|
+
set -euo pipefail
|
|
37
|
+
|
|
38
|
+
usage() {
|
|
39
|
+
echo 'usage: git-defaults --manifest FILE --platform mac|linux --device NAME --mode plan|apply --administrator USER [--path-dirs DIR:DIR...]' >&2
|
|
40
|
+
exit 2
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
manifest=''
|
|
44
|
+
platform=''
|
|
45
|
+
device=''
|
|
46
|
+
mode=''
|
|
47
|
+
administrator=''
|
|
48
|
+
# /usr/local/share/gcm-core comes first so a macOS cask install resolves to the
|
|
49
|
+
# real GCM path rather than its /usr/local/bin symlink. --path-dirs exists for
|
|
50
|
+
# tests; a real run never passes it.
|
|
51
|
+
path_dirs='/usr/local/share/gcm-core:/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin:/usr/sbin:/sbin'
|
|
52
|
+
while [[ $# -gt 0 ]]; do
|
|
53
|
+
case "$1" in
|
|
54
|
+
--manifest) manifest="${2:-}"; shift 2 ;;
|
|
55
|
+
--platform) platform="${2:-}"; shift 2 ;;
|
|
56
|
+
--device) device="${2:-}"; shift 2 ;;
|
|
57
|
+
--mode) mode="${2:-}"; shift 2 ;;
|
|
58
|
+
--administrator) administrator="${2:-}"; shift 2 ;;
|
|
59
|
+
--path-dirs) path_dirs="${2:-}"; shift 2 ;;
|
|
60
|
+
*) usage ;;
|
|
61
|
+
esac
|
|
62
|
+
done
|
|
63
|
+
[[ -n "$manifest" && -f "$manifest" ]] || usage
|
|
64
|
+
[[ "$platform" == mac || "$platform" == linux ]] || usage
|
|
65
|
+
[[ -n "$device" && -n "$administrator" && -n "$path_dirs" ]] || usage
|
|
66
|
+
[[ "$mode" == plan || "$mode" == apply ]] || usage
|
|
67
|
+
|
|
68
|
+
as_administrator() {
|
|
69
|
+
if [[ "$mode" == apply || "$(id -u)" -eq 0 ]]; then
|
|
70
|
+
(cd /tmp && sudo -u "$administrator" -H env PATH="$path_dirs" "$@" </dev/null)
|
|
71
|
+
else
|
|
72
|
+
(cd /tmp && env PATH="$path_dirs" "$@" </dev/null)
|
|
73
|
+
fi
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
scratch="$(mktemp -d "${TMPDIR:-/tmp}/git-defaults.XXXXXX")"
|
|
77
|
+
trap 'rm -rf -- "$scratch"' EXIT
|
|
78
|
+
|
|
79
|
+
# Current values of $1 into the global `current` array, in file order. Exit 1
|
|
80
|
+
# from git means the key is unset; any other failure is real and propagates.
|
|
81
|
+
read_current() {
|
|
82
|
+
local key="$1" rc=0 value
|
|
83
|
+
current=()
|
|
84
|
+
as_administrator git config --global -z --get-all "$key" >"$scratch/values" || rc=$?
|
|
85
|
+
if [[ "$rc" -eq 1 ]]; then
|
|
86
|
+
return 0
|
|
87
|
+
fi
|
|
88
|
+
[[ "$rc" -eq 0 ]] || { echo "ERROR git-config: git config --global --get-all $key failed (exit $rc)" >&2; return "$rc"; }
|
|
89
|
+
while IFS= read -r -d '' value; do
|
|
90
|
+
current+=("$value")
|
|
91
|
+
done <"$scratch/values"
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
gcm_path=''
|
|
95
|
+
gcm_resolved=0
|
|
96
|
+
resolve_gcm() {
|
|
97
|
+
[[ "$gcm_resolved" -eq 0 ]] || return 0
|
|
98
|
+
gcm_resolved=1
|
|
99
|
+
local found rc=0
|
|
100
|
+
found="$(as_administrator sh -c 'command -v git-credential-manager')" || rc=$?
|
|
101
|
+
if [[ "$rc" -eq 0 && "$found" == /* ]]; then
|
|
102
|
+
gcm_path="$found"
|
|
103
|
+
return 0
|
|
104
|
+
fi
|
|
105
|
+
echo "WARN git-config: git-credential-manager not installed on $device; credential helper not changed (install it, then the next reconcile sets it)" >&2
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
declared="$(jq -r --arg platform "$platform" --arg device "$device" '
|
|
109
|
+
. as $m
|
|
110
|
+
| ($m[$platform].devices[$device].git_user // error("git-config: device \($device) has no git_user in the manifest")) as $user
|
|
111
|
+
| ($m.config.git_global_config + ($m[$platform].common.git_global_config // {})
|
|
112
|
+
+ {"user.name": $user.name, "user.email": $user.email})
|
|
113
|
+
| to_entries[]
|
|
114
|
+
| [.key, (.value | if type == "array" then . else [.] end | tojson)]
|
|
115
|
+
| @tsv
|
|
116
|
+
' "$manifest")"
|
|
117
|
+
|
|
118
|
+
changed=0
|
|
119
|
+
while IFS=$'\t' read -r key values_json; do
|
|
120
|
+
[[ -n "$key" ]] || continue
|
|
121
|
+
wanted=()
|
|
122
|
+
needs_gcm=0
|
|
123
|
+
while IFS= read -r value; do
|
|
124
|
+
[[ "$value" != *'{git-credential-manager}'* ]] || needs_gcm=1
|
|
125
|
+
wanted+=("$value")
|
|
126
|
+
done < <(jq -r '.[]' <<<"$values_json")
|
|
127
|
+
if [[ "$needs_gcm" -eq 1 ]]; then
|
|
128
|
+
resolve_gcm
|
|
129
|
+
[[ -n "$gcm_path" ]] || continue
|
|
130
|
+
for index in "${!wanted[@]}"; do
|
|
131
|
+
wanted[index]="${wanted[index]//'{git-credential-manager}'/"$gcm_path"}"
|
|
132
|
+
done
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
read_current "$key"
|
|
136
|
+
same=0
|
|
137
|
+
if [[ "${#current[@]}" -eq "${#wanted[@]}" ]]; then
|
|
138
|
+
same=1
|
|
139
|
+
for index in "${!wanted[@]}"; do
|
|
140
|
+
[[ "${current[index]}" == "${wanted[index]}" ]] || same=0
|
|
141
|
+
done
|
|
142
|
+
fi
|
|
143
|
+
if [[ "$same" -eq 1 ]]; then
|
|
144
|
+
echo "git-config: already set $key"
|
|
145
|
+
continue
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
if [[ "${#wanted[@]}" -eq 1 ]]; then
|
|
149
|
+
shown="${wanted[0]}"
|
|
150
|
+
else
|
|
151
|
+
shown="$(jq -nc '$ARGS.positional' --args -- "${wanted[@]}")"
|
|
152
|
+
fi
|
|
153
|
+
if [[ "$mode" != apply ]]; then
|
|
154
|
+
echo "git-config: would set $key=$shown"
|
|
155
|
+
continue
|
|
156
|
+
fi
|
|
157
|
+
if [[ "${#wanted[@]}" -eq 1 && "${#current[@]}" -le 1 ]]; then
|
|
158
|
+
as_administrator git config --global "$key" "${wanted[0]}"
|
|
159
|
+
else
|
|
160
|
+
if [[ "${#current[@]}" -gt 0 ]]; then
|
|
161
|
+
as_administrator git config --global --unset-all "$key"
|
|
162
|
+
fi
|
|
163
|
+
for value in "${wanted[@]}"; do
|
|
164
|
+
as_administrator git config --global --add "$key" "$value"
|
|
165
|
+
done
|
|
166
|
+
fi
|
|
167
|
+
echo "git-config: set $key=$shown"
|
|
168
|
+
changed=$((changed + 1))
|
|
169
|
+
done <<<"$declared"
|
|
170
|
+
|
|
171
|
+
if [[ "$mode" == apply ]]; then
|
|
172
|
+
echo "git-config: $changed key(s) changed on $device"
|
|
173
|
+
fi
|
package/bin/health-check
CHANGED
|
@@ -21,7 +21,14 @@ case "$device" in
|
|
|
21
21
|
grep -q 'state = running'
|
|
22
22
|
;;
|
|
23
23
|
hostinger-vps-1)
|
|
24
|
-
systemctl is-active
|
|
24
|
+
# One unit per call: `systemctl is-active` given several units exits 0 when at
|
|
25
|
+
# least one is active, so a combined call cannot see a single unit being down.
|
|
26
|
+
for unit_name in docker tailscaled; do
|
|
27
|
+
systemctl is-active --quiet "$unit_name" || {
|
|
28
|
+
echo "required service is not active: $unit_name" >&2
|
|
29
|
+
exit 1
|
|
30
|
+
}
|
|
31
|
+
done
|
|
25
32
|
for container_name in nordvpn-exit-gluetun-1 nordvpn-exit-tailscale-1 traefik-traefik-1; do
|
|
26
33
|
[[ "$(docker inspect -f '{{.State.Running}}' "$container_name" 2>/dev/null)" == true ]] || {
|
|
27
34
|
echo "required container is not running: $container_name" >&2
|
package/bin/kimi-hooks
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
|
-
export PATH="/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
|
4
|
+
export PATH="/usr/local/bin:${HOME:-}/.bun/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
|
5
5
|
|
|
6
6
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
7
|
repo_root="$(cd "$script_dir/.." && pwd)"
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# Where the published adl package lives on a host, and how to prove it is the
|
|
2
|
+
# `adl` the owner gets. Sourced (never executed) by bin/sync-and-reconcile,
|
|
3
|
+
# bin/setup, bin/reconcile-host and bin/reconcile, so the scheduled job, the
|
|
4
|
+
# onboarding command and the reconcile itself all ask the same question the
|
|
5
|
+
# same way.
|
|
6
|
+
#
|
|
7
|
+
# Hosts install with bun (Tarun, 2026-10-01): `bun install -g
|
|
8
|
+
# @amsterdamdatalabs/adl-agent-control`, run as the device's `administrator`.
|
|
9
|
+
# Measured with bun 1.4.2 (packages: workflows/scripts/release/tests/
|
|
10
|
+
# bun-global-install.test.ts): bun HOISTS the platform package as a SIBLING of
|
|
11
|
+
# the wrapper, unlike npm, which nests it inside the wrapper:
|
|
12
|
+
#
|
|
13
|
+
# $HOME/.bun/install/global/node_modules/@amsterdamdatalabs/
|
|
14
|
+
# adl-agent-control/ the wrapper (bin/adl.js)
|
|
15
|
+
# adl-agent-control-<os>-<arch>/ the platform package this job runs from
|
|
16
|
+
# $HOME/.bun/bin/adl -> the wrapper's bin/adl.js
|
|
17
|
+
#
|
|
18
|
+
# bun marks ONLY `bin`-field targets executable; every other shipped file stays
|
|
19
|
+
# 0644, so nothing here ever executes a shipped script directly (always
|
|
20
|
+
# `bash <script>`) or checks it with -x.
|
|
21
|
+
#
|
|
22
|
+
# The owner's bun is found through Homebrew (macOS /opt/homebrew, Linux
|
|
23
|
+
# /home/linuxbrew/.linuxbrew), exactly as the owner's other global tools are.
|
|
24
|
+
|
|
25
|
+
adl_wrapper_package='@amsterdamdatalabs/adl-agent-control'
|
|
26
|
+
|
|
27
|
+
adl_brew_bin_dir() {
|
|
28
|
+
case "$1" in
|
|
29
|
+
Darwin) printf '%s\n' /opt/homebrew/bin ;;
|
|
30
|
+
Linux) printf '%s\n' /home/linuxbrew/.linuxbrew/bin ;;
|
|
31
|
+
*) echo "ERROR unsupported operating system for the adl package: $1" >&2; return 1 ;;
|
|
32
|
+
esac
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# PATH for the bun calls the job makes as the owner (install, nothing else).
|
|
36
|
+
adl_bun_path() {
|
|
37
|
+
local brew
|
|
38
|
+
brew="$(adl_brew_bin_dir "$1")" || return 1
|
|
39
|
+
printf '%s:/usr/bin:/bin\n' "$brew"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
# PATH the owner gets when it runs `adl` (the repo step, and the shadow check).
|
|
43
|
+
# /usr/local/bin stays FIRST: git must resolve to the managed front controller,
|
|
44
|
+
# which routes Azure DevOps traffic through the agent identity; Homebrew's git
|
|
45
|
+
# would bypass it. The owner's bun bin directory comes next, then Homebrew.
|
|
46
|
+
adl_owner_path() {
|
|
47
|
+
local os="$1" home="$2" brew
|
|
48
|
+
brew="$(adl_brew_bin_dir "$os")" || return 1
|
|
49
|
+
printf '/usr/local/bin:%s/.bun/bin:%s:/usr/bin:/bin\n' "${home%/}" "$brew"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# The owner's home directory, asked of the owner (never guessed from the name).
|
|
53
|
+
adl_owner_home() {
|
|
54
|
+
local owner="$1" home
|
|
55
|
+
home="$(cd /tmp && sudo -u "$owner" -H /bin/sh -c 'printf "%s" "$HOME"')" || return 1
|
|
56
|
+
[[ "$home" == /* ]] || { echo "ERROR cannot resolve the home directory of $owner" >&2; return 1; }
|
|
57
|
+
printf '%s\n' "${home%/}"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# bun's global package directory for an owner home. `bun pm bin -g` errors on a
|
|
61
|
+
# host that has never run `bun add -g`, so the path is derived, and pinned in
|
|
62
|
+
# the install call below with an explicit BUN_INSTALL.
|
|
63
|
+
adl_global_node_modules() {
|
|
64
|
+
printf '%s/.bun/install/global/node_modules\n' "${1%/}"
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
adl_platform_package_dir() {
|
|
68
|
+
local global_node_modules="$1" os="$2" arch="$3" platform
|
|
69
|
+
case "$os:$arch" in
|
|
70
|
+
Darwin:arm64) platform=darwin-arm64 ;;
|
|
71
|
+
Linux:x86_64) platform=linux-x64 ;;
|
|
72
|
+
*) echo "ERROR unsupported platform for the adl package: $os $arch" >&2; return 1 ;;
|
|
73
|
+
esac
|
|
74
|
+
# bun hoists the platform package next to the wrapper; it is not nested.
|
|
75
|
+
printf '%s/%s-%s\n' "${global_node_modules%/}" "$adl_wrapper_package" "$platform"
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# Real path of a file, following every symlink (macOS has no `readlink -f` on
|
|
79
|
+
# older releases, and the owner's command is always a symlink).
|
|
80
|
+
adl_realpath() {
|
|
81
|
+
local path="$1" link dir
|
|
82
|
+
while [[ -L "$path" ]]; do
|
|
83
|
+
link="$(readlink "$path")" || return 1
|
|
84
|
+
case "$link" in
|
|
85
|
+
/*) path="$link" ;;
|
|
86
|
+
*) path="$(dirname -- "$path")/$link" ;;
|
|
87
|
+
esac
|
|
88
|
+
done
|
|
89
|
+
dir="$(cd -P -- "$(dirname -- "$path")" 2>/dev/null && pwd -P)" || return 1
|
|
90
|
+
printf '%s/%s\n' "$dir" "$(basename -- "$path")"
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# The registry's `latest` for the package, asked of the owner. `bun pm view`
|
|
94
|
+
# needs a package.json in its working directory (measured with bun 1.4.2), and the
|
|
95
|
+
# owner's bun global directory always has one once the package is installed.
|
|
96
|
+
# Prints the version, or an error and a non-zero status: a failed lookup is never
|
|
97
|
+
# guessed around.
|
|
98
|
+
adl_registry_latest() {
|
|
99
|
+
local owner="$1" os="$2" home="$3" bun_path answer
|
|
100
|
+
bun_path="$(adl_bun_path "$os")" || return 1
|
|
101
|
+
answer="$(sudo -u "$owner" -H env PATH="$bun_path" BUN_INSTALL="${home%/}/.bun" /bin/sh -c 'cd "$1" && bun pm view "$2" version' sh "${home%/}/.bun/install/global" "$adl_wrapper_package")" || return 1
|
|
102
|
+
answer="$(printf '%s' "$answer" | tr -d '[:space:]')"
|
|
103
|
+
[[ "$answer" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$ ]] || {
|
|
104
|
+
echo "ERROR the registry answered '$answer' for $adl_wrapper_package, which is not a release version" >&2
|
|
105
|
+
return 1
|
|
106
|
+
}
|
|
107
|
+
printf '%s\n' "$answer"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# Compares two release versions (x.y.z with an optional -prerelease): prints -1, 0
|
|
111
|
+
# or 1 for A older than, equal to, or newer than B. Semver ordering: components
|
|
112
|
+
# numerically (0.1.9 < 0.1.10), a pre-release is older than its release, and
|
|
113
|
+
# pre-release identifiers compare numerically when both are numbers, numbers
|
|
114
|
+
# before words, else by text. A value that is not a version is an error.
|
|
115
|
+
adl_semver_compare() {
|
|
116
|
+
local a="$1" b="$2" re='^([0-9]+)\.([0-9]+)\.([0-9]+)(-([0-9A-Za-z.-]+))?$' i x y pre_a pre_b
|
|
117
|
+
local -a core_a core_b ids_a ids_b
|
|
118
|
+
[[ "$a" =~ $re ]] || { echo "ERROR not a release version: '$a'" >&2; return 1; }
|
|
119
|
+
core_a=("${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}")
|
|
120
|
+
pre_a="${BASH_REMATCH[5]:-}"
|
|
121
|
+
[[ "$b" =~ $re ]] || { echo "ERROR not a release version: '$b'" >&2; return 1; }
|
|
122
|
+
core_b=("${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}")
|
|
123
|
+
pre_b="${BASH_REMATCH[5]:-}"
|
|
124
|
+
for i in 0 1 2; do
|
|
125
|
+
if ((10#${core_a[i]} > 10#${core_b[i]})); then printf '1\n'; return 0; fi
|
|
126
|
+
if ((10#${core_a[i]} < 10#${core_b[i]})); then printf -- '-1\n'; return 0; fi
|
|
127
|
+
done
|
|
128
|
+
if [[ -z "$pre_a" && -z "$pre_b" ]]; then printf '0\n'; return 0; fi
|
|
129
|
+
if [[ -z "$pre_a" ]]; then printf '1\n'; return 0; fi
|
|
130
|
+
if [[ -z "$pre_b" ]]; then printf -- '-1\n'; return 0; fi
|
|
131
|
+
IFS=. read -r -a ids_a <<<"$pre_a"
|
|
132
|
+
IFS=. read -r -a ids_b <<<"$pre_b"
|
|
133
|
+
for ((i = 0; i < ${#ids_a[@]} || i < ${#ids_b[@]}; i++)); do
|
|
134
|
+
if ((i >= ${#ids_a[@]})); then printf -- '-1\n'; return 0; fi
|
|
135
|
+
if ((i >= ${#ids_b[@]})); then printf '1\n'; return 0; fi
|
|
136
|
+
x="${ids_a[i]}"
|
|
137
|
+
y="${ids_b[i]}"
|
|
138
|
+
if [[ "$x" =~ ^[0-9]+$ && "$y" =~ ^[0-9]+$ ]]; then
|
|
139
|
+
if ((10#$x > 10#$y)); then printf '1\n'; return 0; fi
|
|
140
|
+
if ((10#$x < 10#$y)); then printf -- '-1\n'; return 0; fi
|
|
141
|
+
elif [[ "$x" =~ ^[0-9]+$ ]]; then
|
|
142
|
+
printf -- '-1\n'; return 0
|
|
143
|
+
elif [[ "$y" =~ ^[0-9]+$ ]]; then
|
|
144
|
+
printf '1\n'; return 0
|
|
145
|
+
elif [[ "$x" < "$y" ]]; then
|
|
146
|
+
printf -- '-1\n'; return 0
|
|
147
|
+
elif [[ "$x" > "$y" ]]; then
|
|
148
|
+
printf '1\n'; return 0
|
|
149
|
+
fi
|
|
150
|
+
done
|
|
151
|
+
printf '0\n'
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
# Runs `bun add --global SPEC` as the owner, pinned to the owner's ~/.bun.
|
|
155
|
+
adl_bun_add_global() {
|
|
156
|
+
local owner="$1" os="$2" home="$3" spec="$4" bun_path
|
|
157
|
+
bun_path="$(adl_bun_path "$os")" || return 1
|
|
158
|
+
# cd /tmp: the caller's working directory may be unreadable to the owner (root's home), and sudo then fails.
|
|
159
|
+
(cd /tmp && sudo -u "$owner" -H env PATH="$bun_path" BUN_INSTALL="${home%/}/.bun" bun add --global "$spec")
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
# The `adl` the owner gets must be THIS package: a different one earlier on the
|
|
163
|
+
# owner's PATH (a legacy compiled /usr/local/bin/adl from before the package
|
|
164
|
+
# existed is the real case) would keep running instead of the package the job
|
|
165
|
+
# keeps up to date. Accepts the package's own bin/adl, or the wrapper's
|
|
166
|
+
# bin/adl.js that sits beside it (the link `bun install -g` puts on PATH).
|
|
167
|
+
# adl_check_adl_not_shadowed OWNER OS OWNER_HOME PACKAGE_REAL_DIR CONTEXT
|
|
168
|
+
adl_check_adl_not_shadowed() {
|
|
169
|
+
local owner="$1" os="$2" home="$3" package_real="$4" context="$5" path resolved real wrapper_real
|
|
170
|
+
path="$(adl_owner_path "$os" "$home")" || return 1
|
|
171
|
+
resolved="$(cd /tmp && sudo -u "$owner" -H env PATH="$path" /bin/sh -c 'command -v adl' 2>/dev/null)" || resolved=""
|
|
172
|
+
if [[ -z "$resolved" ]]; then
|
|
173
|
+
{
|
|
174
|
+
echo "ERROR $context: $owner has no 'adl' on PATH ($path)."
|
|
175
|
+
echo "ERROR $context: expected ${home%/}/.bun/bin/adl from: bun install -g $adl_wrapper_package (run as $owner)"
|
|
176
|
+
} >&2
|
|
177
|
+
return 1
|
|
178
|
+
fi
|
|
179
|
+
real="$(adl_realpath "$resolved")" || real="$resolved"
|
|
180
|
+
wrapper_real="$(adl_realpath "$(dirname -- "$package_real")/$(basename -- "$adl_wrapper_package")/bin/adl.js" 2>/dev/null)" || wrapper_real=""
|
|
181
|
+
if [[ "$real" == "$package_real/bin/adl" || ( -n "$wrapper_real" && "$real" == "$wrapper_real" ) ]]; then
|
|
182
|
+
return 0
|
|
183
|
+
fi
|
|
184
|
+
{
|
|
185
|
+
echo "ERROR $context: $owner's 'adl' is $resolved (-> $real), not this package's ($package_real/bin/adl)."
|
|
186
|
+
echo "ERROR $context: a different adl shadows the package, so the job would keep updating one adl while $owner runs another."
|
|
187
|
+
echo "ERROR $context: move it aside (never delete it), then run this again:"
|
|
188
|
+
echo "ERROR $context: sudo mv $resolved $resolved.legacy-$(date +%Y%m%d)"
|
|
189
|
+
} >&2
|
|
190
|
+
return 1
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# ---------------------------------------------------------------------------------------------
|
|
194
|
+
# The two reconcile locks (/var/run/adl-reconcile.lock, /var/run/adl-sync.lock) are mkdir locks.
|
|
195
|
+
# A run that is killed or hangs used to leave the directory behind, and every later `adl setup` /
|
|
196
|
+
# `adl reconcile` then refused "another reconcile is running" forever (m5, 2026-10-01). The holder
|
|
197
|
+
# now records its pid and start time in the lock directory:
|
|
198
|
+
# - pid running with the same start time -> refused, naming the pid;
|
|
199
|
+
# - pid gone, or running with a different start time (the pid was reused) -> stale;
|
|
200
|
+
# - no pid file (the old format, or a holder killed between mkdir and the write) -> stale only
|
|
201
|
+
# when older than the longest a run may take, 3 hours (the systemd unit's TimeoutStartSec).
|
|
202
|
+
# A stale lock is renamed aside and only then re-created with mkdir, so two takers cannot both win.
|
|
203
|
+
# Prints WARN on stderr when it takes over; returns 1 (after an ERROR naming the holder) when the
|
|
204
|
+
# lock is held. The caller removes the directory on exit.
|
|
205
|
+
# adl_lock_acquire LOCK_DIR "what is running"
|
|
206
|
+
adl_lock_max_age_seconds=10800
|
|
207
|
+
|
|
208
|
+
adl_lock_start_time() {
|
|
209
|
+
ps -p "$1" -o lstart= 2>/dev/null | sed -e 's/^ *//' -e 's/ *$//'
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
adl_lock_mtime() {
|
|
213
|
+
stat -c %Y "$1" 2>/dev/null || stat -f %m "$1" 2>/dev/null
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
adl_lock_write_holder() {
|
|
217
|
+
printf '%s\n' "$$" >"$1/pid"
|
|
218
|
+
printf '%s\n' "$(adl_lock_start_time "$$")" >"$1/started"
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
adl_lock_acquire() {
|
|
222
|
+
local lock="$1" running="$2" pid="" recorded_start="" actual_start reason="" now mtime aside
|
|
223
|
+
if mkdir "$lock" 2>/dev/null; then
|
|
224
|
+
adl_lock_write_holder "$lock"
|
|
225
|
+
return 0
|
|
226
|
+
fi
|
|
227
|
+
[[ -d "$lock" ]] && pid="$(tr -d '[:space:]' 2>/dev/null <"$lock/pid" || true)"
|
|
228
|
+
if [[ "$pid" =~ ^[0-9]+$ ]]; then
|
|
229
|
+
if kill -0 "$pid" 2>/dev/null; then
|
|
230
|
+
recorded_start="$(tr -d '\n' <"$lock/started" 2>/dev/null | sed -e 's/^ *//' -e 's/ *$//' || true)"
|
|
231
|
+
actual_start="$(adl_lock_start_time "$pid")"
|
|
232
|
+
if [[ -z "$recorded_start" || "$recorded_start" == "$actual_start" ]]; then
|
|
233
|
+
echo "ERROR $running (lock: $lock, pid $pid)" >&2
|
|
234
|
+
return 1
|
|
235
|
+
fi
|
|
236
|
+
fi
|
|
237
|
+
reason="pid $pid not running"
|
|
238
|
+
else
|
|
239
|
+
now="$(date +%s)"
|
|
240
|
+
mtime="$(adl_lock_mtime "$lock")" || mtime="$now"
|
|
241
|
+
if (( now - mtime < adl_lock_max_age_seconds )); then
|
|
242
|
+
echo "ERROR $running (lock: $lock, no pid recorded; it is treated as stale after 3h)" >&2
|
|
243
|
+
return 1
|
|
244
|
+
fi
|
|
245
|
+
reason="no pid recorded, older than 3h"
|
|
246
|
+
fi
|
|
247
|
+
echo "WARN adl reconcile: removing stale lock $lock ($reason)" >&2
|
|
248
|
+
aside="$lock.stale.$$"
|
|
249
|
+
mv -- "$lock" "$aside" 2>/dev/null || true
|
|
250
|
+
command rm -rf -- "$aside"
|
|
251
|
+
if mkdir "$lock" 2>/dev/null; then
|
|
252
|
+
adl_lock_write_holder "$lock"
|
|
253
|
+
return 0
|
|
254
|
+
fi
|
|
255
|
+
echo "ERROR $running (lock: $lock, taken by another run while removing the stale one)" >&2
|
|
256
|
+
return 1
|
|
257
|
+
}
|
package/bin/lib/fleet-host.sh
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
#
|
|
11
11
|
# fleet_host_resolve COMMAND MANIFEST HOST
|
|
12
12
|
# On success sets fleet_host_platform (mac|linux), fleet_host_owner,
|
|
13
|
-
# fleet_host_minute
|
|
14
|
-
# declares none)
|
|
13
|
+
# fleet_host_minute, fleet_host_repo_location (empty when the device
|
|
14
|
+
# declares none) and fleet_host_branch_max_age_days (the manifest's
|
|
15
|
+
# config.repo_maintain.branch_max_age_days; empty when the manifest has none). On failure prints one `ERROR COMMAND: ...` line to stderr
|
|
15
16
|
# and returns 2 (unknown host) or 1 (unreadable manifest, bad entry, or the
|
|
16
17
|
# host belongs to the other operating system).
|
|
17
18
|
|
|
@@ -22,13 +23,15 @@ fleet_host_resolve() {
|
|
|
22
23
|
fleet_host_owner=""
|
|
23
24
|
fleet_host_minute=""
|
|
24
25
|
fleet_host_repo_location=""
|
|
26
|
+
fleet_host_branch_max_age_days=""
|
|
25
27
|
|
|
26
28
|
[[ -f "$manifest" ]] || { echo "ERROR $command: fleet manifest missing: $manifest" >&2; return 1; }
|
|
27
29
|
|
|
28
30
|
row="$(jq -r --arg host "$host" '
|
|
29
|
-
|
|
31
|
+
(.config // {}) as $config
|
|
32
|
+
| [ ("mac", "linux") as $platform
|
|
30
33
|
| (.[$platform].devices // {}) | to_entries[] | select(.key == $host)
|
|
31
|
-
| [$platform, (.value.administrator // ""), ((.value.schedule_minute // "") | tostring), (.value.repo_location // "")]
|
|
34
|
+
| [$platform, (.value.administrator // ""), ((.value.schedule_minute // "") | tostring), (.value.repo_location // ""), ((($config.repo_maintain.branch_max_age_days) // "") | tostring)]
|
|
32
35
|
| join("\u001f") ] | first // empty
|
|
33
36
|
' "$manifest")" || { echo "ERROR $command: cannot read fleet manifest: $manifest" >&2; return 1; }
|
|
34
37
|
|
|
@@ -43,7 +46,7 @@ fleet_host_resolve() {
|
|
|
43
46
|
|
|
44
47
|
# A non-whitespace delimiter (unit separator): `read` collapses runs of a
|
|
45
48
|
# whitespace IFS such as tab, which would shift a later field into an empty one.
|
|
46
|
-
IFS=$'\x1f' read -r fleet_host_platform fleet_host_owner fleet_host_minute fleet_host_repo_location <<<"$row"
|
|
49
|
+
IFS=$'\x1f' read -r fleet_host_platform fleet_host_owner fleet_host_minute fleet_host_repo_location fleet_host_branch_max_age_days <<<"$row"
|
|
47
50
|
[[ -n "$fleet_host_owner" ]] || { echo "ERROR $command: host '$host' has no administrator in $manifest" >&2; return 1; }
|
|
48
51
|
[[ "$fleet_host_minute" =~ ^[0-9]+$ ]] || { echo "ERROR $command: host '$host' has no schedule_minute in $manifest" >&2; return 1; }
|
|
49
52
|
|