scaffold-gateables

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Performance Notes

性能说明

  • Take your time to understand the game before proposing features
  • Quality is more important than speed — wrong gateables hurt the game permanently
  • Do not skip the locked-path verification in Step 4
  • 先花时间了解游戏,再提出功能建议
  • 质量比速度更重要——错误的可授权解锁功能会对游戏造成永久性伤害
  • 不要跳过步骤4中的锁定路径验证

Scaffold Gateables

搭建可授权解锁功能

Add gateable features to an existing game. This skill produces hooks — skin pickers, continue-after-death flows, bonus modes, save slots, daily challenges — each wired through EventBus with a single capability-check seam (
isEntitled(key)
). It does NOT add any specific monetization SDK (Play.fun, sub.games, Stripe, etc.); it produces the scaffolding that any paywall, subscription, or entitlement layer can later switch on.
The default state is everything locked —
isEntitled(key)
returns
false
for all keys. The game must feel completely normal in that state. When a downstream monetization layer flips an entitlement on, the gateable feature lights up.
为现有游戏添加可授权解锁的功能。该技能会生成“钩子”——皮肤选择器、死后续玩流程、奖励模式、存档槽、每日挑战——每个功能都通过EventBus连接,并带有一个单一的权限检查接口(
isEntitled(key)
)。它不会添加任何特定的变现SDK(如Play.fun、sub.games、Stripe等);它生成的脚手架可让后续任何付费墙、订阅或授权层启用这些功能。
默认状态下所有功能均锁定——
isEntitled(key)
对所有key返回
false
。在此状态下,游戏必须运行完全正常。当下游变现层开启某项权限时,对应的可授权解锁功能才会激活。

Core Principles

核心原则

Use these to reason about what to propose and what to reject. They are rules, not guidelines.
  1. Never gate the core loop. If the game is about jumping, everyone jumps. Gate skins, not gravity.
  2. Prefer additive over subtractive. Add a bonus mode; don't shrink the free mode. Free players never feel punished.
  3. Match the game's rhythm. Short sessions → session-scoped perks (continue, daily skin, daily challenge seed). Long-form → persistence (save slots, unlock tree, bonus chapters).
  4. Propose 2–3 gateables at silver and gold only. Bronze is the default — every player gets the bronze experience by default, so no feature is scaffolded there. Aim for one or two silver conveniences and one gold spectacle. Numbers are targets — suggest what actually fits the game.
  5. Every gateable must degrade cleanly. With
    isEntitled
    returning
    false
    , the game must feel normal — not broken, not missing.
遵循这些原则来判断应提出或拒绝哪些功能。这些是规则,而非指南。
  1. 绝不锁定核心玩法循环。如果游戏的核心是跳跃,那么所有玩家都能跳跃。锁定皮肤,而非重力。
  2. 优先选择新增功能而非削减原有功能。添加奖励模式;不要缩小免费模式的内容。免费玩家永远不应感到被惩罚。
  3. 匹配游戏节奏。短会话游戏→会话级福利(续玩、每日皮肤、每日挑战种子)。长流程游戏→持久化功能(存档槽、解锁树、奖励章节)。
  4. 仅在白银和黄金层级提出2-3项可授权解锁功能。青铜是默认层级——所有玩家默认都能获得青铜体验,因此不会在该层级搭建任何功能。目标是1-2项白银层级的便利功能和1项黄金层级的特色功能。数字仅为参考——建议提出真正适合游戏的功能。
  5. 每项可授权解锁功能都必须能平滑降级。当
    isEntitled
    返回
    false
    时,游戏必须运行正常——不能出现故障或缺失内容。

Tier Vocabulary

层级术语

Use game-standard progression labels: bronze / silver / gold. This keeps the skill monetization-agnostic and reads naturally to players.
Bronze is the default tier — every player is bronze by default. The bronze experience IS the core game loop that everyone always gets. No feature is scaffolded at bronze; scaffold-gateables only produces features at silver and gold.
The downstream integration layer maps silver/gold to its own paid tier system:
scaffold-gateablessub.gamesPlay.fun (points-based)
silversupporter ($3–8/mo)mid-threshold points
goldfounder ($150/yr)high-threshold points
State this mapping in the Step 2 output so the handoff to
/subgames
or
/monetize-game
is explicit.
使用游戏标准的进阶标签:bronze / silver / gold。这能让该技能保持与变现无关,且对玩家来说通俗易懂。
Bronze是默认层级——所有玩家默认都是青铜层级。青铜体验就是所有玩家都能获得的核心游戏玩法循环。不会在青铜层级搭建任何功能;搭建可授权解锁功能仅会在silvergold层级生成功能。
下游集成层会将白银/黄金层级映射到自身的付费层级系统:
scaffold-gateablessub.gamesPlay.fun(基于积分)
silver支持者(3-8美元/月)中等阈值积分
gold创始人(150美元/年)高阈值积分
在步骤2的输出中说明此映射,以便明确对接
/subgames
/monetize-game

Instructions

操作步骤

The user wants to add gateables to the game at
$ARGUMENTS
(or the current directory if no path given). Optional hint tokens after the path (e.g.,
skins continue
) bias the proposal.
用户希望在
$ARGUMENTS
指定的游戏(若未给出路径则为当前目录)中添加可授权解锁功能。路径后的可选提示标记(如
skins continue
)会影响提案方向。

Step 1: Understand the game

步骤1:了解游戏

  • Read
    package.json
    — detect engine (
    phaser
    → Phaser,
    three
    → Three.js).
  • Read
    src/core/Constants.js
    ,
    src/core/EventBus.js
    ,
    src/core/GameState.js
    .
  • Read
    src/main.js
    to find
    window.render_game_to_text()
    and the orchestrator entry point.
  • Read
    progress.md
    at the project root if it exists (written by the
    /make-game
    pipeline).
  • Read the primary scene/system files to understand the core loop.
Then tell the creator one sentence:
The core loop is
<verb>
— I will not gate it. Gateables will be additive features that layer on top.
  • 读取
    package.json
    ——检测引擎(
    phaser
    →Phaser,
    three
    →Three.js)。
  • 读取
    src/core/Constants.js
    src/core/EventBus.js
    src/core/GameState.js
  • 读取
    src/main.js
    以找到
    window.render_game_to_text()
    和编排器入口点。
  • 若项目根目录存在
    progress.md
    (由
    /make-game
    流水线生成),则读取该文件。
  • 读取主要场景/系统文件以理解核心玩法循环。
然后告知创作者一句话:
核心玩法循环是**
<动作>
**——我不会锁定它。可授权解锁功能将是叠加在核心玩法之上的新增功能。

Step 2: Propose features

步骤2:提出功能建议

Generate 2–3 candidate gateables at silver and gold tiers anchored in the five principles. Present as a Markdown table:
FeatureTierEntitlement keyWhat it addsLocked pathEventBus eventsGameState additions
Skin pickersilver
premium_skins
5 cosmetic variants via a picker on GameOverSceneDefault skin only; button greyed out
skin:selected
,
skin:unlocked
selectedSkin: 'default'
,
unlockedSkins: ['default']
(persist through reset)
Continue after deathsilver
continue
One continue per session offered on deathNo continue prompt; immediate restart
continue:offered
,
continue:accepted
continueOffered: false
,
usedContinue: false
(clear on reset)
Daily challenge modegold
daily_challenge
Unique seeded run each day with its own leaderboardNo daily challenge menu visible
daily:opened
,
daily:completed
dailyChallengeSeed: null
,
dailyBestScore: 0
(persist through reset)
Anchor picks in the principles. Reject any suggestion that gates the core loop. Never propose bronze-tier features — bronze is the default everyone gets. Prefer cosmetic > convenience > bonus > persistence for short-session games; flip the order for long-form.
In interactive mode (user-invoked skill): wait for creator confirmation before implementing. Let them drop, swap, or tweak suggestions.
In pipeline mode (called from
/make-game
Step 1.25):
auto-pick the top 2–3 and continue without prompting.
基于五项原则,生成2-3项候选的白银和黄金层级可授权解锁功能。以Markdown表格形式呈现:
功能层级权限Key新增内容锁定路径EventBus事件GameState新增字段
皮肤选择器silver
premium_skins
在GameOverScene中添加包含5种外观变体的选择器仅显示默认皮肤;按钮置灰
skin:selected
,
skin:unlocked
selectedSkin: 'default'
,
unlockedSkins: ['default']
(重置后保留)
死后续玩silver
continue
每次死亡后提供1次续玩机会无续玩提示;立即重启
continue:offered
,
continue:accepted
continueOffered: false
,
usedContinue: false
(重置后清除)
每日挑战模式gold
daily_challenge
每日提供独特的随机种子关卡及专属排行榜不显示每日挑战菜单
daily:opened
,
daily:completed
dailyChallengeSeed: null
,
dailyBestScore: 0
(重置后保留)
基于原则选择功能。拒绝任何锁定核心玩法循环的建议。绝不提出青铜层级的功能——青铜是所有用户默认获得的层级。对于短会话游戏,优先选择外观类>便利类>奖励类>持久化类功能;长流程游戏则顺序相反。
交互模式(用户调用技能): 在实现前等待创作者确认。允许他们删除、替换或调整建议。
流水线模式(由
/make-game
步骤1.25调用):
自动选择排名前2-3的功能并继续执行,无需提示。

Step 3: Implement

步骤3:实现

Follow this order strictly:
3a. Create
src/systems/Entitlements.js
— the single capability-check seam:
js
// src/systems/Entitlements.js
// Single capability check for all gateable features.
// Returns false by default — every gateable must degrade cleanly when locked.
// Wire this to your monetization layer (sub.games, Play.fun, custom paywall)
// by replacing the body with real checks. See `/monetize-game` or `/subgames`.

export function isEntitled(key) {
  // TODO: wire to monetization layer.
  return false;
}
3b. Add events to
src/core/EventBus.js
(append-only,
domain:action
form).
3c. Add state fields to
src/core/GameState.js
. Update
reset()
to preserve persistent fields (e.g.,
unlockedSkins
,
bonusModeUnlocked
) and clear transient ones (e.g.,
usedContinue
,
continueOffered
).
3d. Add constants to
src/core/Constants.js
under a new
GATEABLES
section (skin list, continue cooldown, bonus mode config, etc.).
3e. Create gateable modules in the existing
src/
subdirectories matching the game's layout:
  • src/ui/SkinPicker.js
    (Phaser scene or Three.js panel)
  • src/systems/ContinueFlow.js
  • src/systems/BonusMode.js
  • etc.
Each gateable's entry point calls
isEntitled(key)
and branches:
js
import { isEntitled } from '../systems/Entitlements.js';

function openSkinPicker() {
  if (!isEntitled('premium_skins')) {
    // Locked path: greyed-out button with lock icon, no picker opens.
    // Default skin remains selected. Game continues normally.
    return;
  }
  // Entitled path: open the picker scene.
  scene.scene.launch('SkinPickerScene');
}
Never create a pre-gameplay title screen or skin-picker-first flow. The template boots directly into gameplay. Gateable UI opens from pause menu, settings, or GameOverScene only.
3f. Update
window.render_game_to_text()
in
src/main.js
additively
— add new observable fields (
selectedSkin
,
continueAvailable
,
bonusModeActive
) without removing existing ones. This is load-bearing for AI test harnesses.
严格按照以下顺序执行:
3a. 创建
src/systems/Entitlements.js
——单一权限检查接口:
js
// src/systems/Entitlements.js
// 所有可授权解锁功能的单一权限检查接口。
// 默认返回false——所有可授权解锁功能在锁定时必须能平滑降级。
// 通过替换函数体为真实检查逻辑,将其对接至你的变现层(sub.games、Play.fun、自定义付费墙)。
// 请查看`/monetize-game`或`/subgames`。

export function isEntitled(key) {
  // TODO: 对接至变现层。
  return false;
}
3b. 向
src/core/EventBus.js
添加事件
(仅追加,采用
domain:action
格式)。
3c. 向
src/core/GameState.js
添加状态字段
。更新
reset()
方法以保留持久化字段(如
unlockedSkins
bonusModeUnlocked
)并清除临时字段(如
usedContinue
continueOffered
)。
3d. 向
src/core/Constants.js
添加常量
,新增
GATEABLES
章节(皮肤列表、续玩冷却时间、奖励模式配置等)。
3e. 在现有
src/
子目录中创建可授权解锁功能模块
,匹配游戏的目录结构:
  • src/ui/SkinPicker.js
    (Phaser场景或Three.js面板)
  • src/systems/ContinueFlow.js
  • src/systems/BonusMode.js
  • 等等
每个可授权解锁功能的入口点都会调用
isEntitled(key)
并分支处理:
js
import { isEntitled } from '../systems/Entitlements.js';

function openSkinPicker() {
  if (!isEntitled('premium_skins')) {
    // 锁定路径:按钮置灰并显示锁定图标,不打开选择器。
    // 仍选择默认皮肤。游戏正常运行。
    return;
  }
  // 有权限路径:打开选择器场景。
  scene.scene.launch('SkinPickerScene');
}
绝不要创建游戏开始前的标题界面或先显示皮肤选择器的流程。模板直接进入游戏玩法。可授权解锁功能的UI仅能从暂停菜单、设置界面或GameOverScene打开。
3f. 增量更新
src/main.js
中的
window.render_game_to_text()
——添加新的可观察字段(
selectedSkin
continueAvailable
bonusModeActive
),不要删除现有字段。这对AI测试工具至关重要。

Step 4: Verify

步骤4:验证

  • npm run build
    clean.
  • npm run dev
    and play with
    isEntitled
    returning
    false
    (default). Core loop must feel identical to pre-skill state. If anything feels broken or missing, you gated the core loop — revert and revise.
  • Temporarily edit
    Entitlements.js
    to
    return true;
    for all keys. Confirm each feature activates correctly. Revert.
  • If
    tests/
    exists and snapshots
    render_game_to_text()
    via exact equality (
    toEqual
    ), update baselines — field additions are intentional. If tests use
    toMatchObject
    , no update needed.
  • Append a
    ## Gateables
    section to
    progress.md
    at the project root with:
    • Features added (name + tier + entitlement key)
    • EventBus events added
    • GameState fields added (marked as persistent or transient)
    • Constants keys added
    • Locked-path description (one line per feature)
  • npm run build
    编译正常。
  • 运行
    npm run dev
    并在
    isEntitled
    返回
    false
    (默认状态)下游玩。核心玩法循环必须与使用该技能前的状态完全一致。如果任何内容出现故障或缺失,说明你锁定了核心玩法循环——回滚并修改。
  • 临时编辑
    Entitlements.js
    使其对所有key返回
    true;
    。确认每个功能都能正确激活。然后恢复原代码。
  • 若存在
    tests/
    目录且通过精确相等(
    toEqual
    )快照
    render_game_to_text()
    的输出,则更新基准线——添加字段是有意为之。若测试使用
    toMatchObject
    ,则无需更新。
  • 在项目根目录的
    progress.md
    中追加
    ## 可授权解锁功能
    章节,包含:
    • 添加的功能(名称+层级+权限Key)
    • 添加的EventBus事件
    • 添加的GameState字段(标记为持久化或临时)
    • 添加的常量Key
    • 锁定路径描述(每项功能一行)

Troubleshooting

故障排除

Feature works when entitled but the game breaks when locked

有权限时功能正常,但锁定时游戏出现故障

Cause: You gated part of the core loop, or the locked path is incomplete. Fix: Revert. The locked path must produce normal-feeling gameplay. Test by running with
isEntitled
returning
false
— if anything is missing or broken, revise.
原因: 你锁定了部分核心玩法循环,或锁定路径不完整。 修复: 回滚。锁定路径必须让游戏运行正常。通过在
isEntitled
返回
false
的状态下运行游戏进行测试——如果任何内容缺失或故障,修改方案。

Snapshot tests fail after
render_game_to_text
update

更新
render_game_to_text()
后快照测试失败

Cause: Tests use exact
toEqual
on output; you added new fields. Fix: Regenerate baselines — the additions are intentional and backward-compatible for any consumer that tolerates extra keys.
原因: 测试使用精确的
toEqual
比对输出;你添加了新字段。 修复: 重新生成基准线——添加字段是有意为之,且对任何能容忍额外Key的消费者来说是向后兼容的。

Skin picker blocks first play

皮肤选择器阻碍首次游戏体验

Cause: Picker launches pre-gameplay. Fix: Move entry point to a pause menu, settings screen, or GameOverScene. The template boots directly into gameplay and must continue to do so.
原因: 选择器在游戏开始前启动。 修复: 将入口点移至暂停菜单、设置界面或GameOverScene。模板直接进入游戏玩法,必须保持此逻辑。

Entitlements.js
already exists

Entitlements.js
已存在

Cause: The skill has been run before, or a monetization layer is already wired. Fix: Read the file. If it's a stub (
return false
), add new keys and continue. If it's wired to a real monetization layer, leave it alone and only add the new entitlement keys as new function branches.
原因: 该技能已运行过,或已对接变现层。 修复: 读取该文件。如果是占位符(
return false
),则添加新的key并继续。如果已对接真实的变现层,则保留原文件,仅添加新的权限Key作为新的函数分支。

Proposal over-gates or feels punishing

提案过度锁定或让玩家感到被惩罚

Cause: You picked features that restrict the free experience. Fix: Principle 2 (additive over subtractive). Free players should never feel punished by the absence of a gateable. If removing a gateable makes the game feel worse for a free player, it's gating the wrong thing.
原因: 你选择了限制免费体验的功能。 修复: 遵循原则2(优先新增而非削减)。免费玩家不应因缺少可授权解锁功能而感到被惩罚。如果移除某项可授权解锁功能会让免费玩家的游戏体验变差,说明你锁定了错误的内容。

Output

输出内容

Tell the user:
  1. What was added — list each gateable (name, tier, entitlement key)
  2. The single wiring seam — point at
    src/systems/Entitlements.js
    and explain: "Flip
    isEntitled(key)
    to return
    true
    for a key to activate that feature. Wire it to
    /monetize-game
    (Play.fun) or
    /subgames
    (subscription) next."
  3. How to test — "Run
    npm run dev
    and play. Everything should feel normal (all gateables locked by default). Edit
    Entitlements.js
    to
    return true;
    temporarily to see features light up."
  4. Next step — suggest
    /monetize-game
    or
    /subgames
    as appropriate.
告知用户:
  1. 已添加内容——列出每项可授权解锁功能(名称、层级、权限Key)
  2. 单一对接接口——指向
    src/systems/Entitlements.js
    并说明:“将
    isEntitled(key)
    修改为对指定key返回
    true
    即可激活该功能。下一步可将其对接至
    /monetize-game
    (Play.fun)或
    /subgames
    (订阅)。”
  3. 测试方法——“运行
    npm run dev
    并游玩。所有内容应运行正常(默认状态下所有可授权解锁功能均锁定)。临时编辑
    Entitlements.js
    使其返回
    true;
    以查看功能激活效果。”
  4. 下一步建议——根据情况建议使用
    /monetize-game
    /subgames

Example Usage

示例用法

Default proposal in the current game directory

当前游戏目录下的默认提案

/scaffold-gateables
Result: reads the game, proposes 2–3 gateables, implements them after confirmation. Creates
Entitlements.js
, new UI modules, new events and state. Game feels unchanged until the entitlement seam is flipped.
/scaffold-gateables
结果:读取游戏内容,提出2-3项可授权解锁功能,确认后实现。创建
Entitlements.js
、新的UI模块、新事件和状态。在权限接口未修改前,游戏体验无变化。

Biased proposal with hints

带提示的定向提案

/scaffold-gateables skins continue
Result: proposal biased toward a skin picker and a continue-after-death flow. Other suggestions still possible if they fit the game better.
/scaffold-gateables skins continue
结果:提案偏向皮肤选择器和死后续玩流程。如果其他建议更适合游戏,仍可提出。

Explicit project path

指定项目路径

/scaffold-gateables ./examples/flappy-bird
Result: operates on the given directory rather than the cwd.
/scaffold-gateables ./examples/flappy-bird
结果:在指定目录而非当前工作目录中操作。

Tips

提示

Run this once per game. If you later want to add more gateables, use
/add-feature
for specific additions or run this skill again — it detects existing
Entitlements.js
and only appends new keys.
Integration comes next:
/monetize-game
wires Play.fun points to gateables via
Entitlements.js
;
/subgames
(from the
subdotgames/skills
repo, separate install) wires subscription tiers. Either way,
Entitlements.js
is the only file that needs to change to turn gateables on.
每个游戏运行一次该技能。如果之后想添加更多可授权解锁功能,使用
/add-feature
添加特定功能,或再次运行该技能——它会检测已存在的
Entitlements.js
并仅追加新的key。
下一步是集成:
/monetize-game
通过
Entitlements.js
将Play.fun积分对接至可授权解锁功能;
/subgames
(来自
subdotgames/skills
仓库,需单独安装)将订阅层级对接至可授权解锁功能。无论哪种方式,只需修改
Entitlements.js
即可启用可授权解锁功能。