'use strict'; const assert = require('assert/strict'); const { resolveDirectEditConstraints, SOLVED_KINDS } = require('../src/compile/direct-edit-solver'); const model = { roads: [], endpoints: [], connections: [], diagnostics: [] }; function constraint(overrides = {}) { return { id: 'constraint-1', kind: 'road-edge-offset', anchor: { type: 'road-interval', roadId: 'road:way/1:forward', startStation: 0.3, endStation: 0.7 }, anchorSnapshot: { coordinate: [113.1, 30.2], tangentAzimuth: 45, roadLengthMeters: 120, osmNodeIds: ['1', '2'], }, value: { offsetMeters: 1.5, transition: 'smoothstep' }, enabled: true, status: 'exact', provenance: { operationId: 'operation-1', createdAt: '2026-08-27T00:00:00.000Z' }, ...overrides, }; } function document(constraints) { return { schema: 'native-road-edits/v2', documentVersion: 1, base: {}, constraints, operations: [] }; } // A missing or empty document must resolve to the identity: this is what keeps // the stage insertable ahead of compileGeometry without moving any geometry. for (const empty of [null, undefined, document([])]) { const resolution = resolveDirectEditConstraints(model, empty); assert.equal(resolution.schema, 'road-edit-resolution/v1'); assert.equal(resolution.roadProfiles.size, 0); assert.equal(resolution.junctionPlans.size, 0); assert.deepEqual(resolution.constraintStates, []); assert.deepEqual(resolution.diagnostics, []); assert.equal(resolution.handles.schema, 'road-edit-handles/v1'); assert.deepEqual(resolution.handles.handles, []); assert.deepEqual(resolution.handles.reserves, []); assert.equal(resolution.handles.revisionId, null); assert.equal(resolution.handles.previewSeq, 0); } // Handle manifest context is echoed so a preview response can be matched to the // request that asked for it. const withContext = resolveDirectEditConstraints(model, null, { revisionId: 'rev-0007', previewSeq: 42 }); assert.equal(withContext.handles.revisionId, 'rev-0007'); assert.equal(withContext.handles.previewSeq, 42); // A disabled constraint is reported, never applied, and produces no diagnostic: // the user turned it off deliberately, so it is not a problem to report. const disabled = resolveDirectEditConstraints(model, document([constraint({ enabled: false })])); assert.deepEqual(disabled.constraintStates, [ { constraintId: 'constraint-1', kind: 'road-edge-offset', status: 'exact', applied: false, reason: 'disabled' }, ]); assert.deepEqual(disabled.diagnostics, []); // Only `exact` and `recheck` may reach the solver. The other three statuses mean // the anchor is not trustworthy, so they are skipped with the status as reason. for (const status of ['pending', 'conflicted', 'stale']) { const resolution = resolveDirectEditConstraints(model, document([constraint({ status })])); assert.deepEqual(resolution.constraintStates, [ { constraintId: 'constraint-1', kind: 'road-edge-offset', status, applied: false, reason: `status-${status}` }, ]); assert.deepEqual(resolution.diagnostics, []); } // Until a kind is wired into the solver its constraints are reported as // unapplied with an explicit diagnostic, rather than approximated or ignored. for (const status of ['exact', 'recheck']) { const resolution = resolveDirectEditConstraints(model, document([constraint({ status })])); const expected = SOLVED_KINDS.has('road-edge-offset') ? { applied: true, reason: null, diagnostics: 0 } : { applied: false, reason: 'kind-not-solved', diagnostics: 1 }; assert.deepEqual(resolution.constraintStates, [ { constraintId: 'constraint-1', kind: 'road-edge-offset', status, applied: expected.applied, reason: expected.reason, }, ]); assert.equal(resolution.diagnostics.length, expected.diagnostics); for (const item of resolution.diagnostics) { assert.equal(item.severity, 'info'); assert.equal(item.rule, 'direct-edit-kind-not-solved'); assert.equal(item.subjectId, 'constraint:constraint-1'); assert.equal(item.geometry, null); } } // Every constraint gets exactly one state, in document order, so a caller can // report per-row status without re-deriving the mapping. const many = resolveDirectEditConstraints( model, document([ constraint({ id: 'a', enabled: false }), constraint({ id: 'b', status: 'stale' }), constraint({ id: 'c' }), ]), ); assert.deepEqual( many.constraintStates.map((state) => state.constraintId), ['a', 'b', 'c'], ); // The solver must be free of file and network access so preview can share it. const source = require('fs').readFileSync(require.resolve('../src/compile/direct-edit-solver'), 'utf8'); for (const forbidden of ["require('fs')", "require('path')", "require('http')", "require('https')"]) assert.equal(source.includes(forbidden), false, `direct-edit-solver must not ${forbidden}`); console.log('direct edit solver tests passed');