Scribble assignment- Pramod: all four scenarios + Spec Kit artifacts#141
Open
RawatePramod wants to merge 47 commits into
Open
Scribble assignment- Pramod: all four scenarios + Spec Kit artifacts#141RawatePramod wants to merge 47 commits into
RawatePramod wants to merge 47 commits into
Conversation
Install Spec Kit tooling (.specify scripts/templates/extensions), the speckit.* skills, and CLAUDE.md so spec-driven artifacts can be generated.
Populate .specify/memory/constitution.md with the 8 governing principles, scope boundaries, and Definition of Done for the brownfield Scribble enhancement.
Document incomplete behaviors, assumptions, and relevant files found while inspecting the starter.
Scenario 1 spec: host on create, join validation with distinct empty vs not-found errors, room isolation, ~2s lobby polling, host-only start gated at 2+ players. Includes prioritized user stories, edge cases, FR-001..FR-014, success criteria, and assumptions noting seams for later groups.
… reload scope Encode 3 clarifications into spec.md (## Clarifications + FR-013, US2/US4 scenarios, edge cases, assumptions): host-start advances all players via polling; join errors are 'Enter a room code.' / 'No room with that code.'; browser reload is out of scope.
Phase 0 research (D1-D7 decisions), Phase 1 data-model (Room.hostId + status lobby|active), REST contract (incl. new POST /rooms/:code/start), and two-browser quickstart. Constitution gates PASS (brownfield, polling-only, no new deps). Point CLAUDE.md agent-context at the plan.
20 tasks across Setup, Foundational, US1-US4, and Polish. Backend Vitest tasks at the service layer (roomStore/schemas); frontend validated via quickstart. Includes dependency graph, within-file ordering, parallel markers, and MVP strategy.
T002-T004: add Room.hostId (= creator) and widen RoomStatus to lobby|active; expose hostId+status in toRoomSnapshot; extend frontend RoomSnapshot type. Compiles clean, tests green. Shared data shape for US1-US4.
US1 (T005-T006): badge the host's row in the lobby participant list (FR-001); add roomStore test asserting createRoom records the creator as host and starts in lobby. Validated in-browser (quickstart V1).
US2 (T007-T009): reject empty/whitespace code client-side with 'Enter a room code.' (no API call); change join 404 message to 'No room with that code.' (FR-004, FR-005, FR-014); add roomStore join-success test. Case-insensitive match retained. Validated in-browser (quickstart V2-V3).
US3 (T010): add a 2s setInterval poll in LobbyPage calling fetchRoom(), cleared on unmount; manual Refresh retained as fallback (FR-008, FR-009). Validated in-browser (quickstart V4).
US4 (T011-T017): add POST /rooms/:code/start enforcing host (403) and >=2 players (409) server-side, flipping status to active (FR-010/011/012/013); add startRoomSchema, startGame service + tests, client startRoom/store action; lobby shows a host-only Start gated at 2 players with explanation, and all players auto-advance to /game when status becomes active. Validated in-browser (quickstart V5-V6).
Polish (T018-T020): two-browser quickstart V1-V7 pass (incl. room isolation); backend 9/9 and frontend 2/2 tests green; no spec deviations recorded. All Group 1 tasks complete.
Scenario 2 spec: player-name trim/blank-rejection (create+join), drawer assignment to host/first player on start, deterministic secret-word selection from the starter list, drawer-only word visibility. US1-US4, FR-001..FR-011, success criteria, assumptions. Builds on Group 1 active state + viewer-aware snapshot seam. Repoint feature.json to 002.
Encode 3 clarifications into spec.md (## Clarifications + FR-004/FR-008/FR-010, Assumptions): secret word = room-code-derived index (stable per room); drawer = host (creator); guessers see nothing of the word incl. length.
Phase 0 research (D1-D5), Phase 1 data-model (Room += drawerId/secretWord; viewer-aware RoomSnapshot += drawerId/role/word), contract delta (drawer-only word, name 400s, expanded start), two-browser quickstart. Constitution PASS. Point CLAUDE.md agent-context at the Group 2 plan.
19 tasks across Setup, Foundational, US1-US4, Polish. Backend Vitest tasks at the service layer (name validation, drawer assignment, deterministic selectWord, viewer-aware snapshot); frontend validated via quickstart. Includes dependency graph and within-file ordering for the shared roomStore.ts/GamePage.tsx.
US1 (T004-T007): trim names and reject empty/whitespace (incl. undefined) with 400 'Enter a player name.' on create and join (FR-001..003); remove the silent 'Player' fallback; client guards on Create/Join pages; 3 roomStore tests. Validated in-browser (quickstart V1-V2).
Foundational + US2 (T002,T003,T008-T011): add Room.drawerId/secretWord and viewer-aware RoomSnapshot fields (drawerId/role/word); startGame sets drawerId=hostId; toRoomSnapshot returns drawerId + per-viewer role (FR-004..006); GamePage shows the drawer to all and labels the viewer's role; drawer-assignment test. Validated in-browser (quickstart V3).
US3 (T012-T013): add selectWord(code) = STARTER_WORDS[(sum of char codes) % n]; startGame sets room.secretWord = selectWord(code) (FR-007, FR-008). Word is stored but not yet exposed (US4 reveals it to the drawer). Validated by unit tests (purity + starter-word membership).
US4 (T014-T016): toRoomSnapshot includes word only when the viewer is the drawer (omitted from guesser JSON); GamePage shows 'Your word' to the drawer, nothing to guessers (FR-009, FR-010). Test asserts drawer sees word, guesser snapshot has no word field. Validated in-browser + network check (quickstart V4).
Polish (T017-T019): backend 16/16 and frontend 2/2 tests green; V1-V6 validated per-story; reconcile I1 — name validation lives in roomStore (not schemas.ts), plan.md + data-model.md updated to match; results recorded in quickstart.md. All Group 2 tasks complete.
Scenario 3 spec: drawer interactive canvas + clear; guess submission (trim, reject empty, case-insensitive); shared guess history synced via polling; scoring (start 0, correct=100 once, incorrect=0). US1-US4, FR-001..FR-013, success criteria, assumptions. Builds on Groups 1-2. Repoint feature.json to 003.
…disable-after-correct Encode 3 clarifications into spec.md (## Clarifications + FR-011a, US4 scenario, edge cases, assumptions): drawing is drawer-local (no stroke sync to guessers); guess history shown verbatim to all; a guesser's input is disabled after a correct guess.
Phase 0 research (D1-D5), Phase 1 data-model (Participant.score, Guess, Room.guesses[], snapshot delta), contract (new POST /rooms/:code/guess with 400/403/409, snapshot additions), two-browser quickstart. Native canvas, no new deps; drawing drawer-local. Constitution PASS. Point CLAUDE.md at Group 3 plan.
23 tasks across Setup, Foundational, US1-US4, Polish. Backend Vitest tasks at the service layer (guess validation, correctness, history, scoring/lock); frontend (canvas, scoreboard, history UI) validated via quickstart. Dependency graph + within-file ordering for shared roomStore.ts/GuessForm.tsx. US1 (drawing) independent.
T002-T004: add Participant.score (default 0) and a Guess type; add Room.guesses[] (init []) and expose guesses in the viewer-aware snapshot. Compiles clean, tests green. Shared data shape for US2-US4.
US1 (T005-T006): new DrawingCanvas (native freehand <canvas> + Clear) gated by an enabled prop; GamePage mounts it with enabled={isDrawer} so only the drawer draws, guessers see a waiting placeholder (FR-001..003). Drawer-local (no stroke sync). Validated in-browser (quickstart V1).
US2 (T007-T013): add POST /rooms/:code/guess + submitGuess (404/403 drawer/400 empty, case-insensitive correctness, append to shared guesses history; scoring deferred to US4); submitGuessSchema; client submitGuess action; GuessForm wired (trim + reject empty) and rendered guesser-only. Backend test covers empty/drawer/correct/incorrect. Validated by unit tests.
US3 (T014-T016): render the shared guess history in the Activity panel (newest-first) from room state; add ~2s polling to GamePage so the history (and scores) sync to ALL players on the game screen, not just the lobby (FR-008) — the lobby-only poll was a gap caught during validation; snapshot history test. Validated in two browsers (quickstart V3).
US4 (T017-T020): submitGuess awards 100 once on a correct guess and refuses a guesser who already scored (409); Scoreboard renders participants + scores (sorted); GuessForm disables with 'You guessed it!' once the viewer's score is 100 (FR-009..012, FR-011a). Scores sync to all via the game-screen poll. Validated in two browsers (quickstart V4).
Polish (T021-T023): backend 19/19 and frontend 2/2 tests green; V1-V5 validated per-story; recorded the GamePage-polling deviation (poll was lobby-only; added to game screen in US3 for FR-008/FR-012) and a Group 4 carry-forward note (restart must reset scores/guesses). All Group 3 tasks complete.
Scenario 4 spec: host-ended result state revealing the word + final scores + full history to all; host-only restart returning everyone to the lobby with players preserved and round state cleared (drawer/word/guesses cleared, scores reset 0). US1-US2, FR-001..FR-011, success criteria incl. full end-to-end game, assumptions. Builds on Groups 1-3. Repoint feature.json to 004.
Encode 2 clarifications into spec.md (## Clarifications + Assumptions): the host ends the round explicitly (host-only action); restart returns everyone to the lobby, then the normal Group 1 start flow. FRs already matched these defaults.
Phase 0 research (D1-D5), Phase 1 data-model (RoomStatus += result; endRound/restartGame; reveal word at result; restart reset set), contract (new POST /end + /restart, result snapshot delta), two-browser quickstart incl. full end-to-end + replay. No new deps. Constitution PASS. Point CLAUDE.md at Group 4 plan.
20 tasks across Setup, Foundational, US1 (result), US2 (restart), Polish. Backend Vitest tasks at the service layer (endRound 403/result + word-reveal, restartGame 403/reset/preserve); frontend validated via quickstart. Dependency graph + within-file ordering for shared roomStore.ts/GamePage.tsx.
Foundational + US1 (T002-T011): add 'result' room status; host-only endRound (403 non-host, 409 if not active) → status result; toRoomSnapshot reveals the word to everyone at result (drawer-only during play preserved); participantActionSchema; POST /rooms/:code/end; client endRound action; GamePage host End Round button + Round Over view revealing the word (FR-001..005). Validated in two browsers (quickstart V1-V2).
US2 (T012-T017): host-only restartGame returns the room to lobby, clears drawer/word/guesses and resets every score to 0 while preserving participants (403 non-host); POST /rooms/:code/restart; client restartGame action; GamePage host Restart button (result) + auto-return to /lobby when status flips back (FR-006..010). Validated in two browsers (quickstart V3-V5).
Polish (T018-T020): backend 21/21 and frontend 2/2 tests green; V1-V6 validated per-story incl. full end-to-end + replay and no-regression; recorded the endRound active-guard hardening (analyze U1). Full lifecycle lobby->active->result->lobby complete. All Group 4 tasks done.
Relabel headings and add a summary so the required coverage is unmistakable: 6 gaps (>=3) and 5 assumptions (>=2), plus relevant files. Addresses evaluator finding A1 (content was present but not explicitly counted).
Refinement of Groups 3/4 from evaluation feedback: a correct guess scores then moves the room to the result state for all players; host End Round retained as a fallback; round no longer accepts guesses once ended. US1, FR-001..006, success criteria, assumptions. Supersedes the Group 4 host-only-end clarification for the correct-guess case. Repoint feature.json to 005.
Phase 0 research (D1-D4), Phase 1 data-model (no schema change; submitGuess behavior delta), contract (POST /:code/guess returns result snapshot on correct + 409 when not active), two-browser quickstart. Backend-only; reuses Group 4 result state + existing frontend status handling. Constitution PASS. Point CLAUDE.md at the 005 plan.
6 tasks: Setup, US1 (test + submitGuess active-guard & set result on correct), Polish. Backend-only; service-level Vitest test; frontend validated via quickstart. No model/endpoint/frontend changes.
Increment 005 (T002-T003): submitGuess now rejects guesses unless the round is active (409) and, on a correct guess, sets status='result' after scoring — so a correct guess auto-ends the round to the shared result state (word revealed to all). Reuses the Group 4 result state and existing frontend status handling; host End Round kept as a fallback. Updated the restart test for the new flow; added an auto-end test. Addresses the evaluator's Scenario 3 Major Finding. Validated in two browsers (quickstart V1-V5).
Polish (T004-T006): V1-V5 validated in two browsers; backend 22/22 and frontend 2/2 green; recorded that 005 supersedes the Group 4 host-only-end clarification for the correct-guess case (End Round kept as fallback). Increment complete.
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
Implements all four scenarios of the Scribble assignment using a Spec Kit driven workflow (specify → clarify → plan → tasks → implement → validate, per feature group).
Feature groups delivered:
specs/001-room-setup-lobby) — host identity on room creation, clear join validation errors, automatic lobby polling (~2s), host-only Start gated on at least 2 players, verified multi-room isolation.specs/002-game-start-drawer) — player name trimming and rejection of empty names, drawer assignment, deterministic secret word selection from the starter list (derived from the room code), drawer-only word visibility (hidden in the API response for guessers).specs/003-gameplay-interaction) — interactive drawing canvas with clear, server-side guess validation (trim + case-insensitive compare), synced guess history via polling, deterministic scoring (100 for correct, 0 otherwise), input disabled after a correct guess.specs/004-result-restart) — host-controlled end-of-round that reveals the word, final scores, and full guess history to all players; host restart that returns everyone to a clean lobby with players preserved and round state cleared.Constraints honored (per constitution):
Artifacts:
.specify/memory/constitution.mdspecs/001-…throughspecs/004-…REFLECTION.mdValidation:
npm run buildboth succeed.Contributor