harnex 0.11.0 → 0.29.0

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