Repository navigation
Scribble lab: Spec Kit artifacts and full game implementation - #151
Open
manojm-ship-it wants to merge 40 commits into
Open
manojm-ship-it wants to merge 40 commits into
manojm-ship-it wants to merge 40 commits into
Conversation
Add Spec Kit scaffolding (.specify/ templates and scripts, .claude/skills speckit-* commands) and ignore the local temp/ working-notes folder. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Constitution covers brownfield discipline, server-authoritative game rules, scope boundaries, coding standards, verification gates and AI usage rules. Discovery notes list 10 gaps, 6 assumptions and the relevant starter files, mapped to the four feature groups. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec covers Scenario 1 (host, code validation, isolation, 2 s polling, host-only start with 2+ players, idle cleanup) with 3 clarifications. Plan adds research R1-R8, data model, rooms API contract and quickstart; tasks.md breaks the work into T001-T029 by user story. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The default API base URL ended in /bug, so every request 404'd unless VITE_API_URL was set (discovery gap 1, FR-001). Adds a test pinning the default URL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…able errors - Room gains hostId and lastActiveAt; status widens to lobby | playing; snapshots expose hostId (T003, plus T008's createRoom/snapshot change, which the new required field needs in the same commit to compile). - errorHandler returns the Zod issue message (T004, FR-015). - Room codes are trimmed, checked as 4 letters/digits and upper-cased in the params schema, replacing per-route toUpperCase (T005, FR-005/006). - Schema tests for valid, blank and malformed codes (T006). - Frontend ApiError carries the HTTP status; snapshot types updated (T007). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tests that the creator is host, snapshots expose hostId and 50 rooms get distinct codes. The lobby labels the host and the viewer's own entry "(you)" (FR-002, FR-003, FR-004). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
joinRoom throws 404 "Room not found. Check the code and try again." or 409 "This game has already started." and refreshes lastActiveAt; the route no longer maps null itself. The join form refuses an empty code before calling the API (FR-006, clarification: no late joins). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
getRoom refreshes lastActiveAt, and a missing room now reports "This room is no longer available." The lobby polls every 2000 ms while mounted; a 404 clears the room via RoomStore.clearRoom and the start page shows the notice; other errors keep the last snapshot (FR-007, FR-008). Uses a dedicated notice field rather than error - recorded as a deviation in plan.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
startGame checks room exists (404), requester is host (403), room still in lobby (409) and at least 2 players (400) before moving it to playing; exposed as POST /rooms/:code/start with a Zod-validated body. The lobby shows Start only to the host (disabled under 2 players), tells guests to wait, and navigates everyone to /game once the polled snapshot is playing (FR-009 to FR-012). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
removeInactiveRooms(now) deletes rooms whose lastActiveAt is older than ROOM_IDLE_LIMIT_MS (30 min); server.ts sweeps every 60 s on an unref'd timer. Tests cover removal, retention within the limit, and that joining/starting one room leaves another unchanged (FR-013, FR-014). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ipant id Found during T027 API validation: a missing participantId returned Zod's default "Required", which breaks FR-015. Adds a required_error and a schema test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found during T028 two-browser validation (row 9): with the backend down the lobby showed the browser's raw "Failed to fetch". request() now turns network failures into ApiError(0, "Can't reach the game server. Check your connection and try again.") (FR-008), with a test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All quickstart API and two-browser rows pass after two fixes found during validation. Records results in tasks.md, deviations in plan.md, and renames the isolation test so it is findable by name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er flow Spec covers Scenario 2 (trimmed, required names; host becomes drawer; deterministic word visible only to the drawer) with 3 clarifications: word rule (code char sum + games started) mod 5, hide the candidate word list, 20-character name limit. Plan adds research R1-R8, data model, contract changes and quickstart; tasks T001-T018. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Room gains drawerId, secretWord (both null in the lobby) and gamesStarted (0 at creation); snapshots expose drawerId and an optional secretWord. Frontend snapshot type updated to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A shared playerNameSchema (create and join) trims names and refuses missing/blank names with "Enter your name." and names over 20 characters with "Names can be at most 20 characters.". The "Player" fallback is removed. Feature 001's quickstart join checks now send a name, since body validation runs before the room lookup (FR-001-003a). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
selectSecretWord(code, gamesStarted) picks STARTER_WORDS[(sum of code char codes + gamesStarted) % 5]. startGame records the host as drawer, sets the word with the current count and increments it. Tests pin ABCD/0 -> pizza, ABCD/1 -> castle, AAAA/0 -> rocket, repeatability, and lobby rooms having neither (FR-004, FR-006, FR-008). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The game page's Player Info card replaces the static "Playing" status with "<name> is drawing" and "You are the drawer" / "You are guessing" (FR-005). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
toRoomSnapshot now uses its viewer argument: secretWord is included only when the viewer is the drawer. availableWords, roles, listWords and the frontend ParticipantRole type are removed (no screen used them). The game page shows "Your word: <word>" to the drawer and a hidden-word message to guessers. Tests cover drawer, guesser, unknown, anonymous and lobby views (FR-007, FR-008, FR-009). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All quickstart API and two-tab checks pass on the first run; no deviations from the plan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec covers Scenario 3 (drawer canvas with clear; trimmed, case-insensitive guesses with empty ones refused; 100/0 scoring; history and scores synced by 2 s polling) with 3 clarifications: the round ends when every guesser is correct, the canvas is drawer-only, and correct guess text is hidden while the round is active. Plan adds research R1-R8, data model, contract and a three-tab quickstart; tasks T001-T023. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Participants gain a score (0 on create/join); rooms gain a guess list; status can now be ended; snapshots carry guess views. Frontend types mirror the change. Also corrects quickstart row 8: a guesser who already guessed has a disabled form, so the repeat refusal is checked via the API. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
submitGuessSchema trims guesses and refuses blank ones ("Enter a
guess."). submitGuess refuses guesses outside an active round, from
non-players, from the drawer and repeats after a correct guess; compares
case-insensitively; adds 100 for a correct guess; and ends the round
once every guesser is correct. startGame resets scores and guesses.
POST /rooms/:code/guesses exposes it (FR-004 to FR-009, FR-013, FR-014).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
api.submitGuess and RoomStore.submitGuess post to the new endpoint; GuessForm takes an onSubmit prop, clears on success and shows refusal messages. GamePage passes it (disabled for the drawer); the rest of the game-screen wiring follows in T016. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
toRoomSnapshot sends text: null for correct guesses while the room is playing, for every viewer, and reveals it once the round has ended. Tests cover drawer, guessers and anonymous viewers, and order (FR-011). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves the lobby's 2 s polling, 404 handling and refresh-error state into a hook so the game screen can share it. LobbyPage behaviour unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…reen GamePage polls every 2 s via useRoomPolling. Scoreboard lists every player's score; the Activity panel shows the history in order, with correct guesses as "<name> guessed the word!" while hidden. The guess form is disabled for the drawer, after a correct guess and once the round is over, which is announced on screen (FR-009 to FR-012, FR-014). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DrawingCanvas draws freehand lines with pointer events (mouse and touch, coordinates scaled to the 800x500 surface) and clears with one button. Only the drawer gets it; guessers see "<name> is drawing". Strokes stay in the drawer's browser, as clarified (FR-001 to FR-003). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found during T022 three-tab validation: the notice used .status-line, whose width: max-content stretched the right sidebar past the panel and clipped its text. It is now a plain paragraph that wraps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All API and three-tab checks pass, plus feature 001 lobby regression rows for the extracted polling hook; one layout fix found during validation. Deviations recorded in plan.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Spec covers Scenario 4 (word, final scores and full history shown to everyone; host-only restart back to the lobby with players kept and round state cleared) with 2 clarifications: the host may restart mid-round, and the bouncing Exit Game button is removed. Plan adds research R1-R6, data model, contract and quickstart; tasks T001-T014. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Once the round has ended, every viewer's snapshot includes the secret word (still drawer-only while playing). A RoundResult card shows "The word was <word>" and final scores highest first; the Activity panel already shows the revealed history (FR-001 to FR-003). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
restartGame refuses rooms still in the lobby ("The game has not started
yet.") and non-hosts ("Only the host can restart the game."), then
returns the room to the lobby with players, host and games-started count
kept and drawer, word, guesses and scores cleared. Works from an active
or ended round; exposed as POST /rooms/:code/restart. Tests cover the
rules, the reset, duplicates, mid-round restart and the next word
(FR-004 to FR-006, FR-008).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
api.restartGame and RoomStore.restartGame call the new endpoint. The result card shows "Play again" to the host and a waiting message to others; during a round the host can "End game and return to lobby". Every game screen moves to the lobby when the polled room is back in the lobby. The bouncing "Exit Game" button is removed (FR-007, FR-009, FR-010). T011 shares the GamePage edit, hence one commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All API and two-tab checks pass on the first run, including the full create -> play -> result -> restart -> play again cycle without reloads. Pre-evaluation now reports 4/4 feature folders complete. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Covers what the starter had, what each feature added, how AI was used (Spec Kit flow, 11 clarifications, guardrails) and where its output was wrong and caught, tradeoffs, deviations, known limitations and how the work was verified. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fresh backend, two rooms at once: create, join, host-only start, draw and clear, wrong and correct guesses, shared result, restart with players kept, and the second room playing independently. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… tab count Feature 002's FR-007, contract and data model said the word is sent only to the drawer; feature 004 reveals it to everyone after the round ends. Each now notes the amendment. The reflection's browser-check line now says two to four tabs (the final run used four). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run after implementation (the constitution asks for before; noted in each report). 100% FR-to-task coverage in every feature. Findings: one CRITICAL constitution issue (inline style in RoundResult, Principle IV), one HIGH spec conflict already resolved in f701762, and MEDIUM/LOW documentation and evidence gaps. Nothing is fixed here; reports only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e implementation Scribble lab: Spec Kit artifacts and full game implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brownfield enhancement of the Scribble starter using GitHub Spec Kit. All four business scenarios are specified, planned, implemented and validated.
Artifacts
docs/discovery.md: 10 gaps, 6 assumptions, relevant files..specify/memory/constitution.md: v1.0.0, six principles plus constraints and workflow.specs/001-room-lobby,specs/002-game-start-drawer,specs/003-gameplay,specs/004-result-restart. Each has a spec with clarifications, plan, research, data model, API contract, quickstart, and tasks with validation results.REFLECTION.md: what the starter had, what was added, AI usage, tradeoffs, deviations.specs/NNN/analysis.md:/speckit-analyzecross-artifact reports for each feature (100% requirement-to-task coverage; findings recorded).Implementation (by scenario)
Validation
npm run buildandnpm testpass in both apps (backend 68 tests, frontend 7; the starter had 4 and 2).curl, and every scenario in 2–4 browser tabs. Results are recorded in eachtasks.md.All scope exclusions were respected: polling only (no push protocol), in-memory only, no authentication, single round per game, no timers.
Contributor
🤖 Generated with Claude Code