harnery 0.29.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 +2 -1
- package/dist/commands/work.d.ts.map +1 -1
- package/dist/commands/work.js +55 -25
- 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 +28 -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 +71 -51
- package/dist/core/governor/plan-types.d.ts +181 -0
- 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 +143 -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 +290 -116
- 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/runner.d.ts.map +1 -1
- package/dist/core/work/runner.js +11 -2
- package/dist/core/work/state.d.ts +28 -3
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +148 -16
- 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 +151 -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 +3 -2
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/index.js +2 -1
- package/dist/core/workflow/proof.d.ts +28 -5
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +77 -34
- 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 +28 -8
- 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 +26 -8
- 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 +27 -8
- package/dist/core/workflow/spawn-failure.d.ts +15 -1
- package/dist/core/workflow/spawn-failure.d.ts.map +1 -1
- package/dist/core/workflow/spawn-failure.js +35 -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 +119 -46
- 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/exec.d.ts +7 -0
- package/dist/lib/exec.d.ts.map +1 -1
- package/dist/lib/exec.js +6 -3
- 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 +72 -38
- 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 +28 -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 +120 -96
- package/src/core/{supervisor → governor}/plan-types.ts +64 -50
- package/src/core/{supervisor → governor}/planning.ts +240 -188
- 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 +389 -174
- 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/runner.ts +11 -2
- package/src/core/work/state.ts +185 -21
- 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 +166 -90
- package/src/core/workflow/evidence-preflight.ts +165 -0
- package/src/core/workflow/index.ts +6 -3
- package/src/core/workflow/proof.ts +94 -48
- 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 +34 -12
- package/src/core/workflow/spawn-codex.ts +30 -12
- package/src/core/workflow/spawn-cursor.ts +31 -12
- package/src/core/workflow/spawn-failure.ts +41 -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 +130 -46
- 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/exec.ts +13 -3
- 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 +0 -170
- 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
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preflight: would every specialist on this team land on the same adapter?
|
|
3
|
+
*
|
|
4
|
+
* Harnery does not auto-spread. A specialist without an `adapter` pin inherits
|
|
5
|
+
* the run's default, so a team whose profiles all omit the pin puts every child
|
|
6
|
+
* on one adapter. That is legal and sometimes intended. It is a problem when the
|
|
7
|
+
* host is also `subscriptionOnly`, because then the concentration lands on one
|
|
8
|
+
* seat's session meter rather than on metered per-token billing: the seat hits
|
|
9
|
+
* its limit, and every specialist stops at once rather than the team degrading.
|
|
10
|
+
*
|
|
11
|
+
* The check is deliberately narrow, because a false refusal here is worse than
|
|
12
|
+
* the miss it prevents. It fires only when all four hold:
|
|
13
|
+
*
|
|
14
|
+
* 1. more than one specialist (a solo team cannot spread),
|
|
15
|
+
* 2. every specialist resolves to the same adapter,
|
|
16
|
+
* 3. `subscriptionOnly` is on (otherwise concentration is a cost curve, not a
|
|
17
|
+
* cliff), and
|
|
18
|
+
* 4. more than one adapter is ATTESTED REACHABLE.
|
|
19
|
+
*
|
|
20
|
+
* Condition 4 is the one worth insisting on. Counting *declared* adapters would
|
|
21
|
+
* suggest spreading onto a seat that cannot run — a dead adapter passes a
|
|
22
|
+
* declaration check and then fails every child it is handed. Only an
|
|
23
|
+
* attestation records that the adapter actually completed a turn on this
|
|
24
|
+
* machine, so only an attestation is grounds for telling someone to use it.
|
|
25
|
+
*/
|
|
26
|
+
export interface AdapterSpreadInput {
|
|
27
|
+
/** Specialist id → its optional adapter pin. */
|
|
28
|
+
specialists: Readonly<Record<string, {
|
|
29
|
+
adapter?: string;
|
|
30
|
+
}>>;
|
|
31
|
+
/** The adapter an unpinned specialist inherits. */
|
|
32
|
+
defaultAdapter: string;
|
|
33
|
+
/** Adapters with a live attestation on this machine — proven to run, not
|
|
34
|
+
* merely registered. */
|
|
35
|
+
reachable: readonly string[];
|
|
36
|
+
/** Whether children are confined to subscription (logged-in) auth. */
|
|
37
|
+
subscriptionOnly: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface AdapterSpreadVerdict {
|
|
40
|
+
/** True when the team would put every child on one adapter AND that is worth
|
|
41
|
+
* refusing over. False both when the team spreads and when concentrating is
|
|
42
|
+
* unremarkable (single specialist, one reachable adapter, metered billing). */
|
|
43
|
+
concentrated: boolean;
|
|
44
|
+
/** The adapter everything would land on, when concentrated. */
|
|
45
|
+
adapter?: string;
|
|
46
|
+
/** Operator-facing explanation, present exactly when concentrated. */
|
|
47
|
+
reason?: string;
|
|
48
|
+
/** Attested-reachable adapters this team is not using. */
|
|
49
|
+
unused: string[];
|
|
50
|
+
}
|
|
51
|
+
export declare function inspectAdapterSpread(input: AdapterSpreadInput): AdapterSpreadVerdict;
|
|
52
|
+
//# sourceMappingURL=adapter-spread.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-spread.d.ts","sourceRoot":"","sources":["../../../src/core/governor/adapter-spread.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IAC5D,mDAAmD;IACnD,cAAc,EAAE,MAAM,CAAC;IACvB;4BACwB;IACxB,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,sEAAsE;IACtE,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,oBAAoB;IACnC;;mFAE+E;IAC/E,YAAY,EAAE,OAAO,CAAC;IACtB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,kBAAkB,GAAG,oBAAoB,CA8BpF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preflight: would every specialist on this team land on the same adapter?
|
|
3
|
+
*
|
|
4
|
+
* Harnery does not auto-spread. A specialist without an `adapter` pin inherits
|
|
5
|
+
* the run's default, so a team whose profiles all omit the pin puts every child
|
|
6
|
+
* on one adapter. That is legal and sometimes intended. It is a problem when the
|
|
7
|
+
* host is also `subscriptionOnly`, because then the concentration lands on one
|
|
8
|
+
* seat's session meter rather than on metered per-token billing: the seat hits
|
|
9
|
+
* its limit, and every specialist stops at once rather than the team degrading.
|
|
10
|
+
*
|
|
11
|
+
* The check is deliberately narrow, because a false refusal here is worse than
|
|
12
|
+
* the miss it prevents. It fires only when all four hold:
|
|
13
|
+
*
|
|
14
|
+
* 1. more than one specialist (a solo team cannot spread),
|
|
15
|
+
* 2. every specialist resolves to the same adapter,
|
|
16
|
+
* 3. `subscriptionOnly` is on (otherwise concentration is a cost curve, not a
|
|
17
|
+
* cliff), and
|
|
18
|
+
* 4. more than one adapter is ATTESTED REACHABLE.
|
|
19
|
+
*
|
|
20
|
+
* Condition 4 is the one worth insisting on. Counting *declared* adapters would
|
|
21
|
+
* suggest spreading onto a seat that cannot run — a dead adapter passes a
|
|
22
|
+
* declaration check and then fails every child it is handed. Only an
|
|
23
|
+
* attestation records that the adapter actually completed a turn on this
|
|
24
|
+
* machine, so only an attestation is grounds for telling someone to use it.
|
|
25
|
+
*/
|
|
26
|
+
export function inspectAdapterSpread(input) {
|
|
27
|
+
const ids = Object.keys(input.specialists);
|
|
28
|
+
const resolved = ids.map((id) => input.specialists[id]?.adapter ?? input.defaultAdapter);
|
|
29
|
+
const distinct = [...new Set(resolved)];
|
|
30
|
+
const unused = input.reachable.filter((a) => !distinct.includes(a));
|
|
31
|
+
if (ids.length < 2 || distinct.length !== 1 || !input.subscriptionOnly || unused.length === 0) {
|
|
32
|
+
return { concentrated: false, unused };
|
|
33
|
+
}
|
|
34
|
+
const adapter = distinct[0];
|
|
35
|
+
const pinned = ids.filter((id) => input.specialists[id]?.adapter).length;
|
|
36
|
+
// Say which of the two shapes this is. "You wrote no pins" and "you pinned
|
|
37
|
+
// them all to one" need different corrections, and a single generic message
|
|
38
|
+
// would send half the readers looking in the wrong place.
|
|
39
|
+
const how = pinned === 0
|
|
40
|
+
? `no specialist pins an adapter, so all ${ids.length} inherit the default (${adapter})`
|
|
41
|
+
: `all ${ids.length} specialists resolve to ${adapter}`;
|
|
42
|
+
return {
|
|
43
|
+
concentrated: true,
|
|
44
|
+
adapter,
|
|
45
|
+
unused,
|
|
46
|
+
reason: `${how}, and children are confined to subscription auth — so one seat carries the whole ` +
|
|
47
|
+
`team and every specialist stops together when it hits its limit. ` +
|
|
48
|
+
`${unused.length === 1 ? "This adapter is" : "These adapters are"} attested and idle: ` +
|
|
49
|
+
`${unused.join(", ")}. Pin some specialists onto ${unused.length === 1 ? "it" : "them"}, ` +
|
|
50
|
+
`or pass --allow-single-adapter if one seat is what you want.`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { approveGovernorPlan, findCompletedMissionGoverning, rejectGovernorPlan, reopenGovernorMission, retryGovernorPlan, } from "./plan-api.js";
|
|
2
|
+
export { readGovernorPlan, readGovernorPlanReviewReceipt, readGovernorPlans, } from "./plan-read.js";
|
|
3
|
+
export { type CreateGovernorPlanTemplateInput, type CreateGovernorReplanningInput, GOVERNOR_PLAN_SCHEMA_VERSION, type GovernorPlanEvent, type GovernorPlanEventType, type GovernorPlanHistory, type GovernorPlanMilestone, type GovernorPlanOutcome, type GovernorPlanProposal, type GovernorPlanRecord, type GovernorPlanRequest, type GovernorPlanReviewFinding, type GovernorPlanReviewReceipt, type GovernorPlanReviewReviewer, type GovernorPlanReviewRound, type GovernorPlanReviewStatus, type GovernorPlanReviewSummary, type GovernorPlanReviewVerdict, type GovernorPlanStatus, type GovernorPlanTemplate, type GovernorPlanWorkSpec, type GovernorReplanningPolicy, MAX_GOVERNOR_PLAN_REVIEWERS, MAX_GOVERNOR_PLAN_REVISION_ROUNDS, } from "./plan-types.js";
|
|
4
|
+
export { type GovernorDispatchOutcome, type GovernorRunReport, type GovernorStopReason, type RunGovernorInput, runGovernor, } from "./runner.js";
|
|
5
|
+
export { type ConfigureGovernorServiceInput, configureGovernorService, GOVERNOR_SERVICE_CONFIG_SCHEMA_VERSION, GOVERNOR_SERVICE_RUNTIME_SCHEMA_VERSION, GOVERNOR_SERVICE_STATUS_SCHEMA_VERSION, type GovernorServiceConfig, type GovernorServiceEngineConfig, type GovernorServiceGoalRuntime, type GovernorServiceGoalState, type GovernorServiceProcessState, type GovernorServiceRuntime, type GovernorServiceStatus, type GovernorServiceStatusRecord, type GovernorServiceSweepOutcome, type GovernorServiceSweepReport, governorServiceLogPath, type RunGovernorServiceDaemonInput, type RunGovernorServiceSweepInput, readGovernorServiceConfig, readGovernorServiceRuntime, readGovernorServiceStatus, requestGovernorServiceStop, runGovernorServiceDaemon, runGovernorServiceSweep, spawnGovernorService, } from "./service.js";
|
|
6
|
+
export { assertGovernorId, type CreateGovernorInput, type CreateGovernorMissionInput, collectGovernorWork, createGovernor, GOVERNOR_INTENT_SCHEMA_VERSION, type GovernorAutomationPolicy, type GovernorIntent, type GovernorLimits, type GovernorMission, type GovernorNextAction, type GovernorProjection, type GovernorRecord, type GovernorState, listGovernors, newGovernorId, readGovernor, } from "./state.js";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/governor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,6BAA6B,EAC7B,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,gBAAgB,EAChB,6BAA6B,EAC7B,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,KAAK,+BAA+B,EACpC,KAAK,6BAA6B,EAClC,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,2BAA2B,EAC3B,iCAAiC,GAClC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,6BAA6B,EAClC,wBAAwB,EACxB,sCAAsC,EACtC,uCAAuC,EACvC,sCAAsC,EACtC,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,wBAAwB,EAC7B,KAAK,2BAA2B,EAChC,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,sBAAsB,EACtB,KAAK,6BAA6B,EAClC,KAAK,4BAA4B,EACjC,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,EACzB,0BAA0B,EAC1B,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,gBAAgB,EAChB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAC/B,mBAAmB,EACnB,cAAc,EACd,8BAA8B,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,aAAa,EACb,aAAa,EACb,YAAY,GACb,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { approveGovernorPlan, findCompletedMissionGoverning, rejectGovernorPlan, reopenGovernorMission, retryGovernorPlan, } from "./plan-api.js";
|
|
2
|
+
export { readGovernorPlan, readGovernorPlanReviewReceipt, readGovernorPlans, } from "./plan-read.js";
|
|
3
|
+
export { GOVERNOR_PLAN_SCHEMA_VERSION, MAX_GOVERNOR_PLAN_REVIEWERS, MAX_GOVERNOR_PLAN_REVISION_ROUNDS, } from "./plan-types.js";
|
|
4
|
+
export { runGovernor, } from "./runner.js";
|
|
5
|
+
export { configureGovernorService, GOVERNOR_SERVICE_CONFIG_SCHEMA_VERSION, GOVERNOR_SERVICE_RUNTIME_SCHEMA_VERSION, GOVERNOR_SERVICE_STATUS_SCHEMA_VERSION, governorServiceLogPath, readGovernorServiceConfig, readGovernorServiceRuntime, readGovernorServiceStatus, requestGovernorServiceStop, runGovernorServiceDaemon, runGovernorServiceSweep, spawnGovernorService, } from "./service.js";
|
|
6
|
+
export { assertGovernorId, collectGovernorWork, createGovernor, GOVERNOR_INTENT_SCHEMA_VERSION, listGovernors, newGovernorId, readGovernor, } from "./state.js";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { GovernorPlanOutcome } from "./plan-types.js";
|
|
2
|
+
export declare function approveGovernorPlan(input: {
|
|
3
|
+
coordRoot: string;
|
|
4
|
+
goalId: string;
|
|
5
|
+
planId: string;
|
|
6
|
+
actor?: string;
|
|
7
|
+
reason?: string;
|
|
8
|
+
}): GovernorPlanOutcome;
|
|
9
|
+
export declare function rejectGovernorPlan(input: {
|
|
10
|
+
coordRoot: string;
|
|
11
|
+
goalId: string;
|
|
12
|
+
planId: string;
|
|
13
|
+
actor?: string;
|
|
14
|
+
reason: string;
|
|
15
|
+
}): GovernorPlanOutcome;
|
|
16
|
+
/** The goal of a succeeded mission that governs this work item, if there is one.
|
|
17
|
+
*
|
|
18
|
+
* A work item holds no back-reference to its goal, so this is a scan. It exists so
|
|
19
|
+
* `work reopen` can tell the difference between an item nothing is watching and one
|
|
20
|
+
* whose mission has already been declared complete — the case where reopening the
|
|
21
|
+
* item alone leaves it in `ready_work` that the governor will never dispatch. */
|
|
22
|
+
export declare function findCompletedMissionGoverning(coordRoot: string, workId: string): string | undefined;
|
|
23
|
+
/** ADR 0050: reopen an accepted mission completion by appending to the plan log.
|
|
24
|
+
* Held under the goal lease so it cannot race a foreground governor run. */
|
|
25
|
+
export declare function reopenGovernorMission(input: {
|
|
26
|
+
coordRoot: string;
|
|
27
|
+
goalId: string;
|
|
28
|
+
actor?: string;
|
|
29
|
+
reason: string;
|
|
30
|
+
}): GovernorPlanOutcome;
|
|
31
|
+
export declare function retryGovernorPlan(input: {
|
|
32
|
+
coordRoot: string;
|
|
33
|
+
goalId: string;
|
|
34
|
+
planId: string;
|
|
35
|
+
actor?: string;
|
|
36
|
+
reason: string;
|
|
37
|
+
}): GovernorPlanOutcome;
|
|
38
|
+
//# sourceMappingURL=plan-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-api.d.ts","sourceRoot":"","sources":["../../../src/core/governor/plan-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAS3D,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,mBAAmB,CActB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,mBAAmB,CActB;AAED;;;;;iFAKiF;AACjF,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,MAAM,GAAG,SAAS,CAQpB;AAED;4EAC4E;AAC5E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,mBAAmB,CAatB;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,mBAAmB,CActB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { applyGovernorPlanProposal, rejectGovernorPlanProposal, reopenGovernorMissionPlan, retryGovernorPlanProposal, } from "./planning.js";
|
|
2
|
+
import { acquireGovernorLease, listGovernors, readGovernorIgnoringLease } from "./state.js";
|
|
3
|
+
export function approveGovernorPlan(input) {
|
|
4
|
+
const actor = input.actor?.trim() || `governor:${input.goalId}`;
|
|
5
|
+
const release = acquireGovernorLease(input.coordRoot, input.goalId);
|
|
6
|
+
try {
|
|
7
|
+
return applyGovernorPlanProposal({
|
|
8
|
+
coordRoot: input.coordRoot,
|
|
9
|
+
record: readGovernorIgnoringLease(input.coordRoot, input.goalId),
|
|
10
|
+
planId: input.planId,
|
|
11
|
+
actor,
|
|
12
|
+
reason: input.reason,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
release();
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function rejectGovernorPlan(input) {
|
|
20
|
+
const actor = input.actor?.trim() || `governor:${input.goalId}`;
|
|
21
|
+
const release = acquireGovernorLease(input.coordRoot, input.goalId);
|
|
22
|
+
try {
|
|
23
|
+
return rejectGovernorPlanProposal({
|
|
24
|
+
coordRoot: input.coordRoot,
|
|
25
|
+
goalId: input.goalId,
|
|
26
|
+
planId: input.planId,
|
|
27
|
+
actor,
|
|
28
|
+
reason: input.reason,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
finally {
|
|
32
|
+
release();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** The goal of a succeeded mission that governs this work item, if there is one.
|
|
36
|
+
*
|
|
37
|
+
* A work item holds no back-reference to its goal, so this is a scan. It exists so
|
|
38
|
+
* `work reopen` can tell the difference between an item nothing is watching and one
|
|
39
|
+
* whose mission has already been declared complete — the case where reopening the
|
|
40
|
+
* item alone leaves it in `ready_work` that the governor will never dispatch. */
|
|
41
|
+
export function findCompletedMissionGoverning(coordRoot, workId) {
|
|
42
|
+
for (const record of listGovernors(coordRoot)) {
|
|
43
|
+
if (record.projection.state !== "succeeded" || !record.intent.mission)
|
|
44
|
+
continue;
|
|
45
|
+
if (record.projection.root_work_id === workId || record.projection.work_ids.includes(workId)) {
|
|
46
|
+
return record.intent.id;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
/** ADR 0050: reopen an accepted mission completion by appending to the plan log.
|
|
52
|
+
* Held under the goal lease so it cannot race a foreground governor run. */
|
|
53
|
+
export function reopenGovernorMission(input) {
|
|
54
|
+
const actor = input.actor?.trim() || `governor:${input.goalId}`;
|
|
55
|
+
const release = acquireGovernorLease(input.coordRoot, input.goalId);
|
|
56
|
+
try {
|
|
57
|
+
return reopenGovernorMissionPlan({
|
|
58
|
+
coordRoot: input.coordRoot,
|
|
59
|
+
record: readGovernorIgnoringLease(input.coordRoot, input.goalId),
|
|
60
|
+
actor,
|
|
61
|
+
reason: input.reason,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
release();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function retryGovernorPlan(input) {
|
|
69
|
+
const actor = input.actor?.trim() || `governor:${input.goalId}`;
|
|
70
|
+
const release = acquireGovernorLease(input.coordRoot, input.goalId);
|
|
71
|
+
try {
|
|
72
|
+
return retryGovernorPlanProposal({
|
|
73
|
+
coordRoot: input.coordRoot,
|
|
74
|
+
record: readGovernorIgnoringLease(input.coordRoot, input.goalId),
|
|
75
|
+
planId: input.planId,
|
|
76
|
+
actor,
|
|
77
|
+
reason: input.reason,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
release();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type GovernorPlanHistory, type GovernorPlanRecord, type GovernorPlanReviewReceipt } from "./plan-types.js";
|
|
2
|
+
export declare function readGovernorPlans(coordRootRaw: string, goalId: string, originalRootWorkId: string): GovernorPlanHistory;
|
|
3
|
+
export declare function readGovernorPlan(coordRootRaw: string, goalId: string, planId: string): GovernorPlanRecord;
|
|
4
|
+
export declare function readGovernorPlanReviewReceipt(coordRootRaw: string, goalId: string, planId: string): GovernorPlanReviewReceipt | undefined;
|
|
5
|
+
//# sourceMappingURL=plan-read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-read.d.ts","sourceRoot":"","sources":["../../../src/core/governor/plan-read.ts"],"names":[],"mappings":"AAIA,OAAO,EAIL,KAAK,mBAAmB,EAExB,KAAK,kBAAkB,EAGvB,KAAK,yBAAyB,EAQ/B,MAAM,iBAAiB,CAAC;AA0BzB,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,kBAAkB,EAAE,MAAM,GACzB,mBAAmB,CAwErB;AAED,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,kBAAkB,CAsBpB;AAED,wBAAgB,6BAA6B,CAC3C,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,yBAAyB,GAAG,SAAS,CAWvC"}
|
|
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { readWorkItem } from "../work/read.js";
|
|
5
|
-
import {
|
|
5
|
+
import { GOVERNOR_PLAN_SCHEMA_VERSION, MAX_GOVERNOR_PLAN_REVIEWERS, MAX_GOVERNOR_PLAN_REVISION_ROUNDS, } from "./plan-types.js";
|
|
6
6
|
const PLAN_ID = /^plan-[0-9]{4}-[a-f0-9]{8}$/;
|
|
7
7
|
const GOAL_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
|
|
8
8
|
const WORK_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
|
|
@@ -24,9 +24,10 @@ const EVENT_TYPES = new Set([
|
|
|
24
24
|
"plan.retry_requested",
|
|
25
25
|
"plan.attention",
|
|
26
26
|
"plan.failed",
|
|
27
|
+
"plan.reopened",
|
|
27
28
|
]);
|
|
28
|
-
export function
|
|
29
|
-
assertId(goalId, GOAL_ID, "
|
|
29
|
+
export function readGovernorPlans(coordRootRaw, goalId, originalRootWorkId) {
|
|
30
|
+
assertId(goalId, GOAL_ID, "governor id");
|
|
30
31
|
assertId(originalRootWorkId, WORK_ID, "work id");
|
|
31
32
|
const coordRoot = resolve(coordRootRaw);
|
|
32
33
|
const root = plansRoot(coordRoot, goalId);
|
|
@@ -45,14 +46,14 @@ export function readSupervisorPlans(coordRootRaw, goalId, originalRootWorkId) {
|
|
|
45
46
|
.filter((entry) => entry.isDirectory() && PLAN_ID.test(entry.name))
|
|
46
47
|
.map((entry) => entry.name);
|
|
47
48
|
if (entries.length > MAX_PLANS)
|
|
48
|
-
throw new Error(`
|
|
49
|
+
throw new Error(`governor plan history exceeds ${MAX_PLANS}`);
|
|
49
50
|
const plans = entries
|
|
50
|
-
.map((planId) =>
|
|
51
|
+
.map((planId) => readGovernorPlan(coordRootRaw, goalId, planId))
|
|
51
52
|
.sort((left, right) => left.request.sequence - right.request.sequence);
|
|
52
53
|
const sequences = new Set();
|
|
53
54
|
for (const plan of plans) {
|
|
54
55
|
if (sequences.has(plan.request.sequence)) {
|
|
55
|
-
throw new Error(`
|
|
56
|
+
throw new Error(`governor ${goalId} has duplicate plan sequence ${plan.request.sequence}`);
|
|
56
57
|
}
|
|
57
58
|
sequences.add(plan.request.sequence);
|
|
58
59
|
}
|
|
@@ -83,7 +84,7 @@ export function readSupervisorPlans(coordRootRaw, goalId, originalRootWorkId) {
|
|
|
83
84
|
const completedPlans = plans.filter((plan) => plan.status === "completed");
|
|
84
85
|
if (completedPlans.length > 1 ||
|
|
85
86
|
(completedPlans.length === 1 && completedPlans[0] !== plans.at(-1))) {
|
|
86
|
-
throw new Error(`
|
|
87
|
+
throw new Error(`governor ${goalId} has invalid completion history`);
|
|
87
88
|
}
|
|
88
89
|
completed = completedPlans.length === 1;
|
|
89
90
|
return {
|
|
@@ -97,9 +98,9 @@ export function readSupervisorPlans(coordRootRaw, goalId, originalRootWorkId) {
|
|
|
97
98
|
latest: plans.at(-1),
|
|
98
99
|
};
|
|
99
100
|
}
|
|
100
|
-
export function
|
|
101
|
-
assertId(goalId, GOAL_ID, "
|
|
102
|
-
assertId(planId, PLAN_ID, "
|
|
101
|
+
export function readGovernorPlan(coordRootRaw, goalId, planId) {
|
|
102
|
+
assertId(goalId, GOAL_ID, "governor id");
|
|
103
|
+
assertId(planId, PLAN_ID, "governor plan id");
|
|
103
104
|
const coordRoot = resolve(coordRootRaw);
|
|
104
105
|
const dir = planDir(coordRoot, goalId, planId);
|
|
105
106
|
const request = readJson(join(dir, "request.json"), "plan request");
|
|
@@ -110,7 +111,7 @@ export function readSupervisorPlan(coordRootRaw, goalId, planId) {
|
|
|
110
111
|
: undefined;
|
|
111
112
|
if (proposal)
|
|
112
113
|
validateProposalEnvelope(proposal, planId);
|
|
113
|
-
const review =
|
|
114
|
+
const review = readGovernorPlanReviewReceipt(coordRootRaw, goalId, planId);
|
|
114
115
|
const events = readEvents(join(dir, "events.jsonl"), planId);
|
|
115
116
|
const derived = deriveStatus(coordRoot, events, proposal);
|
|
116
117
|
return {
|
|
@@ -121,9 +122,9 @@ export function readSupervisorPlan(coordRootRaw, goalId, planId) {
|
|
|
121
122
|
...derived,
|
|
122
123
|
};
|
|
123
124
|
}
|
|
124
|
-
export function
|
|
125
|
-
assertId(goalId, GOAL_ID, "
|
|
126
|
-
assertId(planId, PLAN_ID, "
|
|
125
|
+
export function readGovernorPlanReviewReceipt(coordRootRaw, goalId, planId) {
|
|
126
|
+
assertId(goalId, GOAL_ID, "governor id");
|
|
127
|
+
assertId(planId, PLAN_ID, "governor plan id");
|
|
127
128
|
const coordRoot = resolve(coordRootRaw);
|
|
128
129
|
const path = join(planDir(coordRoot, goalId, planId), "review.json");
|
|
129
130
|
if (!existsSync(path))
|
|
@@ -139,6 +140,16 @@ function deriveStatus(coordRoot, events, proposal) {
|
|
|
139
140
|
const latest = events.at(-1);
|
|
140
141
|
const completed = [...events].reverse().find((event) => event.event === "plan.completed");
|
|
141
142
|
if (completed) {
|
|
143
|
+
// ADR 0050: an operator finding on work beneath a completed mission reopens
|
|
144
|
+
// the mission by APPENDING, never by rewriting. The accepted completion stays
|
|
145
|
+
// in the log verbatim; a later `plan.reopened` supersedes it, which is what
|
|
146
|
+
// drops `plans.completed` and lets the projection dispatch again.
|
|
147
|
+
const reopened = [...events]
|
|
148
|
+
.reverse()
|
|
149
|
+
.find((event) => event.event === "plan.reopened" && event.seq > completed.seq);
|
|
150
|
+
if (reopened) {
|
|
151
|
+
return { status: "reopened", work_ids: [], reason: reopened.reason };
|
|
152
|
+
}
|
|
142
153
|
return { status: "completed", work_ids: [], reason: completed.reason };
|
|
143
154
|
}
|
|
144
155
|
const applied = [...events].reverse().find((event) => event.event === "plan.applied");
|
|
@@ -160,7 +171,10 @@ function deriveStatus(coordRoot, events, proposal) {
|
|
|
160
171
|
return { status: "attention", work_ids: [], reason: latest.reason };
|
|
161
172
|
}
|
|
162
173
|
if (latest?.event === "plan.failed") {
|
|
163
|
-
|
|
174
|
+
// ADR 0046: carry the planner run's failure class so the projection can stop
|
|
175
|
+
// an environment failure and bound consecutive upstream ones, rather than
|
|
176
|
+
// replanning an unchanged environment to budget exhaustion.
|
|
177
|
+
return { status: "failed", work_ids: [], reason: latest.reason, class: latest.class };
|
|
164
178
|
}
|
|
165
179
|
const parked = [...events].reverse().find((event) => event.event === "plan.awaiting_approval");
|
|
166
180
|
const resumedAfterPark = parked !== undefined &&
|
|
@@ -182,27 +196,27 @@ function readEvents(path, planId) {
|
|
|
182
196
|
return [];
|
|
183
197
|
const size = statSync(path).size;
|
|
184
198
|
if (size > MAX_EVENTS_BYTES)
|
|
185
|
-
throw new Error("
|
|
199
|
+
throw new Error("governor plan events exceed their byte limit");
|
|
186
200
|
const body = readFileSync(path, "utf8");
|
|
187
201
|
if (body && !body.endsWith("\n"))
|
|
188
|
-
throw new Error(`
|
|
202
|
+
throw new Error(`governor plan ${planId} has a partial event`);
|
|
189
203
|
const lines = body.split("\n").filter(Boolean);
|
|
190
204
|
if (lines.length > MAX_EVENTS)
|
|
191
|
-
throw new Error(`
|
|
205
|
+
throw new Error(`governor plan exceeds ${MAX_EVENTS} events`);
|
|
192
206
|
return lines.map((line, index) => {
|
|
193
207
|
let event;
|
|
194
208
|
try {
|
|
195
209
|
event = JSON.parse(line);
|
|
196
210
|
}
|
|
197
211
|
catch (error) {
|
|
198
|
-
throw new Error(`cannot parse
|
|
212
|
+
throw new Error(`cannot parse governor plan ${planId} event ${index + 1}: ${error.message}`);
|
|
199
213
|
}
|
|
200
214
|
validateEvent(event, planId, index + 1);
|
|
201
215
|
return event;
|
|
202
216
|
});
|
|
203
217
|
}
|
|
204
218
|
function validateRequest(request, goalId, planId) {
|
|
205
|
-
if (request.schema_version !==
|
|
219
|
+
if (request.schema_version !== GOVERNOR_PLAN_SCHEMA_VERSION ||
|
|
206
220
|
request.id !== planId ||
|
|
207
221
|
request.goal_id !== goalId ||
|
|
208
222
|
!Number.isSafeInteger(request.sequence) ||
|
|
@@ -216,11 +230,11 @@ function validateRequest(request, goalId, planId) {
|
|
|
216
230
|
!WORK_ID.test(request.prior_root_work_id) ||
|
|
217
231
|
!/^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/.test(request.workflow_run_id) ||
|
|
218
232
|
!validTimestamp(request.created_at)) {
|
|
219
|
-
throw new Error(`
|
|
233
|
+
throw new Error(`governor plan request ${planId} has an unsupported schema`);
|
|
220
234
|
}
|
|
221
235
|
}
|
|
222
236
|
function validateProposalEnvelope(proposal, planId) {
|
|
223
|
-
if (proposal.schema_version !==
|
|
237
|
+
if (proposal.schema_version !== GOVERNOR_PLAN_SCHEMA_VERSION ||
|
|
224
238
|
proposal.plan_id !== planId ||
|
|
225
239
|
!["apply", "complete", "attention"].includes(proposal.decision) ||
|
|
226
240
|
typeof proposal.rationale !== "string" ||
|
|
@@ -231,7 +245,7 @@ function validateProposalEnvelope(proposal, planId) {
|
|
|
231
245
|
typeof proposal.root !== "string" ||
|
|
232
246
|
proposal.root.length > 32 ||
|
|
233
247
|
!validTimestamp(proposal.proposed_at)) {
|
|
234
|
-
throw new Error(`
|
|
248
|
+
throw new Error(`governor plan proposal ${planId} has an unsupported schema`);
|
|
235
249
|
}
|
|
236
250
|
if (proposal.milestone !== undefined) {
|
|
237
251
|
const milestone = proposal.milestone;
|
|
@@ -248,12 +262,12 @@ function validateProposalEnvelope(proposal, planId) {
|
|
|
248
262
|
milestone.acceptance.length < 1 ||
|
|
249
263
|
milestone.acceptance.length > 50 ||
|
|
250
264
|
milestone.acceptance.some((criterion) => typeof criterion !== "string" || criterion.length < 1 || criterion.length > 500)) {
|
|
251
|
-
throw new Error(`
|
|
265
|
+
throw new Error(`governor plan proposal ${planId} milestone is invalid`);
|
|
252
266
|
}
|
|
253
267
|
}
|
|
254
268
|
if ((proposal.decision === "attention" || proposal.decision === "complete") &&
|
|
255
269
|
(proposal.root !== "" || proposal.work.length > 0 || proposal.milestone !== undefined)) {
|
|
256
|
-
throw new Error(`
|
|
270
|
+
throw new Error(`governor plan proposal ${planId} terminal decision contains work`);
|
|
257
271
|
}
|
|
258
272
|
for (const [index, spec] of proposal.work.entries()) {
|
|
259
273
|
if (!spec ||
|
|
@@ -272,71 +286,71 @@ function validateProposalEnvelope(proposal, planId) {
|
|
|
272
286
|
spec.dependencies.length > 50 ||
|
|
273
287
|
spec.dependencies.some((value) => typeof value !== "string" || value.length > 100) ||
|
|
274
288
|
!TEMPLATE_ID.test(spec.template)) {
|
|
275
|
-
throw new Error(`
|
|
289
|
+
throw new Error(`governor plan proposal ${planId} work[${index}] is invalid`);
|
|
276
290
|
}
|
|
277
291
|
}
|
|
278
292
|
}
|
|
279
293
|
function validateReviewReceipt(receipt, planId) {
|
|
280
294
|
if (!receipt ||
|
|
281
295
|
typeof receipt !== "object" ||
|
|
282
|
-
receipt.schema_version !==
|
|
296
|
+
receipt.schema_version !== GOVERNOR_PLAN_SCHEMA_VERSION ||
|
|
283
297
|
receipt.plan_id !== planId ||
|
|
284
298
|
!["passed", "revision_exhausted", "attention", "failed"].includes(receipt.status) ||
|
|
285
299
|
!/^[a-f0-9]{64}$/.test(receipt.candidate_sha256) ||
|
|
286
300
|
!Array.isArray(receipt.rounds) ||
|
|
287
301
|
receipt.rounds.length < 1 ||
|
|
288
|
-
receipt.rounds.length >
|
|
289
|
-
throw new Error(`
|
|
302
|
+
receipt.rounds.length > MAX_GOVERNOR_PLAN_REVISION_ROUNDS + 1) {
|
|
303
|
+
throw new Error(`governor plan review ${planId} has an unsupported schema`);
|
|
290
304
|
}
|
|
291
305
|
validateProposalEnvelope(receipt.final_candidate, planId);
|
|
292
306
|
if (receipt.candidate_sha256 !== candidateDigest(receipt.final_candidate)) {
|
|
293
|
-
throw new Error(`
|
|
307
|
+
throw new Error(`governor plan review ${planId} has invalid candidate digest`);
|
|
294
308
|
}
|
|
295
309
|
receipt.rounds.forEach((round, index) => {
|
|
296
310
|
validateReviewRound(round, planId, index + 1);
|
|
297
311
|
});
|
|
298
312
|
const finalRound = receipt.rounds.at(-1);
|
|
299
313
|
if (finalRound?.candidate_sha256 !== receipt.candidate_sha256) {
|
|
300
|
-
throw new Error(`
|
|
314
|
+
throw new Error(`governor plan review ${planId} final round does not match its candidate`);
|
|
301
315
|
}
|
|
302
316
|
if (receipt.status === "passed" && finalRound?.outcome !== "approved") {
|
|
303
|
-
throw new Error(`
|
|
317
|
+
throw new Error(`governor plan review ${planId} passed without approval`);
|
|
304
318
|
}
|
|
305
319
|
if (receipt.status === "attention" && finalRound?.outcome === "approved") {
|
|
306
|
-
throw new Error(`
|
|
320
|
+
throw new Error(`governor plan review ${planId} attention conflicts with approval`);
|
|
307
321
|
}
|
|
308
322
|
}
|
|
309
323
|
function readFrozenReviewPolicy(coordRoot, goalId) {
|
|
310
|
-
const path = join(coordRoot, ".harnery", "
|
|
324
|
+
const path = join(coordRoot, ".harnery", "governors", goalId, "intent.json");
|
|
311
325
|
if (!existsSync(path))
|
|
312
326
|
return undefined;
|
|
313
|
-
const intent = readJson(path, "
|
|
327
|
+
const intent = readJson(path, "governor intent");
|
|
314
328
|
return intent.replanning?.review;
|
|
315
329
|
}
|
|
316
330
|
function validateReviewReceiptMatchesPolicy(receipt, planId, review) {
|
|
317
331
|
if (receipt.rounds.length > review.max_revision_rounds + 1) {
|
|
318
|
-
throw new Error(`
|
|
332
|
+
throw new Error(`governor plan review ${planId} exceeds the frozen review policy`);
|
|
319
333
|
}
|
|
320
334
|
for (const round of receipt.rounds) {
|
|
321
335
|
if (round.reviewers.length !== review.reviewer_specialists.length) {
|
|
322
|
-
throw new Error(`
|
|
336
|
+
throw new Error(`governor plan review ${planId} does not match the frozen review policy`);
|
|
323
337
|
}
|
|
324
338
|
round.reviewers.forEach((reviewer, index) => {
|
|
325
339
|
if (reviewer.specialist !== review.reviewer_specialists[index]) {
|
|
326
|
-
throw new Error(`
|
|
340
|
+
throw new Error(`governor plan review ${planId} does not match the frozen review policy`);
|
|
327
341
|
}
|
|
328
342
|
});
|
|
329
343
|
const outcome = aggregateReviewers(round.reviewers);
|
|
330
344
|
if (round.outcome !== outcome) {
|
|
331
|
-
throw new Error(`
|
|
345
|
+
throw new Error(`governor plan review ${planId} has an invalid reviewer outcome`);
|
|
332
346
|
}
|
|
333
347
|
}
|
|
334
348
|
const finalRound = receipt.rounds.at(-1);
|
|
335
349
|
if (receipt.status === "passed" && finalRound.outcome !== "approved") {
|
|
336
|
-
throw new Error(`
|
|
350
|
+
throw new Error(`governor plan review ${planId} passed without policy approval`);
|
|
337
351
|
}
|
|
338
352
|
if (receipt.status === "revision_exhausted" && finalRound.round <= review.max_revision_rounds) {
|
|
339
|
-
throw new Error(`
|
|
353
|
+
throw new Error(`governor plan review ${planId} exhausted before the frozen review limit`);
|
|
340
354
|
}
|
|
341
355
|
}
|
|
342
356
|
function aggregateReviewers(reviewers) {
|
|
@@ -373,11 +387,11 @@ function validateReviewRound(round, planId, sequence) {
|
|
|
373
387
|
!/^[a-f0-9]{64}$/.test(round.candidate_sha256) ||
|
|
374
388
|
!Array.isArray(round.reviewers) ||
|
|
375
389
|
round.reviewers.length < 1 ||
|
|
376
|
-
round.reviewers.length >
|
|
390
|
+
round.reviewers.length > MAX_GOVERNOR_PLAN_REVIEWERS ||
|
|
377
391
|
!["approved", "revise", "attention", "failed"].includes(round.outcome) ||
|
|
378
392
|
(round.revision_workflow_run_id !== undefined &&
|
|
379
393
|
!/^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/.test(round.revision_workflow_run_id))) {
|
|
380
|
-
throw new Error(`
|
|
394
|
+
throw new Error(`governor plan review ${planId} round ${sequence} is invalid`);
|
|
381
395
|
}
|
|
382
396
|
round.reviewers.forEach((reviewer, index) => {
|
|
383
397
|
validateReviewReviewer(reviewer, planId, sequence, index);
|
|
@@ -395,7 +409,7 @@ function validateReviewReviewer(reviewer, planId, round, index) {
|
|
|
395
409
|
reviewer.rationale.length > 2_000 ||
|
|
396
410
|
!Array.isArray(reviewer.findings) ||
|
|
397
411
|
reviewer.findings.length > 50) {
|
|
398
|
-
throw new Error(`
|
|
412
|
+
throw new Error(`governor plan review ${planId} round ${round} reviewer ${index} is invalid`);
|
|
399
413
|
}
|
|
400
414
|
reviewer.findings.forEach((finding, findingIndex) => {
|
|
401
415
|
validateReviewFinding(finding, planId, round, index, findingIndex);
|
|
@@ -413,7 +427,7 @@ function validateReviewFinding(finding, planId, round, reviewerIndex, findingInd
|
|
|
413
427
|
typeof finding.recommendation !== "string" ||
|
|
414
428
|
finding.recommendation.length < 1 ||
|
|
415
429
|
finding.recommendation.length > 1_000) {
|
|
416
|
-
throw new Error(`
|
|
430
|
+
throw new Error(`governor plan review ${planId} round ${round} reviewer ${reviewerIndex} finding ${findingIndex} is invalid`);
|
|
417
431
|
}
|
|
418
432
|
}
|
|
419
433
|
function summarizeReview(receipt) {
|
|
@@ -427,7 +441,7 @@ function summarizeReview(receipt) {
|
|
|
427
441
|
};
|
|
428
442
|
}
|
|
429
443
|
function validateEvent(event, planId, sequence) {
|
|
430
|
-
if (event.schema_version !==
|
|
444
|
+
if (event.schema_version !== GOVERNOR_PLAN_SCHEMA_VERSION ||
|
|
431
445
|
event.plan_id !== planId ||
|
|
432
446
|
event.seq !== sequence ||
|
|
433
447
|
!EVENT_TYPES.has(event.event) ||
|
|
@@ -438,19 +452,25 @@ function validateEvent(event, planId, sequence) {
|
|
|
438
452
|
typeof event.reason !== "string" ||
|
|
439
453
|
event.reason.length < 1 ||
|
|
440
454
|
event.reason.length > 2_000) {
|
|
441
|
-
throw new Error(`
|
|
455
|
+
throw new Error(`governor plan ${planId} event ${sequence} has an unsupported schema`);
|
|
442
456
|
}
|
|
443
457
|
if (event.approval_id !== undefined && !APPROVAL_ID.test(event.approval_id)) {
|
|
444
|
-
throw new Error(`
|
|
458
|
+
throw new Error(`governor plan ${planId} event ${sequence} has an invalid approval id`);
|
|
445
459
|
}
|
|
446
460
|
if (event.root_work_id !== undefined && !WORK_ID.test(event.root_work_id)) {
|
|
447
|
-
throw new Error(`
|
|
461
|
+
throw new Error(`governor plan ${planId} event ${sequence} has an invalid root work id`);
|
|
448
462
|
}
|
|
449
463
|
if (event.work_ids !== undefined) {
|
|
450
464
|
if (!Array.isArray(event.work_ids) || event.work_ids.some((id) => !WORK_ID.test(id))) {
|
|
451
|
-
throw new Error(`
|
|
465
|
+
throw new Error(`governor plan ${planId} event ${sequence} has invalid work ids`);
|
|
452
466
|
}
|
|
453
467
|
}
|
|
468
|
+
if (event.class !== undefined &&
|
|
469
|
+
event.class !== "environment" &&
|
|
470
|
+
event.class !== "upstream" &&
|
|
471
|
+
event.class !== "decision") {
|
|
472
|
+
throw new Error(`governor plan ${planId} event ${sequence} has an unknown failure class`);
|
|
473
|
+
}
|
|
454
474
|
}
|
|
455
475
|
function approvalIsResolved(coordRoot, approvalId) {
|
|
456
476
|
const path = join(coordRoot, ".harnery", "approvals", approvalId, "decision.json");
|
|
@@ -478,7 +498,7 @@ function readJson(path, label) {
|
|
|
478
498
|
}
|
|
479
499
|
}
|
|
480
500
|
function plansRoot(coordRoot, goalId) {
|
|
481
|
-
return join(coordRoot, ".harnery", "
|
|
501
|
+
return join(coordRoot, ".harnery", "governors", goalId, "plans");
|
|
482
502
|
}
|
|
483
503
|
function planDir(coordRoot, goalId, planId) {
|
|
484
504
|
return join(plansRoot(coordRoot, goalId), planId);
|