@bldrs-ai/conway 1.449.1351 → 1.451.1357
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 +36 -22
- package/compiled/examples/browser-bundled.cjs +1 -1
- package/compiled/examples/cli-bundled.cjs +1 -1
- package/compiled/examples/cli-step-bundled.cjs +1 -1
- package/compiled/examples/validator-bundled.cjs +1 -1
- package/compiled/src/ifc/ifc_regression_batch_main.js +36 -2
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -185,14 +185,25 @@ git merge -X rename-threshold=25 --no-commit
|
|
|
185
185
|
|
|
186
186
|
# CI and Testing
|
|
187
187
|
|
|
188
|
+
CI is **tiered** so full-corpus regression + performance cost is paid once per
|
|
189
|
+
release candidate, not on every push. Full architecture, cost rationale, and
|
|
190
|
+
the rc/re-bless/LFS runbook: [design/new/ci-regression-cost.md](design/new/ci-regression-cost.md).
|
|
191
|
+
|
|
188
192
|
Every PR is gated on two checks defined in `.github/workflows/build.yml`:
|
|
189
193
|
|
|
190
194
|
| Job | What it does |
|
|
191
195
|
|---|---|
|
|
192
196
|
| `build` | `yarn install`, WASM + TS compile (WASM cached on the `conway-geom` submodule SHA), `yarn test`, `yarn lint`, and a Tier-A geometry-digest check of the in-repo `data/` models against committed goldens. |
|
|
193
|
-
| `run-ifc-regression` | `needs: build`. Reuses the same WASM cache. Runs the regression batch
|
|
197
|
+
| `run-ifc-regression` | `needs: build`. Reuses the same WASM cache. Runs the regression batch over the **smoke subset** (`regression/smoke_models.txt`) of the public `test-models` ref (`TEST_MODELS_REF`, default `main`), pinned per-run to the resolved commit SHA. Fails on any `failed.csv` row; digest *changes* are informational (reviewed via the visual-diff comment, blessed at the rc). Posts a per-PR comment with the resolved SHA + smoke-scoped `failed.csv` / `errors.csv` / perf summaries, and uploads the candidate npm tarball + `perf.csv` as workflow artifacts. |
|
|
198
|
+
|
|
199
|
+
A `concurrency` group cancels superseded PR runs (main runs are never
|
|
200
|
+
cancelled, so releases always complete). A merge to `main` re-runs those two
|
|
201
|
+
jobs and then chains into `auto-publish` (see [Releases](#releases) below).
|
|
194
202
|
|
|
195
|
-
|
|
203
|
+
**The full public+private corpus runs once per release candidate** — push an
|
|
204
|
+
`rc-*` tag and `rc-regression.yml` regenerates every baseline (opening a
|
|
205
|
+
reviewable baseline PR per test-models repo) while the `perf-three-*` jobs run
|
|
206
|
+
the full benchmark. See the runbook in the CI-cost doc linked above.
|
|
196
207
|
|
|
197
208
|
## Regression batch
|
|
198
209
|
|
|
@@ -209,8 +220,11 @@ The `build` job also runs a fast, hermetic geometry gate over every `data/*.ifc`
|
|
|
209
220
|
**Tier 1 — Conway-only perf in CI (live).** Every regression run emits a `perf.csv` of `parseTimeMs / geometryTimeMs / totalTimeMs / rssMb / heapUsedMb / heapTotalMb` per model. The top-10 slowest are posted in the PR comment; the full CSV is uploaded as a workflow artifact. This piggybacks on the existing regression batch so cost is ~0 extra runner minutes.
|
|
210
221
|
|
|
211
222
|
**Tier 2 — full headless-three perf in CI (live).** Two jobs,
|
|
212
|
-
`perf-three-public` and `perf-three-private`, run on `
|
|
213
|
-
(`needs: run-ifc-regression`)
|
|
223
|
+
`perf-three-public` and `perf-three-private`, run on `rc-*` tags and
|
|
224
|
+
`workflow_dispatch` (`needs: run-ifc-regression`) — once per release
|
|
225
|
+
candidate, not per merge, so per-model timings stay low-variance on the
|
|
226
|
+
isolated runner (see [ci-regression-cost.md](design/new/ci-regression-cost.md)
|
|
227
|
+
for why frequency, not runner size, is the cost lever). Each downloads the candidate Conway tarball
|
|
214
228
|
that the regression job packed, clones [headless-three](https://github.com/bldrs-ai/headless-three)
|
|
215
229
|
at a pinned `H3_SHA`, and forces the whole H3 → adapter → conway chain onto
|
|
216
230
|
the candidate via a yarn `resolutions` override (no `yarn link`), then runs
|
|
@@ -305,23 +319,23 @@ npm dist-tag add @bldrs-ai/conway@<VERSION> stable
|
|
|
305
319
|
|
|
306
320
|
# Roadmap
|
|
307
321
|
|
|
308
|
-
The CI / release pipeline is continuous and
|
|
309
|
-
`run-ifc-regression
|
|
310
|
-
|
|
322
|
+
The CI / release pipeline is continuous and **tiered**: `build` (fixtures) and
|
|
323
|
+
`run-ifc-regression` (smoke subset) gate every PR; the full public+private
|
|
324
|
+
corpus and the headless-three perf jobs run once per `rc-*` release candidate;
|
|
325
|
+
every green merge to `main` auto-publishes (see [Releases](#releases)). The
|
|
326
|
+
architecture, cost rationale, and rc/re-bless/LFS runbook are in
|
|
327
|
+
[design/new/ci-regression-cost.md](design/new/ci-regression-cost.md). Regression
|
|
328
|
+
renders (the visual-diff comment) and per-model perf-in-CI shipped; the
|
|
311
329
|
umbrella waterfall (#316) and performance-in-CI (#314) issues are closed.
|
|
312
|
-
The optional follow-ups below remain.
|
|
313
|
-
|
|
314
|
-
### Headless-three perf on PRs
|
|
315
|
-
|
|
316
|
-
The `perf-three-public` / `perf-three-private` jobs run on `push: main`
|
|
317
|
-
only — to keep PR wall-time down and to keep the private-models token off
|
|
318
|
-
PR events (forks can't be trusted with it). Running them per-PR, behind a
|
|
319
|
-
gate that withholds the private job from fork PRs, would catch H3
|
|
320
|
-
render-time regressions before merge instead of just after.
|
|
321
|
-
|
|
322
|
-
### Golden `errors.csv` diffing + regression renders (#288)
|
|
323
330
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
331
|
+
### Open follow-ups
|
|
332
|
+
|
|
333
|
+
- **Errors as a hard gate.** `errors.csv` is regenerated and reviewed (and,
|
|
334
|
+
at the rc, blessed into the baseline), but a PR is not *failed* on unexpected
|
|
335
|
+
new errors — only on parse/extract failures (`failed.csv`). A golden-errors
|
|
336
|
+
gate could fail smoke-scoped error churn that isn't an intended change.
|
|
337
|
+
- **Smoke-list curation.** The smoke subset (`regression/smoke_models.txt`)
|
|
338
|
+
is a hand-picked spread; as the engine's failure surface shifts, revisit
|
|
339
|
+
which models best catch regressions cheaply.
|
|
340
|
+
- **Perf-threshold gating.** The `perf-three-*` jobs post deltas but don't
|
|
341
|
+
fail an rc on a regression; a threshold could turn perf into a release gate.
|
|
@@ -30,7 +30,7 @@ var import_node_process = require("node:process");
|
|
|
30
30
|
var readline = __toESM(require("node:readline"), 1);
|
|
31
31
|
|
|
32
32
|
// compiled/src/version/version.js
|
|
33
|
-
var versionString = "Conway v1.
|
|
33
|
+
var versionString = "Conway v1.451.1357";
|
|
34
34
|
|
|
35
35
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
36
36
|
var wasmType = "";
|
|
@@ -14965,7 +14965,7 @@ ${t5.join("\n")}` : "";
|
|
|
14965
14965
|
var import_process = require("process");
|
|
14966
14966
|
|
|
14967
14967
|
// compiled/src/version/version.js
|
|
14968
|
-
var versionString = "Conway v1.
|
|
14968
|
+
var versionString = "Conway v1.451.1357";
|
|
14969
14969
|
|
|
14970
14970
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
14971
14971
|
function pThreadsAllowed() {
|
|
@@ -15943,7 +15943,7 @@ var ParsingBuffer = class {
|
|
|
15943
15943
|
};
|
|
15944
15944
|
|
|
15945
15945
|
// compiled/src/version/version.js
|
|
15946
|
-
var versionString = "Conway v1.
|
|
15946
|
+
var versionString = "Conway v1.451.1357";
|
|
15947
15947
|
|
|
15948
15948
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
15949
15949
|
function pThreadsAllowed() {
|
|
@@ -944,7 +944,7 @@ var EntityTypesIfcCount = 909;
|
|
|
944
944
|
var entity_types_ifc_gen_default = EntityTypesIfc;
|
|
945
945
|
|
|
946
946
|
// compiled/src/version/version.js
|
|
947
|
-
var versionString = "Conway v1.
|
|
947
|
+
var versionString = "Conway v1.451.1357";
|
|
948
948
|
|
|
949
949
|
// compiled/dependencies/conway-geom/interface/conway_geometry.js
|
|
950
950
|
var wasmType = "";
|
|
@@ -242,6 +242,40 @@ async function runForFile(filePath, outputPath, maxTimeout, perfPath) {
|
|
|
242
242
|
hash: fileHash,
|
|
243
243
|
};
|
|
244
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Run a file's digest, retrying ONCE if the first attempt times out.
|
|
247
|
+
*
|
|
248
|
+
* A per-model timeout is not a deterministic parse/geometry failure — it
|
|
249
|
+
* surfaces as a failed.csv row with an empty code AND empty signal (the
|
|
250
|
+
* TimeoutError path sets neither) and, historically, has come from transient
|
|
251
|
+
* core oversubscription on the CI runner rather than the model itself.
|
|
252
|
+
* ISSUE_159_kleine_Wohnung_R22.ifc (a geometry-dense ~18.5k-item model) has
|
|
253
|
+
* reddened the rc-regression gate this way twice: first co-scheduled at
|
|
254
|
+
* --concurrency 2, then again running ALONE at --concurrency 1, so serializing
|
|
255
|
+
* the batch was not enough to make it reliable.
|
|
256
|
+
*
|
|
257
|
+
* Digest regeneration is idempotent, so a second attempt is safe: a transient
|
|
258
|
+
* timeout clears on the retry, while a genuine hang times out both times and
|
|
259
|
+
* still lands in failed.csv — the gate keeps its protective value against a
|
|
260
|
+
* model that truly never loads. Only timeouts are retried; a real non-zero
|
|
261
|
+
* exit or signal is returned immediately (those ARE deterministic).
|
|
262
|
+
*
|
|
263
|
+
* @param filePath Model file to digest.
|
|
264
|
+
* @param outputPath Digest output path (without extension).
|
|
265
|
+
* @param maxTimeout Per-attempt timeout in ms.
|
|
266
|
+
* @param perfPath Optional path the child writes its one-row perf CSV to.
|
|
267
|
+
* @return The first attempt's result, or the retry's result on a timeout.
|
|
268
|
+
*/
|
|
269
|
+
async function runForFileWithTimeoutRetry(filePath, outputPath, maxTimeout, perfPath) {
|
|
270
|
+
const timedOut = (r) => r.type === 'Failed' && r.message === 'Execution timed out';
|
|
271
|
+
const first = await runForFile(filePath, outputPath, maxTimeout, perfPath);
|
|
272
|
+
if (!timedOut(first)) {
|
|
273
|
+
return first;
|
|
274
|
+
}
|
|
275
|
+
console.log(`"${path.basename(filePath)}" timed out; retrying once ` +
|
|
276
|
+
`(a transient timeout clears, a true hang times out again).`);
|
|
277
|
+
return runForFile(filePath, outputPath, maxTimeout, perfPath);
|
|
278
|
+
}
|
|
245
279
|
// Model files the regression harness understands: IFC plus STEP AP214.
|
|
246
280
|
const SUPPORTED_MODEL_EXTENSIONS = ['.ifc', '.stp', '.step'];
|
|
247
281
|
/**
|
|
@@ -344,7 +378,7 @@ async function processIFCFilesInParallel(ifcFiles, outputPath, errorLines, fileL
|
|
|
344
378
|
const perfChildPath = perfDir ?
|
|
345
379
|
path.join(perfDir, `${path.parse(ifcPath).name}.perf.csv`) :
|
|
346
380
|
undefined;
|
|
347
|
-
const fileResults = await
|
|
381
|
+
const fileResults = await runForFileWithTimeoutRetry(ifcPath, path.join(outputPath, path.parse(ifcPath).name), maxTimeout, perfChildPath);
|
|
348
382
|
activeTasks--;
|
|
349
383
|
console.log(`Completed task for "${path.basename(ifcPath)}". Active tasks: ${activeTasks}`);
|
|
350
384
|
return { ifcPath, fileResults };
|
|
@@ -396,7 +430,7 @@ async function recursiveWalk(parentPath, excludeRegex, outputPath, errorLines, f
|
|
|
396
430
|
const perfChildPath = perfDir ?
|
|
397
431
|
path.join(perfDir, `${path.parse(resolved).name}.perf.csv`) :
|
|
398
432
|
undefined;
|
|
399
|
-
const fileResults = await
|
|
433
|
+
const fileResults = await runForFileWithTimeoutRetry(resolved, path.join(outputPath, path.parse(resolved).name), maxTimeout, perfChildPath);
|
|
400
434
|
if (fileResults.type === 'Run') {
|
|
401
435
|
if (fileResults.errorLines !== void 0) {
|
|
402
436
|
errorLines.push(...fileResults.errorLines);
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
// only the first segment (major) is meaningful and is the one CI carries forward.
|
|
6
6
|
// Must stay in `vN.N.N` shape: the CI stamp regex, scripts/updateVersion.mjs, and
|
|
7
7
|
// statistics.ts all match `v\d+\.\d+\.\d+`.
|
|
8
|
-
const versionString = 'Conway v1.
|
|
8
|
+
const versionString = 'Conway v1.451.1357';
|
|
9
9
|
export { versionString };
|