Continuity rule: discrete params hold per cue; add DESIGN.md + AGENTS.md

Actors and objects change only at camera cuts. int/bool/discrete
params skip drift, lookahead and reactivity; discrete slowAxis steps
on the section-held journey. Venues fade instead of toggling on
interpolated popMul; roadside density is arrangement-only.

DESIGN.md collects the project's design decisions; AGENTS.md points
agents at it and the build-visualizer loop.
This commit is contained in:
Dejvino
2026-09-20 16:42:44 +02:00
parent 6e70f95d4d
commit a99a7cbe49
15 changed files with 308 additions and 31 deletions
+18 -1
View File
@@ -21,7 +21,7 @@ import { shiftPalette, paletteContrast } from '../look/palette.js';
import { ArcDriver } from '../look/ArcDriver.js';
import { Engine } from '../engine/Engine.js';
import { featureProviderFor } from '../audio/FeatureTrack.js';
import { sampleValues, clampValue, canBackground } from '../params/schema.js';
import { sampleValues, clampValue, canBackground, isDiscreteParam } from '../params/schema.js';
import { Rng } from '../engine/rng.js';
import { frameDistance, frameLuminance } from '../engine/hash.js';
import { SHOT_SIZES, SHOT_SIZE_NAMES, describeFraming } from '../look/framing.js';
@@ -505,6 +505,23 @@ check(11, 'the slow axis is a journey rather than a cycle', () => {
const end = at(t.duration * 0.95);
for (const item of axis) {
// Discrete params step at cuts instead of travelling: held within
// the shot by construction (see schema.js isDiscreteParam), so the
// travel assertion below cannot apply. What is asserted instead is
// the hold itself — two samples inside one cue must agree exactly —
// while the travel magnitude is already covered structurally above.
if (isDiscreteParam(item.def)) {
const t0 = (cue.startFrame + 5) / 60;
const t1 = (cue.endFrame - 5) / 60;
if (t1 > t0) {
const va = at(t0)[item.name], vb = at(t1)[item.name];
if (va !== vb) {
problems.push(`${spec.module.name}.${item.name}: ${va} → ${vb} ` +
`mid-shot — discrete params change only at cuts`);
}
}
continue;
}
const [lo, hi] = item.def.range;
const span = hi - lo;
const a = start[item.name], m = mid[item.name], z = end[item.name];