|
| 1 | +# Plate Next Yjs plugin adapter |
| 2 | + |
| 3 | +Objective: |
| 4 | +Restore a thin Plate Yjs plugin over the Plite Yjs extension without reviving |
| 5 | +the deleted Slate-Yjs/provider runtime. |
| 6 | + |
| 7 | +Flow mode: |
| 8 | +One-shot named public API correction. |
| 9 | + |
| 10 | +Goal plan: |
| 11 | +`docs/plans/2026-07-14-plate-next-yjs-plugin-adapter.md` |
| 12 | + |
| 13 | +Completion threshold: |
| 14 | + |
| 15 | +- `@platejs/yjs` keeps `createYjsExtension` as the Plite substrate. |
| 16 | +- Plate exposes typed `BaseYjsPlugin` and `YjsPlugin` composition owners. |
| 17 | +- Provider packages, authentication, persistence, and transport remain app-owned. |
| 18 | +- Root/react exports, runtime artifacts, type inference, docs, tests, changesets, |
| 19 | + barrels, drift audits, review, and the goal checker close cleanly. |
| 20 | +- No provider registry, `withPlateYjs`, Slate-Yjs enhancer, compatibility alias, |
| 21 | + broad cast, or duplicate runtime returns. |
| 22 | + |
| 23 | +Verification surface: |
| 24 | + |
| 25 | +- Yjs package typecheck, tests, lint, build, runtime import, and emitted declaration |
| 26 | + inspection. |
| 27 | +- Core type contracts and `pnpm check:core` because the adapter exposed a Core |
| 28 | + extension-state inference bug. |
| 29 | +- Exact public package runtime/type export contracts. |
| 30 | +- English/Chinese MDX source generation and docs-source parity. |
| 31 | +- Browser attempt at `/docs/yjs`, with app-wide blockers recorded if the page |
| 32 | + cannot render. |
| 33 | +- Legacy-name, raw-Plite-doc, cast, extracted-file, changeset, and diff-hygiene |
| 34 | + audits. |
| 35 | +- Structured autoreview and final autogoal checker. |
| 36 | + |
| 37 | +Constraints: |
| 38 | + |
| 39 | +- Best Plate v2 architecture, not compatibility preservation. |
| 40 | +- Plate owns product plugin composition; Plite owns editor/Yjs substrate. |
| 41 | +- Keep established `BaseYjsPlugin` and `YjsPlugin` names and owner paths. |
| 42 | +- Do not restore provider registries, Slate-Yjs wrappers, lifecycle duplication, |
| 43 | + fake aliases, broad casts, or helper dumps. |
| 44 | +- Fix owning generic inference instead of adding local annotations or casts. |
| 45 | +- Do not edit generated registry output. |
| 46 | +- No unrelated package cleanup. |
| 47 | + |
| 48 | +Boundaries: |
| 49 | + |
| 50 | +- Runtime: `packages/yjs`, plus the smallest Core generic owner required to |
| 51 | + preserve extension state. |
| 52 | +- Proof contracts: Core/Plite type and public-package smoke tests. |
| 53 | +- Docs: Yjs README, English/Chinese Yjs plugin pages. |
| 54 | +- Release truth: existing Yjs/Core changesets plus one separated Plite changeset. |
| 55 | +- Goal evidence: this plan. |
| 56 | +- Package-wide scoring and broad Core drift review do not apply; this is a named |
| 57 | + API correction. |
| 58 | + |
| 59 | +Blocked condition: |
| 60 | +Stop only if Plate cannot install a configured Plite extension without a public |
| 61 | +Core redesign. That blocker did not occur: the existing composition model works |
| 62 | +after preserving extension state through its generic return types. |
| 63 | + |
| 64 | +Current verdict: |
| 65 | + |
| 66 | +- `createYjsExtension`: keep as Plite-native substrate. |
| 67 | +- `BaseYjsPlugin`: recover established Plate owner as a thin adapter. |
| 68 | +- `YjsPlugin`: recover established React Plate owner via `toPlatePlugin`. |
| 69 | +- Old provider/Slate-Yjs runtime: keep deleted. |
| 70 | +- Final confidence: 100 for the named packet after package, Core, docs, export, |
| 71 | + source-audit, and review proof. |
| 72 | + |
| 73 | +Start Gates: |
| 74 | +| Gate | Applies | Evidence | |
| 75 | +|---|---|---| |
| 76 | +| Prompt captured | yes | User requested correction after the Yjs ownership diagnosis; thin adapter and no legacy runtime are explicit | |
| 77 | +| Plate Next doctrine | yes | `plate-next`, Vision, Plate Vision, and Common Vision read | |
| 78 | +| Durable goal | yes | Goal created against this plan | |
| 79 | +| Mode | yes | Named Yjs API packet; no package-wide or broad Core sweep | |
| 80 | +| Ownership | yes | Plate composition over Plite substrate | |
| 81 | +| Skills | yes | `plate-next`, `autogoal`, `changeset`, `docs-creator`, Browser, and `autoreview` loaded | |
| 82 | +| Public API decision | yes | User accepted restoration of the thin Plate plugin | |
| 83 | +| Export impact | yes | Root/react exports changed, so barrels and runtime export contracts apply | |
| 84 | +| Release impact | yes | Published Yjs/Core types and API require changeset truth | |
| 85 | +| Browser impact | yes | Plugin docs route selected for browser proof | |
| 86 | + |
| 87 | +Work Checklist: |
| 88 | + |
| 89 | +- [x] Capture the request, scope, non-goals, stop condition, proof, and handoff. |
| 90 | +- [x] Confirm `origin/main` owner paths before keeping restored files. |
| 91 | +- [x] Restore `BaseYjsPlugin` as a configured `createYjsExtension` adapter. |
| 92 | +- [x] Restore `YjsPlugin` through `toPlatePlugin`. |
| 93 | +- [x] Preserve extension state inference in Core rather than cast Yjs locally. |
| 94 | +- [x] Add Base/React runtime tests and Core compile-time type contracts. |
| 95 | +- [x] Update root/react exact runtime export contracts and named type smoke. |
| 96 | +- [x] Keep raw Plite `createYjsExtension` public. |
| 97 | +- [x] Update package metadata and current-state English/Chinese documentation. |
| 98 | +- [x] Repair Yjs/Core/Plite changeset ownership and one-bump contracts. |
| 99 | +- [x] Run package typecheck, test, lint, build, artifact, and import proof. |
| 100 | +- [x] Run barrels, docs source parity, source audits, and diff hygiene. |
| 101 | +- [x] Attempt Browser proof and record the unrelated app-wide compile blocker. |
| 102 | +- [x] Run and repair the shared Core gate. |
| 103 | +- [x] Run structured autoreview after the final proof-driven edits. |
| 104 | +- [x] Record changed files, scoped sweep, gaps, errors, and risks. |
| 105 | +- [x] Run the autogoal completion checker. |
| 106 | + |
| 107 | +Phase / pass table: |
| 108 | +| Phase | Status | Evidence | |
| 109 | +|---|---|---| |
| 110 | +| Source map | complete | Current Yjs extension, Core plugin builders, docs, exports, and `origin/main` owners inspected | |
| 111 | +| Implementation | complete | Thin Base/React adapters restored; Core state inference preserved | |
| 112 | +| Focused proof | complete | Yjs tests, typecheck, lint, build, declarations, imports, and type contracts pass | |
| 113 | +| Shared proof | complete | `pnpm check:core` exits 0 after export/changeset contract repair | |
| 114 | +| Docs proof | complete | MDX generation and docs source parity pass | |
| 115 | +| Drift audit | complete | Legacy runtime/cast scan returns zero; plugin docs expose no raw Plite setup | |
| 116 | +| Review | complete | Structured Codex review reports no accepted/actionable findings | |
| 117 | +| Closure | complete | Plan evidence filled and completion checker run | |
| 118 | + |
| 119 | +Completion Gates: |
| 120 | +| Gate | Applies | Evidence | |
| 121 | +|---|---|---| |
| 122 | +| Best Plate v2 recommendation | yes | Thin Plate plugin over Plite extension; legacy runtime remains deleted | |
| 123 | +| Gap ownership | yes | Core generic owner fixed; no remaining Plite/Yjs capability gap | |
| 124 | +| Package proof | yes | Yjs typecheck, 244 tests, lint, build, declaration and runtime import proof pass | |
| 125 | +| Shared Core gate | yes | `pnpm check:core` passes all covered package typechecks, lints, builds, and tests | |
| 126 | +| Public exports | yes | Root/react exact runtime smoke and named type smoke include restored plugins | |
| 127 | +| Barrels | yes | `pnpm brl` passes | |
| 128 | +| Changesets | yes | Yjs major text repaired; Core note merged into existing patch; Plite operation note split | |
| 129 | +| Docs parser | yes | `pnpm --filter www check:docs` passes | |
| 130 | +| Browser | yes | Browser reached `/docs/yjs`; global registry compile drift blocks rendering before Yjs content | |
| 131 | +| Source audit | yes | Zero legacy runtime/cast matches; zero raw `createYjsExtension` matches in plugin pages | |
| 132 | +| Extracted files | yes | Four restored files map to exact `origin/main` owners | |
| 133 | +| Review | yes | Final structured review reports no accepted/actionable findings | |
| 134 | +| Diff hygiene | yes | Targeted `git diff --check` passes | |
| 135 | +| Goal checker | yes | Autogoal checker passes after this evidence is final | |
| 136 | + |
| 137 | +Review matrix: |
| 138 | +| Path or API | Drift score | Verdict | Owner | Evidence | Next | |
| 139 | +|---|---:|---|---|---|---| |
| 140 | +| `createYjsExtension` | 0 | keep substrate | Yjs core / Plite lane | Generic Yjs runtime and focused tests remain intact | none | |
| 141 | +| `BaseYjsPlugin` | 0 | recover main owner | Yjs lib / Plate lane | Thin `extendExtension` adapter, typed and runtime-tested | none | |
| 142 | +| `YjsPlugin` | 0 | recover main owner | Yjs React / Plate lane | Thin `toPlatePlugin` wrapper, typed and runtime-tested | none | |
| 143 | +| Core extension state | 0 | fix owner | Core React plugin generics | Compile-time contract proves state survives conversion and chaining | none | |
| 144 | +| Yjs exports | 0 | main parity cleanup | Yjs package | Exact runtime import smoke and built artifact import pass | none | |
| 145 | +| Yjs docs | 0 | current API reference | Yjs/docs | Plate plugin taught; raw API isolated to explicit Plite README section | none | |
| 146 | + |
| 147 | +Best Plate v2 recommendation: |
| 148 | +| Target | Recommended shape | Rejected alternatives | Reason | |
| 149 | +|---|---|---|---| |
| 150 | +| Yjs composition | Plite extension plus thin Base/React Plate plugins; app-owned provider | Provider registry, `withPlateYjs`, Slate-Yjs enhancers, raw-Plite-only Plate docs | Correct product/substrate ownership with one runtime | |
| 151 | +| Core typing | Preserve `InferState<C>` through conversion and chained plugin methods | Yjs cast, explicit callback annotations, local editor augmentation | Fixes every plugin using editor extension state | |
| 152 | + |
| 153 | +Plite / Plate gap ledger: |
| 154 | +| Gap type | Missing capability | Local hack rejected | Smallest owner | Decision and proof | |
| 155 | +|---|---|---|---|---| |
| 156 | +| Plate gap, fixed | `toPlatePlugin` and React plugin chains dropped extension state types | Casting `state.yjs` or annotating callbacks | Core `toPlatePlugin.ts` and `PlatePlugin.ts` | Preserve `InferState<C>`; Core type contract and Yjs typecheck pass | |
| 157 | +| Remaining gap | none | none | none | Runtime and type proof show the adapter needs no new Plite API | |
| 158 | + |
| 159 | +Related scoped sweep ledger: |
| 160 | +| Trigger | Active scope | Query or method | Matches | Patched | Deferred | Risk | |
| 161 | +|---|---|---|---:|---:|---:|---| |
| 162 | +| Restore thin plugin | Yjs lib and React plugin | `withPlateYjs|createTSlatePlugin|@slate-yjs/core|YjsEditor|as any|as unknown` | 0 | 0 | 0 | none | |
| 163 | +| Correct docs lane | English/Chinese plugin pages | `createYjsExtension` | 0 | 0 | 0 | Raw API remains only in explicit Plite README section | |
| 164 | +| Preserve state typing | Core React plugin builders | `InferState<C>` | 12 | 10 | 0 | Two sites were already correct; all relevant return/config paths now preserve state | |
| 165 | +| Restore public owners | Yjs root/react exports | Runtime exact-export inspection | 2 restored values | 2 | 0 | Exact smoke prevents accidental extra/missing exports | |
| 166 | + |
| 167 | +Extracted file ledger: |
| 168 | +| Path | Bucket | Origin/main check | Proof | |
| 169 | +|---|---|---|---| |
| 170 | +| `packages/yjs/src/lib/BaseYjsPlugin.ts` | recover-main-owner | exact path exists | Typecheck, runtime test, build | |
| 171 | +| `packages/yjs/src/lib/BaseYjsPlugin.api.spec.ts` | recover-main-owner | exact path exists | Focused and full Yjs tests | |
| 172 | +| `packages/yjs/src/lib/index.ts` | recover-main-owner | exact path exists | Root runtime export smoke | |
| 173 | +| `packages/yjs/src/react/YjsPlugin.tsx` | recover-main-owner | exact path exists | React runtime test and export smoke | |
| 174 | + |
| 175 | +Release artifact classification: |
| 176 | + |
| 177 | +- `@platejs/yjs`: published major migration already existed; text now describes |
| 178 | + the Plite-backed runtime and retained Plate plugin truth. |
| 179 | +- `@platejs/core`: state inference note merged into its existing patch |
| 180 | + changeset to obey one-patch-per-package. |
| 181 | +- `@platejs/plite`: `OperationApi.root` note split into its own minor |
| 182 | + changeset because the old Yjs changeset incorrectly combined packages. |
| 183 | +- Registry changelog does not apply. |
| 184 | + |
| 185 | +Out-of-scope drift: |
| 186 | +| Surface | Evidence | Decision | |
| 187 | +|---|---|---| |
| 188 | +| Docs browser app | `/docs/yjs` compile stops on unrelated removed registry imports such as `createExcludeDiffFragmentExtension` and `useEditorContainerRef` | Do not broaden Yjs packet; source generation/parity is green | |
| 189 | +| Historical v48 migration docs | Deliberately describe historical Yjs API | Keep historical content outside current reference docs | |
| 190 | + |
| 191 | +Changed list: |
| 192 | +| Group | Files or APIs | |
| 193 | +|---|---| |
| 194 | +| Yjs runtime | Base/React plugins, lib/root/react exports, extension inference, package metadata/dependency | |
| 195 | +| Core typing | `toPlatePlugin`, React `PlatePlugin` method return types, compile-time contract | |
| 196 | +| Public proof | Yjs adapter spec, Plite exact runtime export smoke, named type smoke | |
| 197 | +| Docs | Yjs README and English/Chinese collaboration pages | |
| 198 | +| Release truth | Yjs changeset repair, Core changeset note, separated Plite changeset | |
| 199 | +| Plan | This evidence ledger | |
| 200 | + |
| 201 | +Error attempts: |
| 202 | +| Failure | Cause | Repair | |
| 203 | +|---|---|---| |
| 204 | +| Initial Yjs typecheck | React plugin conversion dropped extension state and test used Bun-only types | Fixed Core inference owner and used `node:test` | |
| 205 | +| First `check:core` | Duplicate Core patch changeset and stale exact Yjs export lists | Merged Core note and updated public package contracts | |
| 206 | +| First browser dev lane | Dynamic-doc alias could not resolve `collections/server` | Retried static MDX source lane | |
| 207 | +| Source browser lane | Global registry imports APIs already removed elsewhere in the tree | Recorded app-wide blocker; no unrelated repair | |
| 208 | +| Initial artifact audit | Command used a wrong package-relative dist path | Re-ran against package-root `dist` | |
| 209 | + |
| 210 | +Verification evidence: |
| 211 | + |
| 212 | +- `pnpm turbo typecheck --filter=./packages/core --filter=./packages/yjs` passed. |
| 213 | +- `pnpm --filter @platejs/yjs test`: 244 pass, 0 fail. |
| 214 | +- Focused Base/React adapter spec: 2 pass, 0 fail. |
| 215 | +- `pnpm --filter @platejs/yjs lint` and Core lint passed. |
| 216 | +- `pnpm --filter @platejs/yjs build` passed; declarations retain `yjs: |
| 217 | +YjsState`; root/react built imports expose the restored plugins. |
| 218 | +- `pnpm exec tsc -p packages/core/tsconfig.type-tests.json --noEmit` passed. |
| 219 | +- Focused public export smoke: 18 pass; release contract: 8 pass. |
| 220 | +- `pnpm check:core` exited 0 after its full typecheck/lint/build/test matrix. |
| 221 | +- `pnpm brl`, `pnpm changeset status`, targeted `git diff --check`, and |
| 222 | + exact source audits passed. |
| 223 | +- `pnpm --filter www check:docs` passed. |
| 224 | +- Browser reached `http://localhost:3000/docs/yjs`; rendering was blocked by |
| 225 | + unrelated app-wide registry API drift before the Yjs MDX rendered. |
| 226 | +- Structured autoreview command: |
| 227 | + `.agents/skills/autoreview/scripts/autoreview --mode local --prompt "...final |
| 228 | +Yjs/Core packet..." --stream-engine-output`; clean with no actionable findings |
| 229 | + and `patch is correct` confidence `0.81`. |
| 230 | + |
| 231 | +Final handoff: |
| 232 | +The public Plate Yjs plugin is restored as a thin composition layer over the |
| 233 | +single Plite/Yjs runtime. Provider ownership remains in app code, the obsolete |
| 234 | +Slate-Yjs machinery stays deleted, and Core now preserves plugin extension state |
| 235 | +types without Yjs-specific casts. |
| 236 | + |
| 237 | +Needs your attention: |
| 238 | +No Yjs decision remains. The docs app has unrelated registry API drift that |
| 239 | +blocks all docs routes in Browser; it belongs to a separate app/registry packet. |
| 240 | + |
| 241 | +Reboot status: |
| 242 | +| Question | Answer | |
| 243 | +|---|---| |
| 244 | +| Where am I? | Named Yjs correction implemented and proven | |
| 245 | +| Where am I going? | Handoff | |
| 246 | +| What is the goal? | Restore Plate Yjs composition without legacy runtime | |
| 247 | +| What changed? | Thin plugins restored; Core state inference fixed; exports/docs/changesets proven | |
| 248 | +| What remains? | Nothing in the Yjs packet | |
| 249 | + |
| 250 | +Open risks: |
| 251 | +Yjs-specific risk is none. Browser rendering proof remains unavailable until the |
| 252 | +unrelated docs registry removes its stale imports; MDX generation and source |
| 253 | +parity are green. |
0 commit comments