Tweak
Fast path for small Godot 4.x changes: a bugfix, a tuning/value adjustment, a small script or scene
edit that fits 1-3 files. Everything heavier belongs to /game-ship (or /game-debug for hard
bugs) — the gate that decides is shared/TWEAK-DISCIPLINE.md (size
gate, backlog guard, registration policy, never-do list). No TaskCreate phase tracking — a tweak
run is minutes of work with no compaction risk; ceremony is what this skill exists to avoid. Skill
file stays English; user-facing output follows CLAUDE.md § User Preferences → Language:.
Tweak configuration (per shared/TWEAK-DISCIPLINE.md):
- verify: gdlint + scoped GUT tests per PHASE 3 below
- escalation ship target:
/game-ship
- escalation debug target:
/game-debug (standalone skill)
PHASE 0 — Pre-flight, size gate & backlog guard
Repo: resolve $REPO to the main worktree (per shared/SYNC.md Worktree-aware Path
Resolution). .project/ absent → degrade gracefully: skip the card lookup, guard, and learnings
silently, keep the rest (the code change is the value; do not scaffold).
Mode + description: .project/ present → load once:
node ~/.claude/scripts/backlog-load.js "$REPO" guard-items (the game-pipeline stage field
included; reused by step 6's guard — one load, not two). The invocation argument matches a live
POLISH card — exact name, or an unambiguous ≥2-shared-token match — per
shared/TWEAK-DISCIPLINE.md § Card pickup path 1?
- Match → card mode. Description = the card's
description. Run the dependency check now
(one AskUserQuestion only if the card has an open, unshipped dependency).
- No match, or
.project/ absent → free-text mode. Description from the invocation argument;
if empty, ask one short question.
Branch guard per shared/TWEAK-DISCIPLINE.md § Branch guard:
not on the default branch (or detached HEAD) → warn + ask before proceeding.
Baseline per shared/SCOPED-COMMIT.md § 1:
git status --porcelain | sort > .project/session/pre-tweak-status.txt (skip when .project/ is
absent).
Gate + guard: Read shared/TWEAK-DISCIPLINE.md; run § Size
gate on the projected scope (game surface examples: new scene, autoload, signal contract, input
action). § Backlog guard: card mode → skip (the card already names the scope). Free-text
mode → run § Backlog guard as before — the guard-items load includes the game-pipeline
stage field — then § Card pickup path 2 (the POLISH-only mini-guard) against the same
guard-items load from step 2.
Todo: if any gate criterion fires or the guard demands escalation → Read
.claude/skills/game-tweak/references/escalate.md and follow it — never continue silently.
Slug: card mode → the card's own kebab name (no re-derivation). Free-text mode → derive a
kebab-case slug from the description (commit scope + learnings feature key). Print the status:
Gate: ✓ tweak-sized · Guard: ✓ no card overlap (or the warn/advisory lines; card mode prints
Card: {name} instead of the guard line).
PHASE 1 — Locate & context
Locate the change with minimal reads (Grep → targeted Read; .tscn files: read only the
relevant node sections). The files found here feed the size-gate re-check and the learnings load
below.
Pre-seeded from a ship de-escalation handoff (invocation carries a files[] +
acceptance[] pair, per shared/TWEAK-DISCIPLINE.md §
De-escalation gate (a)) → skip the Grep/Read locate itself; use the passed files[] as the
located set directly. The size-gate re-check still runs against that set — the handoff is not
an exemption from it. Hold the passed acceptance[] in memory and use it as PHASE 3's verify
checklist instead of relying on whatever coverage happens to already exist.
Todo (card mode): locate shows the described defect is already resolved on main — a later
commit fixed it, or it never applied → stale card. Do not invent a change to justify the
card. Skip PHASE 2, PHASE 3, and PHASE 4 step 1 entirely (including step 2's learnings load);
go straight to the PHASE 4 card-completion write per
shared/TWEAK-DISCIPLINE.md § Card pickup → Stale card:
shippedSha = the resolving commit (git log -- <file>), or HEAD if none pins it; summary
names the card stale; commit nothing.
Todo (card mode): locate/analysis (or an explicit user call mid-run) shows the card's whole
reason to exist is superseded by a different, wider card — not fixed, just made moot →
obsolete/superseded card. Confirm with one AskUserQuestion naming the superseding card
before touching anything. On confirmation: skip PHASE 2, PHASE 3, and PHASE 4 step 1 entirely;
go straight to the § Card pickup → Obsolete/superseded card cancellation write. On decline:
continue the tweak as originally scoped.
Learnings — mandatory, not gated on tweak size. Run exactly this, after locate so --paths
carries the real file anchors (see shared/LEARNINGS-LOAD.md for
the full parameter/relevance model):
node ~/.claude/scripts/learnings-search.js "$REPO" load \
--feature "{slug}" --scopes component --pitfall-prefix true \
--paths "{located files, comma-separated, repo-relative}"
Any non-zero exit is a failed step, not a zero-match result — fix the invocation and re-run.
Only exit 0 with empty stdout is a genuine zero. Include the printed block verbatim when
non-empty, skip silently otherwise.
PHASE 2 — Implement
- Conditional plan mode (shared/PLAN-MODE.md § Difficulty
escalation): call
EnterPlanMode only when the root cause is still unclear after first evidence,
or the change spans > 2 files. Enter → design → write the decision to the plan file →
ExitPlanMode → execute. Skip entry when plan mode is already active. The typical tweak never
enters.
- Bugfix-shaped tweaks follow shared/DEBUG-LADDER.md tier 1/2:
hypothesis before edit, evidence before a second attempt — never guess-and-check.
- Mid-flight re-check: the moment actual scope exceeds the size gate (a 4th file, a discovered
new surface) → stop and Read
references/escalate.md.
PHASE 3 — Verify light
A tweak that changes no runnable code — only docs or gitignored .project/ state (e.g. recording a
known issue as a learning) — or a stale or obsolete/superseded card with nothing to edit (see
PHASE 1) — has nothing to verify and nothing to commit: skip PHASE 3 and PHASE 4 step 1, say so in
the report (no commit sha line), and go straight to the card-completion (or cancellation) + learning
writes. Everything below assumes a code change.
Scoped to the touched scripts/scenes — never the full suite unless it is genuinely fast:
- Lint:
gdlint on changed .gd files (gdformat already runs via the format-on-save hook).
- Tests: run the GUT test file(s) covering the touched scripts:
godot --headless --path . -s addons/gut/gut_cmdln.gd -gtest={test-file} -gexit
(resolve the Godot executable per .claude/paths.local.yaml → CLAUDE_GODOT_EXECUTABLE).
- No covering test + behavior change: ask the user for one quick scene-run confirmation instead
of writing a new test file (a new test file is size-gate criterion 3).
New failures vs the baseline → fix within the current tier's discipline; unfixable within tweak
scope → Read references/escalate.md.
PHASE 4 — Wrap-up
Scoped commit per shared/SCOPED-COMMIT.md. Deltas: baseline
pre-tweak-status.txt; OVERLAP policy auto-include (the fix is the point); fallback: ask
which files belong to the tweak; message
{fix|refactor|perf|style|test|docs|chore}({slug}): {summary} — never feat (net-new capability
is an escalation criterion by definition), test when the only change is added or expanded test
coverage, docs for a docstring/comment/markdown-only edit; cleanup: remove the baseline file.
Card-mode completion (skip entirely in free-text mode): per
shared/TWEAK-DISCIPLINE.md § Card pickup completion write — flip
the card shipped: true + shippedAt + shippedSha + summary (this tweak's one-line
outcome), remove a board-set transition field if present (it was only ever the board's
queue-marker, never a lifecycle state — see § Never), and move it from
backlog.json#features[] to .project/archive/backlog-archive.json#archived[]. project.json
persists no features list — the dashboard derives features from backlog + archive. Then
re-read backlog.json and confirm the card left features[] before reporting shipped — a
running board app (serve-backlog.js) re-serializes that file from its own in-memory store and
can silently revert an external write; on a revert, re-apply and re-verify.
Obsolete/superseded card instead (PHASE 1's confirmed obsolete branch): run the § Card pickup
→ Obsolete/superseded card cancellation write instead — in place within features[], flip
status: "CANCELLED", add cancelledReason: "superseded by {card}: {one-line why}" and
cancelledAt, remove transition. The card stays in features[] (never moves to the archive —
that move is shipped-only). Same board-app revert guard: re-read backlog.json and confirm
status: "CANCELLED" survived before reporting; re-apply on a revert.
Optional learning (0-1): only for a bugfix whose root cause has value beyond this spot
(filter per shared/LEARNING-WRITE.md § Writer Append Protocol) —
append via learnings-write.js append with type: "pitfall", source: "extracted", 0-3 tags
(game vocabulary: godot, gdscript, scene, game-loop), then run the Consolidation Gate
once (LEARNING-WRITE.md § Consolidation Gate). Skip both silently otherwise. No state auto-push
(TWEAK-DISCIPLINE § Registration policy).
Report (compact prose, no rigid table): what changed with file:line refs, checks run,
commit sha, a Guard: line repeating any card overlap (card mode prints Card: {name} → shipped, or Card: {name} → cancelled (superseded by {card}) for the obsolete/superseded outcome),
a Learning: line when one was written, and Escalation overridden: {criterion} when
applicable. Add Next steps: /game-ship {card} only when the guard flagged a TODO card
(free-text mode only — card mode is already terminal). A tweak is terminal — no next-step offer
otherwise.
1---2name: game-tweak3description: Use when a Godot change fits 1-3 files, no pipeline. Use with /game-tweak.4---56# Tweak78Fast path for small Godot 4.x changes: a bugfix, a tuning/value adjustment, a small script or scene9edit that fits 1-3 files. Everything heavier belongs to `/game-ship` (or `/game-debug` for hard10bugs) — the gate that decides is [shared/TWEAK-DISCIPLINE.md](../shared/TWEAK-DISCIPLINE.md) (size11gate, backlog guard, registration policy, never-do list). No `TaskCreate` phase tracking — a tweak12run is minutes of work with no compaction risk; ceremony is what this skill exists to avoid. Skill13file stays English; user-facing output follows `CLAUDE.md § User Preferences → Language:`.1415Tweak configuration (per shared/TWEAK-DISCIPLINE.md):1617- verify: gdlint + scoped GUT tests per PHASE 3 below18- escalation ship target: `/game-ship`19- escalation debug target: `/game-debug` (standalone skill)2021## PHASE 0 — Pre-flight, size gate & backlog guard22231. **Repo**: resolve `$REPO` to the main worktree (per `shared/SYNC.md` Worktree-aware Path24 Resolution). `.project/` absent → degrade gracefully: skip the card lookup, guard, and learnings25 silently, keep the rest (the code change is the value; do not scaffold).262. **Mode + description**: `.project/` present → load once:27 `node ~/.claude/scripts/backlog-load.js "$REPO" guard-items` (the game-pipeline `stage` field28 included; reused by step 6's guard — one load, not two). The invocation argument matches a live29 `POLISH` card — exact name, or an unambiguous ≥2-shared-token match — per30 [shared/TWEAK-DISCIPLINE.md](../shared/TWEAK-DISCIPLINE.md) § Card pickup path 1?31 - **Match → card mode.** Description = the card's `description`. Run the dependency check now32 (one `AskUserQuestion` only if the card has an open, unshipped dependency).33 - **No match, or `.project/` absent → free-text mode.** Description from the invocation argument;34 if empty, ask one short question.353. **Branch guard** per [shared/TWEAK-DISCIPLINE.md](../shared/TWEAK-DISCIPLINE.md) § Branch guard:36 not on the default branch (or detached HEAD) → warn + ask before proceeding.374. **Baseline** per [shared/SCOPED-COMMIT.md](../shared/SCOPED-COMMIT.md) § 1:38 `git status --porcelain | sort > .project/session/pre-tweak-status.txt` (skip when `.project/` is39 absent).405. **Gate + guard**: Read [shared/TWEAK-DISCIPLINE.md](../shared/TWEAK-DISCIPLINE.md); run § Size41 gate on the projected scope (game surface examples: new scene, autoload, signal contract, input42 action). § Backlog guard: **card mode** → skip (the card already names the scope). **Free-text43 mode** → run § Backlog guard as before — the `guard-items` load includes the game-pipeline44 `stage` field — then § Card pickup path 2 (the POLISH-only mini-guard) against the same45 `guard-items` load from step 2.4647 > **Todo**: if any gate criterion fires or the guard demands escalation → Read48 > `.claude/skills/game-tweak/references/escalate.md` and follow it — never continue silently.49506. **Slug**: card mode → the card's own kebab `name` (no re-derivation). Free-text mode → derive a51 kebab-case slug from the description (commit scope + learnings feature key). Print the status:52 `Gate: ✓ tweak-sized · Guard: ✓ no card overlap` (or the warn/advisory lines; card mode prints53 `Card: {name}` instead of the guard line).5455## PHASE 1 — Locate & context56571. **Locate** the change with minimal reads (Grep → targeted Read; `.tscn` files: read only the58 relevant node sections). The files found here feed the size-gate re-check and the learnings load59 below.6061 **Pre-seeded from a ship de-escalation handoff** (invocation carries a `files[]` +62 `acceptance[]` pair, per [shared/TWEAK-DISCIPLINE.md](../shared/TWEAK-DISCIPLINE.md) §63 De-escalation gate (a)) → skip the Grep/Read locate itself; use the passed `files[]` as the64 located set directly. The size-gate re-check still runs against that set — the handoff is not65 an exemption from it. Hold the passed `acceptance[]` in memory and use it as PHASE 3's verify66 checklist instead of relying on whatever coverage happens to already exist.6768 > **Todo** (card mode): locate shows the described defect is already resolved on `main` — a later69 > commit fixed it, or it never applied → **stale card**. Do not invent a change to justify the70 > card. Skip PHASE 2, PHASE 3, and PHASE 4 step 1 entirely (including step 2's learnings load);71 > go straight to the PHASE 4 card-completion write per72 > [shared/TWEAK-DISCIPLINE.md](../shared/TWEAK-DISCIPLINE.md) § Card pickup → Stale card:73 > `shippedSha` = the resolving commit (`git log -- <file>`), or `HEAD` if none pins it; `summary`74 > names the card stale; commit nothing.7576 > **Todo** (card mode): locate/analysis (or an explicit user call mid-run) shows the card's whole77 > reason to exist is **superseded** by a different, wider card — not fixed, just made moot →78 > **obsolete/superseded card**. Confirm with one `AskUserQuestion` naming the superseding card79 > before touching anything. On confirmation: skip PHASE 2, PHASE 3, and PHASE 4 step 1 entirely;80 > go straight to the § Card pickup → Obsolete/superseded card cancellation write. On decline:81 > continue the tweak as originally scoped.82832. **Learnings** — mandatory, not gated on tweak size. Run exactly this, after locate so `--paths`84 carries the real file anchors (see [shared/LEARNINGS-LOAD.md](../shared/LEARNINGS-LOAD.md) for85 the full parameter/relevance model):8687 ```bash88 node ~/.claude/scripts/learnings-search.js "$REPO" load \89 --feature "{slug}" --scopes component --pitfall-prefix true \90 --paths "{located files, comma-separated, repo-relative}"91 ```9293 Any non-zero exit is a failed step, not a zero-match result — fix the invocation and re-run.94 Only exit 0 with empty stdout is a genuine zero. Include the printed block verbatim when95 non-empty, skip silently otherwise.9697## PHASE 2 — Implement98991. **Conditional plan mode** ([shared/PLAN-MODE.md](../shared/PLAN-MODE.md) § Difficulty100 escalation): call `EnterPlanMode` only when the root cause is still unclear after first evidence,101 or the change spans > 2 files. Enter → design → write the decision to the plan file →102 `ExitPlanMode` → execute. Skip entry when plan mode is already active. The typical tweak never103 enters.1042. Bugfix-shaped tweaks follow [shared/DEBUG-LADDER.md](../shared/DEBUG-LADDER.md) tier 1/2:105 hypothesis before edit, evidence before a second attempt — never guess-and-check.1063. **Mid-flight re-check**: the moment actual scope exceeds the size gate (a 4th file, a discovered107 new surface) → stop and Read `references/escalate.md`.108109## PHASE 3 — Verify light110111A tweak that changes no runnable code — only docs or gitignored `.project/` state (e.g. recording a112known issue as a learning) — or a stale or obsolete/superseded card with nothing to edit (see113PHASE 1) — has nothing to verify and nothing to commit: skip PHASE 3 and PHASE 4 step 1, say so in114the report (no commit sha line), and go straight to the card-completion (or cancellation) + learning115writes. Everything below assumes a code change.116117Scoped to the touched scripts/scenes — never the full suite unless it is genuinely fast:118119- **Lint**: `gdlint` on changed `.gd` files (gdformat already runs via the format-on-save hook).120- **Tests**: run the GUT test file(s) covering the touched scripts:121 `godot --headless --path . -s addons/gut/gut_cmdln.gd -gtest={test-file} -gexit`122 (resolve the Godot executable per `.claude/paths.local.yaml` → `CLAUDE_GODOT_EXECUTABLE`).123- **No covering test + behavior change**: ask the user for one quick scene-run confirmation instead124 of writing a new test file (a new test file is size-gate criterion 3).125126New failures vs the baseline → fix within the current tier's discipline; unfixable within tweak127scope → Read `references/escalate.md`.128129## PHASE 4 — Wrap-up1301311. **Scoped commit** per [shared/SCOPED-COMMIT.md](../shared/SCOPED-COMMIT.md). Deltas: baseline132 `pre-tweak-status.txt`; OVERLAP policy **auto-include** (the fix is the point); fallback: ask133 which files belong to the tweak; message134 `{fix|refactor|perf|style|test|docs|chore}({slug}): {summary}` — never `feat` (net-new capability135 is an escalation criterion by definition), `test` when the only change is added or expanded test136 coverage, `docs` for a docstring/comment/markdown-only edit; cleanup: remove the baseline file.1372. **Card-mode completion** (skip entirely in free-text mode): per138 [shared/TWEAK-DISCIPLINE.md](../shared/TWEAK-DISCIPLINE.md) § Card pickup completion write — flip139 the card `shipped: true` + `shippedAt` + `shippedSha` + `summary` (this tweak's one-line140 outcome), remove a board-set `transition` field if present (it was only ever the board's141 queue-marker, never a lifecycle state — see § Never), and move it from142 `backlog.json#features[]` to `.project/archive/backlog-archive.json#archived[]`. project.json143 persists no features list — the dashboard derives features from backlog + archive. **Then144 re-read `backlog.json` and confirm the card left `features[]` before reporting `shipped`** — a145 running board app (`serve-backlog.js`) re-serializes that file from its own in-memory store and146 can silently revert an external write; on a revert, re-apply and re-verify.147148 **Obsolete/superseded card instead** (PHASE 1's confirmed obsolete branch): run the § Card pickup149 → Obsolete/superseded card cancellation write instead — in place within `features[]`, flip150 `status: "CANCELLED"`, add `cancelledReason: "superseded by {card}: {one-line why}"` and151 `cancelledAt`, remove `transition`. The card stays in `features[]` (never moves to the archive —152 that move is shipped-only). Same board-app revert guard: re-read `backlog.json` and confirm153 `status: "CANCELLED"` survived before reporting; re-apply on a revert.1541553. **Optional learning (0-1)**: only for a bugfix whose root cause has value beyond this spot156 (filter per [shared/LEARNING-WRITE.md](../shared/LEARNING-WRITE.md) § Writer Append Protocol) —157 append via `learnings-write.js append` with `type: "pitfall"`, `source: "extracted"`, 0-3 tags158 (game vocabulary: `godot`, `gdscript`, `scene`, `game-loop`), then run the Consolidation Gate159 once (`LEARNING-WRITE.md § Consolidation Gate`). Skip both silently otherwise. No state auto-push160 (TWEAK-DISCIPLINE § Registration policy).1614. **Report** (compact prose, no rigid table): what changed with `file:line` refs, checks run,162 commit sha, a `Guard:` line repeating any card overlap (card mode prints `Card: {name} →163shipped`, or `Card: {name} → cancelled (superseded by {card})` for the obsolete/superseded outcome),164 a `Learning:` line when one was written, and `Escalation overridden: {criterion}` when165 applicable. Add `Next steps: /game-ship {card}` only when the guard flagged a TODO card166 (free-text mode only — card mode is already terminal). A tweak is terminal — no next-step offer167 otherwise.