docs(linkedin-studio): cold-review R4 (Measure surfaces) — independent kald-review of 6 surfaces

Independent two-lens cold review of the 6 Measure-journey surfaces (import,
report, analyze, audit, ab-test, measure) on frozen HEAD 69f37ba. Largest
batch + only analytics-class batch; analytics-honesty predicate carried
alongside the standard intent/correctness lenses.

Verdict: REWORK (0 BLOCKER · 1 MAJOR · 4 MINOR · 6 SUGGESTION).
- report.md MAJOR: heatmap report type (:72) routes to a nonexistent "Step 6c";
  real handler is Step 2c (:106) — provably-wrong cross-ref on a primary menu
  branch. Caught by the correctness lens alone (intent lens never traced
  step-jump arithmetic); confirmed by main grounding the step inventory.
- 5 of 6 surfaces ALLOW (measure notably clean — delegate-only enforced by the
  allowed-tools whitelist, not just asserted).

Analytics-class predicate PASSES on all 6: saves framed as manual/count-only/
no-API and never folded into engagementRate; dwell called unmeasurable;
parseOptionalCount (csv-parser.ts:71) + getAnalyticsRoot seam described
accurately wherever quoted; graceful degradation present everywhere.

Independence: 2 convergences (import Step 6a invalid trends flags; ab-test
ER-omits-clicks) + 3 divergences resolved by main grounding in both directions
(intent over-rated import 6a MAJOR->MINOR; correctness uniquely caught report
6c + analyze twin severity scales). Two-lens method earned its keep again.

New R4 finding clusters (operator-gated fix, not done here): sibling
interface/metric drift (import stale trends flags vs report; ab-test ER vs CLI
engagementRate), one true under-declaration (report Step 8b Write). No code
changed; cold review finds only.

Cumulative cold-review coverage: 23/29 (S1 + R2a + R2b + R3 + R4). Remaining:
R5 (Grow+Router, 6 surfaces) -> 29/29. test-runner 138/0 unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012GqEHp4uDiivfrAUjw4BdE
This commit is contained in:
Kjell Tore Guttormsen 2026-06-30 09:58:40 +02:00
commit 4109fe7fd0

293
docs/hardening/review-R4.md Normal file
View file

@ -0,0 +1,293 @@
---
type: cold-review
batch: R4
journey: "Measure — analytics & performance surfaces"
scope: "FROZEN committed files at HEAD 69f37ba (clean tree; post-hardening cold pass)"
method: "2 independent cold Opus reviewers for the round (intent + correctness), each covering all 6 surfaces, no cross-feed; every mechanical claim tool-grounded (anti-fabrication mandate); reviewers carry NO drafting-session context. Divergences re-grounded by main before registration."
surfaces: [import, report, analyze, audit, ab-test, measure]
reviewers:
- "intent-lens (conformance: intent delivery + cross-ref resolution + analytics class predicates + graceful degradation + terminology)"
- "correctness-lens (internal consistency + bound-vs-canonical + step/phase arithmetic + allowed-tools completeness + metric-definition cross-check)"
class: "analytics — extra predicate: graceful degradation present · saves/dwell honesty intact (parseOptionalCount → unknown/never 0; dwell unmeasurable; saves NOT folded into engagementRate; analytics I/O via getAnalyticsRoot seam)"
status: "COMPLETE — all 6 surfaces reviewed (import, report, analyze, audit, ab-test, measure)"
verdict: REWORK
counts: { BLOCKER: 0, MAJOR: 1, MINOR: 4, SUGGESTION: 6 }
---
# Cold review — R4 (Measure · analytics & performance)
Independent post-hoc cold review of the 6 Measure-journey surfaces, on the FROZEN committed files
(HEAD `69f37ba`). Mirrors the S1 `review.md` + R2a + R2b + R3 model (the cold-review method that did **not**
fabricate): read-and-show before assert, every `file:line` tool-confirmed, reviewers carry no
drafting-session context. The per-command interactive gate (`log.md`) already passed these; this pass
adds the **independent** axis that gate never had. This is the largest batch (6 surfaces) and the only
**analytics-class** batch, so the round carries the extra class predicate (graceful degradation +
saves/dwell honesty) alongside the standard intent/correctness lenses.
**Analytics-class predicate — PASSES across all 6 surfaces (the headline R4 result).** Both blind lenses
independently confirmed the honesty contract holds wherever a surface touches the metric: **saves** are
consistently framed as native-only / count-only / ~Sept 2025-onward / no self-serve API / manual-entry
(`report.md:143,:241`; `import.md:30,:138,:148`; matches `cli.ts:144-146` + `csv-parser.ts:71` where
`parseOptionalCount` → blank/non-numeric/negative becomes `undefined` = unknown, never 0) and are **never
folded into `engagementRate`** (`csv-parser.ts:205-208` numerator = reactions+comments+shares+clicks, no
saves); **dwell** is consistently called unmeasurable/internal-to-LinkedIn (`report.md:241`,
`import.md:30`); no surface claims to import or compute either. The `getAnalyticsRoot()` per-user data-dir
seam (`storage.ts`) is described accurately wherever quoted. **No analytics-honesty violation anywhere in
R4.**
**Independence cross-check — both outcomes recurred this batch (the case for two lenses, again):**
1. **Convergence (×2):** both blind lenses independently surfaced (a) `import.md` Step 6a's invalid
`trends` flags (`--period 4w` / `--metric engagement_rate`) and (b) `ab-test.md:236`'s manual
engagement-rate formula excluding clicks. Two real defects, found twice without cross-feed.
2. **Divergence resolved by grounding (×3, in BOTH directions):**
- **intent over-rated, main corrected down** — on `import` the intent-lens flagged the Step 6a CLI block
**MAJOR** (→ REWORK), the correctness-lens flagged the same defect **MINOR** (→ ALLOW, "off-primary,
descriptive"). Main re-grounded `import.md:194-217`: the executable instruction is the **delegation**
(`:200` "Run /linkedin:report"); the bash block (`:207-210`) is import's *description* of report's
internals, not import's own step → latent, errors only if copy-run → **MINOR**, import = ALLOW.
- **correctness uniquely caught, main confirmed** — on `report` the correctness-lens flagged a **MAJOR**
(heatmap branch routes to a nonexistent "Step 6c"); the intent-lens was silent (its lens probes
agent/command cross-refs, not internal step-jump arithmetic). Main grounded the step inventory → no
`6c` exists, real handler is `2c`**MAJOR confirmed**. This is the batch's load-bearing defect.
- **correctness uniquely caught, main confirmed** — on `analyze` the correctness-lens flagged a **MINOR**
(two non-reconciling severity scales); the intent-lens was silent → main grounded `:155-178` vs
`:227-231` → confirmed **MINOR**.
Both lenses earned their keep: intent over-rated one finding (corrected by grounding), correctness
uniquely caught the two structural defects intent's lens never traced.
---
## Connections to existing systemic findings (no NEW ★ cross-cutting this batch)
All connections re-grounded by main against the R4 files:
- **#1 (clipboard `printf '%s'`, R2a, 10 files) — R4 adds nothing.** `grep -nE "printf '%s'|clipboard-helper"`
across all 6 R4 files → NONE. The analytics surfaces do not auto-copy to clipboard (they ingest/report
data, they don't emit post text), so this systemic pattern simply does not reach the Measure journey.
- **#2 (5-component scaffold band-mismatch, R2b, 3 files) — R4 adds nothing.** The length-band tokens
that appear (`analyze.md:201` "1,200-1,500", `:217` "1,500-1,800"; `report.md:331` example impressions;
`ab-test.md:80` test-variable "Short (500) vs standard (1,200-1,800) vs long (2,500+)") are
recovery-protocol guidance / illustrative numbers / a test variable — none is a component scaffold that
sums outside the standard band. No defect.
- **#3 (bare reference paths vs `${CLAUDE_PLUGIN_ROOT}/`, R2b+R3) — R4 connects lightly (lowest impact).**
`analyze.md:22,:23,:93,:259,:260,:261` and `report.md:241` carry bare `references/…` — but **none is
inside an executable `Read`/`cat`** (`grep -nE "(Read|cat) .*references/"` → NONE executable); all are
pointer-list entries or prose mentions, the same lowest-impact class as R3's firsthour bare paths.
Latent parity break worth catching in the same repo-wide `${CLAUDE_PLUGIN_ROOT}/` grep pass; not elevated
to a per-surface finding (neither lens raised it; cosmetic on these surfaces).
**Recurring (SUGGESTION-class, NOT elevated to ★) — `allowed-tools` over-declaration now spans R3+R4.**
Four of six R4 surfaces declare a tool the body never invokes: `import`/`report` (`Glob` — listing done via
Bash `ls`/`find`), `audit` (`Grep` — no grep call). Combined with R3's 3-of-4, the pattern now touches ~7
surfaces. Harmless (over-declaration widens the permission surface but breaks nothing; *under*-declaration
is the real risk and there is one true instance this batch — `report` Step 8b, recorded as MINOR below).
Optional minimal-surface trim; fold into the consolidated fix if touched.
**New R4 cluster (not ★, analytics-specific) — sibling-command interface/metric-definition drift.** Two
of the four MINORs are the same shape: an analytics surface quotes another surface's CLI interface or a
shared metric definition and drifts from the SSOT — `import.md` Step 6a's stale `trends` flags vs
`report.md`'s correct ones, and `ab-test.md:236`'s manual engagement-rate (clicks excluded) vs the CLI's
`engagementRate` (clicks included, `csv-parser.ts:205`). Both are latent (cross-reference paths, not
primary execution) but both are real consistency debt between siblings. Worth a single reconciliation note
in the consolidated fix: pin the canonical `engagementRate` definition + CLI flag vocabulary once, and make
the descriptive blocks point at it rather than restate it.
---
## import.md — VERDICT: ALLOW (0 BLOCKER/MAJOR · 1 MINOR · 1 SUGGESTION)
Class: **analytics (import orchestrator)**. Intent delivered: primary artifact is the structured JSON batch
written by `cli.ts import` (Step 4 invokes it; output surfaced Step 5), then analysis delegated to
`/linkedin:report` (Step 6). Step inventory `1·1b·2·3·4·5·5b·6·6a·6b·7·8` sequential, no gaps; Step 1b/Step 3
option lists each carry a Skip/Cancel disposition. `allowed-tools` (`:10-15` Bash/Read/Glob/Write/AskUserQuestion)
— Bash/Read/Write/AskUserQuestion all invoked. Cross-refs resolve (`report.md`, `setup.md`, `quick-import.mjs`,
`assets/analytics/README.md` all exist; no `subagent_type`). Degradation present (no-CSV, nothing-anywhere,
missing-deps `npm install`, skipped rows on empty-title/unparseable-date matching `csv-parser.ts:187,193`).
saves/dwell honesty intact (`:30,:138,:148`). No "thought leadership".
### MINOR — Step 6a documents report's CLI calls with invalid period + metric, contradicting the real owner (`import.md:200, :206, :207-210`)
- **Verified by main (the intent/correctness severity divergence, re-grounded `:194-217`):** `:207-210`
shows `trends --period 4w --metric impressions` and `--metric engagement_rate` inside a bash fence. The
CLI accepts period `week|month|quarter|all` (`cli.ts:217`, validated → `process.exit(1)` `:219-221`) and
metric `…|engagementRate` camelCase (`cli.ts:202-209`, validated → `process.exit(1)` `:233-234`) — both
`4w` and `engagement_rate` would error. The real owner `report.md:153,:171` uses the correct
`--period month --metric engagementRate`. `:200` "(period: 4w)" and `:206` "Read expertise_areas" also
mis-describe report (it takes no period arg, never reads expertise_areas).
- **Why MINOR not MAJOR (intent-lens rated MAJOR; main grounds down):** the **executable** instruction on
this path is the delegation at `:200` ("Run /linkedin:report") → routes to `report.md`, which is correct.
The bash block (`:207-210`) is import's *narrative description* of report's internals ("`/linkedin:report`
will: … 2. Call `trends`…"), not a step import itself runs. Latent (errors only if a reader copy-runs the
illustrative block) and the primary delegation path is unaffected → MINOR, not MAJOR. Both lenses
converged on the defect's existence; only the severity diverged.
- **disposition:** drop the illustrative bash + the "(period: 4w)"/"expertise_areas" description, or mirror
report's real invocations (`--period month --metric engagementRate`). Fold into the sibling-drift
reconciliation note.
### SUGGESTION — `allowed-tools` over-declares `Glob` (`:13`); directory listing uses Bash `ls`/`find` (`:37,:47`). Both lenses. See Recurring note.
---
## report.md — VERDICT: REWORK (0 BLOCKER · 1 MAJOR · 1 MINOR · 1 SUGGESTION)
Class: **analytics (report orchestrator)**. Intent delivered: produces weekly/monthly/heatmap report JSON
via `cli.ts report`/`heatmap` + a formatted presentation (Step 6) + an analytics-interpreter handoff
(`subagent_type: linkedin-studio:analytics-interpreter` `:308``agents/analytics-interpreter.md` ✓, `Task`
declared `:14`). Trends flags `--period month --metric engagementRate` (`:153,:171,:366`) all valid vs CLI.
Degradation present (no-data, npm install, week-not-found/empty-week/ERR_MODULE_NOT_FOUND `:387-400`).
saves/dwell honesty exemplary (`:143,:241`). No "thought leadership".
### MAJOR — the heatmap report type routes to a nonexistent "Step 6c" (`report.md:72`)
- **Verified by main (correctness-lens caught it; intent-lens silent — lens gap, not contradiction):** the
step inventory (`grep -nE '^### Step|^## Step'`) is `1·1b·2·2b·2c·3·4·5·5b·5c·6·7·8·8b` — **there is no
Step 6c**. `:72` ("If heatmap (option 3): Run the heatmap CLI command and jump to **Step 6c**") points a
reader nowhere. The real heatmap handler is **Step 2c** (`:106`, immediately below the monthly Step 2b),
which itself "jump[s] to Step 7" (`:114`). The two sibling branches are correct (monthly `:71`→2b;
weekly→inline), so heatmap — one of three top-level report types in Step 2 — is the lone misroute.
- **Severity:** a provably-wrong cross-reference on a **primary menu branch** (top-level report-type
selection, not a deep-dive). Recoverable (`:72` also says "Run the heatmap CLI command," and 2c sits
right under 2b, so a capable agent recovers by proximity) — hence MAJOR, not BLOCKER — but it is the
batch's one load-bearing navigation defect.
- **disposition:** retarget `:72` from "Step 6c" to "Step 2c".
### MINOR — Step 8b markdown export under-declares its write tool (`report.md:429-431` vs `:9-15`)
- **Verified by main:** Step 8b (reached via Step 8 option 4, "Export report as markdown file") instructs
"Format the data using this template and **write to file**" / "Save to: …`-report.md`" (`:429-431`).
Frontmatter `allowed-tools` (`:9-15`) = Bash/Read/Glob/AskUserQuestion/Task — **no `Write`**. This is the
one genuine *under*-declaration this batch (the real-risk class). Held at MINOR by two mitigations: the
step is an optional deep-dive (not the primary path), and the declared `Bash` can satisfy the write via a
heredoc/`cat >`. Sibling `ab-test.md:12-19` declares `Write` for the same `.md`-save, so the omission
reads as an oversight/parity break.
- **disposition:** add `Write` to `allowed-tools` (parity with ab-test) or rephrase Step 8b to write via the
declared `Bash`.
### SUGGESTION — `allowed-tools` over-declares `Glob` (`:12`); listing uses Bash `ls` (`:30,:197`). Correctness-lens. See Recurring note.
---
## analyze.md — VERDICT: ALLOW (0 BLOCKER/MAJOR · 1 MINOR · 1 SUGGESTION)
Class: **analytics-adjacent (read-only diagnostic; no CLI)**. Intent delivered: diagnosis + recovery plan
from reference files + AskUserQuestion (Steps Load-Context·1-8). Cross-refs resolve
(`subagent_type: linkedin-studio:analytics-interpreter` `:41` → agent ✓, `Task` declared `:12`;
`/linkedin:profile` `:188``commands/profile.md` ✓). Degradation present (analytics delegation is
conditional `:41` with a self-report fallback; functions with zero data). No saves/dwell claims → nothing to
contradict. No "thought leadership".
### MINOR — two non-reconciling severity scales in one command (`analyze.md:155-178` vs `:227-231`)
- **Verified by main (correctness-lens; intent-lens silent — lens gap):** Step 5 grades reach drop on four
percentage bands (`<25` / `25-50` / `50-75` / `75%+`, `:155-178`). Step 7's timeline table (`:227-231`)
uses three rows on a *different* axis — "Moderate (link/off-topic)", "Moderate (partial reach loss)",
"Severe (sharp reach loss)". The two scales share no common key, so a user holding a Step 5 result (e.g.
"Down 50-75% → algorithmic suppression likely") cannot map it to a Step 7 timeline row. Advisory/usability
inconsistency, low-confidence; nothing breaks.
- **disposition:** cross-label the Step 7 rows to the Step 5 bands, or state explicitly that they are
independent axes.
### SUGGESTION — the `:41` existence check ("If imported analytics data exists `…/analytics/`") implies Glob/Bash, neither declared (`allowed-tools` `:9-13` = Read/AskUserQuestion/Task). Softer than report's Write gap: no explicit tool call is written at `:41` (it's a conditional prose phrase) and the real data access is delegated to `analytics-interpreter` via `Task`. Correctness-lens.
---
## audit.md — VERDICT: ALLOW (0 BLOCKER/MAJOR/MINOR · 1 SUGGESTION)
Class: **analytics-adjacent (read-only strategy auditor; no CLI)**. Intent delivered: audit report (Step 7
template) + action items (Step 8). Steps `0·1·2·3·4·5·5.5·6·7·8` sequential. Routing resolves
(`/linkedin:strategy``commands/strategy.md` ✓, `/linkedin:profile` ✓; no `subagent_type`, `Task`
correctly absent from `allowed-tools`). Degradation present (Step 0 checks for analytics data + asks for
screenshots/metrics; milestone block self-skips with no data `:140`). **Correctness cross-check (both
lenses):** the state fields the milestone block reads — `follower_count`, `monthly_growth`,
`growth_rate_needed` (`:105,:109,:128`) — all exist in `config/state-file.template.md:23,26,28`, so it reads
real fields. No saves/dwell claims. No "thought leadership".
### SUGGESTION — `allowed-tools` over-declares `Grep` (`:11`); Step 0 uses Read/Glob, no grep call in the body. Both lenses (convergence). See Recurring note.
---
## ab-test.md — VERDICT: ALLOW (0 BLOCKER/MAJOR · 1 MINOR · 2 SUGGESTION)
Class: **analytics (experiment manager; manual metric entry, no CLI)**. Intent delivered: primary artifact
is the test-plan markdown written to `analytics/ab-tests/[name].md` (Step 2a.8) + running comparison /
analysis (2b/2c). Step inventory `0·1·2a(.1-.8)·2b·2c·2d·2e·3` consistent; Step 1's 6 intents map to 2a-2e +
option 6 self-handles (`:57`). Post-count arithmetic coherent ("3 per variant / 6 total" `:127`; 6-row
execution table `:155-162`; "X of 6" `:255`). `allowed-tools` (`:12-19`
Read/Glob/Write/Bash/AskUserQuestion/Task) — Read/Write/Bash/AskUserQuestion/Task(→`content-optimizer` `:119`
✓) all invoked. Degradation present (Error Handling: No-Tests-Directory, Incomplete-Data, Missing-Analytics,
Corrupted-files `:472-493`). Statistical honesty notably correct — 2c.4/Confidence-Level (`:311,:320-331`)
explicitly demotes small-sample results to "directional, not significant." No saves/dwell claims. No
"thought leadership".
### MINOR — manual engagement-rate formula excludes clicks, diverging from the canonical `engagementRate` (`ab-test.md:236`)
- **Verified by main (both lenses converged):** `:236` computes ER as
`(reactions + comments + reposts) / impressions * 100` — clicks excluded (and 2b.3 `:228-234` never
collects clicks). The CLI's `engagementRate` includes clicks: `totalEngagement = reactions + comments +
shares + clicks` (`csv-parser.ts:205-208`). Step 2c.3 (`:282-288`) cross-references the A/B numbers against
the CLI weekly reports, where the two rates will not match.
- **Severity:** internally consistent within a single test (same formula on both variants, and A/B is
variant-relative), so the verdict-within-a-test is unaffected → MINOR, latent on the cross-reference path.
- **disposition:** add a one-line "clicks excluded by design" caveat, or align the manual formula to the
canonical definition. Fold into the sibling-drift reconciliation note.
### SUGGESTION — bare agent name in a user-facing suggestion (`ab-test.md:468`): "use the `content-optimizer` agent" surfaces a bare name where the canonical form (correctly used at `:119`) is the namespaced `subagent_type`. Cosmetic. Intent-lens.
### SUGGESTION — `allowed-tools` over-declares `Glob` (`:14`); scans use Bash `ls` (`:37,:209`). 2b.4/2c.5 append/update are edit-shaped but the declared `Write` covers them via full rewrite (no `Edit` gap). Correctness-lens. See Recurring note.
---
## measure.md — VERDICT: ALLOW (0 findings — clean)
Class: **front-door router (delegate-only)**. Intent delivered **and structurally enforced** (both lenses
converged): `allowed-tools` (`:10-13`) = `Glob` + `AskUserQuestion` only — no Bash/Read/Task — so the
command *cannot* run analysis itself; it identifies intent (Step 1, 5 intents `:30-34`) and routes (Step 2
table `:41-47`, one row per intent). All five routes — `/linkedin:import`, `/linkedin:report`,
`/linkedin:analyze`, `/linkedin:audit`, `/linkedin:ab-test` — resolve to existing command files. Degradation
present (Step 0 glob optional, "Do not block on it"; order-note `:49-50` routes to import first when nothing
imported). No dangling branch, no analysis logic to drift, no saves/dwell claims, no "thought leadership".
The thinnest, cleanest surface in the batch — the delegate-only contract is enforced by the tool whitelist,
not just asserted.
---
## Gate decision — R4 COMPLETE (6 surfaces)
| Surface | Verdict | BLOCKER | MAJOR | MINOR | SUGGESTION |
|---|---|---|---|---|---|
| import | ALLOW | 0 | 0 | 1 | 1 |
| report | REWORK | 0 | 1 | 1 | 1 |
| analyze | ALLOW | 0 | 0 | 1 | 1 |
| audit | ALLOW | 0 | 0 | 0 | 1 |
| ab-test | ALLOW | 0 | 0 | 1 | 2 |
| measure | ALLOW | 0 | 0 | 0 | 0 |
| **TOTAL** | **REWORK** | **0** | **1** | **4** | **6** |
**Batch verdict: REWORK** — 1 of 6 surfaces (report) carries **1 MAJOR**: the heatmap report type routes to
a nonexistent "Step 6c" (real handler Step 2c) — a provably-wrong cross-reference on a primary menu branch.
**0 BLOCKER anywhere.** The other five are ALLOW (measure notably clean — its delegate-only contract is
enforced by the `allowed-tools` whitelist, not merely asserted).
**Analytics-class predicate verdict: PASS.** The saves/dwell honesty contract holds on every surface that
touches the metric — saves framed as manual/count-only/no-API and never folded into `engagementRate`, dwell
called unmeasurable, neither claimed as imported; `parseOptionalCount` semantics (`csv-parser.ts:71`) and the
`getAnalyticsRoot` seam described accurately wherever quoted. Graceful degradation present on all six. This
was the batch-specific axis and it is clean.
**Independence verdict:** two convergences (import Step 6a flags; ab-test ER-omits-clicks) + three
divergences resolved by main's grounding in **both directions** — intent over-rated import's Step 6a
(MAJOR→MINOR on grounding that the executable path delegates), while correctness uniquely caught report's
Step 6c misroute (MAJOR) and analyze's twin severity scales (MINOR) that intent's lens never traced. The
two-lens method earned its keep again: had only the intent-lens run, report would have shipped ALLOW with a
broken primary branch; had only the correctness-lens run, import would have over-escalated to REWORK.
**Systemic findings now span R2a+R2b+R3+R4:** clipboard `printf` (R2a, 10 files — **R4 adds none**) ·
component scaffold (R2b, 3 files — **R4 adds none**) · bare reference paths (R2b+R3+R4 — R4 adds 7
lowest-impact pointer/prose sites in analyze/report, not executable). **New this batch:** (a) `allowed-tools`
over-declaration now spans R3+R4 (~7 surfaces, SUGGESTION-class, harmless) with one true *under*-declaration
(report Step 8b `Write`, MINOR); (b) a small **sibling interface/metric-definition drift** cluster (import's
stale `trends` flags + ab-test's clicks-excluded ER) — reconcile once against the CLI SSOT. Cold review
**finds**; it changes no code. Each fix is its own operator-gated decision. Recommended consolidated-fix
order unchanged: (1) clipboard `printf` [R2a, 10 files, highest blast radius], (2) component scaffold [3
files], (3) bare reference paths [grep-driven], then the per-surface items — now including **report Step 6c
misroute (the one R4 MAJOR)**, report Step 8b `Write`, the sibling-drift reconciliation (import 6a +
ab-test ER), analyze severity scales, and the over-declaration trims. Local-only (hardening-class), pushed
per the 2026-06-30 operator delegation (public catalog, no secrets).
**Cumulative cold-review coverage: 23/29** (review.md S1=4 · R2a=5 · R2b=4 · R3=4 · R4=6). Remaining: **R5
(Grow+Router)** — strategy · competitive · monetize · outreach · profile · linkedin (6 surfaces) → 29/29.