@openwop/openwop-conformance 2.0.0-rc.35 → 2.0.0-rc.37
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/dist/spec-artifacts.lock.json +2 -2
- package/package.json +2 -2
- package/schemas/CORPUS-STAMP.json +9 -9
- package/src/setup.ts +58 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "@openwop/spec-artifacts",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
4
|
-
"stampSha256": "
|
|
3
|
+
"version": "2.0.0-rc.37",
|
|
4
|
+
"stampSha256": "f77dd01af56f971ef15f2c24ffbc94e09d364c875897ccd1fa85cd702d62d764"
|
|
5
5
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openwop/openwop-conformance",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.37",
|
|
4
4
|
"description": "Production-ready black-box conformance suite for OpenWOP v1.0 compliant servers.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -56,6 +56,6 @@
|
|
|
56
56
|
"@openwop/spec-artifacts": "file:../spec-artifacts"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@openwop/spec-artifacts": "2.0.0-rc.
|
|
59
|
+
"@openwop/spec-artifacts": "2.0.0-rc.37"
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "Provenance of @openwop/spec-artifacts (RFC 0168 §D.2). files: SHA-256 per file; the conformance suite compares the installed peer against dist/spec-artifacts.lock.json at start.",
|
|
3
3
|
"package": "@openwop/spec-artifacts",
|
|
4
|
-
"version": "2.0.0-rc.
|
|
4
|
+
"version": "2.0.0-rc.37",
|
|
5
5
|
"corpusTag": null,
|
|
6
6
|
"files": {
|
|
7
7
|
"api/.redocly.lint-ignore.yaml": "bf5a8350b88a72fa43f59605ed8d903ed24b6cfccda5e45509c9f6ed9ee4e712",
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"api/grpc/openwop.proto": "c3e72bb17cba514ee98feb6434e6c9b6ea6795bfd086489ec69fd882dd1ad977",
|
|
10
10
|
"api/openapi.yaml": "39081c59fb696159806b0f2f9a42e7e9ff830d622fcf2ad4159b21357580a955",
|
|
11
11
|
"api/redocly.yaml": "b0604c89b2ca6d5076ec25725c539dad44a741a811fe524439ee6daef8baa09f",
|
|
12
|
-
"api/seams-v2.yaml": "
|
|
13
|
-
"api/v2/asyncapi.yaml": "
|
|
14
|
-
"api/v2/openapi.yaml": "
|
|
12
|
+
"api/seams-v2.yaml": "f3ab0cf66e5d6011ce97154b05ed3ffc4b4467106e31a177e3e5ad00580455f8",
|
|
13
|
+
"api/v2/asyncapi.yaml": "dedaaa44160af1828729189d2f2b6a5e1746e640cf867be7d1b2e10d7f001721",
|
|
14
|
+
"api/v2/openapi.yaml": "9ca26479c80eb01a6972b01f3a8585f4da4b185e912b74a671ac3011643c6de8",
|
|
15
15
|
"api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
|
|
16
16
|
"schemas/README.md": "0c0b737ffcf8f30e7d2809cec8a498232de710f41443212922ad8337cdde0b51",
|
|
17
17
|
"schemas/a2a-task-state.schema.json": "c9365918f993f943b4b619d42551eb066a1ed33a08d895d51b395432a5b1f1bc",
|
|
@@ -142,7 +142,7 @@
|
|
|
142
142
|
"schemas/v2/envelopes/schema.response.schema.json": "d049a081267c06c28879c331b147f3ed821b14ccfd93005c67aff64db0a8c68e",
|
|
143
143
|
"schemas/v2/envelopes/ui.a2ui-surface.schema.json": "0a06fbbdc8ba797a6818c79336a98e211ac5ba5747945b4e4098072cd3974d79",
|
|
144
144
|
"schemas/v2/error-envelope.schema.json": "d550beeab958b528c8734fd32e74c438006b99172c5c586f9e0af20ef4b2bee7",
|
|
145
|
-
"schemas/v2/eval-summary.schema.json": "
|
|
145
|
+
"schemas/v2/eval-summary.schema.json": "bcb165148531d33b7dc01de83da3a049d19ebbef6d12300b17a234c7b03d77d9",
|
|
146
146
|
"schemas/v2/export-bundle.schema.json": "bd28905a7729437ab7f2ad8bb33e13a371b2bf5605a7eb2962a0d246de312d69",
|
|
147
147
|
"schemas/v2/form-content-pack-manifest.schema.json": "307884e57946703b6f86ec283034bf56beb68bea4a000743ebbc9eebeed31b07",
|
|
148
148
|
"schemas/v2/frontend-plugin-manifest.schema.json": "fed6b8ddb3056c53b1bfc91525410a4445a3c37a8bf9eb9f6f9964ffea26d993",
|
|
@@ -199,7 +199,7 @@
|
|
|
199
199
|
"schemas/workspace-file.schema.json": "464de85c2a068243084ee9c1d969bc7cd5d8f7948574e58450d6493c38a0e1e4",
|
|
200
200
|
"spec/v1/alias-detectors.json": "fee4594ef49953953ffcd0b3813300067d16b3e65ebff2aac722034ac9b3f545",
|
|
201
201
|
"spec/v1/capability-declaration-classes.json": "e7729aed5c4b4e1dd02abab0530f14cc95f5d4070fe51fb139e7f5cccefa00c6",
|
|
202
|
-
"spec/v1/core-standard-manifest.json": "
|
|
202
|
+
"spec/v1/core-standard-manifest.json": "b3d290b36687c78723de2dff2b04d836e8170211f178e7dfea2c0218021d0c7b",
|
|
203
203
|
"spec/v1/deprecations.json": "1d5acb69a9b8ccb57275a95605f74aef1d920685f8407c9d382a46b59dc803bb",
|
|
204
204
|
"spec/v1/deprecations.schema.json": "18c87e78bedc210431f795ae44c5b5d202f2f3317850d5cf86867d4f1fa1cdfb",
|
|
205
205
|
"spec/v1/event-codemap.json": "3da60d884157793a360da532a9fcbbfb5285636db325a74cec94b34622186d97",
|
|
@@ -226,11 +226,11 @@
|
|
|
226
226
|
"spec/v2/facets/replay.schema.json": "0a5aefb0108c708c6794fadd533cf256709704c4f16dbf44cd63fa8980c78018",
|
|
227
227
|
"spec/v2/facets/sandbox.schema.json": "e75f54486d387b2d089791aa93b5093cd1450f1920753a0f97fc23acdfe978ed",
|
|
228
228
|
"spec/v2/facets/webhooks.schema.json": "0b766033ef4b4c6c2ac6f9979a19843ba024d3a1d1576972dcb55aaba52f1b9a",
|
|
229
|
-
"spec/v2/id-field-bindings.json": "
|
|
229
|
+
"spec/v2/id-field-bindings.json": "965814020c462ad13840b41b26f6830ac472734a1e2e5a67140fad92174c0370",
|
|
230
230
|
"spec/v2/path-manifest.json": "034152e09b1458c66810d4050e20a273b2b9b8fe2d92b66e8b819477de58a1be",
|
|
231
231
|
"spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
|
|
232
232
|
"spec/v2/profiles.json": "1f0ee40491131cf561ef19a0394c47ba476b4567514fe16befb6cada4a10a5a4",
|
|
233
|
-
"spec/v2/release.json": "
|
|
233
|
+
"spec/v2/release.json": "7dcd7a5d2c7b57fceda880e85ce501715f0e0eeae3973f1d39de2570beec93bb"
|
|
234
234
|
},
|
|
235
|
-
"corpusCommit": "
|
|
235
|
+
"corpusCommit": "39886d23d14f0adfe4e0fa275fc73330f4e8db6f"
|
|
236
236
|
}
|
package/src/setup.ts
CHANGED
|
@@ -40,6 +40,8 @@ import { softSkipDisposition } from './lib/soft-skip.js';
|
|
|
40
40
|
import { ItIdAllocator, takeExplicitRequirementId } from './lib/requirement-ids.js';
|
|
41
41
|
import { SPEC_COHERENCE_SCENARIOS, SPEC_COHERENCE_DETAIL } from './lib/spec-coherence.js';
|
|
42
42
|
import type { DiscoveryPayload } from './lib/profiles.js';
|
|
43
|
+
import { targetMajor } from './lib/seams.js';
|
|
44
|
+
import { softSkip } from './lib/soft-skip.js';
|
|
43
45
|
|
|
44
46
|
const SUITE_INIT_TIMEOUT_MS = 5_000;
|
|
45
47
|
|
|
@@ -277,6 +279,62 @@ function _fileOf(task: { file?: { filepath?: string; name?: string } } | undefin
|
|
|
277
279
|
const f = task?.file?.filepath ?? task?.file?.name;
|
|
278
280
|
return typeof f === 'string' && f.length > 0 ? basename(f) : null;
|
|
279
281
|
}
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
// The applicability check and the assertion MUST run under the same contract.
|
|
284
|
+
//
|
|
285
|
+
// A scenario's registration in scenario-majors.json says which target majors it
|
|
286
|
+
// is written for. The driver reads OPENWOP_TARGET_MAJOR to decide which header
|
|
287
|
+
// and path space every probe uses. Nothing connected the two: a lane that ran
|
|
288
|
+
// vitest directly over all 501 files at the default (major 1) executed every
|
|
289
|
+
// major-2 scenario with major-1 requests. The scenarios' own gates call
|
|
290
|
+
// v2Discovery(), which sets the header EXPLICITLY, so the gate passed and the
|
|
291
|
+
// probe went out as v1 — a check that proved the host speaks v2 with one
|
|
292
|
+
// request, then tested a v2 requirement with a request that did not.
|
|
293
|
+
//
|
|
294
|
+
// Measured on a tier-1 host 2026-09-04: three "host defects" reported from that
|
|
295
|
+
// lane, all of which evaporated at major 2; the host was one edit from "fixing"
|
|
296
|
+
// correct behaviour. And in the other direction: 4 of 56 v2 files fail on every
|
|
297
|
+
// host forever under a major-1 driver, so a gate that runs them that way is red
|
|
298
|
+
// by construction and gets reasoned past. Both are the same defect: a scoped
|
|
299
|
+
// signal read as unscoped, with the scope nowhere in the output.
|
|
300
|
+
//
|
|
301
|
+
// So: a file whose registered majors do not include the driver's target major
|
|
302
|
+
// is INAPPLICABLE to this lane, recorded as such with the reason, and never
|
|
303
|
+
// probes. Files not in the registry (coherence checks, lib tests) are untouched.
|
|
304
|
+
// ---------------------------------------------------------------------------
|
|
305
|
+
const SCENARIO_MAJORS: Record<string, number[]> = (() => {
|
|
306
|
+
try {
|
|
307
|
+
const p = join(PKG_ROOT_PATH, 'scenario-majors.json');
|
|
308
|
+
if (!existsSync(p)) return {};
|
|
309
|
+
return (JSON.parse(readFileSync(p, 'utf8')) as { majors?: Record<string, number[]> }).majors ?? {};
|
|
310
|
+
} catch {
|
|
311
|
+
return {};
|
|
312
|
+
}
|
|
313
|
+
})();
|
|
314
|
+
|
|
315
|
+
beforeEach((ctx) => {
|
|
316
|
+
const p = (expect.getState() as { testPath?: string }).testPath;
|
|
317
|
+
if (!p) return;
|
|
318
|
+
const file = basename(p);
|
|
319
|
+
const majors = SCENARIO_MAJORS[file];
|
|
320
|
+
if (!majors) return;
|
|
321
|
+
const lane = targetMajor();
|
|
322
|
+
if (majors.includes(lane)) return;
|
|
323
|
+
const detail = `registered for target major ${majors.join('/')} and this lane runs at major ${lane} (OPENWOP_TARGET_MAJOR) — the probe would go out under a contract the scenario's gate does not use; select files with --target-major or set the variable`;
|
|
324
|
+
// Two records, one per resolver. The per-TEST disposition is read from the
|
|
325
|
+
// requirement journal (the same entry behaviorGate writes), so the row lands
|
|
326
|
+
// as `inapplicable` with this reason rather than `skipped`, which under RFC
|
|
327
|
+
// 0148 would claim the operator opted out. The per-FILE note covers the
|
|
328
|
+
// all-skipped fallback in resolveFileRecord.
|
|
329
|
+
try {
|
|
330
|
+
recordRequirement('openwop.family.lane-target-major', 'inapplicable', detail, { scenarioFile: file });
|
|
331
|
+
} catch {
|
|
332
|
+
/* never fail a test for bookkeeping */
|
|
333
|
+
}
|
|
334
|
+
softSkip('inapplicable', detail);
|
|
335
|
+
ctx.skip();
|
|
336
|
+
});
|
|
337
|
+
|
|
280
338
|
beforeAll(({}, suite) => {
|
|
281
339
|
// Mark the ledger journal BEFORE the file's tests run, so a behaviorGate
|
|
282
340
|
// decision made by the very first test is inside the file's window.
|