Files
siloqy/prod/docs/VIOLET_SPEC__CADENCE_CONTROL_PLANE.md
Codex 77e3eddb40 VIOLET V3b: Cadence Control Plane — universal per-action quantization
Spec prod/docs/VIOLET_SPEC__CADENCE_CONTROL_PLANE.md + cadence.py: every
scan-governed action (entry/sizing/each exit reason/each input plane) carries an
INDEPENDENT, runtime-tunable Q knob surfaced in a control plane (HZ-backed,
code defaults as floor). Evaluate-every-tick / actuate-at-Q; SL defaults insta,
TP/entry default scan, OBF ~1s — all loosenable per-action. 9 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 18:39:12 +02:00

5.7 KiB
Raw Blame History

VIOLET Spec — Cadence Control Plane (per-action quantization)

Status: BINDING for V3b (prod/clean_arch/violet/cadence.py). Authored 2026-06-13 from operator doctrine this session. Companion to the master charter (memory violet_subsecond_rebuild_plan, cadence-quantizer section) and violet_v3_alpha_doctrine (points #6, #8). This spec is the painstaking per-ACTION quantization layer the charter only sketched as a principle.


1. The inversion (why this layer exists)

BLUE's clock is its architecture: every decision/action is denominated in 56 s scans. VIOLET inverts this — the architecture is the event-driven / clockless (fastest-clock) reactor (V0: clock.py mono_ns timebase + DeadlineScheduler). BLUE's scan-quantized behaviour is a guest hosted on that reactor. The scan cadence is a quantization setting, not the architecture.

At first, every action is quantized at Q = scan cadence → bit-faithful BLUE replication (warts and all). Over time each action's Q can be loosened independently toward the reactor's faster clock. This is the certification-preserving path: champion params are 5 s-bar-denominated (BIBLE §22.3), so loosening is a deliberate, measured, per-action promotion — never a global flip.

2. Core rules

  1. Evaluate at fastest cadence; actuate at Q. Every action is evaluated every reactor tick (the would-be action is computed and shadow-logged — this is the evidence trail). The action is only actuated when its quantization boundary Q is crossed. Shadow deltas (would-be-at-fast vs actuated-at-Q) are the data that justifies each loosening step.
  2. Adjustability is UNIVERSAL. EVERY scan-governed activity carries its own tunable Q — entry, sizing, each exit reason (TP, catastrophic SL, ADVSL, v7), AND each input-plane consumption (scan, OBF, ExoF, EsoF, MARAS, ACB). No action is hardcoded at scan. SL merely defaults to a tighter Q; mechanically it is the same adjustable primitive as everything else.
  3. Per-action knobs are INDEPENDENTLY configurable. Changing TP's Q must not touch entry's Q. Each action is its own registry entry.
  4. Knobs are SURFACED IN A CONTROL PLANE. The registry is readable and writable at runtime for live inspection and tuning — not compile-time constants. HZ-backed at runtime (mirroring how BLUE reads DOLPHIN_FEATURES["live_tp_threshold"]); code defaults are the floor/fallback when the control plane is silent.
  5. Loosening is per-reason and measured. Q steps down per action on its own schedule (e.g. 6s→3s→1s→500ms→100ms→50ms), each promotion gated on the shadow deltas from rule (1). SL-class first; TP later (TP at scan has desirable properties).

3. Per-action default Q table (initial state — all loosenable)

Action Class Default Q Loosening intent
Catastrophic SL exit/safety tight VIOLET / insta-exec sub-second from early (the versioned safety deviation)
ADVSL exit/safety tight VIOLET (after min-bars gate) sub-second early
TP (mechanical) exit scan loosen cautiously (desirable at scan)
v7 discretionary exit exit scan as-is first; per-reason later
Entry entry scan cautious (champion params 5s-denominated)
Sizing (conviction) sizing scan cautious (couples to entry)
Scan plane consume input scan (~56s native) n/a (source cadence)
OBF plane consume input ~1s (500ms purported / ~1s effective) toward VIOLET clock — fastest service
ExoF / EsoF / MARAS / ACB consume input scan adjustable too, though sources are orders slower

Exit priority is INVARIANT regardless of Q: CATASTROPHIC/ADVSL > mechanical TP > discretionary (v7). A faster Q never lets a discretionary exit mask a mechanical one (the LINK $1,248 bug).

4. Design (cadence.py)

  • Action — enum/identifier per row of §3 (CATASTROPHIC_SL, ADVSL, TP, V7_EXIT, ENTRY, SIZING, CONSUME_SCAN, CONSUME_OBF, CONSUME_EXF, CONSUME_ESOF, CONSUME_MARAS, CONSUME_ACB).
  • CadenceKnob (V-TYPES StrictModel-style, but mutable via the control plane) — per action: q_ns (actuation quantum; 0 ⇒ every reactor tick = "insta"), evaluate_every_tick: bool (default True), enabled: bool, source: "default"|"control_plane".
  • CadenceControlPlane — the registry: get(action) -> CadenceKnob, set(action, **overrides) (independent per action), snapshot() -> dict (surfaced for inspection), refresh_from(provider) where provider reads the HZ map / env at runtime; code defaults seed it. due(action, now_ns, last_actuation_ns) -> bool (Q-boundary test, integrates with DeadlineScheduler).
  • Evaluate/actuate split helpershould_actuate(action, now_ns) -> bool; callers always evaluate, then consult this to actuate, and emit the shadow-delta telemetry on the gap.

5. Tests (V3b)

  • defaults match §3 table; SL defaults tighter than TP.
  • set on one action leaves all others unchanged (independence).
  • control-plane override beats default; absence falls back to default (floor).
  • due/should_actuate honors Q boundaries (insta Q=0 actuates every tick; scan Q actuates once per scan interval), property-tested with hypothesis.
  • evaluate-always invariant: evaluation count ≥ actuation count for every action.
  • exit-priority invariant unaffected by Q (a fast discretionary Q never preempts a mechanical exit in the ordering).

violet_subsecond_rebuild_plan (charter) · violet_v3_alpha_doctrine #6/#8 · clock.py/DeadlineScheduler (V0 substrate) · decision_engine.py (V3c consumer) · prod/docs/TODO_TP_SCAN_CADENCE_BUGFIX.md (TP-at-scan rationale).