@helix3/helix-cli 0.1.22-helix3.412 → 0.1.22-helix3.415
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 +1 -1
- package/dist/index.js +20 -4
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/vehicle/audio.d.ts +52 -2
- package/dist/vehicle/audio.js +177 -9
- package/dist/vehicle/audio.js.map +1 -1
- package/dist/vehicle/audioDefects.d.ts +40 -0
- package/dist/vehicle/audioDefects.js +62 -0
- package/dist/vehicle/audioDefects.js.map +1 -1
- package/dist/vehicle/audioDistinct.d.ts +62 -0
- package/dist/vehicle/audioDistinct.js +479 -0
- package/dist/vehicle/audioDistinct.js.map +1 -0
- package/dist/vehicle/audioReference.d.ts +36 -0
- package/dist/vehicle/audioReference.js +176 -0
- package/dist/vehicle/audioReference.js.map +1 -0
- package/dist/vehicle/drive.js +4 -2
- package/dist/vehicle/drive.js.map +1 -1
- package/dist/vehicle/enginePolicy.d.ts +68 -0
- package/dist/vehicle/enginePolicy.js +209 -0
- package/dist/vehicle/enginePolicy.js.map +1 -0
- package/dist/vehicle/preview.d.ts +3 -0
- package/dist/vehicle/preview.js +38 -0
- package/dist/vehicle/preview.js.map +1 -1
- package/dist/vehicle/simulate.d.ts +10 -1
- package/dist/vehicle/simulate.js +7 -1
- package/dist/vehicle/simulate.js.map +1 -1
- package/dist/vehicle/validate.js +8 -1
- package/dist/vehicle/validate.js.map +1 -1
- package/dist/vehicle/wheelDesign.d.ts +98 -0
- package/dist/vehicle/wheelDesign.js +276 -0
- package/dist/vehicle/wheelDesign.js.map +1 -0
- package/dist/visualQa/harness.d.ts +2 -0
- package/dist/visualQa/vehicle.js +51 -1
- package/dist/visualQa/vehicle.js.map +1 -1
- package/docs/vehicle-simulate.md +16 -0
- package/package.json +1 -1
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_abs.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_audio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_engine.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_expression.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_jbeam.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_materials.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/test_beamng_engine.cpython-312.pyc +0 -0
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ The token is stored in `~/.helix/credentials.json` (mode `600`). It's sent as
|
|
|
53
53
|
| `helix continuum publish-glb <mesh.glb> --title <t> [--package-type asset\|character] [--offer marketplace\|world --price-lix <n> --content-rating <rating>]` | Seal a Package first; optional offer makes it ownable. See [Package-first GLB publication](#package-first-glb-publication). |
|
|
54
54
|
| `helix continuum make-item --package-id <id> --package-version <v> --manifest-cid <cid> --content-rating <rating> [--offer marketplace\|world --price-lix <n>]` | Project one exact sealed Package Version into an Item, with an optional first offer. |
|
|
55
55
|
| `helix continuum publish-owned-item <item-id> --package-id <id> --package-version <v> --manifest-cid <cid> --content-rating <rating> --accept-rating-attestation` | Publish an existing personal Item from its unchanged public sealed Package pin. Offers are separate. |
|
|
56
|
-
| `helix vehicle audio-check <dir\|package.json\|item-id> [--json]` | Proves every sound the runtime will select resolves, is PCM WAV and is audible (pre-publish on local files, or read-back on a published item). |
|
|
56
|
+
| `helix vehicle audio-check <dir\|package.json\|item-id> [--reference <clip>]... [--json]` | Proves every sound the runtime will select resolves, is PCM WAV and is audible (pre-publish on local files, or read-back on a published item), and that no two roles share one recording (shift up = shift down, an exhaust rung = an engine rung) and the rev limiter is a short crack the runtime can retrigger. `--reference <clip>` (repeatable; `slot=clip` for a slot) compares the idle voice's centroid and firing roughness with a real-car recording. |
|
|
57
57
|
| `helix vehicle addon check <dir> [--json]` | Add-on fit gate for local source and host compatibility, including the web customizer's meshless guard (`ADDON_CUSTOMIZER_REFUSES`: a part with no `model.glb` must be a verified tune-only/sound-only definition). |
|
|
58
58
|
| `helix vehicle addon check --item <addOnId>... / --host <vehicleId>... [--json]` | Published mode (public reads, no sign-in): reads each add-on Item's exact Package pin and runs exactly what the web customizer runs; `--host` checks every add-on on the car's rail. Exit `1` = the customizer would refuse a part, with its message. |
|
|
59
59
|
| `helix item list-slots [--json]` | Print the Character-Creator vocabulary a wearable declares: the cosmetic slot tags, and the genders. |
|
package/dist/index.js
CHANGED
|
@@ -624,7 +624,7 @@ vehicleCommand
|
|
|
624
624
|
console.log((0, validate_1.formatVehicleIssues)(result.issues));
|
|
625
625
|
if (result.simulation) {
|
|
626
626
|
const { formatSimulationReport } = await Promise.resolve().then(() => __importStar(require('./vehicle/simulate')));
|
|
627
|
-
console.log(formatSimulationReport(result.simulation).split('\n').map((line) => ` ${line}`).join('\n'));
|
|
627
|
+
console.log(formatSimulationReport(result.simulation, { withPolicy: false }).split('\n').map((line) => ` ${line}`).join('\n'));
|
|
628
628
|
}
|
|
629
629
|
if (provisional > 0)
|
|
630
630
|
console.log(` ${provisional} audio row${provisional === 1 ? '' : 's'} backed by a local WAV: seal the WAV in the Vehicle Package before making its Item; \`helix vehicle audio-check\` proves ${provisional === 1 ? 'it plays' : 'they play'}`);
|
|
@@ -655,6 +655,11 @@ vehicleCommand
|
|
|
655
655
|
.option('--occupants', 'also seat an avatar in every seat, judge the cabin, and report where the runtime\'s cabin fit put each seat vs where it was authored (slow)')
|
|
656
656
|
.option('--reference-paint <#rrggbb>', 'the reference body paint colour, the median of the body-paint pixels in the reference photos: renders the body paint alone from six cameras in the Try Now daylight (the world\'s own sun, exposure, tone mapping and lights) and fails on hue, saturation, lightness or highlight wash. White/silver/grey/black are judged on tint and lightness instead of hue')
|
|
657
657
|
.option('--paint-tolerance <deg>', 'maximum circular hue distance (degrees) the rendered body may sit from a chromatic --reference-paint (default 12)', (v) => Number(v))
|
|
658
|
+
.option('--reference-wheel <image>', 'a close-up photo of the real wheel, face-on or nearly: renders the candidate\'s front-left wheel square-on and fails vehicle.wheels.design.* on spoke count and centre cap (a different finish fails, a neighbouring one warns). The photo\'s wheel is read from the image centre unless --reference-wheel-crop says where it is')
|
|
659
|
+
.option('--reference-wheel-spokes <n>', 'declare the real wheel\'s spoke count (overrides the count read from the photo; use it for an oblique or tight photo)', (v) => Number(v))
|
|
660
|
+
.option('--reference-wheel-finish <finish>', 'declare the real wheel\'s finish: silver, chrome, gunmetal, black, bronze, gold or coloured (overrides the finish read from the photo)')
|
|
661
|
+
.option('--reference-wheel-cap <yes|no>', 'declare whether the real wheel has a centre cap (overrides the photo)')
|
|
662
|
+
.option('--reference-wheel-crop <cx,cy,r>', 'where the wheel sits in the photo, as fractions: centre x of the width, centre y of the height, tyre outer radius of the shorter side (default 0.5,0.5,0.45)')
|
|
658
663
|
.option('--storage-state <file>', 'Playwright storageState of a signed-in QA account (default: sign in with `helix login`, or $HELIX_VQA_STORAGE_STATE)')
|
|
659
664
|
.option('--chrome <path>', 'Chromium executable (default: Playwright Chromium / Chrome for Testing, headless; the macOS system Chrome is refused)')
|
|
660
665
|
.option('--api-url <url>', 'platform API base URL')
|
|
@@ -672,6 +677,13 @@ vehicleCommand
|
|
|
672
677
|
target, addOns: opts.addon, item: opts.item, toleranceCm: Number.isFinite(opts.toleranceCm) ? opts.toleranceCm : undefined,
|
|
673
678
|
glb: opts.glb, out: opts.out, proxyItem: opts.proxyItem, occupants: opts.occupants, apiBase, webBase,
|
|
674
679
|
referencePaint: opts.referencePaint, paintToleranceDeg: Number.isFinite(opts.paintTolerance) ? opts.paintTolerance : undefined,
|
|
680
|
+
referenceWheel: opts.referenceWheel ? {
|
|
681
|
+
image: opts.referenceWheel,
|
|
682
|
+
...(Number.isFinite(opts.referenceWheelSpokes) ? { spokeCount: opts.referenceWheelSpokes } : {}),
|
|
683
|
+
...(opts.referenceWheelFinish ? { finish: opts.referenceWheelFinish } : {}),
|
|
684
|
+
...(opts.referenceWheelCap ? { centreCap: /^(y|yes|true|1)$/i.test(opts.referenceWheelCap) } : {}),
|
|
685
|
+
...(opts.referenceWheelCrop ? { crop: ((p) => ({ cx: p[0], cy: p[1], radius: p[2] }))(opts.referenceWheelCrop.split(',').map(Number)) } : {}),
|
|
686
|
+
} : undefined,
|
|
675
687
|
token: creds?.token ?? null, storageState: opts.storageState ?? process.env.HELIX_VQA_STORAGE_STATE, chrome: opts.chrome, quiet: opts.json,
|
|
676
688
|
});
|
|
677
689
|
}
|
|
@@ -801,13 +813,17 @@ vehicleCommand
|
|
|
801
813
|
.command('audio-check')
|
|
802
814
|
.description('Prove every sound a vehicle declares will actually play: each engine-ladder rung and slot sample the runtime selects must resolve (a local WAV '
|
|
803
815
|
+ 'beside the package before publish, or HTTP 200 with the exact declared bytes and sha256 after), be PCM WAV, and be audible (not silence). '
|
|
804
|
-
+ 'It also measures what each sound is made of: clipping, DC offset, a resampled-copy ladder rung, one fixed formant stack or fixed tone shared by every rung, and an exactly periodic synthetic horn (each reported with its measured value and a fix). '
|
|
816
|
+
+ 'It also measures what each sound is made of: clipping, DC offset, a resampled-copy ladder rung, one fixed formant stack or fixed tone shared by every rung, near-duplicate sounds across roles (shift up = shift down, an exhaust rung = an engine rung), a rev-limiter clip too long to stutter (the runtime re-fires it every 60 ms), and an exactly periodic synthetic horn (each reported with its measured value and a fix). '
|
|
805
817
|
+ 'Pass a package directory / package JSON for the pre-seal check, or a published vehicle item id for the read-back check. Exit 0 = every sample plays')
|
|
806
818
|
.argument('<dir|package.json|item-id>', 'package directory or file (pre-seal), or a published vehicle item UUID (read-back)')
|
|
819
|
+
.option('--reference <clip>', 'a recording of the REAL car to compare the idle voice with: a WAV (or anything ffmpeg reads) of the engine idling; `slot=clip` compares that slot instead (e.g. horn=horn.wav, startup=start.wav). Repeat for several clips (the median is used). Spectral centroid and firing roughness are measured identically on both sides; WARN beyond 2.5x, error beyond 10x (field recordings differ by 2-4x between takes of one car)', (value, previous) => [...previous, value], [])
|
|
807
820
|
.option('--json', 'print the machine-readable report')
|
|
808
821
|
.action(async (target, opts) => {
|
|
809
822
|
try {
|
|
810
823
|
const audio = await Promise.resolve().then(() => __importStar(require('./vehicle/audio')));
|
|
824
|
+
const { loadReferenceClips } = await Promise.resolve().then(() => __importStar(require('./vehicle/audioReference')));
|
|
825
|
+
const reference = opts.reference?.length ? { bySlot: loadReferenceClips(opts.reference).bySlot } : undefined;
|
|
826
|
+
const options = reference ? { reference } : {};
|
|
811
827
|
let report;
|
|
812
828
|
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(target)) {
|
|
813
829
|
const creds = (0, config_1.loadCredentials)();
|
|
@@ -819,7 +835,7 @@ vehicleCommand
|
|
|
819
835
|
const pkg = (body.item ?? body).properties?.vehiclePackage;
|
|
820
836
|
if (!pkg)
|
|
821
837
|
throw new Error(`item ${target} carries no properties.vehiclePackage (is it a vehicle?)`);
|
|
822
|
-
report = await audio.checkAudioReadBack(pkg);
|
|
838
|
+
report = await audio.checkAudioReadBack(pkg, undefined, undefined, options);
|
|
823
839
|
}
|
|
824
840
|
else {
|
|
825
841
|
const path = (0, node_path_1.resolve)(target);
|
|
@@ -827,7 +843,7 @@ vehicleCommand
|
|
|
827
843
|
const isDir = statSync(path).isDirectory();
|
|
828
844
|
const { readVehicleDir } = await Promise.resolve().then(() => __importStar(require('./vehicle/publish')));
|
|
829
845
|
const pkg = isDir ? readVehicleDir(path).pkg : (0, validate_1.readJsonFile)(path);
|
|
830
|
-
report = await audio.checkAudioLocal(pkg, isDir ? path : (0, node_path_1.resolve)(path, '..'));
|
|
846
|
+
report = await audio.checkAudioLocal(pkg, isDir ? path : (0, node_path_1.resolve)(path, '..'), undefined, undefined, options);
|
|
831
847
|
}
|
|
832
848
|
printVehicleJsonOr(opts.json, report, () => console.log(audio.formatAudioReport(report)));
|
|
833
849
|
if (!report.ok)
|