Skip to content

fix(#12274): deep fallback-slop sweep slice 0/1 — fail-fast over fabricated defaults - #13270

Merged
lalalune merged 1 commit into
developfrom
fallback/12274-deep-s0
Jul 4, 2026
Merged

lalalune merged 1 commit into
developfrom
fallback/12274-deep-s0

Conversation

@lalalune

@lalalune lalalune commented Jul 4, 2026

Copy link
Copy Markdown
Member

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/[]/false and ?? <lit> defaults are explicitly deferred (they need per-site judgment; over-removing a legitimate not-found→empty is a bug).

Per-category tally

Category Converted Notes
Fabricated-healthy (return {} on read failure) 4 sites agent-skills preference/acknowledgment loaders — DB read failure masked as "no data" (data-loss bug, see below). Fixed in the exported helpers and the duplicated local copies in skills-routes.ts.
Empty catch (catch {}) 1 site browser-service target-resolution failover scan → kept as designed failover, annotated // error-policy:J4, now logs the exclusion.
Promise-swallow 0 Surviving .catch(()=>{}) in the slice are J6 best-effort temp-file teardown / J3 parse-invalid — left for the annotation pass, not masking-a-failure.
Annotated justified (J1–J7) 1 // error-policy:J4 on the browser failover scan.

The data-loss fix (fabricated-healthy)

loadSkillPreferences / loadSkillAcknowledgments returned {} when the cache read threw, conflating "DB read failed" with "nothing persisted yet". The callers read-modify-write these maps and save them back:

const prefs = await loadSkillPreferences(state.runtime); // threw → returned {}
prefs[skillId] = true;
await saveSkillPreferences(state.runtime, prefs);         // overwrites ALL other prefs

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 bare catch {}. This is legitimate failover — the other registered targets must still be selectable (unlike the pinned-preferredId path, which correctly throws BROWSER_TARGET_UNAVAILABLE). Kept the failover, annotated // error-policy:J4, and now logger.debugs the exclusion so a systemically broken target is observable instead of silently vanishing.

Ratchet (diff-scoped empty-catch, touched files)

plugin-agent-skills/src/api/skill-discovery-helpers.ts: emptyCatch 2->2
plugin-agent-skills/src/api/skills-routes.ts:            emptyCatch 3->3
plugin-browser/src/browser-service.ts:                  emptyCatch 1->0   ← down
no new fallback-slop in 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

  • New 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 whose available() throws is excluded, a healthy target still resolves, and the exclusion is logged.
plugin-agent-skills  test: 9 files, 42 passed
plugin-browser       test: 27 files, 148 passed

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-file unlink().catch(()=>{}) teardown (J6), and ?? <lit> load defaults. Notably the PaddleOCR describe(){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

  • Backend behavior proven by the new unit tests driving the real helpers (real getCache throw → 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

…/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>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 50f238d1-ef59-47bb-afb0-798df12a5ca4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fallback/12274-deep-s0

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lalalune
lalalune merged commit fe03ec2 into develop Jul 4, 2026
18 of 73 checks passed
@lalalune
lalalune deleted the fallback/12274-deep-s0 branch July 4, 2026 15:36
lalalune pushed a commit that referenced this pull request Jul 4, 2026
…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>
@lalalune

lalalune commented Jul 4, 2026

Copy link
Copy Markdown
Member Author

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.

lalalune added a commit that referenced this pull request Jul 4, 2026
#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>
lalalune added a commit that referenced this pull request Jul 4, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants