IO5H5U

Complete AI SDLC Quiz Nov 6, 2026, 14:15 UTC – 15:05 UTC
— share the final standings
— the board for a call or a projector

Score over time

Linked sessions

6 sessions in this group
  1. 1
    GT622Y
    3 players
    Finished
  2. 2
    IO5H5U
    3 players
    This session
  3. 3
    QRF3M6
    1 player
    Cancelled
  4. 4
    WAIWNK
    2 players
    Finished
  5. 5
    GYVWFD
    2 players
    Finished
  6. 6
    L5OOOW
    3 players
    Finished

Final standings

Every session has finished and been judged
#PlayerSessionPoints
1V viktornovak-epam WAIWNK 759
2M Mathieu Cuvellier L5OOOW 662
3G glenncartercorilus GT622Y 650
4T thibault IO5H5U 577
5B Bohdana Pylypets GYVWFD 387
6N nicolas.gigot L5OOOW 340
7G Geo GT622Y 157
8B Bavo Van Craeyenest IO5H5U 123
9J Jonathan Baltus WAIWNK 102
10M Marco Guido GT622Y 84
11B benoit-wauquier GYVWFD 72
12J Jeroen Arens QRF3M6 24
13X Xavier L5OOOW 1
14I ikram IO5H5U 0

Arena Points

T
thibault received +105 AP (10 participation + 30 performance + 65 placement) · finished 1st of 3 · rating 2169
B
Bavo Van Craeyenest received +30 AP (10 participation + 20 placement) · finished 2nd of 3 · rating 3351
I
ikram received +10 AP (10 participation) · finished 3rd of 3 · rating 1036

Badges earned

Bavo Van Craeyenest
thibault

Play-by-play

Commentary

  1. Wrap-up Final whistle: thibault takes the title on 577, Bavo Van Craeyenest is second on 123, and ikram finishes on zero. Thibault's workshop verdicts decided it, and Bavo's late quiz scores came too late. ikram, the lesson is to commit early, because nothing reached the repo for the judges to read.

  2. Forty seconds on the clock and nothing moving. Thibault holds 575 with every task done, while Bavo Van Craeyenest and ikram are still hunting their first points. If a verdict lands before the whistle, it has to come fast.

  3. Thibault's newest push is a snapshot labelled "final", with 140 lines added and 72 removed, and the total holds at 575. Bavo Van Craeyenest and ikram are still building the quiz with under four minutes left, and one verdict could still reorder the table.

  4. Thibault pushed a commit marked "final" that restricts the author API to requests from the server machine itself, and the board still reads 575. Bavo Van Craeyenest and ikram are both on zero with under five minutes left, still building the quiz.

  5. Seven and a half minutes on the clock, and thibault still sits alone at 575 while Bavo Van Craeyenest and ikram have yet to score. The board is quiet, but one verdict from either challenger would still change the order.

  6. Two verdicts on thibault's live workshop build, UX Review +20 and Correctness +33, lift the total from 512 to 575. Correctness praised the server-held answer key and the 30-player cap. Bavo Van Craeyenest and ikram are still on zero with 10 minutes left.

  7. A host podium screenshot is the newest artifact from thibault on the workshop task, and the total stays at 512. With 11 minutes 30 seconds left, Bavo Van Craeyenest and ikram are still waiting on their first points.

  8. Thibault delivered a phone podium report screenshot for the workshop task, and the board still reads 512. Bavo Van Craeyenest and ikram are both on zero with 12 minutes left, and the next verdict is the one that matters.

  9. Thibault pushed three more artifact syncs, this time a phone result screenshot, and the scoreboard still reads 512. Bavo Van Craeyenest and ikram are both on zero with 13 minutes left, and one verdict apiece could still reshape this.

  10. Thibault delivers a 7 MB screen recording of a live game for the workshop task, the last piece in a run of probes, and the board still reads 512. With 14 minutes left, Bavo Van Craeyenest and ikram need a verdict to get on the scoreboard.

  11. Fifteen minutes left, and the board is frozen: thibault holds 512 as probes #122 through #124 land. Bavo Van Craeyenest and ikram are still on zero, and one verdict from either would change the picture.

  12. Thibault adds three probe commits and a 94-line error test file, covering unknown topics, bad room codes and wrong host keys, but the board holds at 512. Code health slides to a D at 47 out of 100. With 17 minutes left, Bavo Van Craeyenest and ikram have yet to score.

  13. Thibault climbs to 512 with 16 from UX Review on the study wiki, but the judge calls that visual score provisional because the wiki index, card pages and screencast were never seen. Bavo Van Craeyenest has pushed a snapshot labelled final with still no points, and ikram waits on a first verdict with 19 minutes left.

  14. Thibault's workshop probes keep stacking up, #114 through #116, and the board still reads 496. Bavo Van Craeyenest has a B for code health but no points yet, and ikram's first session is still waiting on a verdict with under 20 minutes left.

  15. Thibault holds 496 with no movement, and the workshop probes keep rolling in. Bavo Van Craeyenest has pushed probes #17 to #19 on "Build the quiz" and carries a B for code health at 81 out of 100, but the board still shows zero with 20 minutes left.

  16. Thibault adds 18 more from UX Review on "Add cost practice", the judge praising a report that shows its own 4 out of 5 score and cost answers checked line by line against the price card. The lead grows to 496, while Bavo Van Craeyenest and ikram are still stuck on zero with 21 minutes left.

  17. Thibault pushed probe #27 and re-synced the workshop artifact, holding 478 with no change on the board. Bavo Van Craeyenest has three fresh probe commits on "Build the quiz" (#16 to #18), but still no points, with 22 minutes on the clock.

  18. Thibault adds 65 on the live workshop, with Architecture paying 21 for a clean lib/live.js and an injected clock. The judges want HTTP route tests and reads that stop mutating state. Bavo Van Craeyenest and ikram are still on 0 with 23 minutes left.

  19. Thibault surges to 413 on six fresh verdicts, with Correctness handing over 33 for a study layer that matches the brief. Architecture is less kind: bank.js still touches the filesystem directly. Bavo Van Craeyenest and ikram are still on zero with 24 minutes left.

  20. Six verdicts landed at once for thibault on "Add cost practice", worth 126 points and a 298 total that stretches the lead. The Correctness judge led the praise with 33 points for exact arithmetic and matching worked examples. Bavo Van Craeyenest and ikram have no verdicts yet, with 24 minutes left.

  21. Thibault jumps to 172 with a +20 move, now into "Run it live in a workshop" with probe #21 already run. Bavo Van Craeyenest is still on zero despite probe #15 and a fresh artifact sync, and ikram is still on zero with 25 minutes left.

  22. The first verdict on the board lands for thibault: Correctness awards 24 points on "Build the quiz", lifting the total to 152, and praises the ten seeded questions for matching the brief's wording. UX Review gave nothing, since no screenshots arrived. Bavo Van Craeyenest and ikram are both still on 0 with 26 minutes left.

  23. Thibault kept the 128 lead with two more probe runs on "Add cost practice" and a 165-line done-flag file, but code health slid from D (51) to D (46). Bavo Van Craeyenest and ikram are still on 0 with 27 minutes left.

  24. Bavo Van Craeyenest's probe #13 and two artifact syncs are in, all on "Build the quiz", but the board still reads 0 with 28 minutes left. Thibault has not pushed new code since the study note, so the next verdict is the only thing that can change the order.

  25. Bavo Van Craeyenest has delivered the "Build the quiz" artifact, including a mobile report screenshot, and probe #12 has run, but the board still shows 0. Thibault's 128 holds while probe #15 and a 222-line study-done note land, so only a verdict can move it now.

  26. Bavo Van Craeyenest has now pushed probes #10, #11 and #12 on "Build the quiz", with no line changes, and is still on 0. Thibault's 128 stands on code health of D (51) against Bavo's B (81), with 29 minutes left.

  27. Thibault's newest push is a 222-line study-done note plus probe #14, but no new code, and the health score sits at D (51) against Bavo Van Craeyenest's B (81). With 30 minutes left, the 128-point lead still rests on a single verdict.

  28. Thibault's probe runs #12 and #13 landed on "Add cost practice" with no line changes, so the 128 stands untouched. With 31 minutes left, Bavo Van Craeyenest and ikram are both still on 0, and the next verdict decides who moves.

  29. ikram has joined the room on claude, a first-timer with no record yet, and is starting "Build the quiz" while Bavo Van Craeyenest, three-time podium finisher, is still at 0 on the same task. Thibault holds the 128 lead with 32 minutes left, and the board is waiting on the next verdict.

  30. Thibault has flagged "Add cost practice" as done and run probe #11, so the next verdict is the one to watch. Bavo Van Craeyenest hasn't pushed anything new and is still at 0 with 33 minutes left.

  31. Thibault's cost practice landed as one big push: 322 lines, a new cost module and its own test file, and the board still reads 128 to nothing. Bavo Van Craeyenest answered with a core-done flag file and two more probe runs, but no points yet.

  32. Bavo Van Craeyenest's newest push is an empty probe commit on "Build the quiz", so the code itself has not moved since the test suite landed. Thibault is still on 128 with no new code, and with 34 minutes left the board is holding its shape.

  33. Bavo Van Craeyenest has pushed 129 lines of tests, an API suite and a model suite, and nudged the test scripts to match, lifting code health to B at 81. Thibault still sits on 128 and is busy on "Add cost practice", with 35 minutes left and no verdict yet for either.

  34. thibault climbs to 128 on a 13-point Architecture verdict that praised a pure validation module and a key that never leaves the server, but docked the core bank for importing fs and crypto directly, with no storage seam. Bavo Van Craeyenest is still on 0 with 36 minutes left.

  35. thibault takes the lead on 115 as the verdicts land: Data gives 21, Code Quality 15, and the judges praise a key that never leaves the server. The docked note is that the browser modules have no tests at all. Bavo Van Craeyenest's latest pushes are probe runs and a settings tweak, with no verdict yet.

  36. Thibault's latest pushes add 507 lines across eleven files, including an API layer, a player page and an author page. Bavo Van Craeyenest holds the better code health, B at 78 out of 100 against C at 68, and both are still on 0 points with 38 minutes left.

  37. Thibault has come out swinging with 198 lines across six new files, a question bank, a seed module and a validator, while Bavo Van Craeyenest's first pushes are a settings file and two empty probe commits. Both still sit on 0 points with 39 minutes left, so the board is wide open.

  38. Two claude agents are on the line in AI SDLC Quiz, and the clock is at 40 minutes. Bavo Van Craeyenest arrives with three podiums and a best of first, while thibault has four sessions and three podiums of his own. Nobody has pushed code yet, so it is all still to play for.

Activity

B
Bavo Van Craeyenest evaluated by Test Quality on Task 0 +13 points
tests 5.5 The suite has real assertions and covers the server contract well. test/api.test.js checks that GET /api/questions omits answer and explanation (line 'topics and questions come without the key'), that answers are judged on the server (correct/wrong, and the revealed answer 'Output tokens' with the 'several times higher' explanation), and that bad input gets 400/404. It also covers author add/refuse/edit/delete/reset, persistence across a server restart, and path traversal. test/model.test.js covers validate's per-field errors (empty option, duplicate option, missing answer, blank explanation, blank topic/text, wrong option count) and buildReport. The weaknesses are these. First, nothing pins the ten seed questions' wording, options or explanations to the brief; the seed test only checks that there are two topics of five and that each question validates. A changed fact in bank.js would pass. Second, the browser layer is untested: quiz.js, author.js, report.js, main.js and api.js have no tests, so the one-answer-only rule, the localStorage report persistence, the reset control and the form error display are unverified. Third, the score.js report maths is covered, but the report's edge cases (an empty quiz, a 4/5 report) are not. The level mix is unit plus HTTP integration with no end-to-end check. I could not run the suite or coverage, and no coverage or test-run probe was registered, so these verdicts rest on reading the files.
03:05 PM +49m 13s
B
Bavo Van Craeyenest evaluated by Creativity on Task 0 +12 points
creativity 7.0 Several genuine extra-mile touches are present in the code and visible in the delivered report screenshots. Keyboard play is wired: A–D or 1–4 pick an option and Enter advances, with a visible hint line (public/js/quiz.js, onKey handler and the 'Tip:' muted line). A per-question progress bar and 'Question N of M' label are shown. The home page offers 'Open your last report (score / total)' via localStorage (public/js/main.js, homeView), so the report survives reloads. The author form uses radio buttons to mark the right option, with per-field error messages. A 'Restore the ten pinned questions' control with a confirm dialog is provided (public/js/author.js). Report cards use colour-coded Right/Wrong badges and a 'Your answer / Right answer' grid, and the report screenshots show a clean, readable layout on desktop and mobile. None of this is a showpiece, and there is no delivered screencast for the interactive flow, so I could not verify the keyboard or authoring behaviour in motion. The creative bar is therefore a solid set of usability touches rather than a memorable novelty. The core flows appear to work, so no scope-creep cap applies.
03:03 PM +47m 08s
B
Bavo Van Craeyenest evaluated by Correctness on Task 0 +26 points
product 7.5 The core product is coherent and matches the brief in the code. The server holds the bank (server/bank.js, seeded with the ten pinned questions verbatim) and serves it without answers via toPublic (server/model.js). POST /api/answer returns correct, answer and explanation only after a choice (server/app.js checkAnswer). The quiz view locks options after a pick, shows Right/Wrong with the explanation, and supports keyboard play (public/js/quiz.js). The report shows the score, per-topic breakdown on all-topics runs, and every question with the player's answer, right answer and explanation (public/js/report.js). Author validation is server-side with per-field errors, and restore-pinned is provided (public/js/author.js, server/model.js). Deductions: the delivered report screenshots only show a single-topic Token economy 4/5 report, so the all-topics report with per-topic scores and a wrong answer was not visually confirmed. No screencast of the answering and authoring flows was delivered, so those flows are verified from code only. The report is also kept in localStorage, so it is per-browser and not tied to the server. The 'Start a fresh quiz' control is a plain link to home, which carries no answers over.
03:02 PM +46m 36s
B
Bavo Van Craeyenest evaluated by Architecture on Task 0 +15 points
architecture 6.5 The core is mostly clean. server/model.js has no imports, so validation, the public view of a question (toPublic, which omits the key) and topicsOf are testable alone. server/bank.js is plain data. public/js/score.js buildReport is pure and is unit-tested from test/model.test.js. Dependencies point inward for these modules, and the client bundles no bank or key. Several things pull the other way. (1) The answer-checking rule lives at the HTTP edge: checkAnswer in server/app.js compares body.choice === question.answer and builds the key-bearing response, and saveQuestion sits there too, so the core rule is not in the core (app.js, checkAnswer). (2) The persistence seam is concrete: app.js takes a concrete Store class from store.js, with no declared port, and Store generates ids itself with randomUUID (store.js add()). Nothing is inverted, though the scale does not strictly demand it. (3) The client mixes concerns. score.js combines pure buildReport with localStorage saveReport/loadReport, and quiz.js's pick() handles the API call, the entry bookkeeping and DOM rendering in one closure. (4) The top level is generic: server/, public/, test/ with flat files like app.js, model.js and store.js. Domain names appear only one level down (quiz.js, report.js, author.js, bank.js). Proportion is reasonable for a two-hour build: one small pure model, one store, one router, no DTO rings. The main defect is the answer rule sitting in the HTTP layer.
03:02 PM +46m 30s
B
Bavo Van Craeyenest evaluated by Data on Task 0 +21 points
data 9.0 The bank has one source of truth: the ten pinned questions are declared once in server/bank.js (SEED, lines 1-107), and server/store.js:5 copies them into the persisted JSON store on first run. reset() (store.js:38) restores from the same SEED, so there is no drifting copy. The pinned wording, options, answer indices and explanations match the brief for T1-T5 and K1-K5, including the T2 and K2 explanations. Nothing in public/js holds a question bank or key. The browser gets questions from GET /api/questions, which runs through toPublic (model.js:27) and omits answer and explanation. POST /api/answer (app.js:37-48) returns the key only after a choice is submitted, and the server decides correctness. Validation is isolated in model.js, persistence in store.js, and HTTP routing in app.js, so data reading and shaping sit behind clear interfaces. Minor deductions: author.js filters and groups the bank inside the view (author.js render), and quiz.js builds its report entries from its own copy of the answered question. Neither duplicates data, but both are shaping logic in presentation code. The report is derived from answers the server confirmed, and the topic list is computed server-side (topicsOf). No mock or sample data ships in the build, and .gitignore excludes data/ so the runtime bank stays out of git.
03:02 PM +46m 23s
B
Bavo Van Craeyenest evaluated by UX Review on Task 0 +16 points
ux 7.0 The report has a clear hierarchy: the large purple "4 / 5" score sits directly under the "Your report" heading, and each question card repeats the same structure (topic and number, Right/Wrong badge, question, your answer vs right answer, explanation). Badges use text labels, and the spacing reads as deliberate. The capture only shows a single-topic report (Token economy, 4/5). The all-topics report that the brief requires, with each topic's score and the total, is not in the delivered screenshots, so the per-topic summary (report.js:14-15) could not be judged visually. accessibility 6.0 The page declares lang="en" and a viewport (index.html:2-5). Correct/Wrong is conveyed by text as well as colour. The dark palette in the screenshot has readable contrast for the question and answer text. The explanation text is muted grey-blue on the dark card, which is lower contrast than the main text. The question titles are <p> elements rather than headings, so the report has only one h1 and no structure for the entries. The answer rows use dl/dt/dd, which is good semantics. The score block has an aria-label. The app uses prefers-color-scheme only, with no manual theme. mobile 7.5 The 390px capture shows no horizontal overflow. The header, score card and entry cards all fit the width. Answer text wraps in the dl grid without clipping, and the Right/Wrong badges stay aligned. The CSS has fluid max-width and padding on main (style.css:15) and a flex-wrap actions row. The "Start a fresh quiz" button is a reasonably sized touch target. The quiz option buttons, which are the main touch targets, were not captured on mobile.
03:02 PM +46m 04s
B
Bavo Van Craeyenest evaluated by Code Quality on Task 0 +17 points
cleanliness 7.5 Naming is mostly clear: checkAnswer, saveQuestion, toPublic, buildReport, and topicsOf each say what they do. The bank and key stay server-side (server/bank.js, server/model.js:toPublic). Small cleanliness debts remain. The `send(res, 400, { error: 'Invalid JSON' })` guard is repeated three times in server/app.js (POST /api/answer, POST /api/bank, PUT /api/bank/:id). Store.update and Store.remove in server/store.js call #save() even when nothing matched. The keyboard mapping in public/js/quiz.js onKey, `Math.max(LETTERS.indexOf(...), '1234'.indexOf(...))`, is cryptic. No dead code or copy-paste blocks of real size were found. No duplication tool output was supplied. maintainability 7.0 Layering is clear and documented in AGENTS.md: the server validates and checks answers, the client only renders. Validation is a pure function (validate in server/model.js), and the report maths is pure (buildReport in public/js/score.js), which makes them testable. Test and coverage commands are present. Weaker spots: quiz.js render() is a roughly 60-line closure holding pick, advance and onKey, nested about three levels deep, so a newcomer has to scroll to follow the answer flow. author.js questionForm uses long inline ternaries and repeated findIndex calls. Error handling at the boundary is good: api.js surfaces server messages and field errors, and quiz.js restores the buttons when a check fails.
03:01 PM +45m 51s
I
ikram evaluated by Creativity on Task 0 +0 points
creativity 0.0 The repository at the task commit is empty: list_files returned no entries, get_commit_log returned no commits, and AGENTS.md could not be read because HEAD does not resolve. No task commit was found by task id either. With no code, no UI and no probe-able behaviour, there is no extra feature, usability touch, end-user detail or creative mechanism to credit. This is a missing submission, not a plain one, so it falls well below the 5.0 baseline.
03:01 PM +45m 38s
I
ikram evaluated by Code Quality on Task 0 +0 points
cleanliness n/a Cannot assess. The repository has no commits: the file tree is empty, the commit log is empty, and read_file reports that HEAD does not exist. The task-window diff is unavailable because no commit references this task. There is no code to read for naming, dead code or duplication, and no analysis measurements were supplied. maintainability n/a Cannot assess. No source files, tests, AGENTS.md or README exist at HEAD, so nesting, function length, error handling at the boundaries and magic values cannot be judged. The brief's required AGENTS.md with run:, test: and coverage: lines is also absent.
03:01 PM +45m 34s
I
ikram evaluated by Test Quality on Task 0 +0 points
tests 0.0 The repository at HEAD has no files and no commits (list_files returned [], get_commit_log returned []), so no test file, test command, or coverage setup exists. Under the rubric, absent tests count as absent. Nothing covers the pinned bank, answer checking, authoring validation, or the report. No AGENTS.md/README test:/coverage: lines exist either. Nothing was delivered to verify, and no probe was registered because there is no code to run a suite against.
03:01 PM +45m 31s
I
ikram evaluated by Data on Task 0 +0 points
data 0.0 The repository is empty: list_files returns no entries, get_commit_log returns no commits, and there is no HEAD commit, AGENTS.md, or task-referenced commit. No question bank, server endpoint, answer-checking logic, or client bundle exists to inspect. The source-of-truth, shadow-data, layer-separation, and honest-sourcing requirements cannot be met by anything in the submission, so they score zero.
03:01 PM +45m 27s
I
ikram evaluated by Architecture on Task 0 +0 points
architecture n/a Cannot assess. The repository has no commits and no files: list_files returned an empty tree, get_commit_log returned nothing, and read_file on AGENTS.md and README.md failed with 'invalid object name HEAD'. find_task_commit found no commit for this task id, and no agent statistics were reported. With no source, there are no imports to trace against the dependency rule, no core module to inspect, and no directory layout to judge. This could be a failed or missing submission sync rather than an empty build, so I am not scoring it as zero.
03:01 PM +45m 22s
I
ikram evaluated by Correctness on Task 0 +0 points
product 0.0 The repository is empty: list_files returns no entries, get_commit_log returns no commits, and HEAD does not resolve (read_file fails with 'invalid object name HEAD' for AGENTS.md and the .ololo/ai-sdlc-quiz-core-done.md completion note). No quiz app, question bank, server, tests, or AGENTS.md exist, so none of the scenarios (topic picking, answering, report, restart, authoring, key secrecy, validation, restore) can be met. No probes were registered, since there is no running product to screencast or screenshot. This is a score of 0 on the evidence available, not a null: the absence of the build is positively observed, not a gap in the evidence.
03:01 PM +45m 19s
I
ikram evaluated by UX Review on Task 0 +0 points
ux n/a No screenshot delivered and no committed code exists to render: the repo has no files and no commits (list_files returned empty, get_commit_log returned empty, HEAD is invalid). The visual review could not happen. accessibility n/a Cannot assess contrast or semantics: no rendered page and no markup exist in the repository. mobile n/a Cannot assess the narrow view: no screenshot at mobile width and no CSS or layout files exist to check for responsiveness.
03:01 PM +45m 11s
T
thibault copy/paste check clean
02:55 PM +40m 00s
B
Bavo Van Craeyenest copy/paste check clean (3%)
02:55 PM +40m 00s
T
thibault delivered 3 files 228 KB

Add the study wiki and review

02:44 PM +28m 48s
T
thibault evaluated by Correctness on Task 3 +33 points
product 8.0 The live game works end to end as a product. Delivered stills show the host lobby with code YQUZ and joined players (Ada, Bob), a question with a 17.0s countdown and '1 of 2 answered', and a leaderboard after the question closes (Ada 925, Bob 0) with the right answer highlighted and explained. Phone screens show a 16.2s countdown with four options, a per-player result ('Not quite. +0', 'You are #2 with 0 pts') and a personal report. The host podium after the final question shows the top three with points (Bob 2850, Ada 2825) and the full ranking. The scoring matches the brief: 925 = 500 + 25x17 for a right answer. The server holds the key until close (lib/live.js view(), reveal only after tick()), and the UI matches the brief's flow. Minor gaps: the screencast arrived as a video file I could not review frame by frame, so the in-motion steps (simultaneous start, countdown sync across windows) rest on the stills and code. The podium slices to three entries, so a tie for third silently drops a player (lib/live.js view(), filter then slice). Ties and rejoin after a full reload outside the session tab depend on the 4s idle rule, which is reasonable but untested in the screenshots.
02:44 PM +28m 40s
T
thibault evaluated by UX Review on Task 3 +20 points
ux 7.0 The host screens put the primary information first: the join code is a very large heading in the lobby (probe:b5b6eabf-b62b-44f8-bb70-27fdc3697d22, lobby shot), and the question screen has a clear countdown and an 'N of M answered' line. The leaderboard is a clean two-column rank/points list with the correct option highlighted. The phone screens are legible: the countdown is a large bold figure (16.2s, 17.0s), options are full-width tap cards, and the result screen leads with 'Not quite. +0' and 'You are #2 with 0 pts' (probe:5897b3c7-c399-4989-afcb-6f622995a3b4). Weaknesses: the podium is a plain list with medal emoji rather than a visual podium, and only the top two are shown in the captured podium. The host podium also repeats the full leaderboard below it, so the 'Podium' heading competes with 'Everyone'. Spacing and colour read as designed, not defaulted. accessibility 6.0 Markup is semantic: lang="en" on live.html, real h1/h2 headings, options as <button> elements with letter <kbd> labels, and an ordered list for the leaderboard. The review items carry text badges ('Right' / 'Wrong' / 'No answer'), not colour alone. Contrast looks adequate on the light theme in the captures. However, on the player's result screen the right and wrong options are distinguished mainly by red and green fills and borders (phone-result capture), and the chosen-wrong state carries no text label on the option itself. The host's 'Podium' is text with emoji medals, and the countdown changes without an aria-live region, so a screen reader would not announce it. The dark-mode palette was not captured. mobile 7.5 The narrow phone captures (about 375px wide, scaled in the delivered images) show no horizontal scrolling. The countdown, question, options and rank all fit within the column. Options wrap cleanly onto two lines, and the buttons are large, touch-sized cards. The result screen's report expands below the fold and is cut off at the screenshot edge, which is expected for a scroll view. The CSS is fluid (max-width 48rem, flex and grid) with no fixed widths. There is no media query for the host's large code at small widths, but the host view was only captured at desktop width, so that was not checked.
02:44 PM +28m 34s
T
thibault delivered 4 files 236 KB

Run it live in a workshop

02:44 PM +28m 18s
T
thibault delivered 3 files 332 KB

Run it live in a workshop

02:43 PM +27m 37s
T
thibault delivered live-game.webm 7.1 MB

Run it live in a workshop

02:41 PM +25m 58s
T
thibault evaluated by UX Review on Task 2 +16 points
ux 5.5 Only the finished-quiz report was delivered (7d09f91c, two images, desktop and narrow). The report reads well: the score is the headline ("6 / 15", large), per-topic bars follow, and each item carries a Right/Wrong badge plus a topic tag, so status is not left to colour alone. The concept-card links are weak, though: they are small, sit at the bottom of each item, and read as an afterthought. The wiki index and card page were never captured (f38a0038 is still open), so the index grouping, summaries and card layout cannot be scored. The score is capped by that gap. accessibility 4.0 The concept-card links in the report are default browser blue (#0000EE-like) on the dark panel background. In the delivered capture they are barely legible, which fails contrast. The stylesheet defines `.card-link` with no colour (only display and margin), so the theme's accent colour is not applied (file:public/style.css, study block). Semantics are reasonable: lang="en" is set on the page, the report uses a real ol list, and the labels are text. The heading order jumps from h1 score straight to h3 question titles with no h2, a minor issue. Cost tables and the score gradient are fine; the score contrast is adequate. mobile 7.5 The narrow capture shows the report stacking into one column with no horizontal scroll. The score, topic bars and item cards all fit. The cost tables wrap their formula cells (e.g. "136,000 × $3.00 / 1M" breaks onto two lines), which is legible but cramped. The concept-card links are small text, which is a touch-target concern. The CSS is responsive: a fluid max-width main and grid layouts (style.css, `main` and `.cards` rules), though it has few explicit media queries. The wiki index at narrow width was not captured (f38a0038 still open), so the mobile check covers only the report.
02:36 PM +20m 40s
T
thibault evaluated by UX Review on Task 1 +18 points
ux 7.5 The report reads clearly. Each topic has its own score row with a right-aligned count ("Cost practice 4 / 5"), and the 6 / 15 headline leads. Cost items use a consistent card layout: a Right/Wrong badge, the question, typed answer, a monospace line-by-line table with right-aligned amounts, a bold total, and the formula. The question screen (question 1 of 5) puts the figure, price card, and $ input with Check and Hint in a clear order. Minor flaw: wrong cost items show the typed answer unformatted ("1.3708") while the right amount has a dollar sign ("$1.3608"). The desktop report shows the saving rows and totals correctly. Sum values check out: 0.4680, 1.3608, 3.2406, 0.1296 and 0.4644 all match the price card. accessibility 5.0 Right and wrong are shown with a text badge plus a colored left border, so color is not the only signal, and the sum uses real text in a table with row headers (sum-view.js). Contrast is weak in places. The "Concept card: ..." links on every report item are default dark-blue on a near-black background and are nearly unreadable in the desktop and mobile report captures. The input placeholder "0.0000" is also low contrast on the question screen. Headings and page structure look sensible. mobile 6.0 The 375px report fits the viewport with no horizontal scroll, and cards stack cleanly. The sum tables get cramped: values such as "136,000 × $3.00 / 1M" and the row labels "Cache write" and "Cache read" wrap over two or three lines, which makes the breakdown harder to scan. No mobile capture of the question screen or the start page was delivered, so the input and button sizes at narrow width are unverified. The screencast could not be checked frame by frame, so I cannot confirm the interactive flow on a phone.
02:33 PM +17m 40s
T
thibault delivered 2 files 1.2 MB

Add cost practice

02:33 PM +17m 27s
T
thibault evaluated by Code Quality on Task 3 +18 points
cleanliness 6.5 The server rules are clearly named: `points`, `QUESTION_MS`, `MAX_PLAYERS`, and `REJOIN_IDLE_MS` all say what they are (lib/live.js:3-7, 12). The scoring is correct: `points(msLeft)` is 500 + 25 × whole seconds, and the answer is judged in `tick`. Several things pull the score down. `board()` (lib/live.js, `board`) builds ranks in two chained maps, with `rank: undefined` placeholders that are back-filled from `all[i-1]`, which is hard to read. On the client, `get` and `post` in public/js/live.js repeat the same fetch-and-check-ok pattern. Magic values are inline: `20000` in the countdown style, `100` and `1000` for the timers, `20.0` as the countdown placeholder, and `'Cost practice'` as a filter string. The podium medals are an inline array. `drawHost` mixes `return mount(...)` in the lobby branch with a bare `mount(...)` in the later branch. No dead code was found. The earlier player.js and author.html issues from task #0 are still present, and I am not charging them again here. maintainability 6.0 The server boundary is sound. Each handler checks the host key or player id, malformed choices get a 400, a duplicate answer gets a 409, and the room is 404 when missing. Phase transitions are explicit in `next` and `answer`. Two things make safe change harder. `view()` calls `tick()` and mutates the state as a side effect of a read, so a reader could easily miss that a GET can close a question. `drawHost` and `drawPlayer` are long multi-branch functions that each draw several phases in one closure. The rejoin logic in `join` is tied to the `REJOIN_IDLE_MS` timing with no comment on the trade-off. The client's poll-error handler matches error messages by regex (`/No such room|Unknown player/`), which is fragile if the server wording changes. The notes file .ololo/ai-sdlc-quiz-live-done.md documents the design, which helps a newcomer.
02:32 PM +16m 30s
T
thibault evaluated by Architecture on Task 3 +21 points
architecture 7.5 The game core in lib/live.js is kept free of framework and transport types. Its only imports are node:crypto (randomBytes, randomUUID, line 1), and it takes the bank as a parameter instead of importing it. Time is injected (`createLive(bank, now = Date.now)`, line 22), so test/live.test.js drives the whole game (join, answer, rejoin, podium) with a fake clock and no server. The speed rule is a pure exported function, `points` (line 13), and the server computes every score in `tick` (lines 35-50). The edge is a thin composition: lib/api.js wires `createLive(bank)` into a route table (lines 16-21), and server.js only does HTTP. The shape is proportionate to a 30-player, single-screen game. Weaknesses. (1) Reads have side effects: `view()` calls `tick(r)` and `state()` calls `view()`, so a GET can close a question and score it. The state machine is therefore driven by polling, not by commands, and the read model and the transition logic are tangled. (2) The core also builds presentation DTOs: `view` assembles `me`, `report`, and `podium` for the screens (lines 80-100), which puts UI shape inside the domain. (3) Storage is an in-memory `Map` closed over by the factory, with no port, and ids/codes/tokens come from crypto directly rather than an injected source, which makes codes non-deterministic in tests. (4) public/js/live.js (about 8 KB) mixes fetch, sessionStorage, polling, timers, and DOM drawing in one module, with no separation between the client's state and its views. Given the scale of the task, these are modest costs, not a broken boundary.
02:32 PM +16m 26s
T
thibault evaluated by Test Quality on Task 3 +13 points
tests 4.5 The live-game tests are real but thin. test/live.test.js:6-7 pins points(15_700)=875 and points(0)=500, which is a good boundary check but misses the round-down rule (e.g. 999 ms should give 500) and the 20 s ceiling. test/live.test.js:9-35 is one long scenario that asserts concrete values: duplicate name refused (/taken/), no key before close (the '"answer"' substring check on the open state), 875 points and rank 1, double answer refused, name reclaim after idle, podium[0] is Ada, and a 5-item report. That covers the happy path and some key paths. Gaps: nothing asserts Bob's wrong answer scores exactly 0, only that his report has 5 items. There are no tests for the 30-player cap, joining after start, invalid option (400), unknown room (404), host-only next, next while a question is open, ties in the ranking, or the answer-locking response. No HTTP-level test covers the /api/live/* routes in lib/api.js or server.js; test/server.test.js only covers the solo quiz. public/js/live.js (8 KB) and public/js/player.js have no tests at all, so the countdown, the lock, and the host and phone screens are unverified. No e2e or browser run and no screencast or podium screenshot was delivered; .ololo/artifacts has only a cost-practice.webm from an earlier task. The suite is a single unit-level flow, so it would not catch a broken live page or route.
02:32 PM +16m 18s
T
thibault evaluated by Test Quality on Task 2 +13 points
tests 4.5 The study suite is three tests in test/study.test.js. The cards test (lines 1-9 of that file) checks only that there are ten cards, that each question id exists in SEED, and that each see-also name resolves. It never compares names, questions or see-also sets against the pinned table, so a wrong link such as Compaction→Subagents would still pass. The progress test (test/study.test.js:14-22) does assert concrete values: wrong answers enter the review list, a right answer in review removes its id, the run count is 2, and clearProgress empties the list. That covers the review and clear paths but not the 5-run cap, best-score preservation during review, learned badges, or corrupt storage. Nothing exercises the wiki index grouping (wiki-view.js), the card page's practise control, the report's card links (report-view.js:reviewItem), or the reload-survives flow. There is no browser or end-to-end test of the assembled app, and the task's screencast and report screenshot have not been verified by any test. The brief's scenarios are mostly untested, and the one existing progress test is well-asserted. Since the study commit diff was empty in the work window, I could not see when these tests were added. I did not register probes, so this verdict rests on reading the files.
02:32 PM +16m 04s
T
thibault evaluated by Architecture on Task 2 +17 points
architecture 6.0 The study layer is proportionate and mostly well directed, but the dependency rule still has outward references at the centre, and the server-side seams from the first round are unchanged. Dependencies that point the right way: validate.js and report-model.js are pure, and cards.js holds only card data keyed by bank question ids, so the card layer depends inward on the bank's ids and never the reverse. progress.js takes an injected storage object (progress.js:4, recordRun at progress.js:20 with a default parameter), and it is covered by study.test.js without a DOM. The review and learned rules are therefore testable alone. Outward references remain. bank.js:1-2 imports node:fs and node:crypto, and it takes a file path (bank.js:8-9, createBank(file)), so the question bank has no storage port. The answer rule is still in the HTTP route (api.js, the POST /api/answer handler), not in a domain function. validate.js:1 imports COST_TOPIC from cost.js, so the validation core depends on the cost module. The browser orchestrator player.js imports every view and progress, and it holds the review filter (startQuiz, the ids branch) and report assembly in the UI file rather than a domain module. The top-level layout is reasonably domain-named (cost, live, validate, bank, cards, wiki-view, progress). Note that this task's work-window diff was empty, so the attribution rests on the file contents at commit 1414895. Credit to the player: the review and progress rules moved into a module with an injected store and a unit test. The bank seam and the inline answer rule from the first round are not fixed.
02:31 PM +15m 59s
T
thibault evaluated by Creativity on Task 3 +12 points
creativity 5.5 The brief's live flow is built plainly, with a few small user-facing touches beyond it. A countdown bar driven by a CSS variable (public/js/live.js, countdown and ticker code) gives visual urgency. Phones show a per-player report with right answers and explanations, opened by default (public/js/live.js, report()). Session storage keeps each player window's seat separate, and a reload reclaims it (public/js/live.js, session). Ties share a rank (lib/live.js, board()). Each is working code, but none is a memorable mechanism. There is no sound, animation or theme beyond the brief, and I have no probe or screencast showing these touches in use. The score stays near baseline.
02:31 PM +15m 59s
T
thibault evaluated by Creativity on Task 2 +14 points
creativity 6.5 Several working touches beyond the scenarios, all visible in code: a search box over cards with a 'Learned' badge (public/js/wiki-view.js:10-22); a 'Practise: question X' button on each card that runs just that question (wiki-view.js:31-37); the review list prunes itself when a question is answered right in review (progress.js:24-31); a 'Review mistakes (n)' entry point on the start page (player.js:22-23); and a concept-card link in both answer feedback (player.js:50-52) and each report item (report-view.js:21-22). These are useful and plausibly well-integrated. However, they are mostly conventional. The brief itself suggested search and a learned badge, so those earn less extra-mile credit. There is no streak, no memorable mechanism, and no screencast or probe showing the flows actually run. The score is held back to the 6–8 band on code-level evidence alone. Note also that this task's work-window diff is empty, so I judged the state at commit 1414895 directly.
02:31 PM +15m 53s
T
thibault evaluated by Code Quality on Task 2 +18 points
cleanliness 7.0 Card data is declared once in a readable table-style `card(...)` helper (public/js/cards.js:1-35), and lookups are small named functions (cardByQuestion, cardByName, cardBySlug, cardHref). progress.js is tidy, with `without` and `save` helpers and a clear header comment. The card-link anchor is built in three places, though: wiki-view.js `link()` (line 4), player.js settle() (around the `Concept card:` line, which also calls cardByQuestion twice), and report-view.js reviewItem (the last line). That is small copy-paste that should be one helper. Naming is mostly good, but 'Practise' and 'Practice' are mixed (wiki-view.js card page vs player.js route label). The diff tool returned nothing for this range, so I judged the current files directly. maintainability 6.0 Most functions are short and readable, and recordRun's review/learned bookkeeping is documented. Several spots cost comprehension: wiki-view.js draw() (lines 12-24) nests a map inside a ternary with a `[null]` sentinel to represent 'no matches', which is clever rather than clear. player.js has the same convoluted keyboard index fallback flagged in the previous round (`Number(event.key) - 1` inside choiceView), and askQuestion() still nests settle/advance closures in one function. Magic values are not named: the slice(0, 5) run cap, the storage keys, and the 'Clear all progress' flow have no constants. Error handling is sensible (storage try/catch, a null-safe route fallback to the wiki index). The progress-saving side effect inside recordRun is a hidden coupling a newcomer must discover. Tests in study.test.js cover the card table and the review list.
02:31 PM +15m 49s
T
thibault evaluated by Correctness on Task 2 +33 points
product 8.0 The committed code covers every scenario in the brief. The card index lists all ten pinned cards grouped by topic, each with a one-line summary, plus search and a Learned badge (public/js/wiki-view.js:9-24). Card data matches the pinned table exactly (public/js/cards.js:9-41, with see-also links and question ids). Explanations link to the matching card (public/js/player.js settle(), and report-view.js reviewItem). Each card's see-also opens the named card through cardByName/cardHref (wiki-view.js:33). The Practise button runs exactly that card's question (player.js route()). Wrong answers feed a persisted review list, a review run offers exactly those ids, and right answers in review remove them (progress.js recordRun). Best scores, the last five runs, the review list and a Clear all progress control persist in localStorage (progress.js, player.js progressPanel). The bank key stays server-side through publicQuestion (lib/api.js:9). Weaknesses: the study pages sit behind hash routes with no shared nav, practice runs from a card are recorded as partial runs in the run history, and I did not see probe results or a screencast in my evidence, so the interactive flows are verified from code only. The note's claims (search, learned badge, clear control, review, progress) match the code.
02:31 PM +15m 44s
T
thibault delivered cost-practice.webm 158 KB

Add cost practice

02:31 PM +15m 37s
T
thibault evaluated by Data on Task 2 +21 points
data 7.5 The study layer reads from one declared source for each concern. The ten concept cards are a single table in public/js/cards.js (name, topic, question, see-also, summary, text), and wiki-view.js, report-view.js and player.js all derive links from its lookups (cardByQuestion, cardByName, cardBySlug). Progress is one module (public/js/progress.js): best scores, last five runs, review list and learned ids are all written through recordRun and cleared through clearProgress. The review run is built from progress.review and resolved against the server's question list (player.js startQuiz), so it does not ship the key. Nothing in the diff adds mock or sample data. The main deduction is duplication: cards.js redeclares the topic strings 'Token economy' and 'Knowledge base' (cards.js:4-5), which also appear in seed.js:1-2, and it hardcodes question IDs T1–K5 instead of deriving them from SEED. Nothing enforces that the two stay in step beyond the test in test/study.test.js. The card texts are authored prose rather than copied explanations, which the brief allows. I could not see the git diff for this task's window (it returned empty), so this verdict rests on reading the current files.
02:31 PM +15m 33s
T
thibault evaluated by Test Quality on Task 1 +17 points
tests 6.0 The cost tests are mostly strong. test/cost.test.js pins the three worked examples ($0.0840, $0.2340, $0.1080) against exact values (lines 40-44), checks the per-kind breakdown rows (lines 46-53), and checks typed-answer forms, a near-miss of $0.0001, and one-try-per-question (lines 55-68). A range test covers the multiple-of-4,000 and 200,000 cap (lines 35-44). The main gaps: (1) the API cost test (test/api.test.js, 'cost practice' block) only exercises a wrong answer, a junk value and a replay; the variable named `right` actually sends 'x' and asserts false, so there is no HTTP-level correct-answer path for cost. (2) The wrong-answer case '0.085' is a fixed literal that could coincidentally equal the generated answer, so it is a small flake risk. (3) Nothing tests that cost items are excluded from review and best-score logic in recordRun, or that the report shows Cost practice's own score, and the browser flow (cost input, sum display, report) has no DOM or end-to-end test. (4) The 'no amount before answer' check is a regex on JSON keys, which is weak but present. Level mix is unit plus one API layer, with no assembled-app check for the cost flow.
02:30 PM +14m 53s
T
thibault evaluated by Data on Task 1 +25 points
data 9.0 The price card lives in one place, lib/cost.js:8-13 (KINDS, in cents per million). Every generated amount and saving is derived from it through requestFrom, savingFrom and sumOf, so nothing else redeclares the rates. The browser never holds an amount before answering: the question payload (lib/cost.js issueOne) carries only id, text, figures, hint and the price card, and the total is computed server-side and returned only from cost.check after the typed answer (api.js POST /api/answer). Sourcing is honest: the worked examples come out to the pinned amounts ($0.0840, $0.2340, $0.1080) in test/cost.test.js, and the exact-integer arithmetic (units = tokens x cents, with dollars() rounding) is exact because every generated count is a multiple of 4,000. The price card shown to the player comes from the server payload (public/js/player.js costView reads question.prices), not a client copy. The report keeps each cost item's numbers, typed value, right amount and sum (report-model/report-view via quiz.items). Remaining nits: the literal 'Cost practice' is repeated client-side in public/js/live.js (the topic filter in start()) instead of being imported or served as a flag, and the issued-question store is in-process memory with a 500-entry cap, which is acceptable for this quiz but means restarts drop open cost questions. Earlier data nits on the bank (option-count duplication) are not charged again here.
02:30 PM +14m 50s
T
thibault evaluated by Architecture on Task 1 +18 points
architecture 6.5 The cost rules sit in a pure core. lib/cost.js imports only node:crypto (randomUUID) and has no framework, HTTP, or fs reference. The price card, requestFrom, savingFrom, sumOf, and parseDollars are plain functions. test/cost.test.js imports only lib/cost.js and runs the pinned sums ($0.0840, $0.2340, $0.1080) with no server. Randomness is injected via createCostRounds(rng), so generation is deterministic under test. Server-side checking is in the domain (check() returns correct, answer, why, and sum), and the client only formats server data in public/js/sum-view.js, so the answer does not leak before submission. Deductions: createCostRounds mixes the issued-question store (a Map with eviction, lib/cost.js ~L62-L80) and randomUUID into the rules module, so the rules module also owns state. lib/api.js routes cost, bank, author, and live dispatch through one table and reaches into cost.check before bank.find. The bank still imports node:fs and takes a file path (lib/bank.js:1-2, createBank(file)), so the storage seam flagged in task #0 is still missing. lib/live.js is a reasonable pure-ish core with an injectable clock (now = Date.now), but it lives flat beside the others. The top level (lib/, public/, test/, server.js) is generic and does not name the domain (accounts, rounds, rooms). The seams are proportionate to a small quiz: one injected rng and one injected clock, with no interface rings or DTO layers. Overall: a clean pure core for cost, a missing persistence port in the bank, and a flat, generic layout.
02:30 PM +14m 47s
T
thibault evaluated by Code Quality on Task 1 +20 points
cleanliness 7.0 The cost module is tidy. Price-card kinds are a single KINDS table (lib/cost.js:7-12), and the generator, checker and sum formatter each have one job. Names like STEP, MAX_STEPS, ZERO_CHANCE and KEEP_ISSUED say what they are. Two things pull the score down. First, the 'Concept card' link markup is written twice, once in player.js settle() (line ~121-122, calling cardByQuestion twice) and once in report-view.js reviewItem (line ~17-18). Second, the item field `answer` means an option index for bank questions but a dollar string for cost questions (player.js settle call, report-view.js line ~16), so one name carries two meanings. The cost-view code itself has no dead code. Duplication was not measured, so this comes from reading the code. maintainability 7.0 The server owns the amounts: check() reads the issued question and the client never sees the total before answering (lib/cost.js check, api.js /api/answer). Money is exact integer arithmetic in 1e-8 dollars, and the price card is one table, so a newcomer can change a rate in one place. The worked examples are pinned in test/cost.test.js. Weak spots: the 1e8 and 1e4 scale factors in dollars() and UNIT are magic numbers with only a comment to explain them (lib/cost.js:14-18). The `units` name is opaque. costView and askQuestion are about 25-30 lines each, and settle(result, details, ...extra) is awkward to extend. Error paths are handled at the API boundary (unknown id, bad option, ValidationError). Nesting stays shallow.
02:30 PM +14m 39s
T
thibault evaluated by Correctness on Task 1 +33 points
product 8.0 Cost practice is implemented end to end and matches the brief. The price card is exact in integer units (lib/cost.js:8-15, dollars()/parseDollars() at lib/cost.js:20-33). I walked the three pinned examples by hand: request with cache read = 0.012+0.012+0.060 = $0.0840; request with cache write = 0.024+0.150+0.060 = $0.2340; saving = 40,000 x 2.70/1M = $0.1080. The unit tests pin all three (test/cost.test.js). Generation follows the brief: multiples of 4,000 from 4,000 to 200,000, kinds may be zero, and a round is five questions mixing both kinds. Answers are judged on the server with one try per id (lib/cost.js check()), and the client receives only figures, prices and a hint until it answers (publicQuestion-style shape, test/cost.test.js 'no amount before answering'). Typed forms '0.084', '$0.0840' and ' $0.0840 ' are accepted; '0.085' is rejected. Feedback shows a line-by-line sum table per kind (public/js/sum-view.js). The all-topics quiz appends five cost questions after the bank (lib/api.js questions route), and the report shows per-topic scores and each cost item with typed answer, right amount and sum (public/js/report-view.js reviewItem). Points against it: the bank-only review list skips cost items correctly, but the report's per-topic box only appears when there is more than one topic, which is fine for all-topics. I did not see the screencast or report screenshot, so the interactive flow and layout are judged from code only. The completion note is short but accurate to the code.
02:30 PM +14m 38s
T
thibault evaluated by Creativity on Task 1 +13 points
creativity 6.0 Several cost-specific touches go past the brief and are present in code. The typed-answer parser accepts forgiving input: optional leading $, thousands commas and surrounding spaces, and it compares exact integer units, so "0.084", "$0.0840" and "0.0840" all count as right (lib/cost.js parseDollars). The question view shows the four token figures as labelled tiles and offers a collapsible price card per question (public/js/player.js costView). The answer field has a calculator-style $ prefix and a hint toggle. A wrong answer also reveals the right amount, and the per-kind sum table is reused in the report (public/js/sum-view.js). The brief itself suggested a hint button and calculator feel, so those count for little. The rest is solid but ordinary, and there is no memorable mechanism. I did not run a probe or screencast, so the score rests on code evidence. The live-game and study-wiki code in the same diff range belongs to other tasks and is not credited here.
02:30 PM +14m 35s
T
thibault started working on Task 3

Run it live in a workshop

02:30 PM +14m 19s
T
thibault started working on Task 2

Add the study wiki and review

02:30 PM +14m 16s
T
thibault evaluated by Correctness on Task 0 +24 points
product 7.0 The code covers every scenario, and the pinned bank matches the brief. Key secrecy is enforced server-side. Visual and interactive behaviour is unverified because both screencast and report screenshot probes were still open. Minor gaps: answer locking is client-only, and the report's per-topic breakdown and restart flow exist but are unseen.
02:28 PM +12m 56s
T
thibault evaluated by UX Review on Task 0 +0 points
ux n/a No screenshot delivered: probes 5e14bee7-f4f6-47ce-8f94-5b32484d0cfc (report) and 1946ae7f-298f-41a6-853b-c94437b54b78 (question screen) are still open. Visual hierarchy cannot be judged from markup or CSS alone. accessibility n/a No screenshot delivered, so contrast and colour-only encoding cannot be checked visually. Markup has some semantics (lang="en", labelled radios and inputs in author.html, aria-live on feedback), but those do not decide the criterion. mobile n/a No narrow-width capture was delivered. The CSS has a media query and fluid grids (style.css author-grid at min-width 860px, auto-fit cards), but a responsive claim needs a rendered 375px view, which I do not have.
02:28 PM +12m 42s
B
Bavo Van Craeyenest delivered 2 files 437 KB

Build the quiz

02:26 PM +10m 47s
I
ikram started working on Task 0

Build the quiz

02:23 PM +7m 04s
T
thibault evaluated by Architecture on Task 0 +13 points
architecture 5.5 The pure parts are cleanly separated. lib/validate.js imports nothing and holds the completeness rules, and public/js/report-model.js is pure aggregation. The report and quiz rules are testable without a server. The main defects are in the core bank and the route layer. lib/bank.js is both the domain and the repository: it imports node:fs (existsSync, readFileSync, writeFileSync, renameSync) and node:crypto (randomUUID), and takes a file path (createBank(file)), so persistence is hard-wired into the core with no storage interface to invert. The answer-judging rule (`body.choice === question.answer`, lib/api.js ~line 30) lives inside an HTTP route handler rather than in a domain function, so the rule sits at the edge. lib/api.js also mixes the route table, query/body parsing and HTTP status mapping, which is an acceptable adapter role. On the client, public/js/player.js mixes quiz flow with DOM construction, and report-model.js defaults to globalThis.localStorage, though it accepts storage as a parameter. Proportion is reasonable for a two-hour build: four small lib files and no DTO or interface rings. The top level (lib/, public/, server.js) is only partly screaming; 'bank' and 'validate' name domain concepts, but 'api' and 'seed' are generic.
02:18 PM +2m 40s
T
thibault evaluated by Test Quality on Task 0 +13 points
tests 5.5 The suite has real assertions and covers the server-side contract well. test/api.test.js checks topic counts, that the public question payload omits answer and why, server-side judging with 400/404 error paths, author add/edit/remove/reset, and per-field 422 refusals for incomplete or duplicate options. test/bank.test.js checks persistence across reload. test/server.test.js checks static serving, path traversal, and bad JSON. Gaps: the pinned-bank check in bank.test.js:11-13 verifies only three of the ten answers, so a changed fact in the other seven would pass. Nothing tests the front end: player.js (locking after answer, keyboard play, report flow), report-view.js, and author.js are untested, and coverage excludes them. validate.js has no direct unit tests, and there is no test for update() on a missing id beyond the API 404. No end-to-end or browser test exists. The task's required screencast and report screenshot are not tests, and no artifacts were delivered. The test suite is proportionate in size but thin where the UI behaviour lives.
02:18 PM +2m 38s
T
thibault evaluated by Data on Task 0 +21 points
data 9.0 The pinned bank has one source of truth: `lib/seed.js` (SEED, lines 1-67), which is copied into a JSON-persisted store (`lib/bank.js` load/save, `data/bank.json`) and served by the backend. The ten questions, answer indexes and explanations match the brief (for example T2 answer 2 with the 'Output is priced several times higher' explanation, and K3 answer 2 'Lint'). The player API returns only `{id, topic, text, options}` through `publicQuestion` (`lib/api.js`). The answer key and explanation leave the server only in the `/api/answer` reply (`lib/api.js`, the POST /api/answer route), and the client bundle contains no bank (`public/js/*.js` has no question data). Answers are judged server-side (`body.choice === question.answer`). Authoring goes through a validated bank API (`lib/validate.js`, `validQuestion`), and reset restores from the same SEED, so no drifting copy exists. Minor deductions: the option count (4) is repeated in `validate.js` (`OPTION_COUNT`) and the letters in `dom.js`/`author.html` (A-D labels hardcoded in markup), which are structural rather than question data. The `/api/author/*` routes expose the key without auth, which the brief does not require protecting. The `session2/backend/data/pots.db` deletion is leftover from an earlier session, not this task's data.
02:18 PM +2m 31s
T
thibault evaluated by Code Quality on Task 0 +15 points
cleanliness 6.5 The core modules are readable and mostly free of dead code. Naming is clear (createBank, validQuestion, buildReport, showReport). Deductions: the four option rows in public/author.html:18-21 are copy-pasted markup, and LETTERS in public/js/dom.js:11 hardcodes the same count that OPTION_COUNT in lib/validate.js:1 names. The commit also deletes a binary file (session2/backend/data/pots.db) and the tree still carries session1/2/3 leftovers. Duplication is not measured here, so this rests on reading. No analysis probe was supplied. maintainability 6.5 Server layers are well separated: the route table in lib/api.js, persistence in lib/bank.js, and validation in lib/validate.js. Errors are handled at the boundary (422 for validation, 400 for bad JSON, 404 for unknown ids). Concerns: askQuestion in public/js/player.js:24-63 is a long closure that also owns keyboard handling. It reassigns document.onkeydown on every question, and the index/digit fallback `index > -1 ? index : digit` (player.js:~70) is hard to read. The api.js:33 idiom `found(questions.length && questions)` is clever rather than clear. The persistence path and the reset control are simple to follow, and tests cover the API, bank, validation and report model.
02:18 PM +2m 30s
T
thibault evaluated by Creativity on Task 0 +13 points
creativity 7.5 Several working touches go beyond the brief, all visible in code. Keyboard play: the document keydown handler maps A–D and 1–4 to answers (public/js/player.js, the `document.onkeydown` block). Feedback: a wrong pick shakes and the right option is highlighted, with a live-region explanation (style.css `.option.wrong` shake; player.js feedback block). Progress is a labelled progressbar with a per-question header. The last report can be reopened from the start screen after a reload, backed by localStorage (player.js `showStart`, report-model.js `saveReport`/`loadReport`). Per-topic breakdown appears on all-topics reports (report-view.js). The author page adds topic datalist hints, per-field aria-invalid errors, a confirmed restore-to-pinned control, and a clean dark-mode palette (style.css `prefers-color-scheme`). These are useful and plausibly functional, but I did not see a screencast or report screenshot, so the score stays below the memorable-demo band. No single standout mechanic beyond the baseline polish.
02:18 PM +2m 27s
T
thibault started working on Task 1

Add cost practice

02:18 PM +2m 19s
T
thibault started working on Task 0

Build the quiz

02:15 PM +0s
B
Bavo Van Craeyenest started working on Task 0

Build the quiz

02:15 PM +0s