feat: classify direct edit replay states

This commit is contained in:
2026-08-27 12:43:35 +08:00
parent 94e319c717
commit 735ce69d26
3 changed files with 91 additions and 18 deletions

View File

@@ -144,6 +144,26 @@ assert.equal(allKindsResolution.junctionPlans.get('junction').approaches['segmen
assert.equal(allKindsResolution.junctionPlans.get('junction').approaches['segment:a'].cutbackMeters, 2);
assert.equal(allKindsResolution.junctionPlans.get('junction').corners['segment:a->segment:b'], 4);
const recheckResolution = resolveDirectEditConstraints(
junctionModel,
{ ...document([anchored]), base: { compilerGeometryVersion: 'old-geometry' } },
{ compilerGeometryVersion: 'new-geometry' },
);
assert.equal(recheckResolution.constraintStates[0].status, 'recheck');
assert.equal(recheckResolution.constraintStates[0].applied, true);
const pendingResolution = resolveDirectEditConstraints(
junctionModel,
document([
constraint({
anchor: { type: 'road-interval', roadId: 'missing-road', startStation: 0.2, endStation: 0.8, side: 'left' },
anchorSnapshot: { ...constraint().anchorSnapshot, coordinate: [113, 30], osmNodeIds: ['junction'] },
}),
]),
);
assert.equal(pendingResolution.constraintStates[0].status, 'pending');
assert.equal(pendingResolution.constraintStates[0].applied, false);
const invalidDivider = resolveDirectEditConstraints(
junctionModel,
document([
@@ -155,8 +175,8 @@ const invalidDivider = resolveDirectEditConstraints(
]),
);
assert.equal(invalidDivider.constraintStates[0].applied, false);
assert.equal(invalidDivider.constraintStates[0].reason, 'invalid');
assert.equal(invalidDivider.diagnostics[0].severity, 'error');
assert.equal(invalidDivider.constraintStates[0].status, 'stale');
assert.equal(invalidDivider.constraintStates[0].reason, 'status-stale');
assert.equal(invalidDivider.roadProfiles.size, 0);
// A disabled constraint is reported, never applied, and produces no diagnostic:
@@ -177,26 +197,20 @@ for (const status of ['pending', 'conflicted', 'stale']) {
assert.deepEqual(resolution.diagnostics, []);
}
// A solved kind with a missing road anchor is rejected as a blocking
// constraint diagnostic rather than approximated or ignored.
// An exact constraint whose anchor disappeared during reimport is stale and
// must not enter the solver.
for (const status of ['exact', 'recheck']) {
const resolution = resolveDirectEditConstraints(model, document([constraint({ status })]));
assert.deepEqual(resolution.constraintStates, [
{
constraintId: 'constraint-1',
kind: 'road-edge-offset',
status,
status: 'stale',
applied: false,
reason: 'invalid',
reason: 'status-stale',
},
]);
assert.equal(resolution.diagnostics.length, 1);
for (const item of resolution.diagnostics) {
assert.equal(item.severity, 'error');
assert.equal(item.rule, 'direct-edit-road-anchor-missing');
assert.equal(item.subjectId, 'constraint:constraint-1');
assert.equal(item.geometry, null);
}
assert.deepEqual(resolution.diagnostics, []);
}
// Every constraint gets exactly one state, in document order, so a caller can