@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
|
@@ -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)
|
|
@@ -1,320 +1,60 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `briefing` hook kind.
|
|
3
|
-
*
|
|
4
|
-
* Ports `enact-m5/.agents/hooks/session-briefing/`
|
|
5
|
-
* (`session-briefing.mjs` + `src/render.mjs` + `src/warmup.mjs`) onto the
|
|
6
|
-
* `HookHandler` contract in `../contract.ts`.
|
|
7
|
-
*
|
|
8
|
-
* Two subprocess calls into `lean-ctx`, both behind the injected `Runner` so
|
|
9
|
-
* tests never touch a real binary:
|
|
10
|
-
*
|
|
11
|
-
* 1. `hook codex-session-start` — the base lean-ctx session briefing text,
|
|
12
|
-
* read out of its `hookSpecificOutput.additionalContext` JSON.
|
|
13
|
-
* 2. `overview [task]` and `knowledge status` — the PROJECT WARMUP appendix,
|
|
14
|
-
* always emitted (even with no lean-ctx at all) because its static
|
|
15
|
-
* workflow block does not depend on either call succeeding.
|
|
16
|
-
*
|
|
17
|
-
* `lean-ctx` is a GLOBAL binary installed fleet-wide on `PATH` by
|
|
18
|
-
* global-tools (see its `manifest.json`'s `"lean-ctx"` entry) — unlike the
|
|
19
|
-
* reference tree, there is no repo-local `.agents/bin/lean-ctx-local`
|
|
20
|
-
* wrapper here, so every call below resolves `lean-ctx` off the ambient
|
|
21
|
-
* `PATH` directly. What stays repo-local is lean-ctx's own state: every call
|
|
22
|
-
* still sets `LEAN_CTX_CONFIG_DIR`/`LEAN_CTX_DATA_DIR`/`LEAN_CTX_STATE_DIR`/
|
|
23
|
-
* `LEAN_CTX_CACHE_DIR` rooted at `<root>/.agents/lean-ctx/<config/lean-ctx|data|state|cache>`
|
|
24
|
-
* (`../../lean-ctx/env.ts`'s `leanCtxEnv` — shared with the `lean-ctx`
|
|
25
|
-
* pre/post-tool-use hook kind, `../lean-ctx/index.ts`), so lean-ctx's
|
|
26
|
-
* config/data/state/cache stay per-repository even though the binary itself
|
|
27
|
-
* is now shared.
|
|
28
|
-
*
|
|
29
|
-
* HARDCUT (work item A.3): this used to set the plain `XDG_CONFIG_HOME`/
|
|
30
|
-
* `XDG_DATA_HOME`/`XDG_STATE_HOME`/`XDG_CACHE_HOME` vars, mirroring what the
|
|
31
|
-
* reference's wrapper script exported before exec'ing its own repo-local
|
|
32
|
-
* binary. `../../lean-ctx/env.ts`'s header records the live verification
|
|
33
|
-
* (this session, 2026-09-14) that the real v3.9.20 binary does not actually
|
|
34
|
-
* key its config/data/state/cache resolution on those XDG vars at all — only
|
|
35
|
-
* on the four `LEAN_CTX_*` ones now used here.
|
|
36
|
-
*
|
|
37
|
-
* lean-ctx missing or failing is advisory, never fatal: the warmup section
|
|
38
|
-
* still goes out and the failure is named on stderr, but this never returns
|
|
39
|
-
* exitCode 2 — a briefing hook has no host-visible "block" channel, and the
|
|
40
|
-
* reference script's own header says the same ("Advises only — never block
|
|
41
|
-
* the session or prompt"). A spawn that never exits (gap #1) degrades the
|
|
42
|
-
* same way: the injected `Runner` is timeout-enforcing (see
|
|
43
|
-
* `../../lib/spawn-with-timeout.ts`), so a hung `lean-ctx` child is killed
|
|
44
|
-
* and reported exactly like a failed/ENOENT spawn — `status: null` — rather
|
|
45
|
-
* than hanging the calling agent host.
|
|
46
|
-
*
|
|
47
|
-
* `deploy.mjs`-level concerns from the reference tree — wiring the hook into
|
|
48
|
-
* each host's config, `--self-test`/`--host=`/`--event=` argv parsing, the
|
|
49
|
-
* five-surface deploy fixture in `tests/test-wiring.mjs` — are out of scope
|
|
50
|
-
* here: `src/hosts/*` and `src/main.ts`'s dispatch own that, per this task's
|
|
51
|
-
* boundary.
|
|
52
|
-
*/
|
|
53
|
-
|
|
1
|
+
/** Static session-orientation briefing for supported agent hosts. */
|
|
54
2
|
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
|
55
3
|
import { join } from 'node:path'
|
|
56
|
-
|
|
57
4
|
import type { HookHandler, HookInvocation, HookResult, HostId } from '../contract.ts'
|
|
58
5
|
import { spawnWithTimeout } from '../../lib/spawn-with-timeout.ts'
|
|
59
|
-
import { leanCtxEnvFor } from '../../lean-ctx/env.ts'
|
|
60
|
-
|
|
61
|
-
/** The marker lean-ctx's own `hook codex-session-start` output carries, when present. */
|
|
62
|
-
export const MARKER = 'lean-ctx SESSION BRIEFING'
|
|
63
|
-
export const WARMUP_MARKER = 'PROJECT WARMUP'
|
|
64
|
-
|
|
65
|
-
const LEAN_CTX_BIN = 'lean-ctx'
|
|
66
6
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const DEFAULT_TIMEOUT_MS = 8_000
|
|
70
|
-
|
|
71
|
-
export interface RunResult {
|
|
72
|
-
readonly status: number | null
|
|
73
|
-
readonly stdout: string
|
|
74
|
-
readonly stderr: string
|
|
75
|
-
/** `true` only when the spawn was killed for exceeding `timeoutMs` — see gap #1. */
|
|
76
|
-
readonly timedOut?: boolean
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export interface RunOptions {
|
|
80
|
-
readonly cwd: string
|
|
81
|
-
readonly env: Readonly<Record<string, string | undefined>>
|
|
82
|
-
readonly input?: string
|
|
83
|
-
/** Wall-clock spawn timeout in ms; overridable per call, defaults per call site below. */
|
|
84
|
-
readonly timeoutMs?: number
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** Process spawning, injected so tests never need a real `lean-ctx` binary. */
|
|
7
|
+
interface RunResult { readonly status: number | null; readonly stdout: string; readonly stderr: string; readonly timedOut?: boolean }
|
|
8
|
+
interface RunOptions { readonly cwd: string; readonly env: Readonly<Record<string, string | undefined>>; readonly input?: string; readonly timeoutMs?: number }
|
|
88
9
|
export type Runner = (cmd: string, args: readonly string[], opts: RunOptions) => Promise<RunResult>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const raw = payload['session_id'] ?? payload['conversation_id']
|
|
96
|
-
return typeof raw === 'string' && raw.trim().length > 0 ? raw.trim() : 'unknown'
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** Cursor and Kimi have no host-native "fire once at SessionStart" channel; gate on a marker file instead. */
|
|
100
|
-
function usesPromptGate(host: HostId): boolean {
|
|
101
|
-
return host === 'cursor' || host === 'kimi'
|
|
10
|
+
/** Kept for the shared subprocess-runner contract used by focused tests. */
|
|
11
|
+
export const bunRunner: Runner = async (cmd, args, opts) => {
|
|
12
|
+
try {
|
|
13
|
+
const result = await spawnWithTimeout(cmd, args, { cwd: opts.cwd, env: opts.env, timeoutMs: opts.timeoutMs ?? 8_000, ...(opts.input === undefined ? {} : { stdin: opts.input }) })
|
|
14
|
+
return result.timedOut ? { status: null, stdout: result.stdout, stderr: result.stderr.trim() || `${cmd} timed out after ${opts.timeoutMs ?? 8_000}ms`, timedOut: true } : { status: result.exitCode, stdout: result.stdout, stderr: result.stderr }
|
|
15
|
+
} catch (error) { return { status: null, stdout: '', stderr: error instanceof Error ? error.message : String(error) } }
|
|
102
16
|
}
|
|
103
17
|
|
|
104
|
-
|
|
105
|
-
return join(deliveredStateDir(root), `${host}-${session}.done`)
|
|
106
|
-
}
|
|
18
|
+
const WARMUP_MARKER = 'PROJECT WARMUP'
|
|
107
19
|
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
|
|
20
|
+
function deliveredStateDir(root: string): string { return join(root, '.adl', 'state', 'session-briefing-delivered') }
|
|
21
|
+
function sessionId(payload: Record<string, unknown>): string {
|
|
22
|
+
const raw = payload.session_id ?? payload.conversation_id
|
|
23
|
+
return typeof raw === 'string' && raw.trim() ? raw.trim() : 'unknown'
|
|
111
24
|
}
|
|
112
|
-
|
|
25
|
+
function usesPromptGate(host: HostId): boolean { return host === 'cursor' || host === 'kimi' }
|
|
26
|
+
function deliveredPath(root: string, host: HostId, session: string): string { return join(deliveredStateDir(root), `${host}-${session}.done`) }
|
|
27
|
+
function alreadyDelivered(root: string, host: HostId, session: string): boolean { return usesPromptGate(host) && existsSync(deliveredPath(root, host, session)) }
|
|
113
28
|
function markDelivered(root: string, host: HostId, session: string): void {
|
|
114
29
|
if (!usesPromptGate(host)) return
|
|
115
30
|
mkdirSync(deliveredStateDir(root), { recursive: true })
|
|
116
31
|
writeFileSync(deliveredPath(root, host, session), `${new Date().toISOString()}\n`)
|
|
117
32
|
}
|
|
118
|
-
|
|
119
|
-
function runLeanCtx(
|
|
120
|
-
run: Runner,
|
|
121
|
-
root: string,
|
|
122
|
-
env: Readonly<Record<string, string | undefined>>,
|
|
123
|
-
args: readonly string[],
|
|
124
|
-
timeoutMs = DEFAULT_TIMEOUT_MS,
|
|
125
|
-
): Promise<RunResult> {
|
|
126
|
-
return run(LEAN_CTX_BIN, args, { cwd: root, env: leanCtxEnvFor(root, env), timeoutMs })
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function truncateLines(text: string, maxLines: number): string {
|
|
130
|
-
const lines = text.split('\n')
|
|
131
|
-
if (lines.length <= maxLines) return text
|
|
132
|
-
return `${lines.slice(0, maxLines).join('\n')}\n… (${lines.length - maxLines} more lines; call ctx_overview for full map)`
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function taskFromPayload(payload: Record<string, unknown>): string {
|
|
136
|
-
const prompt = payload['prompt']
|
|
137
|
-
const trimmed = typeof prompt === 'string' ? prompt.trim() : ''
|
|
138
|
-
if (trimmed.length < 8) return ''
|
|
139
|
-
return trimmed.length > 120 ? `${trimmed.slice(0, 117)}…` : trimmed
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function workflowBlock(): string {
|
|
33
|
+
function briefingText(): string {
|
|
143
34
|
return [
|
|
144
|
-
WARMUP_MARKER,
|
|
145
|
-
'',
|
|
146
|
-
'Start every session (ctx_* or lean-ctx; use ctx_call when not advertised):',
|
|
147
|
-
'• ctx_overview / lean-ctx overview ["task"] — project map; FIRST on unfamiliar work',
|
|
35
|
+
WARMUP_MARKER, '',
|
|
36
|
+
'Start every session with ctx_overview when it is available; use ctx_call when it is not advertised.',
|
|
148
37
|
'• ctx_knowledge(action="wakeup") — cross-session facts and decisions',
|
|
149
|
-
'• ctx_session(action="status") — last session findings in this
|
|
150
|
-
'',
|
|
151
|
-
'Knowledge: ctx_knowledge or lean-ctx knowledge — status | recall | search | remember | consolidate',
|
|
152
|
-
'Checkpoints: ctx_session(action="task"|"decision", …) after significant progress',
|
|
153
|
-
'',
|
|
38
|
+
'• ctx_session(action="status") — last session findings in this repository', '',
|
|
154
39
|
'After orientation: ctx_compose → ctx_read/ctx_search → ctx_shell (verify) → persist.',
|
|
155
40
|
].join('\n')
|
|
156
41
|
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* The PROJECT WARMUP appendix. Always non-empty — its static workflow block
|
|
160
|
-
* does not depend on `lean-ctx` at all — so a briefing is never fully silent
|
|
161
|
-
* just because the binary is missing.
|
|
162
|
-
*/
|
|
163
|
-
async function projectWarmupAppendix(
|
|
164
|
-
run: Runner,
|
|
165
|
-
root: string,
|
|
166
|
-
env: Readonly<Record<string, string | undefined>>,
|
|
167
|
-
payload: Record<string, unknown>,
|
|
168
|
-
): Promise<string> {
|
|
169
|
-
const parts = [workflowBlock()]
|
|
170
|
-
|
|
171
|
-
const task = taskFromPayload(payload)
|
|
172
|
-
const overviewArgs = task ? ['overview', task] : ['overview']
|
|
173
|
-
const overview = await runLeanCtx(run, root, env, overviewArgs, OVERVIEW_TIMEOUT_MS)
|
|
174
|
-
if (overview.status === 0 && overview.stdout.trim()) {
|
|
175
|
-
parts.push('', '--- ctx_overview (cached snapshot) ---', truncateLines(overview.stdout.trim(), OVERVIEW_MAX_LINES))
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const knowledge = await runLeanCtx(run, root, env, ['knowledge', 'status'])
|
|
179
|
-
if (knowledge.status === 0 && knowledge.stdout.trim()) {
|
|
180
|
-
parts.push('', '--- ctx_knowledge status ---', knowledge.stdout.trim())
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return parts.join('\n')
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function composeBriefing(base: string, warmup: string): string {
|
|
187
|
-
const b = base.trim()
|
|
188
|
-
const w = warmup.trim()
|
|
189
|
-
if (b && w) return `${b}\n\n${w}`
|
|
190
|
-
return b || w
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
interface BaseBriefing {
|
|
194
|
-
readonly text: string
|
|
195
|
-
readonly failureNote: string
|
|
196
|
-
readonly outcome: 'ok' | 'timeout' | 'error'
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/** Runs `lean-ctx hook codex-session-start`; failure degrades to an empty base text plus a stderr note. */
|
|
200
|
-
async function baseBriefing(
|
|
201
|
-
run: Runner,
|
|
202
|
-
root: string,
|
|
203
|
-
env: Readonly<Record<string, string | undefined>>,
|
|
204
|
-
payload: Record<string, unknown>,
|
|
205
|
-
): Promise<BaseBriefing> {
|
|
206
|
-
const result = await run(LEAN_CTX_BIN, ['hook', 'codex-session-start'], {
|
|
207
|
-
cwd: root,
|
|
208
|
-
env: leanCtxEnvFor(root, env),
|
|
209
|
-
input: JSON.stringify(payload),
|
|
210
|
-
timeoutMs: DEFAULT_TIMEOUT_MS,
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
if (result.status !== 0 || !result.stdout.trim()) {
|
|
214
|
-
const reason = result.stderr.trim() || `lean-ctx exited with status ${String(result.status)}`
|
|
215
|
-
return {
|
|
216
|
-
text: '',
|
|
217
|
-
failureNote: `session-briefing: lean-ctx hook codex-session-start failed — ${reason}\n`,
|
|
218
|
-
outcome: result.timedOut ? 'timeout' : 'error',
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
try {
|
|
223
|
-
const parsed = JSON.parse(result.stdout) as { hookSpecificOutput?: { additionalContext?: unknown } }
|
|
224
|
-
const text = parsed.hookSpecificOutput?.additionalContext
|
|
225
|
-
return { text: typeof text === 'string' ? text : '', failureNote: '', outcome: 'ok' }
|
|
226
|
-
} catch (error) {
|
|
227
|
-
const message = error instanceof Error ? error.message : String(error)
|
|
228
|
-
return {
|
|
229
|
-
text: '',
|
|
230
|
-
failureNote: `session-briefing: lean-ctx hook codex-session-start returned invalid JSON — ${message}\n`,
|
|
231
|
-
outcome: 'error',
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Wrap briefing text in a host's native envelope.
|
|
238
|
-
*
|
|
239
|
-
* Per official docs where they differ from the reference tree:
|
|
240
|
-
* - Claude / Codex SessionStart (and any other event): `hookSpecificOutput.additionalContext`.
|
|
241
|
-
* - Cursor: flat `additional_context` — the reference's nested
|
|
242
|
-
* `hookSpecificOutput` shape for Cursor `UserPromptSubmit` is not part of
|
|
243
|
-
* Cursor's documented hook contract, so it is not ported here.
|
|
244
|
-
* - Kimi: bare stdout text (its `UserPromptSubmit` hook has no JSON envelope).
|
|
245
|
-
* - OpenCode: `{"advice": "..."}`, consumed by this repo's own OpenCode plugin.
|
|
246
|
-
*/
|
|
247
42
|
function renderBriefing(host: HostId, event: string, text: string): string {
|
|
248
|
-
if (!text) return ''
|
|
249
43
|
if (host === 'kimi') return `${text}\n`
|
|
250
44
|
if (host === 'opencode') return JSON.stringify({ advice: text })
|
|
251
45
|
if (host === 'cursor') return JSON.stringify({ additional_context: text })
|
|
252
46
|
return JSON.stringify({ hookSpecificOutput: { hookEventName: event, additionalContext: text } })
|
|
253
47
|
}
|
|
254
48
|
|
|
255
|
-
export function createBriefingHandler(
|
|
49
|
+
export function createBriefingHandler(): HookHandler {
|
|
256
50
|
return async (inv: HookInvocation): Promise<HookResult> => {
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
const event = inv.event ?? 'SessionStart'
|
|
260
|
-
const session = sessionId(payload)
|
|
261
|
-
|
|
262
|
-
if (alreadyDelivered(root, host, session)) {
|
|
51
|
+
const session = sessionId(inv.payload)
|
|
52
|
+
if (alreadyDelivered(inv.root, inv.host, session)) {
|
|
263
53
|
inv.record?.({ reason: 'SKIP already delivered this session' })
|
|
264
54
|
return { stdout: '', stderr: '', exitCode: 0 }
|
|
265
55
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const text = composeBriefing(base, warmup)
|
|
270
|
-
|
|
271
|
-
markDelivered(root, host, session)
|
|
272
|
-
const reasons = { ok: 'PASS', timeout: 'TIMEOUT lean-ctx hook codex-session-start', error: 'ERROR lean-ctx hook codex-session-start' }
|
|
273
|
-
inv.record?.({
|
|
274
|
-
reason: reasons[outcome],
|
|
275
|
-
message: failureNote.trim(),
|
|
276
|
-
downstream: 'lean-ctx hook codex-session-start, lean-ctx overview, lean-ctx knowledge status',
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
return {
|
|
280
|
-
stdout: renderBriefing(host, event, text),
|
|
281
|
-
stderr: failureNote,
|
|
282
|
-
exitCode: 0,
|
|
283
|
-
}
|
|
56
|
+
markDelivered(inv.root, inv.host, session)
|
|
57
|
+
inv.record?.({ reason: 'PASS', downstream: 'static session briefing' })
|
|
58
|
+
return { stdout: renderBriefing(inv.host, inv.event ?? 'SessionStart', briefingText()), stderr: '', exitCode: 0 }
|
|
284
59
|
}
|
|
285
60
|
}
|
|
286
|
-
|
|
287
|
-
/**
|
|
288
|
-
* The production `Runner`: a real, timeout-enforcing subprocess via
|
|
289
|
-
* `spawnWithTimeout` (see `../../lib/spawn-with-timeout.ts`) — replaces the
|
|
290
|
-
* reference tree's `Bun.spawnSync`, which had no timeout and could hang the
|
|
291
|
-
* calling agent host forever on a stuck `lean-ctx` child (gap #1). A timeout
|
|
292
|
-
* degrades exactly like an ENOENT/failed spawn: `status: null` with the
|
|
293
|
-
* reason on stderr, plus `timedOut: true` so callers can tell the two apart.
|
|
294
|
-
*/
|
|
295
|
-
export const bunRunner: Runner = async (cmd, args, opts) => {
|
|
296
|
-
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
297
|
-
try {
|
|
298
|
-
const result = await spawnWithTimeout(cmd, args, {
|
|
299
|
-
cwd: opts.cwd,
|
|
300
|
-
env: opts.env,
|
|
301
|
-
timeoutMs,
|
|
302
|
-
...(opts.input !== undefined ? { stdin: opts.input } : {}),
|
|
303
|
-
})
|
|
304
|
-
if (result.timedOut) {
|
|
305
|
-
return {
|
|
306
|
-
status: null,
|
|
307
|
-
stdout: result.stdout,
|
|
308
|
-
stderr: result.stderr.trim() || `${cmd} timed out after ${timeoutMs}ms`,
|
|
309
|
-
timedOut: true,
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
return { status: result.exitCode, stdout: result.stdout, stderr: result.stderr }
|
|
313
|
-
} catch (error) {
|
|
314
|
-
const message = error instanceof Error ? error.message : String(error)
|
|
315
|
-
return { status: null, stdout: '', stderr: message }
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
export const handleBriefing: HookHandler = createBriefingHandler({ run: bunRunner })
|
|
320
|
-
export default handleBriefing
|