@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.10 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adl +2 -2
- package/bin/git +17 -18
- package/bin/git-ado +27 -26
- 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/bun-compile-build.sh +1 -1
- package/bin/lib/fleet-host.sh +62 -0
- package/bin/lib/lean-ctx-observe-hooks.sh +9 -9
- package/bin/reconcile +693 -470
- package/bin/reconcile-host +121 -0
- package/bin/setup +219 -0
- package/bin/shell-path-policy +15 -5
- package/bin/sync-and-reconcile +79 -68
- package/bin/validate-manifest +46 -51
- package/package.json +2 -12
- package/packages/agent-hooks/README.md +14 -9
- package/packages/agent-hooks/assets/hooks.json +0 -20
- package/packages/agent-hooks/package.json +1 -2
- package/packages/agent-hooks/src/cli/args.ts +1 -1
- package/packages/agent-hooks/src/cli/doctor.ts +6 -58
- package/packages/agent-hooks/src/deploy/deploy.ts +12 -41
- package/packages/agent-hooks/src/deploy/doctor.ts +8 -11
- package/packages/agent-hooks/src/deploy/index.ts +14 -14
- package/packages/agent-hooks/src/deploy/json-merge.ts +7 -8
- package/packages/agent-hooks/src/deploy/legacy-lock.ts +2 -2
- package/packages/agent-hooks/src/deploy/list.ts +1 -1
- package/packages/agent-hooks/src/deploy/lock.ts +31 -12
- package/packages/agent-hooks/src/deploy/profile.ts +3 -4
- package/packages/agent-hooks/src/deploy/source.ts +1 -1
- package/packages/agent-hooks/src/gating/config.ts +10 -24
- package/packages/agent-hooks/src/gating/root.ts +3 -3
- package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
- package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
- package/packages/agent-hooks/src/hooks/contract.ts +17 -17
- package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
- package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
- package/packages/agent-hooks/src/hooks/log.ts +8 -10
- package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
- package/packages/agent-hooks/src/hosts/registry.ts +1 -1
- package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
- package/packages/agent-hooks/src/log/writer.ts +16 -2
- package/packages/agent-hooks/src/main.ts +7 -41
- package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
- package/packages/agent-hooks/src/rules/engine.ts +13 -17
- package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
- package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
- package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
- package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
- package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
- package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
- package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
- package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
- package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
- package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
- package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
- package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +159 -0
- package/packages/agent-hooks/src/rules/impl/fs-trash.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
- package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
- package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
- package/packages/agent-hooks/src/rules/impl/tool-grep.ts +34 -12
- package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
- package/packages/agent-hooks/src/rules/ports.ts +5 -7
- package/packages/agent-hooks/src/rules/registry.ts +4 -6
- package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
- package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
- package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
- package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
- package/packages/agent-hooks/src/rules/spec.ts +2 -2
- package/packages/agent-settings/README.md +287 -0
- package/packages/agent-settings/assets/GLOBAL-AGENTS.md +18 -18
- 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 +5 -17
- 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/package.json +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 +2 -5
- package/packages/azdo/src/azdo-pl.ts +2 -54
- package/packages/azdo/src/azdo-pr-review.ts +4 -4
- package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
- package/packages/azdo/src/azdo-wit.ts +41 -2
- package/packages/azdo/src/lib/agent-identity.ts +12 -14
- package/packages/azdo/src/lib/agent-token.ts +2 -2
- package/packages/azdo/src/lib/client.ts +0 -5
- package/packages/azdo/src/lib/graph-identity.ts +4 -4
- package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
- package/packages/azdo/src/workflow-rules.ts +128 -0
- package/packages/fleet/manifest.json +38 -33
- package/packages/fleet/manifest.schema.json +67 -65
- 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 +14 -14
- package/packages/fleet/src/managed-settings.ts +7 -7
- package/packages/fleet/src/repo-maintain.ts +439 -0
- package/packages/fleet/src/scratch-reap.ts +6 -6
- package/packages/fleet/src/vscode-settings.ts +5 -5
- package/packages/repo-controls/README.md +141 -43
- package/packages/repo-controls/assets/promote.ts +4 -4
- package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
- package/packages/repo-controls/assets/version-bump.sh +31 -84
- package/packages/repo-controls/bunfig.toml +6 -7
- package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
- package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/sub/nested.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-001-tenancy.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-002-carrier.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-003-cli.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-old.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-older.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-01.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-02.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-03.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-04.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-05.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-06.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-07.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-08.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-09.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-10.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-11.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-12.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-13.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-14.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-15.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-16.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/e.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/short/only.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-legacy/docs/compliance/index.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-type/docs/compliance/index.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/no-type.md +9 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-experiment.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-research.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs/architecture/bad-status.md +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-last-update.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/created-date.md +21 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/research-shaped.md +19 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/a.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/b.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/a.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/b.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/c.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +256 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
- package/packages/repo-controls/package.json +2 -10
- 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/packages/fleet/jobs/git-maintain/src/main.ts +0 -848
- package/packages/fleet/systemd/adl-azure-agent-update.service +0 -13
- package/packages/fleet/systemd/adl-azure-agent-update.timer +0 -10
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# `sudo adl reconcile --host NAME [--mode plan|apply]` -- one full pass of what
|
|
5
|
+
# the 12-hourly job does (the job's program is `adl reconcile`, which runs this),
|
|
6
|
+
# also run on demand:
|
|
7
|
+
#
|
|
8
|
+
# 1. tools: this package's bin/sync-and-reconcile (run through bash, never
|
|
9
|
+
# executed directly: bun leaves every shipped file but the `bin` targets
|
|
10
|
+
# without an exec bit) with `--source npm --device NAME --owner OWNER`
|
|
11
|
+
# (package update with bun, then tools reconcile). `--source npm` names
|
|
12
|
+
# the registry the package comes from, not the installer. The owner is the
|
|
13
|
+
# device's `administrator` in this package's
|
|
14
|
+
# manifest (bin/lib/fleet-host.sh, the lookup bin/setup shares). --mode is
|
|
15
|
+
# forwarded only when given, so the default is apply.
|
|
16
|
+
# 2. repositories: `adl maintain --location <repo_location> --expect-user
|
|
17
|
+
# OWNER`, the package's own bin/adl, run AS THE ADMINISTRATOR -- never as
|
|
18
|
+
# root. sudo resets PATH to its secure_path, which has neither Homebrew nor
|
|
19
|
+
# /usr/local/bin, so PATH is always handed over explicitly with `env PATH=`
|
|
20
|
+
# (every sudo -u call that ends up running adl, git or bun must); the
|
|
21
|
+
# owner's bun bin directory (~/.bun/bin) is on it, after /usr/local/bin.
|
|
22
|
+
# --mode plan becomes --dry-run.
|
|
23
|
+
#
|
|
24
|
+
# Both steps always run (a failed tools step does not hide a repository problem,
|
|
25
|
+
# and vice versa); the exit code is the first failure's, and each failure is
|
|
26
|
+
# reported as an ERROR line. A host that declares no repo_location skips step 2
|
|
27
|
+
# with a log line.
|
|
28
|
+
#
|
|
29
|
+
# ADL_SETUP_TEST_ROOT is the same single test switch bin/setup has: unset in
|
|
30
|
+
# every real run; when set it only keeps the caller's PATH so `id`, `uname` and
|
|
31
|
+
# `sudo` can be stubbed (packages/fleet/tests/reconcile-host.test.ts).
|
|
32
|
+
|
|
33
|
+
if [[ -n "${ADL_SETUP_TEST_ROOT:-}" ]]; then
|
|
34
|
+
export PATH="${PATH:-/usr/bin:/bin}"
|
|
35
|
+
else
|
|
36
|
+
export PATH="/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
host=""
|
|
40
|
+
mode=""
|
|
41
|
+
while [[ "$#" -gt 0 ]]; do
|
|
42
|
+
case "$1" in
|
|
43
|
+
--host) host="${2:-}"; shift 2 ;;
|
|
44
|
+
--mode) mode="${2:-}"; shift 2 ;;
|
|
45
|
+
*) echo "ERROR unknown argument: $1" >&2; exit 2 ;;
|
|
46
|
+
esac
|
|
47
|
+
done
|
|
48
|
+
[[ -n "$host" ]] || { echo "ERROR usage: sudo adl reconcile --host NAME [--mode plan|apply]" >&2; exit 2; }
|
|
49
|
+
if [[ -n "$mode" && "$mode" != plan && "$mode" != apply ]]; then
|
|
50
|
+
echo "ERROR unsupported mode: $mode (expected plan or apply)" >&2
|
|
51
|
+
exit 2
|
|
52
|
+
fi
|
|
53
|
+
[[ "$(id -u)" -eq 0 ]] || { echo "ERROR adl reconcile must run as root: sudo adl reconcile --host $host" >&2; exit 1; }
|
|
54
|
+
|
|
55
|
+
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
56
|
+
package_dir="$(cd -- "$script_dir/.." && pwd)"
|
|
57
|
+
# shellcheck source=lib/fleet-host.sh
|
|
58
|
+
source "$script_dir/lib/fleet-host.sh"
|
|
59
|
+
fleet_host_resolve "adl reconcile" "$package_dir/packages/fleet/manifest.json" "$host" || exit $?
|
|
60
|
+
owner="$fleet_host_owner"
|
|
61
|
+
repo_location="$fleet_host_repo_location"
|
|
62
|
+
branch_max_age_days="$fleet_host_branch_max_age_days"
|
|
63
|
+
|
|
64
|
+
# shellcheck source=lib/adl-package.sh
|
|
65
|
+
source "$script_dir/lib/adl-package.sh"
|
|
66
|
+
[[ -f "$script_dir/sync-and-reconcile" ]] || { echo "ERROR adl reconcile: package scheduler script is missing: $script_dir/sync-and-reconcile" >&2; exit 1; }
|
|
67
|
+
|
|
68
|
+
# One lock around both steps: an on-demand run overlapping the timer must not
|
|
69
|
+
# run a second repository pass after its tools step lost sync's own lock.
|
|
70
|
+
if [[ -n "${ADL_SETUP_TEST_ROOT:-}" ]]; then
|
|
71
|
+
lock_dir="${ADL_SETUP_TEST_ROOT%/}/adl-reconcile.lock"
|
|
72
|
+
else
|
|
73
|
+
lock_dir=/var/run/adl-reconcile.lock
|
|
74
|
+
fi
|
|
75
|
+
adl_lock_acquire "$lock_dir" "adl reconcile: another reconcile is running" || exit 1
|
|
76
|
+
trap 'rm -rf -- "$lock_dir"' EXIT
|
|
77
|
+
|
|
78
|
+
# 1. tools
|
|
79
|
+
sync_args=(--source npm --device "$host" --owner "$owner")
|
|
80
|
+
if [[ -n "$mode" ]]; then sync_args+=(--mode "$mode"); fi
|
|
81
|
+
tools_rc=0
|
|
82
|
+
bash "$script_dir/sync-and-reconcile" "${sync_args[@]}" || tools_rc=$?
|
|
83
|
+
if [[ "$tools_rc" -ne 0 ]]; then
|
|
84
|
+
echo "ERROR global-tools: tools reconcile failed (exit $tools_rc)" >&2
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# 2. repositories
|
|
88
|
+
repos_rc=0
|
|
89
|
+
if [[ -z "$repo_location" ]]; then
|
|
90
|
+
echo "global-tools: repo maintenance skipped: $host declares no repo_location"
|
|
91
|
+
else
|
|
92
|
+
adl_bin="$package_dir/bin/adl"
|
|
93
|
+
if [[ ! -x "$adl_bin" ]]; then
|
|
94
|
+
echo "ERROR global-tools: package adl is missing or not executable: $adl_bin" >&2
|
|
95
|
+
repos_rc=1
|
|
96
|
+
else
|
|
97
|
+
case "$fleet_host_platform" in
|
|
98
|
+
mac) repo_os=Darwin ;;
|
|
99
|
+
*) repo_os=Linux ;;
|
|
100
|
+
esac
|
|
101
|
+
if ! owner_home="$(adl_owner_home "$owner")"; then
|
|
102
|
+
echo "ERROR global-tools: cannot resolve the home directory of $owner" >&2
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|
|
105
|
+
owner_path="$(adl_owner_path "$repo_os" "$owner_home")"
|
|
106
|
+
maintain_args=(maintain --location "$repo_location" --expect-user "$owner")
|
|
107
|
+
# config.repo_maintain.branch_max_age_days in this package's manifest, never an environment variable.
|
|
108
|
+
if [[ -n "$branch_max_age_days" ]]; then maintain_args+=(--branch-max-age-days "$branch_max_age_days"); fi
|
|
109
|
+
if [[ "$mode" == plan ]]; then maintain_args+=(--dry-run); fi
|
|
110
|
+
# /usr/local/bin first (see adl_owner_path): git must resolve to the managed
|
|
111
|
+
# controller, which routes Azure DevOps traffic through the agent identity;
|
|
112
|
+
# Homebrew's git would bypass it.
|
|
113
|
+
sudo -u "$owner" -H env PATH="$owner_path" "$adl_bin" "${maintain_args[@]}" || repos_rc=$?
|
|
114
|
+
if [[ "$repos_rc" -ne 0 ]]; then
|
|
115
|
+
echo "ERROR global-tools: repository maintenance failed (exit $repos_rc)" >&2
|
|
116
|
+
fi
|
|
117
|
+
fi
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
if [[ "$tools_rc" -ne 0 ]]; then exit "$tools_rc"; fi
|
|
121
|
+
exit "$repos_rc"
|
package/bin/setup
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# `sudo adl setup --host NAME` -- the whole onboarding of a host after
|
|
5
|
+
# `bun install -g @amsterdamdatalabs/adl-agent-control` (run as the device's
|
|
6
|
+
# administrator):
|
|
7
|
+
#
|
|
8
|
+
# 1. check this is THE package the job manages (the one in the owner's bun
|
|
9
|
+
# global directory), that its bin/adl is there, and that the `adl` the
|
|
10
|
+
# owner gets on PATH is this package and not a different one that shadows it
|
|
11
|
+
# 2. run the first reconcile: `<this package>/bin/adl reconcile --host NAME`
|
|
12
|
+
# 3. only if that succeeded, arm the job that re-runs the same command every
|
|
13
|
+
# 12 hours
|
|
14
|
+
#
|
|
15
|
+
# A host that cannot reconcile is never left with a timer that fails unseen.
|
|
16
|
+
# The job's program is the package's own bin/adl, not a shell script: on macOS
|
|
17
|
+
# the one-time Full Disk Access grant (needed to read the repositories under the
|
|
18
|
+
# host's repo_location) goes to that binary, and the launchd/systemd job and
|
|
19
|
+
# `sudo adl reconcile --host NAME` are then literally the same command.
|
|
20
|
+
#
|
|
21
|
+
# Everything comes from this package: it locates itself from its own path and
|
|
22
|
+
# reads packages/fleet/manifest.json beside it (no git checkout, no source
|
|
23
|
+
# flag -- the published package is the only source). The account the job runs
|
|
24
|
+
# bun as is the device's `administrator` in that manifest; there is no owner
|
|
25
|
+
# flag. The package's scripts are run through bash, never executed directly:
|
|
26
|
+
# bun leaves every shipped file but the `bin` targets without an exec bit.
|
|
27
|
+
#
|
|
28
|
+
# ADL_SETUP_TEST_ROOT is the one test switch (packages/fleet/tests/setup.test.ts):
|
|
29
|
+
# unset in every real run. When set it relocates the system paths under that
|
|
30
|
+
# directory and keeps the caller's PATH so the system commands can be stubbed.
|
|
31
|
+
|
|
32
|
+
if [[ -n "${ADL_SETUP_TEST_ROOT:-}" ]]; then
|
|
33
|
+
export PATH="${PATH:-/usr/bin:/bin}"
|
|
34
|
+
# The sourced sync-and-reconcile has its own test switch; one switch here
|
|
35
|
+
# drives both, so a test sets only ADL_SETUP_TEST_ROOT.
|
|
36
|
+
export SYNC_AND_RECONCILE_TEST_ROOT="$ADL_SETUP_TEST_ROOT"
|
|
37
|
+
else
|
|
38
|
+
export PATH="/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
host=""
|
|
42
|
+
while [[ "$#" -gt 0 ]]; do
|
|
43
|
+
case "$1" in
|
|
44
|
+
--host) host="${2:-}"; shift 2 ;;
|
|
45
|
+
*) echo "ERROR unknown argument: $1" >&2; exit 2 ;;
|
|
46
|
+
esac
|
|
47
|
+
done
|
|
48
|
+
[[ -n "$host" ]] || { echo "ERROR usage: sudo adl setup --host NAME" >&2; exit 2; }
|
|
49
|
+
[[ "$(id -u)" -eq 0 ]] || { echo "ERROR adl setup must run as root: sudo adl setup --host $host" >&2; exit 1; }
|
|
50
|
+
|
|
51
|
+
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
52
|
+
package_dir="$(cd -- "$script_dir/.." && pwd)"
|
|
53
|
+
package_dir_real="$(cd -P -- "$script_dir/.." && pwd -P)"
|
|
54
|
+
# shellcheck source=lib/fleet-host.sh
|
|
55
|
+
source "$script_dir/lib/fleet-host.sh"
|
|
56
|
+
fleet_host_resolve "adl setup" "$package_dir/packages/fleet/manifest.json" "$host" || exit $?
|
|
57
|
+
owner="$fleet_host_owner"
|
|
58
|
+
minute="$fleet_host_minute"
|
|
59
|
+
|
|
60
|
+
# The job keeps THE package installed in the owner's bun global directory up to
|
|
61
|
+
# date and reconciles from it. This must be that package, or the host would be
|
|
62
|
+
# armed to manage a different copy than the one the operator just ran. Ask for
|
|
63
|
+
# the location the way the job does (bin/lib/adl-package.sh, shared with
|
|
64
|
+
# sync-and-reconcile), and compare real paths.
|
|
65
|
+
# shellcheck source=lib/adl-package.sh
|
|
66
|
+
source "$script_dir/lib/adl-package.sh"
|
|
67
|
+
os_name="$(uname -s)"
|
|
68
|
+
owner_home="$(adl_owner_home "$owner")" || {
|
|
69
|
+
echo "ERROR adl setup: cannot resolve the home directory of $owner" >&2
|
|
70
|
+
exit 1
|
|
71
|
+
}
|
|
72
|
+
managed_dir="$(adl_platform_package_dir "$(adl_global_node_modules "$owner_home")" "$os_name" "$(uname -m)")" || exit 1
|
|
73
|
+
managed_real="$(cd -P -- "$managed_dir" 2>/dev/null && pwd -P)" || managed_real=""
|
|
74
|
+
if [[ -z "$managed_real" || "$package_dir_real" != "$managed_real" ]]; then
|
|
75
|
+
{
|
|
76
|
+
echo "ERROR adl setup: this package ($package_dir_real) is not the package the scheduled job manages ($managed_dir)."
|
|
77
|
+
echo "ERROR adl setup: install it where the job looks, as $owner, then run setup again:"
|
|
78
|
+
echo "ERROR adl setup: bun install -g @amsterdamdatalabs/adl-agent-control"
|
|
79
|
+
} >&2
|
|
80
|
+
exit 1
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
adl_bin="$package_dir_real/bin/adl"
|
|
84
|
+
[[ -x "$adl_bin" ]] || { echo "ERROR adl setup: the package adl is missing or not executable: $package_dir/bin/adl" >&2; exit 1; }
|
|
85
|
+
adl_check_adl_not_shadowed "$owner" "$os_name" "$owner_home" "$package_dir_real" "adl setup" || exit 1
|
|
86
|
+
|
|
87
|
+
if [[ -n "${ADL_SETUP_TEST_ROOT:-}" ]]; then
|
|
88
|
+
system_root="${ADL_SETUP_TEST_ROOT%/}"
|
|
89
|
+
else
|
|
90
|
+
system_root=""
|
|
91
|
+
fi
|
|
92
|
+
legacy_adl_sync="$system_root/usr/local/libexec/adl-sync"
|
|
93
|
+
launch_daemons_dir="$system_root/Library/LaunchDaemons"
|
|
94
|
+
systemd_dir="$system_root/etc/systemd/system"
|
|
95
|
+
brew_prefix="$system_root/home/linuxbrew/.linuxbrew"
|
|
96
|
+
|
|
97
|
+
# Preflight that must hold before the first reconcile: the Linux job runs
|
|
98
|
+
# Homebrew as a non-root owner, and that owner needs git's safe.directory for
|
|
99
|
+
# the brew repositories or every `brew update` inside the reconcile fails.
|
|
100
|
+
if [[ "$fleet_host_platform" == linux ]]; then
|
|
101
|
+
if [[ -d "$brew_prefix" ]]; then
|
|
102
|
+
brew_owner="$(stat -c '%U' "$brew_prefix")"
|
|
103
|
+
[[ "$brew_owner" != root ]] || {
|
|
104
|
+
echo "ERROR Homebrew prefix must be owned by a non-root account: /home/linuxbrew/.linuxbrew" >&2
|
|
105
|
+
exit 1
|
|
106
|
+
}
|
|
107
|
+
else
|
|
108
|
+
echo "ERROR Homebrew prefix missing: /home/linuxbrew/.linuxbrew" >&2
|
|
109
|
+
exit 1
|
|
110
|
+
fi
|
|
111
|
+
for brew_repo in \
|
|
112
|
+
"$brew_prefix/Homebrew" \
|
|
113
|
+
"$brew_prefix/Homebrew/Library/Taps/adl-tan-theta/homebrew-tap"; do
|
|
114
|
+
[[ -d "$brew_repo/.git" ]] || continue
|
|
115
|
+
if ! (cd /tmp && sudo -u "$brew_owner" -H git config --global --get-all safe.directory 2>/dev/null) | grep -Fxq "$brew_repo"; then
|
|
116
|
+
(cd /tmp && sudo -u "$brew_owner" -H git config --global --add safe.directory "$brew_repo")
|
|
117
|
+
fi
|
|
118
|
+
done
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
mkdir -p "$system_root/var/lib/adl" "$system_root/var/log/adl"
|
|
122
|
+
|
|
123
|
+
echo "adl setup: first reconcile for $host (owner $owner)"
|
|
124
|
+
reconcile_rc=0
|
|
125
|
+
"$adl_bin" reconcile --host "$host" || reconcile_rc=$?
|
|
126
|
+
if [[ "$reconcile_rc" -ne 0 ]]; then
|
|
127
|
+
echo "ERROR adl setup: first reconcile failed (exit $reconcile_rc); scheduler NOT armed. Fix the failure and re-run: sudo adl setup --host $host" >&2
|
|
128
|
+
exit "$reconcile_rc"
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
case "$fleet_host_platform" in
|
|
132
|
+
mac)
|
|
133
|
+
mkdir -p "$launch_daemons_dir"
|
|
134
|
+
plist="$launch_daemons_dir/com.adl.global-tools.plist"
|
|
135
|
+
{
|
|
136
|
+
printf '%s\n' '<?xml version="1.0" encoding="UTF-8"?>'
|
|
137
|
+
printf '%s\n' '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
|
|
138
|
+
printf '%s\n' '<plist version="1.0"><dict>'
|
|
139
|
+
printf '%s\n' '<key>Label</key><string>com.adl.global-tools</string>'
|
|
140
|
+
printf '%s\n' '<key>ProgramArguments</key><array>'
|
|
141
|
+
printf '<string>%s</string>\n' "$adl_bin"
|
|
142
|
+
printf '%s\n' '<string>reconcile</string>'
|
|
143
|
+
printf '<string>--host</string><string>%s</string>\n' "$host"
|
|
144
|
+
printf '%s\n' '</array>'
|
|
145
|
+
printf '%s\n' '<key>StartCalendarInterval</key><array>'
|
|
146
|
+
for hour in 0 12; do printf '<dict><key>Hour</key><integer>%s</integer><key>Minute</key><integer>%s</integer></dict>\n' "$hour" "$minute"; done
|
|
147
|
+
printf '%s\n' '</array><key>ProcessType</key><string>Background</string>'
|
|
148
|
+
printf '%s\n' '<key>StandardOutPath</key><string>/var/log/adl/stdout.log</string>'
|
|
149
|
+
printf '%s\n' '<key>StandardErrorPath</key><string>/var/log/adl/stderr.log</string>'
|
|
150
|
+
printf '%s\n' '</dict></plist>'
|
|
151
|
+
} >"$plist"
|
|
152
|
+
chown root:wheel "$plist"
|
|
153
|
+
chmod 0644 "$plist"
|
|
154
|
+
plutil -lint "$plist"
|
|
155
|
+
# bootout fails when the job is not loaded, so ask first instead of
|
|
156
|
+
# swallowing the error: a bootout that fails on a loaded job must stop us.
|
|
157
|
+
if launchctl print system/com.adl.global-tools >/dev/null 2>&1; then
|
|
158
|
+
launchctl bootout system/com.adl.global-tools
|
|
159
|
+
# bootout returns before launchd has finished unloading, and a
|
|
160
|
+
# bootstrap in that window fails with an I/O error. Wait until the
|
|
161
|
+
# label is really gone, bounded, and fail loud if it is not.
|
|
162
|
+
unloaded=0
|
|
163
|
+
for _ in 1 2 3 4 5 6 7 8 9 10; do
|
|
164
|
+
if ! launchctl print system/com.adl.global-tools >/dev/null 2>&1; then unloaded=1; break; fi
|
|
165
|
+
sleep 0.5
|
|
166
|
+
done
|
|
167
|
+
[[ "$unloaded" -eq 1 ]] || {
|
|
168
|
+
echo "ERROR adl setup: com.adl.global-tools is still loaded after bootout (waited 5s); not bootstrapping. Run: sudo launchctl bootout system/com.adl.global-tools" >&2
|
|
169
|
+
exit 1
|
|
170
|
+
}
|
|
171
|
+
fi
|
|
172
|
+
launchctl bootstrap system "$plist"
|
|
173
|
+
;;
|
|
174
|
+
linux)
|
|
175
|
+
mkdir -p "$systemd_dir"
|
|
176
|
+
cat > "$systemd_dir/adl-global-tools.service" <<EOF
|
|
177
|
+
[Unit]
|
|
178
|
+
Description=Reconcile Adl global tools and repositories (adl reconcile)
|
|
179
|
+
After=network-online.target
|
|
180
|
+
Wants=network-online.target
|
|
181
|
+
|
|
182
|
+
[Service]
|
|
183
|
+
Type=oneshot
|
|
184
|
+
ExecStart=$adl_bin reconcile --host $host
|
|
185
|
+
StandardOutput=append:/var/log/adl/stdout.log
|
|
186
|
+
StandardError=append:/var/log/adl/stderr.log
|
|
187
|
+
Nice=10
|
|
188
|
+
IOSchedulingClass=best-effort
|
|
189
|
+
IOSchedulingPriority=7
|
|
190
|
+
TimeoutStartSec=3h
|
|
191
|
+
EOF
|
|
192
|
+
cat > "$systemd_dir/adl-global-tools.timer" <<EOF
|
|
193
|
+
[Unit]
|
|
194
|
+
Description=Run Adl global-tool reconciliation every 12 hours
|
|
195
|
+
|
|
196
|
+
[Timer]
|
|
197
|
+
OnCalendar=*-*-* 00,12:$minute:00
|
|
198
|
+
Persistent=true
|
|
199
|
+
Unit=adl-global-tools.service
|
|
200
|
+
|
|
201
|
+
[Install]
|
|
202
|
+
WantedBy=timers.target
|
|
203
|
+
EOF
|
|
204
|
+
systemctl daemon-reload
|
|
205
|
+
systemctl enable --now adl-global-tools.timer
|
|
206
|
+
# enable --now leaves an already-active timer on its old schedule.
|
|
207
|
+
systemctl restart adl-global-tools.timer
|
|
208
|
+
;;
|
|
209
|
+
esac
|
|
210
|
+
|
|
211
|
+
# The job used to run a copy of bin/sync-and-reconcile installed here. Its
|
|
212
|
+
# definition now points at the package's adl, so the copy is dead weight that
|
|
213
|
+
# would keep running stale update logic if anyone invoked it.
|
|
214
|
+
if [[ -e "$legacy_adl_sync" ]]; then
|
|
215
|
+
rm -f -- "$legacy_adl_sync"
|
|
216
|
+
echo "adl setup: removed the legacy scheduler copy $legacy_adl_sync"
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
echo "adl setup: $host reconciled and armed (every 12 hours at minute $minute); run on demand with: sudo adl reconcile --host $host"
|
package/bin/shell-path-policy
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Managed by adl global-tools.
|
|
3
3
|
# Keep /usr/local/bin first in interactive shells so manifest-owned front
|
|
4
|
-
# controllers win over Homebrew and system executables on every host.
|
|
4
|
+
# controllers win over Homebrew and system executables on every host. The
|
|
5
|
+
# administrator's bun bin directory comes right after it (Tarun, 2026-10-01):
|
|
6
|
+
# hosts install the adl package with `bun install -g`, which links `adl` into
|
|
7
|
+
# $HOME/.bun/bin, and humans and agents must be able to run it (root on Linux:
|
|
8
|
+
# /root/.bun/bin). It stays behind /usr/local/bin so the managed git wins.
|
|
5
9
|
set -euo pipefail
|
|
6
10
|
|
|
11
|
+
managed_path_line='export PATH="/usr/local/bin:$HOME/.bun/bin${PATH:+:$PATH}"'
|
|
12
|
+
|
|
7
13
|
usage() {
|
|
8
14
|
echo 'usage: shell-path-policy --home ABSOLUTE_PATH --platform mac|linux --mode plan|apply [--owner USER]' >&2
|
|
9
15
|
exit 2
|
|
@@ -35,10 +41,14 @@ upsert_block() {
|
|
|
35
41
|
mkdir -p -- "$(dirname -- "$file")"
|
|
36
42
|
temp="$file.adl-new"
|
|
37
43
|
if [[ -e "$file" ]]; then
|
|
44
|
+
# Trailing blank lines are dropped with the block: the append below puts one
|
|
45
|
+
# blank line back in front of it, so a re-run is byte-identical, not one line longer.
|
|
38
46
|
awk -v begin="$begin" -v end="$end" '
|
|
39
47
|
$0 == begin { inside = 1; next }
|
|
40
48
|
$0 == end { inside = 0; next }
|
|
41
|
-
|
|
49
|
+
inside { next }
|
|
50
|
+
/^$/ { blanks++; next }
|
|
51
|
+
{ while (blanks > 0) { print ""; blanks-- } print }
|
|
42
52
|
' "$file" >"$temp"
|
|
43
53
|
else
|
|
44
54
|
: >"$temp"
|
|
@@ -50,14 +60,14 @@ upsert_block() {
|
|
|
50
60
|
|
|
51
61
|
if [[ "$platform" == mac ]]; then
|
|
52
62
|
upsert_block "$home/.zshenv" '# BEGIN ADL GLOBAL PATH' '# END ADL GLOBAL PATH' \
|
|
53
|
-
|
|
63
|
+
"$managed_path_line"
|
|
54
64
|
exit 0
|
|
55
65
|
fi
|
|
56
66
|
|
|
57
67
|
upsert_block "$home/.bashenv" '# BEGIN ADL GLOBAL PATH ENV' '# END ADL GLOBAL PATH ENV' \
|
|
58
|
-
|
|
68
|
+
"$managed_path_line"
|
|
59
69
|
upsert_block "$home/.zshenv" '# BEGIN ADL GLOBAL PATH ENV' '# END ADL GLOBAL PATH ENV' \
|
|
60
|
-
|
|
70
|
+
"$managed_path_line"
|
|
61
71
|
for shell_file in "$home/.bashrc" "$home/.bash_profile" "$home/.profile"; do
|
|
62
72
|
upsert_block "$shell_file" '# BEGIN ADL GLOBAL PATH SOURCE' '# END ADL GLOBAL PATH SOURCE' \
|
|
63
73
|
'if [[ -r "$HOME/.bashenv" ]]; then . "$HOME/.bashenv"; fi'
|
package/bin/sync-and-reconcile
CHANGED
|
@@ -7,20 +7,26 @@ else
|
|
|
7
7
|
export PATH="/usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
|
8
8
|
fi
|
|
9
9
|
|
|
10
|
-
# Scheduled sync
|
|
11
|
-
# reconcile
|
|
10
|
+
# Scheduled sync installs the published ADL package with bun (as the device's
|
|
11
|
+
# administrator) and runs that package's own reconcile. Checkout mode is an
|
|
12
|
+
# explicit developer-only bypass. Package layout and owner lookups are in
|
|
13
|
+
# lib/adl-package.sh, shared with bin/setup and bin/reconcile.
|
|
14
|
+
_sync_and_reconcile_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
15
|
+
# shellcheck source=lib/adl-package.sh
|
|
16
|
+
source "$_sync_and_reconcile_dir/lib/adl-package.sh"
|
|
17
|
+
|
|
12
18
|
sync_and_reconcile_platform() {
|
|
13
19
|
case "$(uname -s)" in
|
|
14
20
|
Darwin) printf '%s\n' mac ;;
|
|
15
21
|
Linux) printf '%s\n' linux ;;
|
|
16
|
-
*) echo "unsupported operating system for scheduled sync: $(uname -s)" >&2; return 1 ;;
|
|
22
|
+
*) echo "ERROR unsupported operating system for scheduled sync: $(uname -s)" >&2; return 1 ;;
|
|
17
23
|
esac
|
|
18
24
|
}
|
|
19
25
|
|
|
20
26
|
require_linux_automation_root() {
|
|
21
27
|
local platform="$1" owner="$2"
|
|
22
28
|
if [[ "$platform" == linux && "$owner" != root ]]; then
|
|
23
|
-
echo "global-tools: Linux scheduled sync must run as root; got --owner $owner" >&2
|
|
29
|
+
echo "ERROR global-tools: Linux scheduled sync must run as root; got --owner $owner" >&2
|
|
24
30
|
return 1
|
|
25
31
|
fi
|
|
26
32
|
}
|
|
@@ -35,35 +41,25 @@ parse_sync_source() {
|
|
|
35
41
|
done
|
|
36
42
|
case "$sync_source" in
|
|
37
43
|
npm|checkout) ;;
|
|
38
|
-
*) echo "unsupported source: $sync_source" >&2; return 2 ;;
|
|
44
|
+
*) echo "ERROR unsupported source: $sync_source" >&2; return 2 ;;
|
|
39
45
|
esac
|
|
40
46
|
}
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
adl_package_spec() {
|
|
43
49
|
local policy="$1" version="${2:-}"
|
|
44
50
|
case "$policy" in
|
|
45
51
|
latest-stable) printf '%s@latest\n' '@amsterdamdatalabs/adl-agent-control' ;;
|
|
46
52
|
pinned)
|
|
47
53
|
[[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([-.][0-9A-Za-z.-]+)?$ ]] || {
|
|
48
|
-
echo "pinned update_policy requires a valid installed package version" >&2
|
|
54
|
+
echo "ERROR pinned update_policy requires a valid installed package version" >&2
|
|
49
55
|
return 1
|
|
50
56
|
}
|
|
51
57
|
printf '%s@%s\n' '@amsterdamdatalabs/adl-agent-control' "$version"
|
|
52
58
|
;;
|
|
53
|
-
*) echo "unsupported update_policy: $policy" >&2; return 1 ;;
|
|
59
|
+
*) echo "ERROR unsupported update_policy: $policy" >&2; return 1 ;;
|
|
54
60
|
esac
|
|
55
61
|
}
|
|
56
62
|
|
|
57
|
-
npm_platform_package_dir() {
|
|
58
|
-
local npm_root="$1" os="$2" arch="$3" platform
|
|
59
|
-
case "$os:$arch" in
|
|
60
|
-
Darwin:arm64) platform=darwin-arm64 ;;
|
|
61
|
-
Linux:x86_64) platform=linux-x64 ;;
|
|
62
|
-
*) echo "unsupported platform for npm package: $os $arch" >&2; return 1 ;;
|
|
63
|
-
esac
|
|
64
|
-
printf '%s/@amsterdamdatalabs/adl-agent-control-%s\n' "${npm_root%/}" "$platform"
|
|
65
|
-
}
|
|
66
|
-
|
|
67
63
|
prepare_adl_npm_migration() {
|
|
68
64
|
local applied_manifest="$1" device="$2" platform="$3" legacy_adl="$4" hash_file="$5"
|
|
69
65
|
local previous_manager previous_executable
|
|
@@ -72,12 +68,12 @@ prepare_adl_npm_migration() {
|
|
|
72
68
|
previous_executable="$(jq -r --arg platform "$platform" --arg device "$device" '(.[$platform].common.tools // {}) * (.[$platform].devices[$device].tools // {}) | .adl.executable // empty' "$applied_manifest")" || return 1
|
|
73
69
|
[[ "$previous_manager" == bun-compile && "$previous_executable" == /usr/local/bin/adl ]] || return 0
|
|
74
70
|
[[ -f "$legacy_adl" && ! -L "$legacy_adl" ]] || {
|
|
75
|
-
echo "prior manifest proves adl was a Bun binary, but the expected regular file is missing or is a symlink: $legacy_adl" >&2
|
|
71
|
+
echo "ERROR prior manifest proves adl was a Bun binary, but the expected regular file is missing or is a symlink: $legacy_adl" >&2
|
|
76
72
|
return 1
|
|
77
73
|
}
|
|
78
74
|
rm -f -- "$legacy_adl"
|
|
79
75
|
rm -f -- "$hash_file"
|
|
80
|
-
echo "global-tools: removed prior Bun adl binary before
|
|
76
|
+
echo "global-tools: removed prior Bun adl binary before the package install: $legacy_adl"
|
|
81
77
|
}
|
|
82
78
|
|
|
83
79
|
if [[ "${SYNC_AND_RECONCILE_SOURCE_ONLY:-0}" == 1 ]]; then
|
|
@@ -96,94 +92,84 @@ while [[ "$#" -gt 0 ]]; do
|
|
|
96
92
|
--repo) repo="${2:-}"; shift 2 ;;
|
|
97
93
|
--owner) owner="${2:-}"; shift 2 ;;
|
|
98
94
|
--mode) mode="${2:-}"; shift 2 ;;
|
|
99
|
-
*) echo "unknown argument: $1" >&2; exit 2 ;;
|
|
95
|
+
*) echo "ERROR unknown argument: $1" >&2; exit 2 ;;
|
|
100
96
|
esac
|
|
101
97
|
done
|
|
102
98
|
case "$sync_source" in
|
|
103
99
|
npm|checkout) ;;
|
|
104
|
-
*) echo "unsupported source: $sync_source" >&2; exit 2 ;;
|
|
100
|
+
*) echo "ERROR unsupported source: $sync_source" >&2; exit 2 ;;
|
|
105
101
|
esac
|
|
106
102
|
[[ -n "$device" && -n "$owner" ]] || {
|
|
107
|
-
echo "usage: sync-and-reconcile [--source npm|checkout] --device NAME --owner USER [--repo PATH] [--mode audit|plan|apply]" >&2
|
|
103
|
+
echo "ERROR usage: sync-and-reconcile [--source npm|checkout] --device NAME --owner USER [--repo PATH] [--mode audit|plan|apply]" >&2
|
|
108
104
|
exit 2
|
|
109
105
|
}
|
|
110
106
|
[[ "$mode" == audit || "$mode" == plan || "$mode" == apply ]] || {
|
|
111
|
-
echo "unsupported reconcile mode: $mode" >&2
|
|
107
|
+
echo "ERROR unsupported reconcile mode: $mode" >&2
|
|
112
108
|
exit 2
|
|
113
109
|
}
|
|
114
110
|
if [[ "$sync_source" == checkout && -z "$repo" ]]; then
|
|
115
|
-
echo "checkout source requires --repo PATH" >&2
|
|
111
|
+
echo "ERROR checkout source requires --repo PATH" >&2
|
|
116
112
|
exit 2
|
|
117
113
|
fi
|
|
118
114
|
if [[ "$sync_source" == npm && -n "$repo" ]]; then
|
|
119
|
-
echo "npm source does not accept --repo; use --source checkout for a checkout path" >&2
|
|
115
|
+
echo "ERROR npm source does not accept --repo; use --source checkout for a checkout path" >&2
|
|
120
116
|
exit 2
|
|
121
117
|
fi
|
|
122
118
|
|
|
123
119
|
if [[ -n "${SYNC_AND_RECONCILE_TEST_ROOT:-}" ]]; then
|
|
124
120
|
lock_dir="${SYNC_AND_RECONCILE_TEST_ROOT%/}/adl-sync.lock"
|
|
125
|
-
scheduler_path="${SYNC_AND_RECONCILE_TEST_ROOT%/}/scheduler"
|
|
126
121
|
else
|
|
127
122
|
lock_dir=/var/run/adl-sync.lock
|
|
128
|
-
scheduler_path=/usr/local/libexec/adl-sync
|
|
129
|
-
fi
|
|
130
|
-
if ! mkdir "$lock_dir" 2>/dev/null; then
|
|
131
|
-
echo "global-tools: another reconciliation is running (lock: $lock_dir)" >&2
|
|
132
|
-
exit 1
|
|
133
123
|
fi
|
|
134
|
-
|
|
124
|
+
adl_lock_acquire "$lock_dir" "global-tools: another reconciliation is running" || exit 1
|
|
125
|
+
trap 'rm -rf -- "$lock_dir"' EXIT
|
|
135
126
|
|
|
136
127
|
host_platform="$(sync_and_reconcile_platform)"
|
|
137
128
|
require_linux_automation_root "$host_platform" "$owner" || exit 1
|
|
138
129
|
|
|
139
130
|
if [[ "$sync_source" == checkout ]]; then
|
|
140
|
-
[[ -e "$repo/.git" ]] || { echo "developer checkout missing: $repo" >&2; exit 1; }
|
|
131
|
+
[[ -e "$repo/.git" ]] || { echo "ERROR developer checkout missing: $repo" >&2; exit 1; }
|
|
141
132
|
manifest="$repo/packages/fleet/manifest.json"
|
|
142
|
-
[[ -f "$manifest" ]] || { echo "developer checkout manifest missing: $manifest" >&2; exit 1; }
|
|
143
|
-
[[ -
|
|
133
|
+
[[ -f "$manifest" ]] || { echo "ERROR developer checkout manifest missing: $manifest" >&2; exit 1; }
|
|
134
|
+
[[ -f "$repo/bin/reconcile" ]] || { echo "ERROR developer checkout reconcile is missing: $repo/bin/reconcile" >&2; exit 1; }
|
|
144
135
|
echo "global-tools: source=checkout (developer mode)"
|
|
145
136
|
reconcile_dir="$repo/bin"
|
|
146
137
|
else
|
|
147
138
|
os="$(uname -s)"
|
|
148
139
|
arch="$(uname -m)"
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
Linux) npm_path=/home/linuxbrew/.linuxbrew/bin:/usr/bin:/bin ;;
|
|
152
|
-
*) echo "unsupported operating system for npm package: $os" >&2; exit 1 ;;
|
|
153
|
-
esac
|
|
154
|
-
npm_env=(PATH="$npm_path")
|
|
155
|
-
if [[ "$os" == Linux ]]; then npm_env=(npm_config_prefix=/usr/local PATH="$npm_path"); fi
|
|
156
|
-
npm_root="$(sudo -u "$owner" -H env "${npm_env[@]}" npm root -g)" || {
|
|
157
|
-
echo "cannot resolve the global npm root as $owner" >&2
|
|
158
|
-
exit 1
|
|
159
|
-
}
|
|
160
|
-
[[ "$npm_root" == /*/lib/node_modules ]] || {
|
|
161
|
-
echo "global npm root has an unsupported path: $npm_root" >&2
|
|
140
|
+
owner_home="$(adl_owner_home "$owner")" || {
|
|
141
|
+
echo "ERROR cannot resolve the home directory of $owner" >&2
|
|
162
142
|
exit 1
|
|
163
143
|
}
|
|
164
|
-
|
|
165
|
-
platform_dir="$(
|
|
144
|
+
global_node_modules="$(adl_global_node_modules "$owner_home")"
|
|
145
|
+
platform_dir="$(adl_platform_package_dir "$global_node_modules" "$os" "$arch")" || exit 1
|
|
166
146
|
installed_manifest="$platform_dir/packages/fleet/manifest.json"
|
|
167
147
|
package_spec=""
|
|
148
|
+
update_policy=""
|
|
149
|
+
installed_version=""
|
|
168
150
|
if [[ -f "$installed_manifest" ]]; then
|
|
151
|
+
[[ -f "$platform_dir/package.json" ]] && installed_version="$(jq -er '.version | select(type == "string")' "$platform_dir/package.json")" || {
|
|
152
|
+
echo "ERROR installed adl package has no readable version: $platform_dir/package.json" >&2
|
|
153
|
+
exit 1
|
|
154
|
+
}
|
|
169
155
|
update_policy="$(jq -er '.config.update_policy | select(type == "string")' "$installed_manifest")" || {
|
|
170
|
-
echo "installed adl package manifest has no config.update_policy: $installed_manifest" >&2
|
|
156
|
+
echo "ERROR installed adl package manifest has no config.update_policy: $installed_manifest" >&2
|
|
171
157
|
exit 1
|
|
172
158
|
}
|
|
173
159
|
case "$update_policy" in
|
|
174
|
-
latest-stable) package_spec="$(
|
|
160
|
+
latest-stable) package_spec="$(adl_package_spec latest-stable)" ;;
|
|
175
161
|
pinned)
|
|
176
162
|
pinned_version="$(jq -er --arg platform "$host_platform" '.[$platform].common.tools.adl.version | select(type == "string")' "$installed_manifest")" || {
|
|
177
|
-
echo "installed adl package manifest requires a version for pinned update_policy: $installed_manifest" >&2
|
|
163
|
+
echo "ERROR installed adl package manifest requires a version for pinned update_policy: $installed_manifest" >&2
|
|
178
164
|
exit 1
|
|
179
165
|
}
|
|
180
|
-
package_spec="$(
|
|
166
|
+
package_spec="$(adl_package_spec pinned "$pinned_version")" || exit 1
|
|
181
167
|
;;
|
|
182
|
-
*) package_spec="$(
|
|
168
|
+
*) package_spec="$(adl_package_spec "$update_policy")" || exit 1 ;;
|
|
183
169
|
esac
|
|
184
170
|
else
|
|
185
|
-
package_spec="$(
|
|
186
|
-
echo "global-tools: bootstrapping adl package from
|
|
171
|
+
package_spec="$(adl_package_spec latest-stable)"
|
|
172
|
+
echo "global-tools: bootstrapping adl package from the registry latest tag"
|
|
187
173
|
fi
|
|
188
174
|
|
|
189
175
|
if [[ -n "${SYNC_AND_RECONCILE_TEST_ROOT:-}" ]]; then
|
|
@@ -198,18 +184,43 @@ else
|
|
|
198
184
|
fi
|
|
199
185
|
prepare_adl_npm_migration "$applied_manifest" "$device" "$host_platform" "$legacy_adl" "$legacy_hash"
|
|
200
186
|
|
|
201
|
-
|
|
202
|
-
|
|
187
|
+
# NEVER DOWNGRADE (Tarun, 2026-10-01): under latest-stable the installed package is
|
|
188
|
+
# compared with the registry's `latest` first. Newer installed (a local pre-release
|
|
189
|
+
# build) and equal are kept; only an older one is updated. A lookup that fails stops
|
|
190
|
+
# the run loudly. A first install has nothing to compare, and a pinned policy installs
|
|
191
|
+
# exactly its pin.
|
|
192
|
+
skip_install=0
|
|
193
|
+
if [[ -n "$installed_version" && "$update_policy" == latest-stable ]]; then
|
|
194
|
+
registry_latest="$(adl_registry_latest "$owner" "$os" "$owner_home")" || {
|
|
195
|
+
echo "ERROR cannot read the registry latest of $adl_wrapper_package; not updating and not reconciling (run again when the registry is reachable)" >&2
|
|
196
|
+
exit 1
|
|
197
|
+
}
|
|
198
|
+
version_order="$(adl_semver_compare "$installed_version" "$registry_latest")" || exit 1
|
|
199
|
+
case "$version_order" in
|
|
200
|
+
1)
|
|
201
|
+
echo "global-tools: installed $installed_version is newer than registry latest $registry_latest; keeping it"
|
|
202
|
+
skip_install=1
|
|
203
|
+
;;
|
|
204
|
+
0)
|
|
205
|
+
echo "global-tools: installed $installed_version is already the registry latest; no update needed"
|
|
206
|
+
skip_install=1
|
|
207
|
+
;;
|
|
208
|
+
*) echo "global-tools: updating adl package $installed_version -> $registry_latest" ;;
|
|
209
|
+
esac
|
|
210
|
+
fi
|
|
211
|
+
if [[ "$skip_install" -eq 0 ]]; then
|
|
212
|
+
adl_bun_add_global "$owner" "$os" "$owner_home" "$package_spec"
|
|
213
|
+
fi
|
|
214
|
+
[[ -d "$platform_dir" ]] || { echo "ERROR bun add did not create the platform package: $platform_dir" >&2; exit 1; }
|
|
203
215
|
installed_manifest="$platform_dir/packages/fleet/manifest.json"
|
|
204
|
-
[[ -f "$installed_manifest" ]] || { echo "installed adl package manifest missing: $installed_manifest" >&2; exit 1; }
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
[[ -
|
|
208
|
-
"$platform_dir/bin/validate-manifest" "$
|
|
209
|
-
|
|
210
|
-
mv "$scheduler_path.new" "$scheduler_path"
|
|
216
|
+
[[ -f "$installed_manifest" ]] || { echo "ERROR installed adl package manifest missing: $installed_manifest" >&2; exit 1; }
|
|
217
|
+
# bun leaves every shipped file but the `bin` targets 0644, so the package's
|
|
218
|
+
# scripts are checked with -f and run through bash, never executed directly.
|
|
219
|
+
[[ -f "$platform_dir/bin/reconcile" ]] || { echo "ERROR installed adl package reconcile is missing: $platform_dir/bin/reconcile" >&2; exit 1; }
|
|
220
|
+
[[ -f "$platform_dir/bin/validate-manifest" ]] || { echo "ERROR installed adl package manifest validator is missing: $platform_dir/bin/validate-manifest" >&2; exit 1; }
|
|
221
|
+
bash "$platform_dir/bin/validate-manifest" "$installed_manifest"
|
|
211
222
|
reconcile_dir="$platform_dir/bin"
|
|
212
223
|
fi
|
|
213
224
|
|
|
214
|
-
PATH="$reconcile_dir:$PATH" "$reconcile_dir/reconcile" \
|
|
225
|
+
PATH="$reconcile_dir:$PATH" bash "$reconcile_dir/reconcile" \
|
|
215
226
|
--device "$device" --source "$sync_source" --mode "$mode"
|