Skip to content

fix update4#3

Closed
Arifbhrn wants to merge 37 commits into
mainfrom
fix-update4
Closed

fix update4#3
Arifbhrn wants to merge 37 commits into
mainfrom
fix-update4

Conversation

@Arifbhrn

Copy link
Copy Markdown
Owner
  • chore: retire starter/workflows + release machinery — slides are source of truth, learners fork monorepo
  • docs: reconcile contracts to taught reality — deploy.yaml snapshot end-of-S3, minimal report payload, no VITE_CALLSIGN, README un-scaffolded
  • chore: fixed dockerfile
  • feat(launchpad): scripts/report.sh — prop-owned board report, learner workflow calls it with env BOARD_URL+SHIPIT_TOKEN; e2e-tested 202/401/missing-env
  • feat: typing race mode — teach why a backend server exists (feat: typing race mode — teach why a backend server exists Infratify/devops-bootcamp-shipit#20)
  • feat(board): ship goes LIVE (green) only when learner's Pages site is reachable (Board: ship goes LIVE (green) only when the learner's real Pages site is reachable Infratify/devops-bootcamp-shipit#21)
  • fix(launchpad): restore valid ship.config.json color (#22d3ee)
  • feat(launchpad): report.sh 401 fails the step
  • docs: unified 2D race UI design — shared track, live frac progress, /operator console
  • docs: unified race UI implementation plan — 9 TDD tasks
  • feat(board): race racers carry display-only typing frac via report()
  • feat(board): ws progress carries typing frac into race broadcasts
  • feat(board): pure race row math — progressOf, laneOrder, ranks
  • feat(board): cached GLB->PNG ship sprites for the 2D race track
  • fix(board): cache GLB load promise, hide sprite labels in race track
  • feat(board): shared DOM race-track component — rows, sprites, live glide
  • fix(board): race-track banner apostrophe broke the string literal
  • feat(board): projector renders race via shared race-track; drop 3D race scene
  • feat(board): cockpit shows the full shared race field + live frac typing
  • fix(board): cancel pending frac report on prompt completion
  • feat(board): /operator console — start/reset/view buttons replace curl
  • fix(board): operator console survives locked-down localStorage
  • fix(board): final-review wave — start guard, running podium, hud hide, doc drift
  • docs: spec notes running-phase podium medals
  • fix(board): race sprites — 3/4 view, hull-fit framing, 128px canvas
  • fix(board): race sprites face the track — per-model nose axis, bigger boxes
  • fix(board): race sprites face right on all models, +30% size; cockpit auto-focus
  • feat(board): idle race VFX — starfield drift, ship bob, engine glow
  • feat(board): ENTER runs the command — hold at 0.9, boost on run
  • feat(board): cockpit pins own ship row above the typing dock
  • feat(board): synthesized cockpit SFX — Web Audio, zero asset files
  • feat(board): retheme cockpit SFX from arcade to spaceship
  • feat(board): race prompts become sequenced slide-verbatim stories
  • feat(board): terminal-style strict typing — greyed command lights up in place
  • fix(board): terminal command always fits one line
  • fix error

opariffazman and others added 30 commits July 17, 2026 17:27
…ce of truth, learners fork monorepo

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d-of-S3, minimal report payload, no VITE_CALLSIGN, README un-scaffolded

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… workflow calls it with env BOARD_URL+SHIPIT_TOKEN; e2e-tested 202/401/missing-env

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
)

* docs(spec): typing race mode — board race mode + launchpad READY button

Board gains a multiplayer typing-race mode (Three.js ortho 2D view,
server-authoritative race state, /play cockpit, operator control).
Launchpad stays static, gains a READY button + hostname-derived callsign.
Reuses the S3 report/roster contract; race entry gated on the roster.
Teaches "why a backend server" via the static-vs-server contrast; staged
as cicd3 experience + cicd4 dissect/rebuild. Slides reconciliation tracked
in Infratify/slides-devops-bootcamp#161.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(plan): typing race mode implementation plan (7 tasks, TDD)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(board): authoritative race state machine

* fix(board): keep race total an immutable cap across rounds

* feat(board): session-gated command corpus

* feat(board): cockpit ws + roster-gated join + operator race control

* feat(launchpad): derive callsign from Pages hostname

* feat(launchpad): READY button linking to the board cockpit

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(board): typing cockpit page (/play)

* fix(board): lowercase callsign at ingest + robust cockpit resync

* feat(board): ortho race view + operator view switch + server HUD

* fix(board): share ship disposal cascade; race view frees GPU resources

* fix(board): race-view fallback, session validation, corpus + comment; test readyHref

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(spec): wire VITE_BOARD_URL at build; note lowercase callsign display

From whole-branch review: the READY button needs VITE_BOARD_URL on the
npm run build step (build-time var, not the S3 report runtime BOARD_URL),
else the race is unreachable — tracked for the slides in #161. Board now
canonicalizes callsigns lowercase at ingest; document the display change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… reachable (Infratify#21)

report.sh derives the Pages URL (GITHUB_REPOSITORY_OWNER + repo name) and sends
it as siteUrl — inside the script, so the taught two-line env: surface (BOARD_URL
+ SHIPIT_TOKEN) is unchanged. The board probes each siteUrl (HEAD, on arrival +
30s sweep) and broadcasts a per-ship `live` flag; the orbit spectator shows a
green LIVE halo (fallback: a LIVE badge) only when the real site answers 200.
Ties the S3 token + report to the actual deploy artifact.

- board/src/liveness.js: bounded-concurrency reachability sweep; non-200/timeout
  = not-live-yet, never an error; periodic re-check handles fresh-deploy 404 lag
- CLAUDE.md: formalize siteUrl shape + live semantics in the event contract
- board/test/liveness.test.js: 6 cases (200 flips live, throw/404 stay neutral,
  404->200 re-sweep, no-siteUrl skipped, HEAD+timeout signal)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reverts f63f012 "broke color on purpose" — the S2 red-gate teaching artifact is
no longer needed now the cohort has finished. Bare 22d3ee failed the preflight
gate (exit 1) and rendered slate on the board; #22d3ee passes and renders cyan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
curl -sS --fail-with-body: wrong token now exits non-zero (red run)
while still printing {"error":"unauthorized"} in the log. Replaces
the pinned no -f stay-green behavior — cohort finished, red X + reason
is the clearer wrong-token demo. Plain -f would swallow the body.
CLAUDE.md pin updated; slides repo needs hand-update before next cohort.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…operator console

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One-time WebGL renders of each (shipModel, color) pair to small PNG sprites,
cached as data-URLs. OrthographicCamera bounds (±1.6) chosen to frame ships
with accessories (label, trail, halo) that extend to ~1.2-1.8 world units, at
reasonable fill for fallback rendering when live WebGL unavailable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Cache preloadShipTemplates() promise at module scope so all sprite renders share one load, not re-fetching/re-parsing all 4 GLB models on every render() call
- Hide THREE.Sprite label children (the "@callsign" label added by createShip) after creating each ship and before rendering, so cached sprite images carry only the ship model, not the stray "@" glyph

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ce scene

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A pending throttle timer can fire after the user completes a prompt, sending a stale fraction measured against the old prompt with the new completed index, causing phantom progress on the next prompt. Cancel the pending timer and zero its cached fraction whenever a completion is sent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wrap localStorage access in try-catch to degrade gracefully when storage is locked (private mode, enterprise policy) instead of throwing and killing module initialization before event handlers and WebSocket connect wire up, leaving the console silently inert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, doc drift

- operator.js: disable START while a race is running (WS race-message
  handler); RESET stays always enabled as the escape hatch
- race-track.js: show podium medals during 'running' phase too (a ghost
  racer who never finishes would otherwise block them forever)
- race.js:12: comment now lists `frac` on the racer shape
- vite.config.js: header comment now says three pages, including operator.html
- main.js: hide the orbit HUD legend (#hud) while in race mode — it
  occludes the top rows at 40-ship density
- docs spec: race-track is dark-only with local custom properties (not
  the light/dark scheme); dense-label-hide threshold documented as 25+
  racers, matching the shipped DENSE_AT constant

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pure side-on rendered the low-poly hulls as a ~13px sliver. Camera now
frames the hull's real bounding box (label/trail/ring stripped first —
Box3 counts invisible children), ship pitched+yawed to a 3/4 view, and
the canvas doubled for hiDPI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… boxes

The Quaternius GLBs disagree on nose axis (scout/hauler +z — engine
nozzles and cockpit confirm — fighter/interceptor -z), so the yaw flips
per model. Camera world-matrix updated before view-space framing (was
identity on the very first render, which produced a blank sprite), the
ship stays level under an elevated camera instead of the fake nose-down
pitch, and on-screen boxes grow 26/16px to 38/24px.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… auto-focus

- All four GLBs nose down +z — drop the per-model NOSE_POS_Z split that
  had fighter/interceptor mirrored to face left on the track.
- Ship box 38px -> 50px (dense 24px -> 31px).
- Focus the typing input when the race enables it (autofocus dies while
  the input is disabled pre-race, leaving keystrokes going nowhere) and
  refocus it on any click.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CSS-only (no rAF, honours prefers-reduced-motion):
- Parallax starfield drifting left on the track background — seamless
  loop, each layer shifts a whole multiple of its tile size.
- Ships bob/tilt inside their position box (never fights the `left`
  transition), phase + duration hashed from callsign so 40 ships drift
  out of sync.
- Blurred engine-glow streak off each tail, tinted with the racer's
  colour, flickering like a thruster.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A fully typed command no longer auto-completes: the ship holds just short
of the prompt boundary (frac 0.9) with an "ENTER to run ⏎" cue, and ENTER
sends the completion — jumping the ship forward with a one-shot
lunge+flare boost (track.boost()). ENTER on a wrong or incomplete line
shakes the input and sends nothing. Terminal muscle memory: typing a
command and running it are different beats.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The me row moves to the bottom of the stack (last flex order +
margin-top auto) so it sits directly above the prompt/input — the ship
moves where the racer's eyes already are. A thin rule splits it from the
pack; rank chip still shows the real rank. Projector order (no me)
unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
opariffazman and others added 7 commits July 20, 2026 23:45
Every sound is oscillators/filtered noise built at call time (sfx.js):
keystroke tick (pitch-jittered), wrong-char thud, command-ready chirp,
ENTER-boost noise-sweep whoosh, error buzz, race-start beeps, finish
fanfare. AudioContext unlocks on first click/keydown (autoplay policy);
mute toggle in the dock persists to localStorage (guarded for private
mode). Muted skips synthesis entirely.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Same sound API, new palette: sines/triangles with soft attack envelopes
instead of square-wave bleeps. Keystroke = dampened console tap (lowpass
noise puff + faint triangle), ready = single long sonar ping, boost =
deep thruster (low noise sweep + rising rumble), error = descending
double denied thunk, go = two low countdown marks + ignition rumble,
finish = warm docking-complete chord swell instead of a fanfare
arpeggio. blip() gains an attack ramp; whoosh() gains at/filter-type.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the random command grab-bag with ordered STORIES per session,
inventoried verbatim from the 2026 slide decks (linux/git/github/docker/
aws/ci-cd): cicd3 = "fork to first contact" (16 prompts: gh auth login →
fork shipit → gate → build → push → secret → workflow run → Pages URL);
cicd4 = "capstone: container to your own server" (20: sync upstream →
test → docker build/run/tag → ssh → compose up → PR merge). Each line's
precondition is set up by the line before — run top to bottom it is one
coherent workflow, so prompts are never shuffled: the order is the
lesson.

Race total now follows the prompt list length (16/20, no longer capped
at 12); empty list keeps the prior total so progress math never divides
by zero. pickPrompts(session) returns the story copy in order. Fixed
server.test.js so an assertion failure can no longer skip the WS close
and hang the suite on server.close().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…in place

The cockpit dock becomes a terminal window (title bar, $ prompt, block
caret): the command sits greyed on the line and lights up character by
character as it's typed — no visible input field. A hidden 1px input
catches keystrokes (and summons mobile keyboards); its value is snapped
to the correct prefix after every event, so a wrong key never lands: the
caret flashes red with a thud, the cursor stays put, and backspace has
nothing to do (and is disabled). typing.js's typedState is replaced by
the pure advance(target, at, incoming) cursor walk, node-tested.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
white-space: pre (no wrap), dock widened 640 -> 760px, and the line
font clamps down on narrow windows so the longest story command (the
53-char fork) never breaks across lines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Arifbhrn Arifbhrn closed this Jul 21, 2026
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.

2 participants