mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-09-11 03:04:30 +00:00
fix(h3d-carve-15): resolve Creed r1 F1/F2/F3 + camera import + smoke tests
F1: return { update, _prewarmStatic, _prewarmChart } from createRenderer;
screen.js destructures all three (callers at :7377/:7461 were getting undefined).
F2: _applyNoteCamTargets read cameraLockLow/cameraLockZoom as free variables;
replaced with getCameraLockLow() / getCameraLockZoom() getter calls.
F3: add dZ, renderOrderForLayerAtZ to geometry.js import; DI TS, S_BASE,
FRET_LABEL_GOLD_HEX, FRET_LABEL_IDLE_HEX as shorthands from screen.js.
Camera import fix: camera.js only exports createCamera; remove the broken
import of lookaheadBootstrapTime/ComputeFretBounds/TargetWorldX from
camera.js (caused SyntaxError on module load); DI them as shorthands
from screen.js createCamera() destructure at line 6755.
DI count: 177 → 184 (+7 shorthands).
Tests: 6 new execution-readiness guards (17-22) in highway_3d_renderer.test.js,
each RED at 7180eff and GREEN at this tip. Suite 1402/1403 (pre-existing #46).
ESLint gate: Creed F1/F2/F3 names cleared; 160 remaining no-undef identifiers
documented in hive/plans/h3d-cut15-creed-fix.md (categories B-G: deferred
screen.js consts/fn-refs and renderer-internal closure state — carve-15b).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014uZ169yfoFYArXz962g7KW
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
7180eff05d
commit
d475899c5a
@@ -6847,7 +6847,7 @@ import { createRenderer } from './src/renderer.js'; // h3d-carve-15
|
||||
// extracted to src/renderer.js (createRenderer factory).
|
||||
// HONEST GAPS: _prewarmStatic/_prewarmChart need ren.compile() — documented
|
||||
// in renderer.js with ponytail: comments.
|
||||
const { update } = createRenderer({
|
||||
const { update, _prewarmStatic, _prewarmChart } = createRenderer({
|
||||
// ── Consts ─────────────────────────────────────────────────────
|
||||
K, NFRETS, NW, NH, AHEAD, BEHIND, S_GAP,
|
||||
CAM_FOCUS_BLEND_RATE,
|
||||
@@ -6859,6 +6859,7 @@ import { createRenderer } from './src/renderer.js'; // h3d-carve-15
|
||||
INLAY_LABEL_FRETS,
|
||||
GHOST_HOLD_AFTER_ONSET,
|
||||
CHORD_FRAME_RIM_MIN, CHORD_FRAME_RIM_FRAC_H,
|
||||
TS, S_BASE, FRET_LABEL_GOLD_HEX, FRET_LABEL_IDLE_HEX,
|
||||
// ── Fn-refs ─────────────────────────────────────────────────────
|
||||
sY, xFret, xFretMid, fretLabelScaleForFret, pbBeg, pbEnd, pbReportTick,
|
||||
hwyFirstRelevantFrettedTime, _syncOpenStringPitchLabels, txtMat, _setLabelMap,
|
||||
@@ -6866,6 +6867,7 @@ import { createRenderer } from './src/renderer.js'; // h3d-carve-15
|
||||
drawNote, drawArpBrackets, chordHarmonyLabels,
|
||||
// createCamera outputs:
|
||||
camUpdate,
|
||||
lookaheadBootstrapTime, lookaheadComputeFretBounds, lookaheadTargetWorldX,
|
||||
// createArp outputs:
|
||||
chordWireHighDensity, chordTemplateLabel, chordTemplateMarkedArpeggio,
|
||||
chordHandShapeArpeggioHint,
|
||||
|
||||
@@ -4,12 +4,7 @@
|
||||
// VERBATIM-MOVE rule: function bodies moved exactly; only DI rewires applied.
|
||||
// Call-argument fidelity gate: every moved call verified against baseline.
|
||||
|
||||
import { lowerBoundT, camBaseDistU, camLowFretPullbackU } from './geometry.js';
|
||||
import {
|
||||
lookaheadBootstrapTime,
|
||||
lookaheadComputeFretBounds,
|
||||
lookaheadTargetWorldX,
|
||||
} from './camera.js';
|
||||
import { lowerBoundT, camBaseDistU, camLowFretPullbackU, dZ, renderOrderForLayerAtZ } from './geometry.js';
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
export function createRenderer({
|
||||
@@ -24,6 +19,7 @@ export function createRenderer({
|
||||
INLAY_LABEL_FRETS,
|
||||
GHOST_HOLD_AFTER_ONSET,
|
||||
CHORD_FRAME_RIM_MIN, CHORD_FRAME_RIM_FRAC_H,
|
||||
TS, S_BASE, FRET_LABEL_GOLD_HEX, FRET_LABEL_IDLE_HEX,
|
||||
// camAhead, camTau: re-declared as let vars inside update() — not DI
|
||||
// ── Stable fn-refs (shorthand) ────────────────────────────────────────
|
||||
sY, xFret, xFretMid, fretLabelScaleForFret, pbBeg, pbEnd, pbReportTick,
|
||||
@@ -32,6 +28,7 @@ export function createRenderer({
|
||||
drawNote, drawArpBrackets, chordHarmonyLabels,
|
||||
// createCamera outputs:
|
||||
camUpdate,
|
||||
lookaheadBootstrapTime, lookaheadComputeFretBounds, lookaheadTargetWorldX,
|
||||
// arp.js outputs (from createArp destructure in screen.js):
|
||||
chordWireHighDensity, chordTemplateLabel, chordTemplateMarkedArpeggio,
|
||||
chordHandShapeArpeggioHint,
|
||||
@@ -128,7 +125,7 @@ function lookaheadSmoothCamStep(dtSec, tgtXWorld, tgtSpanInt) {
|
||||
// getPrevLockActive() from the returned value).
|
||||
function _applyNoteCamTargets(wX, wSum, distMin, distMax, distGot,
|
||||
camHystF, camDistHystF, skipDistHyst) {
|
||||
const lockActive = cameraLockLow && (!distGot || distMax <= 12);
|
||||
const lockActive = getCameraLockLow() && (!distGot || distMax <= 12);
|
||||
if (lockActive) {
|
||||
// Locked view: frets 0-12 fit in frame, with the peak
|
||||
// low-fret bonus baked in so nut chords stay framed.
|
||||
@@ -141,7 +138,7 @@ function _applyNoteCamTargets(wX, wSum, distMin, distMax, distGot,
|
||||
// and MAX (furthest). Default 0.5 maps to ~1.0× so existing
|
||||
// users see the same locked view as before this slider.
|
||||
const lockZoomMul = CAM_LOCK_ZOOM_MIN +
|
||||
(CAM_LOCK_ZOOM_MAX - CAM_LOCK_ZOOM_MIN) * cameraLockZoom;
|
||||
(CAM_LOCK_ZOOM_MAX - CAM_LOCK_ZOOM_MIN) * getCameraLockZoom();
|
||||
setTgtX(xFretMid(CAM_LOCK_CENTER_FRET));
|
||||
setTgtDist((lockedBaseU + lockedBonusU) * K * lockZoomMul);
|
||||
setPrevLowFretBonus(lockedBonusU);
|
||||
@@ -3616,5 +3613,5 @@ function update(bundle) {
|
||||
pbEnd(0);
|
||||
pbReportTick();
|
||||
}
|
||||
return { update };
|
||||
return { update, _prewarmStatic, _prewarmChart };
|
||||
}
|
||||
|
||||
@@ -42,10 +42,12 @@ test('screen.js imports createRenderer from renderer.js', () => {
|
||||
'screen.js must import createRenderer');
|
||||
});
|
||||
|
||||
test('screen.js wiring block contains expected DI param count (177)', () => {
|
||||
// 177 = 77 getters + 35 setters + 65 shorthands (pinned after r2 phantom/dead-param fixes)
|
||||
// OLD pinned value was 241 (inflated by 44 phantom consts, 2 undefined fn-refs, 16 dead params,
|
||||
// and 2 shadowed locals camAhead/camTau that were re-declared as let inside update()).
|
||||
test('screen.js wiring block contains expected DI param count (184)', () => {
|
||||
// 184 = 77 getters + 35 setters + 72 shorthands
|
||||
// 177→184: +7 Creed r1 F3 fixes: TS, S_BASE, FRET_LABEL_GOLD_HEX, FRET_LABEL_IDLE_HEX,
|
||||
// lookaheadBootstrapTime, lookaheadComputeFretBounds, lookaheadTargetWorldX.
|
||||
// 241→177: removed 44 phantom consts, 2 undefined fn-refs, 16 dead params,
|
||||
// 2 shadowed locals camAhead/camTau.
|
||||
const wiringMatch = screenSrc.match(/createRenderer\(\{([\s\S]*?)\}\)/);
|
||||
assert.ok(wiringMatch, 'screen.js must contain createRenderer({...}) call');
|
||||
const body = wiringMatch[1];
|
||||
@@ -59,7 +61,7 @@ test('screen.js wiring block contains expected DI param count (177)', () => {
|
||||
}, 0);
|
||||
|
||||
const total = getterCount + setterCount + shorthandCount;
|
||||
assert.strictEqual(total, 177,
|
||||
assert.strictEqual(total, 184,
|
||||
`DI param count mismatch: got ${total} (getters=${getterCount}, setters=${setterCount}, shorthands=${shorthandCount})`);
|
||||
});
|
||||
|
||||
@@ -98,9 +100,10 @@ test('screen.js does not contain function update body (per-frame draw loop)', ()
|
||||
|
||||
// ── 3. Renderer exports update ───────────────────────────────────────────────
|
||||
|
||||
test('renderer.js return value exports update function', () => {
|
||||
assert.match(src, /return\s*\{\s*update\s*\}/,
|
||||
'createRenderer must return { update }');
|
||||
test('renderer.js return value exports update, _prewarmStatic, _prewarmChart', () => {
|
||||
// F1 fix: callers need _prewarmStatic/_prewarmChart from the factory return.
|
||||
assert.match(src, /return\s*\{\s*update\s*,\s*_prewarmStatic\s*,\s*_prewarmChart\s*\}/,
|
||||
'createRenderer must return { update, _prewarmStatic, _prewarmChart }');
|
||||
});
|
||||
|
||||
// ── 4. Caller-list corrections (contract §6) ─────────────────────────────────
|
||||
@@ -213,3 +216,93 @@ test('all shorthand identifiers in factory wiring calls are declared in screen.j
|
||||
`This test was RED at 7623ad8 on BEAT_HEAD_SEC (44 phantoms). ` +
|
||||
`Fix: delete undefined names from both the DI signature and wiring call.`);
|
||||
});
|
||||
|
||||
// ── 8. Creed r1 execution-readiness guards (RED at 7180eff, GREEN at fix tip) ─
|
||||
//
|
||||
// Creed r1 review at 7180eff raised THREE HIGH findings — all runtime failures:
|
||||
// F1: _prewarmStatic/_prewarmChart not returned → callers get undefined at
|
||||
// screen.js:7377 and :7461
|
||||
// F2: cameraLockLow/cameraLockZoom free vars in _applyNoteCamTargets → any
|
||||
// fretted note in view triggers ReferenceError (cameraLockLow)
|
||||
// F3: dZ/renderOrderForLayerAtZ not imported from geometry.js; TS/S_BASE/
|
||||
// FRET_LABEL_* not DI'd → chord/beat/lane render paths crash (dZ)
|
||||
// Plus: broken camera.js import (3 names not exported from camera.js) →
|
||||
// module-load SyntaxError prevents renderer.js from loading at all.
|
||||
//
|
||||
// These source-scan guards are RED at 7180eff and GREEN at the fix commit.
|
||||
|
||||
test('F1: renderer.js returns _prewarmStatic and _prewarmChart', () => {
|
||||
// RED at 7180eff: return { update } only — prewarm callers crash with TypeError
|
||||
// GREEN at fix tip: return { update, _prewarmStatic, _prewarmChart }
|
||||
assert.match(src, /_prewarmStatic\s*,\s*_prewarmChart/,
|
||||
'return must include _prewarmStatic and _prewarmChart (F1 fix)');
|
||||
assert.match(src, /return\s*\{[^}]*_prewarmStatic/,
|
||||
'_prewarmStatic must be in return statement');
|
||||
});
|
||||
|
||||
test('F2: _applyNoteCamTargets uses getCameraLockLow() not bare cameraLockLow', () => {
|
||||
// Extract _applyNoteCamTargets body (from function decl to next top-level fn)
|
||||
const fnStart = src.indexOf('function _applyNoteCamTargets(');
|
||||
const fnEnd = src.indexOf('\nfunction ', fnStart + 1);
|
||||
// Strip line comments so identifiers in comments don't trip the checks
|
||||
const fnBody = src.slice(fnStart, fnEnd).replace(/\/\/[^\n]*/g, '');
|
||||
|
||||
// RED at 7180eff: cameraLockLow (free var, line 131); getCameraLockLow() absent
|
||||
assert.doesNotMatch(fnBody, /\bcameraLockLow\b(?!\s*\()/,
|
||||
'_applyNoteCamTargets must not read bare cameraLockLow (F2: use getCameraLockLow())');
|
||||
assert.match(fnBody, /getCameraLockLow\(\)/,
|
||||
'_applyNoteCamTargets must call getCameraLockLow() (F2 fix)');
|
||||
assert.doesNotMatch(fnBody, /\bcameraLockZoom\b(?!\s*\()/,
|
||||
'_applyNoteCamTargets must not read bare cameraLockZoom (F2: use getCameraLockZoom())');
|
||||
assert.match(fnBody, /getCameraLockZoom\(\)/,
|
||||
'_applyNoteCamTargets must call getCameraLockZoom() (F2 fix)');
|
||||
});
|
||||
|
||||
test('F3: renderer.js imports dZ and renderOrderForLayerAtZ from geometry.js', () => {
|
||||
// RED at 7180eff: neither name in geometry.js import — dZ calls crash
|
||||
const importLine = src.match(/import\s*\{[^}]+\}\s*from\s*['"]\.\/geometry\.js['"]/);
|
||||
assert.ok(importLine, 'renderer.js must have a geometry.js import');
|
||||
assert.match(importLine[0], /\bdZ\b/,
|
||||
'geometry.js import must include dZ (F3 fix)');
|
||||
assert.match(importLine[0], /\brenderOrderForLayerAtZ\b/,
|
||||
'geometry.js import must include renderOrderForLayerAtZ (F3 fix)');
|
||||
});
|
||||
|
||||
test('F3: createRenderer DI includes TS, S_BASE, FRET_LABEL_GOLD_HEX, FRET_LABEL_IDLE_HEX', () => {
|
||||
// RED at 7180eff: none of these in DI signature → undefined in hot render paths
|
||||
const diMatch = src.match(/export function createRenderer\(\{([\s\S]*?)\}\s*\)/);
|
||||
assert.ok(diMatch, 'createRenderer DI signature not found');
|
||||
const di = diMatch[1];
|
||||
for (const name of ['TS', 'S_BASE', 'FRET_LABEL_GOLD_HEX', 'FRET_LABEL_IDLE_HEX']) {
|
||||
assert.match(di, new RegExp(`\\b${name}\\b`),
|
||||
`createRenderer DI must include ${name} (F3 fix)`);
|
||||
}
|
||||
});
|
||||
|
||||
test('camera import fix: renderer.js does not import lookahead fns from camera.js', () => {
|
||||
// At 7180eff camera.js only exports createCamera; importing the 3 lookahead names
|
||||
// caused: SyntaxError: does not provide an export named 'lookaheadBootstrapTime'
|
||||
// RED at 7180eff: those names in camera.js import → module-load failure
|
||||
// GREEN at fix tip: removed from camera import, added to DI from screen.js
|
||||
const cameraImport = src.match(/import\s*\{[^}]+\}\s*from\s*['"]\.\/camera\.js['"]/);
|
||||
if (cameraImport) {
|
||||
for (const name of ['lookaheadBootstrapTime', 'lookaheadComputeFretBounds', 'lookaheadTargetWorldX']) {
|
||||
assert.doesNotMatch(cameraImport[0], new RegExp(`\\b${name}\\b`),
|
||||
`renderer.js must not import ${name} from camera.js (not exported — causes module-load SyntaxError)`);
|
||||
}
|
||||
}
|
||||
// Verify the 3 names appear in the DI signature instead
|
||||
const diMatch = src.match(/export function createRenderer\(\{([\s\S]*?)\}\s*\)/);
|
||||
assert.ok(diMatch, 'createRenderer DI not found');
|
||||
const di = diMatch[1];
|
||||
for (const name of ['lookaheadBootstrapTime', 'lookaheadComputeFretBounds', 'lookaheadTargetWorldX']) {
|
||||
assert.match(di, new RegExp(`\\b${name}\\b`),
|
||||
`createRenderer DI must include ${name} (camera import fix — DI'd from screen.js instead)`);
|
||||
}
|
||||
});
|
||||
|
||||
test('F1: screen.js destructures _prewarmStatic and _prewarmChart from createRenderer', () => {
|
||||
// RED at 7180eff: const { update } = createRenderer({...}) — prewarm fns undefined
|
||||
assert.match(screenSrc, /const\s*\{\s*update\s*,\s*_prewarmStatic\s*,\s*_prewarmChart\s*\}/,
|
||||
'screen.js must destructure _prewarmStatic and _prewarmChart from createRenderer return');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user