Commit Graph

6 Commits

Author SHA1 Message Date
type-two
4e4311b568 [lane E+F] The game remembers you: a save file, a level select and an ending
Audit items 9, 10 and 11 — three features whose backends were finished and whose front ends did
not exist.

DIFFICULTY WAS UNREACHABLE. levels/difficulty.js has carried three fully specified tiers since
round 2 — Endoscopy, Clinical, Terminal, with per-tier assists and a note explaining each — and
every single call site in the codebase took the default. `easy` and `hard` were a table nobody
could select. getLevel now takes the saved difficulty (?diff= still wins, so a test URL stays
absolute), and the title has the switch. Verified live: the world boots at 11 spawns on Terminal
against 8 on Clinical.

THE CAMPAIGN WAS SIX LEVELS WITH ONE WAY IN. Reaching anything but L1 meant hand-editing ?lvl=
in the address bar. The title now lists the campaign, unlocking each segment as the one before
it is filed, showing the medal you hold on each. `LS_` is C's secret prefix, so the appendix
stays a row of question marks until you have earned your way in — naming it in the menu would
have given away the one thing in this game you have to discover.

THE CAMPAIGN HAD NO ENDING. C's anal_verge gate carries `to: null` — the only gate in the game
that does, its own note calling it "the end of the campaign" — and boot's ui:continue handler
opened with `if (!e.to) return`. Finishing GUTS parked you on a medal card forever with no way
out but the address bar, and the card said "any key", the same words it uses when it has nothing
to tell you. Now the clear is filed and counted, the card says you are out, and the title carries
CANAL CLEARED.

New core/save.js is the whole persistence layer: one localStorage key, one flat object, best
time / best score / best medal kept per column (they need not come from the same run) plus an
attempt count. Every entry point is wrapped — Safari private mode throws on setItem, and a save
file must never be able to stop the game booting. Its selfcheck (`node web/js/core/save.js
--selfcheck`, now in qa.sh) covers the best-of comparisons and feeds it corrupt, future-versioned
and malformed saves.

cards.js records rather than boot: this file computes the grade, so routing it through the bus
for boot to re-derive would be two copies of the medal table waiting to disagree.

One bug found by clicking rather than reading: the first cut of the chips had no
pointer-events:auto. #ui is pointer-events:none and it inherits — the file's own header says so
— so the buttons rendered, highlighted nothing, and passed the click through to the canvas,
which on the title starts the run. It looked like a menu and behaved like wallpaper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-26 22:02:58 +10:00
type-two
0e2b5c10fe [infra] Stamp the deploy: curl /gutsy/VERSION to see what is actually live
I shipped a working tree earlier and had to tell John "live matches no commit in
the repo" — which is exactly the sentence a deploy should make impossible.

deploy.sh now writes the HEAD short-sha to web root as VERSION, and verifies it
came back. `curl https://partly.party/gutsy/VERSION` answers "what is online right
now" without trusting anyone's memory of the last deploy.

The dirty check is scoped to `git status --porcelain -- web/`, not the whole
tree, because only web/ ships: editing docs or this script does not make the
payload unreproducible, and a stamp that cried wolf on every NOTES edit would get
ignored. A dirty payload ships as `<sha>-dirty` and says so, loudly, rather than
refusing — mid-round lanes need to push a look at something without committing
first, and a deploy tool that blocks that will just get bypassed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:04:05 +10:00
type-two
77ddf88c31 [infra] GUTS is live at partly.party/gutsy — deploy wired, ship-check clean
README said "target: partly.party, not wired yet". It's wired.

tools/deploy.sh follows the GAMES doctrine (deploy-map skill): QA gate -> rsync
web/ to VPS staging -> docker cp into forum-nginx -> verify. No build step, so
web/ ships as-is: vanilla ES modules + importmap with three r175 vendored, all
paths relative or resolved from import.meta.url, which is why it runs from a
subdirectory with no base rewrite. 6.6 MB. nginx.conf needed no edit — its
catch-all `root /usr/share/nginx/html` already routes any new directory, which is
how blobbo works. /gutsy (no slash) 301s to /gutsy/.

Excludes web/dev/ (ruling #5: never shipped). Verified live, not assumed: the
lane harnesses 404 through to the arcade index.

THE 200 THAT ISN'T. That same catch-all try_files means ANY missing file returns
the arcade's index.html with HTTP 200. A deploy that lost every module would
still curl 200 on all of them. So every check asserts on CONTENT, never on the
status code — this is the failure deploy-map records as ".bin data URLs serving
arcade HTML". The guard caught itself, too: it originally grepped for
`<title>MonsterRobot`, but the arcade's real title is
`~*~W3LC0M3 2 TH3 M0NST3R R0B0T P4RTY 4RC4D3~*~`, so it could never have fired.
Matched against the live box now.

DURABILITY, and it's John's call. This docker-cp's into the container's own
layer, matching blobbo/glytch: zero downtime, nothing else touched, survives
restarts and reboots (restart: unless-stopped) — but NOT `docker compose up
--force-recreate` or an nginx image bump, which wipe it. Re-running the script is
the fix. The durable alternative is a bind mount in forum/docker-compose.yml like
cratewars/roguelike have, which costs a forum-nginx recreate and brief downtime
across ALL of partly.party, so this script does not take that decision.

ship-check (README says run it before deploying — I ran it after; my miss, and it
came back clean):
  1 auth        N/A — static files, no endpoint/API/admin surface
  2 secrets     PASS — nothing secret-shaped in the payload or the diff
  3 input/SSRF  PASS — the only user string reaching a fetch is ?lvl=, and C
                gates it on the CAMPAIGN allowlist BEFORE the load
                (levels/index.js:151). Traversal tested live with
                `curl --path-as-is` (plain curl normalises ../ away and proves
                nothing): /etc/passwd never leaked. DEPOT_BASE in assets.js is
                unused — the manifest has zero external URLs.
  4 money       N/A
  5 deploy      PASS — verified by content + booted in a real browser:
                assets.misses() == [], 15 draws, 69k tris, zero console errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:02:04 +10:00
jing
3a6dbc30a3 [lane A] Complete the biome texture set (oral + colon) + a provenance gate
Generated on MODELBEAST flux_local, on-device, $0.00. Lane D's pipeline used
unchanged; **D owns these — ratify, retune or bin them.**

Why A did D's job: the six-biome tint contact sheet could only judge 3 of 6
biomes for real (oral/large_intestine/appendix had no pack and fell back to
procedural), and you cannot ratify a tint against a stand-in. All six are now
textured — the set ART_BIBLE §Biome palettes promises.

- wall_oral_a/b, wall_colon_a/b + normals. Seams 6.35/9.30/14.06/6.37 -> 1.01/
  1.08/0.74/1.36 (D's "indistinguishable" band; the shipped pack's weakest is
  2.39). Means normalised to ~0.50 by D's derive_maps, untouched.
- appendix wears the colon pack at its own gold tint (TEXTURE_SHARE in
  world/index.js) — anatomically it IS colon tissue, and it's ART_BIBLE's
  "one texture, two biomes" law for zero bytes. Distinct from the temporary
  slug map; keep it when that dies.
- oral_a took three subjects. v1 named an ORGAN ("tongue") and FLUX drew the
  organ's silhouette — D's "one urchin of villi" in a field's clothing. v2 named
  the tissue but papillae are 3D projections, so perspective gave it a vanishing
  point that tiles into starbursts. v3 asks for squamous cell pavement: flat by
  construction. Rule for the kit: prompt the SURFACE, not the FEATURE.
  Evidence: docs/shots/laneA/round2_oral_prompt_evolution.png

PROVENANCE DEFECT FOUND AND FIXED (-> Lane D):
batch_textures.json recorded, for 4 of 6 walls, the prompt from the framing
experiment D tried and rejected — not the prompt that made the shipped pack.
record() only runs on generation, so reverting a prompt while keeping its image
(exactly what D correctly did: "four winners kept untouched rather than churned")
drifts the record silently. Proved by regenerating esophagus_a at seed 1101 under
both prompts: the code's prompt reproduces the shipped wall, the recorded one
gives the bland wood-grain D described rejecting. Evidence:
docs/shots/laneA/round2_provenance_probe.png. Records re-pointed at the code's
prompt (images untouched — they were never wrong).
New: gen_textures.py --verify-provenance + qa.sh gate 5b, so it cannot rot again.

qa GREEN incl. the new gate; 11/11 provenance verified; all six biomes eyeballed
in engine (docs/shots/laneA/round2_tint_*.png).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 17:44:58 +10:00
jing
4ccf5edcc0 [lane F] Round 1 integration + ROUND2 instructions: the game is a game
Wired B's player/combat + event pump, D's assets, C's level pick into boot.
Fixed qa ESM gate (node --check no-op, found by B) + added spline selfcheck.
TECH: world contract FROZEN v1.1, bus events ratified, colorspace + crest-speed
laws (CREST_FACTOR 1.6 — B proved surfing lost to throttle at 1.0). Stub complies.
Verified integrated build via 60s stepped sim: 9 draws, 0 errors, 0 asset misses;
one known gap (fiction-id spawn resolve) confirmed and assigned as B's top item.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 14:39:02 +10:00
jing
34f84ab162 [lane F] Round 0 scaffold: docs, contracts, lane charters, bootable stub world
GDD v1 (flow-locked hybrid movement, 5 biomes + secret, boss roster),
TECH contracts (world API, level schema v0, bus events, manifest law),
ART_BIBLE (synthetic scanner look), PIPELINE (MODELBEAST-first, fal gated),
PROCESS (PROCITY lane/round law), charters A-F + ROUND1 instructions.
Seed code: shell + boot + core (rng/bus/flags) + stub world (peristalsis
shader tube, 1 draw / 102k tris, contract-complete) + qa.sh (GREEN).
Verified in-browser; evidence docs/shots/laneF/round0_stub_tube.png.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 01:28:35 +10:00