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:
2026-07-23 17:32:22 -04:00
parent af5f7ee912
commit af34143107
11 changed files with 773 additions and 4 deletions
+35
View File
@@ -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();