Skip to content

refactor(tool): description cleanup + multiedit dead-code removal (PR1 of #129)#235

Merged
Astro-Han merged 12 commits into
devfrom
claude/tool-cleanup-pr1
Apr 26, 2026
Merged

refactor(tool): description cleanup + multiedit dead-code removal (PR1 of #129)#235
Astro-Han merged 12 commits into
devfrom
claude/tool-cleanup-pr1

Conversation

@Astro-Han

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

Copy link
Copy Markdown
Owner

Summary

PR1 of #129. Two strands combined: description cleanup across 7 tool files (including edit.txt line-deletion hint), and multiedit dead-code removal.

8 commits, 16 paths changed (+22 / -192).

  1. expand trash.txt rm-vs-trash boundary
  2. remove speculative-batch over-push from glob.txt
  3. fix skill.txt pointer to "listed below"
  4. rework bash.txt rm/deletion guardrails (rm→mkdir example, add File deletion sub-bullet, drop two TodoWrite/Task negations)
  5. remove over-push framing from todowrite.txt
  6. clean task.txt fictional examples and over-push (drop <example_agent_descriptions> block, Usage 1+4, fix dangling refs)
  7. add line-deletion hint to edit.txt
  8. remove multiedit dead code (atomic 9-path: delete multiedit.ts+multiedit.txt, strip string literals from permission/index.ts+config/agent.ts+config/config.ts, drop spec mention, rename two tests, delete migration test)

Why

Per #129. Tool descriptions in upstream opencode were tuned for a different audience and contained: fictional <example_agent_descriptions> blocks (code-reviewer/greeting-responder not in PawWork), over-push framing ("It is always better to speculatively...", "demonstrates attentiveness"), boundary leaks (rm "path with spaces/file.txt" example contradicting trash-as-canonical), wrong pointers (skill.txt "listed in the system prompt" — actually appended below by registry.ts:283), and dangling references after registry edits. multiedit was never registered in registry.ts (dead code), and its description claimed atomicity that the implementation never provided (multiedit.ts:38-50 was a plain for-loop, no rollback).

Per user decision: PawWork has no legacy users / no legacy config in the wild, so the entire multiedit migration code path is removed (not preserved as no-op).

apply_patch.txt was originally going to get a *** Delete File: prose guardrail; dropped after design review showed the wording risked confusing models on legitimate refactor-time source deletions (apply_patch IS the right tool for tracked-source removal; trash is wrong for git-tracked files). Revisit if real sessions show models reaching for *** Delete File: on user-facing files.

Related Issue

Closes #129 (PR1 only; PR2 will handle codesearch removal).

How To Verify

bun --cwd packages/opencode typecheck
bun --cwd packages/opencode test
{ rg -nw 'multiedit' packages/ --glob '!docs/superpowers/**' ; \
  rg -n '"multiedit"' packages/ --glob '!docs/superpowers/**' ; \
  rg -n 'MultiEditTool' packages/ --glob '!docs/superpowers/**' ; }

Local results:

  • Baseline (before any change): typecheck PASS, test 2072 pass / 0 fail
  • After all 8 commits: typecheck PASS, test 2071 pass / 0 fail (one fewer test, one fewer expect from deleted multiedit migration test; matches expectation)
  • Combined multiedit grep: zero hits

Manual smoke matrix (deferred to real PawWork sessions, recorded in PR comment):

  • Models: Opus / Sonnet / GLM-5.1 / Kimi K2.6 / Qwen Coder
  • Provider routing: at least one Zen-routed run AND one ProviderID.opencode run
  • Use task dispatch; verify deletion goes through trash (not rm); verify multi-edit-style change works as repeated edit calls; no model attempts multiedit
  • Edit-tool line-deletion: ask a model to delete a single line; verify the diff has no stray blank line

Screenshots or Recordings

N/A. No UI surface changed.

Checklist

  • I linked the related issue, or stated why there is no issue
  • This PR has type, scope, and priority labels, or I requested maintainer labeling
  • I listed the relevant verification steps, including tests when behavior changed
  • I manually checked visible UI or copy changes when needed, with screenshots or recordings (N/A — no UI)
  • I considered macOS and Windows impact for desktop, packaging, updater, signing, paths, shell, or permissions changes (none; tool description prose + dead-code removal only)
  • I called out docs, release notes, dependencies, permissions, credentials, deletion behavior, or generated/local file changes when relevant (deletion behavior: trash remains canonical; rm deny rule at agent.ts:99-110 unchanged; bash.txt now points at trash explicitly)
  • I am targeting dev, and my PR title and commit messages use Conventional Commits in English

Summary by CodeRabbit

  • Removed Features

    • Removed the multiedit tool; use individual edit operations instead.
  • Behavior Changes

    • Permission mapping updated so multiedit no longer maps into the general edit permission and now has its own permission entry.
  • Documentation

    • Clarified edit deletion behavior, safer bash quoting examples, stronger trash guidance, and refined skill, task, glob, and todo tool docs.
  • Tests

    • Updated tests to reflect multiedit removal and permission mapping change.

Make trash explicitly the canonical deletion path; contrast with rm/del
permanence; reference the existing permission-layer block on rm. Per #129.
The 'It is always better to speculatively perform multiple searches as a
batch' sentence pushed weaker models toward parallel work without a
supporting reason. Keep the parallel-call capability reminder; drop the
push. Per #129.
The skill list is appended at the end of the skill tool description
itself by registry.ts:283 (describeSkill), not in the system prompt.
Both L1 and L5 had the wrong pointer. Per #129.
- Replace 'rm "path with spaces"' quoting example with 'mkdir "..."';
  bash.txt's own L31 list forbids cat, and python would duplicate L20.
- Add 'File deletion: Use the trash tool, NOT rm/del' sub-bullet to the
  L31 nested 'Avoid using Bash with' list.
- Delete the two 'NEVER/DO NOT use the TodoWrite or Task tools' lines
  inside the git/PR workflow block; they contradict PawWork's project-level
  encouragement of TodoWrite for multi-step work.

Per #129. Note: rm/rmdir/unlink are already denied at the permission layer
(agent.ts:99-110); this commit reduces the wasted first-attempt and stops
bash.txt from suggesting rm as the canonical example.
The 'demonstrate thoroughness to the user' framing on L1 and the
'When in doubt, use this tool ... demonstrates attentiveness' line on
L166 push using the todo tool as performance, not organization. Remove
both. The 8-example demonstration block remains deferred. Per #129.
- Delete fictional <example_agent_descriptions> block and both <example>
  blocks referencing code-reviewer / greeting-responder.
- Delete Usage 1 ('Launch multiple agents concurrently') and Usage 4
  ('outputs should generally be trusted'); renumber remaining.
- Rewrite L12 dangling 'agent descriptions above' and Usage 6's 'agent
  description' to schema-independent 'the available agents'.

Per #129.
Weaker models commonly delete a single line by passing the line content
as oldString and an empty newString, but forget to include the trailing
newline, leaving a stray blank line at the deleted position. Add an
explicit hint so the tool is harder to misuse on this boundary case.
Per #129.
multiedit was never registered in registry.ts builtin tool list. The
description claimed atomicity ('All edits must be valid for the
operation to succeed') but multiedit.ts:38-50 was a plain for loop
with each successful write landing immediately and no rollback; the
description lied about runtime behavior.

Remove .ts + .txt + three string-literal references in permission/config
+ one spec mention + three test references (rename two tests, delete
one multiedit-specific migration test). Atomic so no intermediate state
has dangling references.

Per user decision: no legacy users / no legacy config in the wild, so
the entire multiedit migration code path is removed (not preserved as
no-op). Models that need multiple edits in one file issue multiple edit
calls; functionally equivalent and removes the lying description.

Per #129.
@Astro-Han Astro-Han added enhancement New feature or request P2 Medium priority harness Model harness, prompts, tool descriptions, and session mechanics labels Apr 25, 2026
@coderabbitai

coderabbitai Bot commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

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

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

⌛ How to resolve this issue?

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

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

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

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

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 56ec419d-6233-46e0-89f5-84195e677dd7

📥 Commits

Reviewing files that changed from the base of the PR and between 7c4fcd1 and 15fe288.

📒 Files selected for processing (1)
  • packages/opencode/src/tool/edit.txt
📝 Walkthrough

Walkthrough

Removes the multiedit tool and its docs, updates permission normalization so multiedit maps to its own permission key instead of aliasing edit, and revises multiple tool documentation files for safety and clarity.

Changes

Cohort / File(s) Summary
Multiedit removal
packages/opencode/src/tool/multiedit.ts, packages/opencode/src/tool/multiedit.txt, packages/opencode/specs/effect-migration.md
Deleted the multiedit tool implementation and its documentation; removed multiedit from the migration checklist.
Permission & config normalization
packages/opencode/src/config/agent.ts, packages/opencode/src/config/config.ts, packages/opencode/src/permission/index.ts
Exclude "multiedit" from the special-case EDIT_TOOLS mapping so it no longer remaps into the edit permission; it now yields a dedicated permission.multiedit entry.
Tool documentation edits
packages/opencode/src/tool/bash.txt, packages/opencode/src/tool/edit.txt, packages/opencode/src/tool/glob.txt, packages/opencode/src/tool/skill.txt, packages/opencode/src/tool/task.txt, packages/opencode/src/tool/todowrite.txt, packages/opencode/src/tool/trash.txt
Rewrote examples and guidance to improve deletion guardrails (prefer trash over shell rm/del), clarified edit newline semantics, removed speculative/misleading delegation examples, and tightened usage wording.
Tests updated
packages/opencode/test/agent/agent.test.ts, packages/opencode/test/config/config.test.ts, packages/opencode/test/permission/next.test.ts
Removed/updated tests referencing multiedit migration and adjusted test names/assertions to reflect the new permission mapping behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

documentation, upstream, P3

Poem

🐰 The multiedit hop has skipped away,
Docs trimmed tidy for a safer day,
Trash now shines where errors hide,
Permissions neat, no alias to bide,
A rabbit cheers the cleaner way. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly identifies the main changes: description cleanup across tool files and removal of multiedit dead code, with both strands matching the changeset content.
Description check ✅ Passed The PR description is comprehensive, covering summary, motivation, issue linkage, verification steps, and completed checklist against the template requirements.
Linked Issues check ✅ Passed The PR implements all PR1 objectives from #129: tool description cleanup across 7 files, multiedit code/docs/tests removal, permission/config updates, and enhanced deletion guardrails.
Out of Scope Changes check ✅ Passed All 16 file changes align with PR1 scope: 7 tool .txt documentation updates, multiedit.ts and multiedit.txt deletion, 4 config/permission/spec file updates, and 2 test renames plus 1 test deletion. No out-of-scope changes detected.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/tool-cleanup-pr1

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
packages/opencode/test/agent/agent.test.ts (1)

493-510: ⚠️ Potential issue | 🟡 Minor

Test name overstates coverage.

Line 493 says write/edit/patch are covered, but this case only validates write -> edit. Please either add edit/patch cases or narrow the title.

💡 Minimal title fix
-test("legacy tools config maps write/edit/patch to edit permission", async () => {
+test("legacy tools config maps write to edit permission", async () => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/opencode/test/agent/agent.test.ts` around lines 493 - 510, The test
name "legacy tools config maps write/edit/patch to edit permission" is
misleading because the body only checks write -> edit; update the test to either
rename it to accurately reflect that it only validates write->edit (e.g.,
"legacy tools config maps write to edit permission") or extend the test to cover
the other mappings by adding assertions that set config.agent.build.tools.edit
and config.agent.build.tools.patch (using tmpdir, Instance.provide, Agent.get
and evalPerm) and assert their expected permissions; locate the existing test
declaration and modify the title or add the extra cases for edit and patch
accordingly.
🤖 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/tool/task.txt`:
- Around line 16-17: Edit the two phrases that use redundant “back” wording:
replace “return a single message back to you” with “return a single message to
you” and replace “send a text message back to the user” (and any other
occurrences of “return back”/“send back”) with “send a text message to the user”
or “return to the user” so the instructions read concisely and without
duplicated prepositions.

---

Outside diff comments:
In `@packages/opencode/test/agent/agent.test.ts`:
- Around line 493-510: The test name "legacy tools config maps write/edit/patch
to edit permission" is misleading because the body only checks write -> edit;
update the test to either rename it to accurately reflect that it only validates
write->edit (e.g., "legacy tools config maps write to edit permission") or
extend the test to cover the other mappings by adding assertions that set
config.agent.build.tools.edit and config.agent.build.tools.patch (using tmpdir,
Instance.provide, Agent.get and evalPerm) and assert their expected permissions;
locate the existing test declaration and modify the title or add the extra cases
for edit and patch accordingly.
🪄 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: 35612100-c150-44ad-86ec-0c4bab0242f7

📥 Commits

Reviewing files that changed from the base of the PR and between 787acf2 and f9a82e3.

📒 Files selected for processing (16)
  • packages/opencode/specs/effect-migration.md
  • packages/opencode/src/config/agent.ts
  • packages/opencode/src/config/config.ts
  • packages/opencode/src/permission/index.ts
  • packages/opencode/src/tool/bash.txt
  • packages/opencode/src/tool/edit.txt
  • packages/opencode/src/tool/glob.txt
  • packages/opencode/src/tool/multiedit.ts
  • packages/opencode/src/tool/multiedit.txt
  • packages/opencode/src/tool/skill.txt
  • packages/opencode/src/tool/task.txt
  • packages/opencode/src/tool/todowrite.txt
  • packages/opencode/src/tool/trash.txt
  • packages/opencode/test/agent/agent.test.ts
  • packages/opencode/test/config/config.test.ts
  • packages/opencode/test/permission/next.test.ts
💤 Files with no reviewable changes (4)
  • packages/opencode/specs/effect-migration.md
  • packages/opencode/src/tool/multiedit.txt
  • packages/opencode/test/config/config.test.ts
  • packages/opencode/src/tool/multiedit.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). (11)
  • GitHub Check: unit-windows-opencode-config-project
  • GitHub Check: unit-windows-desktop
  • GitHub Check: unit-windows-opencode-server-tools
  • GitHub Check: unit-windows-app
  • GitHub Check: unit-windows-opencode-session
  • GitHub Check: unit-desktop
  • GitHub Check: unit-opencode
  • GitHub Check: typecheck
  • GitHub Check: smoke-macos-arm64
  • GitHub Check: e2e-artifacts
  • GitHub Check: analyze-js-ts
🧰 Additional context used
📓 Path-based instructions (2)
packages/opencode/**/*.ts

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

packages/opencode/**/*.ts: 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/config/config.ts
  • packages/opencode/src/config/agent.ts
  • packages/opencode/test/permission/next.test.ts
  • packages/opencode/test/agent/agent.test.ts
  • packages/opencode/src/permission/index.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/permission/next.test.ts
  • packages/opencode/test/agent/agent.test.ts
🧠 Learnings (13)
📓 Common learnings
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-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/config.ts
  • packages/opencode/src/config/agent.ts
  • packages/opencode/test/permission/next.test.ts
  • packages/opencode/test/agent/agent.test.ts
  • packages/opencode/src/permission/index.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/config.ts
  • packages/opencode/src/config/agent.ts
📚 Learning: 2026-04-22T08:49:47.800Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/desktop-electron/src/main/index-sidecar-source.test.ts:3-11
Timestamp: 2026-04-22T08:49:47.800Z
Learning: In `packages/desktop-electron/src/main/index-sidecar-source.test.ts` (Astro-Han/pawwork), the test intentionally uses `expect(source).toContain` / `expect(source).not.toContain` string matching against the raw `index.ts` source text as a lightweight sidecar contract guard. The maintainer has explicitly chosen not to introduce an AST parser (e.g., `babel/parser` or acorn) for this purpose. Do not flag these string-based assertions as fragile or suggest converting them to AST-based matching.

Applied to files:

  • packages/opencode/test/permission/next.test.ts
  • packages/opencode/test/agent/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/permission/next.test.ts
  • packages/opencode/test/agent/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} : 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/agent/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 : Test one feature per test file

Applied to files:

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

Applied to files:

  • packages/opencode/test/agent/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/packages/app/src/testing/**/*.ts : Test-only hooks must be inert unless explicitly enabled and should not add normal-runtime listeners, reactive subscriptions, or per-update allocations

Applied to files:

  • packages/opencode/test/agent/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/agent/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 : Use lowercase, descriptive test names (e.g., 'sidebar can be toggled')

Applied to files:

  • packages/opencode/test/agent/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 `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/agent/agent.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: ALWAYS USE PARALLEL TOOLS WHEN APPLICABLE for tool calling

Applied to files:

  • packages/opencode/src/tool/bash.txt
🪛 LanguageTool
packages/opencode/src/tool/task.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)

🔇 Additional comments (12)
packages/opencode/src/tool/skill.txt (1)

1-5: Good pointer cleanup in skill constraints.

Line 1 and Line 5 now reference skills “listed below,” which is clearer and less brittle than referencing an external prompt location.

packages/opencode/src/tool/glob.txt (1)

6-6: Line 6 guidance is appropriately generalized.

This keeps parallel/multi-tool capability explicit without prescribing speculative batching behavior.

packages/opencode/src/tool/edit.txt (1)

11-11: Helpful deletion-specific instruction added.

Line 11 documents a real footgun for exact replacements and should reduce stray blank-line diffs.

packages/opencode/src/tool/todowrite.txt (1)

1-1: Line 1 wording is cleaner and more action-oriented.

The revised sentence stays specific to task tracking value without over-framing.

packages/opencode/src/tool/trash.txt (1)

3-5: Strong safety clarification for deletion workflows.

Line 3 and Line 5 make reversibility vs permanence explicit and reduce misuse of shell deletion commands.

packages/opencode/src/tool/bash.txt (2)

16-16: Line 16 example is a safer, clearer quoting exemplar.

This avoids reinforcing destructive-command examples while still teaching correct path quoting.


38-38: Good hard guardrail on shell-based deletions.

Line 38 is explicit and aligns the Bash tool contract with trash-first deletion behavior.

packages/opencode/src/tool/task.txt (1)

12-12: Line 12 agent-scoping language is clearer.

This better anchors Task-tool exclusions to the actual available agent set.

packages/opencode/src/config/agent.ts (1)

111-115: Permission remapping update looks correct.

This keeps legacy tools migration aligned with multiedit removal while preserving write/edit/patch → permission.edit behavior.

packages/opencode/src/config/config.ts (1)

733-737: Config-side legacy tool normalization is consistent.

This mirrors the agent normalization change and cleanly removes multiedit aliasing from edit permission derivation.

packages/opencode/src/permission/index.ts (1)

297-303: EDIT_TOOLS update is aligned with tool deprecation.

Removing "multiedit" here keeps Permission.disabled() behavior consistent with the runtime tool set.

packages/opencode/test/permission/next.test.ts (1)

390-402: Updated disabled-tool expectation is correct.

This test now precisely reflects the supported edit aliases (edit, write, apply_patch) after multiedit removal.

Comment thread packages/opencode/src/tool/task.txt

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request removes the multiedit tool and its associated configurations, tests, and documentation. It also updates the instruction files for several other tools, including bash, edit, task, and trash, to refine operational guidance and safety protocols. Review feedback suggests using relative paths in documentation examples for better compatibility, clarifying the parameters for line deletion in the edit tool, and standardizing the use of the trash tool for all file deletions.

Comment thread packages/opencode/src/tool/bash.txt
Comment thread packages/opencode/src/tool/edit.txt Outdated
Comment thread packages/opencode/src/tool/trash.txt Outdated

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Review pass: two concrete inline findings, graded by P-level.

Comment thread packages/opencode/src/tool/trash.txt Outdated
Comment thread packages/opencode/test/agent/agent.test.ts Outdated
Address @Astro-Han P2 review on PR #235: original L5 claimed PawWork's
permission system blocks shell deletion 'by default', but agent.ts:106-109
only denies rm/rmdir/unlink/find-delete; Windows del/erase/Remove-Item
are not yet blocked. Narrow the claim to rm-family and explicitly note
the Windows gap. Also drop 'in user-facing flows' qualifier (gemini
review): the trash tool is the canonical deletion path regardless of
flow context.
Address @Astro-Han P3 review on PR #235: the test fixture only sets
'tools.write = false' and asserts the resulting edit permission, so the
'write/edit/patch' name overstates coverage. Narrow the name to
'tools.write' which matches what the test actually exercises. The
agent.ts:111 union check still covers all three legacy aliases; this
is a test-name accuracy fix only.
Address gemini-code-assist review on PR #235: the original hint named
the trailing-newline requirement on oldString but left newString
implicit. Make both sides of the line-deletion contract explicit so
weaker models do not just check the (already-empty) newString and miss
the oldString fix.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/opencode/src/tool/edit.txt`:
- Line 11: Split the long guidance sentence that begins "To delete a line
cleanly, include the trailing newline character in `oldString`..." into two
sentences for readability, and add a short concrete example immediately after
(e.g., show oldString containing "line-to-delete\n" replaced with "" results in
the line being removed with no blank line). Update the surrounding paragraph in
packages/opencode/src/tool/edit.txt to use the shorter sentences and include the
example to demonstrate the behavior.
🪄 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: 02df6eb9-9511-43cd-a88a-adf0de6e5ce3

📥 Commits

Reviewing files that changed from the base of the PR and between f9a82e3 and 7c4fcd1.

📒 Files selected for processing (3)
  • packages/opencode/src/tool/edit.txt
  • packages/opencode/src/tool/trash.txt
  • packages/opencode/test/agent/agent.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: smoke-macos-arm64
  • GitHub Check: unit-windows-app
  • GitHub Check: unit-windows-opencode-config-project
  • GitHub Check: unit-windows-opencode-session
  • GitHub Check: unit-windows-desktop
  • GitHub Check: unit-windows-opencode-server-tools
  • GitHub Check: unit-app
  • GitHub Check: unit-opencode
  • GitHub Check: unit-desktop
  • GitHub Check: typecheck
  • GitHub Check: e2e-artifacts
  • GitHub Check: analyze-js-ts
🧰 Additional context used
📓 Path-based instructions (2)
packages/opencode/**/*.ts

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

packages/opencode/**/*.ts: 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/agent/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/agent/agent.test.ts
🧠 Learnings (10)
📚 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/test/agent/agent.test.ts
  • packages/opencode/src/tool/trash.txt
📚 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/agent/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/agent/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} : 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/agent/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 : Use lowercase, descriptive test names (e.g., 'sidebar can be toggled')

Applied to files:

  • packages/opencode/test/agent/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 : Use camelCase for variable names in tests

Applied to files:

  • packages/opencode/test/agent/agent.test.ts
📚 Learning: 2026-04-22T08:49:47.800Z
Learnt from: Astro-Han
Repo: Astro-Han/pawwork PR: 126
File: packages/desktop-electron/src/main/index-sidecar-source.test.ts:3-11
Timestamp: 2026-04-22T08:49:47.800Z
Learning: In `packages/desktop-electron/src/main/index-sidecar-source.test.ts` (Astro-Han/pawwork), the test intentionally uses `expect(source).toContain` / `expect(source).not.toContain` string matching against the raw `index.ts` source text as a lightweight sidecar contract guard. The maintainer has explicitly chosen not to introduce an AST parser (e.g., `babel/parser` or acorn) for this purpose. Do not flag these string-based assertions as fragile or suggest converting them to AST-based matching.

Applied to files:

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

Applied to files:

  • packages/opencode/test/agent/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 : Test one feature per test file

Applied to files:

  • packages/opencode/test/agent/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/trash.txt
🔇 Additional comments (2)
packages/opencode/src/tool/trash.txt (1)

3-6: Good safety clarification and accurate platform caveat.

This wording is much clearer: it correctly promotes reversible deletion via Trash and avoids over-claiming by explicitly noting that Windows shell deletion commands are not yet blocked by default.

packages/opencode/test/agent/agent.test.ts (1)

493-493: LGTM — test name now accurately reflects coverage.

The updated test name correctly describes what the test actually verifies: that the legacy tools.write config option maps to the edit permission. This implements the suggestion from the past review to narrow the test name to match the actual fixture and assertion.

Comment thread packages/opencode/src/tool/edit.txt Outdated
Address coderabbit nitpick on PR #235: the hint named the trailing
newline requirement abstractly. Add an inline example showing the
literal '\\n' byte and the oldString/newString shape, matching the
existing inline-example convention at L5 ('(e.g., `1: `)'). Helps
weaker models bridge the 'what does trailing newline look like'
gap without expanding to a multi-line bullet.
@Astro-Han Astro-Han merged commit ce3b231 into dev Apr 26, 2026
23 checks passed
@Astro-Han Astro-Han deleted the claude/tool-cleanup-pr1 branch April 26, 2026 01:28
@coderabbitai coderabbitai Bot mentioned this pull request Apr 29, 2026
7 tasks
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 P2 Medium priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Tool set cleanup: rewrite descriptions, remove redundant tools, harden deletion guardrails

1 participant