Skip to content

feat(harness): rename task tool to agent (#128)#247

Merged
Astro-Han merged 12 commits intodevfrom
worktree-claude+agent-rename
Apr 26, 2026
Merged

feat(harness): rename task tool to agent (#128)#247
Astro-Han merged 12 commits intodevfrom
worktree-claude+agent-rename

Conversation

@Astro-Han
Copy link
Copy Markdown
Owner

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

Summary

Renames the model-facing helper tool from task to agent across 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 emit tool: "agent".

Why

task overloaded 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 to agent makes 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

bun --cwd packages/opencode typecheck
bun --cwd packages/app typecheck
bun --cwd packages/ui typecheck
bun --cwd packages/opencode test
bun --cwd packages/app test
bun --cwd packages/ui test

Local results: 2138 pass / 0 fail opencode, 577 pass / 0 fail app, 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 across packages/{opencode,app,ui}/{src,test} for stale TaskTool, task_id, tool: "task", Task tool prose, etc. Allowlists lines tagged // agent-rename:legacy-render. 22/22 assertions.
  • packages/app/test/i18n/agent-rename.test.ts — settings i18n keys present under agent, absent under task. 4/4.
  • packages/ui/test/components/icon-registry-rename.test.ts — icon registry has agent, no task. 3/3.
  • packages/ui/test/components/message-part-rename.test.tsbuildToolInfo returns identical icon/title/subtitle for tool: "task" and tool: "agent" inputs. 3/3.
  • packages/app/test/session/message-timeline-rename.test.tstaskDescription accepts both ids. 3/3.
  • packages/opencode/test/cli/run-rename.test.tsisAgentToolPart returns 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

  • I linked the related issue
  • This PR has type, scope, and priority labels (enhancement, harness, P1)
  • I listed the relevant verification steps and added regression tests
  • I manually checked the new-session subagent dispatch path on dev:desktop
  • macOS/Windows desktop impact: only model-facing strings and TS identifiers; no packaging, updater, signing, paths, shell, or permissions changes beyond the schema field rename (paired atomically with i18n)
  • Permission schema rename + i18n rename land in a single commit (refactor(config,i18n): rename permission task field and settings i18n keys to agent); no migration needed since old session JSON keeps tool: "task" and renderers OR-match
  • PR targets dev, commits use Conventional Commits in English

Notes

  • 19 commits, each one reversible intent per AGENTS.md commit-small rule.
  • Old session JSON on disk is unchanged — there is no JSON migration. Renderers (message-part, message-timeline, cli/cmd/run) accept both ids via OR-match guarded by // agent-rename:legacy-render markers.
  • Storybook fixture renamed to agent rather than OR-matched per plan.
  • buildToolInfo extracted to packages/ui/src/components/tool-info.ts and taskDescription to packages/app/src/pages/session/task-description.ts so unit tests can import without triggering SolidJS/Kobalte module side effects. Behavior unchanged.

Summary by CodeRabbit

  • UI & UX Updates

    • Tool renamed from "Task" to "Agent" across the interface; icons and labels updated.
  • Localization

    • Updated/removed legacy "task" translations; added "agent"/"subagent" strings across locales.
  • Documentation

    • Help text, examples, and guidance updated to reference the agent/subagent workflow.
  • Backward Compatibility

    • Legacy "task" sessions and flows remain supported and continue to render correctly.
  • Tests

    • New/updated tests to validate the agent rename and compatibility.

…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.
@Astro-Han Astro-Han added enhancement New feature or request P1 High priority harness Model harness, prompts, tool descriptions, and session mechanics labels Apr 26, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6bf9949d-0a92-4d53-b6f4-c615782678a8

📥 Commits

Reviewing files that changed from the base of the PR and between 5998fba and c5c75a5.

📒 Files selected for processing (4)
  • packages/app/e2e/session/session-child-navigation.spec.ts
  • packages/opencode/src/cli/cmd/agent.ts
  • packages/opencode/src/cli/cmd/run.ts
  • packages/opencode/test/session/prompt-effect.test.ts
📜 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)
  • GitHub Check: unit-windows-opencode-session
  • GitHub Check: unit-windows-opencode-server-tools
  • GitHub Check: unit-windows-desktop
  • GitHub Check: unit-windows-opencode-config-project
  • GitHub Check: unit-windows-app
  • GitHub Check: unit-desktop
  • GitHub Check: unit-opencode
  • GitHub Check: smoke-macos-arm64
  • GitHub Check: analyze-js-ts
  • GitHub Check: e2e-artifacts
🧰 Additional context used
📓 Path-based instructions (4)
packages/app/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (packages/app/AGENTS.md)

Always prefer createStore over multiple createSignal calls in SolidJS

Files:

  • packages/app/e2e/session/session-child-navigation.spec.ts
packages/app/e2e/**/*.spec.ts

📄 CodeRabbit inference engine (packages/app/e2e/AGENTS.md)

packages/app/e2e/**/*.spec.ts: Import test utilities from ../fixtures instead of @playwright/test
Test files should be named with the pattern feature-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 with withSession(sdk, title, callback) for temporary sessions instead of calling sdk.session.delete(...) directly
Prefer the project fixture for tests that need a dedicated project with LLM mocking
Use data-component, data-action, or semantic roles for selectors instead of CSS class names or IDs
Use modKey from utils for cross-platform keyboard shortcuts (Meta on Mac, Control on Linux/Windows)
In terminal tests, type through the browser using runTerminal() and waitTerminalReady() instead of writing to the PTY through the SDK
Never use wall-clock waits like page.waitForTimeout(...) to make a test pass
Wait on observable state with expect(...), expect.poll(...), or existing helpers instead of assuming work is finished after an action
Use locator assertions like toBeVisible(), toHaveCount(0), and toHaveAttribute(...) for normal UI state verification
Use expect.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 ../actions to account for Windows canonicalization
Test one feature per test file
Call project.trackSession(sessionID, directory?) and project.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: Use Effect.gen(function* () { ... }) for Effect composition
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
Use Effect.callback for callback-based APIs
Prefer DateTime.nowAsDate over new Date(yield* Clock.currentTimeMillis) when you need a Date in Effect code
Use Schema.Class for multi-field data in Effect schemas
Use branded schemas (Schema.brand) for single-value types in Effect
Use Schema.TaggedErrorClass for typed errors in Effect schemas
Use Schema.Defect instead of unknown for defect-like causes in Effect code
In Effect.gen / Effect.fn, prefer yield* new MyError(...) over yield* Effect.fail(new MyError(...)) for direct early-failure branches
Use makeRuntime from src/effect/run-service.ts for all services; it returns { runPromise, runFork, runCallback } backed by a shared memoMap that deduplicates layers
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
Use Effect.addFinalizer or Effect.acquireRelease inside the InstanceState.make closure for cleanup (subscriptions, process teardown, etc.)
Use Effect.forkScoped inside the InstanceState.make closure for background stream consumers — the fiber is interrupted when the instance is disposed
Prefer FileSystem.FileSystem instead of raw fs/promises for effectful file I/O in Effect services
Prefer ChildProcessSpawner.ChildProcessSpawner with ChildProcess.make(...) instead of custom process wrappers in Effect services
Prefer HttpClient.HttpClient instead of raw fetch in Effect services
Prefer Path.Path, Config, Clock, and DateTime services when those concerns are already inside Effect code
For backgroun...

Files:

  • packages/opencode/src/cli/cmd/agent.ts
  • packages/opencode/src/cli/cmd/run.ts
  • packages/opencode/test/session/prompt-effect.test.ts
packages/opencode/test/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (packages/opencode/test/AGENTS.md)

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.
When using the tmpdir function with git repository support, pass the git: true option to initialize a git repo with a root commit.
Use the config option in tmpdir to write an opencode.json config file during test setup by passing a partial Config.Info object.
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.
Use testEffect(...) from test/lib/effect.ts for tests that exercise Effect services or Effect-based workflows.
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.
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.
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.
Avoid custom ManagedRuntime, attach(...), or ad hoc run(...) wrappers in Effect tests when testEffect(...) already provides the runtime.
When a test needs instance-local state, prefer provideTmpdirInstance(...) or provideInstance(...) over manual Instance.provide(...) inside Promise-style tests.

Files:

  • packages/opencode/test/session/prompt-effect.test.ts
🧠 Learnings (39)
📓 Common learnings
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.
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 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.ts
  • packages/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 : Use lowercase, descriptive test names (e.g., 'sidebar can be toggled')

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 : 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.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.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.ts
  • packages/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 : Use camelCase for variable names in tests

Applied to files:

  • packages/app/e2e/session/session-child-navigation.spec.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 one feature per test file

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 : Import test utilities from `../fixtures` instead of `playwright/test`

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.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-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
📚 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 : 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-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/app/e2e/session/session-child-navigation.spec.ts
  • packages/opencode/src/cli/cmd/agent.ts
  • packages/opencode/src/cli/cmd/run.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.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.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-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/cli/cmd/agent.ts
  • packages/opencode/src/cli/cmd/run.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/cli/cmd/agent.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/cli/cmd/agent.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/cli/cmd/agent.ts
  • packages/opencode/src/cli/cmd/run.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/src/cli/cmd/agent.ts
  • packages/opencode/src/cli/cmd/run.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/cli/cmd/agent.ts
📚 Learning: 2026-04-21T16:57:23.748Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 102
File: packages/opencode/src/config/command.ts:23-29
Timestamp: 2026-04-21T16:57:23.748Z
Learning: In Astro-Han/pawwork (`packages/opencode/src/config/`), `Schema.Struct` and `Schema.Class` are both valid and intentionally used patterns across config modules (e.g. `formatter.ts`, `provider.ts`, `permission.ts`, `lsp.ts`, `config.ts`, `keybinds.ts`, `command.ts`). Do not flag `Schema.Struct` usage in config schemas as needing conversion to `Schema.Class` — the choice is driven by upstream alignment and local context, not inconsistency.

Applied to files:

  • packages/opencode/src/cli/cmd/agent.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/cli/cmd/agent.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/cli/cmd/agent.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/cli/cmd/agent.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/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/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} : Use `testEffect(...)` from `test/lib/effect.ts` for tests that exercise Effect services or Effect-based workflows.

Applied to files:

  • packages/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} : 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/prompt-effect.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/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} : 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/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} : 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/prompt-effect.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.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/prompt-effect.test.ts
🔇 Additional comments (7)
packages/app/e2e/session/session-child-navigation.spec.ts (2)

5-5: Test name rename looks correct and remains descriptive.

Good update to reflect the new “agent” terminology while keeping the test title clear and lowercase.

As per coding guidelines, E2E test names should be lowercase and descriptive.


22-22: llm.toolMatch now targets "agent" correctly.

This aligns the mocked dispatch assertion with the renamed tool path and keeps the scenario intent intact.

packages/opencode/test/session/prompt-effect.test.ts (1)

679-683: LGTM!

The mechanical renames from task to agent are correctly applied:

  • Tool invocations now use "agent" tool id
  • Registry access correctly destructures agent from registry.named() (matching the { agent: AgentDef; read: ReadDef } interface)
  • The execute patching pattern is preserved with the renamed variable
  • Test name and error messages are updated to reflect the new terminology

Also applies to: 762-793, 902-910

packages/opencode/src/cli/cmd/run.ts (3)

65-68: LGTM — clean backward-compatible dispatch helper.

The isAgentToolPart helper correctly OR-matches both legacy "task" and new "agent" tool ids, ensuring historical sessions continue to render properly. The inline comment and export for testing are good practices.


167-182: LGTM — renderer and dispatch updates are consistent.

The agent() renderer function and all dispatch sites correctly use the isAgentToolPart helper to handle both legacy and new tool ids. The error path at lines 471-475 properly routes through agent() before printing the error, ensuring consistent UI labeling.

Also applies to: 471-475, 485-491


575-635: LGTM — agent validation variable rename improves clarity.

Renaming the validated agent argument to agentName distinguishes it from the agent() renderer function in the same scope, reducing potential confusion.

Also applies to: 652-652, 662-662

packages/opencode/src/cli/cmd/agent.ts (1)

18-24: LGTM — legacy alias and validation are well-implemented.

The LEGACY_TOOL_ALIASES pattern mirrors Permission.fromConfig's approach, providing symmetric handling of the task → agent migration. The validation logic correctly:

  • Applies legacy aliases before validation
  • Reports unknown tools with a clear error message
  • Exits in non-interactive mode, throws UI.CancelledError in interactive mode
  • De-duplicates the final tool list

Also applies to: 131-151


📝 Walkthrough

Walkthrough

This PR renames the "task" tool to "agent" across code, docs, tests, i18n, CLI, and permissions; it preserves backward compatibility by accepting legacy "task" identifiers and dual-registering renderers where needed.

Changes

Cohort / File(s) Summary
CI / Workflow
\.github/workflows/ci.yml, packages/opencode/test/github/ci-workflow.test.ts
Windows opencode-session shard now runs test/permission-agent.test.ts instead of permission-task.test.ts.
Core tool implementation & docs
packages/opencode/src/tool/agent.ts, packages/opencode/src/tool/agent.txt, packages/opencode/src/agent/generate.txt
Renamed TaskTool → AgentTool and task_idsubagent_session_id; examples and prose updated to "agent"/"subagent".
Tool registry & truncation
packages/opencode/src/tool/registry.ts, packages/opencode/src/tool/truncate.ts
Registry and internal types moved from taskagent; permission checks and truncation hints now evaluate "agent".
Permissions schema & parsing
packages/opencode/src/config/permission.ts, packages/opencode/src/permission/index.ts, packages/sdk/openapi.json
Permission schema key renamed taskagent; config parsing normalizes legacy taskagent.
Session prompt / execution
packages/opencode/src/session/prompt.ts, packages/opencode/src/session/prompt/pawwork.txt
Subtask/subagent execution pathway switched to agent tool stack; prompt text and pawwork guidance updated.
CLI
packages/opencode/src/cli/cmd/agent.ts, packages/opencode/src/cli/cmd/run.ts
Default tool list and render/dispatch updated to agent; adds isAgentToolPart helper and legacy aliasing/validation for task.
App-level i18n & pages
packages/app/src/i18n/en.ts, packages/app/src/i18n/zh.ts, packages/app/src/pages/session/message-timeline.tsx, packages/app/src/pages/session/task-description.ts, packages/app/e2e/...
Renamed permission keys settings.permissions.tool.task.*...tool.agent.*; extracted/shared taskDescription accepts `tool === "task"
UI components & icons
packages/ui/src/components/icon.tsx, packages/ui/src/components/icon.stories.tsx, packages/ui/src/components/message-part.tsx, packages/ui/src/components/tool-info.ts, packages/ui/src/components/tool-error-card.tsx, packages/ui/src/components/timeline-playground.stories.tsx
Icon key taskagent (icons exported), centralized ToolInfo added, message-part rendering unified for "task" and "agent", error card mapping updated.
UI i18n (multiple locales)
packages/ui/src/i18n/{ar,br,bs,da,de,en,es,fr,ja,ko,no,pl,ru,th,tr,zh,zht}.ts
Removed ui.tool.task key across locales.
Tests — permission / tool / cli / ui / message-timeline
packages/opencode/test/permission-agent.test.ts, packages/opencode/test/permission-task.test.ts (deleted), packages/opencode/test/tool/agent.test.ts, packages/opencode/test/tool/agent-rename.test.ts, packages/opencode/test/cli/run-rename.test.ts, packages/opencode/test/session/prompt-effect.test.ts, packages/app/test/i18n/agent-rename.test.ts, packages/app/test/session/message-timeline-rename.test.ts, packages/ui/test/components/icon-registry-rename.test.ts, packages/ui/test/components/message-part-rename.test.ts, packages/opencode/test/tool/truncation.test.ts
Added agent-focused tests, removed legacy permission-task test file, added rename/regex sweep and compatibility tests; updated tests to accept agent/tool field changes.
UI package config & misc
packages/ui/package.json, packages/ui/src/components/icon.stories.tsx
Added test npm script; story samples updated from taskagent.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

app, ui

Poem

🐰 I hopped through code to change a name,
From "task" to "agent" in the dev-frame,
Old sessions nod with legacy grace,
New labels bloom and find their place,
Subagents dance — a tidy, joyful game!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-claude+agent-rename

Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

Code Review

This pull request 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.

Comment thread packages/ui/src/i18n/en.ts
Comment thread packages/opencode/src/tool/agent.ts
Comment thread packages/ui/src/components/message-part.tsx
Comment thread packages/ui/src/components/tool-info.ts Outdated
Copy link
Copy Markdown
Owner Author

@Astro-Han Astro-Han left a comment

Choose a reason for hiding this comment

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

Nitpicky pass for PR #247. I focused on rename drift and backward compatibility gaps.

Comment thread packages/opencode/src/config/permission.ts
Comment thread packages/opencode/test/tool/agent-rename.test.ts
Comment thread packages/ui/src/components/tool-error-card.tsx
Comment thread packages/opencode/src/cli/cmd/run.ts
…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
@Astro-Han Astro-Han force-pushed the worktree-claude+agent-rename branch from 6259a2a to 5998fba Compare April 26, 2026 16:12
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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 | 🟠 Major

Update the mock to assert the new agent tool 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 | 🟡 Minor

Timeout message still references task.

Line 793 should be updated to agent to 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 | 🟡 Minor

Preserve the agent label on failed legacy tool parts.

Completed/running legacy "task" parts go through agent(...), 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

📥 Commits

Reviewing files that changed from the base of the PR and between f283f6f and 5998fba.

📒 Files selected for processing (57)
  • .github/workflows/ci.yml
  • packages/app/e2e/actions.ts
  • packages/app/e2e/session/session-child-navigation.spec.ts
  • packages/app/src/i18n/en.ts
  • packages/app/src/i18n/zh.ts
  • packages/app/src/pages/session/message-timeline.tsx
  • packages/app/src/pages/session/task-description.ts
  • packages/app/test/i18n/agent-rename.test.ts
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/opencode/src/agent/generate.txt
  • packages/opencode/src/cli/cmd/agent.ts
  • packages/opencode/src/cli/cmd/run.ts
  • packages/opencode/src/config/permission.ts
  • packages/opencode/src/permission/index.ts
  • packages/opencode/src/session/prompt.ts
  • packages/opencode/src/session/prompt/pawwork.txt
  • packages/opencode/src/tool/agent.ts
  • packages/opencode/src/tool/agent.txt
  • packages/opencode/src/tool/glob.txt
  • packages/opencode/src/tool/grep.txt
  • packages/opencode/src/tool/registry.ts
  • packages/opencode/src/tool/truncate.ts
  • packages/opencode/test/cli/run-rename.test.ts
  • packages/opencode/test/github/ci-workflow.test.ts
  • packages/opencode/test/permission-agent.test.ts
  • packages/opencode/test/permission-task.test.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/opencode/test/tool/agent.test.ts
  • packages/opencode/test/tool/truncation.test.ts
  • packages/sdk/openapi.json
  • packages/ui/package.json
  • packages/ui/src/components/icon.stories.tsx
  • packages/ui/src/components/icon.tsx
  • packages/ui/src/components/message-part.tsx
  • packages/ui/src/components/timeline-playground.stories.tsx
  • packages/ui/src/components/tool-error-card.tsx
  • packages/ui/src/components/tool-info.ts
  • packages/ui/src/i18n/ar.ts
  • packages/ui/src/i18n/br.ts
  • packages/ui/src/i18n/bs.ts
  • packages/ui/src/i18n/da.ts
  • packages/ui/src/i18n/de.ts
  • packages/ui/src/i18n/en.ts
  • packages/ui/src/i18n/es.ts
  • packages/ui/src/i18n/fr.ts
  • packages/ui/src/i18n/ja.ts
  • packages/ui/src/i18n/ko.ts
  • packages/ui/src/i18n/no.ts
  • packages/ui/src/i18n/pl.ts
  • packages/ui/src/i18n/ru.ts
  • packages/ui/src/i18n/th.ts
  • packages/ui/src/i18n/tr.ts
  • packages/ui/src/i18n/zh.ts
  • packages/ui/src/i18n/zht.ts
  • packages/ui/test/components/icon-registry-rename.test.ts
  • packages/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 createStore over multiple createSignal calls in SolidJS

Files:

  • packages/app/e2e/session/session-child-navigation.spec.ts
  • packages/app/src/pages/session/task-description.ts
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/app/src/i18n/zh.ts
  • packages/app/src/i18n/en.ts
  • packages/app/test/i18n/agent-rename.test.ts
  • packages/app/src/pages/session/message-timeline.tsx
  • packages/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 ../fixtures instead of @playwright/test
Test files should be named with the pattern feature-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 with withSession(sdk, title, callback) for temporary sessions instead of calling sdk.session.delete(...) directly
Prefer the project fixture for tests that need a dedicated project with LLM mocking
Use data-component, data-action, or semantic roles for selectors instead of CSS class names or IDs
Use modKey from utils for cross-platform keyboard shortcuts (Meta on Mac, Control on Linux/Windows)
In terminal tests, type through the browser using runTerminal() and waitTerminalReady() instead of writing to the PTY through the SDK
Never use wall-clock waits like page.waitForTimeout(...) to make a test pass
Wait on observable state with expect(...), expect.poll(...), or existing helpers instead of assuming work is finished after an action
Use locator assertions like toBeVisible(), toHaveCount(0), and toHaveAttribute(...) for normal UI state verification
Use expect.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 ../actions to account for Windows canonicalization
Test one feature per test file
Call project.trackSession(sessionID, directory?) and project.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: Use Effect.gen(function* () { ... }) for Effect composition
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
Use Effect.callback for callback-based APIs
Prefer DateTime.nowAsDate over new Date(yield* Clock.currentTimeMillis) when you need a Date in Effect code
Use Schema.Class for multi-field data in Effect schemas
Use branded schemas (Schema.brand) for single-value types in Effect
Use Schema.TaggedErrorClass for typed errors in Effect schemas
Use Schema.Defect instead of unknown for defect-like causes in Effect code
In Effect.gen / Effect.fn, prefer yield* new MyError(...) over yield* Effect.fail(new MyError(...)) for direct early-failure branches
Use makeRuntime from src/effect/run-service.ts for all services; it returns { runPromise, runFork, runCallback } backed by a shared memoMap that deduplicates layers
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
Use Effect.addFinalizer or Effect.acquireRelease inside the InstanceState.make closure for cleanup (subscriptions, process teardown, etc.)
Use Effect.forkScoped inside the InstanceState.make closure for background stream consumers — the fiber is interrupted when the instance is disposed
Prefer FileSystem.FileSystem instead of raw fs/promises for effectful file I/O in Effect services
Prefer ChildProcessSpawner.ChildProcessSpawner with ChildProcess.make(...) instead of custom process wrappers in Effect services
Prefer HttpClient.HttpClient instead of raw fetch in Effect services
Prefer Path.Path, Config, Clock, and DateTime services when those concerns are already inside Effect code
For backgroun...

Files:

  • packages/opencode/test/github/ci-workflow.test.ts
  • packages/opencode/test/cli/run-rename.test.ts
  • packages/opencode/src/config/permission.ts
  • packages/opencode/src/cli/cmd/agent.ts
  • packages/opencode/src/tool/truncate.ts
  • packages/opencode/src/permission/index.ts
  • packages/opencode/test/tool/truncation.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/opencode/src/cli/cmd/run.ts
  • packages/opencode/test/permission-agent.test.ts
  • packages/opencode/src/tool/registry.ts
  • packages/opencode/src/tool/agent.ts
  • packages/opencode/src/session/prompt.ts
  • packages/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 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.
When using the tmpdir function with git repository support, pass the git: true option to initialize a git repo with a root commit.
Use the config option in tmpdir to write an opencode.json config file during test setup by passing a partial Config.Info object.
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.
Use testEffect(...) from test/lib/effect.ts for tests that exercise Effect services or Effect-based workflows.
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.
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.
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.
Avoid custom ManagedRuntime, attach(...), or ad hoc run(...) wrappers in Effect tests when testEffect(...) already provides the runtime.
When a test needs instance-local state, prefer provideTmpdirInstance(...) or provideInstance(...) over manual Instance.provide(...) inside Promise-style tests.

Files:

  • packages/opencode/test/github/ci-workflow.test.ts
  • packages/opencode/test/cli/run-rename.test.ts
  • packages/opencode/test/tool/truncation.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/opencode/test/permission-agent.test.ts
  • packages/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.ts
  • packages/ui/test/components/icon-registry-rename.test.ts
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/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.ts
  • packages/opencode/test/github/ci-workflow.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/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.ts
  • packages/app/test/i18n/agent-rename.test.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/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.ts
  • packages/ui/test/components/icon-registry-rename.test.ts
  • packages/app/test/i18n/agent-rename.test.ts
  • packages/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.ts
  • packages/ui/test/components/icon-registry-rename.test.ts
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/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.ts
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/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.ts
  • packages/app/test/i18n/agent-rename.test.ts
  • packages/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.ts
  • packages/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.ts
  • packages/ui/test/components/icon-registry-rename.test.ts
  • packages/opencode/test/cli/run-rename.test.ts
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/opencode/test/tool/truncation.test.ts
  • packages/ui/test/components/message-part-rename.test.ts
  • packages/app/test/i18n/agent-rename.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/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.ts
  • packages/app/src/pages/session/task-description.ts
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/app/src/i18n/zh.ts
  • packages/app/src/i18n/en.ts
  • packages/app/test/i18n/agent-rename.test.ts
  • packages/app/src/pages/session/message-timeline.tsx
  • packages/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.ts
  • packages/ui/src/components/icon.tsx
  • packages/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.ts
  • packages/opencode/test/github/ci-workflow.test.ts
  • packages/opencode/test/cli/run-rename.test.ts
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/opencode/test/tool/truncation.test.ts
  • packages/ui/test/components/message-part-rename.test.ts
  • packages/app/test/i18n/agent-rename.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/opencode/test/permission-agent.test.ts
  • packages/opencode/src/tool/registry.ts
  • packages/opencode/src/session/prompt.ts
  • packages/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.yml
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/opencode/test/permission-agent.test.ts
  • packages/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.ts
  • packages/opencode/test/cli/run-rename.test.ts
  • .github/workflows/ci.yml
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/opencode/test/permission-agent.test.ts
  • packages/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.ts
  • packages/opencode/test/cli/run-rename.test.ts
  • packages/opencode/test/tool/truncation.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/opencode/test/permission-agent.test.ts
  • packages/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.ts
  • packages/opencode/test/permission-agent.test.ts
  • packages/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.ts
  • packages/opencode/test/cli/run-rename.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/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.ts
  • packages/opencode/test/cli/run-rename.test.ts
  • packages/opencode/test/tool/truncation.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/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.ts
  • packages/opencode/test/cli/run-rename.test.ts
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/opencode/test/permission-agent.test.ts
  • packages/opencode/src/session/prompt.ts
  • packages/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.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/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.ts
  • packages/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.yml
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/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.ts
  • packages/opencode/src/tool/truncate.ts
  • packages/opencode/src/permission/index.ts
  • packages/app/src/i18n/zh.ts
  • packages/opencode/test/tool/truncation.test.ts
  • packages/app/src/i18n/en.ts
  • packages/sdk/openapi.json
  • packages/opencode/test/tool/agent-rename.test.ts
  • packages/opencode/src/cli/cmd/run.ts
  • packages/opencode/test/permission-agent.test.ts
  • packages/opencode/src/tool/registry.ts
  • packages/opencode/src/tool/agent.ts
  • packages/opencode/src/session/prompt.ts
  • packages/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.ts
  • packages/app/test/session/message-timeline-rename.test.ts
  • packages/ui/test/components/message-part-rename.test.ts
  • packages/app/src/pages/session/message-timeline.tsx
  • packages/opencode/src/cli/cmd/run.ts
  • packages/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.ts
  • packages/app/src/i18n/zh.ts
  • packages/app/src/i18n/en.ts
  • packages/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.ts
  • packages/opencode/src/session/prompt/pawwork.txt
  • packages/app/e2e/actions.ts
  • packages/opencode/test/session/prompt-effect.test.ts
  • packages/opencode/src/session/prompt.ts
  • packages/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.ts
  • packages/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.ts
  • packages/opencode/src/session/prompt/pawwork.txt
  • packages/app/src/i18n/en.ts
  • packages/app/test/i18n/agent-rename.test.ts
  • packages/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.ts
  • packages/app/src/i18n/en.ts
  • packages/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.ts
  • packages/app/test/i18n/agent-rename.test.ts
  • packages/ui/src/components/message-part.tsx
  • packages/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.ts
  • packages/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.ts
  • packages/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.ts
  • packages/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.ts
  • packages/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.ts
  • 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.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.ts
  • 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 : 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.ts
  • packages/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)

Comment thread packages/opencode/src/agent/generate.txt
Comment thread packages/opencode/src/cli/cmd/agent.ts
Comment thread packages/opencode/src/session/prompt.ts
Comment thread packages/opencode/src/tool/agent.txt
Comment thread packages/ui/src/components/message-part.tsx
@Astro-Han
Copy link
Copy Markdown
Owner Author

Outside-diff feedback

Addressed CodeRabbit's three outside-diff items:

1. packages/app/e2e/session/session-child-navigation.spec.ts (Major) — Update mock to assert agent tool

Accepted. Changed llm.toolMatch(inputMatch(taskInput), "task", taskInput)"agent". Test name was updated to "agent tool" earlier in this PR; the stub literal now matches.

2. packages/opencode/test/session/prompt-effect.test.ts:793 (Minor) — Timeout error message terminology

Accepted. Changed "timed out waiting for running task metadata""running agent metadata".

3. packages/opencode/src/cli/cmd/run.ts:465-476 (Minor) — Error branch loses agent label for legacy tool: "task"

Accepted. Added if (isAgentToolPart(part.tool)) { agent(...); UI.error(...); continue } branch before the generic error inline. Failed legacy task parts now render with the localized "Agent" label instead of "task failed".

- 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.
@Astro-Han Astro-Han merged commit b97ce51 into dev Apr 26, 2026
25 checks passed
@Astro-Han Astro-Han deleted the worktree-claude+agent-rename branch April 26, 2026 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request harness Model harness, prompts, tool descriptions, and session mechanics P1 High priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Rename and rewrite task as subagent

1 participant