harnery 0.30.0 → 0.31.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 +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 +61 -60
- 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/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 +193 -23
- 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 +4 -4
- package/dist/core/agents/canonical-emit.js +5 -5
- 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-client.d.ts +21 -2
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +122 -27
- 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/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 +175 -151
- 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 +17 -17
- 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 +3 -3
- package/dist/core/hooks/resolve/coord-root.js +4 -4
- 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/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 +71 -64
- 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/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 +237 -34
- 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 +6 -6
- 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-client.ts +119 -28
- package/src/core/agents/events/consume.ts +1 -1
- package/src/core/agents/events/emit.ts +7 -6
- 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 +185 -162
- package/src/core/hooks/effects/image-capture.ts +6 -6
- package/src/core/hooks/effects/index.ts +17 -17
- 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 +4 -4
- 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/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
|
@@ -23,27 +23,23 @@ import {
|
|
|
23
23
|
type WorkflowProof,
|
|
24
24
|
workflowScriptDigest,
|
|
25
25
|
} from "../workflow/index.ts";
|
|
26
|
+
import { readGovernorPlan, readGovernorPlanReviewReceipt, readGovernorPlans } from "./plan-read.ts";
|
|
26
27
|
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
type
|
|
34
|
-
type
|
|
35
|
-
type
|
|
36
|
-
type
|
|
37
|
-
type
|
|
38
|
-
type
|
|
39
|
-
|
|
40
|
-
type SupervisorPlanReviewReviewer,
|
|
41
|
-
type SupervisorPlanReviewRound,
|
|
42
|
-
type SupervisorPlanWorkSpec,
|
|
43
|
-
type SupervisorReplanningPolicy,
|
|
44
|
-
supervisorGraphFingerprint,
|
|
28
|
+
GOVERNOR_PLAN_SCHEMA_VERSION,
|
|
29
|
+
type GovernorPlanEvent,
|
|
30
|
+
type GovernorPlanMilestone,
|
|
31
|
+
type GovernorPlanOutcome,
|
|
32
|
+
type GovernorPlanProposal,
|
|
33
|
+
type GovernorPlanRequest,
|
|
34
|
+
type GovernorPlanReviewFinding,
|
|
35
|
+
type GovernorPlanReviewReceipt,
|
|
36
|
+
type GovernorPlanReviewReviewer,
|
|
37
|
+
type GovernorPlanReviewRound,
|
|
38
|
+
type GovernorPlanWorkSpec,
|
|
39
|
+
type GovernorReplanningPolicy,
|
|
40
|
+
governorGraphFingerprint,
|
|
45
41
|
} from "./plan-types.ts";
|
|
46
|
-
import type {
|
|
42
|
+
import type { GovernorRecord } from "./state.ts";
|
|
47
43
|
|
|
48
44
|
const PLAN_KEY = /^[a-z][a-z0-9-]{0,31}$/;
|
|
49
45
|
const TEMPLATE_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
@@ -53,26 +49,26 @@ const MAX_REASON = 2_000;
|
|
|
53
49
|
const PROPOSAL_ROOT_RULE =
|
|
54
50
|
"proposal.root names one newly proposed work key using a root-capable template; it does not preserve or repeat active_root, which is context only";
|
|
55
51
|
|
|
56
|
-
export interface
|
|
52
|
+
export interface RunGovernorPlannerInput {
|
|
57
53
|
coordRoot: string;
|
|
58
|
-
record:
|
|
54
|
+
record: GovernorRecord;
|
|
59
55
|
engine: Omit<EngineOpts, "coordRoot" | "runId" | "resumeRunId" | "specialists">;
|
|
60
56
|
actor: string;
|
|
61
57
|
onLog?: (line: string) => void;
|
|
62
58
|
}
|
|
63
59
|
|
|
64
|
-
export async function
|
|
65
|
-
input:
|
|
66
|
-
): Promise<
|
|
60
|
+
export async function runGovernorPlanner(
|
|
61
|
+
input: RunGovernorPlannerInput,
|
|
62
|
+
): Promise<GovernorPlanOutcome> {
|
|
67
63
|
const coordRoot = resolve(input.coordRoot);
|
|
68
64
|
const policy = input.record.intent.replanning;
|
|
69
|
-
if (!policy) throw new Error(`
|
|
70
|
-
const history =
|
|
65
|
+
if (!policy) throw new Error(`governor ${input.record.intent.id} does not allow replanning`);
|
|
66
|
+
const history = readGovernorPlans(
|
|
71
67
|
coordRoot,
|
|
72
68
|
input.record.intent.id,
|
|
73
69
|
input.record.intent.root_work_id,
|
|
74
70
|
);
|
|
75
|
-
const triggerFingerprint =
|
|
71
|
+
const triggerFingerprint = governorGraphFingerprint({
|
|
76
72
|
rootWorkId: input.record.projection.root_work_id,
|
|
77
73
|
generation: input.record.projection.plan_generation,
|
|
78
74
|
work: input.record.work,
|
|
@@ -136,7 +132,7 @@ export async function runSupervisorPlanner(
|
|
|
136
132
|
const reviewInput = resumingReview
|
|
137
133
|
? readBoundedJson<{ candidate: unknown }>(
|
|
138
134
|
reviewInputPath(coordRoot, input.record.intent.id, request.id),
|
|
139
|
-
"
|
|
135
|
+
"governor plan review input",
|
|
140
136
|
)
|
|
141
137
|
: undefined;
|
|
142
138
|
const rawProposal = reviewInput
|
|
@@ -169,9 +165,9 @@ export async function runSupervisorPlanner(
|
|
|
169
165
|
actor: input.actor,
|
|
170
166
|
reason: proposal.rationale,
|
|
171
167
|
});
|
|
172
|
-
return outcome(
|
|
168
|
+
return outcome(readGovernorPlan(coordRoot, input.record.intent.id, request.id));
|
|
173
169
|
}
|
|
174
|
-
let receipt:
|
|
170
|
+
let receipt: GovernorPlanReviewReceipt;
|
|
175
171
|
try {
|
|
176
172
|
receipt = await ensurePlanReview({
|
|
177
173
|
coordRoot,
|
|
@@ -196,7 +192,7 @@ export async function runSupervisorPlanner(
|
|
|
196
192
|
MAX_REASON,
|
|
197
193
|
),
|
|
198
194
|
});
|
|
199
|
-
return outcome(
|
|
195
|
+
return outcome(readGovernorPlan(coordRoot, input.record.intent.id, request.id));
|
|
200
196
|
}
|
|
201
197
|
return finalizeReviewedProposal({
|
|
202
198
|
coordRoot,
|
|
@@ -210,7 +206,7 @@ export async function runSupervisorPlanner(
|
|
|
210
206
|
writeExclusiveJson(
|
|
211
207
|
planProposalPath(coordRoot, input.record.intent.id, request.id),
|
|
212
208
|
proposal,
|
|
213
|
-
"
|
|
209
|
+
"governor plan proposal",
|
|
214
210
|
);
|
|
215
211
|
appendPlanEvent(coordRoot, input.record.intent.id, request.id, {
|
|
216
212
|
event: "plan.proposed",
|
|
@@ -224,18 +220,18 @@ export async function runSupervisorPlanner(
|
|
|
224
220
|
actor: input.actor,
|
|
225
221
|
reason: proposal.rationale,
|
|
226
222
|
});
|
|
227
|
-
return outcome(
|
|
223
|
+
return outcome(readGovernorPlan(coordRoot, input.record.intent.id, request.id));
|
|
228
224
|
}
|
|
229
225
|
if (policy.auto_apply) {
|
|
230
|
-
return
|
|
226
|
+
return applyGovernorPlanProposal({
|
|
231
227
|
coordRoot,
|
|
232
228
|
record: input.record,
|
|
233
229
|
planId: request.id,
|
|
234
230
|
actor: input.actor,
|
|
235
|
-
reason: "proposal applied by frozen
|
|
231
|
+
reason: "proposal applied by frozen governor replanning policy",
|
|
236
232
|
});
|
|
237
233
|
}
|
|
238
|
-
return outcome(
|
|
234
|
+
return outcome(readGovernorPlan(coordRoot, input.record.intent.id, request.id));
|
|
239
235
|
} catch (error) {
|
|
240
236
|
if (proposalWritten) throw error;
|
|
241
237
|
if (error instanceof WorkflowParkedError) {
|
|
@@ -245,7 +241,7 @@ export async function runSupervisorPlanner(
|
|
|
245
241
|
reason: `planning workflow parked for approval ${error.approvalId}`,
|
|
246
242
|
approval_id: error.approvalId,
|
|
247
243
|
});
|
|
248
|
-
return outcome(
|
|
244
|
+
return outcome(readGovernorPlan(coordRoot, input.record.intent.id, request.id));
|
|
249
245
|
}
|
|
250
246
|
// ADR 0046: a planner workflow that never touched the plan (its binary was
|
|
251
247
|
// absent, or the vendor refused) writes a proof carrying run.class. Stamp it
|
|
@@ -266,10 +262,7 @@ export async function runSupervisorPlanner(
|
|
|
266
262
|
/** The failure class (ADR 0046) of a planner workflow run, read from its proof.
|
|
267
263
|
* Undefined when no proof was written, the proof is unreadable, or the run was
|
|
268
264
|
* informative about the plan — all of which default to a charged replan. */
|
|
269
|
-
function plannerFailureClass(
|
|
270
|
-
coordRoot: string,
|
|
271
|
-
workflowRunId: string,
|
|
272
|
-
): SupervisorPlanEvent["class"] {
|
|
265
|
+
function plannerFailureClass(coordRoot: string, workflowRunId: string): GovernorPlanEvent["class"] {
|
|
273
266
|
try {
|
|
274
267
|
return readWorkflowProof(coordRoot, workflowRunId).run.class;
|
|
275
268
|
} catch {
|
|
@@ -279,16 +272,16 @@ function plannerFailureClass(
|
|
|
279
272
|
|
|
280
273
|
async function recoverReviewedPlan(input: {
|
|
281
274
|
coordRoot: string;
|
|
282
|
-
record:
|
|
283
|
-
request:
|
|
284
|
-
history: ReturnType<typeof
|
|
285
|
-
trigger: NonNullable<
|
|
286
|
-
policy:
|
|
275
|
+
record: GovernorRecord;
|
|
276
|
+
request: GovernorPlanRequest;
|
|
277
|
+
history: ReturnType<typeof readGovernorPlans>;
|
|
278
|
+
trigger: NonNullable<GovernorPlanRequest["trigger"]>;
|
|
279
|
+
policy: GovernorReplanningPolicy;
|
|
287
280
|
actor: string;
|
|
288
|
-
}): Promise<
|
|
281
|
+
}): Promise<GovernorPlanOutcome | undefined> {
|
|
289
282
|
const review = input.policy.review;
|
|
290
283
|
if (!review) return undefined;
|
|
291
|
-
const existing =
|
|
284
|
+
const existing = readGovernorPlanReviewReceipt(
|
|
292
285
|
input.coordRoot,
|
|
293
286
|
input.record.intent.id,
|
|
294
287
|
input.request.id,
|
|
@@ -308,7 +301,7 @@ async function recoverReviewedPlan(input: {
|
|
|
308
301
|
writeExclusiveJson(
|
|
309
302
|
reviewReceiptPath(input.coordRoot, input.record.intent.id, input.request.id),
|
|
310
303
|
receipt,
|
|
311
|
-
"
|
|
304
|
+
"governor plan review receipt",
|
|
312
305
|
);
|
|
313
306
|
}
|
|
314
307
|
return finalizeReviewedProposal({
|
|
@@ -323,17 +316,17 @@ async function recoverReviewedPlan(input: {
|
|
|
323
316
|
|
|
324
317
|
async function ensurePlanReview(input: {
|
|
325
318
|
coordRoot: string;
|
|
326
|
-
record:
|
|
327
|
-
request:
|
|
328
|
-
proposal:
|
|
329
|
-
history: ReturnType<typeof
|
|
330
|
-
trigger: NonNullable<
|
|
331
|
-
policy:
|
|
319
|
+
record: GovernorRecord;
|
|
320
|
+
request: GovernorPlanRequest;
|
|
321
|
+
proposal: GovernorPlanProposal;
|
|
322
|
+
history: ReturnType<typeof readGovernorPlans>;
|
|
323
|
+
trigger: NonNullable<GovernorPlanRequest["trigger"]>;
|
|
324
|
+
policy: GovernorReplanningPolicy;
|
|
332
325
|
engine: Omit<EngineOpts, "coordRoot" | "runId" | "resumeRunId" | "specialists">;
|
|
333
326
|
actor: string;
|
|
334
327
|
onLog?: (line: string) => void;
|
|
335
|
-
}): Promise<
|
|
336
|
-
const existing =
|
|
328
|
+
}): Promise<GovernorPlanReviewReceipt> {
|
|
329
|
+
const existing = readGovernorPlanReviewReceipt(
|
|
337
330
|
input.coordRoot,
|
|
338
331
|
input.record.intent.id,
|
|
339
332
|
input.request.id,
|
|
@@ -344,7 +337,7 @@ async function ensurePlanReview(input: {
|
|
|
344
337
|
writeExclusiveJson(
|
|
345
338
|
reviewReceiptPath(input.coordRoot, input.record.intent.id, input.request.id),
|
|
346
339
|
reconstructed,
|
|
347
|
-
"
|
|
340
|
+
"governor plan review receipt",
|
|
348
341
|
);
|
|
349
342
|
return reconstructed;
|
|
350
343
|
}
|
|
@@ -352,12 +345,12 @@ async function ensurePlanReview(input: {
|
|
|
352
345
|
writeExclusiveJson(
|
|
353
346
|
reviewInputPath(input.coordRoot, input.record.intent.id, input.request.id),
|
|
354
347
|
{ candidate: input.proposal },
|
|
355
|
-
"
|
|
348
|
+
"governor plan review input",
|
|
356
349
|
);
|
|
357
350
|
writeExclusive(
|
|
358
351
|
reviewScript,
|
|
359
352
|
plannerReviewScript(input.record, input.request.id, input.proposal, input.trigger),
|
|
360
|
-
"
|
|
353
|
+
"governor plan review script",
|
|
361
354
|
);
|
|
362
355
|
const review = input.policy.review!;
|
|
363
356
|
const runId = reviewWorkflowRunId(input.request.id);
|
|
@@ -385,19 +378,19 @@ async function ensurePlanReview(input: {
|
|
|
385
378
|
writeExclusiveJson(
|
|
386
379
|
reviewReceiptPath(input.coordRoot, input.record.intent.id, input.request.id),
|
|
387
380
|
receipt,
|
|
388
|
-
"
|
|
381
|
+
"governor plan review receipt",
|
|
389
382
|
);
|
|
390
383
|
return receipt;
|
|
391
384
|
}
|
|
392
385
|
|
|
393
386
|
function finalizeReviewedProposal(input: {
|
|
394
387
|
coordRoot: string;
|
|
395
|
-
record:
|
|
396
|
-
request:
|
|
397
|
-
receipt:
|
|
398
|
-
policy:
|
|
388
|
+
record: GovernorRecord;
|
|
389
|
+
request: GovernorPlanRequest;
|
|
390
|
+
receipt: GovernorPlanReviewReceipt;
|
|
391
|
+
policy: GovernorReplanningPolicy;
|
|
399
392
|
actor: string;
|
|
400
|
-
}):
|
|
393
|
+
}): GovernorPlanOutcome {
|
|
401
394
|
if (input.receipt.status !== "passed") {
|
|
402
395
|
const event = input.receipt.status === "failed" ? "plan.failed" : "plan.attention";
|
|
403
396
|
appendPlanEventIfMissing(input.coordRoot, input.record.intent.id, input.request.id, event, {
|
|
@@ -405,7 +398,7 @@ function finalizeReviewedProposal(input: {
|
|
|
405
398
|
actor: input.actor,
|
|
406
399
|
reason: reviewStatusReason(input.receipt),
|
|
407
400
|
});
|
|
408
|
-
return outcome(
|
|
401
|
+
return outcome(readGovernorPlan(input.coordRoot, input.record.intent.id, input.request.id));
|
|
409
402
|
}
|
|
410
403
|
// The review authority must become durable before the proposal can become
|
|
411
404
|
// visible. If the process stops after this event, the plan remains
|
|
@@ -425,7 +418,7 @@ function finalizeReviewedProposal(input: {
|
|
|
425
418
|
writeExclusiveJson(
|
|
426
419
|
planProposalPath(input.coordRoot, input.record.intent.id, input.request.id),
|
|
427
420
|
input.receipt.final_candidate,
|
|
428
|
-
"
|
|
421
|
+
"governor plan proposal",
|
|
429
422
|
);
|
|
430
423
|
appendPlanEventIfMissing(
|
|
431
424
|
input.coordRoot,
|
|
@@ -439,18 +432,18 @@ function finalizeReviewedProposal(input: {
|
|
|
439
432
|
},
|
|
440
433
|
);
|
|
441
434
|
if (input.policy.auto_apply) {
|
|
442
|
-
return
|
|
435
|
+
return applyGovernorPlanProposal({
|
|
443
436
|
coordRoot: input.coordRoot,
|
|
444
437
|
record: input.record,
|
|
445
438
|
planId: input.request.id,
|
|
446
439
|
actor: input.actor,
|
|
447
|
-
reason: "proposal applied by frozen
|
|
440
|
+
reason: "proposal applied by frozen governor replanning policy",
|
|
448
441
|
});
|
|
449
442
|
}
|
|
450
|
-
return outcome(
|
|
443
|
+
return outcome(readGovernorPlan(input.coordRoot, input.record.intent.id, input.request.id));
|
|
451
444
|
}
|
|
452
445
|
|
|
453
|
-
function reviewStatusReason(receipt:
|
|
446
|
+
function reviewStatusReason(receipt: GovernorPlanReviewReceipt): string {
|
|
454
447
|
if (receipt.status === "revision_exhausted") {
|
|
455
448
|
return "plan review exhausted its bounded revision rounds";
|
|
456
449
|
}
|
|
@@ -458,47 +451,43 @@ function reviewStatusReason(receipt: SupervisorPlanReviewReceipt): string {
|
|
|
458
451
|
return "plan review requires attention";
|
|
459
452
|
}
|
|
460
453
|
|
|
461
|
-
export function
|
|
454
|
+
export function applyGovernorPlanProposal(input: {
|
|
462
455
|
coordRoot: string;
|
|
463
|
-
record:
|
|
456
|
+
record: GovernorRecord;
|
|
464
457
|
planId: string;
|
|
465
458
|
actor: string;
|
|
466
459
|
reason?: string;
|
|
467
|
-
}):
|
|
460
|
+
}): GovernorPlanOutcome {
|
|
468
461
|
const coordRoot = resolve(input.coordRoot);
|
|
469
462
|
const policy = input.record.intent.replanning;
|
|
470
|
-
if (!policy) throw new Error(`
|
|
471
|
-
const plan =
|
|
463
|
+
if (!policy) throw new Error(`governor ${input.record.intent.id} does not allow replanning`);
|
|
464
|
+
const plan = readGovernorPlan(coordRoot, input.record.intent.id, input.planId);
|
|
472
465
|
if (plan.status === "applied" || plan.status === "completed") return outcome(plan);
|
|
473
466
|
if (
|
|
474
467
|
plan.status !== "proposed" ||
|
|
475
468
|
!plan.proposal ||
|
|
476
469
|
!["apply", "complete"].includes(plan.proposal.decision)
|
|
477
470
|
) {
|
|
478
|
-
throw new Error(`
|
|
471
|
+
throw new Error(`governor plan ${input.planId} cannot be applied from ${plan.status}`);
|
|
479
472
|
}
|
|
480
473
|
if (policy.review) {
|
|
481
|
-
const receipt =
|
|
482
|
-
coordRoot,
|
|
483
|
-
input.record.intent.id,
|
|
484
|
-
input.planId,
|
|
485
|
-
);
|
|
474
|
+
const receipt = readGovernorPlanReviewReceipt(coordRoot, input.record.intent.id, input.planId);
|
|
486
475
|
if (receipt?.status !== "passed") {
|
|
487
|
-
throw new Error(`
|
|
476
|
+
throw new Error(`governor plan ${input.planId} has no passed review receipt`);
|
|
488
477
|
}
|
|
489
478
|
if (candidateDigest(plan.proposal) !== receipt.candidate_sha256) {
|
|
490
|
-
throw new Error(`
|
|
479
|
+
throw new Error(`governor plan ${input.planId} proposal does not match its passed review`);
|
|
491
480
|
}
|
|
492
481
|
if (!plan.events.some((event) => event.event === "plan.reviewed")) {
|
|
493
|
-
throw new Error(`
|
|
482
|
+
throw new Error(`governor plan ${input.planId} has no reviewed authority event`);
|
|
494
483
|
}
|
|
495
484
|
}
|
|
496
485
|
if (plan.request.prior_root_work_id !== input.record.projection.root_work_id) {
|
|
497
486
|
throw new Error(
|
|
498
|
-
`
|
|
487
|
+
`governor plan ${input.planId} targets stale root ${plan.request.prior_root_work_id}`,
|
|
499
488
|
);
|
|
500
489
|
}
|
|
501
|
-
const history =
|
|
490
|
+
const history = readGovernorPlans(
|
|
502
491
|
coordRoot,
|
|
503
492
|
input.record.intent.id,
|
|
504
493
|
input.record.intent.root_work_id,
|
|
@@ -516,7 +505,7 @@ export function applySupervisorPlanProposal(input: {
|
|
|
516
505
|
actor: input.actor,
|
|
517
506
|
reason: input.reason ?? proposal.rationale,
|
|
518
507
|
});
|
|
519
|
-
return outcome(
|
|
508
|
+
return outcome(readGovernorPlan(coordRoot, input.record.intent.id, input.planId));
|
|
520
509
|
}
|
|
521
510
|
const ids = new Map<string, string>();
|
|
522
511
|
const created: string[] = [];
|
|
@@ -538,7 +527,7 @@ export function applySupervisorPlanProposal(input: {
|
|
|
538
527
|
max_attempts: template.max_attempts,
|
|
539
528
|
source: {
|
|
540
529
|
kind: "workflow" as const,
|
|
541
|
-
ref: `
|
|
530
|
+
ref: `governor:${input.record.intent.id}/plan:${input.planId}`,
|
|
542
531
|
},
|
|
543
532
|
};
|
|
544
533
|
if (existsSync(join(coordRoot, ".harnery", "work", workId, "intent.json"))) {
|
|
@@ -577,55 +566,91 @@ export function applySupervisorPlanProposal(input: {
|
|
|
577
566
|
appendPlanEvent(coordRoot, input.record.intent.id, input.planId, {
|
|
578
567
|
event: "plan.applied",
|
|
579
568
|
actor: input.actor,
|
|
580
|
-
reason: input.reason ?? "
|
|
569
|
+
reason: input.reason ?? "governor plan explicitly approved",
|
|
581
570
|
root_work_id: rootWorkId,
|
|
582
571
|
work_ids: created,
|
|
583
572
|
});
|
|
584
|
-
return outcome(
|
|
573
|
+
return outcome(readGovernorPlan(coordRoot, input.record.intent.id, input.planId));
|
|
585
574
|
}
|
|
586
575
|
|
|
587
|
-
export function
|
|
576
|
+
export function rejectGovernorPlanProposal(input: {
|
|
588
577
|
coordRoot: string;
|
|
589
578
|
goalId: string;
|
|
590
579
|
planId: string;
|
|
591
580
|
actor: string;
|
|
592
581
|
reason: string;
|
|
593
|
-
}):
|
|
594
|
-
const plan =
|
|
582
|
+
}): GovernorPlanOutcome {
|
|
583
|
+
const plan = readGovernorPlan(input.coordRoot, input.goalId, input.planId);
|
|
595
584
|
if (plan.status === "rejected") return outcome(plan);
|
|
596
585
|
if (plan.status !== "proposed") {
|
|
597
|
-
throw new Error(`
|
|
586
|
+
throw new Error(`governor plan ${input.planId} cannot be rejected from ${plan.status}`);
|
|
598
587
|
}
|
|
599
588
|
appendPlanEvent(input.coordRoot, input.goalId, input.planId, {
|
|
600
589
|
event: "plan.rejected",
|
|
601
590
|
actor: input.actor,
|
|
602
591
|
reason: input.reason,
|
|
603
592
|
});
|
|
604
|
-
return outcome(
|
|
593
|
+
return outcome(readGovernorPlan(input.coordRoot, input.goalId, input.planId));
|
|
605
594
|
}
|
|
606
595
|
|
|
607
|
-
|
|
596
|
+
/** ADR 0050: reopen a mission whose completion was already accepted, so an operator
|
|
597
|
+
* finding on work beneath it can be dispatched through the normal governor rather
|
|
598
|
+
* than only by running the work item by hand.
|
|
599
|
+
*
|
|
600
|
+
* The accepted `plan.completed` event is never rewritten. This appends a superseding
|
|
601
|
+
* `plan.reopened` alongside it, which is why the prior completion survives as history
|
|
602
|
+
* and why a reader that cannot understand the new event still sees a completed plan
|
|
603
|
+
* rather than a silently altered one. Refuses when the mission is not complete, so a
|
|
604
|
+
* caller cannot use it to skip the ordinary completion path. */
|
|
605
|
+
export function reopenGovernorMissionPlan(input: {
|
|
608
606
|
coordRoot: string;
|
|
609
|
-
record:
|
|
607
|
+
record: GovernorRecord;
|
|
608
|
+
actor: string;
|
|
609
|
+
reason: string;
|
|
610
|
+
}): GovernorPlanOutcome {
|
|
611
|
+
const goalId = input.record.intent.id;
|
|
612
|
+
if (!input.record.intent.mission) {
|
|
613
|
+
throw new Error(`governor ${goalId} is not a mission`);
|
|
614
|
+
}
|
|
615
|
+
const history = readGovernorPlans(input.coordRoot, goalId, input.record.intent.root_work_id);
|
|
616
|
+
const latest = history.latest;
|
|
617
|
+
if (!latest) {
|
|
618
|
+
throw new Error(`governor ${goalId} has no plan to reopen`);
|
|
619
|
+
}
|
|
620
|
+
if (latest.status === "reopened") return outcome(latest);
|
|
621
|
+
if (!history.completed || latest.status !== "completed") {
|
|
622
|
+
throw new Error(`governor ${goalId} mission is not complete, so there is nothing to reopen`);
|
|
623
|
+
}
|
|
624
|
+
appendPlanEvent(input.coordRoot, goalId, latest.request.id, {
|
|
625
|
+
event: "plan.reopened",
|
|
626
|
+
actor: input.actor,
|
|
627
|
+
reason: bounded(input.reason, "mission reopen reason", MAX_REASON),
|
|
628
|
+
});
|
|
629
|
+
return outcome(readGovernorPlan(input.coordRoot, goalId, latest.request.id));
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
export function retryGovernorPlanProposal(input: {
|
|
633
|
+
coordRoot: string;
|
|
634
|
+
record: GovernorRecord;
|
|
610
635
|
planId: string;
|
|
611
636
|
actor: string;
|
|
612
637
|
reason: string;
|
|
613
|
-
}):
|
|
638
|
+
}): GovernorPlanOutcome {
|
|
614
639
|
const policy = input.record.intent.replanning;
|
|
615
640
|
if (!policy) {
|
|
616
|
-
throw new Error(`
|
|
641
|
+
throw new Error(`governor ${input.record.intent.id} does not allow replanning`);
|
|
617
642
|
}
|
|
618
643
|
const reason = bounded(input.reason, "plan retry reason", MAX_REASON);
|
|
619
|
-
const history =
|
|
644
|
+
const history = readGovernorPlans(
|
|
620
645
|
input.coordRoot,
|
|
621
646
|
input.record.intent.id,
|
|
622
647
|
input.record.intent.root_work_id,
|
|
623
648
|
);
|
|
624
649
|
const latest = history.latest;
|
|
625
650
|
if (!latest || latest.request.id !== input.planId) {
|
|
626
|
-
throw new Error(`
|
|
651
|
+
throw new Error(`governor plan ${input.planId} is not the latest plan`);
|
|
627
652
|
}
|
|
628
|
-
const triggerFingerprint =
|
|
653
|
+
const triggerFingerprint = governorGraphFingerprint({
|
|
629
654
|
rootWorkId: history.active_root_work_id,
|
|
630
655
|
generation: history.generation,
|
|
631
656
|
work: input.record.work,
|
|
@@ -634,18 +659,18 @@ export function retrySupervisorPlanProposal(input: {
|
|
|
634
659
|
latest.request.trigger_fingerprint !== triggerFingerprint ||
|
|
635
660
|
latest.request.prior_root_work_id !== history.active_root_work_id
|
|
636
661
|
) {
|
|
637
|
-
throw new Error(`
|
|
662
|
+
throw new Error(`governor plan ${input.planId} no longer matches the active graph`);
|
|
638
663
|
}
|
|
639
664
|
if (history.completed) {
|
|
640
|
-
throw new Error(`
|
|
665
|
+
throw new Error(`governor ${input.record.intent.id} mission is already complete`);
|
|
641
666
|
}
|
|
642
667
|
if (latest.status === "retry_requested") return outcome(latest);
|
|
643
668
|
if (latest.status !== "attention") {
|
|
644
|
-
throw new Error(`
|
|
669
|
+
throw new Error(`governor plan ${input.planId} cannot be retried from ${latest.status}`);
|
|
645
670
|
}
|
|
646
671
|
if (history.plans.length >= policy.max_replans) {
|
|
647
672
|
throw new Error(
|
|
648
|
-
`
|
|
673
|
+
`governor ${input.record.intent.id} exhausted its ${policy.max_replans} replans`,
|
|
649
674
|
);
|
|
650
675
|
}
|
|
651
676
|
appendPlanEvent(input.coordRoot, input.record.intent.id, input.planId, {
|
|
@@ -653,24 +678,24 @@ export function retrySupervisorPlanProposal(input: {
|
|
|
653
678
|
actor: input.actor,
|
|
654
679
|
reason,
|
|
655
680
|
});
|
|
656
|
-
return outcome(
|
|
681
|
+
return outcome(readGovernorPlan(input.coordRoot, input.record.intent.id, input.planId));
|
|
657
682
|
}
|
|
658
683
|
|
|
659
684
|
function createPlanRequest(
|
|
660
685
|
coordRoot: string,
|
|
661
|
-
record:
|
|
686
|
+
record: GovernorRecord,
|
|
662
687
|
sequence: number,
|
|
663
688
|
triggerFingerprint: string,
|
|
664
|
-
trigger: NonNullable<
|
|
665
|
-
):
|
|
689
|
+
trigger: NonNullable<GovernorPlanRequest["trigger"]>,
|
|
690
|
+
): GovernorPlanRequest {
|
|
666
691
|
const policy = record.intent.replanning;
|
|
667
|
-
if (!policy) throw new Error(`
|
|
692
|
+
if (!policy) throw new Error(`governor ${record.intent.id} does not allow replanning`);
|
|
668
693
|
if (sequence > policy.max_replans) {
|
|
669
|
-
throw new Error(`
|
|
694
|
+
throw new Error(`governor ${record.intent.id} exhausted its ${policy.max_replans} replans`);
|
|
670
695
|
}
|
|
671
696
|
const planId = `plan-${String(sequence).padStart(4, "0")}-${randomBytes(4).toString("hex")}`;
|
|
672
|
-
const request:
|
|
673
|
-
schema_version:
|
|
697
|
+
const request: GovernorPlanRequest = {
|
|
698
|
+
schema_version: GOVERNOR_PLAN_SCHEMA_VERSION,
|
|
674
699
|
id: planId,
|
|
675
700
|
goal_id: record.intent.id,
|
|
676
701
|
sequence,
|
|
@@ -684,19 +709,19 @@ function createPlanRequest(
|
|
|
684
709
|
const dir = planDir(coordRoot, record.intent.id, planId);
|
|
685
710
|
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
686
711
|
chmodSync(dir, 0o700);
|
|
687
|
-
writeExclusiveJson(join(dir, "request.json"), request, "
|
|
688
|
-
writeExclusive(join(dir, "planner.mjs"), script, "
|
|
712
|
+
writeExclusiveJson(join(dir, "request.json"), request, "governor plan request");
|
|
713
|
+
writeExclusive(join(dir, "planner.mjs"), script, "governor planner script");
|
|
689
714
|
return request;
|
|
690
715
|
}
|
|
691
716
|
|
|
692
717
|
function plannerScript(
|
|
693
718
|
coordRoot: string,
|
|
694
|
-
record:
|
|
719
|
+
record: GovernorRecord,
|
|
695
720
|
planId: string,
|
|
696
|
-
trigger: NonNullable<
|
|
721
|
+
trigger: NonNullable<GovernorPlanRequest["trigger"]>,
|
|
697
722
|
): string {
|
|
698
723
|
const policy = record.intent.replanning;
|
|
699
|
-
if (!policy) throw new Error(`
|
|
724
|
+
if (!policy) throw new Error(`governor ${record.intent.id} does not allow replanning`);
|
|
700
725
|
const prompt = [
|
|
701
726
|
"You are producing one bounded replacement plan or milestone decision for a durable supervised goal.",
|
|
702
727
|
record.intent.mission
|
|
@@ -775,14 +800,14 @@ function plannerScript(
|
|
|
775
800
|
}
|
|
776
801
|
|
|
777
802
|
function plannerReviewScript(
|
|
778
|
-
record:
|
|
803
|
+
record: GovernorRecord,
|
|
779
804
|
planId: string,
|
|
780
|
-
initialCandidate:
|
|
781
|
-
trigger: NonNullable<
|
|
805
|
+
initialCandidate: GovernorPlanProposal,
|
|
806
|
+
trigger: NonNullable<GovernorPlanRequest["trigger"]>,
|
|
782
807
|
): string {
|
|
783
808
|
const policy = record.intent.replanning;
|
|
784
809
|
const review = policy?.review;
|
|
785
|
-
if (!policy || !review) throw new Error(`
|
|
810
|
+
if (!policy || !review) throw new Error(`governor ${record.intent.id} does not review plans`);
|
|
786
811
|
const proposalSchema = planProposalSchema(record, trigger);
|
|
787
812
|
const reviewerSchema: StageSchema = {
|
|
788
813
|
type: "object",
|
|
@@ -843,7 +868,7 @@ function plannerReviewScript(
|
|
|
843
868
|
" stage('Review round ' + round);",
|
|
844
869
|
" const reviewersOut = await Promise.all(reviewers.map(async (specialist) => {",
|
|
845
870
|
" const prompt = [",
|
|
846
|
-
" 'Review this bounded
|
|
871
|
+
" 'Review this bounded governor plan candidate independently.',",
|
|
847
872
|
" 'Return approve only when the candidate is complete, scoped, and satisfies the goal context.',",
|
|
848
873
|
" 'Return revise for blocking defects. Return attention when human judgment is required.',",
|
|
849
874
|
" 'Apply proposal_root_rule exactly; never require proposal.root to equal active_root.',",
|
|
@@ -863,7 +888,7 @@ function plannerReviewScript(
|
|
|
863
888
|
" if (round > maxRevisionRounds) break;",
|
|
864
889
|
" stage('Revise round ' + round);",
|
|
865
890
|
" const revisionPrompt = [",
|
|
866
|
-
" 'Revise this
|
|
891
|
+
" 'Revise this governor plan candidate. Return a complete replacement candidate, not a patch.',",
|
|
867
892
|
" 'Do not merge reviewer text mechanically; satisfy the blocking findings within the frozen goal and template constraints.',",
|
|
868
893
|
" 'Apply proposal_root_rule exactly; never require proposal.root to equal active_root.',",
|
|
869
894
|
" 'Goal context: ' + JSON.stringify(goalContext),",
|
|
@@ -885,13 +910,13 @@ function plannerReviewScript(
|
|
|
885
910
|
|
|
886
911
|
function normalizeReviewReceipt(input: {
|
|
887
912
|
raw: unknown;
|
|
888
|
-
initialCandidate:
|
|
889
|
-
record:
|
|
890
|
-
request:
|
|
891
|
-
history: ReturnType<typeof
|
|
892
|
-
trigger: NonNullable<
|
|
893
|
-
policy:
|
|
894
|
-
}):
|
|
913
|
+
initialCandidate: GovernorPlanProposal;
|
|
914
|
+
record: GovernorRecord;
|
|
915
|
+
request: GovernorPlanRequest;
|
|
916
|
+
history: ReturnType<typeof readGovernorPlans>;
|
|
917
|
+
trigger: NonNullable<GovernorPlanRequest["trigger"]>;
|
|
918
|
+
policy: GovernorReplanningPolicy;
|
|
919
|
+
}): GovernorPlanReviewReceipt {
|
|
895
920
|
const review = input.policy.review;
|
|
896
921
|
if (!review) throw new Error("missing review policy");
|
|
897
922
|
if (!input.raw || typeof input.raw !== "object" || Array.isArray(input.raw)) {
|
|
@@ -902,9 +927,9 @@ function normalizeReviewReceipt(input: {
|
|
|
902
927
|
if (raw.rounds.length < 1 || raw.rounds.length > review.max_revision_rounds + 1) {
|
|
903
928
|
throw new Error("review result has an invalid number of rounds");
|
|
904
929
|
}
|
|
905
|
-
const rounds:
|
|
930
|
+
const rounds: GovernorPlanReviewRound[] = [];
|
|
906
931
|
let candidate = input.initialCandidate;
|
|
907
|
-
let status:
|
|
932
|
+
let status: GovernorPlanReviewReceipt["status"] | undefined;
|
|
908
933
|
for (const [index, rawRound] of raw.rounds.entries()) {
|
|
909
934
|
if (!rawRound || typeof rawRound !== "object" || Array.isArray(rawRound)) {
|
|
910
935
|
throw new Error(`review round ${index + 1} must be an object`);
|
|
@@ -915,7 +940,7 @@ function normalizeReviewReceipt(input: {
|
|
|
915
940
|
if (roundNumber !== index + 1) throw new Error(`review round must be ${index + 1}`);
|
|
916
941
|
const reviewers = normalizeReviewers(value.reviewers, review.reviewer_specialists);
|
|
917
942
|
const outcome = aggregateReviewers(reviewers);
|
|
918
|
-
const round:
|
|
943
|
+
const round: GovernorPlanReviewRound = {
|
|
919
944
|
round: roundNumber,
|
|
920
945
|
candidate_sha256: candidateDigest(candidate),
|
|
921
946
|
reviewers,
|
|
@@ -946,7 +971,7 @@ function normalizeReviewReceipt(input: {
|
|
|
946
971
|
}
|
|
947
972
|
status ??= "attention";
|
|
948
973
|
return {
|
|
949
|
-
schema_version:
|
|
974
|
+
schema_version: GOVERNOR_PLAN_SCHEMA_VERSION,
|
|
950
975
|
plan_id: input.request.id,
|
|
951
976
|
status,
|
|
952
977
|
candidate_sha256: candidateDigest(candidate),
|
|
@@ -958,7 +983,7 @@ function normalizeReviewReceipt(input: {
|
|
|
958
983
|
function normalizeReviewers(
|
|
959
984
|
raw: unknown,
|
|
960
985
|
expectedSpecialists: readonly string[],
|
|
961
|
-
):
|
|
986
|
+
): GovernorPlanReviewReviewer[] {
|
|
962
987
|
if (!Array.isArray(raw) || raw.length !== expectedSpecialists.length) {
|
|
963
988
|
throw new Error("reviewer result count does not match the frozen review policy");
|
|
964
989
|
}
|
|
@@ -981,7 +1006,7 @@ function normalizeReviewers(
|
|
|
981
1006
|
});
|
|
982
1007
|
}
|
|
983
1008
|
|
|
984
|
-
function normalizeFindings(raw: unknown, specialist: string):
|
|
1009
|
+
function normalizeFindings(raw: unknown, specialist: string): GovernorPlanReviewFinding[] {
|
|
985
1010
|
if (!Array.isArray(raw) || raw.length > 50) {
|
|
986
1011
|
throw new Error(`review findings from ${specialist} must contain at most 50 items`);
|
|
987
1012
|
}
|
|
@@ -1010,8 +1035,8 @@ function findingCode(value: unknown, specialist: string, index: number): string
|
|
|
1010
1035
|
}
|
|
1011
1036
|
|
|
1012
1037
|
function aggregateReviewers(
|
|
1013
|
-
reviewers: readonly
|
|
1014
|
-
):
|
|
1038
|
+
reviewers: readonly GovernorPlanReviewReviewer[],
|
|
1039
|
+
): GovernorPlanReviewRound["outcome"] {
|
|
1015
1040
|
if (reviewers.length < 1) return "failed";
|
|
1016
1041
|
if (reviewers.some((reviewer) => reviewer.verdict === "attention")) return "attention";
|
|
1017
1042
|
if (
|
|
@@ -1028,12 +1053,12 @@ function aggregateReviewers(
|
|
|
1028
1053
|
|
|
1029
1054
|
function reconstructReviewReceiptFromProof(input: {
|
|
1030
1055
|
coordRoot: string;
|
|
1031
|
-
record:
|
|
1032
|
-
request:
|
|
1033
|
-
history: ReturnType<typeof
|
|
1034
|
-
trigger: NonNullable<
|
|
1035
|
-
policy:
|
|
1036
|
-
}):
|
|
1056
|
+
record: GovernorRecord;
|
|
1057
|
+
request: GovernorPlanRequest;
|
|
1058
|
+
history: ReturnType<typeof readGovernorPlans>;
|
|
1059
|
+
trigger: NonNullable<GovernorPlanRequest["trigger"]>;
|
|
1060
|
+
policy: GovernorReplanningPolicy;
|
|
1061
|
+
}): GovernorPlanReviewReceipt | undefined {
|
|
1037
1062
|
const runId = reviewWorkflowRunId(input.request.id);
|
|
1038
1063
|
const proofPath = join(input.coordRoot, ".harnery", "workflows", runId, "proof.json");
|
|
1039
1064
|
if (!existsSync(proofPath)) return undefined;
|
|
@@ -1065,19 +1090,19 @@ function recoverReviewWorkflowResult(
|
|
|
1065
1090
|
proof: WorkflowProof,
|
|
1066
1091
|
expectedSpecialists: readonly string[],
|
|
1067
1092
|
): {
|
|
1068
|
-
initialCandidate:
|
|
1093
|
+
initialCandidate: GovernorPlanProposal;
|
|
1069
1094
|
result: { rounds: unknown[] };
|
|
1070
1095
|
} {
|
|
1071
1096
|
const inputPath = reviewInputPath(coordRoot, goalId, planId);
|
|
1072
|
-
const reviewInput = readBoundedJson<{ candidate:
|
|
1097
|
+
const reviewInput = readBoundedJson<{ candidate: GovernorPlanProposal }>(
|
|
1073
1098
|
inputPath,
|
|
1074
|
-
"
|
|
1099
|
+
"governor plan review input",
|
|
1075
1100
|
);
|
|
1076
|
-
const
|
|
1101
|
+
const transcript = readVerifiedWorkflowTranscript(coordRoot, reviewWorkflowRunId(planId), proof);
|
|
1077
1102
|
const starts = new Map<string, { specialist?: string }>();
|
|
1078
1103
|
const byRound = new Map<number, Record<string, unknown>>();
|
|
1079
1104
|
let currentCandidate: unknown = reviewInput.candidate;
|
|
1080
|
-
for (const line of
|
|
1105
|
+
for (const line of transcript.split("\n")) {
|
|
1081
1106
|
if (!line.trim()) continue;
|
|
1082
1107
|
const event = JSON.parse(line) as Record<string, unknown>;
|
|
1083
1108
|
if (event.event === "agent.start" && typeof event.id === "string") {
|
|
@@ -1086,7 +1111,7 @@ function recoverReviewWorkflowResult(
|
|
|
1086
1111
|
});
|
|
1087
1112
|
}
|
|
1088
1113
|
if (event.event !== "agent.end" || event.result_kind !== "json") continue;
|
|
1089
|
-
const round =
|
|
1114
|
+
const round = workflowTranscriptRound(event.stage);
|
|
1090
1115
|
if (!round) continue;
|
|
1091
1116
|
let record = byRound.get(round.round);
|
|
1092
1117
|
if (!record) {
|
|
@@ -1097,7 +1122,7 @@ function recoverReviewWorkflowResult(
|
|
|
1097
1122
|
const specialist =
|
|
1098
1123
|
typeof event.id === "string" ? starts.get(event.id)?.specialist : undefined;
|
|
1099
1124
|
if (!event.result || typeof event.result !== "object" || Array.isArray(event.result)) {
|
|
1100
|
-
throw new Error("
|
|
1125
|
+
throw new Error("governor plan review transcript contains an invalid reviewer result");
|
|
1101
1126
|
}
|
|
1102
1127
|
(record.reviewers as unknown[]).push({
|
|
1103
1128
|
specialist,
|
|
@@ -1129,22 +1154,28 @@ function recoverReviewWorkflowResult(
|
|
|
1129
1154
|
};
|
|
1130
1155
|
}
|
|
1131
1156
|
|
|
1132
|
-
function
|
|
1157
|
+
function readVerifiedWorkflowTranscript(
|
|
1133
1158
|
coordRoot: string,
|
|
1134
1159
|
runId: string,
|
|
1135
1160
|
proof: WorkflowProof,
|
|
1136
1161
|
): string {
|
|
1137
|
-
const
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1162
|
+
const transcriptPath = join(
|
|
1163
|
+
coordRoot,
|
|
1164
|
+
".harnery",
|
|
1165
|
+
"workflows",
|
|
1166
|
+
runId,
|
|
1167
|
+
proof.integrity.transcript.path,
|
|
1168
|
+
);
|
|
1169
|
+
const transcript = readFileSync(transcriptPath, "utf8");
|
|
1170
|
+
const bytes = Buffer.byteLength(transcript);
|
|
1171
|
+
if (bytes <= 0 || bytes > MAX_RECORD_BYTES || bytes !== proof.integrity.transcript.bytes) {
|
|
1172
|
+
throw new Error(`governor plan review transcript does not match proof integrity`);
|
|
1142
1173
|
}
|
|
1143
|
-
const sha256 = createHash("sha256").update(
|
|
1144
|
-
if (sha256 !== proof.integrity.
|
|
1145
|
-
throw new Error(`
|
|
1174
|
+
const sha256 = createHash("sha256").update(transcript).digest("hex");
|
|
1175
|
+
if (sha256 !== proof.integrity.transcript.sha256) {
|
|
1176
|
+
throw new Error(`governor plan review transcript does not match proof integrity`);
|
|
1146
1177
|
}
|
|
1147
|
-
return
|
|
1178
|
+
return transcript;
|
|
1148
1179
|
}
|
|
1149
1180
|
|
|
1150
1181
|
function orderRecoveredReviewers(raw: unknown, expectedSpecialists: readonly string[]): unknown[] {
|
|
@@ -1202,7 +1233,7 @@ function aggregateRecoveredReviewers(reviewers: readonly unknown[]): string {
|
|
|
1202
1233
|
|
|
1203
1234
|
function assertResultDigest(raw: unknown, expected: ResultDigest | undefined, runId: string): void {
|
|
1204
1235
|
if (!expected) {
|
|
1205
|
-
throw new Error(`
|
|
1236
|
+
throw new Error(`governor plan review proof ${runId} is missing its result digest`);
|
|
1206
1237
|
}
|
|
1207
1238
|
const actual = digestResult(raw, "json");
|
|
1208
1239
|
if (
|
|
@@ -1210,11 +1241,11 @@ function assertResultDigest(raw: unknown, expected: ResultDigest | undefined, ru
|
|
|
1210
1241
|
actual.sha256 !== expected.sha256 ||
|
|
1211
1242
|
actual.bytes !== expected.bytes
|
|
1212
1243
|
) {
|
|
1213
|
-
throw new Error(`
|
|
1244
|
+
throw new Error(`governor plan review result does not match proof digest`);
|
|
1214
1245
|
}
|
|
1215
1246
|
}
|
|
1216
1247
|
|
|
1217
|
-
function
|
|
1248
|
+
function workflowTranscriptRound(
|
|
1218
1249
|
stage: unknown,
|
|
1219
1250
|
): { kind: "review" | "revision"; round: number } | undefined {
|
|
1220
1251
|
if (typeof stage !== "string") return undefined;
|
|
@@ -1225,13 +1256,13 @@ function workflowJournalRound(
|
|
|
1225
1256
|
return undefined;
|
|
1226
1257
|
}
|
|
1227
1258
|
|
|
1228
|
-
function candidateDigest(candidate:
|
|
1259
|
+
function candidateDigest(candidate: GovernorPlanProposal): string {
|
|
1229
1260
|
return createHash("sha256")
|
|
1230
1261
|
.update(JSON.stringify(canonicalCandidate(candidate)))
|
|
1231
1262
|
.digest("hex");
|
|
1232
1263
|
}
|
|
1233
1264
|
|
|
1234
|
-
function canonicalCandidate(candidate:
|
|
1265
|
+
function canonicalCandidate(candidate: GovernorPlanProposal): unknown {
|
|
1235
1266
|
return {
|
|
1236
1267
|
schema_version: candidate.schema_version,
|
|
1237
1268
|
plan_id: candidate.plan_id,
|
|
@@ -1251,11 +1282,11 @@ function hasReviewRecoveryEvidence(coordRoot: string, goalId: string, planId: st
|
|
|
1251
1282
|
}
|
|
1252
1283
|
|
|
1253
1284
|
function planProposalSchema(
|
|
1254
|
-
record:
|
|
1255
|
-
trigger: NonNullable<
|
|
1285
|
+
record: GovernorRecord,
|
|
1286
|
+
trigger: NonNullable<GovernorPlanRequest["trigger"]>,
|
|
1256
1287
|
): StageSchema {
|
|
1257
1288
|
const policy = record.intent.replanning;
|
|
1258
|
-
if (!policy) throw new Error(`
|
|
1289
|
+
if (!policy) throw new Error(`governor ${record.intent.id} does not allow replanning`);
|
|
1259
1290
|
const rationale: StageSchema = { type: "string", minLength: 1, maxLength: MAX_REASON };
|
|
1260
1291
|
const workItem: StageSchema = {
|
|
1261
1292
|
type: "object",
|
|
@@ -1345,13 +1376,13 @@ function planProposalSchema(
|
|
|
1345
1376
|
function normalizeProposal(
|
|
1346
1377
|
planId: string,
|
|
1347
1378
|
raw: unknown,
|
|
1348
|
-
record:
|
|
1379
|
+
record: GovernorRecord,
|
|
1349
1380
|
previouslyApplied: number,
|
|
1350
|
-
trigger: NonNullable<
|
|
1381
|
+
trigger: NonNullable<GovernorPlanRequest["trigger"]>,
|
|
1351
1382
|
preservedProposedAt?: string,
|
|
1352
|
-
):
|
|
1383
|
+
): GovernorPlanProposal {
|
|
1353
1384
|
const policy = record.intent.replanning;
|
|
1354
|
-
if (!policy) throw new Error(`
|
|
1385
|
+
if (!policy) throw new Error(`governor ${record.intent.id} does not allow replanning`);
|
|
1355
1386
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
1356
1387
|
throw new Error("planner result must be an object");
|
|
1357
1388
|
}
|
|
@@ -1369,7 +1400,7 @@ function normalizeProposal(
|
|
|
1369
1400
|
throw new Error("mission completion may be proposed only at a milestone boundary");
|
|
1370
1401
|
}
|
|
1371
1402
|
return {
|
|
1372
|
-
schema_version:
|
|
1403
|
+
schema_version: GOVERNOR_PLAN_SCHEMA_VERSION,
|
|
1373
1404
|
plan_id: planId,
|
|
1374
1405
|
decision,
|
|
1375
1406
|
rationale,
|
|
@@ -1397,7 +1428,7 @@ function normalizeProposal(
|
|
|
1397
1428
|
}
|
|
1398
1429
|
const active = new Set(record.projection.work_ids);
|
|
1399
1430
|
const seen = new Set<string>();
|
|
1400
|
-
const work = value.work.map((candidate, index):
|
|
1431
|
+
const work = value.work.map((candidate, index): GovernorPlanWorkSpec => {
|
|
1401
1432
|
if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
|
|
1402
1433
|
throw new Error(`plan work[${index}] must be an object`);
|
|
1403
1434
|
}
|
|
@@ -1463,7 +1494,7 @@ function normalizeProposal(
|
|
|
1463
1494
|
`plan contains work not reachable from root: ${unused.map((item) => item.key).join(", ")}`,
|
|
1464
1495
|
);
|
|
1465
1496
|
return {
|
|
1466
|
-
schema_version:
|
|
1497
|
+
schema_version: GOVERNOR_PLAN_SCHEMA_VERSION,
|
|
1467
1498
|
plan_id: planId,
|
|
1468
1499
|
decision,
|
|
1469
1500
|
rationale,
|
|
@@ -1485,7 +1516,7 @@ function persistedProposalTimestamp(raw: unknown): string {
|
|
|
1485
1516
|
return value;
|
|
1486
1517
|
}
|
|
1487
1518
|
|
|
1488
|
-
function normalizeMilestone(raw: unknown, expectedSequence: number):
|
|
1519
|
+
function normalizeMilestone(raw: unknown, expectedSequence: number): GovernorPlanMilestone {
|
|
1489
1520
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
1490
1521
|
throw new Error("mission plan must contain a milestone object");
|
|
1491
1522
|
}
|
|
@@ -1507,7 +1538,7 @@ function normalizeMilestone(raw: unknown, expectedSequence: number): SupervisorP
|
|
|
1507
1538
|
};
|
|
1508
1539
|
}
|
|
1509
1540
|
|
|
1510
|
-
function planTrigger(record:
|
|
1541
|
+
function planTrigger(record: GovernorRecord): NonNullable<GovernorPlanRequest["trigger"]> {
|
|
1511
1542
|
if (
|
|
1512
1543
|
record.intent.mission &&
|
|
1513
1544
|
record.projection.plan_generation === 0 &&
|
|
@@ -1523,13 +1554,13 @@ function appendPlanEvent(
|
|
|
1523
1554
|
coordRootRaw: string,
|
|
1524
1555
|
goalId: string,
|
|
1525
1556
|
planId: string,
|
|
1526
|
-
input: Omit<
|
|
1557
|
+
input: Omit<GovernorPlanEvent, "schema_version" | "plan_id" | "seq" | "ts">,
|
|
1527
1558
|
): void {
|
|
1528
1559
|
const coordRoot = resolve(coordRootRaw);
|
|
1529
1560
|
const path = join(planDir(coordRoot, goalId, planId), "events.jsonl");
|
|
1530
|
-
const current =
|
|
1531
|
-
const event:
|
|
1532
|
-
schema_version:
|
|
1561
|
+
const current = readGovernorPlan(coordRoot, goalId, planId).events;
|
|
1562
|
+
const event: GovernorPlanEvent = {
|
|
1563
|
+
schema_version: GOVERNOR_PLAN_SCHEMA_VERSION,
|
|
1533
1564
|
plan_id: planId,
|
|
1534
1565
|
seq: current.length + 1,
|
|
1535
1566
|
ts: new Date().toISOString(),
|
|
@@ -1540,7 +1571,7 @@ function appendPlanEvent(
|
|
|
1540
1571
|
const line = `${JSON.stringify(event)}\n`;
|
|
1541
1572
|
const existing = existsSync(path) ? statSync(path).size : 0;
|
|
1542
1573
|
if (existing + Buffer.byteLength(line) > MAX_EVENTS_BYTES) {
|
|
1543
|
-
throw new Error("
|
|
1574
|
+
throw new Error("governor plan event log would exceed its byte limit");
|
|
1544
1575
|
}
|
|
1545
1576
|
appendFileSync(path, line, { encoding: "utf8", mode: 0o600 });
|
|
1546
1577
|
chmodSync(path, 0o600);
|
|
@@ -1550,15 +1581,15 @@ function appendPlanEventIfMissing(
|
|
|
1550
1581
|
coordRoot: string,
|
|
1551
1582
|
goalId: string,
|
|
1552
1583
|
planId: string,
|
|
1553
|
-
eventType:
|
|
1554
|
-
input: Omit<
|
|
1584
|
+
eventType: GovernorPlanEvent["event"],
|
|
1585
|
+
input: Omit<GovernorPlanEvent, "schema_version" | "plan_id" | "seq" | "ts">,
|
|
1555
1586
|
): void {
|
|
1556
|
-
const plan =
|
|
1587
|
+
const plan = readGovernorPlan(coordRoot, goalId, planId);
|
|
1557
1588
|
if (plan.events.some((event) => event.event === eventType)) return;
|
|
1558
1589
|
appendPlanEvent(coordRoot, goalId, planId, input);
|
|
1559
1590
|
}
|
|
1560
1591
|
|
|
1561
|
-
function outcome(plan: ReturnType<typeof
|
|
1592
|
+
function outcome(plan: ReturnType<typeof readGovernorPlan>): GovernorPlanOutcome {
|
|
1562
1593
|
return {
|
|
1563
1594
|
plan_id: plan.request.id,
|
|
1564
1595
|
status: plan.status,
|
|
@@ -1599,7 +1630,7 @@ function writeExclusive(path: string, body: string, label: string): void {
|
|
|
1599
1630
|
}
|
|
1600
1631
|
|
|
1601
1632
|
function planDir(coordRoot: string, goalId: string, planId: string): string {
|
|
1602
|
-
return join(coordRoot, ".harnery", "
|
|
1633
|
+
return join(coordRoot, ".harnery", "governors", goalId, "plans", planId);
|
|
1603
1634
|
}
|
|
1604
1635
|
|
|
1605
1636
|
function planScriptPath(coordRoot: string, goalId: string, planId: string): string {
|