feat: insert direct edit constraint solver stage
Adds resolveDirectEditConstraints between compileRoadModel and compileGeometry, per the parent design's data flow. The stage is an identity transform until the individual constraint kinds land: it returns empty road profiles, junction plans and handle manifest, so compileGeometry's geometry code is untouched and output stays byte-identical. Constraint planning is separated from solving up front. Only `exact` and `recheck` constraints may reach the solver; `disabled`, `pending`, `conflicted` and `stale` are reported as unapplied with a reason. SOLVED_KINDS starts empty and grows one entry per kind, so a partially delivered solver reports what it skipped instead of publishing half-solved geometry. diagnostic() moves to src/compile/diagnostics.js so the solver can share the compiler's diagnostic shape without depending on fs, which would break the pure-function boundary that lets preview, the full compile and the CLI export share one implementation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ const os = require('os');
|
||||
const path = require('path');
|
||||
const { nativeRoadEdits, roadRevisions } = require('../src');
|
||||
const { compileInput } = require('../src/compile/compiler');
|
||||
const { snapshot: outputSnapshot } = require('./fixture-baseline');
|
||||
|
||||
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'road-revisions-'));
|
||||
const source = '<osm version="0.6"><node id="1" lon="114.1" lat="22.5"/></osm>\n';
|
||||
@@ -127,5 +128,39 @@ assert.throws(
|
||||
/Area config snapshot is missing/,
|
||||
);
|
||||
|
||||
// The workbench compile is the one caller that passes editsFile. With no v2
|
||||
// constraints the direct-edit solver stage must be an identity transform, so
|
||||
// both compiles have to publish byte-identical outputs.
|
||||
const activeEditsFile = path.join(directory, 'active', 'native-road-edits.json');
|
||||
assert.ok(fs.existsSync(activeEditsFile));
|
||||
assert.deepEqual(nativeRoadEdits.loadEditDocument(activeEditsFile).constraints, []);
|
||||
const identityBase = { ...compileBase, areaId: 'edits-identity-test' };
|
||||
const withoutEdits = {
|
||||
...identityBase,
|
||||
outDir: path.join(directory, 'no-edits-output'),
|
||||
stagingDir: path.join(directory, 'no-edits-pipeline'),
|
||||
};
|
||||
const withEdits = {
|
||||
...identityBase,
|
||||
outDir: path.join(directory, 'with-edits-output'),
|
||||
stagingDir: path.join(directory, 'with-edits-pipeline'),
|
||||
editsFile: activeEditsFile,
|
||||
};
|
||||
compileInput(withoutEdits);
|
||||
compileInput(withEdits);
|
||||
assert.deepEqual(
|
||||
outputSnapshot(withEdits).files,
|
||||
outputSnapshot(withoutEdits).files,
|
||||
'an empty v2 document must not change compiled output',
|
||||
);
|
||||
assert.throws(
|
||||
() => compileInput({ ...identityBase, editsFile: '' }),
|
||||
/editsFile must be a non-empty string when present/,
|
||||
);
|
||||
assert.throws(
|
||||
() => compileInput({ ...identityBase, editsFile: '' }),
|
||||
/editsFile must be a non-empty string when present/,
|
||||
);
|
||||
|
||||
fs.rmSync(directory, { recursive: true, force: true });
|
||||
console.log('road revision storage tests passed');
|
||||
|
||||
Reference in New Issue
Block a user