@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
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,
|
|
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"}
|
package/dist/commands/clash.js
CHANGED
|
@@ -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":"AAAA;;+DAE+D;AAE/D;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
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"}
|