@ifc-lite/cli 0.19.0 → 0.21.0

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 CHANGED
@@ -41,10 +41,43 @@ ifc-lite view model.ifc
41
41
  - `view` - interactive 3D viewer in the browser, controllable via REST (`/api/command`)
42
42
  - `analyze` - query plus colorize/isolate/heatmap results in the running viewer
43
43
  - `mcp` - start an MCP server bound to one or more IFC files (stdio or http)
44
+ - `gym` - reset/step/reward environment loop over the existing schema/clash/ids checks (see below)
44
45
  - `schema`, `bsdd`, `diagnose-geometry`, `extract-entities`, `generate-spaces`, `lod`, `ext` - see `ifc-lite --help`
45
46
 
46
47
  Global flags: `--json`, `--out <file>`, `--verbose`, `--quiet`, `--debug`, `--log-level <level>`.
47
48
 
49
+ ## gym
50
+
51
+ `ifc-lite gym` is a prototype reset/step/reward environment API over the existing headless checks: the skeleton of an RLVR environment for buildings (see [`docs/vision/moonshots-tech.md`](../../docs/vision/moonshots-tech.md) M2 and [`docs/vision/moonshots-execution-plan.md`](../../docs/vision/moonshots-execution-plan.md) B0.4). It wraps a model - either a fixed file (`--model`) or a procedurally generated World Gym episode (`--seed`) - and lets an agent apply data-mutation ops, scoring each step against the same schema/clash/ids checks the `validate`, `clash`, and `ids` commands already run.
52
+
53
+ ```bash
54
+ ifc-lite gym --model model.ifc --checks schema,clash
55
+ ifc-lite gym --model model.ifc --checks schema,clash,ids --ids rules.ids
56
+ ifc-lite gym --seed 42 --checks schema,clash # generated episode (repo checkout only)
57
+ ifc-lite gym --seed 8 --family frame --corrupt --checks schema
58
+ ```
59
+
60
+ The protocol is newline-delimited JSON: one JSON object per line, in both directions.
61
+
62
+ - On start, `gym` prints one line: `{"type":"reset","observation":{...},"channels":{...}}`. `observation` has sorted `entityCounts` (by IFC type), `storeyCount`, and `schema` version. `bounds` is always `null` in v0 (a known gap: no geometry pass runs on `reset`, see below). Generated episodes add an `episode` field: `{seed, family, corrupted}`.
63
+ - Send `{"type":"step","ops":[...]}` on stdin to apply ops and score the result. `gym` replies `{"type":"reward","channels":{...},"done":false}`. A step batch is atomic: it either fully applies or (on any malformed op or scoring failure) leaves the session unchanged and replies with an error line.
64
+ - Send `{"type":"reset"}` to reload the pristine model; replies like the initial reset.
65
+ - Send `{"type":"reset","seed":8}` (optional `family`, `corrupt` OR `corruptRate`) to swap to a fresh generated episode mid-session.
66
+ - Send `{"type":"close"}` to exit 0.
67
+ - Malformed JSON or an unknown command/op never crashes the process: it replies `{"type":"error","message":"..."}` and keeps reading.
68
+
69
+ Episode factory: `--seed <n>` generates a deterministic World Gym benchmark model in-process instead of loading a file. `--family frame|office|auto` pins the family; corruption follows the benchmark's deterministic draw at the spec's corrupt rate unless `--corrupt`/`--no-corrupt` forces it or `--corrupt-rate <p>` overrides the rate (forcing and a rate are mutually exclusive). The generator is dynamically imported from a repo checkout (`tools/world-gym/`); the published npm package prints a clear error for `--seed` while `--model` keeps working.
70
+
71
+ Reward shaping: every channel's `score` is in `[0, 1]` and higher is better. The clash channel scores `1` for a clash-free model and strictly decreases as the clash count grows (the raw count is reported separately as `totalClashes`), so an agent maximizing any channel is never rewarded for making the model worse.
72
+
73
+ v0 ops mirror `bim.mutate`'s method names exactly: `setProperty`, `setAttribute`, `deleteProperty` (all keyed by `expressId`). Geometry-creating ops (new walls, slabs, etc.) are out of scope for v0.
74
+
75
+ ```json
76
+ {"type":"step","ops":[{"op":"setProperty","expressId":42,"psetName":"Pset_WallCommon","propName":"IsExternal","value":true}]}
77
+ ```
78
+
79
+ Determinism: the same model plus the same op sequence yields byte-identical reward lines (sorted arrays, no timestamps, fixed-precision floats).
80
+
48
81
  ## Links
49
82
 
50
83
  - Docs: https://ifclite.dev/docs/
@@ -1 +1 @@
1
- {"version":3,"file":"clash.d.ts","sourceRoot":"","sources":["../../src/commands/clash.ts"],"names":[],"mappings":"AA2JA,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA+DhE"}
1
+ {"version":3,"file":"clash.d.ts","sourceRoot":"","sources":["../../src/commands/clash.ts"],"names":[],"mappings":"AA2JA,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuEhE"}
@@ -13,7 +13,7 @@
13
13
  import { readFile, writeFile } from 'node:fs/promises';
14
14
  import { basename } from 'node:path';
15
15
  import { createHeadlessContext } from '../loader.js';
16
- import { getFlag, hasFlag, fatal, printJson } from '../output.js';
16
+ import { getFlag, hasFlag, fatal, printJson, routeConsoleDiagnosticsToStderr } from '../output.js';
17
17
  import { GeometryProcessor } from '@ifc-lite/geometry';
18
18
  import { createClashEngine, disciplineMatrixRules, groupClashes, } from '@ifc-lite/clash';
19
19
  import { elementsFromStep } from '@ifc-lite/clash/step';
@@ -129,6 +129,13 @@ function printHumanSummary(result) {
129
129
  process.stdout.write('\n');
130
130
  }
131
131
  export async function clashCommand(args) {
132
+ // The geometry/opening pipeline (including wasm print bindings captured at
133
+ // module init) writes "[IFC-LITE] ..." diagnostics via console.log/info,
134
+ // which land on stdout and corrupt the --json payload (consumers were forced
135
+ // to scrape the trailing JSON). Route ALL console diagnostics to stderr for
136
+ // the whole run - before any wasm init - so stdout carries exactly one JSON
137
+ // document (or the human summary) and nothing else.
138
+ routeConsoleDiagnosticsToStderr();
132
139
  const filePath = args.find(a => !a.startsWith('-'));
133
140
  if (!filePath) {
134
141
  fatal('Usage: ifc-lite clash <file.ifc> [--a <selector>] [--b <selector>] [--mode hard|clearance] [--tolerance N] [--clearance N] [--matrix] [--bcf <out.bcfzip>] [--group cluster|rule|typePair|element] [--bcf-status <status>] [--max-topics N] [--json]');
@@ -1 +1 @@
1
- {"version":3,"file":"clash.js","sourceRoot":"","sources":["../../src/commands/clash.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"clash.js","sourceRoot":"","sources":["../../src/commands/clash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The `ifc-lite gym` reward channels (schema/clash/ids) and the reset
3
+ * observation. Every channel's `score` is shaped so that HIGHER IS BETTER,
4
+ * in [0, 1] - an agent maximizing any channel is always pushed toward a
5
+ * healthier model. Determinism contract: every array is explicitly sorted
6
+ * and every fractional number is rounded to a fixed number of decimals, so
7
+ * the same store yields byte-identical channel payloads.
8
+ */
9
+ import type { IfcDataStore } from '@ifc-lite/parser';
10
+ import { GeometryProcessor } from '@ifc-lite/geometry';
11
+ import { IDSNamespace, type IDSSupportedLocale } from '@ifc-lite/sdk';
12
+ /** Reward channels this prototype knows how to compute. */
13
+ export type GymCheck = 'schema' | 'clash' | 'ids';
14
+ export declare const KNOWN_CHECKS: GymCheck[];
15
+ export declare function round(value: number, decimals?: number): number;
16
+ export declare function computeSchemaChannel(store: IfcDataStore): Record<string, unknown>;
17
+ /**
18
+ * Reward shaping for the clash channel: 1 for a clash-free model, strictly
19
+ * decreasing toward 0 as the clash count grows. Keeping the raw count as a
20
+ * separate `totalClashes` field means consumers wanting the magnitude still
21
+ * get it, while the `score` field is safe to maximize (matching the schema
22
+ * and ids channels, where higher is always better).
23
+ */
24
+ export declare function clashScoreFromCount(totalClashes: number): number;
25
+ export declare function computeClashChannel(store: IfcDataStore, processor: GeometryProcessor, modelId: string): Promise<Record<string, unknown>>;
26
+ export declare function computeIdsChannel(store: IfcDataStore, ids: IDSNamespace, idsDoc: unknown, locale: IDSSupportedLocale): Promise<Record<string, unknown>>;
27
+ export declare function computeObservation(store: IfcDataStore): Record<string, unknown>;
28
+ //# sourceMappingURL=channels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.d.ts","sourceRoot":"","sources":["../../../src/commands/gym/channels.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAiB,MAAM,oBAAoB,CAAC;AAItE,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGtE,2DAA2D;AAC3D,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;AAClD,eAAO,MAAM,YAAY,EAAE,QAAQ,EAA+B,CAAC;AAEnE,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAGzD;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASjF;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAmC9I;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,YAAY,EACnB,GAAG,EAAE,YAAY,EACjB,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAiClC;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoB/E"}
@@ -0,0 +1,115 @@
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
+ import { createClashEngine } from '@ifc-lite/clash';
5
+ import { elementsFromStep } from '@ifc-lite/clash/step';
6
+ import { createDataAccessor } from '@ifc-lite/ids/bridge';
7
+ import { computeValidationIssues } from '../validate.js';
8
+ export const KNOWN_CHECKS = ['schema', 'clash', 'ids'];
9
+ export function round(value, decimals = 6) {
10
+ const factor = 10 ** decimals;
11
+ return Math.round(value * factor) / factor;
12
+ }
13
+ export function computeSchemaChannel(store) {
14
+ const issues = computeValidationIssues(store)
15
+ .slice()
16
+ .sort((a, b) => (a.rule === b.rule ? a.message.localeCompare(b.message) : a.rule.localeCompare(b.rule)));
17
+ const errors = issues.filter(i => i.severity === 'error').length;
18
+ const warnings = issues.filter(i => i.severity === 'warning').length;
19
+ const info = issues.filter(i => i.severity === 'info').length;
20
+ const score = errors > 0 ? 0 : warnings > 0 ? 0.5 : 1;
21
+ return { score, errors, warnings, info, issues };
22
+ }
23
+ /**
24
+ * Reward shaping for the clash channel: 1 for a clash-free model, strictly
25
+ * decreasing toward 0 as the clash count grows. Keeping the raw count as a
26
+ * separate `totalClashes` field means consumers wanting the magnitude still
27
+ * get it, while the `score` field is safe to maximize (matching the schema
28
+ * and ids channels, where higher is always better).
29
+ */
30
+ export function clashScoreFromCount(totalClashes) {
31
+ return round(1 / (1 + totalClashes));
32
+ }
33
+ export async function computeClashChannel(store, processor, modelId) {
34
+ const bytes = store.source;
35
+ if (!bytes || bytes.byteLength === 0) {
36
+ return { score: null, error: 'clash check needs source bytes, which the current store did not retain' };
37
+ }
38
+ const result = await processor.process(bytes);
39
+ const meshes = result.meshes;
40
+ const { elements, exclusions } = elementsFromStep({ store, meshes, modelId });
41
+ // v0 default: a single self-clash rule across every element, matching
42
+ // `ifc-lite clash` with no `--matrix`/`--a`/`--b` flags.
43
+ const rules = [{ id: 'gym-self-clash', name: '* self-clash', a: '*', mode: 'hard' }];
44
+ const engine = createClashEngine({ backend: 'ts' });
45
+ const clashResult = await engine.run(elements, rules, { exclusions });
46
+ const sorted = clashResult.clashes.slice().sort((a, b) => {
47
+ if (a.a.key !== b.a.key)
48
+ return a.a.key < b.a.key ? -1 : 1;
49
+ if (a.b.key !== b.b.key)
50
+ return a.b.key < b.b.key ? -1 : 1;
51
+ return a.distance - b.distance;
52
+ });
53
+ return {
54
+ score: clashScoreFromCount(clashResult.summary.total),
55
+ totalClashes: clashResult.summary.total,
56
+ bySeverity: clashResult.summary.bySeverity,
57
+ top: sorted.slice(0, 20).map(c => ({
58
+ a: c.a.key,
59
+ aTag: c.a.tag,
60
+ b: c.b.key,
61
+ bTag: c.b.tag,
62
+ severity: c.severity,
63
+ status: c.status,
64
+ distance: round(c.distance),
65
+ })),
66
+ };
67
+ }
68
+ export async function computeIdsChannel(store, ids, idsDoc, locale) {
69
+ if (!idsDoc) {
70
+ return { score: null, error: 'ids check requested but --ids <rules.xml> was not provided' };
71
+ }
72
+ const accessor = createDataAccessor(store);
73
+ const report = (await ids.validate(idsDoc, {
74
+ accessor,
75
+ modelInfo: { schemaVersion: store.schemaVersion },
76
+ locale,
77
+ includePassingEntities: false,
78
+ }));
79
+ const summary = report.summary;
80
+ const passRatio = summary.totalEntitiesChecked > 0
81
+ ? round(summary.totalEntitiesPassed / summary.totalEntitiesChecked)
82
+ : 1;
83
+ return {
84
+ score: passRatio,
85
+ totalSpecifications: summary.totalSpecifications,
86
+ passedSpecifications: summary.passedSpecifications,
87
+ failedSpecifications: summary.failedSpecifications,
88
+ totalEntitiesChecked: summary.totalEntitiesChecked,
89
+ totalEntitiesPassed: summary.totalEntitiesPassed,
90
+ totalEntitiesFailed: summary.totalEntitiesFailed,
91
+ };
92
+ }
93
+ export function computeObservation(store) {
94
+ const entityCounts = {};
95
+ for (const [type, ids] of store.entityIndex.byType) {
96
+ if (ids.length > 0)
97
+ entityCounts[type] = ids.length;
98
+ }
99
+ const sortedEntityCounts = {};
100
+ for (const type of Object.keys(entityCounts).sort()) {
101
+ sortedEntityCounts[type] = entityCounts[type];
102
+ }
103
+ const storeyCount = (store.entityIndex.byType.get('IFCBUILDINGSTOREY') ?? []).length;
104
+ return {
105
+ entityCounts: sortedEntityCounts,
106
+ storeyCount,
107
+ schema: store.schemaVersion ?? null,
108
+ // v0 gap: no geometry pass runs on reset (only the "clash" channel
109
+ // meshes, and only for clash detection, not to derive bounds), so
110
+ // `bounds` is always null for now. See the command doc's "op vocabulary
111
+ // gaps" note.
112
+ bounds: null,
113
+ };
114
+ }
115
+ //# sourceMappingURL=channels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channels.js","sourceRoot":"","sources":["../../../src/commands/gym/channels.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Episode factory for `ifc-lite gym`: discovery and lazy loading of the
3
+ * World Gym generator (tools/world-gym) from the repo checkout, plus the
4
+ * seed/family/corruption parameter parsing shared by the `--seed` CLI path
5
+ * and mid-session `{"type":"reset","seed":n}` messages.
6
+ *
7
+ * The generator is dynamically imported so the published npm package (which
8
+ * does not ship tools/world-gym) fails `--seed` with a clear, actionable
9
+ * error while `--model` keeps working.
10
+ */
11
+ interface GeneratedModel {
12
+ seed: number | string;
13
+ family: string;
14
+ corrupted: boolean;
15
+ content: string;
16
+ }
17
+ /** Episode descriptor echoed on generated-episode reset lines. */
18
+ export interface EpisodeInfo {
19
+ seed: number | string;
20
+ family: string;
21
+ corrupted: boolean;
22
+ }
23
+ export interface EpisodeSpec {
24
+ seed: number | string;
25
+ family: string;
26
+ forceCorrupt?: boolean;
27
+ corruptRate?: number;
28
+ }
29
+ export declare function parseSeed(raw: unknown, source: string): number | string;
30
+ export declare function parseCorruptRate(raw: unknown, source: string): number;
31
+ export declare function generateEpisode(spec: EpisodeSpec): Promise<{
32
+ model: GeneratedModel;
33
+ episode: EpisodeInfo;
34
+ }>;
35
+ export {};
36
+ //# sourceMappingURL=episode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"episode.d.ts","sourceRoot":"","sources":["../../../src/commands/gym/episode.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAUD,kEAAkE;AAClE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAqCD,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAOvE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC,CAejH"}
@@ -0,0 +1,65 @@
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
+ /** Benchmark default; overwritten from benchmark/splits.mjs when loadable. */
5
+ let benchmarkCorruptRate = 0.3;
6
+ let generatorModule = null;
7
+ async function loadGenerator() {
8
+ if (generatorModule)
9
+ return generatorModule;
10
+ // Both src (vitest) and dist layouts sit 5 levels below the repo root.
11
+ const generatorUrl = new URL('../../../../../tools/world-gym/generator.mjs', import.meta.url);
12
+ try {
13
+ generatorModule = (await import(generatorUrl.href));
14
+ }
15
+ catch (err) {
16
+ throw new Error(`the gym episode factory needs the ifc-lite repo checkout (could not load ${generatorUrl.pathname}: ${err.message}); use --model <file.ifc> instead`);
17
+ }
18
+ try {
19
+ const splits = (await import(new URL('../../../../../tools/world-gym/benchmark/splits.mjs', import.meta.url).href));
20
+ if (typeof splits.CORRUPT_RATE === 'number') {
21
+ benchmarkCorruptRate = splits.CORRUPT_RATE;
22
+ }
23
+ else {
24
+ process.stderr.write('gym: warning: tools/world-gym/benchmark/splits.mjs loaded but exports no numeric CORRUPT_RATE; using the compiled-in default corrupt rate 0.3\n');
25
+ }
26
+ }
27
+ catch (err) {
28
+ // The generator itself loaded, so a broken/missing splits.mjs means the
29
+ // episode distribution would silently drift from the benchmark spec.
30
+ // Keep the compiled-in default, but say so.
31
+ process.stderr.write(`gym: warning: could not load tools/world-gym/benchmark/splits.mjs (${err.message}); using the compiled-in default corrupt rate 0.3\n`);
32
+ }
33
+ return generatorModule;
34
+ }
35
+ export function parseSeed(raw, source) {
36
+ if (typeof raw === 'number' && Number.isInteger(raw) && raw >= 0)
37
+ return raw;
38
+ if (typeof raw === 'string' && raw.length > 0) {
39
+ const n = Number(raw);
40
+ return Number.isInteger(n) && n >= 0 ? n : raw;
41
+ }
42
+ throw new Error(`${source} must be a non-negative integer (benchmark seed) or a non-empty string`);
43
+ }
44
+ export function parseCorruptRate(raw, source) {
45
+ const n = typeof raw === 'number' ? raw : Number(raw);
46
+ if (!Number.isFinite(n) || n < 0 || n > 1) {
47
+ throw new Error(`${source} must be a number in [0, 1]`);
48
+ }
49
+ return n;
50
+ }
51
+ export async function generateEpisode(spec) {
52
+ if (spec.forceCorrupt !== undefined && spec.corruptRate !== undefined) {
53
+ throw new Error('corrupt and corruptRate are mutually exclusive: forcing corruption on/off makes a rate meaningless');
54
+ }
55
+ const generator = await loadGenerator();
56
+ const opts = spec.forceCorrupt !== undefined
57
+ ? { forceCorrupt: spec.forceCorrupt }
58
+ : { corruptRate: spec.corruptRate ?? benchmarkCorruptRate };
59
+ const model = generator.generateModel(spec.seed, spec.family, opts);
60
+ return {
61
+ model,
62
+ episode: { seed: spec.seed, family: model.family, corrupted: model.corrupted },
63
+ };
64
+ }
65
+ //# sourceMappingURL=episode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"episode.js","sourceRoot":"","sources":["../../../src/commands/gym/episode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The `ifc-lite gym` mutation-op vocabulary: parsing/validation of raw
3
+ * JSON ops and their application to a `MutablePropertyView`.
4
+ *
5
+ * Parsing is deliberately separate from application so a `step` batch can
6
+ * be validated as a whole before any op touches session state - the
7
+ * protocol promises atomic batches (a batch either fully applies or leaves
8
+ * the session unchanged).
9
+ */
10
+ import { MutablePropertyView } from '@ifc-lite/mutations';
11
+ /** A single mutation op, applied cumulatively across `step` calls. */
12
+ export type GymOp = {
13
+ op: 'setProperty';
14
+ expressId: number;
15
+ psetName: string;
16
+ propName: string;
17
+ value: string | number | boolean | null;
18
+ } | {
19
+ op: 'setAttribute';
20
+ expressId: number;
21
+ attrName: string;
22
+ value: string;
23
+ } | {
24
+ op: 'deleteProperty';
25
+ expressId: number;
26
+ psetName: string;
27
+ propName: string;
28
+ };
29
+ /**
30
+ * Validate one raw JSON op into a typed {@link GymOp}. Throws a plain Error
31
+ * on anything malformed; nothing is applied. The caller turns the throw
32
+ * into a structured `{type:"error"}` line rather than crashing the process.
33
+ */
34
+ export declare function parseOp(raw: unknown): GymOp;
35
+ /** Apply one already-validated op to the mutation overlay. */
36
+ export declare function applyOp(view: MutablePropertyView, op: GymOp): void;
37
+ //# sourceMappingURL=ops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ops.d.ts","sourceRoot":"","sources":["../../../src/commands/gym/ops.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAG1D,sEAAsE;AACtE,MAAM,MAAM,KAAK,GACb;IAAE,EAAE,EAAE,aAAa,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;CAAE,GACrH;IAAE,EAAE,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,EAAE,EAAE,gBAAgB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AA0BpF;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CA+B3C;AAED,8DAA8D;AAC9D,wBAAgB,OAAO,CAAC,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,KAAK,GAAG,IAAI,CAYlE"}
@@ -0,0 +1,78 @@
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
+ import { PropertyValueType } from '@ifc-lite/data';
5
+ function inferValueType(value) {
6
+ if (typeof value === 'boolean')
7
+ return PropertyValueType.Boolean;
8
+ if (typeof value === 'number')
9
+ return Number.isInteger(value) ? PropertyValueType.Integer : PropertyValueType.Real;
10
+ return PropertyValueType.String;
11
+ }
12
+ function isFiniteNumber(value) {
13
+ return typeof value === 'number' && Number.isFinite(value);
14
+ }
15
+ function requireString(value, field) {
16
+ if (typeof value !== 'string' || value.length === 0) {
17
+ throw new Error(`op field "${field}" must be a non-empty string`);
18
+ }
19
+ return value;
20
+ }
21
+ function requireExpressId(value) {
22
+ if (!isFiniteNumber(value) || value <= 0 || !Number.isInteger(value)) {
23
+ throw new Error('op field "expressId" must be a positive integer');
24
+ }
25
+ return value;
26
+ }
27
+ /**
28
+ * Validate one raw JSON op into a typed {@link GymOp}. Throws a plain Error
29
+ * on anything malformed; nothing is applied. The caller turns the throw
30
+ * into a structured `{type:"error"}` line rather than crashing the process.
31
+ */
32
+ export function parseOp(raw) {
33
+ if (typeof raw !== 'object' || raw === null || typeof raw.op !== 'string') {
34
+ throw new Error('each op needs a string "op" field');
35
+ }
36
+ const op = raw;
37
+ switch (op.op) {
38
+ case 'setProperty': {
39
+ const expressId = requireExpressId(op.expressId);
40
+ const psetName = requireString(op.psetName, 'psetName');
41
+ const propName = requireString(op.propName, 'propName');
42
+ const value = op.value;
43
+ if (value !== null && typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') {
44
+ throw new Error('op field "value" must be a string, number, boolean, or null');
45
+ }
46
+ return { op: 'setProperty', expressId, psetName, propName, value };
47
+ }
48
+ case 'setAttribute': {
49
+ const expressId = requireExpressId(op.expressId);
50
+ const attrName = requireString(op.attrName, 'attrName');
51
+ const value = requireString(op.value, 'value');
52
+ return { op: 'setAttribute', expressId, attrName, value };
53
+ }
54
+ case 'deleteProperty': {
55
+ const expressId = requireExpressId(op.expressId);
56
+ const psetName = requireString(op.psetName, 'psetName');
57
+ const propName = requireString(op.propName, 'propName');
58
+ return { op: 'deleteProperty', expressId, psetName, propName };
59
+ }
60
+ default:
61
+ throw new Error(`Unsupported op "${op.op}" (v0 supports setProperty, setAttribute, deleteProperty)`);
62
+ }
63
+ }
64
+ /** Apply one already-validated op to the mutation overlay. */
65
+ export function applyOp(view, op) {
66
+ switch (op.op) {
67
+ case 'setProperty':
68
+ view.setProperty(op.expressId, op.psetName, op.propName, op.value, inferValueType(op.value));
69
+ return;
70
+ case 'setAttribute':
71
+ view.setAttribute(op.expressId, op.attrName, op.value);
72
+ return;
73
+ case 'deleteProperty':
74
+ view.deleteProperty(op.expressId, op.psetName, op.propName);
75
+ return;
76
+ }
77
+ }
78
+ //# sourceMappingURL=ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ops.js","sourceRoot":"","sources":["../../../src/commands/gym/ops.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Options that let tests drive the stdin/stdout loop without touching the
3
+ * real process streams.
4
+ */
5
+ export interface GymIO {
6
+ input?: NodeJS.ReadableStream;
7
+ output?: NodeJS.WritableStream;
8
+ }
9
+ export declare function gymCommand(args: string[], io?: GymIO): Promise<void>;
10
+ //# sourceMappingURL=gym.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gym.d.ts","sourceRoot":"","sources":["../../src/commands/gym.ts"],"names":[],"mappings":"AAkJA;;;GAGG;AACH,MAAM,WAAW,KAAK;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;CAChC;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAE,KAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAwM9E"}