| name | proximo-passo |
| description | Advances the Navecraft roadmap (TODO.md) by one step: reads TODO.md, picks the single best code-only next item, implements it end-to-end (code + tests), updates TODO.md honestly, and writes a complete report of what happened. Use this whenever the user wants to advance the phased roadmap tracked in TODO.md (not to edit an inline `# TODO` comment) — e.g. "fazer o proximo passo do TODO", "advance the roadmap", "advance the TODO", "pick and do the next thing", "do the next thing/item", "implementar o proximo item", "faz o proximo item", "continue the roadmap / TODO.md", or asks Claude to autonomously choose and ship the next pending task from TODO.md. Trigger on the slash command /proximo-passo, or on bare phrases like "proximo passo" / "next step" ONLY when the user clearly means advancing TODO.md (not a generic "what do I do next?" in an unrelated planning or debugging conversation). |
Próximo Passo — Advance the Navecraft TODO
Pick the best next thing from TODO.md, actually build it, prove it works,
record it, and report — one atomic step per run. This skill turns the roadmap
into forward motion without sprawl: it does one well-chosen item completely
rather than many things halfway.
The Navecraft TODO is deliberately honest (it distinguishes code-only work from
DEFERIDO and REQUIRES EXTERNAL ACTION). Honor that philosophy: only pick
work that can truly be finished with code in this repo, and never record
progress — checkbox, metrics, date, or report — for anything that isn't green.
The loop at a glance
- Preconditions — clean tree + green baseline before touching anything.
- Read & discover — parse
TODO.md, list the live code-only candidates.
- Select — choose ONE atomic item using the priority heuristic below.
- Implement — build it respecting the repo's architecture (see CLAUDE.md).
- Verify — run the full headless test suite; it MUST be green to proceed.
- Update TODO.md — flip the checkbox, annotate, refresh metrics + dates.
- Report — write
docs/reports/<date>-<id>-<slug>.md + a chat summary.
- Commit & push — commit this run's changes on
main and push to origin.
Do not skip the step-4 gate, and do not do more than one item. If you finish
early and want to keep going, run the skill again — each run is a clean,
reviewable unit of work.
Commands below use the POSIX venv path .venv/bin/python (this repo is
cross-platform). On Windows, activate first (.venv\Scripts\activate) and use
plain python, and set the SDL vars with PowerShell syntax
($env:SDL_VIDEODRIVER='dummy'; $env:SDL_AUDIODRIVER='dummy'; ...) as
documented in CLAUDE.md.
Step 0 — Preconditions (establish a clean, green baseline)
Both protect the honesty gate's "leave the tree as you found it" promise:
- Clean working tree. Run
git status --short. If anything unrelated is
already modified/staged, note that pre-existing diff (or git stash it) so
"as you found it" is well-defined and your later revert is scoped — never a
blanket git clean/git checkout . that would nuke someone else's work.
- Green baseline. Run the full suite once before implementing:
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy .venv/bin/python -m unittest discover -s tests
If it is already red, stop: report the pre-existing failure(s) by name and
do not start an item. (This makes any later red unambiguously yours.) Record
the baseline pass count — you'll compare against it in step 4/5.
Step 1 — Read & discover
Read TODO.md in full (it carries the project's real status, the priority
ordering, and the annotation style you must match).
Then run the deterministic candidate finder — it strips out DEFERIDO and
REQUIRES EXTERNAL ACTION items (including ones tagged only at a section
heading) and items with human/account dependencies, leaving a clean list:
.venv/bin/python .claude/skills/proximo-passo/scripts/find_candidates.py
The script discovers; you decide. Its LIVE list is the menu. Its
EXCLUIDOS list is off-limits unless the user explicitly asks for one. The
script is a heuristic aid — still read the full TODO.md and apply judgment; if
a LIVE item turns out on inspection to need art/accounts/external work, drop
it and pick another.
If the LIVE list is empty (everything remaining is deferred or external),
stop and report that honestly: summarize what's left, point out which DEFERIDO
items could plausibly be un-deferred with code, and ask the user how to proceed.
Do not silently pick an external/deferred item.
Step 2 — Select the best next step
Choose exactly one atomic sub-item (e.g. Y.2.1, not all of Y.2). Make
the choice reproducible — two runs of this skill should land on the same
item — by applying this order:
- Roadmap order, advanced past what's done.
TODO.md has a
## PROXIMOS PASSOS RECOMENDADOS list, but it ranks phase groups
(e.g. "Fase Y.1–Y.2"), not atomic items, and its early entries are often
already FEITO. Treat completed entries as satisfied and advance to the
first group that still has LIVE candidates (per find_candidates.py).
- Lowest-numbered atomic item within that group. When the roadmap orders
only groups and not the items inside them (the usual case), pick the
lowest-numbered non-
DEFERIDO/non-external item in the chosen group — e.g.
within Y.2, pick Y.2.1 before Y.2.2. This is the deterministic
tiebreaker.
- AAA-impact tiebreak (only when groups are genuinely equal). The project's
north star is "pessoa random abre, joga 30 min, tem prazer, sem manual."
If two groups sit at the same roadmap priority, prefer the one a new player
feels (game feel, clarity, audio/visual polish, smarter enemies) over
invisible internals — unless an internal item unblocks others.
- Lowest blast radius. All else equal, favor additive changes in a single
subsystem over edits that ripple through
core/game.py's hot update loop.
State your choice and the one-line reason before implementing.
Respect the user's steer. If the invocation named or hinted at an item/area
("faz o de audio", "the boids one", "Y.3.1"), pick that — as long as it's a
LIVE candidate. If they pointed at an EXCLUIDOS item, say why it's excluded
and offer the nearest live alternative.
Step 3 — Implement
Build the item for real — production quality, not a stub. Internalize and obey
the architecture contracts in CLAUDE.md before touching code. The ones that
bite hardest:
- Where code goes. World/gameplay → the
Game class in core/game.py.
Window/state/overlay routing → Navecraft in main.py. New tunables →
settings.py. New subsystem → its own module under systems/ (or core/),
constructed in Game.initialize_world() in dependency order.
- Screen size. Read
display.WIDTH/HEIGHT/ui_scale() per-render from
utils.display; never snapshot settings.SCREEN_*.
- Input lifecycle. Don't move
InputManager.clear_frame() — it runs at the
END of Game.update(). is_control_just_pressed checks happen mid-update.
- Feedback/juice. Route floating text, shake, hitstop, flash, slowmo through
the
feedback singleton (systems/feedback.py) — e.g. feedback.floating(...).
- Audio. SFX are synthesized from numpy in
core/audio.py via
_make_tone(...); music crossfades calm/combat. Extend that machinery,
don't add asset files — everything is procedural at runtime, no assets.
- Strings are PT-BR first. Comments and base in-game text stay Portuguese.
Any user-visible string goes through
utils/i18n.t('your.new.key') and you
add the key to all three languages (pt base, plus en and es).
⚠️ Missing en/es keys fail silently: i18n.t() falls back to pt
then to the raw key, and no test enforces cross-language parity — so the suite
in step 4 will NOT catch a half-translated key. Before finishing, verify each
new key landed in all three dicts, e.g. grep -c "'your.new.key'" utils/i18n.py
should print 3 (better: add a parity assertion in tests/, mirroring the
pattern around tests/test_v13_features.py's tutorial-key checks).
- Keys. New main controls go in
settings.CONTROLS and must not collide
with multiplayer numpad bindings (TestMultiplayerKeyConflicts guards this).
- Accessibility. Honor
is_reduce_motion() in any motion-heavy code.
- Save schema. If you persist new state, bump/extend the versioned
SaveSystem schema rather than breaking it.
Add a regression test. The project tags completed items with a test
reference (e.g. the real tests/test_v13_features.py::TestLeaderboard). Match
that: add or extend a test in tests/ that exercises the new behavior. New
deterministic systems deserve property/edge tests; new render paths deserve a
smoke-render assertion. Follow the conventions already in tests/ (a
pygame.display is created at import; keep tests headless-safe).
Keep the change focused on the selected item. Resist scope creep — unrelated
cleanups belong to their own future step.
Step 4 — Verify (hard gate)
Run the full suite headless. The env vars are required or pygame won't init
without a display/audio device.
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy .venv/bin/python -m unittest discover -s tests -v
- All green → proceed to step 5. Record the final pass count from the summary
line (e.g.
Ran N tests ... OK) — you'll cite it in step 5 and the report.
- Red → first compare against the step-0 baseline; only tests your change
broke are yours to fix. If you cannot get back to green within reason, perform
a scoped revert and stop:
- restore the tracked files you edited:
git checkout -- <those files>;
- delete only files this run created (new
tests/*.py, the report) — never a
blanket git clean -fd;
- make no edits to
TODO.md (no checkbox, no metrics, no dates) and write
no report; then report what blocked you.
Never record progress over a failing suite — that breaks the TODO's honesty
contract.
Step 5 — Update TODO.md (green path only)
Edit TODO.md to reflect reality, matching the existing annotation density and
voice (look at neighboring - [x] lines — terse, with a file/function and a
test reference). Keep PT-BR; minimal, surgical diff; don't reflow unrelated lines.
- Flip the chosen item
- [ ] → - [x] and append a short note: what was
done, the file/function where it lives, and the real test reference.
⚠️ The test reference MUST be a class/function you actually added and that ran
green in step 4 — do not invent one. Shape to mirror surrounding lines, e.g.:
- [x] Y.2.1. Envelope ADSR suavizado em core/audio.py::_make_tone (release ramp); cobertura em tests/<arquivo>::<SuaClasseDeTeste>.
- Phase header status. If a header carried
- PARCIAL and this item
completes the phase, update it to - FEITO; otherwise leave it.
- Metrics block (
## METRICAS DE ESTADO): set the test count to step 4's
number. The bullet carries a running delta (**N testes automatizados** (+M desde v1.2)) — update both: recompute M against the documented v1.2
baseline, or restate as (+K nesta run); never leave a now-wrong delta. Add a
one-line bullet for what shipped, and update the **REVISADO EM:** date at
the bottom of the section to today (same date +%F value as item 4 below).
- Top-of-file header. Update the
> **Status atual real (DATE...)** date to
today (date +%F) and, in one clause, what this run delivered.
Step 6 — Write the report
Write a complete report to docs/reports/<YYYY-MM-DD>-<id>-<slug>.md (create
docs/reports/ if absent). Filename rules, so re-runs stay deterministic and
never clobber a prior report:
- date:
date +%F. branch: git branch --show-current (normally
main — the report is written just before the Step 7 commit, on that branch).
- id: the item id with dots → hyphens (
Y.2.1 → y-2-1).
- slug: lowercase the item title, drop the leading id and trailing period,
take the first 3–4 significant words, kebab-case them.
- collision: if the target file exists, append
-2, -3, … — never overwrite.
Then give the user a tight chat summary (3–6 lines) linking the report file and
the changed files. Use this structure (Portuguese, to match the repo — translate
headings only if the user is clearly working in English):
# Relatório — <id>: <título curto>
**Data:** <YYYY-MM-DD> · **Skill:** proximo-passo · **Branch:** <branch>
## 1. Passo escolhido
- **Item:** <id> — <texto do TODO>
- **Por que este:** <1–2 frases ligando à prioridade/impacto>
- **Candidatos considerados e descartados:** <breve>
## 2. O que foi implementado
<Comportamento novo, do ponto de vista do jogador e do código.>
## 3. Mudanças no código
| Arquivo | Função/área | O que mudou |
|---|---|---|
| `core/...` | `...` | ... |
<Inclua novas chaves i18n (pt/en/es), tunables em settings.py, etc.>
## 4. Testes
- Teste(s) adicionado(s)/estendido(s): `tests/...::...`
- Baseline (passo 0) e resultado final da suíte (headless): `Ran N tests ... OK`
- Comando: `SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy .venv/bin/python -m unittest discover -s tests -v`
## 5. TODO.md atualizado
<Checkbox que virou [x]; métricas (contagem + delta); datas do header e do REVISADO EM.>
## 6. Conformidade com a arquitetura
<Como respeitou as regras do CLAUDE.md relevantes ao item — i18n pt/en/es,
display.*, feedback, ordem do update loop, etc.>
## 7. Riscos & próximos passos
- Riscos/limitações conhecidos: ...
- Próximo passo natural sugerido: <id> — <motivo>
## 8. Como verificar manualmente
<Passos para ver o efeito in-game: rode `python main.py`, faça X, observe Y.
Se for interno, descreva o que olhar no log/teste.>
Step 7 — Commit (directly on main)
Commit this run's changes straight to main — no PR branch. This is reached
only on the green path (after a passing suite and the written report), so a
commit always corresponds to a finished, verified, recorded item.
- Stay on
main. This skill commits in place; do not create or switch
branches. (Confirm with git branch --show-current.)
- Stage only what this run touched, by explicit path — the edited
source/tests,
TODO.md, and the new report — e.g.
git add core/... tests/... TODO.md docs/reports/<file>.md. Never
git add -A / git add .: that would sweep in any unrelated pre-existing
changes you noted in Step 0.
- Commit with a Conventional-Commits subject naming the item, a short body,
and the co-author trailer:
feat(<id>): <slug>
<1–2 lines: what shipped + the test reference>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Push to
origin/main. Run git push origin main so the remote stays in
sync every run. State the commit hash (and that it was pushed) in your chat
summary. If the push is rejected because the remote moved ahead, run
git pull --rebase origin main, re-run the suite to confirm it's still green,
then push again — never force-push.
If the suite went red (Step 4), you never reach this step — there is nothing to
commit because the tree was already restored to as-found.
Invariants & safety rails
- One atomic item per run. Scope discipline is the whole point.
- Never record progress over a red suite — no checkbox, no metrics/date edit,
no success report unless step 4 is green. Honesty > throughput.
- Scoped revert only. On failure, restore exactly what you touched and delete
only what you created; never a blanket
git clean/git checkout ..
- Procedural only. No new binary/asset files — synthesize at runtime.
- PT-BR base + en/es for every user-visible string (and verify the en/es keys
landed — they fail silently).
- Commit then push to
origin/main after a green report (Step 7). Stage only
this run's files by explicit path — never git add -A. A commit/push only ever
follows a passing suite + written report; on a red suite there is nothing to
commit. Never force-push. Co-author trailer:
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>.
- Minimal diff, repo's voice. Touch only what the item needs; match the
comment density, naming, and idiom of the surrounding code and the annotation
style already in
TODO.md.
Notes on scaling the work
Most items are small enough to do inline. For a genuinely large item (e.g. a new
enemy-AI subsystem touching several files), it's fine to plan first and, if the
session supports it, fan the research out to subagents — but the
implement → verify → update → report spine stays exactly as above, and it still
ships as one atomic TODO item.