@osovv/vv-opencode 1.5.0 → 1.7.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.
Files changed (94) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +41 -10
  3. package/dist/lib/agent-tool-catalog.d.ts +144 -0
  4. package/dist/lib/agent-tool-catalog.js +2551 -0
  5. package/dist/lib/agent-tool-catalog.js.map +1 -0
  6. package/dist/lib/agent-tool-contract.d.ts +200 -0
  7. package/dist/lib/agent-tool-contract.js +407 -0
  8. package/dist/lib/agent-tool-contract.js.map +1 -0
  9. package/dist/lib/workflow-contract.d.ts +12 -0
  10. package/dist/lib/workflow-contract.js +71 -18
  11. package/dist/lib/workflow-contract.js.map +1 -1
  12. package/dist/plugins/hashline-edit/index.js +102 -97
  13. package/dist/plugins/hashline-edit/index.js.map +1 -1
  14. package/dist/plugins/hashline-edit/normalize-edits.d.ts +2 -8
  15. package/dist/plugins/hashline-edit/normalize-edits.js +32 -17
  16. package/dist/plugins/hashline-edit/normalize-edits.js.map +1 -1
  17. package/dist/plugins/hashline-edit/schemas.d.ts +246 -0
  18. package/dist/plugins/hashline-edit/schemas.js +659 -0
  19. package/dist/plugins/hashline-edit/schemas.js.map +1 -0
  20. package/dist/plugins/hashline-edit/str-replace-editor.d.ts +6 -17
  21. package/dist/plugins/hashline-edit/str-replace-editor.js +19 -21
  22. package/dist/plugins/hashline-edit/str-replace-editor.js.map +1 -1
  23. package/dist/plugins/hashline-edit/tool-description.d.ts +1 -0
  24. package/dist/plugins/hashline-edit/tool-description.js +20 -4
  25. package/dist/plugins/hashline-edit/tool-description.js.map +1 -1
  26. package/dist/plugins/system-context-injection/index.js +9 -4
  27. package/dist/plugins/system-context-injection/index.js.map +1 -1
  28. package/dist/plugins/web-tools/fetch-service.d.ts +8 -5
  29. package/dist/plugins/web-tools/fetch-service.js +30 -45
  30. package/dist/plugins/web-tools/fetch-service.js.map +1 -1
  31. package/dist/plugins/web-tools/index.js +23 -5
  32. package/dist/plugins/web-tools/index.js.map +1 -1
  33. package/dist/plugins/web-tools/schemas.d.ts +469 -0
  34. package/dist/plugins/web-tools/schemas.js +523 -0
  35. package/dist/plugins/web-tools/schemas.js.map +1 -0
  36. package/dist/plugins/web-tools/search-service.d.ts +6 -3
  37. package/dist/plugins/web-tools/search-service.js +24 -29
  38. package/dist/plugins/web-tools/search-service.js.map +1 -1
  39. package/dist/plugins/workflow/authority.d.ts +6 -0
  40. package/dist/plugins/workflow/authority.js +45 -10
  41. package/dist/plugins/workflow/authority.js.map +1 -1
  42. package/dist/plugins/workflow/authorization.js +16 -8
  43. package/dist/plugins/workflow/authorization.js.map +1 -1
  44. package/dist/plugins/workflow/checkpoints.d.ts +41 -2
  45. package/dist/plugins/workflow/checkpoints.js +176 -47
  46. package/dist/plugins/workflow/checkpoints.js.map +1 -1
  47. package/dist/plugins/workflow/delegated.d.ts +15 -1
  48. package/dist/plugins/workflow/delegated.js +65 -35
  49. package/dist/plugins/workflow/delegated.js.map +1 -1
  50. package/dist/plugins/workflow/execution.d.ts +15 -30
  51. package/dist/plugins/workflow/execution.js +133 -33
  52. package/dist/plugins/workflow/execution.js.map +1 -1
  53. package/dist/plugins/workflow/index.js +177 -112
  54. package/dist/plugins/workflow/index.js.map +1 -1
  55. package/dist/plugins/workflow/input-validation.d.ts +48 -0
  56. package/dist/plugins/workflow/input-validation.js +536 -0
  57. package/dist/plugins/workflow/input-validation.js.map +1 -0
  58. package/dist/plugins/workflow/inspection.d.ts +60 -0
  59. package/dist/plugins/workflow/inspection.js +316 -0
  60. package/dist/plugins/workflow/inspection.js.map +1 -0
  61. package/dist/plugins/workflow/protocol.d.ts +2 -0
  62. package/dist/plugins/workflow/protocol.js +26 -4
  63. package/dist/plugins/workflow/protocol.js.map +1 -1
  64. package/dist/plugins/workflow/recovery.d.ts +2 -1
  65. package/dist/plugins/workflow/recovery.js +79 -12
  66. package/dist/plugins/workflow/recovery.js.map +1 -1
  67. package/dist/plugins/workflow/repair.d.ts +1 -1
  68. package/dist/plugins/workflow/repair.js +9 -10
  69. package/dist/plugins/workflow/repair.js.map +1 -1
  70. package/dist/plugins/workflow/results.d.ts +2566 -0
  71. package/dist/plugins/workflow/results.js +1111 -0
  72. package/dist/plugins/workflow/results.js.map +1 -0
  73. package/dist/plugins/workflow/schemas.d.ts +214 -24
  74. package/dist/plugins/workflow/schemas.js +350 -89
  75. package/dist/plugins/workflow/schemas.js.map +1 -1
  76. package/dist/plugins/workflow/state.d.ts +3 -2
  77. package/dist/plugins/workflow/state.js +15 -8
  78. package/dist/plugins/workflow/state.js.map +1 -1
  79. package/dist/plugins/workflow/system-instruction.md +17 -1
  80. package/dist/plugins/workflow/tooling.d.ts +2 -18
  81. package/dist/plugins/workflow/tooling.js +477 -460
  82. package/dist/plugins/workflow/tooling.js.map +1 -1
  83. package/dist/plugins/workflow/transactions.d.ts +13 -0
  84. package/dist/plugins/workflow/transactions.js +13 -3
  85. package/dist/plugins/workflow/transactions.js.map +1 -1
  86. package/package.json +6 -3
  87. package/schemas/vvoc/v3.json +1 -1
  88. package/templates/agents/vv-code-reviewer.md +13 -4
  89. package/templates/agents/vv-controller.md +17 -0
  90. package/templates/agents/vv-implementer.md +20 -9
  91. package/templates/agents/vv-spec-reviewer.md +13 -4
  92. package/templates/skills/vv-execute/SKILL.md +3 -3
  93. package/templates/skills/vv-execute/references/tool-contracts.md +1750 -0
  94. package/templates/skills/vv-review/SKILL.md +1 -1
@@ -0,0 +1,407 @@
1
+ // FILE: src/lib/agent-tool-contract.ts
2
+ // VERSION: 1.1.0
3
+ // START_MODULE_CONTRACT
4
+ // PURPOSE: Provide reusable cross-plugin agent-tool contract primitives: registered raw argument maps, strict full-object runtime schemas with output inference, bounded diagnostics, fail-closed definition/pre-execute/direct-execute guards, SDK-compatible result-envelope helpers, and loaded contract identity.
5
+ // SCOPE: Generic owned-tool contract descriptors and host-boundary adapters only. No catalog aggregation, no workflow/plugin runtime imports, no permission or state-eligibility decisions. Uses the pinned SDK tool.schema Zod instance; zod imports are type-only. Result-envelope validation is producer/test-only and never wraps post-side-effect execution.
6
+ // DEPENDS: [@opencode-ai/plugin, zod (types), src/lib/package.ts]
7
+ // LINKS: [M-AGENT-TOOL-CONTRACT]
8
+ // ROLE: RUNTIME
9
+ // MAP_MODE: EXPORTS
10
+ // END_MODULE_CONTRACT
11
+ //
12
+ // START_MODULE_MAP
13
+ // AGENT_TOOL_CONTRACT_REVISION - Public tool-contract revision string for loaded identity.
14
+ // PACKAGE_NAME - Re-exported canonical package name from package.ts.
15
+ // PACKAGE_VERSION - Re-exported cached package version from package.ts.
16
+ // resolveToolContractReferencePath - Package-relative path to the tool-contracts reference document.
17
+ // MAX_CONTRACT_ISSUES - Maximum structural issues retained per diagnostic.
18
+ // MAX_ISSUE_PATH_CHARS - Maximum rendered issue path length.
19
+ // MAX_ISSUE_MESSAGE_CHARS - Maximum rendered issue message length.
20
+ // MAX_ISSUE_VALUE_CHARS - Maximum safe scalar preview length.
21
+ // ContractIssueCode - Stable machine-readable structural issue codes.
22
+ // ContractIssue - Bounded, tokenized structural issue with safe value/type summary.
23
+ // escapePathSegment - Escape one issue path segment for safe tokenized rendering.
24
+ // formatIssuePath - Render a Zod path tuple as a bounded, control-safe token path.
25
+ // summarizeReceivedValue - Safe bounded scalar/container value summary.
26
+ // toContractIssues - Convert a ZodError into bounded tokenized contract issues (preserves union branch paths).
27
+ // formatContractIssues - Render issues as a bounded single-line explanation.
28
+ // ContractInputError - Pre-execution structural rejection with code, category, and issues.
29
+ // ContractHostCompatibilityError - Fail-closed host-context rejection for unsupported definition publication.
30
+ // OperationExample - Named accept/reject operation example metadata for a contract.
31
+ // OwnedToolResult - Object branch of the pinned SDK ToolResult (assignable through tool execute).
32
+ // OwnedToolAttachment - Pinned SDK ToolAttachment shape.
33
+ // ownedToolResult - Build an SDK-compatible structured tool result envelope.
34
+ // ownedToolAttachmentSchema - Strict attachment envelope schema for producer/test validation.
35
+ // ownedToolResultSchema - Strict result envelope schema; metadata/document content remain opaque.
36
+ // validateOwnedToolResult - Producer/test-only result envelope validation (no post-side-effect wrapper).
37
+ // strictObject - Build a closed object schema on the SDK tool.schema instance.
38
+ // contractInputJsonSchema - Input-mode JSON Schema projection for a contract schema.
39
+ // OwnedToolArgs - Schema-inferred argument type for an owned-tool registered map.
40
+ // OwnedToolContract - Registered raw map plus strict runtime schema and typed parse helpers.
41
+ // defineOwnedToolContract - Define a closed owned-tool contract from a raw argument map.
42
+ // parseOwnedToolArgs - Direct-execute parse returning schema-inferred output (defaults applied).
43
+ // ToolDefinitionHookOutput - Narrow structural view of the SDK tool.definition hook output.
44
+ // createToolDefinitionAdapter - Owned-only fail-closed tool.definition adapter publishing strict jsonSchema while preserving parameters identity.
45
+ // createPreExecuteGuard - Owned-only tool.execute.before structural guard that never mutates raw args.
46
+ // END_MODULE_MAP
47
+ //
48
+ // START_CHANGE_SUMMARY
49
+ // LAST_CHANGE: [C-AGENT-TOOL-CONTRACTS - Correction cycle: fail-closed definition publication, Zod output inference end-to-end, SDK-compatible result envelope + producer validation schema, escaped diagnostic paths, and preserved nested union issue paths.]
50
+ // END_CHANGE_SUMMARY
51
+ import { tool } from "@opencode-ai/plugin";
52
+ import { join } from "node:path";
53
+ import { fileURLToPath } from "node:url";
54
+ import { PACKAGE_NAME, PACKAGE_VERSION } from "./package.js";
55
+ export { PACKAGE_NAME, PACKAGE_VERSION };
56
+ // START_BLOCK_CONTRACT_IDENTITY
57
+ /** Public tool-contract revision; independent of persistence and workflow contract versions. */
58
+ export const AGENT_TOOL_CONTRACT_REVISION = "1";
59
+ const TOOL_CONTRACT_REFERENCE_PACKAGE_PATH = "templates/skills/vv-execute/references/tool-contracts.md";
60
+ /**
61
+ * Resolve the package-relative path to the shipped tool-contracts reference document.
62
+ * Uses the loaded module location, not global installs or user config.
63
+ */
64
+ export function resolveToolContractReferencePath() {
65
+ const packageRoot = fileURLToPath(new URL("../../", import.meta.url));
66
+ return join(packageRoot, TOOL_CONTRACT_REFERENCE_PACKAGE_PATH);
67
+ }
68
+ // END_BLOCK_CONTRACT_IDENTITY
69
+ // START_BLOCK_ISSUES
70
+ /** Maximum number of structural issues retained in one diagnostic. */
71
+ export const MAX_CONTRACT_ISSUES = 8;
72
+ /** Maximum rendered path length in characters. */
73
+ export const MAX_ISSUE_PATH_CHARS = 120;
74
+ /** Maximum rendered message length in characters. */
75
+ export const MAX_ISSUE_MESSAGE_CHARS = 200;
76
+ /** Maximum safe scalar preview length in characters. */
77
+ export const MAX_ISSUE_VALUE_CHARS = 48;
78
+ function truncateChars(value, max) {
79
+ if (value.length <= max)
80
+ return value;
81
+ return `${value.slice(0, Math.max(0, max - 1))}…`;
82
+ }
83
+ /**
84
+ * Escape one path segment so user-controlled keys cannot inject control characters
85
+ * or forge ambiguous dotted/bracketed paths.
86
+ */
87
+ export function escapePathSegment(segment) {
88
+ let escaped = "";
89
+ for (const character of segment) {
90
+ const code = character.codePointAt(0) ?? 0;
91
+ if (code < 0x20 || code === 0x7f) {
92
+ escaped += `\\u${code.toString(16).padStart(4, "0")}`;
93
+ }
94
+ else if (character === "\\" || character === "." || character === "[" || character === "]") {
95
+ escaped += `\\${character}`;
96
+ }
97
+ else {
98
+ escaped += character;
99
+ }
100
+ }
101
+ return escaped;
102
+ }
103
+ /** Render a Zod path tuple as a bounded dotted/bracketed token path with escaped segments. */
104
+ export function formatIssuePath(path) {
105
+ let rendered = "";
106
+ for (const segment of path) {
107
+ if (typeof segment === "number") {
108
+ rendered += `[${segment}]`;
109
+ }
110
+ else {
111
+ const token = escapePathSegment(typeof segment === "symbol" ? segment.toString() : segment);
112
+ rendered = rendered ? `${rendered}.${token}` : token;
113
+ }
114
+ if (rendered.length >= MAX_ISSUE_PATH_CHARS) {
115
+ return truncateChars(rendered, MAX_ISSUE_PATH_CHARS);
116
+ }
117
+ }
118
+ return rendered || "(root)";
119
+ }
120
+ /**
121
+ * Build a safe, bounded received-value summary.
122
+ * Scalars get a short preview; containers get a type name only — never a payload echo.
123
+ */
124
+ export function summarizeReceivedValue(value) {
125
+ if (value === null)
126
+ return "null";
127
+ if (value === undefined)
128
+ return "undefined";
129
+ if (typeof value === "string") {
130
+ return truncateChars(JSON.stringify(value), MAX_ISSUE_VALUE_CHARS);
131
+ }
132
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
133
+ return truncateChars(String(value), MAX_ISSUE_VALUE_CHARS);
134
+ }
135
+ if (Array.isArray(value))
136
+ return "array";
137
+ if (typeof value === "object")
138
+ return "object";
139
+ return truncateChars(String(value), MAX_ISSUE_VALUE_CHARS);
140
+ }
141
+ function issueCodeOf(code) {
142
+ switch (code) {
143
+ case "unrecognized_keys":
144
+ case "invalid_value":
145
+ case "invalid_type":
146
+ case "invalid_format":
147
+ case "too_small":
148
+ case "too_big":
149
+ case "missing_value":
150
+ case "invalid_union":
151
+ case "custom":
152
+ return code;
153
+ default:
154
+ return "custom";
155
+ }
156
+ }
157
+ function pushConcreteIssue(issues, raw, basePath) {
158
+ if (issues.length >= MAX_CONTRACT_ISSUES)
159
+ return;
160
+ const code = issueCodeOf(raw.code);
161
+ if (raw.code === "unrecognized_keys" && Array.isArray(raw.keys)) {
162
+ for (const key of raw.keys) {
163
+ if (issues.length >= MAX_CONTRACT_ISSUES)
164
+ break;
165
+ issues.push({
166
+ code: "unrecognized_keys",
167
+ path: formatIssuePath([...basePath, String(key)]),
168
+ message: truncateChars(`unrecognized key ${JSON.stringify(truncateChars(String(key), MAX_ISSUE_VALUE_CHARS))}`, MAX_ISSUE_MESSAGE_CHARS),
169
+ expected: "a known property of this request object",
170
+ });
171
+ }
172
+ return;
173
+ }
174
+ const expected = Array.isArray(raw.values) && raw.values.length > 0
175
+ ? truncateChars(raw.values.map((value) => summarizeReceivedValue(value)).join(" | "), MAX_ISSUE_MESSAGE_CHARS)
176
+ : raw.code === "invalid_type" && raw.expected !== undefined
177
+ ? truncateChars(String(raw.expected), MAX_ISSUE_MESSAGE_CHARS)
178
+ : undefined;
179
+ const received = raw.code === "invalid_type" && raw.received !== undefined
180
+ ? truncateChars(String(raw.received), MAX_ISSUE_VALUE_CHARS)
181
+ : undefined;
182
+ issues.push({
183
+ code,
184
+ path: formatIssuePath(basePath),
185
+ message: truncateChars(raw.message ?? "invalid value", MAX_ISSUE_MESSAGE_CHARS),
186
+ ...(expected !== undefined ? { expected } : {}),
187
+ ...(received !== undefined ? { received } : {}),
188
+ });
189
+ }
190
+ function pushIssueTree(issues, rawList, prefix) {
191
+ for (const raw of rawList) {
192
+ if (issues.length >= MAX_CONTRACT_ISSUES)
193
+ return;
194
+ const basePath = [...prefix, ...(raw.path ?? [])];
195
+ if (raw.code === "invalid_union" && Array.isArray(raw.errors) && raw.errors.length > 0) {
196
+ // Preserve nested union/discriminator branch paths (e.g. source.reference, source.kind).
197
+ for (const branch of raw.errors) {
198
+ pushIssueTree(issues, branch, basePath);
199
+ if (issues.length >= MAX_CONTRACT_ISSUES)
200
+ return;
201
+ }
202
+ continue;
203
+ }
204
+ pushConcreteIssue(issues, raw, basePath);
205
+ }
206
+ }
207
+ /**
208
+ * Convert a ZodError into bounded tokenized contract issues.
209
+ * Unknown keys become precise leaf paths; union branch paths are preserved;
210
+ * values are summarized, not echoed wholesale.
211
+ */
212
+ export function toContractIssues(error) {
213
+ const issues = [];
214
+ pushIssueTree(issues, error.issues, []);
215
+ return issues;
216
+ }
217
+ /** Render issues as one bounded single-line explanation suitable for host tool errors. */
218
+ export function formatContractIssues(issues) {
219
+ if (issues.length === 0)
220
+ return "INVALID_INPUT: structural validation failed";
221
+ const parts = issues.map((issue) => {
222
+ const path = issue.path || "(root)";
223
+ const expected = issue.expected ? `; expected ${issue.expected}` : "";
224
+ const received = issue.received ? `; received ${issue.received}` : "";
225
+ return truncateChars(`${path}: ${issue.message}${expected}${received}`, MAX_ISSUE_MESSAGE_CHARS);
226
+ });
227
+ return truncateChars(`INVALID_INPUT: ${parts.join(" | ")}`, MAX_ISSUE_MESSAGE_CHARS * (MAX_CONTRACT_ISSUES + 1));
228
+ }
229
+ /** Pre-execution structural rejection for owned tools. Not a permission or state decision. */
230
+ export class ContractInputError extends Error {
231
+ code = "INVALID_INPUT";
232
+ category = "input";
233
+ toolId;
234
+ issues;
235
+ constructor(toolId, issues) {
236
+ super(formatContractIssues(issues));
237
+ this.name = "ContractInputError";
238
+ this.toolId = toolId;
239
+ this.issues = issues;
240
+ }
241
+ }
242
+ /**
243
+ * Fail-closed host-context rejection when an owned tool cannot publish its contract
244
+ * through the host tool.definition seam. Never mutates the hook output before throwing.
245
+ */
246
+ export class ContractHostCompatibilityError extends Error {
247
+ code = "HOST_CONTRACT_UNSUPPORTED";
248
+ category = "host_context";
249
+ toolId;
250
+ reason;
251
+ constructor(toolId, reason) {
252
+ super(truncateChars(`HOST_CONTRACT_UNSUPPORTED: tool=${escapePathSegment(toolId)}; ${reason}`, MAX_ISSUE_MESSAGE_CHARS));
253
+ this.name = "ContractHostCompatibilityError";
254
+ this.toolId = toolId;
255
+ this.reason = truncateChars(reason, MAX_ISSUE_MESSAGE_CHARS);
256
+ }
257
+ }
258
+ /**
259
+ * Build a structured tool result envelope compatible with the pinned SDK ToolResult.
260
+ * Empty output and empty metadata remain valid for consumers that need them.
261
+ */
262
+ export function ownedToolResult(output, init) {
263
+ return {
264
+ ...(init?.title !== undefined ? { title: init.title } : {}),
265
+ output,
266
+ ...(init?.metadata !== undefined ? { metadata: init.metadata } : {}),
267
+ ...(init?.attachments !== undefined ? { attachments: init.attachments } : {}),
268
+ };
269
+ }
270
+ /** Closed object schema on the SDK tool.schema instance (rejects unknown keys). */
271
+ export function strictObject(shape) {
272
+ return tool.schema.strictObject(shape);
273
+ }
274
+ /** Attachment envelope schema for producer/test validation of owned tool results. */
275
+ export const ownedToolAttachmentSchema = strictObject({
276
+ type: tool.schema.literal("file"),
277
+ mime: tool.schema.string(),
278
+ url: tool.schema.string(),
279
+ filename: tool.schema.string().optional(),
280
+ });
281
+ /**
282
+ * Strict result-envelope schema for producer/test checks.
283
+ * `metadata` and nested document/binary content are declared opaque extension regions
284
+ * (record/unknown or declared opaque fields), not re-validated payload shapes.
285
+ * This is never applied as a throw-after-side-effect execute wrapper.
286
+ */
287
+ export const ownedToolResultSchema = strictObject({
288
+ title: tool.schema.string().optional(),
289
+ output: tool.schema.string(),
290
+ metadata: tool.schema.record(tool.schema.string(), tool.schema.unknown()).optional(),
291
+ attachments: tool.schema.array(ownedToolAttachmentSchema).optional(),
292
+ });
293
+ /**
294
+ * Producer/test-only validation of a structured result envelope.
295
+ * Returns typed output on success; structural issues on failure.
296
+ * Do not call this after irreversible side effects as a gate that invites replay.
297
+ */
298
+ export function validateOwnedToolResult(value) {
299
+ const result = ownedToolResultSchema.safeParse(value);
300
+ if (result.success) {
301
+ return { success: true, data: result.data };
302
+ }
303
+ return { success: false, issues: toContractIssues(result.error) };
304
+ }
305
+ /**
306
+ * Project a contract schema to its input-mode JSON Schema.
307
+ * Consistent with the host registry projection (io: "input", $defs → definitions).
308
+ */
309
+ export function contractInputJsonSchema(schema) {
310
+ const projected = tool.schema.toJSONSchema(schema, { io: "input" });
311
+ if (typeof projected !== "object" || projected === null || Array.isArray(projected)) {
312
+ throw new Error("contract schema produced a non-object JSON Schema");
313
+ }
314
+ const record = projected;
315
+ const { $defs, ...rest } = record;
316
+ if (typeof $defs === "object" && $defs !== null && !Array.isArray($defs)) {
317
+ return { ...rest, definitions: $defs };
318
+ }
319
+ return rest;
320
+ }
321
+ /**
322
+ * Define an owned-tool contract from the same raw argument map used for SDK registration.
323
+ * The runtime schema is a strict full-object validator over that map; nested closedness
324
+ * comes from composing nested shapes with strictObject. Unknown keys are never coerced or filtered.
325
+ */
326
+ export function defineOwnedToolContract(init) {
327
+ const runtimeSchema = strictObject(init.registeredArgs);
328
+ const inputJsonSchema = contractInputJsonSchema(runtimeSchema);
329
+ const examples = init.examples ?? [];
330
+ return {
331
+ toolId: init.toolId,
332
+ description: init.description,
333
+ registeredArgs: init.registeredArgs,
334
+ runtimeSchema,
335
+ inputJsonSchema,
336
+ examples,
337
+ safeParse(raw) {
338
+ const result = runtimeSchema.safeParse(raw);
339
+ if (result.success) {
340
+ return { success: true, data: result.data };
341
+ }
342
+ return { success: false, issues: toContractIssues(result.error) };
343
+ },
344
+ parse(raw) {
345
+ const result = runtimeSchema.safeParse(raw);
346
+ if (result.success)
347
+ return result.data;
348
+ throw new ContractInputError(init.toolId, toContractIssues(result.error));
349
+ },
350
+ };
351
+ }
352
+ /**
353
+ * Direct-execute validation: parse raw (host-forwarded) args through the contract schema,
354
+ * applying schema defaults/canonicalization for execute to consume.
355
+ * Returns the schema-inferred output type (defaults and enum literals preserved).
356
+ */
357
+ export function parseOwnedToolArgs(contract, rawArgs) {
358
+ return contract.parse(rawArgs);
359
+ }
360
+ function isDefinitionHookOutput(value) {
361
+ return (typeof value === "object" && value !== null && "parameters" in value && "description" in value);
362
+ }
363
+ function hasJsonSchemaMember(value) {
364
+ return "jsonSchema" in value;
365
+ }
366
+ /**
367
+ * Owned-only tool.definition adapter (fail-closed).
368
+ * Publishes the strict input-mode jsonSchema through the host's observable jsonSchema member
369
+ * while preserving parameters identity (the host decoder is never replaced).
370
+ * For owned tool IDs, an unsupported host shape (malformed output or missing jsonSchema member)
371
+ * throws ContractHostCompatibilityError without mutating the output.
372
+ * Unowned tool IDs are left untouched.
373
+ */
374
+ export function createToolDefinitionAdapter(contracts) {
375
+ const byId = new Map(contracts.map((contract) => [contract.toolId, contract]));
376
+ return async function toolDefinitionAdapter(input, output) {
377
+ const contract = byId.get(input.toolID);
378
+ if (!contract)
379
+ return;
380
+ if (!isDefinitionHookOutput(output)) {
381
+ throw new ContractHostCompatibilityError(contract.toolId, "malformed tool.definition output: missing required description/parameters members");
382
+ }
383
+ if (!hasJsonSchemaMember(output)) {
384
+ throw new ContractHostCompatibilityError(contract.toolId, "unsupported host tool.definition shape: missing jsonSchema member required for strict publication");
385
+ }
386
+ output.jsonSchema = contract.inputJsonSchema;
387
+ };
388
+ }
389
+ /**
390
+ * Owned-only pre-execute structural guard for tool.execute.before.
391
+ * Inspects raw args and throws ContractInputError on structural failure.
392
+ * Never mutates output.args and never confers state/permission eligibility.
393
+ */
394
+ export function createPreExecuteGuard(contracts) {
395
+ const byId = new Map(contracts.map((contract) => [contract.toolId, contract]));
396
+ return async function preExecuteGuard(input, output) {
397
+ const contract = byId.get(input.tool);
398
+ if (!contract)
399
+ return;
400
+ const result = contract.runtimeSchema.safeParse(output.args);
401
+ if (!result.success) {
402
+ throw new ContractInputError(contract.toolId, toContractIssues(result.error));
403
+ }
404
+ };
405
+ }
406
+ // END_BLOCK_HOST_ADAPTERS
407
+ //# sourceMappingURL=agent-tool-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-tool-contract.js","sourceRoot":"","sources":["../../src/lib/agent-tool-contract.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,12 @@ export declare const WORKFLOW_CONTRACT_VERSION = 1;
2
2
  export declare const WORKFLOW_ID_MAX_CHARS = 128;
3
3
  export declare const WORKFLOW_TEXT_MAX_CHARS = 2000;
4
4
  export declare const WORKFLOW_TEXT_MAX_ITEMS = 64;
5
+ /** Canonical work-item intent values accepted by work_item_open. */
6
+ export declare const WORK_ITEM_MODES: readonly ["implementation", "review_only", "delegated"];
7
+ /** Canonical independent reviewer roles accepted across workflow inputs. */
8
+ export declare const REVIEWER_ROLES: readonly ["spec", "code"];
9
+ /** Canonical delegatable lifecycle stages for advance authority. */
10
+ export declare const AUTHORITY_STAGES: readonly ["specification", "planning", "implementation", "verification"];
5
11
  /** Normalized workspace-relative path, or the reason a declared path is malformed. */
6
12
  export type DeclaredScopePathResult = {
7
13
  ok: true;
@@ -225,6 +231,12 @@ export interface WorkflowMessageClaim {
225
231
  export interface WorkflowContractProblem {
226
232
  code: string;
227
233
  message: string;
234
+ /**
235
+ * Tokenized field/index path of the offending value when it applies to one
236
+ * element (e.g. ["boundary", "files", 0]); absent when the problem applies to
237
+ * the whole value rather than a single indexed element.
238
+ */
239
+ path?: readonly (string | number)[];
228
240
  }
229
241
  export type WorkflowContractValidation<T> = {
230
242
  ok: true;
@@ -1,10 +1,10 @@
1
1
  // FILE: src/lib/workflow-contract.ts
2
- // VERSION: 1.0.0
2
+ // VERSION: 1.1.0
3
3
  // START_MODULE_CONTRACT
4
- // PURPOSE: Dependency-free common execution contract for native-package, provided-plan, and conversation-scoped workflow runs: declared-path normalization, bounded task/checkpoint/boundary contracts, explicit reviewer sets, exact-reference DAG validation, lineage/revision records, and authority/stage provenance shapes.
5
- // SCOPE: Pure path normalization, bounded identity/text validation, explicit reviewer-set normalization, execution boundary containment, task and checkpoint contract validation, exact reference and acyclic dependency checks, native definition adaptation into common contracts, and structural source/lineage/authority record types. No filesystem access, native XML parsing, SDK transport, task dispatch, or persistence.
4
+ // PURPOSE: Dependency-free common execution contract for native-package, provided-plan, and conversation-scoped workflow runs: canonical work-item/reviewer/authority enums, declared-path normalization, bounded task/checkpoint/boundary contracts, explicit reviewer sets, exact-reference DAG validation, lineage/revision records, and authority/stage provenance shapes.
5
+ // SCOPE: Pure path normalization, bounded identity/text validation, canonical enum constants shared by tool schemas and domain owners, explicit reviewer-set normalization, execution boundary containment (with boundary-reporting containment failures), task and checkpoint contract validation, exact reference and acyclic dependency checks, native definition adaptation into common contracts, and structural source/lineage/authority record types. No filesystem access, native XML parsing, SDK transport, task dispatch, or persistence.
6
6
  // DEPENDS: [] (deliberately dependency-free so the native adapter and the generic runtime share one contract without a cycle)
7
- // LINKS: [M-WORKFLOW-CONTRACT, M-SPEC-LINT, M-WORKFLOW-EXECUTION, M-WORKFLOW-AUTHORITY]
7
+ // LINKS: [M-WORKFLOW-CONTRACT, M-SPEC-LINT, M-WORKFLOW-EXECUTION, M-WORKFLOW-AUTHORITY, M-WORKFLOW-STATE, M-WORKFLOW-TOOLING]
8
8
  // ROLE: RUNTIME
9
9
  // MAP_MODE: EXPORTS
10
10
  // END_MODULE_CONTRACT
@@ -14,6 +14,9 @@
14
14
  // WORKFLOW_ID_MAX_CHARS - Maximum accepted workflow identity length.
15
15
  // WORKFLOW_TEXT_MAX_CHARS - Maximum accepted bounded contract text length.
16
16
  // WORKFLOW_TEXT_MAX_ITEMS - Maximum accepted list length inside one contract field.
17
+ // WORK_ITEM_MODES - Canonical work-item intent values accepted by work_item_open.
18
+ // REVIEWER_ROLES - Canonical independent reviewer roles accepted across workflow inputs.
19
+ // AUTHORITY_STAGES - Canonical delegatable lifecycle stages for advance authority.
17
20
  // WorkflowReviewer - Canonical independent reviewer role.
18
21
  // WorkflowObligationOrigin - Where a registered obligation came from (source, user, controller).
19
22
  // DelegatedReviewer - Canonical delegated checkpoint reviewer roles (spec, code).
@@ -43,7 +46,7 @@
43
46
  // WorkflowStageApproval - Recorded stage approval bound to an approved artifact hash.
44
47
  // WorkflowReserveDebit - One consumed unit of the shared advance-recovery reserve.
45
48
  // WorkflowMessageClaim - Session-wide claim that one root-user message already funded a grant.
46
- // WorkflowContractProblem - One deterministic contract validation problem.
49
+ // WorkflowContractProblem - One deterministic contract validation problem, with an optional indexed path.
47
50
  // WorkflowContractValidation - Validation result carrying a value or deterministic problems.
48
51
  // isBoundedWorkflowId - Whether a value is a bounded explicit workflow identity.
49
52
  // isPathInExecutionBoundary - Whether a normalized path is contained in an execution boundary.
@@ -56,13 +59,24 @@
56
59
  // END_MODULE_MAP
57
60
  //
58
61
  // START_CHANGE_SUMMARY
59
- // LAST_CHANGE: [C-WORKFLOW-PLAN-INDEPENDENCE - Initial dependency-free common contract extracted from the native spec linter so provided-plan and conversation-scoped execution share one validated contract.]
62
+ // LAST_CHANGE: [C-AGENT-TOOL-CONTRACTS T-002 - Added canonical work-item mode, reviewer role, and authority stage enum constants for schema/domain reuse, made OUT_OF_BOUNDARY containment failures report the offending scope together with the applicable declared boundary, and gave boundary problems precise indexed paths with bounded value previews.]
60
63
  // END_CHANGE_SUMMARY
61
64
  // START_BLOCK_CONTRACT_CONSTANTS
62
65
  export const WORKFLOW_CONTRACT_VERSION = 1;
63
66
  export const WORKFLOW_ID_MAX_CHARS = 128;
64
67
  export const WORKFLOW_TEXT_MAX_CHARS = 2000;
65
68
  export const WORKFLOW_TEXT_MAX_ITEMS = 64;
69
+ /** Canonical work-item intent values accepted by work_item_open. */
70
+ export const WORK_ITEM_MODES = ["implementation", "review_only", "delegated"];
71
+ /** Canonical independent reviewer roles accepted across workflow inputs. */
72
+ export const REVIEWER_ROLES = ["spec", "code"];
73
+ /** Canonical delegatable lifecycle stages for advance authority. */
74
+ export const AUTHORITY_STAGES = [
75
+ "specification",
76
+ "planning",
77
+ "implementation",
78
+ "verification",
79
+ ];
66
80
  /**
67
81
  * Text-level canonical normalization for declared scope file paths. The linter
68
82
  * and the runtime snapshot fingerprint share this representation so a plan that
@@ -201,32 +215,52 @@ export function normalizeReviewerSet(value) {
201
215
  }
202
216
  // END_BLOCK_REVIEWER_NORMALIZATION
203
217
  // START_BLOCK_BOUNDARY_VALIDATION
204
- function normalizeUniquePaths(raw, field, normalize, problems) {
218
+ /** Bounded preview of one offending value; never echoes an unbounded payload. */
219
+ const DIAGNOSTIC_PREVIEW_MAX_CHARS = 64;
220
+ function previewValue(value) {
221
+ const json = JSON.stringify(value);
222
+ const text = json === undefined ? String(value) : json;
223
+ return text.length <= DIAGNOSTIC_PREVIEW_MAX_CHARS
224
+ ? text
225
+ : `${text.slice(0, DIAGNOSTIC_PREVIEW_MAX_CHARS - 1)}…`;
226
+ }
227
+ function normalizeUniquePaths(raw, field, normalize, problems, pathBase = []) {
205
228
  if (raw === undefined || raw === null)
206
229
  return [];
207
230
  if (!Array.isArray(raw)) {
208
- problems.push({ code: "INVALID_LIST", message: `${field} must be an array` });
231
+ problems.push({
232
+ code: "INVALID_LIST",
233
+ message: `${field} must be an array`,
234
+ path: [...pathBase],
235
+ });
209
236
  return [];
210
237
  }
211
238
  const seen = new Set();
212
239
  const out = [];
213
- for (const entry of raw) {
240
+ for (let index = 0; index < raw.length; index += 1) {
241
+ const entry = raw[index];
214
242
  if (typeof entry !== "string") {
215
- problems.push({ code: "INVALID_PATH", message: `${field} entries must be strings` });
243
+ problems.push({
244
+ code: "INVALID_PATH",
245
+ message: `${field} entries must be strings`,
246
+ path: [...pathBase, index],
247
+ });
216
248
  return [];
217
249
  }
218
250
  const normalized = normalize(entry);
219
251
  if (!normalized.ok) {
220
252
  problems.push({
221
253
  code: "INVALID_PATH",
222
- message: `${field} path ${JSON.stringify(entry)} is malformed (${normalized.reason})`,
254
+ message: `${field} path ${previewValue(entry)} is malformed (${normalized.reason})`,
255
+ path: [...pathBase, index],
223
256
  });
224
257
  return [];
225
258
  }
226
259
  if (seen.has(normalized.path)) {
227
260
  problems.push({
228
261
  code: "DUPLICATE_PATH",
229
- message: `${field} path ${JSON.stringify(normalized.path)} is declared more than once`,
262
+ message: `${field} path ${previewValue(normalized.path)} is declared more than once`,
263
+ path: [...pathBase, index],
230
264
  });
231
265
  return [];
232
266
  }
@@ -241,19 +275,29 @@ export function validateExecutionBoundary(raw) {
241
275
  if (raw === null || typeof raw !== "object") {
242
276
  return {
243
277
  ok: false,
244
- problems: [{ code: "INVALID_BOUNDARY", message: "execution boundary must be an object" }],
278
+ problems: [
279
+ {
280
+ code: "INVALID_BOUNDARY",
281
+ message: "execution boundary must be an object",
282
+ path: ["boundary"],
283
+ },
284
+ ],
245
285
  };
246
286
  }
247
287
  const candidate = raw;
248
- const files = normalizeUniquePaths(candidate.files, "boundary.files", normalizeDeclaredScopePath, problems);
249
- const directories = normalizeUniquePaths(candidate.directories, "boundary.directories", normalizeDeclaredDirectoryPath, problems);
288
+ const files = normalizeUniquePaths(candidate.files, "boundary.files", normalizeDeclaredScopePath, problems, ["boundary", "files"]);
289
+ const directories = normalizeUniquePaths(candidate.directories, "boundary.directories", normalizeDeclaredDirectoryPath, problems, ["boundary", "directories"]);
250
290
  if (problems.length > 0)
251
291
  return { ok: false, problems };
252
292
  if (files.length === 0 && directories.length === 0) {
253
293
  return {
254
294
  ok: false,
255
295
  problems: [
256
- { code: "EMPTY_BOUNDARY", message: "execution boundary declares no files or directories" },
296
+ {
297
+ code: "EMPTY_BOUNDARY",
298
+ message: "execution boundary declares no files or directories",
299
+ path: ["boundary"],
300
+ },
257
301
  ],
258
302
  };
259
303
  }
@@ -265,6 +309,15 @@ export function isPathInExecutionBoundary(path, boundary) {
265
309
  return true;
266
310
  return boundary.directories.some((directory) => path.startsWith(`${directory}/`));
267
311
  }
312
+ /** Bounded one-line summary of a declared boundary for containment diagnostics. */
313
+ function describeExecutionBoundary(boundary) {
314
+ const summarize = (entries) => entries.length <= 8
315
+ ? entries.join(", ")
316
+ : `${entries.slice(0, 8).join(", ")}, …(+${entries.length - 8})`;
317
+ const files = boundary.files.length > 0 ? summarize(boundary.files) : "(none)";
318
+ const directories = boundary.directories.length > 0 ? summarize(boundary.directories) : "(none)";
319
+ return `files: ${files}; directories: ${directories}`;
320
+ }
268
321
  // END_BLOCK_BOUNDARY_VALIDATION
269
322
  // START_BLOCK_TASK_VALIDATION
270
323
  function normalizeBoundaryFiles(raw, field, problems, options) {
@@ -515,7 +568,7 @@ export function validateWorkflowContractGraph(graph) {
515
568
  if (!isPathInExecutionBoundary(path, graph.boundary)) {
516
569
  problems.push({
517
570
  code: "OUT_OF_BOUNDARY",
518
- message: `task ${task.taskId} writeScope ${JSON.stringify(path)} is outside the execution boundary`,
571
+ message: `task ${task.taskId} writeScope ${JSON.stringify(path)} is outside the execution boundary (declared ${describeExecutionBoundary(graph.boundary)})`,
519
572
  });
520
573
  }
521
574
  }
@@ -537,7 +590,7 @@ export function validateWorkflowContractGraph(graph) {
537
590
  if (!isPathInExecutionBoundary(path, graph.boundary)) {
538
591
  problems.push({
539
592
  code: "OUT_OF_BOUNDARY",
540
- message: `checkpoint ${checkpoint.checkpointId} scope ${JSON.stringify(path)} is outside the execution boundary`,
593
+ message: `checkpoint ${checkpoint.checkpointId} scope ${JSON.stringify(path)} is outside the execution boundary (declared ${describeExecutionBoundary(graph.boundary)})`,
541
594
  });
542
595
  }
543
596
  }