feat(view): D2 Wave 2 — apply managed-lane ops + timer-diff auto-tag new content
Drives fixed-lane C_LANEPLAYS for managed lanes only (name-keyed, ordinal-renumber safe) in the view shell; diffs live track/item GUIDs on the panel timer to auto-tag new content to the active mode, first-poll-guarded. Pure guid_diff + lane_keys modules unit-tested; folds in Wave-1 polish.
This commit is contained in:
@@ -940,6 +940,40 @@ static void testLaneOwnershipIndex() {
|
||||
CHECK(!idx.remove("{T}", "l0"));
|
||||
}
|
||||
|
||||
// -- D2.2b Last-writer-wins ownership replace (round-trip) --------------------
|
||||
//
|
||||
// setManual then setManaged on the SAME (guid, laneKey) must leave EXACTLY ONE
|
||||
// managed entry — the ownership record is replaced, not accumulated. Guards the
|
||||
// "retag a lane the tool now owns" contract and its persistence: the replace must
|
||||
// survive a serialize/deserialize round-trip with no stray manual duplicate.
|
||||
static void testLaneOwnershipLastWriterWins() {
|
||||
ViewModeModel vm;
|
||||
|
||||
// Manual first, then managed on the same lane — the managed write replaces.
|
||||
CHECK(vm.lanes().setManual("{T}", "l0"));
|
||||
CHECK(vm.lanes().setManaged("{T}", "l0", kDesignModeId));
|
||||
CHECK(vm.lanes().size() == 1); // one entry, not two
|
||||
const LaneOwnership* o = vm.lanes().query("{T}", "l0");
|
||||
CHECK(o && o->isManaged() && *o->managedMode == kDesignModeId);
|
||||
|
||||
// The reverse also replaces: managed -> manual leaves exactly one manual entry.
|
||||
CHECK(vm.lanes().setManual("{T}", "l0"));
|
||||
CHECK(vm.lanes().size() == 1);
|
||||
const LaneOwnership* m = vm.lanes().query("{T}", "l0");
|
||||
CHECK(m && m->isManual());
|
||||
|
||||
// Back to managed, then round-trip: exactly one managed entry survives, no stray
|
||||
// manual duplicate resurrected by (de)serialization.
|
||||
CHECK(vm.lanes().setManaged("{T}", "l0", kArrangeModeId));
|
||||
auto back = ViewModeModel::deserialize(vm.serialize());
|
||||
CHECK(back.has_value());
|
||||
if (back) {
|
||||
CHECK(back->lanes().size() == 1);
|
||||
const LaneOwnership* r = back->lanes().query("{T}", "l0");
|
||||
CHECK(r && r->isManaged() && *r->managedMode == kArrangeModeId);
|
||||
}
|
||||
}
|
||||
|
||||
// -- D2.3/D2.4 Managed-only: planner + query never emit a manual lane --------
|
||||
//
|
||||
// Required case: a track with a manual lane + managed mode lanes — neither the planner
|
||||
@@ -1124,6 +1158,7 @@ int main() {
|
||||
// D2 two-canvas lane extension
|
||||
testLaneModeStateAndPlayValues();
|
||||
testLaneOwnershipIndex();
|
||||
testLaneOwnershipLastWriterWins();
|
||||
testManagedOnlyPlannerAndQuery();
|
||||
testAutoTagDecision();
|
||||
testLaneJsonRoundTrip();
|
||||
|
||||
Reference in New Issue
Block a user