Skip to content

CL-6365: close proof 4's remainders — sweep, notice, old attachments, audit - #107

Closed
TheGreatAxios wants to merge 3 commits into
cl-6365-unfusefrom
cl-6365-close
Closed

CL-6365: close proof 4's remainders — sweep, notice, old attachments, audit#107
TheGreatAxios wants to merge 3 commits into
cl-6365-unfusefrom
cl-6365-close

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Contributor

What this is

The four named remainders from #106, plus the honest result of actually re-running proof 4.

Everything downstream of the detection signal is now built and unit-proven. The detection signal itself turns out not to fire for the shape proof 4's third hop measures — see What the re-run found.

The four remainders

1. Boot-time terminal sweep. createHubChatPlatform.sweepTerminalRuns scans workbench_launch (bounded at 100 rows), keeps the participants isBeyondWake calls terminal-and-not-merely-parked, and relaunches each through the existing wakeByAddress relaunch path. Every relaunch and every failure is logged under chat·wake; one failure never aborts the pass.

The hub runs it at boot and re-arms it on sidecar.disconnect, as a short bounded series of passes rather than one. That is not belt-and-braces: a run that died with its sidecar only reads as terminal once the restarted sidecar has packed its log back to the hub, seconds after the reconnect.

2. The relaunch notice. createHubChatPlatform takes a notice port — a ref, since the adapter is built before the room-message store it posts through — armed in the hub beside roomMessages. Every relaunch, swept or send-triggered, posts into each room the replaced participant belongs to, under the stable address the room has always known it by, so it reads as the same teammate rather than a stranger. The wording is cause-aware (crashed / stopped / ended) and stays in the reader's language: the turn didn't finish, it's back now, say it again.

3. Pre-relaunch attachments. fetchBlob read through the live run's session, and a folded run's mail session resolves from its principal — a fresh run has a fresh principal, so every attachment sent before the crash became unreachable. workbench_launch.prior_run_ids (migration 0021) records each run as it is retired, capped at 20, and fetchBlob walks those sessions newest-first after the live one. A retired run whose row or session is gone is skipped, never fatal.

4. Audit assertion. Proof 4 gains a hop that reads the replaced run's events back through the ordinary run routes after its replacement is already answering. That is the fresh-run ruling's whole justification, and it is a hop now rather than an argument.

What the re-run found

Proof 4 was re-run on a real stack — scratch database, real signup, real Ollama, both deploy shapes. Proofs 1, 2, 2b and 3 are green; proof 4's restart and boot restore are green at 9.2s. Hop 3 is still red, and the sweep is not why: nothing in its log fired, because it found nothing to sweep.

run_10dd09d1…  failed    <- the SECTION deployment
run_4de07624…  running   <- the folded CHAT run, after the mid-turn kill

#106's note that both top-level runs end up workflow_run.status = 'failed' holds for the section deployment only. The folded chat run's terminal event goes to its durable log — which is why its supervisor rejects the next message — while its workflow_run row stays running forever. isBeyondWake reads that row, so for this shape it answers "still alive", and neither the sweep nor the send-triggered relaunch fires. The room keeps the reader's message with nothing after it: the exact silent drop the hop asserts against.

So the remaining gap is the detection signal, not the relaunch. The hub needs a folded run's lifecycle from the same durable log the supervisor reads (readWorkflowRunLifecycle) rather than from workflow_run.status — either by reconciling the row when a restarted sidecar packs a terminal log back, or by having isBeyondWake consult the log directly.

The section shape stays red for its own separate reason: a plain workflow deployment has no room, so nothing maps a stable id onto a fresh run for it. That is outside CL-6365's scope, which is the room.

Environment note

The proof's own trap #1 bites harder than documented: the onboarding seed pins the definition's model from CATALOG_SEEDS.ollama (qwen3.8:27b), and E2E_OLLAMA_MODEL only redirects the proof's own pins — so on an instance without that model, proof 3 dies as "I can't reach a model right now" before proof 4 is ever reached. The re-run named that model locally so the two agreed. Worth closing in the harness separately.

Checks

  • bun run typecheck (whole repo): clean.
  • packages/chat: 576 pass, 0 fail (595 across 51 files).
  • apps/hub: 130 pass, 0 fail.
  • prettier --check clean on every touched file (7 unrelated files under packages/onboarding and packages/cli were already drifting on the base branch).

Covers the three ways a relaunch is visible from outside: a
routable-but-dead participant is swept up and replaced (and a folded run
merely parked between messages is not), the room is told in the agent's
own voice with wording that names the cause rather than the machinery,
and an attachment sent before the crash still opens afterwards even
though the fresh run's mail session is a different session.

The existing chat fakes gain the prior-run history column every launch
row now carries.
The relaunch was send-triggered, so a room whose agent died in a crash
stayed silently dead until somebody wrote into it — and the turn the
crash interrupted never surfaced at all, because the run that died never
sends the message.run.ended the turn-drop notice hangs off. Three
closing pieces:

- sweepTerminalRuns replaces every participant whose run is beyond
  waking, bounded and logged per relaunch. The hub runs it at boot and
  re-arms it on a sidecar disconnect, across a short bounded series of
  passes: a run that died with its sidecar only reads as terminal once
  the restarted sidecar has packed its log back to the hub.
- Every relaunch, swept or send-triggered, posts a cause-aware notice
  into each room the replaced participant belongs to, under the stable
  address the room has always known it by.
- workbench_launch keeps the runs it used to be, and fetchBlob walks
  them: a folded run's mail session hangs off its principal, and a fresh
  run has a fresh principal, so an attachment sent before the crash is
  otherwise unreachable forever.

Proof 4 gains the hop the fresh-run ruling exists for: the replaced
run's durable log is still readable through the ordinary run routes
after its replacement is already answering.
Records the three closing pieces (boot sweep, relaunch notice,
pre-relaunch attachments) and the audit hop, and corrects an earlier
claim with what a real re-run actually showed: only the section
deployment's workflow_run row goes 'failed' after a mid-turn kill. The
folded chat run's row stays 'running' while its durable log carries the
terminal event, so the status-based detection signal never fires for the
shape proof 4's third hop measures. The relaunch machinery is built; the
signal that should trigger it is the remaining gap.
@TheGreatAxios

Copy link
Copy Markdown
Contributor Author

Landed via the stack tip: PR #108 (merge fbf0852) contains this branch's commits in full.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant