@farmslot/protocol 0.38.0 → 0.39.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.
- package/CHANGELOG.md +18 -0
- package/dist/agents/reviewer-context.d.ts +4 -4
- package/dist/agents/reviewer-context.d.ts.map +1 -1
- package/dist/agents/reviewer-context.js +10 -10
- package/dist/agents/reviewer-context.js.map +1 -1
- package/dist/agents/roles.d.ts +2 -2
- package/dist/agents/roles.d.ts.map +1 -1
- package/dist/agents/roles.js +5 -9
- package/dist/agents/roles.js.map +1 -1
- package/dist/checklist-target.d.ts +6 -6
- package/dist/checklist-target.d.ts.map +1 -1
- package/dist/checklist-target.js +11 -11
- package/dist/checklist-target.js.map +1 -1
- package/dist/contracts/acceptance.d.ts +19 -34
- package/dist/contracts/acceptance.d.ts.map +1 -1
- package/dist/contracts/acceptance.js +11 -156
- package/dist/contracts/acceptance.js.map +1 -1
- package/dist/contracts/agents.d.ts +4 -2
- package/dist/contracts/agents.d.ts.map +1 -1
- package/dist/contracts/agents.js +1 -2
- package/dist/contracts/agents.js.map +1 -1
- package/dist/contracts/analytics.d.ts +2 -2
- package/dist/contracts/analytics.d.ts.map +1 -1
- package/dist/contracts/backlog.d.ts +16 -7
- package/dist/contracts/backlog.d.ts.map +1 -1
- package/dist/contracts/backlog.js.map +1 -1
- package/dist/contracts/config.d.ts +12 -3
- package/dist/contracts/config.d.ts.map +1 -1
- package/dist/contracts/config.js +32 -0
- package/dist/contracts/config.js.map +1 -1
- package/dist/contracts/dispatch.d.ts +7 -4
- package/dist/contracts/dispatch.d.ts.map +1 -1
- package/dist/contracts/family.d.ts +2 -2
- package/dist/contracts/family.d.ts.map +1 -1
- package/dist/contracts/index.d.ts +1 -0
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +1 -0
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/pr-monitoring.d.ts +8 -8
- package/dist/contracts/pr-monitoring.d.ts.map +1 -1
- package/dist/contracts/pr-rules.d.ts +5 -7
- package/dist/contracts/pr-rules.d.ts.map +1 -1
- package/dist/contracts/pr-rules.js +4 -6
- package/dist/contracts/pr-rules.js.map +1 -1
- package/dist/contracts/qa.d.ts +2 -2
- package/dist/contracts/qa.d.ts.map +1 -1
- package/dist/contracts/qa.js +5 -9
- package/dist/contracts/qa.js.map +1 -1
- package/dist/contracts/recipe-conformance.d.ts +51 -0
- package/dist/contracts/recipe-conformance.d.ts.map +1 -1
- package/dist/contracts/recipe-conformance.js +134 -1
- package/dist/contracts/recipe-conformance.js.map +1 -1
- package/dist/contracts/resources.d.ts +1 -1
- package/dist/contracts/resources.d.ts.map +1 -1
- package/dist/contracts/resources.js.map +1 -1
- package/dist/contracts/reviews.d.ts +19 -3
- package/dist/contracts/reviews.d.ts.map +1 -1
- package/dist/contracts/reviews.js +2 -2
- package/dist/contracts/reviews.js.map +1 -1
- package/dist/contracts/runner-mobile-keys.d.ts +217 -0
- package/dist/contracts/runner-mobile-keys.d.ts.map +1 -0
- package/dist/contracts/runner-mobile-keys.js +189 -0
- package/dist/contracts/runner-mobile-keys.js.map +1 -0
- package/dist/contracts/runs.d.ts +105 -91
- package/dist/contracts/runs.d.ts.map +1 -1
- package/dist/contracts/runs.js +10 -14
- package/dist/contracts/runs.js.map +1 -1
- package/dist/contracts/runtime-capabilities.d.ts +2 -0
- package/dist/contracts/runtime-capabilities.d.ts.map +1 -1
- package/dist/contracts/runtime-capabilities.js.map +1 -1
- package/dist/contracts/template-placeholders.d.ts +0 -6
- package/dist/contracts/template-placeholders.d.ts.map +1 -1
- package/dist/contracts/template-placeholders.js +22 -4
- package/dist/contracts/template-placeholders.js.map +1 -1
- package/dist/contracts/worker-terminal.d.ts +19 -0
- package/dist/contracts/worker-terminal.d.ts.map +1 -1
- package/dist/contracts/worker-terminal.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/integrations/pr-monitoring.d.ts.map +1 -1
- package/dist/integrations/pr-monitoring.js +9 -3
- package/dist/integrations/pr-monitoring.js.map +1 -1
- package/dist/integrations/pr-rule-config.d.ts.map +1 -1
- package/dist/integrations/pr-rule-config.js +21 -25
- package/dist/integrations/pr-rule-config.js.map +1 -1
- package/dist/integrations/pr-workflow-defaults.d.ts.map +1 -1
- package/dist/integrations/pr-workflow-defaults.js +2 -5
- package/dist/integrations/pr-workflow-defaults.js.map +1 -1
- package/dist/recipe/artifact.d.ts.map +1 -1
- package/dist/recipe/artifact.js +20 -4
- package/dist/recipe/artifact.js.map +1 -1
- package/dist/recipe/document.d.ts +2 -0
- package/dist/recipe/document.d.ts.map +1 -1
- package/dist/recipe/document.js +38 -35
- package/dist/recipe/document.js.map +1 -1
- package/dist/recipe/evidence.d.ts +128 -0
- package/dist/recipe/evidence.d.ts.map +1 -0
- package/dist/recipe/evidence.js +141 -0
- package/dist/recipe/evidence.js.map +1 -0
- package/dist/recipe/hud-intent.d.ts +56 -0
- package/dist/recipe/hud-intent.d.ts.map +1 -0
- package/dist/recipe/hud-intent.js +46 -0
- package/dist/recipe/hud-intent.js.map +1 -0
- package/dist/recipe/index.d.ts +4 -2
- package/dist/recipe/index.d.ts.map +1 -1
- package/dist/recipe/index.js +4 -2
- package/dist/recipe/index.js.map +1 -1
- package/dist/recipe/recording.d.ts +7 -0
- package/dist/recipe/recording.d.ts.map +1 -1
- package/dist/recipe/recording.js +48 -0
- package/dist/recipe/recording.js.map +1 -1
- package/dist/recipe/workflow.d.ts.map +1 -1
- package/dist/recipe/workflow.js +23 -1
- package/dist/recipe/workflow.js.map +1 -1
- package/dist/recipes/step-io.d.ts +8 -4
- package/dist/recipes/step-io.d.ts.map +1 -1
- package/dist/recipes/step-io.js.map +1 -1
- package/dist/rpc/copilot-runtime.d.ts +1 -1
- package/dist/rpc/copilot-runtime.d.ts.map +1 -1
- package/dist/rpc/dispatch.d.ts +10 -6
- package/dist/rpc/dispatch.d.ts.map +1 -1
- package/dist/rpc/native-session.d.ts +1 -0
- package/dist/rpc/native-session.d.ts.map +1 -1
- package/dist/rpc/native-session.js.map +1 -1
- package/dist/rpc/roadmap.d.ts +2 -0
- package/dist/rpc/roadmap.d.ts.map +1 -1
- package/dist/rpc/run.d.ts +5 -3
- package/dist/rpc/run.d.ts.map +1 -1
- package/dist/rpc/run.js.map +1 -1
- package/dist/rpc/slot.d.ts +1 -0
- package/dist/rpc/slot.d.ts.map +1 -1
- package/dist/rpc/tmux.d.ts +10 -0
- package/dist/rpc/tmux.d.ts.map +1 -1
- package/dist/runs/ci-decision-context.d.ts +40 -0
- package/dist/runs/ci-decision-context.d.ts.map +1 -0
- package/dist/runs/ci-decision-context.js +129 -0
- package/dist/runs/ci-decision-context.js.map +1 -0
- package/dist/runs/decision-resolution.d.ts +37 -1
- package/dist/runs/decision-resolution.d.ts.map +1 -1
- package/dist/runs/decision-resolution.js +36 -0
- package/dist/runs/decision-resolution.js.map +1 -1
- package/dist/runs/family-iteration-ledger.js +1 -1
- package/dist/runs/family-iteration-ledger.js.map +1 -1
- package/dist/runs/publish-approval.d.ts +20 -0
- package/dist/runs/publish-approval.d.ts.map +1 -0
- package/dist/runs/publish-approval.js +29 -0
- package/dist/runs/publish-approval.js.map +1 -0
- package/dist/runs/review-chain.d.ts +2 -2
- package/dist/runs/review-chain.d.ts.map +1 -1
- package/dist/runs/review-chain.js +4 -4
- package/dist/runs/review-chain.js.map +1 -1
- package/dist/runs/review-policy.d.ts +9 -0
- package/dist/runs/review-policy.d.ts.map +1 -0
- package/dist/runs/review-policy.js +34 -0
- package/dist/runs/review-policy.js.map +1 -0
- package/dist/runs/review-retries.d.ts +10 -10
- package/dist/runs/review-retries.d.ts.map +1 -1
- package/dist/runs/review-retries.js +17 -22
- package/dist/runs/review-retries.js.map +1 -1
- package/dist/runs/slot-resolution.js +1 -1
- package/dist/runs/slot-resolution.js.map +1 -1
- package/dist/transport/signal.d.ts +3 -3
- package/dist/transport/signal.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +9 -2
- package/schemas/recipe-v1.schema.json +113 -22
- package/scripts/acceptance.d.mts +16 -0
- package/scripts/acceptance.mjs +233 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// Portable acceptance contract. Operator scripts and clients consume the same implementation.
|
|
2
|
+
const ACCEPTANCE_STATUS_ARTIFACT = 'artifacts/acceptance-status.json';
|
|
3
|
+
const ACCEPTANCE_VERDICTS = [
|
|
4
|
+
'proven',
|
|
5
|
+
'weak',
|
|
6
|
+
'missing',
|
|
7
|
+
'untestable',
|
|
8
|
+
'failed',
|
|
9
|
+
'awaiting-review',
|
|
10
|
+
];
|
|
11
|
+
const ACCEPTANCE_PROOF_MODES = ['state', 'visual', 'mixed'];
|
|
12
|
+
const ACCEPTANCE_CRITERION_ID_PATTERN = /^AC-[1-9][0-9]*$/;
|
|
13
|
+
|
|
14
|
+
function acceptanceCriterionId(index) {
|
|
15
|
+
return `AC-${index + 1}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isRecord(value) {
|
|
19
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function isNonEmptyString(value) {
|
|
23
|
+
return typeof value === 'string' && value.trim().length > 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function validateAcceptanceStatusLedger(value) {
|
|
27
|
+
const issues = [];
|
|
28
|
+
if (!isRecord(value)) return ['acceptance ledger: expected object'];
|
|
29
|
+
if (value.schemaVersion !== 1 && value.schemaVersion !== 2)
|
|
30
|
+
issues.push('acceptance ledger schemaVersion: expected 1 or 2');
|
|
31
|
+
if (value.schemaVersion === 2 && !isNonEmptyString(value.recipeRunId))
|
|
32
|
+
issues.push('acceptance ledger recipeRunId: expected execution identity');
|
|
33
|
+
if (value.schemaVersion === 2) {
|
|
34
|
+
const recording = value.recording;
|
|
35
|
+
if (
|
|
36
|
+
!isRecord(recording) ||
|
|
37
|
+
![
|
|
38
|
+
'not-required',
|
|
39
|
+
'explicit-off',
|
|
40
|
+
'recording',
|
|
41
|
+
'finalizing',
|
|
42
|
+
'complete',
|
|
43
|
+
'incomplete',
|
|
44
|
+
'failed',
|
|
45
|
+
].includes(recording.status) ||
|
|
46
|
+
!Array.isArray(recording.segments) ||
|
|
47
|
+
recording.segments.some(
|
|
48
|
+
(segment) =>
|
|
49
|
+
!isRecord(segment) ||
|
|
50
|
+
!isNonEmptyString(segment.videoPath) ||
|
|
51
|
+
!/^sha256:[a-f0-9]{64}$/.test(segment.videoDigest),
|
|
52
|
+
)
|
|
53
|
+
)
|
|
54
|
+
issues.push('acceptance ledger recording: invalid capture state or segments');
|
|
55
|
+
}
|
|
56
|
+
if (!Array.isArray(value.criteria)) {
|
|
57
|
+
issues.push('acceptance ledger criteria: expected array');
|
|
58
|
+
return issues;
|
|
59
|
+
}
|
|
60
|
+
if (
|
|
61
|
+
value.schemaVersion === 2 &&
|
|
62
|
+
value.judgments !== undefined &&
|
|
63
|
+
(!Array.isArray(value.judgments) ||
|
|
64
|
+
value.judgments.some(
|
|
65
|
+
(judgment) =>
|
|
66
|
+
!isRecord(judgment) ||
|
|
67
|
+
judgment.recipeRunId !== value.recipeRunId ||
|
|
68
|
+
!isNonEmptyString(judgment.claimId) ||
|
|
69
|
+
!['confirmed', 'rejected'].includes(judgment.verdict) ||
|
|
70
|
+
!isNonEmptyString(judgment.actor) ||
|
|
71
|
+
!isNonEmptyString(judgment.reason) ||
|
|
72
|
+
!Number.isFinite(Date.parse(judgment.judgedAt)) ||
|
|
73
|
+
!Array.isArray(judgment.moments),
|
|
74
|
+
))
|
|
75
|
+
)
|
|
76
|
+
issues.push('acceptance ledger judgments: invalid visual review');
|
|
77
|
+
const seen = new Set();
|
|
78
|
+
value.criteria.forEach((entry, index) => {
|
|
79
|
+
const prefix = `acceptance ledger criteria[${index}]`;
|
|
80
|
+
if (!isRecord(entry)) {
|
|
81
|
+
issues.push(`${prefix}: expected object`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (
|
|
85
|
+
!isNonEmptyString(entry.id) ||
|
|
86
|
+
(value.schemaVersion === 1 && !ACCEPTANCE_CRITERION_ID_PATTERN.test(entry.id))
|
|
87
|
+
) {
|
|
88
|
+
issues.push(`${prefix}.id: expected AC-<N>`);
|
|
89
|
+
} else if (seen.has(entry.id)) {
|
|
90
|
+
issues.push(`${prefix}.id: duplicate ${entry.id}`);
|
|
91
|
+
} else {
|
|
92
|
+
seen.add(entry.id);
|
|
93
|
+
}
|
|
94
|
+
if (typeof entry.text !== 'string') issues.push(`${prefix}.text: expected string`);
|
|
95
|
+
if (!ACCEPTANCE_VERDICTS.includes(entry.verdict)) {
|
|
96
|
+
issues.push(`${prefix}.verdict: expected one of ${ACCEPTANCE_VERDICTS.join(', ')}`);
|
|
97
|
+
}
|
|
98
|
+
if (entry.proofMode !== undefined && !ACCEPTANCE_PROOF_MODES.includes(entry.proofMode)) {
|
|
99
|
+
issues.push(`${prefix}.proofMode: expected one of ${ACCEPTANCE_PROOF_MODES.join(', ')}`);
|
|
100
|
+
}
|
|
101
|
+
for (const key of ['evidence', 'recipeNodes']) {
|
|
102
|
+
const list = entry[key];
|
|
103
|
+
if (!Array.isArray(list) || list.some((item) => !isNonEmptyString(item))) {
|
|
104
|
+
issues.push(`${prefix}.${key}: expected an array of non-empty strings`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (value.schemaVersion === 2) {
|
|
108
|
+
if (!['acceptance', 'qa-case', 'qa-check'].includes(entry.kind))
|
|
109
|
+
issues.push(`${prefix}.kind: invalid claim kind`);
|
|
110
|
+
if (!ACCEPTANCE_PROOF_MODES.includes(entry.proofMode))
|
|
111
|
+
issues.push(`${prefix}.proofMode: required`);
|
|
112
|
+
if (
|
|
113
|
+
!Array.isArray(entry.assertionIndices) ||
|
|
114
|
+
entry.assertionIndices.some((index) => !Number.isInteger(index) || index < 0)
|
|
115
|
+
)
|
|
116
|
+
issues.push(`${prefix}.assertionIndices: invalid trace references`);
|
|
117
|
+
if (
|
|
118
|
+
!Array.isArray(entry.moments) ||
|
|
119
|
+
entry.moments.some(
|
|
120
|
+
(moment) =>
|
|
121
|
+
!isRecord(moment) ||
|
|
122
|
+
moment.recipeRunId !== value.recipeRunId ||
|
|
123
|
+
!/^sha256:[a-f0-9]{64}$/.test(moment.videoDigest) ||
|
|
124
|
+
!Number.isInteger(moment.traceIndex) ||
|
|
125
|
+
moment.traceIndex < 0,
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
issues.push(`${prefix}.moments: invalid moment references`);
|
|
129
|
+
}
|
|
130
|
+
if (entry.note !== undefined && typeof entry.note !== 'string') {
|
|
131
|
+
issues.push(`${prefix}.note: expected string`);
|
|
132
|
+
}
|
|
133
|
+
if (value.schemaVersion === 1 && !isNonEmptyString(entry.updatedAt)) {
|
|
134
|
+
issues.push(`${prefix}.updatedAt: expected non-empty string`);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
return issues;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function acceptanceCriteriaView(criteria, ledger) {
|
|
141
|
+
const byId = new Map((ledger?.criteria ?? []).map((entry) => [entry.id, entry]));
|
|
142
|
+
const rows = criteria.map((criterion) => ({
|
|
143
|
+
...criterion,
|
|
144
|
+
status: byId.get(criterion.id) ?? null,
|
|
145
|
+
}));
|
|
146
|
+
for (const entry of ledger?.criteria ?? []) {
|
|
147
|
+
if (!criteria.some((criterion) => criterion.id === entry.id)) {
|
|
148
|
+
rows.push({ id: entry.id, text: entry.text, status: entry });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return rows;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function summarizeAcceptanceStatus(ledger, criteria) {
|
|
155
|
+
const total = criteria
|
|
156
|
+
? Math.max(criteria.length, ledger.criteria.length)
|
|
157
|
+
: ledger.criteria.length;
|
|
158
|
+
const summary = {
|
|
159
|
+
proven: 0,
|
|
160
|
+
weak: 0,
|
|
161
|
+
failed: 0,
|
|
162
|
+
'awaiting-review': 0,
|
|
163
|
+
missing: 0,
|
|
164
|
+
untestable: 0,
|
|
165
|
+
unrecorded: 0,
|
|
166
|
+
total,
|
|
167
|
+
};
|
|
168
|
+
for (const criterion of ledger.criteria) summary[criterion.verdict] += 1;
|
|
169
|
+
summary.unrecorded =
|
|
170
|
+
total - ACCEPTANCE_VERDICTS.reduce((count, verdict) => count + summary[verdict], 0);
|
|
171
|
+
return summary;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function cell(value) {
|
|
175
|
+
return (
|
|
176
|
+
value
|
|
177
|
+
.replace(/\|/g, '\\|')
|
|
178
|
+
.replace(/\s*\n\s*/g, ' ')
|
|
179
|
+
.trim() || '-'
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function list(values) {
|
|
184
|
+
return values.length > 0 ? cell(values.join(', ')) : '-';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function renderAcceptanceCoverage(ledger, criteria = ledger.criteria) {
|
|
188
|
+
const summary = summarizeAcceptanceStatus(ledger, criteria);
|
|
189
|
+
const rows = acceptanceCriteriaView(criteria, ledger);
|
|
190
|
+
const untestable = ledger.criteria
|
|
191
|
+
.filter((criterion) => criterion.verdict === 'untestable')
|
|
192
|
+
.map((criterion) => criterion.id);
|
|
193
|
+
const lines = [
|
|
194
|
+
'## Recipe coverage',
|
|
195
|
+
'',
|
|
196
|
+
'| AC | Criterion | Verdict | Proof mode | Recipe nodes | Evidence | Note |',
|
|
197
|
+
'| --- | --- | --- | --- | --- | --- | --- |',
|
|
198
|
+
];
|
|
199
|
+
for (const row of rows) {
|
|
200
|
+
const status = row.status;
|
|
201
|
+
lines.push(
|
|
202
|
+
`| ${row.id} | ${cell(row.text)} | ${status ? status.verdict.toUpperCase() : 'NO VERDICT'} | ` +
|
|
203
|
+
`${status?.proofMode ?? '-'} | ${list(status?.recipeNodes ?? [])} | ` +
|
|
204
|
+
`${list(status?.evidence ?? [])} | ${cell(status?.note ?? '')} |`,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
lines.push(
|
|
208
|
+
'',
|
|
209
|
+
`Overall recipe coverage: ${summary.proven}/${summary.total} ACs PROVEN ` +
|
|
210
|
+
`(untestable: ${untestable.length > 0 ? untestable.join(', ') : 'none'}, ` +
|
|
211
|
+
`weak: ${summary.weak}, missing: ${summary.missing}` +
|
|
212
|
+
(summary.failed ? `, failed: ${summary.failed}` : '') +
|
|
213
|
+
(summary['awaiting-review'] ? `, awaiting review: ${summary['awaiting-review']}` : '') +
|
|
214
|
+
`${summary.unrecorded > 0 ? `, no verdict: ${summary.unrecorded}` : ''})`,
|
|
215
|
+
'',
|
|
216
|
+
);
|
|
217
|
+
return lines.join('\n');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// ---------------------------------------------------------------------------
|
|
221
|
+
// task-dir IO
|
|
222
|
+
|
|
223
|
+
export {
|
|
224
|
+
ACCEPTANCE_CRITERION_ID_PATTERN,
|
|
225
|
+
ACCEPTANCE_PROOF_MODES,
|
|
226
|
+
ACCEPTANCE_STATUS_ARTIFACT,
|
|
227
|
+
ACCEPTANCE_VERDICTS,
|
|
228
|
+
acceptanceCriteriaView,
|
|
229
|
+
acceptanceCriterionId,
|
|
230
|
+
renderAcceptanceCoverage,
|
|
231
|
+
summarizeAcceptanceStatus,
|
|
232
|
+
validateAcceptanceStatusLedger,
|
|
233
|
+
};
|