@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.12 → 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 +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 +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/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 +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/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 +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 +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 -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
|
@@ -13,13 +13,10 @@
|
|
|
13
13
|
* signal for that lives now, since UserPromptSubmit only WARNS -- an
|
|
14
14
|
* empty corpus has an innocent explanation once it is per-host and
|
|
15
15
|
* per-extension, and a dead prompt is worse than a missing hint);
|
|
16
|
-
* `
|
|
17
|
-
* lean-ctx hooks shell out to it); `code-review-graph` not on PATH
|
|
18
|
-
* (the crg hooks shell out to it).
|
|
16
|
+
* `code-review-graph` not on PATH (the crg hooks shell out to it).
|
|
19
17
|
* warn — unmanaged repo (hooks no-op by design); `[hooks] enabled = false`;
|
|
20
18
|
* embedding model missing/corrupt (user-prompt-submit falls back to
|
|
21
|
-
* BM25-only, never fatal); vector half disabled
|
|
22
|
-
* count not readable.
|
|
19
|
+
* BM25-only, never fatal); vector half disabled.
|
|
23
20
|
*
|
|
24
21
|
* The vector half is "effectively disabled by cosineFloor" when the floor
|
|
25
22
|
* exceeds 1: a vector hit must reach `cosine >= cosineFloor` to enter fusion
|
|
@@ -36,8 +33,6 @@ import { scanSkills } from '../hooks/user-prompt-submit/skills.ts'
|
|
|
36
33
|
import { loadTokenizer } from '../hooks/user-prompt-submit/tokenizer.ts'
|
|
37
34
|
import { loadVectorHalf, resolveGlobalArtifactDir } from '../hooks/user-prompt-submit/vector.ts'
|
|
38
35
|
import { HOOKS_DENY_LOG_REL, HOOKS_LOG_REL } from '../hooks/log.ts'
|
|
39
|
-
import { DEFAULT_LEAN_CTX_DIR, leanCtxEnv } from '../lean-ctx/env.ts'
|
|
40
|
-
import { spawnWithTimeout } from '../lib/spawn-with-timeout.ts'
|
|
41
36
|
import { buildEngineContext } from '../rules/engine.ts'
|
|
42
37
|
import { liveEnv, liveRepoIndex } from '../rules/ports.ts'
|
|
43
38
|
import { BUILTIN_RULES, requireRegistered } from '../rules/registry.ts'
|
|
@@ -46,6 +41,9 @@ import { type CliResult, type LoadedRepo, cliError, loadRepo, parseArgs, unmanag
|
|
|
46
41
|
type Status = 'ok' | 'warn' | 'FAIL' | 'skip' | 'info'
|
|
47
42
|
type Env = Readonly<Record<string, string | undefined>>
|
|
48
43
|
|
|
44
|
+
/** Reserved for callers that previously supplied process-check timeouts. */
|
|
45
|
+
export interface DoctorOptions { readonly timeoutMs?: number }
|
|
46
|
+
|
|
49
47
|
interface Check {
|
|
50
48
|
readonly status: Status
|
|
51
49
|
readonly text: string
|
|
@@ -53,13 +51,6 @@ interface Check {
|
|
|
53
51
|
|
|
54
52
|
const check = (status: Status, name: string, detail: string): Check => ({ status, text: `${name}: ${detail}` })
|
|
55
53
|
|
|
56
|
-
export interface DoctorOptions {
|
|
57
|
-
/** Per-subprocess timeout for `lean-ctx --version` / `lean-ctx doctor --json`. */
|
|
58
|
-
readonly timeoutMs?: number
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const DEFAULT_TIMEOUT_MS = 10_000
|
|
62
|
-
|
|
63
54
|
/** Config + rule resolution, and the config the downstream checks use (null when unusable). */
|
|
64
55
|
function repoChecks(loaded: LoadedRepo): { readonly checks: Check[]; readonly config: AdlRepoConfig | null } {
|
|
65
56
|
const { state } = loaded
|
|
@@ -148,48 +139,6 @@ function modelAndVector(env: Env): Check[] {
|
|
|
148
139
|
return [model, vector]
|
|
149
140
|
}
|
|
150
141
|
|
|
151
|
-
async function leanCtxChecks(
|
|
152
|
-
loaded: LoadedRepo,
|
|
153
|
-
config: AdlRepoConfig | null,
|
|
154
|
-
env: Env,
|
|
155
|
-
timeoutMs: number,
|
|
156
|
-
): Promise<Check[]> {
|
|
157
|
-
const path = Bun.which('lean-ctx', { PATH: env.PATH ?? '' })
|
|
158
|
-
const skipAllowlist = check('skip', 'lean-ctx allowlist', 'lean-ctx not usable')
|
|
159
|
-
if (path === null) return [check('FAIL', 'lean-ctx', `not found on PATH (${env.PATH ?? ''})`), skipAllowlist]
|
|
160
|
-
const version = await spawnWithTimeout(path, ['--version'], { env, timeoutMs })
|
|
161
|
-
if (version.exitCode !== 0) {
|
|
162
|
-
const reason = version.timedOut ? `timed out after ${timeoutMs}ms` : `exited ${version.exitCode}: ${version.stderr.trim()}`
|
|
163
|
-
return [check('FAIL', 'lean-ctx', `${path} --version ${reason}`), skipAllowlist]
|
|
164
|
-
}
|
|
165
|
-
const binary = check('ok', 'lean-ctx', `${path} (${version.stdout.trim().split('\n')[0]})`)
|
|
166
|
-
|
|
167
|
-
// Same env the hooks give lean-ctx: repo-rooted LEAN_CTX_* in a managed repo, lean-ctx's own defaults otherwise (mcp.ts).
|
|
168
|
-
// `config` is the value `repoChecks` already decoded — reusing it keeps an invalid
|
|
169
|
-
// `adl-config.toml` reported by the `config` check above rather than thrown from here.
|
|
170
|
-
const root = loaded.state.managed && config !== null ? (loaded.state.root as string) : null
|
|
171
|
-
const childEnv = root === null ? { ...env } : leanCtxEnv(root, env, config?.hooks.leanCtxDir ?? DEFAULT_LEAN_CTX_DIR)
|
|
172
|
-
const scope = root === null ? 'lean-ctx defaults; LEAN_CTX_CONFIG_DIR unset' : `LEAN_CTX_CONFIG_DIR=${childEnv.LEAN_CTX_CONFIG_DIR}`
|
|
173
|
-
const unavailable = (reason: string): Check[] => [binary, check('warn', 'lean-ctx allowlist', `unavailable (${reason})`)]
|
|
174
|
-
const doctor = await spawnWithTimeout(path, ['doctor', '--json'], { env: childEnv, timeoutMs, ...(root === null ? {} : { cwd: root }) })
|
|
175
|
-
if (doctor.timedOut) return unavailable(`lean-ctx doctor --json timed out after ${timeoutMs}ms`)
|
|
176
|
-
// A non-zero exit alone is not a failure: lean-ctx 3.10.1 exits 1 whenever any of its OWN checks fail
|
|
177
|
-
// (e.g. no shell aliases) while still printing the full report. Only a report we cannot read is.
|
|
178
|
-
let parsed: { readonly checks?: readonly { readonly name?: string }[] }
|
|
179
|
-
try {
|
|
180
|
-
parsed = JSON.parse(doctor.stdout) as typeof parsed
|
|
181
|
-
} catch {
|
|
182
|
-
return unavailable(
|
|
183
|
-
doctor.exitCode === 0
|
|
184
|
-
? 'lean-ctx doctor --json printed invalid JSON'
|
|
185
|
-
: `lean-ctx doctor --json exited ${doctor.exitCode}: ${doctor.stderr.trim()}`,
|
|
186
|
-
)
|
|
187
|
-
}
|
|
188
|
-
const count = (parsed.checks ?? []).map((entry) => /Shell allowlist\s+(\d+) command/.exec(entry.name ?? '')?.[1]).find((n) => n !== undefined)
|
|
189
|
-
if (count === undefined) return unavailable('no "Shell allowlist" check in lean-ctx doctor --json')
|
|
190
|
-
return [binary, check('ok', 'lean-ctx allowlist', `${count} command(s) enforced (${scope})`)]
|
|
191
|
-
}
|
|
192
|
-
|
|
193
142
|
/** Both hook logs: path, row count, and for the deny log its last 5 rows. JSON Lines (docs/architecture/cli-design.md §5a): every line is a record, there is no header row to skip. */
|
|
194
143
|
function logChecks(loaded: LoadedRepo): Check[] {
|
|
195
144
|
if (!loaded.state.managed) return [check('skip', 'logs', 'not a managed repo (hooks log nothing here)')]
|
|
@@ -216,7 +165,7 @@ function crgCheck(env: Env): Check {
|
|
|
216
165
|
}
|
|
217
166
|
|
|
218
167
|
/** `argv` is everything after `doctor`. */
|
|
219
|
-
export async function runDoctor(argv: readonly string[], cwd: string, env: Env,
|
|
168
|
+
export async function runDoctor(argv: readonly string[], cwd: string, env: Env, _options: DoctorOptions = {}): Promise<CliResult> {
|
|
220
169
|
const parsed = parseArgs(argv, false)
|
|
221
170
|
if ('error' in parsed) return cliError(parsed.error)
|
|
222
171
|
if (parsed.positionals.length > 0) return cliError(`unexpected argument '${parsed.positionals[0]}'`)
|
|
@@ -228,7 +177,6 @@ export async function runDoctor(argv: readonly string[], cwd: string, env: Env,
|
|
|
228
177
|
...repo.checks,
|
|
229
178
|
...hooksAndSkills(loaded, repo.config),
|
|
230
179
|
...modelAndVector(env),
|
|
231
|
-
...(await leanCtxChecks(loaded, repo.config, env, options.timeoutMs ?? DEFAULT_TIMEOUT_MS)),
|
|
232
180
|
crgCheck(env),
|
|
233
181
|
...logChecks(loaded),
|
|
234
182
|
]
|
|
@@ -23,7 +23,6 @@ import {
|
|
|
23
23
|
readLegacyLock,
|
|
24
24
|
sha256Hex,
|
|
25
25
|
stripLegacyOwnership,
|
|
26
|
-
unionOwnedCommands,
|
|
27
26
|
} from './legacy-lock.ts'
|
|
28
27
|
import { type HookLockEntry, lockPathFor, readLock, writeLock } from './lock.ts'
|
|
29
28
|
import { type HookDeployProfile, type HookSurface, loadProfile } from './profile.ts'
|
|
@@ -51,13 +50,13 @@ export interface DeployHooksOptions {
|
|
|
51
50
|
readonly dryRun?: boolean
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
interface HookConflict {
|
|
55
54
|
readonly file: string
|
|
56
55
|
readonly reason: string
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
/** One hook healed via the PAIR fallback (not hash, not the legacy channel) this run — see json-merge.ts's `RestoredHook` for the full rationale (2026-09-30, round 5, finding 2). */
|
|
60
|
-
|
|
59
|
+
interface RestoredHookReport {
|
|
61
60
|
readonly file: string
|
|
62
61
|
readonly event: string
|
|
63
62
|
readonly command: string
|
|
@@ -78,17 +77,6 @@ export interface DeployHooksResult {
|
|
|
78
77
|
readonly unchanged: readonly string[]
|
|
79
78
|
readonly conflicts: readonly HookConflict[]
|
|
80
79
|
readonly lockPath: string
|
|
81
|
-
/**
|
|
82
|
-
* Surface files whose lock entry moved from the legacy
|
|
83
|
-
* (`ownedCommands`-only) shape to the content-addressed one
|
|
84
|
-
* (`ownedEntries`) on THIS run (independent review, 2026-09-30, finding
|
|
85
|
-
* 7). This can be non-empty even when the surface's own `written`/
|
|
86
|
-
* `unchanged` outcome looks like nothing happened — the deployed JSON
|
|
87
|
-
* file can stay byte-identical while the LOCK itself is rewritten, and
|
|
88
|
-
* that rewrite deserves its own truthful line in the CLI's output
|
|
89
|
-
* rather than being folded silently into "unchanged".
|
|
90
|
-
*/
|
|
91
|
-
readonly lockMigrated: readonly string[]
|
|
92
80
|
/** Hooks healed via the pair fallback this run, named explicitly (round 5, finding 2) so deploy's own output, doctor's preview, and `adl install` can all say "restored adl hook <event>/<matcher>/<command> — local changes to it were replaced". */
|
|
93
81
|
readonly restored: readonly RestoredHookReport[]
|
|
94
82
|
}
|
|
@@ -134,12 +122,11 @@ export function deployHooks(options: DeployHooksOptions): DeployHooksResult {
|
|
|
134
122
|
const written: string[] = []
|
|
135
123
|
const unchanged: string[] = []
|
|
136
124
|
const conflicts: HookConflict[] = []
|
|
137
|
-
const lockMigrated: string[] = []
|
|
138
125
|
const restored: RestoredHookReport[] = []
|
|
139
126
|
const takeover = { any: false }
|
|
140
127
|
|
|
141
128
|
for (const surface of profile.surfaces) {
|
|
142
|
-
deploySurface(surface, { assetsDir, targetRepo, hooksDoc, lock, legacyDoc, takeover, newEntries, written, unchanged, conflicts,
|
|
129
|
+
deploySurface(surface, { assetsDir, targetRepo, hooksDoc, lock, legacyDoc, takeover, newEntries, written, unchanged, conflicts, restored, dryRun })
|
|
143
130
|
}
|
|
144
131
|
|
|
145
132
|
if (!dryRun) writeLock(targetRepo, { version: 1, entries: newEntries })
|
|
@@ -158,7 +145,6 @@ export function deployHooks(options: DeployHooksOptions): DeployHooksResult {
|
|
|
158
145
|
unchanged: unchanged.sort(),
|
|
159
146
|
conflicts: conflicts.sort((a, b) => a.file.localeCompare(b.file)),
|
|
160
147
|
lockPath: lockPathFor(targetRepo),
|
|
161
|
-
lockMigrated: lockMigrated.sort(),
|
|
162
148
|
restored,
|
|
163
149
|
}
|
|
164
150
|
}
|
|
@@ -176,7 +162,6 @@ interface DeploySurfaceContext {
|
|
|
176
162
|
readonly written: string[]
|
|
177
163
|
readonly unchanged: string[]
|
|
178
164
|
readonly conflicts: HookConflict[]
|
|
179
|
-
readonly lockMigrated: string[]
|
|
180
165
|
readonly restored: RestoredHookReport[]
|
|
181
166
|
readonly dryRun: boolean
|
|
182
167
|
}
|
|
@@ -212,38 +197,24 @@ function deploySurface(surface: HookSurface, ctx: DeploySurfaceContext): void {
|
|
|
212
197
|
// Ownership is content-addressed (json-merge.ts's own header, second
|
|
213
198
|
// independent review 2026-09-29): `recordedEntries` is THIS package's own
|
|
214
199
|
// prior write, read straight from the lock as hash+command pairs, never
|
|
215
|
-
// derived from command text alone.
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
// "command text is the only proof we have" shape).
|
|
200
|
+
// derived from command text alone. `readLock` (lock.ts) has already
|
|
201
|
+
// refused any entry without `ownedEntries` (Tarun, 2026-10-01: the legacy
|
|
202
|
+
// `ownedCommands`-only shape is no longer migrated). The command-anywhere
|
|
203
|
+
// channel below is fed ONLY by `legacyTakeover.ownedByEvent` — the
|
|
204
|
+
// pre-agent-hooks engine's own hash-verified takeover signal, a different
|
|
205
|
+
// legacy source that is deliberately kept.
|
|
222
206
|
const sameFormatPrev = prevEntry !== undefined && prevEntry.format === surface.format ? prevEntry : undefined
|
|
223
|
-
const isLegacyShapedLock = sameFormatPrev !== undefined && sameFormatPrev.ownedEntries === undefined
|
|
224
|
-
// Independent review, 2026-09-30, finding 7: this transitional deploy
|
|
225
|
-
// rewrites the LOCK from the legacy (`ownedCommands`-only) shape to the
|
|
226
|
-
// content-addressed one — report it, since the deployed JSON file can
|
|
227
|
-
// stay byte-identical while that rewrite happens underneath it.
|
|
228
|
-
if (isLegacyShapedLock) ctx.lockMigrated.push(surface.file)
|
|
229
207
|
const recordedEntries = sameFormatPrev?.ownedEntries ?? {}
|
|
230
|
-
const ownCommandsLegacyFallback = isLegacyShapedLock ? sameFormatPrev.ownedCommands : {}
|
|
231
208
|
const existingRaw = readExistingJson(targetAbs)
|
|
232
209
|
const legacyTakeover = legacyTakeoverForJsonHooksSurface(existingRaw, ctx.legacyDoc, surface.file)
|
|
233
210
|
if (legacyTakeover.matched) ctx.takeover.any = true
|
|
234
|
-
const legacyCommandsAnywhere =
|
|
211
|
+
const legacyCommandsAnywhere = legacyTakeover.ownedByEvent
|
|
235
212
|
|
|
236
213
|
if (surface.format === 'cursor-hooks-v1') {
|
|
237
214
|
const desired = renderCursorEntries(ctx.hooksDoc, surface)
|
|
238
215
|
const { fileContent, ownedCommands, ownedEntries, changed, restored, ambiguousConflicts } = mergeCursorHooksFile(existingRaw, desired, recordedEntries, legacyCommandsAnywhere)
|
|
239
216
|
writeJsonIfChanged(targetAbs, fileContent, changed, ctx.dryRun)
|
|
240
|
-
|
|
241
|
-
// migration rewrites the LOCK for real even when this surface's own
|
|
242
|
-
// deployed content stays byte-identical — count that as "written",
|
|
243
|
-
// not "unchanged", so a caller reading these two arrays (which is
|
|
244
|
-
// exactly what "up to date (no changes)" and "written: N" do) never
|
|
245
|
-
// reports a pure no-op when something real did change on disk.
|
|
246
|
-
;(changed || isLegacyShapedLock ? ctx.written : ctx.unchanged).push(surface.file)
|
|
217
|
+
;(changed ? ctx.written : ctx.unchanged).push(surface.file)
|
|
247
218
|
ctx.newEntries[surface.file] = { format: 'cursor-hooks-v1', ownedCommands, ownedEntries }
|
|
248
219
|
for (const hook of restored) ctx.restored.push(makeRestoredReport(surface.file, hook))
|
|
249
220
|
for (const conflict of ambiguousConflicts) ctx.conflicts.push({ file: surface.file, reason: ambiguousConflictReason(conflict) })
|
|
@@ -254,7 +225,7 @@ function deploySurface(surface: HookSurface, ctx: DeploySurfaceContext): void {
|
|
|
254
225
|
const desired = renderJsonHooksGroups(ctx.hooksDoc, surface)
|
|
255
226
|
const { fileContent, ownedCommands, ownedEntries, changed, restored, ambiguousConflicts } = mergeJsonHooksFile(existingRaw, desired, recordedEntries, legacyCommandsAnywhere)
|
|
256
227
|
writeJsonIfChanged(targetAbs, fileContent, changed, ctx.dryRun)
|
|
257
|
-
;(changed
|
|
228
|
+
;(changed ? ctx.written : ctx.unchanged).push(surface.file)
|
|
258
229
|
ctx.newEntries[surface.file] = { format: surface.format, ownedCommands, ownedEntries }
|
|
259
230
|
for (const hook of restored) ctx.restored.push(makeRestoredReport(surface.file, hook))
|
|
260
231
|
for (const conflict of ambiguousConflicts) ctx.conflicts.push({ file: surface.file, reason: ambiguousConflictReason(conflict) })
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
import { renderCursorEntries, renderJsonHooksGroups } from './render.ts'
|
|
30
30
|
import { type CanonicalHooksDoc, loadHooksSource } from './source.ts'
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
interface DoctorIssue {
|
|
33
33
|
readonly severity: 'error' | 'info'
|
|
34
34
|
readonly path: string
|
|
35
35
|
readonly reason: string
|
|
@@ -44,7 +44,7 @@ function toResult(issues: readonly DoctorIssue[]): DoctorResult {
|
|
|
44
44
|
return { ok: issues.every((issue) => issue.severity !== 'error'), issues }
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
|
|
49
49
|
export interface DoctorDeploymentOptions {
|
|
50
50
|
readonly assetsDir: string
|
|
@@ -71,13 +71,10 @@ function doctorJsonSurface(surface: HookSurface, targetRepo: string, hooksDoc: C
|
|
|
71
71
|
const targetAbs = join(targetRepo, surface.file)
|
|
72
72
|
const exists = existsSync(targetAbs)
|
|
73
73
|
const lockEntry = lock.entries[surface.file]?.format === surface.format ? (lock.entries[surface.file] as JsonHooksLockEntry) : undefined
|
|
74
|
-
//
|
|
75
|
-
// (
|
|
76
|
-
//
|
|
77
|
-
// instead -- otherwise doctor would report drift for every currently-
|
|
78
|
-
// enrolled repo's untouched content that deploy itself recognizes fine.
|
|
74
|
+
// `readLock` has already refused any entry without `ownedEntries`
|
|
75
|
+
// (Tarun, 2026-10-01: the legacy `ownedCommands`-only shape is no longer
|
|
76
|
+
// migrated), so ownership here is always the content-addressed record.
|
|
79
77
|
const recordedEntries = lockEntry?.ownedEntries ?? {}
|
|
80
|
-
const legacyCommandsAnywhere = lockEntry !== undefined && lockEntry.ownedEntries === undefined ? lockEntry.ownedCommands : {}
|
|
81
78
|
|
|
82
79
|
let parseFailed = false
|
|
83
80
|
if (exists) {
|
|
@@ -92,8 +89,8 @@ function doctorJsonSurface(surface: HookSurface, targetRepo: string, hooksDoc: C
|
|
|
92
89
|
const existingRaw = readExistingJson(targetAbs)
|
|
93
90
|
const merged =
|
|
94
91
|
surface.format === 'cursor-hooks-v1'
|
|
95
|
-
? mergeCursorHooksFile(existingRaw, renderCursorEntries(hooksDoc, surface), recordedEntries
|
|
96
|
-
: mergeJsonHooksFile(existingRaw, renderJsonHooksGroups(hooksDoc, surface), recordedEntries
|
|
92
|
+
? mergeCursorHooksFile(existingRaw, renderCursorEntries(hooksDoc, surface), recordedEntries)
|
|
93
|
+
: mergeJsonHooksFile(existingRaw, renderJsonHooksGroups(hooksDoc, surface), recordedEntries)
|
|
97
94
|
|
|
98
95
|
if (!exists) {
|
|
99
96
|
return [{ severity: 'error', path: surface.file, reason: 'expected hook wiring has not been deployed' }]
|
|
@@ -144,7 +141,7 @@ function doctorJsonSurface(surface: HookSurface, targetRepo: string, hooksDoc: C
|
|
|
144
141
|
severity: 'error' as const,
|
|
145
142
|
path: `${surface.file}#${event}`,
|
|
146
143
|
reason:
|
|
147
|
-
recordedEntries[event] !== undefined
|
|
144
|
+
recordedEntries[event] !== undefined
|
|
148
145
|
? 'deploy-written hook entries were modified since deploy, or assets/hooks.json changed since; run deploy to update'
|
|
149
146
|
: 'expected hook wiring for this event has not been deployed',
|
|
150
147
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
export { deployHooks,
|
|
2
|
-
export { doctorDeployment,
|
|
3
|
-
export { formatHookLine, listHooks,
|
|
4
|
-
|
|
1
|
+
export { deployHooks, type DeployHooksResult, } from './deploy.ts'
|
|
2
|
+
export { doctorDeployment, type DoctorResult } from './doctor.ts'
|
|
3
|
+
export { formatHookLine, listHooks, } from './list.ts'
|
|
4
|
+
|
|
5
5
|
export {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
12
|
loadProfile,
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
|
|
15
15
|
} from './profile.ts'
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
|
|
17
|
+
|
|
@@ -44,14 +44,13 @@
|
|
|
44
44
|
* position; adl's slot is restored separately, right there — never
|
|
45
45
|
* deleted, never duplicated.
|
|
46
46
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* (`ownedEntries`), so every later deploy uses the full contract.
|
|
47
|
+
* The `legacyOwnedCommands` channel ("command text is the only proof we
|
|
48
|
+
* have") is fed ONLY by the pre-agent-hooks engine's own hash-verified
|
|
49
|
+
* takeover (legacy-lock.ts). It used to ALSO carry a one-deploy transitional
|
|
50
|
+
* fallback for a lock with no hashes at all (`ownedEntries` absent — every
|
|
51
|
+
* repo enrolled before this fix; closed (a)); that transition is over
|
|
52
|
+
* (Tarun, 2026-10-01): lock.ts's `readLock` now refuses such an entry
|
|
53
|
+
* outright, so every deploy here uses the full content-addressed contract.
|
|
55
54
|
*
|
|
56
55
|
* THIRD independent review (2026-09-30) found the fallback ITSELF still
|
|
57
56
|
* leaked through raw array position, in two ways:
|
|
@@ -61,13 +61,13 @@ export function stableStringify(value: unknown): string {
|
|
|
61
61
|
/** Content hash of a JSON value, exactly as the legacy engine recorded it. */
|
|
62
62
|
export const legacyValueHash = (value: unknown): string => sha256Hex(stableStringify(value))
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
interface LegacyJsonMergeEntry {
|
|
65
65
|
readonly type: string
|
|
66
66
|
readonly path: readonly (string | number)[]
|
|
67
67
|
readonly sha256: string
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
interface LegacyMergedRecord {
|
|
71
71
|
readonly entries?: readonly LegacyJsonMergeEntry[]
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -10,7 +10,7 @@ import { type HookLockEntry, readLock } from './lock.ts'
|
|
|
10
10
|
import { type HookDeployProfile, type HookSurface, loadProfile } from './profile.ts'
|
|
11
11
|
import { flattenSourceHooks, hookLabel, loadHooksSource, type CanonicalHooksDoc } from './source.ts'
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
type HookOwner = 'adl' | 'user' | 'conflict' | '-'
|
|
14
14
|
|
|
15
15
|
export interface HookListingEntry {
|
|
16
16
|
readonly name: string
|
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
* read it to report ownership.
|
|
8
8
|
*
|
|
9
9
|
* For a json-hooks surface (claude-settings / codex-hooks / cursor-hooks-v1),
|
|
10
|
-
* "owned" is recorded per surface event name as
|
|
11
|
-
*
|
|
10
|
+
* "owned" is recorded per surface event name as content-addressed hook
|
|
11
|
+
* entries (`ownedEntries`: hash + command + matcher), alongside the exact
|
|
12
|
+
* rendered command strings (`ownedCommands`, already carrying
|
|
13
|
+
* --host=<surface>; informational, read by list.ts). `readLock` refuses an
|
|
14
|
+
* entry without `ownedEntries` (the older `ownedCommands`-only shape is no
|
|
15
|
+
* longer migrated — Tarun, 2026-10-01). For
|
|
12
16
|
* the opencode-plugin surface, the whole file is wholly adl-owned (H3) —
|
|
13
17
|
* `owned: true` records that fact rather than a per-command breakdown.
|
|
14
18
|
*/
|
|
@@ -29,7 +33,7 @@ export const LOCK_RELATIVE_PATH = '.agents/agent-hooks.lock.json'
|
|
|
29
33
|
* never by array position/index, which the second independent review
|
|
30
34
|
* already ruled unreliable.
|
|
31
35
|
*/
|
|
32
|
-
|
|
36
|
+
interface OwnedHookEntry {
|
|
33
37
|
readonly hash: string
|
|
34
38
|
readonly command: string
|
|
35
39
|
readonly matcher?: string
|
|
@@ -37,7 +41,7 @@ export interface OwnedHookEntry {
|
|
|
37
41
|
|
|
38
42
|
export interface JsonHooksLockEntry {
|
|
39
43
|
readonly format: 'claude-settings' | 'codex-hooks' | 'cursor-hooks-v1'
|
|
40
|
-
/** Surface event name -> the exact command strings (with --host) this deploy wrote into that event's array — informational only (list.ts); ownership itself is `ownedEntries`, below. */
|
|
44
|
+
/** Surface event name -> the exact command strings (with --host) this deploy wrote into that event's array — informational only (list.ts reads it to label what is adl's); ownership itself is `ownedEntries`, below. */
|
|
41
45
|
readonly ownedCommands: Readonly<Record<string, readonly string[]>>
|
|
42
46
|
/**
|
|
43
47
|
* Surface event name -> this deploy's own written hooks, content-
|
|
@@ -45,16 +49,14 @@ export interface JsonHooksLockEntry {
|
|
|
45
49
|
* pure array-index tracking, broke the moment a user inserted or
|
|
46
50
|
* removed an entry before adl's own block, and could not express
|
|
47
51
|
* "split a group" when a user hook was appended inside one — see
|
|
48
|
-
* json-merge.ts's header for the corrected rule).
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* once from `ownedCommands` by exact command match, then persist real
|
|
52
|
-
* entries here," never as malformed.
|
|
52
|
+
* json-merge.ts's header for the corrected rule). Required: `readLock`
|
|
53
|
+
* refuses an entry without it (Tarun, 2026-10-01: the transitional
|
|
54
|
+
* rewrite of the older `ownedCommands`-only shape is gone).
|
|
53
55
|
*/
|
|
54
|
-
readonly ownedEntries
|
|
56
|
+
readonly ownedEntries: Readonly<Record<string, readonly OwnedHookEntry[]>>
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
interface OpencodePluginLockEntry {
|
|
58
60
|
readonly format: 'opencode-plugin'
|
|
59
61
|
readonly owned: true
|
|
60
62
|
}
|
|
@@ -86,7 +88,24 @@ export function readLock(targetRepo: string): HookLock {
|
|
|
86
88
|
if (typeof record !== 'object' || record === null || record.version !== 1 || typeof record.entries !== 'object' || record.entries === null) {
|
|
87
89
|
throw new Error(`agent-hooks lock has an unrecognized shape: ${path}`)
|
|
88
90
|
}
|
|
89
|
-
|
|
91
|
+
const entries = record.entries as Record<string, HookLockEntry>
|
|
92
|
+
// Tarun, 2026-10-01: the legacy (`ownedCommands` without `ownedEntries`) ->
|
|
93
|
+
// content-addressed migration is over. Reading such an entry as "owns
|
|
94
|
+
// nothing" would duplicate every adl hook already in the file, and
|
|
95
|
+
// guessing ownership from command text is the very thing content-
|
|
96
|
+
// addressing replaced — so refuse, loudly, and say how to recover.
|
|
97
|
+
for (const [file, entry] of Object.entries(entries)) {
|
|
98
|
+
if (typeof entry !== 'object' || entry === null || entry.format === 'opencode-plugin') continue
|
|
99
|
+
const ownedEntries: unknown = (entry as { ownedEntries?: unknown }).ownedEntries
|
|
100
|
+
if (typeof ownedEntries !== 'object' || ownedEntries === null || Array.isArray(ownedEntries)) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
`agent-hooks lock entry for ${file} has no usable \`ownedEntries\` (the older \`ownedCommands\`-only shape is no longer migrated): ${path}. ` +
|
|
103
|
+
`Recover by removing the adl-written hook commands listed under that entry's \`ownedCommands\` from ${file}, deleting that entry from the lock (or deleting the lock file), ` +
|
|
104
|
+
`then running \`adl hooks deploy --repo ${targetRepo}\` to re-enrol.`,
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return { version: 1, entries }
|
|
90
109
|
}
|
|
91
110
|
|
|
92
111
|
/** Skips the write entirely when the serialized content is already byte-identical (independent review, 2026-09-29, finding 8: a genuine no-op run must not touch the lock file's mtime either). */
|
|
@@ -16,11 +16,10 @@ import Ajv, { type ErrorObject, type ValidateFunction } from 'ajv'
|
|
|
16
16
|
import { readFileSync } from 'node:fs'
|
|
17
17
|
import { fileURLToPath } from 'node:url'
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
export const HOOK_WIRE_FORMATS: readonly HookWireFormat[] = ['claude-settings', 'codex-hooks', 'cursor-hooks-v1', 'opencode-plugin']
|
|
19
|
+
type HookWireFormat = 'claude-settings' | 'codex-hooks' | 'cursor-hooks-v1' | 'opencode-plugin'
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
type UnmappedMatcherPolicy = 'keep' | 'drop'
|
|
22
|
+
type TimeoutUnit = 's' | 'ms'
|
|
24
23
|
|
|
25
24
|
export interface HookSurface {
|
|
26
25
|
readonly name: string
|
|
@@ -23,7 +23,7 @@ export interface CanonicalHookGroup {
|
|
|
23
23
|
|
|
24
24
|
export type CanonicalHooksDoc = ReadonlyMap<string, readonly CanonicalHookGroup[]>
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
const DEFAULT_HOOKS_SOURCE_PATH = fileURLToPath(new URL('../../assets/hooks.json', import.meta.url))
|
|
27
27
|
|
|
28
28
|
function isHookCommand(value: unknown): value is CanonicalHookCommand {
|
|
29
29
|
if (typeof value !== 'object' || value === null) return false
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
* `adl-config.toml` is shared with other tools at the same root: adl hook
|
|
11
11
|
* owns `[hooks]`, `[rules]`, and `[repo]`; `adl-repo-controls` owns
|
|
12
12
|
* `[controls]`; `adl-extensions` owns `[extensions]` (and, before its
|
|
13
|
-
* HARDCUT, `[skills]`). `[
|
|
14
|
-
*
|
|
13
|
+
* HARDCUT, `[skills]`). `[azdo]` is reserved for shared Azure DevOps
|
|
14
|
+
* configuration. `[controls]`, `[skills]`, and `[azdo]` are recognized root
|
|
15
|
+
* tables this module accepts and never reads into.
|
|
15
16
|
*
|
|
16
17
|
* `[extensions]` is the one exception, and a deliberate one: its sub-table
|
|
17
18
|
* KEYS are decoded into `AdlRepoConfig.extensions`. Since adl-extensions
|
|
@@ -27,13 +28,6 @@
|
|
|
27
28
|
* # (pre-tool-use, user-prompt-submit, briefing,
|
|
28
29
|
* # crg) for this repo: exit 0, empty stdout/stderr.
|
|
29
30
|
* skills_dir = ".agents/skills" # optional; see src/hooks/user-prompt-submit
|
|
30
|
-
* lean_ctx_dir = ".agents/lean-ctx" # optional; repo-relative root for
|
|
31
|
-
* # lean-ctx's own config/data/state/cache dirs
|
|
32
|
-
* # (see src/lean-ctx/env.ts). A throwaway repo
|
|
33
|
-
* # — a binary test fixture, say — sets this so
|
|
34
|
-
* # lean-ctx's state, and any daemon it starts
|
|
35
|
-
* # off that state, lands somewhere disposable
|
|
36
|
-
* # instead of the default.
|
|
37
31
|
*
|
|
38
32
|
* [rules]
|
|
39
33
|
* default = "on" # "on" | "off"; baseline for rules with no
|
|
@@ -69,7 +63,7 @@
|
|
|
69
63
|
|
|
70
64
|
import { MARKER } from './root.ts'
|
|
71
65
|
|
|
72
|
-
|
|
66
|
+
interface RuleSection {
|
|
73
67
|
readonly enabled: boolean
|
|
74
68
|
}
|
|
75
69
|
|
|
@@ -79,11 +73,9 @@ export interface RulesConfig {
|
|
|
79
73
|
readonly byId: Readonly<Record<string, RuleSection>>
|
|
80
74
|
}
|
|
81
75
|
|
|
82
|
-
|
|
76
|
+
interface HooksConfig {
|
|
83
77
|
readonly enabled: boolean
|
|
84
78
|
readonly skillsDir: string | undefined
|
|
85
|
-
/** Repo-relative root for lean-ctx's config/data/state/cache; see `../lean-ctx/env.ts`. */
|
|
86
|
-
readonly leanCtxDir: string | undefined
|
|
87
79
|
}
|
|
88
80
|
|
|
89
81
|
/**
|
|
@@ -185,7 +177,7 @@ const DEFAULT_AGENT: AgentSection = {
|
|
|
185
177
|
}
|
|
186
178
|
|
|
187
179
|
const DEFAULT_CONFIG: AdlRepoConfig = {
|
|
188
|
-
hooks: { enabled: true, skillsDir: undefined
|
|
180
|
+
hooks: { enabled: true, skillsDir: undefined },
|
|
189
181
|
rules: { default: 'on', unsafeAllowUncertain: false, byId: {} },
|
|
190
182
|
repo: DEFAULT_REPO,
|
|
191
183
|
agent: DEFAULT_AGENT,
|
|
@@ -222,13 +214,13 @@ function rejectUnknownKeys(
|
|
|
222
214
|
* Top-level keys `decodeConfig` recognizes. `version` is accepted (and
|
|
223
215
|
* ignored) only so the marker file's own minimal `version = 1\n` convention
|
|
224
216
|
* stays valid — this package has no schema migrations to gate on it.
|
|
225
|
-
* controls/skills: see module header for ownership.
|
|
217
|
+
* controls/skills/azdo: see module header for ownership.
|
|
226
218
|
*/
|
|
227
219
|
/**
|
|
228
220
|
* Root tables this module accepts. It owns `version`/`hooks`/`rules`/`repo`
|
|
229
221
|
* and never reads the rest — they belong to the other tools sharing this file:
|
|
230
|
-
* `controls` to adl-repo-controls,
|
|
231
|
-
* adl-extensions.
|
|
222
|
+
* `controls` to adl-repo-controls, `extensions` (formerly `skills`) to
|
|
223
|
+
* adl-extensions, and `azdo` to shared Azure DevOps configuration.
|
|
232
224
|
*
|
|
233
225
|
* `skills` is retained alongside `extensions` on purpose. adl-extensions
|
|
234
226
|
* HARDCUT to `[extensions]` because an extension owns its skills rather than
|
|
@@ -237,7 +229,7 @@ function rejectUnknownKeys(
|
|
|
237
229
|
* here would fail exactly those repos, the ones nobody has touched yet.
|
|
238
230
|
*/
|
|
239
231
|
const KNOWN_ROOT_KEYS: ReadonlySet<string> = new Set([
|
|
240
|
-
'version', 'hooks', 'rules', 'repo', 'agent', 'controls', 'skills', 'extensions',
|
|
232
|
+
'version', 'hooks', 'rules', 'repo', 'agent', 'controls', 'skills', 'extensions', 'azdo',
|
|
241
233
|
])
|
|
242
234
|
|
|
243
235
|
/**
|
|
@@ -314,17 +306,11 @@ function decodeHooks(value: unknown): { ok: true; value: HooksConfig } | { ok: f
|
|
|
314
306
|
return { ok: false, issue: { pointer: '/hooks/skills_dir', message: 'expected a string' } }
|
|
315
307
|
}
|
|
316
308
|
|
|
317
|
-
const leanCtxDirRaw = value.lean_ctx_dir
|
|
318
|
-
if (leanCtxDirRaw !== undefined && typeof leanCtxDirRaw !== 'string') {
|
|
319
|
-
return { ok: false, issue: { pointer: '/hooks/lean_ctx_dir', message: 'expected a string' } }
|
|
320
|
-
}
|
|
321
|
-
|
|
322
309
|
return {
|
|
323
310
|
ok: true,
|
|
324
311
|
value: {
|
|
325
312
|
enabled: enabledRaw ?? true,
|
|
326
313
|
skillsDir: skillsDirRaw,
|
|
327
|
-
leanCtxDir: leanCtxDirRaw,
|
|
328
314
|
},
|
|
329
315
|
}
|
|
330
316
|
}
|
|
@@ -28,7 +28,7 @@ import { dirname, join } from 'node:path'
|
|
|
28
28
|
import { statSync } from 'node:fs'
|
|
29
29
|
|
|
30
30
|
/** Guard against a symlink loop or a pathological mount turning the walk into a hang. */
|
|
31
|
-
|
|
31
|
+
const MAX_WALK_DEPTH = 128
|
|
32
32
|
|
|
33
33
|
/** The repo marker + settings file (docs/architecture/adl-config.md). Hard cut (Tarun, 2026-09-27): no fallback read of the old `adl-config.toml` name. */
|
|
34
34
|
export const MARKER = 'adl-config.toml'
|
|
@@ -40,7 +40,7 @@ export interface RootIO {
|
|
|
40
40
|
readonly cwd: () => string
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
interface GitRootResult {
|
|
44
44
|
readonly root: string | null
|
|
45
45
|
readonly searched: readonly string[]
|
|
46
46
|
}
|
|
@@ -50,7 +50,7 @@ export interface GitRootResult {
|
|
|
50
50
|
* Stops at the first one found, at the filesystem root, or after
|
|
51
51
|
* `MAX_WALK_DEPTH` levels — whichever comes first.
|
|
52
52
|
*/
|
|
53
|
-
|
|
53
|
+
function findGitRoot(io: RootIO, startDir: string): GitRootResult {
|
|
54
54
|
const searched: string[] = []
|
|
55
55
|
let current = startDir
|
|
56
56
|
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import type { HookInvocation, HookResult } from '../contract.ts'
|
|
16
|
-
import {
|
|
16
|
+
import { createBriefingHandler } from './index.ts'
|
|
17
17
|
|
|
18
|
-
const briefingHandler = createBriefingHandler(
|
|
18
|
+
const briefingHandler = createBriefingHandler()
|
|
19
19
|
|
|
20
20
|
export async function handleBriefing(inv: HookInvocation): Promise<HookResult> {
|
|
21
21
|
return briefingHandler(inv)
|