@openwop/openwop-conformance 2.45.17 → 2.45.19

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,121 +0,0 @@
1
- /**
2
- * v2 — the self-hosted-runner frame and registration shapes, statically
3
- * (`spec/v2/core/execution.md` §selfHostedRunner; RFC 0122). The v1 twin is
4
- * the schema half of `self-hosted-runner`; its live legs (subject isolation,
5
- * `runner_unavailable`, at-most-once) need a runner seam and are not ported.
6
- *
7
- * compile the three schemas compile under Ajv 2020 with the v2 tree;
8
- * dispatch a model and a tool dispatch frame validate; a frame with no
9
- * `seq`, a non-integer or negative `seq`, an unknown `kind`, a
10
- * model frame without `provider`/`model`, or a tool frame
11
- * without `tool` is rejected;
12
- * result a result frame validates; one without `output` is rejected;
13
- * closed dispatch, result and registration (and its `capabilities`)
14
- * are closed objects, so no frame or record can carry a
15
- * credential field alongside the step ("A runner credential
16
- * MUST NOT transit the host or appear in any frame");
17
- * registration a registration validates; one without `subject` is rejected
18
- * (subject-first routing keys on it).
19
- *
20
- * The shape rules these schemas state bind the host's dispatch frames and its
21
- * registration record; the result frame is the runner's, so its legs witness
22
- * the corpus shape the host's intake is written against, not the host.
23
- *
24
- * Host-free: every leg runs with no OPENWOP_BASE_URL.
25
- *
26
- * @see spec/v2/core/execution.md §selfHostedRunner
27
- * @see schemas/v2/self-hosted-runner-dispatch-frame.schema.json
28
- */
29
-
30
- import { describe, it, expect } from 'vitest';
31
- import { v2Validator } from '../lib/v2.js';
32
- import { req } from '../lib/requirement-ids.js';
33
-
34
- const DOC = 'execution.md §selfHostedRunner';
35
- const ID_COMPILE = 'openwop.requirement.self-hosted-runner.frame-schemas-compile';
36
- const ID_DISPATCH = 'openwop.requirement.self-hosted-runner.dispatch-frame-shape';
37
- const ID_RESULT = 'openwop.requirement.self-hosted-runner.result-frame-shape';
38
- const ID_CLOSED = 'openwop.requirement.self-hosted-runner.frames-closed';
39
- const ID_REGISTRATION = 'openwop.requirement.self-hosted-runner.registration-shape';
40
-
41
- const SCHEMAS = ['self-hosted-runner-dispatch-frame', 'self-hosted-runner-result-frame', 'self-hosted-runner-registration'] as const;
42
-
43
- const MODEL_FRAME = { runId: 'acme/run_x-xxxxxxxxxx', stepId: 'step_3', seq: 12, kind: 'model', provider: 'anthropic', model: 'claude-x', inputs: { messages: [] } } as const;
44
- const TOOL_FRAME = { runId: 'acme/run_y-xxxxxxxxxx', stepId: 'step_1', seq: 0, kind: 'tool', tool: 'local.shell.readFile', inputs: { path: '/tmp/x' } } as const;
45
- const RESULT = { runId: 'acme/run_x-xxxxxxxxxx', stepId: 'step_3', seq: 12, output: { role: 'assistant', content: 'ok' } } as const;
46
- const REGISTRATION = { runnerId: 'runner_laptop_01', subject: 'user_42', capabilities: { providers: ['anthropic'], models: ['claude-x'] } } as const;
47
-
48
- function without(o: Readonly<Record<string, unknown>>, field: string): Record<string, unknown> {
49
- const c: Record<string, unknown> = { ...o };
50
- delete c[field];
51
- return c;
52
- }
53
-
54
- describe('v2 self-hosted-runner frames: schemas compile', () => {
55
- for (const name of SCHEMAS) {
56
- it(`${name}.schema.json compiles under Ajv 2020`, () => {
57
- expect(() => v2Validator(name), req(ID_COMPILE, DOC, `schemas/v2/${name}.schema.json MUST compile`)).not.toThrow();
58
- });
59
- }
60
- });
61
-
62
- describe('v2 self-hosted-runner frames: dispatch frame', () => {
63
- const validate = v2Validator('self-hosted-runner-dispatch-frame');
64
-
65
- it('accepts a model frame and a tool frame', () => {
66
- for (const f of [MODEL_FRAME, TOOL_FRAME]) {
67
- const r = validate(f);
68
- expect(r.ok, req(ID_DISPATCH, DOC, `a well-formed ${f.kind} dispatch frame MUST validate (${r.errors})`)).toBe(true);
69
- }
70
- });
71
-
72
- it.each<[string, Record<string, unknown>]>([
73
- ['no seq cursor', without(MODEL_FRAME, 'seq')],
74
- ['a fractional seq', { ...MODEL_FRAME, seq: 1.5 }],
75
- ['a negative seq', { ...MODEL_FRAME, seq: -1 }],
76
- ['an unknown kind', { ...MODEL_FRAME, kind: 'agent' }],
77
- ['a model frame without provider', without(MODEL_FRAME, 'provider')],
78
- ['a model frame without model', without(MODEL_FRAME, 'model')],
79
- ['a tool frame without tool', without(TOOL_FRAME, 'tool')],
80
- ['no stepId (the at-most-once key)', without(MODEL_FRAME, 'stepId')],
81
- ])('rejects %s', (_what, frame) => {
82
- expect(validate(frame).ok, req(ID_DISPATCH, DOC, `a dispatch frame with ${_what} MUST be rejected`)).toBe(false);
83
- });
84
- });
85
-
86
- describe('v2 self-hosted-runner frames: result frame', () => {
87
- const validate = v2Validator('self-hosted-runner-result-frame');
88
-
89
- it('accepts a result frame', () => {
90
- const r = validate(RESULT);
91
- expect(r.ok, req(ID_RESULT, DOC, `a well-formed result frame MUST validate (${r.errors})`)).toBe(true);
92
- });
93
-
94
- it('rejects a result frame without output', () => {
95
- expect(validate(without(RESULT, 'output')).ok, req(ID_RESULT, DOC, 'a result frame without output MUST be rejected')).toBe(false);
96
- });
97
- });
98
-
99
- describe('v2 self-hosted-runner frames: closed shapes carry no credential field', () => {
100
- it.each<[string, string, Record<string, unknown>]>([
101
- ['dispatch frame', 'self-hosted-runner-dispatch-frame', { ...MODEL_FRAME, apiKey: 'sk-canary' }],
102
- ['result frame', 'self-hosted-runner-result-frame', { ...RESULT, credential: 'sk-canary' }],
103
- ['registration', 'self-hosted-runner-registration', { ...REGISTRATION, bearer: 'sk-canary' }],
104
- ['registration capabilities', 'self-hosted-runner-registration', { ...REGISTRATION, capabilities: { providers: ['anthropic'], apiKeys: { anthropic: 'sk-canary' } } }],
105
- ])('a %s with an extra credential-named field is rejected', (what, schema, doc) => {
106
- expect(v2Validator(schema)(doc).ok, req(ID_CLOSED, DOC, `the ${what} is closed: a runner credential MUST NOT appear in any frame`)).toBe(false);
107
- });
108
- });
109
-
110
- describe('v2 self-hosted-runner frames: registration', () => {
111
- const validate = v2Validator('self-hosted-runner-registration');
112
-
113
- it('accepts a registration', () => {
114
- const r = validate(REGISTRATION);
115
- expect(r.ok, req(ID_REGISTRATION, DOC, `a well-formed registration MUST validate (${r.errors})`)).toBe(true);
116
- });
117
-
118
- it('rejects a registration without subject', () => {
119
- expect(validate(without(REGISTRATION, 'subject')).ok, req(ID_REGISTRATION, DOC, 'a registration without its owning subject MUST be rejected')).toBe(false);
120
- });
121
- });