docs/plans/5004-fix-hook-stable-leaf-renderers.md
Objective: Fix #5004 hook-stable leaf/text renderers; done when regression tests, package checks, browser proof, review, and plan pass.
Goal plan: docs/plans/5004-fix-hook-stable-leaf-renderers.md
Template: docs/plans/templates/task.md
Primary template: docs/plans/templates/task.md
Applied packs:
Task source:
Completion threshold:
@platejs/core render pipelines so complex renderers call hooks in stable order while simple renderers keep the inactive skip optimization.@platejs/core.node .agents/skills/autogoal/scripts/check-complete.mjs docs/plans/5004-fix-hook-stable-leaf-renderers.md passes.Verification surface:
bun test packages/core/src/react/utils/pipeRenderLeaf.spec.tsxpnpm turbo typecheck --filter=./packages/corepnpm lint:fixConstraints:
Boundaries:
packages/core/src/react/utils/pipeRenderLeaf.tsx, packages/core/src/react/utils/pipeRenderText.tsx, focused tests, .changeset, and this plan.Output budget strategy:
rg with targeted terms and capped output. Read only direct source/test/solution files. Avoid broad package dumps and full repo checks until needed.Blocked condition:
Task state:
Current verdict:
Completion rule:
update_goal(status: complete) while any required checklist item
remains unchecked. If an item does not apply, check it and add N/A: <reason>.update_goal(status: complete) until every completion threshold
above is satisfied, final handoff evidence is recorded, and
node .agents/skills/autogoal/scripts/check-complete.mjs docs/plans/5004-fix-hook-stable-leaf-renderers.md passes.Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Skill analysis before edits | yes | Loaded task, autogoal, tdd, and changeset rules. |
| Active goal checked or created | yes | get_goal returned none; create_goal created active goal for this plan. |
| Source of truth read before edits | yes | gh issue view 5004 --comments --json ... read issue and comment. |
| Tracker comments and attachments read | yes | One Dosu comment read; no attachments/video in issue payload. |
| Video transcript evidence required | no | N/A: no video or screen recording evidence. |
docs/solutions checked for non-trivial existing-code work | yes | Read April 2026 inactive renderer fan-out solution. |
| TDD decision before behavior change or bug fix | yes | Add red tests for hook-stable complex leaf/text rerender. |
| Branch decision for code-changing task | yes | No branch command before edits; PR branch handled only if PR stage is reached. |
| Release artifact decision | yes | .changeset required: published @platejs/core runtime behavior changes. |
| Browser tool decision for browser surface | yes | Use repo-approved Browser if a runnable route is practical; otherwise record blocker. |
| PR expectation decision | yes | Task skill expects PR after verified code unless blocked; repo check gate applies first. |
| Tracker sync expectation decision | yes | Sync back after meaningful verified outcome/PR unless blocked. |
| Output budget strategy recorded | yes | Targeted rg/sed, capped outputs, no full repo dumps. |
| Browser pack selected | yes | Applied browser pack. |
| Browser route / app surface identified | yes | Browser route /docs/examples/code-block identified and verified. |
| Browser tool decision recorded | yes | Use Browser plugin, not raw Playwright/Puppeteer. |
| Console/network caveat policy recorded | yes | Browser proof should include console state; if no target, record explicit caveat. |
| Package/API pack selected | yes | Applied package-api pack. |
| Public surface or package boundary identified | yes | Published @platejs/core React render pipeline. |
| Release artifact path selected | yes | .changeset for @platejs/core patch. |
changeset skill loaded when .changeset is required | yes | Read .agents/rules/changeset.mdc; core package patch only. |
| Barrel/export impact decision recorded | yes | No export/file layout change expected; pnpm brl N/A unless diff changes. |
Work Checklist:
<video-transcripts> XML, or marked N/A with reason..agents/**, .claude/**,
.codex/**, skills, hooks, commands, prompts, or user-action tooling..changeset, registry changelog, or explicit no-artifact reason..changeset work loads changeset and follows its package/version/prose rules.tooling/data/plate-ui-changelog.mdx and generated /registry/changelog/* JSON instead of adding a package changeset.main.Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Named verification threshold | yes | Run the command, proof, source audit, or artifact check named in this plan | bun test packages/core/src/react/utils/pipeRenderLeaf.spec.tsx, pnpm turbo typecheck --filter=./packages/core, Browser proof, autoreview, and pnpm check passed in /Users/zbeyens/git/plate. |
| Bug reproduced before fix | yes | Record failing test/repro or N/A with reason | New leaf rerender spec failed before fix with React hook-order warning. |
| Targeted behavior verification | yes | Run focused test/proof for changed behavior or record N/A | bun test packages/core/src/react/utils/pipeRenderLeaf.spec.tsx -> 16 pass, 0 fail. |
| TypeScript or typed config changed | yes | Run relevant typecheck | pnpm turbo typecheck --filter=./packages/core and pnpm check typecheck passed. |
| Package exports or file layout changed | no | Run pnpm brl before final verification and keep generated barrel updates | N/A: no exports or file layout changed. |
| Package manifests, lockfile, or install graph changed | no | Run pnpm install and relevant package checks | N/A: no manifest, lockfile, or dependency graph change. |
| Agent rules or skills changed | no | Run pnpm install and verify generated skill sync | N/A: no agent rule or skill change. |
| Workspace authority proof | yes | Run verification in the owning repo/package/app/route/tool and record cwd; do not count the wrong workspace as proof | Commands and Browser proof ran in /Users/zbeyens/git/plate; browser route owned by apps/www. |
| Browser surface changed | yes | Capture Browser Use proof or record explicit waiver/blocker | Browser opened http://localhost:3000/docs/examples/code-block and exercised code block language changes. |
| Browser final proof | yes | Attach screenshot or exact browser verification caveat when browser proof applies | Route loaded as code-block-demo - Plate; JavaScript -> Plain Text -> JavaScript changed syntax count 48 -> 0 -> 48 with no warn/error logs. |
| CI-controlled template output changed | no | Restore generated template output or record why it is intentionally kept | N/A: no templates/** changes. |
| Package behavior or public API changed | yes | Add a changeset or record why no changeset applies | .changeset/hook-stable-leaf-renderers.md adds @platejs/core patch. |
| Registry-only component work changed | no | Update tooling/data/plate-ui-changelog.mdx, run node tooling/scripts/generate-ui-changelog-entries.mjs --write, or record N/A | N/A: not registry-only work. |
| Docs or content changed | no | For docs-heavy work, use --template docs; for incidental docs, verify source-backed claims, links, examples, and rendered output or record N/A | N/A: runtime plan file only, no user docs/content. |
| High-risk mini gate | yes | For public API/runtime/package-boundary/browser/agent-action/command-contract changes, record realistic failure mode, proof plan, and why the chosen boundary is right; otherwise N/A | Failure mode: hook-calling renderers executed in Slate Leaf; proof: red/green test and browser language switch; boundary: core pipes own renderer invocation. |
| Agent-native review for agent/tooling changes | no | For .agents/**, .claude/**, .codex/**, skills, hooks, commands, prompts, or user-action tooling, load .agents/skills/agent-native-reviewer/SKILL.md and close accepted/actionable findings, or record N/A | N/A: no agent/tooling files changed. |
| Local install corruption suspected | no | Run pnpm run reinstall once, rerun the exact failing command, or record N/A | N/A: no verification failure; pnpm check passed. |
| Autoreview for non-trivial implementation changes | yes | Load .agents/skills/autoreview/SKILL.md; use dirty local --mode local, branch/PR --mode branch --base <base>, or committed slice --mode commit --commit <ref> until no accepted/actionable findings, or record N/A for docs-only/trivial/no local patch | First local review found stale plan path; fixed. Second .agents/skills/autoreview/scripts/autoreview --mode local clean. |
| PR create or update | yes | Run check before PR work and sync PR body to the task-style final handoff | pnpm check passed; PR #5009 created: https://github.com/udecode/plate/pull/5009. |
| Task-style PR body verified | yes | Verify the PR body with gh pr view --json body; it must preserve auto-release blocks when applicable, must not include a current-PR self-link, and must use the kitcn PR #270 emoji format: ๐ Fixes ..., ๐ข 95-100% confidence, Phase / ๐งช Tests / ๐ Browser table, and bold emoji Outcome/Caveat/Design/Verified sections | gh pr view 5009 --repo udecode/plate --json url,body,headRefName,baseRefName,isDraft verified auto-release block, issue line, confidence, table, and required sections. |
| PR proof image hosting | no | If PR body needs browser proof, replace local image paths with hosted GitHub URLs or record N/A | N/A: PR body will use textual browser proof, no local image. |
| Tracker sync-back | yes | Post concise issue/Linear sync after PR exists, or record N/A/blocker | Issue comment posted: https://github.com/udecode/plate/issues/5004#issuecomment-4699892610. |
| Final handoff contract | yes | Fill the final handoff fields below with exact PR/issue/confidence/tests/browser/outcome/caveats/design/verification content or N/A reason | Final handoff fields below include PR, issue, confidence, tests, browser proof, caveat, design, and verification. |
| Final lint | yes | Run pnpm lint:fix or scoped equivalent | pnpm lint:fix passed; pnpm check lint passed with one pre-existing warning. |
| Output budget discipline | yes | Verify no unbounded high-volume command output was streamed, or record the accidental output and recovery | One broad route search streamed large output; subsequent searches were scoped and capped. |
| Goal plan complete | yes | Run node .agents/skills/autogoal/scripts/check-complete.mjs docs/plans/5004-fix-hook-stable-leaf-renderers.md | [autogoal] complete: docs/plans/5004-fix-hook-stable-leaf-renderers.md. |
| Browser interaction proof | yes | Exercise the target route/interaction with the approved browser tool or record blocker | Browser route /docs/examples/code-block; first combobox JavaScript -> Plain Text -> JavaScript. |
| Browser console/network check | yes | Record console/network state or why it is not applicable | tab.dev.logs({ levels: ['error','warn'] }) returned [] after both language switches. |
| Browser final proof artifact | yes | Record screenshot/trace/route proof or exact caveat | Exact Browser proof recorded in Verification evidence; no screenshot needed. |
| Public API / package boundary proof | yes | Source-audit public API, exports, and package boundary impact | No packages/core/src/react/utils/index.ts or package export change; runtime behavior only. |
| Release artifact classification | yes | Record whether the change is published package behavior/API/types/config/runtime, registry-only, or no published user-visible delta | Published @platejs/core runtime behavior fix. |
| Published package changeset | yes | If published package users see a delta, load changeset, add/update one .changeset/*.md per package, and prove no forbidden minor on @platejs/slate, @platejs/core, or platejs | .changeset/hook-stable-leaf-renderers.md uses "@platejs/core": patch. |
| Registry changelog | no | If the change is registry-only under apps/www/src/registry/**, update tooling/data/plate-ui-changelog.mdx, run node tooling/scripts/generate-ui-changelog-entries.mjs --write, and do not add a package changeset | N/A: no registry files changed. |
| No release artifact | no | If no artifact is needed, record the exact reason: internal-only, docs-only, agent-only, test-only, or no user-visible delta from main | N/A: changeset required and added. |
| Package typecheck/build/test | yes | Run owning package checks or record N/A with reason | Focused test, package typecheck, and full pnpm check passed. |
| Barrel/export generation | no | Run pnpm brl when exports or exported file layout changed, otherwise N/A | N/A: no exports or exported file layout changed. |
Phase / pass table:
| Phase | Status | Evidence | Next |
|---|---|---|---|
| Intake and source read | complete | GitHub issue #5004 and comment read; local source and solution note read. | implementation |
| Implementation | complete | Complex renderers mounted as child components in leaf/text pipes; changeset added. | verification |
| Verification | complete | Focused test, package typecheck, Browser proof, autoreview, and pnpm check passed. | PR / tracker sync |
| PR / tracker sync | complete | Branch codex/fix-hook-stable-leaf-renderers pushed; PR #5009 created; issue #5004 commented. | closeout |
| Closeout | complete | Goal plan final check ready after route and closeout markers were resolved. | final response |
Findings:
pipeRenderLeaf / pipeRenderText executed hook-calling plugin renderers as plain functions only when matching marks were active./docs/examples/code-block reproduces the practical surface with slate-code_syntax decorations.Decisions and tradeoffs:
@platejs/core runtime behavior; no barrel generation because exports did not change.Implementation notes:
pipeRenderLeaf wraps active complex render output as <RenderLeaf {...props}>{props.children}</RenderLeaf>.pipeRenderText mirrors the same pattern for active complex text renderers.Review fixes:
docs/plans/5004-fix-hook-stable-leaf-renderers.md; clean rerun.Error attempts:
| Error / failed attempt | Count | Next different move | Resolution |
|---|---|---|---|
| Broad route search streamed too much output | 1 | Use targeted Browser route and capped reads. | Recovered; evidence recorded and later searches capped. |
| Issue comment body used shell backticks inside a double-quoted shell argument | 1 | Interrupt accidental command substitution and repost with --body-file -. | Accidental command was interrupted before posting; issue comment reposted successfully with a single-quoted heredoc. |
Verification evidence:
bun test packages/core/src/react/utils/pipeRenderLeaf.spec.tsx failed before production fix on new complex leaf hook-order test with React "change in the order of Hooks" warning.bun test packages/core/src/react/utils/pipeRenderLeaf.spec.tsx -> 16 pass, 0 fail, 34 expects.pnpm turbo typecheck --filter=./packages/core -> 5 tasks successful.pnpm lint:fix -> checked 3272 files, no fixes applied.pnpm dev served http://localhost:3000; Browser route /docs/examples/code-block loaded as code-block-demo - Plate; first code block switched JavaScript -> Plain Text -> JavaScript, syntax count 48 -> 0 -> 48, warn/error logs []..agents/skills/autoreview/scripts/autoreview --mode local accepted one plan-path finding; after fix, rerun clean with no accepted/actionable findings.pnpm check passed lint, full package build/typecheck, fast/slow/slowest tests. Lint emitted one pre-existing warning in apps/www/src/components/ui/sidebar.tsx.Final handoff contract:
pnpm check, autoreview/docs/examples/code-block, JavaScript -> Plain Text -> JavaScript, no warn/error logsLeaf hook order when marks appear or disappearpnpm check lint reports one existing warning in apps/www/src/components/ui/sidebar.tsx@platejs/core render pipes own plugin renderer invocationpnpm check, autoreviewgh pr view 5009 --repo udecode/plate --json url,body,headRefName,baseRefName,isDraftTask-style PR body contract:
<!-- auto-release:start --> block. If a changeset is
part of the diff and repo policy expects auto release, include that block.๐ Fixes #123 or ๐ Fixes โ N/A, then
an emoji confidence line like ๐ข 95-100% confidence.| Phase | ๐งช Tests | ๐ Browser |.Reproduced and Verified rows. Mark passing proof with ๐ข, repro or
failing proof with ๐ด, and non-applicable cells with โ N/A.**โ
Outcome**, **โ ๏ธ Caveat**,
**๐๏ธ Design**, and **๐งช Verified**.Summary / Verification PR body, an
adaptive prose body from a git helper skill, plain ## Outcome sections, or
an unrelated generated badge footer unless the caller or repo template
explicitly asks for it.gh pr view --json body output or a concise source-backed summary
of that output.Final handoff / sync:
/docs/examples/code-block language switch, no warn/error logssidebar.tsx lint warning during pnpm checkTimeline:
/docs/examples/code-block.pnpm check passed.codex/fix-hook-stable-leaf-renderers created, commit cbc70dd446 created, and branch pushed.gh pr view --json body.Reboot status:
| Question | Answer |
|---|---|
| Where am I? | Closeout |
| Where am I going? | Final plan check, mark goal complete, final response |
| What is the goal? | Fix #5004 hook-stable leaf/text renderers with tests, browser proof, changeset, PR, and plan closure |
| What have I learned? | Component boundaries fix the hook warning without losing inactive-renderer skipping |
| What have I done? | Implemented, tested, browser-verified, reviewed, passed pnpm check, opened PR, and synced issue |
Open risks: