docs(plan): add Phase Q pre-restructure functional+DSP audit wave (Q-W0)

This commit is contained in:
2026-07-27 14:29:56 -04:00
parent fcca987454
commit bbfb033819
3 changed files with 260 additions and 13 deletions
+82 -7
View File
@@ -454,13 +454,27 @@ L1, L2, L3, L4, L5, L6, and L7 have all landed. **Phase L is complete.**
> changed) — a combinatorial re-resolution, not a linear one. Phase Q is *last* precisely
> because it reshapes the ground every other pillar stands on. Landing it early taxes every
> subsequent phase; landing it last taxes nothing. **The gate is now satisfied — Phase Q
> may begin.**
> may begin, entering at the Q-W0 audit wave** (the structural waves Q-W1+ do not begin until
> Q-W0's triage closes and Daniel signs off — see the Q-W0 sub-gate above).
>
> **M9 disposition — resolved (Daniel, 2026-07-27): abandoned.** M9 is out; it will not be
> reactivated. The gate remains satisfied; no re-arm condition applies.
>
> **PRE-RESTRUCTURE AUDIT WAVE (Q-W0 — added 2026-07-27, Daniel's ask; runs FIRST).** Before any
> structural point (Q-W1+) begins, Phase Q now opens with a **functional + DSP quality audit**
> (`Q-W0`) — a thorough static analysis of the code from a *functional-correctness* and
> *algorithm-quality* point of view, complementary to (not a repeat of) the grep-verified
> SOLID/naming audit that already grounds Q-W1..Q-W6. Q-W0 hunts DSP smells (close eye on the pitch
> engine), reinvented wheels, duplicate code, poor-quality algorithms, leaky pure/shell boundaries,
> and domain-modeling smells around env-coupled constants; it produces a written, triaged findings
> report. **The gate to begin Q-W1 is that Q-W0's triage is complete and Daniel has signed off on
> each finding's disposition** (fix-now vs. document-and-defer). Q-W0's findings may add or reshape
> downstream Q-W1..Q-W6 points; fixes that Q-W0 classifies fix-now are remediated in Q-W0 (or folded
> into the wave that already touches the file), **not** deferred silently into the structural waves.
>
> **Settled (Q-1, this-doc):** the phase is **`Q` (Quality)**; point-id family `Q1..Qn`, wave
> prefixes `Q-W1..Q-W6`. **Recommended, Daniel's to call (Q-2..Q-9, see
> prefixes `Q-W0` (the pre-restructure audit) then `Q-W1..Q-W6` (the structural reorg).
> **Recommended, Daniel's to call (Q-2..Q-9, see
> `docs/product/code-organization.md` §6):** Q-2 JSON extraction in scope + first (rec: yes);
> Q-3 directory shape `core/`/`shell/`/`app/` top-split with subsystem dirs beneath (rec: this
> over pure-Vital subsystem-first — it makes the pure/shell invariant *structural*); Q-4
@@ -500,6 +514,56 @@ L1, L2, L3, L4, L5, L6, and L7 have all landed. **Phase L is complete.**
> or it isn't. **Green-CTest-at-every-point is an acceptance criterion.** Big-bang is rejected;
> the reorg is risk-ordered waves (W1 safe opener → W2W5 god-module splits → W6 OCP finish).
## Q-W0 — pre-restructure functional + DSP quality audit (runs FIRST; gates Q-W1)
**Goal:** Before a single structural point moves, perform a **thorough static/functional audit** of
the codebase and produce a **written, triaged findings report**. This is the *functional-correctness
and algorithm-quality* complement to the grep-verified SOLID/naming audit that already grounds
Q-W1..Q-W6 (§2/§2b of `docs/product/code-organization.md`) — it goes deeper on *does the code do the
right thing well*, not *where does the responsibility live*. It hunts, across the whole `src/` tree:
duplicate code, reinvented wheels, poor-quality algorithms (**close eye on the pitch engine**),
numerical-robustness and artifact hazards in the DSP paths, leaky pure/shell boundaries, and
**domain-modeling smells around env-coupled constants** (values stored in a frame/rate/DPI/tick-coupled
domain that should be stored rate-free and resolved at use). Every finding is **classified for
disposition**: *eliminate-before-restructure* (fix-now) vs. *document-and-defer* (with rationale).
Nothing structural (Q-W1+) begins until this wave closes and Daniel signs off on the disposition of
every finding. CONTEXT.md §Phase Q (Q-W0 audit scope + triage). See
`docs/product/code-organization.md` §2c.
**Verify:** A findings report exists and is complete over the named audit surfaces (DSP/audio incl.
pitch; architecture smells; env-coupled-constant domain-modeling smells). **Every finding is
triaged** (fix-now vs. documented-and-deferred, each with a one-line rationale). Fix-now findings are
either remediated in this wave or explicitly assigned to the downstream wave that already touches the
file (recorded per finding); no fix-now finding is left implicit. Any behavior-changing remediation
lands with its module's CTest executable green and (where a DSP path changes audibly) a stated
before/after listening or null check. **The gate to Q-W1 is: triage complete + Daniel signed off.**
**Depends on:** the GATE (tree quiescent). Precedes every other Q wave — Q-W1 depends on Q-W0.
- [ ] **DSP / audio audit — close eye on pitch.** Assess *algorithm quality* (correctness,
artifacts, numerical robustness, interpolation quality, reinvented-wheel vs. established DSP
technique) across: `src/vst/pitch_shift` (hand-rolled OLA pitch-preserve — window/overlap choice,
phase handling, transient/formant behavior, buffer edges), `sampler_core` (repitch ratio math,
interpolation order/quality, loop-point crossfade, voice-stealing correctness/click behavior),
`peaks` (envelope min/max binning), `wav_trim` (decay-scan threshold + truncate plan), and the
capture/tail paths.
- [ ] **Architecture-smell audit.** Duplicate code, reinvented wheels, poor abstractions, and any
leaky pure/shell boundary (a `core/` module reaching a REAPER/host type, or geometry/algorithm
math living untestable in a shell). Cross-check against — but do not merely restate — the §2/§2b
SOLID/naming findings; Q-W0's contribution is the *functional* smells those audits didn't target.
- [ ] **Env-coupled-constant domain-modeling audit (explicit smell category).** Flag ANY value
stored in a frame/rate/DPI/tick-coupled domain that should be stored **rate-free and resolved at
the point of use** — per the load-bearing invariant that wall-clock times are rate-free SECONDS
resolved against the live project rate (`sample_map`), with NO hardcoded sample rates in `src/`.
Treat this as **domain-modeling** (store rate-free, resolve at use), **not** "rescale by rate."
There was a prior incident here — envelope times stored in the frame domain — so this is a
first-class category, not a footnote. Sweep envelope times, loop points, fade lengths, tail
lengths, and any UI geometry constant that silently assumes a DPI/rate.
- [ ] **Triage + report.** Write the findings report; classify each finding fix-now vs.
document-and-defer with a one-line rationale; for each fix-now, note whether it is remediated in
Q-W0 or assigned to the downstream wave that already opens the file. Deferred findings carry a
documented rationale so they are a decision, not an omission.
- [ ] **Sign-off gate.** Daniel reviews the triage and signs off on each disposition. Q-W1 does not
begin until this is done; fold any new/reshaped downstream points the audit surfaces into
Q-W1..Q-W6 before starting them.
## Q-W1 — safe opener: extract `core/json` + impose the directory/namespace layout on clean modules
**Goal:** The zero-god-module-risk opener. Two moves: (1) extract a pure **`core/json`** module
(parser + serializer) and **delete the four hand-rolled `Parser`s** in `bank_model` /
@@ -515,7 +579,8 @@ surgery. CONTEXT.md §Phase Q (json extraction; directory + namespace map).
compiles and its test executable passes unmoved. `Sample` (model) vs `AudioSample` (audio) vs
unified `Parser` (json) do not collide once sub-namespaced. No REAPER type crosses into any
`core/` file; the CMake pure/shell enforcement still holds.
**Depends on:** the GATE (tree quiescent). Nothing else in Phase Q.
**Depends on:** the GATE (tree quiescent) **and Q-W0 closed** (audit triaged + Daniel signed off;
any fix-now findings the audit assigned to Q-W1 folded in). First structural wave.
- [ ] Extract `core/json` (pure parser + serializer: parseString/parseInt/parseKey/skipValue +
escape, plus emit helpers); unify under `reasampler::json`; guard the `Parser` name against
@@ -663,17 +728,27 @@ GATE: Phase S + Phase L L3 merged to dev (D2 complete, M9 abandoned) — tree qu
("when Phase S and L3 are finished" — L1/L2/L3/L4L7 all landed — GATE SATISFIED)
Q-W0 (pre-restructure functional + DSP quality audit — findings report + triage)
│ ── SUB-GATE: triage complete + Daniel signed off on every disposition ──
▼ (fix-now findings remediated/assigned; downstream Q-W1..W6 reshaped as needed)
Q-W1 (safe opener: core/json extract + directory/namespace layout on clean modules)
├─► Q-W2 (split bank_panel) ──► Q-W4 (split actions + dedupe bank verbs vs panel_bank_ops)
├─► Q-W3 (split main.cpp; hoist orchestration) ──► Q-W6 (OCP registration-table + I splits)
└─► Q-W5 (split persist; isolate prune_fs) [best after Q-W4]
```
W1 is the safe, high-leverage opener (all later waves assume the layout it establishes). The four
god-module splits (W2W5) are risk-ordered and mostly parallel-safe; W4 depends on W2's
`panel_bank_ops`, W6 depends on W3's isolated registration code. Big-bang is rejected — every wave
is independently landable and CTest-green.
Q-W0 is the **entry point** — the functional/DSP audit runs FIRST and gates Q-W1 (no structural
point begins until its triage closes and Daniel signs off). W1 is then the safe, high-leverage
structural opener (all later waves assume the layout it establishes). The four god-module splits
(W2W5) are risk-ordered and mostly parallel-safe; W4 depends on W2's `panel_bank_ops`, W6 depends
on W3's isolated registration code. Big-bang is rejected — every wave is independently landable and
CTest-green.
## Phase Q — must-verify-before-build
- **Q-W0 closed before any structural point** — the functional/DSP audit's findings report exists,
every finding is triaged (fix-now vs. document-and-defer, each with rationale), fix-now findings
are remediated or assigned to the wave that opens their file, and **Daniel has signed off on every
disposition.** Q-W1 does not begin otherwise. (CONTEXT.md §Phase Q Q-W0; naming/DSP smell
categories §2c of `docs/product/code-organization.md`.)
- **Hot-path call/inline shape** — before landing each split, confirm no virtual dispatch and no
header→TU indirection was added on `peaks` envelope compute, audition/preview, or the realtime
tick. `computeEnvelope` stays a free function on `const std::vector<float>&`;