Repository navigation
Register extension-mermaid as the sixth family package #527
Description
Part of #521. Depends on #526. Read the tracker first: its §Shared contract binds this issue. Work on main.
Summary
Run the package-local gates and the CJS gate, then register the sixth package in every family list, CI file, Docker file and doc count. Nothing here changes package source.
Rulings: 8, 12 (#521 §Maintainer rulings). Must land before #528: the Dockerfile lines must exist before the webapp imports the package.
Current behaviour
scripts/publishable-extensions.ts:3-9is the single list that most gates read (read from code). Several files still hard-code the five packages. They are the CI filter, the prod workflow matrix, three Dockerfiles, the dev compose file, and many "five" counts in docs and skills (read from code).
Files
Files
- Modify:
scripts/publishable-extensions.ts,scripts/run-tests.sh:25,.github/filters/extensions.yaml,.github/workflows/prod.docs.plus.yml,.github/workflows/stage.docs.plus.yml:129,.github/actions/build-extensions/action.yml:7,19,.github/dependabot.yml. - Modify:
apps/webapp/docker/Dockerfile.bun(6 lines),apps/hocuspocus.server/docker/Dockerfile.bun(1),apps/admin-dashboard/docker/Dockerfile.bun(1),apps/webapp/docker/docker-compose.dev.yml(1). - Modify:
AGENTS.md,RELEASE_POLICY.md,README.md,extensions/README.md,context7.json,CONTRIBUTING.md,docs/README.md, both copies of therelease-extensionsandrelease-productskills (.cursor/skills/and.agents/skills/),.claude/workflows/release-product.js. - Not touched:
backend-ci.yml,release-family.ts,check-ci.ts,extension-preflight.sh,build-extensions.sh,lockstep-guard.yml(each reads the SSOT, a glob, or never builds mermaid), and the rootCHANGELOG.md(release time).
Implementation steps
-
Step 1: Run the package-local gates.
- In
PKG:bun run build,bun run typecheck,bun run testandbun run prepublishOnly. Each exits 0;testexits 0 withAll specs passed!in its output. - The d.ts greps ([Tracking] Mermaid diagrams in docs.plus through a headless Pele extension #521 §Global constraints → Pele).
- In
PKG:bun pm pack --dry-run. The list holdspackage.json,README.md,CHANGELOG.mdand the sevendist/files, and noassets/,docs/,examples/,cypress/,test/orsrc/.LICENSEappears only when the dry run runsprepack; record which. Record the size. - From
REPO:bun scripts/check-quickstart-example.ts extension-mermaidprintsin sync. Then the Root checks.
- In
-
Step 2: Run the CJS gate (its home).
- Run
grep -n "pele/lazy" PKG/dist/index.cjsand record the emitted form. - Set
NODEto the lowest installed Node binary that is 20 or later (on the maintainer laptop,~/.nvm/versions/node/v22.23.3/bin/node), and record$NODE --version. - In
PKG: for a nativeimport("pele/lazy"), run$NODE -e "import('pele/lazy').then(() => console.log('ok'))". Arequire("pele/lazy")inside any wrapper, such as__toESM(require("pele/lazy")), takes therequirebranch: run$NODE -e "require('pele/lazy'); console.log('ok')". - In both branches, also run
$NODE -e "require('./dist/index.cjs'); console.log('ok')"inPKG. okispass. Anything else isfail, but read the error first: a missing DOM global at load time is a different finding from an ESM error.- A Node 20.19 run is owed when no Node 20 is installed. Install nothing.
- Run
-
Step 3: Add the SSOT entry. Append
{ dir: 'extension-mermaid', hasUnit: false }after the placeholder entry inscripts/publishable-extensions.ts. Runbun scripts/publishable-extensions.ts --only extension-mermaid --gates. Expected:extensions/extension-mermaid 0 @docs.plus/extension-mermaid (clean-room Cypress). -
Step 4: Run the
EXT_ONLYgates. Stop any playground on ports 5173-5178 first.EXT_ONLY=extension-mermaid bash scripts/extension-preflight.shexits 0, and printspreflight @docs.plus/extension-mermaidandquickstart example: in sync for extension-mermaid.EXT_ONLY=extension-mermaid bash scripts/run-tests.sh --extensionsexits 0, withExtension gates: PASSED.
-
Step 5: Wire CI.
.github/filters/extensions.yaml: after the placeholder block, addextension-mermaid:with- *sharedand- 'extensions/extension-mermaid/**'..github/workflows/prod.docs.plus.yml: addR_MERMAID: ${{ steps.filter.outputs.extension-mermaid }}afterR_PLACEHOLDER, add,"extension-mermaid"after"extension-placeholder"in theall=JSON, and add[ "${R_MERMAID}" = "true" ] && sel+=('"extension-mermaid"')after the placeholdersel+=line..github/dependabot.yml: in the bunignore:list, after- dependency-name: 'linkedom'(line 44), add the comment# pele: bump by hand; rerun the render measure, the security probe rows, and check that Pele made no breaking change.and then- dependency-name: 'pele'.- Check:
grep -c extension-mermaid .github/filters/extensions.yaml .github/workflows/prod.docs.plus.ymlprints2and3(the filter names the package twice);grep -c "dependency-name: 'pele'" .github/dependabot.ymlprints1.
-
Step 6: Update Docker. After each line that names
extension-placeholderin the three Dockerfiles, add a copy withextension-mermaid. Indocker-compose.dev.yml, add- ../../extensions/extension-mermaid:/app/extensions/extension-mermaidafter the inline-code mount. Check:grep -c extension-mermaidprints6,1,1and1for the four files. -
Step 7: Add the table rows (alphabetical).
extensions/README.md"Choose an extension":| [`extension-mermaid`](./extension-mermaid/) | Draws each `mermaid` code block as a diagram under its source, and the document stores only the source. |extensions/README.mdCSS-export table:| [`extension-mermaid`](./extension-mermaid/) | Mermaid diagram preview for `codeBlock`, drawn by Pele | `./styles.css` | 5178 |README.mdextensions table:| [`extension-mermaid`](extensions/extension-mermaid/) | Mermaid diagram preview for `codeBlock`, drawn by Pele |RELEASE_POLICY.md, the package bullet list:- `@docs.plus/extension-mermaid`.- Check:
grep -c extension-mermaid extensions/README.md README.md RELEASE_POLICY.mdprints at least2,1and1. AGENTS.mdrun order: insert6. `@docs.plus/extension-mermaid` — clean-room Cypress against built `dist/`.and renumber the webapp Jest item to 7.
-
Step 8: Update the counts. Anchor on text, not line numbers.
- The rule. Where a sentence counts the publishable extensions, change "five" to "six", "Five" to "Six", and "5" to "6" (and
five-tuple→six-tuple,five-package→six-package,4×→5×in RELEASE_POLICY's typing-burden line). Files:prod.docs.plus.yml(3 places),stage.docs.plus.yml,build-extensions/action.yml(2),AGENTS.md(2),RELEASE_POLICY.md,README.md,extensions/README.md,CONTRIBUTING.md(3),docs/README.md, both release skills,release-product.js(2). - Keep "five" in history.
RELEASE_POLICY.mdline 12 (the Phase 1 table row), lines 59-60 (the deleted Releases and "The five git tags stay"), 83, 85, 102, 120 and 125 (Phase 1 and Trigger D); "all five shipped2.0.0independently" in both release-extensions copies; the AGENTS.md "209 s for all five" timing; the README Traefik hostnames line; and the prod "five-service" roll lines. - Change in
RELEASE_POLICY.md(read at the pinned commit): lines 9, 11, 17, 65, 73, 77 (five-tuple), 135 (five-package), 176-178, 268 ("applies to all five"), 290 ("The five per-package tags"), 294 ("Five releases means five Discord embeds") and the4×typing-burden line. - Real rewrites:
File Find Replace with scripts/run-tests.sh:25(5173-5177)(5173-5178)AGENTS.mdports lineplaceholder 5177.placeholder 5177, mermaid 5178.RELEASE_POLICY.mdreadinessBefore any extension ships its `2.0.0` (and joins the lockstep family), it needsBefore any extension first publishes, it needsRELEASE_POLICY.mdreadinessthe whole line - [ ] `[2.0.0]` `CHANGELOG.md` entry following the [style guide](#changelog-style-guide)- [ ] A CHANGELOG.md entry for the first version it publishes, following the [style guide](#changelog-style-guide)RELEASE_POLICY.mdhypermultimedia / inline-code / placeholder:hypermultimedia / inline-code / mermaid / placeholder:README.mdAll five are published on npm and share one version, released together.All six share one version and release together. `extension-mermaid` is not on npm yet; it publishes with the next family release.extensions/README.md:3Five publishable Tiptap extensions for [docs.plus](https://docs.plus). The five packages share one version under the `@docs.plus` npm scope, and they release together.Six publishable Tiptap extensions for [docs.plus](https://docs.plus). The six packages share one version under the `@docs.plus` npm scope, and they release together. `extension-mermaid` is not on npm yet; it publishes with the next family release.extensions/README.mddepsinstalls `@floating-ui/dom`. The other three…None of the five declares a Node or Bun engine floor.installs `@floating-ui/dom`. `extension-mermaid` installs `pele`, which declares Node 20 or later. The other three…None of the six packages declares its own Node or Bun engine floor.extensions/README.mdCSSTwo packages ship a stylesheetand the two-name listThree packages ship a stylesheet, adding@docs.plus/extension-mermaid/styles.cssextensions/README.mdkeysextension-placeholder` binds no key, so it carries no such table.`extension-mermaid` and `extension-placeholder` bind no key, so they carry no such table.extensions/README.mdCONTRIBUTING linksthe inline-code link add [mermaid](./extension-mermaid/CONTRIBUTING.md)docs/README.mdThe five Tiptap extensions docs.plus publishes to npmThe six `@docs.plus/extension-*` Tiptap extensionscontext7.json:6Ships 5 Tiptap 3 extensions: hyperlink, hypermultimedia, indent, inline-code, placeholder.Ships 6 Tiptap 3 extensions: hyperlink, hypermultimedia, indent, inline-code, mermaid, placeholder.context7.json:30The five: …, extension-placeholder.The six: …, extension-mermaid, extension-placeholder. extension-mermaid is not on npm yet; it publishes with the next family release.context7.json: after the hypermultimedia stylesheet rule, add one rule: "With extension-mermaid, import @docs.plus/extension-mermaid/styles.css. Without it, Pele's own error text shows and the diagram dims while the source has a mistake. A host addNodeView for codeBlock, or an earlier plugin that sets nodeViews.codeBlock, replaces the diagram view with no error."- On a CJS
failonly: after the RELEASE_POLICY paragraph that starts "Theextension-hyperlinkpackage is the reference shape", add:**ESM-only exception — `@docs.plus/extension-mermaid`.** Its `dist/index.cjs` cannot load `pele/lazy` on Node <version>, because `pele` ships ESM only. Load the package with `import` or a bundler. Recorded <date>.
- The rule. Where a sentence counts the publishable extensions, change "five" to "six", "Five" to "Six", and "5" to "6" (and
-
Step 9: Format and sync. Run
bunx prettier --write --ignore-unknownon every file this task touched. Then copy each.cursor/skills/<skill>/SKILL.mdto its.agents/skills/twin (.prettierignoreskips.agents/skills), andcmpeach pair. Expected: no output. -
Step 10: Check for leftovers.
git -C REPO grep -n -i -w -e five -e 'all 5' -e 'ships 5'over the files in Step 8 prints only the history lines that Step 8 keeps.for f in $(git -C REPO grep -l extension-placeholder -- ':!bun.lock' ':!extensions/extension-placeholder'); do grep -q extension-mermaid "REPO/$f" || echo "$f"; doneprints exactly:CHANGELOG.md,apps/webapp/package.json,apps/webapp/src/components/TipTap/CLAUDE.md,apps/webapp/src/components/TipTap/TipTap.tsx,apps/webapp/src/components/TipTap/placeholders/buildBreadcrumbPlaceholder.test.tsandapps/webapp/src/components/TipTap/placeholders/buildBreadcrumbPlaceholder.ts. After Draw Mermaid diagrams in the pad, history and /editor #528,apps/webapp/package.jsonandTipTap.tsxdrop off this list; the other four stay, because none of them ever names the package.
-
Step 11: Run
bun run check:agent-docsand the Root checks. Each exits 0. -
Step 12: Review checkpoint. Report the Step 1 gates, the pack list and size, the CJS verdict with its Node version, and the Step 4 and Step 11 results.
Acceptance criteria
- The package-local gates and the
EXT_ONLYgates pass, and the pack list holds only the expected files. - The CJS verdict is
pass, orRELEASE_POLICY.mdholds the ESM-only exception. - The Step 10 leftover checks print exactly their expected lists.
bun run check:agent-docsand the Root checks pass.
Activity
ci(extensions): register extension-mermaid as the sixth family package
HMarzban commentedon Oct 19, 2026
Step 2 CJS gate, progress 2026-10-19
dist/index.cjsloadspele/lazythrough a nativeimport()inside a lazy function, so the import branch is the gate.import('pele/lazy')passes.require('./dist/index.cjs')loads with no DOM global.require('pele/lazy')also passes, but only because Node 22 canrequirean ES module.HMarzban commentedon Oct 19, 2026
Step 2 CJS gate on Node 20.19: pass (2026-10-19)
Node
v20.19.6, installed withnvm install 20.19, was run by full path. The default Node is unchanged.node -e "import('pele/lazy').then(() => console.log('ok'))"in the packageok, exit 0node -e "require('./dist/index.cjs')"ok, exit 0: loads with no DOM global and exportsMermaiddist/index.cjsimport("pele/lazy")inside a lazy function, so Pele loads only on first drawThe other steps were already met. The SSOT entry and the CI wiring are done: tonight's CI/CD run 39297468969 ran
Ext (extension-mermaid)and passed. The Docker images built and deployed in the same run.