Skip to content

fix(practice): converge the practice gate and repair the #41 findings - #43

Merged
NiclasDev63 merged 2 commits into
mainfrom
claude/github-issue-41-b47738
Sep 4, 2026
Merged

NiclasDev63 merged 2 commits into
mainfrom
claude/github-issue-41-b47738

Conversation

@NiclasDev63

Copy link
Copy Markdown
Contributor

Closes #41.

1. Practice work lost on reload — fixed, no new column

gradedBlocks already persists a learnerAnswer per practice field, and a
graded practice field's blockId is its solution field id — so the work
object can be rebuilt rather than stored twice. derivePendingSubmissions
does that, and sdkScript now starts submitted = true in review mode, so a
resumed scene reopens with the learner's own answers and an inert Submit.

An exploratory scene (solution: null) grades no fields, so there is nothing
to rebuild — it reopens blank but non-resubmittable, which is what the ticket
asked for as the floor.

2. Auto-created Introduction scene — fixed

isBlankHtmlState now recognises what the seeder actually writes, so the
untouched default classifies as EMPTY_SCENE ("add content") instead of
UNREADABLE_SCENE ("open the scene and re-save it") — an instruction an agent
can act on.

3. getSceneContent on a PRACTICE scene — fixed

Refuses with BAD_REQUEST naming getPractice, mirroring what insertContent
already does on the write side.

4. Draft SP reads 0 — fixed

Draft and published now sum the same way through a shared
sumPracticeSolutionSp.

5. Tool descriptions and schema — fixed, except correctAnswer

  • createScene says insertContent for DOCUMENT, writePractice for PRACTICE.
  • publishCourse lists the refusals an agent actually hits, including the
    unfinished-practice one, in the words it will get back.
  • explanation takes .default(null) — omit it and you get no explanation.
  • Not changed: validatePractice still returns correctAnswer. It is
    reachable only with an authoring token, and such a caller can already read
    the whole solution from getPractice; hiding it here would remove the field
    feedback without removing the exposure.

6. Polish — fixed

Publish failures now carry details.code + details.params and are
translated client-side (translatePublishFailure, {{param}} interpolation);
every code has en and de copy. PRACTICE scenes get their own icon and label in
the scene list. The stale "Geprüft" note is gone with the stamp it described —
readiness is recomputed live.

7. Zero-to-published over MCP — fixed by converging the gate

One pure function replaces the stamp, the content hash and the browser sweep:

checkPracticeScene({ practiceHtml, practiceSolution }): string[]

It reads the app source and reports what is missing: no __sciblySelfTest
assignment, no scibly.submit(work), no scibly.onGraded(), or a solution
field the html never mentions. Publish, MCP validatePractice and the
editor's readiness line all call it
, so publish refuses with the same
sentence validatePractice reports, and a 12-scene practice course needs zero
editor clicks. practiceValidated is dropped
(20260904140000_drop_practice_validated_stamp).

Known ceiling, carried as a ponytail: comment: these are string checks, not a
parser — an app with all four markers that still throws at runtime gets
through. Upgrade path is a headless Chromium run behind the same function.

Tests

pnpm check (32 tasks), pnpm test:unit (all packages) and pnpm test:int
(6 files, 29 tests) are green. New: check-practice-scene.test.ts,
publish-failure.test.ts, publish-validation SOL9b/SOL11b/SOL12b,
review-path RP4, and MCP integration test IT3 — publish refusing an app whose
self-test hook was renamed, asserting on the sentence the agent sees.

Integration tests now provision their own throwaway Postgres (pgvector, bound
to loopback) and remove it on every exit path including Ctrl-C and failure;
INT_DB= still points them at a local cluster you already have, with the
localhost guard intact. pnpm test:all includes them.

Second commit

chore: working-tree drift unrelated to #41 is deslop/CSS/i18n churn that was
already in the tree when this work started, plus a whitespace-only reformat of
the vendored prism package.json. Split out so the fix commit reads clean —
drop it if the branch should carry only #41.

🤖 Generated with Claude Code

NiclasDev63 and others added 2 commits September 4, 2026 22:15
…akage

Closes #41.

- Practice work survives a reload: derivePendingSubmissions rebuilds
  practiceWork from the gradedBlocks already persisted per field, so a
  completed scene reopens in review mode showing the learner's own answers
  instead of a blank app.
- A blank Introduction scene no longer publishes: author-document treats
  the untouched default document as empty.
- getSceneContent on a PRACTICE scene refuses by name and points at
  getPractice, instead of returning a scene with no content.
- The draft editor counts practice SP the way the player does, through a
  shared sumPracticeSolutionSp.
- One gate for everything: checkPracticeScene(html, solution) is a pure
  check that publish, MCP validatePractice and the editor's readiness line
  all run. No stamp column, no content hash, no browser sweep — so an agent
  goes from createCourse to publishCourse without a UI visit, and publish
  refuses an unfinished app with the same sentence validatePractice gives.
- publish failures carry details.params and are translated client-side;
  every code has en and de copy.

Integration tests provision their own throwaway Postgres (pgvector, bound
to loopback) and tear it down on every exit path, including Ctrl-C and
failure; INT_DB still overrides for a local cluster you already have.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Already present when this branch's work started: deslop comment-scanner
tweaks, editor CSS, two i18n strings, and a whitespace-only reformat of the
vendored prism package.json. Split out so the fix commit stays readable —
drop this one if the branch should carry only #41.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated
startup-app Ignored Ignored Sep 4, 2026 8:16pm UTC
startup-web Ignored Ignored Sep 4, 2026 8:16pm UTC

Request Review

@NiclasDev63
NiclasDev63 merged commit fb761ff into main Sep 4, 2026
4 checks passed
@NiclasDev63
NiclasDev63 deleted the claude/github-issue-41-b47738 branch September 5, 2026 17:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PRACTICE scenes + headless MCP: post-review fixes and refactors

1 participant