@skill-harness/adapters 0.24.2 → 0.25.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.
@@ -31,10 +31,10 @@ const SUPPORTED_KEYWORDS = new Set([
31
31
  // value constraints
32
32
  "enum", "const", "minLength", "maxLength", "minimum", "pattern", "format",
33
33
  ]);
34
- /** Ledger v3 adds only closed composition/conditionals and property-name schemas. */
34
+ /** Ledger v3/current record contracts add closed composition, conditionals, arrays and numeric bounds. */
35
35
  const V3_SUPPORTED_KEYWORDS = new Set([
36
36
  ...SUPPORTED_KEYWORDS,
37
- "allOf", "anyOf", "if", "then", "propertyNames", "minItems", "maxItems",
37
+ "allOf", "anyOf", "if", "then", "not", "propertyNames", "minItems", "maxItems", "uniqueItems", "exclusiveMinimum",
38
38
  ]);
39
39
  /**
40
40
  * The shape each supported keyword must have. A keyword whose *name* is known but
@@ -49,6 +49,7 @@ const KEYWORD_SHAPES = {
49
49
  anyOf: { check: (value) => Array.isArray(value) && value.length > 0, expected: "a non-empty array" },
50
50
  if: { check: (value) => isSchemaObject(value), expected: "a schema object" },
51
51
  then: { check: (value) => isSchemaObject(value), expected: "a schema object" },
52
+ not: { check: (value) => isSchemaObject(value), expected: "a schema object" },
52
53
  propertyNames: { check: (value) => isSchemaObject(value), expected: "a schema object" },
53
54
  type: { check: (value) => typeof value === "string" || (Array.isArray(value) && value.length > 0 && value.every((entry) => typeof entry === "string")), expected: "a string or array of strings" },
54
55
  properties: { check: (value) => isSchemaObject(value), expected: "an object" },
@@ -58,7 +59,9 @@ const KEYWORD_SHAPES = {
58
59
  enum: { check: (value) => Array.isArray(value) && value.length > 0, expected: "a non-empty array" },
59
60
  minLength: { check: (value) => typeof value === "number", expected: "a number" },
60
61
  maxLength: { check: (value) => typeof value === "number", expected: "a number" },
62
+ exclusiveMinimum: { check: (value) => typeof value === "number" && Number.isFinite(value), expected: "a finite number" },
61
63
  minimum: { check: (value) => typeof value === "number", expected: "a number" },
64
+ uniqueItems: { check: (value) => typeof value === "boolean", expected: "a boolean" },
62
65
  minItems: { check: (value) => Number.isInteger(value) && Number(value) >= 0, expected: "a non-negative integer" },
63
66
  maxItems: { check: (value) => Number.isInteger(value) && Number(value) >= 0, expected: "a non-negative integer" },
64
67
  pattern: { check: (value) => typeof value === "string", expected: "a string" },
@@ -122,7 +125,7 @@ function assertSchemaSupported(schema, label, path, v3) {
122
125
  }
123
126
  for (const [name, entry] of Object.entries(object(node.properties) ?? {}))
124
127
  assertSchemaSupported(entry, label, `${path}/properties/${name}`, v3);
125
- for (const keyword of ["items", "propertyNames", "if", "then"]) {
128
+ for (const keyword of ["items", "propertyNames", "if", "then", "not"]) {
126
129
  if (node[keyword] !== undefined)
127
130
  assertSchemaSupported(node[keyword], label, `${path}/${keyword}`, v3);
128
131
  }
@@ -163,7 +166,7 @@ export function declaredPropertyNames(schema) {
163
166
  for (const entry of Array.isArray(current[keyword]) ? current[keyword] : [])
164
167
  walk(entry);
165
168
  }
166
- for (const keyword of ["items", "propertyNames", "if", "then"])
169
+ for (const keyword of ["items", "propertyNames", "if", "then", "not"])
167
170
  if (current[keyword] !== undefined)
168
171
  walk(current[keyword]);
169
172
  if (current.additionalProperties && typeof current.additionalProperties === "object")
@@ -178,6 +181,9 @@ function validate(root, schema, value, path, known) {
178
181
  return validate(root, resolved, value, path, known);
179
182
  }
180
183
  const violations = [];
184
+ if (schema.not !== undefined && validate(root, schema.not, value, path, known).length === 0) {
185
+ violations.push({ path, message: "matches a forbidden schema shape" });
186
+ }
181
187
  if (Array.isArray(schema.allOf)) {
182
188
  for (const branch of schema.allOf)
183
189
  violations.push(...validate(root, branch, value, path, known));
@@ -220,6 +226,9 @@ function validate(root, schema, value, path, known) {
220
226
  if (typeof schema.maxItems === "number" && value.length > schema.maxItems) {
221
227
  violations.push({ path, message: `must contain at most ${schema.maxItems} item(s)` });
222
228
  }
229
+ if (schema.uniqueItems === true && new Set(value.map(canonicalItem)).size !== value.length) {
230
+ violations.push({ path, message: "must contain unique items" });
231
+ }
223
232
  if (schema.items !== undefined) {
224
233
  value.forEach((entry, index) => violations.push(...validate(root, schema.items, entry, `${path}[${index}]`, known)));
225
234
  }
@@ -280,6 +289,9 @@ function validateString(schema, value, path) {
280
289
  return violations;
281
290
  }
282
291
  function validateNumber(schema, value, path) {
292
+ if (typeof schema.exclusiveMinimum === "number" && value <= schema.exclusiveMinimum) {
293
+ return [{ path, message: `must be > ${schema.exclusiveMinimum}` }];
294
+ }
283
295
  if (typeof schema.minimum === "number" && value < schema.minimum) {
284
296
  return [{ path, message: `must be >= ${schema.minimum}` }];
285
297
  }
@@ -406,4 +418,12 @@ function object(value) {
406
418
  function isSchemaObject(value) {
407
419
  return object(value) !== undefined;
408
420
  }
421
+ /** JSON structural identity for uniqueItems, independent of object key order. */
422
+ function canonicalItem(value) {
423
+ if (value === null || typeof value !== "object")
424
+ return JSON.stringify(value);
425
+ if (Array.isArray(value))
426
+ return `[${value.map(canonicalItem).join(",")}]`;
427
+ return `{${Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => `${JSON.stringify(key)}:${canonicalItem(item)}`).join(",")}}`;
428
+ }
409
429
  //# sourceMappingURL=closed-schema.js.map
package/dist/index.d.ts CHANGED
@@ -4,3 +4,4 @@ export declare function getAdapter(name: string): HarnessAdapter;
4
4
  export { piAdapter };
5
5
  export * from "./trajectory.js";
6
6
  export * from "./pi-daddy-ledger-v3.js";
7
+ export { runPiDecision, DECISION_SYSTEM_PROMPT } from "./pi-decision.js";
package/dist/index.js CHANGED
@@ -16,4 +16,5 @@ export function getAdapter(name) {
16
16
  export { piAdapter };
17
17
  export * from "./trajectory.js";
18
18
  export * from "./pi-daddy-ledger-v3.js";
19
+ export { runPiDecision, DECISION_SYSTEM_PROMPT } from "./pi-decision.js";
19
20
  //# sourceMappingURL=index.js.map