Docs: 07-21 G6+G4 build spec + session log (H); guidelines shipped-notes; CLAUDE.md tick-source clause; validation-harness fixture notes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 12:35:29 -07:00
parent c5f73c52dd
commit a5302a7eae
5 changed files with 240 additions and 2 deletions
@@ -0,0 +1,86 @@
# 2026-07-21 (H) — G6 socket honesty + G4 saturation budget (the no-eyes queue)
**Operator: "do the next few things that don't require eyes."** Skipped the finisher-reach ×1.39 eyes-on and the
player hurt flinch (both operator-visual), ran the two autonomous items as one Feature-track pass:
**G6** (SpecialSlam/Cone damage-at-contact + the zone fill telegraph) and **G4** (the co-op saturation budget)
from [[Combat_Attack_Feel_Guidelines]]. Design → [[Socket_Honesty_Saturation_Build_Spec]] (the durable spec).
## Reviews (the sandwich)
- **Pre-code** `wf_98bf1268-51b`: 3 lenses → 14 deduped findings → per-finding refutation critics: **13
confirmed / 1 refuted**, all folded in. Two catches were SHIPPED bugs beyond this slice's scope:
the **melee death-strand** (an armed `MeleeCleavePending` survives death — `PlayerDeathStateSystem` cleared
`MeleeCombo` but not the pending — and fires the cleave from the RESPAWN ring) and the **release-build cue
dishonesty** (the client TuningConfig singleton is editor-only; player builds read `default(TuningConfig)`
contact knobs 0 → melee connect cues ~0.35 s before server damage). Both fixed in this pass.
- **First run's critics all died on the session quota and returned a CLEAN-LOOKING empty result** — the
[[workflow-agent-quota-failures-look-clean]] trap, caught by the failures list; resumed after reset with
`resumeFromRunId` (lenses replayed from cache). ALSO: my dedup key truncated at 120 chars and the plan's long
temp path swallowed 6 distinct findings — recovered from the journal; key fixed (basename + 160) in the
post-impl script.
- **Post-impl** `wf_9757d214-b91`: lenses done (11 deduped findings); critics hit the quota again — resumed
after the 10am reset (see the addendum below for verdicts). Two findings pre-verified by inspection + fixed
immediately: the **base** class-swap path (`ClassSelectReceiveSystem`) lacked the pending clear (dev SetClass
parity), and `ZoneAuthoring`'s doc still said "no hand-written [GhostField]".
## What shipped (14 modified + 6 new files; detail in the build spec)
1. **Cone damage-at-contact**: `ConeContactPending` (server-only, baked zeroed) + knob 32 `ConeContactTicks`
(default 21, 0 = legacy; Count 33; DebugTuningReport +1 = dev-protocol bump) + the schedule/early-flush/
re-validate/consume machinery in `AbilityFireSystem` (one shared `FireCone`). Death + BOTH class-swap paths
drop an armed pending; the melee pending got the same death-clear.
2. **Zone fill telegraph**: `[GhostField]` on `ZoneEffect.CasterNetworkId/Radius/NextTick` (ghost-hash churn;
DamagePerPulse/ExpireTick stay server-only); `PulsePeriodTicks` hoisted shared; new `ZoneTelegraphSystem`
(Geyser-templated latch + arm-guard, `BuildRing` rim = TRUE radius, fill arrival = the damage moment,
**evaluated on `InterpolationTick`** — the zone's observables are interpolated; predicted tick would pin the
fill wrong by ~RTT), mine warm/teal vs ally dim-blue tint.
3. **Cone cue honesty**: `TickWindowMath.FireStartRaw` (single-sourced), contact latched once at the fire edge
(C14), arc reveal ends at contact (C13), `NearestEnemyInCone` shared by 3 call sites, and the
`TuningConfig.Defaults()` fallback at every client read site (the release-build fix).
4. **G4 saturation budget**: `SaturationMath.AllyScale` (Client, HudVisualMath precedent) + FeelConfig
`AllyFxDegradeStart/Full/Floor` (8/16/0.35); degrade set = genuinely ally-attributed FX only (remote arc
BRIGHTNESS — life stays contact-honest — + remote shakes); enemy telegraphs structurally exempt;
`CombatStressDebug.StressAllyFx` (Debug family + SubsystemRegistration reset — NOT FeelConfig, profiles would
capture it) + DebugOverlay `- Saturation (G4) -` rows (Spawn 12 Drowners via DebugOp 14; the stress toggle).
## Validation
- **L1** console clean throughout (edits, bake, Play session).
- **L2 427/427** EditMode (13 new: 5 cone-schedule incl. death-clear + socket-swap drop; 3 FireStartRaw;
5 SaturationMath; knob 32 auto-covered). New fixture lesson: **`NetworkTime.Flags` is internal** — the cone
tests set `IsFirstTimeFullyPredictingTick` via a boxed-reflection write (recorded in validation-harness.md).
- **Live server proof** (guardian sampling): pending stamped tick 9101 → resolve 9122; dummy HP 340 held through
9121, **340→318 exactly across the 9122 boundary, pending consumed atomically**, under real ~4-tick batching.
Zone GhostFields verified on the LIVE client (`caster=1 radius=2.5 next=<stamp>`; `DamagePerPulse` correctly
absent) + the vortex pulse drain (400→340) + `~ZoneTelegraphFX` drawing.
- **L3** screenshot: the teal local-caster rim at the true radius + the new overlay rows.
## Surfaced along the way
- **No current frame loadout sockets `WarriorCone`** (Bathynaut = Vortex/Blink/HookPull/LightZone; Harpooner =
HookPull/Blink/DecoyWisp/LightZone) — the Cone/SpecialSlam archetype is **dormant in-game** until a loadout
carries it. The honesty fix is in place for whenever it returns; the live proof injected the spark directly.
Worth an operator call: give a frame the slam back, or park the archetype until a Spark needs it.
## Post-impl review addendum (critics resumed after the 10am reset)
`wf_9757d214-b91` final: **5 confirmed / 6 refuted / 0 failures** (all confirmed = low). All five fixed same-session:
1. **Saturation census counted corpses** (Dying is server-only; dead ghosts linger ~1 s in the FX cache) → count
only `Hp > 0` entries.
2. **Solo play degraded the local player's own hit shake** (the health-drop shake for enemy victims rode the
ally scale with no co-op gate) → `_remotePlayersQuery` census: 0 remote players ⇒ `_allyFxScale = 1`.
3. **The client connect-cue latches survived local death** (server dropped the damage; the corpse still played
the full connect package at the contact tick) → the death branch zeroes `_pendingConnectTick` +
`_pendingConeConnectTick` — fixes the pre-existing melee variant too. (Two lenses found this independently.)
4. **Base class-swap path lacked the pending clear** (`ClassSelectReceiveSystem` — only the dev SetClass op got
it; the DR-046 "cannot drift" coupling drifted) → parity clear added (pre-verified by inspection while the
critics waited on quota).
5. **Two contracts unpinned**: the no-pending-slot fallback + live-steer-at-contact → two new tests
(`Cone_Missing_Pending_Slot_Falls_Back_To_Immediate`, `Cone_Resolves_With_The_Aim_At_Contact_Not_Cast`).
Plus the `ZoneAuthoring` doc-drift fix ("no hand-written [GhostField]" was no longer true). Suite after fixes:
**429/429 green.** Refuted (correctly): the InterpolationTick rim-flash concern, the two-cone-sockets case, the
FeelProfileService int round-trip, the FireStartRaw-consumer concern, and the remote-arc life scaling.
**Next:** the two eyes-on items (finisher reach ×1.39 · player hurt flinch additive layer) + the G6 remainder
that needs a designer eye (per-Spark G1 time signatures) + the operator fork: no frame loadout sockets a Cone
spark — re-socket the slam or park the archetype.