LearnNewsExamplesServices
Frontmatter
id15358
titleThe docs build wears a deleted package''s name: rename jsdocx.mjs + jsdoc-x/, and stop printing the false `jsdoc-x → catharsis` chain
stateClosed
labels
documentationcontributor-experiencebuildmodel-experience
assigneesneo-opus-grace
createdAtJul 17, 2026, 2:43 PM
updatedAtJul 18, 2026, 1:54 PM
githubUrlhttps://github.com/neomjs/neo/issues/15358
authorneo-opus-grace
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 18, 2026, 1:54 PM

The docs build wears a deleted package's name: rename jsdocx.mjs + jsdoc-x/, and stop printing the false jsdoc-x → catharsis chain

Closed Backlog/active-chunk-7 documentationcontributor-experiencebuildmodel-experience
neo-opus-grace
neo-opus-grace commented on Jul 17, 2026, 2:43 PM

Context

@tobiu: "buildScripts/docs/jsdocx.mjs could use a rename, and the CI descriptions should no longer mention jsdoc-x for clarity."

We removed the discontinued jsdoc-x npm package and replaced it in-repo — #13433 era work, celebrated in learn/blog/context-engineering-done-right.md ("Zero npm security warnings (down from 19...) by removing the legacy siesta and jsdoc-x dependencies", "jsdoc-x rewrite: 5.2s builds, 81% faster than 28s"). The package is gone. The name is still everywhere, and it now describes a thing that does not exist.

The Problem — this is not only cosmetic

1. The live tooling prints a chain that is wrong at two layers.

buildScripts/util/check-jsdoc-types.mjs:195 prints, on every failure:

jsdoc-x → catharsis (Closure/JSDoc grammar, NOT TypeScript); an unparseable type fails the build

Same claim in its docstring (:12) and echoed in test/playwright/unit/ai/buildScripts/util/check-jsdoc-types.spec.mjs:6.

Verified against the tree, the real chain is:

jsdocx.mjs → buildScripts/docs/jsdoc-x/ (OUR replacement; runner.mjs, multi-threaded)
           → jsdoc-api → the jsdoc ENGINE → catharsis
              (jsdoc deps: catharsis ^0.9.0; runner.mjs:17 dictionaries: ['jsdoc','closure'])
  • The jsdoc-x npm package is not installed — nothing in the chain is jsdoc-x. jsdocx.mjs imports ./jsdoc-x/index.mjs, our own directory.
  • Our replacement does not parse types at all. It handles JSON output/transform. The rejecting grammar belongs to the jsdoc engine, which we did not replace — so the message points a reader at the one layer they cannot fix, and away from the one they must understand.

This message is a teaching surface, and it teaches the wrong thing. Evidence, not theory: I hit this lint in a consuming repo, took jsdoc-x → catharsis from its output, and propagated it into a ticket body, two commit messages, and a PR description before @tobiu caught it. A message whose only job is to explain a failure produced four wrong artifacts from one read.

The misconception is systemic, not a typo: #13433's own body encodes buildScripts/docs/jsdocx.mjsjsdoc-xcatharsis. Tool, spec, and governing ticket all agree — and all are wrong. That is why it reproduces so cleanly in anyone who reads it.

2. The names point at the dead package.

path problem
buildScripts/docs/jsdocx.mjs the docs entrypoint, named after a package we deleted
buildScripts/docs/jsdoc-x/ our own replacement, wearing the name of the thing it replaced

The directory is arguably the worse of the two: runner.mjs / transformer.mjs / sorter.mjs / utils.mjs are ours, and the folder tells every reader they are vendored third-party code.

3. Aligned-on-touch (same 6-line message): check-jsdoc-types.mjs sends readers to .github/CODING_GUIDELINES.md#11-jsdoc-type-expressions. The script is deliberately repo-agnostic — its git rev-parse --show-toplevel resolves to the consuming repo, which is what makes it reusable from node_modules. So in any consuming repo the message names a file that does not exist there. Two defects in one message; fix them in one edit.

Scope

In:

  1. Rename buildScripts/docs/jsdocx.mjs and buildScripts/docs/jsdoc-x/ (names below — @tobiu's call).
  2. Correct the chain in live surfaces: check-jsdoc-types.mjs:12,195, check-jsdoc-types.spec.mjs:6, buildScripts/README.md:54, and the ai/services/graph/GoldenPathSynthesizer.mjs:1588 string ("structural jsdocx graph expectations").
  3. Make the message's doc pointer meaningful from a consuming repo (or drop the path and inline the accepted forms).

Out — and deliberately so:

  • resources/content/archive/** and apps/portal/resources/data/** (~50 files). These are archived issues/PRs. They said jsdoc-x because jsdoc-x was true then. Rewriting them falsifies the record — the archive is evidence, not documentation.
  • learn/blog/*.md — the posts discuss the real historical dependency and its removal. Those mentions are correct and must stay.
  • resources/data/deck/training/pages/*.md — historical training material.
  • The .github/workflows/jsdoc-type-lint.yml description is already clean (it says catharsis, not jsdoc-x) — no change needed; noting it so nobody re-audits it.

Blast Radius — the rename is not free

  • package.json:103 ("generate-docs-json": "node ./buildScripts/docs/jsdocx.mjs") — trivial.
  • Downstream apps that reference the file path directly in their own package.json — the pattern "generate-docs-json": "node ./node_modules/neo.mjs/buildScripts/docs/jsdocx.mjs" is published in this repo at resources/data/deck/training/pages/2023-07-01T15-42-45-193Z.md:427. A rename breaks their docs build with MODULE_NOT_FOUND.
  • buildScripts/create/ does NOT emit that line (verified) — so apps scaffolded via create-app are unaffected. The exposed population is apps that copied the documented pattern.

Fork (recommendation, not a decision): hard-rename and note it as breaking — the downstream fix is one line in package.json, and a compat shim at the old path is permanent debt for a one-line problem (§self_evolving_systems accretion defense: a shim would need a sunset trigger nobody will honour). Alternative if that is too sharp: shim + deprecation warning, sunset at v14. Recommend: hard rename + release-note.

Naming (proposal — final call is @tobiu's, per the aesthetics boundary)

Convention, measured: buildScripts/ is camelCase for build/create/helper scripts (20 files: addReactiveTags.mjs, convertDesignTokens.mjs, buildThreads.mjs…), kebab reserved for check-* guards (15: check-jsdoc-types.mjs, check-whitespace.mjs…).

  • jsdocx.mjsgenerateDocsJson.mjs — matches the convention and the npm script it backs (npm run generate-docs-json). One name for one thing; the path stops being a riddle.
  • jsdoc-x/docletPipeline/ (or docsJson/) — says what it does: drives the engine, then sorts/transforms doclets into our JSON.

Acceptance Criteria

  • rg -i "jsdoc-x|jsdocx" over live code/docs (excluding the archive/blog/deck paths above) returns only accurate historical references.
  • check-jsdoc-types failure output names the jsdoc engine → catharsis, and no longer implies a jsdoc-x package exists.
  • The message's doc pointer resolves for a reader in a consuming repo, not just in neo.
  • npm run generate-docs-json and npm run build-all both still pass (the docs step is the tail of build-all; buildScripts/build/all.mjs:162 spawns it by npm-script name, so it is rename-safe — confirm, don't assume).
  • The rename decision (hard vs shim) is recorded in the PR, and if hard, a breaking-change note lands with the release.
  • test/playwright/unit/ai/buildScripts/util/check-jsdoc-types.spec.mjs still green.

Avoided Traps

  • Do not sed the repo for jsdoc-x. ~50 of the 65 matches are archived issues/PRs and blog posts where the term is correct. A global replace corrupts the historical record to fix a build script.
  • Do not "fix" the message by deleting the chain. Naming the engine as the parser is the whole point — a reader who knows the grammar is the engine's stops trying to fix it in our code.
  • Do not rename only the entrypoint. The jsdoc-x/ directory is the more misleading of the two: it labels our own code as someone else's.

Retrieval Hint: "jsdocx rename jsdoc-x discontinued package catharsis jsdoc engine docs build check-jsdoc-types wrong chain error message generateDocsJson doclet pipeline"