feat(harness): rename task tool to agent (#128)#247
Conversation
…o agent.{ts,txt}
Mechanical TS rename only — tool id, parameters, XML wrapper, registry slot,
SubtaskPart field, prose strings, icon, and i18n stay as-is for follow-up
commits per #128 plan.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📜 Recent 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). (10)
🧰 Additional context used📓 Path-based instructions (4)packages/app/**/*.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (packages/app/AGENTS.md)
Files:
packages/app/e2e/**/*.spec.ts📄 CodeRabbit inference engine (packages/app/e2e/AGENTS.md)
Files:
packages/opencode/**/*.ts📄 CodeRabbit inference engine (packages/opencode/AGENTS.md)
Files:
packages/opencode/test/**/*.test.{ts,tsx}📄 CodeRabbit inference engine (packages/opencode/test/AGENTS.md)
Files:
🧠 Learnings (39)📓 Common learnings📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-24T03:51:54.050ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-23T15:25:27.182ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-24T00:02:50.599ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-20T14:36:04.113ZApplied to files:
📚 Learning: 2026-04-26T16:34:54.895ZApplied to files:
📚 Learning: 2026-04-22T08:49:47.800ZApplied to files:
📚 Learning: 2026-04-23T07:23:23.849ZApplied to files:
📚 Learning: 2026-04-24T05:48:36.205ZApplied to files:
📚 Learning: 2026-04-21T16:57:25.580ZApplied to files:
📚 Learning: 2026-04-23T08:51:04.230ZApplied to files:
📚 Learning: 2026-04-22T09:32:58.310ZApplied to files:
📚 Learning: 2026-04-24T17:08:44.294ZApplied to files:
📚 Learning: 2026-04-26T15:35:31.757ZApplied to files:
📚 Learning: 2026-04-20T14:21:56.373ZApplied to files:
📚 Learning: 2026-04-21T16:57:23.748ZApplied to files:
📚 Learning: 2026-04-23T17:02:40.117ZApplied to files:
📚 Learning: 2026-04-23T15:10:26.994ZApplied to files:
📚 Learning: 2026-04-20T17:03:40.214ZApplied to files:
📚 Learning: 2026-04-24T03:51:54.050ZApplied to files:
📚 Learning: 2026-04-20T14:36:31.032ZApplied to files:
📚 Learning: 2026-04-20T14:36:31.032ZApplied to files:
📚 Learning: 2026-04-20T14:36:31.032ZApplied to files:
📚 Learning: 2026-04-22T09:32:54.556ZApplied to files:
📚 Learning: 2026-04-20T14:36:31.032ZApplied to files:
📚 Learning: 2026-04-20T14:36:31.032ZApplied to files:
📚 Learning: 2026-04-23T15:25:31.118ZApplied to files:
📚 Learning: 2026-04-23T08:51:00.819ZApplied to files:
🔇 Additional comments (7)
📝 WalkthroughWalkthroughThis PR renames the "task" tool to "agent" across code, docs, tests, i18n, CLI, and permissions; it preserves backward compatibility by accepting legacy Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Code Review
This pull request performs a comprehensive rename of the 'Task' tool to 'Agent' (or 'Subagent') across the entire repository, including CLI, UI, and core logic. It introduces legacy support to ensure historical sessions remain renderable and extracts tool metadata logic into a testable utility. Feedback focuses on missing i18n keys for the new tool name, potential breaking changes when resuming old subagent sessions due to parameter renaming, logic duplication in UI components, and consistency in handling optional subtitle fields.
…gacy sessions Sets `id = "agent"` in the agent tool, switches the recursion guard, three `Permission.evaluate` namespaces, the truncate hint check, and the CLI AVAILABLE_TOOLS list to the new id. Renames the existing test fixtures (prompt-effect, agent.test, truncation, permission-task -> permission-agent) and the Windows CI shard list to match. Adds renderer or-match in three paths so historical sessions with `tool: "task"` parts continue rendering: message-part dual-register (extracts buildToolInfo and three reactive memos to or-match), message- timeline taskDescription helper, and CLI run dispatch via a new isAgentToolPart helper. Storybook fixture renamed to "agent" instead of or-matched.
Param `task_id` -> `subagent_session_id` (with rewritten describe text), local `taskID` -> `agentSessionID`, output prose updated, and the `<task_result>` / `</task_result>` xml wrapper renamed to `<subagent_result>`. Adds `export` to the parameters const so the literal sweep regression test can assert the schema shape.
Six new regression tests: - packages/opencode/test/tool/agent-rename.test.ts (literal sweep across packages/{opencode,app,ui}/{src,test} + packages/app/e2e) - packages/app/test/i18n/agent-rename.test.ts (settings keys) - packages/ui/test/components/icon-registry-rename.test.ts - packages/ui/test/components/message-part-rename.test.ts - packages/app/test/session/message-timeline-rename.test.ts - packages/opencode/test/cli/run-rename.test.ts Surface cleanups caught by the sweep: - agent.txt model-facing prose rewritten ("Task tool" -> "agent tool") - 18 packages/ui/src/i18n files: drop orphan ui.tool.task key - tool-error-card alias map: keep `task` next to `agent` for legacy parts - buildToolInfo extracted to packages/ui/src/components/tool-info.ts and taskDescription extracted to packages/app/src/pages/session/ task-description.ts so tests can import them without triggering SolidJS / Kobalte module side effects Review feedback applied: - Permission.fromConfig normalizes legacy `permission.task` keys to `agent` so user configs keep applying after the rename, with three regression tests in permission-agent.test.ts - packages/app/e2e/actions.ts + session-child-navigation.spec.ts: rename task-tool prose; or-match the dispatch predicate - packages/sdk/openapi.json: rename single permission schema field task -> agent - cli/cmd/run.ts: fallback name `${agent} Task` -> `${agent} Agent` - tool-info subtitle empty-string -> undefined to match sibling cases
6259a2a to
5998fba
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
packages/app/e2e/session/session-child-navigation.spec.ts (1)
5-23:⚠️ Potential issue | 🟠 MajorUpdate the mock to assert the new
agenttool path.The test is now named as an agent-tool scenario, but Line 22 still stubs
"task". That can miss regressions where new sessions are expected to emit"agent".Proposed fix
- await llm.toolMatch(inputMatch(taskInput), "task", taskInput) + await llm.toolMatch(inputMatch(taskInput), "agent", taskInput)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/app/e2e/session/session-child-navigation.spec.ts` around lines 5 - 23, The test "agent tool child-session link does not trigger stale show errors" still stubs the "task" tool path which doesn't reflect the agent-tool scenario; update the mock invocation(s) that assert or stub the tool type (e.g., the llm.toolMatch(...) call and any inputMatch or seedSessionTask usage that references "task") to expect "agent" instead of "task" so the test asserts the new agent tool path and catches regressions where new sessions should emit "agent".packages/opencode/test/session/prompt-effect.test.ts (1)
793-793:⚠️ Potential issue | 🟡 MinorTimeout message still references
task.Line 793 should be updated to
agentto avoid misleading failures and keep rename terminology consistent.Suggested fix
- throw new Error("timed out waiting for running task metadata") + throw new Error("timed out waiting for running agent metadata")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/test/session/prompt-effect.test.ts` at line 793, The thrown error message still says "timed out waiting for running task metadata" which is inconsistent with the rename to agent; update the throw expression so the Error uses "timed out waiting for running agent metadata" (i.e., change the string in the throw new Error(...) call) to keep terminology consistent in the test (prompt-effect.test.ts).packages/opencode/src/cli/cmd/run.ts (1)
465-476:⚠️ Potential issue | 🟡 MinorPreserve the agent label on failed legacy tool parts.
Completed/running legacy
"task"parts go throughagent(...), but the error branch still renders${part.tool} failed. Historical failed sessions will therefore regress back to a visible"task failed"label even though the rest of the renderer is compatibility-aware.Suggested fix
if (part.type === "tool" && (part.state.status === "completed" || part.state.status === "error")) { if (emit("tool_use", { part })) continue if (part.state.status === "completed") { tool(part) continue } + if (isAgentToolPart(part.tool)) { + agent(props<typeof AgentTool>(part)) + UI.error(part.state.error) + continue + } inline({ icon: "✗", title: `${part.tool} failed`, }) UI.error(part.state.error)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/opencode/src/cli/cmd/run.ts` around lines 465 - 476, The error branch for legacy tool parts always renders `${part.tool} failed`, which loses the compatibility-aware agent label for legacy "task" tools; update the error-handling branch inside the part.type === "tool" block so that if part.tool === "task" you call agent(part) (or render the same agent label used for completed/running "task" parts) instead of inlining `${part.tool} failed`, otherwise keep the existing inline error label; remember to still call UI.error(part.state.error) and continue after rendering.
🤖 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/agent/generate.txt`:
- Around line 44-54: Update the contradictory example so context, user input,
assistant message, and commentary all match a single scenario: either change the
earlier prime-check Context/user to a greeting (e.g., Context: "User is
greeting", user: "Hello") or change the greeting example to be about
prime-checking; ensure the assistant line uses the same agent name
("greeting-responder" not "code-reviewer") and fix the typo "jok" → "joke" in
the example; locate the examples by the strings "Context: User is creating an
agent to respond to the word \"hello\"" and the assistant line that says "Now
let me use the code-reviewer agent" to make the edits.
In `@packages/opencode/src/cli/cmd/agent.ts`:
- Line 18: The CLI silently disables all tools when a legacy value
"--tools=task" is passed because "task" is no longer in AVAILABLE_TOOLS; update
the tool parsing to map the legacy alias "task" to "agent" (or add "task" to
AVAILABLE_TOOLS as an alias) and validate user-specified tools: in the agent CLI
parsing logic that reads the "--tools" flag (referencing AVAILABLE_TOOLS),
accept "task" as equivalent to "agent" and/or throw a clear error if a provided
tool name doesn't match any known tool so we never produce a config with every
tool false.
In `@packages/opencode/src/session/prompt.ts`:
- Around line 604-608: The plugin hook calls for tool execution use the wrong
identifier: replace usages of part.id with part.callID when triggering
"tool.execute.before" and "tool.execute.after" (the plugin.trigger calls where
you pass { tool: AgentTool.id, sessionID, callID: part.id, ... }) so the emitted
callID matches the actual dispatch (also apply the same change to the other
occurrence around the 683-686 region); update the plugin.trigger invocations to
pass callID: part.callID to maintain correlation with the stored tool call and
other hook consumers.
In `@packages/opencode/src/tool/agent.txt`:
- Around line 16-17: Replace the redundant phrase "return back" in the agent
docs: change "it will return a single message back to you" to "it will return a
single message to you" (or "send a single message to you"), and change "To show
the user the result, you should send a text message back to the user" to "To
show the user the result, you should send a text message to the user"; also
update the later "return back to the user" phrasing similarly so all instances
of "return back" are normalized to "return" or "to the user" for clarity.
In `@packages/ui/src/components/message-part.tsx`:
- Around line 1322-1324: The session-link resolution currently reads only
partMetadata().sessionId, which ignores explicit input IDs; update both
locations (the block using part() / partMetadata() around the snippet with
sessionId and the other occurrence at the second location) to first check
partMetadata().subagent_session_id and, if it's a non-empty string, return that,
otherwise fall back to partMetadata().sessionId; keep the early return for
non-"task"/"agent" tools and preserve existing heuristics.
---
Outside diff comments:
In `@packages/app/e2e/session/session-child-navigation.spec.ts`:
- Around line 5-23: The test "agent tool child-session link does not trigger
stale show errors" still stubs the "task" tool path which doesn't reflect the
agent-tool scenario; update the mock invocation(s) that assert or stub the tool
type (e.g., the llm.toolMatch(...) call and any inputMatch or seedSessionTask
usage that references "task") to expect "agent" instead of "task" so the test
asserts the new agent tool path and catches regressions where new sessions
should emit "agent".
In `@packages/opencode/src/cli/cmd/run.ts`:
- Around line 465-476: The error branch for legacy tool parts always renders
`${part.tool} failed`, which loses the compatibility-aware agent label for
legacy "task" tools; update the error-handling branch inside the part.type ===
"tool" block so that if part.tool === "task" you call agent(part) (or render the
same agent label used for completed/running "task" parts) instead of inlining
`${part.tool} failed`, otherwise keep the existing inline error label; remember
to still call UI.error(part.state.error) and continue after rendering.
In `@packages/opencode/test/session/prompt-effect.test.ts`:
- Line 793: The thrown error message still says "timed out waiting for running
task metadata" which is inconsistent with the rename to agent; update the throw
expression so the Error uses "timed out waiting for running agent metadata"
(i.e., change the string in the throw new Error(...) call) to keep terminology
consistent in the test (prompt-effect.test.ts).
🪄 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: 16a628d0-338d-461d-94b2-0924bf06ba98
📒 Files selected for processing (57)
.github/workflows/ci.ymlpackages/app/e2e/actions.tspackages/app/e2e/session/session-child-navigation.spec.tspackages/app/src/i18n/en.tspackages/app/src/i18n/zh.tspackages/app/src/pages/session/message-timeline.tsxpackages/app/src/pages/session/task-description.tspackages/app/test/i18n/agent-rename.test.tspackages/app/test/session/message-timeline-rename.test.tspackages/opencode/src/agent/generate.txtpackages/opencode/src/cli/cmd/agent.tspackages/opencode/src/cli/cmd/run.tspackages/opencode/src/config/permission.tspackages/opencode/src/permission/index.tspackages/opencode/src/session/prompt.tspackages/opencode/src/session/prompt/pawwork.txtpackages/opencode/src/tool/agent.tspackages/opencode/src/tool/agent.txtpackages/opencode/src/tool/glob.txtpackages/opencode/src/tool/grep.txtpackages/opencode/src/tool/registry.tspackages/opencode/src/tool/truncate.tspackages/opencode/test/cli/run-rename.test.tspackages/opencode/test/github/ci-workflow.test.tspackages/opencode/test/permission-agent.test.tspackages/opencode/test/permission-task.test.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/tool/agent.test.tspackages/opencode/test/tool/truncation.test.tspackages/sdk/openapi.jsonpackages/ui/package.jsonpackages/ui/src/components/icon.stories.tsxpackages/ui/src/components/icon.tsxpackages/ui/src/components/message-part.tsxpackages/ui/src/components/timeline-playground.stories.tsxpackages/ui/src/components/tool-error-card.tsxpackages/ui/src/components/tool-info.tspackages/ui/src/i18n/ar.tspackages/ui/src/i18n/br.tspackages/ui/src/i18n/bs.tspackages/ui/src/i18n/da.tspackages/ui/src/i18n/de.tspackages/ui/src/i18n/en.tspackages/ui/src/i18n/es.tspackages/ui/src/i18n/fr.tspackages/ui/src/i18n/ja.tspackages/ui/src/i18n/ko.tspackages/ui/src/i18n/no.tspackages/ui/src/i18n/pl.tspackages/ui/src/i18n/ru.tspackages/ui/src/i18n/th.tspackages/ui/src/i18n/tr.tspackages/ui/src/i18n/zh.tspackages/ui/src/i18n/zht.tspackages/ui/test/components/icon-registry-rename.test.tspackages/ui/test/components/message-part-rename.test.ts
💤 Files with no reviewable changes (18)
- packages/ui/src/i18n/en.ts
- packages/ui/src/i18n/tr.ts
- packages/ui/src/i18n/de.ts
- packages/ui/src/i18n/da.ts
- packages/ui/src/i18n/pl.ts
- packages/ui/src/i18n/th.ts
- packages/ui/src/i18n/zh.ts
- packages/ui/src/i18n/no.ts
- packages/ui/src/i18n/bs.ts
- packages/ui/src/i18n/ko.ts
- packages/ui/src/i18n/zht.ts
- packages/ui/src/i18n/es.ts
- packages/ui/src/i18n/ja.ts
- packages/ui/src/i18n/br.ts
- packages/opencode/test/permission-task.test.ts
- packages/ui/src/i18n/fr.ts
- packages/ui/src/i18n/ru.ts
- packages/ui/src/i18n/ar.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). (10)
- GitHub Check: smoke-macos-arm64
- GitHub Check: unit-windows-desktop
- GitHub Check: unit-windows-opencode-session
- GitHub Check: unit-windows-opencode-config-project
- GitHub Check: unit-windows-app
- GitHub Check: unit-windows-opencode-server-tools
- GitHub Check: unit-opencode
- GitHub Check: unit-desktop
- GitHub Check: e2e-artifacts
- GitHub Check: analyze-js-ts
🧰 Additional context used
📓 Path-based instructions (4)
packages/app/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (packages/app/AGENTS.md)
Always prefer
createStoreover multiplecreateSignalcalls in SolidJS
Files:
packages/app/e2e/session/session-child-navigation.spec.tspackages/app/src/pages/session/task-description.tspackages/app/test/session/message-timeline-rename.test.tspackages/app/src/i18n/zh.tspackages/app/src/i18n/en.tspackages/app/test/i18n/agent-rename.test.tspackages/app/src/pages/session/message-timeline.tsxpackages/app/e2e/actions.ts
packages/app/e2e/**/*.spec.ts
📄 CodeRabbit inference engine (packages/app/e2e/AGENTS.md)
packages/app/e2e/**/*.spec.ts: Import test utilities from../fixturesinstead of@playwright/test
Test files should be named with the patternfeature-name.spec.ts
Use lowercase, descriptive test names (e.g., 'sidebar can be toggled')
Use camelCase for variable names in tests
Use SCREAMING_SNAKE_CASE for constants in tests
Use fixture-managed cleanup withwithSession(sdk, title, callback)for temporary sessions instead of callingsdk.session.delete(...)directly
Prefer theprojectfixture for tests that need a dedicated project with LLM mocking
Usedata-component,data-action, or semantic roles for selectors instead of CSS class names or IDs
UsemodKeyfrom utils for cross-platform keyboard shortcuts (Meta on Mac, Control on Linux/Windows)
In terminal tests, type through the browser usingrunTerminal()andwaitTerminalReady()instead of writing to the PTY through the SDK
Never use wall-clock waits likepage.waitForTimeout(...)to make a test pass
Wait on observable state withexpect(...),expect.poll(...), or existing helpers instead of assuming work is finished after an action
Use locator assertions liketoBeVisible(),toHaveCount(0), andtoHaveAttribute(...)for normal UI state verification
Useexpect.poll(...)for probing mock or backend state rather than transient DOM visibility
Prefer fluent helpers and drivers when they make intent obvious and reduce locator-heavy noise in tests
Use direct locators when the interaction is simple and a helper would not add clarity
When validating routing, assert against canonical or resolved workspace slugs using shared helpers from../actionsto account for Windows canonicalization
Test one feature per test file
Callproject.trackSession(sessionID, directory?)andproject.trackDirectory(directory)for any resources created outside the fixture so teardown can clean them up
Files:
packages/app/e2e/session/session-child-navigation.spec.ts
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/github/ci-workflow.test.tspackages/opencode/test/cli/run-rename.test.tspackages/opencode/src/config/permission.tspackages/opencode/src/cli/cmd/agent.tspackages/opencode/src/tool/truncate.tspackages/opencode/src/permission/index.tspackages/opencode/test/tool/truncation.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/src/cli/cmd/run.tspackages/opencode/test/permission-agent.test.tspackages/opencode/src/tool/registry.tspackages/opencode/src/tool/agent.tspackages/opencode/src/session/prompt.tspackages/opencode/test/tool/agent.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/github/ci-workflow.test.tspackages/opencode/test/cli/run-rename.test.tspackages/opencode/test/tool/truncation.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/test/permission-agent.test.tspackages/opencode/test/tool/agent.test.ts
🧠 Learnings (56)
📓 Common learnings
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.
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.
📚 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 : Use lowercase, descriptive test names (e.g., 'sidebar can be toggled')
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.tspackages/ui/test/components/icon-registry-rename.test.tspackages/app/test/session/message-timeline-rename.test.tspackages/app/test/i18n/agent-rename.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 : Use fixture-managed cleanup with `withSession(sdk, title, callback)` for temporary sessions instead of calling `sdk.session.delete(...)` directly
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.tspackages/opencode/test/github/ci-workflow.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/session/prompt-effect.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 fluent helpers and drivers when they make intent obvious and reduce locator-heavy noise in tests
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.tspackages/app/test/i18n/agent-rename.test.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/test/tool/agent.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 under packages/app/e2e, do not manually call `project.trackSession(sessionID)` when you obtain a `sessionID` via `project.prompt(text)`. The `project.prompt()` implementation already registers `trackSession(next.sessionID, active.directory)` automatically after the prompt submission is observed and the active session is resolved, so calling `project.trackSession(sessionID)` again will create duplicate session ownership/teardown handling.
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.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 : Test files should be named with the pattern `feature-name.spec.ts`
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.tspackages/ui/test/components/icon-registry-rename.test.tspackages/app/test/i18n/agent-rename.test.tspackages/opencode/test/tool/agent-rename.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 : Test one feature per test file
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.tspackages/ui/test/components/icon-registry-rename.test.tspackages/app/test/session/message-timeline-rename.test.tspackages/opencode/test/tool/agent-rename.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/app/e2e/session/session-child-navigation.spec.tspackages/app/test/session/message-timeline-rename.test.tspackages/opencode/test/tool/agent-rename.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 : Use camelCase for variable names in tests
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.tspackages/app/test/i18n/agent-rename.test.tspackages/opencode/test/tool/agent-rename.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 : Use `data-component`, `data-action`, or semantic roles for selectors instead of CSS class names or IDs
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.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 : In terminal tests, type through the browser using `runTerminal()` and `waitTerminalReady()` instead of writing to the PTY through the SDK
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.tspackages/opencode/test/tool/agent-rename.test.ts
📚 Learning: 2026-04-23T15:25:27.182Z
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:27.182Z
Learning: In Astro-Han/pawwork E2E tests (e.g., *.spec.ts under packages/app/e2e), reaching a real "running" session state is not achievable with the bare `sdk` fixture. Use the `project` fixture (to bootstrap the model) and orchestrate the transition with `llm.wait(1)`; even if you set `agent: "build"` and a `system` prompt via `sdk.session.promptAsync`, the current test infrastructure does not trigger an actual LLM call, so it won’t simulate "running" cheaply. Review any attempt to mock/force "running" using only `sdk` as likely ineffective unless it also uses `project` + `llm.wait(1)`.
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.ts
📚 Learning: 2026-04-24T00:02:50.599Z
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:50.599Z
Learning: For Astro-Han/pawwork E2E tests under packages/app/e2e/**/*.spec.ts, do not call project.trackDirectory() or project.trackSession() before project.open() has run. The project fixture throws until open() initializes internal state. Use this ordering pattern: (1) call project.trackSession(sessionID) inside the beforeGoto callback (where state is already available), (2) call project.trackDirectory(directory) and any cross-workspace tracking like project.trackSession(id, directory) immediately after project.open() returns, and (3) if you create any resources before open() that cannot yet be tracked via the fixture, ensure you clean them up explicitly in finally blocks (e.g., cleanupSession / cleanupTestProject).
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.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/app/e2e/session/session-child-navigation.spec.ts.github/workflows/ci.yml
📚 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 : Use `expect.poll(...)` for probing mock or backend state rather than transient DOM visibility
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.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 : Never use wall-clock waits like `page.waitForTimeout(...)` to make a test pass
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.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/app/e2e/session/session-child-navigation.spec.tspackages/ui/test/components/icon-registry-rename.test.tspackages/opencode/test/cli/run-rename.test.tspackages/app/test/session/message-timeline-rename.test.tspackages/opencode/test/tool/truncation.test.tspackages/ui/test/components/message-part-rename.test.tspackages/app/test/i18n/agent-rename.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/tool/agent.test.ts
📚 Learning: 2026-04-23T07:23:23.849Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 180
File: packages/app/src/components/session/session-new-view.tsx:13-18
Timestamp: 2026-04-23T07:23:23.849Z
Learning: In pawwork (Astro-Han/pawwork), prefer using `createStore` instead of multiple `createSignal` calls only when the signals represent **coupled** object state that is updated together (i.e., there is at least one shared batch-update site where the state is changed in the same transaction). If the state fields are **independent** and are mutated by separate handlers (e.g., one handler updates only `selectedSkill` while another updates only `mode`), keep them as individual `createSignal` calls—using `createStore` for truly independent fields adds boilerplate without behavioral benefit.
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.tspackages/app/src/pages/session/task-description.tspackages/app/test/session/message-timeline-rename.test.tspackages/app/src/i18n/zh.tspackages/app/src/i18n/en.tspackages/app/test/i18n/agent-rename.test.tspackages/app/src/pages/session/message-timeline.tsxpackages/app/e2e/actions.ts
📚 Learning: 2026-04-24T05:48:36.205Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 208
File: packages/app/e2e/app/composer-parity.spec.ts:0-0
Timestamp: 2026-04-24T05:48:36.205Z
Learning: In E2E parity tests, prefer using the existing `[data-action]` coverage when asserting UI parity. For elements whose trigger props set `data-action` (e.g., `data-action="prompt-model"` and `data-action="prompt-model-variant"` on prompt input chip triggers), you generally do not need to add separate assertions driven by `[data-component]` for parity. Avoid duplicating component-specific queries when the `[data-action]` selector sweep already includes the elements; any extra unioning of selectors should be treated as optional belt-and-suspenders rather than required.
Applied to files:
packages/app/e2e/session/session-child-navigation.spec.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/ui/test/components/icon-registry-rename.test.tspackages/ui/src/components/icon.tsxpackages/ui/src/components/message-part.tsx
📚 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/ui/test/components/icon-registry-rename.test.tspackages/opencode/test/github/ci-workflow.test.tspackages/opencode/test/cli/run-rename.test.tspackages/app/test/session/message-timeline-rename.test.tspackages/opencode/test/tool/truncation.test.tspackages/ui/test/components/message-part-rename.test.tspackages/app/test/i18n/agent-rename.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/test/permission-agent.test.tspackages/opencode/src/tool/registry.tspackages/opencode/src/session/prompt.tspackages/opencode/test/tool/agent.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/github/ci-workflow.test.ts.github/workflows/ci.yml
📚 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/github/ci-workflow.test.ts.github/workflows/ci.ymlpackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/test/permission-agent.test.tspackages/opencode/src/session/prompt.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/github/ci-workflow.test.tspackages/opencode/test/cli/run-rename.test.ts.github/workflows/ci.ymlpackages/app/test/session/message-timeline-rename.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/permission-agent.test.tspackages/opencode/test/tool/agent.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/github/ci-workflow.test.tspackages/opencode/test/cli/run-rename.test.tspackages/opencode/test/tool/truncation.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/test/permission-agent.test.tspackages/opencode/test/tool/agent.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/test/github/ci-workflow.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/github/ci-workflow.test.tspackages/opencode/test/permission-agent.test.tspackages/opencode/test/tool/agent.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/github/ci-workflow.test.tspackages/opencode/test/cli/run-rename.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/test/tool/agent.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/github/ci-workflow.test.tspackages/opencode/test/cli/run-rename.test.tspackages/opencode/test/tool/truncation.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/session/prompt-effect.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/github/ci-workflow.test.tspackages/opencode/test/cli/run-rename.test.tspackages/app/test/session/message-timeline-rename.test.tspackages/opencode/test/tool/agent-rename.test.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/test/permission-agent.test.tspackages/opencode/src/session/prompt.tspackages/opencode/test/tool/agent.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/cli/run-rename.test.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/src/session/prompt.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/cli/run-rename.test.tspackages/opencode/test/tool/agent-rename.test.ts
📚 Learning: 2026-04-20T14:35:49.291Z
Learnt from: CR
Repo: Astro-Han/pawwork PR: 0
File: packages/app/AGENTS.md:0-0
Timestamp: 2026-04-20T14:35:49.291Z
Learning: For local UI changes, run the backend and app dev servers separately using `bun run --conditions=browser ./src/index.ts serve --port 4096` for backend and `bun dev -- --port 4444` for app, then open `http://localhost:4444` to verify changes targeting backend at `http://localhost:4096`
Applied to files:
packages/ui/package.json
📚 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:
.github/workflows/ci.ymlpackages/app/test/session/message-timeline-rename.test.tspackages/opencode/test/tool/agent-rename.test.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/config/permission.tspackages/opencode/src/tool/truncate.tspackages/opencode/src/permission/index.tspackages/app/src/i18n/zh.tspackages/opencode/test/tool/truncation.test.tspackages/app/src/i18n/en.tspackages/sdk/openapi.jsonpackages/opencode/test/tool/agent-rename.test.tspackages/opencode/src/cli/cmd/run.tspackages/opencode/test/permission-agent.test.tspackages/opencode/src/tool/registry.tspackages/opencode/src/tool/agent.tspackages/opencode/src/session/prompt.tspackages/opencode/test/tool/agent.test.ts
📚 Learning: 2026-04-21T16:57:20.257Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 102
File: packages/opencode/src/config/command.ts:23-29
Timestamp: 2026-04-21T16:57:20.257Z
Learning: In packages/opencode/src/config/ config modules, treat both `Schema.Struct` and `Schema.Class` as valid schema patterns and do not require converting `Schema.Struct` to `Schema.Class`. If `Schema.Struct` is used in a config schema (e.g., in files like `command.ts`, `formatter.ts`, `provider.ts`, `permission.ts`, `lsp.ts`, `config.ts`, `keybinds.ts`), accept it as intentional; the selection should be based on upstream alignment and the local schema context, not on a rule that one form must replace the other.
Applied to files:
packages/opencode/src/config/permission.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/app/src/pages/session/task-description.tspackages/app/test/session/message-timeline-rename.test.tspackages/ui/test/components/message-part-rename.test.tspackages/app/src/pages/session/message-timeline.tsxpackages/opencode/src/cli/cmd/run.tspackages/ui/src/components/tool-info.ts
📚 Learning: 2026-04-23T15:10:21.635Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 191
File: packages/app/src/components/session/pawwork-skill-meta.ts:38-39
Timestamp: 2026-04-23T15:10:21.635Z
Learning: This repo configures Tailwind v4 with `--color-*: initial`, which effectively breaks standard Tailwind palette utilities (e.g., `text-violet-500` can resolve to no CSS variable and render as a no-op/black). For brand/accent colors that are not backed by semantic design tokens, use inline styles with the exact hex value (e.g., `style={{ color: '#8B5FBF' }}` / `homeIconStyle: { color: '#8B5FBF' }`) and add a short comment explaining that Tailwind palette utilities won’t work due to the `--color-*: initial` setup. Do not suggest replacing these inline hex colors with Tailwind palette classes anywhere in this repo.
Applied to files:
packages/app/src/pages/session/task-description.tspackages/app/src/i18n/zh.tspackages/app/src/i18n/en.tspackages/app/src/pages/session/message-timeline.tsx
📚 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/app/test/session/message-timeline-rename.test.tspackages/opencode/src/session/prompt/pawwork.txtpackages/app/e2e/actions.tspackages/opencode/test/session/prompt-effect.test.tspackages/opencode/src/session/prompt.tspackages/opencode/test/tool/agent.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/app/test/session/message-timeline-rename.test.tspackages/opencode/test/tool/agent.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/tool/truncate.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/app/src/i18n/zh.tspackages/opencode/src/session/prompt/pawwork.txtpackages/app/src/i18n/en.tspackages/app/test/i18n/agent-rename.test.tspackages/opencode/src/cli/cmd/run.ts
📚 Learning: 2026-04-22T05:32:29.012Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 98
File: packages/desktop-electron/src/main/menu-labels.ts:1-2
Timestamp: 2026-04-22T05:32:29.012Z
Learning: In Astro-Han/pawwork, the app i18n layer (`packages/app/src/i18n/`) only contains `en.ts` and `zh.ts`, and `normalizeLocale` (in `packages/app/src/context/language.tsx`) only returns `"en"` or `"zh"`. The desktop `MenuLocale = "en" | "zh"` union in `packages/desktop-electron/src/main/menu-labels.ts` is intentionally limited to these two locales and is not a broader restriction — do not flag it as overly restrictive or suggest adding other locales.
Applied to files:
packages/app/src/i18n/zh.tspackages/app/src/i18n/en.tspackages/app/test/i18n/agent-rename.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/app/src/i18n/en.tspackages/app/test/i18n/agent-rename.test.tspackages/ui/src/components/message-part.tsxpackages/ui/src/components/tool-info.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/app/src/i18n/en.tspackages/opencode/src/tool/agent.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 : Use SCREAMING_SNAKE_CASE for constants in tests
Applied to files:
packages/app/test/i18n/agent-rename.test.tspackages/opencode/test/tool/agent-rename.test.ts
📚 Learning: 2026-04-23T15:25:31.118Z
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.
Applied to files:
packages/opencode/test/session/prompt-effect.test.tspackages/opencode/test/tool/agent.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/permission-agent.test.tspackages/opencode/test/tool/agent.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/tool/registry.tspackages/opencode/src/session/prompt.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/tool/registry.tspackages/opencode/src/session/prompt.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/prompt.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/prompt.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/prompt.tspackages/opencode/test/tool/agent.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 : For background loops or scheduled tasks, use `Effect.repeat` or `Effect.schedule` with `Effect.forkScoped` in the layer definition
Applied to files:
packages/opencode/src/session/prompt.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 : In `Effect.gen` / `Effect.fn`, prefer `yield* new MyError(...)` over `yield* Effect.fail(new MyError(...))` for direct early-failure branches
Applied to files:
packages/opencode/src/session/prompt.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/prompt.ts
🪛 LanguageTool
packages/opencode/src/tool/agent.txt
[style] ~16-~16: Using “back” with the verb “return” may be redundant.
Context: ...s done, it will return a single message back to you. The result returned by the agen...
(RETURN_BACK)
[style] ~17-~17: Consider using just “return”.
Context: ...actly what information the agent should return back to you in its final and only message to...
(RETURN_BACK)
Outside-diff feedbackAddressed CodeRabbit's three outside-diff items: 1.
|
- cli/cmd/agent.ts: add LEGACY_TOOL_ALIASES so `--tools=task` keeps
working post-rename, plus unknown-tool validation that errors clearly
instead of silently producing a config with all tools disabled.
- cli/cmd/run.ts error branch: route legacy `tool: "task"` parts through
agent() before falling to the generic `${part.tool} failed` inline so
failed historical sessions render with the localized "Agent" label.
- e2e/session-child-navigation.spec.ts: stub `"agent"` in the new mock
to match the renamed test name; keeps regression coverage on the new
dispatch path.
- prompt-effect.test.ts: terminology consistency in the timeout error.
Summary
Renames the model-facing helper tool from
tasktoagentacross the entire opencode/PawWork codebase per #128. The rename covers tool id, file paths, parameters, XML wrapper, registry slot, renderers, prompts, icons, permission schema, i18n, and adds 6 regression tests.Renderers OR-match both
"task"and"agent"so historical sessions on disk continue to render. New sessions emittool: "agent".Why
taskoverloaded what the LLM ecosystem now means by "agent" (Claude Code, Codex, Kimi all use the agent vocabulary), and the legacy name leaked into model-facing prose, parameter names (task_id), XML wrappers (<task_result>), and permission namespaces. Aligning toagentmakes the harness easier to understand for both models and humans, and matches the direction of the broader CLI agent ecosystem.Related Issue
Closes #128.
How To Verify
Local results:
2138 pass / 0 failopencode,577 pass / 0 failapp, ui green except 2 pre-existing flakes (apply-patch-file,session-diff) that fail on dev baseline as well — unrelated to this PR.Manual smoke (done locally on dev:desktop): new session subagent dispatch renders correctly with the new agent card. Historical session compatibility is covered by the dual-render unit tests below since the test environment has no legacy
tool: "task"parts.Test Coverage
Six new regression tests guard against rename drift:
packages/opencode/test/tool/agent-rename.test.ts— fs-walk literal sweep acrosspackages/{opencode,app,ui}/{src,test}for staleTaskTool,task_id,tool: "task",Task toolprose, etc. Allowlists lines tagged// agent-rename:legacy-render. 22/22 assertions.packages/app/test/i18n/agent-rename.test.ts— settings i18n keys present underagent, absent undertask. 4/4.packages/ui/test/components/icon-registry-rename.test.ts— icon registry hasagent, notask. 3/3.packages/ui/test/components/message-part-rename.test.ts—buildToolInforeturns identical icon/title/subtitle fortool: "task"andtool: "agent"inputs. 3/3.packages/app/test/session/message-timeline-rename.test.ts—taskDescriptionaccepts both ids. 3/3.packages/opencode/test/cli/run-rename.test.ts—isAgentToolPartreturns true for both ids, false for others. 3/3.Screenshots or Recordings
No visible UI change — the agent card looks identical (same SVG, only the registry key renamed).
Checklist
refactor(config,i18n): rename permission task field and settings i18n keys to agent); no migration needed since old session JSON keepstool: "task"and renderers OR-matchdev, commits use Conventional Commits in EnglishNotes
message-part,message-timeline,cli/cmd/run) accept both ids via OR-match guarded by// agent-rename:legacy-rendermarkers.agentrather than OR-matched per plan.buildToolInfoextracted topackages/ui/src/components/tool-info.tsandtaskDescriptiontopackages/app/src/pages/session/task-description.tsso unit tests can import without triggering SolidJS/Kobalte module side effects. Behavior unchanged.Summary by CodeRabbit
UI & UX Updates
Localization
Documentation
Backward Compatibility
Tests