Repository navigation
fix(widget-dev): read a newer node's session view without its unknown top-level fields - #678
Merged
Merged
Conversation
… top-level fields, and say what was left out An older desktop app connected to a newer node on another machine refused the whole widget dev session view when the node added an optional field such as stopCode. The client now reads the view with readNodeView: unknown top-level fields are dropped and never passed on, the status line and the develop card say the node is newer, every known field keeps its bounds, and nested objects carrying activation, approval and reach state stay strict. Requests and the node's own schema stay strict. Fixes #673
This was referenced Oct 8, 2026
…ed, and test the status line's newer-node sentence A new value in a field the app knows (a new stopReason, status or activation state) still refuses the view, so the same-build advice covers it too. lastBuild and placed carry build and placement state, not approval or reach. Approval or reach state is never added as a new top-level field, which an older app would drop. The status report is drawn by its own component so the sentence can be rendered in a test.
Contributor
Author
|
Review attestation: ready to merge at A push to this PR makes this attestation stale; the new head needs its own review. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #673
Problem
An older desktop app connected to a newer node on another machine parsed the widget dev session view with a strict
schema, so one new optional field (for example
stopCode, #662/#665) made it refuse the whole view and lose the session.Change
Follows the directory-entry precedent (#431, #438):
packages/contracts/src/node-view-read.ts:readNodeView(schema, candidate)drops unknown top-level fields and neverpasses them on. Every known field is still validated with all its bounds. The nested objects (
activation,latest,running,lastBuild,placed) stay strict, because they carry activation, approval and reach state. The drop isreturned as an
UnreadListingFieldsnote. Field names are reported only when they are plain identifiers; otherfields are only counted.
packages/conversation-client/src/api.ts: the four widget dev session reads (widgetDevSession,start,rebuild,stop) go through onereadDevSessionand returnWidgetDevSessionRead, which carriesunreadFieldswhensomething was dropped.
/developcard outcomeadd "This node is newer than this app, so some of what it says about this session is not shown. Update the app to
see everything." (EN and VI).
widgetDevSessionCreateSchema) and the node's ownwidgetDevSessionViewSchemastay strict. Runtime filesand
sessions.jsonare not touched, so this does not overlap with widget dev: removing a snapshot can race a build or install that reuses the same digest #670.docs/open-interfaces(.vi).mdadds a Reading a session view rule. The "keep the same build" advice nownames the cases that still refuse: an app built before this change, a newer field inside a nested object, and a
value the app does not know in a field it knows (a new
stopReason,statusor activation state). The rule alsosays approval or reach state is never added as a new top-level field, since an older app would drop it.
Not done here, tracked in #679: the other strict reads below, the optional item 4 (the client reads the node's
version and says older or newer up front), unknown values in known fields, the
/developcard that showsfailedwithraw ZodError text after the node started the session, and making the top-level authoring rule enforceable.
Other strict node→client reads, not changed here
api.tsalso parses these withz.strictObject(or unions of strict objects), so they have the same skew exposure.They are listed for a follow-up rather than changed:
inboxResponseSchema,inboxSummarySchema,noticeSchema,noticeOperationResponseSchema,effectReconcileResponseSchema,waitingItemSchema,memoryListSchema,suggestionsResponseSchema,composerSuggestionsResponseSchema,attachmentRefSchema,conversationDeleteResultSchema,appIntentDecisionSchema,widgetDevFolderForgetResultSchema, and the widget-sdkbrowserTokenWireSchemaandjobSnapshotWireSchema.readNodeViewcovers a plain top-level object directly; unionsand inbox items need their own decision about which fields bind.
Tests
packages/contracts/test/node-view-read.spec.ts:fooCodeparses, withfooCodedropped and reported;activation(active and awaiting-approval) orrunning.deltastill refuses;packages/conversation-client/test/widget-dev-session-read.spec.ts:GatewayClient.widgetDevSessionandstartWidgetDevSessionread a view withfooCodefrom a stubbed node. A nested unknown field rejects. The developoutcome states the drop in EN and VI.
srcchanges reverted, the client spec fails with aZodErroron thefooCodeview,and the contracts spec fails with
readNodeView is not a function.Verification
false &&fails that test)pnpm typecheck: passpnpm invariants: all 15 checks passpnpm verify: exit 0, 586 files and 8022 tests passednode tools/check-invariants.mjs --fix-manifest: no manifest change (open-interfacesis not indocs/manifest.json)