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
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
} from "../agents/index.ts";
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* Agent
|
|
22
|
+
* Agent journal: per-agent markdown journal at `.harnery/journal/<instance_id>.md`.
|
|
23
23
|
*
|
|
24
24
|
* Rules:
|
|
25
25
|
* - Single writer (the agent itself, via this lib). Peers read but never write.
|
|
@@ -27,12 +27,12 @@ import {
|
|
|
27
27
|
* - Strict entry-header format: `## <Chicago datetime> · <category>`. The
|
|
28
28
|
* linter enforces this so format violations are impossible at the write path.
|
|
29
29
|
* - 50 KB hard cap; auto-prunes oldest entries when exceeded.
|
|
30
|
-
* - SessionEnd hook archives to `.harnery/
|
|
30
|
+
* - SessionEnd hook archives to `.harnery/journal/archived/<instance_id>-<ts>.md`;
|
|
31
31
|
* SessionStart janitor deletes archives older than 7 days + surfaces the
|
|
32
32
|
* most-recent archive as a recovery cue.
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
|
-
export const
|
|
35
|
+
export const JOURNAL_CATEGORIES = [
|
|
36
36
|
"note",
|
|
37
37
|
"plan",
|
|
38
38
|
"decision",
|
|
@@ -42,27 +42,27 @@ export const SCRATCH_CATEGORIES = [
|
|
|
42
42
|
"handoff",
|
|
43
43
|
] as const;
|
|
44
44
|
|
|
45
|
-
export type
|
|
45
|
+
export type JournalCategory = (typeof JOURNAL_CATEGORIES)[number];
|
|
46
46
|
|
|
47
|
-
export const
|
|
48
|
-
export const
|
|
47
|
+
export const MAX_JOURNAL_BYTES = 50 * 1024;
|
|
48
|
+
export const WARN_JOURNAL_BYTES = 40 * 1024;
|
|
49
49
|
export const ARCHIVE_RETENTION_DAYS = 7;
|
|
50
50
|
|
|
51
51
|
/** Entry-header regex: `## 2026-05-15 1:48 AM CDT · note` */
|
|
52
52
|
export const ENTRY_HEADER_RE =
|
|
53
53
|
/^## (\d{4}-\d{2}-\d{2}) (\d{1,2}):(\d{2}) (AM|PM) (CDT|CST) · (note|plan|decision|blocker|question|done|handoff)$/;
|
|
54
54
|
|
|
55
|
-
/** First line of every
|
|
56
|
-
export const
|
|
55
|
+
/** First line of every journal file: this prefix followed by the agent name. */
|
|
56
|
+
export const JOURNAL_HEADER_PREFIX = "# Journal: agent-";
|
|
57
57
|
|
|
58
|
-
export interface
|
|
58
|
+
export interface JournalEntry {
|
|
59
59
|
ts_iso: string; // canonical ISO (computed from Chicago wall time at write)
|
|
60
60
|
ts_display: string; // "2026-05-15 1:48 AM CDT", what's in the file
|
|
61
|
-
category:
|
|
61
|
+
category: JournalCategory;
|
|
62
62
|
body: string;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
export interface
|
|
65
|
+
export interface JournalHeader {
|
|
66
66
|
name: string;
|
|
67
67
|
session_id: string;
|
|
68
68
|
machine: string;
|
|
@@ -70,32 +70,32 @@ export interface ScratchHeader {
|
|
|
70
70
|
last_updated: string;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export interface
|
|
73
|
+
export interface JournalDoc {
|
|
74
74
|
path: string;
|
|
75
|
-
header:
|
|
76
|
-
entries:
|
|
75
|
+
header: JournalHeader;
|
|
76
|
+
entries: JournalEntry[];
|
|
77
77
|
bytes: number;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// ─── Paths ────────────────────────────────────────────────────────────────
|
|
81
81
|
|
|
82
|
-
export function
|
|
82
|
+
export function journalDir(): string {
|
|
83
83
|
const root = monorepoRoot();
|
|
84
84
|
if (!root) throw new Error("Not in a coord-aware repo (coord_root() returned null).");
|
|
85
|
-
const dir = resolve(root, ".harnery", "
|
|
85
|
+
const dir = resolve(root, ".harnery", "journal");
|
|
86
86
|
mkdirSync(dir, { recursive: true });
|
|
87
87
|
return dir;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
export function archiveDir(): string {
|
|
91
|
-
const dir = resolve(
|
|
91
|
+
const dir = resolve(journalDir(), "archived");
|
|
92
92
|
mkdirSync(dir, { recursive: true });
|
|
93
93
|
return dir;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
export function
|
|
96
|
+
export function journalPath(instanceId: string): string {
|
|
97
97
|
assertSafeInstanceId(instanceId);
|
|
98
|
-
return resolveContainedFile(
|
|
98
|
+
return resolveContainedFile(journalDir(), `${instanceId}.md`);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
// ─── Chicago time formatting ──────────────────────────────────────────────
|
|
@@ -127,22 +127,22 @@ export function formatChicago(d: Date = new Date()): string {
|
|
|
127
127
|
|
|
128
128
|
// ─── Parse / serialize ────────────────────────────────────────────────────
|
|
129
129
|
|
|
130
|
-
/** Parse a
|
|
131
|
-
export function
|
|
130
|
+
/** Parse a journal file (or empty content) into a structured doc. */
|
|
131
|
+
export function parseJournal(path: string, content: string): JournalDoc {
|
|
132
132
|
const lines = content.split("\n");
|
|
133
|
-
const header:
|
|
133
|
+
const header: JournalHeader = {
|
|
134
134
|
name: "unknown",
|
|
135
135
|
session_id: "",
|
|
136
136
|
machine: "",
|
|
137
137
|
started: "",
|
|
138
138
|
last_updated: "",
|
|
139
139
|
};
|
|
140
|
-
const entries:
|
|
140
|
+
const entries: JournalEntry[] = [];
|
|
141
141
|
|
|
142
142
|
let i = 0;
|
|
143
143
|
// ── header ──
|
|
144
|
-
if (lines[i]?.startsWith(
|
|
145
|
-
header.name = lines[i].replace(
|
|
144
|
+
if (lines[i]?.startsWith(JOURNAL_HEADER_PREFIX)) {
|
|
145
|
+
header.name = lines[i].replace(JOURNAL_HEADER_PREFIX, "").trim();
|
|
146
146
|
i++;
|
|
147
147
|
}
|
|
148
148
|
for (; i < lines.length; i++) {
|
|
@@ -181,7 +181,7 @@ export function parseScratch(path: string, content: string): ScratchDoc {
|
|
|
181
181
|
entries.push({
|
|
182
182
|
ts_iso: chicagoToIso(date, hour, minute, period as "AM" | "PM", tz as "CDT" | "CST"),
|
|
183
183
|
ts_display: `${date} ${hour}:${minute} ${period} ${tz}`,
|
|
184
|
-
category: category as
|
|
184
|
+
category: category as JournalCategory,
|
|
185
185
|
body: bodyLines.join("\n").trim(),
|
|
186
186
|
});
|
|
187
187
|
currentHeader = null;
|
|
@@ -203,9 +203,9 @@ export function parseScratch(path: string, content: string): ScratchDoc {
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
/** Serialize a parsed doc back to markdown. */
|
|
206
|
-
export function
|
|
206
|
+
export function serializeJournal(doc: JournalDoc): string {
|
|
207
207
|
const lines: string[] = [];
|
|
208
|
-
lines.push(`${
|
|
208
|
+
lines.push(`${JOURNAL_HEADER_PREFIX}${doc.header.name}`);
|
|
209
209
|
if (doc.header.session_id) lines.push(`session_id: ${doc.header.session_id}`);
|
|
210
210
|
if (doc.header.machine) lines.push(`machine: ${doc.header.machine}`);
|
|
211
211
|
if (doc.header.started) lines.push(`started: ${doc.header.started}`);
|
|
@@ -245,13 +245,13 @@ export interface LintIssue {
|
|
|
245
245
|
message: string;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
export function
|
|
248
|
+
export function lintJournal(content: string, byteCap = MAX_JOURNAL_BYTES): LintIssue[] {
|
|
249
249
|
const issues: LintIssue[] = [];
|
|
250
250
|
const lines = content.split("\n");
|
|
251
251
|
|
|
252
252
|
// Frontmatter checks
|
|
253
|
-
if (!lines[0]?.startsWith(
|
|
254
|
-
issues.push({ line: 1, message: `missing '${
|
|
253
|
+
if (!lines[0]?.startsWith(JOURNAL_HEADER_PREFIX)) {
|
|
254
|
+
issues.push({ line: 1, message: `missing '${JOURNAL_HEADER_PREFIX}<name>' header` });
|
|
255
255
|
}
|
|
256
256
|
for (const required of ["session_id:", "machine:", "started:"]) {
|
|
257
257
|
if (!lines.slice(0, 10).some((l) => l.startsWith(required))) {
|
|
@@ -310,17 +310,17 @@ export function lintScratch(content: string, byteCap = MAX_SCRATCH_BYTES): LintI
|
|
|
310
310
|
|
|
311
311
|
export function appendEntry(
|
|
312
312
|
instanceId: string,
|
|
313
|
-
category:
|
|
313
|
+
category: JournalCategory,
|
|
314
314
|
body: string,
|
|
315
|
-
):
|
|
315
|
+
): JournalDoc {
|
|
316
316
|
const hb = readHeartbeat(instanceId);
|
|
317
|
-
const path =
|
|
318
|
-
let doc:
|
|
317
|
+
const path = journalPath(instanceId);
|
|
318
|
+
let doc: JournalDoc;
|
|
319
319
|
if (existsSync(path)) {
|
|
320
|
-
doc =
|
|
320
|
+
doc = parseJournal(path, readFileSync(path, "utf8"));
|
|
321
321
|
} else {
|
|
322
322
|
// Seed `started` from the heartbeat's session start so cross-agent writes
|
|
323
|
-
// (`harn agents ping`) don't stamp the peer's
|
|
323
|
+
// (`harn agents ping`) don't stamp the peer's journal with our wall-clock.
|
|
324
324
|
const startedSeed = hb?.started_at ? formatChicago(new Date(hb.started_at)) : formatChicago();
|
|
325
325
|
doc = {
|
|
326
326
|
path,
|
|
@@ -337,7 +337,7 @@ export function appendEntry(
|
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
const now = new Date();
|
|
340
|
-
const entry:
|
|
340
|
+
const entry: JournalEntry = {
|
|
341
341
|
ts_iso: now.toISOString(),
|
|
342
342
|
ts_display: formatChicago(now),
|
|
343
343
|
category,
|
|
@@ -350,22 +350,22 @@ export function appendEntry(
|
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
// Prune from the tail until under cap.
|
|
353
|
-
let serialized =
|
|
353
|
+
let serialized = serializeJournal(doc);
|
|
354
354
|
let pruned = 0;
|
|
355
|
-
while (Buffer.byteLength(serialized, "utf8") >
|
|
355
|
+
while (Buffer.byteLength(serialized, "utf8") > MAX_JOURNAL_BYTES && doc.entries.length > 1) {
|
|
356
356
|
doc.entries.pop();
|
|
357
357
|
pruned++;
|
|
358
|
-
serialized =
|
|
358
|
+
serialized = serializeJournal(doc);
|
|
359
359
|
}
|
|
360
360
|
if (pruned > 0) {
|
|
361
|
-
const pruneEntry:
|
|
361
|
+
const pruneEntry: JournalEntry = {
|
|
362
362
|
ts_iso: new Date().toISOString(),
|
|
363
363
|
ts_display: formatChicago(),
|
|
364
364
|
category: "note",
|
|
365
|
-
body: `(auto-pruned ${pruned} oldest entries to stay under ${
|
|
365
|
+
body: `(auto-pruned ${pruned} oldest entries to stay under ${MAX_JOURNAL_BYTES}-byte cap)`,
|
|
366
366
|
};
|
|
367
367
|
doc.entries.unshift(pruneEntry);
|
|
368
|
-
serialized =
|
|
368
|
+
serialized = serializeJournal(doc);
|
|
369
369
|
}
|
|
370
370
|
doc.bytes = Buffer.byteLength(serialized, "utf8");
|
|
371
371
|
|
|
@@ -381,9 +381,9 @@ export function appendEntry(
|
|
|
381
381
|
// ─── Archive lifecycle ────────────────────────────────────────────────────
|
|
382
382
|
|
|
383
383
|
/** Move `<owner>.md` → `archived/<owner>-<ts>.md`. No-op if missing. Returns archive path (or null). */
|
|
384
|
-
export function
|
|
384
|
+
export function archiveJournal(instanceId: string): string | null {
|
|
385
385
|
assertSafeInstanceId(instanceId);
|
|
386
|
-
const src =
|
|
386
|
+
const src = journalPath(instanceId);
|
|
387
387
|
if (!existsSync(src)) return null;
|
|
388
388
|
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
389
389
|
const dest = resolveContainedFile(archiveDir(), `${instanceId}-${ts}.md`);
|
|
@@ -412,16 +412,16 @@ export function pruneArchives(days = ARCHIVE_RETENTION_DAYS): number {
|
|
|
412
412
|
return deleted;
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
-
/** Sweep `.harnery/
|
|
416
|
-
export function
|
|
417
|
-
const dir =
|
|
415
|
+
/** Sweep `.harnery/journal/<owner>.md` files whose corresponding heartbeat is gone. */
|
|
416
|
+
export function sweepOrphanJournals(): string[] {
|
|
417
|
+
const dir = journalDir();
|
|
418
418
|
const archived: string[] = [];
|
|
419
419
|
for (const f of readdirSync(dir)) {
|
|
420
420
|
if (!f.endsWith(".md")) continue;
|
|
421
421
|
const instanceId = f.replace(/\.md$/, "");
|
|
422
422
|
const hb = readHeartbeat(instanceId);
|
|
423
423
|
if (!hb) {
|
|
424
|
-
const dest =
|
|
424
|
+
const dest = archiveJournal(instanceId);
|
|
425
425
|
if (dest) archived.push(dest);
|
|
426
426
|
}
|
|
427
427
|
}
|
|
@@ -457,10 +457,10 @@ export function currentOwnerOrThrow(): string {
|
|
|
457
457
|
return owner;
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
-
export function
|
|
461
|
-
const path =
|
|
460
|
+
export function loadJournal(instanceId: string): JournalDoc | null {
|
|
461
|
+
const path = journalPath(instanceId);
|
|
462
462
|
if (!existsSync(path)) return null;
|
|
463
|
-
return
|
|
463
|
+
return parseJournal(path, readFileSync(path, "utf8"));
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
/** Resolve an agent name → instance_id by walking active heartbeats (case-insensitive). */
|
|
@@ -22,7 +22,7 @@ const POLICY_FIELDS = new Set([
|
|
|
22
22
|
"name",
|
|
23
23
|
"max_cost_usd",
|
|
24
24
|
"unknown_cost",
|
|
25
|
-
"
|
|
25
|
+
"allowed_adapters",
|
|
26
26
|
"allowed_models",
|
|
27
27
|
"allowed_paths",
|
|
28
28
|
"network",
|
|
@@ -59,7 +59,7 @@ export function normalizePolicy(
|
|
|
59
59
|
name: boundedString(input.name ?? "workflow policy", "policy name", MAX_NAME),
|
|
60
60
|
max_cost_usd: optionalMoney(input.max_cost_usd, "max_cost_usd"),
|
|
61
61
|
unknown_cost: enumValue(input.unknown_cost ?? "deny", ["ask", "deny"], "unknown_cost"),
|
|
62
|
-
|
|
62
|
+
allowed_adapters: optionalStringList(input.allowed_adapters, "allowed_adapters"),
|
|
63
63
|
allowed_models: optionalStringList(input.allowed_models, "allowed_models"),
|
|
64
64
|
allowed_paths: optionalPathList(input.allowed_paths, baseDir),
|
|
65
65
|
network: enumValue(input.network ?? "deny", VERDICTS, "network"),
|
|
@@ -83,12 +83,12 @@ export function evaluatePolicy(
|
|
|
83
83
|
rules.push({ code, verdict, reason });
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
-
if (policy.
|
|
87
|
-
if (!request.
|
|
86
|
+
if (policy.allowed_adapters && request.phase === "dispatch") {
|
|
87
|
+
if (!request.adapter || !policy.allowed_adapters.includes(request.adapter)) {
|
|
88
88
|
add(
|
|
89
|
-
"
|
|
89
|
+
"adapter_not_allowed",
|
|
90
90
|
"deny",
|
|
91
|
-
`
|
|
91
|
+
`adapter ${JSON.stringify(request.adapter ?? "unknown")} is not allowed`,
|
|
92
92
|
);
|
|
93
93
|
}
|
|
94
94
|
}
|
|
@@ -172,7 +172,7 @@ export function evaluatePolicy(
|
|
|
172
172
|
};
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
/** Bound and normalize the receipt-safe subset before it reaches a
|
|
175
|
+
/** Bound and normalize the receipt-safe subset before it reaches a transcript or proof. */
|
|
176
176
|
export function summarizePolicyRequest(input: PolicyRequest): PolicyRequestSummary {
|
|
177
177
|
if (!isRecord(input)) throw new Error("policy request must be an object");
|
|
178
178
|
const phase = enumValue(input.phase, ["dispatch", "external_mutation"], "policy phase");
|
|
@@ -186,7 +186,7 @@ export function summarizePolicyRequest(input: PolicyRequest): PolicyRequestSumma
|
|
|
186
186
|
phase,
|
|
187
187
|
action: boundedString(input.action, "policy action", MAX_FIELD),
|
|
188
188
|
path: optionalBounded(input.path, "policy path"),
|
|
189
|
-
|
|
189
|
+
adapter: optionalBounded(input.adapter, "policy adapter"),
|
|
190
190
|
model: optionalBounded(input.model, "policy model"),
|
|
191
191
|
effort: optionalBounded(input.effort, "policy effort"),
|
|
192
192
|
max_attempts: optionalWholeNumber(input.max_attempts, "policy max_attempts", 1),
|
package/src/core/policy/types.ts
CHANGED
|
@@ -12,7 +12,7 @@ export interface PolicySpec {
|
|
|
12
12
|
max_cost_usd?: number;
|
|
13
13
|
/** Applied when a cost ceiling exists but the host cannot price a dispatch. */
|
|
14
14
|
unknown_cost?: Exclude<PolicyVerdict, "allow">;
|
|
15
|
-
|
|
15
|
+
allowed_adapters?: readonly string[];
|
|
16
16
|
allowed_models?: readonly string[];
|
|
17
17
|
/** Absolute paths, or paths relative to the policy file. */
|
|
18
18
|
allowed_paths?: readonly string[];
|
|
@@ -27,7 +27,7 @@ export interface NormalizedPolicy {
|
|
|
27
27
|
name: string;
|
|
28
28
|
max_cost_usd?: number;
|
|
29
29
|
unknown_cost: Exclude<PolicyVerdict, "allow">;
|
|
30
|
-
|
|
30
|
+
allowed_adapters?: readonly string[];
|
|
31
31
|
allowed_models?: readonly string[];
|
|
32
32
|
allowed_paths?: readonly string[];
|
|
33
33
|
network: PolicyVerdict;
|
|
@@ -39,7 +39,7 @@ export interface PolicyRequest {
|
|
|
39
39
|
phase: PolicyPhase;
|
|
40
40
|
action: string;
|
|
41
41
|
path?: string;
|
|
42
|
-
|
|
42
|
+
adapter?: string;
|
|
43
43
|
model?: string;
|
|
44
44
|
effort?: string;
|
|
45
45
|
max_attempts?: number;
|
package/src/core/work/state.ts
CHANGED
|
@@ -16,9 +16,9 @@ import { hostname } from "node:os";
|
|
|
16
16
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
17
17
|
import { readWorkflowApproval } from "../workflow/approvals.ts";
|
|
18
18
|
import { stableDigest } from "../workflow/durable-record.ts";
|
|
19
|
-
import { WORKFLOW_JOURNAL_EVENT_BYTES, workflowJournalPath } from "../workflow/journal.ts";
|
|
20
19
|
import { readWorkflowProof } from "../workflow/proof.ts";
|
|
21
20
|
import { readWorkflowRunManifest, workflowScriptDigest } from "../workflow/run-state.ts";
|
|
21
|
+
import { WORKFLOW_TRANSCRIPT_EVENT_BYTES, workflowTranscriptPath } from "../workflow/transcript.ts";
|
|
22
22
|
import { isWorkspaceBoundExecutionEvidence } from "../workflow/workspaces/validate.ts";
|
|
23
23
|
|
|
24
24
|
export const WORK_INTENT_SCHEMA_VERSION = 1 as const;
|
|
@@ -42,7 +42,7 @@ const FOREIGN_LEASE_STALE_MS = 24 * 60 * 60 * 1_000;
|
|
|
42
42
|
/** Default ceiling on consecutive uncharged attempts (ADR 0046). Kept low: each
|
|
43
43
|
* one is a real vendor round-trip, so a handful gives a transient outage room
|
|
44
44
|
* to recover before the item stops and names the outside service. There is no
|
|
45
|
-
* backoff between them beyond the cadence of the
|
|
45
|
+
* backoff between them beyond the cadence of the governor and the vendor's own
|
|
46
46
|
* responses, which is why the bound stays small. */
|
|
47
47
|
const DEFAULT_MAX_UNCHARGED_ATTEMPTS = 3;
|
|
48
48
|
|
|
@@ -136,14 +136,17 @@ export interface WorkAttempt {
|
|
|
136
136
|
run_id: string;
|
|
137
137
|
started_at: string;
|
|
138
138
|
trigger?: WorkAttemptTrigger;
|
|
139
|
-
status: "running" | "parked" | "succeeded" | "failed" | "lost" | "
|
|
139
|
+
status: "running" | "parked" | "succeeded" | "failed" | "lost" | "transcript_unreadable";
|
|
140
140
|
approval_id?: string;
|
|
141
141
|
proof_path?: string;
|
|
142
|
-
|
|
142
|
+
transcript_error?: string;
|
|
143
143
|
/** Why this failed attempt was uninformative about the work (ADR 0046), read
|
|
144
144
|
* from the proof's run.class. Absent ⇒ the attempt is charged, exactly as
|
|
145
145
|
* before ADR 0046 (which is also how a proof without a class reads). */
|
|
146
|
-
uncharged?: "environment" | "upstream";
|
|
146
|
+
uncharged?: "environment" | "upstream" | "decision";
|
|
147
|
+
/** Docket id this attempt stopped on, when uncharged is "decision" and the
|
|
148
|
+
* script named one. Lets the projection point at the question itself. */
|
|
149
|
+
blocked_on?: string;
|
|
147
150
|
}
|
|
148
151
|
|
|
149
152
|
export interface WorkProjection {
|
|
@@ -165,6 +168,11 @@ export interface WorkProjection {
|
|
|
165
168
|
latest_run_id?: string;
|
|
166
169
|
approval_id?: string;
|
|
167
170
|
proof_path?: string;
|
|
171
|
+
/** Set when this item stopped because a human must rule. The value is the
|
|
172
|
+
* docket id when the script named one, else the empty string — present either
|
|
173
|
+
* way, so a reader can distinguish "waiting on a person" from every other
|
|
174
|
+
* terminal block without parsing the reason prose. */
|
|
175
|
+
blocked_on_decision?: string;
|
|
168
176
|
updated_at: string;
|
|
169
177
|
}
|
|
170
178
|
|
|
@@ -500,12 +508,12 @@ function deriveWorkProjection(
|
|
|
500
508
|
};
|
|
501
509
|
}
|
|
502
510
|
const attemptsRemaining = intent.max_attempts - chargedAttempts;
|
|
503
|
-
if (latest.status === "
|
|
511
|
+
if (latest.status === "transcript_unreadable") {
|
|
504
512
|
return {
|
|
505
513
|
...base,
|
|
506
514
|
state: "blocked",
|
|
507
|
-
reason: `workflow attempt ${latest.number}
|
|
508
|
-
latest.
|
|
515
|
+
reason: `workflow attempt ${latest.number} transcript is unreadable: ${
|
|
516
|
+
latest.transcript_error ?? "unknown transcript read error"
|
|
509
517
|
}`,
|
|
510
518
|
next_action: attemptsRemaining > 0 ? "retry" : "none",
|
|
511
519
|
};
|
|
@@ -516,7 +524,7 @@ function deriveWorkProjection(
|
|
|
516
524
|
if (latest.status === "failed" && latest.uncharged === "environment") {
|
|
517
525
|
// A missing precondition. The operator chose to STOP the item immediately
|
|
518
526
|
// rather than retry an unchanged environment (ADR 0046); next_action "none"
|
|
519
|
-
// stops the
|
|
527
|
+
// stops the governor. A human who fixes the environment can still force a
|
|
520
528
|
// retry — the attempt was uncharged, so the budget is intact.
|
|
521
529
|
return {
|
|
522
530
|
...base,
|
|
@@ -525,6 +533,20 @@ function deriveWorkProjection(
|
|
|
525
533
|
next_action: "none",
|
|
526
534
|
};
|
|
527
535
|
}
|
|
536
|
+
if (latest.status === "failed" && latest.uncharged === "decision") {
|
|
537
|
+
// The script did its job and the answer was "a person has to settle this".
|
|
538
|
+
// Terminal for the same reason "environment" is terminal — retrying cannot
|
|
539
|
+
// change the blocker — but the fix is a ruling, not a repair, so the reason
|
|
540
|
+
// names the decision instead of a precondition. Uncharged, so once the
|
|
541
|
+
// decision lands the item can be retried with its budget intact.
|
|
542
|
+
return {
|
|
543
|
+
...base,
|
|
544
|
+
state: "blocked",
|
|
545
|
+
reason: decisionBlockedReason(latest),
|
|
546
|
+
next_action: "none",
|
|
547
|
+
blocked_on_decision: latest.blocked_on ?? "",
|
|
548
|
+
};
|
|
549
|
+
}
|
|
528
550
|
if (latest.status === "failed" && latest.uncharged === "upstream") {
|
|
529
551
|
// Count trailing consecutive uncharged attempts in the current window. The
|
|
530
552
|
// bound is the only brake on an outage that never ends, so at the limit the
|
|
@@ -574,7 +596,7 @@ function unchargedProofError(attempt: WorkAttempt): string | undefined {
|
|
|
574
596
|
const run = proof.run;
|
|
575
597
|
const error =
|
|
576
598
|
run && typeof run === "object" ? (run as Record<string, unknown>).error : undefined;
|
|
577
|
-
return typeof error === "string" && error.trim() ?
|
|
599
|
+
return typeof error === "string" && error.trim() ? boundedTranscriptError(error) : undefined;
|
|
578
600
|
} catch {
|
|
579
601
|
return undefined;
|
|
580
602
|
}
|
|
@@ -591,6 +613,21 @@ function upstreamReason(attempt: WorkAttempt): string {
|
|
|
591
613
|
return unchargedProofError(attempt) ?? "the vendor was reached and refused";
|
|
592
614
|
}
|
|
593
615
|
|
|
616
|
+
/** Operator-facing reason for a run that stopped on a human. Reads the script's
|
|
617
|
+
* own sentence out of the proof and drops the WorkflowBlockedError prefix the
|
|
618
|
+
* engine added, so the projection says the thing once rather than twice. */
|
|
619
|
+
function decisionBlockedReason(attempt: WorkAttempt): string {
|
|
620
|
+
const raw = unchargedProofError(attempt);
|
|
621
|
+
const detail = raw
|
|
622
|
+
?.replace(/^blocked on decision \S+: /, "")
|
|
623
|
+
.replace(/^blocked pending a human decision: /, "")
|
|
624
|
+
.trim();
|
|
625
|
+
const named = attempt.blocked_on ? ` (decision ${attempt.blocked_on})` : "";
|
|
626
|
+
return detail
|
|
627
|
+
? `a human must rule before this can proceed: ${detail}${named}`
|
|
628
|
+
: `a human must rule before this can proceed${named}`;
|
|
629
|
+
}
|
|
630
|
+
|
|
594
631
|
function inspectAttempt(
|
|
595
632
|
coordRoot: string,
|
|
596
633
|
event: WorkEvent,
|
|
@@ -659,24 +696,29 @@ function inspectAttempt(
|
|
|
659
696
|
// failed attempt: a succeeded run never carries a class.
|
|
660
697
|
if (
|
|
661
698
|
attempt.status === "failed" &&
|
|
662
|
-
(proof.run.class === "environment" ||
|
|
699
|
+
(proof.run.class === "environment" ||
|
|
700
|
+
proof.run.class === "upstream" ||
|
|
701
|
+
proof.run.class === "decision")
|
|
663
702
|
) {
|
|
664
703
|
attempt.uncharged = proof.run.class;
|
|
704
|
+
if (proof.run.class === "decision" && typeof proof.run.decision_id === "string") {
|
|
705
|
+
attempt.blocked_on = proof.run.decision_id;
|
|
706
|
+
}
|
|
665
707
|
}
|
|
666
708
|
return attempt;
|
|
667
709
|
}
|
|
668
|
-
const
|
|
669
|
-
if (existsSync(
|
|
710
|
+
const transcriptPath = workflowTranscriptPath(coordRoot, runId);
|
|
711
|
+
if (existsSync(transcriptPath)) {
|
|
670
712
|
let parked: string | undefined;
|
|
671
713
|
let resumed = false;
|
|
672
714
|
try {
|
|
673
715
|
for (const line of readBoundedLines(
|
|
674
|
-
|
|
716
|
+
transcriptPath,
|
|
675
717
|
MAX_EVENTS_BYTES,
|
|
676
|
-
|
|
677
|
-
"workflow
|
|
718
|
+
WORKFLOW_TRANSCRIPT_EVENT_BYTES,
|
|
719
|
+
"workflow transcript",
|
|
678
720
|
)) {
|
|
679
|
-
const value = parseObject(line, `workflow run ${runId}
|
|
721
|
+
const value = parseObject(line, `workflow run ${runId} transcript`);
|
|
680
722
|
if (value.event === "run.parked" && typeof value.approval_id === "string") {
|
|
681
723
|
parked = value.approval_id;
|
|
682
724
|
resumed = false;
|
|
@@ -692,8 +734,8 @@ function inspectAttempt(
|
|
|
692
734
|
if (workflowResumeLeaseIsLive(coordRoot, runId)) {
|
|
693
735
|
attempt.status = "running";
|
|
694
736
|
} else {
|
|
695
|
-
attempt.status = "
|
|
696
|
-
attempt.
|
|
737
|
+
attempt.status = "transcript_unreadable";
|
|
738
|
+
attempt.transcript_error = boundedTranscriptError((error as Error).message);
|
|
697
739
|
}
|
|
698
740
|
return attempt;
|
|
699
741
|
}
|
|
@@ -1171,13 +1213,13 @@ export function acquireWorkLease(coordRoot: string, workId: string): () => void
|
|
|
1171
1213
|
return acquireWorkFileLease(coordRoot, workId, "lease.json", "is already active");
|
|
1172
1214
|
}
|
|
1173
1215
|
|
|
1174
|
-
/** @internal Work
|
|
1216
|
+
/** @internal Work transcript mutation seam. */
|
|
1175
1217
|
export function acquireWorkEventLease(coordRoot: string, workId: string): () => void {
|
|
1176
1218
|
return acquireWorkFileLease(
|
|
1177
1219
|
coordRoot,
|
|
1178
1220
|
workId,
|
|
1179
1221
|
"events.lease.json",
|
|
1180
|
-
"event
|
|
1222
|
+
"event transcript is already active",
|
|
1181
1223
|
);
|
|
1182
1224
|
}
|
|
1183
1225
|
|
|
@@ -1308,8 +1350,8 @@ function readBoundedLines(
|
|
|
1308
1350
|
return lines;
|
|
1309
1351
|
}
|
|
1310
1352
|
|
|
1311
|
-
function
|
|
1312
|
-
const normalized = message.trim() || "unknown
|
|
1353
|
+
function boundedTranscriptError(message: string): string {
|
|
1354
|
+
const normalized = message.trim() || "unknown transcript read error";
|
|
1313
1355
|
return normalized.length > MAX_REASON ? normalized.slice(0, MAX_REASON) : normalized;
|
|
1314
1356
|
}
|
|
1315
1357
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-adapter CLI metadata: binary names plus install/login hints, shared by
|
|
3
|
+
* the spawn adapters (a not-found error should say how to fix it, not just
|
|
4
|
+
* that it happened) and `harn doctor`'s workflow-adapter checks.
|
|
5
|
+
*
|
|
6
|
+
* Install commands are the vendors' official one-liners; they drift rarely
|
|
7
|
+
* but they do drift — keep this module the single place they live.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { BUILTIN_ADAPTER_PROFILES } from "../adapters/profiles.ts";
|
|
11
|
+
import type { AdapterName } from "./types.ts";
|
|
12
|
+
|
|
13
|
+
export const ADAPTER_BINARIES: Record<string, string> = Object.fromEntries(
|
|
14
|
+
Object.values(BUILTIN_ADAPTER_PROFILES).map((profile) => [profile.id, profile.binary]),
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
export const ADAPTER_INSTALL_HINTS: Record<string, string> = Object.fromEntries(
|
|
18
|
+
Object.values(BUILTIN_ADAPTER_PROFILES).map((profile) => [profile.id, profile.installHint]),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
/** How to authenticate each CLI with a subscription login (the billing
|
|
22
|
+
* default — see billing.ts). */
|
|
23
|
+
export const ADAPTER_LOGIN_HINTS: Record<string, string> = Object.fromEntries(
|
|
24
|
+
Object.values(BUILTIN_ADAPTER_PROFILES).map((profile) => [profile.id, profile.loginHint]),
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
/** One-line "it's missing, here's the fix" string for spawn adapters. */
|
|
28
|
+
export function notFoundError(adapter: AdapterName): string {
|
|
29
|
+
const binary = ADAPTER_BINARIES[adapter] ?? adapter;
|
|
30
|
+
const install = ADAPTER_INSTALL_HINTS[adapter] ?? "install the adapter CLI";
|
|
31
|
+
const login = ADAPTER_LOGIN_HINTS[adapter] ?? "authenticate the adapter CLI";
|
|
32
|
+
return `${binary} CLI not found on PATH; ` + `install: ${install} then authenticate: ${login}`;
|
|
33
|
+
}
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "node:fs";
|
|
13
13
|
import { dirname, join } from "node:path";
|
|
14
14
|
import type { PolicyEvaluation, PolicyRequestSummary, PolicyVerdict } from "../policy/index.ts";
|
|
15
|
-
import {
|
|
15
|
+
import { appendWorkflowTranscriptEvent } from "./transcript.ts";
|
|
16
16
|
|
|
17
17
|
export const WORKFLOW_APPROVAL_SCHEMA_VERSION = 1 as const;
|
|
18
18
|
|
|
@@ -148,7 +148,7 @@ export function resolveWorkflowApproval(input: ResolveWorkflowApprovalInput): {
|
|
|
148
148
|
`approval ${input.approvalId} is already ${resolved.status}; conflicting ${input.verdict === "allow" ? "approval" : "denial"} refused`,
|
|
149
149
|
);
|
|
150
150
|
}
|
|
151
|
-
if (applied)
|
|
151
|
+
if (applied) appendResolutionTranscript(input.coordRoot, resolved);
|
|
152
152
|
return { approval: resolved, applied };
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -214,16 +214,16 @@ export function assertWorkflowRunId(runId: string): void {
|
|
|
214
214
|
assertRunId(runId);
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
function
|
|
218
|
-
const
|
|
217
|
+
function appendResolutionTranscript(coordRoot: string, approval: WorkflowApproval): void {
|
|
218
|
+
const transcriptPath = join(
|
|
219
219
|
coordRoot,
|
|
220
220
|
".harnery",
|
|
221
221
|
"workflows",
|
|
222
222
|
approval.request.run_id,
|
|
223
|
-
"
|
|
223
|
+
"transcript.jsonl",
|
|
224
224
|
);
|
|
225
|
-
if (!existsSync(
|
|
226
|
-
|
|
225
|
+
if (!existsSync(transcriptPath) || !approval.decision) return;
|
|
226
|
+
appendWorkflowTranscriptEvent(coordRoot, approval.request.run_id, "approval.resolved", {
|
|
227
227
|
ts: approval.decision.decided_at,
|
|
228
228
|
stage: "",
|
|
229
229
|
approval_id: approval.request.id,
|