@farmslot/recipe-runner 0.29.0 → 0.30.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 (95) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/adapters/ui.d.ts +2 -0
  3. package/dist/adapters/ui.d.ts.map +1 -1
  4. package/dist/adapters/ui.js +79 -37
  5. package/dist/adapters/ui.js.map +1 -1
  6. package/dist/cli/support.d.ts.map +1 -1
  7. package/dist/cli/support.js +5 -1
  8. package/dist/cli/support.js.map +1 -1
  9. package/dist/core/execution.d.ts +3 -0
  10. package/dist/core/execution.d.ts.map +1 -1
  11. package/dist/core/execution.js +60 -3
  12. package/dist/core/execution.js.map +1 -1
  13. package/dist/core/graph.d.ts +1 -0
  14. package/dist/core/graph.d.ts.map +1 -1
  15. package/dist/core/graph.js +2 -2
  16. package/dist/core/graph.js.map +1 -1
  17. package/dist/core/hud.d.ts.map +1 -1
  18. package/dist/core/hud.js +3 -3
  19. package/dist/core/hud.js.map +1 -1
  20. package/dist/core/invocation.d.ts +4 -1
  21. package/dist/core/invocation.d.ts.map +1 -1
  22. package/dist/core/invocation.js +3 -1
  23. package/dist/core/invocation.js.map +1 -1
  24. package/dist/core/recording-limits.d.ts +4 -0
  25. package/dist/core/recording-limits.d.ts.map +1 -0
  26. package/dist/core/recording-limits.js +74 -0
  27. package/dist/core/recording-limits.js.map +1 -0
  28. package/dist/core/recording-segments.d.ts +4 -0
  29. package/dist/core/recording-segments.d.ts.map +1 -0
  30. package/dist/core/recording-segments.js +101 -0
  31. package/dist/core/recording-segments.js.map +1 -0
  32. package/dist/core/runner.d.ts.map +1 -1
  33. package/dist/core/runner.js +335 -108
  34. package/dist/core/runner.js.map +1 -1
  35. package/dist/core/types.d.ts +37 -22
  36. package/dist/core/types.d.ts.map +1 -1
  37. package/dist/evidence/assertions.d.ts +50 -0
  38. package/dist/evidence/assertions.d.ts.map +1 -0
  39. package/dist/evidence/assertions.js +156 -0
  40. package/dist/evidence/assertions.js.map +1 -0
  41. package/dist/evidence/claims.d.ts +15 -0
  42. package/dist/evidence/claims.d.ts.map +1 -0
  43. package/dist/evidence/claims.js +201 -0
  44. package/dist/evidence/claims.js.map +1 -0
  45. package/dist/evidence/index.d.ts +4 -0
  46. package/dist/evidence/index.d.ts.map +1 -0
  47. package/dist/evidence/index.js +3 -0
  48. package/dist/evidence/index.js.map +1 -0
  49. package/dist/evidence/moments.d.ts +8 -0
  50. package/dist/evidence/moments.d.ts.map +1 -0
  51. package/dist/evidence/moments.js +26 -0
  52. package/dist/evidence/moments.js.map +1 -0
  53. package/dist/evidence/package.d.ts +4 -0
  54. package/dist/evidence/package.d.ts.map +1 -0
  55. package/dist/evidence/package.js +140 -0
  56. package/dist/evidence/package.js.map +1 -0
  57. package/dist/evidence/plan.d.ts +9 -0
  58. package/dist/evidence/plan.d.ts.map +1 -0
  59. package/dist/evidence/plan.js +87 -0
  60. package/dist/evidence/plan.js.map +1 -0
  61. package/dist/evidence/read-package.d.ts +14 -0
  62. package/dist/evidence/read-package.d.ts.map +1 -0
  63. package/dist/evidence/read-package.js +153 -0
  64. package/dist/evidence/read-package.js.map +1 -0
  65. package/dist/evidence/stills.d.ts +5 -0
  66. package/dist/evidence/stills.d.ts.map +1 -0
  67. package/dist/evidence/stills.js +58 -0
  68. package/dist/evidence/stills.js.map +1 -0
  69. package/dist/file-digest.d.ts +3 -0
  70. package/dist/file-digest.d.ts.map +1 -0
  71. package/dist/file-digest.js +4 -0
  72. package/dist/file-digest.js.map +1 -0
  73. package/dist/index.d.ts +5 -0
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +5 -0
  76. package/dist/index.js.map +1 -1
  77. package/dist/recording/android-mirror.d.ts.map +1 -1
  78. package/dist/recording/android-mirror.js +17 -8
  79. package/dist/recording/android-mirror.js.map +1 -1
  80. package/dist/recording/capture-helper-timing.d.ts +2 -2
  81. package/dist/recording/capture-helper-timing.d.ts.map +1 -1
  82. package/dist/recording/capture-helper.d.ts.map +1 -1
  83. package/dist/recording/capture-helper.js +24 -12
  84. package/dist/recording/capture-helper.js.map +1 -1
  85. package/dist/recording/cdp-video-recorder.d.ts +2 -0
  86. package/dist/recording/cdp-video-recorder.d.ts.map +1 -1
  87. package/dist/recording/cdp-video-recorder.js +160 -50
  88. package/dist/recording/cdp-video-recorder.js.map +1 -1
  89. package/dist/recording/timeline.d.ts +2 -2
  90. package/dist/recording/timeline.d.ts.map +1 -1
  91. package/dist/runtime/cdp.d.ts +1 -0
  92. package/dist/runtime/cdp.d.ts.map +1 -1
  93. package/dist/runtime/cdp.js +71 -16
  94. package/dist/runtime/cdp.js.map +1 -1
  95. package/package.json +8 -3
@@ -0,0 +1,201 @@
1
+ import { digestRecipeDocument, normalizeRecipeClaimId, validateRecipeClaimDeclarations, } from '@farmslot/protocol';
2
+ import { reachableNodes } from '../core/graph.js';
3
+ import { executedProofIndices, qualifyProofNodeRef, } from './assertions.js';
4
+ import { occurrenceRecordingCoverage } from './moments.js';
5
+ const parentVerdictOrder = [
6
+ 'failed',
7
+ 'missing',
8
+ 'weak',
9
+ 'awaiting-review',
10
+ 'untestable',
11
+ ];
12
+ /** Successful actions/captures are evidence, never the assertion that proves a claim. */
13
+ export function deriveRecipeClaims(input) {
14
+ const validation = validateRecipeClaimDeclarations(input.declarations);
15
+ if (validation.status !== 'valid')
16
+ throw new Error(validation.findings.map((finding) => finding.message).join('\n'));
17
+ const excluded = unselectedProofNodes(input.nodes, input.trace);
18
+ const claims = input.declarations.map((declaration) => {
19
+ const id = normalizeRecipeClaimId(declaration.id);
20
+ const recipeNodes = [...input.nodes]
21
+ .filter(([nodeId, node]) => !excluded.has(nodeId) &&
22
+ node.proves?.some((claim) => normalizeRecipeClaimId(claim) === id))
23
+ .map(([nodeId]) => nodeId);
24
+ // Only declared retry groups may replace an earlier result. Repeated ordinary
25
+ // occurrences remain required, so their failure cannot disappear.
26
+ const required = new Map();
27
+ for (const nodeId of recipeNodes) {
28
+ const node = input.nodes.get(nodeId);
29
+ const group = typeof node.retryGroup === 'string'
30
+ ? qualifyProofNodeRef(nodeId, `retry:${node.retryGroup}`)
31
+ : nodeId;
32
+ const occurrences = input.trace.flatMap((entry, index) => {
33
+ if ((entry.nodeId ?? entry.id) !== nodeId)
34
+ return [];
35
+ const eligible = executedProofIndices(nodeId, input.nodes, input.trace, input.artifacts, index + 1);
36
+ return eligible.length ? eligible : [null];
37
+ });
38
+ const prior = required.get(group) ?? [];
39
+ required.set(group, [...prior, ...(occurrences.length ? occurrences : [null])]);
40
+ }
41
+ const indices = [...required].flatMap(([group, values]) => group.includes('retry:')
42
+ ? values.at(-1) === null
43
+ ? [null]
44
+ : [
45
+ values
46
+ .filter((index) => index !== null)
47
+ .sort((a, b) => a - b)
48
+ .at(-1) ?? null,
49
+ ]
50
+ : values);
51
+ const assertionIndices = [
52
+ ...new Set(indices.filter((index) => index !== null)),
53
+ ];
54
+ const uiProof = assertionIndices.some((index) => input.trace[index]?.action.startsWith('ui.')) ||
55
+ recipeNodes.some((nodeId) => [...input.nodes].some(([id, node]) => (id === nodeId || id.startsWith(`${nodeId}/`)) && node.action.startsWith('ui.')));
56
+ const proofMode = declaration.proofMode ?? (uiProof ? 'visual' : 'state');
57
+ const momentData = assertionIndices.map((traceIndex) => ({
58
+ traceIndex,
59
+ ...occurrenceRecordingCoverage(traceIndex, input.segments, input.timelines),
60
+ }));
61
+ const timing = !input.segments.length || momentData.some((moment) => moment.timing === 'outside-recording')
62
+ ? 'outside-recording'
63
+ : momentData.some((moment) => moment.timing === 'untimed')
64
+ ? 'untimed'
65
+ : 'measured';
66
+ let verdict;
67
+ if (assertionIndices.some((index) => input.trace[index]?.ok === false))
68
+ verdict = 'failed';
69
+ else if (!recipeNodes.length || indices.some((index) => index === null))
70
+ verdict = 'missing';
71
+ else if (proofMode !== 'state' && timing === 'outside-recording')
72
+ verdict = 'weak';
73
+ else
74
+ verdict = proofMode === 'state' ? 'proven' : 'awaiting-review';
75
+ const assertionNodes = new Set(assertionIndices.map((index) => input.trace[index]?.nodeId ?? input.trace[index]?.id));
76
+ const media = new Set(momentData.flatMap((moment) => moment.segments.map((segment) => segment.videoPath)));
77
+ const assertionFiles = new Set(recipeNodes.flatMap((nodeId) => typeof input.nodes.get(nodeId)?.path === 'string'
78
+ ? [String(input.nodes.get(nodeId).path)]
79
+ : []));
80
+ const evidence = input.artifacts
81
+ .filter((artifact) => media.has(artifact.path) ||
82
+ assertionFiles.has(artifact.path) ||
83
+ (artifact.nodeId !== undefined &&
84
+ (recipeNodes.includes(artifact.nodeId) || assertionNodes.has(artifact.nodeId))))
85
+ .map((artifact) => artifact.path);
86
+ const moments = momentData.flatMap(({ traceIndex, segments }) => segments.map((segment) => ({
87
+ recipeRunId: input.recipeRunId,
88
+ videoDigest: segment.videoDigest,
89
+ traceIndex,
90
+ })));
91
+ const judgment = input.judgments
92
+ ?.filter((entry) => normalizeRecipeClaimId(entry.claimId) === id)
93
+ .at(-1);
94
+ if (verdict === 'awaiting-review' && judgment) {
95
+ if (judgment.recipeRunId !== input.recipeRunId ||
96
+ !judgment.actor.trim() ||
97
+ !judgment.reason.trim() ||
98
+ !Number.isFinite(Date.parse(judgment.judgedAt)) ||
99
+ digestRecipeDocument(judgment.moments) !== digestRecipeDocument(moments))
100
+ throw new Error(`Visual judgment for ${id} does not bind these retained moments.`);
101
+ verdict = judgment.verdict === 'confirmed' ? 'proven' : 'failed';
102
+ }
103
+ return {
104
+ id,
105
+ text: declaration.claim,
106
+ kind: declaration.kind ?? 'acceptance',
107
+ ...(declaration.parentId ? { parentId: normalizeRecipeClaimId(declaration.parentId) } : {}),
108
+ proofMode,
109
+ verdict,
110
+ recipeNodes,
111
+ assertionIndices,
112
+ evidence: [...new Set(evidence)],
113
+ timing,
114
+ moments,
115
+ ...(verdict === 'missing' ? { note: 'A required executed expectation is missing.' } : {}),
116
+ };
117
+ });
118
+ const byId = new Map(claims.map((claim) => [claim.id, claim]));
119
+ const resolved = new Set();
120
+ function aggregate(id) {
121
+ const claim = byId.get(id);
122
+ if (resolved.has(id))
123
+ return claim;
124
+ const children = claims
125
+ .filter((child) => child.parentId === id)
126
+ .map((child) => aggregate(child.id));
127
+ if (children.length) {
128
+ const verdicts = children.map((child) => child.verdict);
129
+ if (claim.recipeNodes.length)
130
+ verdicts.push(claim.verdict);
131
+ claim.verdict = parentVerdictOrder.find((verdict) => verdicts.includes(verdict)) ?? 'proven';
132
+ claim.recipeNodes = [
133
+ ...new Set([...claim.recipeNodes, ...children.flatMap((child) => child.recipeNodes)]),
134
+ ];
135
+ claim.assertionIndices = [
136
+ ...new Set([
137
+ ...claim.assertionIndices,
138
+ ...children.flatMap((child) => child.assertionIndices),
139
+ ]),
140
+ ];
141
+ claim.evidence = [
142
+ ...new Set([...claim.evidence, ...children.flatMap((child) => child.evidence)]),
143
+ ];
144
+ claim.moments = [...claim.moments, ...children.flatMap((child) => child.moments)];
145
+ claim.timing = children.some((child) => child.timing === 'outside-recording')
146
+ ? 'outside-recording'
147
+ : children.some((child) => child.timing === 'untimed')
148
+ ? 'untimed'
149
+ : 'measured';
150
+ if (claim.verdict !== 'missing')
151
+ delete claim.note;
152
+ }
153
+ resolved.add(id);
154
+ return claim;
155
+ }
156
+ return claims.map((claim) => aggregate(claim.id));
157
+ }
158
+ /** Reuse the engine's graph traversal: an unselected branch is not a skipped required check. */
159
+ function unselectedProofNodes(nodes, trace) {
160
+ const qualified = Object.fromEntries([...nodes].map(([id, node]) => [
161
+ id,
162
+ {
163
+ ...node,
164
+ ...(node.next ? { next: qualifyProofNodeRef(id, node.next) } : {}),
165
+ ...(node.default ? { default: qualifyProofNodeRef(id, node.default) } : {}),
166
+ ...(node.cases
167
+ ? {
168
+ cases: Object.fromEntries(Object.entries(node.cases).map(([key, target]) => [
169
+ key,
170
+ qualifyProofNodeRef(id, target),
171
+ ])),
172
+ }
173
+ : {}),
174
+ },
175
+ ]));
176
+ const excluded = new Set();
177
+ for (const entry of trace) {
178
+ const id = entry.nodeId ?? entry.id;
179
+ if (!id || !entry.next)
180
+ continue;
181
+ const node = qualified[id];
182
+ if (!node?.cases)
183
+ continue;
184
+ const selected = qualifyProofNodeRef(id, entry.next);
185
+ const selectedNodes = reachableNodes(qualified, selected);
186
+ const otherTargets = [...Object.values(node.cases), ...(node.default ? [node.default] : [])];
187
+ for (const target of otherTargets) {
188
+ if (target === selected)
189
+ continue;
190
+ for (const other of reachableNodes(qualified, target)) {
191
+ if (!selectedNodes.has(other))
192
+ excluded.add(other);
193
+ }
194
+ }
195
+ }
196
+ for (const id of nodes.keys())
197
+ if ([...excluded].some((parent) => id.startsWith(`${parent}/`)))
198
+ excluded.add(id);
199
+ return excluded;
200
+ }
201
+ //# sourceMappingURL=claims.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claims.js","sourceRoot":"","sources":["../../src/evidence/claims.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /** Portable evidence validation; importing this entry does not load capture or filesystem code. */
2
+ export { validateRecordedEvidencePackage } from './package.js';
3
+ export type { RecordedEvidencePackageInput } from '@farmslot/protocol';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/evidence/index.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AAC/D,YAAY,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Portable evidence validation; importing this entry does not load capture or filesystem code. */
2
+ export { validateRecordedEvidencePackage } from './package.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/evidence/index.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,OAAO,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { RecipeRecordingTimelineDocument, RecordingSegmentRef } from '@farmslot/protocol';
2
+ export interface OccurrenceRecordingCoverage {
3
+ timing: 'measured' | 'untimed' | 'outside-recording';
4
+ segments: RecordingSegmentRef[];
5
+ }
6
+ /** Reuse measured ranges and ordered originals. A gap never becomes seekable proof. */
7
+ export declare function occurrenceRecordingCoverage(traceIndex: number, segments: readonly RecordingSegmentRef[], timelines?: ReadonlyMap<string, RecipeRecordingTimelineDocument>): OccurrenceRecordingCoverage;
8
+ //# sourceMappingURL=moments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moments.d.ts","sourceRoot":"","sources":["../../src/evidence/moments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,+BAA+B,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE/F,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,mBAAmB,CAAC;IACrD,QAAQ,EAAE,mBAAmB,EAAE,CAAC;CACjC;AAED,uFAAuF;AACvF,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,SAAS,mBAAmB,EAAE,EACxC,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,+BAA+B,CAAC,GAC/D,2BAA2B,CA4B7B"}
@@ -0,0 +1,26 @@
1
+ /** Reuse measured ranges and ordered originals. A gap never becomes seekable proof. */
2
+ export function occurrenceRecordingCoverage(traceIndex, segments, timelines) {
3
+ const spans = segments.flatMap((segment, index) => {
4
+ const timeline = timelines?.get(segment.videoDigest);
5
+ const marker = timeline?.markers.find((entry) => entry.traceIndex === traceIndex);
6
+ return timeline &&
7
+ marker &&
8
+ marker.endRangeMs[1] >= 0 &&
9
+ marker.startRangeMs[0] <= timeline.durationMs
10
+ ? [{ segment, index, timeline, marker }]
11
+ : [];
12
+ });
13
+ const first = spans[0];
14
+ const last = spans.at(-1);
15
+ if (first &&
16
+ last &&
17
+ first.marker.startRangeMs[0] >= 0 &&
18
+ last.marker.endRangeMs[1] <= last.timeline.durationMs &&
19
+ spans.every((span, index) => index === 0 || (!span.segment.gapBefore && span.index === spans[index - 1].index + 1)))
20
+ return { timing: 'measured', segments: spans.map((span) => span.segment) };
21
+ const untimed = segments.filter((segment) => !timelines?.has(segment.videoDigest));
22
+ return untimed.length
23
+ ? { timing: 'untimed', segments: untimed }
24
+ : { timing: 'outside-recording', segments: [] };
25
+ }
26
+ //# sourceMappingURL=moments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moments.js","sourceRoot":"","sources":["../../src/evidence/moments.ts"],"names":[],"mappings":"AAOA,uFAAuF;AACvF,MAAM,UAAU,2BAA2B,CACzC,UAAkB,EAClB,QAAwC,EACxC,SAAgE;IAEhE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QAChD,MAAM,QAAQ,GAAG,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;QAClF,OAAO,QAAQ;YACb,MAAM;YACN,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;YACzB,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,UAAU;YAC7C,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;YACxC,CAAC,CAAC,EAAE,CAAC;IACT,CAAC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1B,IACE,KAAK;QACL,IAAI;QACJ,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU;QACrD,KAAK,CAAC,KAAK,CACT,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CACd,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,GAAG,CAAC,CAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CACzF;QAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7E,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACnF,OAAO,OAAO,CAAC,MAAM;QACnB,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE;QAC1C,CAAC,CAAC,EAAE,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AACpD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type RecipeValidationResult, type RecordedEvidencePackageInput } from '@farmslot/protocol';
2
+ /** Validate actual package identities before consumers derive a moment or publish evidence. */
3
+ export declare function validateRecordedEvidencePackage(input: RecordedEvidencePackageInput): RecipeValidationResult;
4
+ //# sourceMappingURL=package.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../src/evidence/package.ts"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EAIlC,MAAM,oBAAoB,CAAC;AAM5B,+FAA+F;AAC/F,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,4BAA4B,GAClC,sBAAsB,CA4KxB"}
@@ -0,0 +1,140 @@
1
+ import { digestRecipeDocument, isRecord, validateAcceptanceStatusLedger, validateRecipeArtifactPackage, validateRecipeRecordingTimelineBinding, } from '@farmslot/protocol';
2
+ import { deriveRecipeClaims } from './claims.js';
3
+ import { planRecipeEvidence } from './plan.js';
4
+ /** Validate actual package identities before consumers derive a moment or publish evidence. */
5
+ export function validateRecordedEvidencePackage(input) {
6
+ const base = validateRecipeArtifactPackage(input);
7
+ const findings = [...base.findings];
8
+ const issue = (path, message, severity = 'error') => findings.push({ severity, code: 'recorded_evidence.invalid', path, message });
9
+ const indexed = isRecord(input.manifest) && Array.isArray(input.manifest.artifacts)
10
+ ? input.manifest.artifacts.filter(isRecord)
11
+ : [];
12
+ const recipeRunId = isRecord(input.summary) && typeof input.summary.recipeRunId === 'string'
13
+ ? input.summary.recipeRunId
14
+ : undefined;
15
+ if (input.claims) {
16
+ if (!input.recipe)
17
+ issue('recipe.json', 'The retained root recipe must be supplied for claim derivation.');
18
+ if (!recipeRunId)
19
+ issue('summary.json.recipeRunId', 'Recorded package has no retained execution identity.');
20
+ if (input.recipeRunId && input.recipeRunId !== recipeRunId)
21
+ issue('recipeRunId', 'Retained execution differs from the requested execution.');
22
+ if (!isRecord(input.invocation) || input.invocation.recipeRunId !== recipeRunId)
23
+ issue('recipe-invocation.json.recipeRunId', 'Invocation belongs to another execution.');
24
+ }
25
+ else if (indexed.some((artifact) => artifact.path === 'acceptance-status.json') ||
26
+ recipeRunId) {
27
+ issue('acceptance-status.json', 'The retained claim package must be supplied for validation.');
28
+ }
29
+ else {
30
+ issue('acceptance-status.json', 'Legacy package has no automatic claim identity; media remains explicitly untimed.', 'warning');
31
+ }
32
+ if (input.claims && validateAcceptanceStatusLedger(input.claims).length === 0) {
33
+ if (input.claims.recipeRunId !== recipeRunId)
34
+ issue('acceptance-status.json', 'Claims belong to another execution.');
35
+ for (const claim of input.claims.criteria) {
36
+ for (const moment of claim.moments) {
37
+ const segment = input.claims.recording.segments.find((entry) => entry.videoDigest === moment.videoDigest);
38
+ if (!segment ||
39
+ input.artifactDigests[segment.videoPath]?.replace(/^sha256:/u, '') !==
40
+ moment.videoDigest.slice(7))
41
+ issue(`claims.${claim.id}.moments`, 'Moment does not reference retained video bytes.');
42
+ const timeline = segment?.timelinePath ? input.timelines[segment.timelinePath] : undefined;
43
+ if (timeline && !timeline.markers.some((marker) => marker.traceIndex === moment.traceIndex))
44
+ issue(`claims.${claim.id}.moments`, 'Moment does not reference a retained occurrence.');
45
+ }
46
+ }
47
+ if (base.status === 'valid' && input.recipe && isRecord(input.manifest)) {
48
+ try {
49
+ const resolution = input.recipeResolution;
50
+ const documents = new Map(resolution.dependencies.map((dependency) => [
51
+ dependency.ref,
52
+ input.resolvedRecipes[dependency.digest],
53
+ ]));
54
+ const registered = isRecord(input.invocation) && Array.isArray(input.invocation.claims)
55
+ ? input.invocation.claims
56
+ : undefined;
57
+ if (input.invocation &&
58
+ (!isRecord(input.summary) ||
59
+ input.summary.invocationDigest !== digestRecipeDocument(input.invocation)))
60
+ issue('recipe-invocation.json', 'Claim registration does not match the retained execution inputs.');
61
+ const plan = planRecipeEvidence(input.recipe, documents, registered);
62
+ const trace = Array.isArray(input.trace)
63
+ ? input.trace
64
+ : isRecord(input.trace) && Array.isArray(input.trace.entries)
65
+ ? input.trace.entries
66
+ : [];
67
+ const derived = deriveRecipeClaims({
68
+ recipeRunId: recipeRunId ?? input.claims.recipeRunId,
69
+ ...plan,
70
+ trace: trace,
71
+ artifacts: input.manifest.artifacts,
72
+ segments: input.claims.recording.segments,
73
+ judgments: input.claims.judgments,
74
+ timelines: new Map(Object.values(input.timelines).map((timeline) => [timeline.videoDigest, timeline])),
75
+ });
76
+ for (const actual of derived) {
77
+ if (!input.claims.criteria.some((claim) => claim.id === actual.id))
78
+ issue(`claims.${actual.id}`, 'Registered claim is missing from the stored ledger.');
79
+ }
80
+ for (const claim of input.claims.criteria) {
81
+ const actual = derived.find((entry) => entry.id === claim.id);
82
+ if (!actual || actual.verdict !== claim.verdict)
83
+ issue(`claims.${claim.id}.verdict`, 'Stored verdict does not match the executed expectations.');
84
+ if (actual &&
85
+ (digestRecipeDocument(actual.assertionIndices) !==
86
+ digestRecipeDocument(claim.assertionIndices) ||
87
+ digestRecipeDocument(actual.moments) !== digestRecipeDocument(claim.moments)))
88
+ issue(`claims.${claim.id}.moments`, 'Stored assertion/moment references do not match execution.');
89
+ }
90
+ }
91
+ catch (error) {
92
+ issue('acceptance-status.json', `Cannot bind claim evidence: ${error instanceof Error ? error.message : String(error)}`);
93
+ }
94
+ }
95
+ }
96
+ else if (input.claims) {
97
+ for (const message of validateAcceptanceStatusLedger(input.claims))
98
+ issue('acceptance-status.json', message);
99
+ }
100
+ const artifacts = isRecord(input.manifest) && Array.isArray(input.manifest.artifacts)
101
+ ? input.manifest.artifacts.filter(isRecord)
102
+ : [];
103
+ for (const artifact of artifacts) {
104
+ if (artifact.type !== 'video' || typeof artifact.path !== 'string')
105
+ continue;
106
+ const actual = input.artifactDigests[artifact.path];
107
+ if (!actual) {
108
+ issue(artifact.path, 'Video bytes were not hashed by the package reader.');
109
+ continue;
110
+ }
111
+ const digest = actual.startsWith('sha256:') ? actual : `sha256:${actual}`;
112
+ if (typeof artifact.sha256 === 'string' &&
113
+ artifact.sha256.replace(/^sha256:/u, '') !== digest.slice(7))
114
+ issue(artifact.path, 'Artifact index belongs to different video bytes.');
115
+ if (typeof artifact.timelinePath !== 'string') {
116
+ issue(artifact.path, 'Recording moment is untimed: no measured timeline is retained.', 'warning');
117
+ continue;
118
+ }
119
+ const timeline = input.timelines[artifact.timelinePath];
120
+ if (!timeline) {
121
+ issue(artifact.timelinePath, 'Declared recording timeline is missing.');
122
+ continue;
123
+ }
124
+ findings.push(...validateRecipeRecordingTimelineBinding(timeline, {
125
+ videoPath: artifact.path,
126
+ videoDigest: digest,
127
+ trace: input.trace,
128
+ }).findings);
129
+ }
130
+ const errors = findings.filter((finding) => finding.severity === 'error').length;
131
+ return {
132
+ status: errors ? 'invalid' : 'valid',
133
+ findings,
134
+ summary: {
135
+ errors,
136
+ warnings: findings.filter((finding) => finding.severity === 'warning').length,
137
+ },
138
+ };
139
+ }
140
+ //# sourceMappingURL=package.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.js","sourceRoot":"","sources":["../../src/evidence/package.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { type RecipeClaimDeclaration } from '@farmslot/protocol';
2
+ import { type ProofDocument, type ProofNode } from './assertions.js';
3
+ export interface RecipeEvidencePlan {
4
+ declarations: RecipeClaimDeclaration[];
5
+ nodes: Map<string, ProofNode>;
6
+ }
7
+ /** The resolved call path is the identity, even when the same library is called twice. */
8
+ export declare function planRecipeEvidence(root: ProofDocument, documents: ReadonlyMap<string, ProofDocument>, registered?: readonly RecipeClaimDeclaration[]): RecipeEvidencePlan;
9
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/evidence/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,sBAAsB,EAE5B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,sBAAsB,EAAE,CAAC;IACvC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CAC/B;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,aAAa,EACnB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,EAC7C,UAAU,CAAC,EAAE,SAAS,sBAAsB,EAAE,GAC7C,kBAAkB,CAwFpB"}
@@ -0,0 +1,87 @@
1
+ import { normalizeRecipeClaimId, normalizeRecipeRef, validateRecipeClaimDeclarations, } from '@farmslot/protocol';
2
+ import { collectProofNodes, potentiallyEligibleProof, } from './assertions.js';
3
+ /** The resolved call path is the identity, even when the same library is called twice. */
4
+ export function planRecipeEvidence(root, documents, registered) {
5
+ const nodes = collectProofNodes(root, documents);
6
+ const declarations = new Map();
7
+ const register = (claim, taskProjection = false) => {
8
+ const previous = declarations.get(claim.id);
9
+ if (previous && !taskProjection)
10
+ throw new Error(`Duplicate qualified claim ${claim.id}.`);
11
+ if (previous &&
12
+ (previous.claim !== claim.claim ||
13
+ (previous.kind ?? 'acceptance') !== (claim.kind ?? 'acceptance') ||
14
+ (previous.proofMode && claim.proofMode && previous.proofMode !== claim.proofMode)))
15
+ throw new Error(`Conflicting claim declaration ${claim.id}.`);
16
+ declarations.set(claim.id, { ...previous, ...claim });
17
+ };
18
+ if (registered) {
19
+ const validation = validateRecipeClaimDeclarations(registered);
20
+ if (validation.status !== 'valid')
21
+ throw new Error(validation.findings.map((finding) => finding.message).join('\n'));
22
+ }
23
+ const taskClaims = new Map(registered?.map((claim) => [normalizeRecipeClaimId(claim.id), claim]));
24
+ for (const claim of taskClaims.values())
25
+ register({ ...claim, id: normalizeRecipeClaimId(claim.id) });
26
+ function visit(document, prefix = '', bindings = {}) {
27
+ const local = (document.proofTargets ?? []);
28
+ const validation = validateRecipeClaimDeclarations(local);
29
+ if (validation.status !== 'valid')
30
+ throw new Error(validation.findings.map((finding) => finding.message).join('\n'));
31
+ const ids = new Map(local.map((claim) => {
32
+ const id = normalizeRecipeClaimId(claim.id);
33
+ return [id, bindings[id] ?? `${prefix}${id}`];
34
+ }));
35
+ for (const id of Object.keys(bindings))
36
+ if (!ids.has(id))
37
+ throw new Error(`Unknown child claim binding ${prefix}${id}.`);
38
+ for (const claim of local) {
39
+ const id = ids.get(normalizeRecipeClaimId(claim.id));
40
+ const bound = bindings[normalizeRecipeClaimId(claim.id)];
41
+ const task = !prefix ? taskClaims.get(id) : undefined;
42
+ if (!prefix && registered && (claim.kind ?? 'acceptance') === 'acceptance' && !task)
43
+ throw new Error(`Claim ${id} is not registered by the task.`);
44
+ if (task && task.claim !== claim.claim)
45
+ throw new Error(`Claim ${id} conflicts with the task expectation.`);
46
+ if (!bound)
47
+ register({
48
+ ...claim,
49
+ id,
50
+ ...(claim.parentId
51
+ ? { parentId: ids.get(normalizeRecipeClaimId(claim.parentId)) }
52
+ : {}),
53
+ }, Boolean(task));
54
+ else if (!declarations.has(bound))
55
+ throw new Error(`Unknown parent claim binding ${bound}.`);
56
+ }
57
+ for (const [localId, node] of Object.entries(document.workflow.nodes)) {
58
+ const id = prefix + localId;
59
+ const qualified = nodes.get(id);
60
+ qualified.proves = node.proves?.map((claim) => {
61
+ const mapped = ids.get(normalizeRecipeClaimId(claim));
62
+ if (!mapped)
63
+ throw new Error(`Unknown claim ${claim} at ${id}.`);
64
+ return mapped;
65
+ });
66
+ if (node.action !== 'call' || !node.ref)
67
+ continue;
68
+ const child = documents.get(normalizeRecipeRef(node.ref));
69
+ if (!child)
70
+ throw new Error(`Missing resolved recipe ${node.ref}.`);
71
+ const raw = node.claimBindings;
72
+ const childBindings = Object.fromEntries(Object.entries(raw ?? {}).map(([childId, parentId]) => {
73
+ const parent = ids.get(normalizeRecipeClaimId(parentId));
74
+ if (!parent)
75
+ throw new Error(`Unknown claim binding ${parentId} at ${id}.`);
76
+ return [normalizeRecipeClaimId(childId), parent];
77
+ }));
78
+ visit(child, `${id}/`, childBindings);
79
+ }
80
+ }
81
+ visit(root);
82
+ for (const [id, node] of nodes)
83
+ if (node.proves?.length && !potentiallyEligibleProof(id, nodes))
84
+ throw new Error(`Node ${id} declares proof without an observation-bound expectation.`);
85
+ return { declarations: [...declarations.values()], nodes };
86
+ }
87
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/evidence/plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type RecordedEvidencePackageInput } from '@farmslot/protocol';
2
+ export interface RecordedEvidencePackageReadCheck {
3
+ id: string;
4
+ status: 'pass' | 'fail';
5
+ message: string;
6
+ }
7
+ export interface RecordedEvidencePackageReadResult {
8
+ input: RecordedEvidencePackageInput;
9
+ /** Consumers must refuse failed reads as well as invalid package validation. */
10
+ checks: RecordedEvidencePackageReadCheck[];
11
+ }
12
+ /** Read retained files and hash actual bytes before canonical package validation. */
13
+ export declare function readRecordedEvidencePackage(artifactDir: string): Promise<RecordedEvidencePackageReadResult>;
14
+ //# sourceMappingURL=read-package.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-package.d.ts","sourceRoot":"","sources":["../../src/evidence/read-package.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,4BAA4B,EAElC,MAAM,oBAAoB,CAAC;AAK5B,MAAM,WAAW,gCAAgC;IAC/C,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iCAAiC;IAChD,KAAK,EAAE,4BAA4B,CAAC;IACpC,gFAAgF;IAChF,MAAM,EAAE,gCAAgC,EAAE,CAAC;CAC5C;AA6CD,qFAAqF;AACrF,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,iCAAiC,CAAC,CAiJ5C"}