@farmslot/protocol 0.81.0 → 0.82.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 +4 -0
- package/dist/contracts/recipes.d.ts +4 -0
- package/dist/contracts/recipes.d.ts.map +1 -1
- package/dist/contracts/recipes.js +3 -0
- package/dist/contracts/recipes.js.map +1 -1
- package/dist/rpc/nodes.d.ts +2 -0
- package/dist/rpc/nodes.d.ts.map +1 -1
- package/dist/rpc/nodes.js.map +1 -1
- package/dist/transport/node-link-operations.d.ts +13 -0
- package/dist/transport/node-link-operations.d.ts.map +1 -1
- package/dist/transport/node-link-operations.js +15 -1
- package/dist/transport/node-link-operations.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +15 -3
- package/recipe-shape.d.mts +91 -0
- package/recipe-shape.mjs +532 -0
- package/scripts/acceptance.d.mts +6 -0
- package/scripts/acceptance.mjs +11 -0
- package/scripts/recipe-library-identity.d.mts +17 -0
- package/scripts/recipe-library-identity.mjs +45 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,10 @@ All notable changes to `@farmslot/protocol` are tracked here.
|
|
|
6
6
|
|
|
7
7
|
- Active-development baseline; add user-facing changes here before release or package publication.
|
|
8
8
|
|
|
9
|
+
## 0.82.0 - 2026-11-08
|
|
10
|
+
|
|
11
|
+
- Share versioned recipe-shape policy, static AC coverage and concrete feedback across runtime and offline consumers.
|
|
12
|
+
|
|
9
13
|
## 0.81.0 - 2026-11-07
|
|
10
14
|
|
|
11
15
|
- Define capability-gated persistent node commands, durable outcomes and bounded resumable streams without changing peer compatibility rules.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type RecipeShapeFeedback } from '../../recipe-shape.mjs';
|
|
2
|
+
export type { RecipeShapeFeedback } from '../../recipe-shape.mjs';
|
|
1
3
|
import type { FlowType } from './runs.js';
|
|
2
4
|
export type EvidenceQualityVerdict = 'RELEVANT_HIGH' | 'RELEVANT_LOW' | 'IRRELEVANT' | 'MISSING';
|
|
3
5
|
/** Evidence strategy the worker uses for a review-pr run.
|
|
@@ -78,6 +80,8 @@ export interface RecipeQualityArtifactMeta {
|
|
|
78
80
|
source_signals: string[];
|
|
79
81
|
}
|
|
80
82
|
export interface RecipeQualityArtifact {
|
|
83
|
+
/** Advisory shape; never a proof verdict or a catalog completeness attestation. */
|
|
84
|
+
shape?: RecipeShapeFeedback;
|
|
81
85
|
version: 1;
|
|
82
86
|
verdict: RecipeQualityVerdict;
|
|
83
87
|
compact: RecipeQualityCompactProjection;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../../src/contracts/recipes.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../../src/contracts/recipes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isRecipeShapeFeedback } from '../../recipe-shape.mjs';
|
|
1
2
|
export const RECIPE_STRATEGY_LABELS = {
|
|
2
3
|
'full-qa': { label: 'Full QA', tagline: 'screenshots + opt-in motion video' },
|
|
3
4
|
targeted: { label: 'Targeted evidence', tagline: 'smoke + screenshots for changed UI' },
|
|
@@ -140,6 +141,8 @@ export function isRecipeQualityArtifact(value) {
|
|
|
140
141
|
return false;
|
|
141
142
|
if (!isRecipeQualityTrainingFields(artifact.training_fields))
|
|
142
143
|
return false;
|
|
144
|
+
if (artifact.shape !== undefined && !isRecipeShapeFeedback(artifact.shape))
|
|
145
|
+
return false;
|
|
143
146
|
if (!isRecipeQualityMeta(artifact.meta))
|
|
144
147
|
return false;
|
|
145
148
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recipes.js","sourceRoot":"","sources":["../../src/contracts/recipes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"recipes.js","sourceRoot":"","sources":["../../src/contracts/recipes.ts"],"names":[],"mappings":"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"}
|
package/dist/rpc/nodes.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export interface NodeInfo extends PeerVersionDeclaration {
|
|
|
11
11
|
uptime?: number;
|
|
12
12
|
/** This node can cancel exec requests on their original connection. */
|
|
13
13
|
execCancellation?: boolean;
|
|
14
|
+
/** This node supports version 1 of hosted task initialization and receipt verification. */
|
|
15
|
+
taskRuntime?: 1;
|
|
14
16
|
/** This node checks `expectedHash` on file writes, renames and deletes. */
|
|
15
17
|
conditionalWrites?: boolean;
|
|
16
18
|
/** This node types a `tmux.send` carrying `seq` once per (pane, stream, n). */
|
package/dist/rpc/nodes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../../src/rpc/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,MAAM,WAAW,QAAS,SAAQ,sBAAsB;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,+EAA+E;IAC/E,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,sBAAsB,CAAC;CAC/C;AAED,MAAM,WAAW,sBAAuB,SAAQ,sBAAsB;IACpE,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yEAAyE;AACzE,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C,UAAU,oBAAoB;IAC5B,gEAAgE;IAChE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,WAAW,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CACnC;AAED,MAAM,MAAM,cAAc,GACtB,CAAC,oBAAoB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GACtD,CAAC,oBAAoB,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAE7D,wFAAwF;AACxF,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,OAAO,EAAE,MAAM,IAAI,GAClB,MAAM,IAAI,CAOZ;AAED,6FAA6F;AAC7F,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,KAAK,IAAI,EACtD,SAAS,SAAwB,EACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,GACpB;IAAE,SAAS,IAAI,IAAI,CAAC;IAAC,OAAO,IAAI,IAAI,CAAA;CAAE,CAkBxC"}
|
|
1
|
+
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../../src/rpc/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,MAAM,WAAW,QAAS,SAAQ,sBAAsB;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,oBAAoB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2FAA2F;IAC3F,WAAW,CAAC,EAAE,CAAC,CAAC;IAChB,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,+EAA+E;IAC/E,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,oBAAoB,CAAC,EAAE,sBAAsB,CAAC;CAC/C;AAED,MAAM,WAAW,sBAAuB,SAAQ,sBAAsB;IACpE,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yEAAyE;AACzE,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C,UAAU,oBAAoB;IAC5B,gEAAgE;IAChE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,WAAW,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CACnC;AAED,MAAM,MAAM,cAAc,GACtB,CAAC,oBAAoB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GACtD,CAAC,oBAAoB,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAE7D,wFAAwF;AACxF,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,OAAO,EAAE,MAAM,IAAI,GAClB,MAAM,IAAI,CAOZ;AAED,6FAA6F;AAC7F,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,CAAC,MAAM,EAAE,SAAS,GAAG,SAAS,KAAK,IAAI,EACtD,SAAS,SAAwB,EACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,GACpB;IAAE,SAAS,IAAI,IAAI,CAAC;IAAC,OAAO,IAAI,IAAI,CAAA;CAAE,CAkBxC"}
|
package/dist/rpc/nodes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodes.js","sourceRoot":"","sources":["../../src/rpc/nodes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"nodes.js","sourceRoot":"","sources":["../../src/rpc/nodes.ts"],"names":[],"mappings":"AA2CA,yEAAyE;AACzE,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAkB3C,wFAAwF;AACxF,MAAM,UAAU,oBAAoB,CAClC,MAA+B,EAC/B,OAAmB;IAEnB,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,CAAC;QACV,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,OAAO,GAAG,EAAE,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC7D,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,sBAAsB,CACpC,aAAsD,EACtD,SAAS,GAAG,qBAAqB,EACjC,QAAqB;IAErB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,KAAgD,CAAC;IACrD,OAAO;QACL,SAAS;YACP,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,aAAa,CAAC,SAAS,CAAC,CAAC;YACzB,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBACtB,QAAQ,EAAE,EAAE,CAAC;gBACb,aAAa,CAAC,SAAS,CAAC,CAAC;YAC3B,CAAC,EAAE,SAAS,CAAC,CAAC;YACd,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAClB,CAAC;QACD,OAAO;YACL,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -27,6 +27,13 @@ export interface NodeLinkProcessInput {
|
|
|
27
27
|
/** Node-owned PTY attachment. Input uses the existing sequenced terminal command. */
|
|
28
28
|
terminal?: NodeLinkTerminalSize;
|
|
29
29
|
}
|
|
30
|
+
/** Exact node-local library call approved by the gateway's task owner. */
|
|
31
|
+
export interface NodeLinkTaskRuntimeInput {
|
|
32
|
+
action: 'init' | 'verify';
|
|
33
|
+
taskPath: string;
|
|
34
|
+
supportDir: string;
|
|
35
|
+
env: Record<string, string>;
|
|
36
|
+
}
|
|
30
37
|
export interface NodeLinkWriteFilesInput extends NodeFsWriteFilesParams {
|
|
31
38
|
createOnly?: boolean;
|
|
32
39
|
}
|
|
@@ -133,6 +140,10 @@ export interface NodeLinkOperationMap {
|
|
|
133
140
|
input: NodeLinkProcessInput;
|
|
134
141
|
result: ExecResult | NodeLinkProcessSummary;
|
|
135
142
|
};
|
|
143
|
+
'task.runtime': {
|
|
144
|
+
input: NodeLinkTaskRuntimeInput;
|
|
145
|
+
result: ExecResult | NodeLinkProcessSummary;
|
|
146
|
+
};
|
|
136
147
|
}
|
|
137
148
|
export type NodeLinkOperation = keyof NodeLinkOperationMap;
|
|
138
149
|
export type TypedNodeLinkCommand = {
|
|
@@ -150,6 +161,7 @@ export interface NodeLinkGrant {
|
|
|
150
161
|
root?: string;
|
|
151
162
|
/** A process request must match this exact admitted argv/cwd/limit policy. */
|
|
152
163
|
process?: NodeLinkProcessInput;
|
|
164
|
+
task?: NodeLinkTaskRuntimeInput;
|
|
153
165
|
}
|
|
154
166
|
export declare const NODE_LINK_OPERATIONS: NodeLinkOperation[];
|
|
155
167
|
/** Unknown future operation names remain unsupported without breaking peer registration. */
|
|
@@ -161,5 +173,6 @@ export type NodeLinkOperationRequest = {
|
|
|
161
173
|
};
|
|
162
174
|
}[NodeLinkOperation];
|
|
163
175
|
export declare function isNodeLinkGrant(value: unknown): value is NodeLinkGrant;
|
|
176
|
+
export declare function isNodeLinkTaskRuntimeInput(value: unknown): value is NodeLinkTaskRuntimeInput;
|
|
164
177
|
export declare function isNodeLinkProcessInput(value: unknown): value is NodeLinkProcessInput;
|
|
165
178
|
//# sourceMappingURL=node-link-operations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-link-operations.d.ts","sourceRoot":"","sources":["../../src/transport/node-link-operations.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"node-link-operations.d.ts","sourceRoot":"","sources":["../../src/transport/node-link-operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ export const NODE_LINK_OPERATIONS = [
|
|
|
14
14
|
'file.delete',
|
|
15
15
|
'file.rename',
|
|
16
16
|
'process.run',
|
|
17
|
+
'task.runtime',
|
|
17
18
|
];
|
|
18
19
|
/** Unknown future operation names remain unsupported without breaking peer registration. */
|
|
19
20
|
export function nodeLinkCapabilities(value) {
|
|
@@ -38,7 +39,20 @@ export function isNodeLinkGrant(value) {
|
|
|
38
39
|
Array.isArray(grant.operations) &&
|
|
39
40
|
grant.operations.every((operation) => NODE_LINK_OPERATIONS.some((known) => known === operation)) &&
|
|
40
41
|
(grant.root === undefined || typeof grant.root === 'string') &&
|
|
41
|
-
(grant.process === undefined || isNodeLinkProcessInput(grant.process))
|
|
42
|
+
(grant.process === undefined || isNodeLinkProcessInput(grant.process)) &&
|
|
43
|
+
(grant.task === undefined || isNodeLinkTaskRuntimeInput(grant.task)));
|
|
44
|
+
}
|
|
45
|
+
export function isNodeLinkTaskRuntimeInput(value) {
|
|
46
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
47
|
+
return false;
|
|
48
|
+
const task = value;
|
|
49
|
+
return ((task.action === 'init' || task.action === 'verify') &&
|
|
50
|
+
typeof task.taskPath === 'string' &&
|
|
51
|
+
typeof task.supportDir === 'string' &&
|
|
52
|
+
task.env !== null &&
|
|
53
|
+
typeof task.env === 'object' &&
|
|
54
|
+
!Array.isArray(task.env) &&
|
|
55
|
+
Object.values(task.env).every((entry) => typeof entry === 'string'));
|
|
42
56
|
}
|
|
43
57
|
export function isNodeLinkProcessInput(value) {
|
|
44
58
|
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-link-operations.js","sourceRoot":"","sources":["../../src/transport/node-link-operations.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,GAIjB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"node-link-operations.js","sourceRoot":"","sources":["../../src/transport/node-link-operations.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const PROTOCOL_VERSION = "0.
|
|
1
|
+
export declare const PROTOCOL_VERSION = "0.82.0";
|
|
2
2
|
/** Node-facing additions since this release remain additive or capability-gated. */
|
|
3
3
|
export declare const MINIMUM_PROTOCOL_VERSION = "0.76.0";
|
|
4
4
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Published protocol release plus an explicit oldest-supported peer.
|
|
2
2
|
// Different release numbers are harmless when both declared bounds are met;
|
|
3
3
|
// optional methods/events still require their existing feature capabilities.
|
|
4
|
-
export const PROTOCOL_VERSION = '0.
|
|
4
|
+
export const PROTOCOL_VERSION = '0.82.0';
|
|
5
5
|
/** Node-facing additions since this release remain additive or capability-gated. */
|
|
6
6
|
export const MINIMUM_PROTOCOL_VERSION = '0.76.0';
|
|
7
7
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farmslot/protocol",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.82.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -402,6 +402,14 @@
|
|
|
402
402
|
"types": "./dist/performance/index.d.ts",
|
|
403
403
|
"import": "./dist/performance/index.js",
|
|
404
404
|
"default": "./dist/performance/index.js"
|
|
405
|
+
},
|
|
406
|
+
"./recipe-shape.mjs": {
|
|
407
|
+
"types": "./recipe-shape.d.mts",
|
|
408
|
+
"default": "./recipe-shape.mjs"
|
|
409
|
+
},
|
|
410
|
+
"./scripts/recipe-library-identity.mjs": {
|
|
411
|
+
"types": "./scripts/recipe-library-identity.d.mts",
|
|
412
|
+
"default": "./scripts/recipe-library-identity.mjs"
|
|
405
413
|
}
|
|
406
414
|
},
|
|
407
415
|
"scripts": {
|
|
@@ -410,7 +418,7 @@
|
|
|
410
418
|
"format:check": "prettier --check --ignore-path ../../.prettierignore .",
|
|
411
419
|
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
412
420
|
"lint:fix": "eslint \"src/**/*.ts\" \"test/**/*.ts\" --fix",
|
|
413
|
-
"test": "yarn build && node ../../scripts/quality/run-tsx-tests.mjs --cwd . --tsconfig tsconfig.json test",
|
|
421
|
+
"test": "yarn build && node --test test/recipe-shape.test.cjs && node ../../scripts/quality/run-tsx-tests.mjs --cwd . --tsconfig tsconfig.json test",
|
|
414
422
|
"quality": "prettier --check --ignore-path ../../.prettierignore . && eslint \"src/**/*.ts\" \"test/**/*.ts\" && tsc --noEmit --project tsconfig.json && yarn test",
|
|
415
423
|
"build": "rm -rf dist && tsc --project tsconfig.json",
|
|
416
424
|
"prepack": "cd ../.. && node scripts/quality/check-farmslot-package-readiness.mjs --require-changelog --packages @farmslot/protocol && yarn workspace @farmslot/protocol build",
|
|
@@ -453,7 +461,11 @@
|
|
|
453
461
|
"scripts/acceptance.d.cts",
|
|
454
462
|
"scripts/acceptance.d.mts",
|
|
455
463
|
"scripts/review-approval-policy.cjs",
|
|
456
|
-
"scripts/review-approval-policy.d.cts"
|
|
464
|
+
"scripts/review-approval-policy.d.cts",
|
|
465
|
+
"recipe-shape.mjs",
|
|
466
|
+
"recipe-shape.d.mts",
|
|
467
|
+
"scripts/recipe-library-identity.mjs",
|
|
468
|
+
"scripts/recipe-library-identity.d.mts"
|
|
457
469
|
],
|
|
458
470
|
"publishConfig": {
|
|
459
471
|
"access": "public"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export interface RecipeShapeCriterion {
|
|
2
|
+
id: string;
|
|
3
|
+
text?: string;
|
|
4
|
+
proofMode?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RecipeShapeBlock {
|
|
7
|
+
id: string;
|
|
8
|
+
ref?: string;
|
|
9
|
+
tokens?: string[];
|
|
10
|
+
sig?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface RecipeShapeSource {
|
|
13
|
+
name: string;
|
|
14
|
+
revision: string | null;
|
|
15
|
+
fingerprint: string | null;
|
|
16
|
+
}
|
|
17
|
+
export interface RecipeShapeCatalog {
|
|
18
|
+
adapter?: string | null;
|
|
19
|
+
available: boolean;
|
|
20
|
+
blocks: RecipeShapeBlock[];
|
|
21
|
+
sources: RecipeShapeSource[];
|
|
22
|
+
}
|
|
23
|
+
export interface RecipeShapeInput {
|
|
24
|
+
recipe: unknown;
|
|
25
|
+
nonLocalCriteria?: string[];
|
|
26
|
+
criteria?: RecipeShapeCriterion[] | null;
|
|
27
|
+
catalog?: RecipeShapeCatalog | null;
|
|
28
|
+
}
|
|
29
|
+
export interface RecipeShapeHint {
|
|
30
|
+
kind: 'parameterize' | 'compose' | 'shorten' | 'acceptance' | 'catalog';
|
|
31
|
+
message: string;
|
|
32
|
+
field?: string;
|
|
33
|
+
nodes?: string[];
|
|
34
|
+
flow?: string;
|
|
35
|
+
ref?: string;
|
|
36
|
+
criterionId?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface RecipeShapeFeedback {
|
|
39
|
+
policyVersion: number;
|
|
40
|
+
inputIdentity: { recipe: string; criteria: string; catalog: string };
|
|
41
|
+
nodes: number;
|
|
42
|
+
calls: number;
|
|
43
|
+
templatedValues: number;
|
|
44
|
+
literalValues: number;
|
|
45
|
+
short: number;
|
|
46
|
+
composed: number | null;
|
|
47
|
+
parameterized: number;
|
|
48
|
+
inlineDuplicates: { flow: string; ref?: string; nodes: string[] }[];
|
|
49
|
+
goodShape: boolean;
|
|
50
|
+
acCoverage: {
|
|
51
|
+
nonLocal: string[];
|
|
52
|
+
available: boolean;
|
|
53
|
+
expected: string[];
|
|
54
|
+
covered: string[];
|
|
55
|
+
missing: string[];
|
|
56
|
+
reviewOnly: string[];
|
|
57
|
+
unexpected: string[];
|
|
58
|
+
complete: boolean;
|
|
59
|
+
};
|
|
60
|
+
eligibleForImitation: boolean;
|
|
61
|
+
catalogTrust: 'worker-supplied-self-consistent';
|
|
62
|
+
status: 'ok' | 'warn' | 'unavailable';
|
|
63
|
+
hints: RecipeShapeHint[];
|
|
64
|
+
}
|
|
65
|
+
export const POLICY_VERSION: number;
|
|
66
|
+
export const RECIPE_SHAPE_POLICY: Readonly<{
|
|
67
|
+
short: Readonly<{ good: number; max: number }>;
|
|
68
|
+
positive: Readonly<{ short: number; composed: number; parameterized: number }>;
|
|
69
|
+
skipValueKeys: string;
|
|
70
|
+
selectorKeys: string;
|
|
71
|
+
}>;
|
|
72
|
+
export function stableDigest(value: unknown): string;
|
|
73
|
+
export function inspectRecipeShape(recipe: {
|
|
74
|
+
workflow?: { entry?: string; teardown?: string; nodes?: Record<string, unknown> };
|
|
75
|
+
}): { order: string[]; reachable: string[]; tokens: string[]; signature: string[] };
|
|
76
|
+
export function recipeShapeNodeToken(node: Record<string, unknown>): string;
|
|
77
|
+
export function recipeShapeSignature(tokens: string[]): string[];
|
|
78
|
+
export function isRecipeShapeObservation(action?: string): boolean;
|
|
79
|
+
export function scoreRecipeShape(input: RecipeShapeInput): RecipeShapeFeedback;
|
|
80
|
+
export function isRecipeShapeFeedback(value: unknown): value is RecipeShapeFeedback;
|
|
81
|
+
|
|
82
|
+
export function recipeShapeLibraryRef(
|
|
83
|
+
name: string | null,
|
|
84
|
+
relativePath: string,
|
|
85
|
+
platforms?: string[],
|
|
86
|
+
adapter?: string,
|
|
87
|
+
): string | null;
|
|
88
|
+
export function recipeShapeBlock(ref: string, recipe: unknown): RecipeShapeBlock | null;
|
|
89
|
+
export function processShapeRequest(request: Record<string, unknown>): unknown;
|
|
90
|
+
|
|
91
|
+
export function recipeShapeSelector(node: Record<string, unknown>): string | null;
|
package/recipe-shape.mjs
ADDED
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
2
|
+
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
filterWorkerAcceptanceCriteria,
|
|
6
|
+
registeredAcceptanceCriteria,
|
|
7
|
+
} from './scripts/acceptance.mjs';
|
|
8
|
+
import {
|
|
9
|
+
BUILT_IN_RECIPE_PLATFORMS,
|
|
10
|
+
recipeFileIdentity,
|
|
11
|
+
} from './scripts/recipe-library-identity.mjs';
|
|
12
|
+
const POLICY = {
|
|
13
|
+
short: {
|
|
14
|
+
good: 8,
|
|
15
|
+
max: 40,
|
|
16
|
+
},
|
|
17
|
+
positive: {
|
|
18
|
+
short: 0.6,
|
|
19
|
+
composed: 0.8,
|
|
20
|
+
parameterized: 0.7,
|
|
21
|
+
},
|
|
22
|
+
skipValueKeys:
|
|
23
|
+
'^(test_?id|selector|locator|route|screen|page|text|label|key|role|target|path|url|file|dir|expect|expected|equals|contains|match|text_?match|status|state|mode|platform|visibility|direction|surface|title|message|name|description|reason|kind|format|assert|source|stream|cmd|command|cwd|artifacts|category|covers|expression|fail_when|probes|scope|require_features|pixels|distance|width|height|x|y|index|count|timeout|interval|retries|attempts|delay|poll|limit)$|_ms$|^css_|timeout|delay|interval|duration|poll',
|
|
24
|
+
selectorKeys: '^(test_?id|selector|locator|route|text|label|ref|key)$',
|
|
25
|
+
};
|
|
26
|
+
Object.freeze(POLICY.short);
|
|
27
|
+
Object.freeze(POLICY.positive);
|
|
28
|
+
Object.freeze(POLICY);
|
|
29
|
+
const POLICY_VERSION = 1;
|
|
30
|
+
const STRUCTURAL = new Set([
|
|
31
|
+
'action',
|
|
32
|
+
'intent',
|
|
33
|
+
'next',
|
|
34
|
+
'cases',
|
|
35
|
+
'default',
|
|
36
|
+
'proves',
|
|
37
|
+
'claimBindings',
|
|
38
|
+
'ref',
|
|
39
|
+
'review',
|
|
40
|
+
'id',
|
|
41
|
+
]);
|
|
42
|
+
const skipValue = new RegExp(POLICY.skipValueKeys, 'i');
|
|
43
|
+
const selectorKey = new RegExp(POLICY.selectorKeys, 'i');
|
|
44
|
+
const record = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
45
|
+
|
|
46
|
+
function canonical(value) {
|
|
47
|
+
if (Array.isArray(value)) return value.map(canonical);
|
|
48
|
+
if (record(value))
|
|
49
|
+
return Object.fromEntries(
|
|
50
|
+
Object.keys(value)
|
|
51
|
+
.sort()
|
|
52
|
+
.map((key) => [key, canonical(value[key])]),
|
|
53
|
+
);
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
function stableDigest(value) {
|
|
57
|
+
return bytesToHex(sha256(utf8ToBytes(JSON.stringify(canonical(value)))));
|
|
58
|
+
}
|
|
59
|
+
function graphOrder(nodes, start) {
|
|
60
|
+
const seen = new Set(),
|
|
61
|
+
order = [],
|
|
62
|
+
stack = [start];
|
|
63
|
+
while (stack.length) {
|
|
64
|
+
const id = stack.pop();
|
|
65
|
+
if (typeof id !== 'string' || !record(nodes[id]) || seen.has(id)) continue;
|
|
66
|
+
seen.add(id);
|
|
67
|
+
const node = nodes[id];
|
|
68
|
+
if (node.action === 'end') continue;
|
|
69
|
+
order.push(id);
|
|
70
|
+
const edges = [node.next, ...Object.values(record(node.cases) ? node.cases : {}), node.default];
|
|
71
|
+
stack.push(...edges.reverse());
|
|
72
|
+
}
|
|
73
|
+
return order;
|
|
74
|
+
}
|
|
75
|
+
function recipeShapeSelector(node) {
|
|
76
|
+
for (const [key, value] of Object.entries(node))
|
|
77
|
+
if (
|
|
78
|
+
!STRUCTURAL.has(key) &&
|
|
79
|
+
selectorKey.test(key) &&
|
|
80
|
+
['string', 'number'].includes(typeof value)
|
|
81
|
+
)
|
|
82
|
+
return `${key}=${value}`;
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
function recipeShapeNodeToken(node) {
|
|
86
|
+
const action = node.action ?? '?';
|
|
87
|
+
let selector = recipeShapeSelector(node);
|
|
88
|
+
if (!selector) return action;
|
|
89
|
+
if (selector.includes('{{')) {
|
|
90
|
+
selector = selector.replace(/\{\{[^}]*\}\}/g, '*');
|
|
91
|
+
if (!/\w/.test(selector.slice(selector.indexOf('=') + 1).replaceAll('*', ''))) return action;
|
|
92
|
+
}
|
|
93
|
+
return `${action}|${selector}`;
|
|
94
|
+
}
|
|
95
|
+
function isRecipeShapeObservation(action = '') {
|
|
96
|
+
return (
|
|
97
|
+
['wait', 'app.hud', 'end'].includes(action) ||
|
|
98
|
+
action.startsWith('assert') ||
|
|
99
|
+
action.includes('.assert_') ||
|
|
100
|
+
action.includes('.read_') ||
|
|
101
|
+
['wait_for', 'screenshot', 'capture_surface'].some((suffix) => action.endsWith(suffix))
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
function recipeShapeSignature(tokens) {
|
|
105
|
+
return tokens.map((token) =>
|
|
106
|
+
isRecipeShapeObservation(token.split('|')[0]) ? token.split('|')[0] : token,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
function inspectRecipeShape(recipe) {
|
|
110
|
+
const workflow = recipe.workflow ?? {},
|
|
111
|
+
nodes = workflow.nodes ?? {};
|
|
112
|
+
const reachable = [
|
|
113
|
+
...new Set([...graphOrder(nodes, workflow.entry), ...graphOrder(nodes, workflow.teardown)]),
|
|
114
|
+
];
|
|
115
|
+
const order = [
|
|
116
|
+
...reachable,
|
|
117
|
+
...Object.keys(nodes).filter(
|
|
118
|
+
(id) => !reachable.includes(id) && record(nodes[id]) && nodes[id].action !== 'end',
|
|
119
|
+
),
|
|
120
|
+
];
|
|
121
|
+
const tokens = order.map((id) => recipeShapeNodeToken(nodes[id]));
|
|
122
|
+
return { order, reachable, tokens, signature: recipeShapeSignature(tokens) };
|
|
123
|
+
}
|
|
124
|
+
function valueLeaves(value, path, out) {
|
|
125
|
+
if (Array.isArray(value))
|
|
126
|
+
value.forEach((item, index) => valueLeaves(item, [...path, String(index)], out));
|
|
127
|
+
else if (record(value))
|
|
128
|
+
Object.entries(value).forEach(([key, item]) => valueLeaves(item, [...path, key], out));
|
|
129
|
+
else if (typeof value === 'string' && value.includes('{{')) out.templated++;
|
|
130
|
+
else if (
|
|
131
|
+
(typeof value === 'string' && value !== '') ||
|
|
132
|
+
(typeof value === 'number' && Number.isFinite(value))
|
|
133
|
+
)
|
|
134
|
+
out.literals.push(path.join('.'));
|
|
135
|
+
}
|
|
136
|
+
function nodeValues(node, id, out) {
|
|
137
|
+
for (const [key, value] of Object.entries(node)) {
|
|
138
|
+
if (STRUCTURAL.has(key) || skipValue.test(key)) continue;
|
|
139
|
+
if (key === 'params' && record(value)) {
|
|
140
|
+
for (const [parameter, item] of Object.entries(value))
|
|
141
|
+
if (!skipValue.test(parameter)) valueLeaves(item, [id, key, parameter], out);
|
|
142
|
+
} else valueLeaves(value, [id, key], out);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function globRegex(pattern) {
|
|
146
|
+
let result = '^';
|
|
147
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
148
|
+
const char = pattern[index];
|
|
149
|
+
if (char === '*') result += '.*';
|
|
150
|
+
else if (char === '?') result += '.';
|
|
151
|
+
else if (char === '[') {
|
|
152
|
+
let end = index + 1;
|
|
153
|
+
if (pattern[end] === '!') end++;
|
|
154
|
+
if (pattern[end] === ']') end++;
|
|
155
|
+
while (end < pattern.length && pattern[end] !== ']') end++;
|
|
156
|
+
if (end === pattern.length) result += '\\[';
|
|
157
|
+
else {
|
|
158
|
+
let content = pattern.slice(index + 1, end);
|
|
159
|
+
if (content.includes('-')) {
|
|
160
|
+
const chunks = [];
|
|
161
|
+
let beginning = index + 1,
|
|
162
|
+
scan = beginning + (pattern[beginning] === '!' ? 2 : 1);
|
|
163
|
+
for (;;) {
|
|
164
|
+
const dash = pattern.indexOf('-', scan);
|
|
165
|
+
if (dash < 0 || dash >= end) break;
|
|
166
|
+
chunks.push(pattern.slice(beginning, dash));
|
|
167
|
+
beginning = dash + 1;
|
|
168
|
+
scan = dash + 3;
|
|
169
|
+
}
|
|
170
|
+
const tail = pattern.slice(beginning, end);
|
|
171
|
+
if (tail) chunks.push(tail);
|
|
172
|
+
else chunks[chunks.length - 1] += '-';
|
|
173
|
+
// Preserve the dataset's fnmatchcase handling of reversed/empty ranges.
|
|
174
|
+
for (let part = chunks.length - 1; part > 0; part--) {
|
|
175
|
+
if (chunks[part - 1].slice(-1) > chunks[part][0]) {
|
|
176
|
+
chunks[part - 1] = chunks[part - 1].slice(0, -1) + chunks[part].slice(1);
|
|
177
|
+
chunks.splice(part, 1);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
content = chunks
|
|
181
|
+
.map((chunk) => chunk.replaceAll('\\', '\\\\').replaceAll('-', '\\-'))
|
|
182
|
+
.join('-');
|
|
183
|
+
} else content = content.replaceAll('\\', '\\\\');
|
|
184
|
+
content = content.replace(/[&~|]/g, '\\$&');
|
|
185
|
+
if (!content) result += '(?!)';
|
|
186
|
+
else if (content === '!') result += '.';
|
|
187
|
+
else {
|
|
188
|
+
if (content[0] === '!') content = '^' + content.slice(1);
|
|
189
|
+
else if (['^', '['].includes(content[0])) content = '\\' + content;
|
|
190
|
+
result += `[${content}]`;
|
|
191
|
+
}
|
|
192
|
+
index = end;
|
|
193
|
+
}
|
|
194
|
+
} else result += char.replace(/[\\^$+?.()|{}\[\]]/g, '\\$&');
|
|
195
|
+
}
|
|
196
|
+
return new RegExp(result + '$', 's');
|
|
197
|
+
}
|
|
198
|
+
function sameToken(token, pattern, patterns) {
|
|
199
|
+
if (pattern.includes('*') && !patterns.has(pattern)) patterns.set(pattern, globRegex(pattern));
|
|
200
|
+
return (
|
|
201
|
+
token === pattern ||
|
|
202
|
+
(!pattern.includes('|') && token.split('|')[0] === pattern) ||
|
|
203
|
+
(pattern.includes('*') && patterns.get(pattern).test(token))
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
function roundScore(value) {
|
|
207
|
+
const scaled = value * 1000,
|
|
208
|
+
floor = Math.floor(scaled),
|
|
209
|
+
fraction = scaled - floor;
|
|
210
|
+
return (fraction === 0.5 ? floor + (floor % 2) : Math.round(scaled)) / 1000;
|
|
211
|
+
}
|
|
212
|
+
function scoreRecipeShape(input) {
|
|
213
|
+
const recipe = input.recipe;
|
|
214
|
+
if (!record(recipe) || !record(recipe.workflow) || !record(recipe.workflow.nodes))
|
|
215
|
+
throw new TypeError('Expected a Recipe v1 workflow.nodes object');
|
|
216
|
+
const catalog = input.catalog ?? { available: false, blocks: [], sources: [] };
|
|
217
|
+
const blocks = catalog.available ? (catalog.blocks ?? []) : [];
|
|
218
|
+
if (blocks.length > 2048 || utf8ToBytes(JSON.stringify(catalog)).length > 8 * 1024 * 1024)
|
|
219
|
+
throw new TypeError('Shape catalog exceeds 2048 blocks or 8 MiB');
|
|
220
|
+
const inspected = inspectRecipeShape(recipe),
|
|
221
|
+
nodes = recipe.workflow.nodes,
|
|
222
|
+
count = inspected.order.length;
|
|
223
|
+
const calls = inspected.order
|
|
224
|
+
.filter((id) => nodes[id].action === 'call')
|
|
225
|
+
.map((id) => nodes[id].ref);
|
|
226
|
+
const values = { templated: 0, literals: [] };
|
|
227
|
+
inspected.order.forEach((id) => nodeValues(nodes[id], id, values));
|
|
228
|
+
const positions = new Set(),
|
|
229
|
+
duplicates = [];
|
|
230
|
+
const patterns = new Map();
|
|
231
|
+
for (const block of blocks) {
|
|
232
|
+
const signature = block.sig ?? block.tokens ?? [];
|
|
233
|
+
if (!signature.length) continue;
|
|
234
|
+
for (let start = 0; start <= inspected.tokens.length - signature.length; start++) {
|
|
235
|
+
if (
|
|
236
|
+
!signature.every((token, offset) =>
|
|
237
|
+
sameToken(inspected.tokens[start + offset], token, patterns),
|
|
238
|
+
)
|
|
239
|
+
)
|
|
240
|
+
continue;
|
|
241
|
+
const span = Array.from({ length: signature.length }, (_, offset) => start + offset);
|
|
242
|
+
if (span.every((index) => positions.has(index))) continue;
|
|
243
|
+
span.forEach((index) => positions.add(index));
|
|
244
|
+
duplicates.push({
|
|
245
|
+
flow: block.id,
|
|
246
|
+
...(block.ref ? { ref: block.ref } : {}),
|
|
247
|
+
nodes: inspected.order.slice(start, start + signature.length),
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const short =
|
|
252
|
+
count <= POLICY.short.good
|
|
253
|
+
? 1
|
|
254
|
+
: Math.max(
|
|
255
|
+
0,
|
|
256
|
+
1 - (count - POLICY.short.good) / Math.max(1, POLICY.short.max - POLICY.short.good),
|
|
257
|
+
);
|
|
258
|
+
const composed = catalog.available ? (count ? 1 - positions.size / count : 1) : null;
|
|
259
|
+
const parameterized =
|
|
260
|
+
values.templated + values.literals.length
|
|
261
|
+
? values.templated / (values.templated + values.literals.length)
|
|
262
|
+
: 1;
|
|
263
|
+
const criteria = input.criteria ?? null,
|
|
264
|
+
declaredReview = new Set(
|
|
265
|
+
(recipe.proofTargets ?? [])
|
|
266
|
+
.filter((target) => target.proofMode === 'review')
|
|
267
|
+
.map((target) => target.id),
|
|
268
|
+
);
|
|
269
|
+
const expected = criteria?.map((criterion) => criterion.id) ?? [];
|
|
270
|
+
const reviewOnly =
|
|
271
|
+
criteria
|
|
272
|
+
?.filter((criterion) => criterion.proofMode === 'review' || declaredReview.has(criterion.id))
|
|
273
|
+
.map((criterion) => criterion.id) ?? [];
|
|
274
|
+
const proved = new Set(
|
|
275
|
+
inspected.reachable.flatMap((id) => [
|
|
276
|
+
...(Array.isArray(nodes[id].proves) ? nodes[id].proves : []),
|
|
277
|
+
...(nodes[id].action === 'call' && record(nodes[id].claimBindings)
|
|
278
|
+
? Object.values(nodes[id].claimBindings)
|
|
279
|
+
: []),
|
|
280
|
+
]),
|
|
281
|
+
);
|
|
282
|
+
const covered = expected.filter((id) => proved.has(id) && !reviewOnly.includes(id));
|
|
283
|
+
const missing = expected.filter((id) => !covered.includes(id));
|
|
284
|
+
const unexpected = [...proved].filter(
|
|
285
|
+
(id) => !expected.includes(id) && !(input.nonLocalCriteria ?? []).includes(id),
|
|
286
|
+
);
|
|
287
|
+
const hints = [];
|
|
288
|
+
if (parameterized < POLICY.positive.parameterized)
|
|
289
|
+
values.literals.forEach((field) =>
|
|
290
|
+
hints.push({
|
|
291
|
+
kind: 'parameterize',
|
|
292
|
+
field,
|
|
293
|
+
message: `Lift ${field} into typed paramsSchema/params and use a params template at that field.`,
|
|
294
|
+
}),
|
|
295
|
+
);
|
|
296
|
+
duplicates.forEach((duplicate) =>
|
|
297
|
+
hints.push({
|
|
298
|
+
kind: 'compose',
|
|
299
|
+
nodes: duplicate.nodes,
|
|
300
|
+
flow: duplicate.flow,
|
|
301
|
+
...(duplicate.ref ? { ref: duplicate.ref } : {}),
|
|
302
|
+
message: `Replace ${duplicate.nodes.join(', ')} with ${duplicate.ref ?? duplicate.flow}.`,
|
|
303
|
+
}),
|
|
304
|
+
);
|
|
305
|
+
if (short < POLICY.positive.short)
|
|
306
|
+
hints.push({
|
|
307
|
+
kind: 'shorten',
|
|
308
|
+
message: `${count} executable nodes exceed the shortness target; remove repeated setup or compose available blocks.`,
|
|
309
|
+
});
|
|
310
|
+
missing.forEach((id) =>
|
|
311
|
+
hints.push({
|
|
312
|
+
kind: 'acceptance',
|
|
313
|
+
criterionId: id,
|
|
314
|
+
message: reviewOnly.includes(id)
|
|
315
|
+
? `${id} requires review and cannot be recipe-proven; record this limitation, never add an invalid proves node.`
|
|
316
|
+
: `Bind a reachable qualifying proving node to registered ${id}.`,
|
|
317
|
+
}),
|
|
318
|
+
);
|
|
319
|
+
if (!expected.length)
|
|
320
|
+
hints.push({
|
|
321
|
+
kind: 'acceptance',
|
|
322
|
+
message:
|
|
323
|
+
'No registered worker AC set is available; this is not an AC-bearing task-proof candidate.',
|
|
324
|
+
});
|
|
325
|
+
if (!catalog.available)
|
|
326
|
+
hints.push({
|
|
327
|
+
kind: 'catalog',
|
|
328
|
+
message:
|
|
329
|
+
'Declared library catalog is unavailable; composition and imitation eligibility are unknown.',
|
|
330
|
+
});
|
|
331
|
+
const goodShape =
|
|
332
|
+
count > 0 &&
|
|
333
|
+
short >= POLICY.positive.short &&
|
|
334
|
+
composed !== null &&
|
|
335
|
+
composed >= POLICY.positive.composed &&
|
|
336
|
+
parameterized >= POLICY.positive.parameterized;
|
|
337
|
+
const acComplete =
|
|
338
|
+
criteria !== null && expected.length > 0 && missing.length === 0 && unexpected.length === 0;
|
|
339
|
+
return {
|
|
340
|
+
policyVersion: POLICY_VERSION,
|
|
341
|
+
inputIdentity: {
|
|
342
|
+
recipe: stableDigest(recipe),
|
|
343
|
+
criteria: stableDigest({ criteria, nonLocalCriteria: input.nonLocalCriteria ?? [] }),
|
|
344
|
+
catalog: stableDigest({
|
|
345
|
+
adapter: catalog.adapter ?? null,
|
|
346
|
+
available: catalog.available,
|
|
347
|
+
blocks: catalog.blocks ?? [],
|
|
348
|
+
sources: catalog.sources ?? [],
|
|
349
|
+
}),
|
|
350
|
+
},
|
|
351
|
+
nodes: count,
|
|
352
|
+
calls: calls.length,
|
|
353
|
+
templatedValues: values.templated,
|
|
354
|
+
literalValues: values.literals.length,
|
|
355
|
+
short: roundScore(short),
|
|
356
|
+
composed: composed === null ? null : roundScore(composed),
|
|
357
|
+
parameterized: roundScore(parameterized),
|
|
358
|
+
inlineDuplicates: duplicates,
|
|
359
|
+
goodShape,
|
|
360
|
+
acCoverage: {
|
|
361
|
+
nonLocal: input.nonLocalCriteria ?? [],
|
|
362
|
+
available: criteria !== null,
|
|
363
|
+
expected,
|
|
364
|
+
covered,
|
|
365
|
+
missing,
|
|
366
|
+
reviewOnly,
|
|
367
|
+
unexpected,
|
|
368
|
+
complete: acComplete,
|
|
369
|
+
},
|
|
370
|
+
eligibleForImitation: goodShape && acComplete,
|
|
371
|
+
catalogTrust: 'worker-supplied-self-consistent',
|
|
372
|
+
status:
|
|
373
|
+
!catalog.available || criteria === null
|
|
374
|
+
? 'unavailable'
|
|
375
|
+
: goodShape && acComplete
|
|
376
|
+
? 'ok'
|
|
377
|
+
: 'warn',
|
|
378
|
+
hints,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
function recipeShapeLibraryRef(name, relativePath, platforms = [], adapter) {
|
|
382
|
+
const portable = relativePath.replaceAll('\\', '/').replace(/^recipes\//, '');
|
|
383
|
+
// Offline catalogs may include every platform; a bound worker supplies its active adapter.
|
|
384
|
+
const inferred =
|
|
385
|
+
adapter ??
|
|
386
|
+
[...BUILT_IN_RECIPE_PLATFORMS, ...platforms].find(
|
|
387
|
+
(platform) =>
|
|
388
|
+
portable.startsWith(platform + '/') || portable.endsWith('.' + platform + '.recipe.json'),
|
|
389
|
+
);
|
|
390
|
+
const identity = recipeFileIdentity(portable, inferred, platforms);
|
|
391
|
+
if (!identity || 'error' in identity) return null;
|
|
392
|
+
return name ? `${name}.${identity.ref}` : identity.ref;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
function recipeShapeBlock(ref, recipe) {
|
|
396
|
+
const inspected = inspectRecipeShape(recipe);
|
|
397
|
+
const generic = new Set(['call', 'switch', 'wait', 'end', 'command']);
|
|
398
|
+
const changing = inspected.signature.filter(
|
|
399
|
+
(token) => !isRecipeShapeObservation(token.split('|')[0]),
|
|
400
|
+
);
|
|
401
|
+
if (
|
|
402
|
+
inspected.signature.length < 2 ||
|
|
403
|
+
!changing.some((token) => token.includes('|') || !generic.has(token))
|
|
404
|
+
)
|
|
405
|
+
return null;
|
|
406
|
+
return {
|
|
407
|
+
id: `flow:${ref}:${stableDigest(recipe).slice(0, 12)}`,
|
|
408
|
+
ref,
|
|
409
|
+
tokens: inspected.tokens,
|
|
410
|
+
sig: inspected.signature,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
function processShapeRequest(request) {
|
|
414
|
+
if (request.operation === 'policy') return { policyVersion: POLICY_VERSION, policy: POLICY };
|
|
415
|
+
if (request.operation === 'inspect') return inspectRecipeShape(request.recipe);
|
|
416
|
+
if (request.operation === 'selector') return recipeShapeSelector(request.node);
|
|
417
|
+
if (request.operation === 'token') return recipeShapeNodeToken(request.node);
|
|
418
|
+
if (request.operation === 'signature') return recipeShapeSignature(request.tokens);
|
|
419
|
+
if (request.operation === 'observation') return isRecipeShapeObservation(request.action);
|
|
420
|
+
if (request.operation === 'block')
|
|
421
|
+
return recipeShapeBlock(
|
|
422
|
+
request.ref ?? recipeShapeLibraryRef(request.name, request.relativePath, request.platforms),
|
|
423
|
+
request.recipe,
|
|
424
|
+
);
|
|
425
|
+
if (request.operation === 'digest') return stableDigest(request.value);
|
|
426
|
+
if (request.operation === 'criteria') {
|
|
427
|
+
return filterWorkerAcceptanceCriteria(
|
|
428
|
+
registeredAcceptanceCriteria(request.criteria ?? [], request.registration),
|
|
429
|
+
request.registration,
|
|
430
|
+
request.flow,
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
return scoreRecipeShape(request);
|
|
434
|
+
}
|
|
435
|
+
function isRecipeShapeFeedback(value) {
|
|
436
|
+
if (
|
|
437
|
+
!record(value) ||
|
|
438
|
+
!Number.isSafeInteger(value.policyVersion) ||
|
|
439
|
+
value.policyVersion < 1 ||
|
|
440
|
+
!record(value.inputIdentity) ||
|
|
441
|
+
!record(value.acCoverage)
|
|
442
|
+
)
|
|
443
|
+
return false;
|
|
444
|
+
if (
|
|
445
|
+
!['recipe', 'criteria', 'catalog'].every((key) =>
|
|
446
|
+
/^[a-f0-9]{64}$/.test(value.inputIdentity[key]),
|
|
447
|
+
)
|
|
448
|
+
)
|
|
449
|
+
return false;
|
|
450
|
+
if (
|
|
451
|
+
!['nodes', 'calls', 'templatedValues', 'literalValues'].every(
|
|
452
|
+
(key) => Number.isInteger(value[key]) && value[key] >= 0,
|
|
453
|
+
)
|
|
454
|
+
)
|
|
455
|
+
return false;
|
|
456
|
+
if (
|
|
457
|
+
!['short', 'parameterized'].every(
|
|
458
|
+
(key) => typeof value[key] === 'number' && value[key] >= 0 && value[key] <= 1,
|
|
459
|
+
)
|
|
460
|
+
)
|
|
461
|
+
return false;
|
|
462
|
+
if (
|
|
463
|
+
value.composed !== null &&
|
|
464
|
+
!(typeof value.composed === 'number' && value.composed >= 0 && value.composed <= 1)
|
|
465
|
+
)
|
|
466
|
+
return false;
|
|
467
|
+
if (
|
|
468
|
+
!['ok', 'warn', 'unavailable'].includes(value.status) ||
|
|
469
|
+
value.catalogTrust !== 'worker-supplied-self-consistent'
|
|
470
|
+
)
|
|
471
|
+
return false;
|
|
472
|
+
if (
|
|
473
|
+
typeof value.goodShape !== 'boolean' ||
|
|
474
|
+
typeof value.eligibleForImitation !== 'boolean' ||
|
|
475
|
+
!Array.isArray(value.inlineDuplicates) ||
|
|
476
|
+
!Array.isArray(value.hints)
|
|
477
|
+
)
|
|
478
|
+
return false;
|
|
479
|
+
if (
|
|
480
|
+
!value.inlineDuplicates.every(
|
|
481
|
+
(item) =>
|
|
482
|
+
record(item) &&
|
|
483
|
+
typeof item.flow === 'string' &&
|
|
484
|
+
(item.ref === undefined || typeof item.ref === 'string') &&
|
|
485
|
+
Array.isArray(item.nodes) &&
|
|
486
|
+
item.nodes.every((node) => typeof node === 'string'),
|
|
487
|
+
)
|
|
488
|
+
)
|
|
489
|
+
return false;
|
|
490
|
+
if (
|
|
491
|
+
!value.hints.every(
|
|
492
|
+
(item) =>
|
|
493
|
+
record(item) &&
|
|
494
|
+
['field', 'flow', 'ref', 'criterionId'].every(
|
|
495
|
+
(key) => item[key] === undefined || typeof item[key] === 'string',
|
|
496
|
+
) &&
|
|
497
|
+
(item.nodes === undefined ||
|
|
498
|
+
(Array.isArray(item.nodes) && item.nodes.every((node) => typeof node === 'string'))),
|
|
499
|
+
)
|
|
500
|
+
)
|
|
501
|
+
return false;
|
|
502
|
+
return (
|
|
503
|
+
typeof value.acCoverage.available === 'boolean' &&
|
|
504
|
+
typeof value.acCoverage.complete === 'boolean' &&
|
|
505
|
+
['expected', 'covered', 'missing', 'reviewOnly', 'unexpected', 'nonLocal'].every(
|
|
506
|
+
(key) =>
|
|
507
|
+
Array.isArray(value.acCoverage[key]) &&
|
|
508
|
+
value.acCoverage[key].every((id) => typeof id === 'string'),
|
|
509
|
+
) &&
|
|
510
|
+
value.hints.every(
|
|
511
|
+
(hint) =>
|
|
512
|
+
record(hint) &&
|
|
513
|
+
typeof hint.message === 'string' &&
|
|
514
|
+
['parameterize', 'compose', 'shorten', 'acceptance', 'catalog'].includes(hint.kind),
|
|
515
|
+
)
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
export {
|
|
519
|
+
inspectRecipeShape,
|
|
520
|
+
isRecipeShapeFeedback,
|
|
521
|
+
isRecipeShapeObservation,
|
|
522
|
+
POLICY_VERSION,
|
|
523
|
+
processShapeRequest,
|
|
524
|
+
POLICY as RECIPE_SHAPE_POLICY,
|
|
525
|
+
recipeShapeBlock,
|
|
526
|
+
recipeShapeLibraryRef,
|
|
527
|
+
recipeShapeNodeToken,
|
|
528
|
+
recipeShapeSelector,
|
|
529
|
+
recipeShapeSignature,
|
|
530
|
+
scoreRecipeShape,
|
|
531
|
+
stableDigest,
|
|
532
|
+
};
|
package/scripts/acceptance.d.mts
CHANGED
|
@@ -30,3 +30,9 @@ export function validateAcceptanceStatusLedger(value: unknown): string[];
|
|
|
30
30
|
export function acceptanceCriteriaView(criteria: readonly unknown[], ledger: unknown): unknown[];
|
|
31
31
|
export function summarizeAcceptanceStatus(ledger: unknown, criteria?: readonly unknown[]): unknown;
|
|
32
32
|
export function renderAcceptanceCoverage(ledger: unknown, criteria?: readonly unknown[]): string;
|
|
33
|
+
|
|
34
|
+
export function filterWorkerAcceptanceCriteria<T extends { id: string }>(
|
|
35
|
+
criteria: readonly T[],
|
|
36
|
+
registration: unknown,
|
|
37
|
+
flow: string,
|
|
38
|
+
): T[];
|
package/scripts/acceptance.mjs
CHANGED
|
@@ -18,6 +18,16 @@ function acceptanceCriterionId(index) {
|
|
|
18
18
|
return `AC-${index + 1}`;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
function filterWorkerAcceptanceCriteria(criteria, registration, flow) {
|
|
22
|
+
if (flow !== 'pr-complete') return [...criteria];
|
|
23
|
+
const derived = new Set(
|
|
24
|
+
(isRecord(registration) && Array.isArray(registration.derived) ? registration.derived : []).map(
|
|
25
|
+
(row) => row.id,
|
|
26
|
+
),
|
|
27
|
+
);
|
|
28
|
+
return criteria.filter((row) => derived.has(row.id));
|
|
29
|
+
}
|
|
30
|
+
|
|
21
31
|
function registeredAcceptanceCriteria(criteria, registration) {
|
|
22
32
|
const original = criteria
|
|
23
33
|
.filter((text) => String(text).trim().length > 0)
|
|
@@ -311,6 +321,7 @@ export {
|
|
|
311
321
|
acceptanceCriterionId,
|
|
312
322
|
acceptanceRowExecution,
|
|
313
323
|
acceptanceVerdictLabel,
|
|
324
|
+
filterWorkerAcceptanceCriteria,
|
|
314
325
|
INHERITED_ACCEPTANCE_INPUT,
|
|
315
326
|
registeredAcceptanceCriteria,
|
|
316
327
|
renderAcceptanceCoverage,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const BUILT_IN_RECIPE_PLATFORMS: readonly string[];
|
|
2
|
+
export interface RecipeFileIdentity {
|
|
3
|
+
ref: string;
|
|
4
|
+
adapter?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface RecipeFileIdentityError {
|
|
7
|
+
error: {
|
|
8
|
+
code: 'RECIPE_LIBRARY_ADAPTER_DECLARATION_CONFLICT' | 'RECIPE_LIBRARY_RECIPE_INVALID';
|
|
9
|
+
message: string;
|
|
10
|
+
recovery: string;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function recipeFileIdentity(
|
|
14
|
+
relativeFile: string,
|
|
15
|
+
adapter?: string,
|
|
16
|
+
platforms?: readonly string[],
|
|
17
|
+
): RecipeFileIdentity | RecipeFileIdentityError | undefined;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export const BUILT_IN_RECIPE_PLATFORMS = ['core', 'extension', 'mobile'];
|
|
2
|
+
const SUFFIX = '.recipe.json';
|
|
3
|
+
|
|
4
|
+
/** Resolver identity without filesystem access. Diagnostics keep caller-owned errors. */
|
|
5
|
+
export function recipeFileIdentity(relativeFile, adapter, platforms = []) {
|
|
6
|
+
const portable = relativeFile.replaceAll('\\', '/');
|
|
7
|
+
if (!portable.endsWith(SUFFIX)) return undefined;
|
|
8
|
+
const base = portable.slice(0, -SUFFIX.length);
|
|
9
|
+
const first = base.includes('/') ? base.slice(0, base.indexOf('/')) : undefined;
|
|
10
|
+
const adapters = new Set([
|
|
11
|
+
...BUILT_IN_RECIPE_PLATFORMS,
|
|
12
|
+
...platforms,
|
|
13
|
+
...(adapter ? [adapter] : []),
|
|
14
|
+
]);
|
|
15
|
+
const directoryAdapter = adapters.has(first) ? first : undefined;
|
|
16
|
+
const scope = first === 'shared' ? first : directoryAdapter;
|
|
17
|
+
const suffix = base.slice(base.lastIndexOf('.') + 1);
|
|
18
|
+
const filenameAdapter = BUILT_IN_RECIPE_PLATFORMS.includes(suffix) ? suffix : undefined;
|
|
19
|
+
if (scope && filenameAdapter)
|
|
20
|
+
return {
|
|
21
|
+
error: {
|
|
22
|
+
code: 'RECIPE_LIBRARY_ADAPTER_DECLARATION_CONFLICT',
|
|
23
|
+
message: `Library recipe recipes/${portable} declares ${scope} scope in its directory and ${filenameAdapter} adapter in its filename.`,
|
|
24
|
+
recovery:
|
|
25
|
+
'declare the adapter once using recipes/<adapter>/.../*.recipe.json, or use recipes/shared/.../*.recipe.json without an adapter suffix',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
const declaredAdapter = directoryAdapter ?? filenameAdapter;
|
|
29
|
+
const idPath = scope
|
|
30
|
+
? base.slice(scope.length + 1)
|
|
31
|
+
: filenameAdapter
|
|
32
|
+
? base.slice(0, -(filenameAdapter.length + 1))
|
|
33
|
+
: base;
|
|
34
|
+
if ((scope || declaredAdapter) && !idPath.trim())
|
|
35
|
+
return {
|
|
36
|
+
error: {
|
|
37
|
+
code: 'RECIPE_LIBRARY_RECIPE_INVALID',
|
|
38
|
+
message: `Library recipe recipes/${portable} declares ${declaredAdapter ? `adapter ${declaredAdapter}` : 'shared scope'} but has no recipe id.`,
|
|
39
|
+
recovery: `move it to recipes/${scope ?? declaredAdapter}/<name>.recipe.json`,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
if (declaredAdapter && declaredAdapter !== adapter) return undefined;
|
|
43
|
+
const ref = idPath.replaceAll('/', '.').trim();
|
|
44
|
+
return ref ? { ref, ...(declaredAdapter ? { adapter: declaredAdapter } : {}) } : undefined;
|
|
45
|
+
}
|