Systematically rewrite every JSDoc and code comment in shipped source (
packages/*/src) so it serves framework users and AI agents, not maintainers. Governed by the "Documentation for users & AI agents (NON-NEGOTIABLE)" directive inCLAUDE.md.This plan lives outside
codeops/deliberately —codeops/is being removed, so the plan that purges references to it cannot depend on it.
Transform the docs from maintainer-facing to consumer/agent-facing. The work is complete when:
scripts/check-jsdoc.mjsis green acrosspackages/*/src, meaning:- Zero banned references anywhere in shipped code (JSDoc and
////* */comments):RD-/PA-/AR-/PF-/HR-/GATE-/AC-/ST-/ADR-/DEF-codes,codeops|plans|requirementspaths, and TV/C++ provenance (t*.cpp/*.hcitations,getColor(N)palette archaeology). - Every public export (each symbol re-exported from a package
index.ts) has a lead sentence,@param/@returnswhere applicable, and an@example.
- Zero banned references anywhere in shipped code (JSDoc and
- Above-junior logic carries short why comments a junior developer can follow.
yarn verifypasses (the guard is wired into it) and CI enforces it on every PR.
Scale (measured): ~193 of 195 source files carry banned references (~2,730 code occurrences + 693 C++ citations). This is effectively a whole-codebase pass.
Scope boundary: shipped source only. Out of scope — CLAUDE.md, codeops/, test/**. Example
code (packages/examples/**) follows the spirit but is not gated by the guard.
The codes annotate real behavior. Keep the behavior, drop the code. Never blind-delete a sentence.
| Before (maintainer) | After (user/agent) |
|---|---|
Command emitted via ev.emit on activation (PA-1). |
Command name emitted when the button is activated. |
index is DISPLAY order, item the T (PF-003). |
Called on selection; index is the display-order row, item the selected value. |
Faithful to TButton::drawState (tbutton.cpp:102-165). cShadow = getColor(8) = 0x70… |
(delete entirely — provenance, no user value) |
The overlay's visibility (RD-14 PA-5/PF-001)… |
The overlay is visible whenever it hosts a popup, hidden otherwise. |
Every symbol re-exported from an index.ts gets:
/**
* <One lead sentence: what it is / does, in plain language.>
*
* <Behaviors, constraints, and gotchas a caller must know — ordering rules,
* reactive-vs-imperative seams, footguns. Only what a USER needs.>
*
* @param <name> <what it is and any constraint>
* @returns <what comes back, and when>
* @example
* <realistic, copy-pasteable usage — correct enough to paste and run>
*/Per symbol kind:
- Component class (
Button,DataGrid) — lead = what the widget is + primary interaction;@example= construct + add to a parent + bind a signal. - Options interface (
ButtonOptions) — lead = "Options forX."; document each field inline; the worked@examplelives on the class, not repeated here. - Factory / function (
createApplication,filter) — lead = what it produces; full@param/@returns;@example= the call in context. - Pure helper (
addDays,nearest16) — lead = the transform;@example= input → output.
Add a short why comment where a junior would stall: non-obvious algorithms, invariants, subtle
ordering/lifecycle rules (e.g. "bind() must run in onMount because the reactive scope doesn't
exist in the constructor"), and deliberate performance choices. Trivial lines get nothing. No
maintainer traceability.
Build the enforcement before touching a single doc, so it produces the objective worklist and becomes the regression gate. Expect it to fail across ~193 files on first run — that is the point.
Inputs: all *.ts under packages/*/src excluding *.test.ts.
Check A — banned references (whole file, comments only):
- Strip string/template literals, then scan comment ranges for:
/\b(RD|PA|AR|PF|HR|GATE|AC|ST|ADR|DEF)-\d+//\b(codeops|plans|requirements)\///\b[a-z][a-z0-9]*\.(cpp|h)\b/(TV/C++ source refs) and/getColor\s*\(/inside comments
- Report
file:line: banned reference "<match>".
Check B — @example on public exports:
- Resolve the public set: parse each
packages/<pkg>/src/index.ts, follow itsexport { … } from/export * fromre-exports to the declaring symbol. - For each public symbol's declaring JSDoc block, require an
@exampletag (and a non-empty lead line). Reportfile:line: public export "<name>" missing @example.- Note on
export *:reactive/index.tsusesexport *— expand it to concrete names so nothing slips through. (Also a good moment to consider converting it to explicit named exports for consistency, but that's optional and separate.)
- Note on
Behavior: exit non-zero with a grouped, per-file report on any violation. Support
--summary (counts only) so progress is trackable during the cleanup.
Optional hardening (recommended): verify @example snippets type-check — extract each
@example body into a temp .ts that imports from the built package and run tsc --noEmit. This is
what makes examples trustworthy for agents. Can start as a warning, become an error later.
packages/*/package.json: add"check:docs": "node ../../scripts/check-jsdoc.mjs <pkgDir>".turbo.json: add acheck:docspipeline entry.- Root
package.json: addcheck:docsand fold it intoverify(turbo run typecheck build test check:docs). .github/workflows/ci.yml: runyarn check:docs(or rely onverify).- Enable
"stripInternal": trueintsconfig.base.json(harmless now; useful later).
- Commit the JSDoc template (§2.2) into
packages/docs-site/reference/guides/development.md(or a shortCONTRIBUTINGnote). - Run
node scripts/check-jsdoc.mjs --summaryand capture the baseline counts per package — the burn-down target.
Each subsystem is an independent unit: rewrite public JSDoc, strip banned refs, add above-junior
comments, then check:docs for that directory must go green. Ordered by how much a
user/agent touches the API (highest-traffic first).
Every phase's per-file checklist:
- Rewrite the file-header JSDoc for a consumer (drop plan/C++ archaeology).
- For each public export: lead sentence → behaviors/gotchas →
@param/@returns→@example.- Rewrite banned-code sentences semantically (keep meaning, drop code); delete pure provenance.
- Add why comments to above-junior logic; delete maintainer traceability comments.
node scripts/check-jsdoc.mjs packages/<pkg>/src/<dir>→ green.yarn typecheck(examples must still compile) and spot-run the example.
| Phase | Subsystem (dir) | Why this order |
|---|---|---|
| 1 | controls/ (Button, Input, Label, CheckGroup, RadioGroup, MultiCheckGroup, validators) |
The most-used leaf widgets; highest doc traffic. |
| 2 | view/ + reactive/ |
The authoring + reactivity contracts every custom widget depends on. |
| 3 | event/ + app/ + desktop/ + window/ + menu/ + status/ |
The app-shell surface (createApplication, commands, modality). |
| 4 | dialog/ + scroll/ + list/ + dropdown/ |
Containers, scrolling, lists, dropdowns. |
| 5 | table/ + tree/ + tabs/ |
Data/navigation components. |
| 6 | date/ + color/ + feedback/ + surface/ |
Pickers, feedback, surface. |
| 7 | editor/ + terminal/ + layout/ + top-level index.ts |
Editor family, layout primitives, the barrel. |
| Phase | Subsystem (dir) | Notes |
|---|---|---|
| 8 | capability/ + color/ (resolveCapabilities, Attr, Style, toRgb, theme) |
These leak into every UI app — prioritize. |
| 9 | input/ + render/ |
Decoder + rendering primitives (ScreenBuffer, serialize, charWidth). |
| 10 | host/ + safety/ + top-level index.ts |
Host lifecycle, errors/logger, the barrel. |
The phases are independent, so this parallelizes cleanly:
- Recommended: one subagent per subsystem (Phase 1..10), each handed §2's rules + §4's checklist,
each gated by
check:docsgoing green for its directory. A subagent returns only when its slice is green andtypecheckpasses. This is a natural multi-agent fan-out; if you want it run as an orchestrated workflow, say so and I'll drive it. - Alternatively: work the phases sequentially, committing per subsystem (
docs(<subsystem>): …). - Commit granularity: one commit per phase keeps the burn-down reviewable and easy to revert.
- Guard discipline: never mark a phase done on a hand-wave — the objective signal is
node scripts/check-jsdoc.mjs packages/<pkg>/src/<dir>returning zero violations.
- Examples must be correct — agents will trust and paste them. This is why §3.1 recommends
type-checking
@examplebodies. A wrong example is worse than none. - Semantic rewrite, not regex delete — the codes tag real behavior; a naive
sedthat strips(PA-3)and leaves a dangling clause, or deletes whole useful sentences, degrades the docs. Human/ agent judgment per sentence is required. export *inreactive/index.tscomplicates the public-set detection (§3.1 Check B) — expand it explicitly in the guard.- Existing 16
@internalblocks — decide their fate per the directive: if they contain banned provenance, purge it;@internalis not an exemption from the ban (it only hides from published types). - Don't break the examples package —
packages/examples/**imports these symbols; runyarn typecheckafter each phase so a doc edit that accidentally changes a signature is caught. - File-header JSDoc is the densest jargon (whole paragraphs of RD/PA history) — budget the most rewrite time there; it's also the highest-value fix since it's the first thing a reader sees.
- Phase 0 (guard): ~half a day — small, self-contained, unblocks everything and makes progress measurable.
- Phases 1–10 (cleanup): the bulk. ~193 files, but highly regular per the checklist; the
@exampleauthoring is the real cost (~200 examples). Parallelized across subagents by subsystem, this is a small number of focused passes rather than one monolithic slog. - Sequencing: Phase 0 must land first (it's the gate). Phases 1–10 can then run in parallel; merge order doesn't matter because each is independently green.
This is the single highest-leverage initiative from the DX assessment (DX-ASSESSMENT.md):
- Docs / discoverability dimension: 3 → ~8.
- Overall framework DX: ~6.0 → ~7.0–7.3 from this initiative alone.
- Agent-assisted development: the largest practical win — clean, example-first, jargon-free JSDoc lets an AI agent (or a new human) write correct code on the first try instead of spelunking source.
- Zero rendered glyphs and zero architecture touched — pure documentation + comment work, gated by a mechanical guard that keeps it from ever rotting back.