@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
|
@@ -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
|
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* `controls hook <kind> --host=X` is invoked by agent hosts (Claude Code,
|
|
5
5
|
* Codex, Cursor, OpenCode, Kimi) with a JSON payload on stdin. Every kind
|
|
6
|
-
* (`pre-tool-use`, `user-prompt-submit`, `briefing`, `crg
|
|
7
|
-
*
|
|
6
|
+
* (`pre-tool-use`, `user-prompt-submit`, `briefing`, `crg`) is dispatched
|
|
7
|
+
* from `src/main.ts` through one
|
|
8
8
|
* `HookHandler` shape, so a handler never sees `process`, argv, or stdin
|
|
9
9
|
* directly — only the `HookInvocation` it is called with, and it returns a
|
|
10
10
|
* `HookResult` for `main.ts` to write to stdout/stderr and turn into a
|
|
11
|
-
* process exit code.
|
|
12
|
-
* `HookHandler` at all — see `src/lean-ctx/mcp.ts`'s header.
|
|
11
|
+
* process exit code.
|
|
13
12
|
*
|
|
14
13
|
* This file is intentionally the *only* place that shape is defined: other
|
|
15
14
|
* agents implementing `src/hooks/user-prompt-submit/`, `src/hooks/briefing/`,
|
|
@@ -31,26 +30,27 @@ export interface ActivityNote {
|
|
|
31
30
|
/** `PASS`, `DENY <rule>`, `ERROR <what>`, `TIMEOUT <what>`, or `SKIP <why>`. */
|
|
32
31
|
readonly reason: string
|
|
33
32
|
readonly message?: string
|
|
34
|
-
/** What the hook invoked downstream, e.g. `
|
|
33
|
+
/** What the hook invoked downstream, e.g. `skills: tdd, research`. */
|
|
35
34
|
readonly downstream?: string
|
|
36
35
|
/** Set only for a blocked pre-tool-use decision: the rule id written to the deny log. */
|
|
37
36
|
readonly denyRuleId?: string
|
|
38
37
|
/**
|
|
39
38
|
* Set only when an identity decision was actually made for this
|
|
40
|
-
* invocation (a rewrite, or a deny/pass decided by one of the
|
|
41
|
-
*
|
|
42
|
-
* `adl.token-minting-role`, `tool.azure-devops
|
|
43
|
-
*
|
|
44
|
-
* resolution order (
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
39
|
+
* invocation (a rewrite, or a deny/pass decided by one of the identity
|
|
40
|
+
* rules — `adl.run-required-for-writes`, `adl.git-identity`,
|
|
41
|
+
* `adl.token-minting-role`, `tool.azure-devops`, … — or by a role gate on
|
|
42
|
+
* an Azure DevOps MCP call): where the effective agent identity came from,
|
|
43
|
+
* per the one-agent-identity resolution order — `inline` (a valid
|
|
44
|
+
* `ADL_AGENT_ID_AGENT=` on the command itself), `env` (the session
|
|
45
|
+
* environment), `default-file` (the machine default-agent file), or
|
|
46
|
+
* `none` (nothing resolved at all). An allowed Azure DevOps MCP call logs
|
|
47
|
+
* it too, reads included (Tarun, 2026-09-29). See
|
|
48
|
+
* `../pre-tool-use/handler.ts`'s `effectiveIdentityFor` and
|
|
49
|
+
* `fallbackIdentity`.
|
|
49
50
|
*/
|
|
50
51
|
readonly identitySource?: 'inline' | 'env' | 'default-file' | 'none'
|
|
51
52
|
/**
|
|
52
|
-
*
|
|
53
|
-
* identity this decision actually used — set together with
|
|
53
|
+
* The EFFECTIVE agent identity this decision actually used — set together with
|
|
54
54
|
* `identitySource`, whenever that is set to anything but `'none'`. Read
|
|
55
55
|
* by `./log.ts` for the `agent` column INSTEAD OF the session's raw
|
|
56
56
|
* `ADL_AGENT_ID_AGENT` env var — the two differ exactly when a command
|
|
@@ -63,7 +63,7 @@ export interface ActivityNote {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
export interface HookInvocation {
|
|
66
|
-
readonly kind: 'pre-tool-use' | 'user-prompt-submit' | 'briefing' | 'crg'
|
|
66
|
+
readonly kind: 'pre-tool-use' | 'user-prompt-submit' | 'briefing' | 'crg'
|
|
67
67
|
readonly host: HostId
|
|
68
68
|
readonly event?: string
|
|
69
69
|
readonly subcommand?: string
|
|
@@ -29,11 +29,25 @@
|
|
|
29
29
|
* pending marker exists clears it and runs once more. On its way out it
|
|
30
30
|
* releases the lock, then re-checks the marker once and re-acquires the
|
|
31
31
|
* lock (noclobber) if a hook queued in the meantime, closing the last gap.
|
|
32
|
+
*
|
|
33
|
+
* Self-heal: if `code-review-graph update --skip-flows` exits non-zero,
|
|
34
|
+
* the runner runs `code-review-graph build --skip-flows` once and logs a
|
|
35
|
+
* `SELF-HEAL:` marker to stderr (captured by the spawn into
|
|
36
|
+
* `crg-update.log`). The original error is already in the log because
|
|
37
|
+
* the spawn captures the update's own stderr; the marker is appended
|
|
38
|
+
* after, so the failure is never silently swallowed. The build runs at
|
|
39
|
+
* most once per runner invocation (a per-runner shell variable), so a
|
|
40
|
+
* runner that re-iterates because the pending marker was set does not
|
|
41
|
+
* re-trigger the build on the second iteration. If the build itself
|
|
42
|
+
* fails, the runner exits and the next edit tries again — persistent
|
|
43
|
+
* failures stay visible in the log instead of being hidden.
|
|
32
44
|
*/
|
|
33
45
|
|
|
34
46
|
import { closeSync, mkdirSync, openSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs'
|
|
35
47
|
import { join } from 'node:path'
|
|
36
48
|
|
|
49
|
+
import { ensureAdlGitignore } from '../../log/adl-dir.ts'
|
|
50
|
+
|
|
37
51
|
export const LOCK_REL = '.adl/crg-update.lock'
|
|
38
52
|
export const PENDING_REL = '.adl/crg-update.pending'
|
|
39
53
|
export const UPDATE_LOG_REL = '.adl/logs/crg-update.log'
|
|
@@ -43,9 +57,21 @@ export const MAX_LOCK_AGE_MS = 30 * 60 * 1000
|
|
|
43
57
|
|
|
44
58
|
export const RUNNER_SCRIPT = [
|
|
45
59
|
'lock="$1"; pending="$2"; shift 2',
|
|
60
|
+
'build_attempted=',
|
|
46
61
|
'while :; do',
|
|
47
62
|
' rm -f "$pending"',
|
|
48
63
|
' "$@"',
|
|
64
|
+
' rc=$?',
|
|
65
|
+
' if [ "$rc" -ne 0 ] && [ -z "$build_attempted" ]; then',
|
|
66
|
+
' echo "SELF-HEAL: $* exited $rc; running code-review-graph build --skip-flows" >&2',
|
|
67
|
+
' if code-review-graph build --skip-flows; then',
|
|
68
|
+
' echo "SELF-HEAL: build ok; next update will validate" >&2',
|
|
69
|
+
' else',
|
|
70
|
+
' build_rc=$?',
|
|
71
|
+
' echo "SELF-HEAL: build failed (exit $build_rc); self-heal aborted" >&2',
|
|
72
|
+
' fi',
|
|
73
|
+
' build_attempted=1',
|
|
74
|
+
' fi',
|
|
49
75
|
' if [ -e "$pending" ]; then continue; fi',
|
|
50
76
|
' rm -f "$lock"',
|
|
51
77
|
' if [ -e "$pending" ] && (set -C; echo $$ > "$lock") 2>/dev/null; then continue; fi',
|
|
@@ -160,6 +186,7 @@ function acquireAndStart(deps: BackgroundDeps, root: string, env: SpawnSpec['env
|
|
|
160
186
|
|
|
161
187
|
export function requestUpdate(deps: BackgroundDeps, root: string, env: SpawnSpec['env']): UpdateRequest {
|
|
162
188
|
mkdirSync(join(root, '.adl', 'logs'), { recursive: true, mode: 0o700 })
|
|
189
|
+
ensureAdlGitignore(join(root, '.adl'))
|
|
163
190
|
const lockPath = join(root, LOCK_REL)
|
|
164
191
|
const pendingPath = join(root, PENDING_REL)
|
|
165
192
|
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
|
|
48
48
|
import type { HookHandler, HookInvocation, HookResult } from '../contract.ts'
|
|
49
49
|
import { spawnWithTimeout } from '../../lib/spawn-with-timeout.ts'
|
|
50
|
-
import {
|
|
50
|
+
import { requestUpdate, type BackgroundDeps } from './background.ts'
|
|
51
51
|
import { toDecideInput } from '../../pre-tool-use/handler.ts'
|
|
52
52
|
import { invocations } from '../../rules/shell/invocation.ts'
|
|
53
53
|
|
|
@@ -155,7 +155,8 @@ function isGitCommitInvocation(payload: Record<string, unknown>): boolean {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
/**
|
|
158
|
-
* `pre-commit.sh`: silent `detect-changes --brief`,
|
|
158
|
+
* `pre-commit.sh`: silent `detect-changes --brief`, with Codex receiving its
|
|
159
|
+
* native allow envelope rather than the legacy `{"passed":true}` payload,
|
|
159
160
|
* always exit 0 — but ONLY when the invoking payload's shell command is
|
|
160
161
|
* actually a `git commit` (see this file's header, work item B). Anything
|
|
161
162
|
* else — no shell command at all (a non-Bash tool call), or a shell command
|
|
@@ -168,7 +169,10 @@ async function preCommit(run: Runner, inv: HookInvocation): Promise<HookResult>
|
|
|
168
169
|
return { stdout: '', stderr: '', exitCode: 0 }
|
|
169
170
|
}
|
|
170
171
|
const result = await runCrg(run, inv, ['detect-changes', '--brief'])
|
|
171
|
-
|
|
172
|
+
const stdout = inv.host === 'codex'
|
|
173
|
+
? `${JSON.stringify({ hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'allow' } })}\n`
|
|
174
|
+
: '{"passed":true}\n'
|
|
175
|
+
return { stdout, stderr: missingBinaryNote('pre-commit', result), exitCode: 0 }
|
|
172
176
|
}
|
|
173
177
|
|
|
174
178
|
/**
|
|
@@ -235,6 +239,3 @@ export const bunRunner: Runner = async (cmd, args, opts) => {
|
|
|
235
239
|
return { status: null, stdout: '', stderr: message }
|
|
236
240
|
}
|
|
237
241
|
}
|
|
238
|
-
|
|
239
|
-
export const handleCrg: HookHandler = createCrgHandler({ run: bunRunner, background: defaultBackgroundDeps })
|
|
240
|
-
export default handleCrg
|
|
@@ -40,8 +40,7 @@
|
|
|
40
40
|
* `result` is never left empty just because a row has nothing to say.
|
|
41
41
|
* - `rule` is set only for a blocked pre-tool-use decision
|
|
42
42
|
* (`ActivityNote.denyRuleId`), same trigger as the old deny log.
|
|
43
|
-
* - `agent` is `ActivityNote.identityAgent`
|
|
44
|
-
* STATUS.md 12p) — the EFFECTIVE identity the
|
|
43
|
+
* - `agent` is `ActivityNote.identityAgent` — the EFFECTIVE identity the
|
|
45
44
|
* decision actually used, set by `../pre-tool-use/handler.ts`'s
|
|
46
45
|
* `effectiveIdentityFor` — when an identity decision was made; a valid
|
|
47
46
|
* inline `ADL_AGENT_ID_AGENT=` override on the command differs from the
|
|
@@ -50,12 +49,12 @@
|
|
|
50
49
|
* `ADL_AGENT_ID_AGENT` (`../rules/impl/adl-identity.ts`'s env var) for
|
|
51
50
|
* any row with no identity decision at all. `human` has no source at
|
|
52
51
|
* this layer and is left absent.
|
|
53
|
-
* - `identity_source`
|
|
52
|
+
* - `identity_source` comes straight off
|
|
54
53
|
* `ActivityNote.identitySource` (`./contract.ts`), set by
|
|
55
54
|
* `../pre-tool-use/handler.ts`'s `decideAndRespond` only when an
|
|
56
55
|
* identity decision was actually made for this invocation — absent
|
|
57
|
-
* otherwise, never defaulted to `'none'` for an unrelated row.
|
|
58
|
-
*
|
|
56
|
+
* otherwise, never defaulted to `'none'` for an unrelated row. It is set
|
|
57
|
+
* for the "override's PASS" row too: an
|
|
59
58
|
* identity-bearing command whose only identity-bearing pieces already
|
|
60
59
|
* carry a valid inline override needs no rewrite (`rewriteGitNetworkCommands`'s
|
|
61
60
|
* `unchanged` outcome), but it still made a real identity decision.
|
|
@@ -79,9 +78,9 @@ import type { ActivityNote, HookHandler, HookInvocation, HookResult } from './co
|
|
|
79
78
|
|
|
80
79
|
export const HOOKS_LOG_REL = '.adl/logs/hooks.log'
|
|
81
80
|
export const HOOKS_DENY_LOG_REL = '.adl/logs/hooks-deny.log'
|
|
82
|
-
|
|
81
|
+
const MAX_LOGGED_COMMAND_LENGTH = 2000
|
|
83
82
|
|
|
84
|
-
|
|
83
|
+
function truncateCommand(value: string): string {
|
|
85
84
|
return value.length > MAX_LOGGED_COMMAND_LENGTH ? `${value.slice(0, MAX_LOGGED_COMMAND_LENGTH)}...<truncated>` : value
|
|
86
85
|
}
|
|
87
86
|
|
|
@@ -108,7 +107,7 @@ const stringAt = (record: Readonly<Record<string, unknown>>, key: string): strin
|
|
|
108
107
|
* `{"command": "...", "cwd": "...", "sandbox": false}` (no `tool_input` at
|
|
109
108
|
* all). No Cursor-specific field renaming was needed here.
|
|
110
109
|
*/
|
|
111
|
-
|
|
110
|
+
function toolSummary(payload: Readonly<Record<string, unknown>>): string {
|
|
112
111
|
const rawInput = payload.tool_input
|
|
113
112
|
const input = typeof rawInput === 'object' && rawInput !== null && !Array.isArray(rawInput) ? (rawInput as Record<string, unknown>) : {}
|
|
114
113
|
for (const key of ['command', 'cmd', 'script']) {
|
|
@@ -172,8 +171,7 @@ export async function runLogged(inv: HookInvocation, handler: HookHandler, now:
|
|
|
172
171
|
const duration = Math.round(performance.now() - started)
|
|
173
172
|
const sessionId = sessionOf(inv.payload)
|
|
174
173
|
const runId = runIdOf(inv.env)
|
|
175
|
-
//
|
|
176
|
-
// this decision used — set on `outcome` whenever an identity decision
|
|
174
|
+
// The EFFECTIVE identity this decision used — set on `outcome` whenever an identity decision
|
|
177
175
|
// was actually made (`../pre-tool-use/handler.ts`'s `effectiveIdentityFor`)
|
|
178
176
|
// — wins over the session's raw `ADL_AGENT_ID_AGENT` env var: they
|
|
179
177
|
// differ exactly when the command carries a valid inline override
|
|
@@ -51,7 +51,7 @@ function processTerm(term: string): string | null {
|
|
|
51
51
|
* so it is rebuilt per invocation rather than persisted — that keeps the hook
|
|
52
52
|
* stateless and makes an edited SKILL.md take effect immediately.
|
|
53
53
|
*/
|
|
54
|
-
|
|
54
|
+
function buildIndex(skills: readonly Skill[]): MiniSearch {
|
|
55
55
|
const index = new MiniSearch({
|
|
56
56
|
fields: ['name', 'keywords', 'description'],
|
|
57
57
|
storeFields: ['label', 'description'],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Minimal Unigram tokenizer over the pruned tokenizer.json of the
|
|
3
|
-
*
|
|
3
|
+
* enact-embedding artifact. Pure TS — no dependency on a native tokenizer
|
|
4
4
|
* package.
|
|
5
5
|
*
|
|
6
6
|
* Ported unchanged from enact-repo-controls-m5's
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
* the artifact from a repo-local `.cache/enact-embedding/model/` directory
|
|
11
11
|
* built by that repo's own installer. This hook instead treats the model as a
|
|
12
12
|
* GLOBAL, machine-wide asset shared by every repository —
|
|
13
|
-
* `resolveGlobalArtifactDir` resolves `${XDG_CACHE_HOME:-$HOME/.cache}/
|
|
14
|
-
* (
|
|
15
|
-
*
|
|
16
|
-
* own `env`, never
|
|
13
|
+
* `resolveGlobalArtifactDir` resolves `${XDG_CACHE_HOME:-$HOME/.cache}/enact-embedding/model/`
|
|
14
|
+
* (matching `packages/fleet/src/install-embedding-model.ts`, the installer that
|
|
15
|
+
* actually writes this directory; the earlier `adl-embedding` name is a hard
|
|
16
|
+
* cut, never read as a fallback) from the invocation's own `env`, never
|
|
17
|
+
* `process.env` and never repo-relative.
|
|
17
18
|
*
|
|
18
19
|
* `loadVectorHalf`'s `LoadVectorResult.reason` (on `ok: false`) already
|
|
19
20
|
* carries a specific, human-readable cause (directory missing, which files
|
|
@@ -37,7 +38,7 @@ const ARTIFACT_FILES = ['model.bin', 'tokenizer.json', 'tokenizer_config.json',
|
|
|
37
38
|
export function resolveGlobalArtifactDir(env: Readonly<Record<string, string | undefined>>): string {
|
|
38
39
|
const xdgCacheHome = env.XDG_CACHE_HOME
|
|
39
40
|
const base = xdgCacheHome && xdgCacheHome.trim() !== '' ? xdgCacheHome : join(requireHome(env), '.cache')
|
|
40
|
-
return join(base, '
|
|
41
|
+
return join(base, 'enact-embedding', 'model')
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
function requireHome(env: Readonly<Record<string, string | undefined>>): string {
|
|
@@ -15,7 +15,7 @@ import { cursorSpec } from './impl/cursor.ts'
|
|
|
15
15
|
import { opencodeSpec } from './impl/opencode.ts'
|
|
16
16
|
import { kimiSpec } from './impl/kimi.ts'
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
const HOST_SPECS: Readonly<Record<HostId, HostSpec>> = {
|
|
19
19
|
claude: claudeSpec,
|
|
20
20
|
codex: codexSpec,
|
|
21
21
|
cursor: cursorSpec,
|