#208
fix(engine): keep an explicit null consolidated output instead of raw
Fixes #104.
What changes
At settle, the engine picked the consolidated output with nullish coalescing:
output = consolidated.output ?? raw; // engine/engine.ts:918Consolidated.output is zJson.optional() — null is valid JSON and a valid consolidated result, and the hook contract (shared/core/schema/hooks/usage-consolidate.ts) says "absent = unchanged". Nullish coalescing treats explicit null as absent, so a hook returning { credits: {...}, output: null } had its result overwritten by the raw response — re-exposing exactly the vendor billing fields the hook stripped.
The settle path now falls back to raw only when consolidated.output is undefined:
output = consolidated.output === undefined ? raw : consolidated.output;Verification
No deno on this host, so:
- HEAD-vs-fix semantics of the exact expression, Node 26: with
consolidated = { credits: {}, output: null }andraw = { results: [...], vendorTotal: 0 }, HEAD producesraw, the fix producesnull; withoutputomitted (undefined), both produceraw— the "absent = unchanged" case is preserved. - Grep over
engine/engine.ts: line 918 was the only?? raw/ consolidated-output fallback; the newfromResponseanddoc.output.schemasteps downstream are untouched and both already acceptnull(free-form outputs;zJsonincludesnull). - Added a
Deno.testregression inengine/engine.test.tsnext to the empty-claim test, modeled on the sameusageUnitharness: explicit{ credits: {}, output: null }settlesoutput === null, and an omitted output still passes the raw payload through. I could not rundeno testlocally; CI is the authoritative run.
Summary by CodeRabbit
- Bug Fixes
- Explicit
nulloutputs from consolidation are now preserved, while omitted outputs continue to use the raw payload. - Usage is still settled when the consolidation claim is empty.
- Explicit
No actionable comments were generated in the recent review.
183b9f11-387c-410f-ab8b-2748d3dbebd4Reviewing files that changed from the base of the PR and between 09d54479142e36eff876383beacfbd37b33b5908 and efa08da1e0319bfaac16882026888ead7ac77e20.
engine/engine.test.tsengine/engine.tsIncluded review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.
Walkthrough
LoadedEndpoint.settlenow uses the raw payload only whenusage.consolidatereturnsoutput: undefined. Explicitnullremains the settled output. Tests cover both cases and verify derived usage.Priority: Low
Severity of issue fixed: Low
Merge Risk: Minimal · up to
efa08The change implements the requested output behavior, with no identified issue blocking merge after normal checks.
Pre-merge checks: 4
#104requires explicitnullto remain the consolidated output and onlyundefinedor an omittedoutputto preserve the raw payload.engine/engine.tsnow uses anundefinedcheck. `engine…#104. Both changes directly support the linked issue. No unrelated change is shown.Full details: Linked Issues check
Explanation
Issue
#104requires explicitnullto remain the consolidated output and onlyundefinedor an omittedoutputto preserve the raw payload.engine/engine.tsnow uses anundefinedcheck.engine/engine.test.tscovers both explicitnulland omitted output.Comment
@coderabbitai helpto get the list of available commands.