feat(tree): add stagedOptionalRecursive#27042
Open
noencke wants to merge 30 commits intomicrosoft:mainfrom
Open
feat(tree): add stagedOptionalRecursive#27042noencke wants to merge 30 commits intomicrosoft:mainfrom
noencke wants to merge 30 commits intomicrosoft:mainfrom
Conversation
…uired→optional field migration Adds `SchemaFactoryAlpha.stagedOptional(T)` to enable migrating a required field to optional across multiple deployments without breaking cross-version collaboration. - Required field stays in the stored schema during the rollout period, so old clients are unaffected - New clients using `stagedOptional` see the field as Optional in the view (TypeScript type is `T | undefined`) - Writing `undefined` is blocked at runtime until the stored schema is upgraded to Optional - Migrating to `sf.optional(T)` upgrades the stored schema and enables clearing the field Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…clarify docs - filterFieldAllowedTypes now preserves the isOptionalStaged SchemaUpgrade marker when using the Unchanged (view-copy) path, so getSimpleSchema output retains staged optional information. - Clarify SimpleFieldSchema.isOptionalStaged doc comment: false = view, not staged; absent = derived from stored schema. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This reverts commit 2793d4d.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ce ambiguity SchemaFactoryAlpha.stagedOptional has both a static and instance declaration, making it ambiguous for TSDoc links. Link to SchemaStaticsAlpha.stagedOptional instead, which is unambiguous (interface member). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…dering SchemaFactoryAlpha.stagedOptional (instance and static) landed with "stagedOptionalUpgrade" | "defaultProvider" while SchemaStaticsAlpha had "defaultProvider" | "stagedOptionalUpgrade". CI compiles fresh TypeScript and produces alphabetical order for both. Align the class members to match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Optional to includeStaged Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename isOptionalStaged → isStagedOptional to match the stagedOptional factory naming - Fix comment capitalization in discrepancies.ts (optional/required not capitalized) - Rename describe block to "staged allowed type upgrade" (was "staged schema upgrade") - Expand JSDoc on isStagedOptional to explain why false and undefined are distinct Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
undefined for isStagedOptional only means "stored schema" — view schemas are always constructed by the current in-memory package, so there is no "legacy view field" scenario. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
# Conflicts: # packages/dds/tree/src/simple-tree/api/schemaFactoryAlpha.ts
- Remove inline code backticks from changeset title per repo guidelines - Clarify changeset description to lead with required→optional migration - Fix JSDoc in schemaFactoryAlpha.ts step 3 wording (Josh's suggestion) - Reword isStagedOptional JSDoc to "Indicates that..." instead of reading as an action Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aligns with how AllowedTypeMetadata.stagedSchemaUpgrade is documented — no restriction on setting the property by hand. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Swap Omit union member order from "stagedOptionalUpgrade" | "defaultProvider" to "defaultProvider" | "stagedOptionalUpgrade" to match CI's api-extractor output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The @System tag was removed from the source code but the API report files were not regenerated to match. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous ordering fix incorrectly changed all Omit union orderings to "defaultProvider" | "stagedOptionalUpgrade". CI generates different orderings for class members vs interface members: - SchemaFactoryAlpha (class): "stagedOptionalUpgrade" | "defaultProvider" - SchemaStaticsAlpha (interface): "defaultProvider" | "stagedOptionalUpgrade" Reverts the class member ordering to match what CI actually produces, verified against the last passing CI build. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add SchemaFactoryAlpha.stagedOptionalRecursive for recursive schema support, following the same pattern as optionalRecursive/requiredRecursive (relaxed type constraints via ImplicitAllowedTypesUnsafe) - Fix stagedOptional JSDoc to accurately describe the enforcement mechanism: stored-schema validation, not a dedicated runtime guard - Update changeset description to match - Update alpha API report Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds a “staged optional” field mode to support incremental required→optional migrations and introduces the recursive-typing variant, plus updates schema conversion and compatibility logic to recognize staged optional fields.
Changes:
- Add
SchemaFactoryAlpha.stagedOptionalandSchemaFactoryAlpha.stagedOptionalRecursive(and corresponding statics) and plumb staged-optional metadata through schemas. - Extend stored-schema generation to optionally treat staged-optional fields as optional via
includeStagedOptional. - Add/adjust tests and API reports/changesets to reflect the new alpha API surface and behavior.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/dds/tree/src/simple-tree/api/schemaFactoryAlpha.ts | Adds stagedOptional/stagedOptionalRecursive APIs and implementation. |
| packages/dds/tree/src/simple-tree/core/toStored.ts | Extends stored-from-view generation options with includeStagedOptional. |
| packages/dds/tree/src/simple-tree/toStoredSchema.ts | Implements staged-optional kind selection for stored schema generation. |
| packages/dds/tree/src/simple-tree/simpleSchema.ts | Adds isStagedOptional to SimpleFieldSchema with detailed semantics. |
| packages/dds/tree/src/simple-tree/fieldSchema.ts | Adds stagedOptionalUpgrade props and exposes isStagedOptional getter. |
| packages/dds/tree/src/simple-tree/api/discrepancies.ts | Suppresses kind discrepancies for staged-optional vs required stored during rollout. |
| packages/dds/tree/src/simple-tree/api/storedSchema.ts | Wires includeStagedOptional when extracting persisted schema. |
| packages/dds/tree/src/test/simple-tree/api/stagedSchemaUpgrade.spec.ts | Adds staged-optional upgrade tests and renames existing describe. |
| packages/dds/tree/src/test/simple-tree/toStoredSchema.spec.ts | Updates callers for new includeStagedOptional option. |
| packages/dds/tree/src/test/testTrees.ts | Updates stored-schema generation options in test documents. |
| packages/dds/tree/api-report/tree.alpha.api.md | API report updates for new staged optional APIs/fields. |
| packages/framework/fluid-framework/api-report/fluid-framework.alpha.api.md | API report updates for staged optional fields and extractor churn. |
| .changeset/fruity-cars-tell.md | Changeset for stagedOptional. |
| .changeset/brave-owls-jump.md | Changeset for stagedOptionalRecursive. |
Comments suppressed due to low confidence (1)
packages/dds/tree/src/simple-tree/toStoredSchema.ts:1
- The current
isStagedOptionalpreservation logic drops the explicitfalsevalue (it only preserves values that areinstanceof SchemaUpgrade). This loses the documented distinction betweenfalse(“view schema field, not staged optional”) andundefined(“stored schema field”), which can cause downstream logic that relies on!== falsechecks (e.g., discrepancy suppression) to misclassify non-staged fields as staged optional. Preservefalseas well whenpreservesViewData(options)is true (e.g., by passing throughf.isStagedOptionalinstead of filtering to onlySchemaUpgradeinstances).
/*!
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reverts the JSDoc edit to the original fruity-cars-tell changeset. Regenerates all API reports from a clean build to eliminate non-deterministic union member reordering from incremental builds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…churn - Type-level assignability test in schemaFactoryRecursive.spec.ts (parallels optionalRecursive tests) - Runtime test in stagedSchemaUpgrade.spec.ts: recursive schema with stagedOptionalRecursive, ValidateRecursiveSchema, and unhydrated node construction - Revert beta/legacy API reports to base branch versions to avoid upstream merge churn showing in the PR diff Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
199507d to
8d1de83
Compare
jenn-le
approved these changes
Apr 14, 2026
8d1de83 to
a49544c
Compare
jenn-le
approved these changes
Apr 14, 2026
Josmithr
reviewed
Apr 15, 2026
Josmithr
reviewed
Apr 15, 2026
Josmithr
reviewed
Apr 15, 2026
Josmithr
approved these changes
Apr 15, 2026
Merge brave-owls-jump.md into fruity-cars-tell.md since both stagedOptional and stagedOptionalRecursive will ship in the same release. Add usage examples for both the standard and recursive variants. Remove unnecessary blank lines in the schemaStaticsAlpha object. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
a49544c to
316b3ae
Compare
These were incorrectly modified by earlier commits on this branch. This PR has no beta-level API changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Josmithr
approved these changes
Apr 15, 2026
Contributor
|
🔗 No broken links found! ✅ Your attention to detail is admirable. linkcheck output |
1 similar comment
Contributor
|
🔗 No broken links found! ✅ Your attention to detail is admirable. linkcheck output |
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.
Description
Follow-up to #26918 (
stagedOptional). Adds recursive versions of the methods.Changes:
stagedOptionalRecursive— Adds the recursive-type variant ofstagedOptionalonSchemaStaticsAlphaandSchemaFactoryAlpha(instance + static). Follows the same pattern asoptionalRecursive/requiredRecursive/withDefaultRecursive: relaxes type constraints viaImplicitAllowedTypesUnsafeand returnsFieldSchemaAlphaUnsafe. The implementation simply casts the non-recursivestagedOptionalfunction, matching thewithDefaultRecursivepattern.Reviewer Guidance
The review process is outlined on this wiki page.