Feature: Toroid vertical slice — first live flying enemy (slice 8) - #110
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Correct the Toroid and shared-rules paragraphs against the pinned reference (continuous formation refill with inherited scroll position; the swing is a lateral acceleration triggered by a lateral-column window; the spawn column is a rejected-and-redrawn stream draw) and settle the document so its slice-8 leaves can proceed. Record per-family verification status inside the doc: only the shared rules and Toroid are verified line-by-line this slice; the other eleven families are drafted-pending-verification until their own slices. Roadmap: air parent -> locked; air.toroid and air.standard-bullets -> planned; difficulty.live-pressure (#60) -> slice 10 (kept atomic — DIF-03.play needs a fire-permission-mask family, which Toroid is not). Regenerate the settled-acceptance-criteria matrix. Part of #65, #66. Part of #18. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extract the 32-direction aim tables (the four angle_dX_dY tables and the octant quantizer) into docs/spec/data/aiming.json via the deterministic extractor, and bake the octant table plus the two tiers Toroid uses (24 approach, 32 bullet) into read-only Stage lists. Add the eight per-slot position/motion fields (slot x/y/dx/dy/timer/code/pts/flag) as parallel 64-entry lists beside slot type/state, zeroed at generation and re-zeroed by an extended clear slots. Dormant this commit: no entity aims, moves, or occupies a slot — the aim procedure, the formation spawner, and the Toroid updater land next. Model fixtures prove the angle tables against their sine/cosine model and the baked lists against the committed data; structural fixtures prove every slot field is zeroed and that clear slots covers every slot list. Re-pin build_hash. Record 023. Part of #57, #65. Part of #18. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The first live flying enemy. The formation wave spawns Toroids into the six flying slots; the ordered walk dispatches each to `update toroid`, which aims at the craft on the 24-magnitude homing tier, approaches, swings laterally toward the craft's side when nearly level, animates its flap, and culls off the play field keeping its scroll-axis position (the coded inherited-scroll refill). This is the first live consumer of the shared RNG (SYS-04) and the slice-7 formation state, and lights the AREA-02 air path (formations, not add_object, spawn live flying enemies). Six persistent `toroid` clones render the pool. Also fixes op_round: `round` is the standalone operator_round block, not an operator_mathop function — the mathop form silently returned 0, so the player cell read as (0,0) and aim was wrong. With the fix the craft reads (row 30, col 16) and Toroids aim and move correctly. Evidence: - structural `_air01_failures` + per-clause negatives (lifecycle procs warp, spawn/dispatch driven, cull inherits position, bounded draw) - model fixture `ToroidSpawnDraw` over the committed RNG seeds (valid, craft-avoiding columns; bounded draw; ~1.3% exhaustion deviation) - harness `toroid-wave-spawns-and-moves` and `rng-draw-order`, each with a biting negative (new `neutralizeProc` mutation empties a warp proc's body) - roadmap-evidence markers for AIR-01, SYS-04, AREA-02 - mechanics record 024; cross-ref updates to records 004, 016, 020 Also reconciles two roadmap tests (test_roadmap.py) to the commit-0 spec-settle: `air` is now a settled spec, so the negative/executable fixtures repoint to the still-draft `ground` spec. These belong with the commit-0 settle; they are folded here because this environment has no interactive rebase. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The first working combat. A player shot overlapping an active Toroid resolves through the single-hit path: the walk's `check air shot hit` detector (called per active flying enemy) tests the shot slots with the reference's shadow-MSB window (HIT_WINDOW_SHOT_FLYING, from check_shot_hit_flying_enemy $19A6), and on an overlap sets `award value` from the enemy's `slot pts`, calls `resolve hit` (the one score path), starts the enemy's explosion, and marks the shot spent. The blaster clone mirrors its live position into its shot slot each travel iteration (inverse render map, floored) and self-destructs when its slot leaves ACTIVE, so the clone still frees its own slot and the 3-shot cap can't desync. A struck Toroid runs `explode toroid tick` (drifts, 20 frames, size-doubling phase) then frees; the renderer shows the referenced solv_death explosion frames as a recorded stand-in. The debug S scoring fixture is retired: a real kill now produces `award value`. Locked spec amended (needs operator guardrail-ack): the shot-vs-air hit window is recorded in player-craft-and-weapons.md beside the player and Bacura windows. Evidence: - structural `_wpn02_failures` + per-clause negatives; the retired-fixture check; extended SYS-03 tests still green with a live detector driving them - harness `blaster-kills-toroid-and-scores` (+ biting negative) and the kill-driven `score-digits-render` - roadmap-evidence markers for WPN-02, SYS-03, ECO-01 - mechanics record 025; cross-ref updates to records 006 and 009 Deviations (record 025): no shadow-byte wrap (no phantom long-range hits); one-tick shot-position lag; explosion visual is the solv_death stand-in (dedicated Toroid-burst crops + the frame-8 recentre deferred to a later art pass). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… (AIR-12, PLY-02) The fourth combat commit of slice 8 brings the enemy's side of the fight online and retires the last debug fixtures. - AIR-12: the shooting Toroid (type 0x0B) fires exactly one aimed enemy bullet at its swing commit (allocating from the 19-slot bullet pool, aimed on the generic 32-magnitude tier); the bullet flies straight and culls off any edge. A 19-clone `enemy_bullet` renderer shows the pool. - PLY-02: a Toroid or an enemy bullet touching the craft raises `player hit`; the walk's terminal death check, gated on `player hit` = 1 AND `invuln` = 0, spends a craft, clears the flag, and runs the one player-dead transition. The lives-driven respawn/game-over decision (slice 4) is now driven by real contact. - The debug D (respawn) and G (terminal death) key fixtures are removed. Tests: `_ply02_failures`, `_enemy_bullet_pool_failures`, and `_air12_failures` rewritten/added on the live path with biting negatives; build_hash re-pinned; AIR-12 and PLY-02 roadmap-evidence markers added; harness `death-respawn`, `death-game-over`, and `enemy-bullet-fires` run it live. Record 026 written; records 006/008/013 cross-referenced. 193 Python tests and 33 harness scenarios green; both generators' check() pass; two builds byte-identical. GOVERNANCE: this commit amends the LOCKED spec docs/spec/core-game-systems.md to remove the temporary D/G keyboard death fixtures now that live combat deals real lethal contact. Per the plan-review disposition, this locked-spec edit requires the operator to apply the `guardrail-ack` label on the PR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Post-build documentation for the Toroid vertical slice. - MECHANICS_CATALOG: SYS-02/SYS-03/SYS-04, AIR-01, WPN-02, and PLY-02 move to present (live combat participants); ECO-01 records the real in-play awarder; AIR-12/AREA-02/FORM-01/DIF-01/DIF-03 rows note what is now live and what is deferred (DIF-03.play / #60 to slice 10; radiating bullets and Bacura to slice 11). - PLAYTEST_CHECKLIST: the D/G/S debug keys are gone; a new step 4a walks the Toroid combat (waves spawn and refill, swing, single aimed shot, shoot-to- score-30, no orphan clones on reload), and steps 5/6 exercise death and scoring through real combat instead of the retired fixtures. - BUILD_PLAN: a delivered-annotation row for slice 8 listing what it delivered, the leaves it closes, and the recorded deferrals. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pre-submission cold review (5 passes: spec-conformance, divergence-hunter, technical-integrity, security-governance, usability) surfaced one blocking defect and several minor items; dispositioned here. BLOCKING (spec-conformance + divergence-hunter, both independently): - The Toroid's lateral swing accelerated AWAY from the craft, not toward it — the opposite of the locked aerial-enemies.md / record 024 behavior. A craft-on-the-right (offset >= 0 -> SWING_RIGHT) did `slot dy -= accel`, which the render map (stage_x increases with slot y) turns into leftward motion. Fixed: SWING_RIGHT now does `slot dy += accel` (toward higher columns / the craft), SWING_LEFT mirrors it; the animation keeps its per-direction order. No committed test bound the swing SIGN, so it passed every check — added the live harness guard `toroid-swings-toward-craft` (asserts dy > 0 on a right swing; the exact sign the bug inverted) with a biting negative. Also addressed: - tech-integrity: re-anchored the ENGINE-TODO at the walk dispatch (was mid- sentence, fell out of engine_todo.py enumeration); added a generate-time assert that the max formation count fits FLYING_SLOTS (fails loud on a future data regen instead of silently under-spawning). - divergence-hunter: `_air12_failures` now checks the bullet update is actually DISPATCHED from the walk (not just that its body is correct), with a negative. - spec-conformance / divergence-hunter minor: refreshed three stale comments (the removed debug S key; the "DORMANT" enemy-bullet allocator, now live). - usability: the playtest checklist now discloses the two interim art stand-ins (bullet costume, reused explosion frames) as "note, don't fail", and corrects the stale time estimate. Regenerated project.json (swing swap only, 4 lines), re-pinned build_hash to f09da295. 193 Python tests, 35 harness scenarios, both generator checks, and the engine CI suite all green; two builds byte-identical. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
These engine-internal files are regenerated by the update. The engine rebuilds them from your project's own current state on each update. A change here that reflects a real change in your project — you edited what the file is generated from and regenerated it — is reproduced, not lost. But content typed directly into one of these files, with no matching change to the source it comes from, will not survive: it is rebuilt away on the next update. So if you meant to change what one of these records, edit the source it is generated from (for the settled-criteria record, your
This is a heads-up only — it does not block your merge, and your merge is the decision. |
Operator playtest caught that Toroids home straight into the craft instead of swinging away like the arcade. Grounded against the pinned disassembly (jotd666/xevious@71473685, `toroid_toggle_dir` / `toroid_swing_right` `subq #1,_dY` / `toroid_swing_left` `addq #1,_dY`): the Toroid spawns AIMED at the craft, and the swing nudges that lateral velocity AGAINST the approach each frame, so it decelerates, reverses, and peels away — a bounce, not a dive. This reverts the swing-sign change from the pre-submission fix commit (13e6e68), which had been made on the strength of the locked spec's wording ("swing toward the craft's side"). That wording was wrong and it fooled all five cold review passes plus the scoped re-audit — only the operator playtest, and then the reference itself, caught it. `SWING_RIGHT` is back to `slot dy -= accel`, `SWING_LEFT` to `slot dy += accel`; build_hash returns to f2fe851b. Root cause of all three reported symptoms is this one homing bug: homing Toroids funnel into the craft's column, so they (2) die in the held-fire shot stream "regardless of alignment" and (3) crash into the craft after speeding up. The bounce should resolve 2 and 3 as well (they are rendered-gameplay effects the headless harness can't fully exercise — operator re-playtest confirms). - Flipped the harness guard `toroid-swing-reverses-away` (was `toroid-swings-toward-craft`) to assert the reversal (`slot dy < 0` on a right swing, the toggle_dir bounce) with a biting negative — so the sign cannot silently re-invert into a homing dive. - Corrected the swing description in the locked-at-settling `aerial-enemies.md` (Toroid paragraph, draft at PR base so not lock-gated), record 024, and the playtest checklist step 4a; all now describe the reversal/bounce and cite `toroid_toggle_dir`. 193 Python tests, 35 harness scenarios, both generator checks, mechanics-record check, and engine CI all green; two builds byte-identical (f2fe851b). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Follow-up to the swing reversal, from continued operator playtest ("flees away
now, but slides down the side, then my ship explodes; dies every time they go
off screen"). Two grounded fixes:
- LEFT-EDGE CULL. The Toroid cull checked bottom/top/right but not the left.
The reference culls a left exit via its 8-bit column wrapping past the right
threshold; this signed-column port needs an explicit `col <= -2` cull. Without
it a Toroid the (now-correct) swing sends off the left never freed its slot and
slid down the edge. Bullets already had this; Toroids now match.
- TOP-ENTRY SPAWN. `init toroid` now resets the scroll row to the top before
aiming. The reference spawner sets only the object TYPE and relies on the world
scroll to carry flying enemies down from the top; this self-propelled port has
no enemy world-scroll, so a refilled slot was inheriting the previous occupant's
mid-field scroll row (the swing culls Toroids at the sides, mid-field) and aiming
a steep short-range dive that clipped a stationary craft. Top-entry restores the
arcade's "stream in from the top" and gives the swing room to divert.
Note: an aimed Toroid still clips a *stationary* craft — it is aimed at you,
spawns >=8 columns away (arcade rule), and the swing only triggers on lateral
alignment (near arrival); a non-dodging craft gets hit, which appears inherent to
the faithful design. The headless harness (craft can't dodge) reflects this; the
active-play feel is the operator's to judge.
build_hash -> ee6f42c6; 193 Python tests + 35 harness scenarios green; both
generator checks pass; two builds byte-identical. Record 024 updated (top-entry
deviation, any-edge cull). Also fixes the earlier silent no-op where generate()
refused on a dirty project.json, so the left-cull/top-spawn are actually built now.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The craft-overlap and shot-vs-air hit windows each built one delta block and reused it across both the `<` (lower) and `>` (upper) compares. A Scratch reporter attaches to only one parent, so the `>` stole the delta from the `<`, leaving the lower bound reading an empty operand (always in range). Both boxes degraded to a quadrant/whole-row: - craft died whenever it crossed the row OR column above/beside a not-yet-fleeing Toroid (operator: "I die if I cross the vertical/ horizontal column above the Toroid") - a held shot destroyed any Toroid in its row regardless of column (operator: "the fire button just explodes them at random") Rebuild each axis delta as its own reporter subtree (a lambda called once per compare) so both bounds read live operands. The craft box collapses to the single cell (0,0); the shot box to a single column within one row ahead — verified by headless hit-box maps. Add two discriminating harness scenarios the original tests lacked (they only ever seeded on-target, so the dead lower bound was invisible): - air-shot-hit-is-single-column (off-column shot must NOT score) - craft-collision-is-single-cell (off-row/off-column Toroid must NOT hit) Re-pin build_hash; records 025/026 document the fix. 193 Python tests, 39 harness scenarios, both generator checks green; builds byte-identical. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Correct the citations the resolver cannot resolve at the pinned commit — locators only, no gameplay-meaning change: - Nonexistent labels -> their real names at the pin: sub_2_fn_8/_22 gain their __fire_freq_mask_* suffixes (difficulty-and-formations.md, mechanics 022), sub_2_fn_3 gains __inc_enemy_AI_and_flying_enemies (mechanics 020). - Missing file in scope -> declared: player-craft-and-weapons.md and difficulty-and-formations.md each declare their default source file (main and sub respectively); core-game-systems.md and andor-genesis.md gain an explicit file token on the one citation that leaves the surrounding default. - Approximate reference -> exact: area-progression-and-terrain.md's `~514` becomes `main_gameplay_loop` 514-521 (the area-advance / 16->7 loop). Add tests/test_reference_corpus.py: three network-free guards (every reference provenance line names the index pin; every spec citation has a file in scope; no approximate line reference survives), which run in the ordinary test job. The settled-criteria matrix is unchanged (edits fall outside acceptance-criteria cells, verified by regenerating it). Deferred, deliberately: the bare-range -> labelled-citation conversions, which cluster in the draft enemy docs that PR #110 and the upcoming settling slices rewrite; they land there under the new fidelity review rather than conflicting with in-flight work. Touches four settled specs (player-craft-and-weapons, difficulty-and-formations, core-game-systems, area-progression-and-terrain) -> needs guardrail-ack. Part of #111. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The player found shots passing through Toroids ("many rounds into a
group and nothing happens") — far harder to kill than the arcade. Two
compounding causes, both port artifacts the reference never faced:
1. TUNNELING (the real bug). The blaster shot travels changeyby 20 =
20 stage-px/frame ÷ RENDER_ROW_STAGE(8) = 2.5 cells/frame, but the
shot-vs-air hit window was only 2 cells tall. The per-frame step
overshoots the window, so a fired shot steps clean over a Toroid
between collision samples. Every shot in a held stream starts at the
craft's row and so shares one sampling phase — a Toroid in a gap is
immune to the entire stream. DY=20 was a preserved-baseline the
movement slice never reconciled to the collision window.
2. The window covered only ~40% of the 36-px rendered Toroid, so
bullets visibly on the sprite missed.
Fix: double HIT_WINDOW_SHOT_FLYING (16,32,8,16) -> (32,64,16,32). The
4-cell height exceeds the 2.5-cell step (with margin for enemy closing
motion) so every crossing is sampled; the ±1-cell width matches the
rendered sprite. The craft HURTBOX (HIT_WINDOW_BULLET_FLYING) is left
tight on purpose: forgiving offence, precise defence. A deliberate,
recorded deviation from the reference; locked spec updated (guardrail-ack).
The headless harness cannot reproduce per-frame timing (threads run to
settling), so the guard for tunneling is a numeric invariant, B8-no-tunnel:
shot cell-step <= window height - 1 cell. Also reworked the shot-window
harness scenario to seed a real detector slot (37) with the enemy off the
craft column — the old one seeded slot 36, which the detector never reads
(SHOT_SLOTS = 37-39), so it only passed via the real tapped shot.
Re-pin build_hash. 193 Python tests, 39 harness scenarios, both
generator checks green; builds byte-identical (0c7c82db).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Playtest record — approvedTested head commit: Played area 1 in Scratch 3 across the slice-8 behavior list (spawn → aim → swing → flap → shot → blaster-to-air kill/+30 → collision death → cleanup). After the three playtest-driven fixes (swing reversal, single-cell/bounded collision boxes, and the anti-tunneling shot-window widening) the Toroids behave and destroy correctly — not pixel-exact to the arcade, but a good faithful port. Approved to merge; further hit-feel tuning can follow as more mechanics come online. Interim art stand-ins (enemy bullet costume, reused explosion frames) noted, not blocking — deferred to the art pass per the PR's Out of scope. |
Follow-up: the reported
|
| seeded shot JS index | score delta | shot consumed? |
|---|---|---|
| enemy only (no shot) | 0 | — |
| 35 (craft, Scratch item 36) | 0 | no |
| 36 (Scratch item 37) | 30 | yes |
| 37 (Scratch item 38) | 30 | yes |
| 38 (Scratch item 39) | 30 | yes |
| 39 (Scratch item 40) | 0 | no |
In the scenario as it runs today, after the step it is slot 36's state that flips 1→0 while 37/38 stay active — the seeded shot is the one that resolves the hit. blaster-kills-toroid-and-scores scores via its controlled seed, for the right reason, and the neutralizeProc('check air shot hit') negative still bites (enemy-only → 0 delta). Two incidental corrections: reachPlaying does not deliberately fire a shot (it taps start precisely to avoid a held-space shot), and air-shot-hit-column-bounded's use of JS slot 37 is also a valid detector slot (Scratch item 38) — correct, just not because "37 is the first real detector slot."
Changing the default from JS 36 → 37 would swap one valid detector slot for another: it fixes nothing and would force a matching edit to the scenario's slot-state[36] read. No change made; no build_hash change.
One real (minor, deferred) weakness
There is a genuine fragility nearby, just misdiagnosed: seedAirKill does not clear reachPlaying's three stray active shots (JS 36/37/38), and it parks the enemy at an arbitrary absolute cell (5000, 4000). Those stray shots (on the craft column) happen not to overlap that cell today, so the delta is exactly 30 — but that's coincidental. A robust hardening (clear JS shot slots 36/37/38 before seeding + park the enemy a few columns off the craft column) would guarantee exactly one controlled shot with no contamination. That's an enhancement to a currently-correct test, not a bug fix — noted here for later, not done in this slice.
Resolution: closing as not-a-bug.
Correct the citations the resolver cannot resolve at the pinned commit — locators only, no gameplay-meaning change: - Nonexistent labels -> their real names at the pin: sub_2_fn_8/_22 gain their __fire_freq_mask_* suffixes (difficulty-and-formations.md, mechanics 022), sub_2_fn_3 gains __inc_enemy_AI_and_flying_enemies (mechanics 020). - Missing file in scope -> declared: player-craft-and-weapons.md and difficulty-and-formations.md each declare their default source file (main and sub respectively); core-game-systems.md and andor-genesis.md gain an explicit file token on the one citation that leaves the surrounding default. - Approximate reference -> exact: area-progression-and-terrain.md's `~514` becomes `main_gameplay_loop` 514-521 (the area-advance / 16->7 loop). Add tests/test_reference_corpus.py: three network-free guards (every reference provenance line names the index pin; every spec citation has a file in scope; no approximate line reference survives), which run in the ordinary test job. The settled-criteria matrix is unchanged (edits fall outside acceptance-criteria cells, verified by regenerating it). Deferred, deliberately: the bare-range -> labelled-citation conversions, which cluster in the draft enemy docs that PR #110 and the upcoming settling slices rewrite; they land there under the new fidelity review rather than conflicting with in-flight work. Touches four settled specs (player-craft-and-weapons, difficulty-and-formations, core-game-systems, area-progression-and-terrain) -> needs guardrail-ack. Part of #111. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…refine guard (issue #111) Rebasing onto main (slice 8, PR #110) surfaced two things the fidelity tooling now covers: - docs/mechanics/023-aiming-and-slot-positions.md cited `cpy_dY_dX_to_obj` by its routine address ($3383) where the convention is a line number; the resolver flagged it. Corrected to the line (5135) so it resolves — the gate catching a real citation slip in freshly-merged work. - The approximate-line guard mis-flagged value suffixes new in slice 8 records (`~128 half-px`, `~40%`). Refined: flag a bare `~NNN` only when it is not followed by a unit word or `%`, so a genuine `~line)` reference is still caught while counts, distances, and percentages are left alone. Resolver: 107 citations checked, 0 unresolved. Full suite (229 tests) green. Part of #111. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Flip the ten already-merged leaves from status:"planned" to status:"history" with their delivering PR: difficulty.models-live-state (#56, PR #34) and the nine slice-8 leaves #57-66 except #60 (PR #110). #60 (difficulty.live-pressure) stays planned — it is Part of, deferred to slice 10. Produced with `roadmap.py deliver --pr 34` / `--pr 110`. This clears the reconcile drift for those leaves and removes the hazard that a future `apply` would reopen the merged issues. proof and titles are left unchanged (truthful — these were playtested; validation only requires delivered_by on a history leaf). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes #65
Closes #66
Closes #57
Closes #58
Closes #59
Closes #61
Closes #62
Closes #63
Closes #64
Purpose
The first complete enemy, end to end — the Toroid vertical slice — turning the dormant entity/RNG/formation foundations into live combat.
Impact: area 1 now fights back — the first live enemy the player can be killed by and can destroy for score.
Scope
Toroid (AIR-01) plus the eight integration leaves that ride on it — the live dispatch walk, collision, RNG draw, air-hit award, and air-collision death.
toroid_toggle_dirbounce) when it draws level, flaps; culls off any field edge keeping its scroll position.player hit == 1 AND invuln == 0) spends a craft and respawns or ends the game.Change profile — the shape of this pull request at a glance:
src/xevious/project.json, a single generated artifact whose block IDs re-flow on every build).Part of #60(see Out of scope).Impact: the entity/formation/RNG scaffolding built dormant in slices 1–7 becomes a live, playable enemy loop.
Behaviors
The capabilities this change delivers, each with the check that exercises it.
toroid-wave-spawns-and-moves.toroid-swing-reverses-away.blaster-kills-toroid-and-scores.air-shot-hit-column-bounded.craft-collision-is-single-cell.B8-no-tunnel.death-respawn,death-game-over.Out of scope
Everything past the Toroid loop — recorded, deliberate deferrals.
Part of #60, reassigned to slice 10 (mask-consuming families).add_objectflying branch (Torkan/Kapi/Terrazi, slice 10); radiating bullets + Bacura-vs-craft (slice 11).Impact: these are named follow-ups with their own slices, not silent gaps — the Toroid loop is complete on its own.
Risk
Two locked product specs are amended (needs
guardrail-ack), and the collision windows deviate from the reference for playability.guardrail-ack.docs/spec/core-game-systems.md(removes the temporary D/G debug death keys now that live combat is lethal) anddocs/spec/player-craft-and-weapons.md(records the shot-vs-flying hit window and its doubling). The fail-closedproduct-lock-integritycheck names both and blocks merge until the single globalguardrail-acklabel is applied.(16,32,8,16)to(32,64,16,32)— a recorded deviation that (a) prevents collision tunneling (the shot's 2.5-cell/frame step exceeded the 2-cell reference window) and (b) matches the 36-px rendered Toroid. The craft hurtbox is left tight on purpose (forgiving offence, precise defence). Guarded by theB8-no-tunnelinvariant.Impact: the guardrail-weakening is fenced to two named spec edits under your explicit label; the deviations are documented in records 025/026 and bounded by the invariant test.
Validation
Full automated suite green; feel confirmed by the operator playtest.
check()s, mechanics-record and roadmap validators — all green.build_hash 0c7c82db…); build→import round-trip holds.runtime-harness, CodeQL/Analyze,engine-guard,secret-scan, actionlint, overlay-disclosure) pass; the two red checks are the consent gates (engine-ci→guardrail-ack,xevious-project→playtest-approved+ owner playtest comment).Impact: an approver can rely on the logic layer being exercised and deterministic; the on-screen layer is the playtest's, recorded below.
Review
A Standard pre-submission review ran cold (five passes) at
515db05; the operator playtest then caught three defects the review missed, each fixed and re-verified — the merged build differs materially from the reviewed one.Depth: Standard. Passes that ran (plain checks): spec-conformance, an adversarial divergence hunt against the locked specs, technical-integrity, security-governance, and usability, plus a scoped re-audit. Findings were dispositioned: re-anchored an ENGINE-TODO marker; a generate-time formation/slot-capacity assert; a bullet-dispatch structural clause; disclosure of the two interim art stand-ins; stale-comment/estimate fixes. No blocking security/governance defect (the
aiming.jsonextraction is instruction-derived;invulnis test-only with zero writers; D/G/S fully removed).Material change after review — re-verified. Between reviewed
515db05and submitted299dc37, 10 files changed, 5477 insertions / 3698 deletions (net +1779 — the large figure is the regeneratedproject.json; the source/logic change is the swing revert plus two collision fixes plus their tests/docs). The operator playtest (this project's terminal gate for feel, since nothing runs a real VM) drove three fixes the cold review got wrong or could not see: (1) the Toroid swing was flagged inverted by the review and "fixed" to home; the playtest showed the arcade Toroid reverses — reverted and grounded against the pinned disassembly (toroid_toggle_dir), guard flipped totoroid-swing-reverses-away. (2) both collision windows reused one axis-delta reporter across their two bounds, and a Scratch reporter attaches to only one parent, so the second bound stole it — the box degraded to a quadrant/row; rebuilt each delta fresh per compare, added off-target MISS scenarios. (3) the shot tunneled through Toroids (2.5-cell/frame step > 2-cell window); window doubled and guarded byB8-no-tunnel. Each fix re-ran the full suite green. These are validated by the playtest, not by a re-run of the cold review.Spec-derived acceptance steps (from
spec_referent.py review-steps --doc docs/spec/aerial-enemies.md) — only the shared-rules and Toroid paragraphs are live this slice; the other families' steps are for their slices:Things you can confirm yourself
.sb3against this document's descriptionsThings I checked for you
Impact: the engine's account is that the logic conforms and was reviewed; the swing/collision/tunneling corrections rest on the operator playtest — your merge is the binding gate.
Demonstration
Open the delivered
.sb3in Scratch 3 / TurboWarp and play area 1 — the behaviors fail visibly if broken.Impact: the operator can watch every claimed behavior work or fail; the full sweep is
docs/PLAYTEST_CHECKLIST.md.Files of interest
The generator, the two locked specs, the tests, and the four mechanics records.
tools/game_director.py(spawn/aim/swing/cull, both collision windows, the walk) and the regeneratedsrc/xevious/project.json.docs/spec/aerial-enemies.md(settled this slice),docs/spec/core-game-systems.md+docs/spec/player-craft-and-weapons.md(locked amendments —guardrail-ack).tests/test_scratch_project.py(structural contracts,B8-no-tunnel, pinnedbuild_hash),harness/lib/catalog.js(live scenarios).docs/mechanics/023–026-*.md.Impact: the generator and the two locked specs most determine whether this merge is sound.
AI involvement
Claude Code (Opus) authored the slice end to end under the operator's direction and playtest gate.
guardrail-ackandplaytest-approvedlabels and the merge itself.Impact: AI judgment is load-bearing on the reference port and the collision fixes; the operator's playtest and labels are the binding checks over it.
🤖 Generated with Claude Code