@openwop/openwop-conformance 2.0.0-rc.48 → 2.0.0-rc.49

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.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "package": "@openwop/spec-artifacts",
3
- "version": "2.0.0-rc.48",
4
- "stampSha256": "209fc2757dfc867b83db989afa45e48404cefd7aacd015c99328a39a3aa000ec"
3
+ "version": "2.0.0-rc.49",
4
+ "stampSha256": "7e65e852ca8df98dbfd604c7da903894a0cbd15feec6fe88f2e0879f88187f22"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwop/openwop-conformance",
3
- "version": "2.0.0-rc.48",
3
+ "version": "2.0.0-rc.49",
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.48"
59
+ "@openwop/spec-artifacts": "2.0.0-rc.49"
60
60
  }
61
61
  }
@@ -1,4 +1,6 @@
1
1
  {
2
2
  "$comment": "old id → new id. Add a row when a test title is reworded so bundles citing the old id still resolve.",
3
- "aliases": {}
3
+ "aliases": {
4
+ "openwop.it.v2-run-cancel.cancelling-a-terminal-run-answers-409-run-terminal-or-200-idempotently-the-prose": "openwop.it.v2-run-cancel.cancelling-a-terminal-run-is-refused-409-run-terminal"
5
+ }
4
6
  }
package/requirements.json CHANGED
@@ -28172,7 +28172,7 @@
28172
28172
  "interpolated": true
28173
28173
  },
28174
28174
  {
28175
- "section": null,
28175
+ "section": "spec/v2/core/identity.md §5",
28176
28176
  "requirement": null,
28177
28177
  "interpolated": true
28178
28178
  },
@@ -28184,16 +28184,21 @@
28184
28184
  ]
28185
28185
  },
28186
28186
  {
28187
- "id": "openwop.it.v2-run-cancel.cancelling-a-terminal-run-answers-409-run-terminal-or-200-idempotently-the-prose",
28187
+ "id": "openwop.it.v2-run-cancel.cancelling-a-terminal-run-is-refused-409-run-terminal",
28188
28188
  "file": "v2-run-cancel.test.ts",
28189
28189
  "line": 65,
28190
- "title": "cancelling a terminal run answers 409 run_terminal or 200 idempotently — the prose is silent, the leg records which",
28190
+ "title": "cancelling a terminal run is refused 409 run_terminal",
28191
28191
  "explicitId": null,
28192
28192
  "citations": [
28193
28193
  {
28194
28194
  "section": null,
28195
28195
  "requirement": null,
28196
28196
  "interpolated": true
28197
+ },
28198
+ {
28199
+ "section": null,
28200
+ "requirement": "the refusal MUST be run_terminal",
28201
+ "interpolated": true
28197
28202
  }
28198
28203
  ]
28199
28204
  },
@@ -28387,7 +28392,7 @@
28387
28392
  "interpolated": true
28388
28393
  },
28389
28394
  {
28390
- "section": "spec/v2/core/errors.md",
28395
+ "section": null,
28391
28396
  "requirement": null,
28392
28397
  "interpolated": true
28393
28398
  },
@@ -28397,8 +28402,9 @@
28397
28402
  "interpolated": true
28398
28403
  },
28399
28404
  {
28400
- "section": "spec/v2/core/errors.md",
28401
- "requirement": "the 409 MUST carry an error envelope with a registered code"
28405
+ "section": null,
28406
+ "requirement": null,
28407
+ "interpolated": true
28402
28408
  }
28403
28409
  ]
28404
28410
  },
@@ -28439,6 +28445,16 @@
28439
28445
  "requirement": null,
28440
28446
  "interpolated": true
28441
28447
  },
28448
+ {
28449
+ "section": null,
28450
+ "requirement": null,
28451
+ "interpolated": true
28452
+ },
28453
+ {
28454
+ "section": null,
28455
+ "requirement": null,
28456
+ "interpolated": true
28457
+ },
28442
28458
  {
28443
28459
  "section": "spec/v2/core/events.md §run.paused",
28444
28460
  "requirement": null,
@@ -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.48",
4
+ "version": "2.0.0-rc.49",
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": "5bc99c81f5b08a422e0d2132c8214c00b9301bc5c4dc2c54daacdba94f26bcea",
13
- "api/v2/asyncapi.yaml": "dfcee52de5dc650236c2e7707cca679f771c0699a3fcd02809fe67565f3868ab",
14
- "api/v2/openapi.yaml": "789b75d23df21ddfedaa84a9a82cba028bb4eb74fd4d73482064f4eb952b8854",
12
+ "api/seams-v2.yaml": "93ecc218d08555eeac0d652768b78050ae7a4847301ddc6664c7415ab12e038a",
13
+ "api/v2/asyncapi.yaml": "bec2259c5ce9ea7c0935093bdae856570b83d2242d5e298b0b6a8684424a7a83",
14
+ "api/v2/openapi.yaml": "fc4ee6fdf254f2b414038be709acaeaa6f283505ad8545d1ec6b53d83d1bea25",
15
15
  "api/v2/redocly.yaml": "1e66b60e6118ad11a823bb620678be464d99dfe50a40e3e6f93ec9429b88b34c",
16
16
  "schemas/README.md": "0c0b737ffcf8f30e7d2809cec8a498232de710f41443212922ad8337cdde0b51",
17
17
  "schemas/a2a-task-state.schema.json": "c9365918f993f943b4b619d42551eb066a1ed33a08d895d51b395432a5b1f1bc",
@@ -141,7 +141,7 @@
141
141
  "schemas/v2/envelopes/schema.request.schema.json": "be2c5f7aa881cdd252ccff47ac02193659e1393633a1541f4297383205d384a2",
142
142
  "schemas/v2/envelopes/schema.response.schema.json": "d049a081267c06c28879c331b147f3ed821b14ccfd93005c67aff64db0a8c68e",
143
143
  "schemas/v2/envelopes/ui.a2ui-surface.schema.json": "0a06fbbdc8ba797a6818c79336a98e211ac5ba5747945b4e4098072cd3974d79",
144
- "schemas/v2/error-envelope.schema.json": "c08241b74e41f4e3524c25f1c611195ed0e79b49a8ecf63e304add67070bdce5",
144
+ "schemas/v2/error-envelope.schema.json": "2e09ac2c32a0c0b7098b0ffeaa2822b5dd82b69c23bb3c07d6be2053e2102b19",
145
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",
@@ -171,7 +171,7 @@
171
171
  "schemas/v2/run-diff-response.schema.json": "6ab6cd265dc7e0a2086c6659c46aa0e7b43e6302949f0adac5d7deb1c7c0ecd3",
172
172
  "schemas/v2/run-event-payloads.schema.json": "10f56762616535d01f411afdd98a70ecafc0a961f77aa68cf164b1da458464b4",
173
173
  "schemas/v2/run-event.schema.json": "1a9946374af9323b71635d00fed22abe02c300fa2cf3ae3e9c30f3e553e408ec",
174
- "schemas/v2/run-options.schema.json": "6d6052596ab0f17acfb00fdfc89907da7724f952e5ffbe1f81d94ba23d4c77cd",
174
+ "schemas/v2/run-options.schema.json": "ff240805478158cbd2f661979c5eb4f5eda11f9c053b7ba587cb0211a9252d74",
175
175
  "schemas/v2/run-orchestrator-decided-event.schema.json": "bb76e15ff72e669f12938684033b55dc567470e1a378e19ffc3fa0e4034ab5a7",
176
176
  "schemas/v2/run-snapshot.schema.json": "0ee8a50c6be210db415a7c4345298e70a6ae3dd0dd764ccc514bc1c501437586",
177
177
  "schemas/v2/security-advisory.schema.json": "6a382f737730a738d634266315e9d335e5760020a0cdd9f30727c2f987a01770",
@@ -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": "8f3913990bcebac56db79ec3717437f940156bc05ef878ef863814faada569d4",
202
+ "spec/v1/core-standard-manifest.json": "790bd9d6f00c2d258c0d66d56ed1aea0e0edf8d3b8d1ca7aa70db393b252ee48",
203
203
  "spec/v1/deprecations.json": "1d5acb69a9b8ccb57275a95605f74aef1d920685f8407c9d382a46b59dc803bb",
204
204
  "spec/v1/deprecations.schema.json": "18c87e78bedc210431f795ae44c5b5d202f2f3317850d5cf86867d4f1fa1cdfb",
205
205
  "spec/v1/event-codemap.json": "3da60d884157793a360da532a9fcbbfb5285636db325a74cec94b34622186d97",
@@ -213,7 +213,7 @@
213
213
  "spec/v1/spec-gaps.json": "6cc9962c6b969f632e07a78b52a4f61447ff579e2990cbae989866f584a86042",
214
214
  "spec/v2/declaration.json": "c15a6a8f08ebd326d1b60398d93d7f7d5abe5c1b8284874fdb13b59f44443210",
215
215
  "spec/v2/declaration.schema.json": "b0881a76228dfbd1b85a2ec7b7259a60197f768344535cdb475db6ff719b0e54",
216
- "spec/v2/errors.json": "c2dd3fa0401efa0dc78da3b21e32b58a89ed5114cebdde96d3eb999a702118f0",
216
+ "spec/v2/errors.json": "63583dec5a4b6de0bacc2894b0752b3da128a0afed80f3dc244e552bc0dd0e55",
217
217
  "spec/v2/event-codemap.json": "37869a03cdfd8758b57e6f350641a6ebbd383231cebda51f5473ad85f94ab74c",
218
218
  "spec/v2/event-codemap.schema.json": "ce2d0ca085d7668d7ef745d2560b385ec6881d24a6d4b47c49931986b2ba642d",
219
219
  "spec/v2/ext/provider-idempotency/registry.json": "5b5fecad604fb4ab38da39f5abe697a4e57b05406c398f8afeb377331b2bd965",
@@ -230,8 +230,8 @@
230
230
  "spec/v2/path-manifest.json": "034152e09b1458c66810d4050e20a273b2b9b8fe2d92b66e8b819477de58a1be",
231
231
  "spec/v2/peer-dependency-aliases.json": "d10299280abee08258502925bc327293ee413e0108cd6e6ec75ff6110653308d",
232
232
  "spec/v2/profiles.json": "5019ac8209540bfbeee9c3232530d4e599be0ab926d817ff48edcec8419eb209",
233
- "spec/v2/release.json": "fafdf20cd6fda346c9a703aee914f79997e63299dbd7a1b66895f9ba3d29f0db",
233
+ "spec/v2/release.json": "0c1e10938fd53b0b4798e9ac7c92727c3d5c83643847cbb1da91a6920800f27f",
234
234
  "spec/v2/retention-floors.json": "eaf3722d95c79947af1d4269ef85117e126518c588cfcf1a2b21b97269f51624"
235
235
  },
236
- "corpusCommit": "0af233770f4e6261b43fd4122d482fbed2866582"
236
+ "corpusCommit": "67da501622b8d75dff385cb7f20ff8b96f6dd311"
237
237
  }
@@ -51,7 +51,7 @@ describe('v2 run-annotation-not-event (runs.md §Annotations)', () => {
51
51
 
52
52
  const ann = await http(() => driver.post(`/runs/${enc(runId)}/annotations`, { signal: { kind: 'label', label: 'conformance' }, note: 'openwop conformance annotation' }));
53
53
  if (ann === null) return softSkip('blocked', 'POST /runs/{runId}/annotations unreachable (fetch failed)');
54
- if (ann.status === 501 || ann.status === 404) return softSkip('inapplicable', `POST /runs/{runId}/annotations answered ${ann.status} with feedback advertised — runs.md §Surface says 501 when unadvertised and the registry names no 501 code (filed); treated as not mounted`);
54
+ if (ann.status === 501 || ann.status === 404) return softSkip('blocked', `POST /runs/{runId}/annotations answered ${ann.status} although feedback is advertised — the surface is not mounted (an unadvertised feedback answers 404 not_found; 501 is not a registered shape)`);
55
55
  expect(ann.status, req(ID, DOC, `createAnnotation MUST answer 201 — got ${ann.status} ${readErrorCode(ann.json) ?? ''}`.trim())).toBe(201);
56
56
  const check = v2Validator('annotation')(ann.json);
57
57
  expect(check.ok, req(ID, 'schemas/v2/annotation.schema.json', `the 201 body MUST validate: ${check.errors}`)).toBe(true);
@@ -73,7 +73,7 @@ describe('v2 run-bulk-cancel (runs.md §Cancel)', () => {
73
73
  const foreign = entries[1]!;
74
74
  expect(foreign.ok, req(ID, DOC, 'the foreign-tenant entry MUST be ok: false')).toBe(false);
75
75
  const fcode = String(foreign.error?.code);
76
- expect(['run_forbidden', 'id_tenant_mismatch', 'not_found'].includes(fcode), req(ID, DOC, `the foreign entry MUST carry an error envelope with run_forbidden (runs.md) or id_tenant_mismatch / not_found (identity.md §5) got ${fcode}; the two documents disagree (filed)`)).toBe(true);
76
+ expect(['id_tenant_mismatch', 'not_found'].includes(fcode), req(ID, 'spec/v2/core/identity.md §5', `an id whose tenant segment is not the caller's MUST be refused inside the entry with id_tenant_mismatch (or not_found where existence is not leaked) — identity.md §5 applies inside a bulk entry exactly as on a path; run_forbidden is for a same-tenant run the caller may not cancel — got ${fcode}`)).toBe(true);
77
77
  for (const own of [entries[0]!, entries[2]!]) {
78
78
  const okShape = own.ok === true && ['cancelling', 'cancelled'].includes(String(own.status));
79
79
  const terminalShape = own.ok === false && String(own.error?.code) === 'run_terminal';
@@ -62,7 +62,7 @@ async function eventTypes(runId: string): Promise<string[] | null> {
62
62
  const TERMINAL = new Set(['completed', 'failed', 'cancelled']);
63
63
 
64
64
  describe('v2 run-cancel (runs.md §Cancel)', () => {
65
- it('cancelling a terminal run answers 409 run_terminal or 200 idempotently — the prose is silent, the leg records which', async () => {
65
+ it('cancelling a terminal run is refused 409 run_terminal', async () => {
66
66
  if (!(await discovery())) return softSkip('blocked', 'v2 discovery unreachable');
67
67
  const c = await create({ workflowId: NOOP });
68
68
  if ('reason' in c) return softSkip('blocked', c.reason);
@@ -72,8 +72,8 @@ describe('v2 run-cancel (runs.md §Cancel)', () => {
72
72
  if (res === null) return softSkip('blocked', 'POST /runs/{runId}/cancel unreachable (fetch failed)');
73
73
  const code = readErrorCode(res.json);
74
74
  const status = (res.json as { status?: unknown } | null)?.status;
75
- const ok = (res.status === 409 && code === 'run_terminal') || (res.status === 200 && status === 'cancelled');
76
- expect(ok, req(ID, DOC, `cancel on a terminal (${s}) run MUST be 409 run_terminal or 200 { status: cancelled } — got ${res.status} ${code ?? String(status)}. §Cancel's 200 grammar is { runId, status: cancelling | cancelled }; a 200 echoing ${s} is outside it, so the only conforming refusal is 409 run_terminal (the prose does not say so in words — filed)`)).toBe(true);
75
+ expect(res.status, req(ID, DOC, `a cancel on a run that is already terminal (${s}) MUST be refused 409 run_terminal — got ${res.status} ${code ?? String(status)}; a 200 echoing the terminal state is outside §Cancel's 200 grammar { runId, status: cancelling | cancelled }`)).toBe(409);
76
+ expect(code, req(ID, DOC, 'the refusal MUST be run_terminal')).toBe('run_terminal');
77
77
  });
78
78
 
79
79
  it('cancelling a running run answers 200 with cancelling|cancelled, emits run.cancelled within 5 s, and the snapshot reads cancelled', async () => {
@@ -66,11 +66,11 @@ describe('v2 run-pause-resume (runs.md §Pause and resume)', () => {
66
66
  if (pause === null) return softSkip('blocked', 'POST /runs/{runId}:pause unreachable (fetch failed)');
67
67
  if (pause.status === 404) return softSkip('blocked', 'POST /runs/{runId}:pause answered 404 — pauseRun is a core operation (runs.md §Surface) and is not mounted');
68
68
  expect(pause.status, req(ID, DOC, `pause on a terminal (${s}) run MUST answer 409 — got ${pause.status} ${readErrorCode(pause.json) ?? ''}`.trim())).toBe(409);
69
- expect(typeof readErrorCode(pause.json) === 'string', req(ID, 'spec/v2/core/errors.md', `the 409 MUST carry an error envelope with a registered code (got ${String(readErrorCode(pause.json))}); runs.md names none for this case (filed)`)).toBe(true);
69
+ expect(readErrorCode(pause.json), req(ID, DOC, `a pause refused because the run is terminal MUST carry run_terminal (got ${String(readErrorCode(pause.json))})`)).toBe('run_terminal');
70
70
  const resume = await http(() => driver.post(`/runs/${enc(c.runId)}:resume`, {}));
71
71
  if (resume === null) return softSkip('blocked', 'POST /runs/{runId}:resume unreachable (fetch failed)');
72
72
  expect(resume.status, req(ID, DOC, `resume on a run that is not paused MUST answer 409 — got ${resume.status} ${readErrorCode(resume.json) ?? ''}`.trim())).toBe(409);
73
- expect(typeof readErrorCode(resume.json) === 'string', req(ID, 'spec/v2/core/errors.md', 'the 409 MUST carry an error envelope with a registered code')).toBe(true);
73
+ expect(readErrorCode(resume.json), req(ID, DOC, `a resume refused because the run is terminal MUST carry run_terminal (got ${String(readErrorCode(resume.json))})`)).toBe('run_terminal');
74
74
  if (!isFixtureAdvertised(DELAY)) return softSkip('inapplicable', `${DELAY} fixture not advertised — the positive pause/resume leg cannot run, so the two 409s above are witnessed without their control (a host answering 409 to everything would pass them)`);
75
75
  });
76
76
 
@@ -91,6 +91,9 @@ describe('v2 run-pause-resume (runs.md §Pause and resume)', () => {
91
91
  expect(pb?.status, req(ID, DOC, `the 202 MUST carry status paused (got ${String(pb?.status)})`)).toBe('paused');
92
92
  const again = await http(() => driver.post(`/runs/${enc(c.runId)}:pause`, {}));
93
93
  expect(again?.status ?? null, req(ID, DOC, `a second pause on a paused run MUST answer 409 — got ${again?.status ?? 'no response'}`)).toBe(409);
94
+ expect(readErrorCode(again?.json), req(ID, DOC, `a pause refused on a non-terminal run MUST carry run_state_conflict (got ${String(readErrorCode(again?.json))})`)).toBe('run_state_conflict');
95
+ const runStatus = (again?.json as { error?: { details?: { runStatus?: unknown } } } | null)?.error?.details?.runStatus;
96
+ expect(runStatus, req(ID, DOC, `run_state_conflict MUST carry details.runStatus naming the status that refused it (got ${String(runStatus)})`)).toBe('paused');
94
97
  const resume = await http(() => driver.post(`/runs/${enc(c.runId)}:resume`, { reason: 'conformance' }));
95
98
  expect(resume?.status ?? null, req(ID, DOC, `resumeRun on a paused run MUST answer 202 — got ${resume?.status ?? 'no response'} ${readErrorCode(resume?.json) ?? ''}`.trim())).toBe(202);
96
99
  const rb = resume?.json as { runId?: unknown; status?: unknown } | null;