@amsterdamdatalabs/adl-agent-control-linux-x64 0.1.12 → 0.1.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/adl +2 -2
- package/bin/git +16 -17
- package/bin/git-ado +25 -24
- package/bin/git-defaults +173 -0
- package/bin/health-check +8 -1
- package/bin/kimi-hooks +1 -1
- package/bin/lib/adl-package.sh +257 -0
- package/bin/lib/fleet-host.sh +8 -5
- package/bin/reconcile +482 -232
- package/bin/reconcile-host +30 -20
- package/bin/setup +20 -17
- package/bin/shell-path-policy +15 -5
- package/bin/sync-and-reconcile +62 -64
- package/bin/validate-manifest +33 -9
- package/package.json +2 -10
- package/packages/agent-hooks/README.md +14 -9
- package/packages/agent-hooks/assets/hooks.json +0 -20
- package/packages/agent-hooks/src/cli/args.ts +1 -1
- package/packages/agent-hooks/src/cli/doctor.ts +6 -58
- package/packages/agent-hooks/src/deploy/deploy.ts +12 -41
- package/packages/agent-hooks/src/deploy/doctor.ts +8 -11
- package/packages/agent-hooks/src/deploy/index.ts +14 -14
- package/packages/agent-hooks/src/deploy/json-merge.ts +7 -8
- package/packages/agent-hooks/src/deploy/legacy-lock.ts +2 -2
- package/packages/agent-hooks/src/deploy/list.ts +1 -1
- package/packages/agent-hooks/src/deploy/lock.ts +31 -12
- package/packages/agent-hooks/src/deploy/profile.ts +3 -4
- package/packages/agent-hooks/src/deploy/source.ts +1 -1
- package/packages/agent-hooks/src/gating/config.ts +12 -24
- package/packages/agent-hooks/src/gating/root.ts +3 -3
- package/packages/agent-hooks/src/hooks/briefing/handler.ts +2 -2
- package/packages/agent-hooks/src/hooks/briefing/index.ts +27 -287
- package/packages/agent-hooks/src/hooks/contract.ts +17 -17
- package/packages/agent-hooks/src/hooks/crg/background.ts +27 -0
- package/packages/agent-hooks/src/hooks/crg/index.ts +7 -6
- package/packages/agent-hooks/src/hooks/log.ts +8 -10
- package/packages/agent-hooks/src/hooks/user-prompt-submit/match.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/tokenizer.ts +1 -1
- package/packages/agent-hooks/src/hooks/user-prompt-submit/vector.ts +6 -5
- package/packages/agent-hooks/src/hosts/registry.ts +1 -1
- package/packages/agent-hooks/src/log/adl-dir.ts +44 -0
- package/packages/agent-hooks/src/log/writer.ts +16 -2
- package/packages/agent-hooks/src/main.ts +7 -41
- package/packages/agent-hooks/src/pre-tool-use/handler.ts +71 -82
- package/packages/agent-hooks/src/rules/engine.ts +13 -17
- package/packages/agent-hooks/src/rules/impl/adl-build-run-denied.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/adl-git-credential-bypass.ts +12 -14
- package/packages/agent-hooks/src/rules/impl/adl-git-identity.ts +28 -28
- package/packages/agent-hooks/src/rules/impl/adl-git-push-policy.ts +8 -9
- package/packages/agent-hooks/src/rules/impl/adl-human-azdo-bypass.ts +56 -59
- package/packages/agent-hooks/src/rules/impl/adl-identity.ts +16 -23
- package/packages/agent-hooks/src/rules/impl/adl-mcp-cli.ts +19 -16
- package/packages/agent-hooks/src/rules/impl/adl-pr-complete-pending.ts +2 -2
- package/packages/agent-hooks/src/rules/impl/adl-pr-review-role.ts +9 -12
- package/packages/agent-hooks/src/rules/impl/adl-pr-role.ts +5 -7
- package/packages/agent-hooks/src/rules/impl/adl-run-required.ts +411 -0
- package/packages/agent-hooks/src/rules/impl/adl-token-minting-role.ts +4 -5
- package/packages/agent-hooks/src/rules/impl/adl-workitem-role.ts +6 -7
- package/packages/agent-hooks/src/rules/impl/agent-tamper-protection.ts +77 -70
- package/packages/agent-hooks/src/rules/impl/deny-allowlist.ts +131 -0
- package/packages/agent-hooks/src/rules/impl/git-helpers.ts +21 -23
- package/packages/agent-hooks/src/rules/impl/git-worktree.ts +14 -28
- package/packages/agent-hooks/src/rules/impl/mcp-tool.ts +3 -3
- package/packages/agent-hooks/src/rules/impl/messages.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/pr-completion.ts +1 -1
- package/packages/agent-hooks/src/rules/impl/tool-azure-devops.ts +35 -46
- package/packages/agent-hooks/src/rules/impl/tool-find.ts +34 -7
- package/packages/agent-hooks/src/rules/impl/tool-grep.ts +33 -12
- package/packages/agent-hooks/src/rules/impl/tool-native-search.ts +52 -9
- package/packages/agent-hooks/src/rules/ports.ts +5 -7
- package/packages/agent-hooks/src/rules/registry.ts +4 -6
- package/packages/agent-hooks/src/rules/shell/git-identity.ts +86 -101
- package/packages/agent-hooks/src/rules/shell/git-internals.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/invocation.ts +24 -118
- package/packages/agent-hooks/src/rules/shell/piped-script.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/prefixes.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/protected-carrier-writes.ts +11 -10
- package/packages/agent-hooks/src/rules/shell/protected-carriers.ts +26 -26
- package/packages/agent-hooks/src/rules/shell/substitution.ts +1 -1
- package/packages/agent-hooks/src/rules/shell/xargs.ts +2 -2
- package/packages/agent-hooks/src/rules/spec.ts +2 -2
- package/packages/agent-settings/README.md +287 -0
- package/packages/agent-settings/assets/GLOBAL-AGENTS.md +14 -16
- package/packages/agent-settings/assets/agents/architect.toml +2 -0
- package/packages/agent-settings/assets/agents/code-reviewer.toml +2 -0
- package/packages/agent-settings/assets/agents/executor.toml +2 -0
- package/packages/agent-settings/assets/agents/explore.toml +2 -0
- package/packages/agent-settings/assets/agents/planner.toml +2 -0
- package/packages/agent-settings/assets/mcp.json +0 -4
- package/packages/agent-settings/deploy-profile.json +139 -0
- package/packages/agent-settings/deploy-profile.schema.json +147 -0
- package/packages/agent-settings/managed/README.md +29 -30
- package/packages/agent-settings/managed/codex-requirements.toml +9 -9
- package/packages/agent-settings/package.json +20 -0
- package/packages/agent-settings/src/deploy/agent-render.ts +2 -2
- package/packages/agent-settings/src/deploy/agent-toml.ts +1 -1
- package/packages/agent-settings/src/deploy/agents-deploy.ts +17 -3
- package/packages/agent-settings/src/deploy/doctor.ts +3 -83
- package/packages/agent-settings/src/deploy/index.ts +6 -33
- package/packages/agent-settings/src/deploy/legacy-lock.ts +6 -6
- package/packages/agent-settings/src/deploy/list.ts +5 -19
- package/packages/agent-settings/src/deploy/lock.ts +8 -18
- package/packages/agent-settings/src/deploy/mcp-deploy.ts +10 -5
- package/packages/agent-settings/src/deploy/mcp-merge.ts +22 -3
- package/packages/agent-settings/src/deploy/mcp-source.ts +1 -1
- package/packages/agent-settings/src/deploy/profile.ts +11 -35
- package/packages/agent-settings/src/deploy/retire-lean-ctx.ts +184 -0
- package/packages/agent-settings/src/deploy/settings.ts +17 -22
- package/packages/agent-settings/src/global-surface-sweep.ts +0 -2
- package/packages/agent-settings/src/kimi-hooks.ts +339 -192
- package/packages/agent-settings/src/opencode-hooks.ts +1 -1
- package/packages/agent-settings/tsconfig.json +23 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/SKILL.md +120 -0
- package/packages/agent-skills/assets/agent-search-tool-audit/scripts/audit.sh +276 -0
- package/packages/agent-skills/assets/debug-issue/SKILL.md +8 -7
- package/packages/agent-skills/assets/explore-codebase/SKILL.md +13 -13
- package/packages/agent-skills/assets/refactor-safely/SKILL.md +12 -11
- package/packages/agent-skills/assets/review-changes/SKILL.md +7 -7
- package/packages/agent-skills/assets/testing/references/e2e.md +37 -0
- package/packages/agent-skills/assets/testing/references/integration.md +37 -0
- package/packages/agent-skills/assets/testing/references/unit.md +32 -0
- package/packages/agent-skills/dist/deploy.d.ts +2 -0
- package/packages/agent-skills/dist/deploy.d.ts.map +1 -1
- package/packages/agent-skills/dist/deploy.js +27 -1
- package/packages/agent-skills/dist/deploy.js.map +1 -1
- package/packages/agent-skills/dist/doctor.d.ts +0 -2
- package/packages/agent-skills/dist/doctor.d.ts.map +1 -1
- package/packages/agent-skills/dist/doctor.js +1 -1
- package/packages/agent-skills/dist/doctor.js.map +1 -1
- package/packages/agent-skills/dist/fs-utils.d.ts +0 -1
- package/packages/agent-skills/dist/fs-utils.d.ts.map +1 -1
- package/packages/agent-skills/dist/fs-utils.js +1 -1
- package/packages/agent-skills/dist/fs-utils.js.map +1 -1
- package/packages/agent-skills/src/deploy.ts +29 -1
- package/packages/agent-skills/src/doctor.ts +1 -1
- package/packages/agent-skills/src/fs-utils.ts +1 -1
- package/packages/azdo/README.md +10 -9
- package/packages/azdo/package.json +1 -3
- package/packages/azdo/scripts/probe-ado-rules.ts +311 -0
- package/packages/azdo/src/azdo-pl.ts +2 -54
- package/packages/azdo/src/azdo-pr-review.ts +4 -4
- package/packages/azdo/src/azdo-repo-doctor.ts +101 -52
- package/packages/azdo/src/azdo-wit.ts +44 -2
- package/packages/azdo/src/lib/agent-identity.ts +12 -14
- package/packages/azdo/src/lib/agent-token.ts +2 -2
- package/packages/azdo/src/lib/client.ts +0 -5
- package/packages/azdo/src/lib/graph-identity.ts +4 -4
- package/packages/azdo/src/workflow-ladder.csv +241 -0
- package/packages/azdo/src/workflow-rules-matrix.csv +85 -0
- package/packages/azdo/src/workflow-rules.ts +194 -0
- package/packages/fleet/manifest.json +35 -11
- package/packages/fleet/manifest.schema.json +62 -10
- package/packages/fleet/src/default-agent-file.ts +3 -3
- package/packages/fleet/src/install-adl-package.ts +73 -15
- package/packages/fleet/src/install-embedding-model.ts +13 -13
- package/packages/fleet/src/managed-settings.ts +7 -7
- package/packages/fleet/src/repo-maintain.ts +91 -55
- package/packages/fleet/src/scratch-reap.ts +5 -5
- package/packages/fleet/src/vscode-settings.ts +5 -5
- package/packages/repo-controls/README.md +141 -43
- package/packages/repo-controls/assets/promote.ts +4 -4
- package/packages/repo-controls/assets/reconcile-guard.sh +10 -46
- package/packages/repo-controls/assets/version-bump.sh +31 -84
- package/packages/repo-controls/bunfig.toml +6 -7
- package/packages/repo-controls/package/adl-compliance/AGENTS.md +5 -6
- package/packages/repo-controls/package/adl-compliance/conftest.py +3 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/__init__.py +4 -16
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/adr_lifecycle/test_check.py +9 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/fixtures/docs/notes.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/closed_set/test_check.py +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/check.py +266 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.drafts/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/.hidden.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/data.csv +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/diagram.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/mock.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs/guide/sub/nested.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/docs.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p1.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p2.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p3.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p4.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-assets/plans/deep/p5.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/build.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/architecture/overview.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/install.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/docs/guide/start.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-clean/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-001-tenancy.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-002-carrier.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/adr-003-cli.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-old.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/decisions/archive/adr-000-older.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-decisions/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-01.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-02.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-03.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-04.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-05.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-06.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-07.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-08.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-09.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-10.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-11.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-12.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-13.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-14.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-15.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/docs/guide/page-16.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-default-cap/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-exempt/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-grew/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/docs/guide/e.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-no-section/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/docs/short/only.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-over-cap/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/held/d.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/docs/shrunk/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-stale/grants.yaml +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/a.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/b.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/docs/guide/c.md +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/fixtures/docs-size-unusable/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/directory_size/test_check.py +345 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/check.py +18 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/english_only/test_check.py +35 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/__init__.py +7 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/check.py +91 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/CLAUDE.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/-leading-hyphen.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/AGENTS.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/double--hyphen.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/getting started.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/nested/page-here.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/trailing-hyphen-.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/ui-contract.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/architecture/user_profile.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/UI-CONTRACT.png +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/assets/diagram.png +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/index.md +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/notes.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/reference.html +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/2026-10-experiment.md +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs/research/UI-CONTRACT.md +6 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/fixtures/docs.md +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/filename/test_check.py +194 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/check.py +14 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/docs-knowledge-indexes.yaml +5 -5
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-legacy/docs/compliance/index.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/fixtures/knowledge-indexes-shipped-register-type/docs/compliance/index.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/indexes/test_check.py +58 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/ledger/test_check.py +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/check.py +64 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/docs-okf-profiles.yaml +60 -9
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-clean/docs/notes.md +17 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-ledger-no-lines/docs/notes.md +13 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs/architecture/demo.md +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-clean/docs-okf-profiles.yaml +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/no-type.md +9 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-experiment.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs/research/typed-research.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-untyped/docs-okf-profiles.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs/architecture/bad-status.md +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-profile-violation/docs-okf-profiles.yaml +0 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/experiment-ok.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-key.md +15 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/extra-keys.md +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-created.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-description.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-last-update.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-sources.md +10 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-status.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/missing-title.md +11 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/optional-keys.md +16 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research/docs/research/research-ok.md +14 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/created-date.md +21 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/architecture/research-shaped.md +19 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/fixtures/okf-research-neighbours/docs/operations/runbook.md +26 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/okf_profile/test_check.py +228 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/register.py +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/docs/semantics/test_check.py +11 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/__init__.py +5 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/check.py +160 -44
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-clean/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/a.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/frontend/packages/desktop/src/b.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-empty-register/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-excluded/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-missing-tree/grants.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/a.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/b.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/frontend/packages/desktop/src/c.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-no-ceilings/grants.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-stale-entry/grants.yaml +5 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unbaselined/grants.yaml +0 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/frontend/packages/desktop/src/renderer/solo/item.ts +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/fixtures/directory-ratchet-unusable-register/grants.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/register.py +127 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/directory_ratchet/test_check.py +265 -29
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/check.py +75 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/markdown_trees/test_check.py +194 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/check.py +56 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/open_work_cap/test_check.py +258 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/check.py +40 -12
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/placement/test_check.py +108 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plan_metadata.py +9 -4
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/check.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/fixtures/plans-layout-clean/plans/features/az347-test-coverage/items/az351-restore-entrypoint.md +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/plans_layout/test_check.py +3 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/references/check.py +2 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/check.py +23 -6
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_closed_set/test_check.py +76 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/check.py +58 -17
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/root_markdown_allowlist/test_check.py +161 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/check.py +35 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/layout/scripts_size_depth/test_check.py +108 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/check.py +281 -61
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/absolute-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/backslash-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/baseline-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/boolean-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/dot-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/duplicate-path.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-file.yaml +0 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/empty-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/float-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/negative-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-over-limit-baseline.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/no-schema-version.yaml +1 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/non-string-path.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/not-yaml.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/null-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/parent-segment.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/string-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/top-level-is-a-list.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/trailing-slash.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/unknown-key.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/wrong-schema-version.yaml +2 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/malformed/zero-size.yaml +3 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/fixtures/valid.yaml +4 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/lfs/integrity/test_check.py +758 -45
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/check.py +4 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/ignored_paths/test_check.py +2 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/cargo_lock.py +490 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/check.py +368 -55
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_check.py +4 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_declared_paths.py +523 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/checks/repository/lockfile_integrity/test_stale_lock.py +1179 -0
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/cli.py +122 -3
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/check.py +33 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/constants.py +0 -11
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/core/context.py +16 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/config.py +1 -2
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/docs_shape.py +12 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.alt.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/gate-registry.yaml +133 -147
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/registry.py +1 -1
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/policy/root_shape.py +52 -10
- package/packages/repo-controls/package/adl-compliance/src/adl_compliance/runner.py +23 -4
- package/packages/repo-controls/package.json +2 -9
- package/packages/repo-controls/scripts/hooks/post-merge +13 -0
- package/packages/repo-controls/scripts/hooks/pre-push +3 -3
- package/packages/repo-controls/src/azdo-push.ts +64 -36
- package/packages/repo-controls/src/azure-devops-governance.ts +7 -9
- package/packages/repo-controls/src/azure-devops-remote.ts +1 -1
- package/packages/repo-controls/src/cli.ts +29 -8
- package/packages/repo-controls/src/compliance-config.ts +410 -2
- package/packages/repo-controls/src/config.ts +133 -60
- package/packages/repo-controls/src/constants.ts +13 -27
- package/packages/repo-controls/src/coverage-ratchet.ts +4 -4
- package/packages/repo-controls/src/doctor.ts +46 -19
- package/packages/repo-controls/src/gitignore-block.ts +5 -29
- package/packages/repo-controls/src/hook-log.ts +1 -2
- package/packages/repo-controls/src/hook.ts +201 -45
- package/packages/repo-controls/src/install.ts +14 -8
- package/packages/repo-controls/src/integrity.ts +3 -3
- package/packages/repo-controls/src/lfs.ts +111 -0
- package/packages/repo-controls/src/promote.ts +8 -8
- package/packages/repo-controls/src/runtime.ts +9 -1
- package/packages/repo-controls/src/workflows-drift.ts +4 -5
- package/packages/repo-controls/src/worktree-guard.ts +3 -3
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
* file may contain provider API keys, so this script never prints file
|
|
31
31
|
* content — only marker state, paths, and validation results.
|
|
32
32
|
*
|
|
33
|
-
*
|
|
33
|
+
* Local-repo-first rule (Tarun, 2026-09-29, "adl is LOCAL REPO FIRST …
|
|
34
34
|
* the repos where adl-config.toml does not exist has no business of running
|
|
35
35
|
* hooks"): this carrier STAYS global, as the one exception, because Kimi has
|
|
36
36
|
* no per-repo hook configuration to deploy into — confirmed from Kimi's own
|
|
37
37
|
* docs, <https://moonshotai.github.io/kimi-code/en/customization/hooks.html>
|
|
38
38
|
* (fetched 2026-09-29): "All hook rules are written in the `[[hooks]]` array
|
|
39
39
|
* in `~/.kimi-code/config.toml`", no project-local alternative documented.
|
|
40
|
-
*
|
|
40
|
+
* The per-repo-only requirement covers Kimi too, and is built —
|
|
41
41
|
* not here, since the TOML `command` string this file writes is a fixed
|
|
42
42
|
* shell command with no access to the hook payload's JSON `cwd`, but inside
|
|
43
43
|
* `adl hook` itself, which resolves the invoking repository root from the
|
|
@@ -48,13 +48,21 @@
|
|
|
48
48
|
* So this global carrier is safe: a Kimi session outside a managed repo
|
|
49
49
|
* still invokes `adl hook`, which no-ops before any rule runs.
|
|
50
50
|
*/
|
|
51
|
-
import { spawnSync } from
|
|
52
|
-
import { createHash } from
|
|
53
|
-
import {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
import { spawnSync } from "node:child_process";
|
|
52
|
+
import { createHash } from "node:crypto";
|
|
53
|
+
import {
|
|
54
|
+
copyFileSync,
|
|
55
|
+
existsSync,
|
|
56
|
+
mkdirSync,
|
|
57
|
+
readFileSync,
|
|
58
|
+
renameSync,
|
|
59
|
+
rmSync,
|
|
60
|
+
writeFileSync,
|
|
61
|
+
} from "node:fs";
|
|
62
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
63
|
+
|
|
64
|
+
export const BEGIN = "# BEGIN ADL KIMI HOOKS";
|
|
65
|
+
export const END = "# END ADL KIMI HOOKS";
|
|
58
66
|
|
|
59
67
|
/**
|
|
60
68
|
* Legacy markers used before the Enact -> adl rename. A real Kimi install
|
|
@@ -66,10 +74,30 @@ export const END = '# END ADL KIMI HOOKS'
|
|
|
66
74
|
* replaced IN PLACE with the current-marker block on a plain apply/uninstall
|
|
67
75
|
* — never left orphaned alongside a freshly-inserted second block.
|
|
68
76
|
*/
|
|
69
|
-
const LEGACY_BEGIN =
|
|
70
|
-
const LEGACY_END =
|
|
77
|
+
const LEGACY_BEGIN = "# BEGIN ENACT KIMI HOOKS";
|
|
78
|
+
const LEGACY_END = "# END ENACT KIMI HOOKS";
|
|
79
|
+
|
|
80
|
+
const HOOK_BIN = "adl hook";
|
|
81
|
+
|
|
82
|
+
interface DoctorCommandResult {
|
|
83
|
+
readonly status: number | null;
|
|
84
|
+
readonly stdout: string;
|
|
85
|
+
readonly stderr: string;
|
|
86
|
+
}
|
|
71
87
|
|
|
72
|
-
|
|
88
|
+
export type DoctorCommandRunner = (
|
|
89
|
+
command: string,
|
|
90
|
+
args: readonly string[],
|
|
91
|
+
) => DoctorCommandResult;
|
|
92
|
+
|
|
93
|
+
const runDoctorCommand: DoctorCommandRunner = (command, args) => {
|
|
94
|
+
const result = spawnSync(command, [...args], { encoding: "utf8" });
|
|
95
|
+
return {
|
|
96
|
+
status: result.status,
|
|
97
|
+
stdout: result.stdout,
|
|
98
|
+
stderr: result.stderr,
|
|
99
|
+
};
|
|
100
|
+
};
|
|
73
101
|
|
|
74
102
|
/**
|
|
75
103
|
* Broad file-write tool matcher shared with every other host's CRG
|
|
@@ -80,13 +108,13 @@ const HOOK_BIN = 'adl hook'
|
|
|
80
108
|
* simply never matches.
|
|
81
109
|
*/
|
|
82
110
|
const CRG_WRITE_MATCHER =
|
|
83
|
-
|
|
111
|
+
"Write|Edit|MultiEdit|StrReplace|str_replace_editor|edit_file|str_replace|replace_in_file|create_file|write_file";
|
|
84
112
|
|
|
85
113
|
export interface HookEntry {
|
|
86
|
-
readonly event: string
|
|
87
|
-
readonly matcher?: string
|
|
88
|
-
readonly command: string
|
|
89
|
-
readonly timeout: number
|
|
114
|
+
readonly event: string;
|
|
115
|
+
readonly matcher?: string;
|
|
116
|
+
readonly command: string;
|
|
117
|
+
readonly timeout: number;
|
|
90
118
|
}
|
|
91
119
|
|
|
92
120
|
/**
|
|
@@ -96,17 +124,15 @@ export interface HookEntry {
|
|
|
96
124
|
* read-only reference — see the "why hardcode, not derive" note below):
|
|
97
125
|
* - PreToolUse (no matcher -> every tool) -> pre-tool-use gate
|
|
98
126
|
* - PreToolUse (matcher "Bash") -> CRG pre-commit
|
|
99
|
-
* - PreToolUse (no matcher -> every tool) -> lean-ctx pre-tool-use
|
|
100
127
|
* - UserPromptSubmit (no matcher -> every prompt) -> skill-match suggestions
|
|
101
128
|
* - SessionStart (no matcher -> both "startup" and "resume") -> briefing
|
|
102
129
|
* - PostToolUse on file-write tools -> CRG after-file-edit
|
|
103
|
-
* - PostToolUse (no matcher -> every tool) -> lean-ctx post-tool-use
|
|
104
130
|
* - SessionEnd (no matcher -> both "exit" and "archive"; the session-close
|
|
105
131
|
* event, not the per-turn "Stop" event) -> CRG session-stop, matching
|
|
106
132
|
* every other host's own sessionEnd/SessionEnd wiring for this hook.
|
|
107
133
|
*
|
|
108
134
|
* Order within PreToolUse mirrors the canonical file exactly: catch-all guard
|
|
109
|
-
* -> Bash-matched crg pre-commit
|
|
135
|
+
* -> Bash-matched crg pre-commit. The guard must see
|
|
110
136
|
* every tool before host-specific narrower checks run.
|
|
111
137
|
*
|
|
112
138
|
* Why this is hardcoded rather than derived from the canonical hooks list at
|
|
@@ -124,32 +150,60 @@ export interface HookEntry {
|
|
|
124
150
|
* pinned copy, so a deployer change requires an explicit behavior review.
|
|
125
151
|
*/
|
|
126
152
|
export const MANAGED_HOOKS: readonly HookEntry[] = [
|
|
127
|
-
{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
{
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
153
|
+
{
|
|
154
|
+
event: "PreToolUse",
|
|
155
|
+
command: `${HOOK_BIN} pre-tool-use --host=kimi`,
|
|
156
|
+
timeout: 30,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
event: "PreToolUse",
|
|
160
|
+
matcher: "Bash",
|
|
161
|
+
command: `${HOOK_BIN} crg pre-commit --host=kimi`,
|
|
162
|
+
timeout: 30,
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
event: "UserPromptSubmit",
|
|
166
|
+
command: `${HOOK_BIN} user-prompt-submit --host=kimi`,
|
|
167
|
+
timeout: 30,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
event: "SessionStart",
|
|
171
|
+
command: `${HOOK_BIN} briefing --host=kimi`,
|
|
172
|
+
timeout: 15,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
event: "PostToolUse",
|
|
176
|
+
matcher: CRG_WRITE_MATCHER,
|
|
177
|
+
command: `${HOOK_BIN} crg after-file-edit --host=kimi`,
|
|
178
|
+
timeout: 30,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
event: "SessionEnd",
|
|
182
|
+
command: `${HOOK_BIN} crg session-stop --host=kimi`,
|
|
183
|
+
timeout: 30,
|
|
184
|
+
},
|
|
185
|
+
];
|
|
136
186
|
|
|
137
187
|
function tomlEntry(entry: HookEntry): string {
|
|
138
|
-
const lines = [
|
|
139
|
-
if (entry.matcher !== undefined)
|
|
140
|
-
|
|
141
|
-
|
|
188
|
+
const lines = ["[[hooks]]", `event = ${JSON.stringify(entry.event)}`];
|
|
189
|
+
if (entry.matcher !== undefined)
|
|
190
|
+
lines.push(`matcher = ${JSON.stringify(entry.matcher)}`);
|
|
191
|
+
lines.push(
|
|
192
|
+
`command = ${JSON.stringify(entry.command)}`,
|
|
193
|
+
`timeout = ${entry.timeout}`,
|
|
194
|
+
);
|
|
195
|
+
return lines.join("\n");
|
|
142
196
|
}
|
|
143
197
|
|
|
144
198
|
export function managedBlock(): string {
|
|
145
199
|
const header = [
|
|
146
200
|
BEGIN,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
]
|
|
151
|
-
const body = MANAGED_HOOKS.map(tomlEntry).join(
|
|
152
|
-
return [...header, body, END].join(
|
|
201
|
+
"# Deployed by packages/agent-settings/src/kimi-hooks.ts (bin/kimi-hooks).",
|
|
202
|
+
"# Everything between the markers is regenerated on every apply —",
|
|
203
|
+
"# edit the deployer, not this block.",
|
|
204
|
+
];
|
|
205
|
+
const body = MANAGED_HOOKS.map(tomlEntry).join("\n\n");
|
|
206
|
+
return [...header, body, END].join("\n");
|
|
153
207
|
}
|
|
154
208
|
|
|
155
209
|
/**
|
|
@@ -164,14 +218,14 @@ export function managedBlock(): string {
|
|
|
164
218
|
*/
|
|
165
219
|
const PRIOR_BLOCK_HASHES: readonly string[] = [
|
|
166
220
|
// 5-hook block (PreToolUse guard, UserPromptSubmit, SessionStart, PostToolUse crg, SessionEnd) —
|
|
167
|
-
// shipped before crg pre-commit
|
|
168
|
-
|
|
221
|
+
// shipped before crg pre-commit parity was added.
|
|
222
|
+
"fa83560b374bb59b7a45ffa91b5c9d3bfbc2aea36b7e28293b58168fb77db292",
|
|
169
223
|
// 8-hook block before the repository guard became a catch-all PreToolUse hook.
|
|
170
|
-
|
|
224
|
+
"9e6ef84ff230cf29011408dfc7d5798059a6df7790892213efc343e03381d85a",
|
|
171
225
|
// 8-hook block calling the standalone `enact-hook` binary, before it folded
|
|
172
226
|
// into the one `adl` binary (item 15/P4, docs/specs/two-branch-standard-
|
|
173
227
|
// 2026-09-27.md) and HOOK_BIN became `adl hook` — hard cut, no compat shim.
|
|
174
|
-
|
|
228
|
+
"0fa75023b0bb836c199bb0f1f7327fafacea73b4e494a0f45662a1fa3522b7ef",
|
|
175
229
|
// Same 8-hook `enact-hook` body as the entry above, but from one generation
|
|
176
230
|
// earlier: the header comment still reads the pre-reorg deployer path
|
|
177
231
|
// ("global-surface-sweep/src/kimi-hooks.ts") because `acf8ab1` (reorganise
|
|
@@ -185,29 +239,43 @@ const PRIOR_BLOCK_HASHES: readonly string[] = [
|
|
|
185
239
|
// managed block was classified `drifted` instead of `ours-outdated`,
|
|
186
240
|
// aborting a plain `apply` with "hand-edited, or unrecognized content"
|
|
187
241
|
// even though it is byte-for-byte a block this deployer itself shipped.
|
|
188
|
-
|
|
189
|
-
|
|
242
|
+
"bc3f34452cbec3dc0aeb77d917816fd4fbc73a8baedfa09f4e9313a56b330d94",
|
|
243
|
+
// 10-hook `adl hook` block from the window after the enact→adl rename but
|
|
244
|
+
// before lean-ctx was retired (2026-10-04): current markers, current header,
|
|
245
|
+
// and the two `adl hook lean-ctx pre|post-tool-use` entries the canonical
|
|
246
|
+
// block no longer carries. Found live on m3's ~/.kimi-code/config.toml —
|
|
247
|
+
// classified `drifted` and aborted the scheduled reconcile's plain apply
|
|
248
|
+
// even though the only delta from canonical is the two retired lean-ctx
|
|
249
|
+
// entries (diff verified byte-for-byte; see PREVIOUS_LEAN_CTX_ERA_BLOCK in
|
|
250
|
+
// tests/kimi-hooks-upgrade.test.ts).
|
|
251
|
+
"29d2953dd893b6d244bf825b10a7e9deb1a1c25b2acc0db1b74327e19cc8a253",
|
|
252
|
+
];
|
|
190
253
|
|
|
191
254
|
function hashBlock(text: string): string {
|
|
192
|
-
return createHash(
|
|
255
|
+
return createHash("sha256").update(text).digest("hex");
|
|
193
256
|
}
|
|
194
257
|
|
|
195
|
-
export type BlockState =
|
|
258
|
+
export type BlockState =
|
|
259
|
+
| "missing"
|
|
260
|
+
| "matches"
|
|
261
|
+
| "ours-outdated"
|
|
262
|
+
| "drifted"
|
|
263
|
+
| "malformed";
|
|
196
264
|
|
|
197
265
|
interface Region {
|
|
198
|
-
readonly start: number
|
|
266
|
+
readonly start: number;
|
|
199
267
|
/** Exclusive — the index immediately after the closing marker's text. */
|
|
200
|
-
readonly end: number
|
|
268
|
+
readonly end: number;
|
|
201
269
|
}
|
|
202
270
|
|
|
203
|
-
type RegionResult = Region |
|
|
271
|
+
type RegionResult = Region | "missing" | "malformed";
|
|
204
272
|
|
|
205
273
|
function findRegion(content: string, begin: string, end: string): RegionResult {
|
|
206
|
-
const start = content.indexOf(begin)
|
|
207
|
-
const stop = content.indexOf(end)
|
|
208
|
-
if (start < 0 && stop < 0) return
|
|
209
|
-
if (start < 0 || stop < 0 || stop < start) return
|
|
210
|
-
return { start, end: stop + end.length }
|
|
274
|
+
const start = content.indexOf(begin);
|
|
275
|
+
const stop = content.indexOf(end);
|
|
276
|
+
if (start < 0 && stop < 0) return "missing";
|
|
277
|
+
if (start < 0 || stop < 0 || stop < start) return "malformed";
|
|
278
|
+
return { start, end: stop + end.length };
|
|
211
279
|
}
|
|
212
280
|
|
|
213
281
|
/**
|
|
@@ -217,9 +285,9 @@ function findRegion(content: string, begin: string, end: string): RegionResult {
|
|
|
217
285
|
* never mistaken for "missing" and duplicated alongside a fresh insert.
|
|
218
286
|
*/
|
|
219
287
|
function locateManagedRegion(content: string): RegionResult {
|
|
220
|
-
const current = findRegion(content, BEGIN, END)
|
|
221
|
-
if (current !==
|
|
222
|
-
return findRegion(content, LEGACY_BEGIN, LEGACY_END)
|
|
288
|
+
const current = findRegion(content, BEGIN, END);
|
|
289
|
+
if (current !== "missing") return current;
|
|
290
|
+
return findRegion(content, LEGACY_BEGIN, LEGACY_END);
|
|
223
291
|
}
|
|
224
292
|
|
|
225
293
|
/**
|
|
@@ -228,24 +296,27 @@ function locateManagedRegion(content: string): RegionResult {
|
|
|
228
296
|
* missing) and pass it in.
|
|
229
297
|
*/
|
|
230
298
|
export function classifyBlock(existingContent: string | null): BlockState {
|
|
231
|
-
if (existingContent === null || existingContent.length === 0)
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if (region ===
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
299
|
+
if (existingContent === null || existingContent.length === 0)
|
|
300
|
+
return "missing";
|
|
301
|
+
const region = locateManagedRegion(existingContent);
|
|
302
|
+
if (region === "missing") return "missing";
|
|
303
|
+
if (region === "malformed") return "malformed";
|
|
304
|
+
const installed = existingContent.slice(region.start, region.end);
|
|
305
|
+
if (installed === managedBlock()) return "matches";
|
|
306
|
+
return PRIOR_BLOCK_HASHES.includes(hashBlock(installed))
|
|
307
|
+
? "ours-outdated"
|
|
308
|
+
: "drifted";
|
|
238
309
|
}
|
|
239
310
|
|
|
240
311
|
function spliceIn(base: string): string {
|
|
241
|
-
const block = managedBlock()
|
|
242
|
-
const region = locateManagedRegion(base)
|
|
243
|
-
if (region !==
|
|
244
|
-
return `${base.slice(0, region.start)}${block}${base.slice(region.end)}
|
|
312
|
+
const block = managedBlock();
|
|
313
|
+
const region = locateManagedRegion(base);
|
|
314
|
+
if (region !== "missing" && region !== "malformed") {
|
|
315
|
+
return `${base.slice(0, region.start)}${block}${base.slice(region.end)}`;
|
|
245
316
|
}
|
|
246
|
-
if (base.length === 0) return `${block}\n
|
|
247
|
-
const trimmed = base.replace(/\n+$/,
|
|
248
|
-
return `${trimmed}\n\n${block}\n
|
|
317
|
+
if (base.length === 0) return `${block}\n`;
|
|
318
|
+
const trimmed = base.replace(/\n+$/, "");
|
|
319
|
+
return `${trimmed}\n\n${block}\n`;
|
|
249
320
|
}
|
|
250
321
|
|
|
251
322
|
/**
|
|
@@ -255,50 +326,63 @@ function spliceIn(base: string): string {
|
|
|
255
326
|
* freshly-applied block returns the file to byte-identical pre-apply content.
|
|
256
327
|
*/
|
|
257
328
|
function spliceOut(base: string): string {
|
|
258
|
-
const region = locateManagedRegion(base)
|
|
259
|
-
if (region ===
|
|
260
|
-
const head = base.slice(0, region.start).replace(/\n+$/,
|
|
261
|
-
const tail = base.slice(region.end).replace(/^\n+/,
|
|
262
|
-
if (head.length === 0) return tail
|
|
263
|
-
if (tail.length === 0) return `${head}\n
|
|
264
|
-
return `${head}\n\n${tail}
|
|
329
|
+
const region = locateManagedRegion(base);
|
|
330
|
+
if (region === "missing" || region === "malformed") return base;
|
|
331
|
+
const head = base.slice(0, region.start).replace(/\n+$/, "");
|
|
332
|
+
const tail = base.slice(region.end).replace(/^\n+/, "");
|
|
333
|
+
if (head.length === 0) return tail;
|
|
334
|
+
if (tail.length === 0) return `${head}\n`;
|
|
335
|
+
return `${head}\n\n${tail}`;
|
|
265
336
|
}
|
|
266
337
|
|
|
267
338
|
function resolveConfigPath(home: string): string {
|
|
268
|
-
if (!isAbsolute(home)) throw new Error(`--home must be absolute: ${home}`)
|
|
269
|
-
return join(resolve(home),
|
|
339
|
+
if (!isAbsolute(home)) throw new Error(`--home must be absolute: ${home}`);
|
|
340
|
+
return join(resolve(home), ".kimi-code", "config.toml");
|
|
270
341
|
}
|
|
271
342
|
|
|
272
343
|
function readConfig(path: string): string | null {
|
|
273
|
-
if (!existsSync(path)) return null
|
|
274
|
-
return readFileSync(path,
|
|
344
|
+
if (!existsSync(path)) return null;
|
|
345
|
+
return readFileSync(path, "utf8");
|
|
275
346
|
}
|
|
276
347
|
|
|
277
348
|
/** Real TOML syntax check via Bun's built-in parser — never a stub. */
|
|
278
349
|
function assertParseable(text: string, context: string): void {
|
|
279
|
-
if (text.trim().length === 0) return
|
|
350
|
+
if (text.trim().length === 0) return;
|
|
280
351
|
try {
|
|
281
352
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Bun global, no @types/bun in this package
|
|
282
|
-
|
|
353
|
+
(globalThis as any).Bun.TOML.parse(text);
|
|
283
354
|
} catch (error) {
|
|
284
|
-
throw new Error(
|
|
355
|
+
throw new Error(
|
|
356
|
+
`${context} is not valid TOML: ${error instanceof Error ? error.message : String(error)}`,
|
|
357
|
+
);
|
|
285
358
|
}
|
|
286
359
|
}
|
|
287
360
|
|
|
288
361
|
/** Best-effort schema check against the real `kimi` CLI when it is on PATH; a no-op note otherwise. */
|
|
289
|
-
function doctorCheck(
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
362
|
+
function doctorCheck(
|
|
363
|
+
path: string,
|
|
364
|
+
runCommand: DoctorCommandRunner,
|
|
365
|
+
): string | null {
|
|
366
|
+
// Probe the effective PATH this wrapper established. A login shell can add
|
|
367
|
+
// user startup paths and accidentally run an unrelated host Kimi install.
|
|
368
|
+
const which = runCommand("bash", ["-c", "command -v kimi"]);
|
|
369
|
+
if (which.status !== 0) return null;
|
|
370
|
+
const kimi = which.stdout.trim();
|
|
371
|
+
const result = runCommand(kimi, ["doctor", "config", path]);
|
|
293
372
|
if (result.status !== 0) {
|
|
294
|
-
throw new Error(
|
|
373
|
+
throw new Error(
|
|
374
|
+
`kimi doctor rejected the candidate config: ${(result.stderr || result.stdout || "").trim()}`,
|
|
375
|
+
);
|
|
295
376
|
}
|
|
296
|
-
return
|
|
377
|
+
return "kimi doctor: OK";
|
|
297
378
|
}
|
|
298
379
|
|
|
299
380
|
function backupPath(configPath: string): string {
|
|
300
|
-
const stamp = new Date()
|
|
301
|
-
|
|
381
|
+
const stamp = new Date()
|
|
382
|
+
.toISOString()
|
|
383
|
+
.replace(/[-:]/g, "")
|
|
384
|
+
.replace(/\.\d+Z$/, "Z");
|
|
385
|
+
return `${configPath}.pre-kimi-hooks-${stamp}`;
|
|
302
386
|
}
|
|
303
387
|
|
|
304
388
|
/**
|
|
@@ -307,149 +391,212 @@ function backupPath(configPath: string): string {
|
|
|
307
391
|
* the existing file, then atomically rename the staged file into place. A
|
|
308
392
|
* rejected candidate leaves the existing config completely untouched.
|
|
309
393
|
*/
|
|
310
|
-
function commitConfig(
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
394
|
+
function commitConfig(
|
|
395
|
+
path: string,
|
|
396
|
+
next: string,
|
|
397
|
+
notes: string[],
|
|
398
|
+
runCommand: DoctorCommandRunner = runDoctorCommand,
|
|
399
|
+
): string | undefined {
|
|
400
|
+
assertParseable(next, "candidate config");
|
|
401
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
402
|
+
const temporary = join(
|
|
403
|
+
dirname(path),
|
|
404
|
+
`.kimi-hooks.${process.pid}.${Date.now()}.tmp`,
|
|
405
|
+
);
|
|
406
|
+
writeFileSync(temporary, next);
|
|
315
407
|
try {
|
|
316
|
-
const doctorNote = doctorCheck(temporary)
|
|
317
|
-
if (doctorNote) notes.push(doctorNote)
|
|
408
|
+
const doctorNote = doctorCheck(temporary, runCommand);
|
|
409
|
+
if (doctorNote) notes.push(doctorNote);
|
|
318
410
|
} catch (error) {
|
|
319
|
-
rmSync(temporary, { force: true })
|
|
320
|
-
throw error
|
|
411
|
+
rmSync(temporary, { force: true });
|
|
412
|
+
throw error;
|
|
321
413
|
}
|
|
322
|
-
let backup: string | undefined
|
|
414
|
+
let backup: string | undefined;
|
|
323
415
|
if (existsSync(path)) {
|
|
324
|
-
backup = backupPath(path)
|
|
325
|
-
copyFileSync(path, backup)
|
|
326
|
-
notes.push(`backed up previous config to ${backup}`)
|
|
416
|
+
backup = backupPath(path);
|
|
417
|
+
copyFileSync(path, backup);
|
|
418
|
+
notes.push(`backed up previous config to ${backup}`);
|
|
327
419
|
}
|
|
328
|
-
renameSync(temporary, path)
|
|
329
|
-
return backup
|
|
420
|
+
renameSync(temporary, path);
|
|
421
|
+
return backup;
|
|
330
422
|
}
|
|
331
423
|
|
|
332
424
|
export interface PlanResult {
|
|
333
|
-
readonly path: string
|
|
334
|
-
readonly state: BlockState
|
|
335
|
-
readonly wouldChangeOnApply: boolean
|
|
336
|
-
readonly wouldChangeOnUninstall: boolean
|
|
425
|
+
readonly path: string;
|
|
426
|
+
readonly state: BlockState;
|
|
427
|
+
readonly wouldChangeOnApply: boolean;
|
|
428
|
+
readonly wouldChangeOnUninstall: boolean;
|
|
337
429
|
}
|
|
338
430
|
|
|
339
431
|
/** Read-only: current state and what apply/uninstall would do. Never touches the file. */
|
|
340
432
|
export function planKimiHooks(home: string): PlanResult {
|
|
341
|
-
const path = resolveConfigPath(home)
|
|
342
|
-
const state = classifyBlock(readConfig(path))
|
|
433
|
+
const path = resolveConfigPath(home);
|
|
434
|
+
const state = classifyBlock(readConfig(path));
|
|
343
435
|
return {
|
|
344
436
|
path,
|
|
345
437
|
state,
|
|
346
|
-
wouldChangeOnApply:
|
|
347
|
-
|
|
348
|
-
|
|
438
|
+
wouldChangeOnApply:
|
|
439
|
+
state === "missing" || state === "drifted" || state === "ours-outdated",
|
|
440
|
+
wouldChangeOnUninstall:
|
|
441
|
+
state === "matches" || state === "drifted" || state === "ours-outdated",
|
|
442
|
+
};
|
|
349
443
|
}
|
|
350
444
|
|
|
351
445
|
export interface OpResult {
|
|
352
|
-
readonly path: string
|
|
353
|
-
readonly stateBefore: BlockState
|
|
354
|
-
readonly action:
|
|
355
|
-
readonly notes: readonly string[]
|
|
356
|
-
readonly backupPath: string | undefined
|
|
446
|
+
readonly path: string;
|
|
447
|
+
readonly stateBefore: BlockState;
|
|
448
|
+
readonly action: "none" | "installed" | "updated" | "removed";
|
|
449
|
+
readonly notes: readonly string[];
|
|
450
|
+
readonly backupPath: string | undefined;
|
|
357
451
|
}
|
|
358
452
|
|
|
359
|
-
export function applyKimiHooks(
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
453
|
+
export function applyKimiHooks(
|
|
454
|
+
home: string,
|
|
455
|
+
options: {
|
|
456
|
+
readonly force?: boolean;
|
|
457
|
+
readonly doctorCommandRunner?: DoctorCommandRunner;
|
|
458
|
+
} = {},
|
|
459
|
+
): OpResult {
|
|
460
|
+
const path = resolveConfigPath(home);
|
|
461
|
+
const base = readConfig(path);
|
|
462
|
+
const state = classifyBlock(base);
|
|
463
|
+
const notes: string[] = [];
|
|
464
|
+
|
|
465
|
+
if (state === "malformed") {
|
|
466
|
+
throw new Error(
|
|
467
|
+
`malformed managed-block markers in ${path} (BEGIN/END unpaired or out of order) — fix manually`,
|
|
468
|
+
);
|
|
367
469
|
}
|
|
368
|
-
if (base !== null) assertParseable(base, path)
|
|
369
|
-
|
|
370
|
-
if (state ===
|
|
371
|
-
notes.push(
|
|
372
|
-
return {
|
|
470
|
+
if (base !== null) assertParseable(base, path);
|
|
471
|
+
|
|
472
|
+
if (state === "matches") {
|
|
473
|
+
notes.push("managed hook block already present and canonical");
|
|
474
|
+
return {
|
|
475
|
+
path,
|
|
476
|
+
stateBefore: state,
|
|
477
|
+
action: "none",
|
|
478
|
+
notes,
|
|
479
|
+
backupPath: undefined,
|
|
480
|
+
};
|
|
373
481
|
}
|
|
374
|
-
if (state ===
|
|
375
|
-
notes.push(
|
|
482
|
+
if (state === "ours-outdated") {
|
|
483
|
+
notes.push(
|
|
484
|
+
"upgrading managed hook block from a previous ENACT version (no --force needed)",
|
|
485
|
+
);
|
|
376
486
|
}
|
|
377
|
-
if (state ===
|
|
487
|
+
if (state === "drifted" && !(options.force ?? false)) {
|
|
378
488
|
throw new Error(
|
|
379
489
|
`${path} has a managed hook block that differs from the canonical block (hand-edited, or unrecognized content) — rerun apply with --force to overwrite it`,
|
|
380
|
-
)
|
|
490
|
+
);
|
|
381
491
|
}
|
|
382
492
|
|
|
383
|
-
const next = spliceIn(base ??
|
|
384
|
-
const backup = commitConfig(path, next, notes)
|
|
385
|
-
return {
|
|
493
|
+
const next = spliceIn(base ?? "");
|
|
494
|
+
const backup = commitConfig(path, next, notes, options.doctorCommandRunner);
|
|
495
|
+
return {
|
|
496
|
+
path,
|
|
497
|
+
stateBefore: state,
|
|
498
|
+
action: state === "missing" ? "installed" : "updated",
|
|
499
|
+
notes,
|
|
500
|
+
backupPath: backup,
|
|
501
|
+
};
|
|
386
502
|
}
|
|
387
503
|
|
|
388
|
-
export function uninstallKimiHooks(
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
const
|
|
504
|
+
export function uninstallKimiHooks(
|
|
505
|
+
home: string,
|
|
506
|
+
options: { readonly force?: boolean } = {},
|
|
507
|
+
): OpResult {
|
|
508
|
+
const path = resolveConfigPath(home);
|
|
509
|
+
const base = readConfig(path);
|
|
510
|
+
const state = classifyBlock(base);
|
|
511
|
+
const notes: string[] = [];
|
|
393
512
|
|
|
394
|
-
if (state ===
|
|
395
|
-
throw new Error(
|
|
513
|
+
if (state === "malformed") {
|
|
514
|
+
throw new Error(
|
|
515
|
+
`malformed managed-block markers in ${path} (BEGIN/END unpaired or out of order) — fix manually`,
|
|
516
|
+
);
|
|
396
517
|
}
|
|
397
|
-
if (base !== null) assertParseable(base, path)
|
|
398
|
-
|
|
399
|
-
if (state ===
|
|
400
|
-
notes.push(
|
|
401
|
-
return {
|
|
518
|
+
if (base !== null) assertParseable(base, path);
|
|
519
|
+
|
|
520
|
+
if (state === "missing") {
|
|
521
|
+
notes.push("managed hook block not present; nothing to remove");
|
|
522
|
+
return {
|
|
523
|
+
path,
|
|
524
|
+
stateBefore: state,
|
|
525
|
+
action: "none",
|
|
526
|
+
notes,
|
|
527
|
+
backupPath: undefined,
|
|
528
|
+
};
|
|
402
529
|
}
|
|
403
|
-
if (state ===
|
|
404
|
-
notes.push(
|
|
530
|
+
if (state === "ours-outdated") {
|
|
531
|
+
notes.push(
|
|
532
|
+
"removing managed hook block from a previous ENACT version (no --force needed)",
|
|
533
|
+
);
|
|
405
534
|
}
|
|
406
|
-
if (state ===
|
|
535
|
+
if (state === "drifted" && !(options.force ?? false)) {
|
|
407
536
|
throw new Error(
|
|
408
537
|
`${path} has a managed hook block that differs from the canonical block (hand-edited, or unrecognized content) — rerun uninstall with --force to remove it anyway`,
|
|
409
|
-
)
|
|
538
|
+
);
|
|
410
539
|
}
|
|
411
540
|
|
|
412
|
-
const next = spliceOut(base as string)
|
|
413
|
-
const backup = commitConfig(path, next, notes)
|
|
414
|
-
return {
|
|
541
|
+
const next = spliceOut(base as string);
|
|
542
|
+
const backup = commitConfig(path, next, notes);
|
|
543
|
+
return {
|
|
544
|
+
path,
|
|
545
|
+
stateBefore: state,
|
|
546
|
+
action: "removed",
|
|
547
|
+
notes,
|
|
548
|
+
backupPath: backup,
|
|
549
|
+
};
|
|
415
550
|
}
|
|
416
551
|
|
|
417
552
|
function usage(): never {
|
|
418
|
-
throw new Error(
|
|
553
|
+
throw new Error(
|
|
554
|
+
"usage: kimi-hooks --home ABSOLUTE_PATH --mode plan|apply|uninstall [--force]",
|
|
555
|
+
);
|
|
419
556
|
}
|
|
420
557
|
|
|
421
558
|
export function main(argv: readonly string[]): void {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
559
|
+
try {
|
|
560
|
+
let home = "";
|
|
561
|
+
let mode = "";
|
|
562
|
+
let force = false;
|
|
563
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
564
|
+
const argument = argv[index];
|
|
565
|
+
if (argument === "--home") home = argv[++index] ?? "";
|
|
566
|
+
else if (argument === "--mode") mode = argv[++index] ?? "";
|
|
567
|
+
else if (argument === "--force") force = true;
|
|
568
|
+
else usage();
|
|
569
|
+
}
|
|
570
|
+
if (home.length === 0 || !["plan", "apply", "uninstall"].includes(mode))
|
|
571
|
+
usage();
|
|
572
|
+
|
|
573
|
+
if (mode === "plan") {
|
|
574
|
+
const result = planKimiHooks(home);
|
|
575
|
+
console.log(`kimi-hooks: config=${result.path}`);
|
|
576
|
+
console.log(`kimi-hooks: state=${result.state}`);
|
|
577
|
+
console.log(
|
|
578
|
+
`kimi-hooks: apply would ${result.wouldChangeOnApply ? "change this file" : "no-op"}`,
|
|
579
|
+
);
|
|
580
|
+
console.log(
|
|
581
|
+
`kimi-hooks: uninstall would ${result.wouldChangeOnUninstall ? "change this file" : "no-op"}`,
|
|
582
|
+
);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const result =
|
|
587
|
+
mode === "apply"
|
|
588
|
+
? applyKimiHooks(home, { force })
|
|
589
|
+
: uninstallKimiHooks(home, { force });
|
|
590
|
+
for (const note of result.notes) console.log(`kimi-hooks: ${note}`);
|
|
591
|
+
console.log(`kimi-hooks: ${result.action} (${result.path})`);
|
|
592
|
+
} catch (cause) {
|
|
593
|
+
console.error(
|
|
594
|
+
`kimi-hooks: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
595
|
+
);
|
|
596
|
+
process.exitCode = 1;
|
|
441
597
|
}
|
|
442
|
-
|
|
443
|
-
const result = mode === 'apply' ? applyKimiHooks(home, { force }) : uninstallKimiHooks(home, { force })
|
|
444
|
-
for (const note of result.notes) console.log(`kimi-hooks: ${note}`)
|
|
445
|
-
console.log(`kimi-hooks: ${result.action} (${result.path})`)
|
|
446
598
|
}
|
|
447
599
|
|
|
448
600
|
if (import.meta.main) {
|
|
449
|
-
|
|
450
|
-
main(process.argv.slice(2))
|
|
451
|
-
} catch (cause) {
|
|
452
|
-
console.error(`kimi-hooks: ${cause instanceof Error ? cause.message : String(cause)}`)
|
|
453
|
-
process.exitCode = 1
|
|
454
|
-
}
|
|
601
|
+
main(process.argv.slice(2));
|
|
455
602
|
}
|