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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Council manifest helpers: file-based multi-agent coordination primitives.
|
|
3
3
|
*
|
|
4
|
-
* Lives under .harnery/councils/ alongside heartbeats +
|
|
4
|
+
* Lives under .harnery/councils/ alongside heartbeats + journals. Council
|
|
5
5
|
* lifecycle commands serialize manifest mutations through a shared flock;
|
|
6
6
|
* round contribution files are per-member and don't need shared locking.
|
|
7
7
|
*/
|
|
@@ -176,7 +176,7 @@ export function setCouncilSteward(councilId, steward) {
|
|
|
176
176
|
* next-app's same-named constant. */
|
|
177
177
|
const KNOWN_AGENT_STALE_WINDOW_MS = 30 * 24 * 60 * 60 * 1000;
|
|
178
178
|
/**
|
|
179
|
-
* Active heartbeats + recently-archived
|
|
179
|
+
* Active heartbeats + recently-archived journals, deduped by name.
|
|
180
180
|
* Used by `agents council set-steward` to refuse arbitrary names;
|
|
181
181
|
* pass `--allow-unknown` to bypass when bootstrapping a new agent.
|
|
182
182
|
*/
|
|
@@ -185,7 +185,7 @@ export function listKnownAgents() {
|
|
|
185
185
|
if (!root)
|
|
186
186
|
return [];
|
|
187
187
|
const activeDir = resolve(root, ".harnery", "active");
|
|
188
|
-
const archiveDir = resolve(root, ".harnery", "
|
|
188
|
+
const archiveDir = resolve(root, ".harnery", "journal", "archived");
|
|
189
189
|
const byName = new Map();
|
|
190
190
|
if (existsSync(activeDir)) {
|
|
191
191
|
for (const f of readdirSync(activeDir)) {
|
|
@@ -220,7 +220,7 @@ export function listKnownAgents() {
|
|
|
220
220
|
continue;
|
|
221
221
|
try {
|
|
222
222
|
const head = readFileSync(resolve(archiveDir, f), "utf8").slice(0, 200);
|
|
223
|
-
const nameMatch = head.match(/^#\s+
|
|
223
|
+
const nameMatch = head.match(/^#\s+Journal:\s+(agent-[A-Za-z][A-Za-z0-9_-]*)/m);
|
|
224
224
|
if (!nameMatch)
|
|
225
225
|
continue;
|
|
226
226
|
const name = nameMatch[1];
|
|
@@ -504,7 +504,7 @@ export function writeContribution(councilId, round, memberName, body) {
|
|
|
504
504
|
* Path to the round-N prompts directory: `.harnery/councils/<id>/round-N/prompts/`.
|
|
505
505
|
* Sibling to the contribution files. Holds one `<member>.md` per non-self
|
|
506
506
|
* council member, drafted by the steward, read by the operator (copy-paste
|
|
507
|
-
* into each agent
|
|
507
|
+
* into each agent adapter) and the web UI (per-member panel).
|
|
508
508
|
*/
|
|
509
509
|
export function promptsDir(councilId, round) {
|
|
510
510
|
const rd = roundDir(councilId, round);
|
|
@@ -549,9 +549,9 @@ const SUBMIT_FOOTER_MARKER = "<!-- council-submit-footer -->";
|
|
|
549
549
|
* Build the submit footer appended to every steward-drafted prompt. This is the
|
|
550
550
|
* load-bearing instruction that a contribution composed in chat is NOT recorded;
|
|
551
551
|
* the agent must run the command below. It rides on the prompt (the one
|
|
552
|
-
* artifact the operator always pastes) so it reaches every
|
|
552
|
+
* artifact the operator always pastes) so it reaches every adapter regardless of
|
|
553
553
|
* whether the convene-time invitation was delivered or a `/council` skill is
|
|
554
|
-
* available. Without it, agents (esp. non-Claude
|
|
554
|
+
* available. Without it, agents (esp. non-Claude adapters with no skill) write
|
|
555
555
|
* their take as a reply and end the turn, leaving the council showing them as
|
|
556
556
|
* still-pending. Visible markdown (not an HTML comment) so the agent reads it.
|
|
557
557
|
*/
|
|
@@ -567,7 +567,7 @@ export function buildSubmitFooter(councilId) {
|
|
|
567
567
|
`# longer write-up? ${bin} agents council contribute ${councilId} --file <path>`,
|
|
568
568
|
"```",
|
|
569
569
|
"",
|
|
570
|
-
'_(Or invoke the `council` skill in your
|
|
570
|
+
'_(Or invoke the `council` skill in your adapter: `/council contribute` in Claude Code, `$council` / "use the council skill" in Codex/Cursor, for the same flow with routing guards.)_',
|
|
571
571
|
].join("\n");
|
|
572
572
|
}
|
|
573
573
|
/** Strip an appended submit footer from a prompt body, if present. */
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Local collision policy: a fresh heartbeat alone is not enough to block.
|
|
10
10
|
* If the namesake has no live pid-map process (crashed session, healed
|
|
11
|
-
* zombie, or abandoned
|
|
11
|
+
* zombie, or abandoned adapter), reclaim that heartbeat and continue.
|
|
12
12
|
* Refuse only when another process is still alive, or when cached remote
|
|
13
13
|
* presence reports the name.
|
|
14
14
|
*/
|
|
@@ -40,7 +40,7 @@ export interface IdentityAssumeResult {
|
|
|
40
40
|
* presence. No network call occurs; absent presence degrades to local-only. */
|
|
41
41
|
export declare function findIdentityConflict(coordRoot: string, instanceId: string, name: string, nowMs?: number): IdentityConflict | null;
|
|
42
42
|
/**
|
|
43
|
-
* Drop a local namesake whose
|
|
43
|
+
* Drop a local namesake whose adapter process is gone. Fresh heartbeats can
|
|
44
44
|
* linger after a crash (or after heartbeat heal without a live pid-map), and
|
|
45
45
|
* `identity assume` is the supported takeover path — operators should not
|
|
46
46
|
* need a separate kill/sweep step.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Local collision policy: a fresh heartbeat alone is not enough to block.
|
|
10
10
|
* If the namesake has no live pid-map process (crashed session, healed
|
|
11
|
-
* zombie, or abandoned
|
|
11
|
+
* zombie, or abandoned adapter), reclaim that heartbeat and continue.
|
|
12
12
|
* Refuse only when another process is still alive, or when cached remote
|
|
13
13
|
* presence reports the name.
|
|
14
14
|
*/
|
|
@@ -78,7 +78,7 @@ export function findIdentityConflict(coordRoot, instanceId, name, nowMs = Date.n
|
|
|
78
78
|
return null;
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
* Drop a local namesake whose
|
|
81
|
+
* Drop a local namesake whose adapter process is gone. Fresh heartbeats can
|
|
82
82
|
* linger after a crash (or after heartbeat heal without a live pid-map), and
|
|
83
83
|
* `identity assume` is the supported takeover path — operators should not
|
|
84
84
|
* need a separate kill/sweep step.
|
|
@@ -89,13 +89,13 @@ export function reclaimAbandonedLocalConflict(coordRoot, conflict) {
|
|
|
89
89
|
if (instanceHasLivePid(coordRoot, conflict.instance_id))
|
|
90
90
|
return false;
|
|
91
91
|
const hbPath = join(coordRoot, ".harnery", "active", `${conflict.instance_id}.json`);
|
|
92
|
-
let
|
|
92
|
+
let adapter = "claude-code";
|
|
93
93
|
let sessionId = conflict.instance_id;
|
|
94
94
|
let ageSecs;
|
|
95
95
|
if (existsSync(hbPath)) {
|
|
96
96
|
try {
|
|
97
97
|
const hb = JSON.parse(readFileSync(hbPath, "utf8"));
|
|
98
|
-
|
|
98
|
+
adapter = adapterOf(hb.platform);
|
|
99
99
|
sessionId = hb.session_id || conflict.instance_id;
|
|
100
100
|
const ts = Date.parse(hb.last_heartbeat);
|
|
101
101
|
if (Number.isFinite(ts))
|
|
@@ -117,7 +117,7 @@ export function reclaimAbandonedLocalConflict(coordRoot, conflict) {
|
|
|
117
117
|
event_type: "health.heartbeat_swept",
|
|
118
118
|
instance_id: conflict.instance_id,
|
|
119
119
|
session_id: sessionId,
|
|
120
|
-
|
|
120
|
+
adapter,
|
|
121
121
|
source: "agent-coord",
|
|
122
122
|
data: {
|
|
123
123
|
reason: "stale",
|
|
@@ -186,7 +186,7 @@ function acquireLock(coordRoot) {
|
|
|
186
186
|
}
|
|
187
187
|
throw new IdentityAssumeError("identity_busy", "another identity assumption is in progress; retry in a moment");
|
|
188
188
|
}
|
|
189
|
-
function
|
|
189
|
+
function adapterOf(platform) {
|
|
190
190
|
if (platform === "cursor")
|
|
191
191
|
return "cursor";
|
|
192
192
|
if (platform === "codex")
|
|
@@ -239,7 +239,7 @@ export function assumeIdentity(coordRoot, instanceId, target) {
|
|
|
239
239
|
event_type: "identity.assumed",
|
|
240
240
|
instance_id: instanceId,
|
|
241
241
|
session_id: hb.session_id,
|
|
242
|
-
|
|
242
|
+
adapter: adapterOf(hb.platform),
|
|
243
243
|
data: {
|
|
244
244
|
name: identity.name,
|
|
245
245
|
agent_id: identity.agent_id,
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
export declare function readSkillsExclude(projectRoot: string): Set<string>;
|
|
22
22
|
interface ApplyOpts {
|
|
23
23
|
binName: string;
|
|
24
|
-
|
|
24
|
+
adapter: string;
|
|
25
25
|
dryRun: boolean;
|
|
26
26
|
}
|
|
27
27
|
export interface ApplyResult {
|
|
@@ -35,7 +35,7 @@ export interface ApplyResult {
|
|
|
35
35
|
*/
|
|
36
36
|
export declare function applyInstructions(projectRoot: string, opts: ApplyOpts): ApplyResult;
|
|
37
37
|
interface RemoveOpts {
|
|
38
|
-
|
|
38
|
+
adapter: string;
|
|
39
39
|
dryRun: boolean;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
@@ -57,7 +57,7 @@ export interface CheckResult {
|
|
|
57
57
|
*/
|
|
58
58
|
export declare function checkInstructions(projectRoot: string, opts: {
|
|
59
59
|
binName: string;
|
|
60
|
-
|
|
60
|
+
adapter: string;
|
|
61
61
|
}): CheckResult;
|
|
62
62
|
export {};
|
|
63
63
|
//# sourceMappingURL=apply.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/lib/instructions/apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../src/lib/instructions/apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AA8CH,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAYlE;AAiBD,UAAU,SAAS;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,WAAW,CA8GnF;AAED,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,WAAW,CAiFrF;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IACpC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzC,WAAW,CAiDb"}
|
|
@@ -20,8 +20,9 @@
|
|
|
20
20
|
import { existsSync, mkdirSync, readdirSync, readFileSync, rmdirSync, rmSync, writeFileSync, } from "node:fs";
|
|
21
21
|
import { dirname, join } from "node:path";
|
|
22
22
|
import { stripJsonComments } from "../../core/config.js";
|
|
23
|
+
import { readHostAddendum } from "./host-addendum.js";
|
|
23
24
|
import { checkOwnedSkill, checkRegion, isOwnedFile, removeRegion, spliceRegion, } from "./splice.js";
|
|
24
|
-
import { IMPORT_REGION, INSTRUCTIONS_REGION, renderInstructionsBlock, SKILLS, } from "./templates.js";
|
|
25
|
+
import { HOST_ADDENDUM_REGION, IMPORT_REGION, INSTRUCTIONS_REGION, renderInstructionsBlock, SKILLS, } from "./templates.js";
|
|
25
26
|
const AGENTS_FILE = "AGENTS.md";
|
|
26
27
|
const CLAUDE_FILE = "CLAUDE.md";
|
|
27
28
|
const CLAUDE_SKILLS_DIR = join(".claude", "skills");
|
|
@@ -54,8 +55,8 @@ export function readSkillsExclude(projectRoot) {
|
|
|
54
55
|
* codex get the block but no skill files, so both read false there. Kept in one
|
|
55
56
|
* place so `applyInstructions` and `checkInstructions` render byte-identical blocks.
|
|
56
57
|
*/
|
|
57
|
-
function blockSkills(projectRoot,
|
|
58
|
-
const claudeCode =
|
|
58
|
+
function blockSkills(projectRoot, adapter) {
|
|
59
|
+
const claudeCode = adapter === "claude-code";
|
|
59
60
|
const exclude = readSkillsExclude(projectRoot);
|
|
60
61
|
return {
|
|
61
62
|
decide: claudeCode && !exclude.has("harn-decide"),
|
|
@@ -70,28 +71,57 @@ function blockSkills(projectRoot, harness) {
|
|
|
70
71
|
export function applyInstructions(projectRoot, opts) {
|
|
71
72
|
const actions = [];
|
|
72
73
|
const warnings = [];
|
|
73
|
-
const claudeCode = opts.
|
|
74
|
+
const claudeCode = opts.adapter === "claude-code";
|
|
74
75
|
// dry-run narrates the future ("would create"); a real run narrates the past.
|
|
75
76
|
const verbed = (base, past) => (opts.dryRun ? `would ${base}` : past);
|
|
77
|
+
// Resolve the host addendum before touching a single file, so a bad path
|
|
78
|
+
// aborts the whole run instead of leaving AGENTS.md half-updated.
|
|
79
|
+
const addendum = readHostAddendum(projectRoot);
|
|
76
80
|
// ── AGENTS.md orientation block ─────────────────────────────────────────
|
|
77
81
|
const agentsPath = join(projectRoot, AGENTS_FILE);
|
|
78
82
|
const agentsExisted = existsSync(agentsPath);
|
|
79
83
|
const agentsBefore = agentsExisted ? readFileSync(agentsPath, "utf8") : "";
|
|
80
|
-
const body = renderInstructionsBlock(opts.binName, blockSkills(projectRoot, opts.
|
|
84
|
+
const body = renderInstructionsBlock(opts.binName, blockSkills(projectRoot, opts.adapter));
|
|
81
85
|
const spliced = spliceRegion(agentsBefore, INSTRUCTIONS_REGION, body);
|
|
82
86
|
if (!spliced.changed) {
|
|
83
87
|
actions.push(`· ${AGENTS_FILE} instructions block already current`);
|
|
84
88
|
}
|
|
89
|
+
else if (!agentsExisted) {
|
|
90
|
+
actions.push(`+ ${verbed("create", "created")} ${AGENTS_FILE} with the instructions block`);
|
|
91
|
+
}
|
|
92
|
+
else if (!spliced.had) {
|
|
93
|
+
actions.push(`+ ${verbed("inject", "injected")} the instructions block into ${AGENTS_FILE}`);
|
|
94
|
+
}
|
|
85
95
|
else {
|
|
86
|
-
|
|
87
|
-
writeFileSync(agentsPath, spliced.text);
|
|
88
|
-
if (!agentsExisted)
|
|
89
|
-
actions.push(`+ ${verbed("create", "created")} ${AGENTS_FILE} with the instructions block`);
|
|
90
|
-
else if (!spliced.had)
|
|
91
|
-
actions.push(`+ ${verbed("inject", "injected")} the instructions block into ${AGENTS_FILE}`);
|
|
92
|
-
else
|
|
93
|
-
actions.push(`~ ${verbed("update", "updated")} the instructions block in ${AGENTS_FILE}`);
|
|
96
|
+
actions.push(`~ ${verbed("update", "updated")} the instructions block in ${AGENTS_FILE}`);
|
|
94
97
|
}
|
|
98
|
+
// ── host addendum (a second region, content the host owns) ──────────────
|
|
99
|
+
// Harnery places and versions it; what it says is none of harnery's business.
|
|
100
|
+
// No configured source means any region left behind belongs to a config entry
|
|
101
|
+
// that has since been deleted, so init takes it back out.
|
|
102
|
+
let agentsAfter = spliced.text;
|
|
103
|
+
if (addendum.configured) {
|
|
104
|
+
const withAddendum = spliceRegion(agentsAfter, HOST_ADDENDUM_REGION, addendum.body);
|
|
105
|
+
agentsAfter = withAddendum.text;
|
|
106
|
+
if (!withAddendum.changed) {
|
|
107
|
+
actions.push(`· ${AGENTS_FILE} host addendum already current (${addendum.relPath})`);
|
|
108
|
+
}
|
|
109
|
+
else if (!withAddendum.had) {
|
|
110
|
+
actions.push(`+ ${verbed("splice", "spliced")} the host addendum into ${AGENTS_FILE} (${addendum.relPath})`);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
actions.push(`~ ${verbed("update", "updated")} the host addendum in ${AGENTS_FILE} (${addendum.relPath})`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const dropped = removeRegion(agentsAfter, HOST_ADDENDUM_REGION);
|
|
118
|
+
if (dropped.removed) {
|
|
119
|
+
agentsAfter = dropped.text;
|
|
120
|
+
actions.push(`+ ${verbed("remove", "removed")} the host addendum from ${AGENTS_FILE} (no longer configured)`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (!opts.dryRun && agentsAfter !== agentsBefore)
|
|
124
|
+
writeFileSync(agentsPath, agentsAfter);
|
|
95
125
|
// ── CLAUDE.md import shim (claude-code only) ────────────────────────────
|
|
96
126
|
if (claudeCode) {
|
|
97
127
|
const claudePath = join(projectRoot, CLAUDE_FILE);
|
|
@@ -150,23 +180,32 @@ export function applyInstructions(projectRoot, opts) {
|
|
|
150
180
|
export function removeInstructions(projectRoot, opts) {
|
|
151
181
|
const actions = [];
|
|
152
182
|
const warnings = [];
|
|
153
|
-
const claudeCode = opts.
|
|
154
|
-
// ── AGENTS.md block
|
|
183
|
+
const claudeCode = opts.adapter === "claude-code";
|
|
184
|
+
// ── AGENTS.md block + host addendum ─────────────────────────────────────
|
|
155
185
|
const agentsPath = join(projectRoot, AGENTS_FILE);
|
|
156
186
|
if (existsSync(agentsPath)) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
187
|
+
// Both regions are harnery-placed, so deinit leaves neither behind. The
|
|
188
|
+
// addendum's *source file* is the host's and stays where it is.
|
|
189
|
+
const addendumGone = removeRegion(readFileSync(agentsPath, "utf8"), HOST_ADDENDUM_REGION);
|
|
190
|
+
if (addendumGone.removed) {
|
|
191
|
+
actions.push(`+ ${opts.dryRun ? "would remove" : "removed"} the host addendum from ${AGENTS_FILE}`);
|
|
160
192
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
actions.push(`+ ${opts.dryRun ? "would remove" : "removed"} ${AGENTS_FILE} (was block-only)`);
|
|
193
|
+
const { text, removed } = removeRegion(addendumGone.text, INSTRUCTIONS_REGION);
|
|
194
|
+
if (removed) {
|
|
195
|
+
actions.push(`+ ${opts.dryRun ? "would remove" : "removed"} the instructions block from ${AGENTS_FILE}`);
|
|
165
196
|
}
|
|
166
|
-
else {
|
|
167
|
-
|
|
197
|
+
else if (!addendumGone.removed) {
|
|
198
|
+
actions.push(`· no instructions block in ${AGENTS_FILE}`);
|
|
199
|
+
}
|
|
200
|
+
if (removed || addendumGone.removed) {
|
|
201
|
+
if (text === "") {
|
|
202
|
+
if (!opts.dryRun)
|
|
203
|
+
rmSync(agentsPath);
|
|
204
|
+
actions.push(`+ ${opts.dryRun ? "would remove" : "removed"} ${AGENTS_FILE} (nothing left but ours)`);
|
|
205
|
+
}
|
|
206
|
+
else if (!opts.dryRun) {
|
|
168
207
|
writeFileSync(agentsPath, text);
|
|
169
|
-
|
|
208
|
+
}
|
|
170
209
|
}
|
|
171
210
|
}
|
|
172
211
|
// ── CLAUDE.md import shim (claude-code) ─────────────────────────────────
|
|
@@ -233,8 +272,17 @@ export function checkInstructions(projectRoot, opts) {
|
|
|
233
272
|
try {
|
|
234
273
|
const agentsPath = join(projectRoot, AGENTS_FILE);
|
|
235
274
|
const content = existsSync(agentsPath) ? readFileSync(agentsPath, "utf8") : "";
|
|
236
|
-
note(`${AGENTS_FILE} block`, checkRegion(content, INSTRUCTIONS_REGION, renderInstructionsBlock(opts.binName, blockSkills(projectRoot, opts.
|
|
237
|
-
|
|
275
|
+
note(`${AGENTS_FILE} block`, checkRegion(content, INSTRUCTIONS_REGION, renderInstructionsBlock(opts.binName, blockSkills(projectRoot, opts.adapter))));
|
|
276
|
+
// A configured addendum is checked against its source; an unconfigured one
|
|
277
|
+
// still sitting in the file is drift too, since init would take it out.
|
|
278
|
+
const addendum = readHostAddendum(projectRoot);
|
|
279
|
+
if (addendum.configured) {
|
|
280
|
+
note(`${AGENTS_FILE} host addendum (${addendum.relPath})`, checkRegion(content, HOST_ADDENDUM_REGION, addendum.body));
|
|
281
|
+
}
|
|
282
|
+
else if (checkRegion(content, HOST_ADDENDUM_REGION, "") !== "missing") {
|
|
283
|
+
issues.push(`${AGENTS_FILE} host addendum: present but no longer configured (re-run init)`);
|
|
284
|
+
}
|
|
285
|
+
if (opts.adapter === "claude-code") {
|
|
238
286
|
const exclude = readSkillsExclude(projectRoot);
|
|
239
287
|
for (const skill of SKILLS) {
|
|
240
288
|
if (exclude.has(skill.id))
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The host addendum: a second managed region whose *content* belongs to the
|
|
3
|
+
* consumer.
|
|
4
|
+
*
|
|
5
|
+
* Harnery's orientation block is deliberately generic, because it ships to
|
|
6
|
+
* every consumer (ADR 0007's portability split, ADR 0008's ~80-line budget). A
|
|
7
|
+
* project with real coordination policy of its own therefore had nowhere
|
|
8
|
+
* machine-managed to put it, and ended up hand-maintaining it next to the
|
|
9
|
+
* block, where nothing kept the two in step.
|
|
10
|
+
*
|
|
11
|
+
* The fix is declarative rather than programmatic. A consumer names a file:
|
|
12
|
+
*
|
|
13
|
+
* // .harnery/config.jsonc
|
|
14
|
+
* { "instructions": { "hostAddendumFile": ".agents/host-instructions.md" } }
|
|
15
|
+
*
|
|
16
|
+
* and harnery gives that file's contents the same lifecycle as its own block:
|
|
17
|
+
* spliced on `init`, refreshed when the file changes, reported by
|
|
18
|
+
* `init --check`, removed by `deinit` or by deleting the config entry. Harnery
|
|
19
|
+
* never parses, renders, or reasons about what the file says, which is what
|
|
20
|
+
* keeps the arrangement portable: the mechanism is generic even though every
|
|
21
|
+
* consumer's content is not.
|
|
22
|
+
*
|
|
23
|
+
* Exposing the splicer as a public primitive instead would have pushed the
|
|
24
|
+
* whole lifecycle onto each host, since `init` and `deinit` are registered
|
|
25
|
+
* inside harnery and every consumer would have had to wrap or replace them and
|
|
26
|
+
* reimplement apply, check, and remove. The config key keeps one implementation
|
|
27
|
+
* of all four.
|
|
28
|
+
*
|
|
29
|
+
* Every failure here is raised before the caller writes anything.
|
|
30
|
+
*/
|
|
31
|
+
/** Dotted config key naming the addendum source, quoted in every error. */
|
|
32
|
+
export declare const HOST_ADDENDUM_KEY = "instructions.hostAddendumFile";
|
|
33
|
+
/** A host addendum that cannot be used. Callers abort before writing. */
|
|
34
|
+
export declare class HostAddendumError extends Error {
|
|
35
|
+
constructor(message: string);
|
|
36
|
+
}
|
|
37
|
+
export type HostAddendum = {
|
|
38
|
+
configured: false;
|
|
39
|
+
} | {
|
|
40
|
+
configured: true;
|
|
41
|
+
relPath: string;
|
|
42
|
+
body: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the configured addendum, or report that there is none.
|
|
46
|
+
*
|
|
47
|
+
* Absent config, absent key, and explicit `null` all mean "not configured",
|
|
48
|
+
* which is how a consumer turns the addendum off: delete the key and re-run
|
|
49
|
+
* `init`. Anything else that cannot become a readable file inside the project
|
|
50
|
+
* throws, because the alternative is an agent-facing instruction file that
|
|
51
|
+
* quietly lost a section the host believes is still there.
|
|
52
|
+
*/
|
|
53
|
+
export declare function readHostAddendum(projectRoot: string): HostAddendum;
|
|
54
|
+
//# sourceMappingURL=host-addendum.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-addendum.d.ts","sourceRoot":"","sources":["../../../src/lib/instructions/host-addendum.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAMH,2EAA2E;AAC3E,eAAO,MAAM,iBAAiB,kCAAkC,CAAC;AAEjE,yEAAyE;AACzE,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,UAAU,EAAE,KAAK,CAAA;CAAE,GACrB;IAAE,UAAU,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,YAAY,CAmDlE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The host addendum: a second managed region whose *content* belongs to the
|
|
3
|
+
* consumer.
|
|
4
|
+
*
|
|
5
|
+
* Harnery's orientation block is deliberately generic, because it ships to
|
|
6
|
+
* every consumer (ADR 0007's portability split, ADR 0008's ~80-line budget). A
|
|
7
|
+
* project with real coordination policy of its own therefore had nowhere
|
|
8
|
+
* machine-managed to put it, and ended up hand-maintaining it next to the
|
|
9
|
+
* block, where nothing kept the two in step.
|
|
10
|
+
*
|
|
11
|
+
* The fix is declarative rather than programmatic. A consumer names a file:
|
|
12
|
+
*
|
|
13
|
+
* // .harnery/config.jsonc
|
|
14
|
+
* { "instructions": { "hostAddendumFile": ".agents/host-instructions.md" } }
|
|
15
|
+
*
|
|
16
|
+
* and harnery gives that file's contents the same lifecycle as its own block:
|
|
17
|
+
* spliced on `init`, refreshed when the file changes, reported by
|
|
18
|
+
* `init --check`, removed by `deinit` or by deleting the config entry. Harnery
|
|
19
|
+
* never parses, renders, or reasons about what the file says, which is what
|
|
20
|
+
* keeps the arrangement portable: the mechanism is generic even though every
|
|
21
|
+
* consumer's content is not.
|
|
22
|
+
*
|
|
23
|
+
* Exposing the splicer as a public primitive instead would have pushed the
|
|
24
|
+
* whole lifecycle onto each host, since `init` and `deinit` are registered
|
|
25
|
+
* inside harnery and every consumer would have had to wrap or replace them and
|
|
26
|
+
* reimplement apply, check, and remove. The config key keeps one implementation
|
|
27
|
+
* of all four.
|
|
28
|
+
*
|
|
29
|
+
* Every failure here is raised before the caller writes anything.
|
|
30
|
+
*/
|
|
31
|
+
import { readFileSync, statSync } from "node:fs";
|
|
32
|
+
import { isAbsolute, join, resolve, sep } from "node:path";
|
|
33
|
+
import { stripJsonComments } from "../../core/config.js";
|
|
34
|
+
/** Dotted config key naming the addendum source, quoted in every error. */
|
|
35
|
+
export const HOST_ADDENDUM_KEY = "instructions.hostAddendumFile";
|
|
36
|
+
/** A host addendum that cannot be used. Callers abort before writing. */
|
|
37
|
+
export class HostAddendumError extends Error {
|
|
38
|
+
constructor(message) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = "HostAddendumError";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Resolve the configured addendum, or report that there is none.
|
|
45
|
+
*
|
|
46
|
+
* Absent config, absent key, and explicit `null` all mean "not configured",
|
|
47
|
+
* which is how a consumer turns the addendum off: delete the key and re-run
|
|
48
|
+
* `init`. Anything else that cannot become a readable file inside the project
|
|
49
|
+
* throws, because the alternative is an agent-facing instruction file that
|
|
50
|
+
* quietly lost a section the host believes is still there.
|
|
51
|
+
*/
|
|
52
|
+
export function readHostAddendum(projectRoot) {
|
|
53
|
+
const configured = readConfiguredPath(projectRoot);
|
|
54
|
+
if (configured === null)
|
|
55
|
+
return { configured: false };
|
|
56
|
+
if (typeof configured !== "string" || configured.trim() === "") {
|
|
57
|
+
throw new HostAddendumError(`${HOST_ADDENDUM_KEY} must be a repo-relative path to a markdown file`);
|
|
58
|
+
}
|
|
59
|
+
const relPath = configured.trim();
|
|
60
|
+
// An absolute path would name one machine's checkout, and this repo is cloned
|
|
61
|
+
// to a different location on every one of them.
|
|
62
|
+
if (isAbsolute(relPath)) {
|
|
63
|
+
throw new HostAddendumError(`${HOST_ADDENDUM_KEY} must be repo-relative, not absolute (got "${relPath}")`);
|
|
64
|
+
}
|
|
65
|
+
const root = resolve(projectRoot);
|
|
66
|
+
const target = resolve(root, relPath);
|
|
67
|
+
if (target !== root && !target.startsWith(root + sep)) {
|
|
68
|
+
throw new HostAddendumError(`${HOST_ADDENDUM_KEY} resolves outside the project ("${relPath}"); ` +
|
|
69
|
+
`the addendum must be a committed file in this repo`);
|
|
70
|
+
}
|
|
71
|
+
let body;
|
|
72
|
+
try {
|
|
73
|
+
if (statSync(target).isDirectory()) {
|
|
74
|
+
throw new HostAddendumError(`${HOST_ADDENDUM_KEY} points at a directory ("${relPath}")`);
|
|
75
|
+
}
|
|
76
|
+
body = readFileSync(target, "utf8");
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
if (err instanceof HostAddendumError)
|
|
80
|
+
throw err;
|
|
81
|
+
throw new HostAddendumError(`${HOST_ADDENDUM_KEY} not found or unreadable ("${relPath}"): ${err.message}`);
|
|
82
|
+
}
|
|
83
|
+
// Splicing an empty region is never what anyone meant by configuring one, and
|
|
84
|
+
// it fails silently: the file looks fine and the policy simply is not there.
|
|
85
|
+
if (body.trim() === "") {
|
|
86
|
+
throw new HostAddendumError(`${HOST_ADDENDUM_KEY} is empty ("${relPath}")`);
|
|
87
|
+
}
|
|
88
|
+
// Trimmed because the splicer supplies the newlines around a region body;
|
|
89
|
+
// otherwise a trailing newline in the file shows up as a blank line that
|
|
90
|
+
// makes every re-render look like a change.
|
|
91
|
+
return { configured: true, relPath, body: body.trim() };
|
|
92
|
+
}
|
|
93
|
+
/** The raw config value, or null when the file, the section, or the key is absent. */
|
|
94
|
+
function readConfiguredPath(projectRoot) {
|
|
95
|
+
const configPath = join(projectRoot, ".harnery", "config.jsonc");
|
|
96
|
+
let parsed;
|
|
97
|
+
try {
|
|
98
|
+
parsed = JSON.parse(stripJsonComments(readFileSync(configPath, "utf8")));
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// No config, or one harnery cannot parse. The rest of init already tolerates
|
|
102
|
+
// that, so the addendum does too rather than blocking an unrelated run.
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
const value = parsed?.instructions?.hostAddendumFile;
|
|
106
|
+
return value === undefined || value === null ? null : value;
|
|
107
|
+
}
|
|
@@ -14,6 +14,13 @@
|
|
|
14
14
|
export declare const INSTRUCTIONS_REGION = "instructions";
|
|
15
15
|
/** Managed-region name for the CLAUDE.md `@AGENTS.md` import shim. */
|
|
16
16
|
export declare const IMPORT_REGION = "import";
|
|
17
|
+
/**
|
|
18
|
+
* Managed-region name for the consumer's own coordination policy, spliced from
|
|
19
|
+
* the file named by `instructions.hostAddendumFile`. Harnery places and
|
|
20
|
+
* versions the region; the content is the host's and is never rendered here.
|
|
21
|
+
* See `host-addendum.ts`.
|
|
22
|
+
*/
|
|
23
|
+
export declare const HOST_ADDENDUM_REGION = "host-addendum";
|
|
17
24
|
/** Which shipped skills exist in the project the block is rendered for. */
|
|
18
25
|
export interface BlockSkills {
|
|
19
26
|
/** the `harn-decide` skill file is present (claude-code, not excluded) */
|
|
@@ -29,15 +36,15 @@ export interface BlockSkills {
|
|
|
29
36
|
* `harn-council`) even for a renamed bin; only command strings track `binName`.
|
|
30
37
|
*
|
|
31
38
|
* The block only points at a skill that actually exists here: a host that
|
|
32
|
-
* excludes one via `skills.exclude`, or a
|
|
39
|
+
* excludes one via `skills.exclude`, or a adapter with no skill primitive
|
|
33
40
|
* (cursor/codex get the block but no skill files), gets a `--help` pointer
|
|
34
41
|
* instead of a dangling reference to a skill it doesn't have.
|
|
35
42
|
*/
|
|
36
43
|
export declare function renderInstructionsBlock(binName: string, skills?: BlockSkills): string;
|
|
37
|
-
/** A shipped skill: its
|
|
44
|
+
/** A shipped skill: its adapter-relative file path + a bin-name-aware renderer. */
|
|
38
45
|
export interface SkillTemplate {
|
|
39
46
|
id: string;
|
|
40
|
-
/** path under the
|
|
47
|
+
/** path under the adapter skill dir, e.g. `harn-decide/SKILL.md` */
|
|
41
48
|
relPath: string;
|
|
42
49
|
render: (binName: string) => string;
|
|
43
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/lib/instructions/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAClD,sEAAsE;AACtE,eAAO,MAAM,aAAa,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/lib/instructions/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAClD,sEAAsE;AACtE,eAAO,MAAM,aAAa,WAAW,CAAC;AACtC;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,kBAAkB,CAAC;AAEpD,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,0EAA0E;IAC1E,MAAM,EAAE,OAAO,CAAC;IAChB,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,WAA6C,GACpD,MAAM,CAkFR;AAID,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAsKD,eAAO,MAAM,MAAM,EAAE,aAAa,EA4BjC,CAAC"}
|
|
@@ -10,12 +10,19 @@
|
|
|
10
10
|
* files), so they compile into `dist/` and resolve identically under Bun and
|
|
11
11
|
* Node — no `files`-field copy or package-path guesswork.
|
|
12
12
|
*/
|
|
13
|
-
import {
|
|
13
|
+
import { JOURNAL_CATEGORIES } from "../../core/journal/index.js";
|
|
14
14
|
import { buildOwnedSkill } from "./splice.js";
|
|
15
15
|
/** Managed-region name for the AGENTS.md orientation block. */
|
|
16
16
|
export const INSTRUCTIONS_REGION = "instructions";
|
|
17
17
|
/** Managed-region name for the CLAUDE.md `@AGENTS.md` import shim. */
|
|
18
18
|
export const IMPORT_REGION = "import";
|
|
19
|
+
/**
|
|
20
|
+
* Managed-region name for the consumer's own coordination policy, spliced from
|
|
21
|
+
* the file named by `instructions.hostAddendumFile`. Harnery places and
|
|
22
|
+
* versions the region; the content is the host's and is never rendered here.
|
|
23
|
+
* See `host-addendum.ts`.
|
|
24
|
+
*/
|
|
25
|
+
export const HOST_ADDENDUM_REGION = "host-addendum";
|
|
19
26
|
/**
|
|
20
27
|
* The always-on orientation spliced into `AGENTS.md`. Target ≤ 80 rendered
|
|
21
28
|
* lines: it costs every agent context on every turn, so it states that each
|
|
@@ -24,7 +31,7 @@ export const IMPORT_REGION = "import";
|
|
|
24
31
|
* `harn-council`) even for a renamed bin; only command strings track `binName`.
|
|
25
32
|
*
|
|
26
33
|
* The block only points at a skill that actually exists here: a host that
|
|
27
|
-
* excludes one via `skills.exclude`, or a
|
|
34
|
+
* excludes one via `skills.exclude`, or a adapter with no skill primitive
|
|
28
35
|
* (cursor/codex get the block but no skill files), gets a `--help` pointer
|
|
29
36
|
* instead of a dangling reference to a skill it doesn't have.
|
|
30
37
|
*/
|
|
@@ -33,24 +40,25 @@ export function renderInstructionsBlock(binName, skills = { decide: true, counci
|
|
|
33
40
|
const named = [skills.decide && "`harn-decide`", skills.council && "`harn-council`"].filter(Boolean);
|
|
34
41
|
const deeper = named.length > 0
|
|
35
42
|
? `Procedures for the deeper flows live in the ${named.join(" and ")} skill${named.length > 1 ? "s" : ""}.`
|
|
36
|
-
: `See \`${b} decision --help\` and \`${b} council --help\` for the deeper procedures.`;
|
|
43
|
+
: `See \`${b} decision --help\` and \`${b} agents council --help\` for the deeper procedures.`;
|
|
37
44
|
const decidePointer = skills.decide
|
|
38
45
|
? "The `harn-decide` skill has the file / claim / resolve-with-evidence procedure."
|
|
39
46
|
: `See \`${b} decision --help\` for the file / claim / resolve-with-evidence procedure.`;
|
|
40
47
|
const councilPointer = skills.council
|
|
41
48
|
? "The `harn-council` skill has the steward and member flow."
|
|
42
|
-
: `See \`${b} council --help\` for the steward and member flow.`;
|
|
43
|
-
// Render the
|
|
44
|
-
// never drift from what `
|
|
49
|
+
: `See \`${b} agents council --help\` for the steward and member flow.`;
|
|
50
|
+
// Render the journal categories from the canonical enum so this prose can
|
|
51
|
+
// never drift from what `journal add` actually accepts (the "note, plan…" list
|
|
45
52
|
// silently lagged the tool by two categories before this).
|
|
46
|
-
const
|
|
47
|
-
? `${
|
|
48
|
-
:
|
|
53
|
+
const journalCats = JOURNAL_CATEGORIES.length > 1
|
|
54
|
+
? `${JOURNAL_CATEGORIES.slice(0, -1).join(", ")}, or ${JOURNAL_CATEGORIES.at(-1)}`
|
|
55
|
+
: JOURNAL_CATEGORIES[0];
|
|
49
56
|
return `## harnery coordination
|
|
50
57
|
|
|
51
58
|
This project runs [harnery](https://harnery.com) for multi-agent coordination.
|
|
52
59
|
You share this checkout with other agents; the surfaces below keep you oriented
|
|
53
|
-
and out of each other's way
|
|
60
|
+
and out of each other's way, and let you dispatch a team of your own when a job
|
|
61
|
+
is bigger than one session. Run \`${b} <command> --help\` for any command's full
|
|
54
62
|
surface. ${deeper}
|
|
55
63
|
|
|
56
64
|
**Identity + peers.** You are one of several agents in this repo.
|
|
@@ -59,6 +67,20 @@ active peers and the files they've claimed; \`${b} agents set-task "<focus>"\`
|
|
|
59
67
|
declares your current focus so peers can see it. Check for peers before editing
|
|
60
68
|
widely-shared files.
|
|
61
69
|
|
|
70
|
+
**Dispatching a team.** Everything else here coordinates the agents already
|
|
71
|
+
present. These three start new ones, and they differ by how long the objective
|
|
72
|
+
outlives a single execution. \`${b} run <script>\` is one bounded pass:
|
|
73
|
+
plain JS stages fan out to headless subagents that are born
|
|
74
|
+
coordination-registered, with deterministic code deciding the routing between
|
|
75
|
+
stages. \`${b} work create <title> <workflow>\` wraps an objective that has to
|
|
76
|
+
survive many such passes, holding it across retries, failures, and review.
|
|
77
|
+
\`${b} governor create\` drives a whole graph of work toward a goal, choosing
|
|
78
|
+
what runs next and how much it may settle without asking a human. Reach for the
|
|
79
|
+
first when one pass will do, the second when the objective must outlive the
|
|
80
|
+
attempt, and the third when a human would otherwise have to babysit the loop. A
|
|
81
|
+
run that needs authorization parks durably instead of failing, so check
|
|
82
|
+
\`${b} approval list\` when one appears to be waiting rather than stuck.
|
|
83
|
+
|
|
62
84
|
**Durable role handoff.** When you are replacing a prior session in the same
|
|
63
85
|
named role, run \`${b} agents identity assume <name>\` before declaring your task.
|
|
64
86
|
It reclaims an abandoned namesake (no live process) and refuses only when another
|
|
@@ -70,11 +92,18 @@ coordination ledger. Lead a shell command with a \`# intent: <why>\` comment (or
|
|
|
70
92
|
the tool's description) so the recorded event carries a reason instead of
|
|
71
93
|
\`(no intent)\`.
|
|
72
94
|
|
|
73
|
-
**
|
|
95
|
+
**Journal.** \`${b} journal add <category> "<text>"\` (category = ${journalCats})
|
|
74
96
|
leaves breadcrumbs that survive context compaction;
|
|
75
|
-
\`${b}
|
|
97
|
+
\`${b} journal read\` reads yours, \`${b} journal read --name <peer>\` reads a peer's.
|
|
76
98
|
Use it for anything future-you or a peer will need to pick up your thread.
|
|
77
99
|
|
|
100
|
+
**Working artifacts.** For screenshots, exports, audit dumps, rollback inputs,
|
|
101
|
+
and other untracked files that must survive a session, create a managed workspace
|
|
102
|
+
with \`${b} artifacts create <slug> --purpose "<why>"\`. Write files under the
|
|
103
|
+
returned path, then run \`${b} artifacts release <id>\` when active work is done.
|
|
104
|
+
Do not create a repo-root temp directory; \`${b} artifacts clean\` previews
|
|
105
|
+
expired cleanup and requires \`--yes\` to delete anything.
|
|
106
|
+
|
|
78
107
|
**Decision docket.** When you would otherwise stop to ask a human a decision you
|
|
79
108
|
can't resolve from the repo, file it instead. \`${b} decision file "<question>"\`
|
|
80
109
|
records it and lets you proceed on a stated default; \`${b} decision search "<terms>"\`
|