Closes the 2 grep/Read-verified findings from the S12 cold full-brief re-review (docs/remediation/review.md, WARN 0/1/1/0, 0 dropped) and closes the $-injection CLASS — not the line — across the whole state-updater.mjs mutation surface. See docs/remediation/review.md (S13 ALLOW, 0/0/0/0) for the full closure record: replaceField -> replacement function; the 3 additive-insert sites -> functions (m === $1, behavior-preserving); a scalar assert.match pins last_post_topic; and a behavioral, coverage-complete, self-testing Section 12 guard (check-replace-safety.mjs) that is mutation-proven. Docs three-doc + residuals updated. test-runner.sh 71/0/0, node --test 98/98.
166 lines
9.6 KiB
Markdown
166 lines
9.6 KiB
Markdown
---
|
||
type: trekreview
|
||
review_version: "1.0"
|
||
task: "Remediate linkedin-studio from the baseline audit — correctness, honesty, generalization, and the highest-leverage 2026 coverage gaps (full Phase 0–3 roadmap, phased)"
|
||
slug: remediation
|
||
project_dir: docs/remediation/
|
||
brief_path: docs/remediation/brief.md
|
||
scope_sha_start: c5b4c58f4f390aca83c8937880c5fd0bcc983e44
|
||
scope_sha_end: 36f79dd702b9315a0cd9100c3a8dd6dd81b3797f
|
||
reviewed_files_count: 50
|
||
verdict: ALLOW
|
||
mode: default
|
||
effort: high
|
||
profile: premium
|
||
findings: []
|
||
---
|
||
|
||
# Review — linkedin-studio audit-remediation (S13 re-review: `$`-class closure + scalar-test fix)
|
||
|
||
## Executive Summary
|
||
|
||
**Verdict: ALLOW** — 0 BLOCKER, 0 MAJOR, 0 MINOR, 0 SUGGESTION.
|
||
|
||
This is the **S13 re-review** — the **seventh** full-brief sweep
|
||
(`c5b4c58..36f79dd` + the uncommitted S13 working-tree delta), run COLD and
|
||
high-effort. S13 was commissioned to close the two findings the S12 re-review
|
||
left open (verdict WARN, 0/1/1/0): the MAJOR `MISSING_TEST` (the S12 `$`-bearing
|
||
test asserted the Recent Posts section but never the `last_post_topic` scalar, so
|
||
the corruption shipped green) and the MINOR `MISSING_ERROR_HANDLING` (the
|
||
`last_post_topic` scalar was still `$`-unsafe because `replaceField` used a
|
||
replacement *string* for untrusted content). Two independent reviewers
|
||
(brief-conformance, code-correctness) ran without cross-feeding; the coordinator
|
||
applied bounded dedup + the HubSpot Judge filters + verdict (high-effort →
|
||
Cloudflare reasonableness filter skipped; the operator weighs borderline findings).
|
||
**Both reviewers returned empty finding sets.**
|
||
|
||
**Both S12 findings are CLOSED at the reviewed (uncommitted) state:**
|
||
- `replaceField` (`hooks/scripts/state-updater.mjs:14-24`) now uses a replacement
|
||
**function** (`() => \`${field}: ${value}\``), so the untrusted `last_post_topic`
|
||
at the `:64`-equivalent call site is inserted verbatim — no `$&`/`$1`/`` $` ``
|
||
expansion. The MINOR is closed.
|
||
- The existing `$`-bearing test (`hooks/scripts/__tests__/state-updater.test.mjs`)
|
||
now carries `assert.match(result.content, /^last_post_topic: "\$100 budget — \$&
|
||
and \$1 rule"$/m, …)`, distinct from the section-entry `includes()` it already
|
||
had. This assertion **fails on the old string-`replaceField` and passes on the
|
||
function form** (orchestrator-verified by reverting the fix: the test went
|
||
40 pass / 1 fail). The false-green MAJOR is closed.
|
||
|
||
**The class — not just the line — is closed.** The recurring S9→S12 lesson is
|
||
"close the class, not the line"; the class here is "untrusted user content reaching
|
||
ANY `String.replace` replacement *string*". Beyond the `replaceField` scalar, S13
|
||
also converted the three remaining additive-insert sites (`recordFirstHourPlan`
|
||
`:246`-equiv; `recordOutreachContact` `:305/:308`-equiv) from a string replacement
|
||
carrying an intentional `$1` backref + interpolated date to a replacement function
|
||
(`(m) => \`${m}\n…\``). The code-correctness reviewer verified rigorously that this
|
||
is **behavior-preserving**: each regex's capture group spans the *entire* match (the
|
||
only chars outside the group are the zero-width `^`/`$` anchors), so the full match
|
||
`m` is character-identical to the old `$1`. After S13, **every `.replace()` in
|
||
`state-updater.mjs` uses a replacement function or a `$`-free literal** — the class
|
||
is closed by construction, not by per-line patch.
|
||
|
||
**A structural guard replaces the per-line proof.** New
|
||
`scripts/check-replace-safety.mjs` (wired as `test-runner.sh` Section 12) proves the
|
||
property behaviorally: it drives every exported mutator with an adversarial payload
|
||
of every special replacement token (`$&`, `` $` ``, `$'`, `$$`, `$n`) in every
|
||
free-text *and* date field and asserts the payload survives verbatim. Two structural
|
||
backstops run on every invocation — **coverage-completeness** (a newly-exported
|
||
mutator without `$`-coverage fails the guard) and a **non-vacuity self-test** (a
|
||
naive string-replace MUST corrupt the payload and a function MUST preserve it, else a
|
||
PASS is meaningless), mirroring the Section 8/10/11 self-tests. The orchestrator
|
||
mutation-proved it end-to-end: reverting `replaceField` to a string makes the guard
|
||
exit 1 with two findings; restoring it returns exit 0.
|
||
|
||
**No Phase-0–3 Success Criterion regressed.** The brief-conformance reviewer traced
|
||
each S13 clause to delivered code and confirmed the counts (19 agents / 27 commands /
|
||
25 references / 6 skills), the version (4.0.0), the single-source algorithm-signal,
|
||
the model-consistency guard, and the render-chain-propagation guard all still hold;
|
||
S13 touched no command/agent/reference file. The two Non-Goals the brief amendment
|
||
re-opens (the command invocation surface for S14; saves manual-entry for S16) trace
|
||
to **explicit operator decisions** in the brief amendment, and S13 itself did not
|
||
touch either surface — no `SCOPE_CREEP_BUILT`.
|
||
|
||
**Push decision: ALLOW.** The two S12 findings are closed, the class is closed
|
||
structurally, the lint is non-vacuous and mutation-proven, all suites are green
|
||
(`scripts/test-runner.sh` → 71/0/0; `node --test` → 98/98), and no SC regressed. The
|
||
ORIGINAL remediation brief now closes clean. Per `feedback_trekreview_always_last` +
|
||
Handover 6, this review is the gate; with ALLOW, S13 may push.
|
||
|
||
## Coverage
|
||
|
||
Scope SHA range: `c5b4c58` (= `origin/main`, parent of remediation Steg 1) →
|
||
`36f79dd` (HEAD, the S12 commit) **plus the uncommitted S13 working-tree delta**
|
||
(annotated `[uncommitted]` — a brief-level contract; the brief's Assumptions allow
|
||
uncommitted review). The committed range (47 files) was already deep-reviewed and
|
||
cleared at S12 except the 2 WARN findings; the active S13 delta is the 9 working-tree
|
||
files below. **No silent skips.**
|
||
|
||
| Treatment | Count | Notes |
|
||
|-----------|-------|-------|
|
||
| `deep-review` (hooks/** + the new guard) | 4 | `state-updater.mjs`, `state-updater.test.mjs` `[uncommitted]`; `scripts/check-replace-safety.mjs` `[uncommitted, new]`; `scripts/test-runner.sh` `[uncommitted]` |
|
||
| `summary-only` | 46 | the committed `c5b4c58..36f79dd` range (already cleared at S12) + the S13 doc edits `CLAUDE.md`/`README.md`/`docs/integration-test-guide.md` `[uncommitted]` + `docs/remediation/{brief.md (amendment), finish-plan.md}` `[uncommitted]` |
|
||
| `skip` | 0 | no lockfiles / svg / generated / dist |
|
||
|
||
**Cross-cutting execution criteria (run by orchestrator):**
|
||
`scripts/test-runner.sh` → 71 passed / 0 failed / 0 warnings, exit 0 (was 70;
|
||
+1 — Section 12 `$`-safety guard).
|
||
`node --test hooks/scripts/__tests__/*.test.mjs` → 98 tests, 98 pass, 0 fail (the
|
||
S13 scalar assertion was added to an existing test, not a new test).
|
||
`node scripts/check-replace-safety.mjs` → exit 0 (8 adversarial cases / 5 mutators,
|
||
coverage-complete, self-test non-vacuous); mutation-proven (reverting the fix → exit 1).
|
||
|
||
**S12 findings — both confirmed CLOSED:**
|
||
`replaceField` (`state-updater.mjs:14-24`) → replacement function; the `$`-bearing
|
||
test now pins the `last_post_topic` scalar (`state-updater.test.mjs`); the three
|
||
remaining additive-insert string-replacements (`:246/:305/:308`) → functions; the
|
||
class is closed and guarded structurally (Section 12).
|
||
|
||
## Findings
|
||
|
||
None. Both independent reviewers returned empty finding sets; the coordinator's
|
||
bounded passes (dedup, HubSpot Judge, verdict) on an empty set yield ALLOW.
|
||
|
||
## Remediation Summary
|
||
|
||
**Gate: ALLOW.** The S12 WARN is fully resolved: the `replaceField` scalar
|
||
`$`-corruption (MINOR) and the false-green test (MAJOR) are both closed; the
|
||
`$`-injection class is closed across the whole `state-updater.mjs` mutation surface;
|
||
and a behavioral, coverage-complete, self-testing Section-12 lint guards it
|
||
structurally against future regressions. All suites green; no Phase-0–3 SC regressed;
|
||
the two re-opened Non-Goals trace to explicit operator decisions and S13 stayed in its
|
||
lane.
|
||
|
||
**Two non-blocking observations, recorded by both reviewers, neither rising to a
|
||
catalogue finding:**
|
||
1. The S13 dead binding both reviewers named (`check-replace-safety.mjs` `HERE` +
|
||
its now-unused `node:url`/`node:path` imports) was removed during this review
|
||
pass; the guard remains green (exit 0) after removal.
|
||
2. The behavioral guard catches a new *unguarded exported mutator* (coverage
|
||
backstop) but not a new unsafe `String.replace` added *inside* an existing
|
||
battery-covered mutator on a field the battery does not fuzz. This is a documented,
|
||
deliberate limit of the behavioral proxy (vs a per-`.replace()` AST enumeration)
|
||
and is **moot today** — every `.replace()` in `state-updater.mjs` is already a
|
||
function. Recorded as a known boundary, not a defect; closing it further is out of
|
||
S13 scope (no real `$`-unsafe site exists to catch).
|
||
|
||
The two adjacent machine-value `.replace()` sites the correctness reviewer probed —
|
||
`session-start.mjs:396` (`${actualWeek}`, a computed ISO week) and `week-rollover.mjs`
|
||
(computed week / literal int) — carry no untrusted content and are therefore not
|
||
members of the defect class, consistent with how the S12 review itself classified the
|
||
date/integer `replaceField` call sites. No finding.
|
||
|
||
Per Handover 6, this `review.md` is consumable by
|
||
`/trekplan --brief docs/remediation/review.md`; the trailing JSON block is the machine
|
||
contract for that handover. With an ALLOW verdict and no BLOCKER/MAJOR findings, no
|
||
follow-up remediation plan is required — the ORIGINAL brief is closed clean and the
|
||
finish-plan continues at S14.
|
||
|
||
```json
|
||
{
|
||
"verdict": "ALLOW",
|
||
"scope": { "sha_start": "c5b4c58f4f390aca83c8937880c5fd0bcc983e44", "sha_end": "36f79dd702b9315a0cd9100c3a8dd6dd81b3797f", "reviewed_files_count": 50, "uncommitted_delta": true },
|
||
"counts": { "BLOCKER": 0, "MAJOR": 0, "MINOR": 0, "SUGGESTION": 0 },
|
||
"findings": [],
|
||
"dropped_findings": []
|
||
}
|
||
```
|