johns-harness 2026.9.8 → 2026.9.11
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 +63 -10
- package/dist/auth-choice-Ck7FJ_PD.js +1 -1
- package/dist/auth-choice-CtvmIf50.js +2 -2
- package/dist/auth-choice-DYEtgk1X.js +2 -2
- package/dist/auth-choice-DtQ1-QBl.js +1 -1
- package/dist/auth-profiles-5CHn7vq1.js +101 -171
- package/dist/auth-store-transactions.js +135 -0
- package/dist/auth-token-DXCF3dFL.js +28 -28
- package/dist/auth-token-f950j5qR.js +28 -28
- package/dist/codex-oauth-device.js +199 -0
- package/dist/codex-oauth-nudge.js +60 -0
- package/dist/codex-oauth-owner.js +249 -0
- package/dist/codex-oauth-token.js +53 -0
- package/dist/command-registry-ZarkU2_Y.js +5 -1
- package/dist/commands-registry-C78-tPS3.js +8 -0
- package/dist/commands-registry-D0Jkz-Sn.js +8 -0
- package/dist/commands-registry-DJWLO-6B.js +8 -0
- package/dist/commands-registry-l51VuG0m.js +8 -0
- package/dist/compact-B247y5Qt.js +39 -4
- package/dist/config-koj5M_EO.js +10 -9
- package/dist/coord-swarm-board.js +30 -4
- package/dist/daemon-cli.js +12 -48
- package/dist/doctor-config-flow-B1i686kY.js +10 -201
- package/dist/doctor-config-flow-BjBa3YNF.js +10 -201
- package/dist/entry.js +4 -0
- package/dist/exec-approvals-1t-rSzbk.js +4 -5
- package/dist/exec-approvals-oKbYU_E8.js +4 -5
- package/dist/globals-BM8hKFm0.js +1 -0
- package/dist/globals-Bv4ZcVWM.js +1 -0
- package/dist/index.js +5 -0
- package/dist/installs-DGqxcU3J.js +2 -9
- package/dist/manifest-registry-BMEqbkWA.js +8 -7
- package/dist/manifest-registry-Ba187z7Z.js +8 -7
- package/dist/memory-cli-DkhQZF9L.js +29 -2
- package/dist/migrate-inspect.js +215 -0
- package/dist/migrate-plan.js +30 -0
- package/dist/migrate-plugin-adapters.js +31 -0
- package/dist/migrate-service.js +42 -0
- package/dist/migrate-transaction.js +89 -0
- package/dist/migrate.js +28 -0
- package/dist/model-selection-BGlGpPgM.js +102 -143
- package/dist/model-selection-BU6wl1le.js +102 -143
- package/dist/model-selection-L7RMwsG-.js +101 -171
- package/dist/models-CxHdes0w.js +9 -3
- package/dist/models-cli-DZnoM8Ln.js +11 -4
- package/dist/models-cli-U89juIRK.js +3 -1
- package/dist/mr-memory-setup.js +64 -0
- package/dist/onboard-C_T1ajyP.js +2 -0
- package/dist/onboard-CjFEsMQX.js +2 -0
- package/dist/onboarding-DYOenUs-.js +2 -0
- package/dist/onboarding-VbQraljl.js +2 -0
- package/dist/paths-BJV7vkaX.js +3 -39
- package/dist/paths-BfR2LXbA.js +3 -39
- package/dist/paths-GBpjI3o0.js +3 -39
- package/dist/paths-hfkBoC7i.js +3 -39
- package/dist/pi-embedded-C6ITuRXf.js +42 -8
- package/dist/pi-embedded-DoQsYfIY.js +42 -8
- package/dist/plugin-sdk/agents/auth-profiles/profiles.d.ts +1 -1
- package/dist/plugin-sdk/agents/auth-profiles/store.d.ts +2 -2
- package/dist/plugin-sdk/bluebubbles.js +4 -40
- package/dist/plugin-sdk/commands/onboard-auth.credentials.d.ts +2 -2
- package/dist/plugin-sdk/commands-registry-B4ZP4Y1B.js +8 -0
- package/dist/plugin-sdk/commands-registry-B8Og-fWU.js +8 -0
- package/dist/plugin-sdk/commands-registry-BoAXxFpH.js +8 -0
- package/dist/plugin-sdk/commands-registry-Ca1h6XvV.js +8 -0
- package/dist/plugin-sdk/commands-registry-Do-Y2EhN.js +8 -0
- package/dist/plugin-sdk/commands-registry-DpRs-E_M.js +8 -0
- package/dist/plugin-sdk/config/agent-limits.d.ts +1 -1
- package/dist/plugin-sdk/config/types.agent-defaults.d.ts +2 -2
- package/dist/plugin-sdk/config-4Fgm-yEH.js +102 -143
- package/dist/plugin-sdk/config-Di-lyCdh.js +102 -143
- package/dist/plugin-sdk/core.js +3 -26
- package/dist/plugin-sdk/device-pair.js +3 -26
- package/dist/plugin-sdk/diagnostics-otel.js +3 -26
- package/dist/plugin-sdk/discord.js +12 -48
- package/dist/plugin-sdk/dispatch-BP0viZiL.js +42 -8
- package/dist/plugin-sdk/dispatch-CQsjmw7g.js +42 -8
- package/dist/plugin-sdk/dispatch-Cerq29sy.js +42 -8
- package/dist/plugin-sdk/dispatch-Cndjtt0g.js +42 -8
- package/dist/plugin-sdk/dispatch-UogiJYul.js +42 -8
- package/dist/plugin-sdk/feishu.js +4 -40
- package/dist/plugin-sdk/google-gemini-cli-auth.js +3 -39
- package/dist/plugin-sdk/googlechat.js +4 -40
- package/dist/plugin-sdk/imessage.js +4 -40
- package/dist/plugin-sdk/mattermost.js +8 -0
- package/dist/plugin-sdk/model-auth-CX9cPHdC.js +102 -143
- package/dist/plugin-sdk/model-auth-Ciehz0x5.js +102 -143
- package/dist/plugin-sdk/model-auth-DVyo6JSX.js +102 -143
- package/dist/plugin-sdk/model-auth-kiHYHGrs.js +102 -143
- package/dist/plugin-sdk/model-selection-Dbj4jDYM.js +40 -96
- package/dist/plugin-sdk/nostr.js +3 -26
- package/dist/plugin-sdk/paths-B9fwHuf0.js +3 -39
- package/dist/plugin-sdk/paths-D6tDENa_.js +3 -39
- package/dist/plugin-sdk/paths-Dmn791zP.js +3 -39
- package/dist/plugin-sdk/paths-akVZbnot.js +3 -39
- package/dist/plugin-sdk/paths-eFexkPEh.js +3 -39
- package/dist/plugin-sdk/reply-DbZnH8-h.js +42 -8
- package/dist/plugin-sdk/signal.js +4 -40
- package/dist/plugin-sdk/slack.js +4 -40
- package/dist/plugin-sdk/synology-chat.js +3 -39
- package/dist/plugin-sdk/telegram.js +4 -40
- package/dist/plugin-sdk/tlon.js +4 -40
- package/dist/plugin-sdk/twitch.js +4 -40
- package/dist/plugin-sdk/voice-call.js +3 -39
- package/dist/plugin-sdk/zalo.js +4 -40
- package/dist/plugin-sdk/zalouser.js +4 -40
- package/dist/program-Csx0T2gv.js +1 -0
- package/dist/program-context-CKpVgs9O.js +4 -0
- package/dist/prompt-select-styled-C_vP6os-.js +2 -4
- package/dist/prompt-select-styled-ClBOfLjF.js +2 -4
- package/dist/provider-auth-helpers-BKS7ln76.js +1 -1
- package/dist/provider-auth-helpers-D5_z82-N.js +1 -1
- package/dist/register.migrate.js +12 -0
- package/dist/register.onboard-3v4vug5B.js +3 -1
- package/dist/register.onboard-Cwc9htf5.js +3 -1
- package/dist/reply-C5LKjXcC.js +39 -4
- package/dist/status-Cz7cjn88.js +1 -1
- package/dist/status-DH0rKO8q.js +1 -1
- package/dist/swarm-primitive.js +1563 -0
- package/dist/utils-CUUJ4XQX.js +3 -39
- package/docs/PATCHES.md +183 -113
- package/docs/SWARM.md +174 -0
- package/docs/images/swarm-spawn-alt.png +0 -0
- package/docs/images/swarm-spawn.png +0 -0
- package/docs/tools/subagents.md +5 -5
- package/johnness.mjs +5 -0
- package/package.json +1 -1
- package/scripts/postinstall.mjs +3 -6
package/README.md
CHANGED
|
@@ -8,7 +8,17 @@
|
|
|
8
8
|
|
|
9
9
|

|
|
10
10
|
|
|
11
|
-
John's Harness is a production agent harness for engineers who run more than one coding agent at a time. Agents work the same repositories at once, coordinate through a durable board keyed by git origin, message each other while they run, and ship only through an exact-head push gate with per-commit production authority. Memory persists across sessions and compaction and is shared by every agent in the swarm.
|
|
11
|
+
John's Harness is a production agent harness for engineers who run more than one coding agent at a time. Agents work the same repositories at once, coordinate through a durable board keyed by git origin, message each other while they run, and ship only through an exact-head push gate with per-commit production authority. Memory persists across sessions and compaction and is shared by every agent in the swarm. Launching a swarm takes one command and a number; the members divide the work among themselves.
|
|
12
|
+
|
|
13
|
+
## Migrating from OpenClaw
|
|
14
|
+
Bring your agents, memory, credentials, and scheduled jobs into John's Harness.
|
|
15
|
+
```sh
|
|
16
|
+
npm i -g johns-harness && johnness migrate
|
|
17
|
+
```
|
|
18
|
+
The command backs up your state, creates `~/.johnness`, rewrites settings, and checks the result.
|
|
19
|
+
If your gateway is running, it shows the exact stop command before making changes.
|
|
20
|
+
Review any script updates, then follow the printed commands to start the new gateway.
|
|
21
|
+
Your original installation stays intact. Preview with `johnness migrate --dry-run`; undo with `johnness migrate --rollback`.
|
|
12
22
|
|
|
13
23
|
## Quick start
|
|
14
24
|
|
|
@@ -17,12 +27,12 @@ Requires Node 22.12 or newer.
|
|
|
17
27
|
```bash
|
|
18
28
|
npm install -g johns-harness
|
|
19
29
|
johnness onboard
|
|
20
|
-
johnness
|
|
30
|
+
johnness memory mk_your_key
|
|
21
31
|
```
|
|
22
32
|
|
|
23
33
|
The package is `johns-harness`; the command it installs is `johnness`.
|
|
24
34
|
|
|
25
|
-
The wizard sets up credentials, workspace, gateway, and channels.
|
|
35
|
+
The wizard sets up credentials, workspace, gateway, and channels. It asks for your MemoryRouter API key and links to [signup](https://app.memoryrouter.ai/signup), free to start. If you skip memory in the wizard, the third line stores the key later.
|
|
26
36
|
|
|
27
37
|
### First run
|
|
28
38
|
|
|
@@ -30,11 +40,17 @@ The wizard sets up credentials, workspace, gateway, and channels. The third line
|
|
|
30
40
|
| --- | --- | --- |
|
|
31
41
|
| Install | `npm install -g johns-harness` | Installs the CLI, the runtime, and the default memory plugin. A postinstall step applies the patched dependency files. |
|
|
32
42
|
| Configure | `johnness onboard` | Interactive wizard for gateway, workspace, and skills. `johnness configure` reopens it later. |
|
|
33
|
-
| Memory | `johnness
|
|
43
|
+
| Memory | `johnness memory mk_your_key` | Turns on persistent memory. The plugin is already installed and enabled. |
|
|
34
44
|
| Start | `johnness gateway start` | Starts the gateway as a background service. `johnness gateway run` keeps it in the foreground. |
|
|
35
45
|
| Connect | `johnness channels add --channel telegram --token "<bot token>"` | Connects a chat channel. Discord, Slack, WhatsApp, Signal, iMessage, Matrix, and more are supported. |
|
|
36
46
|
| Check | `johnness doctor` | Health checks and quick fixes for the gateway and channels. |
|
|
37
47
|
|
|
48
|
+
### Signing in from chat
|
|
49
|
+
Owners and allowlisted senders can send `/login` (or `/relogin`) in Telegram, Discord, or another chat channel.
|
|
50
|
+
Open the link, enter the device code, and sign in to ChatGPT; the harness reconnects automatically.
|
|
51
|
+
For headless installs, run `johnness models auth login --device`; no browser or localhost callback needed.
|
|
52
|
+
Expired ChatGPT credentials trigger an owner notice with the `/login` recovery command.
|
|
53
|
+
|
|
38
54
|
### From source
|
|
39
55
|
|
|
40
56
|
```bash
|
|
@@ -46,21 +62,54 @@ node johnness.mjs --help
|
|
|
46
62
|
### Verify
|
|
47
63
|
|
|
48
64
|
```bash
|
|
49
|
-
npm test #
|
|
50
|
-
bash scripts/verify-patches.sh #
|
|
65
|
+
npm test # 701 tests against the installed dependency tree
|
|
66
|
+
bash scripts/verify-patches.sh # 258 checks across every patch family
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Launch a swarm with one command
|
|
70
|
+
|
|
71
|
+
One call, one number. The orchestrator writes a single directive and chooses how many agents should work it. The members decide everything else.
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
swarm_spawn({
|
|
75
|
+
directive: "<the whole briefing: goal, scope, forbidden files, push rules, author identity>",
|
|
76
|
+
count: 12,
|
|
77
|
+
coord: { root: "/abs/path/to/repo", branch: "main", prodAuthorized: false },
|
|
78
|
+
model: "anthropic/claude-fable-5-1" // optional, applies to every member
|
|
79
|
+
})
|
|
51
80
|
```
|
|
52
81
|
|
|
82
|
+

|
|
83
|
+
|
|
84
|
+
Every member receives the same directive plus a short runtime preamble that carries the protocol. Nobody hands out work.
|
|
85
|
+
|
|
86
|
+
The lowest-numbered live member decomposes the directive into work items on the shared board. The post is a compare-and-swap, so exactly one plan exists no matter how many members arrive at the same moment; the rest wait for it rather than poll.
|
|
87
|
+
|
|
88
|
+
Each member claims one open item atomically, works it, pushes, marks it done or failed, and claims the next. A claim is exactly one winner, even under concurrent attempts.
|
|
89
|
+
|
|
90
|
+
Claims carry a 15 minute lease that heartbeats extend. A lease that lapses reopens the item the moment anyone looks at the board, so a dead member never strands its work.
|
|
91
|
+
|
|
92
|
+
When work reveals more items, any member appends them to the plan and the addition wakes the others through their inboxes. Members message each other directly only for a real dependency, and each records how the swarm coordinated so the next one starts smarter.
|
|
93
|
+
|
|
94
|
+
The preamble also carries the operating protocol as defaults with named exceptions: the planner declares the shape of the work, one integrator merges parallel branches and builds and pushes once so parallel work flows into a single sequential step, one gateway or a shared budget fronts each rate-limited host, and done means done. Members ask a service holder with a durable request and wait on the answer without polling.
|
|
95
|
+
|
|
96
|
+
Per-member announces are suppressed. When the last member finishes, one `swarm finished` rollup arrives with every item, its owner, its pushed head, and its summary.
|
|
97
|
+
|
|
98
|
+
`count` runs from 2 to 100. Members beyond the concurrency limit are queued and start as slots free, and `swarm_status` reads a swarm's progress without interrupting anyone. Members are ordinary agents: same depth rules, same push preflight, same per-commit production authority, no force pushes.
|
|
99
|
+
|
|
100
|
+
Full guide, including the preamble members receive and the work item state machine: [`docs/SWARM.md`](docs/SWARM.md).
|
|
101
|
+
|
|
53
102
|
## The problem
|
|
54
103
|
|
|
55
104
|
Coding agents today run as isolated processes. Two agents on the same repository have no shared state, no way to talk to each other mid-task, and no gate between a dirty local branch and production. Once a context window compacts, whatever the agent knew is gone.
|
|
56
105
|
|
|
57
106
|
## What makes it different
|
|
58
107
|
|
|
59
|
-
- **A swarm, not a pile of agents.** One coordination board per repository, direct agent-to-agent messages delivered inside a busy agent's run, exclusive claims on shared areas,
|
|
108
|
+
- **A swarm, not a pile of agents.** One coordination board per repository, direct agent-to-agent messages delivered inside a busy agent's run, exclusive claims on shared areas, a push preflight that blocks stale, forced, broad, and unauthorized pushes, and `swarm_spawn`, which launches up to 100 agents from one directive in a single call.
|
|
60
109
|
- **Memory built for production.** Tiered recall that traces from consolidated reflections down to the verbatim record, surviving compaction and shared across the swarm. Installed and enabled by default.
|
|
61
110
|
- **Production authority per commit.** Promotion is granted to an exact SHA, never to a branch name, so one worker's authorization never covers another worker's commits.
|
|
62
111
|
- **An append-only action log.** Agents record every consequential action to `ACTION_LOG.md` and read it before acting.
|
|
63
|
-
- **A fixed runtime surface.** The core does not grow on a schedule. New mechanisms enter only to solve a demonstrated production failure, one narrow, tested, reversible patch at a time:
|
|
112
|
+
- **A fixed runtime surface.** The core does not grow on a schedule. New mechanisms enter only to solve a demonstrated production failure, one narrow, tested, reversible patch at a time: 59 patch families, each with a regression test and a rollback path.
|
|
64
113
|
- **Reliability with a definition.** Bounded retries, explicit failure states, exact-once continuation, context-pressure recovery, durable delivery, and supervised gateway recovery.
|
|
65
114
|
- **Coding first, phone optional.** Direct the work at a high level from a chat channel while agents plan, implement, test, coordinate, and stage releases unattended.
|
|
66
115
|
- **Local voice.** Optional native Whisper transcription of inbound audio, entirely on your machine. Off by default. [Setup](docs/NATIVE-WHISPER-MUSE.md).
|
|
@@ -92,8 +141,12 @@ Agents sharing a filesystem are not a swarm. A swarm knows who owns which work,
|
|
|
92
141
|
|
|
93
142
|
**Production authority belongs to a commit.** Never to a branch name or a timestamp.
|
|
94
143
|
|
|
144
|
+
**One directive, one number.** `swarm_spawn` launches up to 100 members from the same briefing and they divide the work themselves. See the launch section near the top of this page and the [swarm guide](docs/SWARM.md).
|
|
145
|
+
|
|
95
146
|
## Memory
|
|
96
147
|
|
|
148
|
+
Run `johnness memory mk_your_key` to set your MemoryRouter API key and start persistent memory, or enter it during onboarding.
|
|
149
|
+
|
|
97
150
|
The future of AI is not smarter models. It is models with the right context: what is happening, what happened before, and what matters now.
|
|
98
151
|
|
|
99
152
|
An agent in this harness remembers what it was told yesterday, the decision it made last Tuesday, the fix it tried that did not work, and why. That context persists across sessions and survives compaction. It does not live and die inside one context window.
|
|
@@ -123,7 +176,7 @@ The log is a [`RULES.md`](RULES.md) workspace convention enforced through the ac
|
|
|
123
176
|
|
|
124
177
|
## Patch families
|
|
125
178
|
|
|
126
|
-
The runtime carries
|
|
179
|
+
The runtime carries 59 patch families. Each is a production fix applied at the source with a regression test, a durable patch marker, and a rollback path. A verifier runs 258 checks against the package tree and installed dependencies, and 701 tests run against the installed dependency tree.
|
|
127
180
|
|
|
128
181
|
Every family follows the same six steps: reproduce the failure, trace the exact runtime path, make the smallest source-level change that restores the invariant, add a regression test and a patch marker, run the verifier, and retain rollback artifacts. The full index: [`docs/PATCHES.md`](docs/PATCHES.md).
|
|
129
182
|
|
|
@@ -140,7 +193,7 @@ Every family follows the same six steps: reproduce the failure, trace the exact
|
|
|
140
193
|
## Documentation
|
|
141
194
|
|
|
142
195
|
- [`docs/index.md`](docs/index.md): runtime docs, from gateway and channels to plugins, nodes, and CLI reference.
|
|
143
|
-
- [`docs/PATCHES.md`](docs/PATCHES.md): the
|
|
196
|
+
- [`docs/PATCHES.md`](docs/PATCHES.md): the 59 patch families, one record each.
|
|
144
197
|
- [`docs/NATIVE-WHISPER-MUSE.md`](docs/NATIVE-WHISPER-MUSE.md): local Whisper transcription setup.
|
|
145
198
|
- [`RULES.md`](RULES.md): the default operating rules, including Rule Zero on production authorization.
|
|
146
199
|
|
|
@@ -62,7 +62,7 @@ async function applyAuthChoiceAnthropic(params) {
|
|
|
62
62
|
provider,
|
|
63
63
|
name: String(profileNameRaw ?? "")
|
|
64
64
|
});
|
|
65
|
-
upsertAuthProfile({
|
|
65
|
+
await upsertAuthProfile({
|
|
66
66
|
profileId: namedProfileId,
|
|
67
67
|
agentDir: params.agentDir,
|
|
68
68
|
credential: {
|
|
@@ -813,7 +813,7 @@ async function applyAuthChoicePluginProvider(params, options) {
|
|
|
813
813
|
});
|
|
814
814
|
if (result.configPatch) nextConfig = mergeConfigPatch(nextConfig, result.configPatch);
|
|
815
815
|
for (const profile of result.profiles) {
|
|
816
|
-
upsertAuthProfile({
|
|
816
|
+
await upsertAuthProfile({
|
|
817
817
|
profileId: profile.profileId,
|
|
818
818
|
credential: profile.credential,
|
|
819
819
|
agentDir
|
|
@@ -62,7 +62,7 @@ async function applyAuthChoiceAnthropic(params) {
|
|
|
62
62
|
provider,
|
|
63
63
|
name: String(profileNameRaw ?? "")
|
|
64
64
|
});
|
|
65
|
-
upsertAuthProfile({
|
|
65
|
+
await upsertAuthProfile({
|
|
66
66
|
profileId: namedProfileId,
|
|
67
67
|
agentDir: params.agentDir,
|
|
68
68
|
credential: {
|
|
@@ -813,7 +813,7 @@ async function applyAuthChoicePluginProvider(params, options) {
|
|
|
813
813
|
});
|
|
814
814
|
if (result.configPatch) nextConfig = mergeConfigPatch(nextConfig, result.configPatch);
|
|
815
815
|
for (const profile of result.profiles) {
|
|
816
|
-
upsertAuthProfile({
|
|
816
|
+
await upsertAuthProfile({
|
|
817
817
|
profileId: profile.profileId,
|
|
818
818
|
credential: profile.credential,
|
|
819
819
|
agentDir
|