@lannguyensi/harness 0.64.0 → 1.0.0
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/CHANGELOG.md +64 -0
- package/README.md +46 -42
- package/dist/cli/add/index.js +17 -21
- package/dist/cli/add/index.js.map +1 -1
- package/dist/cli/adopt/derive.d.ts +2 -2
- package/dist/cli/adopt/derive.js +2 -19
- package/dist/cli/adopt/derive.js.map +1 -1
- package/dist/cli/adopt/index.d.ts +1 -1
- package/dist/cli/adopt/index.js +1 -12
- package/dist/cli/adopt/index.js.map +1 -1
- package/dist/cli/apply/apply.d.ts +20 -35
- package/dist/cli/apply/apply.js +61 -136
- package/dist/cli/apply/apply.js.map +1 -1
- package/dist/cli/apply/generate-codex-config.js +10 -58
- package/dist/cli/apply/generate-codex-config.js.map +1 -1
- package/dist/cli/apply/generate-memory-index.js +1 -2
- package/dist/cli/apply/generate-memory-index.js.map +1 -1
- package/dist/cli/apply/generate-opencode-config.d.ts +2 -10
- package/dist/cli/apply/generate-opencode-config.js +74 -113
- package/dist/cli/apply/generate-opencode-config.js.map +1 -1
- package/dist/cli/apply/generate-settings.d.ts +11 -64
- package/dist/cli/apply/generate-settings.js +27 -132
- package/dist/cli/apply/generate-settings.js.map +1 -1
- package/dist/cli/apply/index.d.ts +1 -1
- package/dist/cli/apply/index.js +1 -1
- package/dist/cli/apply/index.js.map +1 -1
- package/dist/cli/apply/install-codex-config.d.ts +153 -1
- package/dist/cli/apply/install-codex-config.js +445 -70
- package/dist/cli/apply/install-codex-config.js.map +1 -1
- package/dist/cli/apply/next-steps.d.ts +7 -0
- package/dist/cli/apply/next-steps.js +13 -1
- package/dist/cli/apply/next-steps.js.map +1 -1
- package/dist/cli/bounded-stdin.d.ts +0 -23
- package/dist/cli/bounded-stdin.js +2 -49
- package/dist/cli/bounded-stdin.js.map +1 -1
- package/dist/cli/describe.d.ts +1 -1
- package/dist/cli/describe.js +0 -3
- package/dist/cli/describe.js.map +1 -1
- package/dist/cli/diff/engine.d.ts +0 -11
- package/dist/cli/diff/engine.js +1 -17
- package/dist/cli/diff/engine.js.map +1 -1
- package/dist/cli/diff/index.js +14 -25
- package/dist/cli/diff/index.js.map +1 -1
- package/dist/cli/doctor/claude-mcp.d.ts +4 -19
- package/dist/cli/doctor/claude-mcp.js +11 -22
- package/dist/cli/doctor/claude-mcp.js.map +1 -1
- package/dist/cli/doctor/codex.d.ts +12 -14
- package/dist/cli/doctor/codex.js +31 -144
- package/dist/cli/doctor/codex.js.map +1 -1
- package/dist/cli/doctor/format.js +23 -345
- package/dist/cli/doctor/format.js.map +1 -1
- package/dist/cli/doctor/hook-liveness.d.ts +56 -0
- package/dist/cli/doctor/hook-liveness.js +455 -0
- package/dist/cli/doctor/hook-liveness.js.map +1 -0
- package/dist/cli/doctor/index.d.ts +13 -87
- package/dist/cli/doctor/index.js +57 -713
- package/dist/cli/doctor/index.js.map +1 -1
- package/dist/cli/doctor/opencode.d.ts +2 -1
- package/dist/cli/doctor/opencode.js.map +1 -1
- package/dist/cli/doctor/types.d.ts +21 -387
- package/dist/cli/doctor/types.js.map +1 -1
- package/dist/cli/drain-stdio.d.ts +31 -0
- package/dist/cli/drain-stdio.js +76 -0
- package/dist/cli/drain-stdio.js.map +1 -0
- package/dist/cli/export.d.ts +3 -1
- package/dist/cli/export.js +7 -16
- package/dist/cli/export.js.map +1 -1
- package/dist/cli/gate/codex-disable.d.ts +29 -0
- package/dist/cli/gate/codex-disable.js +195 -0
- package/dist/cli/gate/codex-disable.js.map +1 -0
- package/dist/cli/gate/codex-enable.d.ts +41 -0
- package/dist/cli/gate/codex-enable.js +127 -0
- package/dist/cli/gate/codex-enable.js.map +1 -0
- package/dist/cli/gate/codex-snapshot.d.ts +208 -0
- package/dist/cli/gate/codex-snapshot.js +402 -0
- package/dist/cli/gate/codex-snapshot.js.map +1 -0
- package/dist/cli/gate/disable.d.ts +9 -0
- package/dist/cli/gate/disable.js +263 -28
- package/dist/cli/gate/disable.js.map +1 -1
- package/dist/cli/gate/enable.d.ts +26 -6
- package/dist/cli/gate/enable.js +152 -80
- package/dist/cli/gate/enable.js.map +1 -1
- package/dist/cli/gate/link-chain.d.ts +53 -0
- package/dist/cli/gate/link-chain.js +122 -0
- package/dist/cli/gate/link-chain.js.map +1 -0
- package/dist/cli/gate/snapshot.d.ts +289 -12
- package/dist/cli/gate/snapshot.js +481 -22
- package/dist/cli/gate/snapshot.js.map +1 -1
- package/dist/cli/index.d.ts +0 -9
- package/dist/cli/index.js +9 -2131
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/composer.d.ts +3 -6
- package/dist/cli/init/composer.js +6 -370
- package/dist/cli/init/composer.js.map +1 -1
- package/dist/cli/init/dependencies.d.ts +1 -2
- package/dist/cli/init/dependencies.js +4 -80
- package/dist/cli/init/dependencies.js.map +1 -1
- package/dist/cli/init/detect.js +5 -4
- package/dist/cli/init/detect.js.map +1 -1
- package/dist/cli/init/interactive.d.ts +1 -23
- package/dist/cli/init/interactive.js +33 -247
- package/dist/cli/init/interactive.js.map +1 -1
- package/dist/cli/init/profiles.d.ts +2 -2
- package/dist/cli/init/profiles.js +51 -245
- package/dist/cli/init/profiles.js.map +1 -1
- package/dist/cli/init/templates.d.ts +2 -37
- package/dist/cli/init/templates.js +25 -1237
- package/dist/cli/init/templates.js.map +1 -1
- package/dist/cli/list.d.ts +1 -1
- package/dist/cli/list.js +1 -38
- package/dist/cli/list.js.map +1 -1
- package/dist/cli/loader.d.ts +15 -1
- package/dist/cli/loader.js +56 -39
- package/dist/cli/loader.js.map +1 -1
- package/dist/cli/main.js +7 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/migrate-home/index.js +2 -2
- package/dist/cli/migrate-home/index.js.map +1 -1
- package/dist/cli/pack/add.js +1 -1
- package/dist/cli/pack/add.js.map +1 -1
- package/dist/cli/pack/hook-bootstrap.d.ts +5 -164
- package/dist/cli/pack/hook-bootstrap.js +15 -291
- package/dist/cli/pack/hook-bootstrap.js.map +1 -1
- package/dist/cli/pack/hook-branch-protection.d.ts +28 -21
- package/dist/cli/pack/hook-branch-protection.js +365 -340
- package/dist/cli/pack/hook-branch-protection.js.map +1 -1
- package/dist/cli/pack/index.d.ts +0 -1
- package/dist/cli/pack/index.js +0 -1
- package/dist/cli/pack/index.js.map +1 -1
- package/dist/cli/pack/list.js +1 -6
- package/dist/cli/pack/list.js.map +1 -1
- package/dist/cli/pack/mutate.d.ts +7 -9
- package/dist/cli/pack/mutate.js +6 -9
- package/dist/cli/pack/mutate.js.map +1 -1
- package/dist/cli/pack/reseed.d.ts +2 -2
- package/dist/cli/pack/reseed.js +16 -22
- package/dist/cli/pack/reseed.js.map +1 -1
- package/dist/cli/{delegate/register.d.ts → register-gate-group.d.ts} +1 -1
- package/dist/cli/register-gate-group.js +348 -0
- package/dist/cli/register-gate-group.js.map +1 -0
- package/dist/cli/register-inspect-group.d.ts +6 -0
- package/dist/cli/register-inspect-group.js +189 -0
- package/dist/cli/register-inspect-group.js.map +1 -0
- package/dist/cli/register-operator-lifecycle.d.ts +1 -1
- package/dist/cli/register-operator-lifecycle.js +3 -100
- package/dist/cli/register-operator-lifecycle.js.map +1 -1
- package/dist/cli/register-pack-group.d.ts +5 -0
- package/dist/cli/register-pack-group.js +134 -0
- package/dist/cli/register-pack-group.js.map +1 -0
- package/dist/cli/{register-audit-group.d.ts → register-setup-group.d.ts} +1 -1
- package/dist/cli/register-setup-group.js +495 -0
- package/dist/cli/register-setup-group.js.map +1 -0
- package/dist/cli/remove/index.d.ts +0 -14
- package/dist/cli/remove/index.js +2 -115
- package/dist/cli/remove/index.js.map +1 -1
- package/dist/cli/remove/mutate.d.ts +0 -2
- package/dist/cli/remove/mutate.js +1 -19
- package/dist/cli/remove/mutate.js.map +1 -1
- package/dist/cli/remove/register.js +2 -19
- package/dist/cli/remove/register.js.map +1 -1
- package/dist/cli/shell-quote.d.ts +7 -0
- package/dist/cli/shell-quote.js +17 -0
- package/dist/cli/shell-quote.js.map +1 -0
- package/dist/cli/uninstall/index.d.ts +4 -2
- package/dist/cli/uninstall/index.js +15 -7
- package/dist/cli/uninstall/index.js.map +1 -1
- package/dist/cli/uninstall/register.js +6 -4
- package/dist/cli/uninstall/register.js.map +1 -1
- package/dist/cli/uninstall/snapshot.d.ts +15 -0
- package/dist/cli/uninstall/snapshot.js +38 -0
- package/dist/cli/uninstall/snapshot.js.map +1 -1
- package/dist/cli/validate/checks.d.ts +0 -77
- package/dist/cli/validate/checks.js +3 -1049
- package/dist/cli/validate/checks.js.map +1 -1
- package/dist/cli/validate/index.js +19 -15
- package/dist/cli/validate/index.js.map +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -3
- package/dist/index.js.map +1 -1
- package/dist/io/claude-mcp.d.ts +1 -1
- package/dist/io/claude-mcp.js +27 -14
- package/dist/io/claude-mcp.js.map +1 -1
- package/dist/io/harness-lock.js +2 -2
- package/dist/io/harness-lock.js.map +1 -1
- package/dist/io/lock.d.ts +0 -26
- package/dist/io/lock.js +10 -27
- package/dist/io/lock.js.map +1 -1
- package/dist/io/merge-settings.js +6 -4
- package/dist/io/merge-settings.js.map +1 -1
- package/dist/io/project-name.d.ts +22 -39
- package/dist/io/project-name.js +25 -42
- package/dist/io/project-name.js.map +1 -1
- package/dist/io/read-regular-file.d.ts +103 -40
- package/dist/io/read-regular-file.js +196 -35
- package/dist/io/read-regular-file.js.map +1 -1
- package/dist/io/restart-hints.js +3 -6
- package/dist/io/restart-hints.js.map +1 -1
- package/dist/io/version-compare.d.ts +1 -3
- package/dist/io/version-compare.js +1 -3
- package/dist/io/version-compare.js.map +1 -1
- package/dist/io/write-regular-file.d.ts +30 -0
- package/dist/io/write-regular-file.js +85 -0
- package/dist/io/write-regular-file.js.map +1 -0
- package/dist/overrides/index.d.ts +1 -0
- package/dist/overrides/index.js +1 -0
- package/dist/overrides/index.js.map +1 -1
- package/dist/overrides/merge-layers.d.ts +43 -0
- package/dist/overrides/merge-layers.js +76 -0
- package/dist/overrides/merge-layers.js.map +1 -0
- package/dist/overrides/merge.d.ts +16 -0
- package/dist/overrides/merge.js +21 -8
- package/dist/overrides/merge.js.map +1 -1
- package/dist/policy-packs/builtin/branch-protection-runtime.d.ts +4 -69
- package/dist/policy-packs/builtin/branch-protection-runtime.js +12 -84
- package/dist/policy-packs/builtin/branch-protection-runtime.js.map +1 -1
- package/dist/policy-packs/builtin/branch-protection.d.ts +7 -30
- package/dist/policy-packs/builtin/branch-protection.js +56 -89
- package/dist/policy-packs/builtin/branch-protection.js.map +1 -1
- package/dist/policy-packs/config-check.d.ts +7 -5
- package/dist/policy-packs/config-check.js +2 -2
- package/dist/policy-packs/config-check.js.map +1 -1
- package/dist/policy-packs/expand.d.ts +1 -3
- package/dist/policy-packs/expand.js +5 -42
- package/dist/policy-packs/expand.js.map +1 -1
- package/dist/policy-packs/index.d.ts +3 -3
- package/dist/policy-packs/index.js +2 -2
- package/dist/policy-packs/index.js.map +1 -1
- package/dist/policy-packs/registry.d.ts +9 -38
- package/dist/policy-packs/registry.js +5 -65
- package/dist/policy-packs/registry.js.map +1 -1
- package/dist/policy-packs/runtime.d.ts +0 -4
- package/dist/policy-packs/runtime.js +9 -22
- package/dist/policy-packs/runtime.js.map +1 -1
- package/dist/policy-packs/types.d.ts +0 -19
- package/dist/policy-packs/ux-compare.d.ts +1 -11
- package/dist/policy-packs/ux-compare.js +6 -42
- package/dist/policy-packs/ux-compare.js.map +1 -1
- package/dist/policy-packs/ux-drift-check.d.ts +5 -5
- package/dist/policy-packs/ux-drift-check.js +17 -22
- package/dist/policy-packs/ux-drift-check.js.map +1 -1
- package/dist/policy-packs/version-check.d.ts +5 -26
- package/dist/policy-packs/version-check.js +19 -74
- package/dist/policy-packs/version-check.js.map +1 -1
- package/dist/probes/memory.d.ts +1 -1
- package/dist/probes/memory.js +1 -1
- package/dist/probes/memory.js.map +1 -1
- package/dist/runtime/agent-facing.d.ts +9 -0
- package/dist/runtime/agent-facing.js +28 -14
- package/dist/runtime/agent-facing.js.map +1 -1
- package/dist/runtime/bounded-text.d.ts +15 -0
- package/dist/runtime/bounded-text.js +27 -0
- package/dist/runtime/bounded-text.js.map +1 -0
- package/dist/runtime/git-branch.d.ts +125 -0
- package/dist/runtime/git-branch.js +381 -0
- package/dist/runtime/git-branch.js.map +1 -0
- package/dist/runtime/hermetic-spawn-guard.d.ts +2 -2
- package/dist/runtime/hermetic-spawn-guard.js +24 -34
- package/dist/runtime/hermetic-spawn-guard.js.map +1 -1
- package/dist/runtime/home-dir.js +3 -2
- package/dist/runtime/home-dir.js.map +1 -1
- package/dist/runtime/tool-name-aliases.d.ts +0 -6
- package/dist/runtime/tool-name-aliases.js +5 -18
- package/dist/runtime/tool-name-aliases.js.map +1 -1
- package/dist/schema/grounding.d.ts +7 -54
- package/dist/schema/grounding.js +10 -12
- package/dist/schema/grounding.js.map +1 -1
- package/dist/schema/hooks.d.ts +39 -136
- package/dist/schema/hooks.js +3 -6
- package/dist/schema/hooks.js.map +1 -1
- package/dist/schema/index.d.ts +114 -3828
- package/dist/schema/index.js +41 -80
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/memory.d.ts +54 -131
- package/dist/schema/memory.js +2 -2
- package/dist/schema/memory.js.map +1 -1
- package/dist/schema/policy-packs.d.ts +3 -45
- package/dist/schema/policy-packs.js +7 -13
- package/dist/schema/policy-packs.js.map +1 -1
- package/dist/schema/policy-ux.d.ts +7 -0
- package/dist/schema/policy-ux.js +18 -0
- package/dist/schema/policy-ux.js.map +1 -0
- package/dist/schema/removed-keys.d.ts +185 -0
- package/dist/schema/removed-keys.js +531 -0
- package/dist/schema/removed-keys.js.map +1 -0
- package/dist/schema/tools.d.ts +30 -268
- package/dist/schema/tools.js +4 -4
- package/dist/schema/tools.js.map +1 -1
- package/package.json +5 -16
- package/dist/cli/approve/branch-protection.d.ts +0 -69
- package/dist/cli/approve/branch-protection.js +0 -144
- package/dist/cli/approve/branch-protection.js.map +0 -1
- package/dist/cli/approve/risk.d.ts +0 -112
- package/dist/cli/approve/risk.js +0 -197
- package/dist/cli/approve/risk.js.map +0 -1
- package/dist/cli/approve/stdin-report.d.ts +0 -57
- package/dist/cli/approve/stdin-report.js +0 -145
- package/dist/cli/approve/stdin-report.js.map +0 -1
- package/dist/cli/approve/understanding.d.ts +0 -410
- package/dist/cli/approve/understanding.js +0 -996
- package/dist/cli/approve/understanding.js.map +0 -1
- package/dist/cli/audit.d.ts +0 -80
- package/dist/cli/audit.js +0 -252
- package/dist/cli/audit.js.map +0 -1
- package/dist/cli/delegate/index.d.ts +0 -76
- package/dist/cli/delegate/index.js +0 -444
- package/dist/cli/delegate/index.js.map +0 -1
- package/dist/cli/delegate/register.js +0 -90
- package/dist/cli/delegate/register.js.map +0 -1
- package/dist/cli/doctor/auto-approve-mode.d.ts +0 -37
- package/dist/cli/doctor/auto-approve-mode.js +0 -80
- package/dist/cli/doctor/auto-approve-mode.js.map +0 -1
- package/dist/cli/doctor/bypass-without-auto-approve.d.ts +0 -38
- package/dist/cli/doctor/bypass-without-auto-approve.js +0 -95
- package/dist/cli/doctor/bypass-without-auto-approve.js.map +0 -1
- package/dist/cli/doctor/codex-config-drift.d.ts +0 -28
- package/dist/cli/doctor/codex-config-drift.js +0 -240
- package/dist/cli/doctor/codex-config-drift.js.map +0 -1
- package/dist/cli/doctor/expire-on-tool-match.d.ts +0 -15
- package/dist/cli/doctor/expire-on-tool-match.js +0 -58
- package/dist/cli/doctor/expire-on-tool-match.js.map +0 -1
- package/dist/cli/doctor/rogue-ledger.d.ts +0 -53
- package/dist/cli/doctor/rogue-ledger.js +0 -153
- package/dist/cli/doctor/rogue-ledger.js.map +0 -1
- package/dist/cli/doctor/session-start-preflight-setup-version.d.ts +0 -83
- package/dist/cli/doctor/session-start-preflight-setup-version.js +0 -114
- package/dist/cli/doctor/session-start-preflight-setup-version.js.map +0 -1
- package/dist/cli/doctor/settings-drift.d.ts +0 -25
- package/dist/cli/doctor/settings-drift.js +0 -213
- package/dist/cli/doctor/settings-drift.js.map +0 -1
- package/dist/cli/doctor/toolchain-parity.d.ts +0 -63
- package/dist/cli/doctor/toolchain-parity.js +0 -154
- package/dist/cli/doctor/toolchain-parity.js.map +0 -1
- package/dist/cli/doctor/ug-auto-approvals.d.ts +0 -40
- package/dist/cli/doctor/ug-auto-approvals.js +0 -91
- package/dist/cli/doctor/ug-auto-approvals.js.map +0 -1
- package/dist/cli/doctor/ug-delegations.d.ts +0 -26
- package/dist/cli/doctor/ug-delegations.js +0 -121
- package/dist/cli/doctor/ug-delegations.js.map +0 -1
- package/dist/cli/doctor/ug-inflight.d.ts +0 -35
- package/dist/cli/doctor/ug-inflight.js +0 -57
- package/dist/cli/doctor/ug-inflight.js.map +0 -1
- package/dist/cli/doctor/understanding-mode-env.d.ts +0 -51
- package/dist/cli/doctor/understanding-mode-env.js +0 -98
- package/dist/cli/doctor/understanding-mode-env.js.map +0 -1
- package/dist/cli/dry-run.d.ts +0 -58
- package/dist/cli/dry-run.js +0 -283
- package/dist/cli/dry-run.js.map +0 -1
- package/dist/cli/enriched-event.d.ts +0 -35
- package/dist/cli/enriched-event.js +0 -60
- package/dist/cli/enriched-event.js.map +0 -1
- package/dist/cli/event-input.d.ts +0 -28
- package/dist/cli/event-input.js +0 -73
- package/dist/cli/event-input.js.map +0 -1
- package/dist/cli/explain-action.d.ts +0 -25
- package/dist/cli/explain-action.js +0 -57
- package/dist/cli/explain-action.js.map +0 -1
- package/dist/cli/explain-policy.d.ts +0 -147
- package/dist/cli/explain-policy.js +0 -248
- package/dist/cli/explain-policy.js.map +0 -1
- package/dist/cli/explain.d.ts +0 -31
- package/dist/cli/explain.js +0 -159
- package/dist/cli/explain.js.map +0 -1
- package/dist/cli/gc/index.d.ts +0 -63
- package/dist/cli/gc/index.js +0 -566
- package/dist/cli/gc/index.js.map +0 -1
- package/dist/cli/pack/approve-escape.d.ts +0 -19
- package/dist/cli/pack/approve-escape.js +0 -190
- package/dist/cli/pack/approve-escape.js.map +0 -1
- package/dist/cli/pack/auto-approve-path.d.ts +0 -146
- package/dist/cli/pack/auto-approve-path.js +0 -462
- package/dist/cli/pack/auto-approve-path.js.map +0 -1
- package/dist/cli/pack/hook-codex-post-tool-use.d.ts +0 -25
- package/dist/cli/pack/hook-codex-post-tool-use.js +0 -160
- package/dist/cli/pack/hook-codex-post-tool-use.js.map +0 -1
- package/dist/cli/pack/hook-codex-pre-tool-use.d.ts +0 -48
- package/dist/cli/pack/hook-codex-pre-tool-use.js +0 -474
- package/dist/cli/pack/hook-codex-pre-tool-use.js.map +0 -1
- package/dist/cli/pack/hook-codex-stop.d.ts +0 -35
- package/dist/cli/pack/hook-codex-stop.js +0 -329
- package/dist/cli/pack/hook-codex-stop.js.map +0 -1
- package/dist/cli/pack/hook-codex-user-prompt-submit.d.ts +0 -24
- package/dist/cli/pack/hook-codex-user-prompt-submit.js +0 -93
- package/dist/cli/pack/hook-codex-user-prompt-submit.js.map +0 -1
- package/dist/cli/pack/hook-post-merge-gate-record.d.ts +0 -37
- package/dist/cli/pack/hook-post-merge-gate-record.js +0 -190
- package/dist/cli/pack/hook-post-merge-gate-record.js.map +0 -1
- package/dist/cli/pack/hook-post-merge-gate.d.ts +0 -34
- package/dist/cli/pack/hook-post-merge-gate.js +0 -277
- package/dist/cli/pack/hook-post-merge-gate.js.map +0 -1
- package/dist/cli/pack/hook-post-tool-use.d.ts +0 -45
- package/dist/cli/pack/hook-post-tool-use.js +0 -137
- package/dist/cli/pack/hook-post-tool-use.js.map +0 -1
- package/dist/cli/pack/hook-pre-tool-use.d.ts +0 -92
- package/dist/cli/pack/hook-pre-tool-use.js +0 -1328
- package/dist/cli/pack/hook-pre-tool-use.js.map +0 -1
- package/dist/cli/pack/hook-runtime-reality.d.ts +0 -63
- package/dist/cli/pack/hook-runtime-reality.js +0 -210
- package/dist/cli/pack/hook-runtime-reality.js.map +0 -1
- package/dist/cli/pack/hook-solution-acceptance-writeguard.d.ts +0 -32
- package/dist/cli/pack/hook-solution-acceptance-writeguard.js +0 -438
- package/dist/cli/pack/hook-solution-acceptance-writeguard.js.map +0 -1
- package/dist/cli/pack/hook-solution-acceptance.d.ts +0 -157
- package/dist/cli/pack/hook-solution-acceptance.js +0 -530
- package/dist/cli/pack/hook-solution-acceptance.js.map +0 -1
- package/dist/cli/pack/hook-stay-in-scope.d.ts +0 -37
- package/dist/cli/pack/hook-stay-in-scope.js +0 -128
- package/dist/cli/pack/hook-stay-in-scope.js.map +0 -1
- package/dist/cli/pack/hook-subagent-start.d.ts +0 -23
- package/dist/cli/pack/hook-subagent-start.js +0 -88
- package/dist/cli/pack/hook-subagent-start.js.map +0 -1
- package/dist/cli/pack/hook-subagent-stop.d.ts +0 -19
- package/dist/cli/pack/hook-subagent-stop.js +0 -41
- package/dist/cli/pack/hook-subagent-stop.js.map +0 -1
- package/dist/cli/pack/hook-track-active-claim.d.ts +0 -27
- package/dist/cli/pack/hook-track-active-claim.js +0 -275
- package/dist/cli/pack/hook-track-active-claim.js.map +0 -1
- package/dist/cli/pack/transcript-report-scan.d.ts +0 -71
- package/dist/cli/pack/transcript-report-scan.js +0 -359
- package/dist/cli/pack/transcript-report-scan.js.map +0 -1
- package/dist/cli/pack/understanding-report-schema-hint.d.ts +0 -26
- package/dist/cli/pack/understanding-report-schema-hint.js +0 -120
- package/dist/cli/pack/understanding-report-schema-hint.js.map +0 -1
- package/dist/cli/pack/upgrade.d.ts +0 -32
- package/dist/cli/pack/upgrade.js +0 -273
- package/dist/cli/pack/upgrade.js.map +0 -1
- package/dist/cli/pause/index.d.ts +0 -113
- package/dist/cli/pause/index.js +0 -251
- package/dist/cli/pause/index.js.map +0 -1
- package/dist/cli/pause-check.d.ts +0 -22
- package/dist/cli/pause-check.js +0 -54
- package/dist/cli/pause-check.js.map +0 -1
- package/dist/cli/policy/intercept.d.ts +0 -233
- package/dist/cli/policy/intercept.js +0 -1022
- package/dist/cli/policy/intercept.js.map +0 -1
- package/dist/cli/policy/risk-envelope-enrichment.d.ts +0 -40
- package/dist/cli/policy/risk-envelope-enrichment.js +0 -110
- package/dist/cli/policy/risk-envelope-enrichment.js.map +0 -1
- package/dist/cli/record/index.d.ts +0 -81
- package/dist/cli/record/index.js +0 -348
- package/dist/cli/record/index.js.map +0 -1
- package/dist/cli/register-audit-group.js +0 -91
- package/dist/cli/register-audit-group.js.map +0 -1
- package/dist/cli/resolve-env.d.ts +0 -32
- package/dist/cli/resolve-env.js +0 -46
- package/dist/cli/resolve-env.js.map +0 -1
- package/dist/cli/session-export/index.d.ts +0 -46
- package/dist/cli/session-export/index.js +0 -169
- package/dist/cli/session-export/index.js.map +0 -1
- package/dist/cli/session-export/redact.d.ts +0 -22
- package/dist/cli/session-export/redact.js +0 -47
- package/dist/cli/session-export/redact.js.map +0 -1
- package/dist/cli/session-export/transcript.d.ts +0 -24
- package/dist/cli/session-export/transcript.js +0 -164
- package/dist/cli/session-export/transcript.js.map +0 -1
- package/dist/cli/session-start/branch-check.d.ts +0 -18
- package/dist/cli/session-start/branch-check.js +0 -140
- package/dist/cli/session-start/branch-check.js.map +0 -1
- package/dist/cli/session-start/index.d.ts +0 -121
- package/dist/cli/session-start/index.js +0 -591
- package/dist/cli/session-start/index.js.map +0 -1
- package/dist/cli/session-start/shared-options.d.ts +0 -103
- package/dist/cli/session-start/shared-options.js +0 -107
- package/dist/cli/session-start/shared-options.js.map +0 -1
- package/dist/cli/session-start/stale-base-check.d.ts +0 -46
- package/dist/cli/session-start/stale-base-check.js +0 -352
- package/dist/cli/session-start/stale-base-check.js.map +0 -1
- package/dist/cli/session-start/toolchain-parity.d.ts +0 -267
- package/dist/cli/session-start/toolchain-parity.js +0 -797
- package/dist/cli/session-start/toolchain-parity.js.map +0 -1
- package/dist/cli/smoke/assertions.d.ts +0 -46
- package/dist/cli/smoke/assertions.js +0 -170
- package/dist/cli/smoke/assertions.js.map +0 -1
- package/dist/cli/smoke/index.d.ts +0 -76
- package/dist/cli/smoke/index.js +0 -245
- package/dist/cli/smoke/index.js.map +0 -1
- package/dist/cli/smoke/runner.d.ts +0 -55
- package/dist/cli/smoke/runner.js +0 -134
- package/dist/cli/smoke/runner.js.map +0 -1
- package/dist/cli/smoke/stream-parser.d.ts +0 -65
- package/dist/cli/smoke/stream-parser.js +0 -115
- package/dist/cli/smoke/stream-parser.js.map +0 -1
- package/dist/cli/test-risk.d.ts +0 -27
- package/dist/cli/test-risk.js +0 -38
- package/dist/cli/test-risk.js.map +0 -1
- package/dist/io/display-path.d.ts +0 -11
- package/dist/io/display-path.js +0 -29
- package/dist/io/display-path.js.map +0 -1
- package/dist/io/duration.d.ts +0 -5
- package/dist/io/duration.js +0 -50
- package/dist/io/duration.js.map +0 -1
- package/dist/io/extract.d.ts +0 -79
- package/dist/io/extract.js +0 -226
- package/dist/io/extract.js.map +0 -1
- package/dist/io/ledger-record.d.ts +0 -83
- package/dist/io/ledger-record.js +0 -301
- package/dist/io/ledger-record.js.map +0 -1
- package/dist/io/read-json-dir-entries.d.ts +0 -36
- package/dist/io/read-json-dir-entries.js +0 -48
- package/dist/io/read-json-dir-entries.js.map +0 -1
- package/dist/io/safe-json-parse.d.ts +0 -5
- package/dist/io/safe-json-parse.js +0 -21
- package/dist/io/safe-json-parse.js.map +0 -1
- package/dist/policies/index.d.ts +0 -5
- package/dist/policies/index.js +0 -6
- package/dist/policies/index.js.map +0 -1
- package/dist/policies/ledger-client.d.ts +0 -113
- package/dist/policies/ledger-client.js +0 -500
- package/dist/policies/ledger-client.js.map +0 -1
- package/dist/policies/producers.d.ts +0 -12
- package/dist/policies/producers.js +0 -61
- package/dist/policies/producers.js.map +0 -1
- package/dist/policies/requires.d.ts +0 -75
- package/dist/policies/requires.js +0 -240
- package/dist/policies/requires.js.map +0 -1
- package/dist/policies/timestamp.d.ts +0 -14
- package/dist/policies/timestamp.js +0 -36
- package/dist/policies/timestamp.js.map +0 -1
- package/dist/policy-packs/builtin/permission-profiles.d.ts +0 -11
- package/dist/policy-packs/builtin/permission-profiles.js +0 -74
- package/dist/policy-packs/builtin/permission-profiles.js.map +0 -1
- package/dist/policy-packs/builtin/post-merge-gate-runtime.d.ts +0 -286
- package/dist/policy-packs/builtin/post-merge-gate-runtime.js +0 -397
- package/dist/policy-packs/builtin/post-merge-gate-runtime.js.map +0 -1
- package/dist/policy-packs/builtin/post-merge-gate.d.ts +0 -56
- package/dist/policy-packs/builtin/post-merge-gate.js +0 -347
- package/dist/policy-packs/builtin/post-merge-gate.js.map +0 -1
- package/dist/policy-packs/builtin/solution-acceptance-reconnect.d.ts +0 -50
- package/dist/policy-packs/builtin/solution-acceptance-reconnect.js +0 -151
- package/dist/policy-packs/builtin/solution-acceptance-reconnect.js.map +0 -1
- package/dist/policy-packs/builtin/solution-acceptance-runtime.d.ts +0 -323
- package/dist/policy-packs/builtin/solution-acceptance-runtime.js +0 -672
- package/dist/policy-packs/builtin/solution-acceptance-runtime.js.map +0 -1
- package/dist/policy-packs/builtin/solution-acceptance.d.ts +0 -45
- package/dist/policy-packs/builtin/solution-acceptance.js +0 -226
- package/dist/policy-packs/builtin/solution-acceptance.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/active-claim.d.ts +0 -25
- package/dist/policy-packs/builtin/understanding-before-execution/active-claim.js +0 -94
- package/dist/policy-packs/builtin/understanding-before-execution/active-claim.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.d.ts +0 -35
- package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.js +0 -86
- package/dist/policy-packs/builtin/understanding-before-execution/auto-approve-default.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.d.ts +0 -210
- package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.js +0 -361
- package/dist/policy-packs/builtin/understanding-before-execution/auto-approve.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.d.ts +0 -304
- package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.js +0 -734
- package/dist/policy-packs/builtin/understanding-before-execution/delegation-markers.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/expiry-reason.d.ts +0 -36
- package/dist/policy-packs/builtin/understanding-before-execution/expiry-reason.js +0 -73
- package/dist/policy-packs/builtin/understanding-before-execution/expiry-reason.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/index.d.ts +0 -19
- package/dist/policy-packs/builtin/understanding-before-execution/index.js +0 -83
- package/dist/policy-packs/builtin/understanding-before-execution/index.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/inflight-records.d.ts +0 -135
- package/dist/policy-packs/builtin/understanding-before-execution/inflight-records.js +0 -643
- package/dist/policy-packs/builtin/understanding-before-execution/inflight-records.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/ledger.d.ts +0 -25
- package/dist/policy-packs/builtin/understanding-before-execution/ledger.js +0 -56
- package/dist/policy-packs/builtin/understanding-before-execution/ledger.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/lifecycle.d.ts +0 -20
- package/dist/policy-packs/builtin/understanding-before-execution/lifecycle.js +0 -106
- package/dist/policy-packs/builtin/understanding-before-execution/lifecycle.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/markers.d.ts +0 -126
- package/dist/policy-packs/builtin/understanding-before-execution/markers.js +0 -245
- package/dist/policy-packs/builtin/understanding-before-execution/markers.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.d.ts +0 -29
- package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.js +0 -82
- package/dist/policy-packs/builtin/understanding-before-execution/measured-permission-modes.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.d.ts +0 -71
- package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.js +0 -175
- package/dist/policy-packs/builtin/understanding-before-execution/permission-mode-observations.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.d.ts +0 -625
- package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js +0 -1076
- package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.d.ts +0 -128
- package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.js +0 -213
- package/dist/policy-packs/builtin/understanding-before-execution/post-tool-use-boundary.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/stay-in-scope-config.d.ts +0 -129
- package/dist/policy-packs/builtin/understanding-before-execution/stay-in-scope-config.js +0 -166
- package/dist/policy-packs/builtin/understanding-before-execution/stay-in-scope-config.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution/task-markers.d.ts +0 -164
- package/dist/policy-packs/builtin/understanding-before-execution/task-markers.js +0 -275
- package/dist/policy-packs/builtin/understanding-before-execution/task-markers.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution-runtime.d.ts +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution-runtime.js +0 -10
- package/dist/policy-packs/builtin/understanding-before-execution-runtime.js.map +0 -1
- package/dist/policy-packs/builtin/understanding-before-execution.d.ts +0 -526
- package/dist/policy-packs/builtin/understanding-before-execution.js +0 -1078
- package/dist/policy-packs/builtin/understanding-before-execution.js.map +0 -1
- package/dist/policy-packs/permission-translator.d.ts +0 -9
- package/dist/policy-packs/permission-translator.js +0 -76
- package/dist/policy-packs/permission-translator.js.map +0 -1
- package/dist/runtime/action-envelope.d.ts +0 -64
- package/dist/runtime/action-envelope.js +0 -46
- package/dist/runtime/action-envelope.js.map +0 -1
- package/dist/runtime/approval-signing.d.ts +0 -111
- package/dist/runtime/approval-signing.js +0 -384
- package/dist/runtime/approval-signing.js.map +0 -1
- package/dist/runtime/bash-match-facts.d.ts +0 -60
- package/dist/runtime/bash-match-facts.js +0 -196
- package/dist/runtime/bash-match-facts.js.map +0 -1
- package/dist/runtime/bash-match-registry.d.ts +0 -112
- package/dist/runtime/bash-match-registry.js +0 -406
- package/dist/runtime/bash-match-registry.js.map +0 -1
- package/dist/runtime/bash-prefix-parse.d.ts +0 -31
- package/dist/runtime/bash-prefix-parse.js +0 -576
- package/dist/runtime/bash-prefix-parse.js.map +0 -1
- package/dist/runtime/command-normalize.d.ts +0 -658
- package/dist/runtime/command-normalize.js +0 -2410
- package/dist/runtime/command-normalize.js.map +0 -1
- package/dist/runtime/deletion-target-resolve.d.ts +0 -28
- package/dist/runtime/deletion-target-resolve.js +0 -1078
- package/dist/runtime/deletion-target-resolve.js.map +0 -1
- package/dist/runtime/destructive-shell-floor.d.ts +0 -19
- package/dist/runtime/destructive-shell-floor.js +0 -611
- package/dist/runtime/destructive-shell-floor.js.map +0 -1
- package/dist/runtime/environment-resolver.d.ts +0 -36
- package/dist/runtime/environment-resolver.js +0 -138
- package/dist/runtime/environment-resolver.js.map +0 -1
- package/dist/runtime/git-context.d.ts +0 -201
- package/dist/runtime/git-context.js +0 -422
- package/dist/runtime/git-context.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -12
- package/dist/runtime/index.js +0 -13
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/intercept.d.ts +0 -623
- package/dist/runtime/intercept.js +0 -1384
- package/dist/runtime/intercept.js.map +0 -1
- package/dist/runtime/kube-context.d.ts +0 -16
- package/dist/runtime/kube-context.js +0 -63
- package/dist/runtime/kube-context.js.map +0 -1
- package/dist/runtime/kubectl-target-parse.d.ts +0 -31
- package/dist/runtime/kubectl-target-parse.js +0 -249
- package/dist/runtime/kubectl-target-parse.js.map +0 -1
- package/dist/runtime/ledger-add.d.ts +0 -16
- package/dist/runtime/ledger-add.js +0 -150
- package/dist/runtime/ledger-add.js.map +0 -1
- package/dist/runtime/ledger-writer.d.ts +0 -27
- package/dist/runtime/ledger-writer.js +0 -46
- package/dist/runtime/ledger-writer.js.map +0 -1
- package/dist/runtime/pause-sentinel.d.ts +0 -60
- package/dist/runtime/pause-sentinel.js +0 -156
- package/dist/runtime/pause-sentinel.js.map +0 -1
- package/dist/runtime/pending-approval.d.ts +0 -23
- package/dist/runtime/pending-approval.js +0 -67
- package/dist/runtime/pending-approval.js.map +0 -1
- package/dist/runtime/read-only-bash.d.ts +0 -141
- package/dist/runtime/read-only-bash.js +0 -2204
- package/dist/runtime/read-only-bash.js.map +0 -1
- package/dist/runtime/recovery-git-commit.d.ts +0 -22
- package/dist/runtime/recovery-git-commit.js +0 -284
- package/dist/runtime/recovery-git-commit.js.map +0 -1
- package/dist/runtime/reject-malformed-session-id.d.ts +0 -8
- package/dist/runtime/reject-malformed-session-id.js +0 -16
- package/dist/runtime/reject-malformed-session-id.js.map +0 -1
- package/dist/runtime/risk-classifier.d.ts +0 -38
- package/dist/runtime/risk-classifier.js +0 -311
- package/dist/runtime/risk-classifier.js.map +0 -1
- package/dist/runtime/session-id.d.ts +0 -113
- package/dist/runtime/session-id.js +0 -193
- package/dist/runtime/session-id.js.map +0 -1
- package/dist/runtime/shell-word.d.ts +0 -62
- package/dist/runtime/shell-word.js +0 -410
- package/dist/runtime/shell-word.js.map +0 -1
- package/dist/runtime/task-providers/agent-tasks.d.ts +0 -105
- package/dist/runtime/task-providers/agent-tasks.js +0 -247
- package/dist/runtime/task-providers/agent-tasks.js.map +0 -1
- package/dist/runtime/when-eval.d.ts +0 -62
- package/dist/runtime/when-eval.js +0 -212
- package/dist/runtime/when-eval.js.map +0 -1
- package/dist/runtime/workflow-policies.d.ts +0 -207
- package/dist/runtime/workflow-policies.js +0 -596
- package/dist/runtime/workflow-policies.js.map +0 -1
- package/dist/schema/audit.d.ts +0 -71
- package/dist/schema/audit.js +0 -32
- package/dist/schema/audit.js.map +0 -1
- package/dist/schema/doctor.d.ts +0 -25
- package/dist/schema/doctor.js +0 -23
- package/dist/schema/doctor.js.map +0 -1
- package/dist/schema/environments.d.ts +0 -215
- package/dist/schema/environments.js +0 -101
- package/dist/schema/environments.js.map +0 -1
- package/dist/schema/extract.d.ts +0 -9
- package/dist/schema/extract.js +0 -86
- package/dist/schema/extract.js.map +0 -1
- package/dist/schema/permission-profiles.d.ts +0 -2292
- package/dist/schema/permission-profiles.js +0 -60
- package/dist/schema/permission-profiles.js.map +0 -1
- package/dist/schema/policies.d.ts +0 -974
- package/dist/schema/policies.js +0 -298
- package/dist/schema/policies.js.map +0 -1
- package/dist/schema/requires.d.ts +0 -131
- package/dist/schema/requires.js +0 -88
- package/dist/schema/requires.js.map +0 -1
- package/dist/schema/risk.d.ts +0 -144
- package/dist/schema/risk.js +0 -194
- package/dist/schema/risk.js.map +0 -1
- package/dist/schema/session-start-preflight.d.ts +0 -10
- package/dist/schema/session-start-preflight.js +0 -106
- package/dist/schema/session-start-preflight.js.map +0 -1
- package/dist/schema/stale-base-check.d.ts +0 -18
- package/dist/schema/stale-base-check.js +0 -37
- package/dist/schema/stale-base-check.js.map +0 -1
- package/dist/schema/toolchain-parity.d.ts +0 -21
- package/dist/schema/toolchain-parity.js +0 -48
- package/dist/schema/toolchain-parity.js.map +0 -1
- package/dist/schema/workflows.d.ts +0 -519
- package/dist/schema/workflows.js +0 -81
- package/dist/schema/workflows.js.map +0 -1
- package/scripts/runtime-reality-docker-probe.mjs +0 -71
|
@@ -4,9 +4,34 @@ import * as path from "node:path";
|
|
|
4
4
|
import { parse as parseTomlDocument, TomlError } from "smol-toml";
|
|
5
5
|
import { atomicWriteFile } from "../../io/atomic-write.js";
|
|
6
6
|
import { EX_FAIL, HarnessExitError } from "../exit-codes.js";
|
|
7
|
+
// Import cycle: codex-snapshot.ts imports this module too. It is safe because
|
|
8
|
+
// neither module touches the other's bindings at top level; they are used only
|
|
9
|
+
// inside function bodies. Keep it that way (no top-level use of these three).
|
|
10
|
+
import { codexConfigFlag, listCodexSnapshots, nameInstallConfig, readCodexSnapshot, retireCodexSnapshot, } from "../gate/codex-snapshot.js";
|
|
11
|
+
import { kernelEntry, linkChain, walkLinkChain } from "../gate/link-chain.js";
|
|
12
|
+
import { namesSameEntry, sha256Hex } from "../gate/snapshot.js";
|
|
7
13
|
export const CODEX_MANAGED_SOURCE_PREFIX = "# Harness Codex hook wiring.";
|
|
8
14
|
export const CODEX_MANAGED_BEGIN = "# BEGIN harness-managed codex hooks";
|
|
9
15
|
export const CODEX_MANAGED_END = "# END harness-managed codex hooks";
|
|
16
|
+
/**
|
|
17
|
+
* The comment line the installer writes directly under the BEGIN fence,
|
|
18
|
+
* followed by the block's generation: the sha256 of the generated content
|
|
19
|
+
* the block holds (`codexBlockGeneration`). `harness gate disable --runtime
|
|
20
|
+
* codex` records it in its snapshot, and a snapshot whose recorded generation
|
|
21
|
+
* differs from the block's is one a later install re-rendered the block over:
|
|
22
|
+
* it is retired as superseded and never applied, wherever it sits and whatever
|
|
23
|
+
* backup files exist. A comment adds, removes and reorders no hook entry, so
|
|
24
|
+
* Codex keeps every hook at the position its trust state was recorded for.
|
|
25
|
+
* The same content renders the same line, so an install of an unchanged
|
|
26
|
+
* manifest stays a no-op.
|
|
27
|
+
*/
|
|
28
|
+
export const CODEX_BLOCK_GENERATION_PREFIX = "# harness block generation: ";
|
|
29
|
+
const BLOCK_GENERATION_LINE_RE = /^# harness block generation: ([0-9a-f]{64})$/;
|
|
30
|
+
/** The generation of a block holding `renderedContent` (the generated
|
|
31
|
+
* content as the block holds it, without its trailing newline). */
|
|
32
|
+
function codexBlockGeneration(renderedContent) {
|
|
33
|
+
return sha256Hex(renderedContent);
|
|
34
|
+
}
|
|
10
35
|
/**
|
|
11
36
|
* Thrown instead of a plain `Error` when the install refuses rather than
|
|
12
37
|
* guesses (a duplicate/moved BEGIN marker, or a foreign table wedged
|
|
@@ -1159,10 +1184,12 @@ function ensureTrailingNewline(s) {
|
|
|
1159
1184
|
return s.endsWith("\n") ? s : `${s}\n`;
|
|
1160
1185
|
}
|
|
1161
1186
|
function buildManagedBlock(generatedContent, generatedPath) {
|
|
1187
|
+
const rendered = ensureTrailingNewline(generatedContent).trimEnd();
|
|
1162
1188
|
return [
|
|
1163
1189
|
`${CODEX_MANAGED_SOURCE_PREFIX} Generated source: ${generatedPath}`,
|
|
1164
1190
|
CODEX_MANAGED_BEGIN,
|
|
1165
|
-
|
|
1191
|
+
`${CODEX_BLOCK_GENERATION_PREFIX}${codexBlockGeneration(rendered)}`,
|
|
1192
|
+
rendered,
|
|
1166
1193
|
CODEX_MANAGED_END,
|
|
1167
1194
|
"",
|
|
1168
1195
|
].join("\n");
|
|
@@ -1391,40 +1418,6 @@ export function assertConfigSemanticInvariant(currentContent, nextContent, confi
|
|
|
1391
1418
|
"(if one exists), or file an issue with the config shape that triggered this.", configPath);
|
|
1392
1419
|
}
|
|
1393
1420
|
}
|
|
1394
|
-
/**
|
|
1395
|
-
* Follows a dangling link chain hop by hop with `readlink` and returns the
|
|
1396
|
-
* first path in it that does not exist, so a dangling refusal names the
|
|
1397
|
-
* missing file rather than the first hop (which may be an existing
|
|
1398
|
-
* intermediate link). Each relative link text is resolved against the
|
|
1399
|
-
* physical directory of the link holding it, as the kernel does. Returns
|
|
1400
|
-
* undefined when the chain cannot be walked (it changed under us, or a
|
|
1401
|
-
* hop is not readable); the caller then words the refusal generically.
|
|
1402
|
-
*/
|
|
1403
|
-
function missingEndOfLinkChain(start) {
|
|
1404
|
-
const MAX_HOPS = 40;
|
|
1405
|
-
let current = start;
|
|
1406
|
-
for (let hop = 0; hop < MAX_HOPS; hop++) {
|
|
1407
|
-
let next;
|
|
1408
|
-
try {
|
|
1409
|
-
const linkText = fs.readlinkSync(current);
|
|
1410
|
-
next = path.resolve(fs.realpathSync(path.dirname(current)), linkText);
|
|
1411
|
-
}
|
|
1412
|
-
catch {
|
|
1413
|
-
return undefined;
|
|
1414
|
-
}
|
|
1415
|
-
let nextStat;
|
|
1416
|
-
try {
|
|
1417
|
-
nextStat = fs.lstatSync(next);
|
|
1418
|
-
}
|
|
1419
|
-
catch (err) {
|
|
1420
|
-
return err.code === "ENOENT" ? next : undefined;
|
|
1421
|
-
}
|
|
1422
|
-
if (!nextStat.isSymbolicLink())
|
|
1423
|
-
return undefined;
|
|
1424
|
-
current = next;
|
|
1425
|
-
}
|
|
1426
|
-
return undefined;
|
|
1427
|
-
}
|
|
1428
1421
|
/**
|
|
1429
1422
|
* Resolves a symlinked config path to the regular file it points at (task
|
|
1430
1423
|
* 1637fbc8). `atomicWriteFile` renames a temp file over its destination,
|
|
@@ -1433,9 +1426,13 @@ function missingEndOfLinkChain(start) {
|
|
|
1433
1426
|
* resolved target instead keeps the link intact. A non-symlink path
|
|
1434
1427
|
* (including a missing one) is returned unchanged. A dangling link, an
|
|
1435
1428
|
* unresolvable chain (a loop, a permission error) or a link to anything
|
|
1436
|
-
* other than a regular file is refused before anything is written.
|
|
1429
|
+
* other than a regular file is refused before anything is written. The
|
|
1430
|
+
* chain is walked as the kernel walks it (`walkLinkChain`): a `..` after a
|
|
1431
|
+
* directory link climbs out of the directory that link leads to, so the file
|
|
1432
|
+
* written is the one a read through the path gives. The path itself is taken
|
|
1433
|
+
* as given; a caller passes a spelling with `..` through `kernelEntry` first.
|
|
1437
1434
|
*/
|
|
1438
|
-
function resolveConfigSymlink(requestedPath) {
|
|
1435
|
+
export function resolveConfigSymlink(requestedPath) {
|
|
1439
1436
|
let linkStat;
|
|
1440
1437
|
try {
|
|
1441
1438
|
linkStat = fs.lstatSync(requestedPath);
|
|
@@ -1448,24 +1445,41 @@ function resolveConfigSymlink(requestedPath) {
|
|
|
1448
1445
|
}
|
|
1449
1446
|
if (!linkStat.isSymbolicLink())
|
|
1450
1447
|
return requestedPath;
|
|
1451
|
-
|
|
1448
|
+
// The gate's link walker decides where the chain ends, resolving every hop
|
|
1449
|
+
// as the kernel does. The JavaScript realpath folds `d/..` before it looks at
|
|
1450
|
+
// `d`: on its own it would call a link that reaches a file dangling, refuse
|
|
1451
|
+
// one the kernel resolves, or resolve one that reaches nothing to another
|
|
1452
|
+
// file. The refusal names the end of the chain, not the first hop (which may
|
|
1453
|
+
// be an existing link).
|
|
1454
|
+
const walked = walkLinkChain(requestedPath);
|
|
1455
|
+
if (walked.end === "dangling") {
|
|
1456
|
+
throw new CodexInstallRefusalError(`Codex config ${requestedPath} is a dangling symlink (its link chain ends at ` +
|
|
1457
|
+
`${walked.chain[walked.chain.length - 1]}, which does not exist); refusing to install, ` +
|
|
1458
|
+
`nothing was written. Create the link's target file (or point the link at an ` +
|
|
1459
|
+
`existing config) and re-run.`, requestedPath);
|
|
1460
|
+
}
|
|
1461
|
+
const cannotResolve = (cause) => new CodexInstallRefusalError(`Codex config ${requestedPath} is a symlink that cannot be resolved (${cause}); ` +
|
|
1462
|
+
`refusing to install, nothing was written. Fix the link chain and re-run.`, requestedPath);
|
|
1463
|
+
// The kernel's own lookup of the path is what Codex reads through.
|
|
1464
|
+
let read;
|
|
1452
1465
|
try {
|
|
1453
|
-
|
|
1466
|
+
read = fs.statSync(requestedPath);
|
|
1454
1467
|
}
|
|
1455
1468
|
catch (err) {
|
|
1456
1469
|
const e = err;
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1470
|
+
throw cannotResolve(`${e.code ?? "error"}: ${e.message}`);
|
|
1471
|
+
}
|
|
1472
|
+
if (walked.end !== "target")
|
|
1473
|
+
throw cannotResolve(`the link chain ends in a ${walked.end}`);
|
|
1474
|
+
const resolved = walked.chain[walked.chain.length - 1] ?? requestedPath;
|
|
1475
|
+
const atEnd = fs.statSync(resolved);
|
|
1476
|
+
// Defence in depth: the walker and the kernel have to agree on the file, and
|
|
1477
|
+
// a disagreement of any kind (a walker defect, a platform difference in how
|
|
1478
|
+
// a text is read) would otherwise write a file Codex never reads.
|
|
1479
|
+
if (read.dev !== atEnd.dev || read.ino !== atEnd.ino) {
|
|
1480
|
+
throw cannotResolve(`a read through it reaches another file than ${resolved}`);
|
|
1481
|
+
}
|
|
1482
|
+
if (!atEnd.isFile()) {
|
|
1469
1483
|
throw new CodexInstallRefusalError(`Codex config ${requestedPath} is a symlink to ${resolved}, which is not a regular ` +
|
|
1470
1484
|
`file; refusing to install, nothing was written. Point the link at a config file and re-run.`, requestedPath);
|
|
1471
1485
|
}
|
|
@@ -1729,8 +1743,24 @@ function assertKeptHookTablesAreOperatorOwned(kept, currentContent, generatedCon
|
|
|
1729
1743
|
}
|
|
1730
1744
|
}
|
|
1731
1745
|
export function planCodexConfigInstall(opts) {
|
|
1746
|
+
try {
|
|
1747
|
+
return planCodexConfigInstallUnnamed(opts);
|
|
1748
|
+
}
|
|
1749
|
+
catch (err) {
|
|
1750
|
+
// Every refusal below names the bare install command; the call's config
|
|
1751
|
+
// is added here, once, where it is known.
|
|
1752
|
+
if (err instanceof CodexInstallRefusalError && opts.configPath !== undefined) {
|
|
1753
|
+
throw new CodexInstallRefusalError(nameInstallConfig(err.message, kernelEntry(opts.configPath)), err.configPath);
|
|
1754
|
+
}
|
|
1755
|
+
throw err;
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
function planCodexConfigInstallUnnamed(opts) {
|
|
1732
1759
|
validateCodexManagedConfig(opts.generatedContent);
|
|
1733
|
-
|
|
1760
|
+
// A `..` after a directory link leads elsewhere than a lexical fold of the
|
|
1761
|
+
// spelling: every path built from it (the temp file, the backup) goes
|
|
1762
|
+
// through the directory the kernel reaches.
|
|
1763
|
+
const requestedPath = kernelEntry(opts.configPath ?? defaultCodexConfigPath(opts.homeDir));
|
|
1734
1764
|
const configPath = resolveConfigSymlink(requestedPath);
|
|
1735
1765
|
const linkPath = configPath !== requestedPath ? requestedPath : undefined;
|
|
1736
1766
|
const viaLink = linkPath !== undefined ? ` (via symlink ${linkPath})` : "";
|
|
@@ -1801,6 +1831,7 @@ export function planCodexConfigInstall(opts) {
|
|
|
1801
1831
|
return {
|
|
1802
1832
|
configPath,
|
|
1803
1833
|
...(linkPath !== undefined ? { linkPath } : {}),
|
|
1834
|
+
...(opts.configPath !== undefined ? { namedConfigPath: requestedPath } : {}),
|
|
1804
1835
|
generatedPath: opts.generatedPath,
|
|
1805
1836
|
currentContent,
|
|
1806
1837
|
nextContent,
|
|
@@ -1817,13 +1848,60 @@ export function planCodexConfigInstall(opts) {
|
|
|
1817
1848
|
function timestampForBackup(now) {
|
|
1818
1849
|
return now.toISOString().replace(/[:.]/g, "-");
|
|
1819
1850
|
}
|
|
1851
|
+
const INSTALL_BACKUP_STAMP_RE = /^(\d{4}-\d{2}-\d{2})T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z$/;
|
|
1852
|
+
/** The time of the newest install that rewrote the config at `filePath`, in
|
|
1853
|
+
* epoch milliseconds, read from the `<filePath>.harness-backup-<timestamp>`
|
|
1854
|
+
* files `writeCodexConfigInstall` leaves beside it (one per write of an
|
|
1855
|
+
* existing config), or null when there is none. `harness gate enable
|
|
1856
|
+
* --runtime codex` uses it to tell a snapshot taken before a re-install
|
|
1857
|
+
* (whose units that install re-rendered) from one taken after it. Reads the
|
|
1858
|
+
* directory only. */
|
|
1859
|
+
export function latestCodexInstallBackupMs(filePath) {
|
|
1860
|
+
return latestCodexInstallBackup(filePath)?.ms ?? null;
|
|
1861
|
+
}
|
|
1862
|
+
/** Like {@link latestCodexInstallBackupMs}, and also the path of the newest
|
|
1863
|
+
* backup file, so a message can name the install that dated a snapshot. A
|
|
1864
|
+
* backup whose name spells the file in another letter case or normalization
|
|
1865
|
+
* form (an install that ran through `Config.toml` for `config.toml` on a
|
|
1866
|
+
* filesystem that folds those) counts when both spellings are one entry
|
|
1867
|
+
* (`namesSameEntry`); on a filesystem that keeps them apart, another file's
|
|
1868
|
+
* backups never do. */
|
|
1869
|
+
export function latestCodexInstallBackup(filePath) {
|
|
1870
|
+
const dir = path.dirname(filePath);
|
|
1871
|
+
const base = path.basename(filePath);
|
|
1872
|
+
const marker = ".harness-backup-";
|
|
1873
|
+
let names;
|
|
1874
|
+
try {
|
|
1875
|
+
names = fs.readdirSync(dir);
|
|
1876
|
+
}
|
|
1877
|
+
catch {
|
|
1878
|
+
return null;
|
|
1879
|
+
}
|
|
1880
|
+
let latest = null;
|
|
1881
|
+
for (const name of names) {
|
|
1882
|
+
const at = name.lastIndexOf(marker);
|
|
1883
|
+
if (at <= 0)
|
|
1884
|
+
continue;
|
|
1885
|
+
const spelled = name.slice(0, at);
|
|
1886
|
+
if (!namesSameEntry(dir, spelled, base, { symlinks: true }))
|
|
1887
|
+
continue;
|
|
1888
|
+
const m = INSTALL_BACKUP_STAMP_RE.exec(name.slice(at + marker.length));
|
|
1889
|
+
if (m === null)
|
|
1890
|
+
continue;
|
|
1891
|
+
const ms = Date.parse(`${m[1]}T${m[2]}:${m[3]}:${m[4]}.${m[5]}Z`);
|
|
1892
|
+
if (!Number.isNaN(ms) && (latest === null || ms > latest.ms)) {
|
|
1893
|
+
latest = { ms, path: path.join(dir, name) };
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
return latest;
|
|
1897
|
+
}
|
|
1820
1898
|
/** The config holds operator secrets (API tokens under `[mcp_servers.*]`,
|
|
1821
1899
|
* Codex hook trust hashes); the install must never widen its permissions.
|
|
1822
1900
|
* Preserves the existing file's own mode for both the rewritten config and
|
|
1823
1901
|
* its backup, and falls back to `0o600` (owner read/write only) when
|
|
1824
1902
|
* creating a config that did not exist before this install, rather than
|
|
1825
1903
|
* `atomicWriteFile`'s own `0o644` default. */
|
|
1826
|
-
function existingFileMode(filePath) {
|
|
1904
|
+
export function existingFileMode(filePath) {
|
|
1827
1905
|
try {
|
|
1828
1906
|
return fs.statSync(filePath).mode & 0o777;
|
|
1829
1907
|
}
|
|
@@ -1834,28 +1912,325 @@ function existingFileMode(filePath) {
|
|
|
1834
1912
|
return 0o600;
|
|
1835
1913
|
}
|
|
1836
1914
|
}
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1915
|
+
/** Identity of a file as the filesystem sees it, so a snapshot's recorded
|
|
1916
|
+
* path (the link, the target, or a hard link) is matched to the config by
|
|
1917
|
+
* what it is, not by how it is spelled. */
|
|
1918
|
+
function fileIdentity(filePath) {
|
|
1919
|
+
try {
|
|
1920
|
+
const st = fs.statSync(filePath);
|
|
1921
|
+
return `${st.dev}:${st.ino}`;
|
|
1922
|
+
}
|
|
1923
|
+
catch {
|
|
1924
|
+
return null;
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
/** Whether `recorded` names the file `target` with identity `targetId`
|
|
1928
|
+
* (taken before the install replaced it): the same absolute path, or the
|
|
1929
|
+
* same device and inode, which covers a symlink and a hard link to it. */
|
|
1930
|
+
function namesFile(recorded, target, targetId) {
|
|
1931
|
+
if (path.resolve(recorded) === path.resolve(target))
|
|
1932
|
+
return true;
|
|
1933
|
+
const recordedId = fileIdentity(recorded);
|
|
1934
|
+
return targetId !== null && recordedId !== null && targetId === recordedId;
|
|
1935
|
+
}
|
|
1936
|
+
/** The live Codex gate snapshots, beside the requested path, beside every
|
|
1937
|
+
* further hop of its link chain and beside the target, that
|
|
1938
|
+
* were taken from the config an install is about to rewrite. Read before the
|
|
1939
|
+
* write: the write replaces the file, which changes its inode. A snapshot
|
|
1940
|
+
* that cannot be read is not matched; it is reported so the operator knows
|
|
1941
|
+
* the gate will refuse on it. */
|
|
1942
|
+
function findSnapshotsOfConfig(plan) {
|
|
1943
|
+
const requested = plan.linkPath ?? plan.configPath;
|
|
1944
|
+
const id = fileIdentity(plan.configPath);
|
|
1945
|
+
// A snapshot sits beside the spelling the gate was run through, and every
|
|
1946
|
+
// hop of the chain from the requested path to the target is such a spelling.
|
|
1947
|
+
// One directory under two spellings (a symlinked directory) is read once:
|
|
1948
|
+
// a snapshot found twice would be renamed once and then fail to rename.
|
|
1949
|
+
const dirs = [];
|
|
1950
|
+
const seenDirs = new Set();
|
|
1951
|
+
for (const spelled of [...linkChain(requested), plan.configPath]) {
|
|
1952
|
+
const dir = path.dirname(spelled);
|
|
1953
|
+
let physical = dir;
|
|
1954
|
+
try {
|
|
1955
|
+
physical = fs.realpathSync.native(dir);
|
|
1956
|
+
}
|
|
1957
|
+
catch {
|
|
1958
|
+
// A directory that cannot be resolved is compared by its spelling.
|
|
1959
|
+
}
|
|
1960
|
+
if (seenDirs.has(physical))
|
|
1961
|
+
continue;
|
|
1962
|
+
seenDirs.add(physical);
|
|
1963
|
+
// Listed as spelled, except that a `..` is taken through the directory the
|
|
1964
|
+
// kernel reaches: the listing joins names to the directory, which folds it.
|
|
1965
|
+
dirs.push(dir.split(path.sep).includes("..") ? physical : dir);
|
|
1966
|
+
}
|
|
1967
|
+
const matched = [];
|
|
1968
|
+
const unreadable = [];
|
|
1969
|
+
for (const dir of dirs) {
|
|
1970
|
+
for (const snapPath of listCodexSnapshots(dir)) {
|
|
1971
|
+
const read = readCodexSnapshot(snapPath);
|
|
1972
|
+
if (!read.ok) {
|
|
1973
|
+
unreadable.push(snapPath);
|
|
1974
|
+
continue;
|
|
1975
|
+
}
|
|
1976
|
+
const recorded = read.snapshot.configPath;
|
|
1977
|
+
if (namesFile(recorded, plan.configPath, id) || namesFile(recorded, requested, id))
|
|
1978
|
+
matched.push(snapPath);
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
return { matched, unreadable };
|
|
1982
|
+
}
|
|
1983
|
+
/**
|
|
1984
|
+
* Writes the install. A live gate snapshot of the config holds the hook
|
|
1985
|
+
* lines of the block this write replaces, so enabling it later would put an
|
|
1986
|
+
* outdated line back: every such snapshot (beside every hop of the requested
|
|
1987
|
+
* path's link chain and beside the target) is renamed to `*.superseded.json` right after the
|
|
1988
|
+
* write, whatever backup files exist. A rename that fails never fails the
|
|
1989
|
+
* install, which is already on disk: it is a warning (`snapshotWarnings`,
|
|
1990
|
+
* printed by the caller) naming the snapshot and the move-aside step. A
|
|
1991
|
+
* snapshot this cannot find (beside a link outside that chain) records the
|
|
1992
|
+
* block's generation marker, which this write changes when the content
|
|
1993
|
+
* changes, so `gate enable` and `gate disable` retire it on sight. The
|
|
1994
|
+
* backup-file dating in the gate stays as a further line of defence for a
|
|
1995
|
+
* snapshot without a marker (taken before the marker existed).
|
|
1996
|
+
*/
|
|
1997
|
+
export function writeCodexConfigInstall(planned, opts = {}) {
|
|
1998
|
+
if (!planned.changed)
|
|
1999
|
+
return { ...planned, written: false };
|
|
2000
|
+
fs.mkdirSync(path.dirname(planned.configPath), { recursive: true });
|
|
2001
|
+
// A config directory that did not exist at plan time, spelled with `..`
|
|
2002
|
+
// after a directory link, could not be resolved then (`kernelEntry` keeps
|
|
2003
|
+
// such a spelling). It exists now, so the paths built from the spelling (the
|
|
2004
|
+
// temp file, the snapshot listing) go through the directory the kernel
|
|
2005
|
+
// reaches instead of a lexical fold into another one.
|
|
2006
|
+
const plan = { ...planned, configPath: kernelEntry(planned.configPath) };
|
|
2007
|
+
// The summary was built from the plan-time spelling: name the path written.
|
|
2008
|
+
if (plan.configPath !== planned.configPath) {
|
|
2009
|
+
plan.summary = plan.summary.replace(planned.configPath, () => plan.configPath);
|
|
2010
|
+
}
|
|
1841
2011
|
const mode = existingFileMode(plan.configPath);
|
|
2012
|
+
const snapshots = findSnapshotsOfConfig(plan);
|
|
1842
2013
|
// Only back up a config that actually existed before this install (task
|
|
1843
2014
|
// 461ec064): a fresh install has nothing to protect, and writing a
|
|
1844
2015
|
// 0-byte backup for it misreported a write that never happened.
|
|
2016
|
+
let result;
|
|
1845
2017
|
if (!plan.configExisted) {
|
|
1846
2018
|
atomicWriteFile(plan.configPath, plan.nextContent, { mode });
|
|
1847
|
-
|
|
1848
|
-
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
2019
|
+
result = { ...plan, written: true };
|
|
2020
|
+
}
|
|
2021
|
+
else {
|
|
2022
|
+
// A symlinked config's backup sits beside the link (task 1637fbc8), not
|
|
2023
|
+
// beside the resolved target: the config holds secrets, and the target's
|
|
2024
|
+
// directory is typically a dotfiles git work tree where an untracked
|
|
2025
|
+
// backup is one `git add` away from being pushed. The backup is a fresh
|
|
2026
|
+
// file, so it need not share the target's filesystem; only the atomic
|
|
2027
|
+
// write of the target itself (temp file plus rename) must.
|
|
2028
|
+
const backupBase = plan.linkPath ?? plan.configPath;
|
|
2029
|
+
const backupPath = `${backupBase}.harness-backup-${timestampForBackup(opts.now ?? new Date())}`;
|
|
2030
|
+
atomicWriteFile(backupPath, plan.currentContent, { mode });
|
|
2031
|
+
atomicWriteFile(plan.configPath, plan.nextContent, { mode });
|
|
2032
|
+
result = { ...plan, backupPath, written: true };
|
|
2033
|
+
}
|
|
2034
|
+
const superseded = [];
|
|
2035
|
+
const warnings = snapshots.unreadable.map((p) => `the Codex gate snapshot ${p} cannot be read, so the install could not tell whether it belongs to ` +
|
|
2036
|
+
`this config; \`harness gate enable --runtime codex${codexConfigFlag(plan.namedConfigPath ?? null)}\` will refuse on it ` +
|
|
2037
|
+
"until you move it out of this directory.");
|
|
2038
|
+
for (const snapPath of snapshots.matched) {
|
|
2039
|
+
try {
|
|
2040
|
+
superseded.push(retireCodexSnapshot(snapPath, "superseded", (m) => new Error(m), "the config was installed, but "));
|
|
2041
|
+
}
|
|
2042
|
+
catch (err) {
|
|
2043
|
+
warnings.push(err.message);
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
if (superseded.length > 0)
|
|
2047
|
+
result.supersededSnapshots = superseded;
|
|
2048
|
+
if (warnings.length > 0) {
|
|
2049
|
+
result.snapshotWarnings = warnings;
|
|
2050
|
+
}
|
|
2051
|
+
return result;
|
|
2052
|
+
}
|
|
2053
|
+
const HOOK_UNIT_HEADER_RE = /^\[\[hooks\.([A-Za-z][A-Za-z0-9_]*)\]\]$/;
|
|
2054
|
+
/**
|
|
2055
|
+
* The harness-owned hook units of the fenced managed block in `text`, with
|
|
2056
|
+
* exact offsets, for `harness gate` (the operator's switch for a blocking
|
|
2057
|
+
* hook). It reuses the installer's own range scan (`findManagedRange`), so
|
|
2058
|
+
* the refusals that scan raises (a duplicate BEGIN marker, a foreign table
|
|
2059
|
+
* wedged inside the block) apply here unchanged, and adds the stricter
|
|
2060
|
+
* reading an edit needs: the block must be fenced by BEGIN and a closing END
|
|
2061
|
+
* marker line, every non-blank line inside it must be a comment or part of a
|
|
2062
|
+
* unit of the exact shape the generator writes, and no harness hook comment
|
|
2063
|
+
* may sit outside the block (`assertNoOrphanHarnessHookTable`). Anything else
|
|
2064
|
+
* refuses instead of guessing which bytes are harness-owned. Returns null
|
|
2065
|
+
* when the file holds no managed block. The block's generation marker is read
|
|
2066
|
+
* too, never required: a block without it reads as `generation: null`.
|
|
2067
|
+
* Reads only; the file is never touched.
|
|
2068
|
+
*/
|
|
2069
|
+
export function readCodexManagedHookUnits(text, configPath) {
|
|
2070
|
+
const range = findManagedRange(text, configPath);
|
|
2071
|
+
if (range === null)
|
|
2072
|
+
return null;
|
|
2073
|
+
const refuse = (why) => refuseHookBlockEdit(configPath, why);
|
|
2074
|
+
const beginLine = findMarkerLine(text, CODEX_MANAGED_BEGIN, "prefix", range.start, range.end);
|
|
2075
|
+
if (beginLine === -1) {
|
|
2076
|
+
return refuse(`the harness block has no '${CODEX_MANAGED_BEGIN}' fence (written by an older install); ` +
|
|
2077
|
+
"re-run `harness apply --runtime codex --install` once to rewrite it with fences");
|
|
2078
|
+
}
|
|
2079
|
+
assertNoOrphanHarnessHookTable(text, configPath, range);
|
|
2080
|
+
const endLine = lineStartAt(text, range.end - 1);
|
|
2081
|
+
// A drifted END (a foreign table between the last unit and the END marker)
|
|
2082
|
+
// ends the range before that table, so the range's last line is not the
|
|
2083
|
+
// END marker line and the same check refuses it.
|
|
2084
|
+
if (!createMarkerLineProbe(text)(endLine, CODEX_MANAGED_END, "whole")) {
|
|
2085
|
+
return refuse(`the block is not closed by a '${CODEX_MANAGED_END}' marker line right after its hook tables ` +
|
|
2086
|
+
"(move any table that sits between the last hook unit and the END marker to below the END " +
|
|
2087
|
+
"marker, or re-run `harness apply --runtime codex --install` to rewrite the block)");
|
|
2088
|
+
}
|
|
2089
|
+
const isMarkerLine = createMarkerLineProbe(text);
|
|
2090
|
+
const units = [];
|
|
2091
|
+
let pos = lineEndAfter(text, beginLine);
|
|
2092
|
+
const lineAt = (at) => text.slice(at, lineEndAfter(text, at)).trim();
|
|
2093
|
+
// Only the line right under BEGIN carries the generation; it is a comment,
|
|
2094
|
+
// so the scan below passes over it like the generated header.
|
|
2095
|
+
const generation = pos < endLine ? (BLOCK_GENERATION_LINE_RE.exec(lineAt(pos))?.[1] ?? null) : null;
|
|
2096
|
+
while (pos < endLine) {
|
|
2097
|
+
const trimmed = lineAt(pos);
|
|
2098
|
+
const isUnitComment = trimmed.startsWith("#") && isMarkerLine(pos, HARNESS_HOOK_COMMENT_PREFIX, "prefix");
|
|
2099
|
+
if (trimmed === "" || (trimmed.startsWith("#") && !isUnitComment)) {
|
|
2100
|
+
if (units.length > 0 && trimmed !== "") {
|
|
2101
|
+
return refuse(`line ${lineNumberAt(text, pos)} inside the block is a comment between hook units`);
|
|
2102
|
+
}
|
|
2103
|
+
pos = lineEndAfter(text, pos);
|
|
2104
|
+
continue;
|
|
2105
|
+
}
|
|
2106
|
+
if (!isUnitComment) {
|
|
2107
|
+
return refuse(`line ${lineNumberAt(text, pos)} inside the block is not part of a generated hook unit`);
|
|
2108
|
+
}
|
|
2109
|
+
const id = HOOK_ID_LINE_RE.exec(trimmed)?.[1];
|
|
2110
|
+
if (id === undefined) {
|
|
2111
|
+
return refuse(`the hook comment at line ${lineNumberAt(text, pos)} is not in the generated shape`);
|
|
2112
|
+
}
|
|
2113
|
+
const unitStart = pos;
|
|
2114
|
+
const body = [];
|
|
2115
|
+
let lastLineAt = pos;
|
|
2116
|
+
pos = lineEndAfter(text, pos);
|
|
2117
|
+
while (pos < endLine && lineAt(pos) !== "" && !lineAt(pos).startsWith("#")) {
|
|
2118
|
+
body.push(lineAt(pos));
|
|
2119
|
+
lastLineAt = pos;
|
|
2120
|
+
pos = lineEndAfter(text, pos);
|
|
2121
|
+
}
|
|
2122
|
+
units.push(parseHookUnit(id, body, unitStart, lastLineAt, text, refuse));
|
|
2123
|
+
}
|
|
2124
|
+
return { units, generation };
|
|
2125
|
+
}
|
|
2126
|
+
function refuseHookBlockEdit(configPath, why) {
|
|
2127
|
+
throw new CodexInstallRefusalError(`Codex config ${configPath}: ${why}; refusing to edit the harness-managed hook block. ` +
|
|
2128
|
+
"The file is untouched.", configPath);
|
|
2129
|
+
}
|
|
2130
|
+
function parseHookUnit(id, body, start, lastLineAt, text, refuse) {
|
|
2131
|
+
const where = `the hook unit at line ${lineNumberAt(text, start)}`;
|
|
2132
|
+
const header = HOOK_UNIT_HEADER_RE.exec(body[0] ?? "");
|
|
2133
|
+
const shapeOk = header !== null &&
|
|
2134
|
+
(body.length === 2 || (body.length === 3 && body[1].startsWith("matcher = "))) &&
|
|
2135
|
+
body[body.length - 1].startsWith("hooks = [");
|
|
2136
|
+
if (!shapeOk) {
|
|
2137
|
+
return refuse(`${where} is not the generated shape (header, optional matcher, hooks array)`);
|
|
2138
|
+
}
|
|
2139
|
+
let doc;
|
|
2140
|
+
try {
|
|
2141
|
+
doc = parseToml(body.join("\n"));
|
|
2142
|
+
}
|
|
2143
|
+
catch (err) {
|
|
2144
|
+
return refuse(`${where} does not parse as TOML (${describeTomlParseError(err)})`);
|
|
2145
|
+
}
|
|
2146
|
+
const event = header[1];
|
|
2147
|
+
const hooksTable = isTomlTable(doc) ? doc.hooks : undefined;
|
|
2148
|
+
const entries = isTomlTable(hooksTable) ? hooksTable[event] : undefined;
|
|
2149
|
+
const entry = Array.isArray(entries) && entries.length === 1 ? entries[0] : undefined;
|
|
2150
|
+
if (!isTomlTable(entry) || !Array.isArray(entry.hooks)) {
|
|
2151
|
+
return refuse(`${where} does not define one ${event} entry with a hooks array`);
|
|
2152
|
+
}
|
|
2153
|
+
const matcher = entry.matcher;
|
|
2154
|
+
if (matcher !== undefined && typeof matcher !== "string") {
|
|
2155
|
+
return refuse(`${where} has a matcher that is not a string`);
|
|
2156
|
+
}
|
|
2157
|
+
const commands = entry.hooks.flatMap((h) => isTomlTable(h) && typeof h.command === "string" ? [h.command] : []);
|
|
2158
|
+
const rawLine = text.slice(lastLineAt, lineEndAfter(text, lastLineAt));
|
|
2159
|
+
return {
|
|
2160
|
+
id,
|
|
2161
|
+
event,
|
|
2162
|
+
matcher: matcher ?? null,
|
|
2163
|
+
commands,
|
|
2164
|
+
disabled: entry.hooks.length === 0,
|
|
2165
|
+
start,
|
|
2166
|
+
hooksStart: lastLineAt + (rawLine.length - rawLine.trimStart().length),
|
|
2167
|
+
hooksEnd: lastLineAt + rawLine.trimEnd().length,
|
|
2168
|
+
};
|
|
2169
|
+
}
|
|
2170
|
+
/**
|
|
2171
|
+
* The safety net for a gate edit of the managed block. First the installer's
|
|
2172
|
+
* own semantic invariant (both documents parse, and everything outside the
|
|
2173
|
+
* hook event arrays is deep-equal), then the part that invariant leaves out
|
|
2174
|
+
* on purpose, compared entry by entry: per hook event the arrays have the
|
|
2175
|
+
* same length, every entry is deep-equal to its counterpart except exactly
|
|
2176
|
+
* `expected.counts[event]` entries, and each of those differs only in its
|
|
2177
|
+
* `hooks` array (emptied by a neutralise, filled again by a restore). So a
|
|
2178
|
+
* gate edit can neither drop, add or reorder an entry nor move a key from one
|
|
2179
|
+
* entry to another, and Codex keeps every other hook at the position its
|
|
2180
|
+
* trust state was recorded for.
|
|
2181
|
+
*/
|
|
2182
|
+
export function assertCodexHookEditInvariant(before, after, configPath, expected) {
|
|
2183
|
+
assertConfigSemanticInvariant(before, after, configPath);
|
|
2184
|
+
const eventArrays = (doc) => {
|
|
2185
|
+
const arrays = new Map();
|
|
2186
|
+
const hooks = isTomlTable(doc) ? doc.hooks : undefined;
|
|
2187
|
+
if (!isTomlTable(hooks))
|
|
2188
|
+
return arrays;
|
|
2189
|
+
for (const [key, value] of Object.entries(hooks)) {
|
|
2190
|
+
if (Array.isArray(value))
|
|
2191
|
+
arrays.set(key, value);
|
|
2192
|
+
}
|
|
2193
|
+
return arrays;
|
|
2194
|
+
};
|
|
2195
|
+
const same = (a, b) => firstDifferingKeyPath(a, b, []) === null;
|
|
2196
|
+
const withHooks = (entry, hooks) => isTomlTable(entry) ? { ...entry, hooks } : entry;
|
|
2197
|
+
const hooksOf = (entry) => isTomlTable(entry) ? entry.hooks : undefined;
|
|
2198
|
+
const emptied = (entry) => {
|
|
2199
|
+
const hooks = hooksOf(entry);
|
|
2200
|
+
return Array.isArray(hooks) && hooks.length === 0;
|
|
2201
|
+
};
|
|
2202
|
+
const filled = (entry) => {
|
|
2203
|
+
const hooks = hooksOf(entry);
|
|
2204
|
+
return Array.isArray(hooks) && hooks.length > 0;
|
|
2205
|
+
};
|
|
2206
|
+
const refuse = (event, why) => {
|
|
2207
|
+
throw new CodexInstallRefusalError(`Codex config ${configPath}: the gate edit would ${why} in the '${event}' hook entries; ` +
|
|
2208
|
+
"refusing to write. The file is untouched.", configPath);
|
|
2209
|
+
};
|
|
2210
|
+
const was = eventArrays(parseToml(before));
|
|
2211
|
+
const now = eventArrays(parseToml(after));
|
|
2212
|
+
for (const event of new Set([...was.keys(), ...now.keys(), ...Object.keys(expected.counts)])) {
|
|
2213
|
+
const a = was.get(event) ?? [];
|
|
2214
|
+
const b = now.get(event) ?? [];
|
|
2215
|
+
if (a.length !== b.length) {
|
|
2216
|
+
refuse(event, `change the number of entries from ${a.length} to ${b.length}`);
|
|
2217
|
+
}
|
|
2218
|
+
let changed = 0;
|
|
2219
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
2220
|
+
if (same(a[i], b[i]))
|
|
2221
|
+
continue;
|
|
2222
|
+
changed += 1;
|
|
2223
|
+
const relationHolds = expected.direction === "neutralise"
|
|
2224
|
+
? filled(a[i]) && emptied(b[i]) && same(withHooks(a[i], []), b[i])
|
|
2225
|
+
: emptied(a[i]) && filled(b[i]) && same(withHooks(b[i], []), a[i]);
|
|
2226
|
+
if (!relationHolds) {
|
|
2227
|
+
refuse(event, `change entry ${i} by more than its hooks array`);
|
|
2228
|
+
}
|
|
2229
|
+
}
|
|
2230
|
+
const want = expected.counts[event] ?? 0;
|
|
2231
|
+
if (changed !== want) {
|
|
2232
|
+
refuse(event, `change ${changed} entries, expected ${want}`);
|
|
2233
|
+
}
|
|
2234
|
+
}
|
|
1860
2235
|
}
|
|
1861
2236
|
//# sourceMappingURL=install-codex-config.js.map
|