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
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* the canonical stream. The web image feed (`/images`) groups those events by
|
|
10
10
|
* hash and streams them live over the existing SSE infra.
|
|
11
11
|
*
|
|
12
|
-
* Why this lives at the hook layer: it's the single
|
|
12
|
+
* Why this lives at the hook layer: it's the single adapter-agnostic chokepoint
|
|
13
13
|
* that sees every tool call across Claude Code / Cursor / Codex with the full
|
|
14
14
|
* `tool_input` (file paths) and `tool_response`. No per-command code needed.
|
|
15
15
|
*
|
|
@@ -29,9 +29,9 @@ import {
|
|
|
29
29
|
writeFileSync,
|
|
30
30
|
} from "node:fs";
|
|
31
31
|
import { isAbsolute, join, resolve } from "node:path";
|
|
32
|
+
import type { ParsedPayload } from "../adapter/parse.ts";
|
|
32
33
|
import { emit } from "../events/emit.ts";
|
|
33
|
-
import type {
|
|
34
|
-
import type { ParsedPayload } from "../harness/parse.ts";
|
|
34
|
+
import type { Adapter } from "../events/schema.ts";
|
|
35
35
|
|
|
36
36
|
/** Raster + vector image extensions the feed accepts. PDF is intentionally
|
|
37
37
|
* excluded: book renders aren't an "image feed" and don't thumbnail inline. */
|
|
@@ -59,7 +59,7 @@ export interface CaptureContext {
|
|
|
59
59
|
payload: ParsedPayload | null;
|
|
60
60
|
instanceId: string;
|
|
61
61
|
sessionId: string;
|
|
62
|
-
|
|
62
|
+
adapter: Adapter;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
interface Candidate {
|
|
@@ -95,7 +95,7 @@ export function captureImages(coordRoot: string, ctx: CaptureContext): void {
|
|
|
95
95
|
event_type: "image.captured",
|
|
96
96
|
instance_id: ctx.instanceId,
|
|
97
97
|
session_id: ctx.sessionId,
|
|
98
|
-
|
|
98
|
+
adapter: ctx.adapter,
|
|
99
99
|
data: {
|
|
100
100
|
hash: captured.hash,
|
|
101
101
|
ext: captured.ext,
|
|
@@ -204,7 +204,7 @@ function captureOne(imagesDir: string, cand: Candidate): CapturedBlob | null {
|
|
|
204
204
|
/**
|
|
205
205
|
* Prune `.harnery/images/` past a size cap (default 2 GB) and an age cap
|
|
206
206
|
* (default 30 days), oldest-mtime-first. Fired on session.start next to
|
|
207
|
-
*
|
|
207
|
+
* journalJanitor. Pure-fs, fail-soft. Orphaned `image.captured` events whose
|
|
208
208
|
* blob was pruned render as an "expired" placeholder in the gallery.
|
|
209
209
|
*/
|
|
210
210
|
export function imageJanitor(coordRoot: string): void {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Non-coordination side effects fired from the normalized `agent-hook` handlers.
|
|
3
3
|
*
|
|
4
|
-
* These are DELIBERATELY outside the agent-coord path: sounds,
|
|
4
|
+
* These are DELIBERATELY outside the agent-coord path: sounds, journal
|
|
5
5
|
* lifecycle, session telemetry, presence detection. They used to live in
|
|
6
|
-
* per-
|
|
6
|
+
* per-adapter bash adapters. Per the directive ("use the normalized hooks; if
|
|
7
7
|
* they aren't coordination, implement them outside of coordination") they move
|
|
8
|
-
* here so the
|
|
8
|
+
* here so the adapter configs reference only `agent-hook`, while staying a
|
|
9
9
|
* distinct concern from the coordination logic in cli.ts / agent-coord.
|
|
10
10
|
*
|
|
11
11
|
* Everything here is best-effort: it never throws and never blocks the hook on a
|
|
@@ -17,6 +17,7 @@ import { existsSync, readdirSync, rmSync } from "node:fs";
|
|
|
17
17
|
import os from "node:os";
|
|
18
18
|
import { join } from "node:path";
|
|
19
19
|
import { applyDetection } from "../../../lib/presence.ts";
|
|
20
|
+
import { coordBinPath } from "../../agents/coord-bin.ts";
|
|
20
21
|
|
|
21
22
|
export type { CaptureContext } from "./image-capture.ts";
|
|
22
23
|
export { captureImages, imageJanitor } from "./image-capture.ts";
|
|
@@ -62,16 +63,15 @@ export function soundForEvent(eventName: string): { sound: string; maxPlays: num
|
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
function harnBin(repoRoot: string): string | null {
|
|
65
|
-
|
|
66
|
-
return existsSync(bin) ? bin : null;
|
|
66
|
+
return coordBinPath("harn", repoRoot);
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
/** Prune stale
|
|
70
|
-
export function
|
|
69
|
+
/** Prune stale journal archives + sweep orphans (global, fast). Fire-and-forget. */
|
|
70
|
+
export function journalJanitor(repoRoot: string): void {
|
|
71
71
|
try {
|
|
72
72
|
const bin = harnBin(repoRoot);
|
|
73
73
|
if (!bin) return;
|
|
74
|
-
spawnSync("bash", [bin, "
|
|
74
|
+
spawnSync("bash", [bin, "journal", "janitor", "--quiet"], {
|
|
75
75
|
env: { ...process.env, HARNERY_OUTPUT_SESSION_TEE: "0" },
|
|
76
76
|
timeout: 5000,
|
|
77
77
|
stdio: "ignore",
|
|
@@ -82,15 +82,15 @@ export function scratchJanitor(repoRoot: string): void {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
|
-
* Return the one-line
|
|
85
|
+
* Return the one-line journal recovery cue for SessionStart, or "" if none.
|
|
86
86
|
* The caller merges it into the session-start additionalContext (it used to be
|
|
87
|
-
* a standalone additionalContext emission from the previous
|
|
87
|
+
* a standalone additionalContext emission from the previous journal-on-start adapter).
|
|
88
88
|
*/
|
|
89
|
-
export function
|
|
89
|
+
export function journalRecoveryCue(repoRoot: string): string {
|
|
90
90
|
try {
|
|
91
91
|
const bin = harnBin(repoRoot);
|
|
92
92
|
if (!bin) return "";
|
|
93
|
-
const r = spawnSync("bash", [bin, "
|
|
93
|
+
const r = spawnSync("bash", [bin, "journal", "recovery-cue"], {
|
|
94
94
|
env: { ...process.env, HARNERY_OUTPUT_SESSION_TEE: "0" },
|
|
95
95
|
timeout: 5000,
|
|
96
96
|
encoding: "utf8",
|
|
@@ -101,12 +101,12 @@ export function scratchRecoveryCue(repoRoot: string): string {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
/** Archive the ending agent's
|
|
105
|
-
export function
|
|
104
|
+
/** Archive the ending agent's journal. Fire-and-forget. */
|
|
105
|
+
export function journalArchive(repoRoot: string, owner: string): void {
|
|
106
106
|
try {
|
|
107
107
|
const bin = harnBin(repoRoot);
|
|
108
108
|
if (!bin || !owner) return;
|
|
109
|
-
spawnSync("bash", [bin, "
|
|
109
|
+
spawnSync("bash", [bin, "journal", "archive", "--owner", owner], {
|
|
110
110
|
env: { ...process.env, HARNERY_OUTPUT_SESSION_TEE: "0" },
|
|
111
111
|
timeout: 5000,
|
|
112
112
|
stdio: "ignore",
|
|
@@ -120,13 +120,13 @@ export function scratchArchive(repoRoot: string, owner: string): void {
|
|
|
120
120
|
* Fire the optional host session-sync extension on turn stop / session end.
|
|
121
121
|
* harnery core has no session-telemetry sink of its own; a host that wants one
|
|
122
122
|
* drops an executable at
|
|
123
|
-
* `scripts/hooks/
|
|
123
|
+
* `scripts/hooks/adapter/claude_code/extensions/session-sync.sh` under the coord
|
|
124
124
|
* root, and core runs it detached + unref'd so a slow sink never blocks the
|
|
125
125
|
* hook. `force` arrives as argv $1 ("1" on session end, "0" on turn stop) so the
|
|
126
126
|
* host can rate-limit the stop path and force-flush on end. No-op when the
|
|
127
127
|
* script is absent, so a plain public install spawns nothing. Mirrors
|
|
128
128
|
* `runTurnSummary`'s extension-script pattern. Caller gates to the claude-code
|
|
129
|
-
*
|
|
129
|
+
* adapter.
|
|
130
130
|
*/
|
|
131
131
|
export function runSessionSyncExtension(repoRoot: string, force: boolean): void {
|
|
132
132
|
try {
|
|
@@ -134,7 +134,7 @@ export function runSessionSyncExtension(repoRoot: string, force: boolean): void
|
|
|
134
134
|
repoRoot,
|
|
135
135
|
"scripts",
|
|
136
136
|
"hooks",
|
|
137
|
-
"
|
|
137
|
+
"adapter",
|
|
138
138
|
"claude_code",
|
|
139
139
|
"extensions",
|
|
140
140
|
"session-sync.sh",
|
|
@@ -169,7 +169,7 @@ export function runTurnSummary(
|
|
|
169
169
|
repoRoot,
|
|
170
170
|
"scripts",
|
|
171
171
|
"hooks",
|
|
172
|
-
"
|
|
172
|
+
"adapter",
|
|
173
173
|
"claude_code",
|
|
174
174
|
"extensions",
|
|
175
175
|
"turn-summary.sh",
|
|
@@ -2,9 +2,9 @@ import { appendFileSync, closeSync, mkdirSync, openSync } from "node:fs";
|
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { maybeRotateEventStream } from "./rotate.ts";
|
|
4
4
|
import {
|
|
5
|
+
type Adapter,
|
|
5
6
|
type EventEnvelope,
|
|
6
7
|
type EventType,
|
|
7
|
-
type Harness,
|
|
8
8
|
SCHEMA_VERSION,
|
|
9
9
|
type Source,
|
|
10
10
|
} from "./schema.ts";
|
|
@@ -19,7 +19,7 @@ export interface EmitInput<TType extends EventType, TData> {
|
|
|
19
19
|
event_type: TType;
|
|
20
20
|
instance_id: string;
|
|
21
21
|
session_id: string;
|
|
22
|
-
|
|
22
|
+
adapter: Adapter;
|
|
23
23
|
source?: Source;
|
|
24
24
|
parent_session_id?: string;
|
|
25
25
|
turn_id?: string;
|
|
@@ -45,7 +45,7 @@ export function buildEnvelope<TType extends EventType, TData>(
|
|
|
45
45
|
parent_session_id: input.parent_session_id,
|
|
46
46
|
turn_id: input.turn_id,
|
|
47
47
|
parent_turn_id: input.parent_turn_id,
|
|
48
|
-
|
|
48
|
+
adapter: input.adapter,
|
|
49
49
|
source: input.source ?? "agent-hooks",
|
|
50
50
|
data: input.data,
|
|
51
51
|
};
|
|
@@ -63,7 +63,7 @@ function resolveRollBytes(): number {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
/** `YYYY-MM-DD` (UTC) from a millisecond timestamp. Uses the file's own mtime
|
|
66
|
-
* rather than `Date.now()` so it's deterministic and independent of the
|
|
66
|
+
* rather than `Date.now()` so it's deterministic and independent of the adapter
|
|
67
67
|
* runtime's clock surface. */
|
|
68
68
|
function utcDateStamp(mtimeMs: number): string {
|
|
69
69
|
const d = new Date(mtimeMs);
|
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
|
|
13
13
|
export const SCHEMA_VERSION = 1 as const;
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
/** The adapters harnery ships first-party hook wiring for. The registry's open
|
|
16
|
+
* `AdapterId` covers any adapter a host registers; this is the closed set, and
|
|
17
|
+
* it is declared exactly once. Re-exported by the two event modules that used
|
|
18
|
+
* to keep their own byte-identical copy. */
|
|
19
|
+
export type Adapter = "claude-code" | "cursor" | "codex";
|
|
16
20
|
|
|
17
21
|
export type Source = "agent-hooks" | "agent-coord" | "user" | "system";
|
|
18
22
|
|
|
@@ -28,11 +32,11 @@ export interface EventEnvelope<TType extends string, TData> {
|
|
|
28
32
|
event_type: TType;
|
|
29
33
|
ts: string; // ISO-8601 with milliseconds
|
|
30
34
|
instance_id: string; // resolved by agent-hooks
|
|
31
|
-
session_id: string; //
|
|
35
|
+
session_id: string; // adapter-level session
|
|
32
36
|
parent_session_id?: string; // present iff event is from a subagent
|
|
33
37
|
turn_id?: string; // present when event is bound to an assistant turn
|
|
34
38
|
parent_turn_id?: string; // present iff this turn is nested under another
|
|
35
|
-
|
|
39
|
+
adapter: Adapter;
|
|
36
40
|
source: Source;
|
|
37
41
|
data: TData;
|
|
38
42
|
}
|
|
@@ -48,9 +52,13 @@ export type SessionStart = EventEnvelope<
|
|
|
48
52
|
model?: string;
|
|
49
53
|
pid: number;
|
|
50
54
|
/** Present iff this session is a `workflow run` child: the run id whose
|
|
51
|
-
*
|
|
55
|
+
* transcript owns it (child env HARNERY_WORKFLOW_RUN_ID). Optional-field
|
|
52
56
|
* addition per the schema evolution rules (minor bump). */
|
|
53
57
|
workflow_run_id?: string;
|
|
58
|
+
/** Which agent row of that run this session is running (`a1`, `a2`, …), from
|
|
59
|
+
* child env HARNERY_WORKFLOW_AGENT_ID. Lets a dashboard attribute in-flight
|
|
60
|
+
* child activity to one agent instead of only to the run. */
|
|
61
|
+
workflow_agent_id?: string;
|
|
54
62
|
}
|
|
55
63
|
>;
|
|
56
64
|
|
|
@@ -288,8 +296,8 @@ export type StateStatusChecked = EventEnvelope<
|
|
|
288
296
|
}
|
|
289
297
|
>;
|
|
290
298
|
|
|
291
|
-
export type
|
|
292
|
-
"state.
|
|
299
|
+
export type StateJournalAppend = EventEnvelope<
|
|
300
|
+
"state.journal_append",
|
|
293
301
|
{
|
|
294
302
|
category: "note" | "plan" | "decision" | "blocker" | "question" | "done" | "handoff";
|
|
295
303
|
body_summary: string;
|
|
@@ -470,7 +478,7 @@ export type Event =
|
|
|
470
478
|
| ClaimConflict
|
|
471
479
|
| StateTaskSet
|
|
472
480
|
| StateStatusChecked
|
|
473
|
-
|
|
|
481
|
+
| StateJournalAppend
|
|
474
482
|
| StatePresenceChange
|
|
475
483
|
| StateHeartbeat
|
|
476
484
|
| IdentityAssumed
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Canonicalize a write-tool target path for the claim guard.
|
|
3
3
|
*
|
|
4
4
|
* Returns the monorepo-relative path, or `null` when the target lies OUTSIDE the
|
|
5
|
-
* repo (an absolute path not under coordRoot, e.g. a `/tmp`
|
|
5
|
+
* repo (an absolute path not under coordRoot, e.g. a `/tmp` journal or other
|
|
6
6
|
* session-temp file).
|
|
7
7
|
*
|
|
8
8
|
* The claim system is intentionally repo-scoped: it coordinates monorepo files,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* them is right on two counts. First, it keeps non-repo paths out of a
|
|
11
11
|
* heartbeat's `files_touched`. Second, the ordering rule compares raw path
|
|
12
12
|
* strings, and an absolute `/tmp/…` sorts before every repo-relative path
|
|
13
|
-
* (`/` = 0x2F < any letter), so without this a
|
|
13
|
+
* (`/` = 0x2F < any letter), so without this a journal write would spuriously
|
|
14
14
|
* "block" a legitimately-held repo file. Returning null keeps such paths out of
|
|
15
15
|
* the claim system entirely.
|
|
16
16
|
*
|
package/src/core/hooks/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* the heartbeat pid-map row should be keyed to, so the agent's later shell
|
|
4
4
|
* tool calls (which ppid-walk up to find it) resolve their own identity.
|
|
5
5
|
*
|
|
6
|
-
* Split out of cli.ts's `
|
|
6
|
+
* Split out of cli.ts's `findAdapterAnchorPid` so the comm-matching logic is
|
|
7
7
|
* unit-testable against the real Phase 0 Cursor probe chains without needing a
|
|
8
8
|
* live /proc tree.
|
|
9
9
|
*
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* calls a reachable, stable pid-map row. This faithfully restores the previous
|
|
15
15
|
* cursor anchor behavior (match `cursor` first, then fall back to `node`) that
|
|
16
16
|
* was dropped in the Phase 4-6 TS refactor, the same regression class as the
|
|
17
|
-
* heartbeat-platform + pidmap-self-heal losses. Scoped to `
|
|
17
|
+
* heartbeat-platform + pidmap-self-heal losses. Scoped to `adapter === "cursor"`
|
|
18
18
|
* so Claude Code / Codex never
|
|
19
19
|
* mis-anchor on an unrelated `node` ancestor (they match their own comm token
|
|
20
20
|
* directly).
|
|
@@ -25,24 +25,79 @@
|
|
|
25
25
|
* concurrent same-window chats disambiguate via `--session-id`.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
-
/**
|
|
28
|
+
/** Adapter-binary comm names. CC's tool calls descend from `claude`, Codex's
|
|
29
29
|
* from `codex`; matched directly so neither needs the `node` fallback. */
|
|
30
30
|
const PRIMARY_COMM_TOKENS = new Set(["claude", "claude-code", "cursor", "codex"]);
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Adapter-exported pid environment variables, in precedence order.
|
|
34
|
+
*
|
|
35
|
+
* A adapter that names its own process spares us the guessing entirely, and the
|
|
36
|
+
* guess is the part that breaks: comm matching only recognises a binary called
|
|
37
|
+
* by its adapter name, and at least one Claude Code build installs its CLI
|
|
38
|
+
* under a version-numbered filename, whose comm is a bare version string. The
|
|
39
|
+
* walk then finds nothing, falls back to the ephemeral hook shell, and writes a
|
|
40
|
+
* row that is dead within seconds.
|
|
41
|
+
*
|
|
42
|
+
* Only Claude Code is known to export one today. Absent variables cost a lookup.
|
|
43
|
+
*/
|
|
44
|
+
const ADAPTER_PID_ENV_VARS = ["CLAUDE_PID"] as const;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The adapter pid as stated by the adapter itself, or undefined.
|
|
48
|
+
*
|
|
49
|
+
* Sanity-checked against our own pid: a variable naming this process would
|
|
50
|
+
* anchor the row to whatever short-lived thing is running the hook, which is
|
|
51
|
+
* the failure it exists to avoid.
|
|
52
|
+
*/
|
|
53
|
+
export function adapterPidFromEnv(): number | undefined {
|
|
54
|
+
for (const key of ADAPTER_PID_ENV_VARS) {
|
|
55
|
+
const raw = process.env[key]?.trim();
|
|
56
|
+
if (!raw) continue;
|
|
57
|
+
const pid = Number(raw);
|
|
58
|
+
if (!Number.isInteger(pid) || pid <= 1 || pid === process.pid) continue;
|
|
59
|
+
return pid;
|
|
60
|
+
}
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Does an executable path belong to a adapter?
|
|
66
|
+
*
|
|
67
|
+
* Read as path segments rather than substrings, so a token has to be a whole
|
|
68
|
+
* directory or file name. The leading dot is optional because adapters install
|
|
69
|
+
* under a dotted home directory, and that directory is what identifies the
|
|
70
|
+
* binary when the binary's own name is a version number.
|
|
71
|
+
*/
|
|
72
|
+
function pathNamesAAdapter(exePath: string | undefined): boolean {
|
|
73
|
+
if (!exePath) return false;
|
|
74
|
+
for (const raw of exePath.split("/")) {
|
|
75
|
+
const segment = raw.startsWith(".") ? raw.slice(1) : raw;
|
|
76
|
+
if (PRIMARY_COMM_TOKENS.has(segment)) return true;
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
32
81
|
/**
|
|
33
82
|
* Pick the anchor PID from a ppid chain ordered nearest-first (the resolving
|
|
34
83
|
* process at index 0, walking up toward init). Returns the first ancestor
|
|
35
|
-
* matching a
|
|
84
|
+
* matching a adapter comm token; for cursor, falls back to the first `node`
|
|
36
85
|
* ancestor; otherwise undefined (caller falls back to process.ppid).
|
|
37
86
|
*/
|
|
38
87
|
export function selectAnchorPid(
|
|
39
|
-
chain: ReadonlyArray<{ pid: number; comm: string }>,
|
|
40
|
-
|
|
88
|
+
chain: ReadonlyArray<{ pid: number; comm: string; exe?: string }>,
|
|
89
|
+
adapter?: string,
|
|
41
90
|
): number | undefined {
|
|
42
91
|
for (const hop of chain) {
|
|
43
92
|
if (PRIMARY_COMM_TOKENS.has(hop.comm)) return hop.pid;
|
|
44
93
|
}
|
|
45
|
-
|
|
94
|
+
// Second pass on the executable path, for a adapter whose binary is not named
|
|
95
|
+
// after itself. Kept behind the comm pass so an exactly-named ancestor still
|
|
96
|
+
// wins, and so this only ever adds matches.
|
|
97
|
+
for (const hop of chain) {
|
|
98
|
+
if (pathNamesAAdapter(hop.exe)) return hop.pid;
|
|
99
|
+
}
|
|
100
|
+
if (adapter === "cursor") {
|
|
46
101
|
for (const hop of chain) {
|
|
47
102
|
if (hop.comm === "node") return hop.pid;
|
|
48
103
|
}
|
|
@@ -55,7 +110,7 @@ export function selectAnchorPid(
|
|
|
55
110
|
* shape the `/proc` fast path produces, for the macOS/BSD branch of the anchor
|
|
56
111
|
* walk. `ps` prints `comm` as a full executable path (and some Apple helper
|
|
57
112
|
* names contain spaces, e.g. `Code Helper (Plugin)`), so the comm is reduced to
|
|
58
|
-
* its basename to match the
|
|
113
|
+
* its basename to match the adapter comm tokens the way Linux's `/proc/<pid>/comm`
|
|
59
114
|
* basename does. Returns null when the line has no leading numeric ppid.
|
|
60
115
|
*
|
|
61
116
|
* Pure (no I/O) so the parsing — the error-prone part — is unit-testable
|
|
@@ -1,47 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { dirname, join, resolve } from "node:path";
|
|
3
|
-
import { coordEnv } from "../../../lib/env.ts";
|
|
1
|
+
import { resolveCoordRoot } from "../../agents/coord-client.ts";
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
|
-
*
|
|
7
|
-
* single coord-root resolution so every adapter agrees on the same root.
|
|
4
|
+
* The hooks-side name for THE coordination-root resolution.
|
|
8
5
|
*
|
|
9
|
-
*
|
|
6
|
+
* Delegates to `resolveCoordRoot()` so the hooks and the CLI cannot resolve
|
|
7
|
+
* different roots. They used to: this walked up from `CLAUDE_PROJECT_DIR` or
|
|
8
|
+
* cwd while the CLI's `monorepoRoot()` asked git for the superproject first, so
|
|
9
|
+
* with a shell inside a submodule that carries its own `.harnery/`, the CLI's
|
|
10
|
+
* `state.status_checked` landed in a stream this side never read and rule 1/3
|
|
11
|
+
* blocked every turn.
|
|
12
|
+
*
|
|
13
|
+
* Resolution precedence (see `resolveCoordRoot` for the full rationale):
|
|
10
14
|
* 1. HARNERY_COORD_ROOT_OVERRIDE — explicit pin (tests, git hooks).
|
|
11
|
-
* 2. The
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* 3. Walk up from `start` (default cwd).
|
|
15
|
+
* 2. The adapter's project dir (CLAUDE_PROJECT_DIR) — hook processes inherit
|
|
16
|
+
* the session's *shell* cwd, which follows `cd` into subdirectories or
|
|
17
|
+
* submodules that may carry a `.harnery/` of their own (or none at all,
|
|
18
|
+
* e.g. a journal dir under /tmp). The session's coordination home is the
|
|
19
|
+
* project the adapter opened, not wherever the shell happens to sit.
|
|
20
|
+
* 3. The root that already holds this session's heartbeat.
|
|
21
|
+
* 4. The nearest enclosing `.harnery/`, then a git-derived root.
|
|
19
22
|
*/
|
|
20
23
|
export function findCoordRoot(start: string = process.cwd()): string | null {
|
|
21
|
-
|
|
22
|
-
// bash side. Lets the sandboxed coord-test suite run against a temp
|
|
23
|
-
// directory rather than the real monorepo root. agent-hook's session.start
|
|
24
|
-
// handler may be the FIRST thing to create .harnery/ in a fresh sandbox,
|
|
25
|
-
// so the override is honored unconditionally (we don't require .harnery/
|
|
26
|
-
// to pre-exist).
|
|
27
|
-
const override = coordEnv("COORD_ROOT_OVERRIDE");
|
|
28
|
-
if (override) return override;
|
|
29
|
-
// Claude Code exports CLAUDE_PROJECT_DIR to every hook process; other
|
|
30
|
-
// harnesses don't set it, so this is inert outside claude-code hooks.
|
|
31
|
-
const projectDir = process.env.CLAUDE_PROJECT_DIR;
|
|
32
|
-
if (projectDir) {
|
|
33
|
-
const fromProject = walkUp(projectDir);
|
|
34
|
-
if (fromProject) return fromProject;
|
|
35
|
-
}
|
|
36
|
-
return walkUp(start);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function walkUp(start: string): string | null {
|
|
40
|
-
let dir = resolve(start);
|
|
41
|
-
while (true) {
|
|
42
|
-
if (existsSync(join(dir, ".harnery"))) return dir;
|
|
43
|
-
const parent = dirname(dir);
|
|
44
|
-
if (parent === dir) return null;
|
|
45
|
-
dir = parent;
|
|
46
|
-
}
|
|
24
|
+
return resolveCoordRoot(start);
|
|
47
25
|
}
|
|
@@ -26,7 +26,7 @@ export function resolveIntent(opts: {
|
|
|
26
26
|
}): { intent: string; source: "command-comment" | "description" | "stamp" | "none" } {
|
|
27
27
|
const stampPath = join(opts.coordRoot, ".harnery", `.last-intent.${opts.instanceId}`);
|
|
28
28
|
|
|
29
|
-
// 1. Fresh from the command itself (most reliable, cross-
|
|
29
|
+
// 1. Fresh from the command itself (most reliable, cross-adapter).
|
|
30
30
|
if (opts.commandIntentComment) {
|
|
31
31
|
const cleaned = clamp(opts.commandIntentComment);
|
|
32
32
|
if (cleaned) {
|
|
@@ -2,13 +2,14 @@ import { spawnSync } from "node:child_process";
|
|
|
2
2
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { coordEnv } from "../../../lib/env.ts";
|
|
5
|
+
import { checkPidToken } from "../../agents/state/proc-start.ts";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Resolve the canonical `instance_id` for the current hook invocation.
|
|
8
9
|
*
|
|
9
10
|
* Precedence:
|
|
10
11
|
*
|
|
11
|
-
* 1. `HARNERY_AGENT_COORD_OWNER` env var. Set by
|
|
12
|
+
* 1. `HARNERY_AGENT_COORD_OWNER` env var. Set by adapter adapters when they know
|
|
12
13
|
* the owner identity at spawn time (Codex's apply_patch tool path uses
|
|
13
14
|
* this).
|
|
14
15
|
* 2. Hook payload fields, in order: `agent_id` → `subagent_id` →
|
|
@@ -40,7 +41,7 @@ export function resolveOwner(opts: {
|
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
// Pid-map ancestor walk. Start at own pid (the bash wrapper's bun child),
|
|
43
|
-
// walk up through ppids. The pid-map is stamped keyed by the
|
|
44
|
+
// walk up through ppids. The pid-map is stamped keyed by the adapter PID, so
|
|
44
45
|
// we'll usually find it 1-3 hops up.
|
|
45
46
|
const pidmap = join(opts.coordRoot, ".harnery", "pid-map");
|
|
46
47
|
if (existsSync(pidmap)) {
|
|
@@ -51,9 +52,14 @@ export function resolveOwner(opts: {
|
|
|
51
52
|
if (existsSync(file)) {
|
|
52
53
|
try {
|
|
53
54
|
const row = readFileSync(file, "utf8").trim();
|
|
54
|
-
// Row shape: "<instance_id>"
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
// Row shape: "<instance_id>", "<instance_id>\t<platform>", or
|
|
56
|
+
// "<instance_id>\t<platform>\t<start_token>".
|
|
57
|
+
const [owner, , startToken] = row.split("\t");
|
|
58
|
+
// A row whose start token disagrees with the process now holding this
|
|
59
|
+
// pid is about a different, earlier process. Believing it hands this
|
|
60
|
+
// session another agent's identity, so walk past it.
|
|
61
|
+
const recycled = checkPidToken(pid, startToken || undefined) === "mismatch";
|
|
62
|
+
if (owner && owner.length > 0 && !recycled) {
|
|
57
63
|
return {
|
|
58
64
|
instance_id: owner,
|
|
59
65
|
source: hops === 0 ? "pidmap-self" : "pidmap-ancestor",
|