feat: add device position undo history

Issue: #74
User-Visible: yes
This commit is contained in:
Matysh
2026-08-30 13:16:27 +00:00
committed by claude[bot]
parent 857537c620
commit bdf81fad58
55 changed files with 1091 additions and 281 deletions
+1 -1
View File
@@ -44,7 +44,7 @@ export function checkCoordinateWriteBarriers(root = defaultRoot) {
}
const positionWrites = occurrences(frontend, "type: 'houseplan/layout/update'");
if (positionWrites.length !== 2) errors.push(`frontend position writer inventory: ${positionWrites.length}`);
if (positionWrites.length !== 3) errors.push(`frontend position writer inventory: ${positionWrites.length}`);
for (const [ordinal, index] of positionWrites.entries()) requireWindow(
errors, frontend, index,
/const pos = canonicalizePosition\([^)]+\);[\s\S]*pos(?:[,\s}])/,
+13 -2
View File
@@ -2282,6 +2282,17 @@ const MUTANT_DEFINITIONS = [
replace: ' const exact = false ? exactCoveringWall(walls, a, b, pitch, coordScale) : null;',
}],
},
{
id: 'device-position-cancel-routed-to-commit',
guard: 'node demo/smoke_device_position_history.mjs',
because: 'pointer cancellation and lost capture must restore the uncommitted device preview '
+ 'without creating a position command or writing layout (#74)',
patches: [{
file: 'src/houseplan-card.ts',
find: '@pointercancel=${(e: PointerEvent) => this._pointerCancel(e, d)}',
replace: '@pointercancel=${(e: PointerEvent) => this._pointerUp(e, d)}',
}],
},
{
id: 'stale-space-position-guard-removed',
guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs '
@@ -2290,8 +2301,8 @@ const MUTANT_DEFINITIONS = [
+ 'and websocket side effects when that space has been deleted or renamed',
patches: [{
file: 'src/houseplan-card.ts',
find: ' if (!this._spaceModelById(d.space)) return;\n if (this._norm) {',
replace: ' if (this._norm) {',
find: ' if (!this._spaceModelById(d.space)) return;\n this._layout = applyDevicePlacement(',
replace: ' this._layout = applyDevicePlacement(',
}],
},
{
+11
View File
@@ -27,6 +27,17 @@
/** @type {SmokeLink[]} */
export const SMOKE_LINKS = [
{
symbols: [
'applyDevicePlacement', 'devicePlacement', 'sameDevicePlacement',
'DevicePlacement', 'DevicePositionState',
],
smokes: ['smoke_device_position_history.mjs'],
because: 'the #74 production-bundle scenario drives real Device editor pointer events and '
+ 'observes transaction boundaries, point-wise update/delete, toolbar history, native field '
+ 'shortcuts, cancellation and revision invalidation; none of those browser effects can be '
+ 'proved by the pure placement helpers alone',
},
{
symbols: [
'resolveValueSource', 'valueSourceWriteFields', 'valueBadgeCandidates',