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
package/src/lib/council/index.ts
CHANGED
|
@@ -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
|
*/
|
|
@@ -242,7 +242,7 @@ export interface KnownAgent {
|
|
|
242
242
|
/** `agent-<Name>` canonical handle. */
|
|
243
243
|
name: string;
|
|
244
244
|
/** `active` = currently has a heartbeat in `.harnery/active/`. `stale` =
|
|
245
|
-
* recently ended (
|
|
245
|
+
* recently ended (journal archived within the lookback window). */
|
|
246
246
|
state: "active" | "stale";
|
|
247
247
|
/** ISO timestamp of the most-recent signal. */
|
|
248
248
|
last_seen: string;
|
|
@@ -253,7 +253,7 @@ export interface KnownAgent {
|
|
|
253
253
|
const KNOWN_AGENT_STALE_WINDOW_MS = 30 * 24 * 60 * 60 * 1000;
|
|
254
254
|
|
|
255
255
|
/**
|
|
256
|
-
* Active heartbeats + recently-archived
|
|
256
|
+
* Active heartbeats + recently-archived journals, deduped by name.
|
|
257
257
|
* Used by `agents council set-steward` to refuse arbitrary names;
|
|
258
258
|
* pass `--allow-unknown` to bypass when bootstrapping a new agent.
|
|
259
259
|
*/
|
|
@@ -261,7 +261,7 @@ export function listKnownAgents(): KnownAgent[] {
|
|
|
261
261
|
const root = monorepoRoot();
|
|
262
262
|
if (!root) return [];
|
|
263
263
|
const activeDir = resolve(root, ".harnery", "active");
|
|
264
|
-
const archiveDir = resolve(root, ".harnery", "
|
|
264
|
+
const archiveDir = resolve(root, ".harnery", "journal", "archived");
|
|
265
265
|
const byName = new Map<string, KnownAgent>();
|
|
266
266
|
|
|
267
267
|
if (existsSync(activeDir)) {
|
|
@@ -296,7 +296,7 @@ export function listKnownAgents(): KnownAgent[] {
|
|
|
296
296
|
if (Number.isNaN(ts) || ts < cutoff) continue;
|
|
297
297
|
try {
|
|
298
298
|
const head = readFileSync(resolve(archiveDir, f), "utf8").slice(0, 200);
|
|
299
|
-
const nameMatch = head.match(/^#\s+
|
|
299
|
+
const nameMatch = head.match(/^#\s+Journal:\s+(agent-[A-Za-z][A-Za-z0-9_-]*)/m);
|
|
300
300
|
if (!nameMatch) continue;
|
|
301
301
|
const name = nameMatch[1]!;
|
|
302
302
|
const existing = byName.get(name);
|
|
@@ -588,7 +588,7 @@ export function writeContribution(
|
|
|
588
588
|
* Path to the round-N prompts directory: `.harnery/councils/<id>/round-N/prompts/`.
|
|
589
589
|
* Sibling to the contribution files. Holds one `<member>.md` per non-self
|
|
590
590
|
* council member, drafted by the steward, read by the operator (copy-paste
|
|
591
|
-
* into each agent
|
|
591
|
+
* into each agent adapter) and the web UI (per-member panel).
|
|
592
592
|
*/
|
|
593
593
|
export function promptsDir(councilId: string, round: number): string | null {
|
|
594
594
|
const rd = roundDir(councilId, round);
|
|
@@ -636,9 +636,9 @@ const SUBMIT_FOOTER_MARKER = "<!-- council-submit-footer -->";
|
|
|
636
636
|
* Build the submit footer appended to every steward-drafted prompt. This is the
|
|
637
637
|
* load-bearing instruction that a contribution composed in chat is NOT recorded;
|
|
638
638
|
* the agent must run the command below. It rides on the prompt (the one
|
|
639
|
-
* artifact the operator always pastes) so it reaches every
|
|
639
|
+
* artifact the operator always pastes) so it reaches every adapter regardless of
|
|
640
640
|
* whether the convene-time invitation was delivered or a `/council` skill is
|
|
641
|
-
* available. Without it, agents (esp. non-Claude
|
|
641
|
+
* available. Without it, agents (esp. non-Claude adapters with no skill) write
|
|
642
642
|
* their take as a reply and end the turn, leaving the council showing them as
|
|
643
643
|
* still-pending. Visible markdown (not an HTML comment) so the agent reads it.
|
|
644
644
|
*/
|
|
@@ -654,7 +654,7 @@ export function buildSubmitFooter(councilId: string): string {
|
|
|
654
654
|
`# longer write-up? ${bin} agents council contribute ${councilId} --file <path>`,
|
|
655
655
|
"```",
|
|
656
656
|
"",
|
|
657
|
-
'_(Or invoke the `council` skill in your
|
|
657
|
+
'_(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.)_',
|
|
658
658
|
].join("\n");
|
|
659
659
|
}
|
|
660
660
|
|
|
@@ -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
|
*/
|
|
@@ -126,7 +126,7 @@ export function findIdentityConflict(
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
/**
|
|
129
|
-
* Drop a local namesake whose
|
|
129
|
+
* Drop a local namesake whose adapter process is gone. Fresh heartbeats can
|
|
130
130
|
* linger after a crash (or after heartbeat heal without a live pid-map), and
|
|
131
131
|
* `identity assume` is the supported takeover path — operators should not
|
|
132
132
|
* need a separate kill/sweep step.
|
|
@@ -139,13 +139,13 @@ export function reclaimAbandonedLocalConflict(
|
|
|
139
139
|
if (instanceHasLivePid(coordRoot, conflict.instance_id)) return false;
|
|
140
140
|
|
|
141
141
|
const hbPath = join(coordRoot, ".harnery", "active", `${conflict.instance_id}.json`);
|
|
142
|
-
let
|
|
142
|
+
let adapter: "claude-code" | "cursor" | "codex" = "claude-code";
|
|
143
143
|
let sessionId = conflict.instance_id;
|
|
144
144
|
let ageSecs: number | undefined;
|
|
145
145
|
if (existsSync(hbPath)) {
|
|
146
146
|
try {
|
|
147
147
|
const hb = JSON.parse(readFileSync(hbPath, "utf8")) as Heartbeat;
|
|
148
|
-
|
|
148
|
+
adapter = adapterOf(hb.platform);
|
|
149
149
|
sessionId = hb.session_id || conflict.instance_id;
|
|
150
150
|
const ts = Date.parse(hb.last_heartbeat);
|
|
151
151
|
if (Number.isFinite(ts)) ageSecs = Math.max(0, Math.floor((Date.now() - ts) / 1000));
|
|
@@ -164,7 +164,7 @@ export function reclaimAbandonedLocalConflict(
|
|
|
164
164
|
event_type: "health.heartbeat_swept",
|
|
165
165
|
instance_id: conflict.instance_id,
|
|
166
166
|
session_id: sessionId,
|
|
167
|
-
|
|
167
|
+
adapter,
|
|
168
168
|
source: "agent-coord",
|
|
169
169
|
data: {
|
|
170
170
|
reason: "stale",
|
|
@@ -244,7 +244,7 @@ function acquireLock(coordRoot: string): () => void {
|
|
|
244
244
|
);
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
function
|
|
247
|
+
function adapterOf(platform: string | undefined): "claude-code" | "cursor" | "codex" {
|
|
248
248
|
if (platform === "cursor") return "cursor";
|
|
249
249
|
if (platform === "codex") return "codex";
|
|
250
250
|
return "claude-code";
|
|
@@ -320,7 +320,7 @@ export function assumeIdentity(
|
|
|
320
320
|
event_type: "identity.assumed",
|
|
321
321
|
instance_id: instanceId,
|
|
322
322
|
session_id: hb.session_id,
|
|
323
|
-
|
|
323
|
+
adapter: adapterOf(hb.platform),
|
|
324
324
|
data: {
|
|
325
325
|
name: identity.name,
|
|
326
326
|
agent_id: identity.agent_id,
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
} from "node:fs";
|
|
30
30
|
import { dirname, join } from "node:path";
|
|
31
31
|
import { stripJsonComments } from "../../core/config.ts";
|
|
32
|
+
import { readHostAddendum } from "./host-addendum.ts";
|
|
32
33
|
import {
|
|
33
34
|
checkOwnedSkill,
|
|
34
35
|
checkRegion,
|
|
@@ -39,6 +40,7 @@ import {
|
|
|
39
40
|
} from "./splice.ts";
|
|
40
41
|
import {
|
|
41
42
|
type BlockSkills,
|
|
43
|
+
HOST_ADDENDUM_REGION,
|
|
42
44
|
IMPORT_REGION,
|
|
43
45
|
INSTRUCTIONS_REGION,
|
|
44
46
|
renderInstructionsBlock,
|
|
@@ -81,8 +83,8 @@ export function readSkillsExclude(projectRoot: string): Set<string> {
|
|
|
81
83
|
* codex get the block but no skill files, so both read false there. Kept in one
|
|
82
84
|
* place so `applyInstructions` and `checkInstructions` render byte-identical blocks.
|
|
83
85
|
*/
|
|
84
|
-
function blockSkills(projectRoot: string,
|
|
85
|
-
const claudeCode =
|
|
86
|
+
function blockSkills(projectRoot: string, adapter: string): BlockSkills {
|
|
87
|
+
const claudeCode = adapter === "claude-code";
|
|
86
88
|
const exclude = readSkillsExclude(projectRoot);
|
|
87
89
|
return {
|
|
88
90
|
decide: claudeCode && !exclude.has("harn-decide"),
|
|
@@ -92,7 +94,7 @@ function blockSkills(projectRoot: string, harness: string): BlockSkills {
|
|
|
92
94
|
|
|
93
95
|
interface ApplyOpts {
|
|
94
96
|
binName: string;
|
|
95
|
-
|
|
97
|
+
adapter: string;
|
|
96
98
|
dryRun: boolean;
|
|
97
99
|
}
|
|
98
100
|
|
|
@@ -109,27 +111,61 @@ export interface ApplyResult {
|
|
|
109
111
|
export function applyInstructions(projectRoot: string, opts: ApplyOpts): ApplyResult {
|
|
110
112
|
const actions: string[] = [];
|
|
111
113
|
const warnings: string[] = [];
|
|
112
|
-
const claudeCode = opts.
|
|
114
|
+
const claudeCode = opts.adapter === "claude-code";
|
|
113
115
|
// dry-run narrates the future ("would create"); a real run narrates the past.
|
|
114
116
|
const verbed = (base: string, past: string) => (opts.dryRun ? `would ${base}` : past);
|
|
115
117
|
|
|
118
|
+
// Resolve the host addendum before touching a single file, so a bad path
|
|
119
|
+
// aborts the whole run instead of leaving AGENTS.md half-updated.
|
|
120
|
+
const addendum = readHostAddendum(projectRoot);
|
|
121
|
+
|
|
116
122
|
// ── AGENTS.md orientation block ─────────────────────────────────────────
|
|
117
123
|
const agentsPath = join(projectRoot, AGENTS_FILE);
|
|
118
124
|
const agentsExisted = existsSync(agentsPath);
|
|
119
125
|
const agentsBefore = agentsExisted ? readFileSync(agentsPath, "utf8") : "";
|
|
120
|
-
const body = renderInstructionsBlock(opts.binName, blockSkills(projectRoot, opts.
|
|
126
|
+
const body = renderInstructionsBlock(opts.binName, blockSkills(projectRoot, opts.adapter));
|
|
121
127
|
const spliced = spliceRegion(agentsBefore, INSTRUCTIONS_REGION, body);
|
|
122
128
|
if (!spliced.changed) {
|
|
123
129
|
actions.push(`· ${AGENTS_FILE} instructions block already current`);
|
|
130
|
+
} else if (!agentsExisted) {
|
|
131
|
+
actions.push(`+ ${verbed("create", "created")} ${AGENTS_FILE} with the instructions block`);
|
|
132
|
+
} else if (!spliced.had) {
|
|
133
|
+
actions.push(`+ ${verbed("inject", "injected")} the instructions block into ${AGENTS_FILE}`);
|
|
124
134
|
} else {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
actions.push(`~ ${verbed("update", "updated")} the instructions block in ${AGENTS_FILE}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ── host addendum (a second region, content the host owns) ──────────────
|
|
139
|
+
// Harnery places and versions it; what it says is none of harnery's business.
|
|
140
|
+
// No configured source means any region left behind belongs to a config entry
|
|
141
|
+
// that has since been deleted, so init takes it back out.
|
|
142
|
+
let agentsAfter = spliced.text;
|
|
143
|
+
if (addendum.configured) {
|
|
144
|
+
const withAddendum = spliceRegion(agentsAfter, HOST_ADDENDUM_REGION, addendum.body);
|
|
145
|
+
agentsAfter = withAddendum.text;
|
|
146
|
+
if (!withAddendum.changed) {
|
|
147
|
+
actions.push(`· ${AGENTS_FILE} host addendum already current (${addendum.relPath})`);
|
|
148
|
+
} else if (!withAddendum.had) {
|
|
149
|
+
actions.push(
|
|
150
|
+
`+ ${verbed("splice", "spliced")} the host addendum into ${AGENTS_FILE} (${addendum.relPath})`,
|
|
151
|
+
);
|
|
152
|
+
} else {
|
|
153
|
+
actions.push(
|
|
154
|
+
`~ ${verbed("update", "updated")} the host addendum in ${AGENTS_FILE} (${addendum.relPath})`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
const dropped = removeRegion(agentsAfter, HOST_ADDENDUM_REGION);
|
|
159
|
+
if (dropped.removed) {
|
|
160
|
+
agentsAfter = dropped.text;
|
|
161
|
+
actions.push(
|
|
162
|
+
`+ ${verbed("remove", "removed")} the host addendum from ${AGENTS_FILE} (no longer configured)`,
|
|
163
|
+
);
|
|
164
|
+
}
|
|
131
165
|
}
|
|
132
166
|
|
|
167
|
+
if (!opts.dryRun && agentsAfter !== agentsBefore) writeFileSync(agentsPath, agentsAfter);
|
|
168
|
+
|
|
133
169
|
// ── CLAUDE.md import shim (claude-code only) ────────────────────────────
|
|
134
170
|
if (claudeCode) {
|
|
135
171
|
const claudePath = join(projectRoot, CLAUDE_FILE);
|
|
@@ -185,7 +221,7 @@ export function applyInstructions(projectRoot: string, opts: ApplyOpts): ApplyRe
|
|
|
185
221
|
}
|
|
186
222
|
|
|
187
223
|
interface RemoveOpts {
|
|
188
|
-
|
|
224
|
+
adapter: string;
|
|
189
225
|
dryRun: boolean;
|
|
190
226
|
}
|
|
191
227
|
|
|
@@ -198,22 +234,36 @@ interface RemoveOpts {
|
|
|
198
234
|
export function removeInstructions(projectRoot: string, opts: RemoveOpts): ApplyResult {
|
|
199
235
|
const actions: string[] = [];
|
|
200
236
|
const warnings: string[] = [];
|
|
201
|
-
const claudeCode = opts.
|
|
237
|
+
const claudeCode = opts.adapter === "claude-code";
|
|
202
238
|
|
|
203
|
-
// ── AGENTS.md block
|
|
239
|
+
// ── AGENTS.md block + host addendum ─────────────────────────────────────
|
|
204
240
|
const agentsPath = join(projectRoot, AGENTS_FILE);
|
|
205
241
|
if (existsSync(agentsPath)) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
242
|
+
// Both regions are harnery-placed, so deinit leaves neither behind. The
|
|
243
|
+
// addendum's *source file* is the host's and stays where it is.
|
|
244
|
+
const addendumGone = removeRegion(readFileSync(agentsPath, "utf8"), HOST_ADDENDUM_REGION);
|
|
245
|
+
if (addendumGone.removed) {
|
|
246
|
+
actions.push(
|
|
247
|
+
`+ ${opts.dryRun ? "would remove" : "removed"} the host addendum from ${AGENTS_FILE}`,
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
const { text, removed } = removeRegion(addendumGone.text, INSTRUCTIONS_REGION);
|
|
251
|
+
if (removed) {
|
|
214
252
|
actions.push(
|
|
215
253
|
`+ ${opts.dryRun ? "would remove" : "removed"} the instructions block from ${AGENTS_FILE}`,
|
|
216
254
|
);
|
|
255
|
+
} else if (!addendumGone.removed) {
|
|
256
|
+
actions.push(`· no instructions block in ${AGENTS_FILE}`);
|
|
257
|
+
}
|
|
258
|
+
if (removed || addendumGone.removed) {
|
|
259
|
+
if (text === "") {
|
|
260
|
+
if (!opts.dryRun) rmSync(agentsPath);
|
|
261
|
+
actions.push(
|
|
262
|
+
`+ ${opts.dryRun ? "would remove" : "removed"} ${AGENTS_FILE} (nothing left but ours)`,
|
|
263
|
+
);
|
|
264
|
+
} else if (!opts.dryRun) {
|
|
265
|
+
writeFileSync(agentsPath, text);
|
|
266
|
+
}
|
|
217
267
|
}
|
|
218
268
|
}
|
|
219
269
|
|
|
@@ -277,7 +327,7 @@ export interface CheckResult {
|
|
|
277
327
|
*/
|
|
278
328
|
export function checkInstructions(
|
|
279
329
|
projectRoot: string,
|
|
280
|
-
opts: { binName: string;
|
|
330
|
+
opts: { binName: string; adapter: string },
|
|
281
331
|
): CheckResult {
|
|
282
332
|
const issues: string[] = [];
|
|
283
333
|
let errored = false;
|
|
@@ -295,11 +345,23 @@ export function checkInstructions(
|
|
|
295
345
|
checkRegion(
|
|
296
346
|
content,
|
|
297
347
|
INSTRUCTIONS_REGION,
|
|
298
|
-
renderInstructionsBlock(opts.binName, blockSkills(projectRoot, opts.
|
|
348
|
+
renderInstructionsBlock(opts.binName, blockSkills(projectRoot, opts.adapter)),
|
|
299
349
|
),
|
|
300
350
|
);
|
|
301
351
|
|
|
302
|
-
|
|
352
|
+
// A configured addendum is checked against its source; an unconfigured one
|
|
353
|
+
// still sitting in the file is drift too, since init would take it out.
|
|
354
|
+
const addendum = readHostAddendum(projectRoot);
|
|
355
|
+
if (addendum.configured) {
|
|
356
|
+
note(
|
|
357
|
+
`${AGENTS_FILE} host addendum (${addendum.relPath})`,
|
|
358
|
+
checkRegion(content, HOST_ADDENDUM_REGION, addendum.body),
|
|
359
|
+
);
|
|
360
|
+
} else if (checkRegion(content, HOST_ADDENDUM_REGION, "") !== "missing") {
|
|
361
|
+
issues.push(`${AGENTS_FILE} host addendum: present but no longer configured (re-run init)`);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (opts.adapter === "claude-code") {
|
|
303
365
|
const exclude = readSkillsExclude(projectRoot);
|
|
304
366
|
for (const skill of SKILLS) {
|
|
305
367
|
if (exclude.has(skill.id)) continue;
|
|
@@ -0,0 +1,126 @@
|
|
|
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
|
+
|
|
32
|
+
import { readFileSync, statSync } from "node:fs";
|
|
33
|
+
import { isAbsolute, join, resolve, sep } from "node:path";
|
|
34
|
+
import { stripJsonComments } from "../../core/config.ts";
|
|
35
|
+
|
|
36
|
+
/** Dotted config key naming the addendum source, quoted in every error. */
|
|
37
|
+
export const HOST_ADDENDUM_KEY = "instructions.hostAddendumFile";
|
|
38
|
+
|
|
39
|
+
/** A host addendum that cannot be used. Callers abort before writing. */
|
|
40
|
+
export class HostAddendumError extends Error {
|
|
41
|
+
constructor(message: string) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = "HostAddendumError";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type HostAddendum =
|
|
48
|
+
| { configured: false }
|
|
49
|
+
| { configured: true; relPath: string; body: string };
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Resolve the configured addendum, or report that there is none.
|
|
53
|
+
*
|
|
54
|
+
* Absent config, absent key, and explicit `null` all mean "not configured",
|
|
55
|
+
* which is how a consumer turns the addendum off: delete the key and re-run
|
|
56
|
+
* `init`. Anything else that cannot become a readable file inside the project
|
|
57
|
+
* throws, because the alternative is an agent-facing instruction file that
|
|
58
|
+
* quietly lost a section the host believes is still there.
|
|
59
|
+
*/
|
|
60
|
+
export function readHostAddendum(projectRoot: string): HostAddendum {
|
|
61
|
+
const configured = readConfiguredPath(projectRoot);
|
|
62
|
+
if (configured === null) return { configured: false };
|
|
63
|
+
|
|
64
|
+
if (typeof configured !== "string" || configured.trim() === "") {
|
|
65
|
+
throw new HostAddendumError(
|
|
66
|
+
`${HOST_ADDENDUM_KEY} must be a repo-relative path to a markdown file`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
const relPath = configured.trim();
|
|
70
|
+
|
|
71
|
+
// An absolute path would name one machine's checkout, and this repo is cloned
|
|
72
|
+
// to a different location on every one of them.
|
|
73
|
+
if (isAbsolute(relPath)) {
|
|
74
|
+
throw new HostAddendumError(
|
|
75
|
+
`${HOST_ADDENDUM_KEY} must be repo-relative, not absolute (got "${relPath}")`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const root = resolve(projectRoot);
|
|
80
|
+
const target = resolve(root, relPath);
|
|
81
|
+
if (target !== root && !target.startsWith(root + sep)) {
|
|
82
|
+
throw new HostAddendumError(
|
|
83
|
+
`${HOST_ADDENDUM_KEY} resolves outside the project ("${relPath}"); ` +
|
|
84
|
+
`the addendum must be a committed file in this repo`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let body: string;
|
|
89
|
+
try {
|
|
90
|
+
if (statSync(target).isDirectory()) {
|
|
91
|
+
throw new HostAddendumError(`${HOST_ADDENDUM_KEY} points at a directory ("${relPath}")`);
|
|
92
|
+
}
|
|
93
|
+
body = readFileSync(target, "utf8");
|
|
94
|
+
} catch (err) {
|
|
95
|
+
if (err instanceof HostAddendumError) throw err;
|
|
96
|
+
throw new HostAddendumError(
|
|
97
|
+
`${HOST_ADDENDUM_KEY} not found or unreadable ("${relPath}"): ${(err as Error).message}`,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Splicing an empty region is never what anyone meant by configuring one, and
|
|
102
|
+
// it fails silently: the file looks fine and the policy simply is not there.
|
|
103
|
+
if (body.trim() === "") {
|
|
104
|
+
throw new HostAddendumError(`${HOST_ADDENDUM_KEY} is empty ("${relPath}")`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Trimmed because the splicer supplies the newlines around a region body;
|
|
108
|
+
// otherwise a trailing newline in the file shows up as a blank line that
|
|
109
|
+
// makes every re-render look like a change.
|
|
110
|
+
return { configured: true, relPath, body: body.trim() };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** The raw config value, or null when the file, the section, or the key is absent. */
|
|
114
|
+
function readConfiguredPath(projectRoot: string): unknown {
|
|
115
|
+
const configPath = join(projectRoot, ".harnery", "config.jsonc");
|
|
116
|
+
let parsed: { instructions?: { hostAddendumFile?: unknown } } | null;
|
|
117
|
+
try {
|
|
118
|
+
parsed = JSON.parse(stripJsonComments(readFileSync(configPath, "utf8")));
|
|
119
|
+
} catch {
|
|
120
|
+
// No config, or one harnery cannot parse. The rest of init already tolerates
|
|
121
|
+
// that, so the addendum does too rather than blocking an unrelated run.
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const value = parsed?.instructions?.hostAddendumFile;
|
|
125
|
+
return value === undefined || value === null ? null : value;
|
|
126
|
+
}
|
|
@@ -11,13 +11,20 @@
|
|
|
11
11
|
* Node — no `files`-field copy or package-path guesswork.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import { JOURNAL_CATEGORIES } from "../../core/journal/index.ts";
|
|
15
15
|
import { buildOwnedSkill } from "./splice.ts";
|
|
16
16
|
|
|
17
17
|
/** Managed-region name for the AGENTS.md orientation block. */
|
|
18
18
|
export const INSTRUCTIONS_REGION = "instructions";
|
|
19
19
|
/** Managed-region name for the CLAUDE.md `@AGENTS.md` import shim. */
|
|
20
20
|
export const IMPORT_REGION = "import";
|
|
21
|
+
/**
|
|
22
|
+
* Managed-region name for the consumer's own coordination policy, spliced from
|
|
23
|
+
* the file named by `instructions.hostAddendumFile`. Harnery places and
|
|
24
|
+
* versions the region; the content is the host's and is never rendered here.
|
|
25
|
+
* See `host-addendum.ts`.
|
|
26
|
+
*/
|
|
27
|
+
export const HOST_ADDENDUM_REGION = "host-addendum";
|
|
21
28
|
|
|
22
29
|
/** Which shipped skills exist in the project the block is rendered for. */
|
|
23
30
|
export interface BlockSkills {
|
|
@@ -35,7 +42,7 @@ export interface BlockSkills {
|
|
|
35
42
|
* `harn-council`) even for a renamed bin; only command strings track `binName`.
|
|
36
43
|
*
|
|
37
44
|
* The block only points at a skill that actually exists here: a host that
|
|
38
|
-
* excludes one via `skills.exclude`, or a
|
|
45
|
+
* excludes one via `skills.exclude`, or a adapter with no skill primitive
|
|
39
46
|
* (cursor/codex get the block but no skill files), gets a `--help` pointer
|
|
40
47
|
* instead of a dangling reference to a skill it doesn't have.
|
|
41
48
|
*/
|
|
@@ -51,26 +58,27 @@ export function renderInstructionsBlock(
|
|
|
51
58
|
const deeper =
|
|
52
59
|
named.length > 0
|
|
53
60
|
? `Procedures for the deeper flows live in the ${named.join(" and ")} skill${named.length > 1 ? "s" : ""}.`
|
|
54
|
-
: `See \`${b} decision --help\` and \`${b} council --help\` for the deeper procedures.`;
|
|
61
|
+
: `See \`${b} decision --help\` and \`${b} agents council --help\` for the deeper procedures.`;
|
|
55
62
|
const decidePointer = skills.decide
|
|
56
63
|
? "The `harn-decide` skill has the file / claim / resolve-with-evidence procedure."
|
|
57
64
|
: `See \`${b} decision --help\` for the file / claim / resolve-with-evidence procedure.`;
|
|
58
65
|
const councilPointer = skills.council
|
|
59
66
|
? "The `harn-council` skill has the steward and member flow."
|
|
60
|
-
: `See \`${b} council --help\` for the steward and member flow.`;
|
|
61
|
-
// Render the
|
|
62
|
-
// never drift from what `
|
|
67
|
+
: `See \`${b} agents council --help\` for the steward and member flow.`;
|
|
68
|
+
// Render the journal categories from the canonical enum so this prose can
|
|
69
|
+
// never drift from what `journal add` actually accepts (the "note, plan…" list
|
|
63
70
|
// silently lagged the tool by two categories before this).
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
? `${
|
|
67
|
-
:
|
|
71
|
+
const journalCats =
|
|
72
|
+
JOURNAL_CATEGORIES.length > 1
|
|
73
|
+
? `${JOURNAL_CATEGORIES.slice(0, -1).join(", ")}, or ${JOURNAL_CATEGORIES.at(-1)}`
|
|
74
|
+
: JOURNAL_CATEGORIES[0];
|
|
68
75
|
|
|
69
76
|
return `## harnery coordination
|
|
70
77
|
|
|
71
78
|
This project runs [harnery](https://harnery.com) for multi-agent coordination.
|
|
72
79
|
You share this checkout with other agents; the surfaces below keep you oriented
|
|
73
|
-
and out of each other's way
|
|
80
|
+
and out of each other's way, and let you dispatch a team of your own when a job
|
|
81
|
+
is bigger than one session. Run \`${b} <command> --help\` for any command's full
|
|
74
82
|
surface. ${deeper}
|
|
75
83
|
|
|
76
84
|
**Identity + peers.** You are one of several agents in this repo.
|
|
@@ -79,6 +87,20 @@ active peers and the files they've claimed; \`${b} agents set-task "<focus>"\`
|
|
|
79
87
|
declares your current focus so peers can see it. Check for peers before editing
|
|
80
88
|
widely-shared files.
|
|
81
89
|
|
|
90
|
+
**Dispatching a team.** Everything else here coordinates the agents already
|
|
91
|
+
present. These three start new ones, and they differ by how long the objective
|
|
92
|
+
outlives a single execution. \`${b} run <script>\` is one bounded pass:
|
|
93
|
+
plain JS stages fan out to headless subagents that are born
|
|
94
|
+
coordination-registered, with deterministic code deciding the routing between
|
|
95
|
+
stages. \`${b} work create <title> <workflow>\` wraps an objective that has to
|
|
96
|
+
survive many such passes, holding it across retries, failures, and review.
|
|
97
|
+
\`${b} governor create\` drives a whole graph of work toward a goal, choosing
|
|
98
|
+
what runs next and how much it may settle without asking a human. Reach for the
|
|
99
|
+
first when one pass will do, the second when the objective must outlive the
|
|
100
|
+
attempt, and the third when a human would otherwise have to babysit the loop. A
|
|
101
|
+
run that needs authorization parks durably instead of failing, so check
|
|
102
|
+
\`${b} approval list\` when one appears to be waiting rather than stuck.
|
|
103
|
+
|
|
82
104
|
**Durable role handoff.** When you are replacing a prior session in the same
|
|
83
105
|
named role, run \`${b} agents identity assume <name>\` before declaring your task.
|
|
84
106
|
It reclaims an abandoned namesake (no live process) and refuses only when another
|
|
@@ -90,11 +112,18 @@ coordination ledger. Lead a shell command with a \`# intent: <why>\` comment (or
|
|
|
90
112
|
the tool's description) so the recorded event carries a reason instead of
|
|
91
113
|
\`(no intent)\`.
|
|
92
114
|
|
|
93
|
-
**
|
|
115
|
+
**Journal.** \`${b} journal add <category> "<text>"\` (category = ${journalCats})
|
|
94
116
|
leaves breadcrumbs that survive context compaction;
|
|
95
|
-
\`${b}
|
|
117
|
+
\`${b} journal read\` reads yours, \`${b} journal read --name <peer>\` reads a peer's.
|
|
96
118
|
Use it for anything future-you or a peer will need to pick up your thread.
|
|
97
119
|
|
|
120
|
+
**Working artifacts.** For screenshots, exports, audit dumps, rollback inputs,
|
|
121
|
+
and other untracked files that must survive a session, create a managed workspace
|
|
122
|
+
with \`${b} artifacts create <slug> --purpose "<why>"\`. Write files under the
|
|
123
|
+
returned path, then run \`${b} artifacts release <id>\` when active work is done.
|
|
124
|
+
Do not create a repo-root temp directory; \`${b} artifacts clean\` previews
|
|
125
|
+
expired cleanup and requires \`--yes\` to delete anything.
|
|
126
|
+
|
|
98
127
|
**Decision docket.** When you would otherwise stop to ask a human a decision you
|
|
99
128
|
can't resolve from the repo, file it instead. \`${b} decision file "<question>"\`
|
|
100
129
|
records it and lets you proceed on a stated default; \`${b} decision search "<terms>"\`
|
|
@@ -106,10 +135,10 @@ surfaces prior decisions, so check for precedent before re-deciding. ${decidePoi
|
|
|
106
135
|
|
|
107
136
|
// ── Skills ──────────────────────────────────────────────────────────────────
|
|
108
137
|
|
|
109
|
-
/** A shipped skill: its
|
|
138
|
+
/** A shipped skill: its adapter-relative file path + a bin-name-aware renderer. */
|
|
110
139
|
export interface SkillTemplate {
|
|
111
140
|
id: string;
|
|
112
|
-
/** path under the
|
|
141
|
+
/** path under the adapter skill dir, e.g. `harn-decide/SKILL.md` */
|
|
113
142
|
relPath: string;
|
|
114
143
|
render: (binName: string) => string;
|
|
115
144
|
}
|
package/src/lib/machine.ts
CHANGED
|
@@ -5,12 +5,12 @@ import { coordEnv } from "./env.ts";
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Resolve a human-friendly label for the current machine. Used to tag
|
|
8
|
-
* coordination artifacts (
|
|
8
|
+
* coordination artifacts (journal-doc headers, session telemetry) by the host
|
|
9
9
|
* they originated on.
|
|
10
10
|
*
|
|
11
11
|
* Precedence (first non-empty wins):
|
|
12
12
|
* 1. HARNERY_MACHINE env var: transient / per-launch / CI override
|
|
13
|
-
* 2. ~/.config/harnery/machine file: persistent,
|
|
13
|
+
* 2. ~/.config/harnery/machine file: persistent, adapter-neutral identity
|
|
14
14
|
* 3. os.hostname() (normalized): automatic floor; never empty
|
|
15
15
|
*
|
|
16
16
|
* The env var sits on top for ad-hoc overrides; the file is the durable home for
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { Command } from "commander";
|
|
2
|
-
import type { EmitContext } from "../commander.js";
|
|
3
|
-
import { type BenchResult, type HarnessAttestationReport, type HarnessBenchReport } from "../core/harnesses/index.js";
|
|
4
|
-
import type { HarnessProfile } from "../core/harnesses/types.js";
|
|
5
|
-
export declare function registerHarnessCommand(program: Command, emit: EmitContext): void;
|
|
6
|
-
export declare function renderAttestationReport(report: HarnessAttestationReport): string;
|
|
7
|
-
export declare function renderProfileTable(profiles: readonly HarnessProfile[]): string;
|
|
8
|
-
export declare function renderProfile(profile: HarnessProfile): string;
|
|
9
|
-
export declare function renderBenchReport(report: HarnessBenchReport): string;
|
|
10
|
-
/** Kept exported so command tests can assert row semantics without model calls. */
|
|
11
|
-
export type { BenchResult };
|
|
12
|
-
//# sourceMappingURL=harness.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../src/commands/harness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EAIxB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAmBjE,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CA4JhF;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,wBAAwB,GAAG,MAAM,CAgBhF;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,CAU9E;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAkB7D;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CA6BpE;AAgBD,mFAAmF;AACnF,YAAY,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scratch.d.ts","sourceRoot":"","sources":["../../src/commands/scratch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AA6BnD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,GAAG,IAAI,CA2RrF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/commands/session.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAsCnD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,GAAG,IAAI,CAsDrF"}
|