| Phase | Name |
|---|---|
| F | Foundation — spikes on all experimental components |
| C | Core System Skeleton — apply verified patches |
| I | Integration Layer — first game deployed, full pipeline tested |
| B | Full Feature Build — student workflow + additional templates |
| H | Hardening — error handling, edge cases |
| R | Release |
SPIKE FLAG: All three Zebonastic patches (scanArtifactsDir, tools/page.tsx, tools/[slug]/page.tsx) are unverified against the live codebase. The Foundation phase runs six spike steps — three Claude, three human — before any patch is applied. No C-phase work begins until all Foundation handoff conditions are met.
Before Claude Code touches anything, the human must decide what "this spike passed" means for each experimental component. Claude Code will verify against whatever criteria exist; if the criteria are vague, the verification is vague.
Write down — literally, in a text file or a note — the pass/fail condition for each of the three spikes about to run:
scanArtifactsDir() called on a directory containing one flat .html file and one subdirectory with index.html returns exactly two results, both with correct slug, isDirectory, artifactPath, keywords[], and title fields.PEEP_METADATA overwritten with example-game.json values before any Slideshow/PIXI initialization log appears.Do not proceed to Step 2 without these written down. The spike sequence is only useful if the human can say "pass" or "fail" without ambiguity.
Handoff condition: Spike success criteria exist in writing before Step 2 begins.
Dependency: None.
Context required: trust-template/generate.js, trust-template/example-game.json, a clone of ncase/trust at ./trust-source
Create a directory ./example-game/ containing a copy of example-game.json from trust-template/.
Then run:
node trust-template/generate.js ./example-game ./trust-source ./dist-smoke-test
After the run completes:
1. Verify directory structure: dist-smoke-test/ contains index.html, words.html, js/, css/, assets/
2. Verify meta tag injection in dist-smoke-test/index.html:
grep -n "description\|keywords\|user-config\|Evolution of Trust" dist-smoke-test/index.html
Expected: <title>The Evolution of Trust</title>, <meta name="description"...>, <meta name="keywords"...>, <script src="js/user-config.js">
3. Verify user-config.js was generated:
cat dist-smoke-test/js/user-config.js
Expected: PEEP_METADATA = { tft: { frame: 0, color: "#4089DD" }, all_d: ... } with all 8 strategy IDs
4. Report the full terminal output from the generator, any errors, and the results of steps 2–3.
Expected output: Terminal output showing all copy steps completing with "done", grep showing all 4 expected lines in index.html, user-config.js showing all 8 strategy keys.
Handoff condition: Generator runs without errors, all 4 expected strings found in index.html, all 8 strategy IDs present in user-config.js.
Dependency: None (runs locally, no Zebonastic site involved).
Claude Code can verify that strings exist in files. It cannot open a browser and evaluate whether what appears on screen matches the intended character design. This check requires eyes.
cd dist-smoke-test
npx http-server -p 8080
Open http://localhost:8080. Play through the first three slides. Check:
example-game.json (#4089DD blue for tft/Copycat, #52537F purple for all_d/Always Cheat, etc.)If any character shows the wrong color or the original name ("Copycat" is the original — acceptable here since example-game.json uses original names intentionally), that is not a failure. A failure is: characters all showing a single wrong color, or a JS error in the console before any slide renders.
Handoff condition: Game loads in browser, characters display colors matching example-game.json, no JS errors on load.
Dependency: Step 2.
Context required: trust-template/zebonastic-patches/lib-html-meta-addition.ts, the Zebonastic project's lib/html-meta.ts
Write a test script test-scan-artifacts.ts at the Zebonastic project root that spikes scanArtifactsDir() in isolation before it touches the live codebase.
The script should:
1. Create a temporary test directory at /tmp/test-artifacts-spike/ containing:
- /tmp/test-artifacts-spike/flat-tool.html with:
<title>Flat Tool</title>
<meta name="description" content="A flat HTML tool"/>
<meta name="keywords" content="test, flat, html"/>
- /tmp/test-artifacts-spike/dir-game/index.html with:
<title>Directory Game</title>
<meta name="description" content="A directory-based game"/>
<meta name="keywords" content="game, directory, trust, ethics"/>
2. Run the scanArtifactsDir() function from lib-html-meta-addition.ts against /tmp/test-artifacts-spike/
(copy the function inline or import it — whichever compiles faster)
3. Assert all of the following and print PASS or FAIL for each:
- Result count = 2
- flat-tool: isDirectory=false, slug='flat-tool', artifactPath='/artifacts/flat-tool.html'
- flat-tool: keywords includes 'test', 'flat', 'html'
- dir-game: isDirectory=true, slug='dir-game', artifactPath='/artifacts/dir-game/index.html'
- dir-game: keywords includes 'game', 'directory', 'trust', 'ethics'
- dir-game: title = 'Directory Game'
- Both results: description is non-empty string
4. Run the script with: npx ts-node test-scan-artifacts.ts
Report the full output and any TypeScript compilation errors.
Clean up /tmp/test-artifacts-spike/ after the test.
Expected output: 7 PASS lines, no FAIL lines, no TypeScript errors.
Handoff condition: All 7 assertions pass. If any fail, the failure mode must be diagnosed before Step 10 begins.
Dependency: Step 1 (success criteria defined before running the spike).
The test script verifies what it was told to verify. The human checks whether those assertions are sufficient — whether there are failure modes the test didn't cover.
Read the test output from Step 4. Check two things the test didn't:
"game, directory" → ["game", " directory"]), does the slug-derived keyword strip the space? It should. Check the raw output.index.html? Confirm that scanArtifactsDir() skips it rather than returning an entry with a null/empty artifactPath.If either check fails, log it as a bug to fix in Step 10 before the function is added to the live codebase.
Handoff condition: Keyword strings are trimmed. Directories without index.html are skipped. Both confirmed from test output or via a follow-up test.
Dependency: Step 4.
Context required: The Zebonastic project codebase (app/tools/ToolsBrowser.tsx and any files that import it)
Read-only audit of ToolsBrowser.tsx. Make no changes.
1. Read app/tools/ToolsBrowser.tsx and paste the full TypeScript props interface (the type or interface that defines what the component accepts as props).
2. Run:
grep -rn "ToolsBrowser" --include="*.tsx" --include="*.ts" .
List every file that imports or uses ToolsBrowser and what props it passes.
3. Find the .map() call(s) inside ToolsBrowser that render tool cards. Paste the relevant 10–15 lines showing what fields are accessed on each item (e.g. item.name, item.slug, item.description, etc.).
4. Answer: if we add a new optional prop artifactPath?: string to the item type, does that break any existing caller? (A caller breaks if it passes a prop that no longer exists, or if it omits a prop that becomes required.)
5. The new ToolCard type we need to accept is:
{
id: string;
name: string;
description: string;
tags: string[];
source: 'filesystem' | 'database';
type: 'artifact' | 'link';
href: string;
artifactPath?: string;
externalUrl?: string;
openExternal: boolean;
}
Write the minimal diff to ToolsBrowser.tsx that accepts ToolCard[] while keeping all existing callers working — but do not apply it yet. Return the diff only.
Expected output: The existing props interface, a list of callers, the accessed fields from the .map(), a clear yes/no on breaking change risk, and a minimal diff.
Handoff condition: Existing props interface is documented. All callers identified. Diff produced. The human can read this output and make the decision in Step 7.
Dependency: Step 1.
The audit in Step 6 surfaces facts. The decision about what to change — and whether the change is acceptable given how the rest of the codebase was built — requires someone who knows the full site and can be accountable for the result.
Read the Step 6 output. Decide:
app/tools/page.tsx: the change is safe. Apply the diff from Step 6.Record the decision in a comment in the patch file before Step 11 runs.
Handoff condition: A specific change strategy is chosen. The diff from Step 6 is either approved as-is or annotated with modifications.
Dependency: Step 6.
Context required: dist-smoke-test/ from Step 2, specifically dist-smoke-test/js/user-config.js and dist-smoke-test/index.html
Add a timing probe to the smoke test build to verify that PEEP_METADATA is overwritten before any slide initialization runs.
In dist-smoke-test/js/user-config.js, add these two console.log lines immediately after the PEEP_METADATA = {...} assignment:
console.log('[user-config] PEEP_METADATA set. Keys:', Object.keys(PEEP_METADATA));
console.log('[user-config] tft.color =', PEEP_METADATA.tft && PEEP_METADATA.tft.color);
Also add this at the very top of dist-smoke-test/js/user-config.js (before the IIFE):
console.log('[user-config] script loaded');
Then print instructions for the human to follow:
1. Open a terminal: cd dist-smoke-test && npx http-server -p 8080
2. Open http://localhost:8080 in a browser
3. Open browser DevTools → Console
4. Look for:
- '[user-config] script loaded' appearing in the log
- '[user-config] PEEP_METADATA set. Keys: [tft, all_d, all_c, grudge, prober, tf2t, pavlov, random]'
- '[user-config] tft.color = #4089DD'
- Whether these appear BEFORE or AFTER any Slideshow/PIXI log lines
Do not serve the file automatically — the human must run this step manually and report what the console shows.
Expected output: Instructions printed for the human, probe lines added to user-config.js.
Handoff condition: user-config.js has the probe lines added and is ready for human browser verification.
Dependency: Step 2.
This is the single check Claude Code cannot perform. It requires opening a browser, reading a console, and making a judgment about log order. If the overwrite happens after PIXI initializes, characters will silently display wrong colors in the live site — no error thrown.
Follow the instructions from Step 8. Serve dist-smoke-test/ and open the browser console. Look for:
[user-config] script loaded — confirms the script tag injection worked[user-config] PEEP_METADATA set. — confirms the overwrite executed[user-config] tft.color = #4089DD — confirms the correct valuePASS: All three probe lines appear before any PIXI/Slideshow initialization.
FAIL (and what to do): If probe lines appear after PIXI lines, the <script src="js/user-config.js"> injection point in generate.js is wrong — the tag must be moved later in index.html. Return to generate.js's patchIndexHtml() function and find a script tag that loads after all PIXI dependencies but before any slide initialization.
Handoff condition: All three probe lines appear in console before PIXI/Slideshow logs. The overwrite executes at the right moment.
Dependency: Step 8.
Context required: lib/html-meta.ts (existing file), trust-template/zebonastic-patches/lib-html-meta-addition.ts (the patch to add), Step 5 bug log (if any keyword trimming or empty-directory issues were found)
Add scanArtifactsDir() to lib/html-meta.ts. Source: trust-template/zebonastic-patches/lib-html-meta-addition.ts.
Before adding:
1. Read the existing lib/html-meta.ts — check if there is already an extractMeta or similar helper function for reading title/description/keywords from HTML. If yes, use it instead of duplicating.
2. Check if there is already a slugify() function in lib/html-meta.ts or lib/utils.ts. If yes, use the existing one.
3. Apply the keyword trimming fix if flagged in Step 5: ensure keywords array trims whitespace from each element.
4. Apply the empty-directory guard if flagged in Step 5: directories without index.html are skipped.
Add the function and the ArtifactMeta interface as named exports. Do not modify any existing function.
After adding:
npx tsc --noEmit
Report the compilation result. If there are type errors, paste them and fix them.
Expected output: lib/html-meta.ts updated with scanArtifactsDir() and ArtifactMeta as exports. npx tsc --noEmit exits with no errors.
Handoff condition: TypeScript compilation clean. scanArtifactsDir and ArtifactMeta are named exports from lib/html-meta.ts.
Dependency: Steps 5 (spike passed), 7 (ToolsBrowser decision made — needed before proceeding to 11).
Context required: app/tools/ToolsBrowser.tsx (existing), Step 6 audit output, Step 7 decision
Update ToolsBrowser.tsx to accept ToolCard[] per the decision recorded in [Step 7].
The ToolCard type:
{
id: string;
name: string;
description: string;
tags: string[];
source: 'filesystem' | 'database';
type: 'artifact' | 'link';
href: string;
artifactPath?: string;
externalUrl?: string;
openExternal: boolean;
}
Apply the specific strategy chosen in Step 7 (additive extension, union type, or new component).
In the card rendering:
- Cards with openExternal=true: render as <a href={card.href} target="_blank" rel="noopener noreferrer">
- Cards with openExternal=false: render as <Link href={card.href}>
- Artifact cards (type='artifact'): show 'Artifact' badge
- Link cards (type='link'): show 'Link' badge
Preserve: search input behavior, tag filter bar, card grid layout, all existing visual design.
After the change:
npx tsc --noEmit
Report any type errors and fix them.
Expected output: ToolsBrowser.tsx updated with ToolCard type support. No type errors.
Handoff condition: TypeScript compilation clean. Both link and artifact card types render with correct navigation behavior.
Dependency: Steps 7, 10.
Context required: app/tools/page.tsx (existing), trust-template/zebonastic-patches/app-tools-page.tsx (patch)
Apply the tools/page.tsx patch from trust-template/zebonastic-patches/app-tools-page.tsx.
Before applying:
1. Read the existing app/tools/page.tsx
2. Note any content that differs from the patch:
- Different page metadata (title, description)
- Additional database queries beyond the basic tools table fetch
- Any extra tool types or display logic not in the patch
3. Merge those site-specific elements into the patch before applying
Key behavior to preserve:
- Database link tools must continue to appear alongside filesystem artifact tools
- The page must remain a server component (no 'use client')
Apply the merged file, then:
npx tsc --noEmit
Report any type errors.
Expected output: app/tools/page.tsx replaced with merged version. No type errors.
Handoff condition: TypeScript compilation clean. The page imports scanArtifactsDir from lib/html-meta and passes ToolCard[] to ToolsBrowser.
Dependency: Steps 10, 11.
Context required: app/tools/[slug]/page.tsx (existing), trust-template/zebonastic-patches/app-tools-slug-page.tsx (patch)
Apply the tools/[slug]/page.tsx patch from trust-template/zebonastic-patches/app-tools-slug-page.tsx.
Before applying:
1. Read the existing app/tools/[slug]/page.tsx
2. Note any UI differences in the title bar (different styling, additional buttons, different "Back" link text) or iframe container (different height calculation, sandbox attributes)
3. Merge those into the patch — especially preserve any existing iframe sandbox or allow attributes
The critical behavior change in the patch: resolveFilesystemArtifact() tries both:
public/artifacts/[slug].html (flat file — existing behavior)
public/artifacts/[slug]/index.html (directory artifact — new)
The flat path is tried first, so existing tools are not affected.
Apply the merged file, then:
npx tsc --noEmit
Report any type errors.
Expected output: app/tools/[slug]/page.tsx replaced with merged version. No type errors.
Handoff condition: TypeScript compilation clean. resolveFilesystemArtifact() handles both flat and directory paths.
Dependency: Step 10. (This step is independent of Steps 11–12; it can run in parallel if needed.)
Deciding to push to a preview branch rather than main is a tool orchestration decision. The human chooses when to expose the change to Vercel's build system — and chooses a preview branch so a build failure doesn't break the live site.
git checkout -b feat/directory-artifacts
git add lib/html-meta.ts app/tools/ToolsBrowser.tsx app/tools/page.tsx app/tools/[slug]/page.tsx
git commit -m "feat: add directory artifact discovery for trust-template games"
git push origin feat/directory-artifacts
Wait for the Vercel preview deploy to complete. Check the deploy log for build errors — specifically TypeScript compilation errors and any server component errors.
If the build fails: paste the Vercel deploy log error into Claude Code and ask it to diagnose.
Handoff condition: Vercel preview build succeeds (green check in Vercel dashboard). No build errors in the deploy log.
Dependency: Steps 12, 13.
Regression check before adding any game. The patch should not have changed anything visible on the tools page yet — no directory artifacts exist in the repo. If something broke, it broke because of the code change, not because of new content.
Navigate to the preview deployment's /tools page. Verify:
/tools/[slug] and loads the iframePASS: All existing tools work. Page looks identical to production except it's running the patched code.
FAIL: Any existing tool disappears or its behavior changes. This means the merger in Step 12 dropped something from the original page.tsx. Return to Step 12 and fix.
Handoff condition: All existing tools work on the preview deployment. Zero regressions.
Dependency: Step 14.
Context required: trust-template/generate.js, trust-template/example-game.json, ./trust-source/ (trust game source), the Zebonastic project root path
Deploy the evolution-of-trust starter template to the Zebonastic site.
1. Create ./example-game/ containing example-game.json from trust-template/
2. Run:
node trust-template/generate.js ./example-game ./trust-source --nextjs .
(This writes to ./public/artifacts/evolution-of-trust/)
3. Verify the output:
ls -la public/artifacts/evolution-of-trust/
ls -la public/artifacts/evolution-of-trust/js/
grep -n "description\|keywords\|user-config" public/artifacts/evolution-of-trust/index.html
4. Commit to the preview branch:
git add public/artifacts/evolution-of-trust/
git commit -m "feat: add evolution-of-trust starter template (trust-template reskin)"
git push origin feat/directory-artifacts
Report the generator output, the verification results, and the git output.
Expected output: public/artifacts/evolution-of-trust/ created with full game structure. index.html contains description, keywords, and user-config.js script tag. Committed and pushed to preview branch.
Handoff condition: Directory exists in the repo. index.html passes the grep checks. Commit is on the preview branch.
Dependency: Steps 3 (generator verified), 9 (overwrite timing verified), 15 (site preview stable with no regressions).
The first moment the full pipeline is visible end-to-end. The card should appear; the fact that it does tells you scanArtifactsDir() found the directory, extracted the metadata, and ToolsBrowser rendered it correctly.
After Vercel rebuilds the preview (from the Step 16 commit), navigate to /tools. Verify:
example-game.json/tools/evolution-of-trust (not to an external URL)PASS: All 5 checks clear.
FAIL on 1–4: scanArtifactsDir() or the metadata extraction failed. Add console.log to scanArtifactsDir() and check Vercel function logs.
FAIL on 5: ToolsBrowser is still routing artifact cards to external URLs. The openExternal field isn't being read correctly.
Handoff condition: Card appears on /tools with correct title, description, tags, and routing.
Dependency: Step 16.
The highest-stakes handoff in the build. Three independent failure modes (wrong iframe src, WebGL blocked in iframe, PD.js overwrite timing) all manifest here simultaneously. If this fails, the cause must be isolated before anything else proceeds.
Click through to /tools/evolution-of-trust. Verify end-to-end:
example-game.json (blue for Copycat, dark purple for Always Cheat, etc.)resolveFilesystemArtifact() returned wrong path. Check network tab for the iframe src URL and 404s.PEEP_METADATA overwrite failed in iframe context. Check that user-config.js is present in the deployed public/artifacts/evolution-of-trust/js/.PD.PAYOFFS_DEFAULT assignment in user-config.js failed. Check if PD is in scope when user-config.js runs.Handoff condition: Game loads in iframe, characters display correct colors, payoffs apply correctly, no console errors.
Dependency: Step 17.
This is the gap the course is built on. Claude Code cannot evaluate whether the game works as a teaching tool. That requires playing it, having domain knowledge of how the prisoner's dilemma functions as an ethical frame, and making a judgment about whether a student who has never encountered game theory will encounter moral weight or mere strategy.
Play the Evolution of Trust game end-to-end as a first-time student in Ethical Play Week 7. Ask:
This is not a pass/fail check. It's a content judgment about whether this template will serve the course. Record any observations that should inform how the STUDENT-GUIDE.md (Step 21) frames the template for students.
Handoff condition: Instructor has played the game and has an opinion about whether it serves the pedagogical goal. That opinion feeds Step 20 and Step 21.
Dependency: Step 18.
The most irreducibly human step in the entire build. Claude Code can generate a trust-template reskin for any spec. It cannot decide what ethical framework a reskin should embody, which characters would best dramatize that framework, or what words.html should say to produce felt moral weight rather than ethical description. That is the course's subject matter.
For each additional starter template (estimate 2–3 based on course frameworks), write a spec before Step 22 runs:
This spec is the entire input to Step 22. The quality of Step 22's output is bounded by the quality of this spec.
Handoff condition: Written spec for each additional template exists. Each spec names the ethical framework, the payoff reframing, and the 8 characters before Claude Code writes a line.
Dependency: Step 19 (pedagogical assessment informs the spec).
Context required: Step 3 and Step 9 results (verified generator behavior), Step 19 observations (pedagogical notes), trust-template/README.md
Write a student-facing guide: "How to reskin a trust template with Claude Code."
Save to trust-template/STUDENT-GUIDE.md.
Target reader: a graduate engineering student in the Ethical Play course, Week 7 (Build I: Core Mechanic). They have a completed GDD and a chosen ethical framework. They have not worked with the trust game codebase before. They use Claude Code.
Cover exactly these topics, in this order:
1. What the template gives you (the prisoner's dilemma mechanics, free — you change who's playing and why, not how the math works)
2. The one constraint they cannot change: each of the 8 characters must embody one of the 8 fixed strategy IDs (tft, tf2t, grudge, all_d, all_c, random, pavlov, prober). Explain this as a design constraint, not a technical limitation: the strategy behavior IS the ethical position.
3. The three files they edit: game.json, words.html, assets/
4. game.json step-by-step: name, color, the strategy ID assignment. One concrete example: "If your consequentialist framework casts Copycat as 'The Proportionalist,' change name to 'Proportionalist' and keep strategy: 'tft'."
5. words.html step-by-step: how to find character name spans (<span class="tft">Copycat</span>), how to replace the display text. Warning: replacing the id attribute breaks the game — replace only the text inside the span.
6. Running the generator — exact command: node generate.js ./my-game ./trust-source --nextjs /path/to/zebonastic
7. What to do when the build fails: paste the error into Claude Code and ask: "The trust-template generator returned this error. What's wrong with my game.json?"
Tone: direct. No condescension. These are graduate engineering students. The ethical architecture decisions are theirs; the technical steps are the generator's job.
Length: one page. No headers beyond the 7 topics above.
Expected output: trust-template/STUDENT-GUIDE.md, approximately 600–800 words, covering all 7 topics, no fluff.
Handoff condition: Guide covers all 7 topics. The <span class="tft"> warning is explicit. The strategy ID constraint is explained as a design constraint, not a technical one.
Dependency: Steps 3, 9 (generator is verified, so the commands in the guide are accurate).
Context required: The spec from Step 20 for this specific template, trust-template/example-game.json (as schema reference), ./trust-source/ (trust game source)
Generate a trust-template reskin per this spec:
[PASTE SPEC FROM STEP 20 HERE — title, slug, ethical framework, 8 character definitions, payoff reframing]
Steps:
1. Create ./[slug]/ containing game.json with:
- meta.title, meta.slug, meta.description matching the spec
- meta.keywords including the ethical framework name and 'ethical play'
- 8 characters: each with id matching a valid strategy ID (tft/tf2t/grudge/all_d/all_c/random/pavlov/prober), name and color from the spec, frame 0–7 (one unique frame per character)
- payoffs from the spec (or default 2/3/-1/0 if not specified)
2. Validate the game.json before building:
node trust-template/generate.js ./[slug] . --validate
3. If validation passes, build:
node trust-template/generate.js ./[slug] ./trust-source --nextjs .
4. Verify: ls -la public/artifacts/[slug]/
5. Commit:
git add public/artifacts/[slug]/
git commit -m "feat: add [slug] starter template ([ethical framework])"
Report: any validation errors encountered, the verification output, the final commit hash.
Expected output: New game directory in public/artifacts/[slug]/, committed to the preview branch.
Handoff condition: --validate passes. Generator completes without errors. Directory exists in the repo.
Dependency: Steps 16 (generator is verified end-to-end), 20 (instructor spec exists).
Context required: trust-template/generate.js, observations from Steps 2 and 16 (any edge cases encountered during actual runs)
Improve error handling in trust-template/generate.js. Apply these specific changes:
1. Strip _note fields before processing: after JSON.parse(config), recursively remove any key starting with "_" from all objects. This prevents _note comment fields in game.json from causing unexpected behavior.
2. Specific missing-file error: when trust-source is missing a required engine file (js/sims/PD.js, index.html), fail with: "❌ Missing required file in trust-source: [filename]. Is this the ncase/trust repository?"
3. Keywords as string or array: if meta.keywords is a comma-separated string, split it into an array before validation. If it's already an array, use as-is.
4. Guard against empty alias args: the current arg parsing for output-dir can match '--nextjs' itself if the user forgets the path argument. Add a check: if the output-dir argument starts with '--', it's a flag not a path — fail with a clear error.
5. Add --dry-run flag: when present, print what would be copied/generated without writing any files. Format:
[dry-run] Would copy: ./trust-source/js → ./dist/js
[dry-run] Would generate: ./dist/js/user-config.js
[dry-run] Would write: ./dist/index.html (patched)
After changes:
- Run with example-game.json: node generate.js ./example-game ./trust-source --dry-run
- Run with a broken game.json (remove the 'tft' character): verify the error message is specific
- Report all outputs
Expected output: Updated generate.js with 5 improvements. All three test runs produce expected output.
Handoff condition: --dry-run works. Broken game.json produces specific error naming the missing strategy. _note fields don't cause validation errors.
Dependency: Steps 2, 16 (real runs have surfaced actual edge cases by now).
Deciding how the tool fails is a pedagogical decision, not a technical one. A generator that warns-and-continues with defaults may produce a game that runs but encodes the wrong ethical framing — and the student won't know. A generator that fails loudly may frustrate students who want to iterate quickly. The instructor decides which failure mode serves the course.
Decide the error behavior policy for student-facing generator runs:
description, shortName) print but don't stop the build.For the Ethical Play course, the design decision is the student's core deliverable. A generator that silently patches their mistakes is pedagogically counterproductive.
Handoff condition: Decision is recorded. Claude Code implements it in Step 25.
Dependency: Step 23.
Context required: trust-template/generate.js, decision from Step 24
Implement the error behavior policy decided in [Step 24] consistently across generate.js.
If the decision was FAIL LOUD (expected):
- All errors in validate() cause process.exit(1) with a specific message
- Warnings print with ⚠ but the build continues
- Error messages must include: the field path, the invalid value, and what a valid value looks like. Example: "❌ characters[2].strategy: 'tft' is already used by characters[0]. Each strategy must appear exactly once. Valid strategies: tft, tf2t, grudge, all_d, all_c, random, pavlov, prober"
Apply this standard to every error currently in the validate() function. Check that none of the existing error messages are vague (e.g., "invalid strategy" is vague; "unknown strategy 'tft2' — did you mean tf2t?" is specific).
After changes:
- Test with a game.json that has a duplicate strategy: verify the error names both characters
- Test with a game.json that's valid: verify the build completes without printing any errors
- Report both test outputs
Expected output: Updated generate.js with specific, actionable error messages. Both test cases produce expected behavior.
Handoff condition: Error messages name the exact field, the invalid value, and the valid options. Valid game.json produces clean output with no errors.
Dependency: Step 24.
This is the one step where all four other supervisory capacities are exercised simultaneously. The human must hold the generator, the site patches, the student workflow, and the course taxonomy together and confirm they form a coherent whole before merging to main.
git checkout main
git merge feat/directory-artifacts
git push origin main
After Vercel deploys main:
/tools — all starter templates appear with correct tags. Tag filter "ethical play" returns all course templates./tools/evolution-of-trust (and each additional template from Step 22) — iframe loads, game plays correctly./sitemap.xml — the new tool slugs appear in the sitemap./tools would find the right template.Handoff condition: All templates visible on /tools with correct tags. All iframes load. Sitemap updated. Taxonomy terms in keywords match course vocabulary. STUDENT-GUIDE.md survives a first reader.
Dependency: All prior steps.
| Count | % | |
|---|---|---|
| Total steps | 26 | — |
| Claude tasks | 13 | 50% |
| Human tasks | 13 | 50% |
The longest dependency chain — any delay cascades:
Step 1 → 2 → 3 → 8 → 9 → 16 → 17 → 18 → 19 → 26
Ten steps. Steps 3, 9, 18, and 19 are all human tasks on this path. The build cannot be fully automated — four browser/play checks are on the critical path and each one gates the next.
PEEP_METADATA is consumed by any PIXI initialization that runs before user-config.js finishes parsing, characters will display original colors silently. No error is thrown. The only evidence is the wrong color on screen. This spike exists specifically to catch this failure mode before it reaches the live site.
ToolsBrowser.tsx was written without seeing its full context in the codebase. If the component is used in 3+ places with different prop shapes, the Step 11 change could cascade into multiple type errors not visible until the Vercel build runs. The Step 6 audit exists to surface this risk; Step 7 is where the human decides how to handle it.
| Capacity | Steps | Count |
|---|---|---|
| [PA] Plausibility Auditing | 3, 5, 9, 15, 17, 18 | 6 |
| [PF] Problem Formulation | 1, 20 | 2 |
| [TO] Tool Orchestration | 14, 24 | 2 |
| [IJ] Interpretive Judgment | 7, 19 | 2 |
| [EI] Executive Integration | 26 | 1 |
/tasks implementation document has not been generated. When Step 20 produces specs for additional templates, a full ticket breakdown (parallel tracks for each template build) would clarify ordering. Run /tasks after Step 20 completes.[PASTE SPEC] placeholder. Step 22 cannot be a real prompt until the instructor has made the pedagogical decisions in Step 20.game.json or a game that overwrites another student's slug. If multiple students are deploying to the same Zebonastic repo, a slug collision protection step and a pre-push validation hook belong in the Hardening phase. This score does not include them — add them when the multi-student workflow is defined.The SDD is the music. This score is who plays what, in what order, and when to listen for the wrong note.