Repository navigation
Conversation
The repository stores every text file with LF endings, but nothing said so. A commit made on a machine whose core.autocrlf is false therefore stored whatever the editor happened to write, and a file saved with CRLF endings landed in the commit as CRLF. The next edit to that file then rewrote every line of it, which turned a small fix into a whole-file diff and hid the real change. A .gitattributes file pins the convention, so the line endings of a file no longer depend on the settings of the machine that makes the commit.
The plugin declared @opencode-ai/plugin as a runtime dependency and the host-provided @opentui/solid and solid-js peers as required peers. npm auto-installs required peers, so every host that installed this plugin also installed @opentui/core, typescript, web-tree-sitter, @babel and a second Effect runtime. The OpenCode log reported the resulting install as a stalled plugin preparation step: message="plugin operation stalled" component=plugin stage=prepare elapsedMs=5002 target=@prevalentware/opencode-goal-plugin install=true @opencode-ai/plugin is only imported with `import type`, so it never reaches the built bundle: dist/server.js imports zod, effect-goal-state and node builtins only. The TUI peers are supplied by the OpenCode host at runtime, which is why @opencode-ai/plugin itself declares the equivalent peers as optional. Measured on this repository by packing the published files and installing each variant into an isolated project: before: 10.20s, 157.81 MB, 11928 files after: 5.94s, 33.48 MB, 4589 files Adds test/dependencies.test.ts to keep the runtime imports and the declared dependencies in sync, and to assert that the host-provided peers stay optional so the install footprint cannot silently grow back.
The host resolves the plugin entrypoint through the exports map of the installed package, and it falls back to the main entry when the subpath does not resolve. The subpaths only answered to the "import" condition and the package had no main entry at all, so a host that resolved them under another condition found no entrypoint: the host reports that as "Plugin entrypoint not found", leaves the location without a fully activated plugin set, and fails the commands that need one with "Location plugins did not finish activating". Both subpaths now carry a default condition and the package has a main entry that points at the bundle, so the entrypoint resolves whichever condition the host resolves it under.
The goal plugin replaces its state file through a same-directory temp file and a rename. On Windows that rename fails with EPERM/EACCES/EBUSY while an antivirus scanner, a search indexer, or a concurrent reader still holds the target open, and those locks routinely outlive a couple of hundred milliseconds. The retry budget was three attempts with a 60ms total backoff, so a transient lock surfaced as a failed goal state write and the goal tools threw EPERM to the caller. The budget is now ten attempts with a capped exponential backoff (~2.6s worst case, still one rename when uncontended). Also fixes two Windows-only test failures that the upstream suite carried: the state-recovery log assertion compared a raw path against a JSON stringified payload (JSON escaping doubles the path separators), and the TUI test helpers replaced the state file with a bare rename that has no retry.
ggrabarz
force-pushed
the
pr/02-goal-state-rename-locks
branch
from
October 21, 2026 09:47
733903f to
a1d4fb2
Compare
danyel117
reviewed
Oct 22, 2026
danyel117
left a comment
Contributor
There was a problem hiding this comment.
The retry logic is scoped, but its new regression test injects EPERM through a mock and the repository CI runs only on Ubuntu. It proves the retry loop, not the stated Windows file-lock behavior. Please document that distinction in this PR and provide a Windows reproduction or targeted Windows validation before treating the platform claim as verified. The body also needs the model/harness or manual-work disclosure required by CONTRIBUTING.md. CI has been enabled and is still running.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes in this pull request
fix/windows-rename-lock-hardening- On Windows a rename over a file that another process still has open fails withEPERM. The goal state write now writes a temp file and renames it over the state file with a retry, so a transient lock does not lose the write.Why
The plugin runs in more than one process (the server and the TUI), so the state file is genuinely contended. The failure showed up in the host log as an
EPERMon the goal state file and left the state unchanged, which reads as a lost goal.Verification
This is the second pull request of a stack. Merge the earlier ones first; once they are merged this diff is only the fix above.
Need help on this PR? Tag
@codesmith-botwith what you need.