Skip to content

fix(tui): stabilize plugin reload generations - #43447

Merged
kitlangton merged 4 commits into
v2from
plugin-reload-flake
Aug 19, 2026
Merged

kitlangton merged 4 commits into
v2from
plugin-reload-flake

Conversation

@kitlangton

@kitlangton kitlangton commented Aug 19, 2026 •

Copy link
Copy Markdown
Contributor

What

Harden the setup-failure recovery merged in #43441 so one logical source save remains one plugin generation even when the filesystem exposes several mtimes. This preserves the last good plugin without suppressing legitimate retries caused by changed source or options.

Before / After

Before: Setup failures were memoized by an mtime-derived module URL. A single save can expose several mtimes, so duplicate notifications could still look like distinct generations and repeat the teardown/restore cycle. Mutable config option references could also make an options-only change look unchanged.

After: Local entrypoint contents map to a process-unique numeric generation. Repeated reads of unchanged contents reuse that generation, source reverts still get a fresh ESM URL, and immutable option snapshots make options-only retries reliable.

How

  • packages/tui/src/plugin/context.tsx fingerprints local entrypoint contents, assigns process-wide monotonic generations, snapshots registration options, and centralizes generation comparison and contribution cleanup.
  • packages/tui/src/plugin/discovery.ts keeps cache-busted imports numeric while accepting generation numbers rather than assuming they are mtimes.
  • packages/tui/test/plugin-hot-reload.test.tsx uses a second healthy plugin as a positive reconcile barrier before asserting that an unchanged broken save did not cycle the restored plugin.

Scope

This keeps the existing entrypoint-only watch boundary. Changes to nested helper modules remain outside this fix.

Testing

  • bun run test test/plugin-hot-reload.test.tsx --test-name-pattern "a save whose setup throws" --rerun-each 20 from packages/tui: 20/20 pass; the original implementation failed 18/20 locally.
  • bun run test test/plugin-hot-reload.test.tsx test/plugin-discovery.test.ts test/plugin-reload.test.ts from packages/tui: 16 pass.
  • bun typecheck from packages/tui.
  • Repository pre-push typecheck: 33 packages pass.

Flow

flowchart LR
  A[Filesystem notification] --> B[Hash entrypoint contents]
  B --> C{Content changed?}
  C -- No --> D[Reuse generation]
  C -- Yes --> E[Assign unique generation]
  D --> F{Known setup failure for generation + options?}
  E --> F
  F -- Yes --> G[Keep last good plugin active]
  F -- No --> H[Import and activate]
Loading

@kitlangton
kitlangton enabled auto-merge (squash) August 19, 2026 15:11
# ------------------------ >8 ------------------------
# Do not modify or remove the line above.
# Everything below it will be ignored.
#
# Conflicts:
#	packages/tui/test/plugin-hot-reload.test.tsx
@kitlangton kitlangton changed the title fix(tui): deduplicate failed plugin reloads fix(tui): stabilize plugin reload generations Aug 19, 2026
@kitlangton
kitlangton merged commit d8debaa into v2 Aug 19, 2026
10 checks passed
@kitlangton
kitlangton deleted the plugin-reload-flake branch August 19, 2026 15:26
jinhuang712 pushed a commit to jinhuang712/opencode that referenced this pull request Sep 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant