Skip to content

fix: isolate PawWork runtime storage#126

Merged
Astro-Han merged 7 commits into
devfrom
codex/fix-runtime-namespace
Apr 22, 2026
Merged

fix: isolate PawWork runtime storage#126
Astro-Han merged 7 commits into
devfrom
codex/fix-runtime-namespace

Conversation

@Astro-Han

@Astro-Han Astro-Han commented Apr 22, 2026

Copy link
Copy Markdown
Owner

Summary

  • Added a PawWork runtime namespace gate so desktop-owned config, data, cache, state, database, plan files, and app storage keys are generated under PawWork names.
  • Kept OpenCode Zen and OpenCode Go provider compatibility intact, including provider IDs and provider behavior.
  • Documented the desktop startup change: the shell now waits on sidecar health, while database initialization remains owned by the embedded runtime instead of the legacy sqlite migration overlay.
  • Made existing project .opencode config readable for compatibility in PawWork runtime, but skipped dependency installation there so PawWork does not generate package files under .opencode.

Why

Closes #111. PawWork embeds the OpenCode engine, but users should not need OpenCode installed and PawWork should not create OpenCode-named local files or persisted records on their machine.

Related Issue

Closes #111

How To Verify

bun --cwd packages/opencode test test/global/runtime-namespace.test.ts test/storage/db.test.ts test/index-runtime-namespace.test.ts test/config/pawwork-global-config.test.ts test/config/config.test.ts test/session/instruction.test.ts test/session/session.test.ts test/agent/agent.test.ts test/provider/provider.test.ts
bun test --preload ./happydom.ts src/utils/persist.test.ts src/theme-preload.test.ts src/hooks/use-providers.test.ts
bun --cwd packages/desktop-electron test src/main/server.test.ts src/main/index-sidecar-source.test.ts scripts/ci-smoke.test.ts
bun --cwd packages/shared test test/global.test.ts
bun --cwd packages/opencode typecheck
bun --cwd packages/app typecheck
bun --cwd packages/desktop-electron typecheck
bun --cwd packages/shared typecheck

Also completed repeated fresh-eyes code review loops. The last review found no actionable P0, P1, P2, or P3 issues within scope.

Screenshots or Recordings

Not applicable. This PR changes local runtime namespace, storage keys, and tests, with no intended visible UI change.

Checklist

  • I linked the related issue, or stated why there is no issue
  • This PR has type, scope, and priority labels, or I requested maintainer labeling
  • I listed the relevant verification steps, including tests when behavior changed
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings
  • I considered macOS and Windows impact for desktop, packaging, updater, signing, paths, shell, or permissions changes
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, or generated/local file changes when relevant
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for PawWork project directory naming alongside existing conventions
    • Enhanced configuration system with improved file discovery and migration support
  • Improvements

    • Improved settings and storage organization with updated namespacing
    • Enhanced desktop application with better system directory integration
    • Refined runtime namespace handling for consistent cross-platform behavior
  • Configuration

    • Settings are now automatically migrated to updated storage locations
    • Project configurations support multiple file format options

@Astro-Han Astro-Han added bug Something isn't working P1 High priority platform Electron shell, OS integration, packaging, updater, signing, paths, and permissions labels Apr 22, 2026
@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@Astro-Han has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 23 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 3 minutes and 23 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5257830b-2508-45b8-8342-ee06a2af60cd

📥 Commits

Reviewing files that changed from the base of the PR and between 7ffd855 and 7092442.

📒 Files selected for processing (18)
  • packages/app/e2e/settings/settings.spec.ts
  • packages/app/src/app.tsx
  • packages/desktop-electron/scripts/ci-smoke.test.ts
  • packages/desktop-electron/src/main/server.test.ts
  • packages/opencode/src/config/config.ts
  • packages/opencode/src/config/paths.ts
  • packages/opencode/src/flag/flag.ts
  • packages/opencode/src/session/instruction.ts
  • packages/opencode/test/config/config.test.ts
  • packages/opencode/test/config/pawwork-global-config.test.ts
  • packages/opencode/test/index-runtime-namespace.test.ts
  • packages/opencode/test/provider/provider.test.ts
  • packages/opencode/test/storage/db.test.ts
  • packages/shared/src/runtime.ts
  • packages/shared/test/global.test.ts
  • packages/ui/src/theme/context.tsx
  • packages/ui/src/theme/index.ts
  • packages/ui/src/theme/loader.ts
📝 Walkthrough

Walkthrough

This PR migrates the application namespace from "opencode" to "pawwork" across storage keys, configuration identifiers, database filenames, and environment variables. It introduces a Runtime abstraction based on the PAWWORK_RUNTIME_NAMESPACE environment variable, enabling conditional behavior that supports both OpenCode and PawWork runtime modes.

Changes

Cohort / File(s) Summary
Web App Storage Migrations
packages/app/src/utils/persist.ts, packages/app/src/utils/persist.test.ts, packages/app/src/context/language.tsx, packages/app/src/context/terminal.tsx, packages/app/src/entry.tsx
Updated localStorage and persist-layer key constants: opencode.* prefixes changed to pawwork.*; added legacy eviction support for LEGACY_LOCAL_PREFIX = "opencode."; introduced workspaceStorage() naming changes.
Web App Theme/Public Assets
packages/app/public/oc-theme-preload.js, packages/app/src/theme-preload.test.ts, packages/ui/src/theme/context.tsx, packages/ui/src/theme/loader.ts
Theme storage keys renamed from opencode-theme-id, opencode-color-scheme, etc. to pawwork-* equivalents; theme style element ID changed from "opencode-theme" to "pawwork-theme".
E2E Test Storage Updates
packages/app/e2e/app/server-default.spec.ts, packages/app/e2e/commands/panels.spec.ts, packages/app/e2e/fixtures.ts, packages/app/e2e/settings/settings.spec.ts, packages/app/e2e/sidebar/*.spec.ts, packages/app/e2e/utils.ts
Updated all e2e fixture keys and init-scripts to use pawwork.* localStorage namespaces instead of opencode.*; workspace persistence keys also migrated.
Desktop Electron Main Process
packages/desktop-electron/src/main/runtime-namespace.ts, packages/desktop-electron/src/main/constants.ts, packages/desktop-electron/src/main/index.ts, packages/desktop-electron/src/main/server.ts, packages/desktop-electron/src/main/server.test.ts, packages/desktop-electron/src/main/store.ts
Added PAWWORK_RUNTIME export with client/serverUsername/settingsStore/databaseName; buildSmokeEnv() now sets XDG cache/config/state dirs; server env setup via buildServerEnv() uses PAWWORK_RUNTIME values; removed SQLite migration gating and sqliteFileExists() logic; added test helper exports.
Desktop Electron Renderer
packages/desktop-electron/src/renderer/i18n/index.ts, packages/desktop-electron/src/renderer/index.tsx
Updated i18n initialization to read language from pawwork.global.dat instead of opencode.global.dat.
Smoke Test Assertions
packages/desktop-electron/scripts/ci-smoke.ts, packages/desktop-electron/scripts/ci-smoke.test.ts
Added XDG directory env var setup (XDG_CACHE_HOME, XDG_CONFIG_HOME, XDG_STATE_HOME) in smoke test builder and corresponding test assertions.
Shared Runtime Abstraction
packages/shared/src/runtime.ts, packages/shared/src/global.ts, packages/shared/test/global.test.ts
Added Runtime.isPawWork() and Runtime.appName() functions; updated Global.layer to derive app directory name dynamically via Runtime.appName() instead of hardcoded "opencode".
OpenCode Config System
packages/opencode/src/config/config.ts, packages/opencode/src/config/managed.ts, packages/opencode/src/config/paths.ts, packages/opencode/src/global/index.ts, packages/opencode/src/storage/db.ts
Introduced runtime-aware config file selection (pawwork.json/.jsonc for PawWork vs config.json/opencode.json for OpenCode); globalConfigFiles() switches based on Runtime.isPawWork(); database paths use Runtime.appName() for dynamic filenames; managedPlistDomain() switches domain based on runtime; PAWWORK_CONFIG_DIR env var support alongside OPENCODE_CONFIG_DIR.
OpenCode Agent/Session/Instruction
packages/opencode/src/agent/agent.ts, packages/opencode/src/session/session.ts, packages/opencode/src/session/instruction.ts, packages/opencode/src/index.ts
Updated plan directory selection (${projectPlansDir}/plans/*.md uses .pawwork or .opencode based on Runtime.isPawWork()); instruction system uses runtime-selected configDir(); database marker path switched from hardcoded to Database.getChannelPath(); removed Global import from index.
OpenCode Config Tests
packages/opencode/test/config/config.test.ts, packages/opencode/test/config/pawwork-global-config.test.ts
Updated expected config output filename from config.json to opencode.json in existing test; added comprehensive new test suite validating OpenCode/PawWork config discovery, isolation, and runtime-mode path computation.
OpenCode Runtime/Database Tests
packages/opencode/test/global/runtime-namespace.test.ts, packages/opencode/test/index-runtime-namespace.test.ts, packages/opencode/test/storage/db.test.ts
Added new tests validating Global path resolution and database path naming under PawWork runtime mode via subprocess spawning with PAWWORK_RUNTIME_NAMESPACE env var.
OpenCode Agent/Provider/Session/Instruction Tests
packages/opencode/test/agent/agent.test.ts, packages/opencode/test/provider/provider.test.ts, packages/opencode/test/session/session.test.ts, packages/opencode/test/session/instruction.test.ts
Added tests covering plan directory path selection (.pawwork vs .opencode), system instruction paths under PawWork runtime, provider name assertions, and config dir behavior with PAWWORK_RUNTIME_NAMESPACE set.
Web App Hook/Provider Tests
packages/app/src/hooks/use-providers.test.ts
Added test verifying popularProviders array includes both "opencode" and "opencode-go".

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

The PR spans 50+ files across multiple packages with heterogeneous changes: repetitive storage key migrations (low cognitive load per item but high volume), a new Runtime abstraction requiring careful integration validation, a substantially reworked config system with multiple conditional branches, and numerous new test files validating PawWork runtime behavior. While many individual changes follow predictable patterns, the scope, systemic integration, and config system complexity warrant careful multi-pass review.

Possibly related issues

  • [Bug] Isolate PawWork runtime storage from OpenCode namespace #111: This PR directly implements the PawWork namespace isolation and storage key migration described in the issue, renaming storage prefixes, introducing PAWWORK_RUNTIME identifiers, and updating database/settings store names to establish clear separation between OpenCode and PawWork runtimes.

Possibly related PRs

Poem

🐰 A namespace most pawsome, now pawwork so grand,
Once opencode echoes fade across the land,
Storage keys hop to new homes, configs align,
Runtime abstractions—two paths intertwine,
Let databases flourish in their brand-new name!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: isolating PawWork runtime storage by updating config, data, cache, state, database, and storage keys.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The pull request description is comprehensive and well-structured, covering summary, motivation, related issue, verification steps, and all checklist items.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-runtime-namespace

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a namespacing system to support both OpenCode and PawWork runtimes by updating storage keys, configuration filenames, and directory paths based on the PAWWORK_RUNTIME_NAMESPACE environment variable. Feedback focuses on ensuring backward compatibility for legacy configuration files, updating storage eviction logic to prevent quota issues with the new prefix, and refining the Electron initialization process to correctly show the loading UI during database migrations. Additionally, suggestions were made to improve configuration discovery for JSONC variants and to use preferred filenames when migrating from legacy formats.

Comment thread packages/opencode/src/config/config.ts Outdated
Comment thread packages/app/src/utils/persist.ts
Comment thread packages/desktop-electron/src/main/index.ts
Comment thread packages/desktop-electron/src/main/index.ts
Comment thread packages/desktop-electron/src/main/index.ts
Comment thread packages/opencode/src/config/config.ts Outdated
Comment thread packages/opencode/src/config/config.ts Outdated
Comment thread packages/opencode/src/config/config.ts Outdated
@Astro-Han Astro-Han force-pushed the codex/fix-runtime-namespace branch from 4190608 to b7392ab Compare April 22, 2026 07:38
Comment thread packages/opencode/src/config/config.ts
Comment thread packages/opencode/src/config/config.ts
Comment thread packages/opencode/src/config/config.ts
Comment thread packages/app/src/utils/persist.ts
Comment thread packages/desktop-electron/src/main/server.ts
Comment thread packages/opencode/src/session/instruction.ts
Comment thread packages/opencode/test/config/pawwork-global-config.test.ts
Comment thread packages/opencode/test/config/pawwork-global-config.test.ts
@Astro-Han

Copy link
Copy Markdown
Owner Author

Review Summary

Posted 8 inline comments with nitpick-level feedback. Key themes:

Code Quality

  1. Duplicated isPawWorkRuntime() helper - defined in 7 files, should be centralized
  2. Naming collision - globalFiles() in instruction.ts vs globalConfigFiles() in config.ts

Consistency Issues

  1. Asymmetric config file precedence - PawWork and OpenCode modes search different file lists
  2. Missing eviction coverage - EVICT_PREFIXES covers workspace keys but not global/settings keys
  3. Reverse runtime handling - shouldGenerateInDirectory only checks .opencode in PawWork mode

Test Quality

  1. Case-insensitive assertions - toLowerCase() substring checks could miss edge cases
  2. Test fixture clarity - config.json test might pass accidentally

API Design

  1. Process env mutation - prepareServerEnv mutates global state, needs clear contract

These are all P2/nitpick items - no blocking issues. The core runtime namespace isolation logic appears sound. Addressing the helper duplication and symmetry concerns would improve maintainability.

@Astro-Han Astro-Han force-pushed the codex/fix-runtime-namespace branch from b7392ab to 7ffd855 Compare April 22, 2026 08:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/desktop-electron/src/main/index.ts (1)

246-252: 🧹 Nitpick | 🔵 Trivial

Dead code path: needsMigration is always false.

Since needsMigration is hardcoded to false on line 206, this conditional block can never execute. Consider removing it to reduce maintenance burden.

🧹 Proposed cleanup
-  if (needsMigration) {
-    const show = await Promise.race([loadingTask.then(() => false), delay(1_000).then(() => true)])
-    if (show) {
-      overlay = createLoadingWindow(globals)
-      await delay(1_000)
-    }
-  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/desktop-electron/src/main/index.ts` around lines 246 - 252, The
if-block guarded by the always-false needsMigration (the block using
loadingTask, delay, createLoadingWindow and overlay) is dead code; remove that
conditional and its inner code (including creation/awaits of
loadingTask/delay/show and the overlay assignment) and then delete or refactor
any now-unused symbols (needsMigration, overlay, or related imports/usages) so
there are no dangling references to createLoadingWindow, loadingTask or delay in
this module.
packages/app/e2e/commands/panels.spec.ts (1)

179-207: ⚠️ Potential issue | 🟡 Minor

Rename test constant to SCREAMING_SNAKE_CASE.

const key should follow the test constant naming rule to avoid style drift.

💡 Suggested rename
-    const key = "pawwork.global.dat:layout"
-    const raw = localStorage.getItem(key)
+    const LAYOUT_STORAGE_KEY = "pawwork.global.dat:layout"
+    const raw = localStorage.getItem(LAYOUT_STORAGE_KEY)
@@
-      key,
+      LAYOUT_STORAGE_KEY,

As per coding guidelines "Use SCREAMING_SNAKE_CASE for constants in tests".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/app/e2e/commands/panels.spec.ts` around lines 179 - 207, Rename the
test constant "key" to a SCREAMING_SNAKE_CASE name (e.g., STORAGE_KEY or
LAYOUT_KEY) and update all its usages in this snippet (the declaration currently
"const key" and the calls to localStorage.getItem(key) and
localStorage.setItem(key, ...)) to use the new constant; ensure you only change
the identifier and not the surrounding logic in the parsing/assignment blocks
(variables referenced: key, raw, parsed, review, sessionView, current).
♻️ Duplicate comments (1)
packages/desktop-electron/src/main/server.ts (1)

79-82: ⚠️ Potential issue | 🟠 Major

prepareServerEnv still mutates global process.env in a test-reachable path.

This is the same isolation risk raised earlier: global env mutation can leak across concurrently executing tests/callers. Prefer a non-mutating contract where possible, or make mutation semantics explicit and tightly scoped to bootstrap-only usage.

Also applies to: 84-84

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/desktop-electron/src/main/server.ts` around lines 79 - 82,
prepareServerEnv currently mutates the global process.env (via
Object.assign(process.env, buildServerEnv(password))), which can leak
environment across tests; change its contract to avoid implicit global mutation
by having prepareServerEnv return the env object (e.g., return
buildServerEnv(password)) or accept an explicit targetEnv parameter to apply to,
and update callers of prepareServerEnv (the bootstrap/bootstrap-only usage) to
either call Object.assign(process.env, returnedEnv) in a tightly scoped
bootstrap path or pass an explicit env object when needed; keep the mutation
explicit and documented so only the bootstrap entrypoint mutates process.env and
tests can use the returned env without affecting globals.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/app/e2e/settings/settings.spec.ts`:
- Line 88: Update the test title string in the test(...) declaration that
currently reads "unknown theme ids migrate to pawwork and clear cached CSS" to
use lowercase for "css" — e.g., "unknown theme ids migrate to pawwork and clear
cached css"; locate the test call (the test function around the identifier used
in settings.spec.ts) and replace only the title text, ensuring any references to
the exact test name (if used elsewhere) are updated to match.

In `@packages/desktop-electron/src/main/index-sidecar-source.test.ts`:
- Around line 3-11: The test currently uses fragile string matching against the
raw source; change it to parse the source into an AST (e.g., via `@babel/parser`
or acorn) and assert on AST nodes: parse the contents read into the variable
source, find the exported/object node that contains a Property with key
"username" whose value is a MemberExpression referencing
PAWWORK_RUNTIME.serverUsername, find a VariableDeclarator/Identifier named
needsMigration with an init BooleanLiteral false, assert there is no Identifier
or CallExpression name "sqliteFileExists", and assert there is no StringLiteral
with value "opencode"; update the test body to walk/query the AST for these
patterns instead of using expect(source).toContain/toNotContain so formatting
changes won’t break the assertions.

In `@packages/desktop-electron/src/main/server.test.ts`:
- Line 62: Remove the brittle substring assertion
`expect(Object.values(roots).every((value) =>
!value.toLowerCase().includes("opencode"))).toBeTrue()` and instead assert the
exact shape/values of the `roots` object; update the test around the `roots`
variable to use strict equality checks (e.g., compare `roots` or
`Object.values(roots)` to the expected array/object) so the test relies only on
explicit expected paths already asserted elsewhere in this test.

In `@packages/opencode/src/config/config.ts`:
- Around line 52-53: PROJECT_CONFIG_NAMES incorrectly includes "pawwork" causing
OpenCode to load PawWork configs; remove "pawwork" from the PROJECT_CONFIG_NAMES
constant so PROJECT_CONFIG_FILES no longer contains pawwork.json/pawwork.jsonc,
and update any related directory-scan logic that treats ".pawwork" as a config
directory (references: PROJECT_CONFIG_NAMES, PROJECT_CONFIG_FILES and the config
scanning/merging code paths noted around the other occurrences) to prevent
merging .pawwork/* into OpenCode project config.
- Around line 52-59: PROJECT_CONFIG_FILES currently includes pawwork.json* and
OPENCODE_GLOBAL_CONFIG_FILES is set to PROJECT_CONFIG_FILES, which lets OpenCode
treat pawwork.json* as its global config; change OPENCODE_GLOBAL_CONFIG_FILES so
it excludes pawwork.json and pawwork.jsonc (for example, build it from
PROJECT_CONFIG_NAMES without "pawwork" or filter PROJECT_CONFIG_FILES to remove
files that start with "pawwork") so that globalConfigFiles(), loadGlobal(),
globalConfigFile(), and updateGlobal() will never consider pawwork.json* as an
OpenCode global config.

In `@packages/opencode/test/config/pawwork-global-config.test.ts`:
- Around line 17-47: Replace the bespoke Effect runner helpers (load, save,
saveGlobal, clear, ready, listConfigDirs) and manual layer composition (layer,
infra, emptyAccount, emptyAuth, AppFileSystem.defaultLayer usage) with the repo
test helpers: refactor tests to call testEffect(...) from test/lib/effect.ts and
use provideInstance(...) or provideTmpdirInstance(...) to supply the Config
layer and filesystem mocks instead of Effect.runPromise +
.pipe(Effect.provide(...)). Locate usages of the functions
load/save/saveGlobal/clear/ready/listConfigDirs and the Layer construction
(Layer.provide/Layer.provideMerge etc.) in this file and convert each test to
return a testEffect that provides the required instance via
provideInstance/provideTmpdirInstance, invoking Config.Service.use(...) inside
the Effect passed to testEffect rather than using the custom runPromise
wrappers.
- Around line 101-123: The test "PawWork runtime mode computes Global config
under PawWork before module load" currently hardcodes /tmp paths in the spawned
subprocess script and assertions; replace those with a fixture-managed temporary
directory by calling tmpdir() from fixture/fixture.ts and creating the
runtime/project paths under that temp dir, use the `await using` pattern to
ensure automatic cleanup, and update the script string and the subprocess
env/arguments so ConfigPaths.directories("/tmp/project", "/tmp/project") becomes
ConfigPaths.directories("<tmpdir>/project", "<tmpdir>/project") (use the tmpdir
value injected into the script), and similarly change the expected assertion to
reference the fixture temp path instead of
"/tmp/pawwork-config-root-test/pawwork"; apply the same replacement for the
other occurrences noted (lines ~330-382).

In `@packages/opencode/test/index-runtime-namespace.test.ts`:
- Around line 7-8: Replace the brittle exact-string assertions in the test that
check for "Database.getChannelPath()" and the literal
'path.join(Global.Path.data, "opencode.db")' with regex-based assertions so
formatting/quote changes won’t break the test; update the two expect(...) calls
in index-runtime-namespace.test.ts to use
expect(source).toMatch(/Database\.getChannelPath\(\)/) (or a looser pattern
matching the call) and
expect(source).not.toMatch(/path\.join\(\s*Global\.Path\.data\s*,\s*["'`]opencode\.db["'`]\s*\)/)
to verify structure rather than exact string formatting.

In `@packages/opencode/test/provider/provider.test.ts`:
- Around line 58-79: Replace the raw Jest async test with the Effect-based test
harness: import and use testEffect(...) (from test/lib/effect.ts) and wrap the
body in Effect.gen(...) so the test uses the Effect runtime; move the
tmpdir/Instance.provide logic inside Effect.gen and use Effect-friendly helpers
for env manipulation (replace direct process.env mutation with the provided
set/restore Effects or runEffect-wrapped set calls) while keeping the same
assertions against list() and ProviderID.make("opencode"/"opencode-go") —
specifically, change the top-level test(...) to testEffect(..., () =>
Effect.gen(function*() { ... })) and put the tmpdir, Instance.provide,
set("OPENCODE_API_KEY", ...), and the expects inside that generator so the test
executes under the Effect test harness.

In `@packages/opencode/test/storage/db.test.ts`:
- Around line 20-23: The test's expected channel list is missing "prod" which
makes the assertion diverge from Database.getChannelPath() behavior; update the
test so the condition includes "prod" alongside "latest" and "beta" when
computing expected (the code referencing Installation.CHANNEL and
Database.getChannelPath() should now treat "latest", "beta", and "prod" as the
short-path cases) so the expected path calculation matches runtime logic that
maps those channels to pawwork.db and others to pawwork-<sanitized-channel>.db.

In `@packages/shared/test/global.test.ts`:
- Around line 7-10: The tests hardcode POSIX /tmp paths which fail on Windows;
change the setup in packages/shared/test/global.test.ts to build the temp root
using the platform temp directory (e.g., os.tmpdir()) and construct XDG_* paths
with path.join(os.tmpdir(), 'pawwork-shared-runtime-test',
'share'|'cache'|'config'|'state') instead of "/tmp/...", and update the
corresponding assertions (including the similar assertions referenced at lines
32-41) to compare against those constructed paths so the tests are
platform-independent; locate and update the environment assignments and
assertions in the global.test.ts file (the XDG_* env setup and its later
expectations).
- Around line 11-13: The generated test helper currently only sets
process.env.PAWWORK_RUNTIME_NAMESPACE when namespace is provided, leaving any
existing value intact when namespace is undefined; update the template in
packages/shared/test/global.test.ts so that when ${JSON.stringify(namespace)} is
undefined you explicitly clear the environment variable (e.g., delete
process.env.PAWWORK_RUNTIME_NAMESPACE or set it to undefined) instead of doing
nothing, ensuring tests like "defaults to OpenCode namespace outside PawWork
desktop" are order-independent; modify the conditional around
PAWWORK_RUNTIME_NAMESPACE in the snippet so it has an else branch that clears
the variable.

In `@packages/ui/src/theme/context.tsx`:
- Around line 11-16: STORAGE_KEYS was renamed which will reset existing users'
theme prefs; add a one-time migration run during initialization (e.g., in the
same onMount/init function that reads/writes theme state) that maps old keys
(e.g., "opencode-theme-id", "opencode-color-scheme", "opencode-theme-css-light",
"opencode-theme-css-dark") to the new STORAGE_KEYS entries, and for each key:
read the old value, if present and the new key is empty then write the value to
STORAGE_KEYS (use existing read/write helpers) and then drop the old key (use
drop) so users keep their preferences; implement this as a migrateOldKeys helper
and call it before any code that reads from STORAGE_KEYS or initializes theme
state.

---

Outside diff comments:
In `@packages/app/e2e/commands/panels.spec.ts`:
- Around line 179-207: Rename the test constant "key" to a SCREAMING_SNAKE_CASE
name (e.g., STORAGE_KEY or LAYOUT_KEY) and update all its usages in this snippet
(the declaration currently "const key" and the calls to
localStorage.getItem(key) and localStorage.setItem(key, ...)) to use the new
constant; ensure you only change the identifier and not the surrounding logic in
the parsing/assignment blocks (variables referenced: key, raw, parsed, review,
sessionView, current).

In `@packages/desktop-electron/src/main/index.ts`:
- Around line 246-252: The if-block guarded by the always-false needsMigration
(the block using loadingTask, delay, createLoadingWindow and overlay) is dead
code; remove that conditional and its inner code (including creation/awaits of
loadingTask/delay/show and the overlay assignment) and then delete or refactor
any now-unused symbols (needsMigration, overlay, or related imports/usages) so
there are no dangling references to createLoadingWindow, loadingTask or delay in
this module.

---

Duplicate comments:
In `@packages/desktop-electron/src/main/server.ts`:
- Around line 79-82: prepareServerEnv currently mutates the global process.env
(via Object.assign(process.env, buildServerEnv(password))), which can leak
environment across tests; change its contract to avoid implicit global mutation
by having prepareServerEnv return the env object (e.g., return
buildServerEnv(password)) or accept an explicit targetEnv parameter to apply to,
and update callers of prepareServerEnv (the bootstrap/bootstrap-only usage) to
either call Object.assign(process.env, returnedEnv) in a tightly scoped
bootstrap path or pass an explicit env object when needed; keep the mutation
explicit and documented so only the bootstrap entrypoint mutates process.env and
tests can use the returned env without affecting globals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bce1e9df-6150-4963-b653-3ed5acc6be07

📥 Commits

Reviewing files that changed from the base of the PR and between 34c080e and 7ffd855.

📒 Files selected for processing (50)
  • packages/app/e2e/app/server-default.spec.ts
  • packages/app/e2e/commands/panels.spec.ts
  • packages/app/e2e/fixtures.ts
  • packages/app/e2e/settings/settings.spec.ts
  • packages/app/e2e/sidebar/sidebar-session-search.spec.ts
  • packages/app/e2e/sidebar/sidebar.spec.ts
  • packages/app/e2e/utils.ts
  • packages/app/public/oc-theme-preload.js
  • packages/app/src/context/language.tsx
  • packages/app/src/context/terminal.tsx
  • packages/app/src/entry.tsx
  • packages/app/src/hooks/use-providers.test.ts
  • packages/app/src/pages/session/terminal-panel.tsx
  • packages/app/src/theme-preload.test.ts
  • packages/app/src/utils/persist.test.ts
  • packages/app/src/utils/persist.ts
  • packages/desktop-electron/scripts/ci-smoke.test.ts
  • packages/desktop-electron/scripts/ci-smoke.ts
  • packages/desktop-electron/src/main/constants.ts
  • packages/desktop-electron/src/main/index-sidecar-source.test.ts
  • packages/desktop-electron/src/main/index.ts
  • packages/desktop-electron/src/main/runtime-namespace.ts
  • packages/desktop-electron/src/main/server.test.ts
  • packages/desktop-electron/src/main/server.ts
  • packages/desktop-electron/src/main/store.ts
  • packages/desktop-electron/src/renderer/i18n/index.ts
  • packages/desktop-electron/src/renderer/index.tsx
  • packages/opencode/src/agent/agent.ts
  • packages/opencode/src/config/config.ts
  • packages/opencode/src/config/managed.ts
  • packages/opencode/src/config/paths.ts
  • packages/opencode/src/global/index.ts
  • packages/opencode/src/index.ts
  • packages/opencode/src/session/instruction.ts
  • packages/opencode/src/session/session.ts
  • packages/opencode/src/storage/db.ts
  • packages/opencode/test/agent/agent.test.ts
  • packages/opencode/test/config/config.test.ts
  • packages/opencode/test/config/pawwork-global-config.test.ts
  • packages/opencode/test/global/runtime-namespace.test.ts
  • packages/opencode/test/index-runtime-namespace.test.ts
  • packages/opencode/test/provider/provider.test.ts
  • packages/opencode/test/session/instruction.test.ts
  • packages/opencode/test/session/session.test.ts
  • packages/opencode/test/storage/db.test.ts
  • packages/shared/src/global.ts
  • packages/shared/src/runtime.ts
  • packages/shared/test/global.test.ts
  • packages/ui/src/theme/context.tsx
  • packages/ui/src/theme/loader.ts

Comment thread packages/app/e2e/settings/settings.spec.ts Outdated
Comment thread packages/desktop-electron/src/main/index-sidecar-source.test.ts
Comment thread packages/desktop-electron/src/main/server.test.ts Outdated
Comment thread packages/opencode/src/config/config.ts Outdated
Comment thread packages/opencode/src/config/config.ts Outdated
Comment thread packages/opencode/test/provider/provider.test.ts
Comment thread packages/opencode/test/storage/db.test.ts Outdated
Comment thread packages/shared/test/global.test.ts Outdated
Comment thread packages/shared/test/global.test.ts
Comment thread packages/ui/src/theme/context.tsx Outdated
@Astro-Han Astro-Han force-pushed the codex/fix-runtime-namespace branch from 59e9e7d to 3ba63a9 Compare April 22, 2026 08:48
@Astro-Han

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Astro-Han Astro-Han force-pushed the codex/fix-runtime-namespace branch from 3ba63a9 to f0a140e Compare April 22, 2026 08:55
@Astro-Han

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Astro-Han

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submitting pending review to clear it

Comment thread packages/opencode/test/provider/provider.test.ts
Comment thread packages/shared/test/global.test.ts
Comment thread packages/ui/src/theme/context.tsx Outdated

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See inline comments for issues found.

Comment thread packages/ui/src/theme/loader.ts Outdated
Comment thread packages/ui/src/theme/context.tsx Outdated
Comment thread packages/desktop-electron/src/main/index.ts
Comment thread packages/shared/src/runtime.ts
Comment thread packages/opencode/src/config/config.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working P1 High priority platform Electron shell, OS integration, packaging, updater, signing, paths, and permissions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Isolate PawWork runtime storage from OpenCode namespace

1 participant