fix(cli): pass unrecognised functions entries through the lowering (#7318) - #7461
Conversation
…7318) The map branch of the top-level `functions` lowering REBUILT the map rather than editing it: `out` admitted an entry only in the three shapes it knew — a bare callable, `{ handler: callable }`, or a plain string ref — and deleted everything else. No error, no warning, no key. Two failures came out of that. 1. Lowering stopped being IDEMPOTENT. `{ handler: 'syncBilling', effect: 'writes' }` — the shape this step itself emits for a declared writer, and the one `FlowFunctionLoweredDeclarationSchema` was added to accept in #4976 — matched none of the recognised shapes, so a second pass dropped the key and silently un-declared the writer the first pass had kept. Measured on `examples/app-showcase/dist/objectstack.json`: re-lowering it returned `{ summarizeCompletedTask: 'summarizeCompletedTask' }`, `sweepProjectHealth` gone, and the result still parsed green. 2. A MALFORMED entry was destroyed instead of reported. The headless husk `{ effect: 'writes' }` that a plain `JSON.stringify(stack)` leaves where a declaration was (#6293) left the lowering as `functions: {}` and the stack parsed green, so the build wrote an artifact missing the function rather than refusing — the evidence deleted before the parse could name it. Unrecognised entries now ride through under their own key, untouched, and `FlowFunctionEntrySchema` decides. The husk is refused where the build checks: `invalid_union` on `functions`, with `functions.sweep` in the branch tree that `formatZodErrors` (#5341) prints. The dedicated loop that re-added string entries is folded into the same pass. Bare callables, declared callables, pre-existing refs and the array form lower exactly as before. Tests pin both halves against the real pipeline: a second lowering of a lowered stack leaves the key set and the declarations unchanged (map and array), and the husk reaches the parse and is refused by key. `packages/qa/dogfood/test/build-shaped-artifact.ts` keeps its key-for-key reconciliation — it is now unreachable on this path but is still the only check that compares input `functions` keys against output ones, so it stays as the backstop against a producer that starts dropping again. Its measured claims and the showcase fixture's expectation are updated to the gate that now speaks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RiF5oDWaCLK57mPuBsyB4t
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 2 package(s): 20 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 3 release-owned page(s) also reference the affected code. These are read-only:
|
Fixes #7318
The map branch of the top-level
functionslowering rebuilt the map rather than editing it:outadmitted an entry only in the three shapes it knew — a bare callable,{ handler: callable }, or a plain string ref — and deleted everything else. No error, no warning, no key. Two failures came out of that.1. Lowering stopped being idempotent.
{ handler: 'syncBilling', effect: 'writes' }— the shape this step itself emits for a declared writer, and the oneFlowFunctionLoweredDeclarationSchemawas added to accept in #4976 — matched none of the recognised shapes, so a second pass dropped the key and silently un-declared the writer the first pass had kept. Measured onexamples/app-showcase/dist/objectstack.json: re-lowering it returned{ summarizeCompletedTask: 'summarizeCompletedTask' },sweepProjectHealthgone, and the result still parsed green.2. A malformed entry was destroyed instead of reported. The headless husk
{ effect: 'writes' }that a plainJSON.stringify(stack)leaves where a declaration was (#6293) left the lowering asfunctions: {}and the stack parsed green, so the build wrote an artifact missing the function rather than refusing — the evidence deleted before the parse could name it.The fix
Unrecognised entries now ride through under their own key, untouched, and
FlowFunctionEntrySchemadecides. The husk is refused where the build checks:invalid_uniononfunctions, withfunctions.sweepin the branch tree thatformatZodErrors(#5341) prints. The dedicated loop that re-added string entries is folded into the same pass. Bare callables, declared callables, pre-existing refs and the array form lower exactly as before.Tests pin both halves against the real pipeline: a second lowering of a lowered stack leaves the key set and the declarations unchanged (map and array), and the husk reaches the parse and is refused by key.
On the stand-in the card named
packages/qa/dogfood/test/build-shaped-artifact.tskeeps its key-for-key reconciliation — it is now unreachable on this path but is still the only check that compares inputfunctionskeys against output ones, so it stays as the backstop against a producer that starts dropping again. Its measured claims and the showcase fixture's expectation are updated to the gate that now speaks.Implemented by a dispatched dev agent in its own container; PR opened by the PM seat because the container had git push but no GitHub API access. Full rationale is preserved verbatim in the commit message of
9ec2b2239.Generated by Claude Code