Skip to content

app: a conversation's id is its folder's name; finish the wrap-up after the app's pipes close - #1973

Merged
ZeroPoint95 merged 3 commits into
app/v3from
zeropoint95/app-cell-id-and-sigpipe
Oct 26, 2026
Merged

ZeroPoint95 merged 3 commits into
app/v3from
zeropoint95/app-cell-id-and-sigpipe

Conversation

@ZeroPoint95

@ZeroPoint95 ZeroPoint95 commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes new conversations all getting the id .cell, and lets an app engine finish its leaving wrap-up after its app has gone.

.cell ids

  • Since transcripts moved to <id>/.cell/transcript.jsonl (Wormhole: your codeaf follows you between computers (on by default) #1888), appAgentID took the transcript's parent folder, so every new conversation was named .cell
  • Effects: factory.job_chats asked for .cell and found nothing; once any agent was created, .cell resolved to that agent for every caller
  • appAgentID now uses session.DirOf: the session folder in both layouts; legacy folders answer as before
  • Media listing, attachment staging, deliverables, lazy wake-ups and recorded attachments use the session folder too (they also took .cell)

SIGPIPE

  • An app may quit without waiting for its engine, and a crash cannot wait
  • The engine then writes after both pipes to the app have closed; Go ends a program that writes to a broken stdout or stderr unless SIGPIPE is ignored
  • codeaf app now asks for SIGPIPE with signal.Notify (not Ignore, which children would inherit), so its own writes fail with EPIPE and the bounded wrap-up finishes, while shells and tools it starts keep SIGPIPE

Tests

  • Cells on: the id rule in both layouts; two agents.create calls get distinct folder-name ids that each find their own conversation; factory.job_chats on a cell Talk answers the Talk folder's id (all three fail on the old code)
  • A child writes until both pipes fail with EPIPE after its parent closed them, still finishes, and a shell it starts ends yes | head -1 with 141 (fails with no guard, and with signal.Ignore)
  • A cell conversation's media scope is its own folder
  • Full go test ./... compared with a clean 575a39018: no new failures

Review

  • Independently reviewed; fixes in 57e066c (Notify instead of Ignore, remaining .cell call sites, stronger test, one numbered change entry)
  • Known pre-existing reds on app/v3 are unchanged (e.g. the 4 TestAppMediaAttach* tests fail on the base too)

How to test

  1. go test ./cmd/codeaf -run 'TestAppAgentID|TestAppCreateGivesEachCell|TestAJobsChatsNameTheCellTalksFolder|TestAnEngineWritesOnAfterItsAppsPipesClose'
  2. With cells available, create two conversations through the app protocol: their ids differ and neither is .cell.

🤖 Generated with Claude Code

ZeroPoint95 and others added 3 commits October 26, 2026 15:21
Since transcripts moved into <id>/.cell/transcript.jsonl, appAgentID took
the transcript's parent folder and named every new conversation ".cell".
factory.job_chats then asked for ".cell" and found nothing (ids starting
with "." are refused), and once any agent was created, ".cell" resolved
to that agent for every caller.

appAgentID now uses session.DirOf, the session folder in both layouts; a
legacy flat folder answers exactly as before.

Tests (cells on): the id rule in both layouts, two agents.create calls get
distinct folder-name ids that each find their own conversation, and
factory.job_chats on a cell Talk answers the Talk folder's id. All three
fail on the old code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An app may quit without waiting for its engine, and a crash cannot wait.
The engine then keeps stopping its processes and writing its conversations
down after both pipes to the app have closed, and Go ends a program that
writes to a broken stdout or stderr unless SIGPIPE is ignored. codeaf app
now ignores SIGPIPE, so those writes fail and the bounded wrap-up finishes.

Test: a child that ignores broken pipes writes on after its parent closed
both pipes and still finishes; without the ignore it dies by SIGPIPE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…verywhere

From an independent review of this PR:
- signal.Ignore(SIGPIPE) is inherited across exec, so every shell, tool
  and server the engine starts lost SIGPIPE (`producer | head` never
  ended). surviveBrokenPipes now uses signal.Notify: the engine's own
  writes to a closed pipe still fail with EPIPE, and its children keep
  the default.
- The test waits for the parent to close its ends, writes until both
  writes fail with EPIPE, and checks that a child shell still ends
  `yes | head -1` with 141.
- Media listing, attachment staging, deliverables, lazy wake-ups and
  recorded attachments still took the transcript's parent (".cell") as
  the session folder; they use session.DirOf / appAgentID now. The create
  test checks a cell conversation's media scope is its own folder.
- One change entry, named and numbered for this PR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ZeroPoint95
ZeroPoint95 marked this pull request as ready for review October 26, 2026 19:46
@ZeroPoint95
ZeroPoint95 merged commit 1ac407d into app/v3 Oct 26, 2026
1 check passed
@ZeroPoint95
ZeroPoint95 deleted the zeropoint95/app-cell-id-and-sigpipe branch October 26, 2026 19:47
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