t1k:cocos:base:doc-pass
| Field | Value |
|---|---|
| Module | base |
| Version | 3.3.2 |
| Effort | medium |
| Tools | — |
Keywords: annotate, audit, coverage, doc-flywheel, doc-pass, documentation, one-shot-docs, rag, script-graph, tsdoc
How to invoke
Section titled “How to invoke”/t1k:cocos:base:doc-pass<src-dir> [--work-dir <path>] [--dry-run] [--force] [--top N]Documentation Pass (script-graph + doc-flywheel, one call)
Section titled “Documentation Pass (script-graph + doc-flywheel, one call)”Runs the whole TSDoc chain end-to-end so you call one skill instead of bouncing between
t1k:cocos:base:script-graph (tooling) and t1k:cocos:base:doc-flywheel (quality bar + verify).
preflight → 1 audit → 2 author → 3 annotate → 4 export → [5 ingest: GAP] → 6-7 verify └─ SG ─┘ └─ DF ──┘ └─ SG ───┘ └─ SG ─┘ └─ DF ─┘This skill owns SEQUENCING ONLY. It adds no tooling and no rubric of its own.
t1k-cocos-base-script-graphstays the SSOT fordocs-ts.cjs, cref grammar, doc-XML envelope.t1k-cocos-base-doc-flywheelstays the SSOT for the prose quality bar and the MCP verify contract.rules/code-quality-cocos.mdstays the SSOT for when annotation is obligatory.If a command or a rubric line here ever disagrees with those, they win — fix this file.
When NOT to use this skill
Section titled “When NOT to use this skill”| Situation | Use instead |
|---|---|
| Just want the coverage number | docs-ts.cjs audit directly — read-only, one command, no chain needed |
Annotating the one unit you just changed (the code-quality-cocos.md obligation) | Annotate inline, in the same change. This skill is a deliberate pass, not the per-change habit |
The cocos-doc-drift-stop hook fired with a filtered gap list | t1k-cocos-doc-updater agent — it is already scoped to the changed files; this skill would widen the scope |
| Need classes / modules / scenes / prefabs diagrams | t1k:cocos:base:script-graph — this skill covers the docs branch only |
Hard preconditions — fail loudly, never report “0 gaps”
Section titled “Hard preconditions — fail loudly, never report “0 gaps””The kit has no skill→skill dependency mechanism, so check these yourself and stop on any miss:
t1k-cocos-base-script-graphpresent — this skill invokes itsscripts/docs-ts.cjs. Both ship in modulebase, so absence is a broken install, not a normal state.ts-morphinstalled in the TARGET repo (npm i --save-dev ts-morph). It resolves from the source dir first, then cwd — not from the skill dir — so a Cocos project living in a repo subdirectory with its ownpackage.json+node_modulesis fully supported, and needs noNODE_PATHworkaround. Without itgenerate.cjs --type docsemits a graceful stub withcapabilities_skipped: ["docs"]— do not read that stub as “no gaps”.mcp__knowledge-retrieval__doc_searchloaded — required only for step 6-7. Absent → say so and skip verify; never report “not found in the corpus” when the tool never ran.
scripts/doc-pass.cjs preflight checks 1, 2 and the git state in one shot.
Scope gate — run BEFORE step 1, on the src-dir you are about to pass
Section titled “Scope gate — run BEFORE step 1, on the src-dir you are about to pass”The boundary is ownership, not reusability. Full reasoning:
t1k-cocos-base-doc-flywheel/SKILL.md § Scope rule.
| Target | Verdict |
|---|---|
assets/scripts/ — all of it, game-specific included | In scope. This repo is its only home |
assets/packages/@playablelabs/<n> listed in playableSync or with an upstream release | Skip. The next sync silently deletes your TSDoc; PR the coverage fix upstream |
assets/packages/@playablelabs/<n> just created by contribute ADD, no upstream release | In scope. This repo is its source of truth, and publishing at 0% coverage fails every downstream reuse-scan |
The path is a proxy — check playableSync / upstream existence, not the directory.
Run it
Section titled “Run it”Three-phase invocation (preflight → author overrides.json by hand → finish): exact commands and
per-line output meaning in references/usage-examples.md.
Flags: --dry-run (force report-only), --force (replace existing TSDoc — destructive, see gotchas),
--top N (worklist size, default 30), --skip-annotate, --skip-export, --work-dir <path>,
--no-commit (skip the auto-commit below).
The work dir lives OUTSIDE the project
Section titled “The work dir lives OUTSIDE the project”coverage.json and overrides.json are scratch between Phase A and Phase C. The deliverables are
the annotated source and docs-ts-out/ — never these two. So they default to
a t1k-doc-pass/<project-slug>/ directory under the OS temp dir, not into the repo.
This is deliberate. Writing scratch into the project puts it in every consumer’s git status, and
“solving” that by appending to their .gitignore is worse — a tool has no business mutating repo
config to hide its own litter, and doing so dirties the tree, which is exactly what makes the
documented preflight → author → finish sequence self-block on the annotate gate.
Pass --work-dir .doc-pass if you genuinely want the override map project-local (hand-editing it, or
reviewing a large pass across sessions). The script then warns that it will show in git status
and leaves .gitignore alone — ignoring it is your call, not the tool’s.
Write policy (chosen for this install)
Section titled “Write policy (chosen for this install)”finish writes without asking when git status --porcelain -- <src-dir> is empty. Git is the
only backup, so committed source is the safety property that makes silent writing acceptable.
- Source dir dirty → the script refuses to write TSDoc and runs annotate
--dry-runinstead, printing the diff summary and telling you to commit or stash. It never partially applies. - Not a git repo → same refusal. No backup means no auto-write.
The check is scoped to <src-dir>, not the whole repo — deliberately. The gate asks “are the
files annotate is about to overwrite committed?”, and a repo-wide check answers a different, wrong
question. Two concrete failures a repo-wide check causes: unrelated staged work in another subtree
blocks a legitimate pass, and preflight’s own .gitignore write dirties the tree so the documented
preflight → author → finish sequence self-blocks every time on a clean repo.
The gate covers annotate ONLY. export reads source and writes docs-ts-out/ at the repo root —
it mutates nothing, so a dirty tree never blocks it. Exit code is 1 when TSDoc writes were skipped,
even though the export succeeded.
Likewise, an empty or absent overrides map is not a failure — it means the audit found nothing to
write. finish says so and proceeds to export. Gating the deliverable on there being annotation work
is how a 100%-coverage project ends a “documentation pass” with no documentation files.
finish commits its own output — do not ask
Section titled “finish commits its own output — do not ask”After a successful export, finish stages and commits the annotated source and docs-ts-out/
automatically, with no confirmation prompt. Do NOT stop to ask the user whether to commit, whether
to track the export tree, or whether to gitignore it — that question is answered here, once, for
every run.
The write gate above already established that <src-dir> was committed before annotate touched it,
so everything dirty afterwards is this pass’s own output. Leaving it uncommitted is what turns a
finished pass into work parked where nobody is looking.
- Scoped by pathspec, never
git add -A. Only<src-dir>and the export tree are staged; a consumer’s unrelated dirty files stay pending and out of the commit. - Message:
docs(docs): annotate <src> TSDoc and export doc corpus, with the block count in the body.docsis an allow-listed scope (commit-scope-policy.md). - Never on a refused write. A dirty source dir means the export no longer matches the source;
committing that would record a half-applied pass. Nothing is committed, exit stays
1. - Never on
--dry-run, and skippable with--no-commit/T1K_DOC_PASS_NO_COMMIT=1. - Commits only — never pushes, never branches. Branch choice and push stay the caller’s.
Authoring (Phase B) — the only part no script can do
Section titled “Authoring (Phase B) — the only part no script can do”Behaviour + intent + side-effect. 1-2 sentences. Plain text. English.
That one line is the entire bar. The calibrated good/bad pairs, the override-map shape, and the
4-point self-check live in t1k-cocos-base-doc-flywheel/references/quality-rubric.md — read it
before authoring; it is the SSOT and is deliberately not duplicated here.
Map shape, keyed by cref:
{ "M:CurrencyService.claim(number)": { "summary": "Grants the milestone reward and fires OnMilestoneClaimed, resetting the currency balance to zero.", "params": { "milestoneId": "Index of the milestone being claimed" }, "returns": "Amount granted, or -1 when the milestone was already claimed" }}Only summary / params / returns / remarks are ever written.
Verify (steps 6-7) — MCP, not local audit
Section titled “Verify (steps 6-7) — MCP, not local audit”doc_list_assemblies() → did your assembly's summary-quality distribution shift toward `high`?doc_search({ query: "<behaviour as a PROBLEM statement>", assembly_prefix: "<module>" }) → pass = summary_quality "high" AND similarity ≳ 0.65. Below that → back to Phase B.Step 5 (ingest) is an unresolved gap — nothing documents pushing docs-ts-out/ into the corpus at
mcp.the1studio.org. Phases A–C stand alone and are worth running regardless, but a step-6/7 miss
while this gap stands is a pipeline failure, not a prose failure. Confirm with infra owners before
rewriting good summaries.
Gotchas
Section titled “Gotchas”Inherited from the two source skills; the ones that bite this chain specifically:
auditmeasures presence, not usefulness. A/** */containing “TODO” counts as documented. 100% local coverage is not evidence of RAG quality —doc_list_assembliesis the authority. Treating the Phase A number as the self-check is the core failure mode of this whole flow.- Never use
--summaries deriveon the corpus path. It restates the signature, and in derive mode--documented-onlybecomes a no-op — every symbol passes the “has a doc” gate carrying zero semantic value, and theneeds-summarysignal that told you where to work is destroyed. --forceREPLACES, it does not append. It removes the existing block first, so hand-written prose is lost. Default (skip already-documented) is correct almost always.- Do not bulk-sweep a whole project in one pass. 500 symbols → 500 mediocre summaries and one
unreviewable diff. Scope
<src-dir>to a subsystem;--topbounds the worklist, not the write. - cref uses WRITTEN type nodes, not the checker. An un-annotated param becomes
anyin the cref, so an override key written against the annotated form silently lands inmissing[]— it warns, it does not error. Annotate public-API types before authoring. annotatenever touches.meta. It only edits existing.tscontent — no create/rename/move — so Cocos UUIDs and scene/prefab refs stay stable. That is why this flow needs none oft1k-cocos-playable-modularize’s branch+gate ceremony. Do not “helpfully” reorganize files mid-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.- Neither export entry point defaults to split layout. The
docs-ts-out/{xml,json}tree requires--format both --layout splitexplicitly. Omitting it succeeds and writes a flat XML-only tree — a wrong-shape result, not an error.doc-pass.cjs finishpasses them for you; a hand-run does not. audit’s exit code is swallowed by a pipe.… --min-coverage 80 | tailreportstail’s status. UsePIPESTATUS[0], or don’t pipe when gating.doc_searchcorpus is ~87% .NET noise. A high-similarityTheOne.Features.*hit is irrelevant to a Cocos playable. Constrain withassembly_prefix— it is exact-segment, so use the exact full assembly name, and keep one lowercase word in the query (all-caps queries return junk).- 100% coverage does not mean “pass complete” — the export is still the deliverable. A project
that already annotates as it codes produces an empty Phase B worklist, and it is tempting to stop
there. Stopping leaves no
docs-ts-out/at all. Always runfinish(overrides optional). - The work dir is scratch, not a deliverable. It defaults outside the repo for that reason. If
you move it in with
--work-dir, ignoring it is your job — the script will not touch.gitignore. docs-ts-out/IS tracked — do not gitignore it, and do not ask whether to. It is the corpus payload, and until the step-5 ingest gap is closed, the repo is the only place anyone can see it.finishcommits it for you; a session that stops to ask has already got the answer wrong.
References
Section titled “References”| File | Content |
|---|---|
t1k-cocos-base-script-graph | SSOT — tooling: docs-ts.cjs, extractor, cref grammar, doc-XML |
t1k-cocos-base-doc-flywheel | SSOT — quality bar + verify: rubric, scope rule, MCP contract |
…/doc-flywheel/references/quality-rubric.md | The prose bar, calibrated examples, self-check |
…/doc-flywheel/references/flywheel-lifecycle.md | 7-step detail, corpus facts, safety table |
rules/code-quality-cocos.md | SSOT — when: “annotation moves with the code” |
t1k-cocos-doc-updater (agent) | The per-change path; this skill is the deliberate-pass path |