google-agents-cli-scaffold
Project scaffolding, deployment configuration, and CI/CD setup for Google ADK agents.
gd-validation-playtest
Playwright-based game playtesting and design validation. Use when validating implementation against GDD, testing gameplay mechanics, capturing screenshot evidence, performing game state detection via Vision MCP, or conducting visual GDD compliance validation.
Full skill instructions
Skip playtest for:
Playtest IS required for:
Triggers (any of these):
.claude/session/retrospective.txt contains "[ ] Request playtest"prd.json.session.currentTask.status = "playtest_phase"playtest_session_request messageWhen ANY trigger is true, initiate playtest flow:
⚠️ CRITICAL RULES:
playtest_report - MUST be sent to PM FIRSTNon-negotiable evidence in playtest_report:
.claude/session/screenshots/playtest-{taskId}-*.pngplaytest_report message sent to PMIf Playwright MCP unavailable:
question to PM immediately: "Playwright MCP unavailable - cannot playtest"# Start the dev server
Bash("npm run dev:all:sh")
# Wait for "Vite ready" and "Colyseus server listening" in output
// Navigate to game (detect port first: netstat -an | grep LISTEN | grep -E ":(3000|3001|5173|8080)")
await page.goto('http://localhost:3000');
await page.waitForLoadState('networkidle');
// Capture initial state
await page.screenshot({ path: 'screenshots/playtest-start.png' });
For each mechanic in GDD:
// Test movement
await page.keyboard.down('KeyW');
await page.waitForTimeout(1000);
await page.keyboard.up('KeyW');
// Test interaction
await page.click('[data-testid="interact-button"]');
// Test combat
await page.click('[data-testid="attack-button"]');
// Capture state
await page.screenshot({ path: 'screenshots/mechanic-tested.png' });
For each GDD requirement:
Create playtest report:
{
"taskId": "feat-001",
"playtestedAt": "2025-01-21T12:00:00Z",
"gddCompliance": {
"mechanic-name": {
"status": "matches|deviates|missing",
"notes": "Description"
}
},
"deviations": [
{
"feature": "Mechanic name",
"expected": "GDD description",
"actual": "What happens in game",
"severity": "low|medium|high",
"screenshot": "path/to/evidence"
}
],
"issues": [
{
"type": "bug|missing|polish",
"description": "Issue description",
"severity": "low|medium|high|critical",
"steps": "How to reproduce"
}
],
"screenshots": ["path/to/screenshot1.png", "path/to/screenshot2.png"],
"overall": {
"status": "pass|fail|partial",
"funFactor": 4,
"notes": "Overall assessment"
}
}
Bash("npm run dev:all:sh")
// Navigate and wait for load
await page.goto('http://localhost:3000');
await page.waitForLoadState('networkidle');
// Keyboard input
await page.keyboard.press('KeyW');
await page.keyboard.up('KeyW');
// Mouse input
await page.mouse.click(x, y);
await page.mouse.down();
await page.mouse.up();
// Touch simulation
await page.touchscreen.tap(x, y);
// For game character movement, use key down/up patterns
// Single press() only simulates a quick tap
// Forward movement
await page.keyboard.down('KeyW');
await page.waitForTimeout(1000); // Move for 1 second
await page.keyboard.up('KeyW');
// Diagonal movement with sprint
await page.keyboard.down('KeyW');
await page.keyboard.down('KeyD');
await page.keyboard.down('ShiftLeft');
await page.waitForTimeout(2000);
await page.keyboard.up('ShiftLeft');
await page.keyboard.up('KeyD');
await page.keyboard.up('KeyW');
// Combo sequence
async function executeCombo(page, sequence) {
for (const action of sequence) {
await page.keyboard.down(action.key);
await page.waitForTimeout(action.hold);
await page.keyboard.up(action.key);
await page.waitForTimeout(50); // Combo window
}
}
// Three-hit melee combo
await executeCombo(page, [
{ key: 'KeyJ', hold: 100 },
{ key: 'KeyJ', hold: 100 },
{ key: 'KeyK', hold: 200 },
]);
Use Vision MCP to analyze screenshots and determine current game state:
// Detect game state from screenshot
async function detectGameState(screenshotPath) {
const analysis = await visionAnalyze(screenshotPath, {
prompt: `Analyze this game screenshot and determine:
1. Is this a menu screen, gameplay, game over, victory, or loading?
2. What UI elements are visible? (HUD, health bar, minimap, inventory)
3. Is the player character visible?
4. Are there any error messages?
Respond in JSON:
{
"state": "menu|playing|gameover|win|loading|error",
"uiElements": ["hud", "healthBar", ...],
"playerVisible": true|false,
"details": "description"
}`,
});
return JSON.parse(analysis);
}
// Usage during playtest
await page.screenshot({ path: 'playtest/state-1.png' });
const state = await detectGameState('playtest/state-1.png');
console.log('Current state:', state.state);
// Compare implementation against GDD visual requirements
async function validateVisualGDD(screenshotPath, gddRequirement) {
const analysis = await visionAnalyze(screenshotPath, {
prompt: `According to this GDD requirement:
"${gddRequirement}"
Does the screenshot match? Check:
1. Required elements are present
2. Visual style is correct
3. Colors/theme match specification
4. Layout is as described
Return {
"matches": true|false,
"deviations": [
{ "element": "name", "expected": "spec", "actual": "observed" }
],
"severity": "low|medium|high"
}`,
});
return JSON.parse(analysis);
}
// Example: Validate character appearance
const characterGDD = 'A knight in silver armor with blue cape, holding sword';
const result = await validateVisualGDD('playtest/character.png', characterGDD);
// Compare current state with baseline or previous state
async function comparePlaytestStates(beforePath, afterPath) {
const comparison = await visionAnalyze([beforePath, afterPath], {
prompt: `Compare these two gameplay screenshots.
Image 1 is BEFORE the action.
Image 2 is AFTER the action.
What changed?
1. Did player position change?
2. Did UI elements change (health, score, ammo)?
3. Are there new visual effects?
4. Any bugs or glitches visible?
Return {
"playerMoved": true|false,
"uiChanges": ["health decreased", "score increased", ...],
"newEffects": ["explosion", "particle", ...],
"issues": ["list of visual problems"]
}`,
});
return JSON.parse(comparison);
}
// Get console messages
page.on('console', (msg) => {
console.log(msg.text());
});
// Get page content
const content = await page.content();
// Screenshot
await page.screenshot({
path: 'screenshots/evidence.png',
fullPage: true,
});
// PDF
await page.pdf({
path: 'report.pdf',
});
// Video (if supported)
// Start recording before gameplay
Does the feature work as intended?
Does it match the GDD?
Is it fun?
| Issue | Check Method |
|---|---|
| Console errors | Check browser console |
| Visual glitches | Compare to reference |
| Input lag | Test responsiveness |
| Performance | Monitor FPS |
| Crashes | Try stress scenarios |
# Playtest Report - [Task Name]
**Date:** YYYY-MM-DD
**Tester:** Game Designer Agent
**GDD Version:** X.X.X
## Summary
[Overall assessment]
## GDD Compliance
| Mechanic | Status | Notes |
| -------- | -------- | --------- |
| [Name] | ✅/❌/⚠️ | [Details] |
## Deviations Found
| Feature | Expected | Actual | Severity |
| ------- | -------- | -------- | -------------- |
| [Name] | [GDD] | [Actual] | [High/Med/Low] |
## Issues Found
| ID | Type | Description | Severity | Status |
| --- | ------ | ------------- | -------- | ------ |
| 1 | [Type] | [Description] | [Level] | [Open] |
## Recommendations
1. [Improvement 1]
2. [Improvement 2]
3. [Improvement 3]
## Screenshots


After completing playtest, use Write tool to send message to PM's inbox:
// Use Write tool to send message:
Write(
'.claude/session/messages/pm/msg-playtest-{timestamp}.json',
JSON.stringify({
id: 'msg-playtest-{timestamp}',
from: 'gamedesigner',
to: 'pm',
type: 'playtest_report',
priority: 'high',
payload: {
// Include all findings from playtest
},
timestamp: '{UTC-timestamp}',
status: 'pending',
})
);
When retrospective initiated:
Before completing playtest:
Learned from ui-001 playtest: Functionally complete UI can still be visually inadequate for shipping.
| Category | Pass Criteria | Weight |
|---|---|---|
| Aspect Ratio | 16:9 enforced, letterbox on non-16:9 | High |
| Design System | Tokens, consistent styling, reusable components | High |
| Typography | Gaming fonts, readable, appropriate scale | Medium |
| Button Polish | Hover/active states, feedback animations | High |
| Color Palette | Theme-appropriate, accessible contrast | Medium |
| Animations | Smooth, custom easing, not default/linear | Medium |
| Professional Appearance | Not prototype-like, shipping quality | High |
| Level | Description | Action |
|---|---|---|
| SHIPPABLE | All visual criteria met, professional appearance | PASS |
| CONDITIONAL | Functional but needs polish | CONDITIONAL_PASS |
| PROTOTYPE | Looks like prototype, not shipping game | FAIL - Create redesign task |
Use CONDITIONAL_PASS when:
Mandatory Actions on CONDITIONAL_PASS:
Example:
{
"result": "CONDITIONAL_PASS",
"functionalStatus": "PASS",
"visualStatus": "NEEDS_REDESIGN",
"gaps": [
"No 16:9 aspect ratio enforcement",
"Basic Tailwind styling instead of custom design",
"Generic fonts instead of gaming typography",
"No custom easing curves for animations"
],
"recommendation": "BLOCK until visual design addressed",
"newTask": {
"id": "ui-002",
"title": "Professional UI/UX Redesign",
"priority": "TIER_0_BLOCKER"
}
}
Project scaffolding, deployment configuration, and CI/CD setup for Google ADK agents.
Set up tracing, logging, and monitoring for deployed ADK agents across Cloud Trace, BigQuery, and third-party platforms.
Enterprise Azure infrastructure architect generating Bicep or Terraform from workload descriptions.
Plan and configure production-ready Azure Kubernetes Service clusters with Day-0 and Day-1 best practices.
Raw mechanical interfaces fusing Swiss typographic print with military terminal aesthetics. Rigid grids, extreme type scale contrast, utilitarian color, analog degradation effects. For data-heavy dashboards, portfolios, or editorial sites that need to feel like declassified blueprints.
Web search, scraping, extraction, crawling, and monitoring via ScrapeGraph AI CLI.
Skill for working with Firebase Hosting (Classic). Use this when you want to deploy static web apps, Single Page Apps (SPAs), or simple microservices. Do NOT use for Firebase App Hosting.
Deploy and manage web apps with Firebase App Hosting. Use this skill when deploying Next.js/Angular apps with backends.
Deploy applications and websites to Vercel. Use when the user requests deployment actions like "deploy my app", "deploy and give me the link", "push this live", or "create a preview deployment".
Build SEO-optimized pages at scale using templates, data, and proven playbook patterns.
Design and build isolated, reusable Convex backend components with clear boundaries and app-facing wrappers.
Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".
Opus.ai: Revolutionize Your Web Experience
Build a no-code AI app in minutes.
An IDE for code migration from legacy to modern frameworks through coding agents.
Automate CGI animation in live-action scenes
Branded artistic QR-code concepts
Launch a website in seconds with AI.
Streamline Your Coding Experience with AI Code Helper
Convert any screenshot or design to clean code.