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.
Files changed (128) hide show
  1. package/README.md +63 -10
  2. package/dist/auth-choice-Ck7FJ_PD.js +1 -1
  3. package/dist/auth-choice-CtvmIf50.js +2 -2
  4. package/dist/auth-choice-DYEtgk1X.js +2 -2
  5. package/dist/auth-choice-DtQ1-QBl.js +1 -1
  6. package/dist/auth-profiles-5CHn7vq1.js +101 -171
  7. package/dist/auth-store-transactions.js +135 -0
  8. package/dist/auth-token-DXCF3dFL.js +28 -28
  9. package/dist/auth-token-f950j5qR.js +28 -28
  10. package/dist/codex-oauth-device.js +199 -0
  11. package/dist/codex-oauth-nudge.js +60 -0
  12. package/dist/codex-oauth-owner.js +249 -0
  13. package/dist/codex-oauth-token.js +53 -0
  14. package/dist/command-registry-ZarkU2_Y.js +5 -1
  15. package/dist/commands-registry-C78-tPS3.js +8 -0
  16. package/dist/commands-registry-D0Jkz-Sn.js +8 -0
  17. package/dist/commands-registry-DJWLO-6B.js +8 -0
  18. package/dist/commands-registry-l51VuG0m.js +8 -0
  19. package/dist/compact-B247y5Qt.js +39 -4
  20. package/dist/config-koj5M_EO.js +10 -9
  21. package/dist/coord-swarm-board.js +30 -4
  22. package/dist/daemon-cli.js +12 -48
  23. package/dist/doctor-config-flow-B1i686kY.js +10 -201
  24. package/dist/doctor-config-flow-BjBa3YNF.js +10 -201
  25. package/dist/entry.js +4 -0
  26. package/dist/exec-approvals-1t-rSzbk.js +4 -5
  27. package/dist/exec-approvals-oKbYU_E8.js +4 -5
  28. package/dist/globals-BM8hKFm0.js +1 -0
  29. package/dist/globals-Bv4ZcVWM.js +1 -0
  30. package/dist/index.js +5 -0
  31. package/dist/installs-DGqxcU3J.js +2 -9
  32. package/dist/manifest-registry-BMEqbkWA.js +8 -7
  33. package/dist/manifest-registry-Ba187z7Z.js +8 -7
  34. package/dist/memory-cli-DkhQZF9L.js +29 -2
  35. package/dist/migrate-inspect.js +215 -0
  36. package/dist/migrate-plan.js +30 -0
  37. package/dist/migrate-plugin-adapters.js +31 -0
  38. package/dist/migrate-service.js +42 -0
  39. package/dist/migrate-transaction.js +89 -0
  40. package/dist/migrate.js +28 -0
  41. package/dist/model-selection-BGlGpPgM.js +102 -143
  42. package/dist/model-selection-BU6wl1le.js +102 -143
  43. package/dist/model-selection-L7RMwsG-.js +101 -171
  44. package/dist/models-CxHdes0w.js +9 -3
  45. package/dist/models-cli-DZnoM8Ln.js +11 -4
  46. package/dist/models-cli-U89juIRK.js +3 -1
  47. package/dist/mr-memory-setup.js +64 -0
  48. package/dist/onboard-C_T1ajyP.js +2 -0
  49. package/dist/onboard-CjFEsMQX.js +2 -0
  50. package/dist/onboarding-DYOenUs-.js +2 -0
  51. package/dist/onboarding-VbQraljl.js +2 -0
  52. package/dist/paths-BJV7vkaX.js +3 -39
  53. package/dist/paths-BfR2LXbA.js +3 -39
  54. package/dist/paths-GBpjI3o0.js +3 -39
  55. package/dist/paths-hfkBoC7i.js +3 -39
  56. package/dist/pi-embedded-C6ITuRXf.js +42 -8
  57. package/dist/pi-embedded-DoQsYfIY.js +42 -8
  58. package/dist/plugin-sdk/agents/auth-profiles/profiles.d.ts +1 -1
  59. package/dist/plugin-sdk/agents/auth-profiles/store.d.ts +2 -2
  60. package/dist/plugin-sdk/bluebubbles.js +4 -40
  61. package/dist/plugin-sdk/commands/onboard-auth.credentials.d.ts +2 -2
  62. package/dist/plugin-sdk/commands-registry-B4ZP4Y1B.js +8 -0
  63. package/dist/plugin-sdk/commands-registry-B8Og-fWU.js +8 -0
  64. package/dist/plugin-sdk/commands-registry-BoAXxFpH.js +8 -0
  65. package/dist/plugin-sdk/commands-registry-Ca1h6XvV.js +8 -0
  66. package/dist/plugin-sdk/commands-registry-Do-Y2EhN.js +8 -0
  67. package/dist/plugin-sdk/commands-registry-DpRs-E_M.js +8 -0
  68. package/dist/plugin-sdk/config/agent-limits.d.ts +1 -1
  69. package/dist/plugin-sdk/config/types.agent-defaults.d.ts +2 -2
  70. package/dist/plugin-sdk/config-4Fgm-yEH.js +102 -143
  71. package/dist/plugin-sdk/config-Di-lyCdh.js +102 -143
  72. package/dist/plugin-sdk/core.js +3 -26
  73. package/dist/plugin-sdk/device-pair.js +3 -26
  74. package/dist/plugin-sdk/diagnostics-otel.js +3 -26
  75. package/dist/plugin-sdk/discord.js +12 -48
  76. package/dist/plugin-sdk/dispatch-BP0viZiL.js +42 -8
  77. package/dist/plugin-sdk/dispatch-CQsjmw7g.js +42 -8
  78. package/dist/plugin-sdk/dispatch-Cerq29sy.js +42 -8
  79. package/dist/plugin-sdk/dispatch-Cndjtt0g.js +42 -8
  80. package/dist/plugin-sdk/dispatch-UogiJYul.js +42 -8
  81. package/dist/plugin-sdk/feishu.js +4 -40
  82. package/dist/plugin-sdk/google-gemini-cli-auth.js +3 -39
  83. package/dist/plugin-sdk/googlechat.js +4 -40
  84. package/dist/plugin-sdk/imessage.js +4 -40
  85. package/dist/plugin-sdk/mattermost.js +8 -0
  86. package/dist/plugin-sdk/model-auth-CX9cPHdC.js +102 -143
  87. package/dist/plugin-sdk/model-auth-Ciehz0x5.js +102 -143
  88. package/dist/plugin-sdk/model-auth-DVyo6JSX.js +102 -143
  89. package/dist/plugin-sdk/model-auth-kiHYHGrs.js +102 -143
  90. package/dist/plugin-sdk/model-selection-Dbj4jDYM.js +40 -96
  91. package/dist/plugin-sdk/nostr.js +3 -26
  92. package/dist/plugin-sdk/paths-B9fwHuf0.js +3 -39
  93. package/dist/plugin-sdk/paths-D6tDENa_.js +3 -39
  94. package/dist/plugin-sdk/paths-Dmn791zP.js +3 -39
  95. package/dist/plugin-sdk/paths-akVZbnot.js +3 -39
  96. package/dist/plugin-sdk/paths-eFexkPEh.js +3 -39
  97. package/dist/plugin-sdk/reply-DbZnH8-h.js +42 -8
  98. package/dist/plugin-sdk/signal.js +4 -40
  99. package/dist/plugin-sdk/slack.js +4 -40
  100. package/dist/plugin-sdk/synology-chat.js +3 -39
  101. package/dist/plugin-sdk/telegram.js +4 -40
  102. package/dist/plugin-sdk/tlon.js +4 -40
  103. package/dist/plugin-sdk/twitch.js +4 -40
  104. package/dist/plugin-sdk/voice-call.js +3 -39
  105. package/dist/plugin-sdk/zalo.js +4 -40
  106. package/dist/plugin-sdk/zalouser.js +4 -40
  107. package/dist/program-Csx0T2gv.js +1 -0
  108. package/dist/program-context-CKpVgs9O.js +4 -0
  109. package/dist/prompt-select-styled-C_vP6os-.js +2 -4
  110. package/dist/prompt-select-styled-ClBOfLjF.js +2 -4
  111. package/dist/provider-auth-helpers-BKS7ln76.js +1 -1
  112. package/dist/provider-auth-helpers-D5_z82-N.js +1 -1
  113. package/dist/register.migrate.js +12 -0
  114. package/dist/register.onboard-3v4vug5B.js +3 -1
  115. package/dist/register.onboard-Cwc9htf5.js +3 -1
  116. package/dist/reply-C5LKjXcC.js +39 -4
  117. package/dist/status-Cz7cjn88.js +1 -1
  118. package/dist/status-DH0rKO8q.js +1 -1
  119. package/dist/swarm-primitive.js +1563 -0
  120. package/dist/utils-CUUJ4XQX.js +3 -39
  121. package/docs/PATCHES.md +183 -113
  122. package/docs/SWARM.md +174 -0
  123. package/docs/images/swarm-spawn-alt.png +0 -0
  124. package/docs/images/swarm-spawn.png +0 -0
  125. package/docs/tools/subagents.md +5 -5
  126. package/johnness.mjs +5 -0
  127. package/package.json +1 -1
  128. package/scripts/postinstall.mjs +3 -6
package/README.md CHANGED
@@ -8,7 +8,17 @@
8
8
 
9
9
  ![A collective of AI agents working one codebase together](docs/images/swarm-collective.png)
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 config set plugins.entries.mr-memory.config.key "mk_your_key"
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. The third line stores a MemoryRouter API key from [memoryrouter.ai](https://memoryrouter.ai); until it is set, the harness still runs and prints one setup line saying where to put it.
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 config set plugins.entries.mr-memory.config.key "mk_..."` | Turns on persistent memory. The plugin is already installed and enabled. |
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 # 529 tests against the installed dependency tree
50
- bash scripts/verify-patches.sh # 182 checks across every patch family
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
+ ![One command launches a hundred agents that fan out over a codebase and pick up work from a shared board](docs/images/swarm-spawn.png)
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, and a push preflight that blocks stale, forced, broad, and unauthorized pushes.
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: 54 patch families, each with a regression test and a rollback path.
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 54 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 182 checks against the package tree and installed dependencies, and 529 tests run against the installed dependency tree.
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 54 patch families, one record each.
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
 
@@ -206,7 +206,7 @@ async function applyNonInteractiveAuthChoice(params) {
206
206
  provider,
207
207
  name: ""
208
208
  });
209
- upsertAuthProfile({
209
+ await upsertAuthProfile({
210
210
  profileId,
211
211
  credential: {
212
212
  type: "token",
@@ -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
@@ -206,7 +206,7 @@ async function applyNonInteractiveAuthChoice(params) {
206
206
  provider,
207
207
  name: ""
208
208
  });
209
- upsertAuthProfile({
209
+ await upsertAuthProfile({
210
210
  profileId,
211
211
  credential: {
212
212
  type: "token",