harnex 0.10.2 → 0.12.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +63 -0
- data/README.md +22 -7
- data/TECHNICAL.md +25 -0
- data/docs/pi-rpc.md +151 -0
- data/guides/01_dispatch.md +26 -2
- data/guides/04_monitoring.md +32 -8
- data/lib/harnex/adapters/pi.rb +220 -21
- data/lib/harnex/commands/doctor.rb +57 -9
- data/lib/harnex/commands/run.rb +34 -6
- data/lib/harnex/commands/status.rb +16 -2
- data/lib/harnex/core.rb +15 -0
- data/lib/harnex/runtime/completion_notifier.rb +137 -0
- data/lib/harnex/runtime/session.rb +232 -21
- data/lib/harnex/version.rb +2 -2
- data/lib/harnex.rb +1 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3ea3eab047cc2e9f086fba4cfb98c6f585ffe888fdee0fb018c35515fe6257b4
|
|
4
|
+
data.tar.gz: ba40b96028fd01e6ade7517374e7d26d92a5d147a7be2ec08a581cd0203dae62
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e1e85c57df13dd411b10308659b72376f9491f1c6e4d7c4e5d906f9f78096dc0f82a0ac866c01e356d75cedb5f285b71970d0ea175e5935ca8ed0e3bcf40dd88
|
|
7
|
+
data.tar.gz: 1283d788ceaff2e608f7e13b7f4f640d65d9f683e35cbe649cc9dd7d0223e094740df146fbe10ed6fa15685bf27671e9059c6378bb2bc8acc5c850aef5f6c9ab
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,68 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.12.0] - 2026-09-03 | 10:09 AM | IST
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Registered sessions now atomically publish a typed completion marker under
|
|
8
|
+
`$HARNEX_STATE_DIR/done/` at the first accepted, rejected, failed, or error
|
|
9
|
+
work result, without requiring a `wait` or `watch` client.
|
|
10
|
+
- `harnex run --on-done CMD` launches one non-blocking trusted local shell hook
|
|
11
|
+
with typed completion, receipt, commit, and elapsed-time environment values.
|
|
12
|
+
The option works in foreground, detached, and tmux launches.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- `harnex status` now renders settled live work (`done`, `rejected`, or
|
|
17
|
+
`failed`) ahead of an adapter's prompt/busy state. Existing JSON fields and
|
|
18
|
+
the v2 dispatch envelope remain unchanged.
|
|
19
|
+
|
|
20
|
+
## [0.11.0] - 2026-08-14 | 01:03 PM | IST
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- Pi RPC completion now fences on Pi 0.80.4+'s `agent_settled` event instead of
|
|
25
|
+
the lower-level `agent_end`. Provider retries, compaction recovery, and queued
|
|
26
|
+
continuations can no longer publish premature `task_complete` or open the
|
|
27
|
+
inbox early. Final `error`, `aborted`, and `length` stop reasons fail closed;
|
|
28
|
+
a settled run without an authoritative final assistant reason also fails.
|
|
29
|
+
- Pi 0.84's breaking delta-only `message_update` shape is correlated from
|
|
30
|
+
`message_start` through authoritative `message_end`, preserving streamed
|
|
31
|
+
output without duplicating the final message.
|
|
32
|
+
- Harnex `--model` and `--effort` now become supported Pi `--model` /
|
|
33
|
+
`--thinking` startup controls and are verified through RPC `get_state`,
|
|
34
|
+
instead of adding ignored fields to `prompt` or persisting RPC setters into
|
|
35
|
+
the user's Pi defaults. Model mismatches and clamped effort requests fail
|
|
36
|
+
before prompting, telemetry distinguishes requested from observed effective
|
|
37
|
+
model values, and forced busy sends use Pi's `steer` streaming behavior.
|
|
38
|
+
- Pi RPC request waits are bounded, subprocess stderr is continuously drained
|
|
39
|
+
into a bounded diagnostic tail, and process status is read from Open3's wait
|
|
40
|
+
thread instead of racing it with a second `waitpid` and potentially losing a
|
|
41
|
+
nonzero exit status.
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- **Compatibility:** structured Pi dispatch now requires Pi >= 0.80.4. Both
|
|
46
|
+
foreground and detached/tmux launches validate the installed version before
|
|
47
|
+
spawn. This is the first Pi release with the final `agent_settled` fence.
|
|
48
|
+
- Pi retry/compaction events retain settlement state and expose current
|
|
49
|
+
summarization-retry lifecycle events in Harnex's event stream.
|
|
50
|
+
- Codex schema fixtures are refreshed against CLI 0.147.0 after a bounded
|
|
51
|
+
semantic review. The drift is limited to a string path-alias replacement and
|
|
52
|
+
additive optional thread/item fields that Harnex does not consume; existing
|
|
53
|
+
minimal response fixtures still validate, so no Codex adapter behavior
|
|
54
|
+
changes.
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
|
|
58
|
+
- `harnex doctor --adapter pi` statically verifies the Pi RPC version;
|
|
59
|
+
`--adapter all` checks both Pi and Codex while the no-argument default remains
|
|
60
|
+
Codex-compatible.
|
|
61
|
+
- `docs/pi-rpc.md` documents transport semantics, project trust, lifecycle,
|
|
62
|
+
model controls, telemetry, and known boundaries. An opt-in live contract test
|
|
63
|
+
(`PI_INTEGRATION=1`) verifies the installed Pi event shape without adding
|
|
64
|
+
provider cost to the normal suite.
|
|
65
|
+
|
|
3
66
|
## [0.10.2] - 2026-08-08 | 06:49 PM | IST
|
|
4
67
|
|
|
5
68
|
Docs-only patch: no library or CLI behavior changes. Released so the
|
data/README.md
CHANGED
|
@@ -12,8 +12,8 @@ gem install harnex
|
|
|
12
12
|
|
|
13
13
|
Harnex itself requires **Ruby 3.x** and uses only the Ruby standard
|
|
14
14
|
library. Install the CLIs you want to wrap separately; Codex JSON-RPC
|
|
15
|
-
support requires Codex CLI **0.128.0 or newer**,
|
|
16
|
-
workflows require `tmux`.
|
|
15
|
+
support requires Codex CLI **0.128.0 or newer**, Pi structured RPC requires
|
|
16
|
+
Pi **0.80.4 or newer**, and tmux-backed workflows require `tmux`.
|
|
17
17
|
|
|
18
18
|
Then ask the CLI what to do next:
|
|
19
19
|
|
|
@@ -23,8 +23,15 @@ harnex --help
|
|
|
23
23
|
harnex agents-guide
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
Run the matching static check after installing or upgrading an agent CLI:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
harnex doctor --adapter codex
|
|
30
|
+
harnex doctor --adapter pi
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
These verify the local structured-transport version prerequisites without
|
|
34
|
+
starting a model turn.
|
|
28
35
|
|
|
29
36
|
`harnex agents-guide` is the agent-facing reference for dispatch, chain,
|
|
30
37
|
buddy, monitoring, and naming patterns. It is packaged in the gem; no skills
|
|
@@ -106,7 +113,7 @@ an explicit working-directory/root selector for automation.
|
|
|
106
113
|
|-------|---------|
|
|
107
114
|
| Claude Code | PTY adapter with prompt detection, stop sequence, workspace trust, and vim mode handling |
|
|
108
115
|
| OpenAI Codex | JSON-RPC `codex app-server` adapter by default; PTY mode remains supported for TUI/interactive use via `--legacy-pty` |
|
|
109
|
-
| Pi | JSONL RPC adapter (`pi --mode rpc
|
|
116
|
+
| Pi | JSONL RPC adapter (`pi --mode rpc`, Pi >= 0.80.4) with settled completion, typed failures, tool/retry events, extension-UI auto-cancel, and session stats telemetry |
|
|
110
117
|
| OpenCode | PTY adapter with native Ctrl+C stop handling and OpenCode-specific prompt/readiness heuristics |
|
|
111
118
|
| Any terminal CLI | Generic PTY wrapping with local API, logs, status, and best-effort prompt detection |
|
|
112
119
|
|
|
@@ -121,9 +128,15 @@ terminal UI or PTY-only Codex flags. The flag name is historical; the PTY path
|
|
|
121
128
|
is still supported.
|
|
122
129
|
|
|
123
130
|
`harnex run pi` launches `pi --mode rpc` and sends `--context` as a structured
|
|
124
|
-
`prompt` command (not a CLI positional argument).
|
|
125
|
-
|
|
131
|
+
`prompt` command (not a CLI positional argument). Harnex `--model` / `--effort`
|
|
132
|
+
flags become Pi `--model` / `--thinking` startup controls and are verified over
|
|
133
|
+
RPC before the prompt; use a deterministic `provider/model` value. Pass other
|
|
134
|
+
Pi startup flags after the separator, for example:
|
|
126
135
|
`harnex run pi --context "Implement X" -- --model anthropic/claude-sonnet-4-5 --thinking high`.
|
|
136
|
+
For unattended runs, explicitly choose Pi project trust with child
|
|
137
|
+
`--approve` or `--no-approve`; Harnex never auto-trusts repository code.
|
|
138
|
+
See [docs/pi-rpc.md](docs/pi-rpc.md) for lifecycle, compatibility, and failure
|
|
139
|
+
semantics.
|
|
127
140
|
|
|
128
141
|
## Multi-agent workflows
|
|
129
142
|
|
|
@@ -231,6 +244,8 @@ Choose the wait/watch predicate that matches how you launched the worker:
|
|
|
231
244
|
`harnex wait --id ID --until task_complete --timeout SECS` when you need the
|
|
232
245
|
exact successful-turn event instead of terminal-exit fallback. Use
|
|
233
246
|
`--until task_failed` to wait specifically for a failed structured turn.
|
|
247
|
+
Pi completion is fenced on `agent_settled`, not the earlier `agent_end`, so
|
|
248
|
+
retries, compaction recovery, and queued continuations finish first.
|
|
234
249
|
- `harnex send --wait-for-idle` is an atomic send fence for PTY-style
|
|
235
250
|
interactions. It proves the turn returned to an idle/prompt state, not that
|
|
236
251
|
your acceptance criteria passed.
|
data/TECHNICAL.md
CHANGED
|
@@ -363,6 +363,8 @@ Each adapter in `lib/harnex/adapters/` implements:
|
|
|
363
363
|
| `inject_exit(writer)` | Send adapter-specific stop text |
|
|
364
364
|
| `infer_repo_path(argv)` | Extract repo path from CLI args |
|
|
365
365
|
| `wait_for_sendable(...)` | Wait strategy before sending |
|
|
366
|
+
| `transport` | PTY, JSON-RPC, or JSONL RPC |
|
|
367
|
+
| `validate_runtime!` | Optional version/capability gate |
|
|
366
368
|
|
|
367
369
|
### Input States
|
|
368
370
|
|
|
@@ -404,6 +406,29 @@ The adapter reads the screen and returns a state hash:
|
|
|
404
406
|
- See `docs/codex-appserver.md` for the full mapping table and
|
|
405
407
|
troubleshooting.
|
|
406
408
|
|
|
409
|
+
### Pi Adapter (JSONL RPC)
|
|
410
|
+
|
|
411
|
+
- `transport :stdio_jsonl_rpc` launches `pi --mode rpc` and speaks Pi's
|
|
412
|
+
strict LF-delimited JSONL protocol. It is not JSON-RPC 2.0.
|
|
413
|
+
- Requires Pi >= 0.80.4 and fails before spawn when the installed version
|
|
414
|
+
cannot provide the final `agent_settled` fence. Verify with
|
|
415
|
+
`harnex doctor --adapter pi`.
|
|
416
|
+
- `agent_end` remains busy because retry, compaction recovery, or a queued
|
|
417
|
+
continuation may follow. `agent_settled` inspects the authoritative final
|
|
418
|
+
assistant `stopReason`: `stop` completes; `error`, `aborted`, `length`, a
|
|
419
|
+
missing reason, or an unknown reason fails closed.
|
|
420
|
+
- Pi >= 0.84 emits delta-only `message_update` events. Harnex correlates those
|
|
421
|
+
deltas with `message_start` / `message_end` and does not depend on the removed
|
|
422
|
+
cumulative message snapshot.
|
|
423
|
+
- Harnex `--model` and `--effort` become Pi `--model` / `--thinking`
|
|
424
|
+
startup flags and are verified with `get_state`; a model mismatch or clamped
|
|
425
|
+
effort is rejected before prompting without persisting an RPC model switch
|
|
426
|
+
into Pi's user defaults. Forced busy sends use `streamingBehavior=steer`.
|
|
427
|
+
- RPC requests have a 30-second response bound. Stderr is continuously drained
|
|
428
|
+
into a bounded diagnostic tail, and subprocess status comes from Open3's wait
|
|
429
|
+
thread instead of racing it with another `waitpid`.
|
|
430
|
+
- See `docs/pi-rpc.md` for trust policy, telemetry, and compatibility details.
|
|
431
|
+
|
|
407
432
|
#### Codex Adapter (legacy PTY — `--legacy-pty`, long-term fallback)
|
|
408
433
|
|
|
409
434
|
- Launches with `--no-alt-screen` for inline screen output
|
data/docs/pi-rpc.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Pi RPC adapter
|
|
2
|
+
|
|
3
|
+
Harnex runs Pi workers over Pi's structured subprocess protocol rather than
|
|
4
|
+
scraping the TUI:
|
|
5
|
+
|
|
6
|
+
```text
|
|
7
|
+
harnex run pi -> pi --mode rpc -> LF-delimited JSON objects on stdio
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Pi RPC is JSONL, not JSON-RPC 2.0. Codex uses `codex app-server` JSON-RPC;
|
|
11
|
+
Harnex presents the same run/send/wait/events control surface over both.
|
|
12
|
+
|
|
13
|
+
## Compatibility
|
|
14
|
+
|
|
15
|
+
Harnex requires Pi **0.80.4 or newer** for structured dispatch. Pi 0.80.4 added
|
|
16
|
+
`agent_settled`, the first lifecycle event that guarantees no automatic retry,
|
|
17
|
+
compaction recovery, or queued continuation remains. `agent_end` is only a
|
|
18
|
+
low-level run boundary and is never accepted as Harnex work completion.
|
|
19
|
+
|
|
20
|
+
Check the installed transport before unattended work:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
harnex doctor --adapter pi
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`harnex run pi` also checks the version before spawn and fails closed when the
|
|
27
|
+
version cannot be parsed or predates 0.80.4. The current contract was live
|
|
28
|
+
verified against Pi 0.84.1.
|
|
29
|
+
|
|
30
|
+
Pi 0.84.0 removed cumulative message snapshots from `message_update`. Harnex
|
|
31
|
+
therefore assembles output from `assistantMessageEvent` deltas between
|
|
32
|
+
`message_start` and authoritative `message_end` events. This remains compatible
|
|
33
|
+
with Pi 0.80.4-0.83.x and avoids printing the final message twice on 0.84+.
|
|
34
|
+
|
|
35
|
+
## Dispatch
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
harnex run pi --id cx-i-42 --tmux cx-i-42 \
|
|
39
|
+
--context "Implement issue 42 and run tests" --auto-stop
|
|
40
|
+
|
|
41
|
+
harnex wait --id cx-i-42 --until task_complete --timeout 3600
|
|
42
|
+
harnex events --id cx-i-42
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`--context` is sent as an RPC `prompt` command; it is not passed as a Pi
|
|
46
|
+
positional argument.
|
|
47
|
+
|
|
48
|
+
Harnex model and effort flags are active controls, not telemetry-only labels:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
harnex run pi \
|
|
52
|
+
--model anthropic/claude-sonnet-4-5 --effort high \
|
|
53
|
+
--context "Review the change" --auto-stop
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Harnex maps those controls to Pi `--model` / `--thinking` startup flags, then
|
|
57
|
+
verifies the effective values with RPC `get_state` before prompting. This avoids
|
|
58
|
+
`set_model` / `set_thinking_level` persisting a dispatch override into the
|
|
59
|
+
user's Pi defaults. Use `provider/model` for deterministic dispatch. Harnex
|
|
60
|
+
fails before the prompt if Pi cannot apply the requested model or thinking level
|
|
61
|
+
exactly, so requested and effective policy cannot silently diverge. Direct
|
|
62
|
+
adapter callers can still use Pi's RPC setters for an intentional mid-session
|
|
63
|
+
switch.
|
|
64
|
+
|
|
65
|
+
Pass Pi startup flags after `--`:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
harnex run pi --context "Implement X" --auto-stop -- \
|
|
69
|
+
--no-session --no-extensions --model anthropic/claude-sonnet-4-5
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
When both Harnex `--model` and a Pi child `--model` are supplied, the Harnex
|
|
73
|
+
startup override is appended last and is authoritative for that dispatch.
|
|
74
|
+
|
|
75
|
+
## Project trust
|
|
76
|
+
|
|
77
|
+
Pi 0.79 added project trust. RPC mode cannot show the interactive trust prompt;
|
|
78
|
+
an unresolved project follows Pi's global `defaultProjectTrust` policy. Harnex
|
|
79
|
+
does not auto-trust repository code.
|
|
80
|
+
|
|
81
|
+
For deterministic unattended runs, choose explicitly after reviewing the
|
|
82
|
+
repository:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Load trusted project-local .pi settings, packages, and extensions
|
|
86
|
+
harnex run pi --context "..." -- --approve
|
|
87
|
+
|
|
88
|
+
# Ignore project-local executable resources
|
|
89
|
+
harnex run pi --context "..." -- --no-approve
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Context files continue to follow Pi's documented trust behavior. Third-party or
|
|
93
|
+
project extensions execute with the worker's OS privileges; `--approve` is a
|
|
94
|
+
security decision, not merely a prompt-suppression flag.
|
|
95
|
+
|
|
96
|
+
## Lifecycle and failures
|
|
97
|
+
|
|
98
|
+
Harnex maps Pi events as follows:
|
|
99
|
+
|
|
100
|
+
| Pi event | Harnex behavior |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `agent_start`, `turn_start` | busy |
|
|
103
|
+
| `agent_end` | remain busy; capture outcome/stats, but do not complete |
|
|
104
|
+
| retry/compaction events | remain busy and emit structured telemetry |
|
|
105
|
+
| `agent_settled` + final `stopReason=stop` | emit `task_complete` |
|
|
106
|
+
| `agent_settled` + `error`, `aborted`, or `length` | emit `task_failed` |
|
|
107
|
+
| `agent_settled` without an authoritative final stop reason | fail closed |
|
|
108
|
+
| EOF, malformed JSON, or request timeout | disconnect/failure |
|
|
109
|
+
|
|
110
|
+
A forced send while Pi is busy is translated to a `prompt` with
|
|
111
|
+
`streamingBehavior="steer"`; ordinary sends wait for the settled prompt state.
|
|
112
|
+
This avoids sending a plain prompt that current Pi correctly rejects while
|
|
113
|
+
streaming.
|
|
114
|
+
|
|
115
|
+
RPC requests are bounded, stderr is continuously drained into a bounded
|
|
116
|
+
diagnostic tail, and Harnex consumes Open3's wait thread so the real subprocess
|
|
117
|
+
exit status is not lost to a competing `waitpid`.
|
|
118
|
+
|
|
119
|
+
## Telemetry
|
|
120
|
+
|
|
121
|
+
At settlement and teardown, Harnex reads `get_session_stats` and records:
|
|
122
|
+
|
|
123
|
+
- input/output/cache/total tokens and provider-reported cost;
|
|
124
|
+
- tool-call count;
|
|
125
|
+
- Pi session ID;
|
|
126
|
+
- effective provider and model;
|
|
127
|
+
- terminal and peak active-context usage.
|
|
128
|
+
|
|
129
|
+
Message/tool/retry/compaction events are available through `harnex events`.
|
|
130
|
+
Blocking extension dialogs (`select`, `confirm`, `input`, `editor`) are
|
|
131
|
+
currently auto-cancelled so autonomous workers cannot hang. Full extension UI
|
|
132
|
+
mediation is not implemented.
|
|
133
|
+
|
|
134
|
+
## Boundaries
|
|
135
|
+
|
|
136
|
+
- The structured adapter does not embed Pi's TypeScript SDK.
|
|
137
|
+
- `--tmux` displays Harnex's synthesized RPC transcript, not Pi's native TUI.
|
|
138
|
+
- First-class native Pi TUI/PTTY markers remain tracked in Issue `#45`.
|
|
139
|
+
- Durable Pi session recovery is separate from lifecycle correctness and remains
|
|
140
|
+
part of the broader structured-recovery work.
|
|
141
|
+
|
|
142
|
+
## Verification
|
|
143
|
+
|
|
144
|
+
Hermetic tests cover lifecycle settlement, retry boundaries, failure stop
|
|
145
|
+
reasons, delta-only message streaming, model/effort RPC controls, request
|
|
146
|
+
timeouts, and telemetry. The opt-in live contract test is:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
PI_INTEGRATION=1 ruby -Ilib -Itest \
|
|
150
|
+
test/harnex/adapters/pi_integration_test.rb
|
|
151
|
+
```
|
data/guides/01_dispatch.md
CHANGED
|
@@ -87,6 +87,25 @@ for i in 1 2 3; do harnex watch --id w-$i --until done --max-wait 90m & done
|
|
|
87
87
|
wait
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
For unattended work, add a session-owned push signal rather than depending on
|
|
91
|
+
one long blocking watcher call:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
harnex run pi --id pi-i-NN --tmux pi-i-NN \
|
|
95
|
+
--context "Read and execute /tmp/task-NN.md" --auto-stop \
|
|
96
|
+
--on-done 'printf "%s %s\n" "$HARNEX_ID" "$HARNEX_OUTCOME" >> koder/scratch/HARNEX_WAKE.txt'
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Every registered session writes
|
|
100
|
+
`$HARNEX_STATE_DIR/done/<repo-key>--<normalized-id>.<outcome>`, even without a
|
|
101
|
+
hook. `--on-done CMD` receives `HARNEX_ID`, `HARNEX_OUTCOME`,
|
|
102
|
+
`HARNEX_WORK_STATE`, `HARNEX_RECEIPT_PATH`, `HARNEX_END_SHA`, and
|
|
103
|
+
`HARNEX_ELAPSED_S`. Use a gitignored wake file. `CMD` is trusted `/bin/sh -c`
|
|
104
|
+
input; never embed secrets in the command line.
|
|
105
|
+
|
|
106
|
+
A push only wakes the consumer. Even `completed` requires report, artifact,
|
|
107
|
+
test, and Git verification plus bounded `harnex watch --until done` calls.
|
|
108
|
+
|
|
90
109
|
Rule: when you use `--tmux`, pass the same name as `--id`. If you pass only
|
|
91
110
|
`--tmux NAME`, harnex creates a random session ID and the pane name no longer
|
|
92
111
|
matches `harnex status` or `harnex pane --id`.
|
|
@@ -148,8 +167,13 @@ to the canonical repo/global dispatch stream, which is the only telemetry
|
|
|
148
167
|
destination. Repo `.harnex/config.json` can warn on or reject non-canonical
|
|
149
168
|
phase names before spawn.
|
|
150
169
|
|
|
151
|
-
Pi runs use structured RPC (`pi --mode rpc`)
|
|
152
|
-
|
|
170
|
+
Pi runs use structured RPC (`pi --mode rpc`) and require Pi >= 0.80.4; gate
|
|
171
|
+
unattended work with `harnex doctor --adapter pi`. Harnex `--model` / `--effort`
|
|
172
|
+
apply verified Pi startup controls before the prompt. Pass other Pi startup
|
|
173
|
+
flags after `--` (e.g. `harnex run pi --context "..." -- --model
|
|
174
|
+
anthropic/claude-sonnet-4-5 --thinking high`).
|
|
175
|
+
Since RPC cannot display Pi's trust prompt, explicitly pass child `--approve`
|
|
176
|
+
for reviewed project-local resources or `--no-approve` to ignore them.
|
|
153
177
|
|
|
154
178
|
Codex flag forms differ between transports. The default JSON-RPC adapter
|
|
155
179
|
(`codex app-server`) does not accept `-m`/`--model`; pass the model as
|
data/guides/04_monitoring.md
CHANGED
|
@@ -17,12 +17,30 @@ Prefer signals in this order:
|
|
|
17
17
|
| `harnex pane` | Live UI interpretation and prompt/error diagnosis |
|
|
18
18
|
| `harnex status` | Session liveness and coarse state |
|
|
19
19
|
|
|
20
|
-
For unattended
|
|
21
|
-
|
|
20
|
+
For unattended sessions, combine bounded watcher calls with the runner-owned
|
|
21
|
+
push path. Every session writes
|
|
22
|
+
`$HARNEX_STATE_DIR/done/<repo-key>--<id>.<outcome>` at its first work-terminal
|
|
23
|
+
result. `harnex run --on-done CMD` can also launch one non-blocking local hook,
|
|
24
|
+
even without a watcher and while the agent remains alive at a prompt:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
harnex run pi --id pi-i-NN --tmux pi-i-NN --context "Read the task brief" \
|
|
28
|
+
--auto-stop \
|
|
29
|
+
--on-done 'printf "%s %s\n" "$HARNEX_ID" "$HARNEX_OUTCOME" >> koder/scratch/HARNEX_WAKE.txt'
|
|
30
|
+
harnex watch --id pi-i-NN --until done --max-wait 30m
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Use a gitignored wake destination. `CMD` is trusted shell input; never embed
|
|
34
|
+
secrets. It receives `HARNEX_ID`, `HARNEX_OUTCOME`, `HARNEX_WORK_STATE`,
|
|
35
|
+
`HARNEX_RECEIPT_PATH`, `HARNEX_END_SHA`, and `HARNEX_ELAPSED_S`. `completed`
|
|
36
|
+
wakes the consumer but does not certify the prose; verify the receipt and
|
|
37
|
+
artifact before acting.
|
|
38
|
+
|
|
39
|
+
`harnex watch --until done` returns on the work-level `task_complete` or
|
|
22
40
|
`task_failed` signal, or terminal exit, whichever comes first. Successful work
|
|
23
41
|
exits `0`, failed work exits non-zero, and wall-clock caps exit `124`. For
|
|
24
42
|
callers that need the lower-level primitive, `harnex wait --until done` exposes
|
|
25
|
-
the same work fence.
|
|
43
|
+
the same work fence. Do not park an orchestrator in one unbounded watcher call.
|
|
26
44
|
|
|
27
45
|
## Live-Run Visibility
|
|
28
46
|
|
|
@@ -31,8 +49,10 @@ Every dispatch appends a `dispatch_start` row to the repo's dispatch stream
|
|
|
31
49
|
completes it. Between those two rows the run is visible to every documented
|
|
32
50
|
signal, from any cwd in the same repo:
|
|
33
51
|
|
|
34
|
-
- `harnex status --id X` reports
|
|
35
|
-
|
|
52
|
+
- `harnex status --id X` reports settled work as `done`, `rejected`, or
|
|
53
|
+
`failed` even while the adapter is back at `prompt`. When work is unsettled,
|
|
54
|
+
it reports the adapter input state. If the live HTTP status API is
|
|
55
|
+
unreachable it still reports running from the
|
|
36
56
|
registry (or, failing that, from the uncompleted start row) and labels the
|
|
37
57
|
row `degraded: true` with `source` set to `registry` or `dispatch_start`.
|
|
38
58
|
- `harnex history` shows uncompleted dispatches as `running` (pid alive) or
|
|
@@ -68,8 +88,11 @@ named parent is still running in the same repo is refused. Wait for the parent
|
|
|
68
88
|
(`harnex wait --id <parent> --until done`) or stop it first. Pass
|
|
69
89
|
`--allow-live-parent` only for intentional parallelism (e.g. isolated
|
|
70
90
|
worktrees). `--attempt-kind review` is exempt: a completed parent may still
|
|
71
|
-
sit at a live prompt while its work is reviewed. For structured sessions (Pi
|
|
72
|
-
`harnex wait --until task_complete` remains the exact
|
|
91
|
+
sit at a live prompt while its work is reviewed. For structured sessions (Pi
|
|
92
|
+
RPC and Codex app-server), `harnex wait --until task_complete` remains the exact
|
|
93
|
+
accepted-turn fence. Pi reaches that fence only at `agent_settled`; an earlier
|
|
94
|
+
`agent_end` can still be followed by retry, compaction recovery, or queued work.
|
|
95
|
+
Final Pi `error`, `aborted`, and `length` stop reasons emit `task_failed`.
|
|
73
96
|
Codex acknowledgment-only auto-stop turns are typed
|
|
74
97
|
`completed_no_activity` and fail this fence without transcript parsing. Harnex
|
|
75
98
|
writes the observed-state receipt before publishing `task_complete`; optional
|
|
@@ -205,7 +228,8 @@ interpretation.
|
|
|
205
228
|
- Polling `state=completed` alone and missing live sessions with `task_complete=true`.
|
|
206
229
|
- Polling `state=prompt` alone and calling it done.
|
|
207
230
|
- Wrapping `harnex wait` in loops that swallow non-zero `task_failed` results.
|
|
208
|
-
- Blocking orchestrators on `/tmp/*-done.txt` as the only completion signal.
|
|
231
|
+
- Blocking orchestrators on caller-owned `/tmp/*-done.txt` as the only completion signal.
|
|
232
|
+
- Using one long watcher call without the runner-owned marker or `--on-done` push path.
|
|
209
233
|
- Letting an unattended loop run with no wall-clock cap.
|
|
210
234
|
- Reading raw tmux panes instead of `harnex pane`.
|
|
211
235
|
- Using `--wait-for-idle` as acceptance proof.
|