v0.2.1: see running turns, never downgrade an acknowledged line, heal under a lock, refuse foreign writers #3
Loading…
Reference in a new issue
No description provided.
Delete branch "oss-oo/appserver-send-v021"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
v0.2.1 — the fix release after the neighbour session's read of v0.2.0
The second independent read (Claude session
a7056f09…, with its own harness under~/.zcode/tmp/claude/appserver-resume-measure-20261027/review-pr2/) arrived after v0.2.0 was merged and installed. It found two blockers and two majors; all are folded here, the blocker is proven live.Blockers
thread/resume {excludeTurns: true}with"turns": []— the key is always present (confirmed read-only against the loaded twin thread on the station). v0.2.0 askedthread/turns/listonly when the key was missing, so it never saw a running turn: the heal gate could have restarted the shared server over a running headless turn,--mode steeralways ended asno-active-turn, auto sentturn/start(which the server applies as a steer) and recordeddelivered-app-start. Nowstatus.type == "active"is the signal, the id comes fromthread/turns/list {limit: 1}by itsinProgressstatus (never by position), the heal gate treats active and unreadable loaded threads as busy, and the fake server answersturns: []so the suite sees the real shape.refused,delivered: false— a caller trusting it would resend. Now an acknowledged line is never downgraded:completed: false+wait_error, the throttle stays marked.Majors
ack-unknown: aturn/start/turn/steerrequest on the wire without an acknowledgement (or a connection lost before it) is its own class (exit 8,delivered: null, throttle kept, note "do not resend blindly — look for the line in thread/turns/list first");timeoutis reserved for steps before anything was sent. The WebSocket client splitsrequestandwait_replyso "on the wire" is known.heal.lockserialises concurrent senders, the station is observed again under the lock (already-healed,door-open-now,app-runningskips); a unit active for less than 30 s withoutreadyzis waited for instead of restarted (waited—Type=simplereports active before the server listens); afailedunit is never reset by the sender (door-closed with a hint); the client count is re-read right before every restart; the readyz probe bypasses anyhttp_proxy; the stderr line says what was checked.The thread store's writer lock (rigs v7/v8, folded in
f74fc2d+693ee3e)A thread one server has loaded cannot be written by another: the second server logs
thread-store conflict: … already has an active writer, itsturn/startanswers-32600 thread not found, reads still work, the rollout stays byte-identical;thread/unsubscribedoes not release the lock, only the end of the holding process does. So a "stale pre-loaded thread" cannot arise — the edge is a lock-out of the app's own stdio server while the shared service holds a thread (and the other way round).sendmaps both server verdicts toheld-by-app;oo-appserver releaseis a gated restart that frees every lock — while the app is closed, runs its own app-server or an orphaned stdio server exists, never while the app is attached (app-attached); no client, no busy thread;--dry-runplans only. The launcher wrapper could free the locks before a fallback launch — the owner's call (dotfiles).Minors and nits
--listenservers excluded) isheld-by-app; the station is looked at once more right beforeturn/start.heal --dry-runacts on nothing; no positional steer target; README: ceil in the formula,not-needed,agent_items[], the measured facts (a second resume joins the first load; worst first load 16.7 s = 0.023 s/MB, the 0.05 default stays).Tests
Suite 62 → 92 legs (green on every commit, ~53 s): the real reply shape, close-after-ack, ack-unknown, foreign stdio servers, app appearing mid-send (late-state seam), heal lock with two parallel senders (one restart), three parallel sends to one thread (one pass), young/hung/failed unit, fragmentation + pings, WS request/wait split, process scanners with injected process lists,
heal --dry-run, writer-conflict verdicts,releasein every station state.Live proof 3 (station, app closed, 00:0x)
send … --wait 0started a headless turn on the Luna6 twin (turn/startack 167 ms); one second latersend … --mode steersawthread_status: active, read the same turn id throughthread/turns/listand steered into it (turn/steerack 96 ms,turn/completed7.7 s, answerok). Evidence:~/.zcode/tmp/claude-adapter-design-20261027/v021-proof/.Independent review
The neighbour session (the author of the v0.2.0 findings, read-only, own clone and harness) confirmed every commit:
ae3e69d— "alle neun Befunde und die Nits sind behoben … mergen, releasen und vom Tag installieren ist ok" (83/83);f74fc2d— mapping and known gaps fit (88/88), one usability major:releaserefused the fallback case it exists for;693ee3e— "das Gatter vonreleaseist richtig" (92/92). CI green on every commit (runs 9–11). Review texts:v021-review/in the evidence folder. A second read-only subagent was started onae3e69d; its report, if it brings anything, goes into v0.2.2.🤖 Generated with Claude Code
oo-appserver release