feat(instruction): finalize PawWork instruction fallback order and diagnostics#260
Conversation
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughIntroduces runtime-aware instruction discovery and diagnostics: exports Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant InstructionService as Instruction.Service
participant Config as Config
participant FS as FileSystem
participant HTTP as RemoteFetch
Client->>InstructionService: call sources()
InstructionService->>Config: read runtime mode, env vars, config.instructions
InstructionService->>FS: check project FILES (AGENTS.md, CLAUDE.md...) via projectFiles()
FS-->>InstructionService: project file exists / absent
InstructionService->>FS: check PawWork PAWWORK_CONFIG_DIR AGENTS.md and runtime global candidates
FS-->>InstructionService: pawwork/global file exists / absent
InstructionService->>FS: resolve local config.instructions entries (files, globs, expand ~/)
FS-->>InstructionService: resolved paths / resolution failures
InstructionService->>HTTP: fetch remote config.instructions URLs
HTTP-->>InstructionService: success (body/non-empty) / failure / empty
InstructionService-->>Client: return ordered InstructionSource[] with status (loaded/considered/ignored) and reasons
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Code Review
This pull request prevents the PawWork baseline from falling back to global Claude instructions and introduces a sources() method to track loaded and ignored instruction files. Feedback focuses on improving test isolation and cross-platform compatibility by replacing os.homedir() with an injectable home path and using OPENCODE_TEST_HOME in tests. Suggestions also include using path.resolve() for path consistency and refining the diagnostic logic for ignored sources.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/opencode/test/session/instruction.test.ts`:
- Around line 491-500: The test "sources() reports ~/.claude/CLAUDE.md as
ignored with reason when present in PawWork mode" short-circuits on a missing
real-home file which causes silent skips in CI; modify the test to not depend on
the real home by either creating a temporary HOME with a temp directory
containing .claude/CLAUDE.md (set process.env.HOME or equivalent for Bun) before
computing homeClaude, or stub/mock Bun.file(...).exists() to return true and
provide the file contents so the ignored-path diagnostic is exercised; locate
the variables/homeClaude, fallbackExists and the Bun.file usage in the test and
update setup/teardown to create and remove the temp file (or mock) so the test
runs deterministically in CI.
🪄 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: 2322c610-f3e5-499d-aeeb-9b178b3540a8
📒 Files selected for processing (2)
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
- GitHub Check: smoke-macos-arm64
- GitHub Check: unit-windows-opencode-session
- GitHub Check: unit-windows-opencode-server-tools
- GitHub Check: unit-windows-opencode-config-project
- GitHub Check: unit-windows-desktop
- GitHub Check: unit-windows-app
- GitHub Check: unit-opencode
- GitHub Check: unit-app
- GitHub Check: typecheck
- GitHub Check: unit-desktop
- GitHub Check: analyze-js-ts
- GitHub Check: e2e-artifacts
🧰 Additional context used
📓 Path-based instructions (2)
packages/opencode/**/*.ts
📄 CodeRabbit inference engine (packages/opencode/AGENTS.md)
packages/opencode/**/*.ts: UseEffect.gen(function* () { ... })for Effect composition
UseEffect.fn("Domain.method")for named/traced effects andEffect.fnUntracedfor internal helpers; these accept pipeable operators as extra arguments to avoid unnecessary outer.pipe()wrappers
UseEffect.callbackfor callback-based APIs
PreferDateTime.nowAsDateovernew Date(yield* Clock.currentTimeMillis)when you need aDatein Effect code
UseSchema.Classfor multi-field data in Effect schemas
Use branded schemas (Schema.brand) for single-value types in Effect
UseSchema.TaggedErrorClassfor typed errors in Effect schemas
UseSchema.Defectinstead ofunknownfor defect-like causes in Effect code
InEffect.gen/Effect.fn, preferyield* new MyError(...)overyield* Effect.fail(new MyError(...))for direct early-failure branches
UsemakeRuntimefromsrc/effect/run-service.tsfor all services; it returns{ runPromise, runFork, runCallback }backed by a sharedmemoMapthat deduplicates layers
UseInstanceStatefromsrc/effect/instance-state.tsfor per-directory or per-project state that needs per-instance cleanup; do work directly in theInstanceState.makeclosure whereScopedCachehandles run-once semantics
UseEffect.addFinalizerorEffect.acquireReleaseinside theInstanceState.makeclosure for cleanup (subscriptions, process teardown, etc.)
UseEffect.forkScopedinside theInstanceState.makeclosure for background stream consumers — the fiber is interrupted when the instance is disposed
PreferFileSystem.FileSysteminstead of rawfs/promisesfor effectful file I/O in Effect services
PreferChildProcessSpawner.ChildProcessSpawnerwithChildProcess.make(...)instead of custom process wrappers in Effect services
PreferHttpClient.HttpClientinstead of rawfetchin Effect services
PreferPath.Path,Config,Clock, andDateTimeservices when those concerns are already inside Effect code
For backgroun...
Files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
packages/opencode/test/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (packages/opencode/test/AGENTS.md)
packages/opencode/test/**/*.test.{ts,tsx}: Use thetmpdirfunction fromfixture/fixture.tsto create temporary directories for tests with automatic cleanup. Useawait usingsyntax to ensure automatic cleanup when the variable goes out of scope.
When using thetmpdirfunction with git repository support, pass thegit: trueoption to initialize a git repo with a root commit.
Use theconfigoption intmpdirto write anopencode.jsonconfig file during test setup by passing a partial Config.Info object.
Use theinitoption intmpdirto define custom setup functions that can return extra data accessible viatmp.extra, and use thedisposeoption for custom cleanup logic.
UsetestEffect(...)fromtest/lib/effect.tsfor tests that exercise Effect services or Effect-based workflows.
Useit.effect(...)when the test should run withTestClockandTestConsole. Useit.live(...)when the test depends on real time, filesystem mtimes, child processes, git, locks, or other live OS behavior.
Prefer Effect-aware helpers fromfixture/fixture.tsover building manual runtimes in tests: usetmpdirScoped()for scoped temp directories,provideInstance(dir)(effect)for low-level binding without directory creation,provideTmpdirInstance(...)for single temp instance binding, orprovideTmpdirServer(...)for tests that also need the test LLM server.
Defineconst it = testEffect(...)near the top of the test file and keep the test body insideEffect.gen(function* () { ... }). Yield services directly withyield* MyService.Serviceoryield* MyTool.
Avoid customManagedRuntime,attach(...), or ad hocrun(...)wrappers in Effect tests whentestEffect(...)already provides the runtime.
When a test needs instance-local state, preferprovideTmpdirInstance(...)orprovideInstance(...)over manualInstance.provide(...)inside Promise-style tests.
Files:
packages/opencode/test/session/instruction.test.ts
🧠 Learnings (20)
📚 Learning: 2026-04-23T08:51:00.819Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 186
File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144
Timestamp: 2026-04-23T08:51:00.819Z
Learning: For pawwork tests under packages/opencode/test/**, auth.json teardown may intentionally combine `Filesystem.write` (from `packages/opencode/src/util/filesystem.ts`) with `node:fs/promises` `unlink` for cleanup. Do not flag this as inconsistent style; it is the established/intentional pattern because `Filesystem` does not provide a `remove`/`unlink` helper.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T08:49:47.800Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/desktop-electron/src/main/index-sidecar-source.test.ts:3-11
Timestamp: 2026-04-22T08:49:47.800Z
Learning: In `packages/desktop-electron/src/main/index-sidecar-source.test.ts` (Astro-Han/pawwork), the test intentionally uses `expect(source).toContain` / `expect(source).not.toContain` string matching against the raw `index.ts` source text as a lightweight sidecar contract guard. The maintainer has explicitly chosen not to introduce an AST parser (e.g., `babel/parser` or acorn) for this purpose. Do not flag these string-based assertions as fragile or suggest converting them to AST-based matching.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T00:02:53.315Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 203
File: packages/app/e2e/sidebar/sidebar-session-links.spec.ts:34-55
Timestamp: 2026-04-24T00:02:53.315Z
Learning: In Astro-Han/pawwork E2E tests (`packages/app/e2e/**/*.spec.ts`), `project.trackDirectory()` and `project.trackSession()` cannot be called before `project.open()` — the `project` fixture throws until `open()` initializes its internal state. The correct pattern is: call `project.trackSession(sessionID)` from inside the `beforeGoto` callback (where state already exists), call `project.trackDirectory(directory)` and cross-workspace `project.trackSession(id, directory)` immediately after `project.open()` returns, and rely on explicit `finally` cleanup (e.g. `cleanupSession` / `cleanupTestProject`) for any resources created before `open()` that cannot yet be tracked via the fixture.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Prefer Effect-aware helpers from `fixture/fixture.ts` over building manual runtimes in tests: use `tmpdirScoped()` for scoped temp directories, `provideInstance(dir)(effect)` for low-level binding without directory creation, `provideTmpdirInstance(...)` for single temp instance binding, or `provideTmpdirServer(...)` for tests that also need the test LLM server.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `tmpdir` function from `fixture/fixture.ts` to create temporary directories for tests with automatic cleanup. Use `await using` syntax to ensure automatic cleanup when the variable goes out of scope.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When a test needs instance-local state, prefer `provideTmpdirInstance(...)` or `provideInstance(...)` over manual `Instance.provide(...)` inside Promise-style tests.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T03:51:54.050Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 206
File: packages/app/e2e/prompt/prompt-footer-focus.spec.ts:131-143
Timestamp: 2026-04-24T03:51:54.050Z
Learning: In Astro-Han/pawwork E2E tests (packages/app/e2e/fixtures.ts), `project.prompt(text)` internally calls `trackSession(next.sessionID, active.directory)` after the prompt submission is observed and the active session is resolved. Tests that obtain a `sessionID` from `project.prompt()` do NOT need to call `project.trackSession(sessionID)` manually — it is already registered for teardown. Calling it again would be duplicate ownership.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `init` option in `tmpdir` to define custom setup functions that can return extra data accessible via `tmp.extra`, and use the `dispose` option for custom cleanup logic.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Import test utilities from `../fixtures` instead of `playwright/test`
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Use `InstanceState` from `src/effect/instance-state.ts` for per-directory or per-project state that needs per-instance cleanup; do work directly in the `InstanceState.make` closure where `ScopedCache` handles run-once semantics
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Define `const it = testEffect(...)` near the top of the test file and keep the test body inside `Effect.gen(function* () { ... })`. Yield services directly with `yield* MyService.Service` or `yield* MyTool`.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use `testEffect(...)` from `test/lib/effect.ts` for tests that exercise Effect services or Effect-based workflows.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use `it.effect(...)` when the test should run with `TestClock` and `TestConsole`. Use `it.live(...)` when the test depends on real time, filesystem mtimes, child processes, git, locks, or other live OS behavior.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T09:32:54.556Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/opencode/test/provider/provider.test.ts:64-85
Timestamp: 2026-04-22T09:32:54.556Z
Learning: In `packages/opencode/test/provider/provider.test.ts`, the file intentionally uses AppRuntime-based async helpers (`run`, `list`, `getProvider`, etc.) rather than `testEffect(...)` for all tests. Converting individual tests to `testEffect` while leaving the rest on the async pattern would create internal inconsistency. A full harness migration of this file is the right approach if the pattern needs to change, but that should be a separate PR.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Avoid custom `ManagedRuntime`, `attach(...)`, or ad hoc `run(...)` wrappers in Effect tests when `testEffect(...)` already provides the runtime.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `config` option in `tmpdir` to write an `opencode.json` config file during test setup by passing a partial Config.Info object.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-25T11:52:40.349Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 233
File: packages/desktop-electron/src/main/server.ts:60-60
Timestamp: 2026-04-25T11:52:40.349Z
Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/index.ts`), `ensureLoopbackNoProxy()` (defined at line 551) is called inside `setupApp()` at line 263, which runs synchronously before `initialize()` (line 321) and `spawnLocalServer()` (line 395). It unconditionally upserts `127.0.0.1`, `localhost`, and `::1` into both `process.env.NO_PROXY` and `process.env.no_proxy`. This guarantees that `configureProxyDispatcher(process.env)` in `server.ts` always receives a `process.env` that already excludes loopback from proxying. Do not flag the absence of a loopback-merge inside `configureProxyDispatcher` or `normalizeProxyConfig` — the exclusion is already enforced at a higher layer before those functions are ever called.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T17:03:40.214Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 73
File: packages/opencode/src/cli/cmd/tui/context/sync.tsx:486-489
Timestamp: 2026-04-20T17:03:40.214Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/cli/cmd/tui/context/sync.tsx`), `sync.ready` returning `true` when `process.env.OPENCODE_FAST_BOOT` is set is intentional. The plugin-facing data properties `state.config` (initialized to `{}`) and `state.provider` (initialized to `[]`) expose safe-empty defaults, so they are safe to access before bootstrap completes. Do not flag these as needing null-guards or conditional patterns to match `vcs` — the difference is intentional because `vcs` starts as `undefined` while the others have initialized defaults. Changing this would alter the plugin API contract without a concrete failing case.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T09:32:58.310Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/ui/src/theme/context.tsx:11-16
Timestamp: 2026-04-22T09:32:58.310Z
Learning: In Astro-Han/pawwork (`packages/ui/src/theme/context.tsx` and related files), the renaming of localStorage theme keys from `opencode-*` to `pawwork-*` (THEME_ID, COLOR_SCHEME, THEME_CSS_LIGHT, THEME_CSS_DARK) is intentional and should NOT include a migration path from the old keys. Migrating would re-couple PawWork and OpenCode browser storage namespaces, which the PR is explicitly designed to avoid. A reset to the PawWork default theme on upgrade is acceptable by design.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Prefer `FileSystem.FileSystem` instead of raw `fs/promises` for effectful file I/O in Effect services
Applied to files:
packages/opencode/src/session/instruction.ts
🔇 Additional comments (11)
packages/opencode/src/session/instruction.ts (4)
36-41: LGTM!The conditional correctly excludes
~/.claude/CLAUDE.mdwhen running in PawWork mode while preserving the existingOPENCODE_DISABLE_CLAUDE_CODE_PROMPTflag behavior for plain opencode CLI users. The inline comment clearly documents the rationale and links to the relevant issue.
62-65: LGTM!Well-designed discriminated union type that cleanly separates loaded vs ignored sources while providing the reason field only where applicable.
194-212: LGTM!The implementation correctly builds on
systemPaths()for the loaded entries and conditionally surfaces the Claude fallback as ignored only when it exists in PawWork mode. Usingfs.existsSafealigns with the guideline to preferFileSystemservices over rawfs/promises. The reason string provides good traceability to the originating issue.
265-265: LGTM!Service interface correctly updated to expose the new
sourcesmethod.packages/opencode/test/session/instruction.test.ts (7)
396-412: LGTM!The env snapshot and restore pattern is correctly extended to include
HOMEandOPENCODE_DISABLE_CLAUDE_CODE_PROMPT, ensuring proper test isolation for the new PawWork-specific tests.
536-573: LGTM!Good test coverage for the
sources()"loaded" status path with proper environment isolation using a fake home directory.
575-613: LGTM!This test correctly verifies that
systemPaths()excludes the global Claude fallback in PawWork mode. The double assertion (exact path check andendsWithcheck) provides good coverage.
615-649: LGTM!Excellent acceptance criterion test validating that a fresh PawWork install with no configured instruction files results in an empty instruction surface, ensuring the bundled system prompt is the only baseline.
651-685: LGTM!Good test validating that project-level
AGENTS.mdis correctly loaded in PawWork mode.
687-724: LGTM!Good test for acceptance criterion
#6, confirming that project-levelCLAUDE.mdremains a compatibility fallback when projectAGENTS.mdis absent. The inline comment clearly distinguishes this from the removed global Claude fallback.
726-760: LGTM!Good test validating that
PAWWORK_CONFIG_DIR/AGENTS.mdis correctly loaded as the PawWork-owned global instruction source.
Astro-Han
left a comment
There was a problem hiding this comment.
Review pass: left P-level inline comments focused on the diagnostics contract and regression coverage.
… and test isolation Combined response to inline review on PR #260, kept as one commit because the test changes are tightly coupled to the production refactor. Production: - Route the global Claude Code fallback through Global.Path.home so OPENCODE_TEST_HOME (the codebase's existing test isolation pattern, see packages/shared/src/global.ts:24) makes the fallback deterministic in tests; os.homedir() is locked at process start in Bun. - Expand InstructionSource union with a 'considered' variant so the diagnostic can report candidates that were checked but skipped by priority or absent (issue #230 acceptance #7 says 'considered, loaded, ignored', not just two states). - Rewrite sources() to walk project files, the full global priority chain, config.instructions URLs, and the explicitly ignored Claude Code fallback. Closes the gap where sources() under-reported what system() actually loads (URLs were missing). - Surface OPENCODE_DISABLE_CLAUDE_CODE_PROMPT as a separate ignore reason so opencode CLI users with that flag set also get a clear diagnostic. Tests: - Replace the brittle os.homedir() guard in the ignored-Claude test with OPENCODE_TEST_HOME + a tmpdir, removing the CI-environment-dependent early return CodeRabbit flagged. - Add OPENCODE_TEST_HOME to the env capture/restore block. - Add a regression test for the non-PawWork branch of the gate so an accidental inversion or future Runtime.isPawWork() change is caught. - Add tests covering the new considered (priority-skipped global) and URL diagnostic entries.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
packages/opencode/test/session/instruction.test.ts (1)
830-867:⚠️ Potential issue | 🟡 MinorSame inconsistency: uses
HOMEinstead ofOPENCODE_TEST_HOME.🔧 Proposed fix
process.env.PAWWORK_RUNTIME_NAMESPACE = "pawwork" - process.env.HOME = fakeHome.path + process.env.OPENCODE_TEST_HOME = fakeHome.path process.env.PAWWORK_CONFIG_DIR = pawworkConfig.path🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/test/session/instruction.test.ts` around lines 830 - 867, The test "falls back to project CLAUDE.md when AGENTS.md is absent (compatibility)" incorrectly sets process.env.HOME instead of the project-specific test variable OPENCODE_TEST_HOME; update the test to set process.env.OPENCODE_TEST_HOME = fakeHome.path and remove or avoid setting process.env.HOME, ensure any code that relied on HOME during the test uses OPENCODE_TEST_HOME instead, and keep the same cleanup/restore behavior for Global.Path.config around Instance.provide and run so the environment is correctly isolated; locate the assignment to process.env.HOME in this test and replace it with process.env.OPENCODE_TEST_HOME, leaving other env var modifications (PAWWORK_*, OPENCODE_*) intact.
🤖 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/opencode/src/session/instruction.ts`:
- Around line 240-252: sources() currently only reports URL entries from
config.instructions, omitting local file paths even though systemPaths() and
system() load them; update sources() to also enumerate non-URL entries from
config.instructions (those not starting with "http://" or "https://"), check
their presence/readability and push corresponding provenance entries into result
(e.g., {status: "loaded", path: filePath} or {status: "considered", path:
filePath, reason: "..."}), so that the function reports file-based config
instructions alongside URLs; reference the existing variables/functions
sources(), systemPaths(), config.instructions, and the result array when adding
this new branch.
In `@packages/opencode/test/session/instruction.test.ts`:
- Around line 679-716: The test sets process.env.HOME but Global.Path.home
prefers OPENCODE_TEST_HOME, causing the fake home not to be used; update the
test to set process.env.OPENCODE_TEST_HOME = fakeHome.path instead of
process.env.HOME (keep fakeHome, pawworkConfig, and globals restore logic the
same) so Global.Path.home resolves to the intended temp directory and the
AGENTS.md file is discovered by Instruction.Service.sources().
---
Duplicate comments:
In `@packages/opencode/test/session/instruction.test.ts`:
- Around line 830-867: The test "falls back to project CLAUDE.md when AGENTS.md
is absent (compatibility)" incorrectly sets process.env.HOME instead of the
project-specific test variable OPENCODE_TEST_HOME; update the test to set
process.env.OPENCODE_TEST_HOME = fakeHome.path and remove or avoid setting
process.env.HOME, ensure any code that relied on HOME during the test uses
OPENCODE_TEST_HOME instead, and keep the same cleanup/restore behavior for
Global.Path.config around Instance.provide and run so the environment is
correctly isolated; locate the assignment to process.env.HOME in this test and
replace it with process.env.OPENCODE_TEST_HOME, leaving other env var
modifications (PAWWORK_*, OPENCODE_*) intact.
🪄 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: 6aef4087-c041-45d8-97ab-939a57eac585
📒 Files selected for processing (2)
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
- GitHub Check: unit-windows-opencode-session
- GitHub Check: unit-windows-opencode-config-project
- GitHub Check: unit-windows-desktop
- GitHub Check: unit-windows-app
- GitHub Check: unit-windows-opencode-server-tools
- GitHub Check: unit-app
- GitHub Check: unit-opencode
- GitHub Check: typecheck
- GitHub Check: unit-desktop
- GitHub Check: smoke-macos-arm64
- GitHub Check: analyze-js-ts
- GitHub Check: e2e-artifacts
🧰 Additional context used
📓 Path-based instructions (2)
packages/opencode/**/*.ts
📄 CodeRabbit inference engine (packages/opencode/AGENTS.md)
packages/opencode/**/*.ts: UseEffect.gen(function* () { ... })for Effect composition
UseEffect.fn("Domain.method")for named/traced effects andEffect.fnUntracedfor internal helpers; these accept pipeable operators as extra arguments to avoid unnecessary outer.pipe()wrappers
UseEffect.callbackfor callback-based APIs
PreferDateTime.nowAsDateovernew Date(yield* Clock.currentTimeMillis)when you need aDatein Effect code
UseSchema.Classfor multi-field data in Effect schemas
Use branded schemas (Schema.brand) for single-value types in Effect
UseSchema.TaggedErrorClassfor typed errors in Effect schemas
UseSchema.Defectinstead ofunknownfor defect-like causes in Effect code
InEffect.gen/Effect.fn, preferyield* new MyError(...)overyield* Effect.fail(new MyError(...))for direct early-failure branches
UsemakeRuntimefromsrc/effect/run-service.tsfor all services; it returns{ runPromise, runFork, runCallback }backed by a sharedmemoMapthat deduplicates layers
UseInstanceStatefromsrc/effect/instance-state.tsfor per-directory or per-project state that needs per-instance cleanup; do work directly in theInstanceState.makeclosure whereScopedCachehandles run-once semantics
UseEffect.addFinalizerorEffect.acquireReleaseinside theInstanceState.makeclosure for cleanup (subscriptions, process teardown, etc.)
UseEffect.forkScopedinside theInstanceState.makeclosure for background stream consumers — the fiber is interrupted when the instance is disposed
PreferFileSystem.FileSysteminstead of rawfs/promisesfor effectful file I/O in Effect services
PreferChildProcessSpawner.ChildProcessSpawnerwithChildProcess.make(...)instead of custom process wrappers in Effect services
PreferHttpClient.HttpClientinstead of rawfetchin Effect services
PreferPath.Path,Config,Clock, andDateTimeservices when those concerns are already inside Effect code
For backgroun...
Files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
packages/opencode/test/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (packages/opencode/test/AGENTS.md)
packages/opencode/test/**/*.test.{ts,tsx}: Use thetmpdirfunction fromfixture/fixture.tsto create temporary directories for tests with automatic cleanup. Useawait usingsyntax to ensure automatic cleanup when the variable goes out of scope.
When using thetmpdirfunction with git repository support, pass thegit: trueoption to initialize a git repo with a root commit.
Use theconfigoption intmpdirto write anopencode.jsonconfig file during test setup by passing a partial Config.Info object.
Use theinitoption intmpdirto define custom setup functions that can return extra data accessible viatmp.extra, and use thedisposeoption for custom cleanup logic.
UsetestEffect(...)fromtest/lib/effect.tsfor tests that exercise Effect services or Effect-based workflows.
Useit.effect(...)when the test should run withTestClockandTestConsole. Useit.live(...)when the test depends on real time, filesystem mtimes, child processes, git, locks, or other live OS behavior.
Prefer Effect-aware helpers fromfixture/fixture.tsover building manual runtimes in tests: usetmpdirScoped()for scoped temp directories,provideInstance(dir)(effect)for low-level binding without directory creation,provideTmpdirInstance(...)for single temp instance binding, orprovideTmpdirServer(...)for tests that also need the test LLM server.
Defineconst it = testEffect(...)near the top of the test file and keep the test body insideEffect.gen(function* () { ... }). Yield services directly withyield* MyService.Serviceoryield* MyTool.
Avoid customManagedRuntime,attach(...), or ad hocrun(...)wrappers in Effect tests whentestEffect(...)already provides the runtime.
When a test needs instance-local state, preferprovideTmpdirInstance(...)orprovideInstance(...)over manualInstance.provide(...)inside Promise-style tests.
Files:
packages/opencode/test/session/instruction.test.ts
🧠 Learnings (20)
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Use `InstanceState` from `src/effect/instance-state.ts` for per-directory or per-project state that needs per-instance cleanup; do work directly in the `InstanceState.make` closure where `ScopedCache` handles run-once semantics
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-23T08:51:04.230Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 186
File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144
Timestamp: 2026-04-23T08:51:04.230Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/util/filesystem.ts`), the `Filesystem` utility does NOT expose a `remove` or `unlink` helper. The established repository pattern for auth.json teardown in tests (e.g. `provider.test.ts`, `amazon-bedrock.test.ts`, `workspace-adaptor.test.ts`) is to combine `Filesystem.write` with `node:fs/promises unlink`. Do not flag this mixed usage as inconsistent — it is the correct and intentional pattern.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `tmpdir` function from `fixture/fixture.ts` to create temporary directories for tests with automatic cleanup. Use `await using` syntax to ensure automatic cleanup when the variable goes out of scope.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Prefer Effect-aware helpers from `fixture/fixture.ts` over building manual runtimes in tests: use `tmpdirScoped()` for scoped temp directories, `provideInstance(dir)(effect)` for low-level binding without directory creation, `provideTmpdirInstance(...)` for single temp instance binding, or `provideTmpdirServer(...)` for tests that also need the test LLM server.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When using the `tmpdir` function with git repository support, pass the `git: true` option to initialize a git repo with a root commit.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T08:49:47.800Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/desktop-electron/src/main/index-sidecar-source.test.ts:3-11
Timestamp: 2026-04-22T08:49:47.800Z
Learning: In `packages/desktop-electron/src/main/index-sidecar-source.test.ts` (Astro-Han/pawwork), the test intentionally uses `expect(source).toContain` / `expect(source).not.toContain` string matching against the raw `index.ts` source text as a lightweight sidecar contract guard. The maintainer has explicitly chosen not to introduce an AST parser (e.g., `babel/parser` or acorn) for this purpose. Do not flag these string-based assertions as fragile or suggest converting them to AST-based matching.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-25T12:52:36.999Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 234
File: packages/opencode/src/session/export.ts:75-88
Timestamp: 2026-04-25T12:52:36.999Z
Learning: In `packages/opencode/src/session/export.ts` (Astro-Han/pawwork), the `extractReasonFromCause` function intentionally uses a lightweight cast-based inspection of the Cause `reasons` array instead of `Cause.failures()` / `Cause.defects()` utilities. This is a deliberate choice: the function is diagnostic-only (used to populate a best-effort reason string for export diagnostics), and the maintainer explicitly prefers not to add coupling to Effect's Cause API surface for this purpose. Do not flag this pattern as fragile or suggest replacing it with Cause utilities.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `config` option in `tmpdir` to write an `opencode.json` config file during test setup by passing a partial Config.Info object.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `init` option in `tmpdir` to define custom setup functions that can return extra data accessible via `tmp.extra`, and use the `dispose` option for custom cleanup logic.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When a test needs instance-local state, prefer `provideTmpdirInstance(...)` or `provideInstance(...)` over manual `Instance.provide(...)` inside Promise-style tests.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T00:02:53.315Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 203
File: packages/app/e2e/sidebar/sidebar-session-links.spec.ts:34-55
Timestamp: 2026-04-24T00:02:53.315Z
Learning: In Astro-Han/pawwork E2E tests (`packages/app/e2e/**/*.spec.ts`), `project.trackDirectory()` and `project.trackSession()` cannot be called before `project.open()` — the `project` fixture throws until `open()` initializes its internal state. The correct pattern is: call `project.trackSession(sessionID)` from inside the `beforeGoto` callback (where state already exists), call `project.trackDirectory(directory)` and cross-workspace `project.trackSession(id, directory)` immediately after `project.open()` returns, and rely on explicit `finally` cleanup (e.g. `cleanupSession` / `cleanupTestProject`) for any resources created before `open()` that cannot yet be tracked via the fixture.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Import test utilities from `../fixtures` instead of `playwright/test`
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-23T08:51:00.819Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 186
File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144
Timestamp: 2026-04-23T08:51:00.819Z
Learning: For pawwork tests under packages/opencode/test/**, auth.json teardown may intentionally combine `Filesystem.write` (from `packages/opencode/src/util/filesystem.ts`) with `node:fs/promises` `unlink` for cleanup. Do not flag this as inconsistent style; it is the established/intentional pattern because `Filesystem` does not provide a `remove`/`unlink` helper.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T03:51:54.050Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 206
File: packages/app/e2e/prompt/prompt-footer-focus.spec.ts:131-143
Timestamp: 2026-04-24T03:51:54.050Z
Learning: In Astro-Han/pawwork E2E tests (packages/app/e2e/fixtures.ts), `project.prompt(text)` internally calls `trackSession(next.sessionID, active.directory)` after the prompt submission is observed and the active session is resolved. Tests that obtain a `sessionID` from `project.prompt()` do NOT need to call `project.trackSession(sessionID)` manually — it is already registered for teardown. Calling it again would be duplicate ownership.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T17:03:40.214Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 73
File: packages/opencode/src/cli/cmd/tui/context/sync.tsx:486-489
Timestamp: 2026-04-20T17:03:40.214Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/cli/cmd/tui/context/sync.tsx`), `sync.ready` returning `true` when `process.env.OPENCODE_FAST_BOOT` is set is intentional. The plugin-facing data properties `state.config` (initialized to `{}`) and `state.provider` (initialized to `[]`) expose safe-empty defaults, so they are safe to access before bootstrap completes. Do not flag these as needing null-guards or conditional patterns to match `vcs` — the difference is intentional because `vcs` starts as `undefined` while the others have initialized defaults. Changing this would alter the plugin API contract without a concrete failing case.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/packages/app/src/testing/**/*.ts : Test-only hooks must be inert unless explicitly enabled and should not add normal-runtime listeners, reactive subscriptions, or per-update allocations
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Avoid custom `ManagedRuntime`, `attach(...)`, or ad hoc `run(...)` wrappers in Effect tests when `testEffect(...)` already provides the runtime.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : When validating routing, assert against canonical or resolved workspace slugs using shared helpers from `../actions` to account for Windows canonicalization
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-25T11:52:40.349Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 233
File: packages/desktop-electron/src/main/server.ts:60-60
Timestamp: 2026-04-25T11:52:40.349Z
Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/index.ts`), `ensureLoopbackNoProxy()` (defined at line 551) is called inside `setupApp()` at line 263, which runs synchronously before `initialize()` (line 321) and `spawnLocalServer()` (line 395). It unconditionally upserts `127.0.0.1`, `localhost`, and `::1` into both `process.env.NO_PROXY` and `process.env.no_proxy`. This guarantees that `configureProxyDispatcher(process.env)` in `server.ts` always receives a `process.env` that already excludes loopback from proxying. Do not flag the absence of a loopback-merge inside `configureProxyDispatcher` or `normalizeProxyConfig` — the exclusion is already enforced at a higher layer before those functions are ever called.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T09:32:58.310Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/ui/src/theme/context.tsx:11-16
Timestamp: 2026-04-22T09:32:58.310Z
Learning: In Astro-Han/pawwork (`packages/ui/src/theme/context.tsx` and related files), the renaming of localStorage theme keys from `opencode-*` to `pawwork-*` (THEME_ID, COLOR_SCHEME, THEME_CSS_LIGHT, THEME_CSS_DARK) is intentional and should NOT include a migration path from the old keys. Migrating would re-couple PawWork and OpenCode browser storage namespaces, which the PR is explicitly designed to avoid. A reset to the PawWork default theme on upgrade is acceptable by design.
Applied to files:
packages/opencode/test/session/instruction.test.ts
🔇 Additional comments (14)
packages/opencode/src/session/instruction.ts (4)
36-41: LGTM!The conditional correctly implements the PawWork baseline requirement from issue
#230while preserving Claude Code interop for plain opencode CLI users. The inline comment clearly explains the rationale.
62-66: LGTM!The
InstructionSourcetype now correctly models all three diagnostic states (loaded, considered, ignored) with appropriate reason fields, addressing the previous feedback about the missing "considered" variant.
195-270: LGTM!The
sources()implementation correctly addresses previous feedback:
- Mirrors
systemPaths()priority logic for project-level discovery- Reports the full global instruction file chain with appropriate loaded/considered statuses
- Includes URL contributions from
config.instructions(addressing the under-reporting concern)- Explicitly reports ignored
~/.claude/CLAUDE.mdwith contextual reasons for both PawWork mode and the legacy opt-out flagThe implementation maintains parity with
system()for diagnostic accuracy.
323-323: LGTM!The service correctly exports all methods including the new
sources()function.packages/opencode/test/session/instruction.test.ts (10)
389-415: LGTM!The extended environment variable snapshot/restore correctly isolates the new tests, following the established pattern in the file.
493-535: LGTM!The test correctly uses
OPENCODE_TEST_HOMEto create a deterministic fake home directory, addressing the previous concern about tests being skipped in clean CI environments. The assertions properly verify the ignored diagnostic with PawWork-specific reasoning.
537-586: LGTM!The test correctly verifies that priority-skipped global instruction files are reported as "considered" with an appropriate reason, fulfilling the diagnostic requirements from issue
#230.
588-638: LGTM!The test correctly verifies that URL entries from
config.instructionsappear in the diagnostic output, addressing the previous feedback about URL sources being under-reported. The use of an unreachable URL deterministically exercises the "considered with failure reason" branch.
640-677: LGTM!This test directly addresses the previous review feedback requesting a non-PawWork regression test. It correctly verifies that opencode CLI users retain the
~/.claude/CLAUDE.mdfallback when the PawWork gate is not active, guarding against accidental condition inversions.
905-950: LGTM!This test correctly verifies that relative instruction paths resolve from
PAWWORK_CONFIG_DIRwhen project config is disabled. The test appropriately doesn't manipulate home directory since it's not testing that behavior.
758-792:⚠️ Potential issue | 🟡 MinorSame inconsistency: uses
HOMEinstead ofOPENCODE_TEST_HOME.🔧 Proposed fix
process.env.PAWWORK_RUNTIME_NAMESPACE = "pawwork" - process.env.HOME = fakeHome.path + process.env.OPENCODE_TEST_HOME = fakeHome.path process.env.PAWWORK_CONFIG_DIR = pawworkConfig.path⛔ Skipped due to learnings
Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 186 File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144 Timestamp: 2026-04-23T08:51:04.230Z Learning: In Astro-Han/pawwork (`packages/opencode/src/util/filesystem.ts`), the `Filesystem` utility does NOT expose a `remove` or `unlink` helper. The established repository pattern for auth.json teardown in tests (e.g. `provider.test.ts`, `amazon-bedrock.test.ts`, `workspace-adaptor.test.ts`) is to combine `Filesystem.write` with `node:fs/promises unlink`. Do not flag this mixed usage as inconsistent — it is the correct and intentional pattern.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 203 File: packages/app/e2e/sidebar/sidebar-session-links.spec.ts:34-55 Timestamp: 2026-04-24T00:02:53.315Z Learning: In Astro-Han/pawwork E2E tests (`packages/app/e2e/**/*.spec.ts`), `project.trackDirectory()` and `project.trackSession()` cannot be called before `project.open()` — the `project` fixture throws until `open()` initializes its internal state. The correct pattern is: call `project.trackSession(sessionID)` from inside the `beforeGoto` callback (where state already exists), call `project.trackDirectory(directory)` and cross-workspace `project.trackSession(id, directory)` immediately after `project.open()` returns, and rely on explicit `finally` cleanup (e.g. `cleanupSession` / `cleanupTestProject`) for any resources created before `open()` that cannot yet be tracked via the fixture.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When a test needs instance-local state, prefer `provideTmpdirInstance(...)` or `provideInstance(...)` over manual `Instance.provide(...)` inside Promise-style tests.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 233 File: packages/desktop-electron/src/main/server.ts:60-60 Timestamp: 2026-04-25T11:52:40.349Z Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/index.ts`), `ensureLoopbackNoProxy()` (defined at line 551) is called inside `setupApp()` at line 263, which runs synchronously before `initialize()` (line 321) and `spawnLocalServer()` (line 395). It unconditionally upserts `127.0.0.1`, `localhost`, and `::1` into both `process.env.NO_PROXY` and `process.env.no_proxy`. This guarantees that `configureProxyDispatcher(process.env)` in `server.ts` always receives a `process.env` that already excludes loopback from proxying. Do not flag the absence of a loopback-merge inside `configureProxyDispatcher` or `normalizeProxyConfig` — the exclusion is already enforced at a higher layer before those functions are ever called.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Prefer Effect-aware helpers from `fixture/fixture.ts` over building manual runtimes in tests: use `tmpdirScoped()` for scoped temp directories, `provideInstance(dir)(effect)` for low-level binding without directory creation, `provideTmpdirInstance(...)` for single temp instance binding, or `provideTmpdirServer(...)` for tests that also need the test LLM server.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `tmpdir` function from `fixture/fixture.ts` to create temporary directories for tests with automatic cleanup. Use `await using` syntax to ensure automatic cleanup when the variable goes out of scope.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 126 File: packages/desktop-electron/src/main/index-sidecar-source.test.ts:3-11 Timestamp: 2026-04-22T08:49:47.800Z Learning: In `packages/desktop-electron/src/main/index-sidecar-source.test.ts` (Astro-Han/pawwork), the test intentionally uses `expect(source).toContain` / `expect(source).not.toContain` string matching against the raw `index.ts` source text as a lightweight sidecar contract guard. The maintainer has explicitly chosen not to introduce an AST parser (e.g., `babel/parser` or acorn) for this purpose. Do not flag these string-based assertions as fragile or suggest converting them to AST-based matching.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `config` option in `tmpdir` to write an `opencode.json` config file during test setup by passing a partial Config.Info object.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 193 File: packages/app/e2e/sidebar/sidebar-leading-slot.spec.ts:5-55 Timestamp: 2026-04-23T15:25:31.118Z Learning: In Astro-Han/pawwork E2E tests, reaching a real "running" session state requires the `project` fixture (for model bootstrap) plus `llm.wait(1)` orchestration. The bare `sdk` fixture used by `withSession` does not trigger an LLM call even with `agent: "build"` + `system` prompt set via `sdk.session.promptAsync`, so simulating running state is not lightweight in the current test infrastructure.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 73 File: packages/opencode/src/cli/cmd/tui/context/sync.tsx:486-489 Timestamp: 2026-04-20T17:03:40.214Z Learning: In Astro-Han/pawwork (`packages/opencode/src/cli/cmd/tui/context/sync.tsx`), `sync.ready` returning `true` when `process.env.OPENCODE_FAST_BOOT` is set is intentional. The plugin-facing data properties `state.config` (initialized to `{}`) and `state.provider` (initialized to `[]`) expose safe-empty defaults, so they are safe to access before bootstrap completes. Do not flag these as needing null-guards or conditional patterns to match `vcs` — the difference is intentional because `vcs` starts as `undefined` while the others have initialized defaults. Changing this would alter the plugin API contract without a concrete failing case.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When using the `tmpdir` function with git repository support, pass the `git: true` option to initialize a git repo with a root commit.
869-903:⚠️ Potential issue | 🟡 MinorSame inconsistency: uses
HOMEinstead ofOPENCODE_TEST_HOME.🔧 Proposed fix
process.env.PAWWORK_RUNTIME_NAMESPACE = "pawwork" - process.env.HOME = fakeHome.path + process.env.OPENCODE_TEST_HOME = fakeHome.path process.env.PAWWORK_CONFIG_DIR = pawworkConfig.path⛔ Skipped due to learnings
Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 186 File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144 Timestamp: 2026-04-23T08:51:04.230Z Learning: In Astro-Han/pawwork (`packages/opencode/src/util/filesystem.ts`), the `Filesystem` utility does NOT expose a `remove` or `unlink` helper. The established repository pattern for auth.json teardown in tests (e.g. `provider.test.ts`, `amazon-bedrock.test.ts`, `workspace-adaptor.test.ts`) is to combine `Filesystem.write` with `node:fs/promises unlink`. Do not flag this mixed usage as inconsistent — it is the correct and intentional pattern.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 203 File: packages/app/e2e/sidebar/sidebar-session-links.spec.ts:34-55 Timestamp: 2026-04-24T00:02:53.315Z Learning: In Astro-Han/pawwork E2E tests (`packages/app/e2e/**/*.spec.ts`), `project.trackDirectory()` and `project.trackSession()` cannot be called before `project.open()` — the `project` fixture throws until `open()` initializes its internal state. The correct pattern is: call `project.trackSession(sessionID)` from inside the `beforeGoto` callback (where state already exists), call `project.trackDirectory(directory)` and cross-workspace `project.trackSession(id, directory)` immediately after `project.open()` returns, and rely on explicit `finally` cleanup (e.g. `cleanupSession` / `cleanupTestProject`) for any resources created before `open()` that cannot yet be tracked via the fixture.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 233 File: packages/desktop-electron/src/main/server.ts:60-60 Timestamp: 2026-04-25T11:52:40.349Z Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/index.ts`), `ensureLoopbackNoProxy()` (defined at line 551) is called inside `setupApp()` at line 263, which runs synchronously before `initialize()` (line 321) and `spawnLocalServer()` (line 395). It unconditionally upserts `127.0.0.1`, `localhost`, and `::1` into both `process.env.NO_PROXY` and `process.env.no_proxy`. This guarantees that `configureProxyDispatcher(process.env)` in `server.ts` always receives a `process.env` that already excludes loopback from proxying. Do not flag the absence of a loopback-merge inside `configureProxyDispatcher` or `normalizeProxyConfig` — the exclusion is already enforced at a higher layer before those functions are ever called.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `config` option in `tmpdir` to write an `opencode.json` config file during test setup by passing a partial Config.Info object.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 193 File: packages/app/e2e/sidebar/sidebar-leading-slot.spec.ts:5-55 Timestamp: 2026-04-23T15:25:31.118Z Learning: In Astro-Han/pawwork E2E tests, reaching a real "running" session state requires the `project` fixture (for model bootstrap) plus `llm.wait(1)` orchestration. The bare `sdk` fixture used by `withSession` does not trigger an LLM call even with `agent: "build"` + `system` prompt set via `sdk.session.promptAsync`, so simulating running state is not lightweight in the current test infrastructure.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Prefer Effect-aware helpers from `fixture/fixture.ts` over building manual runtimes in tests: use `tmpdirScoped()` for scoped temp directories, `provideInstance(dir)(effect)` for low-level binding without directory creation, `provideTmpdirInstance(...)` for single temp instance binding, or `provideTmpdirServer(...)` for tests that also need the test LLM server.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When a test needs instance-local state, prefer `provideTmpdirInstance(...)` or `provideInstance(...)` over manual `Instance.provide(...)` inside Promise-style tests.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `tmpdir` function from `fixture/fixture.ts` to create temporary directories for tests with automatic cleanup. Use `await using` syntax to ensure automatic cleanup when the variable goes out of scope.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `init` option in `tmpdir` to define custom setup functions that can return extra data accessible via `tmp.extra`, and use the `dispose` option for custom cleanup logic.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Define `const it = testEffect(...)` near the top of the test file and keep the test body inside `Effect.gen(function* () { ... })`. Yield services directly with `yield* MyService.Service` or `yield* MyTool`.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When using the `tmpdir` function with git repository support, pass the `git: true` option to initialize a git repo with a root commit.
794-828:⚠️ Potential issue | 🟡 MinorSame inconsistency: uses
HOMEinstead ofOPENCODE_TEST_HOME.🔧 Proposed fix
process.env.PAWWORK_RUNTIME_NAMESPACE = "pawwork" - process.env.HOME = fakeHome.path + process.env.OPENCODE_TEST_HOME = fakeHome.path process.env.PAWWORK_CONFIG_DIR = pawworkConfig.path⛔ Skipped due to learnings
Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 203 File: packages/app/e2e/sidebar/sidebar-session-links.spec.ts:34-55 Timestamp: 2026-04-24T00:02:53.315Z Learning: In Astro-Han/pawwork E2E tests (`packages/app/e2e/**/*.spec.ts`), `project.trackDirectory()` and `project.trackSession()` cannot be called before `project.open()` — the `project` fixture throws until `open()` initializes its internal state. The correct pattern is: call `project.trackSession(sessionID)` from inside the `beforeGoto` callback (where state already exists), call `project.trackDirectory(directory)` and cross-workspace `project.trackSession(id, directory)` immediately after `project.open()` returns, and rely on explicit `finally` cleanup (e.g. `cleanupSession` / `cleanupTestProject`) for any resources created before `open()` that cannot yet be tracked via the fixture.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 186 File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144 Timestamp: 2026-04-23T08:51:04.230Z Learning: In Astro-Han/pawwork (`packages/opencode/src/util/filesystem.ts`), the `Filesystem` utility does NOT expose a `remove` or `unlink` helper. The established repository pattern for auth.json teardown in tests (e.g. `provider.test.ts`, `amazon-bedrock.test.ts`, `workspace-adaptor.test.ts`) is to combine `Filesystem.write` with `node:fs/promises unlink`. Do not flag this mixed usage as inconsistent — it is the correct and intentional pattern.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 193 File: packages/app/e2e/sidebar/sidebar-leading-slot.spec.ts:5-55 Timestamp: 2026-04-23T15:25:31.118Z Learning: In Astro-Han/pawwork E2E tests, reaching a real "running" session state requires the `project` fixture (for model bootstrap) plus `llm.wait(1)` orchestration. The bare `sdk` fixture used by `withSession` does not trigger an LLM call even with `agent: "build"` + `system` prompt set via `sdk.session.promptAsync`, so simulating running state is not lightweight in the current test infrastructure.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/app/e2e/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:04.113Z Learning: Applies to packages/app/e2e/**/*.spec.ts : Prefer the `project` fixture for tests that need a dedicated project with LLM mockingLearnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When a test needs instance-local state, prefer `provideTmpdirInstance(...)` or `provideInstance(...)` over manual `Instance.provide(...)` inside Promise-style tests.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Prefer Effect-aware helpers from `fixture/fixture.ts` over building manual runtimes in tests: use `tmpdirScoped()` for scoped temp directories, `provideInstance(dir)(effect)` for low-level binding without directory creation, `provideTmpdirInstance(...)` for single temp instance binding, or `provideTmpdirServer(...)` for tests that also need the test LLM server.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 206 File: packages/app/e2e/prompt/prompt-footer-focus.spec.ts:131-143 Timestamp: 2026-04-24T03:51:54.050Z Learning: In Astro-Han/pawwork E2E tests (packages/app/e2e/fixtures.ts), `project.prompt(text)` internally calls `trackSession(next.sessionID, active.directory)` after the prompt submission is observed and the active session is resolved. Tests that obtain a `sessionID` from `project.prompt()` do NOT need to call `project.trackSession(sessionID)` manually — it is already registered for teardown. Calling it again would be duplicate ownership.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `tmpdir` function from `fixture/fixture.ts` to create temporary directories for tests with automatic cleanup. Use `await using` syntax to ensure automatic cleanup when the variable goes out of scope.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Define `const it = testEffect(...)` near the top of the test file and keep the test body inside `Effect.gen(function* () { ... })`. Yield services directly with `yield* MyService.Service` or `yield* MyTool`.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `config` option in `tmpdir` to write an `opencode.json` config file during test setup by passing a partial Config.Info object.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When using the `tmpdir` function with git repository support, pass the `git: true` option to initialize a git repo with a root commit.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 233 File: packages/desktop-electron/src/main/server.ts:60-60 Timestamp: 2026-04-25T11:52:40.349Z Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/index.ts`), `ensureLoopbackNoProxy()` (defined at line 551) is called inside `setupApp()` at line 263, which runs synchronously before `initialize()` (line 321) and `spawnLocalServer()` (line 395). It unconditionally upserts `127.0.0.1`, `localhost`, and `::1` into both `process.env.NO_PROXY` and `process.env.no_proxy`. This guarantees that `configureProxyDispatcher(process.env)` in `server.ts` always receives a `process.env` that already excludes loopback from proxying. Do not flag the absence of a loopback-merge inside `configureProxyDispatcher` or `normalizeProxyConfig` — the exclusion is already enforced at a higher layer before those functions are ever called.
718-756:⚠️ Potential issue | 🟡 MinorSame inconsistency: uses
HOMEinstead ofOPENCODE_TEST_HOME.Similar to the previous test, this should use
OPENCODE_TEST_HOMEfor consistency withGlobal.Path.home:🔧 Proposed fix
process.env.PAWWORK_RUNTIME_NAMESPACE = "pawwork" - process.env.HOME = fakeHome.path + process.env.OPENCODE_TEST_HOME = fakeHome.path delete process.env.PAWWORK_CONFIG_DIR⛔ Skipped due to learnings
Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 186 File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144 Timestamp: 2026-04-23T08:51:04.230Z Learning: In Astro-Han/pawwork (`packages/opencode/src/util/filesystem.ts`), the `Filesystem` utility does NOT expose a `remove` or `unlink` helper. The established repository pattern for auth.json teardown in tests (e.g. `provider.test.ts`, `amazon-bedrock.test.ts`, `workspace-adaptor.test.ts`) is to combine `Filesystem.write` with `node:fs/promises unlink`. Do not flag this mixed usage as inconsistent — it is the correct and intentional pattern.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 203 File: packages/app/e2e/sidebar/sidebar-session-links.spec.ts:34-55 Timestamp: 2026-04-24T00:02:53.315Z Learning: In Astro-Han/pawwork E2E tests (`packages/app/e2e/**/*.spec.ts`), `project.trackDirectory()` and `project.trackSession()` cannot be called before `project.open()` — the `project` fixture throws until `open()` initializes its internal state. The correct pattern is: call `project.trackSession(sessionID)` from inside the `beforeGoto` callback (where state already exists), call `project.trackDirectory(directory)` and cross-workspace `project.trackSession(id, directory)` immediately after `project.open()` returns, and rely on explicit `finally` cleanup (e.g. `cleanupSession` / `cleanupTestProject`) for any resources created before `open()` that cannot yet be tracked via the fixture.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 126 File: packages/desktop-electron/src/main/index-sidecar-source.test.ts:3-11 Timestamp: 2026-04-22T08:49:47.800Z Learning: In `packages/desktop-electron/src/main/index-sidecar-source.test.ts` (Astro-Han/pawwork), the test intentionally uses `expect(source).toContain` / `expect(source).not.toContain` string matching against the raw `index.ts` source text as a lightweight sidecar contract guard. The maintainer has explicitly chosen not to introduce an AST parser (e.g., `babel/parser` or acorn) for this purpose. Do not flag these string-based assertions as fragile or suggest converting them to AST-based matching.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `tmpdir` function from `fixture/fixture.ts` to create temporary directories for tests with automatic cleanup. Use `await using` syntax to ensure automatic cleanup when the variable goes out of scope.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When a test needs instance-local state, prefer `provideTmpdirInstance(...)` or `provideInstance(...)` over manual `Instance.provide(...)` inside Promise-style tests.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `config` option in `tmpdir` to write an `opencode.json` config file during test setup by passing a partial Config.Info object.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Prefer Effect-aware helpers from `fixture/fixture.ts` over building manual runtimes in tests: use `tmpdirScoped()` for scoped temp directories, `provideInstance(dir)(effect)` for low-level binding without directory creation, `provideTmpdirInstance(...)` for single temp instance binding, or `provideTmpdirServer(...)` for tests that also need the test LLM server.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When using the `tmpdir` function with git repository support, pass the `git: true` option to initialize a git repo with a root commit.Learnt from: Astro-Han Repo: Astro-Han/pawwork PR: 126 File: packages/opencode/test/provider/provider.test.ts:64-85 Timestamp: 2026-04-22T09:32:54.556Z Learning: In `packages/opencode/test/provider/provider.test.ts`, the file intentionally uses AppRuntime-based async helpers (`run`, `list`, `getProvider`, etc.) rather than `testEffect(...)` for all tests. Converting individual tests to `testEffect` while leaving the rest on the async pattern would create internal inconsistency. A full harness migration of this file is the right approach if the pattern needs to change, but that should be a separate PR.Learnt from: CR Repo: Astro-Han/pawwork PR: 0 File: packages/opencode/test/AGENTS.md:0-0 Timestamp: 2026-04-20T14:36:31.032Z Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `init` option in `tmpdir` to define custom setup functions that can return extra data accessible via `tmp.extra`, and use the `dispose` option for custom cleanup logic.
97038df to
020e058
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/opencode/src/session/instruction.ts (1)
29-40:⚠️ Potential issue | 🟠 MajorPawWork can still lose project
CLAUDE.mdwhen the disable flag is inherited.Lines 39-40 remove only the global
~/.claude/CLAUDE.mdfallback. Project discovery still comes fromFILES, andFILESis still built fromFlag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT, so a PawWork process started with that env var will also skip the project-levelCLAUDE.mdcompatibility fallback. That contradicts the new PawWork fallback order this PR is trying to preserve. Please scope the flag to plain opencode CLI project discovery as well, and add a regression for PawWork + projectCLAUDE.md+OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/src/session/instruction.ts` around lines 29 - 40, The project-level CLAUDE.md fallback is still gated by Flag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT causing PawWork processes that inherit that env var to skip project discovery; update globalInstructionFiles and any code that builds FILES so the OPENCODE_DISABLE_CLAUDE_CODE_PROMPT check only applies for plain opencode CLI (i.e., wrap the flag check behind a Runtime.isPawWork() conditional so PawWork always includes the project-level CLAUDE.md), adjust the logic that pushes path.join(Global.Path.home, ".claude", "CLAUDE.md") vs project files accordingly, and add a regression test covering PawWork + project CLAUDE.md with OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 to ensure PawWork still finds the project fallback.
🤖 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/opencode/src/session/instruction.ts`:
- Around line 240-247: sources() and systemPaths() resolve "~/..." differently
(sources() uses Global.Path.home while systemPaths() uses os.homedir()), causing
mismatched paths for the same config.instructions entries; unify resolution by
routing both code paths through a single home-resolver helper (e.g., create or
reuse a function like resolveHome(pathStr) and call it from the
localInstructions loop and from systemPaths()), replacing direct uses of
Global.Path.home and os.homedir() so config.instructions, system(), and
systemPaths() all produce identical expanded paths for entries like
"~/rules.md".
---
Outside diff comments:
In `@packages/opencode/src/session/instruction.ts`:
- Around line 29-40: The project-level CLAUDE.md fallback is still gated by
Flag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT causing PawWork processes that inherit
that env var to skip project discovery; update globalInstructionFiles and any
code that builds FILES so the OPENCODE_DISABLE_CLAUDE_CODE_PROMPT check only
applies for plain opencode CLI (i.e., wrap the flag check behind a
Runtime.isPawWork() conditional so PawWork always includes the project-level
CLAUDE.md), adjust the logic that pushes path.join(Global.Path.home, ".claude",
"CLAUDE.md") vs project files accordingly, and add a regression test covering
PawWork + project CLAUDE.md with OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 to ensure
PawWork still finds the project fallback.
🪄 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: 625e27e0-d56a-41a2-b221-e40d86334bd3
📒 Files selected for processing (2)
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
packages/opencode/**/*.ts
📄 CodeRabbit inference engine (packages/opencode/AGENTS.md)
packages/opencode/**/*.ts: UseEffect.gen(function* () { ... })for Effect composition
UseEffect.fn("Domain.method")for named/traced effects andEffect.fnUntracedfor internal helpers; these accept pipeable operators as extra arguments to avoid unnecessary outer.pipe()wrappers
UseEffect.callbackfor callback-based APIs
PreferDateTime.nowAsDateovernew Date(yield* Clock.currentTimeMillis)when you need aDatein Effect code
UseSchema.Classfor multi-field data in Effect schemas
Use branded schemas (Schema.brand) for single-value types in Effect
UseSchema.TaggedErrorClassfor typed errors in Effect schemas
UseSchema.Defectinstead ofunknownfor defect-like causes in Effect code
InEffect.gen/Effect.fn, preferyield* new MyError(...)overyield* Effect.fail(new MyError(...))for direct early-failure branches
UsemakeRuntimefromsrc/effect/run-service.tsfor all services; it returns{ runPromise, runFork, runCallback }backed by a sharedmemoMapthat deduplicates layers
UseInstanceStatefromsrc/effect/instance-state.tsfor per-directory or per-project state that needs per-instance cleanup; do work directly in theInstanceState.makeclosure whereScopedCachehandles run-once semantics
UseEffect.addFinalizerorEffect.acquireReleaseinside theInstanceState.makeclosure for cleanup (subscriptions, process teardown, etc.)
UseEffect.forkScopedinside theInstanceState.makeclosure for background stream consumers — the fiber is interrupted when the instance is disposed
PreferFileSystem.FileSysteminstead of rawfs/promisesfor effectful file I/O in Effect services
PreferChildProcessSpawner.ChildProcessSpawnerwithChildProcess.make(...)instead of custom process wrappers in Effect services
PreferHttpClient.HttpClientinstead of rawfetchin Effect services
PreferPath.Path,Config,Clock, andDateTimeservices when those concerns are already inside Effect code
For backgroun...
Files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
packages/opencode/test/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (packages/opencode/test/AGENTS.md)
packages/opencode/test/**/*.test.{ts,tsx}: Use thetmpdirfunction fromfixture/fixture.tsto create temporary directories for tests with automatic cleanup. Useawait usingsyntax to ensure automatic cleanup when the variable goes out of scope.
When using thetmpdirfunction with git repository support, pass thegit: trueoption to initialize a git repo with a root commit.
Use theconfigoption intmpdirto write anopencode.jsonconfig file during test setup by passing a partial Config.Info object.
Use theinitoption intmpdirto define custom setup functions that can return extra data accessible viatmp.extra, and use thedisposeoption for custom cleanup logic.
UsetestEffect(...)fromtest/lib/effect.tsfor tests that exercise Effect services or Effect-based workflows.
Useit.effect(...)when the test should run withTestClockandTestConsole. Useit.live(...)when the test depends on real time, filesystem mtimes, child processes, git, locks, or other live OS behavior.
Prefer Effect-aware helpers fromfixture/fixture.tsover building manual runtimes in tests: usetmpdirScoped()for scoped temp directories,provideInstance(dir)(effect)for low-level binding without directory creation,provideTmpdirInstance(...)for single temp instance binding, orprovideTmpdirServer(...)for tests that also need the test LLM server.
Defineconst it = testEffect(...)near the top of the test file and keep the test body insideEffect.gen(function* () { ... }). Yield services directly withyield* MyService.Serviceoryield* MyTool.
Avoid customManagedRuntime,attach(...), or ad hocrun(...)wrappers in Effect tests whentestEffect(...)already provides the runtime.
When a test needs instance-local state, preferprovideTmpdirInstance(...)orprovideInstance(...)over manualInstance.provide(...)inside Promise-style tests.
Files:
packages/opencode/test/session/instruction.test.ts
🧠 Learnings (31)
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When a test needs instance-local state, prefer `provideTmpdirInstance(...)` or `provideInstance(...)` over manual `Instance.provide(...)` inside Promise-style tests.
Applied to files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Prefer Effect-aware helpers from `fixture/fixture.ts` over building manual runtimes in tests: use `tmpdirScoped()` for scoped temp directories, `provideInstance(dir)(effect)` for low-level binding without directory creation, `provideTmpdirInstance(...)` for single temp instance binding, or `provideTmpdirServer(...)` for tests that also need the test LLM server.
Applied to files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-24T00:02:53.315Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 203
File: packages/app/e2e/sidebar/sidebar-session-links.spec.ts:34-55
Timestamp: 2026-04-24T00:02:53.315Z
Learning: In Astro-Han/pawwork E2E tests (`packages/app/e2e/**/*.spec.ts`), `project.trackDirectory()` and `project.trackSession()` cannot be called before `project.open()` — the `project` fixture throws until `open()` initializes its internal state. The correct pattern is: call `project.trackSession(sessionID)` from inside the `beforeGoto` callback (where state already exists), call `project.trackDirectory(directory)` and cross-workspace `project.trackSession(id, directory)` immediately after `project.open()` returns, and rely on explicit `finally` cleanup (e.g. `cleanupSession` / `cleanupTestProject`) for any resources created before `open()` that cannot yet be tracked via the fixture.
Applied to files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `tmpdir` function from `fixture/fixture.ts` to create temporary directories for tests with automatic cleanup. Use `await using` syntax to ensure automatic cleanup when the variable goes out of scope.
Applied to files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-23T08:51:00.819Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 186
File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144
Timestamp: 2026-04-23T08:51:00.819Z
Learning: For pawwork tests under packages/opencode/test/**, auth.json teardown may intentionally combine `Filesystem.write` (from `packages/opencode/src/util/filesystem.ts`) with `node:fs/promises` `unlink` for cleanup. Do not flag this as inconsistent style; it is the established/intentional pattern because `Filesystem` does not provide a `remove`/`unlink` helper.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `init` option in `tmpdir` to define custom setup functions that can return extra data accessible via `tmp.extra`, and use the `dispose` option for custom cleanup logic.
Applied to files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `config` option in `tmpdir` to write an `opencode.json` config file during test setup by passing a partial Config.Info object.
Applied to files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When using the `tmpdir` function with git repository support, pass the `git: true` option to initialize a git repo with a root commit.
Applied to files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T17:03:40.214Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 73
File: packages/opencode/src/cli/cmd/tui/context/sync.tsx:486-489
Timestamp: 2026-04-20T17:03:40.214Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/cli/cmd/tui/context/sync.tsx`), `sync.ready` returning `true` when `process.env.OPENCODE_FAST_BOOT` is set is intentional. The plugin-facing data properties `state.config` (initialized to `{}`) and `state.provider` (initialized to `[]`) expose safe-empty defaults, so they are safe to access before bootstrap completes. Do not flag these as needing null-guards or conditional patterns to match `vcs` — the difference is intentional because `vcs` starts as `undefined` while the others have initialized defaults. Changing this would alter the plugin API contract without a concrete failing case.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/packages/app/src/testing/**/*.ts : Test-only hooks must be inert unless explicitly enabled and should not add normal-runtime listeners, reactive subscriptions, or per-update allocations
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Avoid custom `ManagedRuntime`, `attach(...)`, or ad hoc `run(...)` wrappers in Effect tests when `testEffect(...)` already provides the runtime.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T08:49:47.800Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/desktop-electron/src/main/index-sidecar-source.test.ts:3-11
Timestamp: 2026-04-22T08:49:47.800Z
Learning: In `packages/desktop-electron/src/main/index-sidecar-source.test.ts` (Astro-Han/pawwork), the test intentionally uses `expect(source).toContain` / `expect(source).not.toContain` string matching against the raw `index.ts` source text as a lightweight sidecar contract guard. The maintainer has explicitly chosen not to introduce an AST parser (e.g., `babel/parser` or acorn) for this purpose. Do not flag these string-based assertions as fragile or suggest converting them to AST-based matching.
Applied to files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : When validating routing, assert against canonical or resolved workspace slugs using shared helpers from `../actions` to account for Windows canonicalization
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T03:51:54.050Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 206
File: packages/app/e2e/prompt/prompt-footer-focus.spec.ts:131-143
Timestamp: 2026-04-24T03:51:54.050Z
Learning: In Astro-Han/pawwork E2E tests (packages/app/e2e/fixtures.ts), `project.prompt(text)` internally calls `trackSession(next.sessionID, active.directory)` after the prompt submission is observed and the active session is resolved. Tests that obtain a `sessionID` from `project.prompt()` do NOT need to call `project.trackSession(sessionID)` manually — it is already registered for teardown. Calling it again would be duplicate ownership.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-26T16:34:54.895Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 247
File: packages/ui/src/components/message-part.tsx:1322-1324
Timestamp: 2026-04-26T16:34:54.895Z
Learning: In Astro-Han/pawwork (`packages/ui/src/components/message-part.tsx`), the `taskId` createMemo and `childSessionId` createMemo both intentionally read only from `partMetadata().sessionId` (populated post-execution), not from `input.task_id` / `input.subagent_session_id`. This has always been the case — the original code never read the input field either. Adding an `input.subagent_session_id` fallback would be a new capability, not a bug fix. Do NOT flag the absence of this fallback as a regression in PR `#247` or future PRs unless there is a concrete case where metadata is not populated.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-26T15:35:31.757Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 245
File: packages/opencode/src/question/index.ts:21-24
Timestamp: 2026-04-26T15:35:31.757Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/question/index.ts`), `Question.Option.description` is intentionally **required** (`z.string()`, not `.optional()`). This matches the upstream opencode contract and all current callers (e.g. `PlanExitTool`) always supply a description. The defensive `<Show when={props.description}>` rendering in `session-question-dock.tsx` is a standard guard, not a signal that the field is intended to be optional. Do NOT suggest making `Option.description` optional without a dedicated follow-up that covers schema + tool description + dock copy + tests.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-25T11:52:40.349Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 233
File: packages/desktop-electron/src/main/server.ts:60-60
Timestamp: 2026-04-25T11:52:40.349Z
Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/index.ts`), `ensureLoopbackNoProxy()` (defined at line 551) is called inside `setupApp()` at line 263, which runs synchronously before `initialize()` (line 321) and `spawnLocalServer()` (line 395). It unconditionally upserts `127.0.0.1`, `localhost`, and `::1` into both `process.env.NO_PROXY` and `process.env.no_proxy`. This guarantees that `configureProxyDispatcher(process.env)` in `server.ts` always receives a `process.env` that already excludes loopback from proxying. Do not flag the absence of a loopback-merge inside `configureProxyDispatcher` or `normalizeProxyConfig` — the exclusion is already enforced at a higher layer before those functions are ever called.
Applied to files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-22T09:32:54.556Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/opencode/test/provider/provider.test.ts:64-85
Timestamp: 2026-04-22T09:32:54.556Z
Learning: In `packages/opencode/test/provider/provider.test.ts`, the file intentionally uses AppRuntime-based async helpers (`run`, `list`, `getProvider`, etc.) rather than `testEffect(...)` for all tests. Converting individual tests to `testEffect` while leaving the rest on the async pattern would create internal inconsistency. A full harness migration of this file is the right approach if the pattern needs to change, but that should be a separate PR.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Import test utilities from `../fixtures` instead of `playwright/test`
Applied to files:
packages/opencode/test/session/instruction.test.tspackages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Define `const it = testEffect(...)` near the top of the test file and keep the test body inside `Effect.gen(function* () { ... })`. Yield services directly with `yield* MyService.Service` or `yield* MyTool`.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T09:32:58.310Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/ui/src/theme/context.tsx:11-16
Timestamp: 2026-04-22T09:32:58.310Z
Learning: In Astro-Han/pawwork (`packages/ui/src/theme/context.tsx` and related files), the renaming of localStorage theme keys from `opencode-*` to `pawwork-*` (THEME_ID, COLOR_SCHEME, THEME_CSS_LIGHT, THEME_CSS_DARK) is intentional and should NOT include a migration path from the old keys. Migrating would re-couple PawWork and OpenCode browser storage namespaces, which the PR is explicitly designed to avoid. A reset to the PawWork default theme on upgrade is acceptable by design.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Use `InstanceState` from `src/effect/instance-state.ts` for per-directory or per-project state that needs per-instance cleanup; do work directly in the `InstanceState.make` closure where `ScopedCache` handles run-once semantics
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Prefer `FileSystem.FileSystem` instead of raw `fs/promises` for effectful file I/O in Effect services
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-23T08:51:04.230Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 186
File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144
Timestamp: 2026-04-23T08:51:04.230Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/util/filesystem.ts`), the `Filesystem` utility does NOT expose a `remove` or `unlink` helper. The established repository pattern for auth.json teardown in tests (e.g. `provider.test.ts`, `amazon-bedrock.test.ts`, `workspace-adaptor.test.ts`) is to combine `Filesystem.write` with `node:fs/promises unlink`. Do not flag this mixed usage as inconsistent — it is the correct and intentional pattern.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-25T12:52:36.999Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 234
File: packages/opencode/src/session/export.ts:75-88
Timestamp: 2026-04-25T12:52:36.999Z
Learning: In `packages/opencode/src/session/export.ts` (Astro-Han/pawwork), the `extractReasonFromCause` function intentionally uses a lightweight cast-based inspection of the Cause `reasons` array instead of `Cause.failures()` / `Cause.defects()` utilities. This is a deliberate choice: the function is diagnostic-only (used to populate a best-effort reason string for export diagnostics), and the maintainer explicitly prefers not to add coupling to Effect's Cause API surface for this purpose. Do not flag this pattern as fragile or suggest replacing it with Cause utilities.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-24T17:12:23.931Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 224
File: packages/desktop-electron/electron-builder.config.ts:14-18
Timestamp: 2026-04-24T17:12:23.931Z
Learning: In Astro-Han/pawwork, the `localizedMacDisplayNameByChannel` map in `packages/desktop-electron/electron-builder.config.ts` is intentionally kept separate from `localizedAppDisplayName` in `packages/desktop-electron/src/main/app-display-name.ts`. The former is a build-time packaging helper; the latter is a runtime UI helper that localizes the current app name by locale. Coupling them would introduce a build-time dependency on runtime main logic. Do not suggest deduplicating or sharing this mapping — the explicit local table is covered by focused regression tests in `electron-builder-app-update.test.ts`.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-24T17:08:44.294Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 224
File: packages/app/src/i18n/zh.ts:0-0
Timestamp: 2026-04-24T17:08:44.294Z
Learning: In Astro-Han/pawwork PR `#224`, the first-occurrence `PawWork 爪印` branding rule originally specified in issue `#196` was superseded by an updated Chinese-branding spec. On all zh UI surfaces in `packages/app/src/i18n/zh.ts` (e.g., `dialog.model.unpaid.freeModels.title`, `session.new.subtitle`, `sidebar.gettingStarted.line1`), the correct and intentional target is fully localized `爪印` branding — no `PawWork` prefix. Do NOT flag these strings as missing the first-occurrence `PawWork 爪印` rule in future reviews.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:21:56.373Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 71
File: packages/app/src/components/session/session-status-connections.tsx:146-147
Timestamp: 2026-04-20T14:21:56.373Z
Learning: In the Astro-Han/pawwork repository (SolidJS app), `sync.data.config` is always initialized to `{}` at `packages/app/src/context/global-sync.tsx` line 71 and is never `undefined` at runtime. Non-optional property access like `sync.data.config.plugin` is intentional and consistent with the pattern used in `packages/app/src/components/status-popover-body.tsx` line 243. Do not flag `sync.data.config.plugin` as needing optional chaining.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-21T13:45:45.149Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 99
File: packages/desktop-electron/src/renderer/i18n/index.ts:30-35
Timestamp: 2026-04-21T13:45:45.149Z
Learning: In Astro-Han/pawwork, the locale normalization helpers in `packages/app/src/context/language.tsx` (`normalizeLocale`) and `packages/desktop-electron/src/renderer/i18n/index.ts` (`parseLocale`) are intentionally kept separate and have different fallback shapes: `normalizeLocale` always returns a concrete `Locale` (falling back to `"en"`), while `parseLocale` returns `Locale | null` so the desktop shell can decide whether to fall back to browser detection. Do not suggest extracting a shared normalization helper across these two runtimes.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-25T09:19:30.734Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 231
File: packages/desktop-electron/src/main/index.ts:537-537
Timestamp: 2026-04-25T09:19:30.734Z
Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/`), the convention for IPC registration is that `index.ts` (the bootstrap entry) directly calls each registration function. `registerIpcHandlers({...})` in `src/main/ipc.ts` is a single fat options-bag with inline handler bodies. New, cohesive IPC features (e.g., About) are placed in sub-modules like `src/main/ipc/about.ts`, which own their own exported types, helpers, and a `register*Ipc()` function. The bootstrap in `index.ts` calls each `register*Ipc()` directly — this is intentional, not fragmentation. Do NOT suggest routing sub-module IPC registrations through `ipc.ts`.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-23T17:02:40.117Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 198
File: packages/app/src/index.css:95-97
Timestamp: 2026-04-23T17:02:40.117Z
Learning: In Astro-Han/pawwork, Stylelint is NOT configured in the project. Per AGENTS.md, only linting (not formatting) is used, and the Biome formatter is explicitly disabled. Do NOT raise Stylelint-based review comments (e.g., `declaration-empty-line-before`) in this repo, as they are false positives from the static analysis environment and not enforced by the project toolchain.
Applied to files:
packages/opencode/src/session/instruction.ts
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
packages/opencode/src/session/instruction.ts (1)
159-163:⚠️ Potential issue | 🟠 MajorUnify
~/expansion betweensystemPaths()andsources()to keep prompt and diagnostics in sync.On Line 162,
systemPaths()expands withos.homedir(), while on Line 247,sources()expands withGlobal.Path.home. This can report a different file path than the one actually loaded.🔧 Proposed fix
-import os from "os" import path from "path" @@ +const expandHomeInstruction = (value: string) => + value.startsWith("~/") ? path.join(Global.Path.home, value.slice(2)) : value + @@ - const instruction = raw.startsWith("~/") ? path.join(os.homedir(), raw.slice(2)) : raw + const instruction = expandHomeInstruction(raw) @@ - const instruction = raw.startsWith("~/") ? path.join(Global.Path.home, raw.slice(2)) : raw + const instruction = expandHomeInstruction(raw)Also applies to: 243-248
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/src/session/instruction.ts` around lines 159 - 163, The code expands "~/..." differently in systemPaths() (using os.homedir()) vs sources() (using Global.Path.home); unify them by changing the expansion in systemPaths() so the raw.startsWith("~/") branch uses the same Global.Path.home mechanism used by sources(), ensuring both systemPaths() and sources() produce identical absolute paths for "~/..." inputs and keeping prompts and diagnostics in sync; update all occurrences of the "~/..." expansion logic (including the similar case around the sources() logic) to use the same Global.Path.home-based expansion routine.
🤖 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/opencode/test/session/instruction.test.ts`:
- Around line 588-606: The test title string for the test starting with
test("sources() reports config.instructions URL as loaded when fetch succeeds",
...) is misleading because the test sets up an unreachable URL and asserts the
considered-with-reason branch; change that first argument to a neutral, accurate
description (e.g. "sources() reports config.instructions URL as loaded or
considered when fetch is unavailable") so the test name matches behavior; update
only the test name literal in the test(...) call that wraps the existing setup
and assertions.
---
Duplicate comments:
In `@packages/opencode/src/session/instruction.ts`:
- Around line 159-163: The code expands "~/..." differently in systemPaths()
(using os.homedir()) vs sources() (using Global.Path.home); unify them by
changing the expansion in systemPaths() so the raw.startsWith("~/") branch uses
the same Global.Path.home mechanism used by sources(), ensuring both
systemPaths() and sources() produce identical absolute paths for "~/..." inputs
and keeping prompts and diagnostics in sync; update all occurrences of the
"~/..." expansion logic (including the similar case around the sources() logic)
to use the same Global.Path.home-based expansion routine.
🪄 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: 15a705b5-b2c0-47fd-9b9c-f15f0418dda3
📒 Files selected for processing (2)
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: unit-windows-app
- GitHub Check: unit-windows-opencode-session
- GitHub Check: unit-windows-opencode-config-project
- GitHub Check: unit-windows-opencode-server-tools
- GitHub Check: unit-windows-desktop
- GitHub Check: unit-opencode
- GitHub Check: smoke-macos-arm64
- GitHub Check: e2e-artifacts
- GitHub Check: analyze-js-ts
🧰 Additional context used
📓 Path-based instructions (2)
packages/opencode/**/*.ts
📄 CodeRabbit inference engine (packages/opencode/AGENTS.md)
packages/opencode/**/*.ts: UseEffect.gen(function* () { ... })for Effect composition
UseEffect.fn("Domain.method")for named/traced effects andEffect.fnUntracedfor internal helpers; these accept pipeable operators as extra arguments to avoid unnecessary outer.pipe()wrappers
UseEffect.callbackfor callback-based APIs
PreferDateTime.nowAsDateovernew Date(yield* Clock.currentTimeMillis)when you need aDatein Effect code
UseSchema.Classfor multi-field data in Effect schemas
Use branded schemas (Schema.brand) for single-value types in Effect
UseSchema.TaggedErrorClassfor typed errors in Effect schemas
UseSchema.Defectinstead ofunknownfor defect-like causes in Effect code
InEffect.gen/Effect.fn, preferyield* new MyError(...)overyield* Effect.fail(new MyError(...))for direct early-failure branches
UsemakeRuntimefromsrc/effect/run-service.tsfor all services; it returns{ runPromise, runFork, runCallback }backed by a sharedmemoMapthat deduplicates layers
UseInstanceStatefromsrc/effect/instance-state.tsfor per-directory or per-project state that needs per-instance cleanup; do work directly in theInstanceState.makeclosure whereScopedCachehandles run-once semantics
UseEffect.addFinalizerorEffect.acquireReleaseinside theInstanceState.makeclosure for cleanup (subscriptions, process teardown, etc.)
UseEffect.forkScopedinside theInstanceState.makeclosure for background stream consumers — the fiber is interrupted when the instance is disposed
PreferFileSystem.FileSysteminstead of rawfs/promisesfor effectful file I/O in Effect services
PreferChildProcessSpawner.ChildProcessSpawnerwithChildProcess.make(...)instead of custom process wrappers in Effect services
PreferHttpClient.HttpClientinstead of rawfetchin Effect services
PreferPath.Path,Config,Clock, andDateTimeservices when those concerns are already inside Effect code
For backgroun...
Files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
packages/opencode/test/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (packages/opencode/test/AGENTS.md)
packages/opencode/test/**/*.test.{ts,tsx}: Use thetmpdirfunction fromfixture/fixture.tsto create temporary directories for tests with automatic cleanup. Useawait usingsyntax to ensure automatic cleanup when the variable goes out of scope.
When using thetmpdirfunction with git repository support, pass thegit: trueoption to initialize a git repo with a root commit.
Use theconfigoption intmpdirto write anopencode.jsonconfig file during test setup by passing a partial Config.Info object.
Use theinitoption intmpdirto define custom setup functions that can return extra data accessible viatmp.extra, and use thedisposeoption for custom cleanup logic.
UsetestEffect(...)fromtest/lib/effect.tsfor tests that exercise Effect services or Effect-based workflows.
Useit.effect(...)when the test should run withTestClockandTestConsole. Useit.live(...)when the test depends on real time, filesystem mtimes, child processes, git, locks, or other live OS behavior.
Prefer Effect-aware helpers fromfixture/fixture.tsover building manual runtimes in tests: usetmpdirScoped()for scoped temp directories,provideInstance(dir)(effect)for low-level binding without directory creation,provideTmpdirInstance(...)for single temp instance binding, orprovideTmpdirServer(...)for tests that also need the test LLM server.
Defineconst it = testEffect(...)near the top of the test file and keep the test body insideEffect.gen(function* () { ... }). Yield services directly withyield* MyService.Serviceoryield* MyTool.
Avoid customManagedRuntime,attach(...), or ad hocrun(...)wrappers in Effect tests whentestEffect(...)already provides the runtime.
When a test needs instance-local state, preferprovideTmpdirInstance(...)orprovideInstance(...)over manualInstance.provide(...)inside Promise-style tests.
Files:
packages/opencode/test/session/instruction.test.ts
🧠 Learnings (32)
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Use `InstanceState` from `src/effect/instance-state.ts` for per-directory or per-project state that needs per-instance cleanup; do work directly in the `InstanceState.make` closure where `ScopedCache` handles run-once semantics
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-23T08:51:04.230Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 186
File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144
Timestamp: 2026-04-23T08:51:04.230Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/util/filesystem.ts`), the `Filesystem` utility does NOT expose a `remove` or `unlink` helper. The established repository pattern for auth.json teardown in tests (e.g. `provider.test.ts`, `amazon-bedrock.test.ts`, `workspace-adaptor.test.ts`) is to combine `Filesystem.write` with `node:fs/promises unlink`. Do not flag this mixed usage as inconsistent — it is the correct and intentional pattern.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `tmpdir` function from `fixture/fixture.ts` to create temporary directories for tests with automatic cleanup. Use `await using` syntax to ensure automatic cleanup when the variable goes out of scope.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Prefer Effect-aware helpers from `fixture/fixture.ts` over building manual runtimes in tests: use `tmpdirScoped()` for scoped temp directories, `provideInstance(dir)(effect)` for low-level binding without directory creation, `provideTmpdirInstance(...)` for single temp instance binding, or `provideTmpdirServer(...)` for tests that also need the test LLM server.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When using the `tmpdir` function with git repository support, pass the `git: true` option to initialize a git repo with a root commit.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T08:49:47.800Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/desktop-electron/src/main/index-sidecar-source.test.ts:3-11
Timestamp: 2026-04-22T08:49:47.800Z
Learning: In `packages/desktop-electron/src/main/index-sidecar-source.test.ts` (Astro-Han/pawwork), the test intentionally uses `expect(source).toContain` / `expect(source).not.toContain` string matching against the raw `index.ts` source text as a lightweight sidecar contract guard. The maintainer has explicitly chosen not to introduce an AST parser (e.g., `babel/parser` or acorn) for this purpose. Do not flag these string-based assertions as fragile or suggest converting them to AST-based matching.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-25T12:52:36.999Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 234
File: packages/opencode/src/session/export.ts:75-88
Timestamp: 2026-04-25T12:52:36.999Z
Learning: In `packages/opencode/src/session/export.ts` (Astro-Han/pawwork), the `extractReasonFromCause` function intentionally uses a lightweight cast-based inspection of the Cause `reasons` array instead of `Cause.failures()` / `Cause.defects()` utilities. This is a deliberate choice: the function is diagnostic-only (used to populate a best-effort reason string for export diagnostics), and the maintainer explicitly prefers not to add coupling to Effect's Cause API surface for this purpose. Do not flag this pattern as fragile or suggest replacing it with Cause utilities.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `config` option in `tmpdir` to write an `opencode.json` config file during test setup by passing a partial Config.Info object.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `init` option in `tmpdir` to define custom setup functions that can return extra data accessible via `tmp.extra`, and use the `dispose` option for custom cleanup logic.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When a test needs instance-local state, prefer `provideTmpdirInstance(...)` or `provideInstance(...)` over manual `Instance.provide(...)` inside Promise-style tests.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T00:02:53.315Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 203
File: packages/app/e2e/sidebar/sidebar-session-links.spec.ts:34-55
Timestamp: 2026-04-24T00:02:53.315Z
Learning: In Astro-Han/pawwork E2E tests (`packages/app/e2e/**/*.spec.ts`), `project.trackDirectory()` and `project.trackSession()` cannot be called before `project.open()` — the `project` fixture throws until `open()` initializes its internal state. The correct pattern is: call `project.trackSession(sessionID)` from inside the `beforeGoto` callback (where state already exists), call `project.trackDirectory(directory)` and cross-workspace `project.trackSession(id, directory)` immediately after `project.open()` returns, and rely on explicit `finally` cleanup (e.g. `cleanupSession` / `cleanupTestProject`) for any resources created before `open()` that cannot yet be tracked via the fixture.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Import test utilities from `../fixtures` instead of `playwright/test`
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T17:12:23.931Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 224
File: packages/desktop-electron/electron-builder.config.ts:14-18
Timestamp: 2026-04-24T17:12:23.931Z
Learning: In Astro-Han/pawwork, the `localizedMacDisplayNameByChannel` map in `packages/desktop-electron/electron-builder.config.ts` is intentionally kept separate from `localizedAppDisplayName` in `packages/desktop-electron/src/main/app-display-name.ts`. The former is a build-time packaging helper; the latter is a runtime UI helper that localizes the current app name by locale. Coupling them would introduce a build-time dependency on runtime main logic. Do not suggest deduplicating or sharing this mapping — the explicit local table is covered by focused regression tests in `electron-builder-app-update.test.ts`.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-25T11:52:40.349Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 233
File: packages/desktop-electron/src/main/server.ts:60-60
Timestamp: 2026-04-25T11:52:40.349Z
Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/index.ts`), `ensureLoopbackNoProxy()` (defined at line 551) is called inside `setupApp()` at line 263, which runs synchronously before `initialize()` (line 321) and `spawnLocalServer()` (line 395). It unconditionally upserts `127.0.0.1`, `localhost`, and `::1` into both `process.env.NO_PROXY` and `process.env.no_proxy`. This guarantees that `configureProxyDispatcher(process.env)` in `server.ts` always receives a `process.env` that already excludes loopback from proxying. Do not flag the absence of a loopback-merge inside `configureProxyDispatcher` or `normalizeProxyConfig` — the exclusion is already enforced at a higher layer before those functions are ever called.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T17:08:44.294Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 224
File: packages/app/src/i18n/zh.ts:0-0
Timestamp: 2026-04-24T17:08:44.294Z
Learning: In Astro-Han/pawwork PR `#224`, the first-occurrence `PawWork 爪印` branding rule originally specified in issue `#196` was superseded by an updated Chinese-branding spec. On all zh UI surfaces in `packages/app/src/i18n/zh.ts` (e.g., `dialog.model.unpaid.freeModels.title`, `session.new.subtitle`, `sidebar.gettingStarted.line1`), the correct and intentional target is fully localized `爪印` branding — no `PawWork` prefix. Do NOT flag these strings as missing the first-occurrence `PawWork 爪印` rule in future reviews.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:21:56.373Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 71
File: packages/app/src/components/session/session-status-connections.tsx:146-147
Timestamp: 2026-04-20T14:21:56.373Z
Learning: In the Astro-Han/pawwork repository (SolidJS app), `sync.data.config` is always initialized to `{}` at `packages/app/src/context/global-sync.tsx` line 71 and is never `undefined` at runtime. Non-optional property access like `sync.data.config.plugin` is intentional and consistent with the pattern used in `packages/app/src/components/status-popover-body.tsx` line 243. Do not flag `sync.data.config.plugin` as needing optional chaining.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-21T13:45:45.149Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 99
File: packages/desktop-electron/src/renderer/i18n/index.ts:30-35
Timestamp: 2026-04-21T13:45:45.149Z
Learning: In Astro-Han/pawwork, the locale normalization helpers in `packages/app/src/context/language.tsx` (`normalizeLocale`) and `packages/desktop-electron/src/renderer/i18n/index.ts` (`parseLocale`) are intentionally kept separate and have different fallback shapes: `normalizeLocale` always returns a concrete `Locale` (falling back to `"en"`), while `parseLocale` returns `Locale | null` so the desktop shell can decide whether to fall back to browser detection. Do not suggest extracting a shared normalization helper across these two runtimes.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-25T09:19:30.734Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 231
File: packages/desktop-electron/src/main/index.ts:537-537
Timestamp: 2026-04-25T09:19:30.734Z
Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/`), the convention for IPC registration is that `index.ts` (the bootstrap entry) directly calls each registration function. `registerIpcHandlers({...})` in `src/main/ipc.ts` is a single fat options-bag with inline handler bodies. New, cohesive IPC features (e.g., About) are placed in sub-modules like `src/main/ipc/about.ts`, which own their own exported types, helpers, and a `register*Ipc()` function. The bootstrap in `index.ts` calls each `register*Ipc()` directly — this is intentional, not fragmentation. Do NOT suggest routing sub-module IPC registrations through `ipc.ts`.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-23T17:02:40.117Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 198
File: packages/app/src/index.css:95-97
Timestamp: 2026-04-23T17:02:40.117Z
Learning: In Astro-Han/pawwork, Stylelint is NOT configured in the project. Per AGENTS.md, only linting (not formatting) is used, and the Biome formatter is explicitly disabled. Do NOT raise Stylelint-based review comments (e.g., `declaration-empty-line-before`) in this repo, as they are false positives from the static analysis environment and not enforced by the project toolchain.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-21T16:57:25.580Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 102
File: packages/opencode/src/config/agent.ts:108-119
Timestamp: 2026-04-21T16:57:25.580Z
Learning: In `packages/opencode/src/config/agent.ts` (Astro-Han/pawwork), `ConfigPermission.Info` only accepts permission objects or the three action strings `"ask"`, `"allow"`, `"deny"`, and transforms those action strings into `{ "*": action }` before `normalize()` runs. By the time `normalize()` is reached, `configuredPermission` is always either `undefined` or a `Record<string, Rule>` — never a raw arbitrary string. The `Object.assign(permission, configuredPermission)` pattern is therefore safe. Do not flag it as corrupting string permission references.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-25T12:52:47.074Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 234
File: packages/opencode/src/share/session.ts:27-27
Timestamp: 2026-04-25T12:52:47.074Z
Learning: In `packages/opencode/src/share/session.ts`, the local `ensureEnabled` closure is intentionally duplicated from `ShareRuntime.ensureEnabled` in `runtime.ts`. Using the shared `ShareRuntime.ensureEnabled` effect directly would leak `CloudShareGate` back into the `R` (requirement) type of `share`, `unshare`, and `create`, because the shared effect re-yields the service rather than capturing an already-resolved gate reference. The current pattern resolves `gate` once at the top of the outer `Effect.gen` and then closes over it in a local `ensureEnabled`, keeping the inner effects' requirement types clean. A comment in the file points to `runtime.ts` to make the intentional duplication discoverable. The real fix would be refactoring `ensureEnabled` to accept a gate parameter, but that change is larger than the DRY benefit warrants. Do not flag this duplication as a maintenance issue.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-23T08:51:00.819Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 186
File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144
Timestamp: 2026-04-23T08:51:00.819Z
Learning: For pawwork tests under packages/opencode/test/**, auth.json teardown may intentionally combine `Filesystem.write` (from `packages/opencode/src/util/filesystem.ts`) with `node:fs/promises` `unlink` for cleanup. Do not flag this as inconsistent style; it is the established/intentional pattern because `Filesystem` does not provide a `remove`/`unlink` helper.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T17:03:40.214Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 73
File: packages/opencode/src/cli/cmd/tui/context/sync.tsx:486-489
Timestamp: 2026-04-20T17:03:40.214Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/cli/cmd/tui/context/sync.tsx`), `sync.ready` returning `true` when `process.env.OPENCODE_FAST_BOOT` is set is intentional. The plugin-facing data properties `state.config` (initialized to `{}`) and `state.provider` (initialized to `[]`) expose safe-empty defaults, so they are safe to access before bootstrap completes. Do not flag these as needing null-guards or conditional patterns to match `vcs` — the difference is intentional because `vcs` starts as `undefined` while the others have initialized defaults. Changing this would alter the plugin API contract without a concrete failing case.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/packages/app/src/testing/**/*.ts : Test-only hooks must be inert unless explicitly enabled and should not add normal-runtime listeners, reactive subscriptions, or per-update allocations
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Avoid custom `ManagedRuntime`, `attach(...)`, or ad hoc `run(...)` wrappers in Effect tests when `testEffect(...)` already provides the runtime.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : When validating routing, assert against canonical or resolved workspace slugs using shared helpers from `../actions` to account for Windows canonicalization
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T03:51:54.050Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 206
File: packages/app/e2e/prompt/prompt-footer-focus.spec.ts:131-143
Timestamp: 2026-04-24T03:51:54.050Z
Learning: In Astro-Han/pawwork E2E tests (packages/app/e2e/fixtures.ts), `project.prompt(text)` internally calls `trackSession(next.sessionID, active.directory)` after the prompt submission is observed and the active session is resolved. Tests that obtain a `sessionID` from `project.prompt()` do NOT need to call `project.trackSession(sessionID)` manually — it is already registered for teardown. Calling it again would be duplicate ownership.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-26T16:34:54.895Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 247
File: packages/ui/src/components/message-part.tsx:1322-1324
Timestamp: 2026-04-26T16:34:54.895Z
Learning: In Astro-Han/pawwork (`packages/ui/src/components/message-part.tsx`), the `taskId` createMemo and `childSessionId` createMemo both intentionally read only from `partMetadata().sessionId` (populated post-execution), not from `input.task_id` / `input.subagent_session_id`. This has always been the case — the original code never read the input field either. Adding an `input.subagent_session_id` fallback would be a new capability, not a bug fix. Do NOT flag the absence of this fallback as a regression in PR `#247` or future PRs unless there is a concrete case where metadata is not populated.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-26T15:35:31.757Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 245
File: packages/opencode/src/question/index.ts:21-24
Timestamp: 2026-04-26T15:35:31.757Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/question/index.ts`), `Question.Option.description` is intentionally **required** (`z.string()`, not `.optional()`). This matches the upstream opencode contract and all current callers (e.g. `PlanExitTool`) always supply a description. The defensive `<Show when={props.description}>` rendering in `session-question-dock.tsx` is a standard guard, not a signal that the field is intended to be optional. Do NOT suggest making `Option.description` optional without a dedicated follow-up that covers schema + tool description + dock copy + tests.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T09:32:54.556Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/opencode/test/provider/provider.test.ts:64-85
Timestamp: 2026-04-22T09:32:54.556Z
Learning: In `packages/opencode/test/provider/provider.test.ts`, the file intentionally uses AppRuntime-based async helpers (`run`, `list`, `getProvider`, etc.) rather than `testEffect(...)` for all tests. Converting individual tests to `testEffect` while leaving the rest on the async pattern would create internal inconsistency. A full harness migration of this file is the right approach if the pattern needs to change, but that should be a separate PR.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Define `const it = testEffect(...)` near the top of the test file and keep the test body inside `Effect.gen(function* () { ... })`. Yield services directly with `yield* MyService.Service` or `yield* MyTool`.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T09:32:58.310Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/ui/src/theme/context.tsx:11-16
Timestamp: 2026-04-22T09:32:58.310Z
Learning: In Astro-Han/pawwork (`packages/ui/src/theme/context.tsx` and related files), the renaming of localStorage theme keys from `opencode-*` to `pawwork-*` (THEME_ID, COLOR_SCHEME, THEME_CSS_LIGHT, THEME_CSS_DARK) is intentional and should NOT include a migration path from the old keys. Migrating would re-couple PawWork and OpenCode browser storage namespaces, which the PR is explicitly designed to avoid. A reset to the PawWork default theme on upgrade is acceptable by design.
Applied to files:
packages/opencode/test/session/instruction.test.ts
🔇 Additional comments (2)
packages/opencode/src/session/instruction.ts (1)
36-41: PawWork/non-PawWork Claude fallback gate is correctly scoped.The runtime check keeps Claude global fallback disabled in PawWork while preserving existing opencode CLI behavior behind
OPENCODE_DISABLE_CLAUDE_CODE_PROMPT.packages/opencode/test/session/instruction.test.ts (1)
493-952: Great coverage expansion for fallback order + diagnostics contracts.The new cases exercise PawWork mode, non-PawWork regression behavior, project/global precedence, and
sources()status reporting (loaded/considered/ignored) in a focused way.
Re: CodeRabbit outside-diff range comment on
|
896f9db to
597fd9e
Compare
Update on outside-diff finding (
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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/opencode/src/session/instruction.ts`:
- Around line 217-223: The code currently marks files found by FILES() (via
yield* fs.findUp(...), using Instance.directory/Instance.worktree) as {status:
"loaded"} and adds them to loadedPaths before actually reading their contents;
instead call the existing read() helper on each resolved path (the same one used
by system()) and only push {status: "loaded", path: resolved} and add to
loadedPaths when read() returns non-empty content; if read() returns empty or
throws, push {status: "considered", path: resolved, reason: "<empty or
unreadable>"} (or similar) to keep diagnostics/provenance aligned with system();
apply the same change to the other similar branches around the references you
mentioned (the blocks at the other occurrences).
- Around line 215-228: The project-level file lookup in sources() currently only
pushes the winning file into result and loadedPaths (inside the
Flag.OPENCODE_DISABLE_PROJECT_CONFIG branch using FILES(), fs.findUp,
Instance.directory, Instance.worktree), which drops lower-priority candidates;
modify this loop so that after calling fs.findUp for each file you: for each
found match push a result entry marking the first found file as
{status:"loaded", path: resolved} and any later existing matches as
{status:"considered", path: resolved, reason: "project-priority"} (and for files
not found push {status:"considered", path: expectedPath, reason: "absent"}), and
ensure loadedPaths still records only the actual loaded winner; mirror the same
global-chain semantics used by system() so diagnostics can show loaded vs
considered vs absent project fallbacks.
- Around line 290-299: The current loop in sources() that iterates over
config.instructions and does sequential yield* fetch(url) causes per-URL
timeouts to stack; replace the serialized fetches with a concurrent batch using
Effect.forEach(urls, fetch, { concurrency: 4 }) (or the project's equivalent
concurrent runner) to fetch all urls with concurrency=4, then iterate the
ordered responses and push the same shape into result (status: "loaded" when
body truthy, otherwise status: "considered" with reason "fetch failed or
returned empty body"), keeping the existing behavior and ordering; update the
code around the urls variable, fetch call, and result.push logic to use the
batched responses.
🪄 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: 1a4960ed-2923-4d08-9f03-e103d08e177f
📒 Files selected for processing (2)
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
- GitHub Check: unit-windows-opencode-session
- GitHub Check: unit-windows-opencode-server-tools
- GitHub Check: unit-windows-opencode-config-project
- GitHub Check: unit-windows-desktop
- GitHub Check: unit-windows-app
- GitHub Check: unit-opencode
- GitHub Check: typecheck
- GitHub Check: unit-app
- GitHub Check: unit-desktop
- GitHub Check: smoke-macos-arm64
- GitHub Check: analyze-js-ts
- GitHub Check: e2e-artifacts
🧰 Additional context used
📓 Path-based instructions (2)
packages/opencode/**/*.ts
📄 CodeRabbit inference engine (packages/opencode/AGENTS.md)
packages/opencode/**/*.ts: UseEffect.gen(function* () { ... })for Effect composition
UseEffect.fn("Domain.method")for named/traced effects andEffect.fnUntracedfor internal helpers; these accept pipeable operators as extra arguments to avoid unnecessary outer.pipe()wrappers
UseEffect.callbackfor callback-based APIs
PreferDateTime.nowAsDateovernew Date(yield* Clock.currentTimeMillis)when you need aDatein Effect code
UseSchema.Classfor multi-field data in Effect schemas
Use branded schemas (Schema.brand) for single-value types in Effect
UseSchema.TaggedErrorClassfor typed errors in Effect schemas
UseSchema.Defectinstead ofunknownfor defect-like causes in Effect code
InEffect.gen/Effect.fn, preferyield* new MyError(...)overyield* Effect.fail(new MyError(...))for direct early-failure branches
UsemakeRuntimefromsrc/effect/run-service.tsfor all services; it returns{ runPromise, runFork, runCallback }backed by a sharedmemoMapthat deduplicates layers
UseInstanceStatefromsrc/effect/instance-state.tsfor per-directory or per-project state that needs per-instance cleanup; do work directly in theInstanceState.makeclosure whereScopedCachehandles run-once semantics
UseEffect.addFinalizerorEffect.acquireReleaseinside theInstanceState.makeclosure for cleanup (subscriptions, process teardown, etc.)
UseEffect.forkScopedinside theInstanceState.makeclosure for background stream consumers — the fiber is interrupted when the instance is disposed
PreferFileSystem.FileSysteminstead of rawfs/promisesfor effectful file I/O in Effect services
PreferChildProcessSpawner.ChildProcessSpawnerwithChildProcess.make(...)instead of custom process wrappers in Effect services
PreferHttpClient.HttpClientinstead of rawfetchin Effect services
PreferPath.Path,Config,Clock, andDateTimeservices when those concerns are already inside Effect code
For backgroun...
Files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
packages/opencode/test/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (packages/opencode/test/AGENTS.md)
packages/opencode/test/**/*.test.{ts,tsx}: Use thetmpdirfunction fromfixture/fixture.tsto create temporary directories for tests with automatic cleanup. Useawait usingsyntax to ensure automatic cleanup when the variable goes out of scope.
When using thetmpdirfunction with git repository support, pass thegit: trueoption to initialize a git repo with a root commit.
Use theconfigoption intmpdirto write anopencode.jsonconfig file during test setup by passing a partial Config.Info object.
Use theinitoption intmpdirto define custom setup functions that can return extra data accessible viatmp.extra, and use thedisposeoption for custom cleanup logic.
UsetestEffect(...)fromtest/lib/effect.tsfor tests that exercise Effect services or Effect-based workflows.
Useit.effect(...)when the test should run withTestClockandTestConsole. Useit.live(...)when the test depends on real time, filesystem mtimes, child processes, git, locks, or other live OS behavior.
Prefer Effect-aware helpers fromfixture/fixture.tsover building manual runtimes in tests: usetmpdirScoped()for scoped temp directories,provideInstance(dir)(effect)for low-level binding without directory creation,provideTmpdirInstance(...)for single temp instance binding, orprovideTmpdirServer(...)for tests that also need the test LLM server.
Defineconst it = testEffect(...)near the top of the test file and keep the test body insideEffect.gen(function* () { ... }). Yield services directly withyield* MyService.Serviceoryield* MyTool.
Avoid customManagedRuntime,attach(...), or ad hocrun(...)wrappers in Effect tests whentestEffect(...)already provides the runtime.
When a test needs instance-local state, preferprovideTmpdirInstance(...)orprovideInstance(...)over manualInstance.provide(...)inside Promise-style tests.
Files:
packages/opencode/test/session/instruction.test.ts
🧠 Learnings (44)
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Use `InstanceState` from `src/effect/instance-state.ts` for per-directory or per-project state that needs per-instance cleanup; do work directly in the `InstanceState.make` closure where `ScopedCache` handles run-once semantics
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-23T08:51:04.230Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 186
File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144
Timestamp: 2026-04-23T08:51:04.230Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/util/filesystem.ts`), the `Filesystem` utility does NOT expose a `remove` or `unlink` helper. The established repository pattern for auth.json teardown in tests (e.g. `provider.test.ts`, `amazon-bedrock.test.ts`, `workspace-adaptor.test.ts`) is to combine `Filesystem.write` with `node:fs/promises unlink`. Do not flag this mixed usage as inconsistent — it is the correct and intentional pattern.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `tmpdir` function from `fixture/fixture.ts` to create temporary directories for tests with automatic cleanup. Use `await using` syntax to ensure automatic cleanup when the variable goes out of scope.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Prefer Effect-aware helpers from `fixture/fixture.ts` over building manual runtimes in tests: use `tmpdirScoped()` for scoped temp directories, `provideInstance(dir)(effect)` for low-level binding without directory creation, `provideTmpdirInstance(...)` for single temp instance binding, or `provideTmpdirServer(...)` for tests that also need the test LLM server.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When using the `tmpdir` function with git repository support, pass the `git: true` option to initialize a git repo with a root commit.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T08:49:47.800Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/desktop-electron/src/main/index-sidecar-source.test.ts:3-11
Timestamp: 2026-04-22T08:49:47.800Z
Learning: In `packages/desktop-electron/src/main/index-sidecar-source.test.ts` (Astro-Han/pawwork), the test intentionally uses `expect(source).toContain` / `expect(source).not.toContain` string matching against the raw `index.ts` source text as a lightweight sidecar contract guard. The maintainer has explicitly chosen not to introduce an AST parser (e.g., `babel/parser` or acorn) for this purpose. Do not flag these string-based assertions as fragile or suggest converting them to AST-based matching.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-25T12:52:36.999Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 234
File: packages/opencode/src/session/export.ts:75-88
Timestamp: 2026-04-25T12:52:36.999Z
Learning: In `packages/opencode/src/session/export.ts` (Astro-Han/pawwork), the `extractReasonFromCause` function intentionally uses a lightweight cast-based inspection of the Cause `reasons` array instead of `Cause.failures()` / `Cause.defects()` utilities. This is a deliberate choice: the function is diagnostic-only (used to populate a best-effort reason string for export diagnostics), and the maintainer explicitly prefers not to add coupling to Effect's Cause API surface for this purpose. Do not flag this pattern as fragile or suggest replacing it with Cause utilities.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `config` option in `tmpdir` to write an `opencode.json` config file during test setup by passing a partial Config.Info object.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use the `init` option in `tmpdir` to define custom setup functions that can return extra data accessible via `tmp.extra`, and use the `dispose` option for custom cleanup logic.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : When a test needs instance-local state, prefer `provideTmpdirInstance(...)` or `provideInstance(...)` over manual `Instance.provide(...)` inside Promise-style tests.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T00:02:53.315Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 203
File: packages/app/e2e/sidebar/sidebar-session-links.spec.ts:34-55
Timestamp: 2026-04-24T00:02:53.315Z
Learning: In Astro-Han/pawwork E2E tests (`packages/app/e2e/**/*.spec.ts`), `project.trackDirectory()` and `project.trackSession()` cannot be called before `project.open()` — the `project` fixture throws until `open()` initializes its internal state. The correct pattern is: call `project.trackSession(sessionID)` from inside the `beforeGoto` callback (where state already exists), call `project.trackDirectory(directory)` and cross-workspace `project.trackSession(id, directory)` immediately after `project.open()` returns, and rely on explicit `finally` cleanup (e.g. `cleanupSession` / `cleanupTestProject`) for any resources created before `open()` that cannot yet be tracked via the fixture.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Import test utilities from `../fixtures` instead of `playwright/test`
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T17:12:23.931Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 224
File: packages/desktop-electron/electron-builder.config.ts:14-18
Timestamp: 2026-04-24T17:12:23.931Z
Learning: In Astro-Han/pawwork, the `localizedMacDisplayNameByChannel` map in `packages/desktop-electron/electron-builder.config.ts` is intentionally kept separate from `localizedAppDisplayName` in `packages/desktop-electron/src/main/app-display-name.ts`. The former is a build-time packaging helper; the latter is a runtime UI helper that localizes the current app name by locale. Coupling them would introduce a build-time dependency on runtime main logic. Do not suggest deduplicating or sharing this mapping — the explicit local table is covered by focused regression tests in `electron-builder-app-update.test.ts`.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-25T11:52:40.349Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 233
File: packages/desktop-electron/src/main/server.ts:60-60
Timestamp: 2026-04-25T11:52:40.349Z
Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/index.ts`), `ensureLoopbackNoProxy()` (defined at line 551) is called inside `setupApp()` at line 263, which runs synchronously before `initialize()` (line 321) and `spawnLocalServer()` (line 395). It unconditionally upserts `127.0.0.1`, `localhost`, and `::1` into both `process.env.NO_PROXY` and `process.env.no_proxy`. This guarantees that `configureProxyDispatcher(process.env)` in `server.ts` always receives a `process.env` that already excludes loopback from proxying. Do not flag the absence of a loopback-merge inside `configureProxyDispatcher` or `normalizeProxyConfig` — the exclusion is already enforced at a higher layer before those functions are ever called.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-24T17:08:44.294Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 224
File: packages/app/src/i18n/zh.ts:0-0
Timestamp: 2026-04-24T17:08:44.294Z
Learning: In Astro-Han/pawwork PR `#224`, the first-occurrence `PawWork 爪印` branding rule originally specified in issue `#196` was superseded by an updated Chinese-branding spec. On all zh UI surfaces in `packages/app/src/i18n/zh.ts` (e.g., `dialog.model.unpaid.freeModels.title`, `session.new.subtitle`, `sidebar.gettingStarted.line1`), the correct and intentional target is fully localized `爪印` branding — no `PawWork` prefix. Do NOT flag these strings as missing the first-occurrence `PawWork 爪印` rule in future reviews.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:21:56.373Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 71
File: packages/app/src/components/session/session-status-connections.tsx:146-147
Timestamp: 2026-04-20T14:21:56.373Z
Learning: In the Astro-Han/pawwork repository (SolidJS app), `sync.data.config` is always initialized to `{}` at `packages/app/src/context/global-sync.tsx` line 71 and is never `undefined` at runtime. Non-optional property access like `sync.data.config.plugin` is intentional and consistent with the pattern used in `packages/app/src/components/status-popover-body.tsx` line 243. Do not flag `sync.data.config.plugin` as needing optional chaining.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-21T13:45:45.149Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 99
File: packages/desktop-electron/src/renderer/i18n/index.ts:30-35
Timestamp: 2026-04-21T13:45:45.149Z
Learning: In Astro-Han/pawwork, the locale normalization helpers in `packages/app/src/context/language.tsx` (`normalizeLocale`) and `packages/desktop-electron/src/renderer/i18n/index.ts` (`parseLocale`) are intentionally kept separate and have different fallback shapes: `normalizeLocale` always returns a concrete `Locale` (falling back to `"en"`), while `parseLocale` returns `Locale | null` so the desktop shell can decide whether to fall back to browser detection. Do not suggest extracting a shared normalization helper across these two runtimes.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-25T09:19:30.734Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 231
File: packages/desktop-electron/src/main/index.ts:537-537
Timestamp: 2026-04-25T09:19:30.734Z
Learning: In Astro-Han/pawwork (`packages/desktop-electron/src/main/`), the convention for IPC registration is that `index.ts` (the bootstrap entry) directly calls each registration function. `registerIpcHandlers({...})` in `src/main/ipc.ts` is a single fat options-bag with inline handler bodies. New, cohesive IPC features (e.g., About) are placed in sub-modules like `src/main/ipc/about.ts`, which own their own exported types, helpers, and a `register*Ipc()` function. The bootstrap in `index.ts` calls each `register*Ipc()` directly — this is intentional, not fragmentation. Do NOT suggest routing sub-module IPC registrations through `ipc.ts`.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-23T17:02:40.117Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 198
File: packages/app/src/index.css:95-97
Timestamp: 2026-04-23T17:02:40.117Z
Learning: In Astro-Han/pawwork, Stylelint is NOT configured in the project. Per AGENTS.md, only linting (not formatting) is used, and the Biome formatter is explicitly disabled. Do NOT raise Stylelint-based review comments (e.g., `declaration-empty-line-before`) in this repo, as they are false positives from the static analysis environment and not enforced by the project toolchain.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-21T16:57:25.580Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 102
File: packages/opencode/src/config/agent.ts:108-119
Timestamp: 2026-04-21T16:57:25.580Z
Learning: In `packages/opencode/src/config/agent.ts` (Astro-Han/pawwork), `ConfigPermission.Info` only accepts permission objects or the three action strings `"ask"`, `"allow"`, `"deny"`, and transforms those action strings into `{ "*": action }` before `normalize()` runs. By the time `normalize()` is reached, `configuredPermission` is always either `undefined` or a `Record<string, Rule>` — never a raw arbitrary string. The `Object.assign(permission, configuredPermission)` pattern is therefore safe. Do not flag it as corrupting string permission references.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-23T15:10:26.994Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 191
File: packages/app/src/pages/layout/pawwork-sidebar.tsx:139-139
Timestamp: 2026-04-23T15:10:26.994Z
Learning: In Astro-Han/pawwork, the icon registry in `packages/ui/src/components/icon.tsx` uses **bare (unquoted) TypeScript object keys** for single-word icon names (e.g., `pin:` at line 102, `workspace:` at line 99) and **quoted keys** only for hyphenated names (e.g., `"review-active":`). When verifying icon registration with `rg`, always search for both forms — use a pattern like `rg -n "(\"${key}\"|${key}:)"` — otherwise bare-key icons will be missed and incorrectly flagged as unregistered.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T17:03:40.214Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 73
File: packages/opencode/src/cli/cmd/tui/context/sync.tsx:486-489
Timestamp: 2026-04-20T17:03:40.214Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/cli/cmd/tui/context/sync.tsx`), `sync.ready` returning `true` when `process.env.OPENCODE_FAST_BOOT` is set is intentional. The plugin-facing data properties `state.config` (initialized to `{}`) and `state.provider` (initialized to `[]`) expose safe-empty defaults, so they are safe to access before bootstrap completes. Do not flag these as needing null-guards or conditional patterns to match `vcs` — the difference is intentional because `vcs` starts as `undefined` while the others have initialized defaults. Changing this would alter the plugin API contract without a concrete failing case.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T09:32:58.310Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/ui/src/theme/context.tsx:11-16
Timestamp: 2026-04-22T09:32:58.310Z
Learning: In Astro-Han/pawwork (`packages/ui/src/theme/context.tsx` and related files), the renaming of localStorage theme keys from `opencode-*` to `pawwork-*` (THEME_ID, COLOR_SCHEME, THEME_CSS_LIGHT, THEME_CSS_DARK) is intentional and should NOT include a migration path from the old keys. Migrating would re-couple PawWork and OpenCode browser storage namespaces, which the PR is explicitly designed to avoid. A reset to the PawWork default theme on upgrade is acceptable by design.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Prefer `HttpClient.HttpClient` instead of raw `fetch` in Effect services
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Prefer `Path.Path`, `Config`, `Clock`, and `DateTime` services when those concerns are already inside Effect code
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Prefer `FileSystem.FileSystem` instead of raw `fs/promises` for effectful file I/O in Effect services
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Use `Effect.fn("Domain.method")` for named/traced effects and `Effect.fnUntraced` for internal helpers; these accept pipeable operators as extra arguments to avoid unnecessary outer `.pipe()` wrappers
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-25T12:52:35.671Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 234
File: packages/opencode/src/session/export.ts:24-31
Timestamp: 2026-04-25T12:52:35.671Z
Learning: In `packages/opencode/src/session/export.ts`, the `hashFile` async helper intentionally uses raw `node:fs/promises` (`fs.readFile`) rather than `FileSystem.FileSystem`. It is a small, self-contained helper called inside `Effect.promise(...)` with broad failure tolerance (try/catch returning `undefined`). Using `FileSystem.FileSystem` here would add unnecessary layers without payoff. The `FileSystem.FileSystem` preference applies to Effect-service-style operations, not thin async boundary helpers like `hashFile`.
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Use `testEffect(...)` from `test/lib/effect.ts` for tests that exercise Effect services or Effect-based workflows.
Applied to files:
packages/opencode/src/session/instruction.tspackages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Use `Effect.gen(function* () { ... })` for Effect composition
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Use `makeRuntime` from `src/effect/run-service.ts` for all services; it returns `{ runPromise, runFork, runCallback }` backed by a shared `memoMap` that deduplicates layers
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Prefer `ChildProcessSpawner.ChildProcessSpawner` with `ChildProcess.make(...)` instead of custom process wrappers in Effect services
Applied to files:
packages/opencode/src/session/instruction.ts
📚 Learning: 2026-04-24T03:51:54.050Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 206
File: packages/app/e2e/prompt/prompt-footer-focus.spec.ts:131-143
Timestamp: 2026-04-24T03:51:54.050Z
Learning: In Astro-Han/pawwork E2E tests (packages/app/e2e/fixtures.ts), `project.prompt(text)` internally calls `trackSession(next.sessionID, active.directory)` after the prompt submission is observed and the active session is resolved. Tests that obtain a `sessionID` from `project.prompt()` do NOT need to call `project.trackSession(sessionID)` manually — it is already registered for teardown. Calling it again would be duplicate ownership.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Prefer the `project` fixture for tests that need a dedicated project with LLM mocking
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : Call `project.trackSession(sessionID, directory?)` and `project.trackDirectory(directory)` for any resources created outside the fixture so teardown can clean them up
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-23T08:51:00.819Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 186
File: packages/opencode/test/plugin/workspace-adaptor.test.ts:139-144
Timestamp: 2026-04-23T08:51:00.819Z
Learning: For pawwork tests under packages/opencode/test/**, auth.json teardown may intentionally combine `Filesystem.write` (from `packages/opencode/src/util/filesystem.ts`) with `node:fs/promises` `unlink` for cleanup. Do not flag this as inconsistent style; it is the established/intentional pattern because `Filesystem` does not provide a `remove`/`unlink` helper.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/packages/app/src/testing/**/*.ts : Test-only hooks must be inert unless explicitly enabled and should not add normal-runtime listeners, reactive subscriptions, or per-update allocations
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Avoid custom `ManagedRuntime`, `attach(...)`, or ad hoc `run(...)` wrappers in Effect tests when `testEffect(...)` already provides the runtime.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:04.113Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/e2e/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:04.113Z
Learning: Applies to packages/app/e2e/**/*.spec.ts : When validating routing, assert against canonical or resolved workspace slugs using shared helpers from `../actions` to account for Windows canonicalization
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-26T16:34:54.895Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 247
File: packages/ui/src/components/message-part.tsx:1322-1324
Timestamp: 2026-04-26T16:34:54.895Z
Learning: In Astro-Han/pawwork (`packages/ui/src/components/message-part.tsx`), the `taskId` createMemo and `childSessionId` createMemo both intentionally read only from `partMetadata().sessionId` (populated post-execution), not from `input.task_id` / `input.subagent_session_id`. This has always been the case — the original code never read the input field either. Adding an `input.subagent_session_id` fallback would be a new capability, not a bug fix. Do NOT flag the absence of this fallback as a regression in PR `#247` or future PRs unless there is a concrete case where metadata is not populated.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-26T15:35:31.757Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 245
File: packages/opencode/src/question/index.ts:21-24
Timestamp: 2026-04-26T15:35:31.757Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/question/index.ts`), `Question.Option.description` is intentionally **required** (`z.string()`, not `.optional()`). This matches the upstream opencode contract and all current callers (e.g. `PlanExitTool`) always supply a description. The defensive `<Show when={props.description}>` rendering in `session-question-dock.tsx` is a standard guard, not a signal that the field is intended to be optional. Do NOT suggest making `Option.description` optional without a dedicated follow-up that covers schema + tool description + dock copy + tests.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-22T09:32:54.556Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/opencode/test/provider/provider.test.ts:64-85
Timestamp: 2026-04-22T09:32:54.556Z
Learning: In `packages/opencode/test/provider/provider.test.ts`, the file intentionally uses AppRuntime-based async helpers (`run`, `list`, `getProvider`, etc.) rather than `testEffect(...)` for all tests. Converting individual tests to `testEffect` while leaving the rest on the async pattern would create internal inconsistency. A full harness migration of this file is the right approach if the pattern needs to change, but that should be a separate PR.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:31.032Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/test/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:31.032Z
Learning: Applies to packages/opencode/test/**/*.test.{ts,tsx} : Define `const it = testEffect(...)` near the top of the test file and keep the test body inside `Effect.gen(function* () { ... })`. Yield services directly with `yield* MyService.Service` or `yield* MyTool`.
Applied to files:
packages/opencode/test/session/instruction.test.ts
📚 Learning: 2026-04-20T14:36:21.288Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2026-04-20T14:36:21.288Z
Learning: Applies to packages/opencode/**/*.ts : Use `Schema.Class` for multi-field data in Effect schemas
Applied to files:
packages/opencode/test/session/instruction.test.ts
597fd9e to
9c96899
Compare
…k mode PawWork users on their own provider keys should not silently inherit global Claude Code instructions as their PawWork baseline (issue #230, acceptance #5). Gates the global fallback push behind a Runtime.isPawWork() check so the existing opt-out flag still works for plain opencode CLI users; project-level CLAUDE.md remains as compatibility (acceptance #6) and is unaffected here. The lookup also routes through Global.Path.home so OPENCODE_TEST_HOME can stub the home directory deterministically — Bun's os.homedir() is locked at process start, which would otherwise make this code path untestable under Bun's test runner. Tests cover the five fallback scenarios from acceptance #8: fresh install, project AGENTS.md, project CLAUDE.md compatibility fallback, PawWork global AGENTS.md, and the now-ignored ~/.claude/CLAUDE.md. A non-PawWork regression test guards the Runtime.isPawWork() gate so an accidental inversion would fail the suite.
… of disable flag A PawWork process inheriting OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 from a parent shell would build the project FILES list without CLAUDE.md and silently drop the project-level compatibility fallback that issue #230 acceptance #6 explicitly preserves. Extracts a pure projectFiles({ isPawWork, disableClaudeCodePrompt }) helper so the gate is testable without mutating module-scope flags, and gates CLAUDE.md inclusion on isPawWork || !disableClaudeCodePrompt: PawWork mode keeps the project fallback regardless of the flag, plain opencode CLI still respects it. The runtime FILES() function reads process state at call time so tests that flip Runtime.isPawWork() pick up the new behavior immediately. Tests cover the four-case matrix on the helper directly, providing deterministic coverage for both axes.
…nd ignored chains Adds Instruction.sources() returning structured InstructionSource entries so debug surfaces can explain which files the system loaded, which were considered but skipped or absent, and which were intentionally ignored (issue #230, acceptance #7). This commit covers the project priority chain, the global priority chain, and the explicitly ignored ~/.claude/CLAUDE.md; config.instructions handling lands in a follow-up. Marks a file as loaded only after read() returns non-empty content so diagnostics agree with what system() actually reads into the prompt. Files whose content reads back empty are downgraded to considered with reason 'file is empty or unreadable'. The ignore reason distinguishes Runtime.isPawWork() (PawWork product baseline) from OPENCODE_DISABLE_CLAUDE_CODE_PROMPT (legacy opencode CLI opt-out), and dedupes against loadedPaths so a file never appears as both loaded and ignored. Tests cover loaded project AGENTS.md, the priority-skipped global considered branch, the project priority chain (AGENTS.md + CLAUDE.md), the empty-file downgrade, and the ignored Claude Code fallback with reason. All home-directory isolation runs through OPENCODE_TEST_HOME.
…n sources() diagnostic Extends Instruction.sources() so the diagnostic stays in lockstep with system() across all instruction sources. Local file entries from config.instructions are glob-resolved exactly as systemPaths() does (~/ via Global.Path.home, absolute via fs.glob, relative via the existing relative() helper) and reported as loaded when content reads back non-empty, considered with reason 'config.instructions entry resolved to no files' when no matches resolve, and considered with the empty/unreadable reason when a match resolves but reads back empty. Remote URL entries fetch concurrently via Effect.forEach with concurrency 4, matching system()'s behavior so a handful of dead URLs no longer stack 5s timeouts and slow sources() down. Each URL is reported as loaded on a non-empty body or considered with reason 'fetch failed or returned empty body'. systemPaths()'s ~/ resolution for config.instructions is also routed through Global.Path.home so prompt and diagnostic agree on the path; the os import is no longer needed in this file. Tests cover the URL diagnostic (via OPENCODE_CONFIG_CONTENT with an unreachable URL) and the local file branch (via PAWWORK_CONFIG_DIR + OPENCODE_DISABLE_PROJECT_CONFIG so the relative resolver fires).
9c96899 to
3a979e8
Compare
Summary
~/.claude/CLAUDE.mdglobal fallback in PawWork runtime mode so users on their own provider keys do not silently inherit global Claude Code instructions as their PawWork baseline.CLAUDE.mdas a compatibility fallback (issue [Feature] Improve PawWork system prompt and instruction fallback order #230 acceptance fix(config): harden scoped dependency loading #6) and keep theOPENCODE_DISABLE_CLAUDE_CODE_PROMPTflag working for plain opencode CLI users so their Claude Code interop is unchanged.Instruction.sources()returning structuredInstructionSourceentries so debug surfaces can explain which instruction files were loaded and which were intentionally ignored, including the now-suppressed global Claude Code fallback with reason.AGENTS.md, projectCLAUDE.mdcompatibility, PawWork globalAGENTS.md, and ignored global~/.claude/CLAUDE.md. Plus two more tests for the newsources()diagnostic.Why
Issue #230 was partially landed already: the system prompt rewrite and tool collaboration guidance shipped in
pawwork.txt, and #128 (subagent rename) merged. The remaining acceptance criteria #5, #7, #8 — drop the global Claude Code fallback, expose diagnostics, and add focused tests — were still open. This PR closes those.The global Claude Code fallback currently lets a user with no PawWork or project instructions silently fall back to whatever they have in
~/.claude/CLAUDE.md. That violates the product baseline goal stated in the issue: PawWork should own its default behavior, not inherit it from a different agent's config. PawWork users running their own provider keys are the dominant case and they need the PawWork product baseline to be the source of truth.Related Issue
Closes #230.
How To Verify
bun --cwd packages/opencode test test/session/instruction.test.ts bun run typecheckThe 5 fallback scenario tests turn green only after the runtime gate in commit 2 lands; the diagnostic tests in commit 3 cover acceptance #7. All
Instruction.systemandInstruction.systemPathscallers are unaffected because the change is additive (newsources()method) plus a runtime-conditional removal inglobalInstructionFiles().Screenshots or Recordings
Not applicable. Harness behavior change with no visible UI.
Checklist
dev, and my PR title and commit messages use Conventional Commits in EnglishSummary by CodeRabbit
New Features
Changes
Tests