t1k:cocos:playable:parameter
| Field | Value |
|---|---|
| Module | playable |
| Version | 0.5.6 |
| Effort | high |
| Tools | — |
Keywords: canvas-scan, config-scan, dashboard, dynamic-config, parameter, playable-config, playable-parameter, ui-composite
How to invoke
Section titled “How to invoke”/t1k:cocos:playable:parameter[--ui|--config|--all] [--deep] [--canvas <path>] [--path <folder>] [natural language]Cocos Playable Parameter System
Section titled “Cocos Playable Parameter System”Orchestrator for the flat-primitive parameter architecture.
The Load-Bearing Rule
Section titled “The Load-Bearing Rule”Every
ObjectParameterMUST contain ONLY primitiveBaseParameterinstances. NoComponentParametersubclass instances. No nestedObjectParameter. Max depth = 2 (ObjectParameter -> primitive). Doctor:tools/check-playable-config-depth.cjs.
Every other rule in this skill is a corollary of that one. If you must choose between this rule and any example below, the rule wins.
PlayableConfig is serialized to JSON for the dashboard. Nested ObjectParameter or ComponentParameter instances produce structures the dashboard cannot render or edit. Flattening at the config layer keeps dashboard JSON shallow; ComponentParameter reconstruction happens only at apply-time inside the controller.
Submodule Entities (Do NOT Reship)
Section titled “Submodule Entities (Do NOT Reship)”The submodule db://assets/PlayableParamterTool/ owns the runtime. Skill points at it; do not duplicate.
| Use as | Imports from |
|---|---|
Primitives in PlayableConfig entries | parameter/BaseParameter: ColorParameter, NumberParameter, BooleanParameter, TextParameter, ImageParameter, SelectParameter, CoordinatesParameter, ObjectParameter |
| Apply-time component types | parameter/component-parameter/: SpriteComponentParameter, LabelComponentParameter, ButtonComponentParameter, TransformComponentParameter, UIOpacityComponentParameter, … |
| Apply functions | parameter/ParameterApply: applySpriteComponentParams, applyLabelComponentParams, applyButtonComponentParams, applyTransformComponentParams, applyUIOpacityComponentParams, … |
| Async tracking | parameter/ParameterBinder: ParameterBinder (use only binder.waitForAsync() in v6) |
| SDK manager base | base/BaseParameterManager: extend in project’s ParameterManager |
| SDK selection / redirect | sdk/voodoo: Vsdk (used for CTA redirect) |
| Config injection | config/PlayableConfigProvider: PlayableConfigProvider.initialize(PlayableConfig, CURRENT_SDK) |
Forbidden inside PlayableConfig entries: any ComponentParameter subclass instance, any nested ObjectParameter. ComponentParameter classes are apply-time-only types.
Two-Layer System
Section titled “Two-Layer System”| Layer | Flag | Approval | Use Case |
|---|---|---|---|
| UI Layer | --ui | None (auto) | Visual components: Sprite, Label, Button, UIOpacity |
| Config Layer | --config | Required | Gameplay values: HP, damage, timing, speed |
| Both | --all | Config only | Full parameter pass |
UI parameters are visual, safe to auto-apply. Config parameters affect gameplay balance, require human approval.
Decision Tree
Section titled “Decision Tree”| User Intent | Delegate To |
|---|---|
| ”Parameterize all UI components” | t1k-cocos-playable-parameter-scan --mode ui |
| ”Scan a specific Canvas node” | t1k-cocos-playable-parameter-scan --mode ui --canvas <path> |
| ”Extract config values for params” | t1k-cocos-playable-parameter-scan --mode config |
| ”Find magic numbers in gameplay code” | t1k-cocos-playable-parameter-scan --mode config --deep |
| ”Scan specific game folder for config” | t1k-cocos-playable-parameter-scan --mode config --path <folder> |
| ”Do full parameter pass” | t1k-cocos-playable-parameter-scan --mode all |
| ”What composite/type for this component?” | t1k-cocos-playable-parameter-composite |
| ”Generate PlayableConfig / wire parameters” | t1k-cocos-playable-parameter-implement |
| ”Assign scene nodes via MCP” | t1k-cocos-playable-parameter-mcp |
Flag Passthrough (MANDATORY)
Section titled “Flag Passthrough (MANDATORY)”When invoked with flags, pass them to sub-skills. Never drop flags silently.
| Flag Pattern | Route To | Behavior |
|---|---|---|
--mode ui, --ui | scan skill | Auto-delegate, no AskUserQuestion |
--mode config, --config | scan skill | Auto-delegate, no AskUserQuestion |
--mode all, --all | scan skill | Auto-delegate, no AskUserQuestion |
--canvas <path> | scan skill | Append to delegated args |
--path <folder> | scan skill | Append to delegated args |
--deep | scan skill | Append to delegated args |
--auto | all sub-skills | Skip approval gates |
If args contain any flag: parse all flags, select the first step, pass them along — step-transition gates still fire. If args contain no flags: AskUserQuestion for entry-point chooser, then begin the gated sequence.
Step-Transition Protocol (MANDATORY)
Section titled “Step-Transition Protocol (MANDATORY)”Delegates work as discrete steps. Gates EVERY transition with AskUserQuestion. Gates fire regardless of --auto / --all / --mode.
| Step | Sub-Skill | Report File |
|---|---|---|
| 1 — Scan | ...-parameter-scan | param-step1-scan-{YYMMDD-HHMM}-{slug}.md |
| 2 — Composite | ...-parameter-composite | param-step2-composite-{YYMMDD-HHMM}-{slug}.md |
| 3 — Implement | ...-parameter-implement | param-step3-implement-{YYMMDD-HHMM}-{slug}.md |
| 4 — MCP Assign | ...-parameter-mcp | param-step4-mcp-{YYMMDD-HHMM}-{slug}.md |
Per-Step Procedure
Section titled “Per-Step Procedure”After invoking step N’s sub-skill:
- Write step report to
plans/reports/param-step{N}-{YYMMDD-HHMM}-{slug}.md: step name, sub-skill invoked, flags, output summary, files created/modified, suggested next step + 1-2 alternatives, open questions. - Print report path to chat.
- Suggest next step in one line.
- Call
AskUserQuestionwith exactly 4 options: Continue to N+1 (Recommended) / Review report first / Adjust step N / Abort workflow. - Never skip the gate. Only
--auto+--no-gatestogether may suppress gates.
Before invoking step N, read the step (N-1) report if present and pass its path as --from-report <path> to the next sub-skill.
--resume step{N} skips steps 1..N-1, loads the most recent matching report for step (N-1), starts gating from step N.
{slug} is derived from the user’s natural-language request, or auto if flag-only. Reuse the same slug across all step reports.
Category Convention
Section titled “Category Convention”UI categories use the UILayer-{Screen} prefix where {Screen} names the logical UI grouping. Non-UI uses semantic prefixes (Gameplay-{X}, Audio, Sdk).
Why specific UILayer- prefix: dashboard sidebar can collapse by category; prefix groups all nodes from one logical screen while each node stays its own ObjectParameter entry. Generic names (UI, Combat) are too coarse.
Component-Prefix Rule for Inlined Primitives
Section titled “Component-Prefix Rule for Inlined Primitives”When a node has multiple components, prefix each primitive with the lowercase component name. Single-field components (UIOpacity → opacity) keep their field name only.
| Component | Prefixed primitive examples |
|---|---|
cc.Sprite | spriteColor, spriteType, spriteFillType, spriteFillStart, spriteFillRange, spriteSizeMode, spriteTrim, spriteFrame |
cc.Label | labelString, labelColor, labelFontSize, labelEnableOutline, labelOutlineColor, labelOutlineWidth |
cc.UITransform / cc.Node | transformScale, transformPosition, transformRotation |
cc.UIOpacity | opacity (single field — no prefix) |
cc.Button | buttonTransition, buttonZoomScale, buttonNormalColor, buttonPressedColor, buttonHoverColor, buttonDisabledColor |
| Custom widget | Semantic name without prefix (e.g., mainBarColor) when the field applies via method rather than direct component property |
Project-Side Conveniences (OPTIONAL)
Section titled “Project-Side Conveniences (OPTIONAL)”Project may add thin adapters to bridge the flat-primitive config to apply-time ComponentParameter types. These are project-local conventions, NOT mandated by the skill:
- Factory shortcuts wrapping primitive constructors (e.g.,
color(label, def)→new ColorParameter(...)). DRY for repetitive config. - Flat→Component adapters (e.g.,
spriteFromFlat(p)) building aSpriteComponentParameterfrom flat primitives so existingapply*ComponentParamscan be reused. - Common-shape factories (e.g.,
makeLabel,makeButton) producing literal objects of flat primitives — neverComponentParameterinstances. bind<T>(entry: ObjectParameter<T>, applier: (p: T) => void)helper typed by the entry’s value — avoids string-keyedonUpdateregistration, gives autocomplete on the params object.- Property containers with
@property({ type, group })Inspector grouping — keep scene wiring stable as parameter names evolve.
These all compose primitives — none of them violate the load-bearing rule.
Critical Rules
Section titled “Critical Rules”- Flat-Node Rule (UI): 1 Cocos scene Node = 1
ObjectParameter. No exceptions. - No ComponentParameter wrappers in dashboard JSON. Use prefixed primitives directly. ComponentParameter classes are apply-time only.
- No nested
ObjectParameter. Max depth = 2. Doctor-checked. - Component-prefix on multi-component nodes. Single-field components skip the prefix.
UILayer-XXXcategory for UI nodes. Non-UI usesGameplay-XXX,Audio,Sdk.- Scene values as defaults. Use actual component property values, not generic placeholders.
- Typed
@propertyin containers.@property(Sprite),@property(Label)— not@property(Node). - Containers stay stable across refactors. Property containers keep their nested layout; bind methods route flat params to existing container fields.
- Full-field coverage by default (BOTH architectures). Expose EVERY field the node’s component(s) offer — never a hand-picked subset. Authoritative field list:
references/field-coverage.md(flat-primitive path) and the component’sXxxConfiginterface indb://assets/PlayableParamterTool/parameter/component-parameter/*ComponentParameter.ts(wrapper path). Flat-primitive → one prefixed primitive per field. ComponentParameter-wrapper → pass everyXxxConfigkey to the constructor. Narrow the set ONLY with code evidence the field is programmatically managed, or an explicit user note. ALabelComponentParameteremitted with onlystring/color/fontSize(droppinglineHeight,overflow, alignment, bold/italic/underline, outline, shadow, wrapText) is a DEFECT, not a default.
Anti-Patterns
Section titled “Anti-Patterns”ComponentParameterwrapper instance in aPlayableConfigentry — forbidden; inline its fields directly as flat prefixed primitives.- Bundling multiple Cocos nodes under one
ObjectParameter— each node becomes its own top-level entry. - Generic UI category names —
UI,Combat. AlwaysUILayer-{Screen}. - Missing component prefix on multi-component primitives — collision risk + machine-unreadable.
- Inheritance for composites (e.g., Button IS-A Sprite) — wrong; flat primitives only.
- Pre-filter nodes by name before checking components.
- Generic defaults when scene values are available.
- Skip UIOpacity or Widget detection.
- Modify the submodule for project-specific types — never. Keep project additions in
assets/scripts/parameter/.
References
Section titled “References”references/code-templates.md— Generic v6 templates forPlayableConfigentries + controller wiringreferences/type-hierarchy.md— v6 two-stage model (primitives at config layer, ComponentParameter at apply layer)references/field-coverage.md— Component-by-component primitive field tablesreferences/scan-strategy.md— Canvas scan procedurereferences/intent-detection.md— Natural-language intent → mode routingreferences/discovery-helpers.md— Scan helpers (context, comparison, scene JSON)references/mcp-assignment.md— MCP node→property assignment patternsreferences/workflow-steps.md— End-to-end step procedure
Sub-skills:
t1k-cocos-playable-parameter-scan— Scene discoveryt1k-cocos-playable-parameter-composite— Type system + presetst1k-cocos-playable-parameter-implement— Code generationt1k-cocos-playable-parameter-mcp— Editor integration
Gotchas
Section titled “Gotchas”- Composite-based projects: follow project convention, not this rule. Some projects deliberately use the composite/wrapper architecture (
ObjectParameter<SpriteParameter>,ObjectParameter<SpriteComponentParameter>,ParameterBinderfluent API,NodeComposites/PLAComposites/component-parameterwrapper classes). This is a valid, signed-off alternative shipped by the same submodule. When extending an existing composite project, match the project’s pattern — do NOT introduce flat-primitive entries alongside composites (SSOT/consistency hit). The flat-primitive rule below is the default for NEW projects only. Detection: ifPlayableConfig.tsusesObjectParameter<SpriteParameter>,ObjectParameter<…ComponentParameter>, orParameterBinder, the project is composite/wrapper-based; ask user to confirm architecture before generating code. - Full-field coverage applies on the wrapper path too. When generating an
ObjectParameter<XxxComponentParameter>(wrapper path), populate EVERY key of that component’sXxxConfiginterface by default — not a hand-picked few. Opendb://assets/PlayableParamterTool/parameter/component-parameter/XxxComponentParameter.ts, read theXxxConfiginterface, and pass all keys (using scene values when MCP is connected). Example defect: aLabelComponentParameterconfig with only{ string, color, fontSize }while theLabelConfiginterface also offerslineHeight, overflow, horizontalAlign, verticalAlign, fontFamily, isBold, isItalic, isUnderline, enableOutline, outlineColor, outlineWidth, enableShadow, shadowColor, shadowOffset, enableWrapText. Include them all unless the user says otherwise. See Critical Rule 9. - Hard rule, doctor-checked: every
ObjectParametercontains primitives only. NoComponentParameterinstance, no nestedObjectParameter. - “1 Cocos Node = 1 ObjectParameter” for UI. Logical composites (Crosshair, HPBar, RewardCard) become N top-level entries — never bundle.
- Category prefix =
UILayer-{Screen}for UI. GenericUIorCombatis forbidden. Non-UI usesGameplay-XXX,Audio,Sdk. - Containers do NOT change shape across refactors. Property containers keep their nested layout; bind methods bridge the new flat top-level
ObjectParameterto existing container refs. Zero scene re-wiring. - Single-field components skip the prefix.
UIOpacity.opacityisopacity, notuiOpacityOpacity. - Custom-widget semantic names skip prefix. When a primitive applies through a method (e.g.
hpBar.setBarColor(...)) rather than to a single Cocos component property, use the widget’s semantic name. - Flags govern sub-skill behavior, NOT orchestration gates. Step transition gates ALWAYS fire.
- Every step writes a report under
plans/reports/param-step{N}-…mdBEFORE the gate. - Gate uses
AskUserQuestion(mandatory). Never substitute prose options. Load viaToolSearch(query="select:AskUserQuestion")if deferred. - Resume flag is SSOT.
--resume step{N}reads the latest matchingparam-step{N-1}-…md. Do not re-run earlier steps. - Apply-time only:
ComponentParametersubclasses (SpriteComponentParameter, etc.) appear only insideapply*ComponentParamscalls — never asObjectParametervalues.