Skip to content

docs: exports pushed via this.exports.push() at runtime get no generated doc entries (scrabble: all 4; midi: SHARP/FLAT/NATURAL) #817

Description

@Shrey5132

What's broken

Any Conductor-migrated module that hands data back by calling this.exports.push(...) directly (in the constructor or initialise()) instead of exposing it through an exportedNames-listed @moduleMethod gets zero generated doc entries for that data — not "No description available", entirely absent from the output.

Two confirmed live cases, built directly against origin/conductor-migration @ 961f6414e (2026-07-24):

  • scrabble (src/bundles/scrabble/src/index.ts, merged via Migrate scrabble module to Conductor #792): exportedNames is [] as const since none of its 4 exports (scrabble_words, scrabble_letters, scrabble_words_tiny, scrabble_letters_tiny) are @moduleMethod closures — they're plain arrays built in initialise() and pushed onto this.exports.

    $ node lib/buildtools/dist/index.js build docs src/bundles/scrabble
    docs written to .../build/jsons/scrabble.json
    $ cat build/jsons/scrabble.json
    {}
    

    Empty. None of the 4 exports appear anywhere in the output.

  • midi (merged via Migrate midi module to Conductor #791, including 6207fde's JSDoc pass): SHARP/FLAT/NATURAL are pushed the same runtime way from the constructor and aren't in exportedNames. 6207fde's own commit message verifies "all 19 exports now show real descriptions" — 19 is exactly exportedNames.length, so those 3 constants were never part of that count:

    $ node lib/buildtools/dist/index.js build docs src/bundles/midi
    $ python3 -c "import json; d=json.load(open('build/jsons/midi.json')); print(len(d), 'SHARP' in d)"
    19 False
    

Root cause

lib/buildtools/src/build/docs/conductor/normalisation.ts's normalizeContainer only touches classes that pass isConductorPluginClass() (conductor/utils.ts:85-92), which requires a non-empty exportedNames. For a class that passes, promotePluginMethods (utils.ts:267-286) promotes only the Method-kind children listed in exportedNames (no path for anything else), and only then is the class itself removed from the doc tree (normalisation.ts:151-157).

  • scrabble's class never passes isConductorPluginClass at all (empty exportedNames), so it's never promoted and never removed — it just falls through lib/typedoc-plugin/src/json.ts's parsers table (only handles Function/Variable) with no entries surviving.
  • midi's class does pass (19 real @moduleMethod exports), so it IS removed — taking SHARP/FLAT/NATURAL down with it, since they were never promoted in the first place (not methods, not in exportedNames).

Either way, this.exports.push(...) calls inside a method body are invisible to TypeDoc, which reflects declarations, not statements/arguments inside a function or constructor body. There's currently no convention for attaching a doc comment to one of these pushed exports that any part of the pipeline reads — so no amount of JSDoc placement fixes it as-is.

Why this matters going forward

Team direction (from the scrabble/midi Slack thread on the OPAQUE-vs-array question) is that data-only modules should hand back plain arrays rather than OPAQUE-wrapped objects. That means more modules will look like scrabble — all-data exports, empty exportedNames — going forward, all silently undocumented under the current pipeline as it stands.

Possible directions (not proposing one yet)

  • Extend isConductorPluginClass/promotePluginMethods to also recognize a declared list of data-export names (parallel to exportedNames) plus a place to hang JSDoc on each one (e.g. a static field per export, or a comment block keyed by symbol name).
  • Have BaseModulePlugin expose data exports as real class properties/getters (TypeDoc already reflects properties) instead of imperative this.exports.push(...) calls, so existing declaration-based reflection just works unmodified.
  • Something else — raising this now, before more data-only modules land, rather than guessing at the right convention unilaterally.

Repro

git worktree add /tmp/cm-check origin/conductor-migration
cd /tmp/cm-check && yarn install
node lib/buildtools/dist/index.js build docs src/bundles/scrabble
cat build/jsons/scrabble.json   # {}
node lib/buildtools/dist/index.js build docs src/bundles/midi
python3 -c "import json; print('SHARP' in json.load(open('build/jsons/midi.json')))"   # False

Raised while checking whether scrabble (#782, merged via #792) needed the same JSDoc fix as midi's 6207fde (#791) — it doesn't; this is a different, cross-cutting gap in the shared doc-build tooling, not a per-module JSDoc issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions