Make tool-managed lane splits visually transparent: collapse display + lazy-mint
Drive C_LANESCOLLAPSED=2 and hide lane buttons only on tracks the tool itself splits (gated on the pre-write I_FREEMODE read, so user comp-lane display prefs are never stomped). Lazy-mint managed lanes only for modes with own content, never an empty reserved lane; confinement holds via C_LANEPLAYS on the lone lane.
This commit is contained in:
@@ -1235,9 +1235,11 @@ static void testLaneMintingThreeModesAndOwnershipKeys() {
|
||||
// The exact failing case. A folder {F} has descendant leaves in BOTH modes ({LD} Design,
|
||||
// {LA} Arrange) and carries ONE OWN item ({own}) tagged Design. W3-A's own-item-span test
|
||||
// alone would NOT split {F} (its own content is single-mode Design), so the item leaked
|
||||
// into every mode the folder was derived-visible in. The visibility-aware decision now
|
||||
// mints managed lanes on {F} and lanes {own} onto the Design lane — so it hides+silences
|
||||
// whenever Arrange is active. This is the load-bearing fix; assert it hard.
|
||||
// into every mode the folder was derived-visible in. The visibility-aware decision splits
|
||||
// {F} and lanes {own} onto the Design lane — so it hides+silences whenever Arrange is
|
||||
// active. LAZY-MINT: {F} mints ONLY the Design lane (holding the item), NOT an empty
|
||||
// reserved Arrange lane — confinement holds via C_LANEPLAYS=0 on the lone Design lane when
|
||||
// Arrange is active. This is the load-bearing fix; assert it hard.
|
||||
static void testLaneMintingFolderDerivedVisibleSplitsOwnMedia() {
|
||||
ViewModeModel vm;
|
||||
vm.membership().tag("{LD}", kDesignModeId); // a Design leaf under the folder
|
||||
@@ -1264,17 +1266,69 @@ static void testLaneMintingFolderDerivedVisibleSplitsOwnMedia() {
|
||||
|
||||
// {F} MUST split even though its own item is single-mode: it is visible in 2 modes.
|
||||
CHECK(!plan.empty());
|
||||
CHECK(splitLaneCount(plan, "{F}") == 2); // one lane per stance
|
||||
|
||||
// LAZY-MINT: ONE lane only — the Design lane that holds the item. No empty reserved
|
||||
// Arrange lane is minted, even though {F} is derived-visible in Arrange. The Arrange
|
||||
// lane appears on demand when an Arrange item first lands on {F}.
|
||||
CHECK(splitLaneCount(plan, "{F}") == 1); // Design lane only — no reserved lane
|
||||
CHECK(plan.mints.size() == 1);
|
||||
CHECK(hasMint(plan, "{F}", kDesignModeId)); // Design lane (holds the item)
|
||||
CHECK(hasMint(plan, "{F}", kArrangeModeId)); // Arrange lane (reserves the slot)
|
||||
CHECK(!hasMint(plan, "{F}", kArrangeModeId)); // NO empty reserved Arrange lane
|
||||
|
||||
// The own item is confined to its tagged (Design) lane — the exact hide-in-Arrange fix.
|
||||
// With only the Design lane present, toggling to Arrange sets its C_LANEPLAYS to 0, so
|
||||
// the item hides+silences and the track reads as an empty normal track (no leak).
|
||||
CHECK(plan.assigns.size() == 1);
|
||||
CHECK(hasAssign(plan, "{own}", "{F}", kDesignModeId));
|
||||
for (const auto& a : plan.assigns)
|
||||
CHECK(!(a.itemGuid == "{own}" && a.laneKey == laneNameForMode(kArrangeModeId)));
|
||||
}
|
||||
|
||||
// LAZY-MINT confinement proof. Same single-own-mode / dual-visibility folder, but instead
|
||||
// of asserting the mint COUNT we prove the FUNCTIONAL confinement the lazy split preserves:
|
||||
// apply the minted lane's ownership to a live model, then drive the toggle planner and show
|
||||
// the lone Design lane SILENCES when Arrange is active (C_LANEPLAYS = 0). That is the whole
|
||||
// point — a single managed lane still hides its item in every other mode, so removing the
|
||||
// empty reserved Arrange lane costs nothing functionally. Fails if the split ever leaves the
|
||||
// Design item audible in Arrange (the leak the D2 fix closed) or mints a spurious lane.
|
||||
static void testLaneMintingLazySingleLaneStillConfines() {
|
||||
ViewModeModel vm;
|
||||
vm.membership().tag("{LD}", kDesignModeId); // Design leaf ⇒ folder visible in Design
|
||||
// {LA} untagged ⇒ Arrange member ⇒ folder ALSO derived-visible in Arrange.
|
||||
vm.membership().tag("{own}", kDesignModeId); // the folder's one own item (Design)
|
||||
|
||||
FolderTree tree;
|
||||
tree.nodes.push_back(FolderNode{"{F}", "", /*isParent=*/true});
|
||||
tree.nodes.push_back(FolderNode{"{LD}", "{F}", false});
|
||||
tree.nodes.push_back(FolderNode{"{LA}", "{F}", false});
|
||||
|
||||
std::vector<LaneTrack> tracks{
|
||||
LaneTrack{"{F}", {LaneItem{"{own}", kDesignModeId, false}}},
|
||||
};
|
||||
const LaneMintPlan plan = planLaneMinting(vm, tree, tracks);
|
||||
|
||||
// Exactly one lane minted (the Design lane) — no empty reserved Arrange lane.
|
||||
CHECK(plan.mints.size() == 1);
|
||||
CHECK(hasMint(plan, "{F}", kDesignModeId));
|
||||
|
||||
// Apply the mint's ownership exactly as the shell does, then drive the toggle planner.
|
||||
for (const auto& m : plan.mints)
|
||||
CHECK(vm.lanes().setManaged(m.trackGuid, m.laneKey, m.modeId));
|
||||
CHECK(vm.lanes().size() == 1); // one managed lane on {F}, not two
|
||||
|
||||
const std::string designLane = laneNameForMode(kDesignModeId);
|
||||
|
||||
// Active = Design: the lone Design lane PLAYS (item visible+audible in its own mode).
|
||||
const auto design = vm.planToggle(tree, kDesignModeId);
|
||||
CHECK(lanePlaysFor(design, "{F}", designLane) == kLanePlaysExclusive);
|
||||
|
||||
// Active = Arrange: the lone Design lane SILENCES — with no lane playing, the track
|
||||
// reads as an empty normal track and the Design item does NOT leak. This is the
|
||||
// confinement guarantee that lets us drop the reserved Arrange lane.
|
||||
const auto arrange = vm.planToggle(tree, kArrangeModeId);
|
||||
CHECK(lanePlaysFor(arrange, "{F}", designLane) == kLaneSilent);
|
||||
}
|
||||
|
||||
// A folder carrying its OWN items that already span both modes → still split (the two
|
||||
// triggers OR: own-item span AND derived visibility both point the same way here). Both
|
||||
// own items separate to their tagged lanes.
|
||||
@@ -1470,6 +1524,7 @@ int main() {
|
||||
testLaneMintingManualLaneExempt();
|
||||
testLaneMintingThreeModesAndOwnershipKeys();
|
||||
testLaneMintingFolderDerivedVisibleSplitsOwnMedia();
|
||||
testLaneMintingLazySingleLaneStillConfines();
|
||||
testLaneMintingFolderOwnItemsSpanBothModes();
|
||||
testLaneMintingShowBothNotForceSplit();
|
||||
testLaneMintingSingleModeLeafVisibleOnceNoSplit();
|
||||
|
||||
Reference in New Issue
Block a user