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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +616 -0
- data/GUIDE.md +222 -68
- data/README.md +78 -48
- data/TECHNICAL.md +235 -98
- data/agents/gpt.md +60 -0
- data/docs/agents.md +119 -0
- data/docs/configuration.md +4 -0
- data/docs/dispatch-telemetry.md +184 -50
- data/docs/events.md +20 -7
- data/docs/lanes.md +206 -0
- data/docs/mcp.md +102 -0
- data/docs/pi-rpc.md +81 -7
- data/docs/upgrading-to-0.29.md +87 -0
- data/guides/01_dispatch.md +103 -35
- data/guides/04_monitoring.md +223 -25
- data/guides/05_naming.md +0 -1
- data/guides/06_claude.md +96 -0
- data/lib/harnex/adapters/base.rb +4 -8
- data/lib/harnex/adapters/pi.rb +92 -12
- data/lib/harnex/adapters.rb +1 -16
- data/lib/harnex/artifact_report.rb +206 -12
- data/lib/harnex/cli.rb +68 -50
- data/lib/harnex/commands/ask.rb +285 -0
- data/lib/harnex/commands/delegate.rb +208 -0
- data/lib/harnex/commands/doctor.rb +34 -36
- data/lib/harnex/commands/events.rb +3 -3
- data/lib/harnex/commands/history.rb +2 -8
- data/lib/harnex/commands/land.rb +150 -0
- data/lib/harnex/commands/lanes.rb +84 -0
- data/lib/harnex/commands/logs.rb +3 -3
- data/lib/harnex/commands/mcp.rb +208 -0
- data/lib/harnex/commands/orchestration.rb +88 -9
- data/lib/harnex/commands/pane.rb +3 -3
- data/lib/harnex/commands/preflight.rb +566 -0
- data/lib/harnex/commands/reply.rb +125 -0
- data/lib/harnex/commands/result.rb +108 -0
- data/lib/harnex/commands/run.rb +249 -64
- data/lib/harnex/commands/send.rb +121 -16
- data/lib/harnex/commands/status.rb +32 -4
- data/lib/harnex/commands/stop.rb +14 -4
- data/lib/harnex/commands/telemetry.rb +19 -1
- data/lib/harnex/commands/wait.rb +421 -56
- data/lib/harnex/commands/watch.rb +134 -21
- data/lib/harnex/context_file.rb +85 -0
- data/lib/harnex/core.rb +100 -15
- data/lib/harnex/dispatch_history.rb +157 -10
- data/lib/harnex/lanes.rb +548 -0
- data/lib/harnex/mcp.rb +362 -0
- data/lib/harnex/orchestration.rb +128 -5
- data/lib/harnex/owned_process_group.rb +50 -0
- data/lib/harnex/owner_stream.rb +399 -0
- data/lib/harnex/pricing.rb +4 -9
- data/lib/harnex/runtime/activity_tracker.rb +107 -0
- data/lib/harnex/runtime/api_server.rb +11 -1
- data/lib/harnex/runtime/completion_notifier.rb +90 -11
- data/lib/harnex/runtime/inbox.rb +26 -7
- data/lib/harnex/runtime/message.rb +5 -2
- data/lib/harnex/runtime/runtime_budget.rb +96 -0
- data/lib/harnex/runtime/session.rb +684 -294
- data/lib/harnex/runtime/stop_request.rb +39 -0
- data/lib/harnex/stall.rb +46 -0
- data/lib/harnex/telemetry_reconciler.rb +42 -20
- data/lib/harnex/terminal_status.rb +5 -5
- data/lib/harnex/version.rb +2 -2
- data/lib/harnex.rb +16 -0
- data/recipes/01_fire_and_watch.md +14 -14
- data/recipes/02_chain_implement.md +35 -31
- data/recipes/03_buddy.md +1 -1
- metadata +34 -12
- data/docs/codex-appserver.md +0 -175
- data/lib/harnex/adapters/codex.rb +0 -160
- data/lib/harnex/adapters/codex_appserver.rb +0 -407
- 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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e36a59564be22ba55cda2815e3e72b59b887bb2a4e0417be776295ef1cb10b82
|
|
4
|
+
data.tar.gz: 0a9b1355a5bc153e4d6fdd6ef79df81f022c5b6a75f97de0a8f91ef52353e526
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|