harnery 0.30.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/commander.d.ts +8 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +14 -13
- package/dist/commands/adapter.d.ts +12 -0
- package/dist/commands/adapter.d.ts.map +1 -0
- package/dist/commands/{harness.js → adapter.js} +35 -35
- package/dist/commands/agents.d.ts +3 -2
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +61 -60
- package/dist/commands/artifacts.d.ts +4 -0
- package/dist/commands/artifacts.d.ts.map +1 -0
- package/dist/commands/artifacts.js +143 -0
- package/dist/commands/backup.d.ts +1 -1
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +5 -2
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +310 -7
- package/dist/commands/checkpoint.d.ts +12 -0
- package/dist/commands/checkpoint.d.ts.map +1 -0
- package/dist/commands/checkpoint.js +162 -0
- package/dist/commands/context.d.ts +2 -2
- package/dist/commands/context.d.ts.map +1 -1
- package/dist/commands/context.js +3 -151
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +31 -7
- package/dist/commands/deinit.d.ts +2 -2
- package/dist/commands/deinit.js +15 -15
- package/dist/commands/doctor.js +23 -23
- package/dist/commands/governor.d.ts +4 -0
- package/dist/commands/governor.d.ts.map +1 -0
- package/dist/commands/{supervisor.js → governor.js} +133 -108
- package/dist/commands/init.d.ts +12 -12
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +44 -30
- package/dist/commands/{session.d.ts → journal.d.ts} +2 -2
- package/dist/commands/journal.d.ts.map +1 -0
- package/dist/commands/{scratch.js → journal.js} +47 -47
- package/dist/commands/policy.js +1 -1
- package/dist/commands/presence.js +2 -2
- package/dist/commands/sync.d.ts +1 -1
- package/dist/commands/sync.js +3 -3
- package/dist/commands/tunnel.d.ts +16 -0
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +193 -23
- package/dist/commands/web-fetch.js +1 -1
- package/dist/commands/web.d.ts +19 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +51 -0
- package/dist/commands/work.d.ts.map +1 -1
- package/dist/commands/work.js +38 -22
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +35 -28
- package/dist/core/{harnesses → adapters}/attest-projection.d.ts +2 -2
- package/dist/core/adapters/attest-projection.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/attest.d.ts +16 -16
- package/dist/core/adapters/attest.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/attest.js +9 -9
- package/dist/core/{harnesses → adapters}/attestation.d.ts +16 -16
- package/dist/core/adapters/attestation.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/attestation.js +20 -20
- package/dist/core/{harnesses → adapters}/bench.d.ts +12 -12
- package/dist/core/adapters/bench.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/bench.js +12 -12
- package/dist/core/adapters/index.d.ts +13 -0
- package/dist/core/adapters/index.d.ts.map +1 -0
- package/dist/core/adapters/index.js +6 -0
- package/dist/core/{harnesses → adapters}/profiles.d.ts +11 -11
- package/dist/core/adapters/profiles.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/profiles.js +11 -11
- package/dist/core/adapters/registry.d.ts +15 -0
- package/dist/core/adapters/registry.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/registry.js +11 -11
- package/dist/core/{harnesses → adapters}/types.d.ts +23 -23
- package/dist/core/adapters/types.d.ts.map +1 -0
- package/dist/core/{harnesses → adapters}/types.js +1 -1
- package/dist/core/agents/canonical-emit.d.ts +4 -4
- package/dist/core/agents/canonical-emit.js +5 -5
- package/dist/core/agents/cli-emit.js +1 -1
- package/dist/core/agents/cli.js +30 -26
- package/dist/core/agents/codex-replay.d.ts +1 -1
- package/dist/core/agents/codex-replay.js +6 -6
- package/dist/core/agents/coord-client.d.ts +21 -2
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +122 -27
- package/dist/core/agents/events/consume.d.ts +1 -1
- package/dist/core/agents/events/emit.d.ts +5 -6
- package/dist/core/agents/events/emit.d.ts.map +1 -1
- package/dist/core/agents/events/emit.js +2 -2
- package/dist/core/agents/render/prompt-context.d.ts +21 -9
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +82 -30
- package/dist/core/agents/render/session-context.d.ts +1 -1
- package/dist/core/agents/render/session-context.js +5 -5
- package/dist/core/agents/rules/claim-conflict.d.ts +2 -6
- package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/claim-conflict.js +1 -1
- package/dist/core/agents/rules/commit-conflict.js +98 -22
- package/dist/core/agents/rules/stop-hook.d.ts +9 -9
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +23 -5
- package/dist/core/agents/rules/verdict.d.ts +14 -0
- package/dist/core/agents/rules/verdict.d.ts.map +1 -0
- package/dist/core/agents/rules/verdict.js +1 -0
- package/dist/core/agents/session-events.js +3 -3
- package/dist/core/agents/state/council.d.ts +1 -1
- package/dist/core/agents/state/council.js +1 -1
- package/dist/core/agents/state/heartbeat-projector.d.ts +3 -2
- package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-projector.js +14 -10
- package/dist/core/agents/state/heartbeat-writer.d.ts +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +12 -12
- package/dist/core/agents/state/{scratch.d.ts → journal.d.ts} +7 -7
- package/dist/core/agents/state/{scratch.d.ts.map → journal.d.ts.map} +1 -1
- package/dist/core/agents/state/{scratch.js → journal.js} +12 -12
- package/dist/core/agents/state/pidmap.d.ts +28 -4
- package/dist/core/agents/state/pidmap.d.ts.map +1 -1
- package/dist/core/agents/state/pidmap.js +130 -15
- package/dist/core/agents/state/proc-start.d.ts +95 -0
- package/dist/core/agents/state/proc-start.d.ts.map +1 -0
- package/dist/core/agents/state/proc-start.js +199 -0
- package/dist/core/agents/state/shell-mutation.d.ts +1 -1
- package/dist/core/agents/state/shell-mutation.js +1 -1
- package/dist/core/agents/state/stale-sweep.js +7 -7
- package/dist/core/artifacts/index.d.ts +86 -0
- package/dist/core/artifacts/index.d.ts.map +1 -0
- package/dist/core/artifacts/index.js +421 -0
- package/dist/core/config.d.ts +9 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +26 -2
- package/dist/core/context/index.d.ts +12 -12
- package/dist/core/context/index.js +10 -10
- package/dist/core/governor/adapter-spread.d.ts +52 -0
- package/dist/core/governor/adapter-spread.d.ts.map +1 -0
- package/dist/core/governor/adapter-spread.js +52 -0
- package/dist/core/governor/index.d.ts +7 -0
- package/dist/core/governor/index.d.ts.map +1 -0
- package/dist/core/governor/index.js +6 -0
- package/dist/core/governor/plan-api.d.ts +38 -0
- package/dist/core/governor/plan-api.d.ts.map +1 -0
- package/dist/core/governor/plan-api.js +83 -0
- package/dist/core/governor/plan-read.d.ts +5 -0
- package/dist/core/governor/plan-read.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/plan-read.js +66 -52
- package/dist/core/{supervisor → governor}/plan-types.d.ts +57 -56
- package/dist/core/governor/plan-types.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/plan-types.js +4 -4
- package/dist/core/governor/planning.d.ts +48 -0
- package/dist/core/governor/planning.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/planning.js +125 -94
- package/dist/core/governor/read.d.ts +6 -0
- package/dist/core/governor/read.d.ts.map +1 -0
- package/dist/core/governor/read.js +4 -0
- package/dist/core/governor/runner.d.ts +37 -0
- package/dist/core/governor/runner.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/runner.js +15 -15
- package/dist/core/governor/service-read.d.ts +6 -0
- package/dist/core/governor/service-read.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/service-read.js +12 -12
- package/dist/core/governor/service.d.ts +114 -0
- package/dist/core/governor/service.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/service.js +57 -57
- package/dist/core/governor/state.d.ts +116 -0
- package/dist/core/governor/state.d.ts.map +1 -0
- package/dist/core/{supervisor → governor}/state.js +228 -108
- package/dist/core/hooks/adapter/detect.d.ts +9 -0
- package/dist/core/hooks/{harness → adapter}/detect.d.ts.map +1 -1
- package/dist/core/hooks/{harness → adapter}/detect.js +8 -8
- package/dist/core/hooks/{harness → adapter}/events.d.ts +15 -14
- package/dist/core/hooks/adapter/events.d.ts.map +1 -0
- package/dist/core/hooks/{harness → adapter}/events.js +5 -5
- package/dist/core/hooks/{harness → adapter}/output.d.ts +20 -14
- package/dist/core/hooks/adapter/output.d.ts.map +1 -0
- package/dist/core/hooks/{harness → adapter}/output.js +30 -22
- package/dist/core/hooks/{harness → adapter}/parse.d.ts +5 -5
- package/dist/core/hooks/{harness → adapter}/parse.d.ts.map +1 -1
- package/dist/core/hooks/{harness → adapter}/parse.js +4 -4
- package/dist/core/hooks/{harness → adapter}/wiring.d.ts +15 -15
- package/dist/core/hooks/{harness → adapter}/wiring.d.ts.map +1 -1
- package/dist/core/hooks/{harness → adapter}/wiring.js +13 -13
- package/dist/core/hooks/cli.d.ts +3 -3
- package/dist/core/hooks/cli.js +175 -151
- package/dist/core/hooks/effects/image-capture.d.ts +5 -5
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +3 -3
- package/dist/core/hooks/effects/index.d.ts +12 -12
- package/dist/core/hooks/effects/index.d.ts.map +1 -1
- package/dist/core/hooks/effects/index.js +17 -17
- package/dist/core/hooks/events/emit.d.ts +2 -2
- package/dist/core/hooks/events/emit.d.ts.map +1 -1
- package/dist/core/hooks/events/emit.js +1 -1
- package/dist/core/hooks/events/rotate.js +1 -1
- package/dist/core/hooks/events/schema.d.ts +13 -5
- package/dist/core/hooks/events/schema.d.ts.map +1 -1
- package/dist/core/hooks/guard-path.d.ts +2 -2
- package/dist/core/hooks/guard-path.js +2 -2
- package/dist/core/hooks/index.d.ts +1 -1
- package/dist/core/hooks/index.d.ts.map +1 -1
- package/dist/core/hooks/resolve/anchor.d.ts +14 -5
- package/dist/core/hooks/resolve/anchor.d.ts.map +1 -1
- package/dist/core/hooks/resolve/anchor.js +64 -7
- package/dist/core/hooks/resolve/coord-root.d.ts +3 -3
- package/dist/core/hooks/resolve/coord-root.js +4 -4
- package/dist/core/hooks/resolve/intent.js +1 -1
- package/dist/core/hooks/resolve/owner.d.ts +1 -1
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +11 -5
- package/dist/core/{scratch → journal}/index.d.ts +25 -25
- package/dist/core/{scratch → journal}/index.d.ts.map +1 -1
- package/dist/core/{scratch → journal}/index.js +38 -38
- package/dist/core/policy/evaluate.d.ts +1 -1
- package/dist/core/policy/evaluate.d.ts.map +1 -1
- package/dist/core/policy/evaluate.js +7 -7
- package/dist/core/policy/types.d.ts +3 -3
- package/dist/core/policy/types.d.ts.map +1 -1
- package/dist/core/work/state.d.ts +12 -4
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +50 -17
- package/dist/core/workflow/adapters.d.ts +17 -0
- package/dist/core/workflow/adapters.d.ts.map +1 -0
- package/dist/core/workflow/adapters.js +21 -0
- package/dist/core/workflow/approvals.js +6 -6
- package/dist/core/workflow/billing.d.ts +9 -9
- package/dist/core/workflow/billing.js +9 -9
- package/dist/core/workflow/child-env.d.ts +10 -2
- package/dist/core/workflow/child-env.d.ts.map +1 -1
- package/dist/core/workflow/child-env.js +12 -4
- package/dist/core/workflow/engine.d.ts +15 -5
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +138 -83
- package/dist/core/workflow/evidence-preflight.d.ts +24 -0
- package/dist/core/workflow/evidence-preflight.d.ts.map +1 -0
- package/dist/core/workflow/evidence-preflight.js +134 -0
- package/dist/core/workflow/index.d.ts +1 -1
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/proof.d.ts +11 -5
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +45 -36
- package/dist/core/workflow/run-state.d.ts +1 -1
- package/dist/core/workflow/run-state.js +7 -7
- package/dist/core/workflow/sandbox-projection.d.ts +6 -6
- package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
- package/dist/core/workflow/sandbox-projection.js +11 -11
- package/dist/core/workflow/spawn-claude.d.ts +3 -3
- package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
- package/dist/core/workflow/spawn-claude.js +9 -6
- package/dist/core/workflow/spawn-codex.d.ts +4 -4
- package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
- package/dist/core/workflow/spawn-codex.js +9 -6
- package/dist/core/workflow/spawn-cursor.d.ts +4 -4
- package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
- package/dist/core/workflow/spawn-cursor.js +9 -6
- package/dist/core/workflow/spawn-failure.d.ts +1 -1
- package/dist/core/workflow/spawn-failure.js +1 -1
- package/dist/core/workflow/specialists.js +2 -2
- package/dist/core/workflow/{journal.d.ts → transcript.d.ts} +8 -8
- package/dist/core/workflow/transcript.d.ts.map +1 -0
- package/dist/core/workflow/{journal.js → transcript.js} +14 -14
- package/dist/core/workflow/types.d.ts +98 -51
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/types.js +11 -1
- package/dist/core/workflow/validate.d.ts +1 -1
- package/dist/core/workflow/validate.js +1 -1
- package/dist/core/workflow/workspaces/cancellation.js +2 -2
- package/dist/core/workflow/workspaces/cleanup.js +2 -2
- package/dist/core/workflow/workspaces/execution.js +6 -6
- package/dist/core/workflow/workspaces/inspect.js +9 -9
- package/dist/core/workflow/workspaces/integration.js +14 -14
- package/dist/core/workflow/workspaces/lifecycle.d.ts +1 -1
- package/dist/core/workflow/workspaces/lifecycle.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/lifecycle.js +9 -9
- package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.js +39 -5
- package/dist/core/workflow/workspaces/recovery.js +3 -3
- package/dist/core/workflow/workspaces/state.d.ts +1 -1
- package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/state.js +3 -3
- package/dist/core/workflow/workspaces/types.d.ts +1 -1
- package/dist/core/workflow/workspaces/types.d.ts.map +1 -1
- package/dist/lib/browser/asserts.d.ts +28 -0
- package/dist/lib/browser/asserts.d.ts.map +1 -0
- package/dist/lib/browser/asserts.js +152 -0
- package/dist/lib/browser/client.d.ts +49 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +155 -14
- package/dist/lib/browser/content-checks.d.ts +108 -0
- package/dist/lib/browser/content-checks.d.ts.map +1 -0
- package/dist/lib/browser/content-checks.js +474 -0
- package/dist/lib/browser/critique.d.ts +91 -0
- package/dist/lib/browser/critique.d.ts.map +1 -0
- package/dist/lib/browser/critique.js +167 -0
- package/dist/lib/browser/geometry.d.ts +32 -0
- package/dist/lib/browser/geometry.d.ts.map +1 -1
- package/dist/lib/browser/geometry.js +244 -1
- package/dist/lib/browser/index.d.ts +4 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -0
- package/dist/lib/claude-desktop.d.ts.map +1 -1
- package/dist/lib/claude-desktop.js +4 -1
- package/dist/lib/council/index.d.ts +6 -6
- package/dist/lib/council/index.d.ts.map +1 -1
- package/dist/lib/council/index.js +8 -8
- package/dist/lib/identities/assume.d.ts +2 -2
- package/dist/lib/identities/assume.js +7 -7
- package/dist/lib/instructions/apply.d.ts +3 -3
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +75 -27
- package/dist/lib/instructions/host-addendum.d.ts +54 -0
- package/dist/lib/instructions/host-addendum.d.ts.map +1 -0
- package/dist/lib/instructions/host-addendum.js +107 -0
- package/dist/lib/instructions/templates.d.ts +10 -3
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +41 -12
- package/dist/lib/machine.d.ts +2 -2
- package/dist/lib/machine.js +2 -2
- package/package.json +26 -21
- package/schemas/config.schema.json +26 -1
- package/src/commander.ts +22 -13
- package/src/commands/{harness.ts → adapter.ts} +46 -46
- package/src/commands/agents.ts +71 -64
- package/src/commands/artifacts.ts +168 -0
- package/src/commands/backup.ts +47 -33
- package/src/commands/browse.ts +438 -2
- package/src/commands/checkpoint.ts +196 -0
- package/src/commands/context.ts +3 -176
- package/src/commands/decision.ts +41 -7
- package/src/commands/deinit.ts +16 -16
- package/src/commands/doctor.ts +28 -28
- package/src/commands/{supervisor.ts → governor.ts} +184 -154
- package/src/commands/init.ts +50 -34
- package/src/commands/{scratch.ts → journal.ts} +60 -60
- package/src/commands/policy.ts +1 -1
- package/src/commands/presence.ts +2 -2
- package/src/commands/sync.ts +3 -3
- package/src/commands/tunnel.ts +237 -34
- package/src/commands/web-fetch.ts +1 -1
- package/src/commands/web.ts +56 -1
- package/src/commands/work.ts +50 -35
- package/src/commands/workflow.ts +43 -34
- package/src/core/{harnesses → adapters}/attest-projection.ts +2 -2
- package/src/core/{harnesses → adapters}/attest.ts +27 -27
- package/src/core/{harnesses → adapters}/attestation.ts +41 -41
- package/src/core/{harnesses → adapters}/bench.ts +34 -43
- package/src/core/adapters/index.ts +56 -0
- package/src/core/{harnesses → adapters}/profiles.ts +16 -16
- package/src/core/{harnesses → adapters}/registry.ts +23 -23
- package/src/core/{harnesses → adapters}/types.ts +23 -23
- package/src/core/agents/canonical-emit.ts +6 -6
- package/src/core/agents/cli-emit.ts +1 -1
- package/src/core/agents/cli.ts +30 -28
- package/src/core/agents/codex-replay.ts +6 -6
- package/src/core/agents/coord-client.ts +119 -28
- package/src/core/agents/events/consume.ts +1 -1
- package/src/core/agents/events/emit.ts +7 -6
- package/src/core/agents/render/prompt-context.ts +107 -31
- package/src/core/agents/render/session-context.ts +6 -6
- package/src/core/agents/rules/claim-conflict.ts +4 -7
- package/src/core/agents/rules/commit-conflict.ts +103 -22
- package/src/core/agents/rules/stop-hook.ts +33 -17
- package/src/core/agents/rules/verdict.ts +13 -0
- package/src/core/agents/session-events.ts +4 -4
- package/src/core/agents/state/council.ts +1 -1
- package/src/core/agents/state/heartbeat-projector.ts +16 -12
- package/src/core/agents/state/heartbeat-writer.ts +12 -12
- package/src/core/agents/state/{scratch.ts → journal.ts} +12 -12
- package/src/core/agents/state/pidmap.ts +130 -15
- package/src/core/agents/state/proc-start.ts +208 -0
- package/src/core/agents/state/shell-mutation.ts +1 -1
- package/src/core/agents/state/stale-sweep.ts +7 -7
- package/src/core/artifacts/index.ts +557 -0
- package/src/core/config.ts +30 -2
- package/src/core/context/index.ts +15 -15
- package/src/core/governor/adapter-spread.ts +82 -0
- package/src/core/governor/index.ts +91 -0
- package/src/core/governor/plan-api.ts +115 -0
- package/src/core/{supervisor → governor}/plan-read.ts +112 -97
- package/src/core/{supervisor → governor}/plan-types.ts +59 -56
- package/src/core/{supervisor → governor}/planning.ts +223 -192
- package/src/core/governor/read.ts +59 -0
- package/src/core/{supervisor → governor}/runner.ts +39 -39
- package/src/core/{supervisor → governor}/service-read.ts +22 -22
- package/src/core/{supervisor → governor}/service.ts +117 -119
- package/src/core/{supervisor → governor}/state.ts +325 -167
- package/src/core/hooks/adapter/detect.ts +30 -0
- package/src/core/hooks/{harness → adapter}/events.ts +16 -14
- package/src/core/hooks/{harness → adapter}/output.ts +31 -23
- package/src/core/hooks/{harness → adapter}/parse.ts +5 -5
- package/src/core/hooks/{harness → adapter}/wiring.ts +21 -21
- package/src/core/hooks/cli.ts +185 -162
- package/src/core/hooks/effects/image-capture.ts +6 -6
- package/src/core/hooks/effects/index.ts +17 -17
- package/src/core/hooks/events/emit.ts +3 -3
- package/src/core/hooks/events/rotate.ts +1 -1
- package/src/core/hooks/events/schema.ts +15 -7
- package/src/core/hooks/guard-path.ts +2 -2
- package/src/core/hooks/index.ts +1 -1
- package/src/core/hooks/resolve/anchor.ts +63 -8
- package/src/core/hooks/resolve/coord-root.ts +4 -4
- package/src/core/hooks/resolve/intent.ts +1 -1
- package/src/core/hooks/resolve/owner.ts +11 -5
- package/src/core/{scratch → journal}/index.ts +53 -53
- package/src/core/policy/evaluate.ts +8 -8
- package/src/core/policy/types.ts +3 -3
- package/src/core/work/state.ts +65 -23
- package/src/core/workflow/adapters.ts +33 -0
- package/src/core/workflow/approvals.ts +7 -7
- package/src/core/workflow/billing.ts +12 -12
- package/src/core/workflow/child-env.ts +13 -4
- package/src/core/workflow/engine.ts +155 -90
- package/src/core/workflow/evidence-preflight.ts +165 -0
- package/src/core/workflow/index.ts +3 -3
- package/src/core/workflow/proof.ts +60 -50
- package/src/core/workflow/run-state.ts +7 -7
- package/src/core/workflow/sandbox-projection.ts +16 -16
- package/src/core/workflow/spawn-claude.ts +13 -10
- package/src/core/workflow/spawn-codex.ts +13 -10
- package/src/core/workflow/spawn-cursor.ts +13 -10
- package/src/core/workflow/spawn-failure.ts +1 -1
- package/src/core/workflow/specialists.ts +2 -2
- package/src/core/workflow/{journal.ts → transcript.ts} +16 -16
- package/src/core/workflow/types.ts +108 -51
- package/src/core/workflow/validate.ts +1 -1
- package/src/core/workflow/workspaces/cancellation.ts +2 -2
- package/src/core/workflow/workspaces/cleanup.ts +2 -2
- package/src/core/workflow/workspaces/execution.ts +6 -6
- package/src/core/workflow/workspaces/inspect.ts +14 -11
- package/src/core/workflow/workspaces/integration.ts +18 -14
- package/src/core/workflow/workspaces/lifecycle.ts +10 -10
- package/src/core/workflow/workspaces/local-git.ts +47 -5
- package/src/core/workflow/workspaces/recovery.ts +3 -3
- package/src/core/workflow/workspaces/state.ts +4 -3
- package/src/core/workflow/workspaces/types.ts +1 -1
- package/src/lib/browser/asserts.ts +177 -0
- package/src/lib/browser/client.ts +189 -14
- package/src/lib/browser/content-checks.ts +571 -0
- package/src/lib/browser/critique.ts +231 -0
- package/src/lib/browser/geometry.ts +297 -1
- package/src/lib/browser/index.ts +34 -0
- package/src/lib/claude-desktop.ts +4 -1
- package/src/lib/council/index.ts +9 -9
- package/src/lib/identities/assume.ts +7 -7
- package/src/lib/instructions/apply.ts +87 -25
- package/src/lib/instructions/host-addendum.ts +126 -0
- package/src/lib/instructions/templates.ts +44 -15
- package/src/lib/machine.ts +2 -2
- package/dist/commands/harness.d.ts +0 -12
- package/dist/commands/harness.d.ts.map +0 -1
- package/dist/commands/scratch.d.ts +0 -4
- package/dist/commands/scratch.d.ts.map +0 -1
- package/dist/commands/session.d.ts.map +0 -1
- package/dist/commands/session.js +0 -162
- package/dist/commands/supervisor.d.ts +0 -4
- package/dist/commands/supervisor.d.ts.map +0 -1
- package/dist/core/harnesses/attest-projection.d.ts.map +0 -1
- package/dist/core/harnesses/attest.d.ts.map +0 -1
- package/dist/core/harnesses/attestation.d.ts.map +0 -1
- package/dist/core/harnesses/bench.d.ts.map +0 -1
- package/dist/core/harnesses/index.d.ts +0 -13
- package/dist/core/harnesses/index.d.ts.map +0 -1
- package/dist/core/harnesses/index.js +0 -6
- package/dist/core/harnesses/profiles.d.ts.map +0 -1
- package/dist/core/harnesses/registry.d.ts +0 -15
- package/dist/core/harnesses/registry.d.ts.map +0 -1
- package/dist/core/harnesses/types.d.ts.map +0 -1
- package/dist/core/hooks/harness/detect.d.ts +0 -9
- package/dist/core/hooks/harness/events.d.ts.map +0 -1
- package/dist/core/hooks/harness/output.d.ts.map +0 -1
- package/dist/core/supervisor/index.d.ts +0 -7
- package/dist/core/supervisor/index.d.ts.map +0 -1
- package/dist/core/supervisor/index.js +0 -6
- package/dist/core/supervisor/plan-api.d.ts +0 -23
- package/dist/core/supervisor/plan-api.d.ts.map +0 -1
- package/dist/core/supervisor/plan-api.js +0 -50
- package/dist/core/supervisor/plan-read.d.ts +0 -5
- package/dist/core/supervisor/plan-read.d.ts.map +0 -1
- package/dist/core/supervisor/plan-types.d.ts.map +0 -1
- package/dist/core/supervisor/planning.d.ts +0 -33
- package/dist/core/supervisor/planning.d.ts.map +0 -1
- package/dist/core/supervisor/read.d.ts +0 -6
- package/dist/core/supervisor/read.d.ts.map +0 -1
- package/dist/core/supervisor/read.js +0 -4
- package/dist/core/supervisor/runner.d.ts +0 -37
- package/dist/core/supervisor/runner.d.ts.map +0 -1
- package/dist/core/supervisor/service-read.d.ts +0 -6
- package/dist/core/supervisor/service-read.d.ts.map +0 -1
- package/dist/core/supervisor/service.d.ts +0 -114
- package/dist/core/supervisor/service.d.ts.map +0 -1
- package/dist/core/supervisor/state.d.ts +0 -95
- package/dist/core/supervisor/state.d.ts.map +0 -1
- package/dist/core/workflow/harnesses.d.ts +0 -17
- package/dist/core/workflow/harnesses.d.ts.map +0 -1
- package/dist/core/workflow/harnesses.js +0 -21
- package/dist/core/workflow/journal.d.ts.map +0 -1
- package/src/commands/session.ts +0 -187
- package/src/core/harnesses/index.ts +0 -56
- package/src/core/hooks/harness/detect.ts +0 -30
- package/src/core/supervisor/index.ts +0 -89
- package/src/core/supervisor/plan-api.ts +0 -73
- package/src/core/supervisor/read.ts +0 -59
- package/src/core/workflow/harnesses.ts +0 -33
- /package/dist/core/{harnesses → adapters}/attest-projection.js +0 -0
package/src/core/agents/cli.ts
CHANGED
|
@@ -182,13 +182,13 @@ async function emitClaimRelease(
|
|
|
182
182
|
const { emit } = await import("./events/emit.ts");
|
|
183
183
|
const canonical = path.startsWith(`${root}/`) ? path.slice(root.length + 1) : path;
|
|
184
184
|
const platform = hb.platform;
|
|
185
|
-
const
|
|
185
|
+
const adapter =
|
|
186
186
|
platform === "cursor" ? "cursor" : platform === "codex" ? "codex" : "claude-code";
|
|
187
187
|
emit(root, {
|
|
188
188
|
event_type: "claim.release",
|
|
189
189
|
instance_id: owner,
|
|
190
190
|
session_id: hb.session_id ?? owner,
|
|
191
|
-
|
|
191
|
+
adapter,
|
|
192
192
|
source: "agent-coord",
|
|
193
193
|
data: { path: canonical, reason },
|
|
194
194
|
});
|
|
@@ -291,16 +291,16 @@ async function handleStateAction(root: string, action: string, rest: string[]):
|
|
|
291
291
|
return 0;
|
|
292
292
|
}
|
|
293
293
|
case "heal-heartbeat": {
|
|
294
|
-
//
|
|
294
|
+
// adapter arrives as a `--adapter=<h>` flag (not positional) so the live
|
|
295
295
|
// tool.pre_use heal and the manual `harn agents heal` path (which pass
|
|
296
296
|
// different positional counts) can both supply it without arg-order
|
|
297
297
|
// fragility. Positionals (sessionId, model) stay as-is once flags are
|
|
298
298
|
// filtered out.
|
|
299
|
-
const
|
|
299
|
+
const adapter = args.find((a) => a.startsWith("--adapter="))?.slice("--adapter=".length);
|
|
300
300
|
const positional = args.filter((a) => !a.startsWith("--"));
|
|
301
301
|
const sessionId = positional[0];
|
|
302
302
|
const model = positional[1];
|
|
303
|
-
const hb = writer.healHeartbeat(root, owner, sessionId, model,
|
|
303
|
+
const hb = writer.healHeartbeat(root, owner, sessionId, model, adapter);
|
|
304
304
|
process.stdout.write(`${JSON.stringify({ instance_id: owner, recreated: !!hb })}\n`);
|
|
305
305
|
return hb ? 0 : 1;
|
|
306
306
|
}
|
|
@@ -324,19 +324,19 @@ async function handleStateAction(root: string, action: string, rest: string[]):
|
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
-
async function
|
|
328
|
-
const
|
|
327
|
+
async function handleJournalAction(root: string, action: string, rest: string[]): Promise<number> {
|
|
328
|
+
const journal = await import("./state/journal.ts");
|
|
329
329
|
|
|
330
|
-
if (action === "append-
|
|
330
|
+
if (action === "append-journal") {
|
|
331
331
|
const [owner, category, ...bodyParts] = rest;
|
|
332
332
|
const body = bodyParts.join(" ");
|
|
333
333
|
if (!owner || !category || !body) {
|
|
334
|
-
process.stderr.write("agent-coord append-
|
|
334
|
+
process.stderr.write("agent-coord append-journal <instance_id> <category> <body>\n");
|
|
335
335
|
return 2;
|
|
336
336
|
}
|
|
337
|
-
const result =
|
|
337
|
+
const result = journal.appendJournal(root, owner, category, body);
|
|
338
338
|
if (!result.ok) {
|
|
339
|
-
process.stderr.write(`agent-coord append-
|
|
339
|
+
process.stderr.write(`agent-coord append-journal: ${result.reason}\n`);
|
|
340
340
|
return 1;
|
|
341
341
|
}
|
|
342
342
|
process.stdout.write(
|
|
@@ -345,24 +345,22 @@ async function handleScratchAction(root: string, action: string, rest: string[])
|
|
|
345
345
|
return 0;
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
-
if (action === "edit-
|
|
348
|
+
if (action === "edit-journal") {
|
|
349
349
|
const [owner, newBodyFile, ...summaryParts] = rest;
|
|
350
350
|
const summary = summaryParts.join(" ");
|
|
351
351
|
if (!owner || !newBodyFile) {
|
|
352
|
-
process.stderr.write(
|
|
353
|
-
"agent-coord edit-scratchpad <instance_id> <new-body-file> [<summary>]\n",
|
|
354
|
-
);
|
|
352
|
+
process.stderr.write("agent-coord edit-journal <instance_id> <new-body-file> [<summary>]\n");
|
|
355
353
|
return 2;
|
|
356
354
|
}
|
|
357
355
|
if (!existsSync(newBodyFile)) {
|
|
358
|
-
process.stderr.write(`agent-coord edit-
|
|
356
|
+
process.stderr.write(`agent-coord edit-journal: file not found: ${newBodyFile}\n`);
|
|
359
357
|
return 2;
|
|
360
358
|
}
|
|
361
359
|
const { readFileSync } = await import("node:fs");
|
|
362
360
|
const newBody = readFileSync(newBodyFile, "utf8");
|
|
363
|
-
const result =
|
|
361
|
+
const result = journal.editJournal(root, owner, newBody, summary);
|
|
364
362
|
if (!result.ok) {
|
|
365
|
-
process.stderr.write(`agent-coord edit-
|
|
363
|
+
process.stderr.write(`agent-coord edit-journal: ${result.reason}\n`);
|
|
366
364
|
return 1;
|
|
367
365
|
}
|
|
368
366
|
process.stdout.write(
|
|
@@ -371,7 +369,7 @@ async function handleScratchAction(root: string, action: string, rest: string[])
|
|
|
371
369
|
return 0;
|
|
372
370
|
}
|
|
373
371
|
|
|
374
|
-
process.stderr.write(`agent-coord: unknown
|
|
372
|
+
process.stderr.write(`agent-coord: unknown journal action ${action}\n`);
|
|
375
373
|
return 2;
|
|
376
374
|
}
|
|
377
375
|
|
|
@@ -566,7 +564,7 @@ async function handleShellMutationClaimLog(root: string, rest: string[]): Promis
|
|
|
566
564
|
// in a log file; now a canonical decision.warn so the
|
|
567
565
|
// signal survives in events.ndjson. (The blocking claim-conflict path is
|
|
568
566
|
// separate: claim.conflict / verdict, and unaffected.)
|
|
569
|
-
const
|
|
567
|
+
const adapter = platform === "cursor" ? "cursor" : platform === "codex" ? "codex" : "claude-code";
|
|
570
568
|
const hb = owner ? readHeartbeat(root, owner) : null;
|
|
571
569
|
for (const p of paths) {
|
|
572
570
|
try {
|
|
@@ -574,7 +572,7 @@ async function handleShellMutationClaimLog(root: string, rest: string[]): Promis
|
|
|
574
572
|
event_type: "decision.warn",
|
|
575
573
|
instance_id: owner ?? "unknown",
|
|
576
574
|
session_id: hb?.session_id ?? owner ?? "unknown",
|
|
577
|
-
|
|
575
|
+
adapter,
|
|
578
576
|
data: {
|
|
579
577
|
rule: "shell_mutation_candidate",
|
|
580
578
|
reason: `path=${p} cmd=${truncated} platform=${platform}`,
|
|
@@ -612,10 +610,12 @@ async function handlePromptContext(root: string, rest: string[]): Promise<number
|
|
|
612
610
|
const instanceId = args.instance;
|
|
613
611
|
const sessionId = args.session ?? instanceId;
|
|
614
612
|
const agentName = args.name;
|
|
613
|
+
const sessionNameNudge = args["session-name-nudge"] === "true";
|
|
615
614
|
const taskNudge = args["task-nudge"] === "true";
|
|
615
|
+
const statusFooterNudge = args["status-footer-nudge"] === "true";
|
|
616
616
|
if (!instanceId) {
|
|
617
617
|
process.stderr.write(
|
|
618
|
-
"agent-coord prompt-context --instance <id> [--session <id>] [--name <agent-name>] [--task-nudge]\n",
|
|
618
|
+
"agent-coord prompt-context --instance <id> [--session <id>] [--name <agent-name>] [--session-name-nudge] [--task-nudge] [--status-footer-nudge]\n",
|
|
619
619
|
);
|
|
620
620
|
return 2;
|
|
621
621
|
}
|
|
@@ -625,7 +625,9 @@ async function handlePromptContext(root: string, rest: string[]): Promise<number
|
|
|
625
625
|
instanceId,
|
|
626
626
|
sessionId: sessionId!,
|
|
627
627
|
agentName,
|
|
628
|
+
sessionNameNudge,
|
|
628
629
|
taskNudge,
|
|
630
|
+
statusFooterNudge,
|
|
629
631
|
});
|
|
630
632
|
process.stdout.write(text);
|
|
631
633
|
return 0;
|
|
@@ -743,12 +745,12 @@ async function handleEmitEvent(root: string, rest: string[]): Promise<number> {
|
|
|
743
745
|
const eventType = args.type;
|
|
744
746
|
const instanceId = args.owner;
|
|
745
747
|
const sessionId = args.session;
|
|
746
|
-
const
|
|
748
|
+
const adapter = args.adapter as "claude-code" | "cursor" | "codex" | undefined;
|
|
747
749
|
const dataJson = args["data-json"] ?? "{}";
|
|
748
750
|
|
|
749
|
-
if (!eventType || !instanceId || !sessionId || !
|
|
751
|
+
if (!eventType || !instanceId || !sessionId || !adapter) {
|
|
750
752
|
process.stderr.write(
|
|
751
|
-
"agent-coord emit-event --type <T> --owner <id> --session <id> --
|
|
753
|
+
"agent-coord emit-event --type <T> --owner <id> --session <id> --adapter <h> [--data-json '<json>']\n",
|
|
752
754
|
);
|
|
753
755
|
return 2;
|
|
754
756
|
}
|
|
@@ -774,7 +776,7 @@ async function handleEmitEvent(root: string, rest: string[]): Promise<number> {
|
|
|
774
776
|
event_type: eventType,
|
|
775
777
|
instance_id: instanceId,
|
|
776
778
|
session_id: sessionId,
|
|
777
|
-
|
|
779
|
+
adapter,
|
|
778
780
|
turn_id: args["turn-id"],
|
|
779
781
|
parent_session_id: args["parent-session-id"],
|
|
780
782
|
parent_turn_id: args["parent-turn-id"],
|
|
@@ -822,8 +824,8 @@ async function main(): Promise<number> {
|
|
|
822
824
|
return handleStateAction(root, subcommand, rest);
|
|
823
825
|
}
|
|
824
826
|
|
|
825
|
-
if (subcommand === "append-
|
|
826
|
-
return
|
|
827
|
+
if (subcommand === "append-journal" || subcommand === "edit-journal") {
|
|
828
|
+
return handleJournalAction(root, subcommand, rest);
|
|
827
829
|
}
|
|
828
830
|
|
|
829
831
|
if (
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Production codex sessions emit canonical events from each `harn` invocation
|
|
5
5
|
* via the in-process session-tee middleware (which calls `agent-coord
|
|
6
6
|
* emit-event` for state.task_set / state.status_checked). But the codex
|
|
7
|
-
*
|
|
7
|
+
* adapter itself doesn't wire agent-hook on preToolUse, so user_prompt.submit
|
|
8
8
|
* + tool.pre_use + turn.stop aren't emitted live.
|
|
9
9
|
*
|
|
10
10
|
* This module parses the Codex JSONL transcript at stop time and emits the
|
|
@@ -71,7 +71,7 @@ export function replayCodexJsonl(opts: CodexReplayOpts): { emitted: number } {
|
|
|
71
71
|
event_type: "user_prompt.submit",
|
|
72
72
|
instance_id: instanceId,
|
|
73
73
|
session_id: sessionId,
|
|
74
|
-
|
|
74
|
+
adapter: "codex",
|
|
75
75
|
ts,
|
|
76
76
|
data: {
|
|
77
77
|
prompt_text: clamp(entry.payload.message ?? "", 4000),
|
|
@@ -97,7 +97,7 @@ export function replayCodexJsonl(opts: CodexReplayOpts): { emitted: number } {
|
|
|
97
97
|
event_type: "tool.pre_use",
|
|
98
98
|
instance_id: instanceId,
|
|
99
99
|
session_id: sessionId,
|
|
100
|
-
|
|
100
|
+
adapter: "codex",
|
|
101
101
|
ts,
|
|
102
102
|
data: {
|
|
103
103
|
tool_name: name === "exec_command" ? "Bash" : name,
|
|
@@ -117,7 +117,7 @@ export function replayCodexJsonl(opts: CodexReplayOpts): { emitted: number } {
|
|
|
117
117
|
event_type: "state.status_checked",
|
|
118
118
|
instance_id: instanceId,
|
|
119
119
|
session_id: sessionId,
|
|
120
|
-
|
|
120
|
+
adapter: "codex",
|
|
121
121
|
ts,
|
|
122
122
|
data: { source: "codex-replay" },
|
|
123
123
|
});
|
|
@@ -128,7 +128,7 @@ export function replayCodexJsonl(opts: CodexReplayOpts): { emitted: number } {
|
|
|
128
128
|
event_type: "state.task_set",
|
|
129
129
|
instance_id: instanceId,
|
|
130
130
|
session_id: sessionId,
|
|
131
|
-
|
|
131
|
+
adapter: "codex",
|
|
132
132
|
ts,
|
|
133
133
|
data: { source: "codex-replay" },
|
|
134
134
|
});
|
|
@@ -145,7 +145,7 @@ export function replayCodexJsonl(opts: CodexReplayOpts): { emitted: number } {
|
|
|
145
145
|
event_type: "turn.stop",
|
|
146
146
|
instance_id: instanceId,
|
|
147
147
|
session_id: sessionId,
|
|
148
|
-
|
|
148
|
+
adapter: "codex",
|
|
149
149
|
data: {
|
|
150
150
|
status_box_present: boxPresent,
|
|
151
151
|
tool_call_count: -1,
|
|
@@ -73,7 +73,7 @@ export interface Heartbeat {
|
|
|
73
73
|
last_tool_target?: string;
|
|
74
74
|
/** Free-form task/intent string set via `harn agents set-task`. Phase 2. */
|
|
75
75
|
task?: string;
|
|
76
|
-
/** UTC ISO-8601 timestamp when task was last set/cleared. Used by
|
|
76
|
+
/** UTC ISO-8601 timestamp when task was last set/cleared. Used by adapters without Stop enforcement to compute staleness. 2026-05-24. */
|
|
77
77
|
task_updated_at?: string | null;
|
|
78
78
|
/** Auto-generated per-turn summary written by the Stop hook via Haiku. 2026-05-23. */
|
|
79
79
|
turn_summary?: string | null;
|
|
@@ -146,9 +146,93 @@ export function parsePidmapRowOwner(row: string): string {
|
|
|
146
146
|
|
|
147
147
|
/** Parse platform from a pid-map row; legacy rows default to `claude_code`. */
|
|
148
148
|
export function parsePidmapRowPlatform(row: string): string {
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
const platform = row.trim().split("\t")[1]?.trim();
|
|
150
|
+
return platform || "claude_code";
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Parse the start token from a pid-map row; rows written before it carry none. */
|
|
154
|
+
export function parsePidmapRowStartToken(row: string): string | undefined {
|
|
155
|
+
return row.trim().split("\t")[2]?.trim() || undefined;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Is the process now holding `pid` the one this row was written for?
|
|
160
|
+
*
|
|
161
|
+
* A pid is a number the OS re-issues, and quickly: a `pid_max` of 99999 against
|
|
162
|
+
* ~100 new processes a second recycles the whole space about every quarter
|
|
163
|
+
* hour. Believing a row past that point resolves this session to whichever
|
|
164
|
+
* agent last held the number — which is what made `whoami` report a stranger's
|
|
165
|
+
* name and files. The start token settles it, since two processes may share a
|
|
166
|
+
* pid but never a pid and a start instant.
|
|
167
|
+
*
|
|
168
|
+
* Deliberately inlined rather than imported from `state/proc-start.ts`: this
|
|
169
|
+
* file is vendored verbatim into a downstream consumer and stays on node
|
|
170
|
+
* builtins only. The token is a wire format shared with that module and with
|
|
171
|
+
* the host's commit guard, so the copies must agree byte for byte; exported so
|
|
172
|
+
* a test can hold this one against `processStartToken` and fail on drift.
|
|
173
|
+
*/
|
|
174
|
+
export function pidStartToken(pid: number): string | null {
|
|
175
|
+
const forced = process.env.HARNERY_PID_PROBE;
|
|
176
|
+
const useProcfs = forced === "procfs" || (forced !== "ps" && existsSync("/proc/self/stat"));
|
|
177
|
+
// One machine, one probe. Falling back to the other on a read failure would
|
|
178
|
+
// answer in the wrong dialect and read as a recycled pid.
|
|
179
|
+
if (useProcfs) {
|
|
180
|
+
try {
|
|
181
|
+
const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
|
|
182
|
+
const afterComm = stat.slice(stat.lastIndexOf(") ") + 2);
|
|
183
|
+
// Fields after comm, 0-based: 0 is state (field 3), starttime (22) is 19.
|
|
184
|
+
const ticks = afterComm.split(" ")[19];
|
|
185
|
+
if (!ticks || !/^\d+$/.test(ticks)) return null;
|
|
186
|
+
// Ticks count from boot, so they repeat across reboots; the boot id scopes
|
|
187
|
+
// them. Rows written before it carry ticks alone and still compare.
|
|
188
|
+
let boot = "";
|
|
189
|
+
try {
|
|
190
|
+
const raw = readFileSync("/proc/sys/kernel/random/boot_id", "utf8")
|
|
191
|
+
.trim()
|
|
192
|
+
.replace(/-/g, "");
|
|
193
|
+
if (/^[0-9a-f]{8,}$/.test(raw)) boot = `${raw.slice(0, 8)}.`;
|
|
194
|
+
} catch {
|
|
195
|
+
/* unnamed boot: fall back to the tick-only shape */
|
|
196
|
+
}
|
|
197
|
+
return `l${boot}${ticks}`;
|
|
198
|
+
} catch {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
// TZ and locale are pinned because `ps` renders the date through them, and
|
|
204
|
+
// two callers with different environments must not disagree about one
|
|
205
|
+
// process.
|
|
206
|
+
const out = spawnSync("ps", ["-o", "lstart=", "-p", String(pid)], {
|
|
207
|
+
encoding: "utf8",
|
|
208
|
+
timeout: 2000,
|
|
209
|
+
env: { ...process.env, TZ: "UTC", LC_ALL: "C" },
|
|
210
|
+
});
|
|
211
|
+
if (out.status !== 0) return null;
|
|
212
|
+
const lstart = (out.stdout ?? "").split("\n")[0]?.trim().replace(/\s+/g, " ");
|
|
213
|
+
return lstart ? `p${lstart}` : null;
|
|
214
|
+
} catch {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function pidWasRecycled(pid: number, row: string): boolean {
|
|
220
|
+
const recorded = parsePidmapRowStartToken(row);
|
|
221
|
+
if (!recorded) return false; // pre-token row: unverifiable, behave as before
|
|
222
|
+
const current = pidStartToken(pid);
|
|
223
|
+
if (!current) return false;
|
|
224
|
+
if (current === recorded) return false;
|
|
225
|
+
// A row predating the boot segment recorded ticks alone; compare it on what
|
|
226
|
+
// it recorded rather than pruning every live row on the first upgraded run.
|
|
227
|
+
if (
|
|
228
|
+
recorded[0] === "l" &&
|
|
229
|
+
current[0] === "l" &&
|
|
230
|
+
recorded.includes(".") !== current.includes(".")
|
|
231
|
+
) {
|
|
232
|
+
const ticks = (t: string) => (t.includes(".") ? t.slice(t.indexOf(".") + 1) : t.slice(1));
|
|
233
|
+
return ticks(recorded) !== ticks(current);
|
|
234
|
+
}
|
|
235
|
+
return true;
|
|
152
236
|
}
|
|
153
237
|
|
|
154
238
|
function readPidmapRow(pidmapDir: string, pid: number): string | null {
|
|
@@ -197,9 +281,14 @@ export function resolveOwnerWithSource(): {
|
|
|
197
281
|
const root = monorepoRoot();
|
|
198
282
|
if (!root) return { owner: null, source: "none" };
|
|
199
283
|
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
//
|
|
284
|
+
// Every supported adapter exports its session id into the env of the
|
|
285
|
+
// subprocess it spawns for a tool call, and each heartbeat records the
|
|
286
|
+
// session id it was minted under. Matching the two names us outright, even
|
|
287
|
+
// with many live agents, so it goes ahead of the ppid walk rather than
|
|
288
|
+
// catching what the walk drops. Cursor needed this first because its
|
|
289
|
+
// Glass/Agents UI runs several chats under one node ancestor, making that row
|
|
290
|
+
// last-writer-wins; pid recycling generalises the same hazard to every
|
|
291
|
+
// adapter.
|
|
203
292
|
if (shouldPreferSessionEnv()) {
|
|
204
293
|
const bySession = resolveOwnerBySessionEnv(root);
|
|
205
294
|
if (bySession) {
|
|
@@ -217,7 +306,7 @@ export function resolveOwnerWithSource(): {
|
|
|
217
306
|
for (let hop = 0; hop < 20; hop++) {
|
|
218
307
|
if (pid === null) break;
|
|
219
308
|
const row = readPidmapRow(pidmapDir, pid);
|
|
220
|
-
if (row) {
|
|
309
|
+
if (row && !pidWasRecycled(pid, row)) {
|
|
221
310
|
const rowOwner = parsePidmapRowOwner(row);
|
|
222
311
|
const rowPlat = parsePidmapRowPlatform(row);
|
|
223
312
|
if (rowPlat === prefer) {
|
|
@@ -231,18 +320,6 @@ export function resolveOwnerWithSource(): {
|
|
|
231
320
|
return { owner: fallbackOwner, source: "pidmap_fallback" };
|
|
232
321
|
}
|
|
233
322
|
|
|
234
|
-
// The ppid walk found nothing (e.g. a Bash-tool subshell whose process tree
|
|
235
|
-
// doesn't climb back to the harness anchor). Before guessing, try the
|
|
236
|
-
// harness-provided session id from the environment: every supported harness
|
|
237
|
-
// exports its session id into the tool subprocess env, and each heartbeat
|
|
238
|
-
// records the `session_id` it was minted under. Matching the two resolves us
|
|
239
|
-
// unambiguously even with multiple live agents, which is the case the
|
|
240
|
-
// singleton fallback below cannot handle.
|
|
241
|
-
const bySession = resolveOwnerBySessionEnv(root);
|
|
242
|
-
if (bySession) {
|
|
243
|
-
return { owner: bySession, source: "session_env" };
|
|
244
|
-
}
|
|
245
|
-
|
|
246
323
|
// Last resort: if exactly one agent is live in this coord root, it's
|
|
247
324
|
// unambiguously us — resolve to it. This is what lets the bare `agents
|
|
248
325
|
// status` / `set-task` the stop hook recommends work without a `--session-id`
|
|
@@ -257,8 +334,8 @@ export function resolveOwnerWithSource(): {
|
|
|
257
334
|
}
|
|
258
335
|
|
|
259
336
|
/**
|
|
260
|
-
*
|
|
261
|
-
* supported
|
|
337
|
+
* Adapter-exported session-id environment variables, in precedence order. Each
|
|
338
|
+
* supported adapter propagates its session id into the env of the subprocess it
|
|
262
339
|
* spawns for a tool call (Claude Code's Bash tool, Cursor's terminal, Codex's
|
|
263
340
|
* shell). A coord CLI invoked as such a tool can therefore recover its own
|
|
264
341
|
* identity from the env even when the ppid walk misses.
|
|
@@ -274,7 +351,7 @@ const SESSION_ID_ENV_VARS = [
|
|
|
274
351
|
"CODEX_SESSION_ID",
|
|
275
352
|
] as const;
|
|
276
353
|
|
|
277
|
-
/** Read normalized candidates from the first non-empty
|
|
354
|
+
/** Read normalized candidates from the first non-empty adapter session-id env var. */
|
|
278
355
|
function sessionIdsFromEnv(): string[] {
|
|
279
356
|
for (const key of SESSION_ID_ENV_VARS) {
|
|
280
357
|
const v = process.env[key]?.trim();
|
|
@@ -287,19 +364,33 @@ function sessionIdsFromEnv(): string[] {
|
|
|
287
364
|
return [];
|
|
288
365
|
}
|
|
289
366
|
|
|
290
|
-
/** Read the first non-empty
|
|
367
|
+
/** Read the first non-empty adapter session-id env var, or null. */
|
|
291
368
|
function sessionIdFromEnv(): string | null {
|
|
292
369
|
return sessionIdsFromEnv()[0] ?? null;
|
|
293
370
|
}
|
|
294
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Should the adapter-exported session id be consulted before the ppid walk?
|
|
374
|
+
*
|
|
375
|
+
* Yes, whenever one is exported. The env var is the adapter stating its own
|
|
376
|
+
* identity; the walk is a guess over a namespace the OS recycles. On a box with
|
|
377
|
+
* `pid_max` of 99999 and ~100 pids allocated per second the whole pid space
|
|
378
|
+
* turns over about every quarter hour, so a row written before that can name a
|
|
379
|
+
* pid some unrelated process now holds. Pruning cannot save the walk here:
|
|
380
|
+
* it removes rows whose pid is dead, and a recycled pid is alive. Letting a
|
|
381
|
+
* guess outrank a statement of fact is what made `agents whoami` report another
|
|
382
|
+
* agent's name and file list.
|
|
383
|
+
*
|
|
384
|
+
* This only reorders the two. Session-env resolution still requires a live
|
|
385
|
+
* heartbeat carrying that session id, so when it does not match, the walk runs
|
|
386
|
+
* exactly as before.
|
|
387
|
+
*/
|
|
295
388
|
function shouldPreferSessionEnv(): boolean {
|
|
296
|
-
|
|
297
|
-
const platform = process.env.HARNERY_AGENT_COORD_PLATFORM?.trim();
|
|
298
|
-
return process.env.CURSOR_AGENT === "1" || platform === "cursor";
|
|
389
|
+
return sessionIdFromEnv() !== null;
|
|
299
390
|
}
|
|
300
391
|
|
|
301
392
|
/**
|
|
302
|
-
* Resolve the owner by matching the
|
|
393
|
+
* Resolve the owner by matching the adapter session-id env var against the
|
|
303
394
|
* `session_id` of a live heartbeat in this coord root. Returns the matching
|
|
304
395
|
* `instance_id`, or null if there's no session-id env var or no live heartbeat
|
|
305
396
|
* carries it. "Live" reuses the same 10-minute freshness window the singleton
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* event/schema types).
|
|
6
6
|
*
|
|
7
7
|
* Phase 4: agent-coord uses this from CLI handlers (state.task_set,
|
|
8
|
-
* state.status_checked, state.
|
|
8
|
+
* state.status_checked, state.journal_append, council.*, decision.*,
|
|
9
9
|
* presence.*).
|
|
10
10
|
*/
|
|
11
11
|
|
|
@@ -19,8 +19,9 @@ const STREAM_FILE = ".harnery/events.ndjson";
|
|
|
19
19
|
const LOCK_FILE = ".harnery/events.ndjson.lock";
|
|
20
20
|
const MAX_LINE_BYTES = 64 * 1024;
|
|
21
21
|
|
|
22
|
-
export type
|
|
23
|
-
|
|
22
|
+
export type { Adapter, Source } from "../../hooks/events/schema.ts";
|
|
23
|
+
|
|
24
|
+
import type { Adapter, Source } from "../../hooks/events/schema.ts";
|
|
24
25
|
|
|
25
26
|
export interface Envelope {
|
|
26
27
|
schema_version: typeof SCHEMA_VERSION;
|
|
@@ -32,7 +33,7 @@ export interface Envelope {
|
|
|
32
33
|
parent_session_id?: string;
|
|
33
34
|
turn_id?: string;
|
|
34
35
|
parent_turn_id?: string;
|
|
35
|
-
|
|
36
|
+
adapter: Adapter;
|
|
36
37
|
source: Source;
|
|
37
38
|
data: Record<string, unknown>;
|
|
38
39
|
}
|
|
@@ -41,7 +42,7 @@ export interface EmitInput {
|
|
|
41
42
|
event_type: string;
|
|
42
43
|
instance_id: string;
|
|
43
44
|
session_id: string;
|
|
44
|
-
|
|
45
|
+
adapter: Adapter;
|
|
45
46
|
source?: Source;
|
|
46
47
|
parent_session_id?: string;
|
|
47
48
|
turn_id?: string;
|
|
@@ -61,7 +62,7 @@ export function buildEnvelope(input: EmitInput): Envelope {
|
|
|
61
62
|
parent_session_id: input.parent_session_id,
|
|
62
63
|
turn_id: input.turn_id,
|
|
63
64
|
parent_turn_id: input.parent_turn_id,
|
|
64
|
-
|
|
65
|
+
adapter: input.adapter,
|
|
65
66
|
source: input.source ?? "agent-coord",
|
|
66
67
|
data: input.data,
|
|
67
68
|
};
|