owlrunkit 0.18.2 → 0.18.4

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 (40) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +159 -52
  3. package/docs/architecture/OWLCODA_RUNKIT_0184_EXTERNAL_DELIVERY_INTAKE_PRODUCT_DECISION_20260812.md +209 -0
  4. package/docs/architecture/OWLCODA_RUNKIT_018_PROJECT_DRIVER_PRODUCT_DEFINITION.md +16 -5
  5. package/docs/architecture/OWLCODA_RUNKIT_USAGE_MODE_SELECTION_PRODUCT_DECISION_20260811.md +54 -3
  6. package/docs/architecture/OWLCODA_RUN_KIT_CONTRACT_V0_2.md +7 -0
  7. package/integrations/codex/skills/owlcoda-runkit/SKILL.md +125 -74
  8. package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
  9. package/integrations/codex/skills/owlcoda-runkit/references/contract-v0.1.md +160 -0
  10. package/integrations/codex/skills/owlcoda-runkit/references/contract-v0.2.md +545 -0
  11. package/package.json +1 -1
  12. package/packages/attest/README.md +4 -3
  13. package/packages/attest/consumer-surface-v1.json +1 -0
  14. package/packages/attest/distribution-manifest-v1.json +12 -1
  15. package/packages/attest/schemas/quick-verification-receipt-v2.schema.json +232 -0
  16. package/packages/attest/src/index.mjs +4 -1
  17. package/packages/attest/src/quick-receipt-contract.mjs +16 -6
  18. package/packages/attest/src/quick.mjs +21 -2
  19. package/packages/attest/src/workspace-snapshot.mjs +10 -1
  20. package/registry-release-policy-v1.json +5 -5
  21. package/sbom.spdx.json +5 -5
  22. package/scripts/runkit-contract/assurance-router.mjs +25 -6
  23. package/scripts/runkit-contract/core-contract.mjs +10 -1
  24. package/scripts/runkit-contract/onboarding-doctor.mjs +1 -1
  25. package/scripts/runkit-contract/profile-onboarding.mjs +263 -15
  26. package/scripts/runkit-contract/project-cli-resolver.mjs +6 -0
  27. package/scripts/runkit-contract/project-external-delivery.mjs +707 -0
  28. package/scripts/runkit-contract/quick-metrics.mjs +3 -3
  29. package/scripts/runkit-contract/quick-receipt.mjs +79 -12
  30. package/scripts/runkit-contract/quick-verify.mjs +89 -12
  31. package/scripts/runkit-contract/runkit-bootstrap.mjs +6 -1
  32. package/scripts/runkit-contract/runkit-cli.mjs +363 -143
  33. package/scripts/runkit-contract/schemas/assurance-route-v2.schema.json +26 -0
  34. package/scripts/runkit-contract/schemas/profile-detection-v3.schema.json +170 -0
  35. package/scripts/runkit-contract/schemas/team-project-event-v2.schema.json +128 -0
  36. package/scripts/runkit-contract/schemas/team-project-event-v3.schema.json +146 -0
  37. package/scripts/runkit-contract/schemas/team-project-status-v2.schema.json +85 -0
  38. package/scripts/runkit-contract/schemas/usage-mode-recommendation-v2.schema.json +136 -0
  39. package/scripts/runkit-contract/team-project.mjs +782 -55
  40. package/scripts/runkit-contract/usage-mode.mjs +28 -7
@@ -59,7 +59,7 @@ function trustedReceiptRoot(workspaceRoot) {
59
59
  return { status: "valid", root };
60
60
  }
61
61
 
62
- export function readLocalQuickMetrics(workspaceRoot) {
62
+ export function readLocalQuickMetrics(workspaceRoot, { verbose = false } = {}) {
63
63
  const selected = trustedReceiptRoot(workspaceRoot);
64
64
  if (selected.status === "invalid") {
65
65
  return {
@@ -68,7 +68,7 @@ export function readLocalQuickMetrics(workspaceRoot) {
68
68
  schemaVersion: "OwlCodaRunKitLocalMetricsV1",
69
69
  telemetry: false,
70
70
  networkRequests: 0,
71
- inputs: [],
71
+ ...(verbose ? { inputs: [] } : {}),
72
72
  quick: {
73
73
  total: 0,
74
74
  passed: 0,
@@ -117,7 +117,7 @@ export function readLocalQuickMetrics(workspaceRoot) {
117
117
  schemaVersion: "OwlCodaRunKitLocalMetricsV1",
118
118
  telemetry: false,
119
119
  networkRequests: 0,
120
- inputs: receiptPaths,
120
+ ...(verbose ? { inputs: receiptPaths } : {}),
121
121
  quick: totals,
122
122
  authorizationGranted: false,
123
123
  };
@@ -97,20 +97,36 @@ function cleanOutputLine(line) {
97
97
  .trim();
98
98
  }
99
99
 
100
- function summarizeOutputBytes(bytes) {
101
- const start = Math.max(0, bytes.byteLength - OUTPUT_SUMMARY_BYTES);
102
- let text = bytes.subarray(start).toString("utf8");
103
- if (start > 0) {
104
- const firstLineBreak = text.indexOf("\n");
105
- if (firstLineBreak >= 0) text = text.slice(firstLineBreak + 1);
106
- }
107
- const lines = text
100
+ function cleanOutputLines(text) {
101
+ return text
108
102
  .split(/\r?\n/u)
109
103
  .map(cleanOutputLine)
110
104
  .filter(Boolean);
105
+ }
106
+
107
+ function summarizeOutputBytes(bytes) {
108
+ if (bytes.byteLength <= OUTPUT_SUMMARY_BYTES) {
109
+ const lines = cleanOutputLines(bytes.toString("utf8"));
110
+ return {
111
+ headLines: lines.slice(0, OUTPUT_SUMMARY_LINES),
112
+ tailLines: lines.slice(-OUTPUT_SUMMARY_LINES),
113
+ truncated: lines.length > OUTPUT_SUMMARY_LINES * 2,
114
+ };
115
+ }
116
+
117
+ const windowBytes = Math.floor(OUTPUT_SUMMARY_BYTES / 2);
118
+ let headText = bytes.subarray(0, windowBytes).toString("utf8");
119
+ const lastHeadBreak = headText.lastIndexOf("\n");
120
+ if (lastHeadBreak >= 0) headText = headText.slice(0, lastHeadBreak + 1);
121
+
122
+ let tailText = bytes.subarray(bytes.byteLength - windowBytes).toString("utf8");
123
+ const firstTailBreak = tailText.indexOf("\n");
124
+ if (firstTailBreak >= 0) tailText = tailText.slice(firstTailBreak + 1);
125
+
111
126
  return {
112
- lines: lines.slice(-OUTPUT_SUMMARY_LINES),
113
- truncated: start > 0 || lines.length > OUTPUT_SUMMARY_LINES,
127
+ headLines: cleanOutputLines(headText).slice(0, OUTPUT_SUMMARY_LINES),
128
+ tailLines: cleanOutputLines(tailText).slice(-OUTPUT_SUMMARY_LINES),
129
+ truncated: true,
114
130
  };
115
131
  }
116
132
 
@@ -145,10 +161,59 @@ function validateQuickReceiptStore(workspaceRoot, store) {
145
161
  assertStorePath(root, store.receiptRoot, store.receiptRootIdentity, "directory");
146
162
  assertStorePath(root, store.stdoutPath, store.stdoutIdentity, "file");
147
163
  assertStorePath(root, store.stderrPath, store.stderrIdentity, "file");
164
+ if (store.stdinPath !== undefined) {
165
+ assertStorePath(root, store.stdinPath, store.stdinIdentity, "file");
166
+ const bytes = readFileSync(store.stdinPath);
167
+ if (
168
+ bytes.byteLength !== store.stdinArtifact.sizeBytes
169
+ || sha256Bytes(bytes) !== store.stdinArtifact.sha256
170
+ ) {
171
+ throw new Error(`Quick receipt store stdin material changed: ${store.stdinPath}`);
172
+ }
173
+ }
174
+ }
175
+
176
+ export function persistQuickInputArtifact({ workspaceRoot, store, bytes }) {
177
+ if (!Buffer.isBuffer(bytes)) throw new Error("Quick stdin material must be bytes.");
178
+ validateQuickReceiptStore(workspaceRoot, store);
179
+ const stdinPath = path.join(store.receiptRoot, "stdin.bin");
180
+ writeFileSync(stdinPath, bytes, { flag: "wx", mode: 0o600 });
181
+ const stat = lstatSync(stdinPath);
182
+ if (stat.isSymbolicLink() || !stat.isFile()) {
183
+ throw new Error(`Quick receipt store stdin material is not trusted: ${stdinPath}`);
184
+ }
185
+ const root = realpathSync(workspaceRoot);
186
+ const resolved = realpathSync(stdinPath);
187
+ if (!withinRoot(root, resolved)) {
188
+ throw new Error(`Quick receipt store stdin material escapes the workspace: ${stdinPath}`);
189
+ }
190
+ store.stdinPath = stdinPath;
191
+ store.stdinIdentity = { dev: stat.dev, ino: stat.ino };
192
+ store.stdinArtifact = {
193
+ path: path.relative(root, resolved).split(path.sep).join("/"),
194
+ sha256: sha256Bytes(bytes),
195
+ sizeBytes: bytes.byteLength,
196
+ };
197
+ return {
198
+ artifact: store.stdinArtifact,
199
+ inputPath: stdinPath,
200
+ };
148
201
  }
149
202
 
150
203
  export function persistQuickReceipt({ workspaceRoot, store, receipt }) {
151
204
  validateQuickReceiptStore(workspaceRoot, store);
205
+ const receiptStdin = receipt.inputArtifacts?.stdin;
206
+ if (
207
+ (store.stdinArtifact === undefined) !== (receiptStdin === undefined)
208
+ || store.stdinArtifact !== undefined
209
+ && (
210
+ receiptStdin.path !== store.stdinArtifact.path
211
+ || receiptStdin.sha256 !== store.stdinArtifact.sha256
212
+ || receiptStdin.sizeBytes !== store.stdinArtifact.sizeBytes
213
+ )
214
+ ) {
215
+ throw new Error("Quick receipt stdin binding does not match the persisted material.");
216
+ }
152
217
  const stdout = outputArtifact(workspaceRoot, store.stdoutPath);
153
218
  const stderr = outputArtifact(workspaceRoot, store.stderrPath);
154
219
  const complete = {
@@ -164,8 +229,10 @@ export function persistQuickReceipt({ workspaceRoot, store, receipt }) {
164
229
  receiptPath: store.receiptPath,
165
230
  receiptSha256: sha256Bytes(readFileSync(store.receiptPath)),
166
231
  outputSummary: {
167
- stdoutTail: stdout.summary.lines,
168
- stderrTail: stderr.summary.lines,
232
+ stdoutHead: stdout.summary.headLines,
233
+ stdoutTail: stdout.summary.tailLines,
234
+ stderrHead: stderr.summary.headLines,
235
+ stderrTail: stderr.summary.tailLines,
169
236
  stdoutTruncated: stdout.summary.truncated,
170
237
  stderrTruncated: stderr.summary.truncated,
171
238
  },
@@ -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";
@@ -14,18 +22,34 @@ function shellQuote(value) {
14
22
  }
15
23
 
16
24
  function quickAttestCommand(workspaceRoot, receiptPath) {
17
- return `owlrunkit quick-attest --workspace ${shellQuote(workspaceRoot)} --receipt ${shellQuote(receiptPath)}`;
25
+ return `npx --no-install 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: [],
@@ -22,6 +22,10 @@ function comparablePath(value) {
22
22
  return existsSync(resolved) ? realpathSync(resolved) : resolved;
23
23
  }
24
24
 
25
+ function shellQuote(value) {
26
+ return `'${String(value).replaceAll("'", `'"'"'`)}'`;
27
+ }
28
+
25
29
  function workspaceFromArgv(argv, cwd) {
26
30
  const index = argv.indexOf("--workspace");
27
31
  if (index < 0) return path.resolve(cwd);
@@ -103,7 +107,8 @@ export function runBootstrapV1({
103
107
  `project_local_cli_unavailable:${selected.binding.issueCodes.join(",")}.`,
104
108
  "The current/global package did not execute this project command.",
105
109
  "Repair the exact dependency, lockfile, and local install binding,",
106
- `or use the bootstrap recovery path: owlrunkit init --workspace ${selected.workspaceRoot}`,
110
+ "or use the bootstrap recovery path: npx --no-install owlrunkit init "
111
+ + `--workspace ${shellQuote(selected.workspaceRoot)}`,
107
112
  ].join(" "));
108
113
  }
109
114
  const commandArgv = selected.commandArgv ?? [