Repository navigation
🤖 refactor: plugin discovery, journals and registry read through HostFiles and HostPaths - #7322
Conversation
…les and HostPaths
…very # Conflicts: # src/node/services/hostFiles/hostFiles.contract.testHarness.ts # src/node/services/hostFiles/hostFiles.ts
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
🟢 e2e stories (Haiku): 14 passed27 agent steps · 7 replayed from cache · 31 model calls · 218.1k tokens (70% cached) All 14 tests in 9 files
e2e 0.20.0 · 2m 54s · web · run artifacts 🟢 e2e Electron stories (Haiku): 3 passed3 agent steps · 3 model calls · 8.0k tokens (21% cached) All 3 tests in 3 files
e2e 0.20.0 · 18.7s · electron · run artifacts 🟢 e2e agent repros (Haiku): no tests selectedSpend: $0.00 of the $1.00 cap (proxy ledger) e2e 0.20.0 · 5.3s · 2 targets (web, phone) · run artifacts |
…through HostFiles, HostPaths and HostClock (coder#7371) ## Summary 5b PR 7 of phase 5 (Loop host I/O) of the agent-loop refactor. The instruction readers and the home-clutter reminder reach the host through the phase 5 and phase 3 services: - `instructionFiles.ts` and `homeClutterWatch.ts` read files through `HostFiles` (coder#7319). - `systemMessage.ts` and `tools.ts` take the user home and the Xum home from `HostPaths` (coder#7319). - `HomeClutterReminderSource` arms its scan timeout on the session's `HostClock` (phase 3). The five files import no `fs`, `fs/promises` or `os` any more, and `systemMessage.ts` no longer imports `getXumHome`. Behavior does not change: the Node layers read the same `fs/promises` and `os` namespaces and call `getXumHome` at each call, so the `os.homedir` spies of `systemMessage.test.ts` and `instructionsService.test.ts` still apply. None of the five files is in the `local/no-host-imports` file set, so the frozen pairs do not change. ## Order Plan order: stack 5b is PR 1 to PR 9, and this PR comes after 5b PR 6 (coder#7322, merged). Landing order: this PR lands ahead of 5b PRs 2 to 5, by rule 2 of plan note 1. Those PRs wait for phase 4 and phase 2 PRs that have not merged. This PR waits only for 5a PR 5 (coder#7319, merged) and phase 3 PR 1 (coder#7270, merged), and it uses no code of 5b PRs 2 to 5. So it opens on its own, with base main. No open phase 2 to 5 PR changes these five files. ## Implementation - `utils/main/instructionFiles.ts`: the local file reader calls `nodeHostFiles.promises.readFile`. - `runtime/homeClutterWatch.ts`: the default `readDir` calls `nodeHostFiles.promises.readdir`. - `services/systemMessage.ts`: the Claude-compat global dir comes from `nodeHostPaths.userHome()`. The global instruction set, the settings `config.json` path and its directory come from `nodeHostPaths.xumHome()`. - `agentNotifications/sources/HomeClutterReminderSource.ts`: the constructor takes an optional `clock` (absent: `nodeClock`, as for tool configs that tests build by hand). The scan timeout calls `clock.setTimer`, and the scan start times come from `clock.nowMs()`. - `common/utils/tools/tools.ts`: the reminder gets `nodeHostPaths.userHome()` and `config.clock`. The plan estimated about 320 lines for this PR. It adds 71 lines and removes 21, because no caller passes its own `HostFiles` or `HostPaths` yet (the same reason as in 5b PR 6). ## Validation - `HomeClutterReminderSource.test.ts`: a new case runs a poll on a stuck scan with the TestClock. The poll is still open at 249 ms of TestClock time and ends at 250 ms, with no real wait. With the timer pointed back at `nodeClock`, the case fails. - The plan's tests (`instructionFiles`, `systemMessage`, `instructionsService`, `homeClutterWatch`, `HomeClutterReminderSource`) plus `tools.test.ts`: 135 pass, 0 fail. - `make static-check`, `make lint-eslint`, `make dry-check`, `make crap-check`. - `make test` (host suite lock) on head c9af576: `bun test src` had 27679 pass, 7 skip and 1 fail. The fail is `renderer first load > the entry's static imports do not reach the tool definitions module`, which fails the same way on main 2e2a2b7 (I ran it there alone). `make test` stops at the first failing run, so I ran its other steps by hand: the shared scripts/storybook/vscode run (729 pass, 0 fail) and each of the 18 isolated files (0 fail). - The ui line on that head: 732 pass, 0 fail. - Loop-test tripwire, 3 runs against origin/main 2e2a2b7: 0 trips. - Round 2 (77a0664) merges main 2633118 (coder#7369, the fix for the renderer first load test). On it: `make static-check`, and the plan's tests plus `tools.test.ts` and `rendererFirstLoad.test.ts`: 138 pass, 0 fail. --- _Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `high` • Cost: `$112.49`_ <!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=high costs=112.49 -->
Summary
5b PR 6 of phase 5 (Loop host I/O) of the agent-loop refactor. Plugin discovery, its journals and its registry now read host files through
HostFilesand the user home throughHostPaths(#7319). The three files (agentPlugins/discovery.ts,journals.ts,registry.ts) import nonode:fs,node:fs/promisesornode:osany more. Behavior does not change: each call goes to the Node layers, which read thenode:fs/promisesandnode:osnamespaces at call time, so the spies of the existing tests still apply. The frozen pairs oflocal/no-host-importsstay at 44 in 26 files.Order
The plan order of stack 5b is PR 1 to PR 9. 5b PRs 2 to 5 wait for phase 4 and phase 2 PRs that have not merged. This PR waits only for 5a PR 5 (#7319, merged), and it uses no code of 5b PRs 2 to 5. So it lands now, with base main, as the bottom of the new stack 5b.
Implementation
hostFiles/hostFiles.ts:HostFiles.promisesalso givesopenandconstants.readPluginFileWithinRootCappedreads a plugin file through one handle opened withO_NONBLOCK, so a FIFO cannot hang it and the bytes come from the inode it checked. Both layers already have the two members (the Node layer is the namespace itself, the memory layer is the memfspromises).hostFiles.contract.testHarness.ts: one new case that both layers pass.openwithO_RDONLY | O_NONBLOCKreads through the handle, its bigintstatnames the inode oflstat, andopenof a missing file fails with ENOENT.discovery.ts:nodePluginFsandreadPluginFileWithinRootCappedusenodeHostFiles.promises, andcomputeAgentPluginContainerstakes~/.agents/pluginsfromnodeHostPaths.userHome().journals.ts,registry.ts:nodeHostFiles.promisesin place of thenode:fs/promisesimport.The plan estimated about 450 lines for this PR. It adds 64 lines and removes 28, because no caller passes its own HostFiles or HostPaths yet, so this PR adds no parameter for one. A whole discovery run on a memory host also needs
ensurePathContained(tools/skillFileUtils.ts) on HostFiles. That file belongs to 5a PR 6, and the services that would pass a memory host belong to 5b PR 8.Validation
local/no-host-imports, run on the three files: before,discovery.tshadfs/promises,fsandos, andjournals.tsandregistry.tshadfs/promises. After, the three files have no pair.bun test ./src/node/services/agentPlugins/: 826 pass, 0 fail.bun test ./src/node/services/hostFiles/: 30 pass (the new case on both layers).make static-check,make lint-eslint.make test(host suite lock): 27683 pass, 7 skip, 3 fail. The fails were timeouts under the suite's load, and each file passes alone:backup/gitRepo.test.ts(2 BackupRepoCache cases) passes 61 of 61, andbash_output.test.ts(a known flake) passes 14 of 14. Neither file imports the agentPlugins or hostFiles code.scripts/tests and the others of CI's line): 725 pass, 1 fail. The fail was a timeout inscripts/perf/desktopColdStart.test.tswhile another test process ran on the host. Alone it passes 2 of 2.Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high• Cost:$71.07