harnery 0.38.0 → 0.40.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/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +32 -8
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +97 -6
- package/dist/commands/backup.d.ts +16 -0
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +239 -33
- package/dist/commands/browse.d.ts +8 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +466 -231
- package/dist/commands/diagnostics.d.ts.map +1 -1
- package/dist/commands/diagnostics.js +6 -3
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +20 -4
- package/dist/commands/qa-run.d.ts.map +1 -1
- package/dist/commands/qa-run.js +26 -3
- package/dist/commands/qa-status.d.ts.map +1 -1
- package/dist/commands/qa-status.js +7 -2
- package/dist/commands/resources.d.ts.map +1 -1
- package/dist/commands/resources.js +23 -3
- package/dist/commands/review-pack.d.ts.map +1 -1
- package/dist/commands/review-pack.js +98 -23
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +2 -2
- package/dist/core/adapters/profiles.d.ts +1 -1
- package/dist/core/agents/canonical-emit.d.ts +3 -2
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +2 -0
- package/dist/core/agents/cli.js +13 -6
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +5 -3
- package/dist/core/agents/live-lifecycle-v3.d.ts +2 -2
- package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.d.ts +7 -5
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +63 -8
- package/dist/core/agents/session-finalizer-v3.d.ts +2 -2
- package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.d.ts +3 -3
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +2 -1
- package/dist/core/agents/state/names.d.ts +35 -2
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +80 -5
- package/dist/core/agents/state/stale-sweep.d.ts +2 -1
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +23 -6
- package/dist/core/agents/turn-elapsed.d.ts +51 -0
- package/dist/core/agents/turn-elapsed.d.ts.map +1 -0
- package/dist/core/agents/turn-elapsed.js +91 -0
- package/dist/core/artifacts/activity.d.ts +14 -0
- package/dist/core/artifacts/activity.d.ts.map +1 -0
- package/dist/core/artifacts/activity.js +52 -0
- package/dist/core/artifacts/delivery-card.d.ts +39 -0
- package/dist/core/artifacts/delivery-card.d.ts.map +1 -0
- package/dist/core/artifacts/delivery-card.js +282 -0
- package/dist/core/artifacts/index.d.ts +42 -7
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +288 -76
- package/dist/core/artifacts/mutation-lock.d.ts +2 -0
- package/dist/core/artifacts/mutation-lock.d.ts.map +1 -0
- package/dist/core/artifacts/mutation-lock.js +91 -0
- package/dist/core/backup/host-snapshot.d.ts +18 -0
- package/dist/core/backup/host-snapshot.d.ts.map +1 -0
- package/dist/core/backup/host-snapshot.js +64 -0
- package/dist/core/config.d.ts +20 -5
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +44 -10
- package/dist/core/diagnostics/advice.d.ts +38 -3
- package/dist/core/diagnostics/advice.d.ts.map +1 -1
- package/dist/core/diagnostics/advice.js +103 -99
- package/dist/core/diagnostics/bundle.d.ts.map +1 -1
- package/dist/core/diagnostics/bundle.js +111 -47
- package/dist/core/diagnostics/comparison.d.ts.map +1 -1
- package/dist/core/diagnostics/comparison.js +3 -2
- package/dist/core/diagnostics/contract.d.ts +15 -31
- package/dist/core/diagnostics/contract.d.ts.map +1 -1
- package/dist/core/diagnostics/contract.js +2 -5
- package/dist/core/diagnostics/index.d.ts +2 -0
- package/dist/core/diagnostics/index.d.ts.map +1 -1
- package/dist/core/diagnostics/index.js +2 -0
- package/dist/core/diagnostics/pressure-contract.d.ts +260 -0
- package/dist/core/diagnostics/pressure-contract.d.ts.map +1 -0
- package/dist/core/diagnostics/pressure-contract.js +70 -0
- package/dist/core/diagnostics/pressure.d.ts +25 -0
- package/dist/core/diagnostics/pressure.d.ts.map +1 -0
- package/dist/core/diagnostics/pressure.js +1138 -0
- package/dist/core/diagnostics/replay.d.ts.map +1 -1
- package/dist/core/diagnostics/replay.js +90 -10
- package/dist/core/events/v3/adapter-id.d.ts +6 -0
- package/dist/core/events/v3/adapter-id.d.ts.map +1 -0
- package/dist/core/events/v3/adapter-id.js +7 -0
- package/dist/core/events/v3/archive-retention.d.ts.map +1 -1
- package/dist/core/events/v3/archive-retention.js +3 -2
- package/dist/core/events/v3/bootstrap.d.ts +41 -4
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +120 -17
- package/dist/core/events/v3/capabilities.d.ts +16 -9
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +37 -2
- package/dist/core/events/v3/capability-drift.d.ts +2 -2
- package/dist/core/events/v3/capability-drift.d.ts.map +1 -1
- package/dist/core/events/v3/control-witness.d.ts +48 -5
- package/dist/core/events/v3/control-witness.d.ts.map +1 -1
- package/dist/core/events/v3/control-witness.js +91 -36
- package/dist/core/events/v3/control.d.ts.map +1 -1
- package/dist/core/events/v3/control.js +22 -2
- package/dist/core/events/v3/index.d.ts +2 -1
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +2 -1
- package/dist/core/events/v3/live-feed.d.ts +7 -1
- package/dist/core/events/v3/live-feed.d.ts.map +1 -1
- package/dist/core/events/v3/live-feed.js +21 -3
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +10 -2
- package/dist/core/events/v3/producers/command-recorder.d.ts +2 -2
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/command-recorder.js +2 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +2 -2
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +2 -1
- package/dist/core/events/v3/producers/hook-base.d.ts +2 -2
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +15 -5
- package/dist/core/events/v3/producers/hook.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook.js +17 -4
- package/dist/core/events/v3/producers/intake.d.ts +4 -4
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +3 -2
- package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -1
- package/dist/core/events/v3/producers/producer-state-observer.js +2 -1
- package/dist/core/events/v3/producers/recorder.d.ts +16 -5
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +31 -9
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +10 -13
- package/dist/core/events/v3/runtime-build.d.ts.map +1 -1
- package/dist/core/events/v3/runtime-build.js +3 -2
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +2 -2
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/turn-telemetry.d.ts +2 -2
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.d.ts +16 -14
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +36 -38
- package/dist/core/hooks/backup-schedule.d.ts +34 -0
- package/dist/core/hooks/backup-schedule.d.ts.map +1 -0
- package/dist/core/hooks/backup-schedule.js +114 -0
- package/dist/core/hooks/cli.js +61 -18
- package/dist/core/hooks/codex-wsl-bridge.d.ts +2 -0
- package/dist/core/hooks/codex-wsl-bridge.d.ts.map +1 -1
- package/dist/core/hooks/codex-wsl-bridge.js +18 -4
- package/dist/core/hooks/index.d.ts +1 -0
- package/dist/core/hooks/index.d.ts.map +1 -1
- package/dist/core/hooks/index.js +1 -0
- package/dist/core/hooks/prompt-context/contract.d.ts +61 -0
- package/dist/core/hooks/prompt-context/contract.d.ts.map +1 -0
- package/dist/core/hooks/prompt-context/contract.js +102 -0
- package/dist/core/hooks/prompt-context/index.d.ts +5 -0
- package/dist/core/hooks/prompt-context/index.d.ts.map +1 -0
- package/dist/core/hooks/prompt-context/index.js +2 -0
- package/dist/core/hooks/prompt-context/runner.d.ts +24 -0
- package/dist/core/hooks/prompt-context/runner.d.ts.map +1 -0
- package/dist/core/hooks/prompt-context/runner.js +249 -0
- package/dist/core/qa-artifacts.d.ts +3 -0
- package/dist/core/qa-artifacts.d.ts.map +1 -1
- package/dist/core/qa-artifacts.js +25 -3
- package/dist/core/resources/contract.d.ts +69 -3
- package/dist/core/resources/contract.d.ts.map +1 -1
- package/dist/core/resources/contract.js +1 -1
- package/dist/core/resources/index.d.ts +1 -0
- package/dist/core/resources/index.d.ts.map +1 -1
- package/dist/core/resources/index.js +1 -0
- package/dist/core/resources/native.d.ts +36 -0
- package/dist/core/resources/native.d.ts.map +1 -0
- package/dist/core/resources/native.js +418 -0
- package/dist/core/resources/sampler.d.ts +2 -0
- package/dist/core/resources/sampler.d.ts.map +1 -1
- package/dist/core/resources/sampler.js +31 -1
- package/dist/core/resources/status.d.ts +61 -0
- package/dist/core/resources/status.d.ts.map +1 -0
- package/dist/core/resources/status.js +536 -0
- package/dist/core/resources/system.d.ts +27 -0
- package/dist/core/resources/system.d.ts.map +1 -0
- package/dist/core/resources/system.js +439 -0
- package/dist/core/semantic/contract.d.ts +13 -13
- package/dist/core/semantic/service.d.ts +2 -0
- package/dist/core/semantic/service.d.ts.map +1 -1
- package/dist/core/semantic/service.js +27 -4
- package/dist/core/storage/builtins.js +41 -0
- package/dist/core/supervisor/contract.d.ts +41 -3
- package/dist/core/supervisor/contract.d.ts.map +1 -1
- package/dist/core/supervisor/contract.js +3 -2
- package/dist/core/supervisor/findings.d.ts +3 -0
- package/dist/core/supervisor/findings.d.ts.map +1 -1
- package/dist/core/supervisor/findings.js +88 -0
- package/dist/core/supervisor/history.d.ts.map +1 -1
- package/dist/core/supervisor/history.js +14 -0
- package/dist/core/supervisor/ledger-state.d.ts +55 -0
- package/dist/core/supervisor/ledger-state.d.ts.map +1 -0
- package/dist/core/supervisor/ledger-state.js +0 -0
- package/dist/core/supervisor/service.d.ts.map +1 -1
- package/dist/core/supervisor/service.js +120 -7
- package/dist/core/supervisor/storage.d.ts +3 -1
- package/dist/core/supervisor/storage.d.ts.map +1 -1
- package/dist/core/supervisor/storage.js +4 -0
- package/dist/core/workflow/admission.d.ts +3 -0
- package/dist/core/workflow/admission.d.ts.map +1 -1
- package/dist/core/workflow/admission.js +28 -16
- package/dist/core/workflow/engine.js +2 -2
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +6 -1
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +4 -3
- package/dist/lib/browser/capture-fidelity.d.ts +7 -0
- package/dist/lib/browser/capture-fidelity.d.ts.map +1 -1
- package/dist/lib/browser/capture-fidelity.js +17 -0
- package/dist/lib/browser/client.d.ts +9 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +85 -37
- package/dist/lib/browser/index.d.ts +3 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -1
- package/dist/lib/browser/page-review-budget.d.ts +13 -0
- package/dist/lib/browser/page-review-budget.d.ts.map +1 -0
- package/dist/lib/browser/page-review-budget.js +251 -0
- package/dist/lib/browser/page-review-contracts.d.ts +127 -0
- package/dist/lib/browser/page-review-contracts.d.ts.map +1 -0
- package/dist/lib/browser/page-review-contracts.js +5 -0
- package/dist/lib/browser/page-review-evidence.d.ts +48 -0
- package/dist/lib/browser/page-review-evidence.d.ts.map +1 -0
- package/dist/lib/browser/page-review-evidence.js +340 -0
- package/dist/lib/browser/page-review-judge.d.ts +1 -1
- package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
- package/dist/lib/browser/page-review-judge.js +46 -38
- package/dist/lib/browser/page-review-pack.d.ts +44 -22
- package/dist/lib/browser/page-review-pack.d.ts.map +1 -1
- package/dist/lib/browser/page-review-pack.js +116 -36
- package/dist/lib/browser/page-review-source.d.ts +12 -0
- package/dist/lib/browser/page-review-source.d.ts.map +1 -0
- package/dist/lib/browser/page-review-source.js +22 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +35 -9
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
- package/dist/lib/browser/qa-run-contracts.js +48 -14
- package/dist/lib/browser/qa-run.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.js +215 -68
- package/dist/lib/browser/qa-snapshot.d.ts +6 -0
- package/dist/lib/browser/qa-snapshot.d.ts.map +1 -1
- package/dist/lib/browser/qa-snapshot.js +259 -48
- package/dist/lib/browser/review-capture-transaction.d.ts +13 -0
- package/dist/lib/browser/review-capture-transaction.d.ts.map +1 -0
- package/dist/lib/browser/review-capture-transaction.js +79 -0
- package/dist/lib/browser/standalone-html.d.ts.map +1 -1
- package/dist/lib/browser/standalone-html.js +4 -2
- package/dist/lib/browser/thumbnail-association.d.ts +34 -0
- package/dist/lib/browser/thumbnail-association.d.ts.map +1 -0
- package/dist/lib/browser/thumbnail-association.js +158 -0
- package/dist/lib/browser/tiling.d.ts +30 -0
- package/dist/lib/browser/tiling.d.ts.map +1 -1
- package/dist/lib/browser/tiling.js +38 -0
- package/dist/lib/docs-metadata-managed.d.ts.map +1 -1
- package/dist/lib/docs-metadata-managed.js +4 -1
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +7 -1
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +1 -0
- package/dist/lib/local-file-url.d.ts +12 -0
- package/dist/lib/local-file-url.d.ts.map +1 -1
- package/dist/lib/local-file-url.js +16 -2
- package/dist/lib/tunnel/state.d.ts +19 -4
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +53 -13
- package/package.json +7 -4
- package/schemas/config.schema.json +69 -2
- package/src/commands/agents.ts +42 -9
- package/src/commands/artifacts.ts +130 -6
- package/src/commands/backup.ts +287 -34
- package/src/commands/browse.ts +564 -267
- package/src/commands/diagnostics.ts +6 -3
- package/src/commands/ledger-v3.ts +20 -3
- package/src/commands/qa-run.ts +37 -3
- package/src/commands/qa-status.ts +11 -2
- package/src/commands/resources.ts +23 -3
- package/src/commands/review-pack.ts +165 -62
- package/src/commands/tunnel.ts +2 -1
- package/src/core/agents/canonical-emit.ts +4 -2
- package/src/core/agents/cli.ts +14 -6
- package/src/core/agents/live-authority-v3.ts +7 -3
- package/src/core/agents/live-lifecycle-v3.ts +2 -2
- package/src/core/agents/render/prompt-context.ts +68 -14
- package/src/core/agents/session-finalizer-v3.ts +2 -2
- package/src/core/agents/state/live-coordination-view.ts +4 -4
- package/src/core/agents/state/names.ts +92 -7
- package/src/core/agents/state/stale-sweep.ts +22 -8
- package/src/core/agents/turn-elapsed.ts +135 -0
- package/src/core/artifacts/activity.ts +71 -0
- package/src/core/artifacts/delivery-card.ts +375 -0
- package/src/core/artifacts/index.ts +385 -91
- package/src/core/artifacts/mutation-lock.ts +106 -0
- package/src/core/backup/host-snapshot.ts +76 -0
- package/src/core/config.ts +66 -13
- package/src/core/diagnostics/advice.ts +148 -120
- package/src/core/diagnostics/bundle.ts +138 -52
- package/src/core/diagnostics/comparison.ts +6 -2
- package/src/core/diagnostics/contract.ts +39 -42
- package/src/core/diagnostics/index.ts +2 -0
- package/src/core/diagnostics/pressure-contract.ts +294 -0
- package/src/core/diagnostics/pressure.ts +1361 -0
- package/src/core/diagnostics/replay.ts +116 -11
- package/src/core/events/v3/adapter-id.ts +12 -0
- package/src/core/events/v3/archive-retention.ts +3 -6
- package/src/core/events/v3/bootstrap.ts +163 -16
- package/src/core/events/v3/capabilities.ts +75 -25
- package/src/core/events/v3/capability-drift.ts +2 -2
- package/src/core/events/v3/control-witness.ts +172 -41
- package/src/core/events/v3/control.ts +34 -2
- package/src/core/events/v3/index.ts +3 -0
- package/src/core/events/v3/live-feed.ts +23 -5
- package/src/core/events/v3/live-routing.ts +14 -2
- package/src/core/events/v3/producers/command-recorder.ts +4 -4
- package/src/core/events/v3/producers/coordination-recorder.ts +4 -4
- package/src/core/events/v3/producers/hook-base.ts +21 -16
- package/src/core/events/v3/producers/hook.ts +21 -4
- package/src/core/events/v3/producers/intake.ts +6 -6
- package/src/core/events/v3/producers/producer-state-observer.ts +2 -1
- package/src/core/events/v3/producers/recorder.ts +50 -21
- package/src/core/events/v3/reader.ts +14 -13
- package/src/core/events/v3/runtime-build.ts +3 -2
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +3 -3
- package/src/core/events/v3/turn-telemetry.ts +4 -4
- package/src/core/hooks/adapter/output.ts +50 -36
- package/src/core/hooks/backup-schedule.ts +147 -0
- package/src/core/hooks/cli.ts +65 -14
- package/src/core/hooks/codex-wsl-bridge.ts +21 -5
- package/src/core/hooks/index.ts +1 -0
- package/src/core/hooks/prompt-context/contract.ts +177 -0
- package/src/core/hooks/prompt-context/index.ts +22 -0
- package/src/core/hooks/prompt-context/runner.ts +303 -0
- package/src/core/qa-artifacts.ts +29 -3
- package/src/core/resources/contract.ts +76 -3
- package/src/core/resources/index.ts +1 -0
- package/src/core/resources/native.ts +481 -0
- package/src/core/resources/sampler.ts +46 -1
- package/src/core/resources/status.ts +717 -0
- package/src/core/resources/system.ts +530 -0
- package/src/core/semantic/service.ts +37 -3
- package/src/core/storage/builtins.ts +41 -0
- package/src/core/supervisor/contract.ts +45 -3
- package/src/core/supervisor/findings.ts +159 -0
- package/src/core/supervisor/history.ts +15 -0
- package/src/core/supervisor/ledger-state.ts +0 -0
- package/src/core/supervisor/service.ts +133 -5
- package/src/core/supervisor/storage.ts +7 -0
- package/src/core/workflow/admission.ts +33 -17
- package/src/core/workflow/engine.ts +2 -2
- package/src/core/workflow/live-session-v3.ts +6 -8
- package/src/core/workflow/proof.ts +4 -3
- package/src/lib/browser/capture-fidelity.ts +23 -0
- package/src/lib/browser/client.ts +96 -44
- package/src/lib/browser/index.ts +15 -1
- package/src/lib/browser/page-review-budget.ts +309 -0
- package/src/lib/browser/page-review-contracts.ts +129 -0
- package/src/lib/browser/page-review-evidence.ts +465 -0
- package/src/lib/browser/page-review-judge.ts +56 -40
- package/src/lib/browser/page-review-pack.ts +181 -43
- package/src/lib/browser/page-review-source.ts +30 -0
- package/src/lib/browser/qa-run-contracts.ts +62 -18
- package/src/lib/browser/qa-run.ts +259 -71
- package/src/lib/browser/qa-snapshot.ts +289 -48
- package/src/lib/browser/review-capture-transaction.ts +106 -0
- package/src/lib/browser/standalone-html.ts +4 -2
- package/src/lib/browser/thumbnail-association.ts +190 -0
- package/src/lib/browser/tiling.ts +63 -0
- package/src/lib/docs-metadata-managed.ts +4 -1
- package/src/lib/identities/assume.ts +12 -4
- package/src/lib/instructions/templates.ts +1 -0
- package/src/lib/local-file-url.ts +17 -2
- package/src/lib/tunnel/state.ts +70 -13
|
@@ -8,16 +8,15 @@
|
|
|
8
8
|
* - **Claude Code**: `{hookSpecificOutput: {hookEventName, additionalContext}}`
|
|
9
9
|
* for SessionStart / UserPromptSubmit / SubagentStart; deny uses
|
|
10
10
|
* `{hookSpecificOutput: {hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason}}`.
|
|
11
|
-
* - **Cursor**: `{additional_context
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* Deny uses `{permission: "deny", agent_message, user_message}`.
|
|
11
|
+
* - **Cursor**: `{additional_context}` flat for context-capable events,
|
|
12
|
+
* including beforeSubmitPrompt. Deny uses
|
|
13
|
+
* `{permission: "deny", agent_message, user_message}`.
|
|
15
14
|
* - **Codex**: structurally identical to Claude Code for context and tool
|
|
16
15
|
* denials. Stop blocks are deliberately suppressed because their automatic
|
|
17
16
|
* continuation can replace a completed user-facing answer.
|
|
18
17
|
*
|
|
19
18
|
* Every helper writes to process.stdout + newline-terminates so callers can
|
|
20
|
-
* fire-and-forget. Empty text
|
|
19
|
+
* fire-and-forget. Empty text is a no-op.
|
|
21
20
|
*/
|
|
22
21
|
|
|
23
22
|
import type { Adapter } from "../../adapter.ts";
|
|
@@ -31,23 +30,17 @@ export type SystemEvent =
|
|
|
31
30
|
| "PreToolUse"
|
|
32
31
|
| "PostToolUse";
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
* model context, so anything rendered for that event is discarded. A caller
|
|
38
|
-
* that consumes state to build the text (draining a mailbox, for instance)
|
|
39
|
-
* must check this first, or the state is spent on output nobody reads.
|
|
40
|
-
*/
|
|
41
|
-
export function canReceiveContext(adapter: Adapter, event: SystemEvent): boolean {
|
|
42
|
-
return !(adapter === "cursor" && event === "UserPromptSubmit");
|
|
33
|
+
export interface StopOutputOptions {
|
|
34
|
+
/** Existing coordination verdict. Omit when that check passed. */
|
|
35
|
+
verdict?: { reason?: string; rule: string };
|
|
43
36
|
}
|
|
44
37
|
|
|
45
38
|
/** Emit a context-injection (peer table, wiring check, council pending, …). */
|
|
46
|
-
export function emitContext(adapter: Adapter, event: SystemEvent, text: string):
|
|
47
|
-
if (!text
|
|
48
|
-
if (!canReceiveContext(adapter, event)) return;
|
|
39
|
+
export function emitContext(adapter: Adapter, event: SystemEvent, text: string): boolean {
|
|
40
|
+
if (!text) return false;
|
|
49
41
|
const json = buildContextJson(adapter, event, text);
|
|
50
42
|
process.stdout.write(`${JSON.stringify(json)}\n`);
|
|
43
|
+
return true;
|
|
51
44
|
}
|
|
52
45
|
|
|
53
46
|
/** Emit a PreToolUse deny: blocks the tool call with `reason` shown to the model. */
|
|
@@ -83,26 +76,32 @@ export function emitStopBlock(
|
|
|
83
76
|
adapter: Adapter,
|
|
84
77
|
verdict: { reason?: string; rule: string },
|
|
85
78
|
coordRoot?: string,
|
|
79
|
+
): 0 | 2 {
|
|
80
|
+
return emitStopOutcome(adapter, { verdict }, coordRoot);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Emit the adapter-specific response for one Stop outcome.
|
|
85
|
+
*/
|
|
86
|
+
export function emitStopOutcome(
|
|
87
|
+
adapter: Adapter,
|
|
88
|
+
options: StopOutputOptions,
|
|
89
|
+
coordRoot?: string,
|
|
86
90
|
): 0 | 2 {
|
|
87
91
|
if (adapter === "codex") return 0;
|
|
88
92
|
|
|
89
|
-
const
|
|
93
|
+
const verdict = options.verdict;
|
|
94
|
+
if (!verdict) return 0;
|
|
95
|
+
|
|
90
96
|
if (adapter === "cursor") {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
// Both commands are named because one message that repairs the whole ritual
|
|
95
|
-
// ends the chain in a single followup; the failing rule is context.
|
|
96
|
-
const bin = resolveBinName(coordRoot);
|
|
97
|
-
const statusCommand = endOfTurnStatusCommand(coordRoot);
|
|
98
|
-
const message = [
|
|
99
|
-
`${STOP_REMEDIATION_MARKER} rule=${verdict.rule}]`,
|
|
100
|
-
reason,
|
|
101
|
-
`Repair the ritual in this turn: run \`${bin} agents set-task "<short focus>"\` and then \`${statusCommand}\` as your last tool call.`,
|
|
102
|
-
].join("\n");
|
|
103
|
-
process.stdout.write(`${JSON.stringify({ followup_message: message })}\n`);
|
|
97
|
+
process.stdout.write(
|
|
98
|
+
`${JSON.stringify({ followup_message: cursorCoordinationRemediation(verdict, coordRoot) })}\n`,
|
|
99
|
+
);
|
|
104
100
|
return 0;
|
|
105
101
|
}
|
|
102
|
+
|
|
103
|
+
if (!verdict) return 0;
|
|
104
|
+
const reason = verdict.reason ?? "End-of-turn coordination ritual incomplete.";
|
|
106
105
|
// Claude Code re-prompts inside one native Stop remediation cycle, but tools
|
|
107
106
|
// run after the first terminal are recorded in recovered telemetry turns.
|
|
108
107
|
// Name the whole ritual so one continuation can repair every required signal.
|
|
@@ -113,17 +112,32 @@ export function emitStopBlock(
|
|
|
113
112
|
return 2;
|
|
114
113
|
}
|
|
115
114
|
|
|
115
|
+
function cursorCoordinationRemediation(
|
|
116
|
+
verdict: { reason?: string; rule: string },
|
|
117
|
+
coordRoot?: string,
|
|
118
|
+
): string {
|
|
119
|
+
const reason = verdict.reason ?? "End-of-turn coordination ritual incomplete.";
|
|
120
|
+
// The marker leads the message so the Stop verdict can recognize the turn
|
|
121
|
+
// Cursor opens from it (`STOP_REMEDIATION_MARKER`), and so the operator can
|
|
122
|
+
// see in chat that the message came from Harnery rather than from them.
|
|
123
|
+
// Both commands are named because one message that repairs the whole ritual
|
|
124
|
+
// ends the chain in a single followup; the failing rule is context.
|
|
125
|
+
const bin = resolveBinName(coordRoot);
|
|
126
|
+
const statusCommand = endOfTurnStatusCommand(coordRoot);
|
|
127
|
+
const message = [
|
|
128
|
+
`${STOP_REMEDIATION_MARKER} rule=${verdict.rule}]`,
|
|
129
|
+
reason,
|
|
130
|
+
`Repair the ritual in this turn: run \`${bin} agents set-task "<short focus>"\` and then \`${statusCommand}\` as your last tool call.`,
|
|
131
|
+
].join("\n");
|
|
132
|
+
return message;
|
|
133
|
+
}
|
|
134
|
+
|
|
116
135
|
function buildContextJson(
|
|
117
136
|
adapter: Adapter,
|
|
118
137
|
event: SystemEvent,
|
|
119
138
|
text: string,
|
|
120
139
|
): Record<string, unknown> {
|
|
121
140
|
if (adapter === "cursor") {
|
|
122
|
-
// Cursor uses a flat top-level key + an env block that survives across the
|
|
123
|
-
// session. The dispatcher historically also wrote
|
|
124
|
-
// `env: {HARNERY_AGENT_COORD_ADAPTER, HARNERY_AGENT_COORD_PLATFORM}`. These are
|
|
125
|
-
// observer hints, not load-bearing; agent-hook + agent-coord recover the
|
|
126
|
-
// adapter from event metadata. Drop them.
|
|
127
141
|
return { additional_context: text };
|
|
128
142
|
}
|
|
129
143
|
// Claude Code + Codex share the `hookSpecificOutput` envelope.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
3
|
+
import { hostname } from "node:os";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { parseBackupDuration, readHostSnapshotCache } from "../backup/host-snapshot.ts";
|
|
7
|
+
import { backupConfig } from "../config.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Detached runner for the scheduled snapshot. It owns no inherited stdio: a
|
|
11
|
+
* hook that hands its stderr pipe to a background child keeps the harness
|
|
12
|
+
* waiting until restic and the remote provider finish, which is the delay the
|
|
13
|
+
* schedule exists to avoid. Output goes to the log; the exit code goes to the
|
|
14
|
+
* status file the next session start reads.
|
|
15
|
+
*/
|
|
16
|
+
const RUNNER = `
|
|
17
|
+
harn_bin="$1"
|
|
18
|
+
if_stale="$2"
|
|
19
|
+
log_file="$3"
|
|
20
|
+
status_file="$4"
|
|
21
|
+
shift 4
|
|
22
|
+
stamp() { date -u +%Y-%m-%dT%H:%M:%SZ; }
|
|
23
|
+
if [ -f "$log_file" ] && [ "$(wc -c <"$log_file")" -gt 262144 ]; then
|
|
24
|
+
tail -c 65536 "$log_file" >"$log_file.rotating" && mv "$log_file.rotating" "$log_file"
|
|
25
|
+
fi
|
|
26
|
+
printf '%s scheduled snapshot start (if-stale %s)\\n' "$(stamp)" "$if_stale" >>"$log_file"
|
|
27
|
+
"$harn_bin" backup snapshot --if-stale "$if_stale" "$@" >>"$log_file" 2>&1
|
|
28
|
+
status=$?
|
|
29
|
+
printf '%s scheduled snapshot exit %s\\n' "$(stamp)" "$status" >>"$log_file"
|
|
30
|
+
printf '{"exit_code":%s,"finished_at":"%s"}\\n' "$status" "$(stamp)" >"$status_file.tmp" && mv "$status_file.tmp" "$status_file"
|
|
31
|
+
exit "$status"
|
|
32
|
+
`.trim();
|
|
33
|
+
|
|
34
|
+
export interface ScheduledBackupInvocation {
|
|
35
|
+
harnBin: string;
|
|
36
|
+
ifStale: string;
|
|
37
|
+
tags: readonly string[];
|
|
38
|
+
logFile: string;
|
|
39
|
+
statusFile: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface ScheduledBackupStatus {
|
|
43
|
+
exitCode: number;
|
|
44
|
+
finishedAt: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface ScheduledBackupPlan {
|
|
48
|
+
/** `disabled`: no schedule; `fresh`: local cache proves this host is current; `launch`: run the snapshot. */
|
|
49
|
+
action: "disabled" | "fresh" | "launch";
|
|
50
|
+
/** One line for the session context when the previous scheduled run failed. */
|
|
51
|
+
cue: string | null;
|
|
52
|
+
invocation: ScheduledBackupInvocation | null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function scheduledBackupInvocation(coordRoot: string): ScheduledBackupInvocation | null {
|
|
56
|
+
const schedule = backupConfig(coordRoot).schedule;
|
|
57
|
+
if (!schedule) return null;
|
|
58
|
+
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
|
|
59
|
+
const logsDir = join(resolve(coordRoot), ".harnery", "logs");
|
|
60
|
+
return {
|
|
61
|
+
harnBin: join(packageRoot, "bin", "harn"),
|
|
62
|
+
ifStale: schedule.ifStale,
|
|
63
|
+
tags: schedule.tags,
|
|
64
|
+
logFile: join(logsDir, "backup-schedule.log"),
|
|
65
|
+
statusFile: join(logsDir, "backup-schedule.status.json"),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function readScheduledBackupStatus(statusFile: string): ScheduledBackupStatus | null {
|
|
70
|
+
if (!existsSync(statusFile)) return null;
|
|
71
|
+
try {
|
|
72
|
+
const parsed = JSON.parse(readFileSync(statusFile, "utf8")) as {
|
|
73
|
+
exit_code?: unknown;
|
|
74
|
+
finished_at?: unknown;
|
|
75
|
+
};
|
|
76
|
+
if (typeof parsed.exit_code !== "number" || typeof parsed.finished_at !== "string") {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return { exitCode: parsed.exit_code, finishedAt: parsed.finished_at };
|
|
80
|
+
} catch {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Decide what session start should do. The local host cache written by
|
|
87
|
+
* `harn backup snapshot` is only an optimisation: when it is missing, stale,
|
|
88
|
+
* or from another host, the launched command still asks restic. A failed
|
|
89
|
+
* previous run always relaunches so a transient error heals on the next
|
|
90
|
+
* session instead of waiting out the freshness window.
|
|
91
|
+
*/
|
|
92
|
+
export function planScheduledBackup(coordRoot: string, now = Date.now()): ScheduledBackupPlan {
|
|
93
|
+
const invocation = scheduledBackupInvocation(coordRoot);
|
|
94
|
+
if (!invocation) return { action: "disabled", cue: null, invocation: null };
|
|
95
|
+
const status = readScheduledBackupStatus(invocation.statusFile);
|
|
96
|
+
const failed = status !== null && status.exitCode !== 0;
|
|
97
|
+
const cue = failed
|
|
98
|
+
? `harnery backup: the last scheduled snapshot failed (exit ${status.exitCode} at ${status.finishedAt}); see ${invocation.logFile}. Fix the cause or run \`harn backup snapshot --if-stale ${invocation.ifStale}\` to retry.`
|
|
99
|
+
: null;
|
|
100
|
+
const staleMs = parseBackupDuration(invocation.ifStale);
|
|
101
|
+
const cache = readHostSnapshotCache(join(resolve(coordRoot), ".harnery"));
|
|
102
|
+
const fresh =
|
|
103
|
+
!failed &&
|
|
104
|
+
staleMs !== null &&
|
|
105
|
+
cache !== null &&
|
|
106
|
+
cache.host === hostname() &&
|
|
107
|
+
now - cache.snapshotAt < staleMs;
|
|
108
|
+
return { action: fresh ? "fresh" : "launch", cue, invocation };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Launch the configured SessionStart snapshot without extending hook latency. */
|
|
112
|
+
export function scheduleBackupSnapshot(coordRoot: string): {
|
|
113
|
+
launched: boolean;
|
|
114
|
+
cue: string | null;
|
|
115
|
+
} {
|
|
116
|
+
const plan = planScheduledBackup(coordRoot);
|
|
117
|
+
if (plan.cue) process.stderr.write(`${plan.cue}\n`);
|
|
118
|
+
if (plan.action !== "launch" || !plan.invocation) return { launched: false, cue: plan.cue };
|
|
119
|
+
const invocation = plan.invocation;
|
|
120
|
+
mkdirSync(dirname(invocation.logFile), { recursive: true });
|
|
121
|
+
const tagArgs = invocation.tags.flatMap((tag) => ["--tag", tag]);
|
|
122
|
+
const child = spawn(
|
|
123
|
+
"bash",
|
|
124
|
+
[
|
|
125
|
+
"-c",
|
|
126
|
+
RUNNER,
|
|
127
|
+
"harnery-backup",
|
|
128
|
+
invocation.harnBin,
|
|
129
|
+
invocation.ifStale,
|
|
130
|
+
invocation.logFile,
|
|
131
|
+
invocation.statusFile,
|
|
132
|
+
...tagArgs,
|
|
133
|
+
],
|
|
134
|
+
{
|
|
135
|
+
cwd: resolve(coordRoot),
|
|
136
|
+
detached: true,
|
|
137
|
+
stdio: "ignore",
|
|
138
|
+
},
|
|
139
|
+
);
|
|
140
|
+
child.once("error", () => {
|
|
141
|
+
process.stderr.write(
|
|
142
|
+
`harnery backup: scheduled snapshot could not start; see ${invocation.logFile}\n`,
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
child.unref();
|
|
146
|
+
return { launched: true, cue: plan.cue };
|
|
147
|
+
}
|
package/src/core/hooks/cli.ts
CHANGED
|
@@ -56,7 +56,12 @@ import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.
|
|
|
56
56
|
import { ensureLiveCoordinationHeartbeat } from "../agents/state/live-coordination-writer.ts";
|
|
57
57
|
import { assignName } from "../agents/state/names.ts";
|
|
58
58
|
import { writePidmapRow } from "../agents/state/pidmap.ts";
|
|
59
|
-
import {
|
|
59
|
+
import {
|
|
60
|
+
agentsRequireGitFinalization,
|
|
61
|
+
coordFreshnessSeconds,
|
|
62
|
+
hostPromptContextConfig,
|
|
63
|
+
resolveBinName,
|
|
64
|
+
} from "../config.ts";
|
|
60
65
|
import {
|
|
61
66
|
checkpointContext,
|
|
62
67
|
completeContextRecovery,
|
|
@@ -89,6 +94,7 @@ import {
|
|
|
89
94
|
parsePayload,
|
|
90
95
|
} from "./adapter/parse.ts";
|
|
91
96
|
import { discoverCodexSessionTranscript } from "./adapter/runtime-telemetry.ts";
|
|
97
|
+
import { scheduleBackupSnapshot } from "./backup-schedule.ts";
|
|
92
98
|
import {
|
|
93
99
|
codexWslFileLinkTelemetry,
|
|
94
100
|
inspectCodexWslBridge,
|
|
@@ -246,7 +252,10 @@ function assignNameInProcess(
|
|
|
246
252
|
forkedFrom?: string,
|
|
247
253
|
): { name: string; kind: string } | null {
|
|
248
254
|
try {
|
|
249
|
-
const name = assignName(coordRoot, instanceId, kind,
|
|
255
|
+
const name = assignName(coordRoot, instanceId, kind, {
|
|
256
|
+
freshnessSecs: coordFreshnessSeconds(coordRoot),
|
|
257
|
+
...(forkedFrom ? { forkedFrom } : {}),
|
|
258
|
+
});
|
|
250
259
|
return { name, kind };
|
|
251
260
|
} catch {
|
|
252
261
|
return null;
|
|
@@ -834,6 +843,11 @@ async function main(): Promise<number> {
|
|
|
834
843
|
|
|
835
844
|
const sessionId = payload?.session_id ?? payload?.conversation_id ?? owner.instance_id;
|
|
836
845
|
const priorCoordination = readHeartbeat(coordRoot, owner.instance_id);
|
|
846
|
+
const topLevelSession =
|
|
847
|
+
coordEnv("WORKFLOW_CHILD") !== "1" &&
|
|
848
|
+
priorCoordination?.kind !== "subagent" &&
|
|
849
|
+
priorCoordination?.kind !== "transient" &&
|
|
850
|
+
!priorCoordination?.workflow_run_id;
|
|
837
851
|
if (
|
|
838
852
|
norm.event_type !== "session.ended" &&
|
|
839
853
|
coordEnv("WORKFLOW_CHILD") !== "1" &&
|
|
@@ -1074,6 +1088,16 @@ async function main(): Promise<number> {
|
|
|
1074
1088
|
// Adapter-agnostic since v0.5.0; replaces the previous bash UX layer
|
|
1075
1089
|
// and the equivalent per-adapter bash session_start handlers.
|
|
1076
1090
|
if (norm.event_type === "session.started") {
|
|
1091
|
+
// A configured backup runs out of process and is freshness-gated per host.
|
|
1092
|
+
// Startup never waits for restic or a remote provider; the child owns no
|
|
1093
|
+
// hook stdio, so the harness is not held open until it finishes. A failed
|
|
1094
|
+
// previous run surfaces as one line in this session's context.
|
|
1095
|
+
let backupCue = "";
|
|
1096
|
+
try {
|
|
1097
|
+
backupCue = scheduleBackupSnapshot(coordRoot).cue ?? "";
|
|
1098
|
+
} catch (err) {
|
|
1099
|
+
logError(coordRoot, err, { phase: "backup-schedule" });
|
|
1100
|
+
}
|
|
1077
1101
|
// Effect (claude-code): prune stale journal archives + sweep orphans.
|
|
1078
1102
|
// The recovery-cue is merged into the
|
|
1079
1103
|
// session-start additionalContext inside emitSessionStartSystemMessage.
|
|
@@ -1141,6 +1165,7 @@ async function main(): Promise<number> {
|
|
|
1141
1165
|
data,
|
|
1142
1166
|
adapter,
|
|
1143
1167
|
recovery?.briefing ?? "",
|
|
1168
|
+
backupCue,
|
|
1144
1169
|
);
|
|
1145
1170
|
if (injected && recovery) {
|
|
1146
1171
|
completeRecoveryInjection(coordRoot, owner.instance_id, sessionId, recovery);
|
|
@@ -1240,6 +1265,29 @@ async function main(): Promise<number> {
|
|
|
1240
1265
|
logError(coordRoot, err, { phase: "context-recovery-user-prompt" });
|
|
1241
1266
|
}
|
|
1242
1267
|
}
|
|
1268
|
+
let hostPromptContext = "";
|
|
1269
|
+
const hostPromptEnabled = hostPromptContextConfig(coordRoot)?.enabled === true;
|
|
1270
|
+
if (hostPromptEnabled && topLevelSession && !stopRemediation) {
|
|
1271
|
+
try {
|
|
1272
|
+
const { runPromptContext } = await import("./prompt-context/runner.ts");
|
|
1273
|
+
const result = await runPromptContext({
|
|
1274
|
+
coordRoot,
|
|
1275
|
+
adapter,
|
|
1276
|
+
sessionId,
|
|
1277
|
+
turnId: payload?.turn_id ?? v3EventId ?? sessionId,
|
|
1278
|
+
cwd: payload?.cwd ?? process.cwd(),
|
|
1279
|
+
prompt: payload?.prompt ?? "",
|
|
1280
|
+
});
|
|
1281
|
+
appendDebug(coordRoot, {
|
|
1282
|
+
...debugBase,
|
|
1283
|
+
effect: "prompt-context",
|
|
1284
|
+
...result.audit,
|
|
1285
|
+
});
|
|
1286
|
+
hostPromptContext = result.context ?? "";
|
|
1287
|
+
} catch (err) {
|
|
1288
|
+
logError(coordRoot, err, { phase: "prompt-context-user-prompt" });
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1243
1291
|
try {
|
|
1244
1292
|
const injected = await emitUserPromptSubmitSystemMessage(
|
|
1245
1293
|
coordRoot,
|
|
@@ -1248,6 +1296,7 @@ async function main(): Promise<number> {
|
|
|
1248
1296
|
adapter,
|
|
1249
1297
|
payload?.cwd,
|
|
1250
1298
|
recovery?.briefing ?? "",
|
|
1299
|
+
hostPromptContext,
|
|
1251
1300
|
);
|
|
1252
1301
|
if (injected && recovery) {
|
|
1253
1302
|
completeRecoveryInjection(coordRoot, owner.instance_id, sessionId, recovery);
|
|
@@ -1311,10 +1360,9 @@ async function main(): Promise<number> {
|
|
|
1311
1360
|
} else {
|
|
1312
1361
|
// Adapter-aware enforcement channel: Claude Code honors exit-2 + stderr
|
|
1313
1362
|
// as a turn block; Cursor ignores exit codes and re-prompts only via a
|
|
1314
|
-
// `followup_message` it auto-submits.
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
return emitStopBlock(adapter, verdict, coordRoot);
|
|
1363
|
+
// `followup_message` it auto-submits.
|
|
1364
|
+
const { emitStopOutcome } = await import("./adapter/output.ts");
|
|
1365
|
+
return emitStopOutcome(adapter, { verdict }, coordRoot);
|
|
1318
1366
|
}
|
|
1319
1367
|
} else {
|
|
1320
1368
|
const { clearRemediationCount } = await import("./remediation-cap.ts");
|
|
@@ -1906,16 +1954,16 @@ async function emitUserPromptSubmitSystemMessage(
|
|
|
1906
1954
|
adapter: Adapter,
|
|
1907
1955
|
workspaceCwd?: string,
|
|
1908
1956
|
recoveryBriefing = "",
|
|
1957
|
+
hostPromptContext = "",
|
|
1909
1958
|
): Promise<boolean> {
|
|
1910
1959
|
const { renderPromptContext } = await import("../agents/render/prompt-context.ts");
|
|
1911
1960
|
let additionalContext = renderPromptContext({
|
|
1912
1961
|
coordRoot,
|
|
1913
1962
|
instanceId,
|
|
1914
1963
|
sessionId,
|
|
1915
|
-
adapter,
|
|
1916
1964
|
sessionNameNudge: true,
|
|
1917
1965
|
taskNudge: adapter === "cursor" || adapter === "codex",
|
|
1918
|
-
hostPromptReminder: adapter === "codex",
|
|
1966
|
+
hostPromptReminder: adapter === "codex" || adapter === "cursor",
|
|
1919
1967
|
statusFooterNudge: adapter === "codex",
|
|
1920
1968
|
turnRitualNudge: adapter === "claude-code" ? adapter : undefined,
|
|
1921
1969
|
}).trim();
|
|
@@ -1928,11 +1976,13 @@ async function emitUserPromptSubmitSystemMessage(
|
|
|
1928
1976
|
if (recoveryBriefing) {
|
|
1929
1977
|
additionalContext = [additionalContext, recoveryBriefing].filter(Boolean).join("\n\n");
|
|
1930
1978
|
}
|
|
1979
|
+
if (hostPromptContext) {
|
|
1980
|
+
additionalContext = [additionalContext, hostPromptContext].filter(Boolean).join("\n\n");
|
|
1981
|
+
}
|
|
1931
1982
|
if (!additionalContext) return false;
|
|
1932
1983
|
|
|
1933
1984
|
const { emitContext } = await import("./adapter/output.ts");
|
|
1934
|
-
emitContext(adapter, "UserPromptSubmit", additionalContext);
|
|
1935
|
-
return true;
|
|
1985
|
+
return emitContext(adapter, "UserPromptSubmit", additionalContext);
|
|
1936
1986
|
}
|
|
1937
1987
|
|
|
1938
1988
|
async function emitSubagentStartContext(
|
|
@@ -1989,6 +2039,7 @@ async function emitSessionStartSystemMessage(
|
|
|
1989
2039
|
emittedData: Record<string, unknown>,
|
|
1990
2040
|
adapter: Adapter,
|
|
1991
2041
|
recoveryBriefing = "",
|
|
2042
|
+
backupCue = "",
|
|
1992
2043
|
): Promise<boolean> {
|
|
1993
2044
|
const workflowChild = coordEnv("WORKFLOW_CHILD") === "1";
|
|
1994
2045
|
let additionalContext = "";
|
|
@@ -2026,6 +2077,9 @@ async function emitSessionStartSystemMessage(
|
|
|
2026
2077
|
if (recoveryBriefing && !workflowChild) {
|
|
2027
2078
|
additionalContext = [additionalContext, recoveryBriefing].filter(Boolean).join("\n\n");
|
|
2028
2079
|
}
|
|
2080
|
+
if (backupCue && !workflowChild) {
|
|
2081
|
+
additionalContext = [additionalContext, backupCue].filter(Boolean).join("\n\n");
|
|
2082
|
+
}
|
|
2029
2083
|
if (adapter === "codex" && !workflowChild && isWslUncPath(emittedData.cwd)) {
|
|
2030
2084
|
const fileLinkContext = renderCodexWslFileLinkContext(coordRoot, emittedData.cwd);
|
|
2031
2085
|
if (fileLinkContext) {
|
|
@@ -2041,11 +2095,8 @@ async function emitSessionStartSystemMessage(
|
|
|
2041
2095
|
.join("\n\n");
|
|
2042
2096
|
}
|
|
2043
2097
|
}
|
|
2044
|
-
if (!additionalContext) return false;
|
|
2045
|
-
|
|
2046
2098
|
const { emitContext } = await import("./adapter/output.ts");
|
|
2047
|
-
emitContext(adapter, "SessionStart", additionalContext);
|
|
2048
|
-
return true;
|
|
2099
|
+
return emitContext(adapter, "SessionStart", additionalContext);
|
|
2049
2100
|
}
|
|
2050
2101
|
|
|
2051
2102
|
function completeRecoveryInjection(
|
|
@@ -71,10 +71,7 @@ export function codexWslWorkspaceLinkMapping(
|
|
|
71
71
|
const parsed = parseWslUncPath(workspaceCwd);
|
|
72
72
|
const linuxRoot = trimTrailingSlash(coordRootRaw.replace(/\\/g, "/"));
|
|
73
73
|
if (!parsed || !linuxRoot.startsWith("/")) return null;
|
|
74
|
-
|
|
75
|
-
if (!isWithinOrEqual(linuxCwd, linuxRoot) && !isWithinOrEqual(linuxRoot, linuxCwd)) {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
74
|
+
if (!codexWslWorkspaceLinuxPath(coordRootRaw, workspaceCwd)) return null;
|
|
78
75
|
return {
|
|
79
76
|
linuxRoot,
|
|
80
77
|
hostRoot: `//${parsed.host}/${parsed.distro}${linuxRoot}`,
|
|
@@ -82,6 +79,21 @@ export function codexWslWorkspaceLinkMapping(
|
|
|
82
79
|
};
|
|
83
80
|
}
|
|
84
81
|
|
|
82
|
+
/** Translate an overlapping WSL UNC workspace into its Linux-native path. */
|
|
83
|
+
export function codexWslWorkspaceLinuxPath(
|
|
84
|
+
coordRootRaw: string,
|
|
85
|
+
workspaceCwd: unknown,
|
|
86
|
+
): string | null {
|
|
87
|
+
const parsed = parseWslUncPath(workspaceCwd);
|
|
88
|
+
const linuxRoot = trimTrailingSlash(coordRootRaw.replace(/\\/g, "/"));
|
|
89
|
+
if (!parsed || !linuxRoot.startsWith("/")) return null;
|
|
90
|
+
const linuxCwd = trimTrailingSlash(parsed.linuxPath);
|
|
91
|
+
if (!isWithinOrEqual(linuxCwd, linuxRoot) && !isWithinOrEqual(linuxRoot, linuxCwd)) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
return linuxCwd;
|
|
95
|
+
}
|
|
96
|
+
|
|
85
97
|
/** Fresh adapter context for the model. Shell paths stay Linux-native; only
|
|
86
98
|
* Markdown destinations use the host-visible root. */
|
|
87
99
|
export function renderCodexWslFileLinkContext(coordRoot: string, workspaceCwd: unknown): string {
|
|
@@ -90,7 +102,11 @@ export function renderCodexWslFileLinkContext(coordRoot: string, workspaceCwd: u
|
|
|
90
102
|
return (
|
|
91
103
|
"Codex WSL file links: this task is hosted by Windows while tools run inside WSL. " +
|
|
92
104
|
`For clickable local-file Markdown links, replace the Linux workspace root \`${mapping.linuxRoot}\` with the host-visible root \`${mapping.hostRoot}\`. ` +
|
|
93
|
-
`Example: \`[label](
|
|
105
|
+
`Example: \`[label](${mapping.hostRoot}/path/to/file)\`. ` +
|
|
106
|
+
"Percent-encode a space as %20 and a parenthesis as %28 or %29 in the link, " +
|
|
107
|
+
"and do not wrap the destination in angle brackets: that form is valid " +
|
|
108
|
+
"Markdown but some renderers style it as a link without keeping the target, " +
|
|
109
|
+
"so it looks clickable and does nothing. " +
|
|
94
110
|
"Keep Linux paths unchanged in shell commands and tool inputs."
|
|
95
111
|
);
|
|
96
112
|
}
|
package/src/core/hooks/index.ts
CHANGED