Skip to content

t1k:cocos:base:doc-flywheel

FieldValue
Modulebase
Version3.3.2
Effortmedium
Tools—

Keywords: annotate, discoverability, doc-comment, documentation-flywheel, hybrid-search, lexical-search, rag, summary-quality, tsdoc

/t1k:cocos:base:doc-flywheel
[audit|author|annotate|verify] <src-dir> [--dry-run]

Documentation Flywheel (RAG discoverability)

Section titled “Documentation Flywheel (RAG discoverability)”

Make this project’s own TypeScript findable by hybrid lexical + vector search (doc_search), so t1k-cocos-playable-modularize-reuse-scan — yours and every future project’s — classifies a subsystem REUSE instead of rebuilding it.

Three-way ownership — do not collapse these.

  • rules/code-quality-cocos.md (auto-loaded, binding) owns WHEN: “annotation moves with the code” — any symbol you add or whose signature you change carries its TSDoc in the same change.
  • t1k-cocos-base-script-graph owns the TOOLING: docs-ts.cjs, the extractor, cref grammar, the doc-XML envelope.
  • This skill owns the QUALITY BAR and the VERIFY LOOP — what makes prose retrievable, and proving via MCP that it actually is. It calls those scripts; it never copies or reimplements them.

The rule tells you to annotate. This skill tells you whether what you wrote was worth writing.

IntentPath
”How documented are we?” (read-only, no trigger needed)Step 1 — docs-ts.cjs audit
”Write the summaries”Step 2 + references/quality-rubric.md
”Write them into the source”Step 3 — annotate, clean tree + --dry-run first
”doc_search can’t find my subsystem”Step 6-7 — verify via MCP, not local audit
”Which code deserves this at all?”Scope rule
”Is this package mine to annotate?”Scope rule — owner-resolution table

The kit has no skill→skill dependency mechanism (install.json requires covers CLI tools only; module.json dependencies is module-level). So state it and fail loudly:

  • t1k-cocos-base-script-graph must be present — this skill invokes its scripts/docs-ts.cjs. Both ship in module base (required: true), so absence means a broken install, not a normal state.
  • ts-morph must be installed in the TARGET repo (npm i --save-dev ts-morph) — it resolves from the target repo and cwd, not from the skill directory.

Missing either → error and stop. Never report “0 undocumented symbols” when the tool never ran.

Scope rule — annotate what this repo owns, skip what another repo owns

Section titled “Scope rule — annotate what this repo owns, skip what another repo owns”

The boundary is ownership, not reusability. Annotate the code whose only home is this repo; skip the code that is a copy of something maintained elsewhere.

Annotate assets/scripts/ — all of it, game-specific included. A studio ships many playables that rehearse the same mechanics, so a rhythm project’s ChartParser, Conductor, or JudgeService is exactly what the next rhythm playable should find instead of rewriting. Game code that is genuinely single-use still earns its summary here: this repo is its only home, so if it is not annotated here it is annotated nowhere, and the corpus is what makes it discoverable at all.

Skip vendored assets/packages/@playablelabs/*. A package you already consume is a separate repo / module with its own release pipeline, and what sits in your project is a copy synced from playableSync. Two consequences, both fatal to annotating it here:

  • The work is destroyed. The next sync overwrites the copy; your TSDoc goes with it.
  • The corpus gets duplicates. The same subsystem, ingested once per consumer project that vendored it, at whatever version each happened to have — so doc_search returns N stale copies and no authoritative one.

Package annotation belongs in the package’s own repo, ingested once from there. That is what keeps a single authoritative entry per subsystem. If a package’s coverage is bad, the fix is a PR on that package — not a local sweep. (There is no correct local edit to a vendored package: t1k-cocos-playable-modularize-contribute’s UPDATE mode authors its change in the package’s upstream source repo, precisely because the vendored copy is deleted on the next sync and is published output rather than source.)

The path is a proxy; ownership is the test. A package contribute ADD just created sits under assets/packages/@playablelabs/<name>/ but has no upstream release and is not in playableSync yet — this repo is its source of truth, so it is in scope. Resolve the case by asking who owns it, never by matching the directory:

Subsystem under assets/packages/@playablelabs/<name>/OwnerAction
Listed in playableSync, or has an upstream releaseThe package repoSkip — PR the coverage fix upstream
Just created by contribute ADD; no upstream release yetThis repoAnnotate — you are authoring the authoritative copy

Annotating a new package is the highest-value moment in the whole flywheel: it is about to enter the corpus as the entry for that subsystem. Publishing it at 0% coverage fails every downstream reuse-scan’s summary_quality: high gate, so the next project rebuilds what you just packaged — precisely the outcome this skill exists to prevent.

Cheapest ordering: annotate before extracting. Do it while the code is still in assets/scripts; contribute ADD copies source as-is, so the TSDoc travels into the package and this ambiguity never arises.

Do not use t1k-cocos-base-code-conventions § “Reusable Framework vs Game-Specific Code” as the scope test here. That section governs naming — whether a name may carry a game token. It is a different question from which code earns a corpus summary, and reading it as the scope boundary is what produced the earlier framework-only rule.

Terminal window
# 1. FIND GAPS — read-only, writes nothing to the project
node <script-graph>/scripts/docs-ts.cjs audit <src> --json cov.json --by file --top 30
# → worstUndocumented[] = [{cref, file, line, module}] ← this IS the worklist
# 2. AUTHOR the override map (AI reads source, writes intent prose)
# { "<cref>": { summary, params?, returns?, remarks? } }
# Quality bar is the whole point → references/quality-rubric.md
# 3. WRITE INTO SOURCE — clean git tree, dry-run first
node <script-graph>/scripts/docs-ts.cjs annotate <src> overrides.json --dry-run
node <script-graph>/scripts/docs-ts.cjs annotate <src> overrides.json
# 4. EXPORT doc-XML — comment mode, NEVER derive (see the trap below)
node <script-graph>/scripts/docs-ts.cjs export <src> docs-ts-out \
--format both --layout split --summaries comment --documented-only
# 5. INGEST -- external + automatic, NOT fed by step 4's export. See "Ingest (step 5)" below.
# 6-7. VERIFY via MCP (NOT via local audit)
# doc_list_assemblies() → summary-quality distribution shifted toward `high`?
# doc_search({ query: "<behaviour in natural language>", assembly_prefix: "<module>" })
# → your member returns with summary_quality "high" and similarity ≳ 0.65?
# If not → the summary is not good enough. Back to step 2.

assembly = a top-level directory under assets/scripts/. Member ids are <assembly>#<kind>:<full-name>, kinds T/M/P/E/F.

The --summaries derive trap (read before using it)

Section titled “The --summaries derive trap (read before using it)”

derive synthesizes each summary from the AST signature. Its real output:

Class `ObjectPoolManager` extending `Component`.
Public method `spawn(key: string, parent: Node): Node`.

Pure signature restatement — zero behaviour, zero side-effect, nothing for an embedding to bite on. It is the mechanized form of “Gets or sets the value.”

Worse: in derive mode --documented-only becomes a no-op (derive documents everything). So every symbol passes the “has a doc” gate while carrying no semantic value — and you lose the needs-summary signal that told you where to work.

Use derive only for reading local code with stale/non-English comments. Never for the corpus path.

  • audit measures presence, not usefulness. A /** */ containing “TODO” counts as documented. 100% local coverage is NOT evidence of RAG quality — doc_list_assemblies’ high/low/missing distribution is the authority. Treating audit as the self-check is the core failure mode here.
  • annotate rewrites source IN PLACE. Git is the only backup. Clean tree + --dry-run first. Default skips already-documented symbols; --force REPLACES (removes the old block, does not append) — hand-written prose is lost.
  • annotate does NOT touch .meta. It only edits existing .ts content — no create, rename, or move — so Cocos UUIDs stay stable and scene/prefab refs are safe. This is why it needs none of t1k-cocos-playable-modularize’s branch+gate ceremony. Do not “helpfully” reorganize files during an annotate pass.
  • annotate writes LF. On a CRLF checkout the touched files go mixed-EOL until git normalizes. Cosmetic, but it inflates the diff — check .gitattributes before a large pass.
  • cref uses WRITTEN type nodes, not the checker. A param with no type annotation becomes any in the cref, so your override key silently will not match. Annotate public-API types first.
  • doc_search corpus is mostly .NET noise. ~435 TheOne.* Unity/.NET assemblies dominate. A hit is only meaningful when its assembly is a Cocos foundation subsystem — a TheOne.Features.* hit at high similarity is noise. Constrain with assembly_prefix, but remember it is exact-segment: use the exact full assembly name, and mix one lowercase word into every query (all-caps queries return confident junk).
  • Bad summaries silently corrupt reuse-scan. Its REUSE rule needs similarity ≳ 0.65 AND summary_quality: high. Fail either and the subsystem is misclassified CONTRIBUTE — you rebuild something that already exists. That is the real cost of a lazy summary.
  • Do not bulk-sweep a whole project. Annotate the unit you are touching, or the subsystem you are about to publish. A 500-symbol sweep produces 500 mediocre summaries and one unreviewable diff.
  • Annotating a vendored @playablelabs/* copy silently throws the work away. The folder is git-tracked in the consumer repo, so the diff looks perfectly normal and the commit lands clean — then the next playableSync overwrites it. Nothing errors; the TSDoc is just gone. Resolve ownership before authoring, not after.
  • Do not read the skip as “anything under assets/packages/”. A package contribute ADD just created lives there too, and it is in scope — skipping it publishes a 0%-coverage package that fails every downstream reuse-scan. Check playableSync / upstream existence, not the path.

Ingest (step 5) — external and automatic, not a step you run

Section titled “Ingest (step 5) — external and automatic, not a step you run”

Ingest is owned by The1Studio/AIPoweredGameDevelopmentSystem (private), not by this kit. Its indexer polls on a roughly 5-minute cadence, re-clones enrolled repos, and re-exports from source itself using its own exporter — it does not consume this repo’s docs-ts-out/ output, so there is no “push” action for you to perform. Enrollment is by GitHub topic (theone-docs + cocos), not by anything in this repo’s tree. Full mechanism, the verification date, and what remains unverified (indexer uptime, credential reach into private repos): references/flywheel-lifecycle.md § “Step 5”.

FileContent
references/quality-rubric.mdThe quality bar + good/bad examples + override-map shape
references/flywheel-lifecycle.mdFull 7-step detail, MCP verify contract, corpus facts
rules/code-quality-cocos.mdOwns WHEN — binding, auto-loaded: “annotation moves with the code”, no deferred docs pass
t1k-cocos-base-script-graphOwns the tooling — docs-ts.cjs, extractor, cref grammar, doc-XML
t1k-cocos-playable-modularize-reuse-scanDownstream consumer — its REUSE signal depends on this skill’s output quality
t1k-cocos-playable-modularize-contributeUPDATE mode — the only sanctioned path for changing a vendored @playablelabs/* copy
t1k-cocos-base-code-conventions§ Reusable Framework vs Game-Specific — a naming rule; explicitly NOT this skill’s scope test