Repository navigation
test: check structured-chat code for Electron imports even before the runtime loads it - #24988
Conversation
…lectron-free-ratchet
Cover src/main/{native-chat,claude,codex}, src/shared and every structured-*
or agent-session-* file under src/main/runtime, so new files are checked by
default. A lane that exists today now fails loudly if it goes missing; only
the not-yet-landed acp/ and provider-process/ may be absent.
Move the test-only file rule into one classifier shared with the
localization audit, so -test-<thing> helpers and test doubles no longer
enter the production gate.
…ent lanes Export main() so the real-tree tests exercise the entry list CI uses, check every required lane for the missing-directory error, and fail once acp/ or provider-process/ exists while still allowed to be absent.
Review summary (head
|
…lectron-free-ratchet
|
This run was cancelled 🛑 The workflow was cancelled before completion. Please check the link below for details. |
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (6)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe change adds shared helpers that classify test-only source paths and uses them in the localization coverage audit. The Electron import ratchet now checks runtime entry points and configured structured-chat lanes, including files not yet loaded by the runtime. The ratchet supports injected esbuild plugins, returns status codes from Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to No actionable merge-blocking risk is identified in these audit changes; merge after normal checks. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 5 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |

ELI5
Structured chat (Orca's native chat with Claude, Codex, and the agents coming next) has to run in orcad, Orca's headless runtime. That's a plain Node process with no Electron. Orca already has a build-time check that fails CI when any file the runtime loads imports Electron. It only looked at files reachable from the runtime's three entry files, though. Structured-chat code the runtime doesn't load yet, or that's only reached from the desktop app, could take on an Electron dependency without anything noticing. The problem would only show up later, when someone tried to run that code headless.
No user-visible change. This PR widens that existing check to whole structured-chat directories, so new files there are checked from the day they're added.
What Changed
config/scripts/check-runtime-electron-ratchet.mjs) still bundles the runtime with esbuild and lists every module that importselectron. Besides the three runtime entry files, it now starts from every non-test source file in:src/main/native-chat/,src/main/claude/,src/main/codex/andsrc/shared/, as whole directories at any depth;src/main/runtime/, only files namedstructured-*oragent-session-*, at any depth. That directory still holds desktop-only code (browser commands, the desktop relay), so the whole directory can't be checked yet;src/main/acp/andsrc/main/provider-process/, which don't exist on main yet (see Review).config/scripts/test-only-source-path.mjs). It covers specs (*.test.*,*.spec.*), helpers beside a spec (*-test-<anything>), fixtures and test doubles (*-fixture(s),*-mock(s),*-fake(s),*-stub(s),*-double(s)), and test directories (__tests__/,__fixtures__/,test-support/,orca-runtime-tests/, and so on).*-self-test*files and names that only end in-teststay in, because they ship. The localization audit (audit-localization-coverage.mjs) had its own narrower copy of this rule and now uses the shared one. It now skips 20 more renderer files, all test helpers with no user-visible strings, and its result is unchanged: 13 allowlisted candidates, as before.pnpm lint.Why
What's newly covered. On current main, the lanes add 2,375 entry files. 1,830 of them were already reached from the three runtime entries, so they were checked before. The other 545 are newly checked: 499 in
src/shared, 33 insrc/main/codex, 12 insrc/main/native-chatand 1 insrc/main/claude. Some of those only declare types, so they contain no code. The native-chat ones include the transcript readers that only the desktop IPC handler (the bridge between the window and the main process) reaches today. No newly checked file imports Electron.Policy note. This widens the rule from "code the headless runtime loads" to "structured-chat and shared code, wherever it runs today". For example, Codex session code that only the desktop process uses can no longer import Electron directly. That keeps such code movable to the runtime without a rewrite.
Why this approach.
codex-provider-timeline-identity.tsandruntime/rpc/methods/structured-agent-session-agents.ts. Whole directories cover new files by default, and the missing-directory error keeps the list honest.Linked Issue
N/A — internal foundation work to keep structured chat runnable without Electron; no separate issue was opened.
Visual Proof
N/A — build-time check only; no visual or interaction change.
Testing
What I verified / didn't
On macOS, at head
0c968d4b68c:Local setup caveat. My local dependency install predates main's new
stream-json/stream-chainpackages. Because of that,node config/scripts/check-runtime-electron-ratchet.mjsand the two tests that bundle the real source tree can't resolve them here. Main's own three runtime entries fail the same way locally. CI installs fresh dependencies. To cover those checks, I ran the same calls with only those two packages marked external:vitest,@vitest/*,chaiorrolldown-vitefile reaches the bundle any more (before this change, test helpers pulled them in);Tests.
check-runtime-electron-ratchet.test.mjsat this head: 14 passed. The 2 failures are the real-tree tests hitting the dependency caveat above.test-only-source-path.test.mjsandaudit-localization-coverage.test.mjsalso passed.New tests. They cover:
structured-*/agent-session-*files undersrc/main/runtime;acp/andprovider-process/;src/main/acp/orsrc/main/provider-process/exists while still allowed to be absent.The two real-tree tests call the command-line check itself (
main(), exported for this), which is whatpnpm lintand CI run:import 'electron'tosrc/main/native-chat/transcript-read-cache.tsin memory only, never on disk, and expects the check to fail and name that file (the runtime entries alone don't reach it);Mutation check. I broke the script by hand, one change at a time, then restored it from the commit:
acp,provider-processorsrc/shared; allowcodexto be missing; check all ofsrc/main/runtime; drop the test-file rule; drop the test-directory rule;main()check only the runtime entries; drop the directories from the default list; allow each existing directory in turn to be missing (5 variants); createsrc/main/acp/while it's still allowed to be absent.Every variant turned at least one test red. The
main()and default-list variants are caught by the in-memory injection test. Because that test can't run locally as is, I saw it go red through the samemain()call plus the dependency workaround.Lint and formatting.
oxfmtandoxlinton the changed files andgit diff --checkare clean. The lockfile is unchanged fromorigin/main.CI.
b42050bf4e6, static analysis and typecheck passed. That step runs this check with fresh dependencies. Its unit shards were cancelled by the next push.0c968d4b68c, check the run on this head.qoder-history-search-downgradetest fails on unrelated PRs too. If it fails here, it isn't from this change.Known limit: test files are recognised by name. A future shipped file in these directories whose name contains
-test-(other thanself-test), or ends in-fixture,-mock,-fake,-stubor-double, would be wrongly treated as test code. It would then not be an entry point of its own; it's still checked if other checked code imports it. Today no shipped file in these directories matches. Revisit if a product feature with "test" in its name (an A/B test, a connection test) lands here.I didn't launch Orca, Electron, orcad or a real agent. I didn't run Windows or Linux, and I didn't run a typecheck locally: only
.mjsfiles changed, and CI's typecheck is the authority. Passing checks show today's code is clean and the scope is wired in; they don't prove the scope is complete for code that later lands outside these directories.AI Disclosure
Review
Differences from the common pattern
The common pattern keeps Electron out of headless code by package boundaries: only the desktop app's package declares
electron, so other code can't resolve it at all.src/main/runtime/is filtered by name (structured-*,agent-session-*) instead of being checked whole, because it still holds desktop-only files that import Electron. Those runtime files that the three runtime entries load are already checked through them.src/main/acp/andsrc/main/provider-process/may be absent. This lasts until the ACP adapter and provider-process PRs in this stack land. A test fails as soon as either directory exists while still allowed to be absent, so the PR that creates it has to remove the flag, and the directory then fails loudly like the others.Possible follow-up (not built here)
The scope that can't drift is the inverse: check every production file under
src/mainandsrc/sharedexcept a short list of desktop-shell directories, with a list of today's Electron users that may only shrink. That's an app-wide policy beyond structured chat, so it isn't part of this PR.Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Notes
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)