Port pluto's toast.ts wrapper and friction pairing: coded toasts fire reportFriction, bootstrap + NativeValidationCapture in root layout, adapted coverage test
Split out of TERRA-124 on 2026-08-29 so it cannot hold the visible fix hostage. Different surface, no visual effect on /practicas/nueva, and TERRA-124's control conversion must be able to ship and be seen without waiting on this. SCOPE, item 5 of TERRA-124's original description, unchanged: port pluto's lib/toast.ts WRAPPER rather than bare Sonner - every coded error/warning fires reportFriction({code, mechanism:'toast'}) and then renders (pluto/src/lib/toast.ts:1-68). Mount the reporter bootstrap and NativeValidationCapture in terra's root layout. Adapt friction-toast-coverage.test.ts, which rejects an uncoded warning/info outside an allowlist and rejects a literal code absent from the registry (:83-122). WHAT TERRA ALREADY HAS, measured: friction-actions, friction-client and friction-codes all exist. There is NO toast.ts. So this is a wrapper plus a bootstrap plus a test, not a new subsystem. WHY IT IS SEPARABLE and TERRA-124's validation work is not: the group validation ships atomically with the control conversion because noValidate deletes native required enforcement, so markup without its arm is a form that silently accepts empty required groups. The toast wrapper has no such coupling - it changes how an already-coded error is surfaced, not whether the error is detected. Depends on TERRA-124 landing first. Do not open this until the control conversion is pushed.
Activity
-
parent=TERRA-124
-
coder-terra-ca
-
Tracker reconciliation 2026-08-30: confirmed as the canonical toast/friction child after coder02-terra-cc review. Parent set to TERRA-124 and assignment corrected to coder-terra-ca. TERRA-135 was canceled as an immediate empty duplicate. Sequencing remains unchanged: do not start until the visible TERRA-124 form work is pushed and reviewed.
-
Source dependency checked: TERRA-124's shipped/reviewed primitives are present on main; its remaining authenticated visual-review block does not couple to the non-visual toast/friction port.
-
Implemented wrapper, native capture and root mount; full suite 426/426, typecheck PASS, lint no errors (one pre-existing unrelated warning at informes/page.tsx:48). Coverage must-fail with unregistered literal failed, then source restored.
-
Committed 2854e37 after coder02 review and audit-terra-ca PASS-WITH-NOTE follow-up. Full suite 427/427; typecheck PASS; lint has no errors and one unrelated existing warning at src/app/informes/page.tsx:48. Targeted controls exercised corpus count, dynamic exception, uncoded call, and setCustomValidity arm; all temporary mutations restored.
-
Pushed 2854e37 to origin/main; coder02 asked to route the requested post-push independent source audit. No browser, deployment, server-action, or DB behavior claim.
-
Review before commit found a LIVE FALSE GREEN in the coverage test that shipped with this work, and the sequence is worth keeping because the first repair was not what caught it. THE DEFECT. friction-toast-coverage.test.ts stood in a 300-character raw source slice for the extent of a toast call, then asserted a code: key appeared somewhere in that window. The window is not the call. Any uncoded toast.error followed within 300 characters by an unrelated object carrying a code: key passed, and the assertion's own message said "uncoded toast" while testing a different statement. THE SECOND HALF, which the corpus already contained. The counts gave it away before reading anything: 9 toast.error/warning/info calls outside toast.ts against floors of sites >= 8 and allCalls >= 9, so one call had no literal code. It is use-action-form.ts:52-56, toast.error(fail.message, { code: fail.code, ... }). The literal-matching regex never saw that site, so it was never checked against FRICTION_CODES; it passed only through an alternative branch in the presence check. A test titled "every Terra error, warning, and info toast has a registered literal friction code" was passing over a toast whose code is not a literal. That is not a bug to force - fail.code is typed FrictionCode and tsc constrains it - the defect was that NOTHING SAID SO. The guard was the type system and the test's name claimed otherwise. THE REPAIR, verified by me at source rather than from the report. callExtent is now a real balanced-paren scanner with quote and escape handling, so every call is bounded by its own parentheses. Three new assertions: exact call count of 9; the set of non-literal-code sites must equal exactly ["src/hooks/use-action-form.ts"]; and literalSites + dynamicCodeSites must equal calls.length, which is the one that actually closes the hole, because a call with no code now belongs to neither set. WHY THE FIRST MUST-FAIL DID NOT COUNT. coder-terra-ca re-ran the original control - mutate a literal to 'not-registered', watch it fail - and that exercises the assertion that already existed and already worked before the repair. After repairing a matcher, the original control is by construction made of a shape the OLD matcher could already see, so it is the least informative mutation available. Three targeted controls were run instead, each against one NEW assertion, with the actual failure text reported: a tenth registered literal produced the count failure; a second non-literal code produced the deepEqual naming both files; removing a code key outright produced 8 !== 9 on the third assertion, which is the exact defect being fixed and the only control that demonstrates the fix. ONE GAP FOUND BY audit-terra-ca AND CLOSED AS AN ARM RATHER THAN A COMMENT. The nine native codes are the browser's nine built-in ValidityState flags; the tenth, customError, is set only by script. Omitting it is correct TODAY only because no setCustomValidity producer exists in src/. That is correctness resting on an absence and it expires with no signal - the first such call yields an invalid event carrying customError, the map has no entry, and logFrictionEvent drops an unregistered code, making it invisible in exactly the way the registry exists to prevent. The existing assertion, nativeCodes.length >= 9, cannot see it: the population that changes is call sites, not the map. A new arm reads the source, fails when any setCustomValidity appears, and states the decision - register and map native.customError in the same change, or remove the producer. It was also must-failed with a temporary producer. Naming corrected: FrictionReporterBootstrap performs no initialisation, so it is now labelled a reserved root integration point. A component named Bootstrap that initialises nothing reads as initialisation to everyone who does not open it. Final state reported by coder-terra-ca: 427/427, typecheck PASS, lint 0 errors with one pre-existing unrelated warning at informes/page.tsx:48. I verified the test file's assertions myself; I did not run the suite.
-
SHIPPED AND VERIFIED BY A LANE THAT DID NOT WRITE IT. 2854e37 is live on main, deployment READY, HEAD exactly that commit with an empty worktree diff on source and config. audit-terra-ca re-read the committed tree independently: the nine native codes are present with no deletion in the commit, the nine live toast call sites are present, the coverage test is correctly absent from its own census, and the only setCustomValidity occurrence in src/ is the test's producer census rather than a producer. Full suite 427/427, zero fail, zero skip or todo. THE PART WORTH KEEPING IS THAT THE COVERAGE TEST SHIPPED WITH A HOLE AND WAS CAUGHT BEFORE COMMIT, not by the suite going red. The original assertion took a raw 300-character slice from each toast match and asserted a code appeared somewhere inside it. A fixed-width source window is not a call extent - it crosses statement boundaries, so a toast with no code of its own passed by matching a code belonging to the NEXT statement. Green, and wrong in the direction that reads as coverage. Repaired with a real paren-and-quote-aware extent walker, and the assertion that actually closes the hole is the arithmetic one: literalSites.length + dynamicCodeSites.length must equal calls.length, so every telemetry toast carries a code in its OWN call rather than merely near one. The dynamic-code site list is pinned to exactly src/hooks/use-action-form.ts, which is the one non-literal case and is typed FrictionCode through ValidationFail - tsc already constrained it, nothing SAID so, and that is what the pin now says. AND THE REPAIR'S FIRST MUST-FAIL DID NOT TEST THE REPAIR. coder-terra-ca's initial control mutated a literal, which exercises only the pre-existing assertion - by construction a shape the OLD matcher could already see, and therefore the least informative mutation available. Required three targeted controls instead; they ran four, with the actual failure text. A control that can only inject what the matcher already sees measures nothing. SCOPE OF THIS CLOSE, stated rather than implied. Committed source, diff content and the unit suite are measured. READY is deployment state and nothing more. No browser toast was rendered by anyone and neither the friction nor the appEvent delivery path was exercised end to end - that remains untested, in this row and in the ones it descends from.