@ifc-lite/cli 0.20.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/commands/clash.d.ts.map +1 -1
- package/dist/commands/clash.js +8 -1
- package/dist/commands/clash.js.map +1 -1
- package/dist/commands/gym/channels.d.ts +28 -0
- package/dist/commands/gym/channels.d.ts.map +1 -0
- package/dist/commands/gym/channels.js +115 -0
- package/dist/commands/gym/channels.js.map +1 -0
- package/dist/commands/gym/episode.d.ts +36 -0
- package/dist/commands/gym/episode.d.ts.map +1 -0
- package/dist/commands/gym/episode.js +65 -0
- package/dist/commands/gym/episode.js.map +1 -0
- package/dist/commands/gym/ops.d.ts +37 -0
- package/dist/commands/gym/ops.d.ts.map +1 -0
- package/dist/commands/gym/ops.js +78 -0
- package/dist/commands/gym/ops.js.map +1 -0
- package/dist/commands/gym.d.ts +10 -0
- package/dist/commands/gym.d.ts.map +1 -0
- package/dist/commands/gym.js +324 -0
- package/dist/commands/gym.js.map +1 -0
- package/dist/commands/validate.d.ts +40 -0
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +155 -6
- package/dist/commands/validate.js.map +1 -1
- package/dist/hbjson-export.d.ts +37 -0
- package/dist/hbjson-export.d.ts.map +1 -0
- package/dist/hbjson-export.js +39 -0
- package/dist/hbjson-export.js.map +1 -0
- package/dist/headless-backend.d.ts.map +1 -1
- package/dist/headless-backend.js +4 -19
- package/dist/headless-backend.js.map +1 -1
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -1
- package/dist/output.d.ts +14 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +26 -0
- package/dist/output.js.map +1 -1
- package/package.json +17 -17
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/**
|
|
5
|
+
* `ifc-lite gym (--model <file.ifc> | --seed <n>) [--checks schema,clash,ids] [--ids <rules.xml>]`
|
|
6
|
+
*
|
|
7
|
+
* A reset/step/reward environment loop over the existing headless checks:
|
|
8
|
+
* the skeleton of an RLVR environment for buildings (docs/vision/moonshots-tech.md
|
|
9
|
+
* M2, docs/vision/moonshots-execution-plan.md B0.4). The environment wraps a
|
|
10
|
+
* model - either a fixed file (`--model`) or a procedurally generated World
|
|
11
|
+
* Gym episode (`--seed`, see `gym/episode.ts`) - and lets an agent apply
|
|
12
|
+
* data-mutation ops, scoring each step against the same schema/clash/ids
|
|
13
|
+
* checks the `validate`, `clash`, and `ids` commands already run.
|
|
14
|
+
* Geometry-creating ops are out of scope for v0, see "op vocabulary gaps"
|
|
15
|
+
* below.
|
|
16
|
+
*
|
|
17
|
+
* Protocol (newline-delimited JSON on stdout, one JSON command per stdin line):
|
|
18
|
+
*
|
|
19
|
+
* -> (on start) {"type":"reset","observation":{...},"channels":{...}}
|
|
20
|
+
* <- {"type":"step","ops":[{"op":"setProperty","expressId":42,"psetName":"Pset_WallCommon","propName":"IsExternal","value":true}]}
|
|
21
|
+
* -> {"type":"reward","channels":{...},"done":false}
|
|
22
|
+
* <- {"type":"reset"}
|
|
23
|
+
* -> {"type":"reset","observation":{...},"channels":{...}}
|
|
24
|
+
* <- {"type":"close"}
|
|
25
|
+
* -> (process exits 0, no reply line)
|
|
26
|
+
*
|
|
27
|
+
* Malformed input never crashes the process: it replies with a structured
|
|
28
|
+
* {"type":"error","message":"..."} line and keeps reading. A `step` batch is
|
|
29
|
+
* ATOMIC: it either fully applies (one `reward` line) or leaves the session
|
|
30
|
+
* exactly as it was (one `error` line) - a malformed op mid-batch never
|
|
31
|
+
* leaves earlier ops of the same batch applied.
|
|
32
|
+
*
|
|
33
|
+
* Episode factory (B2.2): instead of `--model`, `--seed <n>` generates a
|
|
34
|
+
* World Gym benchmark model in-process (tools/world-gym/generator.mjs,
|
|
35
|
+
* dynamically imported from the repo checkout - the published npm package
|
|
36
|
+
* does not ship the generator, so `--seed` fails there with a clear error
|
|
37
|
+
* while `--model` keeps working). `[--family frame|office|auto]` pins the
|
|
38
|
+
* family; corruption follows the benchmark's deterministic Bernoulli draw at
|
|
39
|
+
* the spec's corrupt rate (tools/world-gym/benchmark/splits.mjs) unless
|
|
40
|
+
* `--corrupt` / `--no-corrupt` forces it or `--corrupt-rate <p>` overrides
|
|
41
|
+
* the rate (forcing and a rate are mutually exclusive). Mid-session,
|
|
42
|
+
* `{"type":"reset","seed":8}` (plus optional "family"/"corrupt"/"corruptRate"
|
|
43
|
+
* fields) swaps to a fresh generated episode, so an RL consumer can stream
|
|
44
|
+
* the whole benchmark through one gym process without touching generator
|
|
45
|
+
* internals. Generated-episode reset lines carry an extra `episode` field:
|
|
46
|
+
* {seed, family, corrupted}. (The `corrupted` flag is deliberately exposed:
|
|
47
|
+
* the gym is the TRAINING surface; benchmark ground truth is regenerable
|
|
48
|
+
* from the seed anyway - see tools/world-gym/benchmark/BENCHMARK.md.)
|
|
49
|
+
*
|
|
50
|
+
* Determinism: the same model plus the same op sequence must yield
|
|
51
|
+
* byte-identical reward lines - see `gym/channels.ts` for the sorting and
|
|
52
|
+
* rounding contract. Reward shaping: every channel's `score` is in [0, 1]
|
|
53
|
+
* with higher-is-better (the clash channel scores 1 for clash-free and
|
|
54
|
+
* decreases as the clash count grows; the raw count is `totalClashes`).
|
|
55
|
+
*
|
|
56
|
+
* Mutation surface: v0 supports `setProperty` / `setAttribute` /
|
|
57
|
+
* `deleteProperty`, mirroring `bim.mutate`'s method names exactly (see
|
|
58
|
+
* `gym/ops.ts`). Ops are applied via `MutablePropertyView` + `StepExporter`
|
|
59
|
+
* (the same classes `ifc-lite mutate` uses) rather than through `bim.mutate`
|
|
60
|
+
* itself, because `HeadlessBackend.mutate` (packages/cli/src/headless-backend.ts)
|
|
61
|
+
* is currently a no-op stub: `bim.mutate.setProperty()` silently does
|
|
62
|
+
* nothing in headless mode. Wiring that backend up to the same
|
|
63
|
+
* MutablePropertyView this file drives is a mechanical follow-up, not a
|
|
64
|
+
* redesign, since the op vocabulary already matches.
|
|
65
|
+
*
|
|
66
|
+
* Each step re-exports the accumulated mutation overlay to STEP text and
|
|
67
|
+
* re-parses it into a fresh `IfcDataStore` before running checks. This is
|
|
68
|
+
* deliberate, not a perf shortcut we forgot to remove: `ids`/`clash`/the
|
|
69
|
+
* schema checks all read directly from an `IfcDataStore` (via
|
|
70
|
+
* `createDataAccessor(store)` / `EntityNode(store, id)`), with no
|
|
71
|
+
* mutation-overlay awareness, so a live overlay would silently be invisible
|
|
72
|
+
* to every check. Re-parsing after export guarantees the checks see exactly
|
|
73
|
+
* what a human re-opening the mutated file would see.
|
|
74
|
+
*
|
|
75
|
+
* Op vocabulary gaps (v0, tracked for a follow-up bet, not fixed here):
|
|
76
|
+
* - Ops target entities by `expressId`, not `GlobalId`. Stable within one
|
|
77
|
+
* gym session (StepExporter never renumbers existing entities), but a
|
|
78
|
+
* GlobalId-keyed op format would be more robust for agents that only
|
|
79
|
+
* ever see a model's IFC-standard identifiers.
|
|
80
|
+
* - `observation.bounds` is always `null`: no geometry pass runs on
|
|
81
|
+
* `reset`, and even the `clash` channel's mesh pass never feeds a
|
|
82
|
+
* bounding box back into the observation.
|
|
83
|
+
* - No entity-creation ops (new walls/slabs/etc. via `packages/create`) and
|
|
84
|
+
* no episode-termination signal (`done` is always `false`); both need a
|
|
85
|
+
* real reward-shaping design, not just wiring.
|
|
86
|
+
* - `bim.mutate.setProperty/setAttribute/deleteProperty` are no-ops on
|
|
87
|
+
* `HeadlessBackend` (see above); this file works around that directly
|
|
88
|
+
* rather than fixing the backend, to keep this bet's diff scoped to one
|
|
89
|
+
* new command.
|
|
90
|
+
*/
|
|
91
|
+
import { createInterface } from 'node:readline';
|
|
92
|
+
import { readFile } from 'node:fs/promises';
|
|
93
|
+
import { basename } from 'node:path';
|
|
94
|
+
import { loadIfcFile, loadIfcBytes } from '../loader.js';
|
|
95
|
+
import { getFlag, fatal } from '../output.js';
|
|
96
|
+
import { extractPropertiesOnDemand } from '@ifc-lite/parser';
|
|
97
|
+
import { MutablePropertyView } from '@ifc-lite/mutations';
|
|
98
|
+
import { StepExporter } from '@ifc-lite/export';
|
|
99
|
+
import { GeometryProcessor } from '@ifc-lite/geometry';
|
|
100
|
+
import { IDSNamespace } from '@ifc-lite/sdk';
|
|
101
|
+
import { KNOWN_CHECKS, computeSchemaChannel, computeClashChannel, computeIdsChannel, computeObservation, } from './gym/channels.js';
|
|
102
|
+
import { parseOp, applyOp } from './gym/ops.js';
|
|
103
|
+
import { generateEpisode, parseSeed, parseCorruptRate, } from './gym/episode.js';
|
|
104
|
+
const USAGE = 'Usage: ifc-lite gym (--model <file.ifc> | --seed <n> [--family frame|office|auto] [--corrupt|--no-corrupt|--corrupt-rate <p>]) [--checks schema,clash,ids] [--ids <rules.xml>] [--locale en|de|fr]';
|
|
105
|
+
const SUPPORTED_LOCALES = ['en', 'de', 'fr'];
|
|
106
|
+
function parseChecks(raw, idsPath) {
|
|
107
|
+
if (raw === undefined) {
|
|
108
|
+
return idsPath ? new Set(['schema', 'clash', 'ids']) : new Set(['schema', 'clash']);
|
|
109
|
+
}
|
|
110
|
+
const result = new Set();
|
|
111
|
+
for (const part of raw.split(',').map(s => s.trim()).filter(Boolean)) {
|
|
112
|
+
if (!KNOWN_CHECKS.includes(part)) {
|
|
113
|
+
fatal(`Unknown check "${part}" in --checks (supported: ${KNOWN_CHECKS.join(', ')})`);
|
|
114
|
+
}
|
|
115
|
+
result.add(part);
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
function parseLocale(raw) {
|
|
120
|
+
if (raw === undefined)
|
|
121
|
+
return 'en';
|
|
122
|
+
if (!SUPPORTED_LOCALES.includes(raw)) {
|
|
123
|
+
fatal(`Unsupported --locale "${raw}" (supported: ${SUPPORTED_LOCALES.join(', ')})`);
|
|
124
|
+
}
|
|
125
|
+
return raw;
|
|
126
|
+
}
|
|
127
|
+
export async function gymCommand(args, io = {}) {
|
|
128
|
+
const modelPath = getFlag(args, '--model');
|
|
129
|
+
const seedFlag = getFlag(args, '--seed');
|
|
130
|
+
if (!modelPath && seedFlag === undefined)
|
|
131
|
+
fatal(USAGE);
|
|
132
|
+
if (modelPath && seedFlag !== undefined)
|
|
133
|
+
fatal(`--model and --seed are mutually exclusive\n${USAGE}`);
|
|
134
|
+
const idsPath = getFlag(args, '--ids');
|
|
135
|
+
const checks = parseChecks(getFlag(args, '--checks'), idsPath);
|
|
136
|
+
const locale = parseLocale(getFlag(args, '--locale'));
|
|
137
|
+
const output = io.output ?? process.stdout;
|
|
138
|
+
const input = io.input ?? process.stdin;
|
|
139
|
+
function send(msg) {
|
|
140
|
+
output.write(`${JSON.stringify(msg)}\n`);
|
|
141
|
+
}
|
|
142
|
+
let modelId;
|
|
143
|
+
let originalStore;
|
|
144
|
+
let episode = null;
|
|
145
|
+
async function loadEpisode(spec) {
|
|
146
|
+
const { model, episode: info } = await generateEpisode(spec);
|
|
147
|
+
originalStore = await loadIfcBytes(new TextEncoder().encode(model.content), `gym-seed-${info.seed}.ifc`);
|
|
148
|
+
episode = info;
|
|
149
|
+
modelId = `gym-seed-${info.seed}.ifc`;
|
|
150
|
+
}
|
|
151
|
+
if (modelPath) {
|
|
152
|
+
modelId = basename(modelPath);
|
|
153
|
+
originalStore = await loadIfcFile(modelPath);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
const forceCorrupt = args.includes('--corrupt') ? true : args.includes('--no-corrupt') ? false : undefined;
|
|
157
|
+
const corruptRateFlag = getFlag(args, '--corrupt-rate');
|
|
158
|
+
if (forceCorrupt !== undefined && corruptRateFlag !== undefined) {
|
|
159
|
+
fatal(`--corrupt/--no-corrupt and --corrupt-rate are mutually exclusive\n${USAGE}`);
|
|
160
|
+
}
|
|
161
|
+
await loadEpisode({
|
|
162
|
+
seed: parseSeed(seedFlag, '--seed'),
|
|
163
|
+
family: getFlag(args, '--family') ?? 'auto',
|
|
164
|
+
forceCorrupt,
|
|
165
|
+
corruptRate: corruptRateFlag !== undefined ? parseCorruptRate(corruptRateFlag, '--corrupt-rate') : undefined,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
const ids = new IDSNamespace();
|
|
169
|
+
let idsDoc = null;
|
|
170
|
+
if (idsPath) {
|
|
171
|
+
const idsXml = await readFile(idsPath, 'utf-8');
|
|
172
|
+
idsDoc = await ids.parse(idsXml);
|
|
173
|
+
}
|
|
174
|
+
// Lazily initialised: wasm geometry init is only worth paying for when
|
|
175
|
+
// the "clash" channel is actually requested.
|
|
176
|
+
let processor = null;
|
|
177
|
+
async function getProcessor() {
|
|
178
|
+
if (!processor) {
|
|
179
|
+
// Assign only after init() succeeds: caching the instance before a
|
|
180
|
+
// failed init would hand every later call an uninitialized processor
|
|
181
|
+
// instead of retrying (the init throw itself surfaces as a structured
|
|
182
|
+
// error line on the step that requested the clash channel).
|
|
183
|
+
const p = new GeometryProcessor();
|
|
184
|
+
await p.init();
|
|
185
|
+
processor = p;
|
|
186
|
+
}
|
|
187
|
+
return processor;
|
|
188
|
+
}
|
|
189
|
+
function createMutationView() {
|
|
190
|
+
const view = new MutablePropertyView(null, 'default');
|
|
191
|
+
view.setOnDemandExtractor((entityId) => extractPropertiesOnDemand(originalStore, entityId));
|
|
192
|
+
return view;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The committed op journal: every op of every successfully rewarded step,
|
|
196
|
+
* in order. `step` batches are atomic - a failing batch (malformed op,
|
|
197
|
+
* export/parse failure, channel failure) must leave the session exactly as
|
|
198
|
+
* it was - so the journal is the single source of truth and the view is
|
|
199
|
+
* rebuilt from it whenever a batch fails partway through.
|
|
200
|
+
*/
|
|
201
|
+
let journal = [];
|
|
202
|
+
let mutationView = createMutationView();
|
|
203
|
+
function rebuildViewFromJournal() {
|
|
204
|
+
mutationView = createMutationView();
|
|
205
|
+
for (const op of journal)
|
|
206
|
+
applyOp(mutationView, op);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Materialise the current mutation overlay into a fresh, independently
|
|
210
|
+
* parsed store. See the module doc for why re-export + re-parse is
|
|
211
|
+
* required rather than reading through the overlay directly.
|
|
212
|
+
*/
|
|
213
|
+
async function materializeStore() {
|
|
214
|
+
const schema = (originalStore.schemaVersion ?? 'IFC4');
|
|
215
|
+
const exporter = new StepExporter(originalStore, mutationView);
|
|
216
|
+
const result = exporter.export({ schema, applyMutations: true });
|
|
217
|
+
return loadIfcBytes(result.content, modelId);
|
|
218
|
+
}
|
|
219
|
+
async function computeChannels(store) {
|
|
220
|
+
const channels = {};
|
|
221
|
+
// Fixed canonical key order regardless of --checks argument order, so
|
|
222
|
+
// two runs requesting the same set in a different order still produce
|
|
223
|
+
// byte-identical JSON.
|
|
224
|
+
if (checks.has('schema'))
|
|
225
|
+
channels.schema = computeSchemaChannel(store);
|
|
226
|
+
if (checks.has('clash'))
|
|
227
|
+
channels.clash = await computeClashChannel(store, await getProcessor(), modelId);
|
|
228
|
+
if (checks.has('ids'))
|
|
229
|
+
channels.ids = await computeIdsChannel(store, ids, idsDoc, locale);
|
|
230
|
+
return channels;
|
|
231
|
+
}
|
|
232
|
+
/** Apply a step batch atomically: on ANY failure, restore the pre-batch state. */
|
|
233
|
+
async function stepBatch(rawOps) {
|
|
234
|
+
// Phase 1: validate the whole batch before anything is applied.
|
|
235
|
+
const ops = rawOps.map(raw => parseOp(raw));
|
|
236
|
+
// Phase 2: apply + materialize + score; roll back to the journal on failure.
|
|
237
|
+
try {
|
|
238
|
+
for (const op of ops)
|
|
239
|
+
applyOp(mutationView, op);
|
|
240
|
+
const store = await materializeStore();
|
|
241
|
+
const channels = await computeChannels(store);
|
|
242
|
+
journal.push(...ops);
|
|
243
|
+
return channels;
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
rebuildViewFromJournal();
|
|
247
|
+
throw err;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async function emitReset() {
|
|
251
|
+
journal = [];
|
|
252
|
+
mutationView = createMutationView();
|
|
253
|
+
const observation = computeObservation(originalStore);
|
|
254
|
+
const channels = await computeChannels(originalStore);
|
|
255
|
+
// `episode` only exists for generated episodes; --model resets keep the
|
|
256
|
+
// exact v0 payload shape for backward compatibility.
|
|
257
|
+
send(episode ? { type: 'reset', episode, observation, channels } : { type: 'reset', observation, channels });
|
|
258
|
+
}
|
|
259
|
+
await emitReset();
|
|
260
|
+
const rl = createInterface({ input, terminal: false, crlfDelay: Infinity });
|
|
261
|
+
// A broken pipe on stdout or a stdin failure must end the loop cleanly,
|
|
262
|
+
// not take the process down with an uncaught 'error' emitter event.
|
|
263
|
+
const onStreamError = () => {
|
|
264
|
+
rl.close();
|
|
265
|
+
};
|
|
266
|
+
input.on('error', onStreamError);
|
|
267
|
+
output.on('error', onStreamError);
|
|
268
|
+
for await (const line of rl) {
|
|
269
|
+
const trimmed = line.trim();
|
|
270
|
+
if (!trimmed)
|
|
271
|
+
continue;
|
|
272
|
+
let msg;
|
|
273
|
+
try {
|
|
274
|
+
msg = JSON.parse(trimmed);
|
|
275
|
+
}
|
|
276
|
+
catch (err) {
|
|
277
|
+
send({ type: 'error', message: `Malformed JSON: ${err.message}` });
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
const type = typeof msg === 'object' && msg !== null ? msg.type : undefined;
|
|
281
|
+
try {
|
|
282
|
+
if (type === 'step') {
|
|
283
|
+
const ops = msg.ops;
|
|
284
|
+
if (!Array.isArray(ops))
|
|
285
|
+
throw new Error('"step" command needs an "ops" array');
|
|
286
|
+
const channels = await stepBatch(ops);
|
|
287
|
+
send({ type: 'reward', channels, done: false });
|
|
288
|
+
}
|
|
289
|
+
else if (type === 'reset') {
|
|
290
|
+
const m = msg;
|
|
291
|
+
if (m.seed !== undefined) {
|
|
292
|
+
// New generated episode over the same protocol (episode factory).
|
|
293
|
+
if (m.family !== undefined && typeof m.family !== 'string') {
|
|
294
|
+
throw new Error('reset field "family" must be a string (frame|office|auto)');
|
|
295
|
+
}
|
|
296
|
+
if (m.corrupt !== undefined && typeof m.corrupt !== 'boolean') {
|
|
297
|
+
throw new Error('reset field "corrupt" must be a boolean');
|
|
298
|
+
}
|
|
299
|
+
if (m.corrupt !== undefined && m.corruptRate !== undefined) {
|
|
300
|
+
throw new Error('reset fields "corrupt" and "corruptRate" are mutually exclusive');
|
|
301
|
+
}
|
|
302
|
+
await loadEpisode({
|
|
303
|
+
seed: parseSeed(m.seed, 'reset field "seed"'),
|
|
304
|
+
family: m.family ?? 'auto',
|
|
305
|
+
forceCorrupt: m.corrupt,
|
|
306
|
+
corruptRate: m.corruptRate !== undefined ? parseCorruptRate(m.corruptRate, 'reset field "corruptRate"') : undefined,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
await emitReset();
|
|
310
|
+
}
|
|
311
|
+
else if (type === 'close') {
|
|
312
|
+
rl.close();
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
send({ type: 'error', message: `Unknown command type: ${JSON.stringify(type ?? null)}` });
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
catch (err) {
|
|
320
|
+
send({ type: 'error', message: err.message });
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
//# sourceMappingURL=gym.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gym.js","sourceRoot":"","sources":["../../src/commands/gym.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,42 @@
|
|
|
1
|
+
import { type IfcDataStore } from '@ifc-lite/parser';
|
|
2
|
+
export interface ValidationIssue {
|
|
3
|
+
severity: 'error' | 'warning' | 'info';
|
|
4
|
+
rule: string;
|
|
5
|
+
message: string;
|
|
6
|
+
/** Referencing entity's expressId (set by per-reference rules like reference-integrity). */
|
|
7
|
+
entityId?: number;
|
|
8
|
+
/** Zero-based top-level attribute slot of the offending value within the referencing entity. */
|
|
9
|
+
attributeIndex?: number;
|
|
10
|
+
/** The referenced expressId that does not exist in the file. */
|
|
11
|
+
target?: number;
|
|
12
|
+
}
|
|
13
|
+
/** One `#N` reference whose target expressId does not exist in the file. */
|
|
14
|
+
interface DanglingReference {
|
|
15
|
+
/** expressId of the entity containing the reference. */
|
|
16
|
+
entityId: number;
|
|
17
|
+
/** STEP type name of the referencing entity (UPPERCASE, as scanned). */
|
|
18
|
+
entityType: string;
|
|
19
|
+
/** Zero-based top-level attribute slot the reference sits in (nested refs report their containing slot). */
|
|
20
|
+
attributeIndex: number;
|
|
21
|
+
/** The missing expressId being referenced. */
|
|
22
|
+
target: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Walk every indexed entity record and collect `#N` references whose target
|
|
26
|
+
* does not exist in the file (rule `reference-integrity`). Uses the parsed
|
|
27
|
+
* entity index for both iteration and existence checks; entities held in the
|
|
28
|
+
* deferred index (lazily-parsed property entities) count as existing and are
|
|
29
|
+
* scanned too.
|
|
30
|
+
*/
|
|
31
|
+
export declare function collectDanglingReferences(store: IfcDataStore): DanglingReference[];
|
|
32
|
+
/**
|
|
33
|
+
* Run the structural validation checks (required entities, storeys, GlobalId
|
|
34
|
+
* uniqueness, naming, schema version, quantity completeness, reference
|
|
35
|
+
* integrity) against an already-parsed store. Pulled out of
|
|
36
|
+
* {@link validateCommand} so other consumers (tests, harnesses) reuse the
|
|
37
|
+
* exact same rules instead of re-implementing them.
|
|
38
|
+
*/
|
|
39
|
+
export declare function computeValidationIssues(store: IfcDataStore): ValidationIssue[];
|
|
1
40
|
export declare function validateCommand(args: string[]): Promise<void>;
|
|
41
|
+
export {};
|
|
2
42
|
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAgC,KAAK,YAAY,EAAkB,MAAM,kBAAkB,CAAC;AAEnG,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gGAAgG;IAChG,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,4EAA4E;AAC5E,UAAU,iBAAiB;IACzB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,4GAA4G;IAC5G,cAAc,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAuFD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,EAAE,CAmBlF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,YAAY,GAAG,eAAe,EAAE,CA2H9E;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCnE"}
|
|
@@ -10,17 +10,132 @@
|
|
|
10
10
|
* - Spatial structure completeness
|
|
11
11
|
* - Orphan entity detection
|
|
12
12
|
* - GlobalId uniqueness
|
|
13
|
+
* - Reference integrity (#N references that point at no entity)
|
|
13
14
|
*/
|
|
14
15
|
import { loadIfcFile } from '../loader.js';
|
|
15
16
|
import { hasFlag, fatal, printJson } from '../output.js';
|
|
16
17
|
import { EntityNode } from '@ifc-lite/query';
|
|
17
18
|
import { getInheritanceChainForEntity } from '@ifc-lite/parser';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
/** Cap on individually-reported dangling references; the remainder is rolled into one summary issue. */
|
|
20
|
+
const DANGLING_REF_ISSUE_CAP = 50;
|
|
21
|
+
const CH_QUOTE = 0x27; // '
|
|
22
|
+
const CH_LPAREN = 0x28; // (
|
|
23
|
+
const CH_RPAREN = 0x29; // )
|
|
24
|
+
const CH_COMMA = 0x2c; // ,
|
|
25
|
+
const CH_HASH = 0x23; // #
|
|
26
|
+
const CH_SLASH = 0x2f; // /
|
|
27
|
+
const CH_STAR = 0x2a; // *
|
|
28
|
+
/**
|
|
29
|
+
* Scan one entity record's source bytes for `#N` attribute references and
|
|
30
|
+
* report the ones whose target expressId is not indexed. Operates directly on
|
|
31
|
+
* the raw bytes the parser already indexed (`store.entityIndex.byId` spans),
|
|
32
|
+
* so it is a single pass over each record with no string allocation. Quote
|
|
33
|
+
* tracking (including STEP's doubled-quote escape) keeps `#N` sequences inside
|
|
34
|
+
* string literals from being read as references; embedded STEP comments are
|
|
35
|
+
* skipped.
|
|
36
|
+
*/
|
|
37
|
+
function scanEntityForDanglingRefs(source, ref, exists, out) {
|
|
38
|
+
const end = ref.byteOffset + ref.byteLength;
|
|
39
|
+
// References only occur inside the attribute list; skip the "#id = TYPE" prefix.
|
|
40
|
+
let i = ref.byteOffset;
|
|
41
|
+
while (i < end && source[i] !== CH_LPAREN)
|
|
42
|
+
i++;
|
|
43
|
+
if (i >= end)
|
|
44
|
+
return; // malformed record, nothing to scan
|
|
45
|
+
let depth = 1; // we are inside the outermost '(' now
|
|
46
|
+
let attrIndex = 0;
|
|
47
|
+
i++;
|
|
48
|
+
while (i < end) {
|
|
49
|
+
const c = source[i];
|
|
50
|
+
if (c === CH_QUOTE) {
|
|
51
|
+
// String literal: skip to the closing quote, honouring '' escapes.
|
|
52
|
+
i++;
|
|
53
|
+
while (i < end) {
|
|
54
|
+
if (source[i] === CH_QUOTE) {
|
|
55
|
+
if (i + 1 < end && source[i + 1] === CH_QUOTE) {
|
|
56
|
+
i += 2; // escaped quote, still inside the string
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
break; // closing quote
|
|
60
|
+
}
|
|
61
|
+
i++;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else if (c === CH_SLASH && i + 1 < end && source[i + 1] === CH_STAR) {
|
|
65
|
+
// STEP comment inside a record (rare but legal): skip to closing marker.
|
|
66
|
+
i += 2;
|
|
67
|
+
while (i + 1 < end && !(source[i] === CH_STAR && source[i + 1] === CH_SLASH))
|
|
68
|
+
i++;
|
|
69
|
+
i++; // lands on '/', loop increment moves past it
|
|
70
|
+
}
|
|
71
|
+
else if (c === CH_LPAREN) {
|
|
72
|
+
depth++;
|
|
73
|
+
}
|
|
74
|
+
else if (c === CH_RPAREN) {
|
|
75
|
+
depth--;
|
|
76
|
+
if (depth === 0)
|
|
77
|
+
return; // end of attribute list
|
|
78
|
+
}
|
|
79
|
+
else if (c === CH_COMMA && depth === 1) {
|
|
80
|
+
attrIndex++;
|
|
81
|
+
}
|
|
82
|
+
else if (c === CH_HASH) {
|
|
83
|
+
let id = 0;
|
|
84
|
+
let digits = 0;
|
|
85
|
+
let j = i + 1;
|
|
86
|
+
while (j < end) {
|
|
87
|
+
const d = source[j] - 0x30;
|
|
88
|
+
if (d < 0 || d > 9)
|
|
89
|
+
break;
|
|
90
|
+
id = id * 10 + d;
|
|
91
|
+
digits++;
|
|
92
|
+
j++;
|
|
93
|
+
}
|
|
94
|
+
if (digits > 0) {
|
|
95
|
+
if (!exists(id)) {
|
|
96
|
+
out.push({ entityId: ref.expressId, entityType: ref.type, attributeIndex: attrIndex, target: id });
|
|
97
|
+
}
|
|
98
|
+
i = j - 1; // loop increment moves past the last digit
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
i++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Walk every indexed entity record and collect `#N` references whose target
|
|
106
|
+
* does not exist in the file (rule `reference-integrity`). Uses the parsed
|
|
107
|
+
* entity index for both iteration and existence checks; entities held in the
|
|
108
|
+
* deferred index (lazily-parsed property entities) count as existing and are
|
|
109
|
+
* scanned too.
|
|
110
|
+
*/
|
|
111
|
+
export function collectDanglingReferences(store) {
|
|
112
|
+
const source = store.source;
|
|
113
|
+
const byId = store.entityIndex.byId;
|
|
114
|
+
const deferred = store.deferredEntityIndex;
|
|
115
|
+
if (!source || source.byteLength === 0 || !byId)
|
|
116
|
+
return [];
|
|
117
|
+
const exists = (id) => byId.has(id) || deferred?.has(id) === true;
|
|
118
|
+
const out = [];
|
|
119
|
+
for (const ref of byId.values()) {
|
|
120
|
+
scanEntityForDanglingRefs(source, ref, exists, out);
|
|
121
|
+
}
|
|
122
|
+
if (deferred) {
|
|
123
|
+
for (const ref of deferred.values()) {
|
|
124
|
+
if (byId.has(ref.expressId))
|
|
125
|
+
continue; // already scanned above
|
|
126
|
+
scanEntityForDanglingRefs(source, ref, exists, out);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return out;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Run the structural validation checks (required entities, storeys, GlobalId
|
|
133
|
+
* uniqueness, naming, schema version, quantity completeness, reference
|
|
134
|
+
* integrity) against an already-parsed store. Pulled out of
|
|
135
|
+
* {@link validateCommand} so other consumers (tests, harnesses) reuse the
|
|
136
|
+
* exact same rules instead of re-implementing them.
|
|
137
|
+
*/
|
|
138
|
+
export function computeValidationIssues(store) {
|
|
24
139
|
const issues = [];
|
|
25
140
|
// 1. Check required spatial entities
|
|
26
141
|
const requiredTypes = ['IFCPROJECT', 'IFCSITE', 'IFCBUILDING'];
|
|
@@ -114,6 +229,40 @@ export async function validateCommand(args) {
|
|
|
114
229
|
message: `${withoutQuantities}/${totalQuantifiable} building elements (${pct}%) have no quantity sets — quantity-based analysis may be incomplete`,
|
|
115
230
|
});
|
|
116
231
|
}
|
|
232
|
+
// 7. Reference integrity: every #N attribute reference must resolve to an
|
|
233
|
+
// entity that exists in the file. A dangling reference is structurally
|
|
234
|
+
// broken data (consumers following it get nothing, or worse, garbage), so
|
|
235
|
+
// it reports as an error like unique-globalid does.
|
|
236
|
+
const dangling = collectDanglingReferences(store);
|
|
237
|
+
for (const d of dangling.slice(0, DANGLING_REF_ISSUE_CAP)) {
|
|
238
|
+
// Display names render in IFC PascalCase (IfcWall, not IFCWALL); the
|
|
239
|
+
// collector carries the raw STEP token, so resolve through the table.
|
|
240
|
+
const typeName = store.entities.getTypeName(d.entityId) || d.entityType;
|
|
241
|
+
issues.push({
|
|
242
|
+
severity: 'error',
|
|
243
|
+
rule: 'reference-integrity',
|
|
244
|
+
message: `#${d.entityId} ${typeName} attribute ${d.attributeIndex} references missing entity #${d.target}`,
|
|
245
|
+
entityId: d.entityId,
|
|
246
|
+
attributeIndex: d.attributeIndex,
|
|
247
|
+
target: d.target,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
if (dangling.length > DANGLING_REF_ISSUE_CAP) {
|
|
251
|
+
issues.push({
|
|
252
|
+
severity: 'error',
|
|
253
|
+
rule: 'reference-integrity',
|
|
254
|
+
message: `${dangling.length - DANGLING_REF_ISSUE_CAP} more dangling reference(s) not listed (${dangling.length} total)`,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return issues;
|
|
258
|
+
}
|
|
259
|
+
export async function validateCommand(args) {
|
|
260
|
+
const filePath = args.find(a => !a.startsWith('-'));
|
|
261
|
+
if (!filePath)
|
|
262
|
+
fatal('Usage: ifc-lite validate <file.ifc> [--json]');
|
|
263
|
+
const jsonOutput = hasFlag(args, '--json');
|
|
264
|
+
const store = await loadIfcFile(filePath);
|
|
265
|
+
const issues = computeValidationIssues(store);
|
|
117
266
|
const summary = {
|
|
118
267
|
file: filePath,
|
|
119
268
|
schema: store.schemaVersion,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HBJSON export for `HeadlessBackend` (issue #1908).
|
|
3
|
+
*
|
|
4
|
+
* Split out of `headless-backend.ts` (already over the ~400-line module
|
|
5
|
+
* guideline) rather than inlined there. HBJSON is rebuilt analytically from
|
|
6
|
+
* IFC STEP bytes (rooms/openings/shades/constructions/adjacency) via the
|
|
7
|
+
* wasm geometry engine. When the mutation view carries actual edits
|
|
8
|
+
* (`mutationView.hasPendingChanges()` — e.g. `bim.store.addSpace` /
|
|
9
|
+
* `bim.spaces.generate` ran earlier in this session), bytes are regenerated
|
|
10
|
+
* through `StepExporter` first — the same mutation-view application the
|
|
11
|
+
* `ifc:` STEP export adapter already uses in `headless-backend.ts` — so
|
|
12
|
+
* overlay-authored entities (drawn spaces, in particular) are visible to the
|
|
13
|
+
* analytic exporter. A mutation view with no pending changes (the common
|
|
14
|
+
* case — `getOrCreateStoreEditor` can register a view before any edit lands,
|
|
15
|
+
* e.g. `bim.store.removeEntity` on an id that doesn't exist still allocates
|
|
16
|
+
* one) falls straight through to `store.source`, unchanged from before this
|
|
17
|
+
* fix.
|
|
18
|
+
*
|
|
19
|
+
* `hasPendingChanges()`, not `hasChanges()`: the latter reads the
|
|
20
|
+
* append-only `mutationHistory`, which `restoreNewEntity` repopulates
|
|
21
|
+
* `newEntities` WITHOUT pushing to (it's the undo-of-delete path for an
|
|
22
|
+
* overlay-created entity). `hasPendingChanges()` reads the current overlay
|
|
23
|
+
* footprint instead — the same set `StepExporter` actually serializes — so a
|
|
24
|
+
* restored overlay-created space is not silently missed.
|
|
25
|
+
*
|
|
26
|
+
* No IFC5/IFCX guard here (unlike the viewer's `resolveHbjsonMutationSource`,
|
|
27
|
+
* which excludes `schemaVersion === 'IFC5'`): `loader.ts` only ever parses
|
|
28
|
+
* with `IfcParser` (the STEP/columnar parser) and never constructs an
|
|
29
|
+
* IFCX/IFC5 data store, so a CLI-loaded `IfcDataStore` cannot carry IFC5
|
|
30
|
+
* content to regenerate in the first place. The `ifc:` STEP-export adapter
|
|
31
|
+
* directly above this one in `headless-backend.ts` makes the same assumption
|
|
32
|
+
* (it applies `mutationView` unconditionally, with no schema check).
|
|
33
|
+
*/
|
|
34
|
+
import type { IfcDataStore } from '@ifc-lite/parser';
|
|
35
|
+
import type { MutablePropertyView } from '@ifc-lite/mutations';
|
|
36
|
+
export declare function exportHbjson(store: IfcDataStore, mutationView: MutablePropertyView | null, name: string): Promise<string>;
|
|
37
|
+
//# sourceMappingURL=hbjson-export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hbjson-export.d.ts","sourceRoot":"","sources":["../src/hbjson-export.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAI/D,wBAAsB,YAAY,CAChC,KAAK,EAAE,YAAY,EACnB,YAAY,EAAE,mBAAmB,GAAG,IAAI,EACxC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,CAAC,CA+BjB"}
|