owlrunkit 0.18.1 → 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 (32) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +85 -19
  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 +78 -4
  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 +12 -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 +21 -2
  18. package/registry-release-policy-v1.json +5 -5
  19. package/sbom.spdx.json +5 -5
  20. package/scripts/runkit-contract/assurance-router.mjs +3 -1
  21. package/scripts/runkit-contract/core-contract.mjs +2 -1
  22. package/scripts/runkit-contract/onboarding-doctor.mjs +46 -18
  23. package/scripts/runkit-contract/profile-onboarding.mjs +4 -0
  24. package/scripts/runkit-contract/project-cli-resolver.mjs +3 -0
  25. package/scripts/runkit-contract/quick-metrics.mjs +3 -3
  26. package/scripts/runkit-contract/quick-receipt.mjs +110 -5
  27. package/scripts/runkit-contract/quick-verify.mjs +93 -11
  28. package/scripts/runkit-contract/runkit-cli.mjs +172 -24
  29. package/scripts/runkit-contract/schemas/profile-reconcile-plan-v1.schema.json +2 -0
  30. package/scripts/runkit-contract/schemas/team-project-event-v2.schema.json +128 -0
  31. package/scripts/runkit-contract/team-project.mjs +310 -45
  32. package/scripts/runkit-contract/usage-mode.mjs +11 -13
@@ -0,0 +1,232 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://owlcoda.dev/schemas/runkit/trust/quick-verification-receipt-v2.schema.json",
4
+ "title": "OwlCoda Quick Verification Receipt V2",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schemaVersion",
9
+ "receiptId",
10
+ "assurance",
11
+ "authorizationGranted",
12
+ "coreIdentity",
13
+ "workspaceBefore",
14
+ "exactCommand",
15
+ "inputArtifacts",
16
+ "verificationContext",
17
+ "startedAt",
18
+ "finishedAt",
19
+ "exitResult",
20
+ "outputArtifacts",
21
+ "workspaceAfter",
22
+ "mutationDecision",
23
+ "issueCodes"
24
+ ],
25
+ "properties": {
26
+ "schemaVersion": {
27
+ "const": "OwlCodaQuickVerificationReceiptV2"
28
+ },
29
+ "receiptId": {
30
+ "type": "string",
31
+ "minLength": 1
32
+ },
33
+ "assurance": {
34
+ "const": "captured_verification"
35
+ },
36
+ "authorizationGranted": {
37
+ "const": false
38
+ },
39
+ "coreIdentity": {
40
+ "type": "object",
41
+ "additionalProperties": false,
42
+ "required": [
43
+ "contractVersion",
44
+ "coreVersion",
45
+ "coreManifestSha256"
46
+ ],
47
+ "properties": {
48
+ "contractVersion": {
49
+ "type": "string",
50
+ "minLength": 1
51
+ },
52
+ "coreVersion": {
53
+ "type": "string",
54
+ "minLength": 1
55
+ },
56
+ "coreManifestSha256": {
57
+ "type": "string",
58
+ "pattern": "^sha256:[0-9a-f]{64}$"
59
+ }
60
+ }
61
+ },
62
+ "workspaceBefore": {
63
+ "$ref": "workspace-snapshot-v1.schema.json"
64
+ },
65
+ "exactCommand": {
66
+ "type": "object",
67
+ "additionalProperties": false,
68
+ "required": [
69
+ "executable",
70
+ "argv",
71
+ "cwd"
72
+ ],
73
+ "properties": {
74
+ "executable": {
75
+ "type": "string",
76
+ "minLength": 1
77
+ },
78
+ "argv": {
79
+ "type": "array",
80
+ "items": {
81
+ "type": "string"
82
+ }
83
+ },
84
+ "cwd": {
85
+ "type": "string",
86
+ "minLength": 1
87
+ }
88
+ }
89
+ },
90
+ "inputArtifacts": {
91
+ "type": "object",
92
+ "additionalProperties": false,
93
+ "required": [
94
+ "stdin"
95
+ ],
96
+ "properties": {
97
+ "stdin": {
98
+ "$ref": "#/$defs/materialArtifact"
99
+ }
100
+ }
101
+ },
102
+ "verificationContext": {
103
+ "type": "object",
104
+ "additionalProperties": false,
105
+ "required": [
106
+ "platform",
107
+ "architecture",
108
+ "runtime"
109
+ ],
110
+ "properties": {
111
+ "platform": {
112
+ "type": "string",
113
+ "minLength": 1
114
+ },
115
+ "architecture": {
116
+ "type": "string",
117
+ "minLength": 1
118
+ },
119
+ "runtime": {
120
+ "type": "string",
121
+ "minLength": 1
122
+ }
123
+ }
124
+ },
125
+ "startedAt": {
126
+ "type": "string",
127
+ "format": "date-time"
128
+ },
129
+ "finishedAt": {
130
+ "type": "string",
131
+ "format": "date-time"
132
+ },
133
+ "exitResult": {
134
+ "type": "object",
135
+ "additionalProperties": false,
136
+ "required": [
137
+ "exitCode",
138
+ "signal"
139
+ ],
140
+ "properties": {
141
+ "exitCode": {
142
+ "type": [
143
+ "integer",
144
+ "null"
145
+ ]
146
+ },
147
+ "signal": {
148
+ "type": [
149
+ "string",
150
+ "null"
151
+ ]
152
+ }
153
+ }
154
+ },
155
+ "outputArtifacts": {
156
+ "type": "object",
157
+ "additionalProperties": false,
158
+ "required": [
159
+ "stdout",
160
+ "stderr"
161
+ ],
162
+ "properties": {
163
+ "stdout": {
164
+ "$ref": "#/$defs/materialArtifact"
165
+ },
166
+ "stderr": {
167
+ "$ref": "#/$defs/materialArtifact"
168
+ }
169
+ }
170
+ },
171
+ "workspaceAfter": {
172
+ "$ref": "workspace-snapshot-v1.schema.json"
173
+ },
174
+ "mutationDecision": {
175
+ "enum": [
176
+ "source_unchanged",
177
+ "invalidated_by_command_source_mutation"
178
+ ]
179
+ },
180
+ "issueCodes": {
181
+ "type": "array",
182
+ "uniqueItems": true,
183
+ "items": {
184
+ "type": "string",
185
+ "minLength": 1
186
+ }
187
+ },
188
+ "signatureRef": {
189
+ "type": "object",
190
+ "additionalProperties": false,
191
+ "required": [
192
+ "path",
193
+ "sha256"
194
+ ],
195
+ "properties": {
196
+ "path": {
197
+ "type": "string",
198
+ "minLength": 1
199
+ },
200
+ "sha256": {
201
+ "type": "string",
202
+ "pattern": "^sha256:[0-9a-f]{64}$"
203
+ }
204
+ }
205
+ }
206
+ },
207
+ "$defs": {
208
+ "materialArtifact": {
209
+ "type": "object",
210
+ "additionalProperties": false,
211
+ "required": [
212
+ "path",
213
+ "sha256",
214
+ "sizeBytes"
215
+ ],
216
+ "properties": {
217
+ "path": {
218
+ "type": "string",
219
+ "minLength": 1
220
+ },
221
+ "sha256": {
222
+ "type": "string",
223
+ "pattern": "^sha256:[0-9a-f]{64}$"
224
+ },
225
+ "sizeBytes": {
226
+ "type": "integer",
227
+ "minimum": 0
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
@@ -41,7 +41,10 @@ function readSubject(subjectPath) {
41
41
 
42
42
  export function attestFile({ subjectPath, workspaceRoot }) {
43
43
  const subject = readSubject(subjectPath);
44
- if (subject.value.schemaVersion === "OwlCodaQuickVerificationReceiptV1") {
44
+ if (new Set([
45
+ "OwlCodaQuickVerificationReceiptV1",
46
+ "OwlCodaQuickVerificationReceiptV2",
47
+ ]).has(subject.value.schemaVersion)) {
45
48
  const details = attestQuickReceiptDetailsFromBytes({
46
49
  receiptPath: subject.absolutePath,
47
50
  receiptBytes: subject.bytes,
@@ -110,10 +110,14 @@ function validOutputArtifact(value) {
110
110
  }
111
111
 
112
112
  export function validQuickReceiptShape(receipt) {
113
- if (!hasExactKeys(receipt, RECEIPT_REQUIRED_KEYS, ["signatureRef"])) return false;
113
+ const receiptV1 = receipt?.schemaVersion === "OwlCodaQuickVerificationReceiptV1";
114
+ const receiptV2 = receipt?.schemaVersion === "OwlCodaQuickVerificationReceiptV2";
115
+ const requiredKeys = receiptV2
116
+ ? [...RECEIPT_REQUIRED_KEYS, "inputArtifacts"]
117
+ : RECEIPT_REQUIRED_KEYS;
118
+ if (!(receiptV1 || receiptV2) || !hasExactKeys(receipt, requiredKeys, ["signatureRef"])) return false;
114
119
  if (
115
- receipt.schemaVersion !== "OwlCodaQuickVerificationReceiptV1"
116
- || typeof receipt.receiptId !== "string"
120
+ typeof receipt.receiptId !== "string"
117
121
  || receipt.receiptId.length === 0
118
122
  || receipt.assurance !== "captured_verification"
119
123
  || receipt.authorizationGranted !== false
@@ -145,6 +149,12 @@ export function validQuickReceiptShape(receipt) {
145
149
  ) {
146
150
  return false;
147
151
  }
152
+ if (receiptV2 && (
153
+ !hasExactKeys(receipt.inputArtifacts, ["stdin"])
154
+ || !validOutputArtifact(receipt.inputArtifacts.stdin)
155
+ )) {
156
+ return false;
157
+ }
148
158
  if (receipt.signatureRef !== undefined) {
149
159
  if (!hasExactKeys(receipt.signatureRef, ["path", "sha256"])
150
160
  || typeof receipt.signatureRef.path !== "string"
@@ -18,6 +18,16 @@ import { captureWorkspaceSnapshot } from "./workspace-snapshot.mjs";
18
18
  export { validQuickReceiptShape } from "./quick-receipt-contract.mjs";
19
19
 
20
20
  export const SUPPORTED_QUICK_CORE_IDENTITIES = Object.freeze([
21
+ {
22
+ contractVersion: "0.2",
23
+ coreVersion: "0.18.3",
24
+ coreManifestSha256: "sha256:cc7a923649592084150828f24f0d90f280af92514bafdbc4999f4015b3175d5c",
25
+ },
26
+ {
27
+ contractVersion: "0.2",
28
+ coreVersion: "0.18.2",
29
+ coreManifestSha256: "sha256:abe17ff794b4019d8d476f09eb5d4105bae1070b1df0aab53e6c94c7ec8b65a6",
30
+ },
21
31
  {
22
32
  contractVersion: "0.2",
23
33
  coreVersion: "0.18.1",
@@ -189,7 +199,11 @@ export function attestQuickReceiptDetailsFromBytes({
189
199
  throw error;
190
200
  }
191
201
 
192
- const issues = [...receipt.issueCodes, "signature_absent", "anchor_absent"];
202
+ const issues = [
203
+ ...receipt.issueCodes.filter((issue) => issue !== "quick_ignored_artifact_unbound"),
204
+ "signature_absent",
205
+ "anchor_absent",
206
+ ];
193
207
  const materials = [];
194
208
  let materialMissing = false;
195
209
  let materialMismatch = false;
@@ -228,7 +242,12 @@ export function attestQuickReceiptDetailsFromBytes({
228
242
  const commandWorkspaceMatches = selectedWorkspaceRoot !== undefined
229
243
  && receiptWorkspaceRoot === selectedWorkspaceRoot;
230
244
  if (commandWorkspaceMatches) {
231
- for (const artifact of [receipt.outputArtifacts.stdout, receipt.outputArtifacts.stderr]) {
245
+ const boundArtifacts = [
246
+ ...(receipt.inputArtifacts === undefined ? [] : [receipt.inputArtifacts.stdin]),
247
+ receipt.outputArtifacts.stdout,
248
+ receipt.outputArtifacts.stderr,
249
+ ];
250
+ for (const artifact of boundArtifacts) {
232
251
  try {
233
252
  const materialPath = resolveBoundMaterial(receiptWorkspaceRoot, artifact.path);
234
253
  const { bytes } = readFileBytesBounded(materialPath);
@@ -2,7 +2,7 @@
2
2
  "schemaVersion": "OwlCodaRunKitRegistryReleasePolicyV1",
3
3
  "status": "release_candidate_unpublished",
4
4
  "packageName": "owlrunkit",
5
- "candidateVersion": "0.18.1",
5
+ "candidateVersion": "0.18.3",
6
6
  "registry": "https://registry.npmjs.org",
7
7
  "registryRequiredBeforeAdoption": true,
8
8
  "exactVersionRequired": true,
@@ -23,10 +23,10 @@
23
23
  ],
24
24
  "currentPublishedRelease": {
25
25
  "packageName": "owlrunkit",
26
- "version": "0.18.0",
27
- "shasum": "ab2d9c9ed81f9dcccd4c1affa519cfca1cc32032",
28
- "integrity": "sha512-asi4CKofzjzQ9gGxnv6/NDCM6rZcMMqpwd4uRStfUUwDetFLYHEPDMBv1JGvYotdUwwoODxwdJ3KMGXQSYorgA==",
29
- "tarballUrl": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.18.0.tgz"
26
+ "version": "0.18.2",
27
+ "shasum": "4a85e31dad306260e4a6b1fcbccb3807e8647a0a",
28
+ "integrity": "sha512-Clpr8UQdNitzMMmQHUtjs9mesmukUqZrQ5nrda+Ryo8SuvECH8eBiis378NnzV1lI79kmljv49ToRRe867zlBg==",
29
+ "tarballUrl": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.18.2.tgz"
30
30
  },
31
31
  "registryRelease": null,
32
32
  "registryEvidenceMustBeExternal": true,
package/sbom.spdx.json CHANGED
@@ -2,8 +2,8 @@
2
2
  "spdxVersion": "SPDX-2.3",
3
3
  "dataLicense": "CC0-1.0",
4
4
  "SPDXID": "SPDXRef-DOCUMENT",
5
- "name": "owlrunkit-0.18.1",
6
- "documentNamespace": "https://owlcoda.com/spdx/owlrunkit/0.18.1",
5
+ "name": "owlrunkit-0.18.3",
6
+ "documentNamespace": "https://owlcoda.com/spdx/owlrunkit/0.18.3",
7
7
  "creationInfo": {
8
8
  "created": "2026-07-29T00:00:00Z",
9
9
  "creators": [
@@ -14,8 +14,8 @@
14
14
  {
15
15
  "name": "owlrunkit",
16
16
  "SPDXID": "SPDXRef-Package-OwlRunKit",
17
- "versionInfo": "0.18.1",
18
- "downloadLocation": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.18.1.tgz",
17
+ "versionInfo": "0.18.3",
18
+ "downloadLocation": "https://registry.npmjs.org/owlrunkit/-/owlrunkit-0.18.3.tgz",
19
19
  "filesAnalyzed": false,
20
20
  "licenseConcluded": "GPL-3.0-or-later",
21
21
  "licenseDeclared": "GPL-3.0-or-later",
@@ -24,7 +24,7 @@
24
24
  {
25
25
  "referenceCategory": "PACKAGE-MANAGER",
26
26
  "referenceType": "purl",
27
- "referenceLocator": "pkg:npm/owlrunkit@0.18.1"
27
+ "referenceLocator": "pkg:npm/owlrunkit@0.18.3"
28
28
  }
29
29
  ]
30
30
  }
@@ -14,7 +14,7 @@ const BOOLEAN_FACTS = [
14
14
  "schemaOrDataMigration",
15
15
  ];
16
16
 
17
- const RISK_CATEGORIES = new Set([
17
+ export const RUNKIT_RISK_CATEGORIES = Object.freeze([
18
18
  "backtest",
19
19
  "deployment",
20
20
  "destructive",
@@ -26,6 +26,8 @@ const RISK_CATEGORIES = new Set([
26
26
  "release",
27
27
  ]);
28
28
 
29
+ const RISK_CATEGORIES = new Set(RUNKIT_RISK_CATEGORIES);
30
+
29
31
  const MATERIAL_RISK_CATEGORIES = new Set([
30
32
  "destructive",
31
33
  "foreign_write",
@@ -14,7 +14,7 @@ import { fileURLToPath } from "node:url";
14
14
  import { parseProjectControlState } from "./project-control-parser.mjs";
15
15
 
16
16
  export const CONTRACT_VERSION = "0.2";
17
- export const CORE_VERSION = "0.18.1";
17
+ export const CORE_VERSION = "0.18.3";
18
18
  export const RUNTIME_ROOT = ".owlcoda/runkit";
19
19
 
20
20
  const CORE_FILES = [
@@ -126,6 +126,7 @@ const CORE_FILES = [
126
126
  "schemas/verification-context-v1.schema.json",
127
127
  "schemas/team-project-definition-v1.schema.json",
128
128
  "schemas/team-project-event-v1.schema.json",
129
+ "schemas/team-project-event-v2.schema.json",
129
130
  "schemas/team-project-successor-receipt-v1.schema.json",
130
131
  "schemas/team-project-status-v1.schema.json",
131
132
  "schemas/usage-mode-recommendation-v1.schema.json",
@@ -190,11 +190,16 @@ function parseJsonStrict(text) {
190
190
  export function resolveBoundedWorkspaceRoot(workspaceRoot) {
191
191
  const requested = path.resolve(workspaceRoot);
192
192
  const stat = lstatSync(requested);
193
- if (
194
- stat.isSymbolicLink()
195
- || !stat.isDirectory()
196
- || realpathSync(requested) !== requested
197
- ) {
193
+ const resolved = realpathSync(requested);
194
+ if ((stat.isSymbolicLink() || resolved !== requested)
195
+ && lstatSync(resolved).isDirectory()) {
196
+ const quoted = `'${resolved.replaceAll("'", `'"'"'`)}'`;
197
+ throw new Error(
198
+ "workspace root must be a real directory without symlink ancestors. "
199
+ + `Retry with --workspace ${quoted}.`,
200
+ );
201
+ }
202
+ if (!stat.isDirectory()) {
198
203
  throw new Error("workspace root must be a real directory without symlink ancestors");
199
204
  }
200
205
  return requested;
@@ -317,28 +322,51 @@ export function readLocalInstallBinding({ workspaceRoot } = {}) {
317
322
  };
318
323
  }
319
324
 
325
+ function registryTransportFailure(error) {
326
+ const code = error?.cause?.code ?? error?.code ?? null;
327
+ if (error?.name === "TimeoutError"
328
+ || error?.name === "AbortError"
329
+ || code === "ETIMEDOUT") {
330
+ return { issueCode: "registry_timeout", retryable: true };
331
+ }
332
+ if (code === "ENOTFOUND" || code === "EAI_AGAIN") {
333
+ return { issueCode: "registry_dns_failed", retryable: true };
334
+ }
335
+ if (code === "ERR_INVALID_URL") {
336
+ return { issueCode: "registry_url_invalid", retryable: false };
337
+ }
338
+ return { issueCode: "registry_connection_failed", retryable: true };
339
+ }
340
+
320
341
  export async function readRegistryExact({
321
342
  registryUrl,
322
343
  packageName = PACKAGE_NAME,
323
344
  version = EXPECTED_VERSION,
324
345
  timeoutMs = 1_500,
346
+ fetchImpl = fetch,
325
347
  } = {}) {
326
348
  const base = registryUrl.replace(/\/+$/, "");
327
349
  const url = `${base}/${encodeURIComponent(packageName)}/${encodeURIComponent(version)}`;
328
350
  let response;
329
- try {
330
- response = await fetch(url, {
331
- headers: {
332
- accept: "application/json",
333
- },
334
- redirect: "manual",
335
- signal: AbortSignal.timeout(timeoutMs),
336
- });
337
- } catch {
338
- return {
339
- status: "unavailable",
340
- issueCodes: ["registry_dns_or_timeout"],
341
- };
351
+ for (let attempt = 0; attempt < 2; attempt += 1) {
352
+ try {
353
+ response = await fetchImpl(url, {
354
+ headers: {
355
+ accept: "application/json",
356
+ },
357
+ redirect: "manual",
358
+ signal: AbortSignal.timeout(timeoutMs),
359
+ });
360
+ break;
361
+ } catch (error) {
362
+ const failure = registryTransportFailure(error);
363
+ if (!failure.retryable || attempt === 1) {
364
+ return {
365
+ status: "unavailable",
366
+ issueCodes: [failure.issueCode],
367
+ };
368
+ }
369
+ }
342
370
  }
343
371
  if (response.status === 401 || response.status === 403) {
344
372
  return {
@@ -1511,10 +1511,14 @@ export function reconcileProfilesV2({
1511
1511
  }
1512
1512
  const proposedProfilesBytes = `${JSON.stringify(merged.proposedProfiles, null, 2)}\n`;
1513
1513
  const proposedProfilesSha256 = sha256(proposedProfilesBytes);
1514
+ const normalizationOnly = proposedProfilesSha256 !== currentProfilesSha256
1515
+ && merged.addedProfileIds.length === 0
1516
+ && merged.updatedProfiles.length === 0;
1514
1517
  const planBody = {
1515
1518
  detectionSha256: detection.detectionSha256,
1516
1519
  currentProfilesSha256,
1517
1520
  proposedProfilesSha256,
1521
+ normalizationOnly,
1518
1522
  addedProfileIds: merged.addedProfileIds,
1519
1523
  updatedProfiles: merged.updatedProfiles,
1520
1524
  };
@@ -18,6 +18,9 @@ const OFFICIAL_CLI_ENTRYPOINT =
18
18
  const EXACT_VERSION = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?$/;
19
19
  const SHA256_REF = /^sha256:[a-f0-9]{64}$/;
20
20
  const TRUSTED_PRIOR_CORE_IDENTITIES = new Map([
21
+ ["0.18.1", new Set([
22
+ "sha256:349b4157d3d089462b172de1619ccd169b5c1669b9322e2580ac6ec4f8616b07",
23
+ ])],
21
24
  ["0.18.0", new Set([
22
25
  "sha256:72c481dbafe06a9c56cd940d74a3fe109a82b73a3c43d0bb54923ea6c584c04e",
23
26
  ])],
@@ -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
  };