@lannguyensi/harness 0.63.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 +90 -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 -338
- 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 -705
- 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 -378
- 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 +15 -2607
- 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 -243
- 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/register-gate-group.d.ts +5 -0
- 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 +5 -0
- package/dist/cli/register-operator-lifecycle.js +20 -0
- package/dist/cli/register-operator-lifecycle.js.map +1 -0
- 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-setup-group.d.ts +5 -0
- 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.d.ts +5 -0
- package/dist/cli/remove/register.js +25 -0
- package/dist/cli/remove/register.js.map +1 -0
- 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.d.ts +5 -0
- package/dist/cli/uninstall/register.js +171 -0
- package/dist/cli/uninstall/register.js.map +1 -0
- 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 -443
- package/dist/cli/delegate/index.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/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 -46
- package/dist/cli/dry-run.js +0 -250
- package/dist/cli/dry-run.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 -20
- package/dist/cli/explain-action.js +0 -27
- package/dist/cli/explain-action.js.map +0 -1
- package/dist/cli/explain-policy.d.ts +0 -135
- package/dist/cli/explain-policy.js +0 -266
- 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 -337
- 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 -1020
- 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 -108
- 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/resolve-env.d.ts +0 -32
- package/dist/cli/resolve-env.js +0 -47
- 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 -26
- package/dist/cli/test-risk.js +0 -34
- 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 -618
- 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 -93
- 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 -620
- package/dist/policy-packs/builtin/understanding-before-execution/persisted-reports.js +0 -1047
- 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 -1074
- 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 -494
- package/dist/runtime/intercept.js +0 -1313
- 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 -103
- package/dist/runtime/task-providers/agent-tasks.js +0 -245
- 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
|
@@ -1,399 +1,424 @@
|
|
|
1
|
-
// `harness pack hook branch-protection
|
|
2
|
-
// `branch-protection` policy pack.
|
|
1
|
+
// `harness pack hook branch-protection`: PreToolUse blocker for the
|
|
2
|
+
// `branch-protection` policy pack (task a4d8adc5).
|
|
3
3
|
//
|
|
4
|
-
// Receives
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// Receives the runtime's PreToolUse event JSON on stdin and refuses the tool
|
|
5
|
+
// call when a directory it writes into belongs to a repository whose
|
|
6
|
+
// checked-out branch is protected. The branch is git's own answer
|
|
7
|
+
// (`git -C <dir> symbolic-ref -q HEAD`, src/runtime/git-branch.ts); this hook
|
|
8
|
+
// never reads git's files itself.
|
|
7
9
|
//
|
|
8
|
-
//
|
|
10
|
+
// Every event is judged twice, and the hook refuses when either judgment
|
|
11
|
+
// refuses or cannot answer; it allows only when both allow. The as-written
|
|
12
|
+
// judgment runs first.
|
|
9
13
|
//
|
|
10
|
-
// 1.
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
+
// 1. As written: each path made absolute against the event cwd with `.` and
|
|
15
|
+
// `..` resolved on the text (`path.resolve`), symlinks left in the path;
|
|
16
|
+
// the presence walk runs on that text and git runs in that directory.
|
|
17
|
+
// Write, Edit, MultiEdit, NotebookEdit: the nearest existing directory
|
|
18
|
+
// holding the target path. Codex `apply_patch`: the same for every path
|
|
19
|
+
// named by an `*** Add File:`, `*** Update File:`, `*** Delete File:` or
|
|
20
|
+
// `*** Move to:` header line of the patch text in tool_input.patch,
|
|
21
|
+
// tool_input.input or a string tool_input, relative to the event cwd.
|
|
22
|
+
// Anything else, or a patch without a header there: the event cwd.
|
|
23
|
+
// 2. Physical, as the operating system resolves the path (symlinks
|
|
24
|
+
// followed, `..` taken from the directory reached so far), which is the
|
|
25
|
+
// directory `git -C` changes into. Write, Edit, MultiEdit, NotebookEdit:
|
|
26
|
+
// the nearest existing directory of the target path (a Write may create
|
|
27
|
+
// the directories in between), and, when the target is a symlink, the
|
|
28
|
+
// directory it leads to as well. Codex `apply_patch`: the same for every
|
|
29
|
+
// path named by a header line found in any string of the event (any
|
|
30
|
+
// field or array of tool_input, raw_input or input, and JSON text inside
|
|
31
|
+
// a string: the field Codex carries the patch in is not pinned). A
|
|
32
|
+
// relative path resolves against the event cwd and, when the tool input
|
|
33
|
+
// names a per-call `workdir` or `cwd`, against that as well. Anything
|
|
34
|
+
// else, or a patch without a header: the event cwd (and that per-call
|
|
35
|
+
// directory).
|
|
14
36
|
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
// tag to bless its own edit. The marker lives under
|
|
24
|
-
// `harness.generated/`, which Edit / Write / Bash are all gated from
|
|
25
|
-
// writing, so only a process the operator launched can produce it.
|
|
26
|
-
// The ack ledger row is still recorded for audit and surfaced in the
|
|
27
|
-
// diagnostics, but its presence alone never satisfies the gate.
|
|
37
|
+
// Decision, per directory: git names a protected branch (compared
|
|
38
|
+
// case-insensitively) -> refuse; git could not answer (any error, a timeout,
|
|
39
|
+
// git missing, an unexpected answer) -> refuse with one fixed sentence naming
|
|
40
|
+
// git's first stderr line; a detached HEAD, or no `.git` entry anywhere above
|
|
41
|
+
// the directory -> allow. A manifest that does not load refuses every call.
|
|
42
|
+
// Resolving the paths and every git call are bounded, together, from the
|
|
43
|
+
// hook's start and below the pack's hook budget (a hook the runtime kills at
|
|
44
|
+
// its budget is read as an allow): past the bound the hook refuses.
|
|
28
45
|
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
46
|
+
// Block contract per runtime: Claude Code reads a JSON deny envelope on
|
|
47
|
+
// stdout (exit 0); Codex reads exit 2 with the reason on stderr
|
|
48
|
+
// (`--runtime codex`). The agent-facing text names `git checkout -b` as the
|
|
49
|
+
// way forward and nothing else. A Claude Code block whose envelope cannot be
|
|
50
|
+
// written (the reader has gone, or the stream is closed) fails closed too:
|
|
51
|
+
// exit 2 with the reason on stderr, since exit 0 without an envelope is read
|
|
52
|
+
// as an allow.
|
|
35
53
|
import * as path from "node:path";
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import { resolveGeneratedDir } from "../../io/generated-dir.js";
|
|
39
|
-
import { resolveGitContext } from "../../runtime/git-context.js";
|
|
40
|
-
import { POLICY_DECISION_TYPE } from "../../io/ledger-record.js";
|
|
54
|
+
import { PACK_NAME, isProtectedBranch, resolveProtectedBranches, } from "../../policy-packs/builtin/branch-protection-runtime.js";
|
|
55
|
+
import { GIT_BRANCH_TIMEOUT_MS, PathBoundError, absolutePath, nearestExistingDirectory, nearestExistingDirectoryAsWritten, readBranchAt, resolveDirectory, writeTargetDirectories, } from "../../runtime/git-branch.js";
|
|
41
56
|
import { renderAgentFacing } from "../../runtime/agent-facing.js";
|
|
42
|
-
import {
|
|
57
|
+
import { boundUtf8 } from "../../runtime/bounded-text.js";
|
|
58
|
+
import { STDIO_DRAIN_TIMEOUT_MS, tolerateClosedStdio } from "../drain-stdio.js";
|
|
59
|
+
import { loadManifestOrInjected, parseConfigUx, pickString, readStdinChecked, } from "./hook-bootstrap.js";
|
|
43
60
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* Path-aware tools today: Write, Edit, MultiEdit, NotebookEdit.
|
|
61
|
+
* Bound on resolving the paths and on all git calls of one event together,
|
|
62
|
+
* in ms, counted from the moment the hook starts (the stdin read and the
|
|
63
|
+
* manifest load included), so neither a slow stdin nor a large event can
|
|
64
|
+
* push the hook past its budget.
|
|
50
65
|
*/
|
|
51
|
-
|
|
66
|
+
export const GIT_READ_DEADLINE_MS = 3000;
|
|
67
|
+
/** The runtimes whose block contract this hook speaks. */
|
|
68
|
+
export const BRANCH_PROTECTION_RUNTIMES = ["claude-code", "codex"];
|
|
69
|
+
const CODEX_EXIT_BLOCK = 2;
|
|
70
|
+
/** Target path of the Claude Code tools that write a single file. */
|
|
71
|
+
function singleTargetPath(toolName, toolInput) {
|
|
52
72
|
if (typeof toolInput !== "object" || toolInput === null)
|
|
53
73
|
return null;
|
|
54
74
|
const input = toolInput;
|
|
55
75
|
switch (toolName) {
|
|
56
76
|
case "Write":
|
|
57
77
|
case "Edit":
|
|
58
|
-
case "MultiEdit":
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
case "NotebookEdit": {
|
|
63
|
-
const np = input["notebook_path"];
|
|
64
|
-
return typeof np === "string" && np.length > 0 ? np : null;
|
|
65
|
-
}
|
|
78
|
+
case "MultiEdit":
|
|
79
|
+
return pickString(input["file_path"]) ?? null;
|
|
80
|
+
case "NotebookEdit":
|
|
81
|
+
return pickString(input["notebook_path"]) ?? null;
|
|
66
82
|
default:
|
|
67
83
|
return null;
|
|
68
84
|
}
|
|
69
85
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (e.content.startsWith(`${POLICY_DECISION_TYPE}:`))
|
|
91
|
-
continue;
|
|
92
|
-
if (e.content.includes(ACK_TAG_PREFIX)) {
|
|
93
|
-
hasAck = true;
|
|
94
|
-
if (ackContent === null)
|
|
95
|
-
ackContent = e.content;
|
|
96
|
-
continue;
|
|
86
|
+
/**
|
|
87
|
+
* Every string in `value`, in document order: objects and arrays are walked,
|
|
88
|
+
* and a string holding JSON text is parsed and walked too.
|
|
89
|
+
*/
|
|
90
|
+
function stringsIn(value) {
|
|
91
|
+
const out = [];
|
|
92
|
+
const stack = [value];
|
|
93
|
+
while (stack.length > 0) {
|
|
94
|
+
const v = stack.pop();
|
|
95
|
+
if (typeof v === "string") {
|
|
96
|
+
out.push(v);
|
|
97
|
+
const t = v.trim();
|
|
98
|
+
if (t.startsWith("{") || t.startsWith("[")) {
|
|
99
|
+
try {
|
|
100
|
+
stack.push(JSON.parse(t));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
/* not JSON text */
|
|
104
|
+
}
|
|
105
|
+
}
|
|
97
106
|
}
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
freshProducerContent = e.content;
|
|
107
|
+
else if (Array.isArray(v)) {
|
|
108
|
+
for (let i = v.length - 1; i >= 0; i -= 1)
|
|
109
|
+
stack.push(v[i]);
|
|
110
|
+
}
|
|
111
|
+
else if (typeof v === "object" && v !== null) {
|
|
112
|
+
const children = Object.values(v);
|
|
113
|
+
for (let i = children.length - 1; i >= 0; i -= 1)
|
|
114
|
+
stack.push(children[i]);
|
|
107
115
|
}
|
|
108
116
|
}
|
|
109
|
-
return
|
|
110
|
-
hasFreshProducer,
|
|
111
|
-
hasAck,
|
|
112
|
-
freshProducerContent,
|
|
113
|
-
ackContent,
|
|
114
|
-
totalEntries: entries.length,
|
|
115
|
-
degraded: null,
|
|
116
|
-
};
|
|
117
|
+
return out;
|
|
117
118
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
totalEntries: 0,
|
|
128
|
-
degraded: r.degraded,
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
return evaluateEntries(r, opts.now ?? new Date());
|
|
119
|
+
const PATCH_HEADER = /^\*\*\*\s*(?:Add File|Update File|Delete File|Move to):\s*(.+)$/;
|
|
120
|
+
/** The paths named by the file header lines of one text. */
|
|
121
|
+
function headerPaths(text) {
|
|
122
|
+
const out = [];
|
|
123
|
+
for (const raw of text.split("\n")) {
|
|
124
|
+
const m = PATCH_HEADER.exec(raw.trim());
|
|
125
|
+
const target = m?.[1]?.trim() ?? "";
|
|
126
|
+
if (target.length > 0)
|
|
127
|
+
out.push(target);
|
|
132
128
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
129
|
+
return out;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Every path an `apply_patch` call names in a file header line, read from
|
|
133
|
+
* every string of `value` (the whole event, or any part of it), each once.
|
|
134
|
+
*/
|
|
135
|
+
export function patchTargetPaths(value) {
|
|
136
|
+
return [...new Set(stringsIn(value).flatMap(headerPaths))];
|
|
137
|
+
}
|
|
138
|
+
/** The patch text the as-written judgment reads: tool_input.patch, tool_input.input or a string tool_input. */
|
|
139
|
+
function asWrittenPatchText(toolInput) {
|
|
140
|
+
if (typeof toolInput === "string")
|
|
141
|
+
return toolInput;
|
|
142
|
+
if (typeof toolInput !== "object" || toolInput === null)
|
|
143
|
+
return "";
|
|
144
|
+
const input = toolInput;
|
|
145
|
+
return pickString(input["patch"], input["input"]) ?? "";
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The directories an `apply_patch` call's relative paths resolve against:
|
|
149
|
+
* the event cwd, plus a per-call `workdir` or `cwd` named in tool_input,
|
|
150
|
+
* raw_input or input.
|
|
151
|
+
*/
|
|
152
|
+
function patchBaseDirectories(event, cwd) {
|
|
153
|
+
const bases = [cwd];
|
|
154
|
+
for (const holder of [event.tool_input, event.raw_input, event.input]) {
|
|
155
|
+
if (typeof holder !== "object" || holder === null || Array.isArray(holder))
|
|
156
|
+
continue;
|
|
157
|
+
const fields = holder;
|
|
158
|
+
for (const key of ["workdir", "cwd"]) {
|
|
159
|
+
const value = pickString(fields[key]);
|
|
160
|
+
if (value !== undefined)
|
|
161
|
+
bases.push(absolutePath(value, cwd));
|
|
162
|
+
}
|
|
142
163
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
164
|
+
return [...new Set(bases)];
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* The directories of the as-written judgment: each path made absolute
|
|
168
|
+
* against the event cwd with `.` and `..` resolved on the text, then its
|
|
169
|
+
* nearest existing directory with symlinks left in place.
|
|
170
|
+
*/
|
|
171
|
+
function asWrittenTargets(toolName, toolInput, cwd, res) {
|
|
172
|
+
const single = singleTargetPath(toolName, toolInput);
|
|
173
|
+
const paths = single !== null ? [single] : toolName === "apply_patch" ? [...new Set(headerPaths(asWrittenPatchText(toolInput)))] : [];
|
|
174
|
+
if (paths.length === 0)
|
|
175
|
+
return { source: "cwd", dirs: [nearestExistingDirectoryAsWritten(cwd, res)] };
|
|
176
|
+
const dirs = paths.map((p) => nearestExistingDirectoryAsWritten(path.dirname(path.resolve(cwd, p)), res));
|
|
177
|
+
return { source: single !== null ? "target" : "patch", dirs: [...new Set(dirs)] };
|
|
178
|
+
}
|
|
179
|
+
/** The directories of the physical judgment: where the operating system resolves each path. */
|
|
180
|
+
function checkTargets(toolName, event, cwd, res) {
|
|
181
|
+
const single = singleTargetPath(toolName, event.tool_input);
|
|
182
|
+
if (single !== null)
|
|
183
|
+
return { source: "target", dirs: writeTargetDirectories(single, cwd, res) };
|
|
184
|
+
if (toolName !== "apply_patch")
|
|
185
|
+
return { source: "cwd", dirs: [nearestExistingDirectory(cwd, res)] };
|
|
186
|
+
const bases = patchBaseDirectories(event, cwd);
|
|
187
|
+
const paths = patchTargetPaths(event);
|
|
188
|
+
if (paths.length === 0)
|
|
189
|
+
return { source: "cwd", dirs: [...new Set(bases.map((b) => nearestExistingDirectory(b, res)))] };
|
|
190
|
+
const dirs = paths.flatMap((p) => (path.isAbsolute(p) ? [cwd] : bases).flatMap((b) => writeTargetDirectories(p, b, res)));
|
|
191
|
+
return { source: "patch", dirs: [...new Set(dirs)] };
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Write `text` to `stream` and wait for the write to complete, for at most
|
|
195
|
+
* `timeoutMs`. The write counts as failed when the stream is already closed,
|
|
196
|
+
* when the completion callback carries an error, when the stream emits
|
|
197
|
+
* 'error' during the wait, or when it has closed by the time the wait ends.
|
|
198
|
+
* A wait that ends with the stream still open is a slow reader, not a failed
|
|
199
|
+
* write: the entry point's drain gives the rest of the text its own bounded
|
|
200
|
+
* wait.
|
|
201
|
+
*/
|
|
202
|
+
function writeAndAwait(stream, text, timeoutMs) {
|
|
203
|
+
const closedReason = () => {
|
|
204
|
+
const s = stream;
|
|
205
|
+
return s.destroyed === true || s.writable === false ? "stdout is closed" : undefined;
|
|
206
|
+
};
|
|
207
|
+
return new Promise((resolve) => {
|
|
208
|
+
const before = closedReason();
|
|
209
|
+
if (before !== undefined) {
|
|
210
|
+
resolve({ delivered: false, why: before });
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
let timer;
|
|
214
|
+
const onError = (err) => settle({ delivered: false, why: err.message });
|
|
215
|
+
const settle = (result) => {
|
|
216
|
+
clearTimeout(timer);
|
|
217
|
+
stream.removeListener("error", onError);
|
|
218
|
+
resolve(result);
|
|
152
219
|
};
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
220
|
+
stream.on("error", onError);
|
|
221
|
+
timer = setTimeout(() => {
|
|
222
|
+
const why = closedReason();
|
|
223
|
+
settle(why === undefined ? { delivered: true } : { delivered: false, why });
|
|
224
|
+
}, timeoutMs);
|
|
225
|
+
try {
|
|
226
|
+
stream.write(text, (err) => {
|
|
227
|
+
settle(err ? { delivered: false, why: err.message } : { delivered: true });
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
settle({ delivered: false, why: err instanceof Error ? err.message : String(err) });
|
|
232
|
+
}
|
|
164
233
|
});
|
|
165
|
-
if (result.kind === "degraded") {
|
|
166
|
-
return {
|
|
167
|
-
hasFreshProducer: false,
|
|
168
|
-
hasAck: false,
|
|
169
|
-
freshProducerContent: null,
|
|
170
|
-
ackContent: null,
|
|
171
|
-
totalEntries: 0,
|
|
172
|
-
degraded: result.reason,
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
return evaluateEntries(result.entries, opts.now ?? new Date());
|
|
176
234
|
}
|
|
177
|
-
function
|
|
178
|
-
// When the pack config declares `ux:`, the agent-facing surface
|
|
179
|
-
// becomes the plain-language `{ cannot, required, run }` shape and
|
|
180
|
-
// the legacy "branch-protection: refusing ..." vocabulary is
|
|
181
|
-
// suppressed. The stderr BLOCK diagnostic keeps the engine reason
|
|
182
|
-
// (`detail`) for operator audit. `${BRANCH}` / `${TOOL_NAME}` /
|
|
183
|
-
// `${SESSION_ID}` substitute against the pack runtime context.
|
|
184
|
-
let reasonText;
|
|
185
|
-
if (ux) {
|
|
186
|
-
reasonText = renderAgentFacing(ux, {
|
|
187
|
-
BRANCH: branch,
|
|
188
|
-
TOOL_NAME: toolName,
|
|
189
|
-
SESSION_ID: sessionId,
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
const minutes = Math.round(PRODUCER_FRESHNESS_MS / 60000);
|
|
194
|
-
reasonText =
|
|
195
|
-
`branch-protection: refusing ${toolName} on protected branch "${branch}". ` +
|
|
196
|
-
`${detail}\n` +
|
|
197
|
-
`To proceed, cut a feature branch and re-run the producer:\n` +
|
|
198
|
-
` git checkout -b <feature-slug>\n` +
|
|
199
|
-
` harness session-start branch-check\n` +
|
|
200
|
-
`Once the gate sees a fresh ${NON_PROTECTED_TAG_PREFIX} tag (within ${minutes}m), this tool call will succeed.\n` +
|
|
201
|
-
`\n` +
|
|
202
|
-
`Override (operator only): the operator runs, from an un-hooked shell:\n` +
|
|
203
|
-
` harness approve branch-protection --session ${sessionId}\n` +
|
|
204
|
-
`which writes the canonical approval marker the gate consults. ` +
|
|
205
|
-
`A \`${ACK_TAG_PREFIX}:<reason>\` ledger tag is no longer a sufficient override on its own ` +
|
|
206
|
-
`(it is agent-writable); the marker file under harness.generated/ is the trusted signal.\n` +
|
|
207
|
-
`\n` +
|
|
208
|
-
`Protected branches: ${protectedList.join(", ")}.`;
|
|
209
|
-
}
|
|
235
|
+
function claudeBlockEnvelope(reason) {
|
|
210
236
|
return JSON.stringify({
|
|
211
237
|
decision: "block",
|
|
212
|
-
reason
|
|
238
|
+
reason,
|
|
213
239
|
hookSpecificOutput: {
|
|
214
240
|
hookEventName: "PreToolUse",
|
|
215
241
|
permissionDecision: "deny",
|
|
216
|
-
permissionDecisionReason:
|
|
242
|
+
permissionDecisionReason: reason,
|
|
217
243
|
},
|
|
218
244
|
});
|
|
219
245
|
}
|
|
220
|
-
|
|
221
|
-
|
|
246
|
+
/** Agent-facing text for a protected branch: the ux block, or the default. */
|
|
247
|
+
function protectedBranchText(toolName, branch, dir, protectedList, ux, sessionId) {
|
|
248
|
+
if (ux) {
|
|
249
|
+
return renderAgentFacing(ux, { BRANCH: branch, TOOL_NAME: toolName, SESSION_ID: sessionId });
|
|
250
|
+
}
|
|
251
|
+
return (`branch-protection: refusing ${toolName} on protected branch "${branch}" (checked in ${dir}).\n` +
|
|
252
|
+
`Create a feature branch first, then retry:\n` +
|
|
253
|
+
` git checkout -b <feature>\n` +
|
|
254
|
+
`Protected branches: ${protectedList.join(", ")}.`);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* `harness pack hook branch-protection`. `opts.runtime` selects the block
|
|
258
|
+
* contract; an unknown value refuses with exit 2, which both runtimes read as
|
|
259
|
+
* a block.
|
|
260
|
+
*/
|
|
261
|
+
export async function runPackHookBranchProtectionCli(opts = {}) {
|
|
262
|
+
const now = opts.now ?? Date.now;
|
|
263
|
+
const startedAt = now();
|
|
222
264
|
const stdout = opts.stdout ?? process.stdout;
|
|
223
265
|
const stderr = opts.stderr ?? process.stderr;
|
|
266
|
+
// Before the first write of any kind: a reader that has gone makes a write
|
|
267
|
+
// fail with EPIPE, and the error is emitted while this function is still
|
|
268
|
+
// awaiting git, so a listener attached only at exit comes too late.
|
|
269
|
+
// The exit code is the decision's, whatever happens to the pipe.
|
|
270
|
+
tolerateClosedStdio([stdout, stderr]);
|
|
224
271
|
const note = (msg) => {
|
|
225
272
|
stderr.write(`harness pack hook branch-protection: ${msg}\n`);
|
|
226
273
|
};
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const
|
|
232
|
-
|
|
274
|
+
const allow = (diagnostic) => {
|
|
275
|
+
note(diagnostic);
|
|
276
|
+
return { exitCode: 0, blocked: false, diagnostic };
|
|
277
|
+
};
|
|
278
|
+
const runtime = opts.runtime ?? "claude-code";
|
|
279
|
+
if (!BRANCH_PROTECTION_RUNTIMES.includes(runtime)) {
|
|
280
|
+
// The value comes from the command line, so the diagnostic is bounded like every other block detail.
|
|
281
|
+
const diagnostic = boundUtf8(`BLOCK: unknown --runtime ${JSON.stringify(runtime)} (expected ${BRANCH_PROTECTION_RUNTIMES.join(" or ")}); refusing`);
|
|
282
|
+
note(diagnostic);
|
|
283
|
+
return { exitCode: CODEX_EXIT_BLOCK, blocked: true, diagnostic };
|
|
284
|
+
}
|
|
285
|
+
// Every block flows through here, so the detail and the agent text are cut
|
|
286
|
+
// to a fixed size once, whatever they embed (a manifest parse error grows
|
|
287
|
+
// with the manifest). The envelope is built from the cut text with
|
|
288
|
+
// JSON.stringify, so the cut cannot break the JSON.
|
|
289
|
+
const block = async (detail, agentText) => {
|
|
290
|
+
const diagnostic = boundUtf8(`BLOCK: ${detail}`);
|
|
291
|
+
const bounded = boundUtf8(agentText);
|
|
292
|
+
note(diagnostic);
|
|
293
|
+
if (runtime === "codex") {
|
|
294
|
+
stderr.write(`${bounded}\n`);
|
|
295
|
+
return { exitCode: CODEX_EXIT_BLOCK, blocked: true, diagnostic };
|
|
296
|
+
}
|
|
297
|
+
const written = await writeAndAwait(stdout, `${claudeBlockEnvelope(bounded)}\n`, STDIO_DRAIN_TIMEOUT_MS);
|
|
298
|
+
if (written.delivered)
|
|
299
|
+
return { exitCode: 0, blocked: true, diagnostic };
|
|
300
|
+
// Exit 0 without the envelope would be read as an allow, so the block
|
|
301
|
+
// falls back to the exit code both runtimes read as one.
|
|
302
|
+
try {
|
|
303
|
+
stderr.write(`harness pack hook branch-protection: the block envelope could not be written to stdout (${written.why}); ` +
|
|
304
|
+
`exiting ${CODEX_EXIT_BLOCK} so the refusal still counts as a block.\n${bounded}\n`);
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
// best effort: stderr may be gone as well; the exit code carries the decision
|
|
308
|
+
}
|
|
309
|
+
return { exitCode: CODEX_EXIT_BLOCK, blocked: true, diagnostic };
|
|
310
|
+
};
|
|
311
|
+
// A read that timed out never received the whole event, so nothing can be
|
|
312
|
+
// judged: refuse (fail closed).
|
|
313
|
+
const read = await readStdinChecked(opts.stdin ?? process.stdin);
|
|
314
|
+
if (read.timedOut) {
|
|
315
|
+
const reason = `stdin timeout: no complete event arrived and closed on stdin within ${read.idleTimeoutMs} ms, ` +
|
|
316
|
+
`so branch-protection cannot judge the tool call and refuses it (fail closed). Retry the tool call.`;
|
|
317
|
+
return await block(reason, reason);
|
|
318
|
+
}
|
|
319
|
+
let parsed;
|
|
233
320
|
try {
|
|
234
|
-
|
|
321
|
+
parsed = JSON.parse(read.text);
|
|
235
322
|
}
|
|
236
323
|
catch {
|
|
237
|
-
|
|
324
|
+
parsed = undefined;
|
|
238
325
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
// way.
|
|
243
|
-
if (checkHookPause("branch-protection", stderr, opts).paused) {
|
|
244
|
-
const diagnostic = "harness paused; branch-protection allowing without evaluating.";
|
|
245
|
-
return { exitCode: 0, blocked: false, diagnostic };
|
|
326
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
327
|
+
const detail = "the event on stdin is not a JSON object";
|
|
328
|
+
return await block(detail, `branch-protection: refusing the tool call: ${detail}, so it cannot be judged.`);
|
|
246
329
|
}
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
? opts.cwd
|
|
254
|
-
: typeof event.cwd === "string" && event.cwd.length > 0
|
|
255
|
-
? event.cwd
|
|
256
|
-
: process.cwd();
|
|
257
|
-
// Load manifest to resolve the protected-branches list AND the
|
|
258
|
-
// grounding-mcp wiring. A manifest load failure forces BLOCK with a
|
|
259
|
-
// clear hint — we can't know if the gate should fire if we can't
|
|
260
|
-
// read its config.
|
|
261
|
-
// Resolved manifest path feeds the harness.generated/ lookup below (the
|
|
262
|
-
// override-marker directory). An injected manifest (tests) has no
|
|
263
|
-
// on-disk path, so `generatedDir` falls back to opts.generatedDir.
|
|
330
|
+
const event = parsed;
|
|
331
|
+
const toolName = pickString(event.tool_name, event.tool) ?? "(unknown)";
|
|
332
|
+
const sessionId = pickString(event.session_id) ?? "";
|
|
333
|
+
const cwdText = pickString(opts.cwd, event.cwd) ?? process.cwd();
|
|
334
|
+
// Without the manifest the gate cannot know whether it is enabled or what
|
|
335
|
+
// is protected, so a load failure refuses.
|
|
264
336
|
let manifest;
|
|
265
|
-
let manifestPath;
|
|
266
337
|
try {
|
|
267
|
-
({ manifest
|
|
338
|
+
({ manifest } = loadManifestOrInjected(opts, opts.manifest));
|
|
268
339
|
}
|
|
269
340
|
catch (err) {
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
note(diagnostic);
|
|
273
|
-
// Manifest didn't load, so no ux config to honour; legacy
|
|
274
|
-
// envelope is the only available surface here.
|
|
275
|
-
stdout.write(`${blockJson(toolName, "(unresolvable)", reason, DEFAULT_PROTECTED_BRANCHES, undefined, sessionId)}\n`);
|
|
276
|
-
return { exitCode: 0, blocked: true, diagnostic };
|
|
341
|
+
const detail = `the harness manifest could not be loaded (${err.message})`;
|
|
342
|
+
return await block(`${detail}; refusing on failsafe`, `branch-protection: refusing ${toolName}: ${detail}.`);
|
|
277
343
|
}
|
|
278
344
|
const pack = manifest.policy_packs.find((p) => p.name === PACK_NAME);
|
|
279
|
-
if (!pack)
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
return {
|
|
283
|
-
}
|
|
284
|
-
if (!pack.enabled) {
|
|
285
|
-
const diagnostic = `pack "${PACK_NAME}" is enabled:false, allowing`;
|
|
286
|
-
note(diagnostic);
|
|
287
|
-
return { exitCode: 0, blocked: false, diagnostic };
|
|
288
|
-
}
|
|
345
|
+
if (!pack)
|
|
346
|
+
return allow(`pack "${PACK_NAME}" not declared in manifest, allowing`);
|
|
347
|
+
if (!pack.enabled)
|
|
348
|
+
return allow(`pack "${PACK_NAME}" is enabled:false, allowing`);
|
|
289
349
|
const { branches: protectedList } = resolveProtectedBranches(pack);
|
|
290
350
|
const configUx = parseConfigUx(pack.config["ux"], stderr, "harness pack hook branch-protection");
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
})
|
|
353
|
-
: undefined);
|
|
354
|
-
// Best-effort audit echo of the now-untrusted ledger ack, appended to
|
|
355
|
-
// diagnostics so an operator chasing the gate can see the historic tag
|
|
356
|
-
// without it being mistaken for the thing that opened (or failed to
|
|
357
|
-
// open) the gate.
|
|
358
|
-
const ackEcho = check.hasAck
|
|
359
|
-
? ` [audit: ledger ${check.ackContent ?? ACK_TAG_PREFIX} present, no longer satisfies the gate]`
|
|
360
|
-
: "";
|
|
361
|
-
// Distinct audit note when the override marker FILE existed but failed
|
|
362
|
-
// signature verification (harness/f9485cc7) — missing/invalid signature,
|
|
363
|
-
// wrong alg, or a tampered payload — so it reads apart from the routine
|
|
364
|
-
// "no operator override marker" case below.
|
|
365
|
-
let markerForgedNote = "";
|
|
366
|
-
if (generatedDir !== undefined) {
|
|
367
|
-
const markerCheck = checkBranchProtectionMarker(generatedDir, sessionId);
|
|
368
|
-
if (markerCheck.matched) {
|
|
369
|
-
const diagnostic = `branch-protection override marker active (${markerCheck.detail}); allowing${ackEcho}`;
|
|
370
|
-
note(diagnostic);
|
|
371
|
-
return { exitCode: 0, blocked: false, diagnostic };
|
|
372
|
-
}
|
|
373
|
-
if (markerCheck.forged) {
|
|
374
|
-
markerForgedNote = ` [forged/unsigned override marker rejected: ${markerCheck.detail}]`;
|
|
351
|
+
const deadlineMs = opts.gitDeadlineMs ?? GIT_READ_DEADLINE_MS;
|
|
352
|
+
const perCallMs = opts.gitTimeoutMs ?? GIT_BRANCH_TIMEOUT_MS;
|
|
353
|
+
const deadline = startedAt + deadlineMs;
|
|
354
|
+
const bound = { overBound: () => now() >= deadline, memo: new Map() };
|
|
355
|
+
const asWritten = {
|
|
356
|
+
targets: (res) => asWrittenTargets(toolName, event.tool_input, path.resolve(cwdText), res),
|
|
357
|
+
at: (dir) => ({ kind: "path", path: dir }),
|
|
358
|
+
};
|
|
359
|
+
const physical = {
|
|
360
|
+
targets: (res) => checkTargets(toolName, event, absolutePath(cwdText), res),
|
|
361
|
+
at: resolveDirectory,
|
|
362
|
+
};
|
|
363
|
+
// Both judgments, the as-written one first: the hook allows only what both allow.
|
|
364
|
+
const judgments = [asWritten, physical];
|
|
365
|
+
// Each directory git ran in is read once per event.
|
|
366
|
+
const answers = new Map();
|
|
367
|
+
const sources = [];
|
|
368
|
+
const seen = [];
|
|
369
|
+
try {
|
|
370
|
+
for (const judgment of judgments) {
|
|
371
|
+
const targets = judgment.targets(bound);
|
|
372
|
+
if (!sources.includes(targets.source))
|
|
373
|
+
sources.push(targets.source);
|
|
374
|
+
for (const dir of targets.dirs) {
|
|
375
|
+
const remaining = deadline - now();
|
|
376
|
+
if (remaining <= 0) {
|
|
377
|
+
const detail = `the branch of ${dir} was not checked: the hook passed its ${deadlineMs} ms bound`;
|
|
378
|
+
return await block(detail, `branch-protection: refusing ${toolName}: git could not report the branch of ${dir} (${detail}).`);
|
|
379
|
+
}
|
|
380
|
+
const at = judgment.at(dir);
|
|
381
|
+
let branchRead;
|
|
382
|
+
if (at.kind === "error") {
|
|
383
|
+
branchRead = at;
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
const known = answers.get(at.path);
|
|
387
|
+
if (known !== undefined)
|
|
388
|
+
continue;
|
|
389
|
+
branchRead = await readBranchAt(at.path, {
|
|
390
|
+
...(opts.gitReader !== undefined ? { reader: opts.gitReader } : {}),
|
|
391
|
+
timeoutMs: Math.min(perCallMs, remaining),
|
|
392
|
+
});
|
|
393
|
+
answers.set(at.path, branchRead);
|
|
394
|
+
}
|
|
395
|
+
switch (branchRead.kind) {
|
|
396
|
+
case "error":
|
|
397
|
+
return await block(`git could not report the branch of ${dir}: ${branchRead.detail}`, `branch-protection: refusing ${toolName}: git could not report the branch of ${dir} (${branchRead.detail}).`);
|
|
398
|
+
case "branch":
|
|
399
|
+
if (isProtectedBranch(branchRead.name, protectedList)) {
|
|
400
|
+
return await block(`branch "${branchRead.name}" of ${dir} is protected (${protectedList.join(", ")})`, protectedBranchText(toolName, branchRead.name, dir, protectedList, configUx, sessionId));
|
|
401
|
+
}
|
|
402
|
+
seen.push(`${dir}: branch "${branchRead.name}" is not in the protected list (${protectedList.join(", ")})`);
|
|
403
|
+
break;
|
|
404
|
+
case "detached":
|
|
405
|
+
seen.push(`${dir}: detached HEAD`);
|
|
406
|
+
break;
|
|
407
|
+
case "outside":
|
|
408
|
+
seen.push(`${dir}: outside any git repository`);
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
375
412
|
}
|
|
376
413
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
414
|
+
catch (err) {
|
|
415
|
+
// Fail closed: a path that could not be resolved within the bound, or
|
|
416
|
+
// any other failure while judging, refuses.
|
|
417
|
+
const detail = err instanceof PathBoundError
|
|
418
|
+
? `the paths of the tool call were not resolved: the hook passed its ${deadlineMs} ms bound`
|
|
419
|
+
: `the tool call could not be judged (${err instanceof Error ? err.message : String(err)})`;
|
|
420
|
+
return await block(detail, `branch-protection: refusing ${toolName}: ${detail}.`);
|
|
381
421
|
}
|
|
382
|
-
|
|
383
|
-
? `ledger degraded (${check.degraded}); refusing on failsafe`
|
|
384
|
-
: `no fresh ${NON_PROTECTED_TAG_PREFIX} tag (${check.totalEntries} entries scanned) and no operator override marker${ackEcho}${markerForgedNote}`;
|
|
385
|
-
const diagnostic = `BLOCK — ${why}`;
|
|
386
|
-
note(diagnostic);
|
|
387
|
-
stdout.write(`${blockJson(toolName, branch, why, protectedList, configUx, sessionId)}\n`);
|
|
388
|
-
return { exitCode: 0, blocked: true, diagnostic };
|
|
389
|
-
}
|
|
390
|
-
/**
|
|
391
|
-
* `harness pack hook branch-protection`. A stdin read that times out is refused here
|
|
392
|
-
* instead of being handed to the gate as an empty or truncated event it would
|
|
393
|
-
* treat as malformed input (task 7dfdcaaf). The operator pause still wins;
|
|
394
|
-
* every other input runs the gate unchanged.
|
|
395
|
-
*/
|
|
396
|
-
export function runPackHookBranchProtectionCli(opts = {}) {
|
|
397
|
-
return runGateWithStdinRefusal(opts, (stderr) => checkHookPause("branch-protection", stderr, opts).paused, stdoutBlockRefusal("branch-protection"), runPackHookBranchProtectionCliInner);
|
|
422
|
+
return allow(`${sources.join("+")} ${seen.join("; ")}; allowing`);
|
|
398
423
|
}
|
|
399
424
|
//# sourceMappingURL=hook-branch-protection.js.map
|