Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when working on any browser game (Phaser, PixiJS, three.js, Babylon.js, PlayCanvas, Excalibur, KAPLAY) - requestAnimationFrame with clamped delta and visibility pause, zero-allocation frame loops, measuring in DevTools, bundle and asset size budgets, Vitest with seeded RNG and injected time, and a seeded Playwright smoke test with console capture.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
A browser game shares a thread with the page, a garbage collector with every closure, and a download budget with the player's patience. It is also the easiest kind of game for you to verify end to end on this machine: the build, the unit tests and a real browser run are all available. Use them.
Core principle: No allocations in the frame loop, a measured bundle, rules tested in Vitest with injected time and a seed, and one seeded Playwright smoke test that fails on console errors.
requestAnimationFrame (or the engine's loop built on it); never setInterval.document.visibilitychange, and resume without a catch-up burst.resume() the AudioContext on the first click/key/tap.touch-action: none so gestures do not scroll or zoom the page.// ❌ allocates every frame: new vectors, arrays, closures
function update(dt: number) {
const dir = new THREE.Vector3().subVectors(target.position, enemy.position).normalize();
enemies.filter((e) => e.alive).forEach((e) => e.step(dt));
hud.setText(`Score: ${score}`);
}
// ✅ reuses module-level temporaries; plain loops; updates text only on change
const tmp = new THREE.Vector3();
let shownScore = -1;
function update(dt: number) {
tmp.subVectors(target.position, enemy.position).normalize();
for (let i = 0; i < enemies.length; i++) if (enemies[i].alive) enemies[i].step(dt);
if (score !== shownScore) { shownScore = score; hud.setText(`Score: ${score}`); }
}
Pool bullets, particles and damage numbers; prefer typed arrays (Float32Array) for large particle or boid sets; avoid Array.prototype.map/filter/forEach with fresh closures in hot paths.
Minor GC) in the frame track.renderer.info (three.js), Babylon Inspector statistics, PixiJS devtools, Phaser's debug FPS.performance.mark/performance.measure around a system to get numbers into a test or log.npm run build lists chunk sizes; add rollup-plugin-visualizer only if the repository already has it.import().// src/logic/rng.ts
export function mulberry32(seed: number) {
return () => { seed |= 0; seed = (seed + 0x6d2b79f5) | 0; let t = Math.imul(seed ^ (seed >>> 15), 1 | seed);
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; };
}
// src/logic/spawner.test.ts
import { describe, it, expect } from "vitest";
import { Spawner } from "./spawner";
import { mulberry32 } from "./rng";
describe("Spawner", () => {
it("spawns one wave every 5 seconds regardless of step size", () => {
const a = new Spawner({ waveEverySeconds: 5 }, mulberry32(1));
const b = new Spawner({ waveEverySeconds: 5 }, mulberry32(1));
for (let i = 0; i < 600; i++) a.step(1 / 60);
for (let i = 0; i < 300; i++) b.step(1 / 30);
expect(a.wavesSpawned).toBe(2);
expect(b.wavesSpawned).toBe(2);
});
it("is deterministic for a seed", () => {
const run = () => { const s = new Spawner({ waveEverySeconds: 1 }, mulberry32(42)); for (let i = 0; i < 180; i++) s.step(1 / 60); return s.positions(); };
expect(run()).toEqual(run());
});
});
vi.useFakeTimers() and vi.advanceTimersByTime(ms).NullEngine in Vitest.// e2e/smoke.spec.ts
import { test, expect } from "@playwright/test";
test("boots, takes input, no console errors", async ({ page }) => {
const errors: string[] = [];
page.on("pageerror", (e) => errors.push(e.message));
page.on("console", (m) => { if (m.type() === "error") errors.push(m.text()); });
await page.goto("/?seed=42&scene=Level1&debug=1");
await expect(page.locator("canvas")).toBeVisible();
await expect.poll(() => page.evaluate(() => (window as any).__GAME__?.ready)).toBe(true);
await page.keyboard.press("Space");
await expect.poll(() => page.evaluate(() => (window as any).__GAME__?.player.jumps)).toBe(1);
await page.screenshot({ path: "test-results/level1-after-jump.png" });
expect(errors).toEqual([]);
});
window.__GAME__ read-only debug handle exposed only in debug/dev builds lets tests assert state instead of guessing from pixels.toHaveScreenshot) only with the loop paused on a deterministic frame and a tolerance; GPU differences make exact matches flaky.npx playwright test); if Playwright is not set up and not installed, use the browser tools and say what the smoke run would have covered (game-visual-self-review).setInterval loops; unclamped delta after a background tab.new inside the rAF callback or a system's update.pageerror listener.아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.
Use when the repository keeps its alerting in code, or a person asks for alerts outside TaskTrooper - PrometheusRule YAML, a Cloud Monitoring alert policy in Terraform, a Datadog monitor, each routed to TaskTrooper's alert ingest URL so it opens an incident here
한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.