Skip to content

t1k:cocos:base:script-graph

FieldValue
Modulebase
Version3.3.2
Effortmedium
Tools—

Keywords: class-diagram, code-index, dependency-cruiser, doc-comments, doc-xml, docs, documentation, prefab, scene, script-graph, tsdoc

/t1k:cocos:base:script-graph

Cocos Creator 3.x diagram adapter and TypeScript documentation generator for the T1K toolchain.

Scope — generation and reporting, not authoring. This skill extracts documentation from source and reports on its coverage. Deciding what to annotate and writing it is a refactor-phase obligation, owned by the auto-loaded rule rules/code-quality-cocos.md and executed per-unit by t1k-cocos-playable-modularize-refactor (Tier 2.5). The quality bar for that prose and its RAG-discoverability verification are owned by t1k-cocos-base-doc-flywheel. The annotate command still ships here — it is the tool those phases call — but this skill does not own the when or what. Do not run a bulk annotate sweep as a standalone docs task; annotate alongside the code change that needs it.

Produces five outputs from Cocos project sources:

  1. classes — @ccclass-decorated class diagram via ts-morph (inheritance + @property cross-refs)
  2. modules — TypeScript module import graph via dependency-cruiser
  3. scenes — Scene node hierarchy from assets/**/*.scene JSON via a custom JSON walker
  4. prefabs — Prefab component tree from assets/**/*.prefab JSON via the same walker
  5. docs — TSDoc doc-comment extraction into per-module doc-XML via ts-morph — the TypeScript analog of C#‘s <GenerateDocumentationFile> output (see Documentation extraction)

Install the full Cocos toolchain:

t1k diagram install --preset cocos

Per-project tools (ts-morph, dependency-cruiser) are recorded as npm i --save-dev hints — version locks stay aligned with the project’s TypeScript version.

Global tools (mermaid-cli, graphviz) render Mermaid diagrams into images.

Invoked with no arguments, generate the docs. Run the canonical docs command below from the Cocos project dir, then report the coverage audit. Do NOT reach for generate.cjs --type docs for that — see the entry-point table.

This is the one that produces the docs-ts-out/{xml,json} tree:

Terminal window
node scripts/docs-ts.cjs export assets/scripts --format both --layout split

Omit the out-dir so output lands at the OUTERMOST repo root. Then audit coverage:

Terminal window
node scripts/docs-ts.cjs audit assets/scripts

Two entry points reach the same extractor but default differently (docs-ts.cjs export vs generate.cjs --type docs) — full comparison table, every diagram-type invocation, and the diagnostic commands (detect.cjs, list-capabilities.cjs, requirements.cjs): references/usage-examples.md.

CapabilityOutput
classesclasses.md — Mermaid classDiagram of @ccclass components
modulesmodules.md — Mermaid graph from dependency-cruiser --output-type mermaid
scenesscenes.md — Mermaid flowchart TD of scene node hierarchy (one section per .scene file)
prefabsprefabs.md — Mermaid flowchart TD of prefab component tree (one section per .prefab file)
docs<module>.xml (one per top-level assets/scripts/ dir) in the C#-compiler doc-XML envelope, plus docs.md index

The read-only counterpart to annotate. buildModel already flags every undocumented member needs-summary="true", so the audit just aggregates that in memory — it writes nothing to the project and never needs a refactor to run.

Terminal window
node scripts/docs-ts.cjs audit assets/scripts # per-module coverage table
node scripts/docs-ts.cjs audit assets/scripts --by file --top 20 # worst files + 20 worst symbols
node scripts/docs-ts.cjs audit assets/scripts --json cov.json # machine-readable report
node scripts/docs-ts.cjs audit assets/scripts --min-coverage 80 # soft gate: exit 1 if under

Rows sort worst coverage first. --json emits {total, documented, missing, coverage, pass, groups[], worstUndocumented[]} — worstUndocumented carries {cref, file, line, module} so it doubles as a worklist for an annotate overrides map.

Exit codes: 0 normally; 1 only when --min-coverage is set and unmet. Absent that flag the audit never fails, so it is safe in any pipeline. When piping to head/tail, read PIPESTATUS[0] — the pipe’s exit status is the tail command’s, not the audit’s.

  • <<ccclass>> stereotype on every detected @ccclass class.
  • Inheritance edge: class X extends Y where Y is another @ccclass.
  • Composition edge: @property(...) field labeled with the field name, pointing at the referenced class when resolvable.
  • Scene/prefab nodes: hierarchy follows _children; component attachments come from _components[].
  • UUID cross-references in components: resolved to a readable path via a prebuilt UUID → file map when possible; otherwise the first 8 chars of the UUID are kept for traceability.

The docs capability is the TypeScript analog of C#‘s per-assembly doc-XML (what the C# compiler emits with <GenerateDocumentationFile>true). It walks every .ts under the project via ts-morph and emits one <module>.xml per top-level assets/scripts/ dir, in the identical envelope:

<?xml version="1.0"?>
<doc>
<assembly><name>gameplay</name></assembly>
<members>
<member name="M:BlockageDetector.scan(number,TileModel[])"
file="assets/scripts/gameplay/BlockageDetector.ts" line="88">
<summary>Scan forward from the tip…</summary>
<param name="arrowIndex">Index of the arrow being checked</param>
<returns>ScanResult with the blocked flag and blocker index</returns>
</member>
<member name="M:BlockageDetector.buildOccupancy(number[])"
file="assets/scripts/gameplay/BlockageDetector.ts" line="61" needs-summary="true">
<summary></summary>
</member>
</members>
</doc>

EVERY symbol is emitted (not just documented ones) — undocumented members get an empty <summary> and a needs-summary="true" flag instead of being dropped, so the tier-1 hybrid code-index keeps the full surface (30–60% of engine code is typically undocumented). Each <member> also carries file="…" + line="…" attributes (provenance + the tier-2 file:line link). Members sorted, 4-space indent; the “assembly” is the top-level script-folder name (Cocos has no .asmdef). Pass --documented-only for the legacy docs-xml.py parity (drop undocumented).

Summary source — --summaries:

  • comment (default) — copy the author’s TSDoc verbatim (preserves the author’s language).
  • derive — ignore the author comment and synthesize each summary from the CURRENT ts-morph signature (name, kind, params+types, return, extends/implements, @ccclass/@property, enum members, alias type). Deterministic, English, never stale — the fix when comments are outdated, wrong, or non-English.

Human-friendly summaries — apply: for out/out-style intent prose, an AI reads the source and writes concise summaries into an overrides map { "<cref>": { summary, params, returns } }; docs-ts.cjs apply <module.json> <overrides.json> merges them onto the structural model and re-renders (code merges, AI reasons — rules/ai-driven-design.md).

Self-document the source — annotate: the same override map, but written BACK INTO the .ts source as real /** */ TSDoc (above @ccclass/@property decorators), so a re-extract yields zero needs-summary. Skips already-documented symbols unless --force; --dry-run reports diffs without writing. This is the fill-the-gaps loop: export to find needs-summary crefs → AI authors the map → annotate writes them → export --layout split to regenerate. See Documentation extraction / references/docs-extraction.md. The full docs-ts.cjs / generate.cjs command surface (export/convert/apply/annotate flags) is in the Usage block above — not repeated here to avoid drift.

For docs as a deliverable use docs-ts.cjs export (see Which entry point?); generate.cjs --type docs serves the adapter contract. Both are supported entry points; the wider t1k diagram toolchain only invokes docs once it recognizes the 5th capability, so run it directly until then.

Full spec — cref-ID grammar (T:/M:/P:/F:), TSDoc→XML element mapping, the JSON↔XML model, grouping rules, and the docs-xml.py comparison: references/docs-extraction.md.

classes/modules still stub out until the Mermaid Layer A/C extractors land — the scene walker and docs extractor are the fully-implemented capabilities today. This adapter targets Cocos 3.x scene JSON only (2.x differs; detect.cjs gates on it). Full scope breakdown, JSON-size ceiling, and the other known limitations: references/scope-notes.md.

  • Cocos Creator class graphs depend on @ccclass decorator — utility scripts without @ccclass are skipped silently.
  • Component dependency graph != class graph — components reference each other through @property(Type), which is editor-only metadata. Use a separate parser pass for runtime deps.
  • Scene graph diagrams from .scene JSON are large — flat-collapse leaf transforms (Sprite, Label inside layout containers) before rendering.
  • Cocos 2.x is unsupported — detect.cjs only matches 3.x scene JSON; running against a 2.x project no-ops with a warning.
  • docs emits EVERY symbol, flagging undocumented ones — members with no TSDoc /** */ block are emitted with an empty <summary> + needs-summary="true" (the tier-1 hybrid index keeps the full surface). Pass --documented-only to drop them (legacy docs-xml.py parity). Two summary modes: --summaries comment (verbatim author text, default) and --summaries derive (AST-synthesized English, ignores stale/non-English comments). For human-readable intent prose, AI-author an overrides map and run docs-ts.cjs apply.
  • export without an out-dir writes to the OUTERMOST repo root — the default is <repo-root>/docs-ts-out, resolved via git rev-parse --show-toplevel then the --show-superproject-working-tree chain, so a Cocos project vendored as a submodule does NOT get generated docs dumped inside it. Falls back to an upward .git scan, then the source dir, when git is unavailable. Passing an explicit out-dir opts out — it resolves against the process cwd as before, so export . docs-ts-out run from inside a submodule still writes inside that submodule. Omit the argument unless you specifically want another location.
  • Neither docs entry point defaults to the split layout. docs-ts.cjs export and generate.cjs --type docs both default to --format xml --layout flat. The docs-ts-out/{xml,json} tree people expect requires --format both --layout split explicitly, on either one. Omitting it succeeds and writes a flat XML-only tree — a wrong-shape result, not an error, which is exactly how this gets missed.
  • file= is relative to the SCRIPTS ROOT, not to the src-dir you passed (since v1.22.0). file="UI/GameView.ts" regardless of whether you invoked with assets/scripts or the project root — so the two entry points now agree byte-for-byte, and file:line links survive a regeneration invoked from somewhere else. Behaviour change: before v1.22.0 relFile() anchored on the raw srcDir, so export <project-root> emitted assets/scripts/UI/GameView.ts. Anything that stored those paths needs a one-time regenerate.
  • docs needs per-project ts-morph — without it, generate.cjs --type docs emits a graceful stub with capabilities_skipped: ["docs"] (it does NOT hard-fail). Install with npm i --save-dev ts-morph. ts-morph is resolved from the target repo (and cwd), NOT from the skill’s own location — so you run the scripts in-place against any repo that has ts-morph installed; you do NOT install ts-morph next to the skill.
  • docs scans only under the scripts root — <src>/assets/scripts (or <src> when it has no such subtree). The repo’s node_modules/ and *.d.ts are auto-excluded, so a repo with hundreds of installed packages still yields only project members. Pointing --src at a single module dir scopes the scan to that dir.
  • docs cref uses written type nodes, not the type checker — param types are the annotated text (Vec3, TileModel[]), so inferred-only params fall back to any. Annotate public APIs (Cocos convention anyway).
  • docs grouping ≠ asset bundles — modules are top-level assets/scripts/ dirs, not Cocos asset-bundle roots. Bundle-aware grouping is a future enhancement.
  • audit is read-only; annotate is not. Reach for audit for any “how documented are we” question — it never touches the project. Only annotate writes. Confusing the two is how a reporting task becomes a source mutation.
  • audit exit code is swallowed by a pipe. docs-ts.cjs audit … --min-coverage 80 | tail reports tail’s status, so a failed gate looks green. Use PIPESTATUS[0], or don’t pipe when gating.
  • audit counts symbols, not quality. A /** */ block containing “TODO” counts as documented. It measures presence, not usefulness — do not treat 100% as “well documented” (--summaries derive exists precisely because comments go stale).
  • annotate rewrites source IN PLACE — it writes TSDoc into the real .ts files (up to N per run). Run on a clean git tree and/or --dry-run first; git is the only backup. Default skips already-documented symbols; --force overwrites existing TSDoc (removes the old block, not append). Only summary/@param/@returns/@remarks are written — never @throws/@example/@deprecated/@stability.
  • annotate writes LF line-endings — ts-morph inserts \n, so on a CRLF repo the touched files become mixed-EOL until git normalizes them (.gitattributes / core.autocrlf). Cosmetic; the diff stays additive.
FileContent
references/scene-prefab-walker.mdJSON shape notes for Cocos Creator 3.x + walker algorithm (~50 LOC)
references/ts-morph-ccclass.md@ccclass decorator extraction spec
references/dependency-cruiser-config.mdCustom rule snippets for Cocos project layout
references/docs-extraction.mddocs capability: cref grammar, TSDoc→XML mapping, JSON↔XML, vs docs-xml.py
rules/code-quality-cocos.mdOwns the annotation obligation — when/what to annotate. This skill owns the tooling only.
t1k-cocos-base-doc-flywheelOwns the annotation quality bar — behaviour+intent+side-effect prose, the --summaries derive trap, and MCP verification that the result is actually discoverable.