space-data-module-sdk 0.8.10 → 0.8.11
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/package.json +1 -1
- package/src/standards/catalogCore.js +28 -1
- package/src/testing/parityGate.js +64 -11
package/package.json
CHANGED
|
@@ -62,8 +62,35 @@ function collectFlatbufferTableFields(idl, tableName) {
|
|
|
62
62
|
.filter(Boolean);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
// A schema has TWO written forms in this ecosystem and they mean the same file:
|
|
66
|
+
//
|
|
67
|
+
// "SCV.fbs" — the catalog's canonical form, built as `<CODE>.fbs` from
|
|
68
|
+
// the standards manifest (parseStandardsEntry below).
|
|
69
|
+
// "SCV/main.fbs" — the PATH form, which is how the schema actually lives in
|
|
70
|
+
// spacedatastandards.org (`schema/SCV/main.fbs`) and is
|
|
71
|
+
// therefore what modules, tests and generated bindings across
|
|
72
|
+
// the stack write.
|
|
73
|
+
//
|
|
74
|
+
// Matching them as raw strings made every manifest using the path form fail
|
|
75
|
+
// resolution with `standards-type-identity-mismatch` — "mixes a known
|
|
76
|
+
// schemaName ... with a different standards entry" — because the `$SCV` file
|
|
77
|
+
// identifier DID resolve while the name did not. That is not a manifest defect
|
|
78
|
+
// and not a schema defect; it is this matcher refusing a spelling the standards
|
|
79
|
+
// repository itself uses. The rest of the toolchain already treats the two as
|
|
80
|
+
// one schema (see the closed-modules builder's
|
|
81
|
+
// `^([A-Z][A-Z0-9]{2})(?:\/main)?\.fbs$` header-injection regex), so the
|
|
82
|
+
// catalog must too, or a correct module cannot be compiled.
|
|
83
|
+
//
|
|
84
|
+
// Deliberately narrow: ONLY the exact `<CODE>/main.fbs` shape collapses. Any
|
|
85
|
+
// other path is left alone so two genuinely different schemas can never be
|
|
86
|
+
// merged by a loose rule.
|
|
87
|
+
const SCHEMA_PATH_FORM = /^([A-Za-z][A-Za-z0-9_]*)\/main\.fbs$/;
|
|
88
|
+
|
|
65
89
|
function normalizeSchemaName(value) {
|
|
66
|
-
|
|
90
|
+
if (value === undefined || value === null) return "";
|
|
91
|
+
const text = String(value);
|
|
92
|
+
const pathForm = SCHEMA_PATH_FORM.exec(text);
|
|
93
|
+
return pathForm ? `${pathForm[1]}.fbs` : text;
|
|
67
94
|
}
|
|
68
95
|
|
|
69
96
|
function normalizeFileIdentifier(value) {
|
|
@@ -61,6 +61,7 @@ import { toLoadableWasmBytes } from "../bundle/artifactBytes.js";
|
|
|
61
61
|
import {
|
|
62
62
|
classifyArtifactImports,
|
|
63
63
|
describeClassification,
|
|
64
|
+
readWasmExportNames,
|
|
64
65
|
resolveHostSurface,
|
|
65
66
|
} from "./hostContract.js";
|
|
66
67
|
import { normalizeWasmEdgeOutcome } from "./wasmedgeOutput.js";
|
|
@@ -250,6 +251,21 @@ export function classifyWasmEdgeProbe({
|
|
|
250
251
|
if (/(loading failed|validation failed|magic header|malformed|invalid section)/i.test(text)) {
|
|
251
252
|
return { outcome: "compile-error", missingImport: null, detail: head() };
|
|
252
253
|
}
|
|
254
|
+
// The CLI rejected the INVOCATION, before loading anything: reactor mode
|
|
255
|
+
// needs an entry name. This says nothing about the artifact, so it must not
|
|
256
|
+
// be reported against the artifact — stageArtifact() now names `_initialize`
|
|
257
|
+
// for reactor artifacts, and this branch exists so a regression there is
|
|
258
|
+
// legible instead of masquerading as a cross-runtime divergence.
|
|
259
|
+
if (/function name is required when reactor mode is enabled/i.test(text)) {
|
|
260
|
+
return {
|
|
261
|
+
outcome: "probe-failure",
|
|
262
|
+
missingImport: null,
|
|
263
|
+
detail:
|
|
264
|
+
"WasmEdge refused the invocation: reactor mode requires an entry " +
|
|
265
|
+
"function name. This is a PROBE defect, not an artifact defect — the " +
|
|
266
|
+
"lane must pass the artifact's reactor entry (see resolveReactorEntry).",
|
|
267
|
+
};
|
|
268
|
+
}
|
|
253
269
|
// Linked, then the CLI could not find a start entry: a reactor artifact.
|
|
254
270
|
// Only reachable after successful instantiation.
|
|
255
271
|
if (/(wasm function not found|function not found|_start|_initialize)/i.test(text)) {
|
|
@@ -359,15 +375,11 @@ async function probeWithNativeWasmEdge(context, staged) {
|
|
|
359
375
|
context.pin,
|
|
360
376
|
`native binary ${detected.binary}`,
|
|
361
377
|
);
|
|
362
|
-
const outcome = await spawnCapture(
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
env: { PATH: process.env.PATH ?? "" },
|
|
368
|
-
timeoutMs: context.timeoutMs,
|
|
369
|
-
},
|
|
370
|
-
);
|
|
378
|
+
const outcome = await spawnCapture(detected.binary, wasmEdgeProbeArgs(staged), {
|
|
379
|
+
cwd: staged.dir,
|
|
380
|
+
env: { PATH: process.env.PATH ?? "" },
|
|
381
|
+
timeoutMs: context.timeoutMs,
|
|
382
|
+
});
|
|
371
383
|
const normalized = normalizeWasmEdgeOutcome(outcome);
|
|
372
384
|
return classifyWasmEdgeProbe({
|
|
373
385
|
code: outcome.code,
|
|
@@ -391,7 +403,7 @@ async function probeWithDockerWasmEdge(context, staged) {
|
|
|
391
403
|
"/parity",
|
|
392
404
|
];
|
|
393
405
|
if (context.dockerPlatform) args.push("--platform", String(context.dockerPlatform));
|
|
394
|
-
args.push(context.pin.dockerImage,
|
|
406
|
+
args.push(context.pin.dockerImage, ...wasmEdgeProbeArgs(staged));
|
|
395
407
|
const outcome = await spawnCapture(context.dockerBinary ?? "docker", args, {
|
|
396
408
|
cwd: staged.dir,
|
|
397
409
|
env: process.env,
|
|
@@ -688,11 +700,52 @@ export function lanesAgree(a, b) {
|
|
|
688
700
|
|
|
689
701
|
// --- Orchestrator ---------------------------------------------------------------
|
|
690
702
|
|
|
703
|
+
/**
|
|
704
|
+
* A REACTOR artifact has no `_start`; its initialisation entry is `_initialize`
|
|
705
|
+
* (clang `-mexec-model=reactor`). The WasmEdge CLI refuses to run one without
|
|
706
|
+
* being told which function to call — "A function name is required when reactor
|
|
707
|
+
* mode is enabled." on stderr, exit 1, and NO runtime diagnostic — which the
|
|
708
|
+
* probe classifier could only honestly report as `probe-failure`. The effect
|
|
709
|
+
* was that a CORRECTLY built library module (the shape the module contract
|
|
710
|
+
* mandates for the RF family) was reported as a P1 cross-runtime divergence
|
|
711
|
+
* while the browser lane passed: the gate failed the artifact for the gate's
|
|
712
|
+
* own inability to invoke it.
|
|
713
|
+
*
|
|
714
|
+
* Naming the entry is also STRICTLY STRONGER evidence than the old bare
|
|
715
|
+
* invocation: a clean exit 0 means the runtime linked the imports, instantiated
|
|
716
|
+
* the module, and RAN its initialiser — observed, not inferred from an error
|
|
717
|
+
* string.
|
|
718
|
+
*/
|
|
719
|
+
export function resolveReactorEntry(loadableBytes) {
|
|
720
|
+
let exportNames;
|
|
721
|
+
try {
|
|
722
|
+
exportNames = readWasmExportNames(loadableBytes);
|
|
723
|
+
} catch {
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
if (exportNames.includes("_start")) return null;
|
|
727
|
+
return exportNames.includes("_initialize") ? "_initialize" : null;
|
|
728
|
+
}
|
|
729
|
+
|
|
691
730
|
async function stageArtifact(artifact) {
|
|
692
731
|
const dir = await mkdtemp(path.join(os.tmpdir(), `sdm-gate-${artifact.id}-`));
|
|
693
732
|
const basename = "artifact.wasm";
|
|
694
733
|
await writeFile(path.join(dir, basename), artifact.loadableBytes);
|
|
695
|
-
return {
|
|
734
|
+
return {
|
|
735
|
+
dir,
|
|
736
|
+
basename,
|
|
737
|
+
reactorEntry: resolveReactorEntry(artifact.loadableBytes),
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* The invocation tail shared by both WasmEdge lanes, so the native and Docker
|
|
743
|
+
* lanes can never drift into probing the same artifact two different ways.
|
|
744
|
+
*/
|
|
745
|
+
export function wasmEdgeProbeArgs(staged) {
|
|
746
|
+
return staged.reactorEntry
|
|
747
|
+
? ["--enable-threads", "--reactor", staged.basename, staged.reactorEntry]
|
|
748
|
+
: ["--enable-threads", staged.basename];
|
|
696
749
|
}
|
|
697
750
|
|
|
698
751
|
/**
|