@openwop/openwop-conformance 2.45.15 → 2.45.17

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +2 -2
  3. package/dist/spec-artifacts.lock.json +2 -2
  4. package/package.json +2 -2
  5. package/requirements.json +1335 -14
  6. package/scenario-majors.json +104 -2
  7. package/schemas/CORPUS-STAMP.json +13 -13
  8. package/src/lib/artifact-schema-url-witness.ts +83 -0
  9. package/src/lib/dispatch-witness.ts +212 -0
  10. package/src/lib/family-advert-witness.ts +204 -5
  11. package/src/lib/fixture-run-observer.ts +97 -0
  12. package/src/lib/prompt-library-witness.ts +11 -2
  13. package/src/lib/provider-usage-witness.ts +63 -0
  14. package/src/lib/run-graph-double.ts +144 -0
  15. package/src/lib/subworkflow-witness.ts +192 -0
  16. package/src/scenarios/v2-agent-runtime-advertisement.test.ts +51 -0
  17. package/src/scenarios/v2-ai-envelope-advertisement.test.ts +43 -0
  18. package/src/scenarios/v2-artifact-created-static.test.ts +92 -0
  19. package/src/scenarios/v2-artifact-type-schema-url.test.ts +44 -0
  20. package/src/scenarios/v2-artifact-types-advertisement.test.ts +64 -0
  21. package/src/scenarios/v2-authorization-advertisement.test.ts +66 -0
  22. package/src/scenarios/v2-channel-presence-advertisement.test.ts +41 -0
  23. package/src/scenarios/v2-conversation-turn-model-provenance-advertisement.test.ts +41 -0
  24. package/src/scenarios/v2-conversation-turn-model-provenance.test.ts +110 -0
  25. package/src/scenarios/v2-credentials-advertisement.test.ts +66 -0
  26. package/src/scenarios/v2-data-residency-admission.test.ts +98 -0
  27. package/src/scenarios/v2-data-residency-advertisement.test.ts +52 -0
  28. package/src/scenarios/v2-dead-letter-advertisement.test.ts +54 -0
  29. package/src/scenarios/v2-discovery-etag.test.ts +86 -0
  30. package/src/scenarios/v2-dispatch-input-mapping.test.ts +70 -0
  31. package/src/scenarios/v2-dispatch-loop.test.ts +80 -0
  32. package/src/scenarios/v2-envelope-contracts-advertisement.test.ts +40 -0
  33. package/src/scenarios/v2-export-bundle-static.test.ts +108 -0
  34. package/src/scenarios/v2-multi-party-conversation-advertisement.test.ts +52 -0
  35. package/src/scenarios/v2-node-pack-runtimes-advertisement.test.ts +52 -0
  36. package/src/scenarios/v2-nondeterminism-policy-advertisement.test.ts +41 -0
  37. package/src/scenarios/v2-portability-advertisement.test.ts +63 -0
  38. package/src/scenarios/v2-prompt-library-advertisement.test.ts +40 -0
  39. package/src/scenarios/v2-prompt-list-and-fetch.test.ts +4 -2
  40. package/src/scenarios/v2-provider-usage-advertisement.test.ts +61 -0
  41. package/src/scenarios/v2-provider-usage-emission.test.ts +50 -0
  42. package/src/scenarios/v2-provider-usage-payload-static.test.ts +92 -0
  43. package/src/scenarios/v2-purpose-propagation-advertisement.test.ts +52 -0
  44. package/src/scenarios/v2-run-snapshot-etag.test.ts +35 -22
  45. package/src/scenarios/v2-scheduling-advertisement.test.ts +55 -0
  46. package/src/scenarios/v2-self-hosted-runner-advertisement.test.ts +52 -0
  47. package/src/scenarios/v2-self-hosted-runner-frames-static.test.ts +121 -0
  48. package/src/scenarios/v2-sub-workflow-advertisement.test.ts +53 -0
  49. package/src/scenarios/v2-subworkflow-input-mapping.test.ts +74 -0
  50. package/src/scenarios/v2-subworkflow-linkage.test.ts +76 -0
  51. package/src/scenarios/v2-ui-plugins-advertisement.test.ts +85 -0
@@ -0,0 +1,85 @@
1
+ /**
2
+ * v2 — the `uiPlugins` advertisement (`spec/v2/core/packs.md` §Front-end plugin packs): the front-end plugin pack claim. The v1 twin is
3
+ * `frontend-plugin-packs`;
4
+ * the legs live in `lib/family-advert-witness.ts` (witness wave 3).
5
+ *
6
+ * record the record validates against its capabilities-schema seat;
7
+ * isolation-model uiPlugins.isolation is a closed mechanism or an x-host value;
8
+ * surfaces-closed uiPlugins.surfaces are unique members of the closed surface set;
9
+ * host-api-closed uiPlugins.hostApi are unique members of the ui-plugin/1 method set;
10
+ * max-entry-bytes uiPlugins.maxEntryBytes is a positive integer;
11
+ *
12
+ * Not here: isolation, egress, the RPC allow-list and the no-BYOK rule are seam-gated and v2 mounts no plugin seam; they need a normative observation path (TODO §8).
13
+ *
14
+ * Dispositions: discovery unreadable ⇒ `blocked`; `uiPlugins` absent, or the
15
+ * facet a leg reads absent ⇒ `inapplicable`.
16
+ *
17
+ * @see spec/v2/core/packs.md §Front-end plugin packs
18
+ */
19
+
20
+ import { describe, it, expect } from 'vitest';
21
+ import { v2Discovery, familyAdvertised } from '../lib/v2.js';
22
+ import { softSkip } from '../lib/soft-skip.js';
23
+ import { req } from '../lib/requirement-ids.js';
24
+ import { majorProfile } from '../lib/major-profile.js';
25
+ import { recordSchemaLeg, uiPluginsHostApiLeg, uiPluginsIsolationLeg, uiPluginsMaxEntryBytesLeg, uiPluginsSurfacesLeg } from '../lib/family-advert-witness.js';
26
+
27
+ const PROFILE = majorProfile(2);
28
+ const DOC = 'packs.md §Front-end plugin packs';
29
+ const UNREADABLE = 'v2 discovery unreachable — /.well-known/openwop did not answer 200 JSON under OpenWOP-Version: 2.0';
30
+ const ID_RECORD = 'openwop.requirement.ui-plugins.advert-record-schema';
31
+ const ID_ISOLATION_MODEL = 'openwop.requirement.ui-plugins.isolation-model';
32
+ const ID_SURFACES_CLOSED = 'openwop.requirement.ui-plugins.surfaces-closed';
33
+ const ID_HOST_API_CLOSED = 'openwop.requirement.ui-plugins.host-api-closed';
34
+ const ID_MAX_ENTRY_BYTES = 'openwop.requirement.ui-plugins.max-entry-bytes';
35
+
36
+ async function discovery(): Promise<Record<string, unknown> | null> {
37
+ try { return await v2Discovery(); } catch { return null; }
38
+ }
39
+
40
+ describe('v2 uiPlugins advertisement (packs.md §Front-end plugin packs)', () => {
41
+ it('the uiPlugins record validates against its capabilities-schema seat', async () => {
42
+ const doc = await discovery();
43
+ if (!doc) return softSkip('blocked', UNREADABLE);
44
+ if (!(await familyAdvertised('uiPlugins'))) return softSkip('inapplicable', 'the host does not advertise uiPlugins');
45
+ const out = recordSchemaLeg(PROFILE, doc, 'uiPlugins', DOC);
46
+ if (out.kind === 'skip') return softSkip(out.disposition, out.reason);
47
+ for (const x of out.findings) expect(x.ok, req(ID_RECORD, x.doc, x.message)).toBe(true);
48
+ });
49
+
50
+ it('uiPlugins.isolation is a closed mechanism or an x-host value', async () => {
51
+ const doc = await discovery();
52
+ if (!doc) return softSkip('blocked', UNREADABLE);
53
+ if (!(await familyAdvertised('uiPlugins'))) return softSkip('inapplicable', 'the host does not advertise uiPlugins');
54
+ const out = uiPluginsIsolationLeg(PROFILE, doc);
55
+ if (out.kind === 'skip') return softSkip(out.disposition, out.reason);
56
+ for (const x of out.findings) expect(x.ok, req(ID_ISOLATION_MODEL, x.doc, x.message)).toBe(true);
57
+ });
58
+
59
+ it('uiPlugins.surfaces are unique members of the closed surface set', async () => {
60
+ const doc = await discovery();
61
+ if (!doc) return softSkip('blocked', UNREADABLE);
62
+ if (!(await familyAdvertised('uiPlugins'))) return softSkip('inapplicable', 'the host does not advertise uiPlugins');
63
+ const out = uiPluginsSurfacesLeg(PROFILE, doc);
64
+ if (out.kind === 'skip') return softSkip(out.disposition, out.reason);
65
+ for (const x of out.findings) expect(x.ok, req(ID_SURFACES_CLOSED, x.doc, x.message)).toBe(true);
66
+ });
67
+
68
+ it('uiPlugins.hostApi are unique members of the ui-plugin/1 method set', async () => {
69
+ const doc = await discovery();
70
+ if (!doc) return softSkip('blocked', UNREADABLE);
71
+ if (!(await familyAdvertised('uiPlugins'))) return softSkip('inapplicable', 'the host does not advertise uiPlugins');
72
+ const out = uiPluginsHostApiLeg(PROFILE, doc);
73
+ if (out.kind === 'skip') return softSkip(out.disposition, out.reason);
74
+ for (const x of out.findings) expect(x.ok, req(ID_HOST_API_CLOSED, x.doc, x.message)).toBe(true);
75
+ });
76
+
77
+ it('uiPlugins.maxEntryBytes is a positive integer', async () => {
78
+ const doc = await discovery();
79
+ if (!doc) return softSkip('blocked', UNREADABLE);
80
+ if (!(await familyAdvertised('uiPlugins'))) return softSkip('inapplicable', 'the host does not advertise uiPlugins');
81
+ const out = uiPluginsMaxEntryBytesLeg(PROFILE, doc);
82
+ if (out.kind === 'skip') return softSkip(out.disposition, out.reason);
83
+ for (const x of out.findings) expect(x.ok, req(ID_MAX_ENTRY_BYTES, x.doc, x.message)).toBe(true);
84
+ });
85
+ });