[orchestrator] MEGA round 5: the paint and the pipe
Supersedes unexecuted round-5 orders. Folds in the live first-eyes review findings (silence, void floor, onboarding cliff, quiet payoffs) + John's hidden-radio idea. Contracts v6: AudioFX (THE SPEAKER - all Web Audio synthesis, no asset files), RelicState + excavate + relicFound (the optical-fossil hidden pipe: find it and the game grows a tuner - FKTRY FM, Correction propaganda subtitled by THE SCREEN's chyron, a shortwave numbers station reading hidden-seam coordinates, dead air). main.ts wires audio + first-gesture unlock; src/audio stub awaits LANE-SCREEN. Lane orders: SIM = wildlife + seams-become-real + the relic + research time; RENDER = the floor (seam glints, strata whispers), relic shimmer (no signposting), juice, break-room cabinet -> match.html; UI = mercy toast, tuner dock, SCREEN click-to-enlarge, camera hints; SCREEN = era feed + THE SPEAKER (3 audio layers, 4 stations, spectral verification); DATA = the commission-ladder tutorial, stations.json broadcast schedule, seams.json final. Ship gate: after review, redeploy partly.party/glytch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
e3d1a724e9
commit
8dd4616580
@ -68,3 +68,16 @@ batches them between rounds. Until granted, work around locally inside your lane
|
|||||||
whose heatPerTick ≤ its coolPerTick can never overheat — the validator enforces it.
|
whose heatPerTick ≤ its coolPerTick can never overheat — the validator enforces it.
|
||||||
- Research gating: ids appearing in any `TechDef.unlocks` are locked until researched;
|
- Research gating: ids appearing in any `TechDef.unlocks` are locked until researched;
|
||||||
ids referenced by no tech are always available.
|
ids referenced by no tech are always available.
|
||||||
|
|
||||||
|
## v6 notes
|
||||||
|
|
||||||
|
- **THE SPEAKER**: `AudioFX` (src/audio/**, LANE-SCREEN) — all sound is Web Audio
|
||||||
|
synthesis, no asset files. main.ts wires init/unlock/onEvents/frame. Pre-discovery
|
||||||
|
only the diegetic minimum plays; the band unlocks on `relicFound`.
|
||||||
|
- **Sanctioned narrow imports** (read-only, documented at the export site):
|
||||||
|
`src/sim/constants.ts` (tuning truth) and `src/audio`'s `radio` control (UI's
|
||||||
|
tuner dock). Everything else stays contract-mediated.
|
||||||
|
- **Relics are secrets.** `snapshot.relics` is always present, but nothing may
|
||||||
|
signpost an unfound relic: RENDER draws the subtle shimmer, UI shows nothing until
|
||||||
|
`found`. Discoverability budget: wandering + curiosity. That's the design.
|
||||||
|
- New jam reason string: `'no seam'` (extractor off-seam).
|
||||||
|
|||||||
@ -102,3 +102,11 @@ diff each lane against its owned paths (ownership violations get reverted), veri
|
|||||||
claimed features actually work, reconcile cross-lane questions, update CONTRACTS if
|
claimed features actually work, reconcile cross-lane questions, update CONTRACTS if
|
||||||
(and only if) two lanes need it, write next CURRENT ORDERS in each lane doc, commit
|
(and only if) two lanes need it, write next CURRENT ORDERS in each lane doc, commit
|
||||||
`[orchestrator] round N orders`.
|
`[orchestrator] round N orders`.
|
||||||
|
|
||||||
|
## ROUND 5 (MEGA) addendum
|
||||||
|
|
||||||
|
The original round-5 orders were superseded before execution by the MEGA round
|
||||||
|
(same goals + the paint-and-pipe layer from the live first-eyes review: sound via
|
||||||
|
the hidden optical-fossil radio, the commission-ladder tutorial, the floor, juice,
|
||||||
|
click-to-enlarge SCREEN, the break-room cabinet). After this round's review passes:
|
||||||
|
**redeploy to partly.party/glytch via ../deploy.sh** — that's the ship gate.
|
||||||
|
|||||||
@ -25,41 +25,52 @@ REQUESTs.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## CURRENT ORDERS — Round 5 (goal: the world gets teeth and ground)
|
## CURRENT ORDERS — ROUND 5 (MEGA) — supersedes the earlier round-5 text
|
||||||
|
|
||||||
Round 4 review: the gating audit — measuring 0-of-24 reachability, fixing it as two
|
Review verdict you're executing: the onboarding cliff. The fax IS the tutorial —
|
||||||
tested rules, deleting six fake nodes instead of repurposing them — is the round's
|
you write the ladder. Plus the radio's entire broadcast schedule and the ground
|
||||||
headline and the reason the tree tells a story now. The cooler retune that survives
|
truth for the floor.
|
||||||
both readings of an ambiguous contract sentence was defensive tuning of the highest
|
|
||||||
order; the sentence is now clarified (ADDITIVE, capped at HEAT_COOL_MAX). Verdicts:
|
|
||||||
constants.ts landed in SIM's final commit (your grep raced it — it exports 12,
|
|
||||||
retire your hand-copies now). Your ungating of the mosh reactor + starter-plant
|
|
||||||
arithmetic: RATIFIED, SIM's reference factory now pre-grants its techs in the demo.
|
|
||||||
|
|
||||||
1. **Retire the hand-copied constants** — import from `src/sim/constants.ts`
|
### PART A — carried from round 5
|
||||||
(read-only cross-lane import is sanctioned for constants).
|
1. **Constants**: import from `src/sim/constants.ts`, retire hand-copies.
|
||||||
2. **Wildlife data** (SIM builds the mechanic this round — coordinate via NOTES):
|
2. **Wildlife data**: MOSQUITO TRAP machine (§5: bug-zapper shaped like a
|
||||||
the MOSQUITO TRAP machine (§5 codex: bug-zapper shaped like a high-contrast edge
|
high-contrast edge target) + catch recipe (canned `mosquito-swarm`), pile/hatch
|
||||||
target), its catch recipe producing the canned `mosquito-swarm` item, pile/hatch
|
tuning if SIM makes it data-driven, `vaporwave-sunset` unblocked, FORWARD_CANON
|
||||||
tuning numbers if SIM makes them data-driven, and the commissions that suddenly
|
pruned, fax celebrates in voice.
|
||||||
work: `vaporwave-sunset` finally unblocked — prune FORWARD_CANON accordingly and
|
3. **Cooler numbers final** under the additive ruling; duty table in CANON-DELTA.
|
||||||
let the fax celebrate in voice.
|
|
||||||
3. **Cooler numbers final** under the clarified additive rule — your 0.0018 was
|
|
||||||
tuned to survive ambiguity; now tune it to be *right*, show the duty-cycle table
|
|
||||||
in CANON-DELTA.
|
|
||||||
4. **The seam map — start the ground game** (the content gap you own): author
|
|
||||||
`data/seams.json` — seam regions per stratum era (shape your call: rects or
|
|
||||||
points + richness), the codex §1 geology as actual coordinates. SIM consumes it
|
|
||||||
round 6 (extractors will require seam tiles); this round it's data + validator
|
|
||||||
coverage + a CANON-DELTA spec of intended mechanics, so SIM has something real to
|
|
||||||
build against instead of a guess.
|
|
||||||
5. **Fixture/validator upkeep**: v5 fields (wildlife), grantResearch in any test
|
|
||||||
flows you own, FORWARD_CANON pruned.
|
|
||||||
|
|
||||||
**Definition of done:** trap + swarm economy closes (catchable → cannable →
|
### PART B — the ladder, the ground, the broadcast schedule (new)
|
||||||
commissionable) against SIM's real mechanic; seams.json exists with validator
|
4. **THE COMMISSION LADDER — the game's real tutorial.** Rewrite the opening queue
|
||||||
coverage and a written consumption spec; constants imported from truth; CANON-DELTA
|
as an escalating teaching ladder, one mechanic per rung, all in voice:
|
||||||
carries the cooler table.
|
- Rung 1: ~20 MDAT-ORE, raw ("Do not wash it. Do not ask why.") — teaches
|
||||||
|
extractor→belt→uplink. MUST be completable inside 3 minutes with 4 machine
|
||||||
|
types; prove it with a sim probe test like your tick-0 melt guard.
|
||||||
|
- Rung 2: LUMA BARS (teaches demuxer + byproduct pain — the slurry has to go
|
||||||
|
somewhere and the fax does not care).
|
||||||
|
- Rung 3: HF DUST (teaches the quantizer + that waste is product — DUST
|
||||||
|
ALLOWANCE fits here).
|
||||||
|
- Rung 4: one MELT, fresh (first-taste, reward bumped — it's a graduation now).
|
||||||
|
- Thereafter: your existing escalation. Ladder intent documented in CANON-DELTA.
|
||||||
|
5. **`data/seams.json` FINAL** (SIM consumes this round): seam regions per stratum
|
||||||
|
era with richness; the reference factory's ground coordinated with SIM; include
|
||||||
|
2-3 `hidden: true` bonus seams — the numbers station reads their coordinates.
|
||||||
|
6. **`data/stations.json`**: the broadcast schedule — station ids, band, frequency,
|
||||||
|
name, format tag, flavor line, and the copy pools: THE STANDARD's propaganda
|
||||||
|
chyron lines (polite, clean, horrifying — this is The Correction with a
|
||||||
|
transmitter; 20+ lines so it doesn't loop fast), NUMBERS digit-group config
|
||||||
|
(incl. the hidden-seam pointers), DEAD AIR's one ghost line. Schema agreed with
|
||||||
|
SCREEN in NOTES.
|
||||||
|
7. **Relic canon**: CANON-DELTA the optical-fossil mechanics reading (§1 fossils
|
||||||
|
"sing when excavated" → the severed audio bus) + one mid-ladder fax margin that
|
||||||
|
*hints* without pointing ("someone has drawn a sine wave in the corner of this
|
||||||
|
fax. it is not our department.").
|
||||||
|
8. **Validator**: seams/stations schemas, ladder invariants (rung-1 buildability at
|
||||||
|
tick 0), relic never on a seam (cross-check vs SIM's placement rule).
|
||||||
|
|
||||||
|
**Definition of done:** cold-start rung 1 provably completable fast; every station
|
||||||
|
has enough copy to broadcast for 10 minutes without repeating; seams validated
|
||||||
|
against both SIM's consumption and RENDER's rendering; CANON-DELTA tells the whole
|
||||||
|
story of the round.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -25,35 +25,45 @@ you never simulate. If motion looks wrong, interpolate better or note it — don
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## CURRENT ORDERS — Round 5 (goal: a living, inspectable world)
|
## CURRENT ORDERS — ROUND 5 (MEGA) — supersedes the earlier round-5 text
|
||||||
|
|
||||||
Round 4 review: ERA_TELL (signal vs surface) and the chebyshev-rectangle honesty are
|
The review verdict driving this round: *the game about place has no place.* You own
|
||||||
both canon reasoning now; the showroom axis-overflow lesson is quoted in my head
|
fixing that. Everything from the previous round-5 orders is carried, plus the floor,
|
||||||
weekly. Verdicts: CONTRACT REQUEST 1 GRANTED — `SelectionState` grew
|
the juice, and one secret you must draw without signposting.
|
||||||
`{mode:'inspect'; entity}` in v5; UI publishes it when the inspector opens. The
|
|
||||||
sentinel bridge is DEAD as promised: main.ts now sends `setGhost(null, tile, 0,
|
|
||||||
'remove')` — you already ignore the def, so nothing changes for you, but confirm.
|
|
||||||
Your divergence-then-convergence with UI on the lock rule was handled exactly right.
|
|
||||||
|
|
||||||
1. **Inspect mode**: on `{mode:'inspect'}`, highlight the inspected entity (outline
|
### PART A — carried from round 5
|
||||||
or ground ring — your language) and, when it has `coolRadius`, draw the aura
|
1. **Inspect mode**: highlight the inspected entity via `{mode:'inspect'}`; cooler
|
||||||
rectangle — order 3's "placed-and-selected" case, now reachable.
|
aura rectangle on inspect (the placed-and-selected case).
|
||||||
2. **Wildlife visuals** (SIM lands `snapshot.wildlife` this round): DUST PILES as
|
2. **Wildlife visuals**: piles = §2 glitter heaps growing with `size`; swarms =
|
||||||
§2's glitter heaps — instanced, growing with `size`, subtle shimmer; MOSQUITO
|
pixel-gnat clouds clustering on `target` (harassed machines flicker); trap zap
|
||||||
SWARMS as pixel-gnat particle clouds that visibly cluster on their `target`
|
read from wildlife-state deltas.
|
||||||
machine (which should read as *harassed* — flicker its accent); trap machines get
|
3. **Fixture hygiene**: commissionQueue/research/wildlife/relics in fabricated snapshots.
|
||||||
a zap flash on the `wildlife cleared` event... which you don't receive — read
|
|
||||||
state deltas instead, or tell me if you want Renderer to get events (that's a
|
|
||||||
contract conversation I'm open to in v6, say so in NOTES if hover-state isn't
|
|
||||||
enough).
|
|
||||||
3. **Fixture hygiene**: `commissionQueue` + `research` into your fabricated
|
|
||||||
snapshots (devscene, showroom) — v6 hardens both.
|
|
||||||
4. **MODELBEAST intake stays armed**: no assets have landed yet; `?showroom` is the
|
|
||||||
live manifest. First drops get a NOTES line each on how normalization treated them.
|
|
||||||
|
|
||||||
**Definition of done:** an infested factory is legible from across the map (piles
|
### PART B — the floor, the juice, the secret (new)
|
||||||
grow, swarms harass, traps zap); inspect-highlight + aura verified with UI's flow;
|
4. **THE FLOOR.** Kill the void: seam regions from `data/seams.json` render as
|
||||||
perf rule still holds with 50 piles + 10 swarms in the stress scene.
|
subtle glinting mineral patches (the player should *discover* that extractors
|
||||||
|
want them — the glint is the tell); large-scale ground-tone variation (fbm
|
||||||
|
patches, barely-there) so the plane reads as terrain; era hinting toward the
|
||||||
|
world edges per §1 strata (sepia/phosphor whispers at the rim). Restraint rule:
|
||||||
|
the floor must never compete with belts/machines — it's a stage, not a set.
|
||||||
|
5. **THE RELIC SHIMMER.** `snapshot.relics` unfound → a faint animated static-patch
|
||||||
|
decal at its pos: visible to a player actually looking, invisible to one who
|
||||||
|
isn't. NO signpost, NO minimap ping, NO tutorial arrow — this is a Mario hidden
|
||||||
|
pipe; its discoverability budget is 'wandering + curiosity'. Found → the patch
|
||||||
|
becomes a small excavated monument (fossil on a plinth, §1: it *sings*).
|
||||||
|
6. **JUICE**: placement thunk (scale-pop + dust puff), demolition burst, shipment
|
||||||
|
flash at the uplink (read shippedTotal deltas from the snapshot). Cheap,
|
||||||
|
instanced, everywhere.
|
||||||
|
7. **THE BREAK ROOM.** A decorative arcade cabinet prop near the start zone, marquee
|
||||||
|
glowing 'GLYTCH', render-owned raycast: click → `window.open('./match.html')`.
|
||||||
|
The two games finally meet. Coordinate the cursor affordance with UI.
|
||||||
|
8. **CAMERA + CLICKS (review findings)**: default framing centers the start zone
|
||||||
|
clear of the build bar (my first machines spawned half-behind it and were
|
||||||
|
unclickable); investigate entity picking near UI chrome and report what you find.
|
||||||
|
|
||||||
|
**Definition of done:** before/after screenshots of the floor; relic shimmer shown
|
||||||
|
at two zoom levels (proving subtle-but-findable); cabinet opens match.html; thunk
|
||||||
|
felt; perf rule holds with floor + 50 piles + 10 swarms.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -27,34 +27,59 @@ seed stock — port, don't move).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## CURRENT ORDERS — Round 5 (goal: the sky learns eras and insects)
|
## CURRENT ORDERS — ROUND 5 (MEGA) — supersedes the earlier round-5 text
|
||||||
|
|
||||||
Round 4 review: the two-clock decision (card in seconds because it's a broadcast;
|
You are now two organs: THE SCREEN (sky) and **THE SPEAKER** (`src/audio/**` is
|
||||||
scram wipe in frames because it's tape) is the most codex-literate engineering choice
|
yours — replace the orchestrator stub; contracts v6 `AudioFX` is wired in main.ts
|
||||||
so far, and the capacity-trap catch protected the sterile guarantee twice over.
|
with a first-gesture `unlock()`). House law: **every sound is synthesized with Web
|
||||||
Verdicts: your jammed-rot PROPOSAL is APPROVED (rot ≠ rest); your era-feed NEXT idea
|
Audio. No asset files, ever.** A game about broken media makes its own noise.
|
||||||
is this round's centerpiece — you called it, you build it.
|
|
||||||
|
|
||||||
1. **The base feed ages with the player** (your idea, ordered): drive the clean
|
### PART A — carried from round 5 (THE SCREEN)
|
||||||
programming's palette/texture from the highest era with a ratified tech
|
1. **Era base feed**: the clean programming ages with the highest ratified era
|
||||||
(`research.unlocked` × tech eras from GameData): reel = sepia + gate weave +
|
(sepia/gate-weave reel → phosphor/interlace broadcast → rainbow-on-black disc →
|
||||||
sprocket judder, broadcast = phosphor + interlace flicker, disc = rainbow-on-black
|
current SMPTE stream → blinding fortress). Corruption stays era-agnostic; the
|
||||||
sheen, stream = the current SMPTE feed, fortress = blinding white (§8 skins).
|
SUBSTRATE ages. Sterile guarantee holds per era (test one).
|
||||||
Corruption artifacts stay era-agnostic — it's the SUBSTRATE that ages. Sterile
|
2. **Jammed-rot**: jammed entities accelerate boredom decay; clean idle stays gentle.
|
||||||
guarantee holds per era (test at least one).
|
3. **Wildlife shimmer**: swarms drive regional mosquito-noise via the growth-mask
|
||||||
2. **Jammed-rot**: `jammed` entities accelerate boredom decay (the work is rotting);
|
template, seeded from the swarm pos.
|
||||||
a clean idle keeps the gentle horizon. One-line read, as you said — plus a test
|
4. **Title card**: WIMVEE FKTRY burn-in ~2s on boot (the game never says its own
|
||||||
distinguishing the two.
|
name — fix that), then NOTHING IS WRONG. First-ever shipment's awakening upgrades
|
||||||
3. **Wildlife on the sky** (SIM lands `snapshot.wildlife` + events): mosquito swarms
|
from 1 frame to a ~0.5s full-canvas moment.
|
||||||
drive a *regional* mosquito-noise shimmer via your growth-mask template (seeded
|
|
||||||
from the swarm's pos — the sky itches where the factory itches). Piles need
|
|
||||||
nothing unless you disagree.
|
|
||||||
4. **Fixture hygiene**: done last round for commissionQueue/research — add
|
|
||||||
`wildlife` where fixtures fabricate snapshots.
|
|
||||||
|
|
||||||
**Definition of done:** era progression visible on the feed (contact sheet per era),
|
### PART B — THE SPEAKER (new, the big build)
|
||||||
rot vs rest distinguishable under test, swarm shimmer regional and pinned by pixels,
|
5. **Layer 1 — diegetic minimum (always on, pre-discovery)**: placement thunk (low
|
||||||
budget still <2ms.
|
sine + noise burst), fax dot-matrix chatter, brownout pop-crackle + power-down
|
||||||
|
whine (the codex's catastrophic underrun sound — finally), scram klaxon,
|
||||||
|
ratification sting (a clean consonant triad — The Correction resolves; you don't).
|
||||||
|
NOTHING else before discovery: the silence is the tease.
|
||||||
|
6. **Layer 2 — THE BAND (unlocks on relicFound)**: a tuner. Frequency sweep with
|
||||||
|
band-appropriate inter-station noise (AM = brown crackle, FM = white hiss, SW =
|
||||||
|
warble + heterodyne whistles near carriers); station lock via gaussian around
|
||||||
|
each station's freq. Stations from `data/stations.json` (DATA authors; schema
|
||||||
|
yours to agree in NOTES):
|
||||||
|
- **88.1 FKTRY FM** — generative music: seeded 16-step sequencer, square+triangle
|
||||||
|
voices, pentatonic minor ~92bpm, pattern mutates every 32 bars, flavored by the
|
||||||
|
current era (reel era gets wow/flutter + crackle).
|
||||||
|
- **AM 640 THE STANDARD** — Correction propaganda: ring-mod mumble cadence, and
|
||||||
|
the flagship trick: **THE SCREEN's chyron subtitles the radio** when tuned
|
||||||
|
(DATA writes the lines). The sky captions the audio. Do this one properly.
|
||||||
|
- **SW 6955 NUMBERS** — cold formant-synth digit groups; chyron shows the digits;
|
||||||
|
some groups encode coordinates of DATA's `hidden: true` bonus seams — the radio
|
||||||
|
is a treasure map for players with a pencil.
|
||||||
|
- **108.0 DEAD AIR** — room tone, breathing, one reversed-chime ghost per ~10min,
|
||||||
|
seeded.
|
||||||
|
7. **Layer 3 — world ambience (post-discovery)**: factory hum scaled by draw/gen,
|
||||||
|
tape-chunk per shipment stamp, heat adds a strained whine near scram. Subtle;
|
||||||
|
ducked under the radio.
|
||||||
|
8. **The control surface**: export a narrow `radio` API (setFrequency/setBand/
|
||||||
|
volume/mute/getState/subscribe) — UI's tuner dock drives it (sanctioned import,
|
||||||
|
document it). Master chain: gain → soft limiter; zero per-frame allocations.
|
||||||
|
|
||||||
|
**Definition of done:** spectral verification (AnalyserNode: station lock vs static
|
||||||
|
show distinct spectra; brownout pop is a real transient); pre-discovery silence
|
||||||
|
guarantee tested; subtitles verified on the chyron; era feed contact sheet; CPU
|
||||||
|
budget stated. This round, verification includes LISTENING — describe what it
|
||||||
|
sounds like in NOTES, in words.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -21,40 +21,45 @@ playable through unit tests. You are the lane the other four trust with their li
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## CURRENT ORDERS — Round 5 (goal: M2 closes — the Bitstream comes alive)
|
## CURRENT ORDERS — ROUND 5 (MEGA) — supersedes the earlier round-5 text
|
||||||
|
|
||||||
Round 4 review: the realtech.test.ts tripwire caught DATA's circular tree and your
|
This is the big one: everything from the previous round-5 orders PLUS the world's
|
||||||
premise-guard philosophy caught their fix — the system is working. Verdicts:
|
first secret. Read it all before starting; the parts interlock.
|
||||||
**grantResearch PROPOSAL GRANTED** — it's in v5 as a real Command (sandbox is a
|
|
||||||
feature, not a cheat); implement it, and it replaces the testkit import currently in
|
|
||||||
main.ts's `__fktryDemo` (I wired testkit as the stopgap — swap is mine once you land).
|
|
||||||
**Research time APPROVED** (your NEXT): labs take `RESEARCH_TICKS_PER_PACK` per pack
|
|
||||||
(export it) so a tech is an investment, not a purchase. **Pack abandonment on target
|
|
||||||
switch: KEPT** — "packs are the cost of indecision" is design, write it no further.
|
|
||||||
Cooling cap reasoning accepted; the additive-stacking rule is now a contract comment
|
|
||||||
(DATA tuned blind against the ambiguity — your sentence, my fault for not catching it).
|
|
||||||
|
|
||||||
1. **`grantResearch` command** — instant unlock list, idempotent, save/load safe.
|
### PART A — carried from round 5 (unchanged in spirit)
|
||||||
2. **Research time** — per-pack ticks; progress visible in `research.progress`
|
1. **`grantResearch` command** — idempotent, save/load safe. Tell me in NOTES when it
|
||||||
between packs is your design call (fractional or stepped — note it).
|
lands; main.ts's `__fktryDemo` swaps off testkit.
|
||||||
3. **Wildlife v1 — the round's centerpiece** (contracts v5: `snapshot.wildlife`,
|
2. **Research time** — `RESEARCH_TICKS_PER_PACK` (export it); a tech is an
|
||||||
`WildlifeState`, the `wildlife` event): HF DUST PILES accumulate near machines
|
investment, not a purchase. Fractional vs stepped progress: your call, note it.
|
||||||
whose recipes emit hf-dust while they run (rate/threshold your design; the seeded
|
3. **Wildlife v1** (contracts v5 shapes): dust piles accumulate near running
|
||||||
RNG finally rolls); a pile at size 1.0 hatches a MOSQUITO SWARM that drifts to the
|
hf-dust-emitting machines (seeded RNG finally rolls); size 1.0 hatches a MOSQUITO
|
||||||
nearest running machine and degrades its speed while attached (`target`); swarms
|
SWARM that drifts to the nearest running machine and degrades its speed while
|
||||||
are cleared by a trap machine (DATA authors it — coordinate the mechanic: trap
|
attached (`target`); cleared by DATA's trap machine (suggested shape: trap crafts
|
||||||
with an empty-input recipe that only crafts while a swarm is in radius, producing
|
its empty-input catch recipe only while a swarm is in radius, producing the canned
|
||||||
the canned `mosquito-swarm` item, is my suggested shape). Deterministic, save/load
|
`mosquito-swarm` item). Deterministic; save/load carries it; spawn/clear events.
|
||||||
carries it all, events on spawn/clear. Tests including "a factory that vents dust
|
Include the design-point test: a factory that sinks its dust never hatches.
|
||||||
into product instead of shipping it never hatches a swarm" — the design point.
|
|
||||||
4. **Reference factory v5**: grow the research rig (bottler + archaeology lab fed by
|
|
||||||
quantizer surplus) so research is playable in the demo, and the 20k run should now
|
|
||||||
also hatch at least one swarm and trap it if DATA's trap lands — the demo becomes
|
|
||||||
the whole M2 story. Regression stays green.
|
|
||||||
|
|
||||||
**Definition of done:** wildlife lifecycle proven under test (accumulate → hatch →
|
### PART B — the ground and the pipe (new)
|
||||||
degrade → trap → event trail), research takes time, grantResearch lands (tell me in
|
4. **SEAMS BECOME REAL.** Consume `data/seams.json` (DATA authors this round —
|
||||||
NOTES so I swap main.ts off testkit), reference v5 researches a real tech in-demo.
|
coordinate the schema in NOTES early): extractors only extract while their
|
||||||
|
footprint overlaps a seam region; off-seam extractors idle with a new jam reason
|
||||||
|
`'no seam'` (edge-triggered like the others; UI will voice it). Reference factory
|
||||||
|
v5 must sit on seams — coordinate layout coordinates with DATA.
|
||||||
|
5. **THE RELIC (the hidden pipe).** One `optical-fossil` per world (contracts v6:
|
||||||
|
`RelicState`, `excavate`, `relicFound`): position derived from the seed —
|
||||||
|
deterministic, 18-28 tiles from origin in a quiet corner, never on a seam, never
|
||||||
|
under the reference factory. `excavate` within 1 tile of the unfound relic flips
|
||||||
|
`found`, emits `relicFound`, persists through save/load forever. `relics` always
|
||||||
|
present in the snapshot (found or not — RENDER draws the shimmer, UI must not be
|
||||||
|
able to cheat-detect it any other way). No bandwidth cost, no research gate: the
|
||||||
|
only lock is *finding it*.
|
||||||
|
6. **Reference factory v5**: research rig (bottler + archaeology lab off quantizer
|
||||||
|
surplus) so research runs in-demo; sits on seams per #4; one swarm hatches and is
|
||||||
|
trapped within the 20k window if DATA's trap lands. Zero-brownout regression stays.
|
||||||
|
|
||||||
|
**Definition of done:** relic lifecycle tested (excavate too far = dropped; found
|
||||||
|
persists through save→load→20k ticks); off-seam extractor refuses with 'no seam';
|
||||||
|
wildlife full lifecycle; research takes time; reference v5 green and on-seam.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -24,33 +24,46 @@ dispatch Commands via the bus and read state from `update(snap, events)`.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## CURRENT ORDERS — Round 5 (goal: the pressure has a face)
|
## CURRENT ORDERS — ROUND 5 (MEGA) — supersedes the earlier round-5 text
|
||||||
|
|
||||||
Round 4 review: the live.test.ts research loop — lock → refuse → lab → ratify →
|
Review verdicts you're executing: first-click punishment without guidance, camera
|
||||||
padlock falls → place succeeds — is the single best proof in the repo, and your
|
controls taught nowhere, THE SCREEN's payoff too quiet, and one suspect tab click.
|
||||||
"re-probe before writing NOTES" practice is now a MASTERPLAN process note for
|
Plus the radio — the game's sound is a *discovery*, and you build its face.
|
||||||
everyone. Verdicts: your save-schema coupling PROPOSAL is answered by v5's
|
|
||||||
`grantResearch` Command (SIM implements) — migrate your tests to it and the blob
|
|
||||||
coupling dies. Scrolling tab strip: APPROVED (you flagged the wrap). RENDER's tint
|
|
||||||
verification is still owed — close it this round.
|
|
||||||
|
|
||||||
1. **Scrolling tab strip** — your design; keep every tab reachable by `[`/`]` and
|
### PART A — carried from round 5
|
||||||
the strip legible at 29+ machines and REMOVE + RESEARCH.
|
1. **Scrolling tab strip** (your design, approved).
|
||||||
2. **Publish inspect mode**: when the inspector opens, `setSelection({mode:
|
2. **Publish inspect mode**: inspector open → `setSelection({mode:'inspect',
|
||||||
'inspect', entity})`; clear on close. RENDER highlights + draws cooler auras off
|
entity})`; clear on close; Esc order preserved (drop tool → close inspector).
|
||||||
it — coordinate the timing so Esc clears both cleanly.
|
3. **Wildlife surfacing**: infestation toasts in voice; MOSQUITO EXPOSURE line +
|
||||||
3. **Wildlife surfacing** (SIM lands it this round): infestation toasts in house
|
speed penalty in the inspector; one hatch-warning toast per pile, not a nag.
|
||||||
voice ("QUANTIZER HOSTS A SWARM. OSHA HAS BEEN NOTIFIED. OSHA IS THE SWARM."),
|
4. **Migrate research tests** to `grantResearch`; **verify RENDER's demolition tint
|
||||||
inspector shows a MOSQUITO EXPOSURE line on a targeted machine + the speed
|
+ inspect highlight with screenshots** (third round owed — close it).
|
||||||
penalty; a pile nearing hatch (size > 0.8) earns one warning toast, not a nag.
|
|
||||||
4. **Migrate research-granting tests** to the `grantResearch` command once SIM
|
|
||||||
lands it (drop the save-blob mutation).
|
|
||||||
5. **Verify RENDER's demolition tint + inspect highlight** with your own eyes and
|
|
||||||
screenshot it in NOTES — third round this handshake has floated unverified.
|
|
||||||
|
|
||||||
**Definition of done:** tab strip scrolls; inspect mode round-trips with RENDER
|
### PART B — onboarding + the radio face (new)
|
||||||
(screenshot); a swarm's lifecycle is narratable from UI alone (warning → infested →
|
5. **First-brownout mercy toast** (once per session): "NOTHING IS GENERATING. THE
|
||||||
trapped); research tests no longer parse save blobs.
|
COMMITTEE SUGGESTS: POWER." — fires on the first brownout event only. The alarm
|
||||||
|
currently teaches nothing; this is the one hint the opening needs.
|
||||||
|
6. **Camera hint** in the idle line ("MMB/WASD PAN · WHEEL ZOOM") and a **tab
|
||||||
|
hitbox check**: in review, a direct click on the POWER tab did nothing once
|
||||||
|
(keyboard paging worked; may be harness — reproduce with a real mouse, fix or
|
||||||
|
file it as harness with evidence).
|
||||||
|
7. **New jam voice**: `'no seam'` lands from SIM — give it the line it deserves
|
||||||
|
("SEAM EXTRACTOR: THERE IS NOTHING DOWN THERE. MOVE.").
|
||||||
|
8. **THE SCREEN click-to-enlarge**: click toggles a centered ~2.5× overlay (CSS
|
||||||
|
transform + backdrop dim), Esc/click closes. The sky is the score; let people
|
||||||
|
look at it.
|
||||||
|
9. **THE TUNER DOCK (the radio's face).** Hidden until `relicFound`/`relics.found`.
|
||||||
|
Then: a dock slides in (bottom-right) — frequency dial (drag + arrow keys), band
|
||||||
|
AM/FM/SW, volume + mute, station readout in voice ("88.1 FKTRY FM — SIGNAL
|
||||||
|
LOCKED"). Controls talk to THE SPEAKER via its exported `radio` control (narrow
|
||||||
|
sanctioned import from `src/audio` — SCREEN documents the API; coordinate in
|
||||||
|
NOTES). Discovery ceremony: relicFound → "AUDIO BUS RESTORED. THE BITSTREAM HAS
|
||||||
|
A VOICE." toast + dock slide-in. Radio state persists per session only (the
|
||||||
|
fossil's `found` is the durable part, sim-side).
|
||||||
|
|
||||||
|
**Definition of done:** cold-start first-brownout shows the mercy toast; tuner dock
|
||||||
|
appears only after excavation and drives the real audio engine; enlarge verified;
|
||||||
|
tint/highlight screenshots in NOTES; tab click adjudicated.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
12
fktry/src/audio/index.ts
Normal file
12
fktry/src/audio/index.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/** LANE-SCREEN territory (THE SPEAKER). Stub — replace per lanes/LANE-SCREEN.md.
|
||||||
|
* All sound is Web Audio synthesis; no asset files, ever. */
|
||||||
|
import type { AudioFX, GameData, SimEvent, SimSnapshot } from '../contracts';
|
||||||
|
|
||||||
|
export function createAudioFX(): AudioFX {
|
||||||
|
return {
|
||||||
|
init(_data: GameData) {},
|
||||||
|
unlock() {},
|
||||||
|
onEvents(_events: SimEvent[]) {},
|
||||||
|
frame(_timeMs: number, _snap?: SimSnapshot) {},
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -132,6 +132,14 @@ export interface SimSnapshot {
|
|||||||
commissionProgress: Record<string, number>;
|
commissionProgress: Record<string, number>;
|
||||||
research?: ResearchState; // v4: research progress (hardens in v6)
|
research?: ResearchState; // v4: research progress (hardens in v6)
|
||||||
wildlife?: ReadonlyArray<WildlifeState>; // v5: piles & swarms (M2's living hazards)
|
wildlife?: ReadonlyArray<WildlifeState>; // v5: piles & swarms (M2's living hazards)
|
||||||
|
relics?: ReadonlyArray<RelicState>; // v6: buried secrets (the hidden pipe)
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RelicState {
|
||||||
|
id: number;
|
||||||
|
kind: 'optical-fossil'; // v6: the severed audio bus — one per world
|
||||||
|
pos: Vec2;
|
||||||
|
found: boolean; // excavated; persists through save/load
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WildlifeState {
|
export interface WildlifeState {
|
||||||
@ -160,6 +168,7 @@ export type Command =
|
|||||||
| { kind: 'grantResearch'; tech: string[] } // v5: instant unlock — the
|
| { kind: 'grantResearch'; tech: string[] } // v5: instant unlock — the
|
||||||
// sandbox/demo verb, also a
|
// sandbox/demo verb, also a
|
||||||
// legitimate creative mode
|
// legitimate creative mode
|
||||||
|
| { kind: 'excavate'; pos: Vec2 } // v6: dig at a relic site
|
||||||
| { kind: 'setPaused'; paused: boolean };
|
| { kind: 'setPaused'; paused: boolean };
|
||||||
|
|
||||||
export type SimEvent =
|
export type SimEvent =
|
||||||
@ -173,7 +182,8 @@ export type SimEvent =
|
|||||||
| { kind: 'scram'; entity: number; on: boolean; tick: number } // v2: heat shutdown edge
|
| { kind: 'scram'; entity: number; on: boolean; tick: number } // v2: heat shutdown edge
|
||||||
| { kind: 'researched'; tech: string; tick: number } // v4: research complete
|
| { kind: 'researched'; tech: string; tick: number } // v4: research complete
|
||||||
| { kind: 'wildlife'; on: 'spawned' | 'cleared'; wildlife: 'dust-pile' | 'mosquito-swarm';
|
| { kind: 'wildlife'; on: 'spawned' | 'cleared'; wildlife: 'dust-pile' | 'mosquito-swarm';
|
||||||
id: number; pos: Vec2; tick: number }; // v5: hazard lifecycle
|
id: number; pos: Vec2; tick: number } // v5: hazard lifecycle
|
||||||
|
| { kind: 'relicFound'; relic: 'optical-fossil'; id: number; tick: number }; // v6
|
||||||
|
|
||||||
// ---------------------------------------------------------------- module interfaces
|
// ---------------------------------------------------------------- module interfaces
|
||||||
|
|
||||||
@ -223,6 +233,18 @@ export interface UI {
|
|||||||
update(snap: SimSnapshot, events: SimEvent[]): void;
|
update(snap: SimSnapshot, events: SimEvent[]): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** v6: THE SPEAKER — everything audible. All sound is synthesized (Web Audio), no
|
||||||
|
* asset files. Pre-discovery: minimal diegetic UI sounds only. After the optical
|
||||||
|
* fossil is found (snapshot.relics / relicFound), the full band unlocks: tuner,
|
||||||
|
* stations, world ambience. Owned by LANE-SCREEN (src/audio/**). */
|
||||||
|
export interface AudioFX {
|
||||||
|
init(data: GameData): void;
|
||||||
|
/** call on first user gesture — browsers gate AudioContext on interaction */
|
||||||
|
unlock(): void;
|
||||||
|
onEvents(events: SimEvent[]): void;
|
||||||
|
frame(timeMs: number, snap?: SimSnapshot): void;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ScreenFX {
|
export interface ScreenFX {
|
||||||
init(canvas: HTMLCanvasElement, data: GameData): void;
|
init(canvas: HTMLCanvasElement, data: GameData): void;
|
||||||
onEvents(events: SimEvent[]): void; // shipped items feed the corruption
|
onEvents(events: SimEvent[]): void; // shipped items feed the corruption
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { createSim } from './sim';
|
|||||||
import { createRenderer } from './render';
|
import { createRenderer } from './render';
|
||||||
import { createUI } from './ui';
|
import { createUI } from './ui';
|
||||||
import { createScreenFX } from './screen';
|
import { createScreenFX } from './screen';
|
||||||
|
import { createAudioFX } from './audio';
|
||||||
|
|
||||||
import items from '../data/items.json';
|
import items from '../data/items.json';
|
||||||
import machines from '../data/machines.json';
|
import machines from '../data/machines.json';
|
||||||
@ -20,6 +21,7 @@ const sim = createSim();
|
|||||||
const renderer = createRenderer();
|
const renderer = createRenderer();
|
||||||
const ui = createUI();
|
const ui = createUI();
|
||||||
const screen = createScreenFX();
|
const screen = createScreenFX();
|
||||||
|
const audio = createAudioFX();
|
||||||
|
|
||||||
// v4 bridge: _sel keeps the legacy {def,dir} shape (including the deprecated
|
// v4 bridge: _sel keeps the legacy {def,dir} shape (including the deprecated
|
||||||
// '__remove' sentinel) so unmigrated lanes keep working; selection()/setSelection()
|
// '__remove' sentinel) so unmigrated lanes keep working; selection()/setSelection()
|
||||||
@ -52,6 +54,9 @@ async function boot() {
|
|||||||
await renderer.init(document.getElementById('game')!, data);
|
await renderer.init(document.getElementById('game')!, data);
|
||||||
ui.init(document.getElementById('ui')!, data, bus);
|
ui.init(document.getElementById('ui')!, data, bus);
|
||||||
screen.init(document.getElementById('screen') as HTMLCanvasElement, data);
|
screen.init(document.getElementById('screen') as HTMLCanvasElement, data);
|
||||||
|
audio.init(data);
|
||||||
|
// browsers gate AudioContext on a user gesture — unlock on the first one
|
||||||
|
addEventListener('pointerdown', () => audio.unlock(), { once: true });
|
||||||
|
|
||||||
// click-to-place / hover ghost glue
|
// click-to-place / hover ghost glue
|
||||||
const game = document.getElementById('game')!;
|
const game = document.getElementById('game')!;
|
||||||
@ -86,6 +91,8 @@ async function boot() {
|
|||||||
ui.update(snap, events);
|
ui.update(snap, events);
|
||||||
screen.onEvents(events);
|
screen.onEvents(events);
|
||||||
screen.frame(now, snap);
|
screen.frame(now, snap);
|
||||||
|
audio.onEvents(events);
|
||||||
|
audio.frame(now, snap);
|
||||||
requestAnimationFrame(loop);
|
requestAnimationFrame(loop);
|
||||||
}
|
}
|
||||||
requestAnimationFrame(loop);
|
requestAnimationFrame(loop);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user