Skip to content

🤖 refactor: the turn's scratchpad, memory context, scratch dir and transcript index go through SessionFiles - #7430

Merged
ThomasK33 merged 5 commits into
mainfrom
phase5/b-turn-session-files
Oct 24, 2026
Merged

ThomasK33 merged 5 commits into
mainfrom
phase5/b-turn-session-files

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

Summary

5b PR 3 of phase 5 (Loop host I/O) of the agent-loop refactor. Four modules that an agent turn reaches read and write their files through injected file services instead of fs/promises, os and writeFileAtomic:

  • additionalSystemContext.ts: the scratchpad (additional-system-context.md) and its disabled marker.
  • memoryContextPersistence.ts: the memory-context file of the context window.
  • runtimeScratchDir.ts: the host scratch dir, and the Docker client config read of the devcontainer mount check.
  • subagentTranscriptArtifacts.ts: the sub-agent transcript index.

The session-dir files go through SessionFiles (phase 2). The turn passes the SessionFiles of its HistoryService, so a memory layer keeps these files off the disk too. The Docker client config (~/.docker) is no session file, so that read goes through HostFiles and HostPaths (5a PR 5).

Behavior does not change: every default is the Node layer (nodeSessionFiles, nodeHostFiles, nodeHostPaths), which calls the same fs/promises functions, os.homedir(), ensurePrivateDir and writeFileAtomic.

Order

Plan order: stack 5b is PR 1 to PR 9. This PR waits for phase 2 PR 7 and phase 4 PR 14 (#7425, merged), which changed updateSubagentTranscriptArtifactsFile. It uses no code of 5b PRs 4 and 5, so it opens on its own, with base main.

Implementation

  • additionalSystemContext.ts: readAdditionalSystemContext and writeAdditionalSystemContext take an optional last files argument (default nodeSessionFiles). ensurePrivateDir is files.ensurePrivateDir.
  • memoryContextPersistence.ts: the MemoryContextStore constructor takes files (same default). AgentSession passes historyService.files.
  • runtimeScratchDir.ts: ensureScratchDirForSpec takes files after abortSignal, and RemoteScratchDirCache.ensure forwards an optional files. Both create the host and devcontainer-mount dirs, which are in the session dir. canBindMountHostPathsIntoContainers takes the home dir from nodeHostPaths.userHome() and gets a HostFiles argument.
  • subagentTranscriptArtifacts.ts: readSubagentTranscriptArtifactsFile takes files, and updateSubagentTranscriptArtifactsFile and upsertSubagentTranscriptArtifactIndexEntry take files? beside locks. HistoryService passes this.files to its 2 index reads.
  • turnRequestBuilder.ts: the scratchpad read and both scratch-dir calls pass historyService.files.
  • Callers outside the turn keep the Node default: InstructionsService (the scratchpad panel), the child-artifact roll-up of WorkspaceService (its copies still call fs/promises), artifactsOperations.ts and terminalService.ts.

The plan estimated about 360 lines. This PR adds 266 and removes 47.

Validation

  • Done check of the plan: pairs.mjs --phase5 lists no host import in the 4 files (it listed 2 in each on main).
  • 5 new cases, each on memory file layers. With main's production files, all 5 fail:
    • additionalSystemContext.test.ts: the scratchpad and its marker are in the memory volume, the Node default reads none, and the temp dir on disk stays empty.
    • memoryContextPersistence.test.ts: save, load and discard work in memory, and the session dir on disk does not exist.
    • runtimeScratchDir.test.ts: ensureScratchDirForSpec creates the host dir in memory only. canBindMountHostPathsIntoContainers reads a client config that exists only in memory HostFiles and names a remote context (false), while the disk without a config gives true.
    • historyService.test.ts: a transcript index written through memory SessionFiles is in memory and not on disk, and getSubagentTranscript finds it by owner and by session scan.
  • The plan's tests (additionalSystemContext.test.ts, agentSession*.test.ts, runtimeScratchDir.test.ts, historyService*.test.ts) plus the golden and contract tests of sessionFiles/, memoryContextPersistence, subagentTranscript*, instructionsService, turnRequestBuilder*, terminalService*, artifactsOperations*, DevcontainerRuntime* and sessionLocks/: 2476 pass, 0 fail in 94 files.
  • make static-check, make lint-eslint, make crap-check and make dry-check pass. crap-check warns only that the AgentSession constructor and prepareOrThrow are touched hotspots, with unchanged complexity.
  • make test (host suite lock) on head 0c9c084: bun test src had 27908 pass, 7 skip, 1 fail. The failure was BackgroundProcessManager > terminate > should deliver SIGTERM to the bash process (a 3 s timeout under a host load of 13). Its file passed twice on a rerun (166 pass, 0 fail). The shared scripts/storybook/vscode run had 729 pass, 1 skip, 0 fail, and the 18 isolated files had 0 fail. Loop-test tripwire, 3 runs against main: 0 trips.
  • After a merge of main e89cf28 (🤖 refactor: the durable journal and the removal tombstones read and write through SessionFiles and HostFiles #7426, 🤖 refactor: the session usage service reads and writes its files through the HistoryService's SessionFiles #7428): a test-only commit drops a duplicate import, typecheck and the 4 static gates pass, and the related tests (the list above plus workspaceRemoval, sessionUsageService* and utils/journal/) have 2582 pass, 0 fail in 101 files.

Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high • Cost: $197.19

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-24T19:58:03.514666Z 348be23 PR opened
🔒 Security Review ✅ Completed 2026-10-24T19:57:39.626362Z 348be23 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown
Contributor

🟢 e2e stories (Haiku): 14 passed

27 agent steps · 7 replayed from cache · 31 model calls · 219.0k tokens (70% cached)
Spend: $0.10 of the $1.00 cap (proxy ledger)

All 14 tests in 9 files
Test Agent Time
🟢 chatRestart.e2e.ts · 1 passed 2 steps · 4 calls 24.1s
🟢 a chat survives a restart of the server 2 steps · 4 calls 24.1s
🟢 compaction.e2e.ts · 1 passed 3 steps · 7 calls 43.1s
🟢 /compact replaces the old chat with a summary 3 steps · 7 calls 43.1s
🟢 pluginTrustRestart.e2e.ts · 1 passed 4 steps · 2 calls 9.2s
🟢 a trusted plugin hook stays trusted after the server restarts 4 steps · 2 calls 9.2s
🟢 settingsRoundTrip.e2e.ts · 1 passed 3 steps · 5 calls 29.6s
🟢 a chat survives trips through Settings 3 steps · 5 calls 29.6s
🟢 sidebarPerWorkspace.e2e.ts · 1 passed 4 steps · 1 call 7.3s
🟢 a new workspace starts with its right sidebar collapsed while another keeps it open 4 steps · 1 call 7.3s
🟢 smoke.e2e.ts · 1 passed 2 steps · 1 call 3.7s
🟢 the agent opens the playground workspace 2 steps · 1 call 3.7s
🟢 streamErrors.e2e.ts · 1 passed 1 step · 1 call 10.2s
🟢 stream errors show in the chat, and the chat recovers 1 step · 1 call 10.2s
🟢 todoNudge.e2e.ts · 1 passed 2 steps · 4 calls 24.1s
🟢 the agent finishes open TODO items after the turn-end nudge 2 steps · 4 calls 24.1s
🟢 touchAlignment.e2e.ts · 6 passed 6 steps · 6 calls 27.2s
🟢 the Settings close button is level with the title on a touch screen 390px wide 1 step · 1 call 3.7s
🟢 the Settings close button is level with the title on a touch screen 768px wide 1 step · 1 call 7.6s
🟢 Backup settings checkboxes are small and level with their labels on a touch phone 1 step · 1 call 7.0s
🟢 the heartbeat checkbox is small and level with its label on a touch phone 1 step · 1 call 3.3s
🟢 a reply's model and time stay on one line on a touch phone 1 step · 1 call 3.0s
🟢 the workspace actions menu stays on the title row on a touch phone 1 step · 1 call 2.6s

e2e 0.20.0 · 3m 2s · web · run artifacts

🟢 e2e Electron stories (Haiku): 3 passed

3 agent steps · 3 model calls · 8.0k tokens (21% cached)
Spend: $0.02 of the $1.00 cap (proxy ledger)

All 3 tests in 3 files
Test Agent Time
🟢 electron/deepLink.e2e.ts · 1 passed 1 step · 1 call 5.2s
🟢 a deep link of a second launch starts a chat in the running app 1 step · 1 call 5.2s
🟢 electron/menuBar.e2e.ts · 1 passed 1 step · 1 call 8.9s
🟢 the workspace menu bar is the desktop title bar 1 step · 1 call 8.9s
🟢 electron/smoke.e2e.ts · 1 passed 1 step · 1 call 5.4s
🟢 Xum Electron opens the playground workspace 1 step · 1 call 5.4s

e2e 0.20.0 · 21.5s · electron · run artifacts

🟢 e2e agent repros (Haiku): no tests selected

Spend: $0.00 of the $1.00 cap (proxy ledger)

e2e 0.20.0 · 5.3s · 2 targets (web, phone) · run artifacts

@ThomasK33
ThomasK33 added this pull request to the merge queue Oct 24, 2026
Merged via the queue into main with commit 56db5a4 Oct 24, 2026
33 of 34 checks passed
@ThomasK33
ThomasK33 deleted the phase5/b-turn-session-files branch October 24, 2026 20:33
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