owlrunkit 0.18.2 → 0.18.3

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 (26) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +41 -7
  3. package/docs/architecture/OWLCODA_RUNKIT_018_PROJECT_DRIVER_PRODUCT_DEFINITION.md +16 -5
  4. package/docs/architecture/OWLCODA_RUNKIT_USAGE_MODE_SELECTION_PRODUCT_DECISION_20260811.md +53 -3
  5. package/docs/architecture/OWLCODA_RUN_KIT_CONTRACT_V0_2.md +7 -0
  6. package/integrations/codex/skills/owlcoda-runkit/SKILL.md +28 -9
  7. package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
  8. package/integrations/codex/skills/owlcoda-runkit/references/contract-v0.1.md +160 -0
  9. package/integrations/codex/skills/owlcoda-runkit/references/contract-v0.2.md +545 -0
  10. package/package.json +1 -1
  11. package/packages/attest/README.md +4 -3
  12. package/packages/attest/consumer-surface-v1.json +1 -0
  13. package/packages/attest/distribution-manifest-v1.json +7 -1
  14. package/packages/attest/schemas/quick-verification-receipt-v2.schema.json +232 -0
  15. package/packages/attest/src/index.mjs +4 -1
  16. package/packages/attest/src/quick-receipt-contract.mjs +13 -3
  17. package/packages/attest/src/quick.mjs +16 -2
  18. package/registry-release-policy-v1.json +5 -5
  19. package/sbom.spdx.json +5 -5
  20. package/scripts/runkit-contract/core-contract.mjs +2 -1
  21. package/scripts/runkit-contract/quick-metrics.mjs +3 -3
  22. package/scripts/runkit-contract/quick-receipt.mjs +79 -12
  23. package/scripts/runkit-contract/quick-verify.mjs +88 -11
  24. package/scripts/runkit-contract/runkit-cli.mjs +91 -9
  25. package/scripts/runkit-contract/schemas/team-project-event-v2.schema.json +128 -0
  26. package/scripts/runkit-contract/team-project.mjs +310 -45
@@ -1,10 +1,18 @@
1
1
  import { spawn } from "node:child_process";
2
- import { realpathSync } from "node:fs";
2
+ import {
3
+ closeSync,
4
+ constants,
5
+ openSync,
6
+ realpathSync,
7
+ } from "node:fs";
8
+ import path from "node:path";
3
9
 
10
+ import { readFileBytesBounded } from "../../packages/attest/src/formal.mjs";
4
11
  import { currentCoreIdentity } from "./core-contract.mjs";
5
12
  import {
6
13
  closeQuickOutputFiles,
7
14
  createQuickReceiptStore,
15
+ persistQuickInputArtifact,
8
16
  persistQuickReceipt,
9
17
  } from "./quick-receipt.mjs";
10
18
  import { captureWorkspaceSnapshot } from "./quick-workspace-snapshot.mjs";
@@ -17,15 +25,31 @@ function quickAttestCommand(workspaceRoot, receiptPath) {
17
25
  return `owlrunkit quick-attest --workspace ${shellQuote(workspaceRoot)} --receipt ${shellQuote(receiptPath)}`;
18
26
  }
19
27
 
20
- function runExactCommand({ executable, argv, cwd, stdoutFd, stderrFd }) {
28
+ function runExactCommand({ executable, argv, cwd, stdinPath, stdoutFd, stderrFd }) {
21
29
  return new Promise((resolve) => {
22
30
  let settled = false;
23
- const child = spawn(executable, argv, {
24
- cwd,
25
- shell: false,
26
- stdio: ["ignore", stdoutFd, stderrFd],
27
- env: process.env,
28
- });
31
+ let stdinFd;
32
+ let child;
33
+ try {
34
+ stdinFd = stdinPath === undefined
35
+ ? undefined
36
+ : openSync(stdinPath, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
37
+ child = spawn(executable, argv, {
38
+ cwd,
39
+ shell: false,
40
+ stdio: [stdinFd ?? "ignore", stdoutFd, stderrFd],
41
+ env: process.env,
42
+ });
43
+ } catch (error) {
44
+ if (stdinFd !== undefined) closeSync(stdinFd);
45
+ resolve({
46
+ exitCode: null,
47
+ signal: null,
48
+ launchError: error instanceof Error ? error.message : String(error),
49
+ });
50
+ return;
51
+ }
52
+ if (stdinFd !== undefined) closeSync(stdinFd);
29
53
  child.once("error", (error) => {
30
54
  if (settled) return;
31
55
  settled = true;
@@ -39,7 +63,13 @@ function runExactCommand({ executable, argv, cwd, stdoutFd, stderrFd }) {
39
63
  });
40
64
  }
41
65
 
42
- export async function runQuickVerification({ workspaceRoot, commandArgv }) {
66
+ function inputArtifactResult(stdinArtifact) {
67
+ return stdinArtifact === null
68
+ ? {}
69
+ : { inputArtifacts: { stdin: stdinArtifact } };
70
+ }
71
+
72
+ export async function runQuickVerification({ workspaceRoot, commandArgv, stdinFile }) {
43
73
  if (!Array.isArray(commandArgv) || commandArgv.length === 0 || !commandArgv.every((value) => typeof value === "string")) {
44
74
  return {
45
75
  status: "quick_verification_input_invalid",
@@ -60,12 +90,49 @@ export async function runQuickVerification({ workspaceRoot, commandArgv }) {
60
90
  };
61
91
  }
62
92
 
93
+ let stdinBytes;
94
+ if (stdinFile !== undefined) {
95
+ if (typeof stdinFile !== "string" || stdinFile.length === 0) {
96
+ return {
97
+ status: "quick_verification_input_invalid",
98
+ exitCode: 3,
99
+ issues: ["--stdin-file requires a non-empty regular file path."],
100
+ authorizationGranted: false,
101
+ };
102
+ }
103
+ try {
104
+ const selected = path.isAbsolute(stdinFile)
105
+ ? stdinFile
106
+ : path.resolve(root, stdinFile);
107
+ stdinBytes = readFileBytesBounded(selected).bytes;
108
+ } catch (error) {
109
+ return {
110
+ status: "quick_verification_input_invalid",
111
+ exitCode: 3,
112
+ issues: [`Quick stdin file is invalid: ${error instanceof Error ? error.message : String(error)}`],
113
+ authorizationGranted: false,
114
+ };
115
+ }
116
+ }
117
+
63
118
  let workspaceBefore;
64
119
  let store;
120
+ let stdinArtifact = null;
121
+ let persistedStdinPath;
65
122
  try {
66
123
  workspaceBefore = captureWorkspaceSnapshot(root);
67
124
  store = createQuickReceiptStore(root);
125
+ if (stdinBytes !== undefined) {
126
+ const persistedInput = persistQuickInputArtifact({
127
+ workspaceRoot: root,
128
+ store,
129
+ bytes: stdinBytes,
130
+ });
131
+ stdinArtifact = persistedInput.artifact;
132
+ persistedStdinPath = persistedInput.inputPath;
133
+ }
68
134
  } catch (error) {
135
+ if (store !== undefined) closeQuickOutputFiles(store);
69
136
  return {
70
137
  status: "quick_verification_input_invalid",
71
138
  exitCode: 3,
@@ -80,6 +147,7 @@ export async function runQuickVerification({ workspaceRoot, commandArgv }) {
80
147
  executable,
81
148
  argv,
82
149
  cwd: root,
150
+ stdinPath: persistedStdinPath,
83
151
  stdoutFd: store.stdoutFd,
84
152
  stderrFd: store.stderrFd,
85
153
  });
@@ -101,7 +169,7 @@ export async function runQuickVerification({ workspaceRoot, commandArgv }) {
101
169
  }
102
170
 
103
171
  const sourceMutated = workspaceBefore.sourceFingerprint !== workspaceAfter.sourceFingerprint;
104
- const issueCodes = ["quick_ignored_artifact_unbound"];
172
+ const issueCodes = [];
105
173
  if (sourceMutated) issueCodes.push("source_mutated_during_verification");
106
174
  let persisted;
107
175
  try {
@@ -109,7 +177,9 @@ export async function runQuickVerification({ workspaceRoot, commandArgv }) {
109
177
  workspaceRoot: root,
110
178
  store,
111
179
  receipt: {
112
- schemaVersion: "OwlCodaQuickVerificationReceiptV1",
180
+ schemaVersion: stdinArtifact === null
181
+ ? "OwlCodaQuickVerificationReceiptV1"
182
+ : "OwlCodaQuickVerificationReceiptV2",
113
183
  receiptId: store.receiptId,
114
184
  assurance: "captured_verification",
115
185
  authorizationGranted: false,
@@ -124,6 +194,9 @@ export async function runQuickVerification({ workspaceRoot, commandArgv }) {
124
194
  argv,
125
195
  cwd: root,
126
196
  },
197
+ ...(stdinArtifact === null
198
+ ? {}
199
+ : { inputArtifacts: { stdin: stdinArtifact } }),
127
200
  verificationContext: {
128
201
  platform: process.platform,
129
202
  architecture: process.arch,
@@ -154,6 +227,7 @@ export async function runQuickVerification({ workspaceRoot, commandArgv }) {
154
227
  ? "invalidated_by_command_source_mutation"
155
228
  : "source_unchanged",
156
229
  issueCodes: [...issueCodes, "quick_receipt_store_invalid"],
230
+ ...inputArtifactResult(stdinArtifact),
157
231
  issues: [error instanceof Error ? error.message : String(error)],
158
232
  nextAllowedAction: "repair_quick_receipt_store_and_rerun",
159
233
  authorizationGranted: false,
@@ -173,6 +247,7 @@ export async function runQuickVerification({ workspaceRoot, commandArgv }) {
173
247
  commandExitCode: execution.exitCode,
174
248
  mutationDecision: "invalidated_by_command_source_mutation",
175
249
  issueCodes,
250
+ ...inputArtifactResult(stdinArtifact),
176
251
  outputSummary,
177
252
  attestCommand,
178
253
  issues: [],
@@ -191,6 +266,7 @@ export async function runQuickVerification({ workspaceRoot, commandArgv }) {
191
266
  commandExitCode: execution.exitCode,
192
267
  mutationDecision: "source_unchanged",
193
268
  issueCodes,
269
+ ...inputArtifactResult(stdinArtifact),
194
270
  outputSummary,
195
271
  attestCommand,
196
272
  issues: execution.launchError ? [execution.launchError] : [],
@@ -208,6 +284,7 @@ export async function runQuickVerification({ workspaceRoot, commandArgv }) {
208
284
  commandExitCode: 0,
209
285
  mutationDecision: "source_unchanged",
210
286
  issueCodes,
287
+ ...inputArtifactResult(stdinArtifact),
211
288
  outputSummary,
212
289
  attestCommand,
213
290
  issues: [],
@@ -158,6 +158,7 @@ import {
158
158
  integrateTeamProjectV1,
159
159
  openTeamProjectDecisionV1,
160
160
  readTeamProjectStatusV1,
161
+ rejectAndReturnTeamProjectV1,
161
162
  resolveTeamProjectDecisionV1,
162
163
  } from "./team-project.mjs";
163
164
  import {
@@ -200,7 +201,7 @@ Fleet and status
200
201
  owlrunkit fleet discover; owlrunkit status --workspace .
201
202
 
202
203
  Agent team projects
203
- owlrunkit project <init|assign|checkpoint|handoff|decision|verification|capture|status|takeover|successor> [options]
204
+ owlrunkit project <init|assign|checkpoint|handoff|reject-and-return|decision|verification|capture|status|takeover|successor> [options]
204
205
  Durable Agent work, dependencies, decisions, gates, progress, and handoffs.
205
206
  Core successor
206
207
  owlrunkit core-successor <plan|apply|resume> --workspace . [...]
@@ -264,11 +265,20 @@ Attests one Quick Receipt against its bound materials and current workspace.
264
265
  It never grants repository or business authority.
265
266
  `,
266
267
  "quick-verify": `Usage:
267
- owlrunkit quick-verify --workspace <directory> [--json] -- <executable> [args...]
268
+ owlrunkit quick-verify --workspace <directory> [--stdin-file <file>] [--attest] [--json]
269
+ -- <executable> [args...]
268
270
 
269
271
  Runs one exact command, saves source-bound stdout/stderr and a Quick receipt,
270
- and returns a bounded output summary. Supply the exact command after --.
272
+ and returns a bounded head/tail output summary. --stdin-file copies and hash-binds
273
+ up to 1 MiB of exact stdin bytes in the receipt store. --attest immediately
274
+ attests the saved receipt without merging Quick and attestation semantics.
271
275
  Quick evidence is not Formal acceptance and grants no repository or business authority.
276
+ `,
277
+ "quick-metrics": `Usage:
278
+ owlrunkit quick-metrics --workspace <directory> --local [--verbose] [--json]
279
+
280
+ Returns aggregate local-only Quick counts with no telemetry or network access.
281
+ --verbose additionally lists the receipt paths used for the aggregation.
272
282
  `,
273
283
  fleet: `Usage:
274
284
  owlrunkit fleet register-root --fleet-root <directory>
@@ -419,6 +429,9 @@ action without granting any authority.
419
429
  owlrunkit project handoff --workspace <directory> --handoff-id <id> --at <ISO-UTC>
420
430
  --assignment-id <current> --work-item <id> --from-agent <id> --to-agent <id>
421
431
  --summary <text> --next <text> --evidence <ref> [--evidence <ref> ...] [--json]
432
+ owlrunkit project reject-and-return --workspace <directory> --rework-id <id> --at <ISO-UTC>
433
+ --work-item <failed-id> --reviewer-agent <id> --to-agent <id>
434
+ --reason <text> --next <text> --evidence <ref> [--evidence <ref> ...] [--json]
422
435
  owlrunkit project decision --workspace <directory> --open --decision-id <id> --at <ISO-UTC>
423
436
  --title <text> --question <text> --owner-agent <id>
424
437
  [--blocking-work-item <id> ...] --option <text> [--option <text> ...] [--json]
@@ -459,6 +472,15 @@ No self-reported percentage is accepted.
459
472
  Measured WorkItems require --completed-units on every checkpoint. A completed
460
473
  checkpoint must use the WorkItem's declared total. Example:
461
474
  owlrunkit project checkpoint --workspace . --checkpoint-id checkpoint-x --at 2026-08-11T00:00:00.000Z --assignment-id assign-x --work-item x --state completed --summary 'Completed x.' --completed-units 5 --evidence receipt:quick
475
+ `,
476
+ "project reject-and-return": `Usage:
477
+ owlrunkit project reject-and-return --workspace <directory> --rework-id <id> --at <ISO-UTC>
478
+ --work-item <failed-id> --reviewer-agent <id> --to-agent <id>
479
+ --reason <text> --next <text> --evidence <ref> [--evidence <ref> ...] [--json]
480
+
481
+ Atomically records the rejection and opens a new assigned rework attempt. The
482
+ failed attempt remains immutable and evidence-linked. This action does not
483
+ grant Git, release, deployment, production, or business authority.
462
484
  `,
463
485
  "project status": `Usage:
464
486
  owlrunkit project status --workspace <directory> [--json]
@@ -536,6 +558,20 @@ function formatTeamProjectHandoffHuman(result) {
536
558
  ].join("\n");
537
559
  }
538
560
 
561
+ function formatTeamProjectReworkHuman(result) {
562
+ const disposition = result.resumed ? "Resumed" : "Returned";
563
+ const nextAction = result.nextAction === null
564
+ ? "none"
565
+ : String(result.nextAction).replace(/\s+/gu, " ").trim();
566
+ return [
567
+ `${disposition} failed WorkItem ${result.workItemId} to Agent ${result.toAgentId} for rework attempt ${result.reworkAttempt}.`,
568
+ `Failed checkpoint preserved: ${result.failedCheckpointEventId}`,
569
+ `Next: ${nextAction}`,
570
+ `Rework assignment: ${result.assignmentId}`,
571
+ "",
572
+ ].join("\n");
573
+ }
574
+
539
575
  function formatTeamProjectDecisionHuman(result) {
540
576
  const disposition = result.resumed
541
577
  ? "Resumed"
@@ -1923,6 +1959,8 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
1923
1959
  ? ["owned-path"]
1924
1960
  : command === "project" && action === "handoff"
1925
1961
  ? ["evidence"]
1962
+ : command === "project" && action === "reject-and-return"
1963
+ ? ["evidence"]
1926
1964
  : command === "project" && action === "integrate"
1927
1965
  ? ["evidence"]
1928
1966
  : command === "project" && action === "verification"
@@ -1960,7 +1998,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
1960
1998
  ? ["json", "open", "resolve"]
1961
1999
  : command === "project" && action === "verification"
1962
2000
  ? ["json", "defer", "close"]
1963
- : command === "project" && new Set(["assign", "handoff", "checkpoint", "integrate", "status", "takeover", "successor"]).has(action)
2001
+ : command === "project" && new Set(["assign", "handoff", "reject-and-return", "checkpoint", "integrate", "status", "takeover", "successor"]).has(action)
1964
2002
  ? ["json"]
1965
2003
  : command === "doctor" || command === "adopt" || command === "status"
1966
2004
  ? ["json"]
@@ -1974,8 +2012,12 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
1974
2012
  ? ["adopt-orphan-success-receipts"]
1975
2013
  : command === "deployment" && action === "execute"
1976
2014
  ? ["resume"]
1977
- : new Set(["quick-verify", "quick-attest", "quick-metrics"]).has(command)
1978
- ? ["json", "local"]
2015
+ : command === "quick-verify"
2016
+ ? ["json", "attest"]
2017
+ : command === "quick-attest"
2018
+ ? ["json"]
2019
+ : command === "quick-metrics"
2020
+ ? ["json", "local", "verbose"]
1979
2021
  : [],
1980
2022
  });
1981
2023
  if (command === "init") return await initialize(options);
@@ -2811,6 +2853,10 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2811
2853
  "workspace", "request", "handoff-id", "at", "assignment-id", "work-item",
2812
2854
  "from-agent", "to-agent", "summary", "next", "evidence", "json",
2813
2855
  ],
2856
+ "reject-and-return": [
2857
+ "workspace", "rework-id", "at", "work-item", "reviewer-agent",
2858
+ "to-agent", "reason", "next", "evidence", "json",
2859
+ ],
2814
2860
  decision: [
2815
2861
  "workspace", "request", "open", "resolve", "decision-id", "at", "title",
2816
2862
  "question", "owner-agent", "blocking-work-item", "option", "resolution",
@@ -2918,6 +2964,22 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2918
2964
  ? handedOff
2919
2965
  : withHumanOutput(handedOff, formatTeamProjectHandoffHuman(handedOff));
2920
2966
  }
2967
+ if (action === "reject-and-return") {
2968
+ const returned = rejectAndReturnTeamProjectV1({
2969
+ workspaceRoot: root,
2970
+ reworkId: requireOption(options, "rework-id"),
2971
+ occurredAt: requireOption(options, "at"),
2972
+ workItemId: requireOption(options, "work-item"),
2973
+ reviewerAgentId: requireOption(options, "reviewer-agent"),
2974
+ toAgentId: requireOption(options, "to-agent"),
2975
+ reason: requireOption(options, "reason"),
2976
+ nextAction: requireOption(options, "next"),
2977
+ evidenceRefs: options.evidence ?? [],
2978
+ });
2979
+ return options.json === true
2980
+ ? returned
2981
+ : withHumanOutput(returned, formatTeamProjectReworkHuman(returned));
2982
+ }
2921
2983
  if (action === "decision") {
2922
2984
  const directDecisionFields = [
2923
2985
  "open",
@@ -3228,7 +3290,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3228
3290
  ? successor
3229
3291
  : withHumanOutput(successor, formatTeamProjectSuccessorHumanV1(successor));
3230
3292
  }
3231
- throw new Error("Usage: owlrunkit project <init|assign|checkpoint|handoff|decision|verification|integrate|capture|status|takeover|successor> [options]");
3293
+ throw new Error("Usage: owlrunkit project <init|assign|checkpoint|handoff|reject-and-return|decision|verification|integrate|capture|status|takeover|successor> [options]");
3232
3294
  }
3233
3295
  if (command === "profiles") {
3234
3296
  const root = requireOption(options, "workspace");
@@ -3314,10 +3376,28 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3314
3376
  if (commandArgv.length === 0) {
3315
3377
  throw new Error("Usage: runkit-cli.mjs quick-verify --workspace <path> -- <executable> [args...]");
3316
3378
  }
3317
- return runQuickVerification({
3379
+ const verification = await runQuickVerification({
3318
3380
  workspaceRoot: workspace(options),
3319
3381
  commandArgv,
3382
+ stdinFile: options["stdin-file"],
3383
+ });
3384
+ if (options.attest !== true || typeof verification.receiptPath !== "string") {
3385
+ return verification;
3386
+ }
3387
+ const details = attestQuickReceiptDetails({
3388
+ receiptPath: verification.receiptPath,
3389
+ workspaceRoot: workspace(options),
3320
3390
  });
3391
+ return {
3392
+ ...verification,
3393
+ exitCode: details.exitCode === 0 ? verification.exitCode : details.exitCode,
3394
+ attestationDecision: details.attestation.decision,
3395
+ attestation: details.attestation,
3396
+ nextAllowedAction: details.attestation.decision === "GO"
3397
+ ? "consume_attestation"
3398
+ : "inspect_attestation_issues",
3399
+ authorizationGranted: false,
3400
+ };
3321
3401
  }
3322
3402
  if (command === "quick-attest") {
3323
3403
  const details = attestQuickReceiptDetails({
@@ -3342,7 +3422,9 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3342
3422
  if (options.local !== true) {
3343
3423
  throw new Error("Quick metrics requires --local; network telemetry is not available.");
3344
3424
  }
3345
- const local = readLocalQuickMetrics(workspace(options));
3425
+ const local = readLocalQuickMetrics(workspace(options), {
3426
+ verbose: options.verbose === true,
3427
+ });
3346
3428
  return {
3347
3429
  ...local,
3348
3430
  metrics: local.quick,
@@ -0,0 +1,128 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://owlcoda.com/schemas/runkit/team-project-event-v2.schema.json",
4
+ "title": "OwlCoda RunKit Team Project Event V2",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["schemaVersion", "eventId", "type", "occurredAt"],
8
+ "properties": {
9
+ "schemaVersion": { "const": "OwlCodaRunKitTeamProjectEventV2" },
10
+ "eventId": { "$ref": "#/$defs/id" },
11
+ "type": { "enum": ["agent_assigned", "checkpoint_recorded", "handoff_recorded", "rework_returned", "decision_opened", "decision_resolved", "integration_gate_passed", "verification_deferred", "verification_closed", "data_candidate_recorded"] },
12
+ "occurredAt": { "type": "string", "minLength": 24 },
13
+ "assignmentId": { "$ref": "#/$defs/id" },
14
+ "supersedesAssignmentId": { "$ref": "#/$defs/id" },
15
+ "failedAssignmentId": { "$ref": "#/$defs/id" },
16
+ "failedCheckpointEventId": { "$ref": "#/$defs/id" },
17
+ "reworkId": { "$ref": "#/$defs/id" },
18
+ "workItemId": { "$ref": "#/$defs/id" },
19
+ "agentId": { "$ref": "#/$defs/id" },
20
+ "executionRunId": { "$ref": "#/$defs/id" },
21
+ "executionWorkItemId": { "$ref": "#/$defs/id" },
22
+ "state": { "enum": ["active", "waiting_dependency", "waiting_decision", "verifying", "ready_to_integrate", "completed", "failed"] },
23
+ "summary": { "type": "string", "minLength": 1 },
24
+ "completedUnits": { "type": "integer", "minimum": 0 },
25
+ "evidenceRefs": { "$ref": "#/$defs/strings" },
26
+ "blockerRefs": { "$ref": "#/$defs/strings" },
27
+ "decisionRefs": { "$ref": "#/$defs/strings" },
28
+ "nextAction": { "oneOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] },
29
+ "sourceFingerprint": { "type": "string", "pattern": "^(sha256:)?[a-f0-9]{64}$" },
30
+ "fromAgentId": { "$ref": "#/$defs/id" },
31
+ "reviewerAgentId": { "$ref": "#/$defs/id" },
32
+ "toAgentId": { "$ref": "#/$defs/id" },
33
+ "reason": { "type": "string", "minLength": 1 },
34
+ "decisionId": { "$ref": "#/$defs/id" },
35
+ "title": { "type": "string", "minLength": 1 },
36
+ "question": { "type": "string", "minLength": 1 },
37
+ "ownerAgentId": { "$ref": "#/$defs/id" },
38
+ "blockingWorkItemIds": { "$ref": "#/$defs/strings" },
39
+ "options": { "$ref": "#/$defs/strings" },
40
+ "resolution": { "type": "string", "minLength": 1 },
41
+ "rationale": { "type": "string", "minLength": 1 },
42
+ "gateId": { "$ref": "#/$defs/id" },
43
+ "verificationId": { "$ref": "#/$defs/id" },
44
+ "checkIds": { "$ref": "#/$defs/ids" },
45
+ "dueGateId": { "$ref": "#/$defs/id" },
46
+ "disposition": { "enum": ["verified", "no_longer_required"] },
47
+ "decisionIds": { "$ref": "#/$defs/ids" },
48
+ "candidateId": { "$ref": "#/$defs/id" },
49
+ "sourceRef": { "type": "string", "minLength": 1 },
50
+ "rights": { "type": "string", "minLength": 1 },
51
+ "inputRef": { "type": "string", "minLength": 1 },
52
+ "outputRef": { "type": "string", "minLength": 1 },
53
+ "decisionRef": { "oneOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] },
54
+ "verificationRefs": { "$ref": "#/$defs/strings" },
55
+ "outcomeRef": { "oneOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] },
56
+ "version": { "type": "string", "minLength": 1 }
57
+ },
58
+ "allOf": [
59
+ {
60
+ "if": { "properties": { "type": { "const": "agent_assigned" } }, "required": ["type"] },
61
+ "then": {
62
+ "required": ["assignmentId", "workItemId", "agentId"],
63
+ "dependentRequired": {
64
+ "executionRunId": ["executionWorkItemId"],
65
+ "executionWorkItemId": ["executionRunId"]
66
+ }
67
+ }
68
+ },
69
+ {
70
+ "if": { "properties": { "type": { "const": "checkpoint_recorded" } }, "required": ["type"] },
71
+ "then": { "required": ["assignmentId", "workItemId", "state", "summary", "evidenceRefs", "blockerRefs", "decisionRefs", "nextAction"] }
72
+ },
73
+ {
74
+ "if": { "properties": { "type": { "const": "handoff_recorded" } }, "required": ["type"] },
75
+ "then": { "required": ["assignmentId", "workItemId", "fromAgentId", "toAgentId", "summary", "evidenceRefs", "nextAction"] }
76
+ },
77
+ {
78
+ "if": { "properties": { "type": { "const": "rework_returned" } }, "required": ["type"] },
79
+ "then": { "required": ["reworkId", "assignmentId", "failedAssignmentId", "failedCheckpointEventId", "workItemId", "fromAgentId", "reviewerAgentId", "toAgentId", "reason", "evidenceRefs", "nextAction"] }
80
+ },
81
+ {
82
+ "if": { "properties": { "type": { "const": "decision_opened" } }, "required": ["type"] },
83
+ "then": { "required": ["decisionId", "title", "question", "ownerAgentId", "blockingWorkItemIds", "options"] }
84
+ },
85
+ {
86
+ "if": { "properties": { "type": { "const": "decision_resolved" } }, "required": ["type"] },
87
+ "then": { "required": ["decisionId", "resolution", "rationale", "evidenceRefs"] }
88
+ },
89
+ {
90
+ "if": { "properties": { "type": { "const": "integration_gate_passed" } }, "required": ["type"] },
91
+ "then": { "required": ["gateId", "summary", "evidenceRefs"] }
92
+ },
93
+ {
94
+ "if": { "properties": { "type": { "const": "verification_deferred" } }, "required": ["type"] },
95
+ "then": { "required": ["verificationId", "workItemId", "ownerAgentId", "checkIds", "reason", "dueGateId"] }
96
+ },
97
+ {
98
+ "if": { "properties": { "type": { "const": "verification_closed" } }, "required": ["type"] },
99
+ "then": { "required": ["verificationId", "disposition", "summary", "evidenceRefs", "decisionIds"] }
100
+ },
101
+ {
102
+ "if": { "properties": { "type": { "const": "data_candidate_recorded" } }, "required": ["type"] },
103
+ "then": { "required": ["candidateId", "sourceRef", "rights", "inputRef", "outputRef", "decisionRef", "verificationRefs", "outcomeRef", "version"] }
104
+ }
105
+ ],
106
+ "$defs": {
107
+ "id": { "type": "string", "pattern": "^[A-Za-z0-9][A-Za-z0-9._-]*$" },
108
+ "ids": { "type": "array", "uniqueItems": true, "items": { "$ref": "#/$defs/id" } },
109
+ "strings": { "type": "array", "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }
110
+ },
111
+ "examples": [{
112
+ "schemaVersion": "OwlCodaRunKitTeamProjectEventV2",
113
+ "eventId": "rework-returned-review-001",
114
+ "type": "rework_returned",
115
+ "occurredAt": "2026-08-12T00:00:00.000Z",
116
+ "reworkId": "review-001",
117
+ "assignmentId": "rework-review-001",
118
+ "failedAssignmentId": "assignment-001",
119
+ "failedCheckpointEventId": "checkpoint-failed-001",
120
+ "workItemId": "engine",
121
+ "fromAgentId": "agent-kimi",
122
+ "reviewerAgentId": "agent-control",
123
+ "toAgentId": "agent-kimi",
124
+ "reason": "The candidate violates its versioned contract.",
125
+ "evidenceRefs": ["receipt:quick-failed"],
126
+ "nextAction": "Repair the contract and rerun the focused check."
127
+ }]
128
+ }