harnery 0.30.0 → 0.31.1
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 +4 -4
- package/dist/commander.d.ts +8 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +14 -13
- package/dist/commands/adapter.d.ts +12 -0
- package/dist/commands/adapter.d.ts.map +1 -0
- package/dist/commands/{harness.js → adapter.js} +35 -35
- package/dist/commands/agents.d.ts +3 -2
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +185 -74
- package/dist/commands/artifacts.d.ts +4 -0
- package/dist/commands/artifacts.d.ts.map +1 -0
- package/dist/commands/artifacts.js +143 -0
- package/dist/commands/backup.d.ts +1 -1
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +5 -2
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +310 -7
- package/dist/commands/checkpoint.d.ts +12 -0
- package/dist/commands/checkpoint.d.ts.map +1 -0
- package/dist/commands/checkpoint.js +162 -0
- package/dist/commands/context.d.ts +2 -2
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +3 -151
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +31 -7
- package/dist/commands/deinit.d.ts +2 -2
- package/dist/commands/deinit.js +15 -15
- package/dist/commands/doctor.js +23 -23
- package/dist/commands/governor.d.ts +4 -0
- package/dist/commands/governor.d.ts.map +1 -0
- package/dist/commands/{supervisor.js → governor.js} +133 -108
- package/dist/commands/grep.d.ts +1 -1
- package/dist/commands/grep.d.ts.map +1 -1
- package/dist/commands/grep.js +19 -2
- package/dist/commands/init.d.ts +12 -12
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +44 -30
- package/dist/commands/{session.d.ts → journal.d.ts} +2 -2
- package/dist/commands/journal.d.ts.map +1 -0
- package/dist/commands/{scratch.js → journal.js} +47 -47
- package/dist/commands/policy.js +1 -1
- package/dist/commands/presence.js +2 -2
- package/dist/commands/sync.d.ts +1 -1
- package/dist/commands/sync.js +3 -3
- package/dist/commands/tunnel.d.ts +16 -0
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +213 -27
- package/dist/commands/web-fetch.js +1 -1
- package/dist/commands/web.d.ts +19 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +51 -0
- package/dist/commands/work.d.ts.map +1 -1
- package/dist/commands/work.js +38 -22
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +35 -28
- package/dist/core/{harnesses → adapters}/attest-projection.d.ts +2 -2
- package/dist/core/adapters/attest-projection.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/attest.d.ts +16 -16
- package/dist/core/adapters/attest.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/attest.js +9 -9
- package/dist/core/{harnesses → adapters}/attestation.d.ts +16 -16
- package/dist/core/adapters/attestation.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/attestation.js +20 -20
- package/dist/core/{harnesses → adapters}/bench.d.ts +12 -12
- package/dist/core/adapters/bench.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/bench.js +12 -12
- package/dist/core/adapters/index.d.ts +13 -0
- package/dist/core/adapters/index.d.ts.map +1 -0
- package/dist/core/adapters/index.js +6 -0
- package/dist/core/{harnesses → adapters}/profiles.d.ts +11 -11
- package/dist/core/adapters/profiles.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/profiles.js +11 -11
- package/dist/core/adapters/registry.d.ts +15 -0
- package/dist/core/adapters/registry.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/registry.js +11 -11
- package/dist/core/{harnesses → adapters}/types.d.ts +23 -23
- package/dist/core/adapters/types.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/types.js +1 -1
- package/dist/core/agents/canonical-emit.d.ts +9 -14
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +15 -44
- package/dist/core/agents/cli-emit.js +1 -1
- package/dist/core/agents/cli.js +30 -26
- package/dist/core/agents/codex-replay.d.ts +1 -1
- package/dist/core/agents/codex-replay.js +6 -6
- package/dist/core/agents/coord-bin.d.ts +33 -0
- package/dist/core/agents/coord-bin.d.ts.map +1 -0
- package/dist/core/agents/coord-bin.js +89 -0
- package/dist/core/agents/coord-client.d.ts +78 -8
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +303 -75
- package/dist/core/agents/events/consume.d.ts +1 -1
- package/dist/core/agents/events/emit.d.ts +5 -6
- package/dist/core/agents/events/emit.d.ts.map +1 -1
- package/dist/core/agents/events/emit.js +2 -2
- package/dist/core/agents/paths.d.ts +5 -2
- package/dist/core/agents/paths.d.ts.map +1 -1
- package/dist/core/agents/paths.js +7 -13
- package/dist/core/agents/render/prompt-context.d.ts +21 -9
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +82 -30
- package/dist/core/agents/render/session-context.d.ts +1 -1
- package/dist/core/agents/render/session-context.js +5 -5
- package/dist/core/agents/rules/claim-conflict.d.ts +2 -6
- package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/claim-conflict.js +1 -1
- package/dist/core/agents/rules/commit-conflict.js +98 -22
- package/dist/core/agents/rules/stop-hook.d.ts +9 -9
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +23 -5
- package/dist/core/agents/rules/verdict.d.ts +14 -0
- package/dist/core/agents/rules/verdict.d.ts.map +1 -0
- package/dist/core/agents/rules/verdict.js +1 -0
- package/dist/core/agents/session-events.js +3 -3
- package/dist/core/agents/state/council.d.ts +1 -1
- package/dist/core/agents/state/council.js +1 -1
- package/dist/core/agents/state/heartbeat-projector.d.ts +3 -2
- package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-projector.js +14 -10
- package/dist/core/agents/state/heartbeat-writer.d.ts +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +12 -12
- package/dist/core/agents/state/{scratch.d.ts → journal.d.ts} +7 -7
- package/dist/core/agents/state/{scratch.d.ts.map → journal.d.ts.map} +1 -1
- package/dist/core/agents/state/{scratch.js → journal.js} +12 -12
- package/dist/core/agents/state/pidmap.d.ts +28 -4
- package/dist/core/agents/state/pidmap.d.ts.map +1 -1
- package/dist/core/agents/state/pidmap.js +130 -15
- package/dist/core/agents/state/proc-start.d.ts +95 -0
- package/dist/core/agents/state/proc-start.d.ts.map +1 -0
- package/dist/core/agents/state/proc-start.js +199 -0
- package/dist/core/agents/state/shell-mutation.d.ts +1 -1
- package/dist/core/agents/state/shell-mutation.js +1 -1
- package/dist/core/agents/state/stale-sweep.js +7 -7
- package/dist/core/artifacts/index.d.ts +86 -0
- package/dist/core/artifacts/index.d.ts.map +1 -0
- package/dist/core/artifacts/index.js +421 -0
- package/dist/core/config.d.ts +9 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +26 -2
- package/dist/core/context/index.d.ts +12 -12
- package/dist/core/context/index.js +10 -10
- package/dist/core/governor/adapter-spread.d.ts +52 -0
- package/dist/core/governor/adapter-spread.d.ts.map +1 -0
- package/dist/core/governor/adapter-spread.js +52 -0
- package/dist/core/governor/index.d.ts +7 -0
- package/dist/core/governor/index.d.ts.map +1 -0
- package/dist/core/governor/index.js +6 -0
- package/dist/core/governor/plan-api.d.ts +38 -0
- package/dist/core/governor/plan-api.d.ts.map +1 -0
- package/dist/core/governor/plan-api.js +83 -0
- package/dist/core/governor/plan-read.d.ts +5 -0
- package/dist/core/governor/plan-read.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/plan-read.js +66 -52
- package/dist/core/{supervisor → governor}/plan-types.d.ts +57 -56
- package/dist/core/governor/plan-types.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/plan-types.js +4 -4
- package/dist/core/governor/planning.d.ts +48 -0
- package/dist/core/governor/planning.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/planning.js +125 -94
- package/dist/core/governor/read.d.ts +6 -0
- package/dist/core/governor/read.d.ts.map +1 -0
- package/dist/core/governor/read.js +4 -0
- package/dist/core/governor/runner.d.ts +37 -0
- package/dist/core/governor/runner.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/runner.js +15 -15
- package/dist/core/governor/service-read.d.ts +6 -0
- package/dist/core/governor/service-read.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/service-read.js +12 -12
- package/dist/core/governor/service.d.ts +114 -0
- package/dist/core/governor/service.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/service.js +57 -57
- package/dist/core/governor/state.d.ts +116 -0
- package/dist/core/governor/state.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/state.js +228 -108
- package/dist/core/hooks/adapter/detect.d.ts +9 -0
- package/dist/core/hooks/{harness → adapter}/detect.d.ts.map +1 -1
- package/dist/core/hooks/{harness → adapter}/detect.js +8 -8
- package/dist/core/hooks/{harness → adapter}/events.d.ts +15 -14
- package/dist/core/hooks/adapter/events.d.ts.map +1 -0
- package/dist/core/hooks/{harness → adapter}/events.js +5 -5
- package/dist/core/hooks/{harness → adapter}/output.d.ts +20 -14
- package/dist/core/hooks/adapter/output.d.ts.map +1 -0
- package/dist/core/hooks/{harness → adapter}/output.js +30 -22
- package/dist/core/hooks/{harness → adapter}/parse.d.ts +5 -5
- package/dist/core/hooks/{harness → adapter}/parse.d.ts.map +1 -1
- package/dist/core/hooks/{harness → adapter}/parse.js +4 -4
- package/dist/core/hooks/{harness → adapter}/wiring.d.ts +15 -15
- package/dist/core/hooks/{harness → adapter}/wiring.d.ts.map +1 -1
- package/dist/core/hooks/{harness → adapter}/wiring.js +13 -13
- package/dist/core/hooks/cli.d.ts +3 -3
- package/dist/core/hooks/cli.js +187 -162
- package/dist/core/hooks/effects/image-capture.d.ts +5 -5
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +3 -3
- package/dist/core/hooks/effects/index.d.ts +12 -12
- package/dist/core/hooks/effects/index.d.ts.map +1 -1
- package/dist/core/hooks/effects/index.js +19 -19
- package/dist/core/hooks/events/emit.d.ts +2 -2
- package/dist/core/hooks/events/emit.d.ts.map +1 -1
- package/dist/core/hooks/events/emit.js +1 -1
- package/dist/core/hooks/events/rotate.js +1 -1
- package/dist/core/hooks/events/schema.d.ts +13 -5
- package/dist/core/hooks/events/schema.d.ts.map +1 -1
- package/dist/core/hooks/guard-path.d.ts +2 -2
- package/dist/core/hooks/guard-path.js +2 -2
- package/dist/core/hooks/index.d.ts +1 -1
- package/dist/core/hooks/index.d.ts.map +1 -1
- package/dist/core/hooks/resolve/anchor.d.ts +14 -5
- package/dist/core/hooks/resolve/anchor.d.ts.map +1 -1
- package/dist/core/hooks/resolve/anchor.js +64 -7
- package/dist/core/hooks/resolve/coord-root.d.ts +16 -11
- package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
- package/dist/core/hooks/resolve/coord-root.js +18 -43
- package/dist/core/hooks/resolve/intent.js +1 -1
- package/dist/core/hooks/resolve/owner.d.ts +1 -1
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +11 -5
- package/dist/core/{scratch → journal}/index.d.ts +25 -25
- package/dist/core/{scratch → journal}/index.d.ts.map +1 -1
- package/dist/core/{scratch → journal}/index.js +38 -38
- package/dist/core/policy/evaluate.d.ts +1 -1
- package/dist/core/policy/evaluate.d.ts.map +1 -1
- package/dist/core/policy/evaluate.js +7 -7
- package/dist/core/policy/types.d.ts +3 -3
- package/dist/core/policy/types.d.ts.map +1 -1
- package/dist/core/work/state.d.ts +12 -4
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +50 -17
- package/dist/core/workflow/adapters.d.ts +17 -0
- package/dist/core/workflow/adapters.d.ts.map +1 -0
- package/dist/core/workflow/adapters.js +21 -0
- package/dist/core/workflow/approvals.js +6 -6
- package/dist/core/workflow/billing.d.ts +9 -9
- package/dist/core/workflow/billing.js +9 -9
- package/dist/core/workflow/child-env.d.ts +10 -2
- package/dist/core/workflow/child-env.d.ts.map +1 -1
- package/dist/core/workflow/child-env.js +12 -4
- package/dist/core/workflow/engine.d.ts +15 -5
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +138 -83
- package/dist/core/workflow/evidence-preflight.d.ts +24 -0
- package/dist/core/workflow/evidence-preflight.d.ts.map +1 -0
- package/dist/core/workflow/evidence-preflight.js +134 -0
- package/dist/core/workflow/index.d.ts +1 -1
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/proof.d.ts +11 -5
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +45 -36
- package/dist/core/workflow/run-state.d.ts +1 -1
- package/dist/core/workflow/run-state.js +7 -7
- package/dist/core/workflow/sandbox-projection.d.ts +6 -6
- package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
- package/dist/core/workflow/sandbox-projection.js +11 -11
- package/dist/core/workflow/spawn-claude.d.ts +3 -3
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +9 -6
- package/dist/core/workflow/spawn-codex.d.ts +4 -4
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +9 -6
- package/dist/core/workflow/spawn-cursor.d.ts +4 -4
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +9 -6
- package/dist/core/workflow/spawn-failure.d.ts +1 -1
- package/dist/core/workflow/spawn-failure.js +1 -1
- package/dist/core/workflow/specialists.js +2 -2
- package/dist/core/workflow/{journal.d.ts → transcript.d.ts} +8 -8
- package/dist/core/workflow/transcript.d.ts.map +1 -0
- package/dist/core/workflow/{journal.js → transcript.js} +14 -14
- package/dist/core/workflow/types.d.ts +98 -51
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/types.js +11 -1
- package/dist/core/workflow/validate.d.ts +1 -1
- package/dist/core/workflow/validate.js +1 -1
- package/dist/core/workflow/workspaces/cancellation.js +2 -2
- package/dist/core/workflow/workspaces/cleanup.js +2 -2
- package/dist/core/workflow/workspaces/execution.js +6 -6
- package/dist/core/workflow/workspaces/inspect.js +9 -9
- package/dist/core/workflow/workspaces/integration.js +14 -14
- package/dist/core/workflow/workspaces/lifecycle.d.ts +1 -1
- package/dist/core/workflow/workspaces/lifecycle.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/lifecycle.js +9 -9
- package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.js +39 -5
- package/dist/core/workflow/workspaces/recovery.js +3 -3
- package/dist/core/workflow/workspaces/state.d.ts +1 -1
- package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/state.js +3 -3
- package/dist/core/workflow/workspaces/types.d.ts +1 -1
- package/dist/core/workflow/workspaces/types.d.ts.map +1 -1
- package/dist/lib/browser/asserts.d.ts +28 -0
- package/dist/lib/browser/asserts.d.ts.map +1 -0
- package/dist/lib/browser/asserts.js +152 -0
- package/dist/lib/browser/client.d.ts +49 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +155 -14
- package/dist/lib/browser/content-checks.d.ts +108 -0
- package/dist/lib/browser/content-checks.d.ts.map +1 -0
- package/dist/lib/browser/content-checks.js +474 -0
- package/dist/lib/browser/critique.d.ts +91 -0
- package/dist/lib/browser/critique.d.ts.map +1 -0
- package/dist/lib/browser/critique.js +167 -0
- package/dist/lib/browser/geometry.d.ts +32 -0
- package/dist/lib/browser/geometry.d.ts.map +1 -1
- package/dist/lib/browser/geometry.js +244 -1
- package/dist/lib/browser/index.d.ts +4 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -0
- package/dist/lib/claude-desktop.d.ts.map +1 -1
- package/dist/lib/claude-desktop.js +4 -1
- package/dist/lib/context/index.js +9 -2
- package/dist/lib/council/index.d.ts +6 -6
- package/dist/lib/council/index.d.ts.map +1 -1
- package/dist/lib/council/index.js +8 -8
- package/dist/lib/identities/assume.d.ts +2 -2
- package/dist/lib/identities/assume.js +7 -7
- package/dist/lib/instructions/apply.d.ts +3 -3
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +75 -27
- package/dist/lib/instructions/host-addendum.d.ts +54 -0
- package/dist/lib/instructions/host-addendum.d.ts.map +1 -0
- package/dist/lib/instructions/host-addendum.js +107 -0
- package/dist/lib/instructions/templates.d.ts +10 -3
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +41 -12
- package/dist/lib/machine.d.ts +2 -2
- package/dist/lib/machine.js +2 -2
- package/package.json +26 -21
- package/schemas/config.schema.json +26 -1
- package/src/commander.ts +22 -13
- package/src/commands/{harness.ts → adapter.ts} +46 -46
- package/src/commands/agents.ts +200 -78
- package/src/commands/artifacts.ts +168 -0
- package/src/commands/backup.ts +47 -33
- package/src/commands/browse.ts +438 -2
- package/src/commands/checkpoint.ts +196 -0
- package/src/commands/context.ts +3 -176
- package/src/commands/decision.ts +41 -7
- package/src/commands/deinit.ts +16 -16
- package/src/commands/doctor.ts +28 -28
- package/src/commands/{supervisor.ts → governor.ts} +184 -154
- package/src/commands/grep.ts +19 -2
- package/src/commands/init.ts +50 -34
- package/src/commands/{scratch.ts → journal.ts} +60 -60
- package/src/commands/policy.ts +1 -1
- package/src/commands/presence.ts +2 -2
- package/src/commands/sync.ts +3 -3
- package/src/commands/tunnel.ts +256 -38
- package/src/commands/web-fetch.ts +1 -1
- package/src/commands/web.ts +56 -1
- package/src/commands/work.ts +50 -35
- package/src/commands/workflow.ts +43 -34
- package/src/core/{harnesses → adapters}/attest-projection.ts +2 -2
- package/src/core/{harnesses → adapters}/attest.ts +27 -27
- package/src/core/{harnesses → adapters}/attestation.ts +41 -41
- package/src/core/{harnesses → adapters}/bench.ts +34 -43
- package/src/core/adapters/index.ts +56 -0
- package/src/core/{harnesses → adapters}/profiles.ts +16 -16
- package/src/core/{harnesses → adapters}/registry.ts +23 -23
- package/src/core/{harnesses → adapters}/types.ts +23 -23
- package/src/core/agents/canonical-emit.ts +16 -43
- package/src/core/agents/cli-emit.ts +1 -1
- package/src/core/agents/cli.ts +30 -28
- package/src/core/agents/codex-replay.ts +6 -6
- package/src/core/agents/coord-bin.ts +92 -0
- package/src/core/agents/coord-client.ts +302 -78
- package/src/core/agents/events/consume.ts +1 -1
- package/src/core/agents/events/emit.ts +7 -6
- package/src/core/agents/paths.ts +7 -11
- package/src/core/agents/render/prompt-context.ts +107 -31
- package/src/core/agents/render/session-context.ts +6 -6
- package/src/core/agents/rules/claim-conflict.ts +4 -7
- package/src/core/agents/rules/commit-conflict.ts +103 -22
- package/src/core/agents/rules/stop-hook.ts +33 -17
- package/src/core/agents/rules/verdict.ts +13 -0
- package/src/core/agents/session-events.ts +4 -4
- package/src/core/agents/state/council.ts +1 -1
- package/src/core/agents/state/heartbeat-projector.ts +16 -12
- package/src/core/agents/state/heartbeat-writer.ts +12 -12
- package/src/core/agents/state/{scratch.ts → journal.ts} +12 -12
- package/src/core/agents/state/pidmap.ts +130 -15
- package/src/core/agents/state/proc-start.ts +208 -0
- package/src/core/agents/state/shell-mutation.ts +1 -1
- package/src/core/agents/state/stale-sweep.ts +7 -7
- package/src/core/artifacts/index.ts +557 -0
- package/src/core/config.ts +30 -2
- package/src/core/context/index.ts +15 -15
- package/src/core/governor/adapter-spread.ts +82 -0
- package/src/core/governor/index.ts +91 -0
- package/src/core/governor/plan-api.ts +115 -0
- package/src/core/{supervisor → governor}/plan-read.ts +112 -97
- package/src/core/{supervisor → governor}/plan-types.ts +59 -56
- package/src/core/{supervisor → governor}/planning.ts +223 -192
- package/src/core/governor/read.ts +59 -0
- package/src/core/{supervisor → governor}/runner.ts +39 -39
- package/src/core/{supervisor → governor}/service-read.ts +22 -22
- package/src/core/{supervisor → governor}/service.ts +117 -119
- package/src/core/{supervisor → governor}/state.ts +325 -167
- package/src/core/hooks/adapter/detect.ts +30 -0
- package/src/core/hooks/{harness → adapter}/events.ts +16 -14
- package/src/core/hooks/{harness → adapter}/output.ts +31 -23
- package/src/core/hooks/{harness → adapter}/parse.ts +5 -5
- package/src/core/hooks/{harness → adapter}/wiring.ts +21 -21
- package/src/core/hooks/cli.ts +197 -173
- package/src/core/hooks/effects/image-capture.ts +6 -6
- package/src/core/hooks/effects/index.ts +19 -19
- package/src/core/hooks/events/emit.ts +3 -3
- package/src/core/hooks/events/rotate.ts +1 -1
- package/src/core/hooks/events/schema.ts +15 -7
- package/src/core/hooks/guard-path.ts +2 -2
- package/src/core/hooks/index.ts +1 -1
- package/src/core/hooks/resolve/anchor.ts +63 -8
- package/src/core/hooks/resolve/coord-root.ts +18 -40
- package/src/core/hooks/resolve/intent.ts +1 -1
- package/src/core/hooks/resolve/owner.ts +11 -5
- package/src/core/{scratch → journal}/index.ts +53 -53
- package/src/core/policy/evaluate.ts +8 -8
- package/src/core/policy/types.ts +3 -3
- package/src/core/work/state.ts +65 -23
- package/src/core/workflow/adapters.ts +33 -0
- package/src/core/workflow/approvals.ts +7 -7
- package/src/core/workflow/billing.ts +12 -12
- package/src/core/workflow/child-env.ts +13 -4
- package/src/core/workflow/engine.ts +155 -90
- package/src/core/workflow/evidence-preflight.ts +165 -0
- package/src/core/workflow/index.ts +3 -3
- package/src/core/workflow/proof.ts +60 -50
- package/src/core/workflow/run-state.ts +7 -7
- package/src/core/workflow/sandbox-projection.ts +16 -16
- package/src/core/workflow/spawn-claude.ts +13 -10
- package/src/core/workflow/spawn-codex.ts +13 -10
- package/src/core/workflow/spawn-cursor.ts +13 -10
- package/src/core/workflow/spawn-failure.ts +1 -1
- package/src/core/workflow/specialists.ts +2 -2
- package/src/core/workflow/{journal.ts → transcript.ts} +16 -16
- package/src/core/workflow/types.ts +108 -51
- package/src/core/workflow/validate.ts +1 -1
- package/src/core/workflow/workspaces/cancellation.ts +2 -2
- package/src/core/workflow/workspaces/cleanup.ts +2 -2
- package/src/core/workflow/workspaces/execution.ts +6 -6
- package/src/core/workflow/workspaces/inspect.ts +14 -11
- package/src/core/workflow/workspaces/integration.ts +18 -14
- package/src/core/workflow/workspaces/lifecycle.ts +10 -10
- package/src/core/workflow/workspaces/local-git.ts +47 -5
- package/src/core/workflow/workspaces/recovery.ts +3 -3
- package/src/core/workflow/workspaces/state.ts +4 -3
- package/src/core/workflow/workspaces/types.ts +1 -1
- package/src/lib/browser/asserts.ts +177 -0
- package/src/lib/browser/client.ts +189 -14
- package/src/lib/browser/content-checks.ts +571 -0
- package/src/lib/browser/critique.ts +231 -0
- package/src/lib/browser/geometry.ts +297 -1
- package/src/lib/browser/index.ts +34 -0
- package/src/lib/claude-desktop.ts +4 -1
- package/src/lib/context/index.ts +11 -1
- package/src/lib/council/index.ts +9 -9
- package/src/lib/identities/assume.ts +7 -7
- package/src/lib/instructions/apply.ts +87 -25
- package/src/lib/instructions/host-addendum.ts +126 -0
- package/src/lib/instructions/templates.ts +44 -15
- package/src/lib/machine.ts +2 -2
- package/dist/commands/harness.d.ts +0 -12
- package/dist/commands/harness.d.ts.map +0 -1
- package/dist/commands/scratch.d.ts +0 -4
- package/dist/commands/scratch.d.ts.map +0 -1
- package/dist/commands/session.d.ts.map +0 -1
- package/dist/commands/session.js +0 -162
- package/dist/commands/supervisor.d.ts +0 -4
- package/dist/commands/supervisor.d.ts.map +0 -1
- package/dist/core/harnesses/attest-projection.d.ts.map +0 -1
- package/dist/core/harnesses/attest.d.ts.map +0 -1
- package/dist/core/harnesses/attestation.d.ts.map +0 -1
- package/dist/core/harnesses/bench.d.ts.map +0 -1
- package/dist/core/harnesses/index.d.ts +0 -13
- package/dist/core/harnesses/index.d.ts.map +0 -1
- package/dist/core/harnesses/index.js +0 -6
- package/dist/core/harnesses/profiles.d.ts.map +0 -1
- package/dist/core/harnesses/registry.d.ts +0 -15
- package/dist/core/harnesses/registry.d.ts.map +0 -1
- package/dist/core/harnesses/types.d.ts.map +0 -1
- package/dist/core/hooks/harness/detect.d.ts +0 -9
- package/dist/core/hooks/harness/events.d.ts.map +0 -1
- package/dist/core/hooks/harness/output.d.ts.map +0 -1
- package/dist/core/supervisor/index.d.ts +0 -7
- package/dist/core/supervisor/index.d.ts.map +0 -1
- package/dist/core/supervisor/index.js +0 -6
- package/dist/core/supervisor/plan-api.d.ts +0 -23
- package/dist/core/supervisor/plan-api.d.ts.map +0 -1
- package/dist/core/supervisor/plan-api.js +0 -50
- package/dist/core/supervisor/plan-read.d.ts +0 -5
- package/dist/core/supervisor/plan-read.d.ts.map +0 -1
- package/dist/core/supervisor/plan-types.d.ts.map +0 -1
- package/dist/core/supervisor/planning.d.ts +0 -33
- package/dist/core/supervisor/planning.d.ts.map +0 -1
- package/dist/core/supervisor/read.d.ts +0 -6
- package/dist/core/supervisor/read.d.ts.map +0 -1
- package/dist/core/supervisor/read.js +0 -4
- package/dist/core/supervisor/runner.d.ts +0 -37
- package/dist/core/supervisor/runner.d.ts.map +0 -1
- package/dist/core/supervisor/service-read.d.ts +0 -6
- package/dist/core/supervisor/service-read.d.ts.map +0 -1
- package/dist/core/supervisor/service.d.ts +0 -114
- package/dist/core/supervisor/service.d.ts.map +0 -1
- package/dist/core/supervisor/state.d.ts +0 -95
- package/dist/core/supervisor/state.d.ts.map +0 -1
- package/dist/core/workflow/harnesses.d.ts +0 -17
- package/dist/core/workflow/harnesses.d.ts.map +0 -1
- package/dist/core/workflow/harnesses.js +0 -21
- package/dist/core/workflow/journal.d.ts.map +0 -1
- package/src/commands/session.ts +0 -187
- package/src/core/harnesses/index.ts +0 -56
- package/src/core/hooks/harness/detect.ts +0 -30
- package/src/core/supervisor/index.ts +0 -89
- package/src/core/supervisor/plan-api.ts +0 -73
- package/src/core/supervisor/read.ts +0 -59
- package/src/core/workflow/harnesses.ts +0 -33
- /package/dist/core/{harnesses → adapters}/attest-projection.js +0 -0
package/dist/commands/sync.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* via rclone (typically a Google Drive remote, but any rclone remote works).
|
|
4
4
|
*
|
|
5
5
|
* Scope: a deliberately small set of file types: durable identities,
|
|
6
|
-
* archived
|
|
6
|
+
* archived journals, council manifests. The high-churn machine-local
|
|
7
7
|
* stuff (events.ndjson, .pid-map/, active/, .last-intent.*) stays put.
|
|
8
8
|
*
|
|
9
9
|
* Subcommands:
|
|
@@ -25,7 +25,7 @@ import path from "node:path";
|
|
|
25
25
|
import { syncJsoncConfig } from "../core/config.js";
|
|
26
26
|
// What we sync. Anything matching one of these (relative to .harnery/) is
|
|
27
27
|
// considered part of the sync set. Everything else stays local-only.
|
|
28
|
-
const SYNC_PATHS = ["identities/", "
|
|
28
|
+
const SYNC_PATHS = ["identities/", "journal/archived/", "councils/"];
|
|
29
29
|
function configPath() {
|
|
30
30
|
return path.join(os.homedir(), ".config", "harnery", "sync.json");
|
|
31
31
|
}
|
|
@@ -119,7 +119,7 @@ export function registerSyncCommand(program, emit) {
|
|
|
119
119
|
const sync = program
|
|
120
120
|
.command("sync")
|
|
121
121
|
.description("Cross-machine sync of curated .harnery/ subset (identities, archived " +
|
|
122
|
-
"
|
|
122
|
+
"journals, council manifests) via rclone. Google Drive is the " +
|
|
123
123
|
"expected remote; any rclone backend works.");
|
|
124
124
|
sync
|
|
125
125
|
.command("init")
|
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
import type { EmitContext, HarneryProgramContext } from "../commander.js";
|
|
3
|
+
import { type TunnelState } from "../lib/tunnel/state.js";
|
|
4
|
+
/**
|
|
5
|
+
* Restart ONE instance's gate in place, deliberately leaving the provider
|
|
6
|
+
* process running.
|
|
7
|
+
*
|
|
8
|
+
* That asymmetry is the whole point. A Cloudflare quick tunnel's hostname is
|
|
9
|
+
* minted by cloudflared at startup, so a full `down`/`up` hands back a NEW
|
|
10
|
+
* random *.trycloudflare.com URL and breaks every link already shared — a
|
|
11
|
+
* miserable trade for adding one IP. cloudflared only ever forwards to
|
|
12
|
+
* `localhost:<gate_port>`, so the gate beneath it can be swapped out and the
|
|
13
|
+
* edge reconnects without noticing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function reloadOne(state: TunnelState): Promise<{
|
|
16
|
+
ok: boolean;
|
|
17
|
+
message: string;
|
|
18
|
+
}>;
|
|
3
19
|
export declare function registerTunnelCommand(program: Command, emitParam: EmitContext, contextParam?: HarneryProgramContext): void;
|
|
4
20
|
//# sourceMappingURL=tunnel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../../src/commands/tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../../src/commands/tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAa1E,OAAO,EAYL,KAAK,WAAW,EAGjB,MAAM,wBAAwB,CAAC;AA+rBhC;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAsE7F;AAgND,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,WAAW,EACtB,YAAY,CAAC,EAAE,qBAAqB,GACnC,IAAI,CA4EN"}
|
package/dist/commands/tunnel.js
CHANGED
|
@@ -6,6 +6,7 @@ function cachePath(tool, filename) {
|
|
|
6
6
|
import { spawn, spawnSync } from "node:child_process";
|
|
7
7
|
import { existsSync, openSync, readFileSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { resolve } from "node:path";
|
|
9
|
+
import { resolveBinName } from "../core/config.js";
|
|
9
10
|
import { clearState, DEFAULT_INSTANCE, ensureCloudflared, gateLogFile, isProcessAlive, listStates, providerLogFile, readConfig, readState, writeConfig, writeState, } from "../lib/tunnel/state.js";
|
|
10
11
|
/**
|
|
11
12
|
* `tunnel`: provider-backed tunnel in front of a local upstream.
|
|
@@ -145,12 +146,28 @@ function sweepStrays(gatePort, alreadyKilled) {
|
|
|
145
146
|
return (killByPattern(`gate\\.ts.*--port ${gatePort}( |$)`, alreadyKilled) +
|
|
146
147
|
killByPattern(`--url http://localhost:${gatePort}( |$)`, alreadyKilled));
|
|
147
148
|
}
|
|
148
|
-
/**
|
|
149
|
+
/**
|
|
150
|
+
* Ports currently bound by a LISTEN socket (best-effort, platform-dependent).
|
|
151
|
+
*
|
|
152
|
+
* `ss` (iproute2) is Linux-only. Without the lsof fallback this returns an empty
|
|
153
|
+
* set on macOS/BSD. That does not fail loudly. It reports every port as free, so
|
|
154
|
+
* `allocateGatePort` can hand out an occupied port and the reload port-release
|
|
155
|
+
* check becomes inert.
|
|
156
|
+
*/
|
|
149
157
|
function listeningPorts() {
|
|
150
158
|
const ports = new Set();
|
|
151
|
-
const
|
|
152
|
-
if (
|
|
153
|
-
for (const m of
|
|
159
|
+
const ss = spawnSync("ss", ["-tlnH"], { encoding: "utf-8" });
|
|
160
|
+
if (ss.status === 0 && typeof ss.stdout === "string") {
|
|
161
|
+
for (const m of ss.stdout.matchAll(/:(\d+)\s/g))
|
|
162
|
+
ports.add(Number(m[1]));
|
|
163
|
+
return ports;
|
|
164
|
+
}
|
|
165
|
+
// Rows look like: `bun 123 user 4u IPv4 0x… 0t0 TCP 127.0.0.1:58055 (LISTEN)`.
|
|
166
|
+
// Status can be nonzero while stdout still holds usable rows (lsof reports a
|
|
167
|
+
// failure when any single process is unreadable), so judge it on the output.
|
|
168
|
+
const lsof = spawnSync("lsof", ["-nP", "-iTCP", "-sTCP:LISTEN"], { encoding: "utf-8" });
|
|
169
|
+
if (typeof lsof.stdout === "string") {
|
|
170
|
+
for (const m of lsof.stdout.matchAll(/:(\d+) \(LISTEN\)$/gm))
|
|
154
171
|
ports.add(Number(m[1]));
|
|
155
172
|
}
|
|
156
173
|
return ports;
|
|
@@ -313,6 +330,33 @@ function providerIsAlive(state) {
|
|
|
313
330
|
function tunnelIsAlive(state) {
|
|
314
331
|
return isProcessAlive(state.gate_pid) && providerIsAlive(state);
|
|
315
332
|
}
|
|
333
|
+
/**
|
|
334
|
+
* Spawn the detached gate worker.
|
|
335
|
+
*
|
|
336
|
+
* Shared by `up` (fresh start) and `reload` (in-place restart) so both hand the
|
|
337
|
+
* gate an identical environment and record the same kind of PID. The allowlist
|
|
338
|
+
* is passed as an env var, which the gate snapshots at module load and never
|
|
339
|
+
* re-reads — that snapshot is precisely why `reload` has to exist.
|
|
340
|
+
*/
|
|
341
|
+
function spawnGate(o) {
|
|
342
|
+
const gateFd = openSync(o.gateLogPath, "a");
|
|
343
|
+
// `--name`/`--port` on argv mirror the env vars; they're what makes the gate
|
|
344
|
+
// process distinguishable per-instance in `pgrep -f` (see sweepStrays).
|
|
345
|
+
const gateProc = spawn("bun", ["run", gateScriptPath(), "--name", o.name, "--port", String(o.gatePort)], {
|
|
346
|
+
detached: true,
|
|
347
|
+
stdio: ["ignore", gateFd, gateFd],
|
|
348
|
+
env: {
|
|
349
|
+
...process.env,
|
|
350
|
+
HARNERY_TUNNEL_ALLOW: o.allowedIps.join(","),
|
|
351
|
+
HARNERY_TUNNEL_ACCESS: o.provider === "cloudflare" ? "cloudflare-allowlist" : "trusted-local-proxy",
|
|
352
|
+
HARNERY_TUNNEL_TARGET: o.target,
|
|
353
|
+
HARNERY_TUNNEL_VHOST: o.vhost,
|
|
354
|
+
HARNERY_TUNNEL_PORT: String(o.gatePort),
|
|
355
|
+
},
|
|
356
|
+
});
|
|
357
|
+
gateProc.unref();
|
|
358
|
+
return gateProc;
|
|
359
|
+
}
|
|
316
360
|
async function up(opts) {
|
|
317
361
|
if (!bunAvailable()) {
|
|
318
362
|
emit.error({
|
|
@@ -374,22 +418,15 @@ async function up(opts) {
|
|
|
374
418
|
const providerLogPath = cachePath("tunnel", providerLogFile(name, provider));
|
|
375
419
|
writeFileSync(gateLogPath, "");
|
|
376
420
|
writeFileSync(providerLogPath, "");
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
HARNERY_TUNNEL_ALLOW: cfg.allowed_ips.join(","),
|
|
386
|
-
HARNERY_TUNNEL_ACCESS: provider === "cloudflare" ? "cloudflare-allowlist" : "trusted-local-proxy",
|
|
387
|
-
HARNERY_TUNNEL_TARGET: target,
|
|
388
|
-
HARNERY_TUNNEL_VHOST: vhost,
|
|
389
|
-
HARNERY_TUNNEL_PORT: String(gatePort),
|
|
390
|
-
},
|
|
421
|
+
const gateProc = spawnGate({
|
|
422
|
+
name,
|
|
423
|
+
gatePort,
|
|
424
|
+
target,
|
|
425
|
+
vhost,
|
|
426
|
+
provider,
|
|
427
|
+
allowedIps: cfg.allowed_ips,
|
|
428
|
+
gateLogPath,
|
|
391
429
|
});
|
|
392
|
-
gateProc.unref();
|
|
393
430
|
await sleep(800);
|
|
394
431
|
if (!isProcessAlive(gateProc.pid)) {
|
|
395
432
|
emit.error({
|
|
@@ -538,6 +575,140 @@ function down(opts) {
|
|
|
538
575
|
? `No tunnel processes found for [${name}]. Nothing to stop.\n`
|
|
539
576
|
: `Stopped ${killed.size} process(es). Tunnel [${name}] down.\n`);
|
|
540
577
|
}
|
|
578
|
+
/** Poll until `port` has no LISTEN socket (or the deadline passes). */
|
|
579
|
+
async function waitForPortFree(port, timeoutMs) {
|
|
580
|
+
const deadline = Date.now() + timeoutMs;
|
|
581
|
+
while (Date.now() < deadline) {
|
|
582
|
+
if (!listeningPorts().has(port))
|
|
583
|
+
return true;
|
|
584
|
+
await sleep(100);
|
|
585
|
+
}
|
|
586
|
+
return !listeningPorts().has(port);
|
|
587
|
+
}
|
|
588
|
+
/** Poll until `port` has a LISTEN socket (or the deadline passes). */
|
|
589
|
+
async function waitForPortBound(port, timeoutMs) {
|
|
590
|
+
const deadline = Date.now() + timeoutMs;
|
|
591
|
+
while (Date.now() < deadline) {
|
|
592
|
+
if (listeningPorts().has(port))
|
|
593
|
+
return true;
|
|
594
|
+
await sleep(100);
|
|
595
|
+
}
|
|
596
|
+
return listeningPorts().has(port);
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Restart ONE instance's gate in place, deliberately leaving the provider
|
|
600
|
+
* process running.
|
|
601
|
+
*
|
|
602
|
+
* That asymmetry is the whole point. A Cloudflare quick tunnel's hostname is
|
|
603
|
+
* minted by cloudflared at startup, so a full `down`/`up` hands back a NEW
|
|
604
|
+
* random *.trycloudflare.com URL and breaks every link already shared — a
|
|
605
|
+
* miserable trade for adding one IP. cloudflared only ever forwards to
|
|
606
|
+
* `localhost:<gate_port>`, so the gate beneath it can be swapped out and the
|
|
607
|
+
* edge reconnects without noticing.
|
|
608
|
+
*/
|
|
609
|
+
export async function reloadOne(state) {
|
|
610
|
+
const bin = resolveBinName();
|
|
611
|
+
const name = state.name;
|
|
612
|
+
const gatePort = state.gate_port;
|
|
613
|
+
if (!providerIsAlive(state)) {
|
|
614
|
+
return {
|
|
615
|
+
ok: false,
|
|
616
|
+
message: `[${name}] the provider process is gone, so the public URL is already dead. ` +
|
|
617
|
+
`Reloading the gate can't bring it back — run \`${bin} tunnel up --name ${name}\`.`,
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
if (!bunAvailable()) {
|
|
621
|
+
return { ok: false, message: `[${name}] bun is not on PATH, so the gate can't be respawned.` };
|
|
622
|
+
}
|
|
623
|
+
// Kill ONLY the gate. sweepStrays() is deliberately avoided here: it also
|
|
624
|
+
// matches `--url http://localhost:<port>`, which is the provider process we
|
|
625
|
+
// are going out of our way to keep alive.
|
|
626
|
+
const killed = new Set();
|
|
627
|
+
if (isProcessAlive(state.gate_pid)) {
|
|
628
|
+
try {
|
|
629
|
+
process.kill(state.gate_pid);
|
|
630
|
+
killed.add(state.gate_pid);
|
|
631
|
+
}
|
|
632
|
+
catch {
|
|
633
|
+
/* race: already gone */
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
killByPattern(`gate\\.ts.*--port ${gatePort}( |$)`, killed);
|
|
637
|
+
if (!(await waitForPortFree(gatePort, 5_000))) {
|
|
638
|
+
return {
|
|
639
|
+
ok: false,
|
|
640
|
+
message: `[${name}] port ${gatePort} never released, so the old gate looks wedged. ` +
|
|
641
|
+
`Tunnel is down; check \`${bin} tunnel status\`.`,
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
const cfg = readConfig();
|
|
645
|
+
const gateProc = spawnGate({
|
|
646
|
+
name,
|
|
647
|
+
gatePort,
|
|
648
|
+
target: state.target,
|
|
649
|
+
vhost: state.vhost,
|
|
650
|
+
provider: state.provider,
|
|
651
|
+
allowedIps: cfg.allowed_ips,
|
|
652
|
+
gateLogPath: cachePath("tunnel", gateLogFile(name)),
|
|
653
|
+
});
|
|
654
|
+
await sleep(800);
|
|
655
|
+
const pid = gateProc.pid;
|
|
656
|
+
if (typeof pid !== "number" ||
|
|
657
|
+
!isProcessAlive(pid) ||
|
|
658
|
+
!(await waitForPortBound(gatePort, 5_000))) {
|
|
659
|
+
return {
|
|
660
|
+
ok: false,
|
|
661
|
+
message: `[${name}] the gate did not come back on port ${gatePort}. ` +
|
|
662
|
+
`Tunnel is down; check \`${bin} tunnel logs --name ${name}\`.`,
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
writeState({ ...state, gate_pid: pid });
|
|
666
|
+
const allowNote = state.provider === "cloudflare" ? ` Allowlist: ${cfg.allowed_ips.length} IP(s).` : "";
|
|
667
|
+
return { ok: true, message: `[${name}] gate reloaded, URL unchanged: ${state.url}.${allowNote}` };
|
|
668
|
+
}
|
|
669
|
+
async function reload(opts) {
|
|
670
|
+
const bin = resolveBinName();
|
|
671
|
+
if (opts.all) {
|
|
672
|
+
const all = listStates();
|
|
673
|
+
// Only live tunnels are reloadable, and a box commonly accumulates stale
|
|
674
|
+
// state files from long-dead runs. Reporting those as failures would make
|
|
675
|
+
// the common post-`allow add` path exit non-zero for no real reason.
|
|
676
|
+
const live = all.filter((s) => providerIsAlive(s));
|
|
677
|
+
const stale = all.length - live.length;
|
|
678
|
+
if (live.length === 0) {
|
|
679
|
+
emit.text(all.length === 0
|
|
680
|
+
? "No tunnels up. Nothing to reload.\n"
|
|
681
|
+
: `No live tunnels to reload (${all.length} stale). Start one with \`${bin} tunnel up\`.\n`);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
let failed = 0;
|
|
685
|
+
for (const s of live) {
|
|
686
|
+
const r = await reloadOne(s);
|
|
687
|
+
emit.text(`${r.ok ? "ok " : "FAIL"} ${r.message}\n`);
|
|
688
|
+
if (!r.ok)
|
|
689
|
+
failed++;
|
|
690
|
+
}
|
|
691
|
+
emit.text(`Reloaded ${live.length - failed} of ${live.length} live tunnel(s)` +
|
|
692
|
+
(stale > 0 ? `; skipped ${stale} stale.\n` : ".\n"));
|
|
693
|
+
if (failed > 0)
|
|
694
|
+
process.exitCode = 1;
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
const name = resolveName(opts.name);
|
|
698
|
+
const state = readState(name);
|
|
699
|
+
if (!state) {
|
|
700
|
+
emit.error({
|
|
701
|
+
code: "tunnel_not_found",
|
|
702
|
+
message: `No tunnel state for [${name}]. Start it with \`${bin} tunnel up --name ${name}\`.`,
|
|
703
|
+
});
|
|
704
|
+
process.exit(1);
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
const r = await reloadOne(state);
|
|
708
|
+
emit.text(`${r.message}\n`);
|
|
709
|
+
if (!r.ok)
|
|
710
|
+
process.exit(1);
|
|
711
|
+
}
|
|
541
712
|
function instanceState(state) {
|
|
542
713
|
return tunnelIsAlive(state) ? "up" : "stale";
|
|
543
714
|
}
|
|
@@ -643,6 +814,21 @@ function allowList() {
|
|
|
643
814
|
for (const ip of cfg.allowed_ips)
|
|
644
815
|
emit.text(`${ip}\n`);
|
|
645
816
|
}
|
|
817
|
+
/**
|
|
818
|
+
* Trailer for `allow add`/`allow rm`. Each gate snapshots the allowlist at
|
|
819
|
+
* spawn, so a config edit alone changes nothing until the gates restart.
|
|
820
|
+
* Only LIVE tunnels are listed — stale state files pile up on a long-running
|
|
821
|
+
* box, and naming nine dead instances made the old hint read like nine
|
|
822
|
+
* restarts were owed.
|
|
823
|
+
*/
|
|
824
|
+
function allowChangedHint() {
|
|
825
|
+
const live = listStates().filter((s) => s.provider === "cloudflare" && providerIsAlive(s));
|
|
826
|
+
if (live.length === 0)
|
|
827
|
+
return;
|
|
828
|
+
emit.text(`Each gate reads the allowlist once at start, so this applies on reload ` +
|
|
829
|
+
`(${live.map((s) => s.name).join(", ")}):\n` +
|
|
830
|
+
` ${resolveBinName()} tunnel reload --all\n`);
|
|
831
|
+
}
|
|
646
832
|
function allowAdd(ip) {
|
|
647
833
|
const cfg = readConfig();
|
|
648
834
|
if (cfg.allowed_ips.includes(ip)) {
|
|
@@ -652,10 +838,7 @@ function allowAdd(ip) {
|
|
|
652
838
|
cfg.allowed_ips.push(ip);
|
|
653
839
|
writeConfig(cfg);
|
|
654
840
|
emit.text(`Added ${ip}.\n`);
|
|
655
|
-
|
|
656
|
-
if (up.length > 0) {
|
|
657
|
-
emit.text(`Cloudflare allowlist is shared across Cloudflare tunnels; restart each to apply (${up.map((s) => s.name).join(", ")}).\n`);
|
|
658
|
-
}
|
|
841
|
+
allowChangedHint();
|
|
659
842
|
}
|
|
660
843
|
function allowRm(ip) {
|
|
661
844
|
const cfg = readConfig();
|
|
@@ -667,10 +850,7 @@ function allowRm(ip) {
|
|
|
667
850
|
cfg.allowed_ips.splice(idx, 1);
|
|
668
851
|
writeConfig(cfg);
|
|
669
852
|
emit.text(`Removed ${ip}.\n`);
|
|
670
|
-
|
|
671
|
-
if (up.length > 0) {
|
|
672
|
-
emit.text(`Cloudflare allowlist is shared across Cloudflare tunnels; restart each to apply (${up.map((s) => s.name).join(", ")}).\n`);
|
|
673
|
-
}
|
|
853
|
+
allowChangedHint();
|
|
674
854
|
}
|
|
675
855
|
let emit;
|
|
676
856
|
let context;
|
|
@@ -700,6 +880,12 @@ export function registerTunnelCommand(program, emitParam, contextParam) {
|
|
|
700
880
|
.option("--name <name>", "instance to stop", DEFAULT_INSTANCE)
|
|
701
881
|
.option("--all", "stop every running tunnel")
|
|
702
882
|
.action(down);
|
|
883
|
+
cmd
|
|
884
|
+
.command("reload")
|
|
885
|
+
.description("Restart an instance's gate in place to pick up allowlist changes, keeping the public URL")
|
|
886
|
+
.option("--name <name>", "instance to reload", DEFAULT_INSTANCE)
|
|
887
|
+
.option("--all", "reload every live tunnel")
|
|
888
|
+
.action(reload);
|
|
703
889
|
cmd
|
|
704
890
|
.command("status")
|
|
705
891
|
.description("Show tunnel state: a table of all instances, or detail for one via --name")
|
|
@@ -14,7 +14,7 @@ import { fileURLToPath } from "node:url";
|
|
|
14
14
|
* harnery repo at the *matching version tag* into a cache dir and install the
|
|
15
15
|
* web app's deps. Subsequent runs reuse the cache.
|
|
16
16
|
*
|
|
17
|
-
* The only thing `web/` pulls from `src/` is `harnery/core/
|
|
17
|
+
* The only thing `web/` pulls from `src/` is `harnery/core/journal` (a single,
|
|
18
18
|
* dependency-free module), so the install is `web/` deps only: no root install,
|
|
19
19
|
* no Playwright browser download.
|
|
20
20
|
*/
|
package/dist/commands/web.d.ts
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
import type { EmitContext } from "../commander.js";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the V8 old-space ceiling for the dashboard process.
|
|
5
|
+
*
|
|
6
|
+
* Next sizes `--max-old-space-size` to roughly half of system RAM when the
|
|
7
|
+
* flag is absent, which on a large machine hands a long-lived dashboard a
|
|
8
|
+
* ceiling it will never approach — so V8 never feels enough pressure to run a
|
|
9
|
+
* major GC and the process settles at a multi-gigabyte working set made mostly
|
|
10
|
+
* of collectable garbage. Pinning a modest ceiling restores that pressure.
|
|
11
|
+
*
|
|
12
|
+
* Precedence: explicit flag → `HARNERY_WEB_MAX_OLD_SPACE` → the default.
|
|
13
|
+
* `0` (or any non-positive value) opts out and restores Next's own sizing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveMaxOldSpaceMb(flag?: string): number;
|
|
16
|
+
/**
|
|
17
|
+
* Append the heap ceiling to any inherited `NODE_OPTIONS`. Next only supplies
|
|
18
|
+
* its own `--max-old-space-size` when the flag is absent, so appending here
|
|
19
|
+
* wins without clobbering flags the caller set (source maps, inspector, …).
|
|
20
|
+
*/
|
|
21
|
+
export declare function nodeOptionsWithHeapCap(mb: number): string | undefined;
|
|
3
22
|
export declare function registerWebCommand(program: Command, emit: EmitContext): void;
|
|
4
23
|
//# sourceMappingURL=web.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/commands/web.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/commands/web.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAgCnD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKrE;AA8BD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CA2J5E"}
|
package/dist/commands/web.js
CHANGED
|
@@ -27,6 +27,42 @@ function webRoot() {
|
|
|
27
27
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
28
28
|
return path.resolve(here, "..", "..", "web");
|
|
29
29
|
}
|
|
30
|
+
/** Default V8 old-space ceiling (MB) for the dashboard server. */
|
|
31
|
+
const DEFAULT_MAX_OLD_SPACE_MB = 2048;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the V8 old-space ceiling for the dashboard process.
|
|
34
|
+
*
|
|
35
|
+
* Next sizes `--max-old-space-size` to roughly half of system RAM when the
|
|
36
|
+
* flag is absent, which on a large machine hands a long-lived dashboard a
|
|
37
|
+
* ceiling it will never approach — so V8 never feels enough pressure to run a
|
|
38
|
+
* major GC and the process settles at a multi-gigabyte working set made mostly
|
|
39
|
+
* of collectable garbage. Pinning a modest ceiling restores that pressure.
|
|
40
|
+
*
|
|
41
|
+
* Precedence: explicit flag → `HARNERY_WEB_MAX_OLD_SPACE` → the default.
|
|
42
|
+
* `0` (or any non-positive value) opts out and restores Next's own sizing.
|
|
43
|
+
*/
|
|
44
|
+
export function resolveMaxOldSpaceMb(flag) {
|
|
45
|
+
const raw = flag ?? process.env.HARNERY_WEB_MAX_OLD_SPACE;
|
|
46
|
+
if (raw === undefined || raw === "")
|
|
47
|
+
return DEFAULT_MAX_OLD_SPACE_MB;
|
|
48
|
+
const n = Number(raw);
|
|
49
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
50
|
+
return 0;
|
|
51
|
+
return Math.floor(n);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Append the heap ceiling to any inherited `NODE_OPTIONS`. Next only supplies
|
|
55
|
+
* its own `--max-old-space-size` when the flag is absent, so appending here
|
|
56
|
+
* wins without clobbering flags the caller set (source maps, inspector, …).
|
|
57
|
+
*/
|
|
58
|
+
export function nodeOptionsWithHeapCap(mb) {
|
|
59
|
+
const inherited = process.env.NODE_OPTIONS ?? "";
|
|
60
|
+
if (mb <= 0)
|
|
61
|
+
return inherited || undefined;
|
|
62
|
+
if (/--max-old-space-size[=\s]/.test(inherited))
|
|
63
|
+
return inherited;
|
|
64
|
+
return `${inherited} --max-old-space-size=${mb}`.trim();
|
|
65
|
+
}
|
|
30
66
|
/**
|
|
31
67
|
* Resolve the web app root. A local `web/` (source checkout / submodule) wins.
|
|
32
68
|
* Otherwise, on an npm install, lazy-fetch it (clone + install) unless the
|
|
@@ -59,6 +95,7 @@ export function registerWebCommand(program, emit) {
|
|
|
59
95
|
.option("--coord-root <dir>", "Override the coord root (default: cwd; web walks up looking for .harnery/)")
|
|
60
96
|
.option("--prod", "Use next start instead of next dev (requires prior build)")
|
|
61
97
|
.option("--no-fetch", "Don't auto-fetch the dashboard if it's missing (npm installs)")
|
|
98
|
+
.option("--max-old-space <mb>", `V8 old-space ceiling in MB; 0 restores Next's own sizing (default ${DEFAULT_MAX_OLD_SPACE_MB}, env HARNERY_WEB_MAX_OLD_SPACE)`)
|
|
62
99
|
.action(async (opts) => {
|
|
63
100
|
const root = resolveWebRoot(emit, opts.fetch !== false);
|
|
64
101
|
if (!root) {
|
|
@@ -80,14 +117,21 @@ export function registerWebCommand(program, emit) {
|
|
|
80
117
|
return;
|
|
81
118
|
}
|
|
82
119
|
}
|
|
120
|
+
const heapMb = resolveMaxOldSpaceMb(opts.maxOldSpace);
|
|
83
121
|
emit.log(`harn web · http://localhost:${port} (${mode})`, "info");
|
|
122
|
+
emit.log(`files origin · http://harnery-files.localhost:${port}`, "info");
|
|
84
123
|
emit.log(`reading .harnery/ from: ${coordRoot}`, "info");
|
|
124
|
+
if (heapMb > 0)
|
|
125
|
+
emit.log(`heap ceiling · ${heapMb} MB`, "info");
|
|
85
126
|
const child = spawn(webRunner(), ["run", mode], {
|
|
86
127
|
cwd: root,
|
|
87
128
|
env: {
|
|
88
129
|
...process.env,
|
|
89
130
|
HARNERY_COORD_ROOT: coordRoot,
|
|
90
131
|
HARNERY_WEB_PORT: port,
|
|
132
|
+
...(nodeOptionsWithHeapCap(heapMb)
|
|
133
|
+
? { NODE_OPTIONS: nodeOptionsWithHeapCap(heapMb) }
|
|
134
|
+
: {}),
|
|
91
135
|
},
|
|
92
136
|
stdio: "inherit",
|
|
93
137
|
});
|
|
@@ -130,6 +174,7 @@ export function registerWebCommand(program, emit) {
|
|
|
130
174
|
.option("-p, --port <port>", "Listen port", "9000")
|
|
131
175
|
.option("--coord-root <dir>", "Override the coord root")
|
|
132
176
|
.option("--no-fetch", "Don't auto-fetch the dashboard if it's missing (npm installs)")
|
|
177
|
+
.option("--max-old-space <mb>", `V8 old-space ceiling in MB; 0 restores Next's own sizing (default ${DEFAULT_MAX_OLD_SPACE_MB}, env HARNERY_WEB_MAX_OLD_SPACE)`)
|
|
133
178
|
.action((opts) => {
|
|
134
179
|
const root = resolveWebRoot(emit, opts.fetch !== false);
|
|
135
180
|
if (!root) {
|
|
@@ -148,14 +193,20 @@ export function registerWebCommand(program, emit) {
|
|
|
148
193
|
}
|
|
149
194
|
const coordRoot = opts.coordRoot ?? process.cwd();
|
|
150
195
|
const port = String(opts.port);
|
|
196
|
+
const heapMb = resolveMaxOldSpaceMb(opts.maxOldSpace);
|
|
151
197
|
emit.log(`harn web · http://localhost:${port} (start)`, "info");
|
|
152
198
|
emit.log(`reading .harnery/ from: ${coordRoot}`, "info");
|
|
199
|
+
if (heapMb > 0)
|
|
200
|
+
emit.log(`heap ceiling · ${heapMb} MB`, "info");
|
|
153
201
|
const child = spawn(webRunner(), ["run", "start"], {
|
|
154
202
|
cwd: root,
|
|
155
203
|
env: {
|
|
156
204
|
...process.env,
|
|
157
205
|
HARNERY_COORD_ROOT: coordRoot,
|
|
158
206
|
HARNERY_WEB_PORT: port,
|
|
207
|
+
...(nodeOptionsWithHeapCap(heapMb)
|
|
208
|
+
? { NODE_OPTIONS: nodeOptionsWithHeapCap(heapMb) }
|
|
209
|
+
: {}),
|
|
159
210
|
},
|
|
160
211
|
stdio: "inherit",
|
|
161
212
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work.d.ts","sourceRoot":"","sources":["../../src/commands/work.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"work.d.ts","sourceRoot":"","sources":["../../src/commands/work.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAWnD,OAAO,EAUL,KAAK,WAAW,EAChB,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAC;AAwC/B,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CAqG7E;AAwPD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAM7D;AAkBD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAK9D"}
|
package/dist/commands/work.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
|
+
import { adapterProofInputs, createBuiltinAdapterRegistry, probeBinaryVersion, } from "../core/adapters/index.js";
|
|
2
3
|
import { workflowSubscriptionOnly } from "../core/config.js";
|
|
3
|
-
import {
|
|
4
|
+
import { findCompletedMissionGoverning, reopenGovernorMission } from "../core/governor/index.js";
|
|
4
5
|
import { findCoordRoot } from "../core/hooks/resolve/coord-root.js";
|
|
5
6
|
import { loadPolicyFile } from "../core/policy/index.js";
|
|
6
7
|
import { acceptWorkItem, cancelWorkItem, createWorkItem, listWorkItems, readWorkItem, reconcileAllWorkItems, reconcileWorkItem, reopenWorkItem, runWorkItem, } from "../core/work/index.js";
|
|
7
8
|
import { WorkflowParkedError } from "../core/workflow/index.js";
|
|
8
|
-
const
|
|
9
|
+
const MAX_ATTEMPT_TRANSCRIPT_ERROR_RENDER = 240;
|
|
9
10
|
export function registerWorkCommand(program, emit) {
|
|
10
|
-
const registry =
|
|
11
|
-
const
|
|
11
|
+
const registry = createBuiltinAdapterRegistry();
|
|
12
|
+
const adapters = registry.ids();
|
|
12
13
|
const work = program
|
|
13
14
|
.command("work")
|
|
14
15
|
.description("Track durable objectives across bounded workflow attempts.");
|
|
@@ -96,13 +97,13 @@ export function registerWorkCommand(program, emit) {
|
|
|
96
97
|
}
|
|
97
98
|
});
|
|
98
99
|
});
|
|
99
|
-
registerRunCommand(work, "run", false, registry,
|
|
100
|
-
registerRunCommand(work, "retry", true, registry,
|
|
100
|
+
registerRunCommand(work, "run", false, registry, adapters, emit);
|
|
101
|
+
registerRunCommand(work, "retry", true, registry, adapters, emit);
|
|
101
102
|
registerGovernanceCommand(work, "accept", emit);
|
|
102
103
|
registerGovernanceCommand(work, "cancel", emit);
|
|
103
104
|
registerGovernanceCommand(work, "reopen", emit);
|
|
104
105
|
}
|
|
105
|
-
function registerRunCommand(work, name, retry, registry,
|
|
106
|
+
function registerRunCommand(work, name, retry, registry, adapters, emit) {
|
|
106
107
|
work
|
|
107
108
|
.command(`${name} <work-id>`)
|
|
108
109
|
.description(retry
|
|
@@ -111,8 +112,8 @@ function registerRunCommand(work, name, retry, registry, harnesses, emit) {
|
|
|
111
112
|
.option("--max-agents <n>", "Total-agent ceiling for the workflow")
|
|
112
113
|
.option("--concurrency <n>", "Concurrent-subagent cap")
|
|
113
114
|
.option("--cwd <dir>", "Working directory children spawn in")
|
|
114
|
-
.option("--
|
|
115
|
-
.option("--subscription-only", "Require stored
|
|
115
|
+
.option("--adapter <name>", `Default adapter: ${adapters.join(" | ")}`)
|
|
116
|
+
.option("--subscription-only", "Require stored adapter-login billing")
|
|
116
117
|
.option("--allow-api-billing", "Permit API-key override billing")
|
|
117
118
|
.option("--policy <file>", "Host policy JSON/JSONC")
|
|
118
119
|
.option("--isolation <mode>", "shared | worktree | sandbox | remote")
|
|
@@ -122,8 +123,8 @@ function registerRunCommand(work, name, retry, registry, harnesses, emit) {
|
|
|
122
123
|
.option("--json", "Emit the workflow report or parked result as JSON")
|
|
123
124
|
.action(async (workId, opts) => {
|
|
124
125
|
await withWorkRootAsync(emit, async (coordRoot) => {
|
|
125
|
-
if (opts.
|
|
126
|
-
throw new Error(`unknown
|
|
126
|
+
if (opts.adapter && !registry.get(opts.adapter)) {
|
|
127
|
+
throw new Error(`unknown adapter ${JSON.stringify(opts.adapter)}`);
|
|
127
128
|
}
|
|
128
129
|
if (opts.workspaceRoot && opts.isolation !== "worktree") {
|
|
129
130
|
throw new Error("--workspace-root requires --isolation worktree");
|
|
@@ -147,13 +148,13 @@ function registerRunCommand(work, name, retry, registry, harnesses, emit) {
|
|
|
147
148
|
actor: opts.actor,
|
|
148
149
|
engine: {
|
|
149
150
|
spawners: registry.spawners(),
|
|
150
|
-
|
|
151
|
+
defaultAdapter: opts.adapter,
|
|
151
152
|
maxAgents: opts.maxAgents ? Number.parseInt(opts.maxAgents, 10) : undefined,
|
|
152
153
|
concurrency: opts.concurrency ? Number.parseInt(opts.concurrency, 10) : undefined,
|
|
153
154
|
cwd: opts.cwd,
|
|
154
155
|
subscriptionOnly: opts.subscriptionOnly === true ? true : workflowSubscriptionOnly(coordRoot),
|
|
155
156
|
allowApiBilling: opts.allowApiBilling,
|
|
156
|
-
...
|
|
157
|
+
...adapterProofInputs(registry.list().map((adapter) => adapter.profile), { versionProbe: probeBinaryVersion }),
|
|
157
158
|
policy: opts.policy ? loadPolicyFile(opts.policy) : undefined,
|
|
158
159
|
approvalMode: "park",
|
|
159
160
|
approvalAddressee: opts.approvalTo,
|
|
@@ -189,7 +190,7 @@ function registerRunCommand(work, name, retry, registry, harnesses, emit) {
|
|
|
189
190
|
workId,
|
|
190
191
|
runId: error.runId,
|
|
191
192
|
approvalId: error.approvalId,
|
|
192
|
-
|
|
193
|
+
transcriptPath: error.transcriptPath,
|
|
193
194
|
});
|
|
194
195
|
}
|
|
195
196
|
else {
|
|
@@ -224,11 +225,26 @@ function registerGovernanceCommand(work, name, emit) {
|
|
|
224
225
|
command.action((workId, opts) => {
|
|
225
226
|
withWorkRoot(emit, (coordRoot) => {
|
|
226
227
|
const fn = name === "accept" ? acceptWorkItem : name === "cancel" ? cancelWorkItem : reopenWorkItem;
|
|
227
|
-
|
|
228
|
+
// ADR 0050: a reopen under a mission that already succeeded has to reopen the
|
|
229
|
+
// mission too, or the item lands in ready_work that the governor will never
|
|
230
|
+
// dispatch. Resolve the goal BEFORE touching the work item so a refusal leaves
|
|
231
|
+
// nothing half-done.
|
|
232
|
+
const goalId = name === "reopen" ? findCompletedMissionGoverning(coordRoot, workId) : undefined;
|
|
233
|
+
const record = fn(coordRoot, workId, {
|
|
228
234
|
...opts,
|
|
229
235
|
...(opts.finding?.length ? { findings: opts.finding } : {}),
|
|
230
236
|
...(opts.dispose?.length ? { dispositions: opts.dispose.map(parseDisposition) } : {}),
|
|
231
|
-
})
|
|
237
|
+
});
|
|
238
|
+
if (goalId) {
|
|
239
|
+
reopenGovernorMission({
|
|
240
|
+
coordRoot,
|
|
241
|
+
goalId,
|
|
242
|
+
actor: opts.actor,
|
|
243
|
+
reason: opts.reason?.trim() || `work ${workId} was reopened after mission completion`,
|
|
244
|
+
});
|
|
245
|
+
emit.log(`mission ${goalId} had completed; its completion was reopened so ${workId} can be dispatched`, "warn");
|
|
246
|
+
}
|
|
247
|
+
emitWork(record, opts.json, emit, true);
|
|
232
248
|
});
|
|
233
249
|
});
|
|
234
250
|
}
|
|
@@ -284,17 +300,17 @@ function emitWork(record, json, emit, detail = false) {
|
|
|
284
300
|
emit.text(`${lines.join("\n")}\n`);
|
|
285
301
|
}
|
|
286
302
|
export function renderAttemptRow(attempt) {
|
|
287
|
-
const statusDetail = attempt.status === "
|
|
288
|
-
? `: ${
|
|
303
|
+
const statusDetail = attempt.status === "transcript_unreadable"
|
|
304
|
+
? `: ${renderAttemptTranscriptError(attempt.transcript_error)}`
|
|
289
305
|
: "";
|
|
290
306
|
return ` ${attempt.number}. ${attempt.run_id} ${attempt.status}${statusDetail}`;
|
|
291
307
|
}
|
|
292
|
-
function
|
|
308
|
+
function renderAttemptTranscriptError(error) {
|
|
293
309
|
const normalized = (error ?? "").replace(/\s+/g, " ").trim();
|
|
294
|
-
const value = normalized || "unknown
|
|
295
|
-
if (value.length <=
|
|
310
|
+
const value = normalized || "unknown transcript read error";
|
|
311
|
+
if (value.length <= MAX_ATTEMPT_TRANSCRIPT_ERROR_RENDER)
|
|
296
312
|
return value;
|
|
297
|
-
return `${value.slice(0,
|
|
313
|
+
return `${value.slice(0, MAX_ATTEMPT_TRANSCRIPT_ERROR_RENDER - 3).trimEnd()}...`;
|
|
298
314
|
}
|
|
299
315
|
function renderWorkRow(record) {
|
|
300
316
|
const projection = record.projection;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/commands/workflow.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAyEnD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/commands/workflow.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAyEnD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CA4uBjF"}
|