mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-06 10:48:12 +02:00
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - The web UI embeds CodeMirror editors, and CodeMirror validates
extensions with `instanceof`
> - Different CodeMirror packages pin different transitive minors of
`@codemirror/state` (6.7.1 / 6.7.2) and `@codemirror/view` (6.43.9 /
6.43.11), so the bundle ships two module instances
> - The second instance makes valid extensions fail the `instanceof`
check and crashes the editor
> - This pull request adds a shared caret override to `pnpm.overrides`,
the same mechanism the existing `react` and `rollup` overrides use, so
every consumer resolves one copy of each package
> - The lockfile is not edited by hand; the lockfile automation
regenerates it from the manifests
> - The benefit is that the editor stops crashing with "Unrecognized
extension value in extension set"
## Linked Issues or Issue Description
**What happened?**
The production UI throws `Error: Unrecognized extension value in
extension set ([object Object]). This sometimes happens because multiple
instances of @codemirror/state are loaded, breaking instanceof checks.`
Observed 43 times in one week.
**Expected behavior**
The editor loads its extension set without errors. One instance of
`@codemirror/state` and `@codemirror/view` serves every CodeMirror
package.
**Steps to reproduce**
1. Run `grep "'@codemirror/state@" pnpm-lock.yaml` on master: two
versions resolve (6.7.1 and 6.7.2).
2. Build `ui/` and search the output for `Unrecognized extension value`,
a string unique to `@codemirror/state`: two chunks each carry a full
copy, one with a 6.7.1-only code pattern and one without it.
3. Open a view that composes extensions from packages on different
copies: the extension set rejects the foreign-instance extension.
**Paperclip version or commit**
master (0e14c61da)
## What Changed
- `package.json` (`pnpm.overrides`): added `"@codemirror/state":
"^6.7.2"` and `"@codemirror/view": "^6.43.11"`. A shared range forces
every consumer onto one resolution of each package.
- `pnpm-workspace.yaml`: the mirror overrides block gets the same two
entries, kept in sync with `package.json`.
- `ui/src/lib/codemirror-single-instance.test.ts`: regression pin that
fails when the lockfile resolves more than one version of either
package.
- No lockfile change in this PR. The `policy` job regenerates
`pnpm-lock.yaml` from the manifests for downstream jobs; CI owns
lockfile updates.
## Verification
- With the override, `pnpm install` resolves a single
`@codemirror/state@6.7.2` and a single `@codemirror/view@6.43.11`.
- Built `ui/` before and after. Before: two chunks each carried a full
copy of `@codemirror/state` (four total occurrences of its unique error
string; one chunk fingerprints as 6.7.1, the other as 6.7.2). After: one
chunk carries one copy (two occurrences, no 6.7.1 fingerprint).
- `pnpm vitest run src/components/IssuesList.test.tsx` in `ui/` — 46/46
pass.
- New test `ui/src/lib/codemirror-single-instance.test.ts` pins the
invariant: the lockfile must resolve exactly one version of
`@codemirror/state` and `@codemirror/view`. The PR CI policy job
regenerates the lockfile from the manifests, so the test evaluates this
PR's real resolution — verified locally against a lockfile regenerated
the same way (`pnpm install --resolution-only`): 2/2 pass, and the same
test fails against the current master lockfile with its two resolved
copies.
## Risks
- Low risk. The override stays inside the caret ranges every consumer
already declares, so no package receives a version outside its stated
compatibility. Rollback is removing the two override lines.
- A future CodeMirror consumer that needs a major bump of these packages
must update the override; the override comment states why it exists.
## Model Used
Claude (Anthropic) — claude-fable-5 (Claude Fable 5), Claude Code
harness, extended thinking with tool use.
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
46 lines
2.3 KiB
YAML
46 lines
2.3 KiB
YAML
packages:
|
|
- packages/*
|
|
- packages/adapters/*
|
|
- packages/plugins/*
|
|
# Keep sandbox-provider plugins installable as standalone packages without
|
|
# forcing root pnpm-lock.yaml churn for their third-party deps.
|
|
- "!packages/plugins/sandbox-providers/**"
|
|
- packages/plugins/examples/*
|
|
# Keep this smoke fixture installable as a local plugin example without
|
|
# forcing PRs to commit pnpm-lock.yaml for a new workspace importer.
|
|
- "!packages/plugins/examples/plugin-orchestration-smoke-example"
|
|
- server
|
|
- ui
|
|
- cli
|
|
|
|
# Keep in sync with package.json#pnpm.patchedDependencies. Newer pnpm
|
|
# versions read patch configuration only from the workspace manifest.
|
|
patchedDependencies:
|
|
embedded-postgres@18.1.0-beta.16: patches/embedded-postgres@18.1.0-beta.16.patch
|
|
acpx@0.12.0: patches/acpx@0.12.0.patch
|
|
acpx@0.13.1: patches/acpx@0.13.1.patch
|
|
"@agentclientprotocol/claude-agent-acp@0.73.0": patches/@agentclientprotocol__claude-agent-acp@0.73.0.patch
|
|
"@agentclientprotocol/codex-acp@1.6.2": patches/@agentclientprotocol__codex-acp@1.6.2.patch
|
|
"@chat-adapter/slack@4.39.0": patches/@chat-adapter__slack@4.39.0.patch
|
|
"@chat-adapter/discord@4.39.0": patches/@chat-adapter__discord@4.39.0.patch
|
|
"@chat-adapter/telegram@4.39.0": patches/@chat-adapter__telegram@4.39.0.patch
|
|
"@chat-adapter/teams@4.39.0": patches/@chat-adapter__teams@4.39.0.patch
|
|
"@chat-adapter/github@4.39.0": patches/@chat-adapter__github@4.39.0.patch
|
|
"@discordjs/ws@1.2.3": patches/@discordjs__ws@1.2.3.patch
|
|
|
|
# Agent CLIs share the current runtime used by the native provider pack.
|
|
# pnpm patches change package files, but overrides control dependency resolution.
|
|
overrides:
|
|
"@agentclientprotocol/codex-acp@1.6.2>@openai/codex": "0.153.4"
|
|
"@agentclientprotocol/claude-agent-acp@0.73.0>@anthropic-ai/claude-agent-sdk": "0.3.263"
|
|
rollup: ">=4.59.0"
|
|
react: "^19.2.8"
|
|
react-dom: "^19.2.8"
|
|
# CodeMirror validates extensions with instanceof, so exactly one copy of
|
|
# these two packages may resolve. Different CodeMirror packages pin
|
|
# different transitive minors, which resolves two copies and crashes the
|
|
# editor with "Unrecognized extension value in extension set". A shared
|
|
# range forces every consumer onto one resolution.
|
|
"@codemirror/state": "^6.7.2"
|
|
"@codemirror/view": "^6.43.11"
|