harnery 0.40.0 → 0.42.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/README.md +1 -1
- package/dist/commander.js +4 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +34 -20
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +113 -12
- package/dist/commands/browse-ai.d.ts.map +1 -1
- package/dist/commands/browse-ai.js +4 -0
- package/dist/commands/browse.d.ts +164 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +388 -45
- package/dist/commands/checkpoint.js +8 -12
- package/dist/commands/claude-desktop.d.ts.map +1 -1
- package/dist/commands/claude-desktop.js +52 -0
- package/dist/commands/deinit.d.ts +1 -1
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +8 -4
- package/dist/commands/disk.d.ts +6 -0
- package/dist/commands/disk.d.ts.map +1 -0
- package/dist/commands/disk.js +80 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +2 -0
- package/dist/commands/doctor.d.ts +8 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +58 -3
- package/dist/commands/fetch.d.ts.map +1 -1
- package/dist/commands/fetch.js +10 -0
- package/dist/commands/files.d.ts +16 -0
- package/dist/commands/files.d.ts.map +1 -1
- package/dist/commands/files.js +54 -2
- package/dist/commands/init.d.ts +21 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +271 -109
- package/dist/commands/instructions.js +5 -4
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +2 -1
- package/dist/commands/rm.d.ts +4 -0
- package/dist/commands/rm.d.ts.map +1 -0
- package/dist/commands/rm.js +87 -0
- package/dist/commands/servers.d.ts +7 -0
- package/dist/commands/servers.d.ts.map +1 -0
- package/dist/commands/servers.js +394 -0
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +82 -2
- package/dist/commands/webview.d.ts +4 -0
- package/dist/commands/webview.d.ts.map +1 -0
- package/dist/commands/webview.js +94 -0
- package/dist/core/adapter.d.ts +50 -1
- package/dist/core/adapter.d.ts.map +1 -1
- package/dist/core/adapter.js +59 -1
- package/dist/core/adapters/attestation.d.ts.map +1 -1
- package/dist/core/adapters/attestation.js +3 -2
- package/dist/core/adapters/profiles.d.ts +29 -3
- package/dist/core/adapters/profiles.d.ts.map +1 -1
- package/dist/core/adapters/profiles.js +53 -1
- package/dist/core/adapters/registry.d.ts.map +1 -1
- package/dist/core/adapters/registry.js +33 -0
- package/dist/core/adapters/types.d.ts +9 -0
- package/dist/core/adapters/types.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.d.ts +1 -1
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +2 -7
- package/dist/core/agents/cli.js +25 -16
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +7 -2
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +2 -0
- package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/claim-conflict.js +3 -9
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/commit-conflict.js +2 -8
- package/dist/core/agents/rules/stop-hook.d.ts +2 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +1 -1
- package/dist/core/agents/session-events.d.ts +6 -2
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +105 -26
- package/dist/core/agents/session-finalization-state-v3.d.ts.map +1 -1
- package/dist/core/agents/session-finalization-state-v3.js +2 -1
- package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -1
- package/dist/core/agents/session-finalizer-v3.js +5 -4
- package/dist/core/agents/session-name-display.d.ts +28 -0
- package/dist/core/agents/session-name-display.d.ts.map +1 -1
- package/dist/core/agents/session-name-display.js +43 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts +7 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.d.ts +10 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +21 -2
- package/dist/core/agents/state/live-coordination-view.d.ts +20 -0
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +61 -0
- package/dist/core/agents/state/live-coordination-writer.js +3 -0
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +2 -10
- package/dist/core/agents/turn-changes.d.ts +17 -0
- package/dist/core/agents/turn-changes.d.ts.map +1 -0
- package/dist/core/agents/turn-changes.js +76 -0
- package/dist/core/artifacts/delivery-card.d.ts.map +1 -1
- package/dist/core/artifacts/delivery-card.js +11 -3
- package/dist/core/artifacts/index.d.ts +140 -4
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +526 -52
- package/dist/core/config.d.ts +73 -11
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +142 -3
- package/dist/core/context/index.d.ts.map +1 -1
- package/dist/core/context/index.js +2 -1
- package/dist/core/conversations/archive.d.ts.map +1 -1
- package/dist/core/conversations/archive.js +4 -3
- package/dist/core/diagnostics/bundle.d.ts.map +1 -1
- package/dist/core/diagnostics/bundle.js +5 -4
- package/dist/core/events/legacy-storage/canary.d.ts.map +1 -1
- package/dist/core/events/legacy-storage/canary.js +5 -4
- package/dist/core/events/legacy-storage/compression.d.ts.map +1 -1
- package/dist/core/events/legacy-storage/compression.js +2 -1
- package/dist/core/events/v3/adapter-id.d.ts +10 -2
- package/dist/core/events/v3/adapter-id.d.ts.map +1 -1
- package/dist/core/events/v3/adapter-id.js +16 -0
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +2 -1
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +5 -4
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +17 -0
- package/dist/core/events/v3/contract.d.ts +5 -0
- package/dist/core/events/v3/contract.d.ts.map +1 -1
- package/dist/core/events/v3/contract.js +7 -1
- package/dist/core/events/v3/control-witness.d.ts.map +1 -1
- package/dist/core/events/v3/control-witness.js +3 -2
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-transaction-recovery.js +4 -3
- package/dist/core/events/v3/fingerprint-keys.d.ts.map +1 -1
- package/dist/core/events/v3/fingerprint-keys.js +7 -6
- package/dist/core/events/v3/generated.d.ts +1 -1
- package/dist/core/events/v3/generated.js +1 -1
- package/dist/core/events/v3/live-feed.d.ts.map +1 -1
- package/dist/core/events/v3/live-feed.js +5 -4
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/command-recorder.js +8 -7
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +8 -7
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -1
- package/dist/core/events/v3/producers/diagnostic-summaries.js +5 -4
- package/dist/core/events/v3/producers/hook-base.d.ts +1 -0
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +10 -4
- package/dist/core/events/v3/producers/hook.d.ts +2 -0
- package/dist/core/events/v3/producers/hook.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook.js +16 -1
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +16 -6
- package/dist/core/events/v3/producers/recorder.d.ts +2 -4
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +125 -101
- package/dist/core/events/v3/projection.js +9 -1
- package/dist/core/events/v3/recovery.d.ts.map +1 -1
- package/dist/core/events/v3/recovery.js +4 -3
- package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/inventory.js +2 -1
- package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/maintenance.js +4 -3
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/pack-reader.js +4 -3
- package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -1
- package/dist/core/events/v3/support-storage/pack-writer.js +6 -5
- package/dist/core/events/v3/tool-line-changes.d.ts +8 -0
- package/dist/core/events/v3/tool-line-changes.d.ts.map +1 -0
- package/dist/core/events/v3/tool-line-changes.js +135 -0
- package/dist/core/events/v3/writer.d.ts.map +1 -1
- package/dist/core/events/v3/writer.js +8 -7
- package/dist/core/governor/planning.d.ts.map +1 -1
- package/dist/core/governor/planning.js +6 -5
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +12 -11
- package/dist/core/governor/state.d.ts.map +1 -1
- package/dist/core/governor/state.js +7 -6
- package/dist/core/guard/evaluator.js +1 -0
- package/dist/core/guard/storage.d.ts.map +1 -1
- package/dist/core/guard/storage.js +3 -2
- package/dist/core/hooks/adapter/behaviors/claude-code.d.ts +4 -0
- package/dist/core/hooks/adapter/behaviors/claude-code.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/claude-code.js +31 -0
- package/dist/core/hooks/adapter/behaviors/codex.d.ts +15 -0
- package/dist/core/hooks/adapter/behaviors/codex.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/codex.js +82 -0
- package/dist/core/hooks/adapter/behaviors/cursor.d.ts +7 -0
- package/dist/core/hooks/adapter/behaviors/cursor.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/cursor.js +35 -0
- package/dist/core/hooks/adapter/behaviors/index.d.ts +11 -0
- package/dist/core/hooks/adapter/behaviors/index.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/index.js +20 -0
- package/dist/core/hooks/adapter/behaviors/openclaw.d.ts +7 -0
- package/dist/core/hooks/adapter/behaviors/openclaw.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/openclaw.js +34 -0
- package/dist/core/hooks/adapter/behaviors/opencode.d.ts +7 -0
- package/dist/core/hooks/adapter/behaviors/opencode.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/opencode.js +34 -0
- package/dist/core/hooks/adapter/behaviors/types.d.ts +89 -0
- package/dist/core/hooks/adapter/behaviors/types.d.ts.map +1 -0
- package/dist/core/hooks/adapter/behaviors/types.js +1 -0
- package/dist/core/hooks/adapter/detect.d.ts +1 -1
- package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
- package/dist/core/hooks/adapter/detect.js +2 -3
- package/dist/core/hooks/adapter/events.d.ts +46 -1
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +36 -0
- package/dist/core/hooks/adapter/opencode-plugin.d.ts +60 -0
- package/dist/core/hooks/adapter/opencode-plugin.d.ts.map +1 -0
- package/dist/core/hooks/adapter/opencode-plugin.js +129 -0
- package/dist/core/hooks/adapter/output.d.ts +7 -0
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +8 -1
- package/dist/core/hooks/adapter/runtime-telemetry.js +3 -1
- package/dist/core/hooks/adapter/wiring.d.ts +52 -8
- package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
- package/dist/core/hooks/adapter/wiring.js +133 -12
- package/dist/core/hooks/cli.js +676 -531
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +2 -1
- package/dist/core/hooks/prompt-context/contract.d.ts.map +1 -1
- package/dist/core/hooks/prompt-context/contract.js +1 -0
- package/dist/core/hooks/resolve/transcript.d.ts +1 -1
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +35 -4
- package/dist/core/hooks/run-markers.d.ts +37 -0
- package/dist/core/hooks/run-markers.d.ts.map +1 -0
- package/dist/core/hooks/run-markers.js +109 -0
- package/dist/core/hooks/session-name-presence.d.ts +3 -1
- package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
- package/dist/core/hooks/session-name-presence.js +7 -2
- package/dist/core/hooks/shell-waiter.d.ts +2 -0
- package/dist/core/hooks/shell-waiter.d.ts.map +1 -0
- package/dist/core/hooks/shell-waiter.js +173 -0
- package/dist/core/resources/service.d.ts.map +1 -1
- package/dist/core/resources/service.js +5 -4
- package/dist/core/semantic/review.d.ts.map +1 -1
- package/dist/core/semantic/review.js +5 -4
- package/dist/core/semantic/service.d.ts.map +1 -1
- package/dist/core/semantic/service.js +15 -14
- package/dist/core/semantic/storage.d.ts.map +1 -1
- package/dist/core/semantic/storage.js +5 -4
- package/dist/core/servers/index.d.ts +211 -0
- package/dist/core/servers/index.d.ts.map +1 -0
- package/dist/core/servers/index.js +560 -0
- package/dist/core/servers/net.d.ts +58 -0
- package/dist/core/servers/net.d.ts.map +1 -0
- package/dist/core/servers/net.js +270 -0
- package/dist/core/servers/tunnels.d.ts +14 -0
- package/dist/core/servers/tunnels.d.ts.map +1 -0
- package/dist/core/servers/tunnels.js +33 -0
- package/dist/core/storage/atomic-json.d.ts.map +1 -1
- package/dist/core/storage/atomic-json.js +7 -3
- package/dist/core/storage/builtins.js +1 -0
- package/dist/core/storage/durable-history.d.ts.map +1 -1
- package/dist/core/storage/durable-history.js +6 -5
- package/dist/core/storage/maintenance-providers.d.ts.map +1 -1
- package/dist/core/storage/maintenance-providers.js +2 -1
- package/dist/core/storage/maintenance.d.ts.map +1 -1
- package/dist/core/storage/maintenance.js +7 -6
- package/dist/core/storage/metrics.d.ts.map +1 -1
- package/dist/core/storage/metrics.js +5 -1
- package/dist/core/storage/modes.d.ts +17 -0
- package/dist/core/storage/modes.d.ts.map +1 -0
- package/dist/core/storage/modes.js +47 -0
- package/dist/core/storage/process-log.d.ts.map +1 -1
- package/dist/core/storage/process-log.js +3 -2
- package/dist/core/storage/receipts.d.ts.map +1 -1
- package/dist/core/storage/receipts.js +4 -3
- package/dist/core/storage/segments.d.ts.map +1 -1
- package/dist/core/storage/segments.js +7 -6
- package/dist/core/supervisor/hook-health.d.ts +2 -1
- package/dist/core/supervisor/hook-health.d.ts.map +1 -1
- package/dist/core/supervisor/hook-health.js +4 -3
- package/dist/core/supervisor/service.d.ts.map +1 -1
- package/dist/core/supervisor/service.js +7 -6
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +8 -7
- package/dist/core/workflow/adapters.d.ts +7 -0
- package/dist/core/workflow/adapters.d.ts.map +1 -1
- package/dist/core/workflow/adapters.js +9 -0
- package/dist/core/workflow/approvals.d.ts.map +1 -1
- package/dist/core/workflow/approvals.js +6 -5
- package/dist/core/workflow/billing.d.ts.map +1 -1
- package/dist/core/workflow/billing.js +33 -4
- package/dist/core/workflow/durable-record.d.ts.map +1 -1
- package/dist/core/workflow/durable-record.js +4 -3
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +30 -1
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +2 -3
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +3 -2
- package/dist/core/workflow/sandbox-projection.d.ts +13 -2
- package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
- package/dist/core/workflow/sandbox-projection.js +23 -0
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +6 -1
- package/dist/core/workflow/spawn-codex.d.ts +2 -0
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +20 -1
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +6 -1
- package/dist/core/workflow/spawn-opencode.d.ts +36 -0
- package/dist/core/workflow/spawn-opencode.d.ts.map +1 -0
- package/dist/core/workflow/spawn-opencode.js +135 -0
- package/dist/core/workflow/transcript.d.ts.map +1 -1
- package/dist/core/workflow/transcript.js +3 -2
- package/dist/core/workflow/types.d.ts +47 -2
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/worker-access.d.ts +92 -0
- package/dist/core/workflow/worker-access.d.ts.map +1 -0
- package/dist/core/workflow/worker-access.js +450 -0
- package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/leases.js +5 -4
- package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.js +3 -2
- package/dist/core/workflow/workspaces/paths.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/paths.js +2 -1
- package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/state.js +10 -9
- package/dist/lazy-commands.js +8 -1
- package/dist/lib/agent-browser/client.d.ts +9 -0
- package/dist/lib/agent-browser/client.d.ts.map +1 -1
- package/dist/lib/agent-browser/client.js +13 -0
- package/dist/lib/browser/batch-steps.d.ts +18 -0
- package/dist/lib/browser/batch-steps.d.ts.map +1 -0
- package/dist/lib/browser/batch-steps.js +82 -0
- package/dist/lib/browser/client.d.ts +35 -1
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +117 -8
- package/dist/lib/browser/collect/collector.d.ts +99 -0
- package/dist/lib/browser/collect/collector.d.ts.map +1 -0
- package/dist/lib/browser/collect/collector.js +202 -0
- package/dist/lib/browser/collect/fields.d.ts +31 -0
- package/dist/lib/browser/collect/fields.d.ts.map +1 -0
- package/dist/lib/browser/collect/fields.js +75 -0
- package/dist/lib/browser/collect/index.d.ts +6 -0
- package/dist/lib/browser/collect/index.d.ts.map +1 -0
- package/dist/lib/browser/collect/index.js +5 -0
- package/dist/lib/browser/collect/page-driver.d.ts +14 -0
- package/dist/lib/browser/collect/page-driver.d.ts.map +1 -0
- package/dist/lib/browser/collect/page-driver.js +306 -0
- package/dist/lib/browser/collect/presets.d.ts +52 -0
- package/dist/lib/browser/collect/presets.d.ts.map +1 -0
- package/dist/lib/browser/collect/presets.js +176 -0
- package/dist/lib/browser/collect/scroll-plan.d.ts +85 -0
- package/dist/lib/browser/collect/scroll-plan.d.ts.map +1 -0
- package/dist/lib/browser/collect/scroll-plan.js +118 -0
- package/dist/lib/browser/identity.d.ts +25 -0
- package/dist/lib/browser/identity.d.ts.map +1 -0
- package/dist/lib/browser/identity.js +66 -0
- package/dist/lib/browser/index.d.ts +3 -2
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -1
- package/dist/lib/browser/launch-args.d.ts +26 -0
- package/dist/lib/browser/launch-args.d.ts.map +1 -1
- package/dist/lib/browser/launch-args.js +41 -1
- package/dist/lib/browser/page-review-judge.d.ts +2 -0
- package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
- package/dist/lib/browser/page-review-judge.js +13 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +10 -0
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.js +1 -0
- package/dist/lib/browser/user-agent.d.ts +53 -0
- package/dist/lib/browser/user-agent.d.ts.map +1 -0
- package/dist/lib/browser/user-agent.js +79 -0
- package/dist/lib/browser/windows-chrome.d.ts +59 -0
- package/dist/lib/browser/windows-chrome.d.ts.map +1 -0
- package/dist/lib/browser/windows-chrome.js +179 -0
- package/dist/lib/claude-desktop-share.d.ts +136 -0
- package/dist/lib/claude-desktop-share.d.ts.map +1 -0
- package/dist/lib/claude-desktop-share.js +394 -0
- package/dist/lib/disk-usage.d.ts +50 -0
- package/dist/lib/disk-usage.d.ts.map +1 -0
- package/dist/lib/disk-usage.js +303 -0
- package/dist/lib/docs-lint.d.ts +6 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +8 -3
- package/dist/lib/docs-metadata-managed.d.ts +1 -0
- package/dist/lib/docs-metadata-managed.d.ts.map +1 -1
- package/dist/lib/docs-metadata-managed.js +17 -1
- package/dist/lib/guarded-remove.d.ts +34 -0
- package/dist/lib/guarded-remove.d.ts.map +1 -0
- package/dist/lib/guarded-remove.js +310 -0
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +4 -9
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +2 -0
- package/dist/lib/instructions/templates.js +8 -8
- package/dist/lib/pace/index.d.ts +2 -0
- package/dist/lib/pace/index.d.ts.map +1 -0
- package/dist/lib/pace/index.js +1 -0
- package/dist/lib/pace/pace.d.ts +95 -0
- package/dist/lib/pace/pace.d.ts.map +1 -0
- package/dist/lib/pace/pace.js +313 -0
- package/dist/lib/tunnel/error-page.d.ts +1 -1
- package/dist/lib/tunnel/error-page.d.ts.map +1 -1
- package/dist/lib/tunnel/error-page.js +19 -8
- package/dist/lib/tunnel/forward-headers.d.ts +11 -0
- package/dist/lib/tunnel/forward-headers.d.ts.map +1 -0
- package/dist/lib/tunnel/forward-headers.js +17 -0
- package/dist/lib/tunnel/gate.js +34 -10
- package/dist/lib/tunnel/path-scope.d.ts +22 -0
- package/dist/lib/tunnel/path-scope.d.ts.map +1 -0
- package/dist/lib/tunnel/path-scope.js +62 -0
- package/dist/lib/tunnel/state.d.ts +5 -0
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +17 -3
- package/dist/lib/webview/index.d.ts +2 -0
- package/dist/lib/webview/index.d.ts.map +1 -0
- package/dist/lib/webview/index.js +1 -0
- package/dist/lib/webview/webview.d.ts +116 -0
- package/dist/lib/webview/webview.d.ts.map +1 -0
- package/dist/lib/webview/webview.js +289 -0
- package/opencode-plugin/package.json +19 -0
- package/opencode-plugin/src/index.ts +791 -0
- package/package.json +16 -4
- package/schemas/config.schema.json +104 -0
- package/schemas/event-v3.schema.json +164 -0
- package/src/commander.ts +26 -0
- package/src/commands/agents.ts +47 -18
- package/src/commands/artifacts.ts +171 -19
- package/src/commands/browse-ai.ts +8 -0
- package/src/commands/browse.ts +570 -48
- package/src/commands/checkpoint.ts +7 -9
- package/src/commands/claude-desktop.ts +61 -0
- package/src/commands/deinit.ts +9 -4
- package/src/commands/disk.ts +114 -0
- package/src/commands/docs.ts +2 -0
- package/src/commands/doctor.ts +63 -3
- package/src/commands/fetch.ts +14 -0
- package/src/commands/files.ts +93 -2
- package/src/commands/init.ts +334 -122
- package/src/commands/instructions.ts +8 -4
- package/src/commands/ledger-v3.ts +2 -1
- package/src/commands/rm.ts +115 -0
- package/src/commands/servers.ts +506 -0
- package/src/commands/tunnel.ts +102 -2
- package/src/commands/webview.ts +159 -0
- package/src/core/adapter.ts +102 -1
- package/src/core/adapters/attestation.ts +3 -2
- package/src/core/adapters/profiles.ts +63 -1
- package/src/core/adapters/registry.ts +37 -0
- package/src/core/adapters/types.ts +10 -0
- package/src/core/agents/canonical-emit.ts +2 -5
- package/src/core/agents/cli.ts +26 -17
- package/src/core/agents/coord-client.ts +9 -3
- package/src/core/agents/render/session-context.ts +1 -0
- package/src/core/agents/rules/claim-conflict.ts +3 -8
- package/src/core/agents/rules/commit-conflict.ts +2 -7
- package/src/core/agents/rules/stop-hook.ts +3 -1
- package/src/core/agents/session-events.ts +120 -26
- package/src/core/agents/session-finalization-state-v3.ts +2 -1
- package/src/core/agents/session-finalizer-v3.ts +5 -4
- package/src/core/agents/session-name-display.ts +48 -0
- package/src/core/agents/state/heartbeat-reader.ts +7 -0
- package/src/core/agents/state/heartbeat-writer.ts +24 -2
- package/src/core/agents/state/live-coordination-view.ts +74 -0
- package/src/core/agents/state/live-coordination-writer.ts +3 -0
- package/src/core/agents/state/stale-sweep.ts +2 -9
- package/src/core/agents/turn-changes.ts +97 -0
- package/src/core/artifacts/delivery-card.ts +12 -3
- package/src/core/artifacts/index.ts +701 -47
- package/src/core/config.ts +206 -4
- package/src/core/context/index.ts +2 -1
- package/src/core/conversations/archive.ts +4 -3
- package/src/core/diagnostics/bundle.ts +5 -3
- package/src/core/events/legacy-storage/canary.ts +5 -4
- package/src/core/events/legacy-storage/compression.ts +2 -1
- package/src/core/events/v3/adapter-id.ts +29 -1
- package/src/core/events/v3/authority-outbox.ts +2 -1
- package/src/core/events/v3/bootstrap.ts +5 -4
- package/src/core/events/v3/capabilities.ts +17 -0
- package/src/core/events/v3/contract.ts +9 -1
- package/src/core/events/v3/control-witness.ts +3 -2
- package/src/core/events/v3/coordination-transaction-recovery.ts +4 -3
- package/src/core/events/v3/fingerprint-keys.ts +7 -6
- package/src/core/events/v3/generated.ts +1 -1
- package/src/core/events/v3/live-feed.ts +5 -4
- package/src/core/events/v3/producers/command-recorder.ts +8 -6
- package/src/core/events/v3/producers/coordination-recorder.ts +8 -7
- package/src/core/events/v3/producers/diagnostic-summaries.ts +5 -4
- package/src/core/events/v3/producers/hook-base.ts +11 -4
- package/src/core/events/v3/producers/hook.ts +19 -1
- package/src/core/events/v3/producers/intake.ts +18 -6
- package/src/core/events/v3/producers/recorder.ts +139 -114
- package/src/core/events/v3/projection.ts +11 -1
- package/src/core/events/v3/recovery.ts +4 -3
- package/src/core/events/v3/support-storage/inventory.ts +2 -1
- package/src/core/events/v3/support-storage/maintenance.ts +8 -3
- package/src/core/events/v3/support-storage/pack-reader.ts +4 -3
- package/src/core/events/v3/support-storage/pack-writer.ts +6 -5
- package/src/core/events/v3/tool-line-changes.ts +139 -0
- package/src/core/events/v3/writer.ts +8 -7
- package/src/core/governor/planning.ts +6 -5
- package/src/core/governor/service.ts +12 -11
- package/src/core/governor/state.ts +7 -6
- package/src/core/guard/evaluator.ts +1 -0
- package/src/core/guard/storage.ts +3 -2
- package/src/core/hooks/adapter/behaviors/claude-code.ts +33 -0
- package/src/core/hooks/adapter/behaviors/codex.ts +96 -0
- package/src/core/hooks/adapter/behaviors/cursor.ts +37 -0
- package/src/core/hooks/adapter/behaviors/index.ts +31 -0
- package/src/core/hooks/adapter/behaviors/openclaw.ts +36 -0
- package/src/core/hooks/adapter/behaviors/opencode.ts +36 -0
- package/src/core/hooks/adapter/behaviors/types.ts +110 -0
- package/src/core/hooks/adapter/detect.ts +2 -3
- package/src/core/hooks/adapter/events.ts +72 -1
- package/src/core/hooks/adapter/opencode-plugin.ts +177 -0
- package/src/core/hooks/adapter/output.ts +8 -1
- package/src/core/hooks/adapter/runtime-telemetry.ts +3 -1
- package/src/core/hooks/adapter/wiring.ts +198 -16
- package/src/core/hooks/cli.ts +776 -539
- package/src/core/hooks/effects/image-capture.ts +2 -1
- package/src/core/hooks/prompt-context/contract.ts +1 -0
- package/src/core/hooks/resolve/transcript.ts +42 -5
- package/src/core/hooks/run-markers.ts +132 -0
- package/src/core/hooks/session-name-presence.ts +10 -3
- package/src/core/hooks/shell-waiter.ts +166 -0
- package/src/core/resources/service.ts +5 -4
- package/src/core/semantic/review.ts +5 -4
- package/src/core/semantic/service.ts +15 -14
- package/src/core/semantic/storage.ts +5 -4
- package/src/core/servers/index.ts +712 -0
- package/src/core/servers/net.ts +283 -0
- package/src/core/servers/tunnels.ts +39 -0
- package/src/core/storage/atomic-json.ts +7 -3
- package/src/core/storage/builtins.ts +1 -0
- package/src/core/storage/durable-history.ts +6 -5
- package/src/core/storage/maintenance-providers.ts +2 -1
- package/src/core/storage/maintenance.ts +7 -6
- package/src/core/storage/metrics.ts +5 -1
- package/src/core/storage/modes.ts +53 -0
- package/src/core/storage/process-log.ts +3 -2
- package/src/core/storage/receipts.ts +4 -3
- package/src/core/storage/segments.ts +7 -6
- package/src/core/supervisor/hook-health.ts +4 -4
- package/src/core/supervisor/service.ts +7 -6
- package/src/core/work/state.ts +8 -7
- package/src/core/workflow/adapters.ts +15 -0
- package/src/core/workflow/approvals.ts +6 -5
- package/src/core/workflow/billing.ts +34 -4
- package/src/core/workflow/durable-record.ts +4 -3
- package/src/core/workflow/engine.ts +38 -1
- package/src/core/workflow/live-session-v3.ts +2 -3
- package/src/core/workflow/run-state.ts +3 -2
- package/src/core/workflow/sandbox-projection.ts +38 -2
- package/src/core/workflow/spawn-claude.ts +5 -1
- package/src/core/workflow/spawn-codex.ts +18 -1
- package/src/core/workflow/spawn-cursor.ts +5 -1
- package/src/core/workflow/spawn-opencode.ts +153 -0
- package/src/core/workflow/transcript.ts +3 -2
- package/src/core/workflow/types.ts +62 -2
- package/src/core/workflow/worker-access.ts +525 -0
- package/src/core/workflow/workspaces/leases.ts +5 -4
- package/src/core/workflow/workspaces/local-git.ts +3 -2
- package/src/core/workflow/workspaces/paths.ts +2 -1
- package/src/core/workflow/workspaces/state.ts +10 -9
- package/src/lazy-commands.ts +11 -1
- package/src/lib/agent-browser/client.ts +18 -0
- package/src/lib/browser/batch-steps.ts +79 -0
- package/src/lib/browser/client.ts +147 -9
- package/src/lib/browser/collect/collector.ts +306 -0
- package/src/lib/browser/collect/fields.ts +87 -0
- package/src/lib/browser/collect/index.ts +47 -0
- package/src/lib/browser/collect/page-driver.ts +327 -0
- package/src/lib/browser/collect/presets.ts +237 -0
- package/src/lib/browser/collect/scroll-plan.ts +179 -0
- package/src/lib/browser/identity.ts +64 -0
- package/src/lib/browser/index.ts +16 -1
- package/src/lib/browser/launch-args.ts +53 -1
- package/src/lib/browser/page-review-judge.ts +16 -0
- package/src/lib/browser/qa-run-contracts.ts +11 -0
- package/src/lib/browser/qa-run.ts +1 -0
- package/src/lib/browser/user-agent.ts +130 -0
- package/src/lib/browser/windows-chrome.ts +227 -0
- package/src/lib/claude-desktop-share.ts +511 -0
- package/src/lib/disk-usage.ts +347 -0
- package/src/lib/docs-lint.ts +8 -3
- package/src/lib/docs-metadata-managed.ts +21 -0
- package/src/lib/guarded-remove.ts +376 -0
- package/src/lib/identities/assume.ts +7 -7
- package/src/lib/instructions/apply.ts +2 -0
- package/src/lib/instructions/templates.ts +8 -8
- package/src/lib/pace/index.ts +14 -0
- package/src/lib/pace/pace.ts +370 -0
- package/src/lib/tunnel/error-page.ts +25 -9
- package/src/lib/tunnel/forward-headers.ts +16 -0
- package/src/lib/tunnel/gate.ts +39 -10
- package/src/lib/tunnel/path-scope.ts +73 -0
- package/src/lib/tunnel/state.ts +20 -3
- package/src/lib/webview/index.ts +13 -0
- package/src/lib/webview/webview.ts +457 -0
|
@@ -22,6 +22,7 @@ import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
|
22
22
|
import { buildEventV3 } from "../../events/v3/builder.ts";
|
|
23
23
|
import type { EventV3 } from "../../events/v3/contract.ts";
|
|
24
24
|
import { writeEventV3 } from "../../events/v3/writer.ts";
|
|
25
|
+
import { stateFileMode } from "../../storage/modes.ts";
|
|
25
26
|
import type { ParsedPayload } from "../adapter/parse.ts";
|
|
26
27
|
|
|
27
28
|
const IMAGE_EXTS = new Set(["png", "jpg", "jpeg", "gif", "webp", "bmp", "svg"]);
|
|
@@ -258,7 +259,7 @@ function captureOne(
|
|
|
258
259
|
if (!existsSync(destination)) {
|
|
259
260
|
mkdirSync(imagesDir, { recursive: true });
|
|
260
261
|
const temporary = `${destination}.tmp.${process.pid}.${randomUUID().slice(0, 8)}`;
|
|
261
|
-
writeFileSync(temporary, bytes, { mode:
|
|
262
|
+
writeFileSync(temporary, bytes, { mode: stateFileMode() });
|
|
262
263
|
renameSync(temporary, destination);
|
|
263
264
|
}
|
|
264
265
|
return { hash, ext, bytes: stat.size };
|
|
@@ -71,6 +71,7 @@ const DELIVERY_BY_ADAPTER: Readonly<Record<Adapter, PromptContextDelivery>> = {
|
|
|
71
71
|
"claude-code": "direct",
|
|
72
72
|
codex: "direct",
|
|
73
73
|
cursor: "direct",
|
|
74
|
+
opencode: "direct",
|
|
74
75
|
};
|
|
75
76
|
|
|
76
77
|
export function promptContextDelivery(adapter: Adapter): PromptContextDelivery {
|
|
@@ -132,7 +132,10 @@ export function scanSessionNameDisplayedImmediately(
|
|
|
132
132
|
export type SessionNameDisplayInspection =
|
|
133
133
|
| { state: "present" }
|
|
134
134
|
| { state: "absent" }
|
|
135
|
-
| {
|
|
135
|
+
| {
|
|
136
|
+
state: "unavailable";
|
|
137
|
+
reason: "missing_transcript" | "transcript_not_ready" | "transcript_parse_error";
|
|
138
|
+
};
|
|
136
139
|
|
|
137
140
|
/**
|
|
138
141
|
* Inspect the ordered post-mint reply without conflating a malformed display
|
|
@@ -152,17 +155,34 @@ export function inspectSessionNameDisplayImmediately(
|
|
|
152
155
|
if (!text) return { state: "unavailable", reason: "transcript_not_ready" };
|
|
153
156
|
let sawMintResult = false;
|
|
154
157
|
let awaitingReply = false;
|
|
158
|
+
let sawParseError = false;
|
|
159
|
+
let missedReplyAtToolBoundary = false;
|
|
155
160
|
for (const line of text.split("\n")) {
|
|
156
161
|
const row = parseTranscriptRow(line);
|
|
157
|
-
if (!row)
|
|
162
|
+
if (!row) {
|
|
163
|
+
if (line.trim()) {
|
|
164
|
+
sawParseError = true;
|
|
165
|
+
// A corrupt row inside the evidence window could be the display.
|
|
166
|
+
// Never turn lost evidence into a negative observation.
|
|
167
|
+
if (awaitingReply) return { state: "unavailable", reason: "transcript_parse_error" };
|
|
168
|
+
}
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
158
171
|
if (toolResponseMintedSessionName(row, name)) {
|
|
159
172
|
sawMintResult = true;
|
|
160
173
|
awaitingReply = true;
|
|
174
|
+
missedReplyAtToolBoundary = false;
|
|
161
175
|
continue;
|
|
162
176
|
}
|
|
163
177
|
if (!awaitingReply) continue;
|
|
164
178
|
const assistantText = assistantTextFromRow(row);
|
|
165
|
-
if (assistantText
|
|
179
|
+
if (!assistantText?.trim() && rowContainsAssistantToolCall(row)) {
|
|
180
|
+
missedReplyAtToolBoundary = true;
|
|
181
|
+
}
|
|
182
|
+
// Claude Code streams thinking, text, and tool_use as separate rows with
|
|
183
|
+
// the same message id. Only visible text can satisfy or violate the
|
|
184
|
+
// display contract; an empty extraction is not a mismatching reply.
|
|
185
|
+
if (assistantText !== null && assistantText.trim().length > 0) {
|
|
166
186
|
if (startsWithBlock(assistantText, name)) return { state: "present" };
|
|
167
187
|
awaitingReply = false;
|
|
168
188
|
}
|
|
@@ -173,12 +193,29 @@ export function inspectSessionNameDisplayImmediately(
|
|
|
173
193
|
// rather than proof that the agent displayed the title incorrectly. Only a
|
|
174
194
|
// transcript that contains the mint followed by a non-matching assistant
|
|
175
195
|
// reply can safely deny the next tool.
|
|
176
|
-
if (!sawMintResult || awaitingReply) {
|
|
177
|
-
return {
|
|
196
|
+
if (!sawMintResult || awaitingReply || missedReplyAtToolBoundary) {
|
|
197
|
+
return {
|
|
198
|
+
state: "unavailable",
|
|
199
|
+
reason: !sawMintResult && sawParseError ? "transcript_parse_error" : "transcript_not_ready",
|
|
200
|
+
};
|
|
178
201
|
}
|
|
179
202
|
return { state: "absent" };
|
|
180
203
|
}
|
|
181
204
|
|
|
205
|
+
function rowContainsAssistantToolCall(row: Record<string, unknown>): boolean {
|
|
206
|
+
if (row.type === "assistant") {
|
|
207
|
+
const content = objectValue(row.message)?.content;
|
|
208
|
+
return (
|
|
209
|
+
Array.isArray(content) && content.some((block) => objectValue(block)?.type === "tool_use")
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
if (row.type === "response_item") {
|
|
213
|
+
const type = objectValue(row.payload)?.type;
|
|
214
|
+
return type === "function_call" || type === "custom_tool_call";
|
|
215
|
+
}
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
182
219
|
/**
|
|
183
220
|
* Resolve a transcript path at the adapter boundary. Windows-native Codex can
|
|
184
221
|
* send `C:\...` while the managed hook executes inside WSL, where the same
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Start markers for hook runs on adapters that kill a hook at its `timeout`
|
|
3
|
+
* (ADR 0197). A Codex hook that times out has its process tree killed and the
|
|
4
|
+
* tool proceeds without that hook's checks, and the killed process never
|
|
5
|
+
* reaches the completion receipt in `health.ts`. A small marker written at
|
|
6
|
+
* start and removed at completion leaves evidence of that case for doctor.
|
|
7
|
+
*
|
|
8
|
+
* Observer-only: every write, read, and removal swallows its own errors so a
|
|
9
|
+
* marker can never change hook behavior.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
|
|
15
|
+
/** Markers older than this are pruned when a new one is written. */
|
|
16
|
+
const MARKER_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
17
|
+
/** A run is unfinished once its marker outlives the timeout by this much. */
|
|
18
|
+
const UNFINISHED_GRACE_MS = 30_000;
|
|
19
|
+
|
|
20
|
+
export interface HookRunMarker {
|
|
21
|
+
event: string;
|
|
22
|
+
adapter: string;
|
|
23
|
+
pid: number;
|
|
24
|
+
started_at: string;
|
|
25
|
+
timeout_sec: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function hookRunMarkerDir(coordRoot: string): string {
|
|
29
|
+
return join(coordRoot, ".harnery", "active", "hook-runs");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Write this run's marker; returns its path, or null when it could not be written. */
|
|
33
|
+
export function writeHookRunMarker(
|
|
34
|
+
coordRoot: string,
|
|
35
|
+
marker: Omit<HookRunMarker, "started_at">,
|
|
36
|
+
now = new Date(),
|
|
37
|
+
): string | null {
|
|
38
|
+
try {
|
|
39
|
+
const dir = hookRunMarkerDir(coordRoot);
|
|
40
|
+
mkdirSync(dir, { recursive: true });
|
|
41
|
+
pruneHookRunMarkers(dir, now.getTime());
|
|
42
|
+
const path = join(dir, `${marker.pid}-${safeName(marker.event)}.json`);
|
|
43
|
+
const body: HookRunMarker = { ...marker, started_at: now.toISOString() };
|
|
44
|
+
writeFileSync(path, `${JSON.stringify(body)}\n`);
|
|
45
|
+
return path;
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function clearHookRunMarker(path: string | null): void {
|
|
52
|
+
if (!path) return;
|
|
53
|
+
try {
|
|
54
|
+
rmSync(path, { force: true });
|
|
55
|
+
} catch {
|
|
56
|
+
// Observer-only.
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface UnfinishedHookRuns {
|
|
61
|
+
count: number;
|
|
62
|
+
/** Count per event name, most frequent first. */
|
|
63
|
+
events: Array<{ event: string; count: number }>;
|
|
64
|
+
latest: string | null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Markers whose run outlived its timeout plus a grace period and whose
|
|
69
|
+
* process is gone, within the window. A live process past its timeout is
|
|
70
|
+
* still running and is not counted.
|
|
71
|
+
*/
|
|
72
|
+
export function findUnfinishedHookRuns(
|
|
73
|
+
coordRoot: string,
|
|
74
|
+
nowMs = Date.now(),
|
|
75
|
+
windowMs = 24 * 60 * 60 * 1000,
|
|
76
|
+
isAlive: (pid: number) => boolean = processAlive,
|
|
77
|
+
): UnfinishedHookRuns {
|
|
78
|
+
const counts = new Map<string, number>();
|
|
79
|
+
let latest: string | null = null;
|
|
80
|
+
let count = 0;
|
|
81
|
+
let names: string[] = [];
|
|
82
|
+
try {
|
|
83
|
+
names = readdirSync(hookRunMarkerDir(coordRoot)).filter((n) => n.endsWith(".json"));
|
|
84
|
+
} catch {
|
|
85
|
+
return { count: 0, events: [], latest: null };
|
|
86
|
+
}
|
|
87
|
+
for (const name of names) {
|
|
88
|
+
let marker: HookRunMarker;
|
|
89
|
+
try {
|
|
90
|
+
marker = JSON.parse(
|
|
91
|
+
readFileSync(join(hookRunMarkerDir(coordRoot), name), "utf8"),
|
|
92
|
+
) as HookRunMarker;
|
|
93
|
+
} catch {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const started = Date.parse(marker.started_at);
|
|
97
|
+
if (!Number.isFinite(started) || nowMs - started > windowMs) continue;
|
|
98
|
+
if (nowMs - started < marker.timeout_sec * 1000 + UNFINISHED_GRACE_MS) continue;
|
|
99
|
+
if (isAlive(marker.pid)) continue;
|
|
100
|
+
count++;
|
|
101
|
+
counts.set(marker.event, (counts.get(marker.event) ?? 0) + 1);
|
|
102
|
+
if (!latest || marker.started_at > latest) latest = marker.started_at;
|
|
103
|
+
}
|
|
104
|
+
const events = [...counts.entries()]
|
|
105
|
+
.map(([event, n]) => ({ event, count: n }))
|
|
106
|
+
.sort((a, b) => b.count - a.count || a.event.localeCompare(b.event));
|
|
107
|
+
return { count, events, latest };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function pruneHookRunMarkers(dir: string, nowMs: number): void {
|
|
111
|
+
for (const name of readdirSync(dir)) {
|
|
112
|
+
const path = join(dir, name);
|
|
113
|
+
try {
|
|
114
|
+
if (nowMs - statSync(path).mtimeMs > MARKER_RETENTION_MS) rmSync(path, { force: true });
|
|
115
|
+
} catch {
|
|
116
|
+
// Observer-only.
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function processAlive(pid: number): boolean {
|
|
122
|
+
try {
|
|
123
|
+
process.kill(pid, 0);
|
|
124
|
+
return true;
|
|
125
|
+
} catch (err) {
|
|
126
|
+
return (err as NodeJS.ErrnoException).code === "EPERM";
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function safeName(value: string): string {
|
|
131
|
+
return value.replace(/[^a-zA-Z0-9._-]+/g, "-").slice(0, 64) || "unknown";
|
|
132
|
+
}
|
|
@@ -25,16 +25,18 @@
|
|
|
25
25
|
import { sessionNameDisplayAcceptedNames } from "../agents/session-name-display.ts";
|
|
26
26
|
import { stampSessionNameSeen } from "../agents/state/heartbeat-writer.ts";
|
|
27
27
|
import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.ts";
|
|
28
|
+
import type { SessionNameDisplayInspection } from "./resolve/transcript.ts";
|
|
28
29
|
|
|
29
30
|
export interface SessionNamePresence {
|
|
30
31
|
session_name_present?: boolean;
|
|
31
32
|
session_name_present_for?: string;
|
|
33
|
+
session_name_unavailable_reason?: string;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
export function sessionNamePresence(
|
|
35
37
|
coordRoot: string,
|
|
36
38
|
instanceId: string,
|
|
37
|
-
scanAssistantText: (name: string) =>
|
|
39
|
+
scanAssistantText: (name: string) => SessionNameDisplayInspection,
|
|
38
40
|
): SessionNamePresence {
|
|
39
41
|
try {
|
|
40
42
|
const row = readLiveCoordinationRow(coordRoot, instanceId);
|
|
@@ -45,12 +47,17 @@ export function sessionNamePresence(
|
|
|
45
47
|
}
|
|
46
48
|
// A display of the title Harnery last asked for counts here too, so Stop
|
|
47
49
|
// and the PreToolUse gate cannot disagree about the same reply.
|
|
48
|
-
const
|
|
50
|
+
const inspections = sessionNameDisplayAcceptedNames(row).map((candidate) =>
|
|
49
51
|
scanAssistantText(candidate),
|
|
50
52
|
);
|
|
53
|
+
const present = inspections.some((inspection) => inspection.state === "present");
|
|
54
|
+
const unavailable = inspections.find((inspection) => inspection.state === "unavailable");
|
|
55
|
+
if (!present && unavailable?.state === "unavailable") {
|
|
56
|
+
return { session_name_unavailable_reason: unavailable.reason };
|
|
57
|
+
}
|
|
51
58
|
if (present) stampSessionNameSeen(coordRoot, instanceId, name);
|
|
52
59
|
return { session_name_present: present, session_name_present_for: name };
|
|
53
60
|
} catch {
|
|
54
|
-
return {};
|
|
61
|
+
return { session_name_unavailable_reason: "observation_error" };
|
|
55
62
|
}
|
|
56
63
|
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/** Recognize inline waiters; this is not a proof of arbitrary shell termination. */
|
|
2
|
+
const REASON =
|
|
3
|
+
"Inline shell waiter blocked: polling loops and delayed log-only checks can outlive the job " +
|
|
4
|
+
"and accumulate as background tasks. Read the existing task output now, or wait on its " +
|
|
5
|
+
"existing task handle. If polling is necessary, use a reviewed script with a hard deadline, " +
|
|
6
|
+
"nonzero timeout exit, and producer-exit/failure detection. Do not create another waiter " +
|
|
7
|
+
"to check progress or infer completion from a broad pgrep -f pattern.";
|
|
8
|
+
|
|
9
|
+
interface Token {
|
|
10
|
+
value: string;
|
|
11
|
+
quoted: boolean;
|
|
12
|
+
operator?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Keep quoted arguments opaque, including examples and heredoc bodies. */
|
|
16
|
+
function tokenize(source: string): Token[] {
|
|
17
|
+
const out: Token[] = [];
|
|
18
|
+
const heredocs: { end: string; tabs: boolean }[] = [];
|
|
19
|
+
for (let i = 0; i < source.length; ) {
|
|
20
|
+
const ch = source[i]!;
|
|
21
|
+
if (ch === "\\" && source[i + 1] === "\n") {
|
|
22
|
+
i += 2;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (ch === "\n") {
|
|
26
|
+
out.push({ value: ";", quoted: false, operator: true });
|
|
27
|
+
i++;
|
|
28
|
+
for (const doc of heredocs.splice(0)) {
|
|
29
|
+
while (i < source.length) {
|
|
30
|
+
const end = source.indexOf("\n", i);
|
|
31
|
+
const stop = end === -1 ? source.length : end;
|
|
32
|
+
const line = source.slice(i, stop);
|
|
33
|
+
i = end === -1 ? source.length : end + 1;
|
|
34
|
+
if ((doc.tabs ? line.replace(/^\t+/, "") : line) === doc.end) break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (/\s/.test(ch)) {
|
|
40
|
+
i++;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (ch === "#") {
|
|
44
|
+
const end = source.indexOf("\n", i);
|
|
45
|
+
i = end === -1 ? source.length : end;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (";|&(){}<>".includes(ch)) {
|
|
49
|
+
const op = source.slice(i).match(/^(?:<<-?|>>|&&|\|\||[;|&(){}<>])/)![0];
|
|
50
|
+
out.push({ value: op, quoted: false, operator: true });
|
|
51
|
+
i += op.length;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
let value = "";
|
|
55
|
+
let quoted = false;
|
|
56
|
+
while (i < source.length && !/[\s;|&(){}<>]/.test(source[i]!)) {
|
|
57
|
+
const next = source[i++]!;
|
|
58
|
+
if (next === "'" || next === '"' || next === "`") {
|
|
59
|
+
quoted = true;
|
|
60
|
+
while (i < source.length && source[i] !== next) {
|
|
61
|
+
if (source[i] === "\\" && next !== "'" && i + 1 < source.length) i++;
|
|
62
|
+
value += source[i++]!;
|
|
63
|
+
}
|
|
64
|
+
if (source[i] === next) i++;
|
|
65
|
+
} else if (next === "\\" && i < source.length) {
|
|
66
|
+
const escaped = source[i++]!;
|
|
67
|
+
if (escaped !== "\n") value += escaped;
|
|
68
|
+
} else {
|
|
69
|
+
value += next;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const previous = out.at(-1)?.value;
|
|
73
|
+
if (previous === "<<" || previous === "<<-") {
|
|
74
|
+
heredocs.push({ end: value, tabs: previous === "<<-" });
|
|
75
|
+
}
|
|
76
|
+
out.push({ value, quoted });
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function basename(value: string): string {
|
|
82
|
+
return value.split(/[\\/]/).at(-1) ?? value;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isWaiter(source: string, depth = 0): boolean {
|
|
86
|
+
if (depth > 8) return false;
|
|
87
|
+
const tokens = tokenize(source);
|
|
88
|
+
let loops = 0;
|
|
89
|
+
const commands: string[] = [];
|
|
90
|
+
let start = true;
|
|
91
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
92
|
+
const token = tokens[i]!;
|
|
93
|
+
if (token.operator) {
|
|
94
|
+
if ([";", "|", "||", "&", "&&", "(", ")", "{", "}"].includes(token.value)) start = true;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (!start) continue;
|
|
98
|
+
if (!token.quoted) {
|
|
99
|
+
if (["while", "until", "for", "select"].includes(token.value)) {
|
|
100
|
+
loops++;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (token.value === "done") {
|
|
104
|
+
loops = Math.max(0, loops - 1);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (["do", "if", "then", "elif", "else", "!"].includes(token.value)) continue;
|
|
108
|
+
if (/^[A-Za-z_][A-Za-z_0-9]*=/.test(token.value)) continue;
|
|
109
|
+
}
|
|
110
|
+
const name = basename(token.value);
|
|
111
|
+
if (name === "timeout") {
|
|
112
|
+
// Skip timeout options and its duration; inspect the wrapped executable.
|
|
113
|
+
let j = i + 1;
|
|
114
|
+
for (; j < tokens.length && !tokens[j]!.operator; j++) {
|
|
115
|
+
if (/^(?:\d+(?:\.\d*)?|\.\d+)[smhd]?$/.test(tokens[j]!.value)) {
|
|
116
|
+
// -k/--kill-after takes its own duration before the main duration.
|
|
117
|
+
const previous = tokens[j - 1]?.value;
|
|
118
|
+
if (previous === "-k" || previous === "--kill-after") continue;
|
|
119
|
+
i = j;
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (i === j) continue;
|
|
124
|
+
}
|
|
125
|
+
if (["command", "exec", "builtin", "nohup"].includes(name)) continue;
|
|
126
|
+
start = false;
|
|
127
|
+
commands.push(name);
|
|
128
|
+
if (loops && ["sleep", "pgrep"].includes(name)) return true;
|
|
129
|
+
if (["bash", "sh", "dash", "zsh", "ksh"].includes(name)) {
|
|
130
|
+
for (let j = i + 1; j < tokens.length && !tokens[j]!.operator; j++) {
|
|
131
|
+
if (/^-[a-z]*c[a-z]*$/.test(tokens[j]!.value)) {
|
|
132
|
+
const script = tokens[j + 1];
|
|
133
|
+
if (script && !script.operator && isWaiter(script.value, depth + 1)) return true;
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const sleep = commands.indexOf("sleep");
|
|
140
|
+
// sed can edit files or execute commands; its name alone does not prove a log read.
|
|
141
|
+
const readers = new Set(["tail", "cat", "head", "grep", "rg", "wc"]);
|
|
142
|
+
const harmless = new Set(["sleep", "cd", "pwd", "echo", "printf", "date", ...readers]);
|
|
143
|
+
return (
|
|
144
|
+
sleep !== -1 &&
|
|
145
|
+
commands.slice(sleep + 1).some((name) => readers.has(name)) &&
|
|
146
|
+
commands.every((name) => harmless.has(name))
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function shellWaiterReason(toolName: unknown, toolInput: unknown): string | null {
|
|
151
|
+
if (typeof toolName !== "string") return null;
|
|
152
|
+
const name = toolName.toLowerCase().replace(/^functions\./, "");
|
|
153
|
+
if (!["bash", "shell", "shell_command", "exec_command"].includes(name)) return null;
|
|
154
|
+
let input = toolInput;
|
|
155
|
+
if (typeof input === "string") {
|
|
156
|
+
try {
|
|
157
|
+
input = JSON.parse(input);
|
|
158
|
+
} catch {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (!input || typeof input !== "object") return null;
|
|
163
|
+
const args = input as Record<string, unknown>;
|
|
164
|
+
const command = args.command ?? args.cmd;
|
|
165
|
+
return typeof command === "string" && isWaiter(command) ? REASON : null;
|
|
166
|
+
}
|
|
@@ -14,6 +14,7 @@ import { hostname, platform } from "node:os";
|
|
|
14
14
|
import { resolve } from "node:path";
|
|
15
15
|
import { checkPidToken, processStartToken } from "../agents/state/proc-start.ts";
|
|
16
16
|
import { closeProcessLoggers, legacyLogFields, processLogger } from "../storage/logger.ts";
|
|
17
|
+
import { stateDirMode, stateFileMode } from "../storage/modes.ts";
|
|
17
18
|
import {
|
|
18
19
|
RESOURCE_SERVICE_STATUS_SCHEMA_VERSION,
|
|
19
20
|
type ResourceSamplerState,
|
|
@@ -60,7 +61,7 @@ export async function spawnResourceService(
|
|
|
60
61
|
}
|
|
61
62
|
const intervalMs = normalizeInterval(options.intervalMs);
|
|
62
63
|
const paths = resourcePaths(coordRoot);
|
|
63
|
-
mkdirSync(paths.root, { recursive: true, mode:
|
|
64
|
+
mkdirSync(paths.root, { recursive: true, mode: stateDirMode() });
|
|
64
65
|
rmSync(paths.stop, { force: true });
|
|
65
66
|
const harnBin = new URL("../../../bin/harn", import.meta.url).pathname;
|
|
66
67
|
if (!existsSync(harnBin)) throw new Error(`cannot find harn executable at ${harnBin}`);
|
|
@@ -122,7 +123,7 @@ export function requestResourceServiceStop(coordRootRaw: string): ResourceServic
|
|
|
122
123
|
const coordRoot = resolve(coordRootRaw);
|
|
123
124
|
const paths = resourcePaths(coordRoot);
|
|
124
125
|
const status = readResourceServiceStatus(coordRoot);
|
|
125
|
-
mkdirSync(paths.root, { recursive: true, mode:
|
|
126
|
+
mkdirSync(paths.root, { recursive: true, mode: stateDirMode() });
|
|
126
127
|
writePrivateJsonAtomic(paths.stop, {
|
|
127
128
|
requested_at: new Date().toISOString(),
|
|
128
129
|
requested_by_pid: process.pid,
|
|
@@ -231,7 +232,7 @@ export async function runResourceService(
|
|
|
231
232
|
|
|
232
233
|
function acquireLease(coordRoot: string, now: Date): ResourceServiceLease {
|
|
233
234
|
const paths = resourcePaths(coordRoot);
|
|
234
|
-
mkdirSync(paths.root, { recursive: true, mode:
|
|
235
|
+
mkdirSync(paths.root, { recursive: true, mode: stateDirMode() });
|
|
235
236
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
236
237
|
const daemonStartToken = processStartToken(process.pid);
|
|
237
238
|
const lease: ResourceServiceLease = {
|
|
@@ -242,7 +243,7 @@ function acquireLease(coordRoot: string, now: Date): ResourceServiceLease {
|
|
|
242
243
|
created_at: now.toISOString(),
|
|
243
244
|
};
|
|
244
245
|
try {
|
|
245
|
-
const fd = openSync(paths.lease, "wx",
|
|
246
|
+
const fd = openSync(paths.lease, "wx", stateFileMode());
|
|
246
247
|
try {
|
|
247
248
|
writeFileSync(fd, `${JSON.stringify(lease)}\n`, "utf8");
|
|
248
249
|
} finally {
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
writeFileSync,
|
|
12
12
|
} from "node:fs";
|
|
13
13
|
import { dirname, join, resolve } from "node:path";
|
|
14
|
+
import { stateDirMode, stateFileMode } from "../storage/modes.ts";
|
|
14
15
|
import type {
|
|
15
16
|
SemanticAcceptedReadModelV2,
|
|
16
17
|
SemanticConfiguredModel,
|
|
@@ -630,12 +631,12 @@ function writePrivateJsonAtomic(path: string, value: unknown): void {
|
|
|
630
631
|
const body = `${JSON.stringify(value, null, 2)}\n`;
|
|
631
632
|
if (Buffer.byteLength(body) > MAX_JSON_BYTES)
|
|
632
633
|
throw new Error("semantic review file is too large");
|
|
633
|
-
mkdirSync(dirname(path), { recursive: true, mode:
|
|
634
|
-
chmodSync(dirname(path),
|
|
634
|
+
mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
|
|
635
|
+
chmodSync(dirname(path), stateDirMode());
|
|
635
636
|
const temporary = `${path}.tmp-${process.pid}-${randomBytes(4).toString("hex")}`;
|
|
636
|
-
writeFileSync(temporary, body, { encoding: "utf8", flag: "wx", mode:
|
|
637
|
+
writeFileSync(temporary, body, { encoding: "utf8", flag: "wx", mode: stateFileMode() });
|
|
637
638
|
renameSync(temporary, path);
|
|
638
|
-
chmodSync(path,
|
|
639
|
+
chmodSync(path, stateFileMode());
|
|
639
640
|
}
|
|
640
641
|
|
|
641
642
|
function isSemanticReviewCandidate(value: unknown): value is SemanticReviewCandidateV1 {
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
legacyLogFields,
|
|
31
31
|
processLogger,
|
|
32
32
|
} from "../storage/logger.ts";
|
|
33
|
+
import { stateDirMode, stateFileMode } from "../storage/modes.ts";
|
|
33
34
|
import type { SemanticHarness } from "./contract.ts";
|
|
34
35
|
import { runSemanticOnce, type SemanticOnceReport } from "./once.ts";
|
|
35
36
|
import { semanticPendingPassDue } from "./scheduler.ts";
|
|
@@ -145,10 +146,10 @@ export async function spawnSemanticService(
|
|
|
145
146
|
throw new Error(`semantic service is already running under pid ${current.record?.pid}`);
|
|
146
147
|
}
|
|
147
148
|
const paths = semanticPaths(coordRoot);
|
|
148
|
-
mkdirSync(paths.root, { recursive: true, mode:
|
|
149
|
+
mkdirSync(paths.root, { recursive: true, mode: stateDirMode() });
|
|
149
150
|
const sharedLogs = coordEnv("SHARED_LOGS") !== "0";
|
|
150
|
-
const logFd = sharedLogs ? undefined : openSync(paths.log, "a",
|
|
151
|
-
if (logFd !== undefined) chmodSync(paths.log,
|
|
151
|
+
const logFd = sharedLogs ? undefined : openSync(paths.log, "a", stateFileMode());
|
|
152
|
+
if (logFd !== undefined) chmodSync(paths.log, stateFileMode());
|
|
152
153
|
const harnBin = new URL("../../../bin/harn", import.meta.url).pathname;
|
|
153
154
|
if (!existsSync(harnBin)) {
|
|
154
155
|
if (logFd !== undefined) closeSync(logFd);
|
|
@@ -225,7 +226,7 @@ export async function ensureSemanticServiceRunning(
|
|
|
225
226
|
export function requestSemanticServiceStop(coordRootRaw: string): SemanticServiceStatus {
|
|
226
227
|
const coordRoot = resolve(coordRootRaw);
|
|
227
228
|
const status = readSemanticServiceStatus(coordRoot);
|
|
228
|
-
mkdirSync(semanticPaths(coordRoot).root, { recursive: true, mode:
|
|
229
|
+
mkdirSync(semanticPaths(coordRoot).root, { recursive: true, mode: stateDirMode() });
|
|
229
230
|
writePrivateJsonAtomic(semanticPaths(coordRoot).stop, {
|
|
230
231
|
requested_at: new Date().toISOString(),
|
|
231
232
|
requested_by_pid: process.pid,
|
|
@@ -452,7 +453,7 @@ export async function runSemanticServiceDaemon(
|
|
|
452
453
|
|
|
453
454
|
export function acquireSemanticServiceLease(coordRootRaw: string): () => void {
|
|
454
455
|
const path = semanticPaths(coordRootRaw).lease;
|
|
455
|
-
mkdirSync(dirname(path), { recursive: true, mode:
|
|
456
|
+
mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
|
|
456
457
|
const owner: SemanticServiceLease = {
|
|
457
458
|
pid: process.pid,
|
|
458
459
|
host: hostname(),
|
|
@@ -461,7 +462,7 @@ export function acquireSemanticServiceLease(coordRootRaw: string): () => void {
|
|
|
461
462
|
};
|
|
462
463
|
const acquire = (): boolean => {
|
|
463
464
|
try {
|
|
464
|
-
const fd = openSync(path, "wx",
|
|
465
|
+
const fd = openSync(path, "wx", stateFileMode());
|
|
465
466
|
try {
|
|
466
467
|
writeFileSync(fd, `${JSON.stringify(owner)}\n`, "utf8");
|
|
467
468
|
} finally {
|
|
@@ -671,20 +672,20 @@ function prepareSemanticServiceDiagnostic(entry: Record<string, unknown>): {
|
|
|
671
672
|
|
|
672
673
|
function appendSemanticServiceLegacyLog(coordRoot: string, entry: Record<string, unknown>): void {
|
|
673
674
|
const path = semanticPaths(coordRoot).log;
|
|
674
|
-
mkdirSync(dirname(path), { recursive: true, mode:
|
|
675
|
+
mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
|
|
675
676
|
appendFileSync(
|
|
676
677
|
path,
|
|
677
678
|
`${JSON.stringify({ schema_version: 1, ts: new Date().toISOString(), ...entry })}\n`,
|
|
678
|
-
{ encoding: "utf8", mode:
|
|
679
|
+
{ encoding: "utf8", mode: stateFileMode() },
|
|
679
680
|
);
|
|
680
|
-
chmodSync(path,
|
|
681
|
+
chmodSync(path, stateFileMode());
|
|
681
682
|
if (statSync(path).size <= MAX_LOG_BYTES) return;
|
|
682
683
|
const buffer = readFileSync(path);
|
|
683
684
|
const tail = buffer.subarray(Math.max(0, buffer.length - Math.floor(MAX_LOG_BYTES / 2)));
|
|
684
685
|
const newline = tail.indexOf(10);
|
|
685
686
|
const body = newline >= 0 ? tail.subarray(newline + 1) : tail;
|
|
686
687
|
const temporary = `${path}.tmp-${process.pid}-${randomBytes(4).toString("hex")}`;
|
|
687
|
-
writeFileSync(temporary, body, { flag: "wx", mode:
|
|
688
|
+
writeFileSync(temporary, body, { flag: "wx", mode: stateFileMode() });
|
|
688
689
|
renameSync(temporary, path);
|
|
689
690
|
}
|
|
690
691
|
|
|
@@ -693,12 +694,12 @@ function writePrivateJsonAtomic(path: string, value: unknown): void {
|
|
|
693
694
|
if (Buffer.byteLength(body) > MAX_FILE_BYTES) {
|
|
694
695
|
throw new Error(`semantic service file exceeds ${MAX_FILE_BYTES} bytes`);
|
|
695
696
|
}
|
|
696
|
-
mkdirSync(dirname(path), { recursive: true, mode:
|
|
697
|
-
chmodSync(dirname(path),
|
|
697
|
+
mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
|
|
698
|
+
chmodSync(dirname(path), stateDirMode());
|
|
698
699
|
const temporary = `${path}.tmp-${process.pid}-${randomBytes(4).toString("hex")}`;
|
|
699
|
-
writeFileSync(temporary, body, { encoding: "utf8", flag: "wx", mode:
|
|
700
|
+
writeFileSync(temporary, body, { encoding: "utf8", flag: "wx", mode: stateFileMode() });
|
|
700
701
|
renameSync(temporary, path);
|
|
701
|
-
chmodSync(path,
|
|
702
|
+
chmodSync(path, stateFileMode());
|
|
702
703
|
}
|
|
703
704
|
|
|
704
705
|
function validTimestamp(value: unknown): value is string {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { dirname, join, resolve } from "node:path";
|
|
14
14
|
import { canonicalJsonV3, sha256V3 } from "../events/v3/canonical.ts";
|
|
15
15
|
import type { LedgerCursorV3 } from "../events/v3/reader.ts";
|
|
16
|
+
import { stateDirMode, stateFileMode } from "../storage/modes.ts";
|
|
16
17
|
import type {
|
|
17
18
|
SEMANTIC_EVIDENCE_CONTRACT_VERSION,
|
|
18
19
|
SEMANTIC_PROMPT_CONTRACT_VERSION,
|
|
@@ -291,10 +292,10 @@ function writePrivateJsonAtomic(path: string, value: unknown): void {
|
|
|
291
292
|
if (Buffer.byteLength(body) > MAX_JSON_BYTES) {
|
|
292
293
|
throw new Error(`semantic file exceeds ${MAX_JSON_BYTES} bytes`);
|
|
293
294
|
}
|
|
294
|
-
mkdirSync(dirname(path), { recursive: true, mode:
|
|
295
|
-
chmodSync(dirname(path),
|
|
295
|
+
mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
|
|
296
|
+
chmodSync(dirname(path), stateDirMode());
|
|
296
297
|
const temporary = `${path}.tmp-${process.pid}-${randomBytes(4).toString("hex")}`;
|
|
297
|
-
writeFileSync(temporary, body, { encoding: "utf8", flag: "wx", mode:
|
|
298
|
+
writeFileSync(temporary, body, { encoding: "utf8", flag: "wx", mode: stateFileMode() });
|
|
298
299
|
renameSync(temporary, path);
|
|
299
|
-
chmodSync(path,
|
|
300
|
+
chmodSync(path, stateFileMode());
|
|
300
301
|
}
|