fix(#12274): deep fallback-slop sweep slice 0/1 — fail-fast over fabricated defaults - #13270
Conversation
…/fabricated-default/promise-swallow to fail-fast Residual deep sweep over the app-plugins-B slice (wallet/vision/music/ agent-skills/browser/workflow/training) after the primary #12274 sweep (#12825). Converts the clear-slop that survived, keeps and annotates genuine J-categories, defers the ambiguous return-null/false + ??-literal tail for a judgment pass. Fabricated-healthy (data-loss) — agent-skills skill preference/acknowledgment loaders returned `{}` on a cache *read failure*, conflating "DB read failed" with "nothing persisted". Callers read-modify-write these maps and save them back (`prefs[id]=true; save(prefs)`), so the fabricated empty overwrote every other skill's saved preference on a transient DB error. Now the read failure propagates to the route boundary (a genuinely-empty cache still returns `{}` via `?? {}`). Fixed in both the exported helpers and the duplicated local copies in skills-routes.ts. Empty catch — browser-service target-resolution failover scan swallowed an unhealthy candidate's availability error with an empty `catch {}`. Kept as designed failover (other targets still resolve, unlike the pinned path which throws) but annotated `// error-policy:J4` and now logs the exclusion so a systemically broken target is observable. Tests — new skill-discovery-helpers.test.ts asserts a cache read failure now throws (would have resolved `{}` before); browser-service.test.ts gains a failover-scan case asserting the broken candidate is excluded, a healthy one still resolves, and the exclusion is logged. Refs #12274 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…r fabricated defaults (#12182) Reviewed MERGE_AS_IS: loadSkillPreferences/Acknowledgments no longer fabricate {} on read failure (which wiped saved prefs via read-modify-write); browser-service J4 failover. Real tests. (Pre-existing save-write-swallow noted as follow-up.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Reviewed (adversarial): #12274 slop sweep: skill preference/ack loaders rethrow read failures (fixes a real read-modify-write data-loss bug where a transient getCache error would overwrite all prefs) while still empty-for-genuinely-empty. All throws contained (HTTP 500 wrap + boot try/catch). Tested. No failing CI. Queuing auto-merge on green. |
#13336) Two of the five wave-2 fallback-slop-sweep PRs left real reds on develop: - #13278: database-rows-compat-routes.test.ts failed 5 OWNER-gate tests in the full app-core suite. app-core runs vitest with isolate:false, so a preceding suite's cached ./auth/sessions mock leaked into the real ensureRouteMinRole. Fix: vi.resetModules() in the hoisted block (the same immunization ensure-route-min-role.test.ts already uses). - #13277: useWhatsAppPairing.test.tsx had a TS2556 — the zero-arg onWsEvent vi.fn spread unknown[]. Fix: type the mock with a rest-param signature. Findings #13271, #13270, #13287 were already green on current develop and are left unchanged. No fail-fast/reportError conversion reverted. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…gagement) (#13335) * test(#12775): author SR slice of persona pack E1 (low-activation-reengagement) Completes the scenario-runner slice of LifeOps persona pack E1 — low-activation-reengagement (persona tara_low / P6, #12775), mirroring the A1 (#13286) and B1 (#13312) pack conventions. Coverage gate: E1 2/28 -> 28/28 authored (22 verified). Authored 10 new SR scenarios on top of the 2 pre-existing E1 scenarios: pr-deterministic (keyless, real lifeops_scheduler tick, no LLM): - lowact-quiet-streak-softens-next-nudge — three check-ins are fired + terminally expired through REAL ticks so the production state-log lays down a checkin/expired streak; the next reminder times out and the quiet-streak softener (#12779/#13237) steps intensity normal->minimal, read back off the persisted task (noReplyState.quietStreakSoftened=true, quietStreakDays>=3, appliedReminderIntensity=minimal, emptied ladder). - lowact-morning-single-priority-fires-once — one gentle high-priority morning pick fires once inside quiet hours while a low-value whole-list ping is HELD (quiet_hours gate); single-delivery finalCheck. - lowact-values-anchored-activity-fires-in-window — a during_window values-anchored evening activity fires inside the seeded eveningWindow and defers outside it. - lowact-micro-step-deferred-not-dropped — a captured one-small-step is parked (snooze override), does not resurface early, and resurfaces exactly once (scheduled_override_due) at the promised gentle time. Added to EXPECTED_PR_DETERMINISTIC_SCENARIO_IDS in the same commit (G1). live-only (status: authored, live-verify deferred to #12781): - lowact-lapse-return-triage-no-guilt (definitionCountDelta + shame-free judge) - lowact-quiet-user-reengagement-tone - lowact-crisis-language-safe-reengagement - lowact-make-whole-list-smaller-bulk-shrink - lowact-celebration-without-infantilizing - lowact-cannot-choose-single-option (definitionCountDelta{delta:1}) Each has effect-reading finalChecks, non-echo-satisfiable, personas-as-data in turns[].text (never promptInstructions). Crisis-boundary handling: #12780 crisis guard is CLOSED/NOT_PLANNED, so no scenario asserts a crisis-guard/988 effect. lowact-crisis-language-safe- reengagement takes the #12280 crisis-adjacent premise and asserts only the SAFE behavior per the A1 adhd-task-initiation convention: warm non-clinical stand-down, NO productivity push (definitionCountDelta{delta:0} proves no task/schedule created against her "not right now"), and does NOT assert a 988/crisis-guard side-effect fires. Catalog: 10 new surface:scenario-runner rows + 16 registered surface:lifeops-bench Python ids (append-only; no lifeops-bench/** file touched). 12 SR + 16 bench = 28 = target. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: repair wave-2 fallback-sweep regressions (test mocks + typecheck) (#13336) Two of the five wave-2 fallback-slop-sweep PRs left real reds on develop: - #13278: database-rows-compat-routes.test.ts failed 5 OWNER-gate tests in the full app-core suite. app-core runs vitest with isolate:false, so a preceding suite's cached ./auth/sessions mock leaked into the real ensureRouteMinRole. Fix: vi.resetModules() in the hoisted block (the same immunization ensure-route-min-role.test.ts already uses). - #13277: useWhatsAppPairing.test.tsx had a TS2556 — the zero-arg onWsEvent vi.fn spread unknown[]. Fix: type the mock with a rest-param signature. Findings #13271, #13270, #13287 were already green on current develop and are left unchanged. No fail-fast/reportError conversion reverted. Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * ci: exhaustive-lane matrix proof + vacuous-green guard, GitHub-native turbo cache foundation, Linux Bun cache (advances #12342/#12341/#12338) (#13332) * ci(#12342): add exhaustive-lane matrix proof + vacuous-green guard Additive proof infrastructure for the exhaustive develop lane. Nothing here touches a PR-critical workflow or renames a required status check. - packages/scripts/ci-lane-manifest.json: committed source of truth enumerating every expected exhaustive lane plus plan floors. - packages/scripts/ci-full-matrix-proof.mjs: cross-checks the manifest against test.yml (job present, not pinned pull_request-only) and against `run-all-tests.mjs --plan=json` (task/package floors, required core packages, non-empty per-script lanes). Fails on a missing lane, a lane pointed at a nonexistent glob, or a whole script lane collapsing to zero. Emits a GitHub step summary enumerating every lane. - run-all-tests.mjs: `--min-tasks`/`MIN_TEST_TASKS` vacuous-green guard. A filter/shard/glob that collapses a lane to (near-)zero tasks, or a run whose every task skips (no test files), now exits 3 instead of green. Strictly additive: default 0 preserves historical behaviour. - .github/workflows/ci-full-matrix-proof.yml: un-cancellable (cancel-in-progress: false) scheduled proof job, twice daily + workflow_dispatch, plus a path-scoped PR trigger on its own inputs only. - Tests: negative cases for the proof (missing lane, PR-only pin, each plan-floor breach) and the guard (collapsed filter, env parity, usage error, historical exit preserved), all deterministic and dependency-free. Advances #12342 (mechanism only). The DoD's "≥ twice daily for 7 consecutive days without cancellation" is observation-gated and requires post-merge live-CI sampling. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci(#12341): add pinned GitHub-native turbo cache shim + migration contract Lays the additive foundation for the move off the Vercel remote Turbo cache without doing the risky removal across ~13 workflows in this change. - .github/actions/turbo-cache-github/action.yml: pinned composite action that restores/saves the local .turbo cache via actions/cache (SHA-pinned) keyed on the deterministic turbo-cache-key.mjs hash. No SaaS, no secrets. Nothing adopts it yet — migration of individual workflows is proven safe one at a time under #12341. - packages/scripts/ci-turbo-cache-contract.mjs: static contract. (1) the shim exists, is composite, keys off turbo-cache-key, pins actions/cache to a full SHA, and carries no SaaS env; (2) no workflow that ADOPTS the shim also wires TURBO_TOKEN/TURBO_TEAM/TURBO_CACHE: remote:rw — re-adding SaaS env to a migrated workflow fails the contract. Deliberately silent about not-yet-migrated workflows; the existing dedup contract still pins the SaaS wiring that remains live (nightly/release). - Wired the contract into test.yml's `changes` job (one additive step beside the existing dedup contract) and the new proof workflow. - Negative tests: clean adopter passes; SaaS re-adder fails; floating (unpinned) actions/cache fails; SaaS-in-shim fails. Advances #12341 (mechanism + contract). Removing SaaS env from live workflows and moving PR lanes to `turbo --affected` is deferred — it edits PR-critical workflows and its "cache hit rate >= baseline" DoD is observation-gated on representative post-merge PR runs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci(#12338): cache the Bun install store on Linux too, pin the cache action The shared setup action skipped the Bun install-store cache on Linux (`if: runner.os != 'Linux'`), so every Linux job re-downloaded the whole dependency tree cold. #12338 explicitly asks to enable Linux Bun store caching in the shared setup action; this does exactly that and pins the cache action by SHA (it was floating `@v5`) to kill the drift the issue targets. Additive and low-risk: a cache miss is just no speedup and a cache write failure is non-fatal, so a cold Linux runner behaves exactly as before while warm runners skip the re-download. The cache key already includes this action's own content, so entries rotate correctly on this edit. Advances #12338 (this DoD item: "Linux jobs restore the Bun store cache"). The "cache logs show Linux Bun store restore" verification is observation-gated on a real post-merge Linux run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci(#12342): capture the plan via a file, not a pipe; add spawn-test timeouts The matrix-proof's default plan discovery spawned run-all-tests and read its stdout through a pipe. The plan JSON is >64KB and the runner calls process.exit(0) immediately after writing it, so a piped stdout gets truncated mid-flush (SyntaxError: Unterminated JSON at byte 65536). Redirect the runner's stdout to a temp file instead — a file descriptor is flushed on close, so capture is lossless. This mirrors how the CI workflow already invokes it (`> plan.json`, which was never affected). Also give the runner-spawning tests explicit 60s timeouts. They do whole-repo workspace discovery and were tripping bun's default per-test timeout on a cold/contended runner, producing a flaky red. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test: cover remote deep-link profile registry sync * style: format CI lane manifest --------- Co-authored-by: Shaw <shawgotbags@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * test: verify A1 task initiation live proof --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Shaw <shawgotbags@gmail.com>
Deep fallback-slop sweep — app plugins B, slice 0/1 (#12274)
Residual deep sweep over the app-plugins-B slice (
plugin-{wallet,vision,music,agent-skills,browser,workflow,training}) after the primary #12274 sweep already merged as #12825. This pass re-derived the full suspect list, converted the clear slop that survived, kept + annotated genuine J-categories, and deferred the ambiguous tail for a per-site judgment pass.Scope per the parent convention (#12182 / foundation #12263): the unambiguous slop categories only — empty catch, fabricated-healthy-on-error, promise-swallow. Ambiguous
return null/[]/falseand?? <lit>defaults are explicitly deferred (they need per-site judgment; over-removing a legitimate not-found→empty is a bug).Per-category tally
return {}on read failure)skills-routes.ts.catch {})// error-policy:J4, now logs the exclusion..catch(()=>{})in the slice are J6 best-effort temp-file teardown / J3 parse-invalid — left for the annotation pass, not masking-a-failure.// error-policy:J4on the browser failover scan.The data-loss fix (fabricated-healthy)
loadSkillPreferences/loadSkillAcknowledgmentsreturned{}when the cache read threw, conflating "DB read failed" with "nothing persisted yet". The callers read-modify-write these maps and save them back:So a transient cache-read error silently wiped every other skill's saved preference. Now the read failure propagates to the route boundary (which surfaces it), while a genuinely-empty cache still returns
{}via the existing?? {}. This is the parent's canonical "not loaded must never read as empty" rule.The empty-catch fix (browser-service)
The target-resolution scan swallowed an unhealthy candidate's
available()error with a barecatch {}. This is legitimate failover — the other registered targets must still be selectable (unlike the pinned-preferredIdpath, which correctly throwsBROWSER_TARGET_UNAVAILABLE). Kept the failover, annotated// error-policy:J4, and nowlogger.debugs the exclusion so a systemically broken target is observable instead of silently vanishing.Ratchet (diff-scoped empty-catch, touched files)
Empty-catch count goes down (browser-service 1→0) or stays equal — never up. Remaining empty catches in the agent-skills files are pre-existing comment-only J3 parse sites left for the annotation pass.
Tests
plugin-agent-skills/src/api/skill-discovery-helpers.test.ts— asserts a cache read failure now throws (would have resolved{}against the pre-change code), and that a genuinely-empty/absent cache still returns{}. 7 cases.plugin-browser/src/__tests__/browser-service.test.ts— new failover-scan case: a target whoseavailable()throws is excluded, a healthy target still resolves, and the exclusion is logged.Deferred (ambiguousLeft — not touched this pass)
The slice's large residual tail is genuine J-categories and judgment-heavy sites: URL/JSON/base58 parse-invalid →
null/false/[](J3), executable/model-file existence probes (accessSync/fs.access→ false), provider health/availability degrades (J4), best-effort temp-fileunlink().catch(()=>{})teardown (J6), and?? <lit>load defaults. Notably the PaddleOCRdescribe()→{blocks:[]}-on-error path is a coordinated J7 vision-loop / OCR-service-family decision (no runtime handle at the leaf; all sibling OCR services share the shape) — left for a dedicated pass rather than a risky partial conversion. These need per-site judgment and are the next wave, not clear slop.Evidence
getCachethrow → real propagation; no mock-swallow of the thing under test). Real-LLM trajectory / rendered-UI evidence: N/A — this is a server-side error-handling refactor with no new user-facing surface; the observable behavior is "a failed cache read becomes a 500 instead of a silent preference wipe", asserted by the tests.Refs #12274
🤖 Generated with Claude Code