Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

plugin add/remove: nothing records what an install created, so the undo and the uninstall both guess

オープン
#98 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@MatAtBread がすでに取り組んでいます。

2026年10月14日 から。

  • #102 @MatAtBread による — マージされずにクローズ
  • #103 @MatAtBread による — オープン

評価

難易度
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 の本文から書いたものです。

説明

bug

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):

  1. readDependencyNames was widened to devDependencies and peerDependencies for the undo's before-snapshot. remove shares it, so plugin remove @x/foo now offers to pm remove a package the project declares only as a peer or dev dependency, deleting the project's own declaration.
  2. A new pre-install name-clash guard refuses plugin add [email protected] when foo is 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:

  1. The self-link .plugins/node_modules/@matatbread/matbot-email. It survives remove, 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.
  2. The cached source and its installed dependencies. .plugins/raw.githubusercontent.com/MatAtBread/matbot-email/ kept HEAD/, main/ and refs/heads/main/, each with src/ and a full node_modules (imapflow, mailparser, nodemailer, …). Each spelling of the same repo is a separate cache directory that is never reclaimed; main/ held an older revision.
  3. Empty .plugins/.restore/… directories left behind after discardRestore.
  4. The host's pnpm-lock.yaml rewritten. After the npm cycle the lockfile had lost its catalogs: block, while package.json was back as it was. The node_modules/.pnpm entries also remain, though pruning those is arguably pnpm's job.
  5. Local route: installing dependencies writes node_modules and package-lock.json into the user's checkout. That is by design, but remove never 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 → remove leaves nothing that add created, unless remove was told to keep it.
  • A failed or disowned add leaves nothing behind.
  • Neither path ever touches a dependency that add did not introduce.
  • plugin add foo@<version> on a loaded foo has a defined, documented behaviour.
主要言語
TypeScript
スター
5
フォーク
2
平均マージ
1日 4時間
マージ済み PR(30日)
11

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

MatAtBread/matbot のほかの issue

MatAtBread/matbot の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。