t1k:cocos:base:doc-flywheel
| Field | Value |
|---|---|
| Module | base |
| Version | 3.3.2 |
| Effort | medium |
| Tools | — |
Keywords: annotate, discoverability, doc-comment, documentation-flywheel, hybrid-search, lexical-search, rag, summary-quality, tsdoc
How to invoke
Section titled “How to invoke”/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-graphowns 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.
Decision Tree
Section titled “Decision Tree”| Intent | Path |
|---|---|
| ”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 |
Hard precondition
Section titled “Hard precondition”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-graphmust be present — this skill invokes itsscripts/docs-ts.cjs. Both ship in modulebase(required: true), so absence means a broken install, not a normal state.ts-morphmust 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_searchreturns 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>/ | Owner | Action |
|---|---|---|
Listed in playableSync, or has an upstream release | The package repo | Skip — PR the coverage fix upstream |
Just created by contribute ADD; no upstream release yet | This repo | Annotate — 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.
Lifecycle
Section titled “Lifecycle”# 1. FIND GAPS — read-only, writes nothing to the projectnode <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 firstnode <script-graph>/scripts/docs-ts.cjs annotate <src> overrides.json --dry-runnode <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.
Gotchas
Section titled “Gotchas”auditmeasures presence, not usefulness. A/** */containing “TODO” counts as documented. 100% local coverage is NOT evidence of RAG quality —doc_list_assemblies’high/low/missingdistribution is the authority. Treatingauditas the self-check is the core failure mode here.annotaterewrites source IN PLACE. Git is the only backup. Clean tree +--dry-runfirst. Default skips already-documented symbols;--forceREPLACES (removes the old block, does not append) — hand-written prose is lost.annotatedoes NOT touch.meta. It only edits existing.tscontent — no create, rename, or move — so Cocos UUIDs stay stable and scene/prefab refs are safe. This is why it needs none oft1k-cocos-playable-modularize’s branch+gate ceremony. Do not “helpfully” reorganize files during an annotate pass.annotatewrites LF. On a CRLF checkout the touched files go mixed-EOL until git normalizes. Cosmetic, but it inflates the diff — check.gitattributesbefore a large pass.- cref uses WRITTEN type nodes, not the checker. A param with no type annotation becomes
anyin the cref, so your override key silently will not match. Annotate public-API types first. doc_searchcorpus is mostly .NET noise. ~435TheOne.*Unity/.NET assemblies dominate. A hit is only meaningful when itsassemblyis a Cocos foundation subsystem — aTheOne.Features.*hit at high similarity is noise. Constrain withassembly_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 needssimilarity ≳ 0.65ANDsummary_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 nextplayableSyncoverwrites 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 packagecontributeADD just created lives there too, and it is in scope — skipping it publishes a 0%-coverage package that fails every downstreamreuse-scan. CheckplayableSync/ 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”.
References
Section titled “References”| File | Content |
|---|---|
references/quality-rubric.md | The quality bar + good/bad examples + override-map shape |
references/flywheel-lifecycle.md | Full 7-step detail, MCP verify contract, corpus facts |
rules/code-quality-cocos.md | Owns WHEN — binding, auto-loaded: “annotation moves with the code”, no deferred docs pass |
t1k-cocos-base-script-graph | Owns the tooling — docs-ts.cjs, extractor, cref grammar, doc-XML |
t1k-cocos-playable-modularize-reuse-scan | Downstream consumer — its REUSE signal depends on this skill’s output quality |
t1k-cocos-playable-modularize-contribute | UPDATE 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 |