@cleocode/contracts 2026.6.12 → 2026.6.14
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/__tests__/operation-def.test.js +5 -1
- package/dist/__tests__/operation-def.test.js.map +1 -1
- package/dist/__tests__/provider-def.test.d.ts +12 -0
- package/dist/__tests__/provider-def.test.d.ts.map +1 -0
- package/dist/__tests__/provider-def.test.js +84 -0
- package/dist/__tests__/provider-def.test.js.map +1 -0
- package/dist/__tests__/sealed-credential.test.d.ts +19 -0
- package/dist/__tests__/sealed-credential.test.d.ts.map +1 -0
- package/dist/__tests__/sealed-credential.test.js +74 -0
- package/dist/__tests__/sealed-credential.test.js.map +1 -0
- package/dist/__tests__/service-provider.test.d.ts +17 -0
- package/dist/__tests__/service-provider.test.d.ts.map +1 -0
- package/dist/__tests__/service-provider.test.js +108 -0
- package/dist/__tests__/service-provider.test.js.map +1 -0
- package/dist/__tests__/skill-executor-contract.test.js +3 -0
- package/dist/__tests__/skill-executor-contract.test.js.map +1 -1
- package/dist/acceptance-gate.d.ts +2 -3
- package/dist/acceptance-gate.d.ts.map +1 -1
- package/dist/boundary.d.ts +52 -0
- package/dist/boundary.d.ts.map +1 -1
- package/dist/boundary.js +24 -19
- package/dist/boundary.js.map +1 -1
- package/dist/conduit.d.ts +171 -0
- package/dist/conduit.d.ts.map +1 -1
- package/dist/config/index.d.ts +23 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +22 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config.d.ts +104 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/data-accessor.d.ts +21 -1
- package/dist/data-accessor.d.ts.map +1 -1
- package/dist/data-accessor.js.map +1 -1
- package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.d.ts +21 -0
- package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.d.ts.map +1 -0
- package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.js +84 -0
- package/dist/dispatch/__tests__/tasks-gateway-crud-ops.test.js.map +1 -0
- package/dist/dispatch/identity.d.ts +1 -1
- package/dist/dispatch/identity.d.ts.map +1 -1
- package/dist/dispatch/identity.js +25 -0
- package/dist/dispatch/identity.js.map +1 -1
- package/dist/dispatch/operation-def.d.ts +20 -0
- package/dist/dispatch/operation-def.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.js +1044 -182
- package/dist/dispatch/operations-registry.js.map +1 -1
- package/dist/docs/read.d.ts +2 -2
- package/dist/index.d.ts +25 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/lease-ipc/__tests__/freeze.test.d.ts +15 -0
- package/dist/lease-ipc/__tests__/freeze.test.d.ts.map +1 -0
- package/dist/lease-ipc/__tests__/freeze.test.js +313 -0
- package/dist/lease-ipc/__tests__/freeze.test.js.map +1 -0
- package/dist/lease-ipc/index.d.ts +17 -0
- package/dist/lease-ipc/index.d.ts.map +1 -0
- package/dist/lease-ipc/index.js +16 -0
- package/dist/lease-ipc/index.js.map +1 -0
- package/dist/lease-ipc/messages.d.ts +918 -0
- package/dist/lease-ipc/messages.d.ts.map +1 -0
- package/dist/lease-ipc/messages.js +476 -0
- package/dist/lease-ipc/messages.js.map +1 -0
- package/dist/lease-ipc/version.d.ts +41 -0
- package/dist/lease-ipc/version.d.ts.map +1 -0
- package/dist/lease-ipc/version.js +43 -0
- package/dist/lease-ipc/version.js.map +1 -0
- package/dist/llm/catalog-schema.d.ts +242 -0
- package/dist/llm/catalog-schema.d.ts.map +1 -0
- package/dist/llm/catalog-schema.js +153 -0
- package/dist/llm/catalog-schema.js.map +1 -0
- package/dist/llm/catalog-schema.json +139 -0
- package/dist/llm/index.d.ts +15 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +14 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/interfaces.d.ts +23 -0
- package/dist/llm/interfaces.d.ts.map +1 -1
- package/dist/llm/oauth.d.ts +16 -2
- package/dist/llm/oauth.d.ts.map +1 -1
- package/dist/llm/onboarding.d.ts +126 -0
- package/dist/llm/onboarding.d.ts.map +1 -0
- package/dist/llm/onboarding.js +34 -0
- package/dist/llm/onboarding.js.map +1 -0
- package/dist/llm/provider-def.d.ts +254 -0
- package/dist/llm/provider-def.d.ts.map +1 -0
- package/dist/llm/provider-def.js +93 -0
- package/dist/llm/provider-def.js.map +1 -0
- package/dist/llm/sealed-credential.d.ts +164 -0
- package/dist/llm/sealed-credential.d.ts.map +1 -0
- package/dist/llm/sealed-credential.js +43 -0
- package/dist/llm/sealed-credential.js.map +1 -0
- package/dist/llm/system-of-use.d.ts +383 -0
- package/dist/llm/system-of-use.d.ts.map +1 -0
- package/dist/llm/system-of-use.js +238 -0
- package/dist/llm/system-of-use.js.map +1 -0
- package/dist/llm/system-resolver.d.ts +87 -11
- package/dist/llm/system-resolver.d.ts.map +1 -1
- package/dist/llm/system-resolver.js +14 -7
- package/dist/llm/system-resolver.js.map +1 -1
- package/dist/operations/__tests__/ensures-schema-registry.test.d.ts +17 -0
- package/dist/operations/__tests__/ensures-schema-registry.test.d.ts.map +1 -0
- package/dist/operations/__tests__/ensures-schema-registry.test.js +113 -0
- package/dist/operations/__tests__/ensures-schema-registry.test.js.map +1 -0
- package/dist/operations/admin.d.ts +124 -1
- package/dist/operations/admin.d.ts.map +1 -1
- package/dist/operations/ensures-schema-registry.d.ts +172 -0
- package/dist/operations/ensures-schema-registry.d.ts.map +1 -0
- package/dist/operations/ensures-schema-registry.js +226 -0
- package/dist/operations/ensures-schema-registry.js.map +1 -0
- package/dist/operations/entities.d.ts +110 -0
- package/dist/operations/entities.d.ts.map +1 -0
- package/dist/operations/entities.js +695 -0
- package/dist/operations/entities.js.map +1 -0
- package/dist/operations/llm.d.ts +116 -9
- package/dist/operations/llm.d.ts.map +1 -1
- package/dist/operations/output-contracts-data.d.ts.map +1 -1
- package/dist/operations/output-contracts-data.js +230 -0
- package/dist/operations/output-contracts-data.js.map +1 -1
- package/dist/operations/service.d.ts +68 -0
- package/dist/operations/service.d.ts.map +1 -0
- package/dist/operations/service.js +336 -0
- package/dist/operations/service.js.map +1 -0
- package/dist/operations/tasks.d.ts +109 -0
- package/dist/operations/tasks.d.ts.map +1 -1
- package/dist/operations/tasks.js.map +1 -1
- package/dist/operations/validate.d.ts +1 -12
- package/dist/operations/validate.d.ts.map +1 -1
- package/dist/operations/validate.js +1 -1
- package/dist/playbook.d.ts +116 -0
- package/dist/playbook.d.ts.map +1 -1
- package/dist/release/plan.d.ts +5 -5
- package/dist/session.d.ts +11 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/dist/templates/manifest.d.ts +1 -1
- package/dist/tools/agent-tools.d.ts +231 -0
- package/dist/tools/agent-tools.d.ts.map +1 -0
- package/dist/tools/agent-tools.js +25 -0
- package/dist/tools/agent-tools.js.map +1 -0
- package/dist/tools/atomic.d.ts +19 -0
- package/dist/tools/atomic.d.ts.map +1 -1
- package/dist/tools/atomic.js +17 -0
- package/dist/tools/atomic.js.map +1 -1
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/skill-executor.d.ts +7 -0
- package/dist/tools/skill-executor.d.ts.map +1 -1
- package/dist/tools/web-tools.d.ts +217 -0
- package/dist/tools/web-tools.d.ts.map +1 -0
- package/dist/tools/web-tools.js +31 -0
- package/dist/tools/web-tools.js.map +1 -0
- package/dist/vault/service-provider.d.ts +343 -0
- package/dist/vault/service-provider.d.ts.map +1 -0
- package/dist/vault/service-provider.js +857 -0
- package/dist/vault/service-provider.js.map +1 -0
- package/dist/workgraph.d.ts +12 -12
- package/package.json +14 -2
- package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
- package/src/__tests__/operation-def.test.ts +7 -1
- package/src/__tests__/provider-def.test.ts +93 -0
- package/src/__tests__/sealed-credential.test.ts +100 -0
- package/src/__tests__/service-provider.test.ts +129 -0
- package/src/__tests__/skill-executor-contract.test.ts +3 -0
- package/src/acceptance-gate.ts +2 -3
- package/src/boundary.ts +70 -20
- package/src/conduit.ts +200 -0
- package/src/config/index.ts +35 -0
- package/src/config.ts +106 -1
- package/src/data-accessor.ts +22 -1
- package/src/dispatch/__tests__/tasks-gateway-crud-ops.test.ts +99 -0
- package/src/dispatch/identity.ts +25 -0
- package/src/dispatch/operation-def.ts +21 -0
- package/src/dispatch/operations-registry.ts +1083 -176
- package/src/index.ts +240 -25
- package/src/lease-ipc/__tests__/freeze.test.ts +342 -0
- package/src/lease-ipc/index.ts +75 -0
- package/src/lease-ipc/messages.ts +588 -0
- package/src/lease-ipc/version.ts +46 -0
- package/src/llm/catalog-schema.json +139 -0
- package/src/llm/catalog-schema.ts +184 -0
- package/src/llm/index.ts +29 -0
- package/src/llm/interfaces.ts +23 -0
- package/src/llm/oauth.ts +16 -2
- package/src/llm/onboarding.ts +131 -0
- package/src/llm/provider-def.ts +291 -0
- package/src/llm/sealed-credential.ts +166 -0
- package/src/llm/system-of-use.ts +503 -0
- package/src/llm/system-resolver.ts +91 -11
- package/src/operations/__tests__/ensures-schema-registry.test.ts +169 -0
- package/src/operations/admin.ts +144 -0
- package/src/operations/ensures-schema-registry.ts +260 -0
- package/src/operations/entities.ts +758 -0
- package/src/operations/llm.ts +120 -8
- package/src/operations/output-contracts-data.ts +264 -0
- package/src/operations/service.ts +360 -0
- package/src/operations/tasks.ts +119 -0
- package/src/operations/validate.ts +1 -14
- package/src/playbook.ts +117 -0
- package/src/session.ts +11 -0
- package/src/tools/agent-tools.ts +270 -0
- package/src/tools/atomic.ts +21 -0
- package/src/tools/index.ts +46 -0
- package/src/tools/skill-executor.ts +7 -0
- package/src/tools/web-tools.ts +247 -0
- package/src/vault/service-provider.ts +1137 -0
- package/dist/tessera.d.ts +0 -32
- package/dist/tessera.d.ts.map +0 -1
- package/dist/tessera.js +0 -11
- package/dist/tessera.js.map +0 -1
- package/dist/warp-chain.d.ts +0 -129
- package/dist/warp-chain.d.ts.map +0 -1
- package/dist/warp-chain.js +0 -13
- package/dist/warp-chain.js.map +0 -1
- package/src/tessera.ts +0 -35
- package/src/warp-chain.ts +0 -185
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the ensures-schema Zod registry (T11762 ST-1 · T11900).
|
|
3
|
+
*
|
|
4
|
+
* Behavior-parity guard: every input the deleted bespoke validators
|
|
5
|
+
* (`validateDecompositionTaskTree` / `validateIvtrEvidenceOutput`,
|
|
6
|
+
* `packages/playbooks/src/runtime.ts:794-902`) REJECTED must still be rejected
|
|
7
|
+
* here, with the FIRST Zod issue message equal to the SUFFIX of the original
|
|
8
|
+
* violation string (the part after the `ensures.schema[<name>] on <nodeId>: `
|
|
9
|
+
* prefix that ST-2's runtime wrapper re-applies). Every input they ACCEPTED must
|
|
10
|
+
* still parse. The ACs call out: empty array, missing title, empty acceptance,
|
|
11
|
+
* `{}` evidence, numeric evidence.
|
|
12
|
+
*
|
|
13
|
+
* @task T11900
|
|
14
|
+
* @epic T11762
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { describe, expect, it } from 'vitest';
|
|
18
|
+
import {
|
|
19
|
+
ENSURES_SCHEMA_REGISTRY,
|
|
20
|
+
type EnsuresSchemaSpec,
|
|
21
|
+
evidenceSchema,
|
|
22
|
+
LEGACY_PASSTHROUGH_SCHEMA_NAMES,
|
|
23
|
+
passthroughSchema,
|
|
24
|
+
taskTreeSchema,
|
|
25
|
+
} from '../ensures-schema-registry.js';
|
|
26
|
+
|
|
27
|
+
/** First Zod issue message for a failing parse (or `undefined` if it parsed). */
|
|
28
|
+
function firstIssueMessage(schema: typeof taskTreeSchema, value: unknown): string | undefined {
|
|
29
|
+
const result = schema.safeParse(value);
|
|
30
|
+
return result.success ? undefined : result.error.issues[0]?.message;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
describe('ensures-schema-registry — registry DATA', () => {
|
|
34
|
+
it('registers the two strict schemas plus every legacy passthrough name', () => {
|
|
35
|
+
// T11762 ST-2 (R1): the two strict ports (`task_tree`, `evidence`) PLUS the
|
|
36
|
+
// legacy starter `.cantbook` schema names — registered with passthrough so
|
|
37
|
+
// the fail-closed flip does not regress the shipped playbooks.
|
|
38
|
+
expect([...ENSURES_SCHEMA_REGISTRY.keys()].sort()).toEqual(
|
|
39
|
+
['task_tree', 'evidence', ...LEGACY_PASSTHROUGH_SCHEMA_NAMES].sort(),
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('each strict spec carries name, contextKey (= name by default), and a schema', () => {
|
|
44
|
+
for (const name of ['task_tree', 'evidence'] as const) {
|
|
45
|
+
const spec = ENSURES_SCHEMA_REGISTRY.get(name) as EnsuresSchemaSpec;
|
|
46
|
+
expect(spec).toBeDefined();
|
|
47
|
+
expect(spec.name).toBe(name);
|
|
48
|
+
expect(spec.contextKey).toBe(name);
|
|
49
|
+
expect(typeof spec.schema.safeParse).toBe('function');
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('every legacy passthrough name is registered with the passthrough schema', () => {
|
|
54
|
+
// R1: passthrough accepts ANY value (including `undefined`) so the historical
|
|
55
|
+
// "silently skipped" behavior is preserved EXACTLY.
|
|
56
|
+
for (const name of LEGACY_PASSTHROUGH_SCHEMA_NAMES) {
|
|
57
|
+
const spec = ENSURES_SCHEMA_REGISTRY.get(name) as EnsuresSchemaSpec;
|
|
58
|
+
expect(spec).toBeDefined();
|
|
59
|
+
expect(spec.name).toBe(name);
|
|
60
|
+
expect(spec.schema).toBe(passthroughSchema);
|
|
61
|
+
expect(spec.schema.safeParse(undefined).success).toBe(true);
|
|
62
|
+
expect(spec.schema.safeParse({ anything: 1 }).success).toBe(true);
|
|
63
|
+
expect(spec.schema.safeParse(42).success).toBe(true);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('ensures-schema-registry — task_tree (ports validateDecompositionTaskTree)', () => {
|
|
69
|
+
it('accepts a minimal valid task tree', () => {
|
|
70
|
+
expect(taskTreeSchema.safeParse([{ title: 'Build X', acceptance: ['does X'] }]).success).toBe(
|
|
71
|
+
true,
|
|
72
|
+
);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('accepts a tree with optional id/parentId/depends populated', () => {
|
|
76
|
+
expect(
|
|
77
|
+
taskTreeSchema.safeParse([
|
|
78
|
+
{ title: 'Root', acceptance: ['ac1'], id: 'T1' },
|
|
79
|
+
{ title: 'Child', acceptance: ['ac2', 'ac3'], id: 'T2', parentId: 'T1', depends: ['T1'] },
|
|
80
|
+
]).success,
|
|
81
|
+
).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('rejects a non-array (parity: "task_tree must be a non-empty array")', () => {
|
|
85
|
+
expect(firstIssueMessage(taskTreeSchema, 'not-an-array')).toBe(
|
|
86
|
+
'task_tree must be a non-empty array',
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('rejects an EMPTY ARRAY (parity: empty-array message)', () => {
|
|
91
|
+
expect(firstIssueMessage(taskTreeSchema, [])).toBe(
|
|
92
|
+
'task_tree is an empty array — decomposition produced no tasks',
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('rejects a MISSING TITLE (parity: "title must be a non-empty string")', () => {
|
|
97
|
+
expect(firstIssueMessage(taskTreeSchema, [{ acceptance: ['ac1'] }])).toBe(
|
|
98
|
+
'title must be a non-empty string',
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('rejects a whitespace-only title (parity: same non-empty-title message)', () => {
|
|
103
|
+
expect(firstIssueMessage(taskTreeSchema, [{ title: ' ', acceptance: ['ac1'] }])).toBe(
|
|
104
|
+
'title must be a non-empty string',
|
|
105
|
+
);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('rejects an EMPTY ACCEPTANCE array (parity: non-empty-acceptance message)', () => {
|
|
109
|
+
expect(firstIssueMessage(taskTreeSchema, [{ title: 'X', acceptance: [] }])).toBe(
|
|
110
|
+
'must have a non-empty acceptance array',
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('rejects an acceptance array with no non-empty strings (parity message)', () => {
|
|
115
|
+
expect(firstIssueMessage(taskTreeSchema, [{ title: 'X', acceptance: [' ', ''] }])).toBe(
|
|
116
|
+
'acceptance array contains no non-empty strings',
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe('ensures-schema-registry — evidence (ports validateIvtrEvidenceOutput)', () => {
|
|
122
|
+
it('accepts a non-empty string', () => {
|
|
123
|
+
expect(evidenceSchema.safeParse('commit:abc123').success).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('accepts a non-empty array', () => {
|
|
127
|
+
expect(evidenceSchema.safeParse(['atom']).success).toBe(true);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('accepts an object with at least one key', () => {
|
|
131
|
+
expect(evidenceSchema.safeParse({ commit: 'abc' }).success).toBe(true);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('rejects null/undefined (parity: must-be-present message)', () => {
|
|
135
|
+
expect(firstIssueMessage(evidenceSchema, null)).toBe(
|
|
136
|
+
'evidence must be present (non-null, non-undefined)',
|
|
137
|
+
);
|
|
138
|
+
expect(firstIssueMessage(evidenceSchema, undefined)).toBe(
|
|
139
|
+
'evidence must be present (non-null, non-undefined)',
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('rejects an empty / whitespace-only string (parity message)', () => {
|
|
144
|
+
expect(firstIssueMessage(evidenceSchema, '')).toBe('evidence string must not be empty');
|
|
145
|
+
expect(firstIssueMessage(evidenceSchema, ' ')).toBe('evidence string must not be empty');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('rejects an empty array (parity message)', () => {
|
|
149
|
+
expect(firstIssueMessage(evidenceSchema, [])).toBe('evidence array must not be empty');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('rejects an EMPTY OBJECT {} (parity: at-least-one-key message)', () => {
|
|
153
|
+
expect(firstIssueMessage(evidenceSchema, {})).toBe(
|
|
154
|
+
'evidence object must have at least one key (got {})',
|
|
155
|
+
);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('rejects NUMERIC evidence (parity: wrong-type message with typeof)', () => {
|
|
159
|
+
expect(firstIssueMessage(evidenceSchema, 42)).toBe(
|
|
160
|
+
'evidence must be a string, array, or object (got number)',
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('rejects boolean evidence (parity: wrong-type message with typeof)', () => {
|
|
165
|
+
expect(firstIssueMessage(evidenceSchema, true)).toBe(
|
|
166
|
+
'evidence must be a string, array, or object (got boolean)',
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
});
|
package/src/operations/admin.ts
CHANGED
|
@@ -380,6 +380,9 @@ export type AdminOp =
|
|
|
380
380
|
| 'admin.health'
|
|
381
381
|
| 'admin.config.show'
|
|
382
382
|
| 'admin.config.presets'
|
|
383
|
+
| 'admin.config.get'
|
|
384
|
+
| 'admin.config.list'
|
|
385
|
+
| 'admin.config.validate'
|
|
383
386
|
| 'admin.stats'
|
|
384
387
|
| 'admin.context'
|
|
385
388
|
| 'admin.context.pull'
|
|
@@ -406,6 +409,7 @@ export type AdminOp =
|
|
|
406
409
|
| 'admin.health.mutate'
|
|
407
410
|
| 'admin.config.set'
|
|
408
411
|
| 'admin.config.set-preset'
|
|
412
|
+
| 'admin.config.unset'
|
|
409
413
|
| 'admin.backup.mutate'
|
|
410
414
|
| 'admin.migrate'
|
|
411
415
|
| 'admin.cleanup'
|
|
@@ -513,6 +517,109 @@ export interface AdminConfigPresetsResult {
|
|
|
513
517
|
presets: AdminPresetDefinition[];
|
|
514
518
|
}
|
|
515
519
|
|
|
520
|
+
// ---------------------------------------------------------------------------
|
|
521
|
+
// admin.config.get (T11917 — config-as-domain, ConfigManifest cascade)
|
|
522
|
+
// ---------------------------------------------------------------------------
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Cascade slice selector for the config-as-domain query ops.
|
|
526
|
+
*
|
|
527
|
+
* - `'global'` — read ONLY `~/.cleo/config.json` (precedence 10)
|
|
528
|
+
* - `'project'` — read ONLY `<project>/.cleo/config.json` (precedence 20)
|
|
529
|
+
* - `'merged'` — read the deep-merge `{ ...global, ...project }` (default)
|
|
530
|
+
*
|
|
531
|
+
* Mirrors the `ResolveScope` of the `resolveCleoConfig` cascade resolver.
|
|
532
|
+
*
|
|
533
|
+
* @task T11917
|
|
534
|
+
*/
|
|
535
|
+
export type AdminConfigScope = 'global' | 'project' | 'merged';
|
|
536
|
+
|
|
537
|
+
/** Parameters for `admin.config.get`. */
|
|
538
|
+
export interface AdminConfigGetParams {
|
|
539
|
+
/** Dot-notation config key to read a single value (required). */
|
|
540
|
+
key: string;
|
|
541
|
+
/** Cascade slice to read from. Defaults to `'merged'`. */
|
|
542
|
+
scope?: AdminConfigScope;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* Result of `admin.config.get`.
|
|
547
|
+
*
|
|
548
|
+
* Returns the resolved value for `key`, or `null` when the key is absent in the
|
|
549
|
+
* selected cascade slice. `found` disambiguates a present `null` value from an
|
|
550
|
+
* absent key.
|
|
551
|
+
*
|
|
552
|
+
* @task T11917
|
|
553
|
+
*/
|
|
554
|
+
export interface AdminConfigGetResult {
|
|
555
|
+
/** The dot-notation key that was resolved. */
|
|
556
|
+
key: string;
|
|
557
|
+
/** Cascade slice the value was resolved against. */
|
|
558
|
+
scope: AdminConfigScope;
|
|
559
|
+
/** Resolved value, or `null` when the key is absent. */
|
|
560
|
+
value: unknown;
|
|
561
|
+
/** `true` IFF the key resolved to a defined value in the cascade. */
|
|
562
|
+
found: boolean;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// ---------------------------------------------------------------------------
|
|
566
|
+
// admin.config.list (T11917 — full resolved cascade)
|
|
567
|
+
// ---------------------------------------------------------------------------
|
|
568
|
+
|
|
569
|
+
/** Parameters for `admin.config.list`. */
|
|
570
|
+
export interface AdminConfigListParams {
|
|
571
|
+
/** Cascade slice to project. Defaults to `'merged'`. */
|
|
572
|
+
scope?: AdminConfigScope;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Result of `admin.config.list`.
|
|
577
|
+
*
|
|
578
|
+
* Returns the full resolved config object for the selected cascade slice plus
|
|
579
|
+
* the flattened dot-notation key list for discovery.
|
|
580
|
+
*
|
|
581
|
+
* @task T11917
|
|
582
|
+
*/
|
|
583
|
+
export interface AdminConfigListResult {
|
|
584
|
+
/** Cascade slice the config was resolved against. */
|
|
585
|
+
scope: AdminConfigScope;
|
|
586
|
+
/** Full resolved config object for the slice. */
|
|
587
|
+
config: Record<string, unknown>;
|
|
588
|
+
/** Flattened dot-notation keys present in the resolved config. */
|
|
589
|
+
keys: string[];
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// ---------------------------------------------------------------------------
|
|
593
|
+
// admin.config.validate (T11917 — schema-validate the cascade entry)
|
|
594
|
+
// ---------------------------------------------------------------------------
|
|
595
|
+
|
|
596
|
+
/** Parameters for `admin.config.validate`. */
|
|
597
|
+
export interface AdminConfigValidateParams {
|
|
598
|
+
/**
|
|
599
|
+
* Scope to validate. Only the cascade-participating scopes are valid —
|
|
600
|
+
* `'merged'` is rejected because validation runs against a single file's
|
|
601
|
+
* manifest entry schema. Defaults to `'project'`.
|
|
602
|
+
*/
|
|
603
|
+
scope?: 'global' | 'project';
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Result of `admin.config.validate`.
|
|
608
|
+
*
|
|
609
|
+
* `ok` is `true` IFF the file passed its manifest entry's schema gate (or no
|
|
610
|
+
* schema was configured). `issues` carries human-readable rejection reasons.
|
|
611
|
+
*
|
|
612
|
+
* @task T11917
|
|
613
|
+
*/
|
|
614
|
+
export interface AdminConfigValidateResult {
|
|
615
|
+
/** Scope that was validated. */
|
|
616
|
+
scope: 'global' | 'project';
|
|
617
|
+
/** `true` IFF every gate passed. */
|
|
618
|
+
ok: boolean;
|
|
619
|
+
/** Human-readable schema issues. Empty when `ok === true`. */
|
|
620
|
+
issues: string[];
|
|
621
|
+
}
|
|
622
|
+
|
|
516
623
|
// ---------------------------------------------------------------------------
|
|
517
624
|
// admin.stats
|
|
518
625
|
// ---------------------------------------------------------------------------
|
|
@@ -1466,6 +1573,35 @@ export interface AdminConfigSetResult {
|
|
|
1466
1573
|
value: unknown;
|
|
1467
1574
|
}
|
|
1468
1575
|
|
|
1576
|
+
// ---------------------------------------------------------------------------
|
|
1577
|
+
// admin.config.unset (T11917 — remove a key from a scoped config file)
|
|
1578
|
+
// ---------------------------------------------------------------------------
|
|
1579
|
+
|
|
1580
|
+
/** Parameters for `admin.config.unset`. */
|
|
1581
|
+
export interface AdminConfigUnsetParams {
|
|
1582
|
+
/** Dot-notation config key to remove (required). */
|
|
1583
|
+
key: string;
|
|
1584
|
+
/** Remove from the global file instead of the project file. */
|
|
1585
|
+
global?: boolean;
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
/**
|
|
1589
|
+
* Result of `admin.config.unset`.
|
|
1590
|
+
*
|
|
1591
|
+
* `removed` is `true` IFF the key existed and was deleted; `false` when the key
|
|
1592
|
+
* was already absent (idempotent no-op).
|
|
1593
|
+
*
|
|
1594
|
+
* @task T11917
|
|
1595
|
+
*/
|
|
1596
|
+
export interface AdminConfigUnsetResult {
|
|
1597
|
+
/** Config key that was targeted. */
|
|
1598
|
+
key: string;
|
|
1599
|
+
/** Scope the key was removed from. */
|
|
1600
|
+
scope: 'project' | 'global';
|
|
1601
|
+
/** `true` IFF a value was actually deleted. */
|
|
1602
|
+
removed: boolean;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1469
1605
|
// ---------------------------------------------------------------------------
|
|
1470
1606
|
// admin.config.set-preset
|
|
1471
1607
|
// ---------------------------------------------------------------------------
|
|
@@ -1996,6 +2132,13 @@ export type AdminOps =
|
|
|
1996
2132
|
params: AdminConfigPresetsParams;
|
|
1997
2133
|
result: AdminConfigPresetsResult;
|
|
1998
2134
|
}
|
|
2135
|
+
| { op: 'admin.config.get'; params: AdminConfigGetParams; result: AdminConfigGetResult }
|
|
2136
|
+
| { op: 'admin.config.list'; params: AdminConfigListParams; result: AdminConfigListResult }
|
|
2137
|
+
| {
|
|
2138
|
+
op: 'admin.config.validate';
|
|
2139
|
+
params: AdminConfigValidateParams;
|
|
2140
|
+
result: AdminConfigValidateResult;
|
|
2141
|
+
}
|
|
1999
2142
|
| { op: 'admin.stats'; params: AdminStatsParams; result: AdminStatsResult }
|
|
2000
2143
|
| { op: 'admin.context'; params: AdminContextParams; result: AdminContextResult }
|
|
2001
2144
|
| { op: 'admin.context.pull'; params: AdminContextPullParams; result: AdminContextPullResult }
|
|
@@ -2046,6 +2189,7 @@ export type AdminOps =
|
|
|
2046
2189
|
params: AdminConfigSetPresetParams;
|
|
2047
2190
|
result: AdminConfigSetPresetResult;
|
|
2048
2191
|
}
|
|
2192
|
+
| { op: 'admin.config.unset'; params: AdminConfigUnsetParams; result: AdminConfigUnsetResult }
|
|
2049
2193
|
| {
|
|
2050
2194
|
op: 'admin.backup.mutate';
|
|
2051
2195
|
params: AdminBackupMutateParams;
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensures-schema Zod registry — the cantbook `ensures.schema` name → Zod
|
|
3
|
+
* validator SSoT (T11762 ST-1 · Lane A).
|
|
4
|
+
*
|
|
5
|
+
* ## Why this exists
|
|
6
|
+
*
|
|
7
|
+
* The playbook runtime (`packages/playbooks/src/runtime.ts`) validates a node's
|
|
8
|
+
* post-merge `context` against a named shape declared as `ensures.schema:` in a
|
|
9
|
+
* `.cantbook`. Historically the runtime HARDCODED two bespoke validators
|
|
10
|
+
* (`validateDecompositionTaskTree` / `validateIvtrEvidenceOutput`) in an
|
|
11
|
+
* `if (schema === 'task_tree') … else if (=== 'evidence')` block, and silently
|
|
12
|
+
* SKIPPED any other schema name. T11762 replaces that hardcode with a
|
|
13
|
+
* registry-driven lookup so:
|
|
14
|
+
*
|
|
15
|
+
* - `ensures.schema` names resolve to a registered Zod validator (AC1).
|
|
16
|
+
* - the runtime no longer hardcodes `'task_tree'` / `'evidence'` (AC2).
|
|
17
|
+
* - an unknown schema name FAILS CLOSED instead of silently passing.
|
|
18
|
+
*
|
|
19
|
+
* This module holds ONLY the Gate-10 (`lint-no-runtime-in-contracts`)-ALLOWED
|
|
20
|
+
* kinds: the Zod schema **const values**, the {@link EnsuresSchemaSpec} **type**,
|
|
21
|
+
* and the registry **data** (a `ReadonlyMap` value). The bodied accessors
|
|
22
|
+
* (`getEnsuresSchema` / `listEnsuresSchemaNames` / `defineEnsuresSchema`) live in
|
|
23
|
+
* `@cleocode/core` (`packages/core/src/dispatch/contracts/ensures-schema.ts`,
|
|
24
|
+
* ST-1b) because a `Map.get` helper is a net-new runtime function that the
|
|
25
|
+
* contracts-purity gate forbids in this leaf package.
|
|
26
|
+
*
|
|
27
|
+
* ## Message parity (behavior preservation)
|
|
28
|
+
*
|
|
29
|
+
* The Zod schemas are crafted so that — for every input the deleted bespoke
|
|
30
|
+
* validators rejected — the FIRST Zod issue message equals the SUFFIX of the
|
|
31
|
+
* original human-readable violation string (the part after the
|
|
32
|
+
* `ensures.schema[<name>] on <nodeId>: ` prefix). ST-2's runtime wrapper
|
|
33
|
+
* re-applies that prefix, so the end-to-end violation strings are unchanged. The
|
|
34
|
+
* ST-1 parity test asserts on these issue messages directly.
|
|
35
|
+
*
|
|
36
|
+
* ## Genkit-forward naming
|
|
37
|
+
*
|
|
38
|
+
* The registry surface is deliberately Genkit-shaped so a future Genkit
|
|
39
|
+
* `ai.defineSchema(name, zodSchema)` bridge (T11768) is a thin adapter over this
|
|
40
|
+
* SSoT, never a competing source.
|
|
41
|
+
*
|
|
42
|
+
* @packageDocumentation
|
|
43
|
+
* @module @cleocode/contracts/operations/ensures-schema-registry
|
|
44
|
+
*
|
|
45
|
+
* @epic T11762 — E-OUTPUT-SCHEMA-ENFORCEMENT
|
|
46
|
+
* @task T11900 — ST-1: ensures-schema Zod registry DATA + schemas
|
|
47
|
+
* @see validateDecompositionTaskTree — the ported bespoke task_tree validator
|
|
48
|
+
* @see validateIvtrEvidenceOutput — the ported bespoke evidence validator
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
import { type ZodType, z } from 'zod';
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* One registered `ensures.schema` entry: the Zod validator plus which playbook
|
|
55
|
+
* `context` key holds the value to validate.
|
|
56
|
+
*
|
|
57
|
+
* @public
|
|
58
|
+
*/
|
|
59
|
+
export interface EnsuresSchemaSpec {
|
|
60
|
+
/**
|
|
61
|
+
* The schema NAME used in `ensures.schema:` (e.g. `'task_tree'`, `'evidence'`).
|
|
62
|
+
*/
|
|
63
|
+
readonly name: string;
|
|
64
|
+
/**
|
|
65
|
+
* The playbook `context` key whose value is validated. Defaults to {@link name}
|
|
66
|
+
* (matching today's `context['task_tree']` / `context['evidence']` convention).
|
|
67
|
+
*/
|
|
68
|
+
readonly contextKey: string;
|
|
69
|
+
/**
|
|
70
|
+
* The Zod validator applied to `context[contextKey]`.
|
|
71
|
+
*/
|
|
72
|
+
readonly schema: ZodType;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ─── task_tree — ports validateDecompositionTaskTree (runtime.ts:794-855) ──────
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Zod schema for a single `task_tree` entry.
|
|
79
|
+
*
|
|
80
|
+
* Parity rules ported from `validateDecompositionTaskTree`:
|
|
81
|
+
* - `title` must be a non-empty string (after trim).
|
|
82
|
+
* - `acceptance` must be a non-empty array containing at least one non-empty
|
|
83
|
+
* (after-trim) string.
|
|
84
|
+
* - `id` / `parentId` / `depends` are optional and not hard-validated (the
|
|
85
|
+
* bespoke validator was intentionally lenient on these).
|
|
86
|
+
*
|
|
87
|
+
* @remarks
|
|
88
|
+
* The `title` check is split so the message echoes the bespoke
|
|
89
|
+
* `entry[i].title must be a non-empty string` regardless of whether the field is
|
|
90
|
+
* absent, the wrong type, or whitespace-only.
|
|
91
|
+
*/
|
|
92
|
+
export const taskTreeEntrySchema: ZodType = z.object({
|
|
93
|
+
title: z
|
|
94
|
+
.string({ message: 'title must be a non-empty string' })
|
|
95
|
+
.refine((s) => s.trim().length > 0, { message: 'title must be a non-empty string' }),
|
|
96
|
+
acceptance: z
|
|
97
|
+
.array(z.unknown(), { message: 'must have a non-empty acceptance array' })
|
|
98
|
+
.min(1, { message: 'must have a non-empty acceptance array' })
|
|
99
|
+
.refine((arr) => arr.some((s) => typeof s === 'string' && s.trim().length > 0), {
|
|
100
|
+
message: 'acceptance array contains no non-empty strings',
|
|
101
|
+
}),
|
|
102
|
+
id: z.string().optional(),
|
|
103
|
+
parentId: z.string().optional(),
|
|
104
|
+
depends: z.array(z.string()).optional(),
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Zod schema for the `task_tree` context value emitted by a RCASD decomposition
|
|
109
|
+
* node — a non-empty array of {@link taskTreeEntrySchema} entries.
|
|
110
|
+
*
|
|
111
|
+
* Parity: an empty array is rejected with `task_tree is an empty array …`; a
|
|
112
|
+
* non-array is rejected by Zod's base array type error.
|
|
113
|
+
*
|
|
114
|
+
* @public
|
|
115
|
+
*/
|
|
116
|
+
export const taskTreeSchema: ZodType = z
|
|
117
|
+
.array(taskTreeEntrySchema, { message: 'task_tree must be a non-empty array' })
|
|
118
|
+
.min(1, { message: 'task_tree is an empty array — decomposition produced no tasks' });
|
|
119
|
+
|
|
120
|
+
// ─── evidence — ports validateIvtrEvidenceOutput (runtime.ts:873-902) ──────────
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Zod schema for the `evidence` context value emitted by an IVTR validation
|
|
124
|
+
* node.
|
|
125
|
+
*
|
|
126
|
+
* Parity rules ported from `validateIvtrEvidenceOutput`. Valid evidence is one
|
|
127
|
+
* of:
|
|
128
|
+
* - a non-empty (after-trim) string,
|
|
129
|
+
* - a non-empty array,
|
|
130
|
+
* - an object with at least one key.
|
|
131
|
+
*
|
|
132
|
+
* `null` / `undefined`, the empty string, the empty array, the empty object, and
|
|
133
|
+
* any other primitive (number, boolean) are rejected — matching the bespoke
|
|
134
|
+
* validator exactly.
|
|
135
|
+
*
|
|
136
|
+
* @remarks
|
|
137
|
+
* A `z.union` of the three valid shapes would reject the SAME set of inputs, but
|
|
138
|
+
* collapses every rejection to a generic `"Invalid input"` union error. To
|
|
139
|
+
* preserve the bespoke validator's branch-specific messages (`evidence must be
|
|
140
|
+
* present …`, `evidence string must not be empty`, `evidence array must not be
|
|
141
|
+
* empty`, `evidence object must have at least one key (got {})`, `evidence must
|
|
142
|
+
* be a string, array, or object (got <type>)`), this schema replicates the
|
|
143
|
+
* original branch order in a single `superRefine`. The `superRefine` callback is
|
|
144
|
+
* an inline argument — NOT an exported bodied function/arrow — so it does not
|
|
145
|
+
* trip the Gate-10 contracts-purity lint.
|
|
146
|
+
*
|
|
147
|
+
* @public
|
|
148
|
+
*/
|
|
149
|
+
export const evidenceSchema: ZodType = z.unknown().superRefine((value, ctx) => {
|
|
150
|
+
if (value === null || value === undefined) {
|
|
151
|
+
ctx.addIssue({
|
|
152
|
+
code: 'custom',
|
|
153
|
+
message: 'evidence must be present (non-null, non-undefined)',
|
|
154
|
+
});
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (typeof value === 'string') {
|
|
158
|
+
if (value.trim().length === 0) {
|
|
159
|
+
ctx.addIssue({ code: 'custom', message: 'evidence string must not be empty' });
|
|
160
|
+
}
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (Array.isArray(value)) {
|
|
164
|
+
if (value.length === 0) {
|
|
165
|
+
ctx.addIssue({ code: 'custom', message: 'evidence array must not be empty' });
|
|
166
|
+
}
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (typeof value === 'object') {
|
|
170
|
+
if (Object.keys(value).length === 0) {
|
|
171
|
+
ctx.addIssue({
|
|
172
|
+
code: 'custom',
|
|
173
|
+
message: 'evidence object must have at least one key (got {})',
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// Numbers, booleans, symbols, bigints, functions — not valid evidence shapes.
|
|
179
|
+
ctx.addIssue({
|
|
180
|
+
code: 'custom',
|
|
181
|
+
message: `evidence must be a string, array, or object (got ${typeof value})`,
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// ─── passthrough — legacy starter `ensures.schema` names (R1 fail-closed) ──────
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Passthrough validator that accepts ANY value (including `undefined`).
|
|
189
|
+
*
|
|
190
|
+
* Used to register the legacy `ensures.schema` names already declared in the
|
|
191
|
+
* shipped starter `.cantbook` files ({@link LEGACY_PASSTHROUGH_SCHEMA_NAMES}).
|
|
192
|
+
*
|
|
193
|
+
* @remarks
|
|
194
|
+
* Before T11762, the runtime hardcoded ONLY `task_tree` / `evidence` and
|
|
195
|
+
* SILENTLY SKIPPED every other `ensures.schema` name. ST-2 flips that to
|
|
196
|
+
* fail-closed: an UNREGISTERED name is now a contract violation. To avoid
|
|
197
|
+
* regressing the in-repo starter playbooks (`release` / `rcasd` / `ivtr`),
|
|
198
|
+
* which declare a dozen descriptive schema names that were never actually
|
|
199
|
+
* shape-checked, each such name is registered here with this passthrough
|
|
200
|
+
* schema — preserving their historical "always pass" behavior EXACTLY while
|
|
201
|
+
* still failing-closed for genuinely-unknown names (Risk R1). Tightening any of
|
|
202
|
+
* these into a real shape is a follow-up; the name is the SSoT anchor.
|
|
203
|
+
*
|
|
204
|
+
* @public
|
|
205
|
+
*/
|
|
206
|
+
export const passthroughSchema: ZodType = z.unknown();
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* The legacy `ensures.schema` names declared in the shipped starter
|
|
210
|
+
* `.cantbook` files that were SILENTLY SKIPPED pre-T11762. Registered with
|
|
211
|
+
* {@link passthroughSchema} so the fail-closed flip (ST-2) does not regress
|
|
212
|
+
* them. Kept as exported DATA so the parity test can assert the exact set.
|
|
213
|
+
*
|
|
214
|
+
* @public
|
|
215
|
+
*/
|
|
216
|
+
export const LEGACY_PASSTHROUGH_SCHEMA_NAMES: readonly string[] = [
|
|
217
|
+
// release.cantbook
|
|
218
|
+
'version_bump_report',
|
|
219
|
+
'changelog_entry',
|
|
220
|
+
'publish_report',
|
|
221
|
+
// rcasd.cantbook
|
|
222
|
+
'research_summary',
|
|
223
|
+
'consensus_decision',
|
|
224
|
+
'architecture_plan',
|
|
225
|
+
'specification_document',
|
|
226
|
+
// ivtr.cantbook
|
|
227
|
+
'implementation_diff',
|
|
228
|
+
'validation_report',
|
|
229
|
+
'audit_report',
|
|
230
|
+
'test_report',
|
|
231
|
+
'release_confirmation',
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* The ensures-schema registry DATA — a `ReadonlyMap` from `ensures.schema` name
|
|
236
|
+
* to its {@link EnsuresSchemaSpec}.
|
|
237
|
+
*
|
|
238
|
+
* This is a VALUE (data), not a bodied function, so it is Gate-10-safe in the
|
|
239
|
+
* `@cleocode/contracts` leaf package. The bodied accessor layer in
|
|
240
|
+
* `@cleocode/core` (ST-1b) reads this map.
|
|
241
|
+
*
|
|
242
|
+
* Two strict entries (`task_tree`, `evidence`) port the deleted bespoke
|
|
243
|
+
* validators; the remaining entries are the legacy starter names
|
|
244
|
+
* ({@link LEGACY_PASSTHROUGH_SCHEMA_NAMES}) registered with
|
|
245
|
+
* {@link passthroughSchema} so the ST-2 fail-closed flip does not regress the
|
|
246
|
+
* shipped playbooks (Risk R1).
|
|
247
|
+
*
|
|
248
|
+
* @public
|
|
249
|
+
*/
|
|
250
|
+
export const ENSURES_SCHEMA_REGISTRY: ReadonlyMap<string, EnsuresSchemaSpec> = new Map<
|
|
251
|
+
string,
|
|
252
|
+
EnsuresSchemaSpec
|
|
253
|
+
>([
|
|
254
|
+
['task_tree', { name: 'task_tree', contextKey: 'task_tree', schema: taskTreeSchema }],
|
|
255
|
+
['evidence', { name: 'evidence', contextKey: 'evidence', schema: evidenceSchema }],
|
|
256
|
+
...LEGACY_PASSTHROUGH_SCHEMA_NAMES.map((name): [string, EnsuresSchemaSpec] => [
|
|
257
|
+
name,
|
|
258
|
+
{ name, contextKey: name, schema: passthroughSchema },
|
|
259
|
+
]),
|
|
260
|
+
]);
|