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
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { spawnSync } from "node:child_process";
|
|
10
10
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
11
|
-
import { dirname, resolve, sep } from "node:path";
|
|
11
|
+
import { dirname, join, resolve, sep } from "node:path";
|
|
12
12
|
// NOTE: kept dependency-free (node builtins only); this file is vendored verbatim into
|
|
13
13
|
// a downstream consumer, so it cannot import the coordEnv helper.
|
|
14
14
|
const MAX_INSTANCE_ID_LENGTH = 128;
|
|
@@ -53,52 +53,171 @@ export function resolveContainedFile(directory, fileName) {
|
|
|
53
53
|
/**
|
|
54
54
|
* Resolve the monorepo root for coord-state purposes.
|
|
55
55
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* `<superproject>/.git/modules/<name>/` to recover the superproject for
|
|
59
|
-
* submodule worktrees. Without that fallback, a TS coord caller running
|
|
60
|
-
* inside a `harn worktree add-submodule` checkout would resolve a different
|
|
61
|
-
* `.harnery/` than the bash hooks and the two layers would silently diverge.
|
|
56
|
+
* Thin alias for `resolveCoordRoot()`; kept because it is the name the CLI
|
|
57
|
+
* command modules and the vendored downstream consumer already import.
|
|
62
58
|
*/
|
|
63
59
|
export function monorepoRoot() {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
return resolveCoordRoot();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* THE coordination-root resolution. Every surface — the hooks, the CLI's reads,
|
|
64
|
+
* and the CLI's canonical emits — resolves through this one function, because a
|
|
65
|
+
* root the two layers disagree about is a root that silently breaks the
|
|
66
|
+
* end-of-turn rules: the hook evaluates `state.status_checked` from the stream
|
|
67
|
+
* it reads, so an emit into a different `.harnery/events.ndjson` is invisible
|
|
68
|
+
* and rule 1/3 blocks a turn that did run `agents status`, with no sequence of
|
|
69
|
+
* CLI commands able to satisfy it.
|
|
70
|
+
*
|
|
71
|
+
* Precedence:
|
|
72
|
+
* 1. `HARNERY_COORD_ROOT_OVERRIDE` — explicit pin (tests, git hooks, and the
|
|
73
|
+
* root every coord-helper spawn pins for its child).
|
|
74
|
+
* 2. `CLAUDE_PROJECT_DIR` — the adapter stating which project it opened. Hook
|
|
75
|
+
* processes inherit the session's *shell* cwd, which follows `cd` into a
|
|
76
|
+
* subdirectory or submodule that may carry a `.harnery/` of its own (or
|
|
77
|
+
* none at all), so the adapter's own statement outranks the cwd walk.
|
|
78
|
+
* 3. The candidate root that already holds THIS session's heartbeat.
|
|
79
|
+
* 4. The nearest enclosing `.harnery/`, then a git-derived root.
|
|
80
|
+
*
|
|
81
|
+
* Step 3 is what makes CLI/hook disagreement structurally impossible rather
|
|
82
|
+
* than a coin flip. Choosing either root unconditionally is wrong in one
|
|
83
|
+
* direction each: preferring the git superproject strands a session whose
|
|
84
|
+
* adapter opened the submodule itself (its heartbeat lives in the submodule,
|
|
85
|
+
* so status/set-task wrote events the hook never read), while walking up from
|
|
86
|
+
* cwd alone strands the opposite case, a session opened on the superproject
|
|
87
|
+
* whose shell has cd'd into a submodule that carries its own `.harnery/`
|
|
88
|
+
* (regression-tested in tests/unit/coord-helper-root-pin.test.ts). The session's
|
|
89
|
+
* own heartbeat settles it: whichever root the hook registered this session in
|
|
90
|
+
* is the root the CLI must use, and the adapter-exported session id needed to
|
|
91
|
+
* recognize it is available to a plain tool-call subprocess even though
|
|
92
|
+
* `CLAUDE_PROJECT_DIR` is not.
|
|
93
|
+
*/
|
|
94
|
+
export function resolveCoordRoot(start = process.cwd()) {
|
|
67
95
|
const rootOverride = process.env.HARNERY_COORD_ROOT_OVERRIDE;
|
|
68
|
-
if (rootOverride)
|
|
96
|
+
if (rootOverride)
|
|
69
97
|
return rootOverride;
|
|
98
|
+
const projectDir = process.env.CLAUDE_PROJECT_DIR;
|
|
99
|
+
if (projectDir) {
|
|
100
|
+
const fromProject = nearestCoordRoot(projectDir);
|
|
101
|
+
if (fromProject)
|
|
102
|
+
return fromProject;
|
|
70
103
|
}
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
// 2. --git-common-dir fallback for submodule worktrees. `git worktree add`
|
|
79
|
-
// inside a submodule produces a worktree whose --show-superproject-working-
|
|
80
|
-
// tree is empty (the worktree has no submodule relationship of its own),
|
|
81
|
-
// but --git-common-dir points at <superproject>/.git/modules/<name>/, so
|
|
82
|
-
// we recover the superproject by stripping that suffix.
|
|
83
|
-
const common = spawnSync("git", ["rev-parse", "--git-common-dir"], {
|
|
84
|
-
encoding: "utf8",
|
|
85
|
-
});
|
|
86
|
-
if (common.status === 0) {
|
|
87
|
-
const cd = common.stdout.trim();
|
|
88
|
-
const idx = cd.indexOf("/.git/modules/");
|
|
89
|
-
if (idx !== -1) {
|
|
90
|
-
return cd.substring(0, idx);
|
|
91
|
-
}
|
|
104
|
+
// Nearest-first, so the fallback at the end keeps the historical cwd-walk
|
|
105
|
+
// behavior for a shell that has no registered session at all.
|
|
106
|
+
const ancestors = ancestorCoordRoots(start);
|
|
107
|
+
for (const candidate of ancestors) {
|
|
108
|
+
if (rootKnowsSession(candidate))
|
|
109
|
+
return candidate;
|
|
92
110
|
}
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
111
|
+
// Only reached when no enclosing root knows this session: a submodule
|
|
112
|
+
// worktree (`harn worktree add-submodule`) has no ancestor relationship with
|
|
113
|
+
// the superproject that registered the session, so ask git for it.
|
|
114
|
+
const gitRoots = gitCoordRoots(start).filter((r) => !ancestors.includes(r));
|
|
115
|
+
for (const candidate of gitRoots) {
|
|
116
|
+
if (rootKnowsSession(candidate))
|
|
117
|
+
return candidate;
|
|
99
118
|
}
|
|
100
|
-
|
|
119
|
+
if (ancestors.length > 0)
|
|
120
|
+
return ancestors[0];
|
|
121
|
+
if (gitRoots.length > 0)
|
|
122
|
+
return gitRoots[0];
|
|
123
|
+
// Nothing carries `.harnery/` yet. Hand back the enclosing checkout so a
|
|
124
|
+
// first run (`harn init`, agent-hook's session.start) has somewhere to
|
|
125
|
+
// create it.
|
|
126
|
+
return gitToplevel(start);
|
|
127
|
+
}
|
|
128
|
+
/** Nearest enclosing directory carrying `.harnery/`, or null. */
|
|
129
|
+
export function nearestCoordRoot(start) {
|
|
130
|
+
return ancestorCoordRoots(start)[0] ?? null;
|
|
131
|
+
}
|
|
132
|
+
/** Every enclosing directory carrying `.harnery/`, nearest first. */
|
|
133
|
+
function ancestorCoordRoots(start) {
|
|
134
|
+
const found = [];
|
|
135
|
+
let dir = resolve(start);
|
|
136
|
+
while (true) {
|
|
137
|
+
if (existsSync(join(dir, ".harnery")))
|
|
138
|
+
found.push(dir);
|
|
139
|
+
const parent = dirname(dir);
|
|
140
|
+
if (parent === dir)
|
|
141
|
+
break;
|
|
142
|
+
dir = parent;
|
|
143
|
+
}
|
|
144
|
+
return found;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Does this root's `.harnery/` already know the process asking?
|
|
148
|
+
*
|
|
149
|
+
* Two discriminators, both genuinely about *this* session: the adapter-exported
|
|
150
|
+
* session id matching a live heartbeat, and a pid-map row on our own ppid
|
|
151
|
+
* chain. Deliberately NOT the single-live-agent fallback that owner resolution
|
|
152
|
+
* ends with — a lone stranger in the wrong root is exactly how `whoami` came to
|
|
153
|
+
* report another agent's name and task as its own.
|
|
154
|
+
*/
|
|
155
|
+
export function rootKnowsSession(root) {
|
|
156
|
+
if (resolveOwnerBySessionEnv(root))
|
|
157
|
+
return true;
|
|
158
|
+
return resolveOwnerByPidmap(root).owner !== null;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Git-derived candidate roots for `start`, in preference order, filtered to
|
|
162
|
+
* those that actually carry `.harnery/`.
|
|
163
|
+
*
|
|
164
|
+
* Spawns run with `cwd: start` rather than the process cwd so an injected
|
|
165
|
+
* start dir resolves its own repository — without that, a call about some
|
|
166
|
+
* unrelated directory inherits this process's repo and can resolve a root that
|
|
167
|
+
* has nothing to do with the question asked.
|
|
168
|
+
*/
|
|
169
|
+
function gitCoordRoots(start) {
|
|
170
|
+
const roots = [];
|
|
171
|
+
const push = (value) => {
|
|
172
|
+
if (value && existsSync(join(value, ".harnery")) && !roots.includes(value))
|
|
173
|
+
roots.push(value);
|
|
174
|
+
};
|
|
175
|
+
// Superproject working tree (running from inside a submodule).
|
|
176
|
+
push(gitRevParse(start, "--show-superproject-working-tree"));
|
|
177
|
+
// `--git-common-dir` fallback for submodule worktrees: `git worktree add`
|
|
178
|
+
// inside a submodule produces a worktree whose superproject working tree is
|
|
179
|
+
// empty (the worktree has no submodule relationship of its own), but the
|
|
180
|
+
// common dir points at `<superproject>/.git/modules/<name>/`, so the
|
|
181
|
+
// superproject is recoverable by stripping that suffix.
|
|
182
|
+
const common = gitRevParse(start, "--git-common-dir");
|
|
183
|
+
if (common) {
|
|
184
|
+
const idx = common.indexOf("/.git/modules/");
|
|
185
|
+
if (idx !== -1)
|
|
186
|
+
push(common.substring(0, idx));
|
|
187
|
+
}
|
|
188
|
+
// Top-level (regular checkout).
|
|
189
|
+
push(gitRevParse(start, "--show-toplevel"));
|
|
190
|
+
return roots;
|
|
191
|
+
}
|
|
192
|
+
function gitToplevel(start) {
|
|
193
|
+
return gitRevParse(start, "--show-toplevel");
|
|
101
194
|
}
|
|
195
|
+
function gitRevParse(cwd, flag) {
|
|
196
|
+
const key = `${cwd}${flag}`;
|
|
197
|
+
const cached = gitRevParseCache.get(key);
|
|
198
|
+
if (cached !== undefined)
|
|
199
|
+
return cached;
|
|
200
|
+
let value = null;
|
|
201
|
+
try {
|
|
202
|
+
// `cwd` must exist or the spawn itself fails; callers pass paths that may
|
|
203
|
+
// not (a project dir from a stale env var), so treat any failure as "no
|
|
204
|
+
// answer" rather than letting it throw.
|
|
205
|
+
const r = spawnSync("git", ["rev-parse", flag], { encoding: "utf8", cwd });
|
|
206
|
+
if (r.status === 0)
|
|
207
|
+
value = r.stdout.trim() || null;
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
value = null;
|
|
211
|
+
}
|
|
212
|
+
gitRevParseCache.set(key, value);
|
|
213
|
+
return value;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Memoized because git spawns are the expensive part of resolution and every
|
|
217
|
+
* CLI command resolves the root many times per invocation. Keyed by (cwd, flag);
|
|
218
|
+
* a repository's identity does not change under a running process.
|
|
219
|
+
*/
|
|
220
|
+
const gitRevParseCache = new Map();
|
|
102
221
|
/** Parse owner from a pid-map row (`owner` or `owner\tplatform`). */
|
|
103
222
|
export function parsePidmapRowOwner(row) {
|
|
104
223
|
const trimmed = row.trim();
|
|
@@ -107,9 +226,97 @@ export function parsePidmapRowOwner(row) {
|
|
|
107
226
|
}
|
|
108
227
|
/** Parse platform from a pid-map row; legacy rows default to `claude_code`. */
|
|
109
228
|
export function parsePidmapRowPlatform(row) {
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
229
|
+
const platform = row.trim().split("\t")[1]?.trim();
|
|
230
|
+
return platform || "claude_code";
|
|
231
|
+
}
|
|
232
|
+
/** Parse the start token from a pid-map row; rows written before it carry none. */
|
|
233
|
+
export function parsePidmapRowStartToken(row) {
|
|
234
|
+
return row.trim().split("\t")[2]?.trim() || undefined;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Is the process now holding `pid` the one this row was written for?
|
|
238
|
+
*
|
|
239
|
+
* A pid is a number the OS re-issues, and quickly: a `pid_max` of 99999 against
|
|
240
|
+
* ~100 new processes a second recycles the whole space about every quarter
|
|
241
|
+
* hour. Believing a row past that point resolves this session to whichever
|
|
242
|
+
* agent last held the number — which is what made `whoami` report a stranger's
|
|
243
|
+
* name and files. The start token settles it, since two processes may share a
|
|
244
|
+
* pid but never a pid and a start instant.
|
|
245
|
+
*
|
|
246
|
+
* Deliberately inlined rather than imported from `state/proc-start.ts`: this
|
|
247
|
+
* file is vendored verbatim into a downstream consumer and stays on node
|
|
248
|
+
* builtins only. The token is a wire format shared with that module and with
|
|
249
|
+
* the host's commit guard, so the copies must agree byte for byte; exported so
|
|
250
|
+
* a test can hold this one against `processStartToken` and fail on drift.
|
|
251
|
+
*/
|
|
252
|
+
export function pidStartToken(pid) {
|
|
253
|
+
const forced = process.env.HARNERY_PID_PROBE;
|
|
254
|
+
const useProcfs = forced === "procfs" || (forced !== "ps" && existsSync("/proc/self/stat"));
|
|
255
|
+
// One machine, one probe. Falling back to the other on a read failure would
|
|
256
|
+
// answer in the wrong dialect and read as a recycled pid.
|
|
257
|
+
if (useProcfs) {
|
|
258
|
+
try {
|
|
259
|
+
const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
|
|
260
|
+
const afterComm = stat.slice(stat.lastIndexOf(") ") + 2);
|
|
261
|
+
// Fields after comm, 0-based: 0 is state (field 3), starttime (22) is 19.
|
|
262
|
+
const ticks = afterComm.split(" ")[19];
|
|
263
|
+
if (!ticks || !/^\d+$/.test(ticks))
|
|
264
|
+
return null;
|
|
265
|
+
// Ticks count from boot, so they repeat across reboots; the boot id scopes
|
|
266
|
+
// them. Rows written before it carry ticks alone and still compare.
|
|
267
|
+
let boot = "";
|
|
268
|
+
try {
|
|
269
|
+
const raw = readFileSync("/proc/sys/kernel/random/boot_id", "utf8")
|
|
270
|
+
.trim()
|
|
271
|
+
.replace(/-/g, "");
|
|
272
|
+
if (/^[0-9a-f]{8,}$/.test(raw))
|
|
273
|
+
boot = `${raw.slice(0, 8)}.`;
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
/* unnamed boot: fall back to the tick-only shape */
|
|
277
|
+
}
|
|
278
|
+
return `l${boot}${ticks}`;
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
try {
|
|
285
|
+
// TZ and locale are pinned because `ps` renders the date through them, and
|
|
286
|
+
// two callers with different environments must not disagree about one
|
|
287
|
+
// process.
|
|
288
|
+
const out = spawnSync("ps", ["-o", "lstart=", "-p", String(pid)], {
|
|
289
|
+
encoding: "utf8",
|
|
290
|
+
timeout: 2000,
|
|
291
|
+
env: { ...process.env, TZ: "UTC", LC_ALL: "C" },
|
|
292
|
+
});
|
|
293
|
+
if (out.status !== 0)
|
|
294
|
+
return null;
|
|
295
|
+
const lstart = (out.stdout ?? "").split("\n")[0]?.trim().replace(/\s+/g, " ");
|
|
296
|
+
return lstart ? `p${lstart}` : null;
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function pidWasRecycled(pid, row) {
|
|
303
|
+
const recorded = parsePidmapRowStartToken(row);
|
|
304
|
+
if (!recorded)
|
|
305
|
+
return false; // pre-token row: unverifiable, behave as before
|
|
306
|
+
const current = pidStartToken(pid);
|
|
307
|
+
if (!current)
|
|
308
|
+
return false;
|
|
309
|
+
if (current === recorded)
|
|
310
|
+
return false;
|
|
311
|
+
// A row predating the boot segment recorded ticks alone; compare it on what
|
|
312
|
+
// it recorded rather than pruning every live row on the first upgraded run.
|
|
313
|
+
if (recorded[0] === "l" &&
|
|
314
|
+
current[0] === "l" &&
|
|
315
|
+
recorded.includes(".") !== current.includes(".")) {
|
|
316
|
+
const ticks = (t) => (t.includes(".") ? t.slice(t.indexOf(".") + 1) : t.slice(1));
|
|
317
|
+
return ticks(recorded) !== ticks(current);
|
|
318
|
+
}
|
|
319
|
+
return true;
|
|
113
320
|
}
|
|
114
321
|
function readPidmapRow(pidmapDir, pid) {
|
|
115
322
|
const candidate = resolve(pidmapDir, String(pid));
|
|
@@ -153,15 +360,43 @@ export function resolveOwnerWithSource() {
|
|
|
153
360
|
const root = monorepoRoot();
|
|
154
361
|
if (!root)
|
|
155
362
|
return { owner: null, source: "none" };
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
-
//
|
|
363
|
+
// Every supported adapter exports its session id into the env of the
|
|
364
|
+
// subprocess it spawns for a tool call, and each heartbeat records the
|
|
365
|
+
// session id it was minted under. Matching the two names us outright, even
|
|
366
|
+
// with many live agents, so it goes ahead of the ppid walk rather than
|
|
367
|
+
// catching what the walk drops. Cursor needed this first because its
|
|
368
|
+
// Glass/Agents UI runs several chats under one node ancestor, making that row
|
|
369
|
+
// last-writer-wins; pid recycling generalises the same hazard to every
|
|
370
|
+
// adapter.
|
|
159
371
|
if (shouldPreferSessionEnv()) {
|
|
160
372
|
const bySession = resolveOwnerBySessionEnv(root);
|
|
161
373
|
if (bySession) {
|
|
162
374
|
return { owner: bySession, source: "session_env" };
|
|
163
375
|
}
|
|
164
376
|
}
|
|
377
|
+
if (!existsSync(resolve(root, ".harnery", "pid-map")))
|
|
378
|
+
return { owner: null, source: "none" };
|
|
379
|
+
const byPidmap = resolveOwnerByPidmap(root);
|
|
380
|
+
if (byPidmap.owner)
|
|
381
|
+
return byPidmap;
|
|
382
|
+
// Last resort: if exactly one agent is live in this coord root, it's
|
|
383
|
+
// unambiguously us — resolve to it. This is what lets the bare `agents
|
|
384
|
+
// status` / `set-task` the stop hook recommends work without a `--session-id`
|
|
385
|
+
// flag in the common single-agent case. With 0 or 2+ live agents it would be
|
|
386
|
+
// a guess, so we stay null and require the explicit flag.
|
|
387
|
+
const singleton = resolveSingleActiveOwner(root);
|
|
388
|
+
if (singleton) {
|
|
389
|
+
return { owner: singleton, source: "active_singleton" };
|
|
390
|
+
}
|
|
391
|
+
return { owner: null, source: "none" };
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Walk our own ppid chain for a pid-map row in ONE given root.
|
|
395
|
+
*
|
|
396
|
+
* Root-parameterized (rather than resolving the root itself) so root resolution
|
|
397
|
+
* can use it as a discriminator without recursing back into itself.
|
|
398
|
+
*/
|
|
399
|
+
export function resolveOwnerByPidmap(root) {
|
|
165
400
|
const pidmapDir = resolve(root, ".harnery", "pid-map");
|
|
166
401
|
if (!existsSync(pidmapDir))
|
|
167
402
|
return { owner: null, source: "none" };
|
|
@@ -172,7 +407,7 @@ export function resolveOwnerWithSource() {
|
|
|
172
407
|
if (pid === null)
|
|
173
408
|
break;
|
|
174
409
|
const row = readPidmapRow(pidmapDir, pid);
|
|
175
|
-
if (row) {
|
|
410
|
+
if (row && !pidWasRecycled(pid, row)) {
|
|
176
411
|
const rowOwner = parsePidmapRowOwner(row);
|
|
177
412
|
const rowPlat = parsePidmapRowPlatform(row);
|
|
178
413
|
if (rowPlat === prefer) {
|
|
@@ -186,31 +421,11 @@ export function resolveOwnerWithSource() {
|
|
|
186
421
|
if (fallbackOwner) {
|
|
187
422
|
return { owner: fallbackOwner, source: "pidmap_fallback" };
|
|
188
423
|
}
|
|
189
|
-
// The ppid walk found nothing (e.g. a Bash-tool subshell whose process tree
|
|
190
|
-
// doesn't climb back to the harness anchor). Before guessing, try the
|
|
191
|
-
// harness-provided session id from the environment: every supported harness
|
|
192
|
-
// exports its session id into the tool subprocess env, and each heartbeat
|
|
193
|
-
// records the `session_id` it was minted under. Matching the two resolves us
|
|
194
|
-
// unambiguously even with multiple live agents, which is the case the
|
|
195
|
-
// singleton fallback below cannot handle.
|
|
196
|
-
const bySession = resolveOwnerBySessionEnv(root);
|
|
197
|
-
if (bySession) {
|
|
198
|
-
return { owner: bySession, source: "session_env" };
|
|
199
|
-
}
|
|
200
|
-
// Last resort: if exactly one agent is live in this coord root, it's
|
|
201
|
-
// unambiguously us — resolve to it. This is what lets the bare `agents
|
|
202
|
-
// status` / `set-task` the stop hook recommends work without a `--session-id`
|
|
203
|
-
// flag in the common single-agent case. With 0 or 2+ live agents it would be
|
|
204
|
-
// a guess, so we stay null and require the explicit flag.
|
|
205
|
-
const singleton = resolveSingleActiveOwner(root);
|
|
206
|
-
if (singleton) {
|
|
207
|
-
return { owner: singleton, source: "active_singleton" };
|
|
208
|
-
}
|
|
209
424
|
return { owner: null, source: "none" };
|
|
210
425
|
}
|
|
211
426
|
/**
|
|
212
|
-
*
|
|
213
|
-
* supported
|
|
427
|
+
* Adapter-exported session-id environment variables, in precedence order. Each
|
|
428
|
+
* supported adapter propagates its session id into the env of the subprocess it
|
|
214
429
|
* spawns for a tool call (Claude Code's Bash tool, Cursor's terminal, Codex's
|
|
215
430
|
* shell). A coord CLI invoked as such a tool can therefore recover its own
|
|
216
431
|
* identity from the env even when the ppid walk misses.
|
|
@@ -225,7 +440,7 @@ const SESSION_ID_ENV_VARS = [
|
|
|
225
440
|
"CURSOR_CONVERSATION_ID",
|
|
226
441
|
"CODEX_SESSION_ID",
|
|
227
442
|
];
|
|
228
|
-
/** Read normalized candidates from the first non-empty
|
|
443
|
+
/** Read normalized candidates from the first non-empty adapter session-id env var. */
|
|
229
444
|
function sessionIdsFromEnv() {
|
|
230
445
|
for (const key of SESSION_ID_ENV_VARS) {
|
|
231
446
|
const v = process.env[key]?.trim();
|
|
@@ -238,18 +453,31 @@ function sessionIdsFromEnv() {
|
|
|
238
453
|
}
|
|
239
454
|
return [];
|
|
240
455
|
}
|
|
241
|
-
/** Read the first non-empty
|
|
456
|
+
/** Read the first non-empty adapter session-id env var, or null. */
|
|
242
457
|
function sessionIdFromEnv() {
|
|
243
458
|
return sessionIdsFromEnv()[0] ?? null;
|
|
244
459
|
}
|
|
460
|
+
/**
|
|
461
|
+
* Should the adapter-exported session id be consulted before the ppid walk?
|
|
462
|
+
*
|
|
463
|
+
* Yes, whenever one is exported. The env var is the adapter stating its own
|
|
464
|
+
* identity; the walk is a guess over a namespace the OS recycles. On a box with
|
|
465
|
+
* `pid_max` of 99999 and ~100 pids allocated per second the whole pid space
|
|
466
|
+
* turns over about every quarter hour, so a row written before that can name a
|
|
467
|
+
* pid some unrelated process now holds. Pruning cannot save the walk here:
|
|
468
|
+
* it removes rows whose pid is dead, and a recycled pid is alive. Letting a
|
|
469
|
+
* guess outrank a statement of fact is what made `agents whoami` report another
|
|
470
|
+
* agent's name and file list.
|
|
471
|
+
*
|
|
472
|
+
* This only reorders the two. Session-env resolution still requires a live
|
|
473
|
+
* heartbeat carrying that session id, so when it does not match, the walk runs
|
|
474
|
+
* exactly as before.
|
|
475
|
+
*/
|
|
245
476
|
function shouldPreferSessionEnv() {
|
|
246
|
-
|
|
247
|
-
return false;
|
|
248
|
-
const platform = process.env.HARNERY_AGENT_COORD_PLATFORM?.trim();
|
|
249
|
-
return process.env.CURSOR_AGENT === "1" || platform === "cursor";
|
|
477
|
+
return sessionIdFromEnv() !== null;
|
|
250
478
|
}
|
|
251
479
|
/**
|
|
252
|
-
* Resolve the owner by matching the
|
|
480
|
+
* Resolve the owner by matching the adapter session-id env var against the
|
|
253
481
|
* `session_id` of a live heartbeat in this coord root. Returns the matching
|
|
254
482
|
* `instance_id`, or null if there's no session-id env var or no live heartbeat
|
|
255
483
|
* carries it. "Live" reuses the same 10-minute freshness window the singleton
|
|
@@ -5,12 +5,12 @@
|
|
|
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
|
declare const SCHEMA_VERSION: 1;
|
|
12
|
-
export type
|
|
13
|
-
|
|
12
|
+
export type { Adapter, Source } from "../../hooks/events/schema.js";
|
|
13
|
+
import type { Adapter, Source } from "../../hooks/events/schema.js";
|
|
14
14
|
export interface Envelope {
|
|
15
15
|
schema_version: typeof SCHEMA_VERSION;
|
|
16
16
|
event_id: string;
|
|
@@ -21,7 +21,7 @@ export interface Envelope {
|
|
|
21
21
|
parent_session_id?: string;
|
|
22
22
|
turn_id?: string;
|
|
23
23
|
parent_turn_id?: string;
|
|
24
|
-
|
|
24
|
+
adapter: Adapter;
|
|
25
25
|
source: Source;
|
|
26
26
|
data: Record<string, unknown>;
|
|
27
27
|
}
|
|
@@ -29,7 +29,7 @@ export interface EmitInput {
|
|
|
29
29
|
event_type: string;
|
|
30
30
|
instance_id: string;
|
|
31
31
|
session_id: string;
|
|
32
|
-
|
|
32
|
+
adapter: Adapter;
|
|
33
33
|
source?: Source;
|
|
34
34
|
parent_session_id?: string;
|
|
35
35
|
turn_id?: string;
|
|
@@ -39,5 +39,4 @@ export interface EmitInput {
|
|
|
39
39
|
}
|
|
40
40
|
export declare function buildEnvelope(input: EmitInput): Envelope;
|
|
41
41
|
export declare function emit(coordRoot: string, input: EmitInput): Envelope;
|
|
42
|
-
export {};
|
|
43
42
|
//# sourceMappingURL=emit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../../src/core/agents/events/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,QAAA,MAAM,cAAc,EAAG,CAAU,CAAC;AAKlC,
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../../src/core/agents/events/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,QAAA,MAAM,cAAc,EAAG,CAAU,CAAC;AAKlC,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAEpE,MAAM,WAAW,QAAQ;IACvB,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,CAexD;AAED,wBAAgB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,QAAQ,CA4BlE"}
|
|
@@ -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
|
import { appendFileSync, closeSync, mkdirSync, openSync } from "node:fs";
|
|
@@ -27,7 +27,7 @@ export function buildEnvelope(input) {
|
|
|
27
27
|
parent_session_id: input.parent_session_id,
|
|
28
28
|
turn_id: input.turn_id,
|
|
29
29
|
parent_turn_id: input.parent_turn_id,
|
|
30
|
-
|
|
30
|
+
adapter: input.adapter,
|
|
31
31
|
source: input.source ?? "agent-coord",
|
|
32
32
|
data: input.data,
|
|
33
33
|
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Resolve the coordination root.
|
|
3
|
+
*
|
|
4
|
+
* Delegates to `resolveCoordRoot()`. This was a third, independent copy of the
|
|
5
|
+
* walk-up — the kind of duplication that let the hooks and the CLI drift onto
|
|
6
|
+
* different roots in the first place; keep resolution in one place.
|
|
4
7
|
*/
|
|
5
8
|
export declare function findCoordRoot(start?: string): string | null;
|
|
6
9
|
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/core/agents/paths.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/core/agents/paths.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CAE1E"}
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { dirname, join, resolve } from "node:path";
|
|
1
|
+
import { resolveCoordRoot } from "./coord-client.js";
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Resolve the coordination root.
|
|
4
|
+
*
|
|
5
|
+
* Delegates to `resolveCoordRoot()`. This was a third, independent copy of the
|
|
6
|
+
* walk-up — the kind of duplication that let the hooks and the CLI drift onto
|
|
7
|
+
* different roots in the first place; keep resolution in one place.
|
|
6
8
|
*/
|
|
7
9
|
export function findCoordRoot(start = process.cwd()) {
|
|
8
|
-
|
|
9
|
-
while (true) {
|
|
10
|
-
if (existsSync(join(dir, ".harnery")))
|
|
11
|
-
return dir;
|
|
12
|
-
const parent = dirname(dir);
|
|
13
|
-
if (parent === dir)
|
|
14
|
-
return null;
|
|
15
|
-
dir = parent;
|
|
16
|
-
}
|
|
10
|
+
return resolveCoordRoot(start);
|
|
17
11
|
}
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* UserPromptSubmit UX renderer. Combines the peer-refresh dedup, the
|
|
3
|
-
* council-pending hash-dedup,
|
|
3
|
+
* council-pending hash-dedup, the cross-adapter first-session naming nudge,
|
|
4
|
+
* the Cursor/Codex set-task staleness nudge, and the Codex status-footer
|
|
5
|
+
* reminder.
|
|
4
6
|
* agent-hook's user_prompt.submit post-emit handler calls this
|
|
5
|
-
* and forwards the result as the
|
|
7
|
+
* and forwards the result as the adapter-shaped additionalContext payload.
|
|
6
8
|
*
|
|
7
|
-
*
|
|
9
|
+
* Four subsections combined into one additionalContext payload:
|
|
8
10
|
* 1. Peer table: semantically-relevant peer fields hashed; only re-emits
|
|
9
11
|
* when peers change (name + instance_id + session_id + kind + started_at
|
|
10
12
|
* + sorted(files_touched) + platform, sorted by instance_id).
|
|
11
13
|
* 2. Council pending: pending open-council IDs hashed; re-emits when the
|
|
12
14
|
* ID set changes.
|
|
13
|
-
* 3.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* 3. Focus nudge. Before the first set-task in a human-facing session, tells
|
|
16
|
+
* every adapter to reproduce set-task's suggested session name in a fenced
|
|
17
|
+
* code block. Cursor/Codex additionally get the existing unset/stale-task
|
|
18
|
+
* reminder because their Stop hooks do not enforce task declarations as
|
|
19
|
+
* reliably as Claude Code's.
|
|
20
|
+
* 4. Codex status footer: a non-deduplicated reminder to put the live status
|
|
21
|
+
* box after the substantive answer. Stop stays observe-only, so missing the
|
|
22
|
+
* footer can never trigger a replacement response.
|
|
17
23
|
*
|
|
18
24
|
* Hash files live at:
|
|
19
25
|
* .harnery/.last-peer-hash.<instance_id>
|
|
@@ -27,9 +33,15 @@ export interface PromptContextOpts {
|
|
|
27
33
|
instanceId: string;
|
|
28
34
|
sessionId: string;
|
|
29
35
|
agentName?: string;
|
|
30
|
-
/** When true,
|
|
31
|
-
*
|
|
36
|
+
/** When true, remind a human-facing session to print the session name before
|
|
37
|
+
* its first set-task. UserPromptSubmit enables this for every adapter. */
|
|
38
|
+
sessionNameNudge?: boolean;
|
|
39
|
+
/** When true, run the unset/stale-task check after the first set-task.
|
|
40
|
+
* Cursor/Codex use this; Claude Code has Stop-hook transcript enforcement. */
|
|
32
41
|
taskNudge?: boolean;
|
|
42
|
+
/** When true, append the non-deduplicated Codex status-footer reminder.
|
|
43
|
+
* The caller enables this only for human-facing Codex sessions. */
|
|
44
|
+
statusFooterNudge?: boolean;
|
|
33
45
|
}
|
|
34
46
|
/**
|
|
35
47
|
* Build the combined UserPromptSubmit additionalContext string. Returns "" when
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-context.d.ts","sourceRoot":"","sources":["../../../../src/core/agents/render/prompt-context.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"prompt-context.d.ts","sourceRoot":"","sources":["../../../../src/core/agents/render/prompt-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAoCH,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;8EAC0E;IAC1E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;kFAC8E;IAC9E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;uEACmE;IACnE,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CA0CnE"}
|