docs(linkedin-studio): cold-review R5 (Grow+Router) — independent kald-review of 6 surfaces -> 29/29 coverage
Final cold-review round: strategy, competitive, monetize, outreach, profile, linkedin. 2 independent cold Opus reviewers (intent + correctness), no cross-feed, every claim tool-grounded; divergences re-grounded by main before registration. Result: verdict MINOR, 0 MAJOR (cleanest batch of the sweep). Resolution integrity PASS across all 6 (2/2 subagent_type, 28/28 routes, 11/11 router-suggested agents, helper-script exports all resolve; 0 under-declared tools; 0 dead executable refs). Findings (all advisory, no REWORK): thought-leader terminology cluster (5 surfaces, 9 instances; profile :79/:101 are correct negative examples, NOT violations); monetize :6 description<->body scope self-contradiction; bare ref-paths in strategy+profile (folds into systemic #3); monetize Audience-Size scorecard +40 vs /25 cap (suggestion). Cold-review sweep COMPLETE: 29/29 coverage (S1 + R2a + R2b + R3 + R4 + R5). v1.0.0 review-blocker lifted. 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:
parent
4109fe7fd0
commit
4fd038ad1d
1 changed files with 258 additions and 0 deletions
258
docs/hardening/review-R5.md
Normal file
258
docs/hardening/review-R5.md
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
---
|
||||
type: cold-review
|
||||
batch: R5
|
||||
journey: "Grow + Router — growth/authority surfaces + the command router (FINAL round)"
|
||||
scope: "FROZEN committed files at HEAD 4109fe7 (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: [strategy, competitive, monetize, outreach, profile, linkedin]
|
||||
reviewers:
|
||||
- "intent-lens (conformance: intent delivery + cross-ref resolution + class predicates + graceful degradation + thought-leadership terminology ban)"
|
||||
- "correctness-lens (internal consistency + bound-vs-canonical + step/phase arithmetic + allowed-tools completeness + dead-ref / executable-path checks)"
|
||||
class: "guided/stateful (strategy·competitive·monetize·outreach·profile — primary artifact produced · subagent targets resolve · graceful degradation) + routing (linkedin — every emitted /linkedin:Y resolves)"
|
||||
status: "COMPLETE — all 6 surfaces reviewed (strategy, competitive, monetize, outreach, profile, linkedin). R5 completes 29/29 cold-review coverage."
|
||||
verdict: MINOR
|
||||
counts: { BLOCKER: 0, MAJOR: 0, MINOR: 3, SUGGESTION: 2 }
|
||||
---
|
||||
|
||||
# Cold review — R5 (Grow + Router) · FINAL round → 29/29 coverage
|
||||
|
||||
Independent post-hoc cold review of the 6 remaining surfaces — the five Grow-journey
|
||||
guided/stateful commands (`strategy`, `competitive`, `monetize`, `outreach`, `profile`) plus the
|
||||
`linkedin` router — on the FROZEN committed files (HEAD `4109fe7`). Mirrors the S1 `review.md` +
|
||||
R2a + R2b + R3 + R4 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. **R5 completes the sweep: 23/29 + 6 = 29/29 cold-review coverage.**
|
||||
|
||||
**Resolution integrity — PASS across all 6 surfaces (the headline R5 result).** Both blind lenses
|
||||
independently confirmed, target-by-target against their own `ls`/`test -f`:
|
||||
- **2/2** `subagent_type: linkedin-studio:X` refs resolve — `strategy-advisor` (`strategy.md:153`),
|
||||
`network-builder` (`outreach.md:171`).
|
||||
- **28/28** unique `/linkedin:Y` route tokens resolve to `commands/Y.md` (router + cross-command
|
||||
suggestions).
|
||||
- **11/11** router-suggested agents (named in `linkedin.md`) resolve to `agents/*.md`.
|
||||
- **2/2** helper-script invocations resolve: `outreach.md`'s `state-updater.mjs --record-outreach`
|
||||
(flags `--date/--track/--partner/--stage/--next/--due` match `state-updater.mjs:394-411`
|
||||
byte-for-byte) and `linkedin.md`'s `queue-manager.mjs` import (`queueUpcoming`/`queueOverdue`/
|
||||
`queueFormatSummary` exist at `queue-manager.mjs:52,94,112`).
|
||||
- **0 under-declared tools** — every body-invoked tool (Task/Read/Write/Edit/Bash/WebSearch/
|
||||
AskUserQuestion) is in the surface's `allowed-tools`; only harmless `Glob`/`Grep` over-declarations.
|
||||
- **0 dead executable Read/Bash targets** — every `references/*`, `${CLAUDE_PLUGIN_ROOT}/skills/…`,
|
||||
and script path on an executable path verified present.
|
||||
|
||||
**No broken invocation, no missing primary artifact, no failing gate, no runtime-breaking
|
||||
contradiction anywhere in R5 → 0 MAJOR, verdict MINOR (advisory, not REWORK).** This is the
|
||||
cleanest batch of the sweep.
|
||||
|
||||
**Independence cross-check — both outcomes recurred (the case for two lenses, again):**
|
||||
1. **Convergence:** both blind lenses independently surfaced the same `monetize.md` description↔body
|
||||
scope mismatch and the same `thought leader` terminology cluster — high confidence these are real.
|
||||
2. **Divergence (re-grounded by main):**
|
||||
- **Terminology severity** — intent-lens called the `thought leader` hits MINOR (it owns the
|
||||
conformity predicate; memory `no-thought-leadership-phrase` makes this a *standing plugin rule*,
|
||||
not a nicety), correctness-lens called them SUGGESTION (no runtime break). **Main ruling:
|
||||
MINOR** — a direct violation of an explicit plugin terminology rule in user-facing strings is a
|
||||
conformity defect; it is not MAJOR (no runtime break).
|
||||
- **`monetize` scope mismatch severity** — intent-lens SUGGESTION ("description under-claims
|
||||
body"), correctness-lens MINOR ("description contradicts its own 0-1K Stage 1"). **Main ruling:
|
||||
MINOR** — it is a genuine self-contradiction about the command's scope, not a mere under-claim.
|
||||
- **Lens-unique:** correctness-lens alone caught the `monetize` Audience-Size scorecard
|
||||
arithmetic; intent-lens alone caught the bare-relative-path robustness gap. Both re-grounded by
|
||||
main below and kept.
|
||||
|
||||
---
|
||||
|
||||
## strategy.md — VERDICT: MINOR
|
||||
|
||||
- **Intent delivered:** yes. Phase auto-detect from state (`:32-44`), phase strategy + delegation
|
||||
to `strategy-advisor` (`:153`), trajectory overlay (`:250-284`), authority building Phase 2+
|
||||
(`:286-419`), stall points (Step 4), 90-day plan (Step 5), metrics (Step 6).
|
||||
- **Resolution:** all resolve — `subagent_type: linkedin-studio:strategy-advisor` (`:153`) →
|
||||
`agents/strategy-advisor.md` ✓; routes `/linkedin:profile` (`:292,:360`) ✓; `Task` declared.
|
||||
- **Class predicate (guided/stateful):** growth-plan artifact produced ✓; subagent resolves ✓;
|
||||
graceful degradation present ✓ (`follower_count` 0/missing handled `:42`; "If no milestone data:
|
||||
Skip this step" `:284`; authority skipped in Phase 0-1 `:290`).
|
||||
- **Arithmetic (correctness-lens, grounded):** 5 phases (0–4) consistent between Step 0.5
|
||||
auto-detect ranges and Step 2 headers; step numbering monotonic (0.5,1,2,3,3.5,3.6,4,5,6), no
|
||||
gaps/dupes. PASS.
|
||||
- **allowed-tools:** declared {Read, Glob, Grep, AskUserQuestion, Task}; under-declared {} ✓;
|
||||
over {Glob, Grep} (harmless).
|
||||
- **Findings:**
|
||||
1. **[MINOR]** `strategy.md:371` "Engaging with other thought leaders" — `thought leader`
|
||||
terminology-ban hit (off-primary checklist label). Part of the cross-cutting cluster.
|
||||
2. **[MINOR]** bare relative paths for all file loads; **0×** `${CLAUDE_PLUGIN_ROOT}` (grounded
|
||||
`grep -c` = 0, vs 1–10× in competitive/monetize/outreach/linkedin) → `Read` resolves against
|
||||
cwd, not plugin root. Has `Glob` in allowed-tools as a fallback so it degrades, not fatal.
|
||||
Folds into systemic finding #3 (bare ref-paths).
|
||||
|
||||
## competitive.md — VERDICT: MINOR
|
||||
|
||||
- **Intent delivered:** yes. Competitor analysis template (Step 2), landscape map (Step 3),
|
||||
gap/opportunity matrix (Step 4), differentiation plan (Step 5), inspired takeaways (Step 6),
|
||||
ethics note.
|
||||
- **Resolution:** fully self-contained — **no** `subagent_type`, **no** `/linkedin:` routes;
|
||||
`allowed-tools` (Read/Glob/WebSearch/AskUserQuestion) correctly omits `Task`. ✓
|
||||
- **Class predicate (guided/stateful):** competitive-analysis artifact produced ✓; no subagents to
|
||||
resolve ✓; graceful degradation ✓ (Step 1 user-input/WebSearch-driven, runs with no state).
|
||||
- **Arithmetic:** Steps 0–6 linear/monotonic; no stated totals to miscount. PASS.
|
||||
- **allowed-tools:** declared {Read, Glob, WebSearch, AskUserQuestion}; under {} ✓; over {Glob}.
|
||||
- **Findings:**
|
||||
1. **[MINOR]** `thought leader(s)` appears **4×** — including the frontmatter `description`
|
||||
(`:4`, **user-facing**, shows in command listings) and the opening promise (`:17`), plus
|
||||
`:31,:34`. **Worst terminology offender of the six.** Conformity defect, no runtime break.
|
||||
|
||||
## monetize.md — VERDICT: MINOR
|
||||
|
||||
- **Intent delivered:** yes. All 8 steps present: scorecard (1), stage strategy (2), lead-magnet
|
||||
blueprint (3), funnel calendar (4), CTA + A/B variants (5), Featured optimization (6), revenue
|
||||
model (7), tracking dashboard (8).
|
||||
- **Resolution:** all resolve — no `subagent_type`; routes `/linkedin:post` + `/linkedin:pipeline`
|
||||
(`:367`) both exist. ✓
|
||||
- **Class predicate (guided/stateful):** monetization-plan artifact produced ✓; no subagents ✓;
|
||||
graceful degradation ✓ ("Stage 1: Visibility (0-1K followers)" `:92` serves brand-new users).
|
||||
- **Gating honesty:** does NOT hard-gate; serves 0-1K. The real state-read gate is the router's
|
||||
soft prepend (`linkedin.md:175`, `<1000` → prepend, continue anyway) — consistent with outreach.
|
||||
- **Findings:**
|
||||
1. **[MINOR]** **description↔body scope self-contradiction** — `monetize.md:6` "Works from 1K+
|
||||
followers" contradicts its own Stage 1 "Visibility (**0-1K** followers, score 0-30)" (`:92`,
|
||||
`:81`) and the router's "they work at any follower count" (`linkedin.md:126`). The body
|
||||
genuinely covers sub-1K; the description misstates scope. Off-primary (a frontmatter string)
|
||||
but user-facing. **Strongest non-terminology R5 finding.** Fix: align `:6` to "any follower
|
||||
count (compounds at 1K+)".
|
||||
2. **[MINOR]** `thought leaders` in the frontmatter `description` (`:4`, user-facing). Part of the
|
||||
cross-cutting cluster.
|
||||
3. **[SUGGESTION]** Audience-Size scorecard arithmetic (`:51-56`): sub-items +5/+10/+15/+5/+5 sum
|
||||
to **+40** against a **`/25`** cap if read additively, whereas the other three categories each
|
||||
sum to exactly 25 (e.g. Engagement Quality 5+5+10+3+2=25). The follower tiers (1K/5K/10K) are
|
||||
clearly intended mutually-exclusive (one tier) but aren't marked as such → a literal additive
|
||||
read overflows. AI-interpreted (not machine-summed) so intent is recoverable; cosmetic, but it
|
||||
feeds the band that selects the stage. Fix: mark the three follower tiers "(pick one)".
|
||||
|
||||
## outreach.md — VERDICT: PASS
|
||||
|
||||
- **Intent delivered:** yes, thoroughly. Two-track (collab + speaking) orchestrator with a
|
||||
Capability Checklist mapping every predecessor function to a step (`:31-62`) + 10 steps + state
|
||||
persistence.
|
||||
- **Resolution:** all resolve — `subagent_type: linkedin-studio:network-builder` (`:171`) ✓;
|
||||
routes `/linkedin:strategy` (`:112`), `/linkedin:firsthour`+`/linkedin:outreach` (`:1078`),
|
||||
`/linkedin:calendar` (`:1097`) all exist ✓; **Bash executable path sound** — Step 8c's
|
||||
`state-updater.mjs --record-outreach` (`:1084-1092`) matches the script's handler
|
||||
(`state-updater.mjs:294,:394-411`) byte-for-byte. ✓
|
||||
- **Class predicate (guided/stateful):** outreach-plan + persisted pipeline produced ✓; subagent +
|
||||
script resolve ✓; graceful degradation ✓ (Step 2a "Not ready: <3 met → build foundation first" +
|
||||
recommend `/linkedin:strategy` `:112`).
|
||||
- **Arithmetic (correctness-lens, grounded):** "12 collab formats" → 12 (`FORMAT 1–12`); "4 talk
|
||||
templates" → A–D; "5 phases" → PHASE 1–5; scorecards 4×/25=/100 and 5×/5=/25 check out; step
|
||||
numbering monotonic. PASS.
|
||||
- **allowed-tools:** declared {Read, Glob, WebSearch, AskUserQuestion, Task, Bash}; under {} ✓;
|
||||
over {Glob}.
|
||||
- **Gating honesty:** "1K+ followers" self-report (`:100,:143`) consistent with router's `~1K` soft
|
||||
gate (`linkedin.md:120,:176`) and monetize's 1K. ✓
|
||||
- **Findings:**
|
||||
1. **[SUGGESTION]** `thought leader` inside a WebSearch query template (`:229`,
|
||||
`"[your niche] linkedin thought leader"`). It is a *search string* targeting how others
|
||||
self-label (intentional — to find such profiles), so the **lowest-priority** instance of the
|
||||
terminology cluster — but the literal string is still in the plugin.
|
||||
|
||||
## profile.md — VERDICT: PASS
|
||||
|
||||
- **Intent delivered:** yes. Relevance-model context (`:20-44`), Profile SEO + per-section keyword
|
||||
targets (`:46-79`), 7-section audit walkthrough (`:82-199`), profile-content alignment check
|
||||
(`:200-212`), prioritized action plan (`:214-231`), alignment test (`:232-238`).
|
||||
- **Resolution:** self-contained — no `subagent_type`, no `/linkedin:` routes; `allowed-tools`
|
||||
Read/AskUserQuestion (tightest frontmatter of the six). ✓
|
||||
- **Class predicate (guided/stateful + topic-relevance-audit):** the topic-relevance audit **is**
|
||||
actually performed (the body *is* that audit) ✓; artifact (audit + action plan) produced ✓;
|
||||
graceful degradation ✓ (every step AskUserQuestion-driven, runs with zero state). Notable
|
||||
verification discipline: explicitly refuses to fabricate a scoring breakdown (`:28,:32-36,:179`).
|
||||
- **Arithmetic:** Sections 1–7 monotonic; profile-field limits (headline 220, About 2,600) are
|
||||
LinkedIn field limits, NOT post hook/length bounds — no canonical contradiction. PASS.
|
||||
- **Terminology — IMPORTANT NON-VIOLATION:** the two `thought leader` hits (`:79,:101`) are
|
||||
**legitimate negative examples** — the command explicitly tells the user to AVOID the phrase
|
||||
(`:79` lists it with "guru"/"ninja" as keyword-wasters; `:101` is a "Weak example"). Both lenses
|
||||
agree; main confirmed by reading both lines. **profile.md models the correct behavior.**
|
||||
- **Findings:** none of defect class.
|
||||
1. **[Note — systemic #3]** bare relative paths; **0×** `${CLAUDE_PLUGIN_ROOT}` and no `Glob`
|
||||
fallback → most-exposed instance of the bare-path robustness item. BUT correctness-lens
|
||||
verified all three referenced files exist (`test -f` OK), so this is a cwd-robustness concern,
|
||||
not a dead ref. Folds into systemic #3; profile.md is otherwise the cleanest surface of R5.
|
||||
|
||||
## linkedin.md (router) — VERDICT: MINOR
|
||||
|
||||
- **Intent delivered:** yes. Status line (`:19-29`), upcoming/overdue posts via queue (`:31-57`),
|
||||
five-journey menu with front-doors (`:59-127`), gating rule (`:122-127`), interactive menu
|
||||
(`:129-146`), direct-routing table (`:156-198`).
|
||||
- **Resolution (routing class):** **all 28 unique route tokens resolve** to `commands/*.md`
|
||||
(verified token-by-token vs `ls commands/`); all 11 suggested agents resolve; `queue-manager.mjs`
|
||||
node call (`:35-42`) uses exports that all exist (`:52,:94,:112`). **The router advertises nothing
|
||||
that doesn't exist.** ✓ Correctly has no `Task` (delegate-only).
|
||||
- **Class predicate (routing):** every route resolves ✓; graceful degradation ✓ (missing state
|
||||
"No LinkedIn state tracked yet" `:28`; empty queue `:57`; follower segment only if
|
||||
`follower_count > 0` `:30`).
|
||||
- **Gating honesty/consistency:** `:175-176` give monetize + outreach the **same** soft state-read
|
||||
gate (`<1000` → prepend, continue anyway); `:122-127` document the soft-gate design honestly
|
||||
("they work at any follower count… competitive is **not** gated"). Consistent with both command
|
||||
bodies. ✓
|
||||
- **Findings:**
|
||||
1. **[MINOR]** `linkedin.md:118` "Competitive analysis of other thought leaders" — `thought
|
||||
leader` terminology-ban hit in the **user-facing** routing-menu table. Part of the cluster.
|
||||
|
||||
---
|
||||
|
||||
## Summary table
|
||||
|
||||
| Surface | Verdict | MAJOR | MINOR | SUGGESTION |
|
||||
|---|---|---|---|---|
|
||||
| strategy.md | MINOR | 0 | 2 | 0 |
|
||||
| competitive.md | MINOR | 0 | 1 | 0 |
|
||||
| monetize.md | MINOR | 0 | 2 | 1 |
|
||||
| outreach.md | PASS | 0 | 0 | 1 |
|
||||
| profile.md | PASS | 0 | 0 | 0 (1 systemic-#3 note) |
|
||||
| linkedin.md | MINOR | 0 | 1 | 0 |
|
||||
| **R5 total** | **MINOR** | **0** | **3 distinct** | **2 distinct** |
|
||||
|
||||
(Per-surface MINOR counts include shared cross-cutting findings; the 3 *distinct* R5 MINOR findings
|
||||
are: the terminology cluster, the monetize scope contradiction, and the bare-path robustness item.)
|
||||
|
||||
## Cross-cutting findings (for the consolidated fix-pass)
|
||||
|
||||
1. **[MINOR · NEW R5 systemic] `thought leader` terminology cluster — 5 surfaces, 9 instances.**
|
||||
competitive `:4`(description, user-facing)/`:17`/`:31`/`:34` · monetize `:4`(description,
|
||||
user-facing) · linkedin `:118`(menu, user-facing) · strategy `:371`(checklist) · outreach
|
||||
`:229`(WebSearch string, lowest priority). **profile `:79,:101` are NON-violations** (correct
|
||||
negative examples — do not "fix" them). Memory `no-thought-leadership-phrase` confirms this is a
|
||||
standing plugin terminology rule. **Recommended fix:** one terminology sweep replacing the
|
||||
user-facing instances first ("thought leaders" → "creators"/"experts"/"voices in your niche"),
|
||||
leaving profile's avoid-list intact and the outreach search-string as lowest priority. No runtime
|
||||
risk — the buzzword gate scopes to post content, not command markdown.
|
||||
|
||||
2. **[MINOR · per-flate] `monetize.md:6` description↔body scope self-contradiction.** "Works from
|
||||
1K+ followers" vs the body's own 0-1K Stage 1 (`:92`) and the router's "any follower count"
|
||||
(`linkedin.md:126`). Fix: align the description to the body's actual sub-1K-onward range.
|
||||
|
||||
3. **[MINOR · folds into existing systemic #3] bare ref-paths — strategy + profile (0×
|
||||
`${CLAUDE_PLUGIN_ROOT}`).** profile most exposed (no `Glob` fallback). Refs verified to exist, so
|
||||
cwd-robustness not a dead ref. Reconcile in the repo-wide path-style pass already scoped by
|
||||
systemic #3 (R3/R4 found the same pattern in batch/pipeline/firsthour/analyze/report).
|
||||
|
||||
4. **[SUGGESTION · per-flate] `monetize.md:51-56` Audience-Size scorecard sums to +40 vs `/25`
|
||||
cap.** Follower tiers intended mutually-exclusive but unmarked. Fix: annotate "(pick one)".
|
||||
|
||||
**R5 adds NO new ★ systemic finding to the existing three** (clipboard, scaffold-band, bare-paths) —
|
||||
the only genuinely new cross-cutting item is the terminology cluster, which is a conformity sweep,
|
||||
not a code-behavior defect.
|
||||
|
||||
## Verification
|
||||
|
||||
- Spot-checks re-grounded by main (this file): `grep -rniE 'thought.?leader'` over the 6 (9 hits,
|
||||
classifications above); `sed -n '1,8p'`/`'92p'`/`'48,64p' monetize.md` (scope + scorecard);
|
||||
`grep -c CLAUDE_PLUGIN_ROOT` per surface (strategy 0, competitive 4, monetize 10, outreach 10,
|
||||
profile 0, linkedin 1).
|
||||
- `bash scripts/test-runner.sh` → see STATE telling (expected 138 passed / 0 failed, floor 123) —
|
||||
unchanged by this review (review is read-only; no command edits).
|
||||
|
||||
## Sweep status after R5
|
||||
|
||||
**29/29 cold-review coverage reached** (S1 `review.md` + R2a + R2b + R3 + R4 + R5). The independent
|
||||
cold-review phase is COMPLETE; the v1.0.0 review blocker is lifted. Remaining v1.0.0 work: the
|
||||
consolidated fix-pass (operator-gated — review FINDS, fix is a separate decision) and the GUI.
|
||||
Loading…
Add table
Add a link
Reference in a new issue