t1k:cocos:base:system-design
| Field | Value |
|---|---|
| Module | base |
| Version | 3.3.2 |
| Effort | low |
| Tools | — |
Keywords: as-is, converged, design-doc, design-manifest, doc-contract, generate-manifest, migrate-design-doc, module-map, module-table, system-design, to-be, verify-manifest
How to invoke
Section titled “How to invoke”/t1k:cocos:base:system-design[generate|verify|migrate] <path> [--out <path>] [--apply]Cocos System-Design Artifact
Section titled “Cocos System-Design Artifact”Owns docs/system-design.md as a machine-checkable artifact: its blank, its module-table
contract, and the scripts that read, verify, and migrate it.
This skill owns the ARTIFACT, not the architecture. Architecture doctrine — SOLID, module boundaries, mandatory class roles, anti-patterns — lives inside
docs/system-design.mditself (§ “Code Structure Rules (Mandatory)”). When a pattern becomes mandatory, and whether a codebase conforms, belong tot1k-cocos-base-architecture-patterns, which reads this artifact and never writes it. Keeping the two apart is the point: a skill that both defines the target and grades against it can never report that the target is wrong.
This skill does not author your doc
Section titled “This skill does not author your doc”Producing docs/system-design.md is distributed on purpose, because the producers genuinely
differ. Forcing them through one authoring mode would mean one procedure pretending to fit four jobs:
| Producer | Writes | From |
|---|---|---|
t1k-cocos-playable-preproduction | to-be | a spec, no code — the greenfield archetype |
t1k-cocos-playable-modularize (Phase 0) | as-is | a legacy repo, from the code as it exists |
t1k-cocos-playable-preproduction (refactor mode) | revised to-be | the as-is doc + architecture-audit.json + reuse-scan.json — modularize Phase 2.5 |
t1k-docs-manager | edits in place | a doc that already exists |
The refactor row is a distinct job, not a variant of row 1. Rows 1 and 3 share one procedure —
top-down module slicing, which is why preproduction owns both — but the input differs completely:
greenfield slices a spec, refactor slices a documented baseline against a list of what is wrong with
it. Leave row 3 unassigned and the refactor archetype’s lifecycle (as-is → revised to-be →
converged, below) has a step nobody performs, and every plan downstream is built at
designState: null.
What makes multiple producers safe is that the contract is verifiable, not that everyone remembered the guideline:
node scripts/verify-manifest.cjs docs/design-manifest.json <project-root>A producer proves conformance by running it. That is the whole reason this skill exists as a contract rather than a style note.
| You are | Do this |
|---|---|
| Producing a doc | Take the blank (Step 0a), fill it, generate, verify |
| Holding a non-canonical or tree-shaped doc | migrate |
| Consuming the module map | Read docs/design-manifest.json — and read parse beside modules |
| Grading code against the doc | Not here — t1k-cocos-base-architecture-patterns audit |
| Looking for the SOLID / anti-pattern rules | Not here — the project’s docs/system-design.md |
The four script modes
Section titled “The four script modes”Deterministic, no judgment, no LLM step (rules/ai-driven-design.md). The doc is the sole SSOT, and
generating the manifest from it is what makes doc↔manifest drift impossible by construction rather
than policed by a gate.
# does this doc describe THIS project at all? Exit 0 ok · 1 repair required · 2 usage error.node scripts/probe-design-doc.cjs docs/system-design.md <project-root> [--project-name <name>]
# doc -> manifest. One-way; never writes into the doc.node scripts/generate-manifest.cjs docs/system-design.md --out docs/design-manifest.json
# manifest <-> code. Exit 0 verified · 1 verification failed · 2 usage error.node scripts/verify-manifest.cjs docs/design-manifest.json <project-root> [--scan-root <rel>]
# non-canonical or tree-shaped doc -> canonical table. Report-only unless --apply.node scripts/migrate-design-doc.cjs docs/system-design.md [--apply] [--print]<project-root> is the directory containing assets/ — frequently a subdirectory of the repo
(<repo>/CocosFooPLA/), not the repo root. probe is the one exception: pass it the repo root,
because that is where it locates the Cocos project directory to read the project’s identity from.
probe runs FIRST — the other three assume a doc that is already yours
Section titled “probe runs FIRST — the other three assume a doc that is already yours”generate and verify answer “does the doc match the code?”. Neither asks the question one level
up: is this doc even about this project? A doc inherited verbatim from PlayableAdsTemplate and
never rewritten answers every existing check exactly as a real doc does — structure-audit R9 only
asks whether the file EXISTS, generate-manifest fails on the missing state: and that failure is
reported downstream as the generic designState: null, and the refactor plan is emitted anyway
behind a prose warning. Measured 2026-08-20 (HexaBugFlowPLA): the doc named PlayableAdsTemplate
four times and the actual game zero times, and a 16-step plan carrying six Tier 2.5 module-boundary
steps was produced against it.
probe closes that gap deterministically. Verdicts, worst first; all matched signals are reported
and verdict is the worst, so a doc failing three ways never hides two of them:
| Verdict | Means | Repair |
|---|---|---|
absent | no file, or empty | author it — Step 0a, fill from the code, state: as-is |
template-verbatim | ≥60% of substantive lines match the vendored blank or a sibling *-template.md | rewrite it for this project |
template-unfilled | [Placeholder] tokens survive | resolve every placeholder |
foreign | never names this project | rewrite the overview + § Module Architecture from THIS codebase |
indeterminate | project identity unresolvable | pass --project-name; fails closed on purpose |
non-canonical | no state: and/or no § Module Architecture | migrate-design-doc.cjs |
ok | canonical and project-specific | none — run verify-manifest next |
ok is a claim about identity and shape, not about drift; drift is still verify-manifest’s
question. Identity matching ignores spacing and case, so a doc titled “Hexa Bug Flow” is not foreign
to CocosHexaBugFlowPLA.
Who reads the probe: refactor (plan-refactor.cjs --design-probe), which withholds Tiers
2.5/2.75 while the verdict is not ok — see that skill’s § “Hard precondition”.
Who reads the manifest: reuse-scan (enumerate-subsystems.cjs --manifest), refactor
(plan-refactor.cjs --manifest, plus verify as an --apply gate), and
architecture-patterns audit. Who does not: structure-audit reads neither the doc nor the
manifest — it grades folders against a pinned blueprint, and that is legitimate, not a gap.
Schema lives in
references/design-manifest.md— field semantics, the module-table contract, and thestate:frontmatter placement. Do not restate it here; the copy is the one people read.
Reading the output — the four fields that decide whether you can trust it
Section titled “Reading the output — the four fields that decide whether you can trust it”parse—complete|partial|unparseable.modules: []alone means nothing; readparsebeside it.unparseablemeans the doc could not be read, not that the project has no modules. A tree-shaped or non-canonical doc lands here and namesmigrate-design-doc.cjs.priorArt—searched|unavailable. A consumer may skip its owndoc_searchonly onsearched.unavailablemeans unverified, not disproven.pathsChecked(verify) —falseunderto-be. A passing to-be verification is not evidence the code matches.scan.scanned(verify) —falsemeans the scan root was unreadable, sounclaimedFilesisnull, not0. Usually the repo root was passed instead of the Cocos project root.cohesion(verify) —findingslists each directory that more than one module calls home, derived fromfiles.enforcedistrueonly underto-be, where such a finding fails the verification: a target doc gives every module its own directory. Underas-is/convergedthe same finding is reported and ignored — a legacy flat layout is the truth an as-is doc records.
Unclaimed files are reported, never failed on. A legacy project is mostly unclaimed — that is the
finding, not an error. verify fails on exactly three things: internal-consistency errors,
unresolvable paths in the states that check them, and a to-be doc whose modules share a home
directory.
The doc has a tense
Section titled “The doc has a tense”state: is not a label — it changes what verification means.
| Archetype | Lifecycle |
|---|---|
| From scratch | created to-be → build → converged |
| Existing doc, audit | converged → verify vs code → drift is the finding |
| Old code, refactor | as-is → revised to-be (git keeps the as-is) → plan = diff → converged on land |
| Old code → new gameplay | as-is from code → to-be = retained + new modules → converged |
as-is and converged check that every documented file resolves; to-be checks internal
consistency only, because the code is expected not to match — that is the work. Without this
carve-out a to-be doc fails verification by design, and a gate that fails by design gets switched off
within a week.
Flipping to converged when the work lands is a required step, not a nicety. While a doc sits at
to-be nothing compares it to code, so that flip is the only gate that ever catches a to-be doc
drifting from what was actually built.
The delta never lives in the doc. The doc holds one state; plan-refactor.cjs output is the
delta, and git holds the previous state
(development-principles.md § “Automate Over Manual — Git Is Truth”).
Step 0a — resolve the template
Section titled “Step 0a — resolve the template”Resolve two things independently — the filled doc, and the blank it is authored from. Many repos (older playables, forks, anything predating the template) have neither.
| Template state | Action |
|---|---|
docs/system-design-template.md present | Use it. It is byte-identical across studio projects. |
| Absent | Copy this skill’s vendored blank, stripping the kit frontmatter (see unfm below): unfm assets/system-design-template.md > <project>/docs/system-design-template.md. A filled reference is vendored alongside as assets/system-design-example.md. |
| Present but modified | diff --strip-trailing-cr <(unfm assets/system-design-template.md) <project>/docs/system-design-template.md. An intentional project change is fine — keep it and note it. An accidental drift should be reset to the vendored copy. |
The vendored files are copy-payloads, not documentation, but they live under .claude/ so CI stamps
kit origin: frontmatter into them like every other .md. Strip it on both sides of any copy or diff —
otherwise the payload pollutes the project’s docs/ and the drift check reports a phantom 7-line delta:
unfm() { awk 'NR==1 && $0=="---"{f=1;next} f && $0=="---"{f=0;next} !f' "$1"; }Passes files through untouched when they have no frontmatter, so it is safe on the project-side copy too.
⚠ Always pass
--strip-trailing-cr. Line endings are inconsistent across studio projects: the vendored copies are LF, but most project checkouts are CRLF. A barediffthen reports every line as changed and reads as total drift when the content is identical. Verified 2026-08-03 —system-design-example.mdis LF inPlayableAdsTemplateand CRLF inAnimalHunterPLA,Arrow3DPLA,BeadsOutMapGenerator, andBearKnitColorPuzzlePLA; content matches exactly once CR is stripped. Usegit diff --ignore-cr-at-eolfor the same reason.
Step 0b — resolve the design doc
Section titled “Step 0b — resolve the design doc”| Doc state | Action |
|---|---|
| Absent | Author it from the template, filling § Module Architecture, Communication Flow, Class Summary, Signal Contracts, Class Reference from the code as it exists today. Document reality, not the aspiration — the refactor is what closes the gap. Run t1k-cocos-base-knowledge-sweep while filling § Module Architecture: a module that already exists upstream should be recorded as such from the start, so the refactor plan never schedules work to rebuild it. |
| Present | Audit it — architecture-patterns audit. Drift is a finding in its own right. |
| Present but stale | Correct it to current reality first, then proceed. Never plan a refactor against a design doc you know is wrong. |
When the project genuinely has no architecture to document
Section titled “When the project genuinely has no architecture to document”A legacy playable may have no modules, no signals, and one 900-line GameController — nothing
§ Module Architecture can describe. Do not skip the doc and do not invent a structure. Fill it
with what exists (one row: the god-class, its files, its responsibility) and mark everything else
TBD. That doc is correct: it accurately records a project with no architecture, and every TBD
becomes a Tier 2.5 refactor target — which is exactly the signal the refactor plan needs.
migrate — adopting the canonical template
Section titled “migrate — adopting the canonical template”scripts/migrate-design-doc.cjs <doc> [--apply]. Report-only by default; --apply rewrites in
place and requires a clean git tree.
Detected format | Action |
|---|---|
canonical — § Module Architecture holds a module table | none; already migrated |
canonical-tree — § Module Architecture holds a fenced ASCII tree | tree lifted into the table, sub-paths preserved; original tree retained below as human reference |
non-canonical — § Project Structure + § Key Architecture Components | re-rooted at assets/scripts/, then lifted into the table |
| anything else | exit 3, nothing written |
This is the only place the ASCII-tree parser lives, and that is deliberate. Reading a tree means
recovering structure from indentation columns over a guessed connector charset; every way it fails is
silent. As a one-time migration whose report a human reviews, that is acceptable. As a gate between
every doc edit and every consumer, it was not — see
references/design-manifest.md § “Why this is a table”.
Gotchas
Section titled “Gotchas”- The manifest is generated. Editing it is always wrong. Fix the doc and regenerate. A hand-edited
manifest reintroduces exactly the drift this design eliminates, and nothing detects it.
verifyrejects a manifest with a missingpriorArtpartly because that is the fingerprint of one. - Generation is one-way.
generate-manifest.cjsnever writes into the doc — not to normalize the table, not to add a missingstate:. A generator that “fixes” its own input makes the doc’s history unreadable. modules: []alone means nothing. Always readparsealongside it. This is the single most likely way a consumer of this file goes wrong.unclaimedFiles: 0is only meaningful whenscan.scannedis true. An absentassets/scripts(usually: the repo root was passed instead of the project root) reportsnull, not0.- Write real sub-paths in the Files column —
combat/hit/HitDetection.ts, notHitDetection.ts. A shortened path resolves to nothing and reports as missing underas-is; underto-benothing checks it at all and it propagates silently. statusis transcribed, never inferred. An empty Files cell does not make a moduleTBD. That inference used to launder “the parser captured nothing” into “declared, not built yet”, which then fed work to rebuild modules that already existed.- A bare
diffon the vendored assets lies twice — CRLF and the CI-injected kit frontmatter. See the warning in Step 0a; getting either wrong makes a clean file look completely rewritten. status: "TBD"is a legitimate entry, not an incomplete one. A legacy project records its god-class as one module and marks the restTBD; each is a Tier 2.5 target forrefactorand ADD-mode input forcontribute.
References
Section titled “References”references/design-manifest.md— SSOT for the manifest schema, thestate/parse/priorArtsemantics, and the § Module Architecture module-table contract. Consumers link here; nothing restates it.assets/system-design-template.md+assets/system-design-example.md— verbatim vendored copy-payloads. Strip the CI-injected kit frontmatter (unfm) on both copy anddiff --strip-trailing-cr. Each carries a second frontmatter block holdingstate:— that block is the payload and must survive the copy; do not merge it into the kit block.scripts/— the three deterministic modes, with suites intests/(node --test tests/).t1k-cocos-base-architecture-patterns— reads this artifact to grade code against it. Owns the pattern triggers and the audit; owns none of this.t1k-cocos-base-knowledge-sweep— prior-art sweep; what makes an→ @playablelabs/…upstream claim evidence rather than a guess.t1k-cocos-playable-preproduction/t1k-cocos-playable-modularize— the producers.preproductionwrites bothto-bedocs (greenfield from a spec; refactor from anas-isdoc + audits);t1k-cocos-playable-modularizewrites the legacyas-isbaseline at its Phase 0 and callspreproductionat its Phase 2.5 for the target. See § “This skill does not author your doc”.rules/code-quality-cocos.md— the binding obligation the artifact serves.