Skip to content

Carry each request's answer, who gave it and its delivery through the journal, replay and the phone (CF-6, request half) - #308

Merged
BunsDev merged 5 commits into
mainfrom
cf6-requests
Oct 19, 2026
Merged

BunsDev merged 5 commits into
mainfrom
cf6-requests

Conversation

@BunsDev

@BunsDev BunsDev commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

The request half of CF-6 (#279), on CF-3's human-request lifecycle (#276): a card is the record of its request across the event journal, snapshots, paired desktops and the phone.

What changes

  • Who answered, and whether it arrived. An accepted answer saves answeredBy (desktop or phone) and delivery: "sending" before the CLI hears anything, then delivery: "sent" after the hand-off. These travel as whole field values in the existing item/item_update events, so the journal stores, merges and replays them with no new event type.
  • Restart. A card still sending becomes uncertain: Modex stopped between taking the answer and recording its hand-off. The answer is never sent again, a late answer is refused, and the card says "Modex stopped before it could confirm the agent received this answer." Cards nobody answered still close as ended. Answers saved before these fields existed are left as they were.
  • The phone gets answeredBy, delivery and withdrawn on approvals, and a question's notice says when delivery is uncertain. A card the phone answered reads "Answered on your phone." in the window.
  • Fix: the phone could not act on a thread started on the Mac. Since Install verified macOS updates with durable draft recovery #181 (v0.0.12), such a thread keeps the full UUID its draft reserved, but the companion's thread routes took only 8 hex characters. Answering, sending, setting the policy and archiving from the phone all got a 404. The routes now take any id the store accepts, and the thread must exist. CF-8's fidelity e2e found it.

Journal on and journal off behave as before for everything else. Coding still runs only through codex app-server and claude -p.

Tests, red first

  • test/request-journal.test.ts (new). All six cases failed first on the missing fields:
    • who answered and the delivery, in the window, the snapshot, the journal replayed once and twice (a duplicated event), the phone, and after a restart, with no second decision;
    • simultaneous desktop and phone answers: exactly one accepted, the phone's a 409, the CLI hears one decision;
    • a paired desktop over TLS that reconnects after the decision was sent sees it answered, and its stale answer is refused;
    • an expired cursor reloads to a snapshot with the same fields;
    • a crash between taking an answer and recording its hand-off: uncertain, inert, never re-sent;
    • with the journal on, a secret answer reaches the CLI and no file under MODEX_HOME (SQLite pages and WAL included), event or phone snapshot.
  • test/human-requests.test.ts: answerNote failed first (no such export).
  • test/companion.test.ts: a UUID thread failed first with 404.
  • e2e/human-requests.spec.ts: with the journal on, it answers a Codex question, stops a second one, and marks the first card as if Modex died mid-send. After a restart, both cards are inert, the uncertain one says so, a second answer is refused, Codex hears nothing more, and no file holds the secret.

Checks

On 067d89c, rebased onto main 57e7607 (CF-3), macOS 26.7.1, Node v24.18.1, pnpm 10.34.5:

  • pnpm build at the root and pnpm typecheck in apps/desktop: passed.
  • pnpm test in apps/desktop: 1,589 passed, 16 skipped, 0 failed; second stage 21 of 21.
  • pnpm --filter @modex/store-desktop test: passed.
  • e2e human-requests (including the new journal-on restart case), companion, event-journal, approvals: 10 of 10.
  • On the stacked head before CF-3 landed (same CF-6 code): e2e human-requests, approvals, companion, event-journal, store-desktop, conversation-fidelity: 21 of 21.
  • Not run locally: the rest of pnpm test:e2e. CI runs it.

All commits are signed. docs/status.md adds CF-6 under "On main, unreleased" and drops the Markdown parser (#283, landed) from "Still open".

Refs #279, #276. Tracker #273.

@vercel

vercel Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
modex Ready Ready Preview Oct 19, 2026 12:05am UTC

Request Review

@github-code-quality

github-code-quality Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Code coverage overview

Languages: TypeScript

TypeScript / code-coverage-agent

main 81798d7 cf6-requests e408f54 +/-
63% 63% 0%

ℹ️ Calculations represent line coverage. Results may change as calculations are updated.


Updated October 19, 2026 00:43 UTC

A card is the record of its request across the journal, snapshots, paired desktops and the phone
(CF-6, request half). An accepted answer now saves answeredBy ("desktop" or "phone") and
delivery "sending" before the CLI hears anything, then delivery "sent" after the hand-off. They
travel as whole field values in the existing item events, so the journal stores and replays them
with no new event type.

On a restart, a card still "sending" becomes "uncertain": Modex stopped between taking the answer
and recording its hand-off. The answer is never sent again, and a late answer is refused. The
phone gets answeredBy, delivery and withdrawn on approvals, and a question's notice says when
delivery is uncertain.

test/request-journal.test.ts failed first on each missing field: replay once and twice, a
restart, desktop and phone answering at once (one accepted, the phone's a 409), a paired desktop
resuming after the decision, an expired cursor, a crash mid-send, and a secret kept out of every
file with the journal on.

Refs #279

Coven-Harness: Claude Code / claude-opus-5-5
answerNote adds "Answered on your phone." under a card the phone answered, and "Modex stopped
before it could confirm the agent received this answer." when delivery is uncertain. An answer
given in the window and sent adds nothing. Its unit test failed first (no such export).

e2e/human-requests.spec.ts runs the Codex question fixture with the journal on, closes Modex,
marks the answered card as if Modex died mid-send, and restarts: the answered and stopped cards
are inert, the uncertain one says so, a second answer is refused, Codex hears nothing more, and no
file holds the secret.

Refs #279

Coven-Harness: Claude Code / claude-opus-5-5
docs/human-requests.md maps each broker step to the card fields that carry it, and says what a
restart, replay, a late answer, two clients at once, the phone and the window do with them.
docs/event-journal.md points there instead of saying the lifecycle is still to come.

Refs #279

Coven-Harness: Claude Code / claude-opus-5-5
Since #181 (v0.0.12), a thread created from a Mac draft keeps the full UUID its draft reserved,
but the companion's thread routes accepted only 8 hex characters. So the phone got a 404 when it
answered an approval, sent a follow-up, set the approval policy or archived any thread started on
the Mac; threads started on the phone, with short ids, worked. CF-8's fidelity e2e found it.

The routes now take any id the store accepts, and the thread must still exist. The new companion
test failed first with 404 for a UUID thread.

Refs #279

Coven-Harness: Claude Code / claude-opus-5-5
Refs #279

Coven-Harness: Claude Code / claude-opus-5-5
@BunsDev
BunsDev merged commit d625eda into main Oct 19, 2026
13 checks passed
@BunsDev
BunsDev deleted the cf6-requests branch October 19, 2026 00:45
BunsDev added a commit that referenced this pull request Oct 19, 2026
…ch-comparison slice

Coven-Harness: Claude Code / claude-opus-5-5
BunsDev added a commit that referenced this pull request Oct 19, 2026
Brings in #308 (CF-6 request half) so #310 is up to date with main.

Coven-Harness: Claude Code / claude-opus-5-5
BunsDev added a commit that referenced this pull request Oct 19, 2026
Brings in the CF-6 request half (#308) and #306, #307. One conflict, in
mobileItem: #308 rewrote the question case's text, adding the delivery wording,
where this branch adds the default for unknown kinds. Both are kept: main's
question text, then the default case.

Coven-Harness: Claude Code / claude-opus-5-5
BunsDev added a commit that referenced this pull request Oct 19, 2026
CF-2 (#286), CF-3 (#293), CF-4's Markdown slice (#283), CF-6's request half (#308) and CF-7's
clarifications (#312) are on main, with their merge commits. The candidate note says the fixture
rows now run on main, and no candidate is pinned while the live-provider and human gates stay open.

Refs #281

Coven-Harness: Claude Code / claude-opus-5-5
BunsDev added a commit that referenced this pull request Oct 19, 2026
…nts at once, reconnect, a clarifying question (CF-8) (#313)

* Add the request variants to the fidelity path

Four cases in e2e/conversation-fidelity.spec.ts, through the real app:

- A native withdrawal: the Claude fixture takes its own request back (control_cancel_request).
  The card closes as withdrawn, no answer reaches the CLI, a late answer is refused, and the file
  is unchanged.
- The desktop and the phone answer at once, over the bridge and the companion's HTTPS. Exactly one
  is accepted, the CLI reads one decision, the card names who gave it, and the file matches the
  winner.
- With the journal on, a phone that loaded the open card reconnects after the desktop's decision.
  Its delta shows the card answered by the desktop and sent, its late answer is a 409, and every
  count stays at one.
- A clarifying question inside the path, from a codex-cli 0.163.0-shaped fixture: answered on its
  card, heard once, followed by a real edit and check, saved to Notes, and inert after a restart
  that re-runs nothing.

The fixture now counts every decision the CLI reads, so the earlier cases assert that too. The
golden path is marked slow: since #301 it also takes 18 reference captures and relaunches, and it
ran past 90 s on a Mac at load average 100.

These cases found the companion's 404 for threads started on the Mac, fixed in the CF-6 branch.

Refs #281

Coven-Harness: Claude Code / claude-opus-5-5

* Record the request variants in the acceptance receipt

The matrix rows for a clarifying question, a native withdrawal, simultaneous answers and a
reconnect after a decision move from open to verified with a fixture, with what each case asserts.
The defects list adds the companion's 404 for threads started on the Mac. The fidelity summary gains
rows for questions and approvals.

Refs #281

Coven-Harness: Claude Code / claude-opus-5-5

* Record CF-8's request variants in status

Refs #281

Coven-Harness: Claude Code / claude-opus-5-5

* Record the landed children in the acceptance receipt

CF-2 (#286), CF-3 (#293), CF-4's Markdown slice (#283), CF-6's request half (#308) and CF-7's
clarifications (#312) are on main, with their merge commits. The candidate note says the fixture
rows now run on main, and no candidate is pinned while the live-provider and human gates stay open.

Refs #281

Coven-Harness: Claude Code / claude-opus-5-5

This branch was successfully deployed

1 active deployment
Preview — e408f543 Deployed Oct 19, 2026 by vercel[bot]
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