Releases: natsume-777/AddressTeller
Releases · natsume-777/AddressTeller
Release list
v0.6.1
Fixed
- JUnit report:
CheckCLInow attaches a<failure>to a Validation<testcase>only when its status has
at least oneIsOk=falseresult — matchingCheckCLI's own exit code 2 criteria, so aDuplicateAddress
notice that only involves duplicates outside this run's writes (IsOk=true) does not get a<failure>.
ApplyAllCLIandApplyWithValidateCLInow attach<failure>only to a status that actually blocks
Apply, matching their own exit code 2 criteria: aDuplicateAddressthat does not block the write no
longer produces a<failure>from these two, even when reported asIsOk=false— this matches 0.6.0's
documented exit code contract, which already excludedDuplicateAddressfrom aborting Apply or affecting
its exit code.<testcase>elements are still generated for every status present, as before (unchanged);
only the presence of the nested<failure>element changes. Direct calls to the public
AddressTellerReportWriter.ToJUnitXml/WriteToFileoverloads are unchanged: they still attach
<failure>unconditionally to every Validation<testcase>, regardless ofIsOk. - Snapshot auto-rotation: if
Auto-snapshot retention countis manually edited in
ProjectSettings/AddressTellerSettings.jsonto 0 or less, the safety snapshotCaptureAndSavehad just
saved before an apply runs could be deleted by the rotation that same call performs right after saving it
— before Apply itself has even started — leavingUndo Last Applyunable to restore it. The count is now
clamped to 1 on load (in-memory only; the JSON file is not re-written with the correction), and a
Warningis logged. Values set via Project Settings UI are already constrained to 1 or more.
Changed
- Project Settings UI: the empty-list message for "Managed Groups" now reflects the current ownership
definition: groups targeted by enabled rules'Address()calls, not justGroup()references. Added a
note toIAddressRuleBuilder.Group()'s XML doc that Addressables replaces/and\in a group name
with-when the group is actually created or renamed, so aGroup()name containing either character
may not match the group Addressables ends up with; changed the Writing Rules example accordingly
(BossAudioinstead ofAudio/Boss).
Documentation
- Documented that
Summary.Issuescounts every entry inIssues[], including report-only notices that
don't affectSummary.ExitCode— checkSummary.ExitCodeto tell whether a report represents a passing
or failing run, not this count. The value itself is unchanged. - Documented that the JUnit report is built from the pre-Apply dry-run result, not the actual execution
result an apply's exit code is based on, so a status that can only be produced by actually performing a
write (e.g.ValidationStatus.EntryRejectedByAddressables) can affectApplyAllCLI/ApplyWithValidateCLI's
exit code without ever appearing in that run's JUnit output. - Expanded the 0.6.0 upgrade guidance for the settings-storage change into a dedicated "Upgrading from
0.5.x" note: a fuller list of the settings that reset to their defaults, what an early automatic apply
on import can and cannot do before you get a chance to restore your values, and safeguards that don't
depend on that timing. Also fixed inaccurate/incomplete notes forValidationResult.IsOk, the
label-only rule change, andPostprocessOrder(all BREAKING), and for theTypeBasedRulessample
(not BREAKING).
v0.6.0
Added
- Broad-rule-overridden-by-specific-rule address authoring:
AddressRuleBase.Ordernow also acts as a
priority when two or more matching rules produce an address for the same asset. See
Writing Rules: Address priority and conflicts
for an example. - Cross-asset duplicate address detection:
Validate/Apply All(andCheckCLI/ApplyAllCLI/
ApplyWithValidateCLI) now report when two different assets resolve to the same address
(ValidationStatus.DuplicateAddress), as an error or a non-blocking notice depending on whether
AddressTeller itself would write one of the colliding addresses. See
Design Decisions: Address Priority and Conflicts.
Changed
- BREAKING:
AddressRuleBase.Ordernow doubles as an address priority, not just an evaluation order.
When two or more matching rules produce an address for the same asset, the one with the lowestOrder
wins instead of it always being a conflict; it is only a conflict when the lowest-Ordermatches tie.
If your project has assets that were previously reported asConflictingAddress(and therefore never
written), run Preview (dry-run) before the firstApply Allafter upgrading — those assets will now be
written using whichever matching rule has the lowestOrder, including via auto-apply on import if that
setting is enabled. See
Design Decisions: Address Priority and Conflicts
and Compatibility: Rule Authoring Behavior. - BREAKING: Settings now persist to
ProjectSettings/AddressTellerSettings.jsoninstead of
ProjectSettings/AddressTellerSettings.asset. The old.assetfile is no longer read. Settings reset
to their defaults once, the first time this version runs — notably, this turns Auto-apply on import
and Remove unmatched entries back ON if you had turned either off, since that's their default. Check
Project Settings > AddressTellerand re-apply your values (including these two) after upgrading.
Delete the old.assetfile — it is no longer used. See
Settings Asset. - BREAKING: Ownership for every deletion-related operation —
CleanupStaleEntries, the invalid-path
entry sweep, deletion follow-up for deleted assets,ClearScope.Managed(including CLI
-addressTellerClearScope managed), and the removable-entry filter inUndo Last Apply— is now
determined by which groups a rule declaresAddress()for, not by every group referenced via
Group(). Each of these now considers a narrower set of groups "managed": aGroup("X")rule that
hasn't calledAddress()yet no longer makes groupXeligible. See
Design Decisions: Deletions Are Determined by Per-Asset Ownership. - BREAKING: Label-only rules (
AnyGroup(), or aGroup()rule with noAddress()) now add labels
to an asset's existing entry regardless of which group it belongs to — previously, labels were only
added when that group was referenced by another rule'sGroup(). If your project has such a rule, run
Preview (dry-run) before the firstApply Allafter upgrading: entries in groups the rule previously
couldn't reach will gain labels, including via auto-apply on import if that setting is enabled. See
Writing Rules: AnyGroup. - BREAKING:
ApplyAllCLI/ApplyWithValidateCLIno longer exit with code 1 for a completed apply
that had drift; a successful apply now always exits 0. See
Compatibility: Exit Codes. - BREAKING:
ApplyAllCLI/ApplyWithValidateCLI's JUnit report no longer reports drift as a
<failure>on thedrifttestcase, matching the exit code change above (a completed apply's own
report should not fail a CI job that ingests it).AddressTellerReportWriter.ToJUnitXml/
WriteToFilegained an optionaltreatDriftAsFailureparameter for this (defaulttrue, matching
CheckCLI's existing behavior). See
Compatibility: Report Output. - BREAKING:
AddressTellerCliArgs.TryParsenow rejects an unrecognized-addressTeller-prefixed
argument as a parse error instead of silently ignoring it. See
Compatibility: Command-Line Arguments. ApplyAllCLI/ApplyWithValidateCLI/ClearCLInow callAssetDatabase.SaveAssets()right before
exiting. See Apply & Operations: CI Integration.- Projects with a pre-existing duplicate address may now see
CheckCLIexit 2 where it previously
exited 0 or 1.ApplyAllCLI/ApplyWithValidateCLI/Apply with Validateare unaffected by a
duplicate either way — it is only ever logged and reported, never a reason to abort or to change
their exit code. See
Design Decisions: Address Priority and Conflicts.
Verified
- EditMode test suite: 656 tests (654 pass / 0 fail / 2 skip), run on Unity 6000.3.8f1 with Addressables 2.8.1. The minimum Addressables requirement remains 2.8.1.
v0.5.0
Added
IAddressRuleGroupBuilder.IncludeFolders()andILabelRuleBuilder.IncludeFolders():
opt a rule into receiving folder assets during evaluation. Callable once per rule or group; calling
twice throwsInvalidOperationException. Without this call, folders are skipped entirely (predicate
is never invoked).AssetContext.IsFolder: true when the asset is a folder rather than a file. Useful for rules that
opt into folder evaluation and need to distinguish between the two; also available to tests and
tooling that construct AssetContext manually.- Overload of
AssetContextconstructor acceptingisFolderparameter, in addition to the existing
constructor. The existing constructor (withoutisFolder) defaults tofalse. AddressRuleEntry.IncludesFolders: read-only property indicating whether this entry opted in to
folder evaluation. Not settable through the publicAddressRuleEntryconstructor — it is only ever
truewhen the entry was produced by the builder (i.e.IncludeFolders()was called). Useful for
code that constructs its own evaluation loop over collected entries (e.g. testing helpers).ValidationStatus.EntryRejectedByAddressables: reported when a rule matched, resolved an address,
and the target group exists, but Addressables itself refused to create or move a usable entry for
this asset (the path is not valid for an Addressables entry; Addressables returns no entry when the
asset's main type also belongs to an editor assembly, and a read-only placeholder otherwise). This
is distinct fromValidationStatus.GroupNotFound, which covers the target group itself not
existing. Any read-only placeholder entry Addressables did create in this edge case is removed.
Fixed
- Windows:
AddressableAssetSettings.ConfigFoldermay be returned with backslash separators. This
meant that, on Windows, assets under the Config Folder were not actually excluded from rule
evaluation, andAddressTellerPostprocessor's early-exit check did not recognize changes confined to
the Config Folder, so saving Addressables settings triggered an unnecessary incremental apply for the
changed settings assets. The path is now normalized to forward slashes at the point of retrieval,
restoring both behaviors; any Config Folder entries created while the exclusion was ineffective are
removed by the invalid-path cleanup described below whenCleanupStaleEntriesis enabled. - Apply no longer aborts with a
NullReferenceExceptionwhen Addressables'CreateOrMoveEntryreturns
null; the asset is now reported asEntryRejectedByAddressablesinstead. - Read-only placeholder entries that Addressables silently creates for a path it considers invalid
(when the asset's main type is not from an editor assembly) are no longer left behind;Applynow
removes them.
Changed
- BREAKING: Folders are now opt-in via
IncludeFolders(). By default, folder assets do not appear
in rule evaluation — neither theWhere()predicate nor address/label selectors are invoked for
folders. Rules that wish to register entries for folders must explicitly callIncludeFolders()on
the builder (once per rule /Group()/AnyGroup()). Previously, every folder path returned by
AssetDatabase.GetAllAssetPaths()was evaluated like a file, so a broad predicate (e.g.
Match.All()orMatch.InFolder(...)) could match a folder and create an Addressables folder entry
that implicitly covers everything beneath it. Rules that do not callIncludeFolders()can now use
broad predicates without matching folders. IfCleanupStaleEntriesis enabled, a folder entry that
only existed because such a broad rule matched it before this change is treated as unmatched once
the rule stops seeing it, and is removed by the same stale-entry cleanup that has always applied to
unmatched file entries — this is not a new cleanup mechanism, and follows the same scoping as file
cleanup (only assets actually evaluated by that particular apply are affected). - BREAKING: Path validity checks now align with Addressables. Addressables itself rejects certain
paths when users manually create entries via the Groups window or the Inspector "Addressable"
checkbox: paths outsideAssets/and outside a package's own folder (e.g.ProjectSettings/,
Library/,Temp/); a package's ownpackage.json; a package's own root folder with nothing
beneath it; extensions.presetand.asmdef; paths containing/Editor/or ending in/Editor;
theAssetsroot itself; and the Addressables Config Folder (see below). Such paths are now
filtered out before rules run — no rule sees them and no result is reported for them, the same as
any other pre-filtered path.ValidationStatus.EntryRejectedByAddressablesis reported only if
Addressables still refuses a write for a path that passed this filter (a rare case, see Added). - BREAKING:
CleanupStaleEntries, when enabled, also removes entries in managed groups whose
asset path is structurally invalid for an Addressables entry at all — regardless of whether any rule
matches them — for example leftovers created by an older AddressTeller version under
ProjectSettings/, or with a.preset/.asmdefpath. Unlike the stale-entry cleanup described
above, this check scans every entry in every managed group on every apply, including import-time
auto-apply, independent of which assets were actually imported or changed. - BREAKING: Extension exclusion is now case-sensitive. File paths ending in
.CS,.DLL,
.PRESET, etc. (uppercase) are no longer automatically excluded from evaluation and will now pass
through to rules. This matches Addressables' own behavior. - BREAKING: The Config Folder exclusion now uses Addressables' own boundary-less prefix match,
reverting the boundary-aware check introduced in 0.4.0. Folders that merely share the Config
Folder's name prefix (e.g.Assets/AddressableAssetsData_Backup) are now excluded, matching the
Groups window and Inspector; existing entries for assets under them — files as well as folders — in
managed groups are removed on the next apply whenCleanupStaleEntriesis enabled. - Upgrading from 0.4.x: with
CleanupStaleEntriesenabled (the default), the first apply after
upgrading can delete existing entries in managed groups: folder entries (whether created by a broad
rule or added by hand) that no rule opting in withIncludeFolders()matches; and entries whose path
Addressables itself rejects (.preset/.asmdef, anEditorfolder or anything under one, the
Assetsroot, a package root or itspackage.json, paths outsideAssets//packages such as
ProjectSettings/, and anything under or sharing a name prefix with the Config Folder). Invalid-path
entries are removed by any apply, including the automatic apply on import, which does not take an
automatic snapshot. Before upgrading: save a snapshot (Tools/AddressTeller/Snapshot/Save Snapshot), or temporarily disableCleanupStaleEntriesand turn off auto-apply on import; add
IncludeFolders()to rules that are meant to register folders; then runApply Alland review the
removal warnings in the Console. RuleUnitTestHelpersample:ExampleRuleTest.FindFirstnow skips a rule'sPredicatefor a folder
AssetContextwhen the rule did not opt in viaIncludeFolders(), matching the production
evaluator's behavior;RuleTestHelper's doc comments and the sample's README explain this for
hand-rolled evaluation loops.
Documentation
compatibility.md: documented that adding a method to a rule-builder interface
(IAddressRuleBuilder,IAddressRuleGroupBuilder,ILabelRuleBuilder) is a non-breaking change,
since these interfaces are only ever implemented internally and are meant to be consumed, not
implemented, by rule authors. Also documented theIncludeFolders()single-call constraint, that a
folder never reaches a rule'sWhere()unless the rule opts in, and the stale-entry cleanup's
expanded scope (structurally invalid paths, not just unmatched entries).design-decisions.md: documented the folder opt-in model, the rationale for aligning path validity
checks with Addressables, and a design principle comparing AddressTeller's rule surface against what
the Addressables Groups window allows and refuses manually.operations.md: documented the new path exclusion categories, the cleanup of path-invalid entries
in managed groups, and a pointer to the upgrade note above.writing-rules.md: added guidance onIncludeFolders()use and folder context detection
viaIsFolder.
v0.4.2
Documentation
- README.md, README.ja.md, Documentation~/writing-rules.md and .ja.md: corrected the asmdef
reference guidance. A custom assembly that only defines rule classes needsAddressTeller.Core
alone — the entire rule-authoring surface (AddressRuleBase,IAddressRuleBuilder,Match,
AssetCondition,Naming,AssetContext,RuleInspector) lives there, as the
Rule Unit Test Helpersample's own asmdef demonstrates.AddressTeller.Editoris required
only when the assembly also calls the operational APIs (AddressTellerService,
ValidationResult, snapshots, reports); referencing it always requires referencing
AddressTeller.Coretoo, since those signatures expose Core types. The previous text told
every rule assembly to reference both. - README.md and README.ja.md: documented pinning the install to a release tag and clarified
that the Compatibility Policy takes effect only from1.0.0
onward; while in0.x, breaking changes may land in minor releases, so tag pinning is strongly
recommended. Noted that unpinned git URLs track the default branch, and that release tags exist
only for version 0.4.0 and later.
v0.4.1
Documentation
- README.md and README.ja.md: clarified that an asset matched by a rule is moved
into that rule's group regardless of its current group, while deletions and
label additions are limited to groups referenced by at least one rule. - README.md and README.ja.md: added an Addressables primer (address / label /
group, initializing Addressables) and expanded Quick Start with notes on entry
creation and moving, managed-group scoping, and auto-apply on import —
including that auto-apply also deletes entries that no longer match any rule
(CleanupStaleEntries). - Documentation~/operations.md and .ja.md: added a non-interactive CLI section
covering the four CLI entry points' exit behavior, a batch-mode example for CI,
and the fact thatTools/AddressTeller/Clear All Addresses & Labels...always
shows a confirmation dialog with no dry-run gate. - Documentation~/operations.md and .ja.md: added the previously undocumented
Tools/AddressTeller/Preview Group...and
Assets/AddressTeller/Preview (Apply Preview)entries to the Apply Methods table. - Documentation~/operations.md and .ja.md: documented the per-rule preview
("Validate/Apply this rule only" button in Project Settings), including that it
can predictRemovedfor entries owned by another rule targeting the same
group, because only the selected rule is in evaluation scope. - AddressTellerScopedPreview.cs XML doc comment: removed an inaccurate mention of
sub-assets from the folder-expansion note onRunGroupPreview.
v0.4.0
Added
ReportFormatandDistributionFormatenums: new public types representing the format choices for report and distribution exports.ReportFormatsupportsJsonandJunit(used byAddressTellerReportWriter.WriteToFile), whileDistributionFormatsupportsCsvandMarkdown(used byBundleDistributionSerializer.WriteToFile).ValidationStatus.RuleConfigureFailed: returned when a user rule'sConfigure()method throws an exception. The problematic rule is skipped (treated as producing no entries) and evaluation continues; this status helps identify which rule has a configuration problem.- Warnings displayed in
Undo Last Applydialog andExplainwindow when rule configuration errors exist, so users are aware that reported results are incomplete. AddressTellerReport.SchemaVersion: a new field parallel toAddressTellerSnapshot.SchemaVersion, defaulting to 1 and set byAddressTellerReportBuilder.Build.AddressTellerReport.CurrentSchemaVersion: a new public constant (= 1) exposing the schema versionAddressTellerReport.SchemaVersiondefaults to andFromJsoncompares against. Previously this value existed only as an internal constant onAddressTellerReportBuilder, which meant it wasn't covered by the public API approval baseline;AddressTellerReportBuildernow reads this new public constant instead of defining its own.AddressTeller.Testing.RuleInspector: public API for inspecting rule configuration results without a real Addressables project. ProvidesCollect()to retrieve all rule entries registered by the rule,IsUnresolvedDefaultGroup()to check for unresolvedGroupDefault()references, andDisplayGroupName()to format group names for display. Enables comprehensive rule unit tests; replaces the custom Fake builders previously used inRuleUnitTestHelpersamples.
Fixed
RestoreExactWithRemovalAPI:Undo Last Applynow correctly deletes entries matching the confirmation dialog count, instead of leaving all entries intact.- Rule collection no longer stops on constructor exceptions or open generic types; problematic rules are skipped and evaluation continues.
- Settings folder exclusion filter now includes path separators to prevent adjacent folders (e.g.,
AddressableAssetsData_Backup) from being mistakenly excluded. - Cleanup no longer incorrectly deletes entries for assets matched by label-only rules; added
ValidationStatus.LabelsOnlyto properly track label-only rule matches. CollectManagedGroupsnow excludesnullvalues and unresolvedGroupDefault()sentinels from the managed groups list.NullReferenceExceptionwhenApplyAllis called withpaths: null.- Duplicate warnings and processing for the same group after
AutoCreateMissingGroups. - Potential
NullReferenceExceptionin the result window whenContextis null. - Snapshot file overwriting when multiple saves occur within the same second; improved error handling for write failures.
- Snapshot file helper duplication and folder boundary detection.
SnapshotFolderpath traversal vulnerability; added range check to restrict paths to the project directory.Apply Alllacking progress bar display and cancellation support; integratedEditorProgressReporter.- Incorrect comment in
Namingclass. - Unnecessary array allocations in
AssetContext.PathSegmentsby caching. - Label-only rules incorrectly writing labels to unmanaged group entries without ownership check; labels are now restricted to managed groups.
- Automatic safety snapshot save failures were previously ignored;
Apply All/Apply with Validatenow properly handle these errors by stopping the operation and notifying the user. - Snapshot save operation now handles
Directory.CreateDirectoryfailures (e.g., invalid path or permission error) gracefully, preventing unhandled exceptions. - Snapshot restoration now tolerates duplicate group names instead of throwing an exception; duplicate groups are reported as warnings.
AddressTellerSnapshotService.RestoreandBundleModeReaderhave been updated to handle this gracefully. AssetFilter.ShouldExcludeByPath: added null check before callingpath.Replace()to preventNullReferenceException.- Snapshot JSON loading (
LoadFromFile): extended mandatory field validation to includeGroupNameandEntries(in addition to the existingGuidcheck). - Project Settings UI: Postprocessor order field now displays the effective clamped value (e.g., 0 becomes 1000) when the user leaves the field or presses Enter.
ExportDistribution: now displays an error dialog when file write fails, instead of silently suppressing the error.AddressTellerSnapshotService.Restore/RestoreExactWithRemoval/Diffnow throwArgumentNullExceptionfor missing required arguments instead of an unguardedNullReferenceException, matchingAddressTellerClearService.Clear's existing contract. The package's null-argument policy (explicit entry points throw; methods with default-value fallback such asAddressTellerService.*do not) is now documented in the relevant XML doc comments.AddressTellerSettings.DisabledRuleClassNamesnow returns a defensive copy instead of the internal list instance, so mutating the returned collection can no longer affect the persisted setting.
Changed
- BREAKING: Core domain model and evaluation engine (
Editor/Core/content) are now split into an independent assemblyAddressTeller.Core. The asmdef name isAddressTeller.Core, and the namespace remainsAddressTeller(unchanged). If your project has a custom asmdef that referencesAddressTeller.Editor, you must also addAddressTeller.Coreto itsreferences; since public APIs inAddressTeller.Editorexpose Core types (e.g.,ValidationResult.ContextisAddressTeller.AssetContext,AddressTellerService.ApplyAll(..., rules)acceptsIReadOnlyList<AddressTeller.AddressRuleBase>), the compiler requires both assemblies inreferences. - Validation notifications with
IsOk=true(e.g.,GroupWillBeCreated) are now logged asWarninginstead ofErroracross all entry points (Postprocessor, Menu, ApplyFlow). This distinguishes informational status messages from actual errors. AddressTellerMenu.Validate()now opens the result window (showing Issues tab) when one or more errors (IsOk=false) are detected. Previously, results were only logged to the console.- BREAKING:
BundleModeReader.ReadBundleModes()andBundleDistributionSummarizer.Build()now include anoutparameter for reporting duplicate group name warnings. Callers must accept this new parameter. - BREAKING:
IAddressRuleBuilder.Address()now throwsInvalidOperationExceptionwhen called twice on the same rule, matchingWhere()behavior. Previously, duplicate address assignments were silently overwritten; this change ensures early detection of ambiguous address specification. ApplyAll,ValidateAll, andBuildPredictedSnapshotnow skip stale-entry cleanup (DeletedAssets tracking) if any rule configuration error is detected, preventing incorrect deletions of entries managed by broken rules.ApplyAll/Apply with Validatemenu operations now cancel instead of continuing when automatic safety snapshot save fails, matching the fail-fast design ofClearAll.ClearAllmenu andClearCLIcommand now abort when rule configuration errors exist (CLI exits with code 3).- BREAKING:
AddressTellerReportWriter.WriteToFileandBundleDistributionSerializer.WriteToFilenow takeReportFormat/DistributionFormatenum arguments instead of raw strings ("json"/"junit"and"csv"/"markdown"). CLI text arguments (-addressTellerReportFormat) are unaffected; only the public API surface changed. - BREAKING:
SnapshotDiff.Added/Removed/Changedare nowIReadOnlyList<T>instead ofList<T>. Code that mutated these collections directly must be updated. - BREAKING:
SnapshotDiffandDryRunResultparameterless public constructors are nowinternal. These types are instantiated only by the library's snapshot and dry-run APIs; tests continue to construct them viaInternalsVisibleTo. - BREAKING:
ValidationResultandAddressCandidatepublic constructors are nowinternal. These types are only ever constructed by the library's own rule evaluation pipeline; tests continue to construct them viaInternalsVisibleTo. - BREAKING:
AddressTellerPostprocessoris nowsealed. - BREAKING:
AddressTellerService.RemoveEntriesForDeletedAssetsnow returnsIReadOnlyList<ClearedEntry>(previouslyvoid), reporting the entries actually removed. This matches the convention already used byApplyAll/ValidateAllof surfacing results instead of discarding them. - BREAKING:
AddressTellerExplainReport,AddressTellerExplainAsset, andAddressTellerExplainRuleare nowinternal(previouslypublic). No supported code path constructs or exposes these types outside the package. - BREAKING:
AddressTellerCliArgs.ReportFormatis nowReportFormat?instead ofstring. Code that read this property as a raw string ("json"/"junit") must be updated to compare against theReportFormatenum. RuleUnitTestHelpersample:DefaultGroupSentinelconstant removed;Collect()now delegates to the package's ownRuleInspectorpublic API, ensuring the exact same builder contract (callingWhere()/Address()a second time on the same group now throwsInvalidOperationException). New helper methodsIsUnresolvedDefaultGroup()andDisplayGroupName()added for checking and displaying unresolved default group sentinels in tests.- BREAKING:
LogicalBundleDtorenamed toBundleDistributionReportEntry. This is a C# API-only rename; the JSON report output (field names) is unchanged. - Enum members of
ValidationStatus,ClearScope,ReportFormat,DistributionFormat,SnapshotRestoreMode, andBundleModeKindnow carry explic...