plugin add/remove: nothing records what an install created, so the undo and the uninstall both guess
メンテナーはふだん 1 日以内に返信
@MatAtBread がすでに取り組んでいます。
2026年10月14日 から。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 12/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 技術スタック
- node.js, typescript
- 領域
- tooling
調査の方向性
Start with the plugin add and plugin remove paths that write matbot.yaml, the root package.json key, .plugins/node_modules/<name> and .plugins/.restore/, and with readDependencyNames, which the payload says both paths share. Reproduce one add then remove on the npm route and list what remains under .plugins/. Done when a per-plugin install record drives both the undo and remove, and add then remove leaves nothing add created. Open PR #103 already targets this, so coordinate with it before starting.
索引モデルが issue の本文から書いたものです。
説明
Summary
plugin add creates things in up to six places depending on the route: a package.json key, node_modules, .plugins/<host>/…, a .plugins/node_modules/<name> self-link, dependencies installed into a cache directory or a local checkout, and .plugins/.restore/. Nothing records which of them a given install created. So remove, and the undo of an add that then disowns the plugin, both infer it from the state they find. Each fix to one inference has broken the other, and a live run shows remove leaving most of it behind.
These should be fixed together. They are two halves of one question: what did this install create, and who takes it back out?
Already known
The gap #90 left. On the npm route, an add that then disowns the plugin keeps the install. That happens on a duplicate name, an incompatible runtime, or "not a plugin". On a duplicate name config is never written, so remove has no entry to offer the uninstall against.
Two regressions in the attempted fix. The fix is in PR #93's commits (6d56bd1, 1f42280, never merged; #93 is closed in favour of this issue):
readDependencyNameswas widened todevDependenciesandpeerDependenciesfor the undo's before-snapshot.removeshares it, soplugin remove @x/foonow offers topm removea package the project declares only as a peer or dev dependency, deleting the project's own declaration.- A new pre-install name-clash guard refuses
plugin add [email protected]whenfoois loaded. That removes the only in-tool way to change an npm plugin's version; before, the version changed on disk and a reload picked it up despite the clash error.
Found by a live add → reload → remove run
The run used @matatbread/matbot-email from github, a local path, npm and http. All four routes installed, reloaded and worked. remove cleans matbot.yaml and, for npm, the root package.json key and node_modules link, but leaves:
- The self-link
.plugins/node_modules/@matatbread/matbot-email. It survivesremove, so a removed plugin is still resolvable by bare name. It was repointed by whichever route installed last, and was left dangling at the end. - The cached source and its installed dependencies.
.plugins/raw.githubusercontent.com/MatAtBread/matbot-email/keptHEAD/,main/andrefs/heads/main/, each withsrc/and a fullnode_modules(imapflow, mailparser, nodemailer, …). Each spelling of the same repo is a separate cache directory that is never reclaimed;main/held an older revision. - Empty
.plugins/.restore/…directories left behind afterdiscardRestore. - The host's
pnpm-lock.yamlrewritten. After the npm cycle the lockfile had lost itscatalogs:block, whilepackage.jsonwas back as it was. Thenode_modules/.pnpmentries also remain, though pruning those is arguably pnpm's job. - Local route: installing dependencies writes
node_modulesandpackage-lock.jsoninto the user's checkout. That is by design, butremovenever mentions it.
Suggested direction
Use the same shape as the #89 fix (#97): state it instead of deriving it. add would write an install record per plugin, saying which route it took, the dependency key it introduced into package.json (if any), the cache root, the self-link, and the dependency directories and lockfile it created. Both the undo-on-disown and remove would replay that record and act on nothing else, with nothing inferred from the specifier or a manifest diff. Changing an installed plugin's version would become an explicit operation rather than a side effect of the clash path.
Done when
- For every route,
add→removeleaves nothing thataddcreated, unlessremovewas told to keep it. - A failed or disowned
addleaves nothing behind. - Neither path ever touches a dependency that
adddid not introduce. plugin add foo@<version>on a loadedfoohas a defined, documented behaviour.
- 主要言語
- TypeScript
- スター
- 5
- フォーク
- 2
- 平均マージ
- 1日 4時間
- マージ済み PR(30日)
- 11
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
MatAtBread/matbot のほかの issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 74/100
MatAtBread/matbot#99 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
MatAtBread/matbot#95 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
MatAtBread/matbot#94 ·
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 半日 初心者へのやさしさ 66/100
MatAtBread/matbot#100 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
MatAtBread/matbot#96 ·
メンテナーはふだん 1 日以内に返信
MatAtBread/matbot の issue をすべて見る
似ている issue
-
afk-ok area:data-quality importer size:S
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
enorm-labs/event-junkie#3301 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
one-zero-eight/apply-bot#39 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
bigbluebutton/bbb-ui-components-react#108 ·
メンテナーはふだん 2 日以内に返信
-
area: app type: bug
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
ExpidetGames/code-reviewer#308 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 1 日以内に返信