Skip to content

fix(miro): move the Node project under server/ so plugin install skips npm ci - #4096

Merged
kyle-sexton merged 2 commits into
mainfrom
claude/audit-install-state-yr1tvm
Sep 11, 2026
Merged

fix(miro): move the Node project under server/ so plugin install skips npm ci#4096
kyle-sexton merged 2 commits into
mainfrom
claude/audit-install-state-yr1tvm

Conversation

@kyle-sexton

Copy link
Copy Markdown
Contributor

Closes #4084

Summary

Claude Code runs npm ci --ignore-scripts inside a consumer's plugin cache whenever a plugin root holds both a package.json and a supported lockfile, and that install cannot be turned off (plugins-reference.md, "Node.js package dependencies", verified 2026-09-11). The miro plugin kept its whole TypeScript project at the plugin root, so every install of the plugin materialised the dev toolchain (typescript, biome, esbuild, vitest and their transitive tree: 176 MB / 6,120 files in the audited cloud-session cache) even though the committed bundle needs none of it at runtime. #4087's size attribution is what surfaced it.

Fix

  • Move package.json, package-lock.json, biome.json, build.mjs, tsconfig.json, vitest.config.ts, src/, dist/ and the project .gitignore one level down into plugins/miro/server/. The plugin root no longer carries a lockfile, so the automatic install never fires; CI and Dependabot keep pinning and rebuilding from the same lockfile at its new path.
  • Follow the move everywhere the old layout was named: .mcp.json launches ${CLAUDE_PLUGIN_ROOT}/server/dist/index.min.js; the miro CI steps, .github/dependabot.yml and dependabot-miro-bundle.yml run in plugins/miro/server; the bugs lane glob, docs/CLOUD-SESSIONS.md and the miro README point at server/; build.mjs's header explains the placement with its upstream basis.
  • Record plugins/miro/server/* in scripts/affected-tests-no-suite.txt with the miro CI lane that covers it. Its vitest suites are not one of the four conventions the selector recognises, and the tree reported as UNMAPPED on main before this change as well.
  • Bump miro to 0.4.0 with a matching CHANGELOG entry.

No source or bundle content changed: every moved file is a 100% rename except build.mjs (header comment) and .mcp.json (path).

Verification

  • Full miro lane run locally from plugins/miro/server: npm ci, npm run typecheck, npm run lint, npm test, npm run verify-bundle ("matches source"), and the stdio smoke test (tools/list returns miro_create_board). All pass.
  • actionlint on the two edited workflows: clean. check-jsonschema coverage of dependabot.yml is exercised by CI.
  • scripts/affected-tests.sh --explain: no UNMAPPED files (was 18 for this diff before the no-suite entry); --run: every selected shell suite passed, including scripts/affected-tests.test.sh (76 checks) which reads the live no-suite list.
  • scripts/check-changelog-parity.sh --check, scripts/check-purged-em-dashes.sh, markdownlint-cli2 on the changed markdown: clean.
  • Upstream rule re-read in raw markdown on 2026-09-11: install fires only on a plugin-root package.json plus lockfile; yarn and pnpm lockfiles are skipped; the install cannot be disabled. A nested project is the documented-safe placement.

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_019KEd5QnRjyz3TvieTd5UbN


Generated by Claude Code

…s npm ci

Closes #4084

Claude Code runs `npm ci --ignore-scripts` inside a consumer's plugin
cache whenever the plugin root holds both a package.json and a supported
lockfile, and that install cannot be turned off. The miro plugin kept its
whole TypeScript project at the root, so every install materialised the
dev toolchain (typescript, biome, esbuild, vitest and their transitive
tree, about 178 MB in the audited cache) even though the committed
bundle needs nothing at runtime.

Move package.json, the lockfile, biome.json, build.mjs, tsconfig.json,
vitest.config.ts, src/, dist/ and the project .gitignore one level down
into plugins/miro/server/. The plugin root no longer carries a lockfile,
so the automatic install never fires, while CI and Dependabot keep
pinning and rebuilding from the same lockfile at its new path.

Follow the move everywhere that named the old layout: .mcp.json now
launches server/dist/index.min.js; the miro CI steps, the dependabot
manifest and the dependabot-miro-bundle workflow run in
plugins/miro/server; the bugs lane glob, CLOUD-SESSIONS and the README
point at server/. Record plugins/miro/server/* in the affected-tests
no-suite list with the miro CI lane that covers it, since its vitest
suites are not one of the four conventions the selector recognises and
the tree previously reported as unmapped.

Basis: plugins-reference.md, "Node.js package dependencies", verified
2026-09-11. Bump miro to 0.4.0 with a matching changelog entry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019KEd5QnRjyz3TvieTd5UbN
@kyle-sexton
kyle-sexton marked this pull request as ready for review September 11, 2026 16:28
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-11T16:33:29.383534Z bf32181 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@claude

claude Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 27s —— View job


Reviewing PR #4096

  • Gather context (diff, changed files, repo conventions)
  • Run /review:code-review per instructions
  • Post findings as inline comments (if any)
  • Post summary comment

Summary

Reviewed the full diff (git diff origin/main...HEAD), scoped to correctness and maintainability per the /review:code-review lane (security is out of scope here; this repo has no dedicated security lane triggered on this PR). This is a mechanical file move of the miro Node project from plugins/miro/ to plugins/miro/server/, with every moved file a 100% rename except build.mjs (comment only) and .mcp.json (path only) — confirmed via git diff -M.

I traced every reference to the old layout across the repo (not just the PR's changed-files list) to check for anything missed:

  • .mcp.json${CLAUDE_PLUGIN_ROOT}/server/dist/index.min.js, and build.mjs's outfile is derived from import.meta.url, so the rename doesn't break the relative path resolution.
  • CI (ci.yml): run_node's path filter at line 200 is still plugins/miro/**, which correctly matches the new server/ subtree; all six miro steps' working-directory updated consistently; the stdio smoke test's node dist/index.min.js resolves correctly under the new working-directory: plugins/miro/server.
  • dependabot.yml and dependabot-miro-bundle.yml: directory/path-filter/grep patterns all updated in lockstep.
  • .claude/bugs.md, docs/CLOUD-SESSIONS.md, README.md, CHANGELOG.md, scripts/affected-tests-no-suite.txt: all consistent with the new path.
  • Repo-wide grep for miro/package.json, miro/dist/, miro/src/, miro/tsconfig, miro/vitest, miro/biome, miro/build.mjs outside plugins/miro/server/ turned up nothing stale. The handful of remaining bare plugins/miro mentions I found (marketplace.json's source pointing at the plugin dir itself, docs/architecture/landscape.json, historical docs/specs/* and docs/MIGRATION-PLAYBOOK.md entries, scripts/em-dash-purged-paths.txt's README/CHANGELOG/skills globs) are either still correct as written or out of this PR's scope (e.g. landscape.json is a separately-regenerated extraction snapshot per docs/architecture/landscape-notes.md, not something this change is expected to update).
  • The affected-tests-no-suite.txt entry plugins/miro/server/* matches nested paths correctly under this script's [[ "$p" == $pat ]] glob semantics (bash pattern matching here isn't filesystem globbing, so * does cross /), consistent with the sibling entries' style.

No high-signal correctness or maintainability issues found — no inline comments posted. The PR author's local verification (test runs, actionlint, --explain/--run) is author-claimed and I did not independently re-run it (compound/script-executing bash commands required approval this lane doesn't have); everything I could independently verify by reading the diff and cross-referencing the tree checks out.

@claude

claude Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 45s —— View job


Security review

  • Gather context (PR diff, changed files)
  • Apply skip gate
  • Review diff for security-relevant surface
  • Report findings

No security issues found.

This PR is a pure path-relocation of the miro plugin's Node project from plugins/miro/ to plugins/miro/server/, so that Claude Code's automatic npm ci --ignore-scripts (triggered by a package.json + lockfile at a plugin root) no longer fires on install. I reviewed the full diff (git diff origin/main...HEAD):

  • 26 files are 100%-identical renames (source, tests, config, lockfile, committed bundle) — no content change.
  • plugins/miro/server/build.mjs differs from its pre-move version only in its header comment, which now explains the server/ placement. The build logic (esbuild bundling, shebang stripping, --check drift verification) is unchanged.
  • .mcp.json, .github/workflows/ci.yml, .github/workflows/dependabot-miro-bundle.yml, and .github/dependabot.yml only update path strings (plugins/miro/...plugins/miro/server/...). Workflow permissions:, triggers, and the dependabot[bot]-only actor gate in dependabot-miro-bundle.yml are unchanged.
  • README.md, CHANGELOG.md, docs/CLOUD-SESSIONS.md, .claude/bugs.md, and scripts/affected-tests-no-suite.txt are documentation/test-infra updates with no security surface.

No authorization, injection, secret-handling, or Actions-trigger/permission changes are present in this diff. Per this lane's scope, GitHub Actions hardening (pins, pull_request_target, expression injection) is zizmor's advisory lane and out of scope here regardless.

@github-actions

Copy link
Copy Markdown
Contributor

Last security-reviewed head: bf321811076b376ba627ec69b9a03bc809d0d884. On the next push, the relevance gate compares only the commits since this SHA; delete this comment to force a full re-review.

@github-actions

Copy link
Copy Markdown
Contributor

Claude has reviewed this PR 1 time. The lane skips further automatic reviews after 5; deleting this comment resets the count.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bf32181107

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/miro/README.md
The MCP carry table in docs/MIGRATION-PLAYBOOK.md still said the miro
server's TypeScript lives directly under plugins/miro and prescribed
`node ${CLAUDE_PLUGIN_ROOT}/dist/index.min.js`, both of which the
server/ move removed. The row now names plugins/miro/server, the
server/dist bundle path, and the reason the project sits one level
below the plugin root.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019KEd5QnRjyz3TvieTd5UbN
@kyle-sexton
kyle-sexton merged commit b4d5d93 into main Sep 11, 2026
13 checks passed
@kyle-sexton
kyle-sexton deleted the claude/audit-install-state-yr1tvm branch September 11, 2026 16:48
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.

miro: the plugin ships package-lock.json beside a self-contained bundle, so every consumer's cache installs 188 MB of dev toolchain

2 participants