@openwop/openwop-conformance 1.130.0 → 1.131.0
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/schemas/CORPUS-STAMP.json +2 -2
- package/src/scenarios/compensation-recovery.test.ts +8 -0
- package/src/scenarios/org-position-no-authority-escalation.test.ts +9 -0
- package/src/scenarios/workspace-behavior.test.ts +7 -6
- package/src/scenarios/workspace-capability-shape.test.ts +3 -2
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "Provenance of this vendored schemas/ copy. See conformance/README.md \u00a7\"Resolving the contract\". Compare against the stamp in your installed @openwop/openwop-conformance to detect a stale hand-copied contract.",
|
|
3
|
-
"suiteVersion": "1.
|
|
4
|
-
"corpusCommit": "
|
|
3
|
+
"suiteVersion": "1.131.0",
|
|
4
|
+
"corpusCommit": "b2a25cf7013d21838b8b5abeaea7dff12355bfc5"
|
|
5
5
|
}
|
|
@@ -34,6 +34,14 @@
|
|
|
34
34
|
* extension is `blocked` here (named as such via `seamAbsent`) and keeps its
|
|
35
35
|
* `compensation-behavior` witness — the base and the extension are different
|
|
36
36
|
* claims and are recorded separately.
|
|
37
|
+
*
|
|
38
|
+
* Mode matters, and the first host to advertise pointed it out: `seamAbsent`
|
|
39
|
+
* records `blocked` in DEFAULT mode but THROWS under
|
|
40
|
+
* `OPENWOP_REQUIRE_BEHAVIOR=true` (RFC 0148 §B — an advertised capability
|
|
41
|
+
* whose witness seam is missing is a failure in strict certification, not a
|
|
42
|
+
* disposition). So a host that flips `compensation.supported` on without the
|
|
43
|
+
* §21 recovery extension is honest-red here in strict runs. Wire the extension
|
|
44
|
+
* with the advert, or run default mode and read the `blocked` rows.
|
|
37
45
|
*/
|
|
38
46
|
|
|
39
47
|
import { describe, it, expect } from 'vitest';
|
|
@@ -55,6 +55,15 @@ describe('org-position-no-authority-escalation (RFC 0087 §B, behavioral)', () =
|
|
|
55
55
|
const chart = await getOrgChart();
|
|
56
56
|
if (chart === null) return seamAbsent('host advertises org-position authority but GET /v1/agents/org-chart is not served');
|
|
57
57
|
|
|
58
|
+
// An EMPTY chart has nothing that could carry authority: the invariant is
|
|
59
|
+
// unobservable, and RFC 0148 §A says unobservable is `blocked`, not a
|
|
60
|
+
// zero-assertion pass (which is what this leg recorded on such a host).
|
|
61
|
+
if ((chart.members ?? []).length === 0 && (chart.departments ?? []).length === 0) {
|
|
62
|
+
return seamAbsent('host advertises org-position authority but the org chart is EMPTY — no member or department to check; the invariant is unobservable until the host seeds one');
|
|
63
|
+
}
|
|
64
|
+
// The chart root is a wire object too.
|
|
65
|
+
expectNoAuthority(chart as unknown as Record<string, unknown>, 'the org-chart root');
|
|
66
|
+
|
|
58
67
|
for (const m of chart.members ?? []) {
|
|
59
68
|
expectNoAuthority(m as Record<string, unknown>, 'an org-chart member');
|
|
60
69
|
}
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
import { describe, it, expect } from 'vitest';
|
|
24
24
|
import { driver } from '../lib/driver.js';
|
|
25
|
+
import { softSkip, seamAbsent } from '../lib/soft-skip.js';
|
|
25
26
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
26
27
|
|
|
27
28
|
interface DiscoveryWorkspace {
|
|
@@ -49,7 +50,7 @@ interface WorkspaceFile {
|
|
|
49
50
|
|
|
50
51
|
describe('workspace-behavior: §C CRUD round-trip (RFC 0059)', () => {
|
|
51
52
|
it('PUT creates v1, GET returns it, list omits content, DELETE removes it', async () => {
|
|
52
|
-
if (!(await workspaceCap())) return;
|
|
53
|
+
if (!(await workspaceCap())) return softSkip('inapplicable', 'optional advertisement — `capabilities.workspace` not advertised by this host (RFC 0059 §A)');
|
|
53
54
|
const path = 'behavior/CRUD.md';
|
|
54
55
|
|
|
55
56
|
const created = await driver.put(`${FILES}/${encodeURIComponent(path)}`, { content: 'first body' });
|
|
@@ -78,7 +79,7 @@ describe('workspace-behavior: §C CRUD round-trip (RFC 0059)', () => {
|
|
|
78
79
|
|
|
79
80
|
describe('workspace-behavior: §C optimistic concurrency (RFC 0059)', () => {
|
|
80
81
|
it('stale If-Match → 409 workspace_conflict; matching If-Match bumps version', async () => {
|
|
81
|
-
if (!(await workspaceCap())) return;
|
|
82
|
+
if (!(await workspaceCap())) return softSkip('inapplicable', 'optional advertisement — `capabilities.workspace` not advertised by this host (RFC 0059 §A)');
|
|
82
83
|
const path = 'behavior/ETAG.md';
|
|
83
84
|
|
|
84
85
|
const v1 = await driver.put(`${FILES}/${encodeURIComponent(path)}`, { content: 'v1' });
|
|
@@ -101,7 +102,7 @@ describe('workspace-behavior: §C optimistic concurrency (RFC 0059)', () => {
|
|
|
101
102
|
describe('workspace-behavior: §C size ceiling (RFC 0059)', () => {
|
|
102
103
|
it('content beyond maxFileBytes returns workspace_too_large', async () => {
|
|
103
104
|
const cap = await workspaceCap();
|
|
104
|
-
if (cap === null) return;
|
|
105
|
+
if (cap === null) return softSkip('inapplicable', 'optional advertisement — `capabilities.workspace` not advertised by this host (RFC 0059 §A)');
|
|
105
106
|
const max = typeof cap.maxFileBytes === 'number' ? cap.maxFileBytes : 1_048_576;
|
|
106
107
|
const tooBig = 'x'.repeat(max + 1);
|
|
107
108
|
const res = await driver.put(`${FILES}/${encodeURIComponent('behavior/TOOBIG.md')}`, { content: tooBig });
|
|
@@ -112,14 +113,14 @@ describe('workspace-behavior: §C size ceiling (RFC 0059)', () => {
|
|
|
112
113
|
|
|
113
114
|
describe('workspace-behavior: §D run-start snapshot (RFC 0059)', () => {
|
|
114
115
|
it('a run started after a write exposes the workspace snapshot', async () => {
|
|
115
|
-
if (!(await workspaceCap())) return;
|
|
116
|
+
if (!(await workspaceCap())) return softSkip('inapplicable', 'optional advertisement — `capabilities.workspace` not advertised by this host (RFC 0059 §A)');
|
|
116
117
|
const path = 'behavior/SNAPSHOT.md';
|
|
117
118
|
await driver.put(`${FILES}/${encodeURIComponent(path)}`, { content: 'snapshot body' });
|
|
118
119
|
|
|
119
120
|
const create = await driver.post('/v1/runs', { workflowId: 'conformance-noop' });
|
|
120
|
-
if (create.status !== 201 && create.status !== 200) return
|
|
121
|
+
if (create.status !== 201 && create.status !== 200) return seamAbsent(`host advertises workspace but the noop fixture run could not be created (POST /v1/runs → ${create.status})`);
|
|
121
122
|
const runId = (create.json as { runId?: string }).runId;
|
|
122
|
-
if (runId === undefined) return;
|
|
123
|
+
if (runId === undefined) return seamAbsent('host advertises workspace but the created run carried no runId');
|
|
123
124
|
|
|
124
125
|
const snap = await driver.get(`/v1/runs/${encodeURIComponent(runId)}`);
|
|
125
126
|
const ws = (snap.json as { workspace?: Array<{ path: string }> }).workspace;
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import { describe, it, expect } from 'vitest';
|
|
25
25
|
import { driver } from '../lib/driver.js';
|
|
26
|
+
import { softSkip } from '../lib/soft-skip.js';
|
|
26
27
|
import { capabilityFamily } from '../lib/discovery-capabilities.js';
|
|
27
28
|
|
|
28
29
|
interface DiscoveryWorkspace {
|
|
@@ -48,7 +49,7 @@ const POSITIVE_INT_FIELDS = ['maxFileBytes', 'maxFiles', 'maxVersions'] as const
|
|
|
48
49
|
describe('workspace-capability-shape: advertisement shape (RFC 0059 §A)', () => {
|
|
49
50
|
it('capabilities.workspace is either absent or well-formed', async () => {
|
|
50
51
|
const ws = await readWorkspace();
|
|
51
|
-
if (ws === null) return
|
|
52
|
+
if (ws === null) return softSkip('inapplicable', 'optional advertisement — `capabilities.workspace` not advertised by this host (RFC 0059 §A)');
|
|
52
53
|
expect(
|
|
53
54
|
typeof ws.supported,
|
|
54
55
|
driver.describe(
|
|
@@ -60,7 +61,7 @@ describe('workspace-capability-shape: advertisement shape (RFC 0059 §A)', () =>
|
|
|
60
61
|
|
|
61
62
|
it('maxFileBytes / maxFiles / maxVersions are positive integers when present', async () => {
|
|
62
63
|
const ws = await readWorkspace();
|
|
63
|
-
if (ws === null) return;
|
|
64
|
+
if (ws === null) return softSkip('inapplicable', 'optional advertisement — `capabilities.workspace` not advertised by this host (RFC 0059 §A)');
|
|
64
65
|
for (const field of POSITIVE_INT_FIELDS) {
|
|
65
66
|
const v = ws[field];
|
|
66
67
|
if (v === undefined) continue;
|