Skip to content

fix: opencode plugin install/remove preserves foreign entries verbatim (#1002) - #1005

Merged
ranxianglei merged 1 commit into
masterfrom
2026-09-19_opencode-plugin-preserve
Sep 19, 2026
Merged

ranxianglei merged 1 commit into
masterfrom
2026-09-19_opencode-plugin-preserve

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Fixes #1002

What

bili plugin install/remove opencode was lossy on foreign plugin entries:

  1. Install rewrite — pluginEntries() projected the raw value to strings only, and that projection was written back. Object entries ({package, options}) silently vanished; map-form plugins collapsed to bare keys.
  2. "plugin present" lied — the early-return fired after write(), so an idempotent install still rewrote (and mangled) the key.
  3. Remove rewrite — same strings-only projection, plus the key was deleted when no string survived: an array holding one object entry + ours lost the whole key.
  4. Stale backup — .bili-bak was written once ever (first write), so it quickly stopped representing any recoverable state.

Fix

  • applyOpencodePluginEntry operates on the raw value: foreign entries (objects, map forms, odd scalars) are preserved verbatim in form and position; only our own entries are added/removed. "plugin present" short-circuits before any write (idempotent install = byte-identical file).
  • opencodeRemove drops the key only when nothing raw survives, and keeps map form.
  • Backup discipline: re-snapshot on every write whose pre-write bytes differ from bili's own last output (.bili-last sidecar hash). User edits refresh the backup; bili's consecutive writes do not — so the install→upgrade→remove compaction-restore chain still yields the user's pre-install value, while a user edit between bili writes is never lost from the backup.
  • codex/omp write paths funnel through the same writeConfigText discipline.

Tests

  • tests/issue1002-opencode-foreign-entries.test.ts (new): array objects + map forms survive install AND remove; key kept when only objects remain; "plugin present" leaves the file byte-identical; backup reflects the latest user-edited state.
  • Updated the two tests that asserted the old lossy behavior as contract (non-string entries ignored, version-map normalized to keys) — they now assert preservation.
  • npm run typecheck ✅ · npm test 1965 pass / 0 fail (2 e2e-gated skips) ✅ · npm run build ✅

Notes

#1002)

- applyOpencodePluginEntry now operates on the RAW plugin value: object
  entries ({package, options}), map-form plugins with per-key options and
  odd scalars survive install in form and position; a strings-only
  projection is never written back
- 'plugin present' short-circuits BEFORE any write — an idempotent
  install no longer rewrites (and mangles) the key
- opencodeRemove drops the key only when NOTHING raw survives, and keeps
  map form; foreign entries are no longer collapsed to bare keys
- backup re-snapshots on every write whose pre-write bytes differ from
  bili's own last output (.bili-last sidecar hash): user edits refresh
  the backup, bili's consecutive writes do not — the install→upgrade→
  remove restore chain still yields the user's pre-install value
- codex/omp write paths funnel through the same writeConfigText discipline

Fixes #1002
@github-actions

Copy link
Copy Markdown
Contributor

📦 Built Package Artifact

Branch: 2026-09-19_opencode-plugin-preserve (d052bbf)

Option A — Install from npm PR tag (recommended)

npm install -g billion-context@pr-1005

Each push to this PR publishes a new version under the pr-1005 npm tag.

Option B — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pr1005.tgz
npm install -g package

Install instructions are refreshed on each push.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] bili plugin install/remove opencode 会静默删除 plugins 数组里的对象形态条目({package, options} 一起丢)

1 participant