harnex 0.12.0 → 0.29.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.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +616 -0
  3. data/GUIDE.md +222 -68
  4. data/README.md +78 -48
  5. data/TECHNICAL.md +235 -98
  6. data/agents/gpt.md +60 -0
  7. data/docs/agents.md +119 -0
  8. data/docs/configuration.md +4 -0
  9. data/docs/dispatch-telemetry.md +184 -50
  10. data/docs/events.md +20 -7
  11. data/docs/lanes.md +206 -0
  12. data/docs/mcp.md +102 -0
  13. data/docs/pi-rpc.md +81 -7
  14. data/docs/upgrading-to-0.29.md +87 -0
  15. data/guides/01_dispatch.md +103 -35
  16. data/guides/04_monitoring.md +223 -25
  17. data/guides/05_naming.md +0 -1
  18. data/guides/06_claude.md +96 -0
  19. data/lib/harnex/adapters/base.rb +4 -8
  20. data/lib/harnex/adapters/pi.rb +92 -12
  21. data/lib/harnex/adapters.rb +1 -16
  22. data/lib/harnex/artifact_report.rb +206 -12
  23. data/lib/harnex/cli.rb +68 -50
  24. data/lib/harnex/commands/ask.rb +285 -0
  25. data/lib/harnex/commands/delegate.rb +208 -0
  26. data/lib/harnex/commands/doctor.rb +34 -36
  27. data/lib/harnex/commands/events.rb +3 -3
  28. data/lib/harnex/commands/history.rb +2 -8
  29. data/lib/harnex/commands/land.rb +150 -0
  30. data/lib/harnex/commands/lanes.rb +84 -0
  31. data/lib/harnex/commands/logs.rb +3 -3
  32. data/lib/harnex/commands/mcp.rb +208 -0
  33. data/lib/harnex/commands/orchestration.rb +88 -9
  34. data/lib/harnex/commands/pane.rb +3 -3
  35. data/lib/harnex/commands/preflight.rb +566 -0
  36. data/lib/harnex/commands/reply.rb +125 -0
  37. data/lib/harnex/commands/result.rb +108 -0
  38. data/lib/harnex/commands/run.rb +249 -64
  39. data/lib/harnex/commands/send.rb +121 -16
  40. data/lib/harnex/commands/status.rb +32 -4
  41. data/lib/harnex/commands/stop.rb +14 -4
  42. data/lib/harnex/commands/telemetry.rb +19 -1
  43. data/lib/harnex/commands/wait.rb +421 -56
  44. data/lib/harnex/commands/watch.rb +134 -21
  45. data/lib/harnex/context_file.rb +85 -0
  46. data/lib/harnex/core.rb +100 -15
  47. data/lib/harnex/dispatch_history.rb +157 -10
  48. data/lib/harnex/lanes.rb +548 -0
  49. data/lib/harnex/mcp.rb +362 -0
  50. data/lib/harnex/orchestration.rb +128 -5
  51. data/lib/harnex/owned_process_group.rb +50 -0
  52. data/lib/harnex/owner_stream.rb +399 -0
  53. data/lib/harnex/pricing.rb +4 -9
  54. data/lib/harnex/runtime/activity_tracker.rb +107 -0
  55. data/lib/harnex/runtime/api_server.rb +11 -1
  56. data/lib/harnex/runtime/completion_notifier.rb +90 -11
  57. data/lib/harnex/runtime/inbox.rb +26 -7
  58. data/lib/harnex/runtime/message.rb +5 -2
  59. data/lib/harnex/runtime/runtime_budget.rb +96 -0
  60. data/lib/harnex/runtime/session.rb +684 -294
  61. data/lib/harnex/runtime/stop_request.rb +39 -0
  62. data/lib/harnex/stall.rb +46 -0
  63. data/lib/harnex/telemetry_reconciler.rb +42 -20
  64. data/lib/harnex/terminal_status.rb +5 -5
  65. data/lib/harnex/version.rb +2 -2
  66. data/lib/harnex.rb +16 -0
  67. data/recipes/01_fire_and_watch.md +14 -14
  68. data/recipes/02_chain_implement.md +35 -31
  69. data/recipes/03_buddy.md +1 -1
  70. metadata +34 -12
  71. data/docs/codex-appserver.md +0 -175
  72. data/lib/harnex/adapters/codex.rb +0 -160
  73. data/lib/harnex/adapters/codex_appserver.rb +0 -407
  74. data/lib/harnex/codex/app_server/client.rb +0 -347
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ea3eab047cc2e9f086fba4cfb98c6f585ffe888fdee0fb018c35515fe6257b4
4
- data.tar.gz: ba40b96028fd01e6ade7517374e7d26d92a5d147a7be2ec08a581cd0203dae62
3
+ metadata.gz: e36a59564be22ba55cda2815e3e72b59b887bb2a4e0417be776295ef1cb10b82
4
+ data.tar.gz: 0a9b1355a5bc153e4d6fdd6ef79df81f022c5b6a75f97de0a8f91ef52353e526
5
5
  SHA512:
6
- metadata.gz: e1e85c57df13dd411b10308659b72376f9491f1c6e4d7c4e5d906f9f78096dc0f82a0ac866c01e356d75cedb5f285b71970d0ea175e5935ca8ed0e3bcf40dd88
7
- data.tar.gz: 1283d788ceaff2e608f7e13b7f4f640d65d9f683e35cbe649cc9dd7d0223e094740df146fbe10ed6fa15685bf27671e9059c6378bb2bc8acc5c850aef5f6c9ab
6
+ metadata.gz: 1794b1c8190bf40109732a821470d9a24772be9e68e46b9c49732ac46bd24fb73a88d07d0097dece3ec43e3b164932903d69ffda7fa6b4f18b244989990c8a52
7
+ data.tar.gz: 8163c5eb86dacb6174868459fcc9bba2fb87b66c503e61a96f38baefbe2ca93423df3a84fd07da626927402fe5432f4f541eec202a7b4cc4fde131e1b9ff7de4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,621 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.29.1] - 2026-10-23 | 10:31 AM | IST
4
+
5
+ Local-only fix release for #88: lanes in repos with a phase allowlist.
6
+
7
+ ### Fixed
8
+
9
+ - In a repo whose `.harnex/config.json` phase allowlist has
10
+ `"policy": "reject"`, harnex refused every `delegate`, `ask --write` and
11
+ `reply` (`meta.phase (none) is not allowlisted`). The run behind a lane
12
+ is now tagged with phase `delegate` or `ask`. These are harnex's own
13
+ phases, like `preflight`, so every allowlist accepts them.
14
+ - A lane that harnex refused before the worker started left a `failed`
15
+ record, so a retry under the same name failed with `lane NAME already
16
+ exists (failed)` until `discard`. Now a refused new lane leaves no record
17
+ and no brief. A refused `reply` keeps the state the lane's last turn left.
18
+ The next `delegate` under the same name also clears a record left this way
19
+ by 0.29.0.
20
+
21
+ ### Added
22
+
23
+ - `harnex delegate --phase NAME` and `harnex ask --phase NAME` tag a lane
24
+ with a work phase such as `implement`. The repo allowlist checks a named
25
+ phase, and `reply` reuses it.
26
+
27
+ ## [0.29.0] - 2026-10-22 | 06:08 PM | IST
28
+
29
+ **The agent release.** harnex becomes a tool your coding agents use directly:
30
+ hand a question or a task to a Pi worker (GPT by default) and get the reply
31
+ back as plain text, with a footer saying what happened and what to do next.
32
+ This entry summarizes 0.22.0–0.29.0, the first public release since 0.12.0.
33
+ Website and docs: <https://harnex.zyt.app>. Upgrading:
34
+ `docs/upgrading-to-0.29.md`.
35
+
36
+ ### Highlights
37
+
38
+ - **Lanes** (0.22):
39
+ - `harnex delegate [--worktree NAME]` hands a task to a worker, optionally
40
+ in its own git worktree;
41
+ - `result` collects parallel lanes;
42
+ - `reply` follows up with the worker's context (a finished lane resumes its
43
+ Pi session);
44
+ - `land` merges and cleans up; `discard` drops a lane; `lanes` shows what
45
+ each worker is doing right now.
46
+ - **`harnex mcp`** (0.23): the same verbs as native MCP tools for Claude Code,
47
+ Pi and any MCP client. Long calls report progress, and Claude Code moves them
48
+ to the background and notifies on completion. `harnex mcp install`
49
+ registers it for both clients.
50
+ - **The `gpt` subagent for Claude Code** (0.21, MCP relay since 0.23): ships
51
+ as `agents/gpt.md`, and `harnex mcp install` installs it.
52
+ - **Smoothness work** (0.24–0.28), measured with `evals/agents/run`. Real
53
+ Claude Code and Pi supervisors, with and without MCP, run seven scenarios;
54
+ 0.28 passed two consecutive full rounds (28/28 each) with no harnex usage
55
+ errors, no doc lookups and nothing left behind. Along the way:
56
+ - progress detail;
57
+ - the hand-merge sweep;
58
+ - model-failure next steps;
59
+ - forgiving flags and MCP arguments;
60
+ - workers never see harnex's own MCP tools.
61
+
62
+ ### Breaking (since 0.12.0)
63
+
64
+ - Codex adapters, the JSON-RPC transport, `run --fast`/`--legacy-pty` and
65
+ `preflight --legacy-pty` were removed (0.20); harnex is Pi + GPT first.
66
+ - `harnex ask` waits 9 minutes by default (0.22); use `--timeout none` for no
67
+ cap.
68
+ - Pi starts with `--no-approve` unless `-- --approve` is passed (0.22).
69
+
70
+ ### Added in 0.29.0
71
+
72
+ - **Docs:**
73
+ - `docs/lanes.md`, `docs/mcp.md`, `docs/agents.md` and
74
+ `docs/upgrading-to-0.29.md`;
75
+ - `GUIDE.md` now starts with lanes;
76
+ - `TECHNICAL.md` gains a "Lanes and MCP" architecture section.
77
+ - **The website** `site/`: a monospace, terminal-styled site built from these
78
+ docs and the live CLI help, deployed as a Holm app to harnex.zyt.app.
79
+ - **The `gpt` agent ships in the gem** (`agents/gpt.md`). `harnex mcp
80
+ install` installs it at `~/.claude/agents/gpt.md` unless one exists
81
+ (`--no-agent` skips it). `uninstall` removes only an unmodified copy.
82
+ - **Gem metadata:** a new summary and description, plus documentation and
83
+ changelog links.
84
+
85
+ ### Changed
86
+
87
+ - Examples use generic model names (`openai/gpt-5.1`).
88
+
89
+ ## [0.28.0] - 2026-10-22 | 05:15 PM | IST
90
+
91
+ Owner-authorized local-only release (#87): fixes from round B on 0.27.0.
92
+
93
+ ### Changed
94
+
95
+ - The MCP `ask` tool description, `harnex ask --help` and the skill index
96
+ say that an ask worker only reads and cannot run commands; to run tests,
97
+ scripts or benchmarks, use `delegate`. In round B, a relay sent "run
98
+ bin/slow-bench" to a read-only ask, and the worker could only read the
99
+ script.
100
+ - Outside this repo: the `gpt` relay routes a brief that asks to run
101
+ something or change files to `delegate` (in place), questions and reviews
102
+ to `ask`, and honours `mode: read`.
103
+ - Evals: `bin/slow-bench` prints a random score and records it in
104
+ `.git/bench-last-score`. S4 and S6 pass only when the benchmark really
105
+ ran and the answer quotes that score; a fixed score in the script could
106
+ be read without running it.
107
+
108
+ ## [0.27.0] - 2026-10-22 | 04:58 PM | IST
109
+
110
+ Owner-authorized local-only release (#87): fixes from round A on 0.26.0
111
+ (27/28 pass, 0 leftovers, 0 doc lookups).
112
+
113
+ ### Changed
114
+
115
+ - MCP tools accept the argument names agents reach for from their other
116
+ tools:
117
+ - `prompt`, `brief`, `message` or `instructions` for `task`;
118
+ - `prompt` or `query` for `question`;
119
+ - `prompt` or `text` for `message`;
120
+ - `lane`, `id` or `worktree` for `name`;
121
+ - `name` or `lanes` for `names`.
122
+
123
+ A supervisor passed `prompt` to `delegate` and got "task is required".
124
+ - Evals: `--resummarize DIR`, and an `HxErr` column that counts harnex
125
+ usage friction apart from worker failures harnex reported properly.
126
+ - Outside this repo: the `gpt` agent's description says that `harnex lanes`
127
+ (or the `lanes` tool) shows what a running worker is doing.
128
+
129
+ ## [0.26.0] - 2026-10-22 | 04:40 PM | IST
130
+
131
+ Owner-authorized local-only release (#87): fixes from the first full 0.25.0
132
+ eval round (28/28 pass).
133
+
134
+ ### Added
135
+
136
+ - `harnex land` with no name, and the MCP `land` tool without `names`,
137
+ land every finished worktree lane the caller started in this repo,
138
+ oldest first. A supervisor called `land {}` expecting this. `discard`
139
+ still requires names.
140
+ - `harnex doctor` reports `integrations`: whether the harnex MCP server is
141
+ registered for Claude Code and Pi, whether the `gpt` agent is linked, and
142
+ a hint to run `harnex mcp install`.
143
+ - Closed lane records and their briefs are pruned after 30 days; open lanes
144
+ never are.
145
+
146
+ ### Changed
147
+
148
+ - README: `harnex mcp uninstall` before `gem uninstall`.
149
+
150
+ ## [0.25.0] - 2026-10-22 | 04:14 PM | IST
151
+
152
+ Owner-authorized local-only release (#87).
153
+
154
+ ### Fixed
155
+
156
+ - **Workers never get harnex's own MCP tools.** With harnex MCP registered
157
+ in Pi, every harnex-launched Pi worker also saw `delegate` and the other
158
+ harnex tools, and Pi 1.4.0 keeps MCP tools despite a `--tools` allowlist.
159
+ In an eval, a read-only ask worker used `delegate` to launch a writable
160
+ lane. Now:
161
+ - Pi workers start with `--exclude-tools mcp__harnex__…` (merged with the
162
+ caller's own exclusions; Pi >= 0.99);
163
+ - allowlisted (read-only) workers start with `--no-mcp` (Pi >= 1.0.4).
164
+
165
+ ### Changed
166
+
167
+ - Progress lines read `now bash 12s`, without nested parentheses.
168
+ - Lane names generated from a task skip filler words (`pi-slow-bench`, not
169
+ `pi-run-the-slow-bench`).
170
+ - Evals lift Claude print mode's 10-minute background ceiling
171
+ (`CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=0`), as interactive sessions have
172
+ none. S6 accepts `tmux capture-pane` as checking on a worker.
173
+
174
+ ## [0.24.0] - 2026-10-22 | 03:51 PM | IST
175
+
176
+ Owner-authorized local-only release (#87): fixes from the 0.23.0 agent evals.
177
+
178
+ ### Added
179
+
180
+ - **What a worker is doing now.** The live activity snapshot records the
181
+ current tool's name and the turn's tool-call count. Tool arguments are
182
+ still never retained.
183
+ - MCP progress shows it: `wc: working 2m10s · 7 tool calls · now bash (12s)`.
184
+ - So does `harnex lanes`: `working (now bash 12s)`.
185
+ - MCP names ask and delegate lanes up front so progress can follow them.
186
+ - **Hand merges are tidied.** A lane whose branch was merged by hand (into
187
+ HEAD, worktree clean, at least one commit) is marked landed, and its
188
+ worktree and branch are removed on the next `delegate`, `result` or
189
+ `lanes`.
190
+ - **Clearer next steps in the footer.**
191
+ - Model and provider failures suggest retrying on Pi's default model:
192
+ `harnex reply NAME "Continue..." --model provider/model` keeps the task
193
+ through the lane's Pi session.
194
+ - Lanes with no commits say there is nothing to merge.
195
+ - Done lanes say `land` merges and cleans up (instead of `git merge`); the
196
+ MCP instructions say the same.
197
+ - **Evals:**
198
+ - two new scenarios: S6 (check on a running worker) and S7 (recover from
199
+ a broken model);
200
+ - the exit-124 continuation no longer counts as a tool error.
201
+
202
+ ## [0.23.0] - 2026-10-22 | 03:28 PM | IST
203
+
204
+ Owner-authorized local-only release (#87).
205
+
206
+ ### Added
207
+
208
+ - `harnex mcp`: a stdio MCP server exposing `ask`, `delegate`, `result`,
209
+ `reply`, `land`, `discard` and `lanes` as native tools for Claude Code, Pi
210
+ and any MCP client. Each tool runs the CLI verb and returns its text.
211
+ - Blocking calls send `notifications/progress` every 15s; the default wait
212
+ is 25 minutes.
213
+ - Calls run concurrently.
214
+ - A cancel stops the wait, never the worker.
215
+ - `harnex mcp install|uninstall|status`: register the server for Claude Code
216
+ (`claude mcp add --scope user`) and Pi (`~/.pi/agent/mcp.json`, exposure
217
+ `direct`, 2h request timeout). It registers the RubyGems wrapper, so no
218
+ version-manager shim or client cwd is involved.
219
+ - `harnex doctor` capabilities add `mcp`.
220
+ - Lane verbs accept habits from `harnex run` instead of refusing them:
221
+ - `--id` and `--tmux [NAME]` name the lane;
222
+ - `--auto-stop` and `--wait-done` are accepted and ignored;
223
+ - `--wait-timeout` is an alias for `--timeout`;
224
+ - `--context` and `--context-file` give the task;
225
+ - `reply` takes `--id` and `--message`.
226
+ - `evals/agents/run` routes: `claude-cli` (no MCP, no `gpt` agent) and
227
+ `pi-cli` (`--no-mcp`) beside the configured `claude` and `pi`.
228
+
229
+ ## [0.22.0] - 2026-10-22 | 03:07 PM | IST
230
+
231
+ Owner-authorized local-only release (no RubyGems publication); breaking
232
+ changes allowed (#87). Plan: `koder/plans/39_agent_smoothness.md`.
233
+
234
+ ### Added
235
+
236
+ - **Lanes: a small agent-facing layer over Pi workers.**
237
+ - `harnex delegate [--worktree NAME] TASK`: one call hands a task to a
238
+ worker and prints its reply plus a lane footer: state, time, model, cost,
239
+ commits, diffstat and next commands. `--worktree NAME` creates
240
+ `.harnex/worktrees/NAME` on branch `harnex/NAME`. `--no-wait` starts
241
+ parallel lanes.
242
+ - `harnex result [NAME...]`: wait for lanes and print each result as it
243
+ lands. With no names it covers every uncollected lane the caller
244
+ started in this repo.
245
+ - `harnex reply NAME MESSAGE`: a follow-up. A busy worker takes it
246
+ mid-turn; a finished lane is relaunched on its own Pi session
247
+ (`pi --session`), so it keeps its context.
248
+ - `harnex land NAME`: merge `harnex/NAME` into the current branch, then
249
+ remove the worktree and branch. Leftovers are committed first; a
250
+ conflict leaves the merge in progress for the caller.
251
+ - `harnex discard NAME` and `harnex lanes`.
252
+ - Lane records live in `STATE_DIR/lanes/`. Blocking commands default to
253
+ `--timeout 9m`, and exit 124 names `harnex result NAME`.
254
+ - `harnex wait --since TIME` ignores events from an earlier launch of the
255
+ same id (each launch restarts the events-log seq).
256
+ - `harnex doctor` capabilities add `lanes`.
257
+ - `evals/agents/run`: agent smoothness evals. Real supervisors (Claude Code
258
+ headless, Pi print mode) run five scenarios against a fixture repo,
259
+ scored for correctness, tool calls, errors, doc lookups and leftovers.
260
+
261
+ ### Changed
262
+
263
+ - **Breaking:**
264
+ - `harnex ask` defaults to `--timeout 9m` (`none` for no cap).
265
+ - Every ask is a lane, so a timed-out ask names `harnex result ID`, and
266
+ `harnex reply ID "..."` follows up with the worker's context.
267
+ `ask --resume ID` still works and no longer needs `--repo`.
268
+ - Pi starts with `--no-approve` unless the caller passes `--approve`.
269
+ - Top-level `harnex --help` leads with the agent verbs;
270
+ `harnex agents-guide claude` is rewritten around them.
271
+ - Help examples use Pi session ids (`pi-i-42`) instead of Codex-era ones.
272
+
273
+ ### Fixed
274
+
275
+ - Harnex state in a repo no longer shows up as untracked work: writing a
276
+ dispatch row under `.harnex/` adds `.harnex/` to the clone's
277
+ `info/exclude`. This also unblocks `git worktree remove` for lane
278
+ worktrees.
279
+
280
+ ## [0.21.0] - 2026-10-22 | 12:40 PM | IST
281
+
282
+ Owner-authorized local-only release (no RubyGems publication). Makes Pi/GPT
283
+ workers usable as a Claude Code subagent type (#86 slice 1): the `gpt` agent
284
+ (kept in `~/Projects/pi/.claude/agents/gpt.md`) relays briefs through
285
+ `harnex ask` and needs `ask --resume` to outlast the 10-minute Bash cap.
286
+
287
+ ### Added
288
+
289
+ - `harnex ask --resume ID --repo ROOT [--timeout DUR]` (#86): keep waiting on
290
+ an ask that timed out and print its answer like the original ask (same
291
+ exit codes, the full answer even when truncated in the result). A timed-out
292
+ ask now names this command on stderr instead of a raw `harnex wait`, so a
293
+ Claude Code subagent loops on one command shape under the 10-minute Bash
294
+ cap. `--json` output still carries the run's own `resume` field.
295
+ - `harnex doctor` capabilities add `ask_resume`.
296
+
297
+ ## [0.20.0] - 2026-10-20 | 09:55 PM | +04
298
+
299
+ Owner-authorized local-only release (no RubyGems publication). Harnex is now
300
+ Pi + GPT only: Codex support is removed (owner decision 2026-10-20: "we are
301
+ going to be exclusively pi & gpt models").
302
+
303
+ ### Removed
304
+
305
+ - The `codex` (PTY) and `codex app-server` (JSON-RPC) adapters, the
306
+ `stdio_jsonrpc` session transport, the app-server client, and their
307
+ fixtures and tests. `harnex run codex` is no longer special-cased (it would
308
+ wrap a `codex` binary as a generic PTY CLI).
309
+ - `harnex run --fast` and `--legacy-pty`; Codex service-tier forcing;
310
+ `harnex preflight --legacy-pty`; `docs/codex-appserver.md`.
311
+ - `harnex doctor` Codex checks: it now checks Pi by default and only Pi
312
+ (`--adapter pi|all`).
313
+ - Issues #40, #42 and #43 (Codex recovery/fallback/throughput work) closed.
314
+
315
+ ### Changed
316
+
317
+ - Shared session behavior previously tested through Codex (receipts and
318
+ claims, completion-notification ordering, boot-failure classification,
319
+ stop sequencing, auto-stop, status fields, usage pricing, `preflight`
320
+ end to end) is now tested through Pi or adapter-neutral fakes.
321
+ - Dispatch-row schema fields are unchanged; `agent.service_tier`,
322
+ `actual.rate_limits` and Codex error details stay `null` for new rows.
323
+ - `harnex doctor` capabilities add `ask`, `final_message` and `owner_tag`.
324
+ - Docs, guides, recipes and repo instructions are Pi-only; session ids use
325
+ `pi-<role>-<tag>`.
326
+
327
+ ## [0.19.0] - 2026-10-20 | 06:35 PM | +04
328
+
329
+ Owner-authorized local-only release (no RubyGems publication). Makes Pi
330
+ (GPT-backed) workers usable as native tools from Claude Code sessions and
331
+ subagents (#85), driven by live Claude-subagent stress runs.
332
+
333
+ ### Added
334
+
335
+ - `harnex ask "QUESTION"`: one blocking call that hands a question to a Pi
336
+ worker (read-only tools by default; `--write` to allow edits) and prints its
337
+ answer. `--model`, `--fallback-model` (one more try on provider capacity),
338
+ `--effort`, `--file/--section`, `--timeout`, `--json`; stderr names the
339
+ lane, time and model. A read-only ask records in the global stream, so the
340
+ repository stays untouched.
341
+ - Turn results carry the worker's reply: `final_message` (at most 4,000
342
+ characters), `final_message_path` (full text), `final_message_truncated`,
343
+ plus the lane's `end_sha`, `commits` (since launch), `turn_commits` and
344
+ `model`, in events, `wait`, `send --wait-done` and owner-stream lines.
345
+ - `harnex run --wait-done [--wait-timeout DUR]`: launch and block until the
346
+ first turn's result in one call; on 124 the output names the `resume`
347
+ command.
348
+ - `--owner-tag TAG` on `run` and `watch --owner`: a subagent's own owner
349
+ (`<session>/<TAG>`), so its stream holds only its lanes and no backlog.
350
+ - `watch --owner --match GLOB` filters lanes by id; `--until-idle` blocks
351
+ until no matching lane is running and prints every result on the way.
352
+ - `send --stall-after DUR` (with `--wait-done`); `send --wait-done` timeouts
353
+ print `resume`.
354
+ - Status and stall lines name Pi's running shell commands
355
+ (`running_commands`; "stalled … while running `sleep 150`").
356
+ - `harnex agents-guide claude`: the operating guide for Claude Code.
357
+
358
+ ### Changed
359
+
360
+ - `watch --owner --once` prints every event ready in its pass, not only the
361
+ first.
362
+ - The owner stream delivers each turn's result once and in settle order, even
363
+ when several turns end between polls (owner records keep a bounded
364
+ per-turn history). Previously a turn replaced by the next before a poll was
365
+ lost.
366
+ - `harnex send` to an exited session fails fast (exit 1, `status: "exited"`)
367
+ instead of spending its whole timeout on lookup.
368
+ - `send --wait-done` output: `status` is the turn's verdict and
369
+ `delivery_status` the delivery's.
370
+ - `wait --until done` on a session already gone reports `process_state:
371
+ "exited"` and names a caller's stop `stopped_by_caller`.
372
+ - Stall lines carry `turn` and `elapsed_s`; durations under 10 minutes print
373
+ as `3m05s`.
374
+ - Durations accept compound forms (`8m30s`, `1h30m`); `--context-section`
375
+ accepts a heading with its marks (`"## Task"`).
376
+ - A follow-up whose run settled while the send was in flight is sent as a
377
+ plain prompt, and follow-ups are counted for the turn they joined.
378
+ - `resume` hints name the checkout's `bin/harnex` when running from source.
379
+
380
+ ## [0.18.0] - 2026-10-20 | 04:41 PM | +04
381
+
382
+ Owner-authorized local-only release (no RubyGems publication). Closes the
383
+ subagent-orchestration gaps found by Holm Queues 159/160 (#79-#84).
384
+
385
+ ### Added
386
+
387
+ - `harnex run --context-file PATH [--context-section TEXT]` sends a brief from
388
+ disk, or only the part after a heading (to the next heading of its level)
389
+ or a plain marker line (to end of file), and refuses an empty result.
390
+ `--meta-file PATH` reads `--meta` JSON from a file (inline `--meta` keys
391
+ win). The brief path and SHA-256 of the sent text land in
392
+ `meta.context_file` / `meta.context_sha256` (#83).
393
+ - `harnex watch --owner --once [--timeout DUR] [--cursor NAME]`: print the
394
+ first undelivered result or stall, advance the cursor, exit 0 (124 on
395
+ timeout). One blocking call covers every lane an owner launched; named
396
+ cursors keep a parent and its subagent apart (#84).
397
+ - Per-turn completion (#81): `harnex send` reports `after_seq`;
398
+ `harnex wait --until done --after-seq N` waits for the turn after that point;
399
+ `harnex send --wait-done` does both in one call. `task_complete` /
400
+ `task_failed` events carry `turn`, and the owner stream reports every turn's
401
+ result (a nudged turn included) instead of one per session.
402
+ - `provider_capacity` outcome class: a Pi turn that fails after Pi's own
403
+ provider retries ran out (`auto_retry_end success:false`). In status JSON,
404
+ dispatch rows, the owner stream and `orchestration report`; fatal by default
405
+ for `--failure-budget`, as `task_failed` was (#82).
406
+ - Turn results carry `follow_ups: {sent, pending}` when follow-ups joined the
407
+ turn (from Pi's `queue_update` counts; `pending: 0` means each reached the
408
+ model), and owner events add `settled_at`. A later turn's `elapsed_s` runs
409
+ from that turn's start. `harnex run --tmux` prints `tmux_target`.
410
+
411
+ ### Changed
412
+
413
+ - A send to a busy Pi session is handed to Pi at once as a follow-up
414
+ (`delivery: "follow_up"`), delivered when the current turn ends, instead of
415
+ waiting in the 120 s inbox and expiring unread. Other adapters: an expired
416
+ message makes `send` exit 1 with `status: "expired"`, and a send that times
417
+ out withdraws its queued message before exiting 124 (#79).
418
+ - Worktree lanes (`--cwd` in a different Git toplevel than `--root`) are
419
+ observed in the lane: `commit_sha`, branch, receipt, activity and acceptance
420
+ describe the lane; the end row adds `root_commit_sha` (#80).
421
+ - `run --tmux --context-file` hands the brief to the inner runner by path,
422
+ so long briefs no longer hit tmux's command-length limit.
423
+
424
+ ## [0.17.0] - 2026-10-18 | 01:13 PM | +04
425
+
426
+ Owner-authorized local-only release (no RubyGems publication).
427
+
428
+ ### Added
429
+
430
+ - `harnex watch --owner [ID]`: one owner-scoped stream of compact JSON lines
431
+ (`harnex.owner_event.v1`, with a readable `msg`) for every dispatch an owner
432
+ started: `started`, `done`, `rejected`, `failed`, `stalled` (with
433
+ `--stall-after`), `stopped`, `timeout`. No heartbeats; runs until killed or
434
+ `--max-wait`. A per-owner cursor delivers each result once across restarts.
435
+ Built for Claude Code's `Monitor` (#77).
436
+ - `harnex run` from a Claude Code Bash shell records `CLAUDE_CODE_SESSION_ID`
437
+ as the dispatch owner, as Pi does with `PI_SESSION_ID` (Pi's wins if both
438
+ are set; explicit `--orchestration-session-id` wins over both). The tmux
439
+ hand-off marks the owner resolved, so a tmux server's stale environment
440
+ cannot re-attribute a dispatch.
441
+ - Documented the stable `harnex status --json` fields for status-line and
442
+ panel consumers.
443
+
444
+ ## [0.16.1] - 2026-10-18 | 12:41 PM | +04
445
+
446
+ Owner-authorized local-only release (no RubyGems publication).
447
+
448
+ ### Added
449
+
450
+ - `harnex watch --stall-after DUR` (and `wait --until done --stall-after DUR`)
451
+ exits 4 (`wait_result: stalled`) once the live session shows no progress for
452
+ DUR, leaving the worker running. Pi and other structured adapters use the
453
+ most recent turn-start/model/tool event during an active turn
454
+ (`clock: activity`); PTY adapters fall back to transcript idle
455
+ (`clock: output_log`). Stalls write no marker and skip
456
+ `--stop-on-terminal`. The predicate (`Harnex::Stall`) is shared for #77
457
+ (#76).
458
+
459
+ ## [0.16.0] - 2026-10-18 | 12:55 AM | +04
460
+
461
+ Owner-authorized local-only release. Owner decision (2026-10-18): Harnex is
462
+ installed locally and is not published to RubyGems.
463
+
464
+ ### Added
465
+
466
+ - Final gates: `harnex run --final-gate '<cmd>'` (repeatable; or meta
467
+ `final_gates`) declares final acceptance commands. Receipts gain
468
+ `validation.commands_had_failures` (whole-history, harness-observed) and
469
+ `validation.final_gates` (`declared`, `observed_pass`, `observed_fail`,
470
+ `missing`, `status: pass|fail|unknown|undeclared`, per-gate last exit).
471
+ With gates declared, `validation.status` reports them, so an exploratory or
472
+ intermediate failure no longer marks a green final run as `fail`. Matching
473
+ is exact, after unwrapping a single `bash -lc`/`sh -c` transport wrapper.
474
+ Without gates, behavior is unchanged. Diagnostics only: acceptance and
475
+ outcome classes do not change (#68).
476
+ - Dispatch-row `outcome.class` gains process classes from signals Harnex
477
+ already holds: `boot_failure`, `permission_prompt`, `timeout`,
478
+ `stopped_by_caller`, `process_failed`. They refine an `unknown`/`task_failed`
479
+ terminal or the receipt rejection of a process that never signalled
480
+ completion; completion and proof verdicts are never overridden, and the
481
+ vocabulary is closed with an `unknown` fallback.
482
+ - `harnex orchestration report` counts worker outcome classes per raw attempt
483
+ and per retry family (joined by parent attempt/dispatch id), accepts
484
+ `--queue-id` as well as `--run-id`, and takes an optional
485
+ `--failure-budget N [--budget-unit attempts|families] [--fatal-classes A,B]`
486
+ that adds a `failure_budget` verdict and exits 3 on breach (#57).
487
+ - `harnex preflight ADAPTER [--cwd DIR] [--commit-check]` runs one tiny real
488
+ dispatch through `harnex run` and prints a JSON verdict
489
+ (`harnex.preflight.v1`): registration, boot, permission prompt, task read
490
+ from the task root (default `/tmp`), workspace write, harness-observed
491
+ command exit (via a final gate), receipt, worker claims, completion, and
492
+ stop, plus a scratch-repo commit with `--commit-check`. Each failure is a
493
+ distinct check and failure class; a turn that fails before any work reports
494
+ its (redacted) error as the root cause. Usage, cost and context telemetry
495
+ provenance is reported per adapter. Exits non-zero on any failed check. Its
496
+ dispatch row carries `phase=preflight` (exempt from repo phase allowlists)
497
+ and `orchestration report` excludes such rows unless `--include-preflight`.
498
+ Workers are stopped through the session API and carry a `--max-runtime`
499
+ backstop, so a killed or timed-out preflight cannot orphan them (#56).
500
+ - `harnex doctor` capabilities add `final_gates: 1`, `outcome_classes: 1` and
501
+ `preflight: 1`.
502
+
503
+ ### Changed
504
+
505
+ - `harnex status` (default current-repo view) now says how many sessions are
506
+ active in other repos, with up to three ids, instead of a bare
507
+ "No active harnex sessions" that read as global emptiness when workers run
508
+ in sibling worktrees. `--repo`, `--all` and `--json` output is unchanged
509
+ (#26).
510
+ - A bare `harnex wait` (process-exit fence) prints a stderr `note:` when the
511
+ session was not started with `--auto-stop`, and again if its turn settles
512
+ while the wait is blocked, pointing at `--until done`. Events from an
513
+ earlier run of the same id are ignored. Status JSON gains `auto_stop` (#49).
514
+ - Events JSONL `ts` now has millisecond precision (`iso8601(3)`), so teardown
515
+ races can be measured from the events log (#36/#37 follow-up). Readers that
516
+ parse ISO-8601 are unaffected; older rows keep whole seconds.
517
+
518
+ ### Fixed
519
+
520
+ - Two status tests that sat below a `private` keyword never ran; they run now.
521
+ - Test-suite flakes: cross-repo status hint tests no longer see registries
522
+ leaked by other suites, and the detached on-done smoke waits for teardown.
523
+
524
+ ## [0.15.0] - 2026-10-16 | 07:20 AM | +04
525
+
526
+ Owner-authorized local-only release; public publication, tag and push remain deferred.
527
+
528
+ ### Added
529
+
530
+ - Pi RPC receipts now attest built-in `bash` commands: bounded command text,
531
+ integer exit from `result.structuredContent.exit_code`, status and duration,
532
+ correlated by `toolCallId`. Output is never persisted. Pi bash calls count in
533
+ `commands_executed`; other tools stay `tool_calls` (#70).
534
+ - Receipts gain `command_observation: "partial"` and
535
+ `observed.commands_unobserved`: Pi command calls without structured exit
536
+ evidence (abort, timeout, extension override, older Pi, in flight at
537
+ teardown) are counted rather than inferred, and `validation.status` reads
538
+ `unknown` instead of `pass` while any exist. Live verified on Pi 1.2.0/1.3.0.
539
+ - `harnex doctor` advertises `capabilities.pi_command_proof: 1`; consumers
540
+ should check it before treating Pi receipt commands as proof.
541
+
542
+ ### Fixed
543
+
544
+ - `wait`/`watch` observers no longer exit 1 when a sibling session's registry
545
+ file is removed between the session scan's glob and read (stop/cleanup
546
+ race); `doctor`'s registry sweep is guarded the same way (#75).
547
+
548
+ ## [0.14.1] - 2026-10-05 | 09:55 PM | +04
549
+
550
+ Owner-authorized local-only release; public publication, tag and push remain deferred.
551
+
552
+ ### Fixed
553
+
554
+ - New dispatch records and reconciliation repair appends store paths under the
555
+ user's home as `~`/`~/...`, without mutating runtime records or rewriting
556
+ existing rows. Nested data and home-prefix boundaries are preserved (#74).
557
+ - Canonical reconciliation accepts equivalent absolute and home-relative paths
558
+ while retaining genuine payload conflicts. Status results keep their absolute
559
+ repository roots, and retention still protects portable live-record paths.
560
+
561
+ ## [0.14.0] - 2026-09-28 | 08:25 PM | +04
562
+
563
+ Owner-authorized local-only release; public publication, tag and push remain deferred.
564
+
565
+ ### Fixed
566
+
567
+ - Explicit idle Pi shutdown preserves the latest settled accepted/no-change
568
+ proof, including follow-up turns. Busy/newly dispatched work cannot reuse an
569
+ older receipt; unexpected transport loss and malformed output still fail.
570
+ Raw child exits remain observable separately from logical cleanup status (#69).
571
+ - `wait`/`watch` observer deadlines now include slow registry, event, HTTP and
572
+ exit-grace probes. A private observer process enforces the monotonic cap without
573
+ stopping the worker; late results cannot override timeout (#71).
574
+
575
+ ### Added
576
+
577
+ - Opt-in `wait/watch --heartbeat DUR` streams flushed diagnostics on stderr while
578
+ preserving one final JSON stdout result. `wait --max-wait` aliases `--timeout`.
579
+ - Structured work/model/tool activity clocks distinguish real events from UI/log
580
+ freshness, with unknown PTY clocks and no retained thinking-stream content.
581
+ - Bounded stop reason/origin survives events, status, receipts and dispatch-end
582
+ telemetry. Expected cancellation is distinct from provider disconnection.
583
+ - `run --max-runtime DUR` enforces a fixed runner-owned worker budget independent
584
+ of supervisors, prompts, retries or UI chatter. Active expiry fails work; idle
585
+ cleanup preserves accepted proof. Doctor exposes versioned capabilities (#71).
586
+
587
+ ## [0.13.0] - 2026-09-23 | 01:56 AM | +04
588
+
589
+ Local-only activation approved by the owner. Public RubyGems publication, Git
590
+ tag, and push are deferred; later publication must use the exact verified gem
591
+ built from this commit rather than rebuilding version 0.13.0.
592
+
593
+ ### Added
594
+
595
+ - Dispatch telemetry now has an opt-in local archive bridge. A stable sidecar
596
+ lock encloses archive preparation and append, preventing atomic rotation from
597
+ stranding writers on an old inode. A separate complete-history reader feeds
598
+ history, canonical reconciliation, latest-row lookup, status, and attempt
599
+ accounting. Helper failures never drop a new dispatch row, while unavailable
600
+ or malformed complete history fails explicitly instead of appearing empty.
601
+ - `harnex telemetry archive-capability --json` exposes the local helper protocol
602
+ version and exact archiver/history environment names so automation can refuse
603
+ to trim active dispatch history against an older installed Harnex.
604
+
605
+ ## [0.12.1] - 2026-09-19 | 12:30 PM | +04
606
+
607
+ ### Fixed
608
+
609
+ - Pi-launched dispatches now capture the invoking primary's `PI_SESSION_ID`
610
+ before crossing detached/tmux process boundaries and publish a durable,
611
+ owner-addressed, per-attempt completion record. Reusing a dispatch name no
612
+ longer erases an unacknowledged attempt, and nested workers never implicitly
613
+ nominate themselves as completion consumers.
614
+ - Addressed delivery registration fails before the initial structured prompt
615
+ when it cannot be persisted. A terminal delivery-write failure leaves the
616
+ registered running record available for native `harnex watch` recovery.
617
+ Existing typed markers and optional `--on-done` hooks remain compatible.
618
+
3
619
  ## [0.12.0] - 2026-09-03 | 10:09 AM | IST
4
620
 
5
621
  ### Added