harnery 0.30.0 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/commander.d.ts +8 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +14 -13
- package/dist/commands/adapter.d.ts +12 -0
- package/dist/commands/adapter.d.ts.map +1 -0
- package/dist/commands/{harness.js → adapter.js} +35 -35
- package/dist/commands/agents.d.ts +3 -2
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +185 -74
- package/dist/commands/artifacts.d.ts +4 -0
- package/dist/commands/artifacts.d.ts.map +1 -0
- package/dist/commands/artifacts.js +143 -0
- package/dist/commands/backup.d.ts +1 -1
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +5 -2
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +310 -7
- package/dist/commands/checkpoint.d.ts +12 -0
- package/dist/commands/checkpoint.d.ts.map +1 -0
- package/dist/commands/checkpoint.js +162 -0
- package/dist/commands/context.d.ts +2 -2
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +3 -151
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +31 -7
- package/dist/commands/deinit.d.ts +2 -2
- package/dist/commands/deinit.js +15 -15
- package/dist/commands/doctor.js +23 -23
- package/dist/commands/governor.d.ts +4 -0
- package/dist/commands/governor.d.ts.map +1 -0
- package/dist/commands/{supervisor.js → governor.js} +133 -108
- package/dist/commands/grep.d.ts +1 -1
- package/dist/commands/grep.d.ts.map +1 -1
- package/dist/commands/grep.js +19 -2
- package/dist/commands/init.d.ts +12 -12
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +44 -30
- package/dist/commands/{session.d.ts → journal.d.ts} +2 -2
- package/dist/commands/journal.d.ts.map +1 -0
- package/dist/commands/{scratch.js → journal.js} +47 -47
- package/dist/commands/policy.js +1 -1
- package/dist/commands/presence.js +2 -2
- package/dist/commands/sync.d.ts +1 -1
- package/dist/commands/sync.js +3 -3
- package/dist/commands/tunnel.d.ts +16 -0
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +213 -27
- package/dist/commands/web-fetch.js +1 -1
- package/dist/commands/web.d.ts +19 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +51 -0
- package/dist/commands/work.d.ts.map +1 -1
- package/dist/commands/work.js +38 -22
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +35 -28
- package/dist/core/{harnesses → adapters}/attest-projection.d.ts +2 -2
- package/dist/core/adapters/attest-projection.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/attest.d.ts +16 -16
- package/dist/core/adapters/attest.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/attest.js +9 -9
- package/dist/core/{harnesses → adapters}/attestation.d.ts +16 -16
- package/dist/core/adapters/attestation.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/attestation.js +20 -20
- package/dist/core/{harnesses → adapters}/bench.d.ts +12 -12
- package/dist/core/adapters/bench.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/bench.js +12 -12
- package/dist/core/adapters/index.d.ts +13 -0
- package/dist/core/adapters/index.d.ts.map +1 -0
- package/dist/core/adapters/index.js +6 -0
- package/dist/core/{harnesses → adapters}/profiles.d.ts +11 -11
- package/dist/core/adapters/profiles.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/profiles.js +11 -11
- package/dist/core/adapters/registry.d.ts +15 -0
- package/dist/core/adapters/registry.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/registry.js +11 -11
- package/dist/core/{harnesses → adapters}/types.d.ts +23 -23
- package/dist/core/adapters/types.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/types.js +1 -1
- package/dist/core/agents/canonical-emit.d.ts +9 -14
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +15 -44
- package/dist/core/agents/cli-emit.js +1 -1
- package/dist/core/agents/cli.js +30 -26
- package/dist/core/agents/codex-replay.d.ts +1 -1
- package/dist/core/agents/codex-replay.js +6 -6
- package/dist/core/agents/coord-bin.d.ts +33 -0
- package/dist/core/agents/coord-bin.d.ts.map +1 -0
- package/dist/core/agents/coord-bin.js +89 -0
- package/dist/core/agents/coord-client.d.ts +78 -8
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +303 -75
- package/dist/core/agents/events/consume.d.ts +1 -1
- package/dist/core/agents/events/emit.d.ts +5 -6
- package/dist/core/agents/events/emit.d.ts.map +1 -1
- package/dist/core/agents/events/emit.js +2 -2
- package/dist/core/agents/paths.d.ts +5 -2
- package/dist/core/agents/paths.d.ts.map +1 -1
- package/dist/core/agents/paths.js +7 -13
- package/dist/core/agents/render/prompt-context.d.ts +21 -9
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +82 -30
- package/dist/core/agents/render/session-context.d.ts +1 -1
- package/dist/core/agents/render/session-context.js +5 -5
- package/dist/core/agents/rules/claim-conflict.d.ts +2 -6
- package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/claim-conflict.js +1 -1
- package/dist/core/agents/rules/commit-conflict.js +98 -22
- package/dist/core/agents/rules/stop-hook.d.ts +9 -9
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +23 -5
- package/dist/core/agents/rules/verdict.d.ts +14 -0
- package/dist/core/agents/rules/verdict.d.ts.map +1 -0
- package/dist/core/agents/rules/verdict.js +1 -0
- package/dist/core/agents/session-events.js +3 -3
- package/dist/core/agents/state/council.d.ts +1 -1
- package/dist/core/agents/state/council.js +1 -1
- package/dist/core/agents/state/heartbeat-projector.d.ts +3 -2
- package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-projector.js +14 -10
- package/dist/core/agents/state/heartbeat-writer.d.ts +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +12 -12
- package/dist/core/agents/state/{scratch.d.ts → journal.d.ts} +7 -7
- package/dist/core/agents/state/{scratch.d.ts.map → journal.d.ts.map} +1 -1
- package/dist/core/agents/state/{scratch.js → journal.js} +12 -12
- package/dist/core/agents/state/pidmap.d.ts +28 -4
- package/dist/core/agents/state/pidmap.d.ts.map +1 -1
- package/dist/core/agents/state/pidmap.js +130 -15
- package/dist/core/agents/state/proc-start.d.ts +95 -0
- package/dist/core/agents/state/proc-start.d.ts.map +1 -0
- package/dist/core/agents/state/proc-start.js +199 -0
- package/dist/core/agents/state/shell-mutation.d.ts +1 -1
- package/dist/core/agents/state/shell-mutation.js +1 -1
- package/dist/core/agents/state/stale-sweep.js +7 -7
- package/dist/core/artifacts/index.d.ts +86 -0
- package/dist/core/artifacts/index.d.ts.map +1 -0
- package/dist/core/artifacts/index.js +421 -0
- package/dist/core/config.d.ts +9 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +26 -2
- package/dist/core/context/index.d.ts +12 -12
- package/dist/core/context/index.js +10 -10
- package/dist/core/governor/adapter-spread.d.ts +52 -0
- package/dist/core/governor/adapter-spread.d.ts.map +1 -0
- package/dist/core/governor/adapter-spread.js +52 -0
- package/dist/core/governor/index.d.ts +7 -0
- package/dist/core/governor/index.d.ts.map +1 -0
- package/dist/core/governor/index.js +6 -0
- package/dist/core/governor/plan-api.d.ts +38 -0
- package/dist/core/governor/plan-api.d.ts.map +1 -0
- package/dist/core/governor/plan-api.js +83 -0
- package/dist/core/governor/plan-read.d.ts +5 -0
- package/dist/core/governor/plan-read.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/plan-read.js +66 -52
- package/dist/core/{supervisor → governor}/plan-types.d.ts +57 -56
- package/dist/core/governor/plan-types.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/plan-types.js +4 -4
- package/dist/core/governor/planning.d.ts +48 -0
- package/dist/core/governor/planning.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/planning.js +125 -94
- package/dist/core/governor/read.d.ts +6 -0
- package/dist/core/governor/read.d.ts.map +1 -0
- package/dist/core/governor/read.js +4 -0
- package/dist/core/governor/runner.d.ts +37 -0
- package/dist/core/governor/runner.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/runner.js +15 -15
- package/dist/core/governor/service-read.d.ts +6 -0
- package/dist/core/governor/service-read.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/service-read.js +12 -12
- package/dist/core/governor/service.d.ts +114 -0
- package/dist/core/governor/service.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/service.js +57 -57
- package/dist/core/governor/state.d.ts +116 -0
- package/dist/core/governor/state.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/state.js +228 -108
- package/dist/core/hooks/adapter/detect.d.ts +9 -0
- package/dist/core/hooks/{harness → adapter}/detect.d.ts.map +1 -1
- package/dist/core/hooks/{harness → adapter}/detect.js +8 -8
- package/dist/core/hooks/{harness → adapter}/events.d.ts +15 -14
- package/dist/core/hooks/adapter/events.d.ts.map +1 -0
- package/dist/core/hooks/{harness → adapter}/events.js +5 -5
- package/dist/core/hooks/{harness → adapter}/output.d.ts +20 -14
- package/dist/core/hooks/adapter/output.d.ts.map +1 -0
- package/dist/core/hooks/{harness → adapter}/output.js +30 -22
- package/dist/core/hooks/{harness → adapter}/parse.d.ts +5 -5
- package/dist/core/hooks/{harness → adapter}/parse.d.ts.map +1 -1
- package/dist/core/hooks/{harness → adapter}/parse.js +4 -4
- package/dist/core/hooks/{harness → adapter}/wiring.d.ts +15 -15
- package/dist/core/hooks/{harness → adapter}/wiring.d.ts.map +1 -1
- package/dist/core/hooks/{harness → adapter}/wiring.js +13 -13
- package/dist/core/hooks/cli.d.ts +3 -3
- package/dist/core/hooks/cli.js +187 -162
- package/dist/core/hooks/effects/image-capture.d.ts +5 -5
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +3 -3
- package/dist/core/hooks/effects/index.d.ts +12 -12
- package/dist/core/hooks/effects/index.d.ts.map +1 -1
- package/dist/core/hooks/effects/index.js +19 -19
- package/dist/core/hooks/events/emit.d.ts +2 -2
- package/dist/core/hooks/events/emit.d.ts.map +1 -1
- package/dist/core/hooks/events/emit.js +1 -1
- package/dist/core/hooks/events/rotate.js +1 -1
- package/dist/core/hooks/events/schema.d.ts +13 -5
- package/dist/core/hooks/events/schema.d.ts.map +1 -1
- package/dist/core/hooks/guard-path.d.ts +2 -2
- package/dist/core/hooks/guard-path.js +2 -2
- package/dist/core/hooks/index.d.ts +1 -1
- package/dist/core/hooks/index.d.ts.map +1 -1
- package/dist/core/hooks/resolve/anchor.d.ts +14 -5
- package/dist/core/hooks/resolve/anchor.d.ts.map +1 -1
- package/dist/core/hooks/resolve/anchor.js +64 -7
- package/dist/core/hooks/resolve/coord-root.d.ts +16 -11
- package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
- package/dist/core/hooks/resolve/coord-root.js +18 -43
- package/dist/core/hooks/resolve/intent.js +1 -1
- package/dist/core/hooks/resolve/owner.d.ts +1 -1
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +11 -5
- package/dist/core/{scratch → journal}/index.d.ts +25 -25
- package/dist/core/{scratch → journal}/index.d.ts.map +1 -1
- package/dist/core/{scratch → journal}/index.js +38 -38
- package/dist/core/policy/evaluate.d.ts +1 -1
- package/dist/core/policy/evaluate.d.ts.map +1 -1
- package/dist/core/policy/evaluate.js +7 -7
- package/dist/core/policy/types.d.ts +3 -3
- package/dist/core/policy/types.d.ts.map +1 -1
- package/dist/core/work/state.d.ts +12 -4
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +50 -17
- package/dist/core/workflow/adapters.d.ts +17 -0
- package/dist/core/workflow/adapters.d.ts.map +1 -0
- package/dist/core/workflow/adapters.js +21 -0
- package/dist/core/workflow/approvals.js +6 -6
- package/dist/core/workflow/billing.d.ts +9 -9
- package/dist/core/workflow/billing.js +9 -9
- package/dist/core/workflow/child-env.d.ts +10 -2
- package/dist/core/workflow/child-env.d.ts.map +1 -1
- package/dist/core/workflow/child-env.js +12 -4
- package/dist/core/workflow/engine.d.ts +15 -5
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +138 -83
- package/dist/core/workflow/evidence-preflight.d.ts +24 -0
- package/dist/core/workflow/evidence-preflight.d.ts.map +1 -0
- package/dist/core/workflow/evidence-preflight.js +134 -0
- package/dist/core/workflow/index.d.ts +1 -1
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/proof.d.ts +11 -5
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +45 -36
- package/dist/core/workflow/run-state.d.ts +1 -1
- package/dist/core/workflow/run-state.js +7 -7
- package/dist/core/workflow/sandbox-projection.d.ts +6 -6
- package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
- package/dist/core/workflow/sandbox-projection.js +11 -11
- package/dist/core/workflow/spawn-claude.d.ts +3 -3
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +9 -6
- package/dist/core/workflow/spawn-codex.d.ts +4 -4
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +9 -6
- package/dist/core/workflow/spawn-cursor.d.ts +4 -4
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +9 -6
- package/dist/core/workflow/spawn-failure.d.ts +1 -1
- package/dist/core/workflow/spawn-failure.js +1 -1
- package/dist/core/workflow/specialists.js +2 -2
- package/dist/core/workflow/{journal.d.ts → transcript.d.ts} +8 -8
- package/dist/core/workflow/transcript.d.ts.map +1 -0
- package/dist/core/workflow/{journal.js → transcript.js} +14 -14
- package/dist/core/workflow/types.d.ts +98 -51
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/types.js +11 -1
- package/dist/core/workflow/validate.d.ts +1 -1
- package/dist/core/workflow/validate.js +1 -1
- package/dist/core/workflow/workspaces/cancellation.js +2 -2
- package/dist/core/workflow/workspaces/cleanup.js +2 -2
- package/dist/core/workflow/workspaces/execution.js +6 -6
- package/dist/core/workflow/workspaces/inspect.js +9 -9
- package/dist/core/workflow/workspaces/integration.js +14 -14
- package/dist/core/workflow/workspaces/lifecycle.d.ts +1 -1
- package/dist/core/workflow/workspaces/lifecycle.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/lifecycle.js +9 -9
- package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.js +39 -5
- package/dist/core/workflow/workspaces/recovery.js +3 -3
- package/dist/core/workflow/workspaces/state.d.ts +1 -1
- package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/state.js +3 -3
- package/dist/core/workflow/workspaces/types.d.ts +1 -1
- package/dist/core/workflow/workspaces/types.d.ts.map +1 -1
- package/dist/lib/browser/asserts.d.ts +28 -0
- package/dist/lib/browser/asserts.d.ts.map +1 -0
- package/dist/lib/browser/asserts.js +152 -0
- package/dist/lib/browser/client.d.ts +49 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +155 -14
- package/dist/lib/browser/content-checks.d.ts +108 -0
- package/dist/lib/browser/content-checks.d.ts.map +1 -0
- package/dist/lib/browser/content-checks.js +474 -0
- package/dist/lib/browser/critique.d.ts +91 -0
- package/dist/lib/browser/critique.d.ts.map +1 -0
- package/dist/lib/browser/critique.js +167 -0
- package/dist/lib/browser/geometry.d.ts +32 -0
- package/dist/lib/browser/geometry.d.ts.map +1 -1
- package/dist/lib/browser/geometry.js +244 -1
- package/dist/lib/browser/index.d.ts +4 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -0
- package/dist/lib/claude-desktop.d.ts.map +1 -1
- package/dist/lib/claude-desktop.js +4 -1
- package/dist/lib/context/index.js +9 -2
- package/dist/lib/council/index.d.ts +6 -6
- package/dist/lib/council/index.d.ts.map +1 -1
- package/dist/lib/council/index.js +8 -8
- package/dist/lib/identities/assume.d.ts +2 -2
- package/dist/lib/identities/assume.js +7 -7
- package/dist/lib/instructions/apply.d.ts +3 -3
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +75 -27
- package/dist/lib/instructions/host-addendum.d.ts +54 -0
- package/dist/lib/instructions/host-addendum.d.ts.map +1 -0
- package/dist/lib/instructions/host-addendum.js +107 -0
- package/dist/lib/instructions/templates.d.ts +10 -3
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +41 -12
- package/dist/lib/machine.d.ts +2 -2
- package/dist/lib/machine.js +2 -2
- package/package.json +26 -21
- package/schemas/config.schema.json +26 -1
- package/src/commander.ts +22 -13
- package/src/commands/{harness.ts → adapter.ts} +46 -46
- package/src/commands/agents.ts +200 -78
- package/src/commands/artifacts.ts +168 -0
- package/src/commands/backup.ts +47 -33
- package/src/commands/browse.ts +438 -2
- package/src/commands/checkpoint.ts +196 -0
- package/src/commands/context.ts +3 -176
- package/src/commands/decision.ts +41 -7
- package/src/commands/deinit.ts +16 -16
- package/src/commands/doctor.ts +28 -28
- package/src/commands/{supervisor.ts → governor.ts} +184 -154
- package/src/commands/grep.ts +19 -2
- package/src/commands/init.ts +50 -34
- package/src/commands/{scratch.ts → journal.ts} +60 -60
- package/src/commands/policy.ts +1 -1
- package/src/commands/presence.ts +2 -2
- package/src/commands/sync.ts +3 -3
- package/src/commands/tunnel.ts +256 -38
- package/src/commands/web-fetch.ts +1 -1
- package/src/commands/web.ts +56 -1
- package/src/commands/work.ts +50 -35
- package/src/commands/workflow.ts +43 -34
- package/src/core/{harnesses → adapters}/attest-projection.ts +2 -2
- package/src/core/{harnesses → adapters}/attest.ts +27 -27
- package/src/core/{harnesses → adapters}/attestation.ts +41 -41
- package/src/core/{harnesses → adapters}/bench.ts +34 -43
- package/src/core/adapters/index.ts +56 -0
- package/src/core/{harnesses → adapters}/profiles.ts +16 -16
- package/src/core/{harnesses → adapters}/registry.ts +23 -23
- package/src/core/{harnesses → adapters}/types.ts +23 -23
- package/src/core/agents/canonical-emit.ts +16 -43
- package/src/core/agents/cli-emit.ts +1 -1
- package/src/core/agents/cli.ts +30 -28
- package/src/core/agents/codex-replay.ts +6 -6
- package/src/core/agents/coord-bin.ts +92 -0
- package/src/core/agents/coord-client.ts +302 -78
- package/src/core/agents/events/consume.ts +1 -1
- package/src/core/agents/events/emit.ts +7 -6
- package/src/core/agents/paths.ts +7 -11
- package/src/core/agents/render/prompt-context.ts +107 -31
- package/src/core/agents/render/session-context.ts +6 -6
- package/src/core/agents/rules/claim-conflict.ts +4 -7
- package/src/core/agents/rules/commit-conflict.ts +103 -22
- package/src/core/agents/rules/stop-hook.ts +33 -17
- package/src/core/agents/rules/verdict.ts +13 -0
- package/src/core/agents/session-events.ts +4 -4
- package/src/core/agents/state/council.ts +1 -1
- package/src/core/agents/state/heartbeat-projector.ts +16 -12
- package/src/core/agents/state/heartbeat-writer.ts +12 -12
- package/src/core/agents/state/{scratch.ts → journal.ts} +12 -12
- package/src/core/agents/state/pidmap.ts +130 -15
- package/src/core/agents/state/proc-start.ts +208 -0
- package/src/core/agents/state/shell-mutation.ts +1 -1
- package/src/core/agents/state/stale-sweep.ts +7 -7
- package/src/core/artifacts/index.ts +557 -0
- package/src/core/config.ts +30 -2
- package/src/core/context/index.ts +15 -15
- package/src/core/governor/adapter-spread.ts +82 -0
- package/src/core/governor/index.ts +91 -0
- package/src/core/governor/plan-api.ts +115 -0
- package/src/core/{supervisor → governor}/plan-read.ts +112 -97
- package/src/core/{supervisor → governor}/plan-types.ts +59 -56
- package/src/core/{supervisor → governor}/planning.ts +223 -192
- package/src/core/governor/read.ts +59 -0
- package/src/core/{supervisor → governor}/runner.ts +39 -39
- package/src/core/{supervisor → governor}/service-read.ts +22 -22
- package/src/core/{supervisor → governor}/service.ts +117 -119
- package/src/core/{supervisor → governor}/state.ts +325 -167
- package/src/core/hooks/adapter/detect.ts +30 -0
- package/src/core/hooks/{harness → adapter}/events.ts +16 -14
- package/src/core/hooks/{harness → adapter}/output.ts +31 -23
- package/src/core/hooks/{harness → adapter}/parse.ts +5 -5
- package/src/core/hooks/{harness → adapter}/wiring.ts +21 -21
- package/src/core/hooks/cli.ts +197 -173
- package/src/core/hooks/effects/image-capture.ts +6 -6
- package/src/core/hooks/effects/index.ts +19 -19
- package/src/core/hooks/events/emit.ts +3 -3
- package/src/core/hooks/events/rotate.ts +1 -1
- package/src/core/hooks/events/schema.ts +15 -7
- package/src/core/hooks/guard-path.ts +2 -2
- package/src/core/hooks/index.ts +1 -1
- package/src/core/hooks/resolve/anchor.ts +63 -8
- package/src/core/hooks/resolve/coord-root.ts +18 -40
- package/src/core/hooks/resolve/intent.ts +1 -1
- package/src/core/hooks/resolve/owner.ts +11 -5
- package/src/core/{scratch → journal}/index.ts +53 -53
- package/src/core/policy/evaluate.ts +8 -8
- package/src/core/policy/types.ts +3 -3
- package/src/core/work/state.ts +65 -23
- package/src/core/workflow/adapters.ts +33 -0
- package/src/core/workflow/approvals.ts +7 -7
- package/src/core/workflow/billing.ts +12 -12
- package/src/core/workflow/child-env.ts +13 -4
- package/src/core/workflow/engine.ts +155 -90
- package/src/core/workflow/evidence-preflight.ts +165 -0
- package/src/core/workflow/index.ts +3 -3
- package/src/core/workflow/proof.ts +60 -50
- package/src/core/workflow/run-state.ts +7 -7
- package/src/core/workflow/sandbox-projection.ts +16 -16
- package/src/core/workflow/spawn-claude.ts +13 -10
- package/src/core/workflow/spawn-codex.ts +13 -10
- package/src/core/workflow/spawn-cursor.ts +13 -10
- package/src/core/workflow/spawn-failure.ts +1 -1
- package/src/core/workflow/specialists.ts +2 -2
- package/src/core/workflow/{journal.ts → transcript.ts} +16 -16
- package/src/core/workflow/types.ts +108 -51
- package/src/core/workflow/validate.ts +1 -1
- package/src/core/workflow/workspaces/cancellation.ts +2 -2
- package/src/core/workflow/workspaces/cleanup.ts +2 -2
- package/src/core/workflow/workspaces/execution.ts +6 -6
- package/src/core/workflow/workspaces/inspect.ts +14 -11
- package/src/core/workflow/workspaces/integration.ts +18 -14
- package/src/core/workflow/workspaces/lifecycle.ts +10 -10
- package/src/core/workflow/workspaces/local-git.ts +47 -5
- package/src/core/workflow/workspaces/recovery.ts +3 -3
- package/src/core/workflow/workspaces/state.ts +4 -3
- package/src/core/workflow/workspaces/types.ts +1 -1
- package/src/lib/browser/asserts.ts +177 -0
- package/src/lib/browser/client.ts +189 -14
- package/src/lib/browser/content-checks.ts +571 -0
- package/src/lib/browser/critique.ts +231 -0
- package/src/lib/browser/geometry.ts +297 -1
- package/src/lib/browser/index.ts +34 -0
- package/src/lib/claude-desktop.ts +4 -1
- package/src/lib/context/index.ts +11 -1
- package/src/lib/council/index.ts +9 -9
- package/src/lib/identities/assume.ts +7 -7
- package/src/lib/instructions/apply.ts +87 -25
- package/src/lib/instructions/host-addendum.ts +126 -0
- package/src/lib/instructions/templates.ts +44 -15
- package/src/lib/machine.ts +2 -2
- package/dist/commands/harness.d.ts +0 -12
- package/dist/commands/harness.d.ts.map +0 -1
- package/dist/commands/scratch.d.ts +0 -4
- package/dist/commands/scratch.d.ts.map +0 -1
- package/dist/commands/session.d.ts.map +0 -1
- package/dist/commands/session.js +0 -162
- package/dist/commands/supervisor.d.ts +0 -4
- package/dist/commands/supervisor.d.ts.map +0 -1
- package/dist/core/harnesses/attest-projection.d.ts.map +0 -1
- package/dist/core/harnesses/attest.d.ts.map +0 -1
- package/dist/core/harnesses/attestation.d.ts.map +0 -1
- package/dist/core/harnesses/bench.d.ts.map +0 -1
- package/dist/core/harnesses/index.d.ts +0 -13
- package/dist/core/harnesses/index.d.ts.map +0 -1
- package/dist/core/harnesses/index.js +0 -6
- package/dist/core/harnesses/profiles.d.ts.map +0 -1
- package/dist/core/harnesses/registry.d.ts +0 -15
- package/dist/core/harnesses/registry.d.ts.map +0 -1
- package/dist/core/harnesses/types.d.ts.map +0 -1
- package/dist/core/hooks/harness/detect.d.ts +0 -9
- package/dist/core/hooks/harness/events.d.ts.map +0 -1
- package/dist/core/hooks/harness/output.d.ts.map +0 -1
- package/dist/core/supervisor/index.d.ts +0 -7
- package/dist/core/supervisor/index.d.ts.map +0 -1
- package/dist/core/supervisor/index.js +0 -6
- package/dist/core/supervisor/plan-api.d.ts +0 -23
- package/dist/core/supervisor/plan-api.d.ts.map +0 -1
- package/dist/core/supervisor/plan-api.js +0 -50
- package/dist/core/supervisor/plan-read.d.ts +0 -5
- package/dist/core/supervisor/plan-read.d.ts.map +0 -1
- package/dist/core/supervisor/plan-types.d.ts.map +0 -1
- package/dist/core/supervisor/planning.d.ts +0 -33
- package/dist/core/supervisor/planning.d.ts.map +0 -1
- package/dist/core/supervisor/read.d.ts +0 -6
- package/dist/core/supervisor/read.d.ts.map +0 -1
- package/dist/core/supervisor/read.js +0 -4
- package/dist/core/supervisor/runner.d.ts +0 -37
- package/dist/core/supervisor/runner.d.ts.map +0 -1
- package/dist/core/supervisor/service-read.d.ts +0 -6
- package/dist/core/supervisor/service-read.d.ts.map +0 -1
- package/dist/core/supervisor/service.d.ts +0 -114
- package/dist/core/supervisor/service.d.ts.map +0 -1
- package/dist/core/supervisor/state.d.ts +0 -95
- package/dist/core/supervisor/state.d.ts.map +0 -1
- package/dist/core/workflow/harnesses.d.ts +0 -17
- package/dist/core/workflow/harnesses.d.ts.map +0 -1
- package/dist/core/workflow/harnesses.js +0 -21
- package/dist/core/workflow/journal.d.ts.map +0 -1
- package/src/commands/session.ts +0 -187
- package/src/core/harnesses/index.ts +0 -56
- package/src/core/hooks/harness/detect.ts +0 -30
- package/src/core/supervisor/index.ts +0 -89
- package/src/core/supervisor/plan-api.ts +0 -73
- package/src/core/supervisor/read.ts +0 -59
- package/src/core/workflow/harnesses.ts +0 -33
- /package/dist/core/{harnesses → adapters}/attest-projection.js +0 -0
|
@@ -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");
|
|
@@ -185,27 +196,27 @@ function readEvents(path, planId) {
|
|
|
185
196
|
return [];
|
|
186
197
|
const size = statSync(path).size;
|
|
187
198
|
if (size > MAX_EVENTS_BYTES)
|
|
188
|
-
throw new Error("
|
|
199
|
+
throw new Error("governor plan events exceed their byte limit");
|
|
189
200
|
const body = readFileSync(path, "utf8");
|
|
190
201
|
if (body && !body.endsWith("\n"))
|
|
191
|
-
throw new Error(`
|
|
202
|
+
throw new Error(`governor plan ${planId} has a partial event`);
|
|
192
203
|
const lines = body.split("\n").filter(Boolean);
|
|
193
204
|
if (lines.length > MAX_EVENTS)
|
|
194
|
-
throw new Error(`
|
|
205
|
+
throw new Error(`governor plan exceeds ${MAX_EVENTS} events`);
|
|
195
206
|
return lines.map((line, index) => {
|
|
196
207
|
let event;
|
|
197
208
|
try {
|
|
198
209
|
event = JSON.parse(line);
|
|
199
210
|
}
|
|
200
211
|
catch (error) {
|
|
201
|
-
throw new Error(`cannot parse
|
|
212
|
+
throw new Error(`cannot parse governor plan ${planId} event ${index + 1}: ${error.message}`);
|
|
202
213
|
}
|
|
203
214
|
validateEvent(event, planId, index + 1);
|
|
204
215
|
return event;
|
|
205
216
|
});
|
|
206
217
|
}
|
|
207
218
|
function validateRequest(request, goalId, planId) {
|
|
208
|
-
if (request.schema_version !==
|
|
219
|
+
if (request.schema_version !== GOVERNOR_PLAN_SCHEMA_VERSION ||
|
|
209
220
|
request.id !== planId ||
|
|
210
221
|
request.goal_id !== goalId ||
|
|
211
222
|
!Number.isSafeInteger(request.sequence) ||
|
|
@@ -219,11 +230,11 @@ function validateRequest(request, goalId, planId) {
|
|
|
219
230
|
!WORK_ID.test(request.prior_root_work_id) ||
|
|
220
231
|
!/^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/.test(request.workflow_run_id) ||
|
|
221
232
|
!validTimestamp(request.created_at)) {
|
|
222
|
-
throw new Error(`
|
|
233
|
+
throw new Error(`governor plan request ${planId} has an unsupported schema`);
|
|
223
234
|
}
|
|
224
235
|
}
|
|
225
236
|
function validateProposalEnvelope(proposal, planId) {
|
|
226
|
-
if (proposal.schema_version !==
|
|
237
|
+
if (proposal.schema_version !== GOVERNOR_PLAN_SCHEMA_VERSION ||
|
|
227
238
|
proposal.plan_id !== planId ||
|
|
228
239
|
!["apply", "complete", "attention"].includes(proposal.decision) ||
|
|
229
240
|
typeof proposal.rationale !== "string" ||
|
|
@@ -234,7 +245,7 @@ function validateProposalEnvelope(proposal, planId) {
|
|
|
234
245
|
typeof proposal.root !== "string" ||
|
|
235
246
|
proposal.root.length > 32 ||
|
|
236
247
|
!validTimestamp(proposal.proposed_at)) {
|
|
237
|
-
throw new Error(`
|
|
248
|
+
throw new Error(`governor plan proposal ${planId} has an unsupported schema`);
|
|
238
249
|
}
|
|
239
250
|
if (proposal.milestone !== undefined) {
|
|
240
251
|
const milestone = proposal.milestone;
|
|
@@ -251,12 +262,12 @@ function validateProposalEnvelope(proposal, planId) {
|
|
|
251
262
|
milestone.acceptance.length < 1 ||
|
|
252
263
|
milestone.acceptance.length > 50 ||
|
|
253
264
|
milestone.acceptance.some((criterion) => typeof criterion !== "string" || criterion.length < 1 || criterion.length > 500)) {
|
|
254
|
-
throw new Error(`
|
|
265
|
+
throw new Error(`governor plan proposal ${planId} milestone is invalid`);
|
|
255
266
|
}
|
|
256
267
|
}
|
|
257
268
|
if ((proposal.decision === "attention" || proposal.decision === "complete") &&
|
|
258
269
|
(proposal.root !== "" || proposal.work.length > 0 || proposal.milestone !== undefined)) {
|
|
259
|
-
throw new Error(`
|
|
270
|
+
throw new Error(`governor plan proposal ${planId} terminal decision contains work`);
|
|
260
271
|
}
|
|
261
272
|
for (const [index, spec] of proposal.work.entries()) {
|
|
262
273
|
if (!spec ||
|
|
@@ -275,71 +286,71 @@ function validateProposalEnvelope(proposal, planId) {
|
|
|
275
286
|
spec.dependencies.length > 50 ||
|
|
276
287
|
spec.dependencies.some((value) => typeof value !== "string" || value.length > 100) ||
|
|
277
288
|
!TEMPLATE_ID.test(spec.template)) {
|
|
278
|
-
throw new Error(`
|
|
289
|
+
throw new Error(`governor plan proposal ${planId} work[${index}] is invalid`);
|
|
279
290
|
}
|
|
280
291
|
}
|
|
281
292
|
}
|
|
282
293
|
function validateReviewReceipt(receipt, planId) {
|
|
283
294
|
if (!receipt ||
|
|
284
295
|
typeof receipt !== "object" ||
|
|
285
|
-
receipt.schema_version !==
|
|
296
|
+
receipt.schema_version !== GOVERNOR_PLAN_SCHEMA_VERSION ||
|
|
286
297
|
receipt.plan_id !== planId ||
|
|
287
298
|
!["passed", "revision_exhausted", "attention", "failed"].includes(receipt.status) ||
|
|
288
299
|
!/^[a-f0-9]{64}$/.test(receipt.candidate_sha256) ||
|
|
289
300
|
!Array.isArray(receipt.rounds) ||
|
|
290
301
|
receipt.rounds.length < 1 ||
|
|
291
|
-
receipt.rounds.length >
|
|
292
|
-
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`);
|
|
293
304
|
}
|
|
294
305
|
validateProposalEnvelope(receipt.final_candidate, planId);
|
|
295
306
|
if (receipt.candidate_sha256 !== candidateDigest(receipt.final_candidate)) {
|
|
296
|
-
throw new Error(`
|
|
307
|
+
throw new Error(`governor plan review ${planId} has invalid candidate digest`);
|
|
297
308
|
}
|
|
298
309
|
receipt.rounds.forEach((round, index) => {
|
|
299
310
|
validateReviewRound(round, planId, index + 1);
|
|
300
311
|
});
|
|
301
312
|
const finalRound = receipt.rounds.at(-1);
|
|
302
313
|
if (finalRound?.candidate_sha256 !== receipt.candidate_sha256) {
|
|
303
|
-
throw new Error(`
|
|
314
|
+
throw new Error(`governor plan review ${planId} final round does not match its candidate`);
|
|
304
315
|
}
|
|
305
316
|
if (receipt.status === "passed" && finalRound?.outcome !== "approved") {
|
|
306
|
-
throw new Error(`
|
|
317
|
+
throw new Error(`governor plan review ${planId} passed without approval`);
|
|
307
318
|
}
|
|
308
319
|
if (receipt.status === "attention" && finalRound?.outcome === "approved") {
|
|
309
|
-
throw new Error(`
|
|
320
|
+
throw new Error(`governor plan review ${planId} attention conflicts with approval`);
|
|
310
321
|
}
|
|
311
322
|
}
|
|
312
323
|
function readFrozenReviewPolicy(coordRoot, goalId) {
|
|
313
|
-
const path = join(coordRoot, ".harnery", "
|
|
324
|
+
const path = join(coordRoot, ".harnery", "governors", goalId, "intent.json");
|
|
314
325
|
if (!existsSync(path))
|
|
315
326
|
return undefined;
|
|
316
|
-
const intent = readJson(path, "
|
|
327
|
+
const intent = readJson(path, "governor intent");
|
|
317
328
|
return intent.replanning?.review;
|
|
318
329
|
}
|
|
319
330
|
function validateReviewReceiptMatchesPolicy(receipt, planId, review) {
|
|
320
331
|
if (receipt.rounds.length > review.max_revision_rounds + 1) {
|
|
321
|
-
throw new Error(`
|
|
332
|
+
throw new Error(`governor plan review ${planId} exceeds the frozen review policy`);
|
|
322
333
|
}
|
|
323
334
|
for (const round of receipt.rounds) {
|
|
324
335
|
if (round.reviewers.length !== review.reviewer_specialists.length) {
|
|
325
|
-
throw new Error(`
|
|
336
|
+
throw new Error(`governor plan review ${planId} does not match the frozen review policy`);
|
|
326
337
|
}
|
|
327
338
|
round.reviewers.forEach((reviewer, index) => {
|
|
328
339
|
if (reviewer.specialist !== review.reviewer_specialists[index]) {
|
|
329
|
-
throw new Error(`
|
|
340
|
+
throw new Error(`governor plan review ${planId} does not match the frozen review policy`);
|
|
330
341
|
}
|
|
331
342
|
});
|
|
332
343
|
const outcome = aggregateReviewers(round.reviewers);
|
|
333
344
|
if (round.outcome !== outcome) {
|
|
334
|
-
throw new Error(`
|
|
345
|
+
throw new Error(`governor plan review ${planId} has an invalid reviewer outcome`);
|
|
335
346
|
}
|
|
336
347
|
}
|
|
337
348
|
const finalRound = receipt.rounds.at(-1);
|
|
338
349
|
if (receipt.status === "passed" && finalRound.outcome !== "approved") {
|
|
339
|
-
throw new Error(`
|
|
350
|
+
throw new Error(`governor plan review ${planId} passed without policy approval`);
|
|
340
351
|
}
|
|
341
352
|
if (receipt.status === "revision_exhausted" && finalRound.round <= review.max_revision_rounds) {
|
|
342
|
-
throw new Error(`
|
|
353
|
+
throw new Error(`governor plan review ${planId} exhausted before the frozen review limit`);
|
|
343
354
|
}
|
|
344
355
|
}
|
|
345
356
|
function aggregateReviewers(reviewers) {
|
|
@@ -376,11 +387,11 @@ function validateReviewRound(round, planId, sequence) {
|
|
|
376
387
|
!/^[a-f0-9]{64}$/.test(round.candidate_sha256) ||
|
|
377
388
|
!Array.isArray(round.reviewers) ||
|
|
378
389
|
round.reviewers.length < 1 ||
|
|
379
|
-
round.reviewers.length >
|
|
390
|
+
round.reviewers.length > MAX_GOVERNOR_PLAN_REVIEWERS ||
|
|
380
391
|
!["approved", "revise", "attention", "failed"].includes(round.outcome) ||
|
|
381
392
|
(round.revision_workflow_run_id !== undefined &&
|
|
382
393
|
!/^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/.test(round.revision_workflow_run_id))) {
|
|
383
|
-
throw new Error(`
|
|
394
|
+
throw new Error(`governor plan review ${planId} round ${sequence} is invalid`);
|
|
384
395
|
}
|
|
385
396
|
round.reviewers.forEach((reviewer, index) => {
|
|
386
397
|
validateReviewReviewer(reviewer, planId, sequence, index);
|
|
@@ -398,7 +409,7 @@ function validateReviewReviewer(reviewer, planId, round, index) {
|
|
|
398
409
|
reviewer.rationale.length > 2_000 ||
|
|
399
410
|
!Array.isArray(reviewer.findings) ||
|
|
400
411
|
reviewer.findings.length > 50) {
|
|
401
|
-
throw new Error(`
|
|
412
|
+
throw new Error(`governor plan review ${planId} round ${round} reviewer ${index} is invalid`);
|
|
402
413
|
}
|
|
403
414
|
reviewer.findings.forEach((finding, findingIndex) => {
|
|
404
415
|
validateReviewFinding(finding, planId, round, index, findingIndex);
|
|
@@ -416,7 +427,7 @@ function validateReviewFinding(finding, planId, round, reviewerIndex, findingInd
|
|
|
416
427
|
typeof finding.recommendation !== "string" ||
|
|
417
428
|
finding.recommendation.length < 1 ||
|
|
418
429
|
finding.recommendation.length > 1_000) {
|
|
419
|
-
throw new Error(`
|
|
430
|
+
throw new Error(`governor plan review ${planId} round ${round} reviewer ${reviewerIndex} finding ${findingIndex} is invalid`);
|
|
420
431
|
}
|
|
421
432
|
}
|
|
422
433
|
function summarizeReview(receipt) {
|
|
@@ -430,7 +441,7 @@ function summarizeReview(receipt) {
|
|
|
430
441
|
};
|
|
431
442
|
}
|
|
432
443
|
function validateEvent(event, planId, sequence) {
|
|
433
|
-
if (event.schema_version !==
|
|
444
|
+
if (event.schema_version !== GOVERNOR_PLAN_SCHEMA_VERSION ||
|
|
434
445
|
event.plan_id !== planId ||
|
|
435
446
|
event.seq !== sequence ||
|
|
436
447
|
!EVENT_TYPES.has(event.event) ||
|
|
@@ -441,21 +452,24 @@ function validateEvent(event, planId, sequence) {
|
|
|
441
452
|
typeof event.reason !== "string" ||
|
|
442
453
|
event.reason.length < 1 ||
|
|
443
454
|
event.reason.length > 2_000) {
|
|
444
|
-
throw new Error(`
|
|
455
|
+
throw new Error(`governor plan ${planId} event ${sequence} has an unsupported schema`);
|
|
445
456
|
}
|
|
446
457
|
if (event.approval_id !== undefined && !APPROVAL_ID.test(event.approval_id)) {
|
|
447
|
-
throw new Error(`
|
|
458
|
+
throw new Error(`governor plan ${planId} event ${sequence} has an invalid approval id`);
|
|
448
459
|
}
|
|
449
460
|
if (event.root_work_id !== undefined && !WORK_ID.test(event.root_work_id)) {
|
|
450
|
-
throw new Error(`
|
|
461
|
+
throw new Error(`governor plan ${planId} event ${sequence} has an invalid root work id`);
|
|
451
462
|
}
|
|
452
463
|
if (event.work_ids !== undefined) {
|
|
453
464
|
if (!Array.isArray(event.work_ids) || event.work_ids.some((id) => !WORK_ID.test(id))) {
|
|
454
|
-
throw new Error(`
|
|
465
|
+
throw new Error(`governor plan ${planId} event ${sequence} has invalid work ids`);
|
|
455
466
|
}
|
|
456
467
|
}
|
|
457
|
-
if (event.class !== undefined &&
|
|
458
|
-
|
|
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`);
|
|
459
473
|
}
|
|
460
474
|
}
|
|
461
475
|
function approvalIsResolved(coordRoot, approvalId) {
|
|
@@ -484,7 +498,7 @@ function readJson(path, label) {
|
|
|
484
498
|
}
|
|
485
499
|
}
|
|
486
500
|
function plansRoot(coordRoot, goalId) {
|
|
487
|
-
return join(coordRoot, ".harnery", "
|
|
501
|
+
return join(coordRoot, ".harnery", "governors", goalId, "plans");
|
|
488
502
|
}
|
|
489
503
|
function planDir(coordRoot, goalId, planId) {
|
|
490
504
|
return join(plansRoot(coordRoot, goalId), planId);
|