@farmslot/agent-runtime 0.18.1 → 0.19.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 +8 -0
- package/dist/execution-template/source-config.d.ts +6 -1
- package/dist/execution-template/source-config.d.ts.map +1 -1
- package/dist/execution-template/source-config.js +15 -1
- package/dist/execution-template/source-config.js.map +1 -1
- package/package.json +7 -2
- package/scripts/check-task-artifact-contract.mjs +17 -3
- package/scripts/retained-recipe-attempt.cjs +48 -0
- package/scripts/retained-recipe-attempt.d.cts +4 -0
- package/scripts/worker-terminal-contract.cjs +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Active-development baseline; add user-facing changes here before release or package publication.
|
|
6
|
+
|
|
7
|
+
## 0.19.0 - 2026-10-13
|
|
8
|
+
|
|
9
|
+
- Validate the current retained recipe attempt selected by the task pointer while keeping earlier packages intact.
|
|
10
|
+
- Resolve declared execution-template sources through an attested source binding.
|
|
11
|
+
- Accept the reviewer feedback path binding in template lint while retaining the required feedback artifact check.
|
|
12
|
+
|
|
5
13
|
## 0.18.1 - 2026-10-12
|
|
6
14
|
|
|
7
15
|
- Update shared runtime dependencies for bounded recipe log observations.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ProjectExecutionTemplatesConfig, UnavailableExecutionTemplateSource } from '@farmslot/protocol';
|
|
1
|
+
import type { ProjectExecutionTemplatesConfig, SourceEntryRef, UnavailableExecutionTemplateSource } from '@farmslot/protocol';
|
|
2
2
|
import type { ExecutionTemplateSource } from './types.js';
|
|
3
3
|
export type { UnavailableExecutionTemplateSource } from '@farmslot/protocol';
|
|
4
4
|
export interface ResolvedExecutionTemplateSources {
|
|
@@ -6,6 +6,11 @@ export interface ResolvedExecutionTemplateSources {
|
|
|
6
6
|
unavailable: UnavailableExecutionTemplateSource[];
|
|
7
7
|
}
|
|
8
8
|
export interface ResolveConfiguredExecutionTemplateSourcesOptions {
|
|
9
|
+
resolveSourceBinding?: (selection: SourceEntryRef) => {
|
|
10
|
+
root: string;
|
|
11
|
+
commit: string;
|
|
12
|
+
lockDigest: string;
|
|
13
|
+
};
|
|
9
14
|
projectPackRoot: string;
|
|
10
15
|
env?: NodeJS.ProcessEnv;
|
|
11
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-config.d.ts","sourceRoot":"","sources":["../../src/execution-template/source-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,+BAA+B,EAC/B,kCAAkC,EACnC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1D,YAAY,EAAE,kCAAkC,EAAE,MAAM,oBAAoB,CAAC;AAE7E,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,WAAW,EAAE,kCAAkC,EAAE,CAAC;CACnD;AAED,MAAM,WAAW,gDAAgD;IAC/D,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAUD,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQhF;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAO9E;
|
|
1
|
+
{"version":3,"file":"source-config.d.ts","sourceRoot":"","sources":["../../src/execution-template/source-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,+BAA+B,EAC/B,cAAc,EACd,kCAAkC,EACnC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1D,YAAY,EAAE,kCAAkC,EAAE,MAAM,oBAAoB,CAAC;AAE7E,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,WAAW,EAAE,kCAAkC,EAAE,CAAC;CACnD;AAED,MAAM,WAAW,gDAAgD;IAC/D,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,cAAc,KAAK;QACpD,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAUD,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQhF;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAO9E;AA2BD;;;GAGG;AACH,wBAAgB,yCAAyC,CACvD,MAAM,EAAE,+BAA+B,GAAG,SAAS,EACnD,OAAO,EAAE,gDAAgD,GACxD,gCAAgC,CAoDlC"}
|
|
@@ -26,7 +26,19 @@ export function executionTemplateSourceDirty(root) {
|
|
|
26
26
|
return result.stdout.trim().length > 0;
|
|
27
27
|
}
|
|
28
28
|
function configuredRoot(source, options) {
|
|
29
|
+
if (source.root.sourceId) {
|
|
30
|
+
if (!options.resolveSourceBinding)
|
|
31
|
+
return { reason: 'invalid-root' };
|
|
32
|
+
return {
|
|
33
|
+
path: options.resolveSourceBinding({
|
|
34
|
+
sourceId: source.root.sourceId,
|
|
35
|
+
entry: source.root.entry,
|
|
36
|
+
}).root,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
29
39
|
if (typeof source.root.env === 'string') {
|
|
40
|
+
if (options.resolveSourceBinding)
|
|
41
|
+
return { reason: 'invalid-root' };
|
|
30
42
|
const value = (options.env ?? process.env)[source.root.env]?.trim();
|
|
31
43
|
if (!value)
|
|
32
44
|
return { reason: 'missing-environment' };
|
|
@@ -34,7 +46,9 @@ function configuredRoot(source, options) {
|
|
|
34
46
|
return { reason: 'invalid-root' };
|
|
35
47
|
return { path: value };
|
|
36
48
|
}
|
|
37
|
-
return
|
|
49
|
+
return source.root.projectPath
|
|
50
|
+
? { path: path.resolve(options.projectPackRoot, source.root.projectPath) }
|
|
51
|
+
: { reason: 'invalid-root' };
|
|
38
52
|
}
|
|
39
53
|
/**
|
|
40
54
|
* Resolve optional configured sources only when catalog options are requested.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-config.js","sourceRoot":"","sources":["../../src/execution-template/source-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"source-config.js","sourceRoot":"","sources":["../../src/execution-template/source-config.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farmslot/agent-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
"./scripts/subtask-unit.cjs": "./scripts/subtask-unit.cjs",
|
|
22
22
|
"./scripts/worker-terminal-contract.cjs": "./scripts/worker-terminal-contract.cjs",
|
|
23
23
|
"./scripts/check-task-artifact-contract.mjs": "./scripts/check-task-artifact-contract.mjs",
|
|
24
|
+
"./scripts/retained-recipe-attempt.cjs": {
|
|
25
|
+
"types": "./scripts/retained-recipe-attempt.d.cts",
|
|
26
|
+
"default": "./scripts/retained-recipe-attempt.cjs"
|
|
27
|
+
},
|
|
24
28
|
"./scripts/execution-template-cli.mjs": "./scripts/execution-template-cli.mjs",
|
|
25
29
|
"./scripts/task-init-cli.mjs": "./scripts/task-init-cli.mjs",
|
|
26
30
|
"./native": {
|
|
@@ -45,7 +49,7 @@
|
|
|
45
49
|
"prepublishOnly": "node ../../scripts/quality/check-farmslot-package-readiness.mjs --publish --packages @farmslot/agent-runtime"
|
|
46
50
|
},
|
|
47
51
|
"dependencies": {
|
|
48
|
-
"@farmslot/protocol": "0.
|
|
52
|
+
"@farmslot/protocol": "0.41.0"
|
|
49
53
|
},
|
|
50
54
|
"devDependencies": {
|
|
51
55
|
"@types/node": "^22.0.0",
|
|
@@ -82,6 +86,7 @@
|
|
|
82
86
|
"dist/**/*.js.map",
|
|
83
87
|
"scripts/**/*.cjs",
|
|
84
88
|
"scripts/**/*.mjs",
|
|
89
|
+
"scripts/retained-recipe-attempt.d.cts",
|
|
85
90
|
"scripts/execution-template-cli.mjs"
|
|
86
91
|
],
|
|
87
92
|
"publishConfig": {
|
|
@@ -324,14 +324,28 @@ function validateRecipeDocumentArtifact() {
|
|
|
324
324
|
if (authoredRecipe === undefined) return;
|
|
325
325
|
validateRecipeDocumentValue(authoredRecipe, 'recipe.json', { skipRecipeCallResolution: true });
|
|
326
326
|
|
|
327
|
-
|
|
327
|
+
let packageRoot = 'artifacts/recipe-run';
|
|
328
|
+
const pointerValue = readJsonArtifact(
|
|
329
|
+
'artifacts/latest-valid-recipe-run.json',
|
|
330
|
+
'latest-valid-recipe-run.json',
|
|
331
|
+
);
|
|
332
|
+
if (pointerValue !== undefined) {
|
|
333
|
+
const pointer = recipeProtocol?.sanitizeLatestValidRecipeRunPointer?.(pointerValue);
|
|
334
|
+
if (!pointer) {
|
|
335
|
+
issues.push(
|
|
336
|
+
'latest-valid-recipe-run.json: invalid pointer or current @farmslot/protocol is unavailable',
|
|
337
|
+
);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
packageRoot = `artifacts/${pointer.relativeArtifactRoot}`;
|
|
341
|
+
}
|
|
328
342
|
const recipe = readJsonArtifact(`${packageRoot}/recipe.json`, 'recipe-run/recipe.json');
|
|
329
343
|
if (recipe === undefined) {
|
|
330
|
-
issues.push(
|
|
344
|
+
issues.push(`${packageRoot}/recipe.json is missing`);
|
|
331
345
|
return;
|
|
332
346
|
}
|
|
333
347
|
if (canonicalJson(authoredRecipe) !== canonicalJson(recipe)) {
|
|
334
|
-
issues.push(
|
|
348
|
+
issues.push(`${packageRoot}/recipe.json does not match artifacts/recipe.json`);
|
|
335
349
|
}
|
|
336
350
|
const manifest = readJsonArtifact(
|
|
337
351
|
`${packageRoot}/artifact-manifest.json`,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { randomUUID } = require('node:crypto');
|
|
4
|
+
const {
|
|
5
|
+
existsSync,
|
|
6
|
+
readFileSync,
|
|
7
|
+
realpathSync,
|
|
8
|
+
renameSync,
|
|
9
|
+
rmSync,
|
|
10
|
+
writeFileSync,
|
|
11
|
+
} = require('node:fs');
|
|
12
|
+
const path = require('node:path');
|
|
13
|
+
const { sanitizeLatestValidRecipeRunPointer } = require('@farmslot/protocol/recipe');
|
|
14
|
+
|
|
15
|
+
/** Advance task selection after success without changing any attempt bytes. */
|
|
16
|
+
function recordRecipeAttemptSelection(taskDir, artifactDir) {
|
|
17
|
+
const artifacts = realpathSync(path.join(taskDir, 'artifacts'));
|
|
18
|
+
const attempt = realpathSync(artifactDir);
|
|
19
|
+
const relative = path.relative(artifacts, attempt).split(path.sep).join('/');
|
|
20
|
+
const pointer = sanitizeLatestValidRecipeRunPointer({
|
|
21
|
+
version: 1,
|
|
22
|
+
relativeArtifactRoot: relative,
|
|
23
|
+
updatedAt: new Date().toISOString(),
|
|
24
|
+
});
|
|
25
|
+
if (!pointer) return false;
|
|
26
|
+
const summary = JSON.parse(readFileSync(path.join(attempt, 'summary.json'), 'utf8'));
|
|
27
|
+
if (summary.status !== 'pass') return false;
|
|
28
|
+
const destination = path.join(artifacts, 'latest-valid-recipe-run.json');
|
|
29
|
+
const temporary = `${destination}.${randomUUID()}.tmp`;
|
|
30
|
+
try {
|
|
31
|
+
writeFileSync(temporary, `${JSON.stringify(pointer)}\n`, { flag: 'wx', mode: 0o600 });
|
|
32
|
+
renameSync(temporary, destination);
|
|
33
|
+
} finally {
|
|
34
|
+
rmSync(temporary, { force: true });
|
|
35
|
+
}
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function readRecipeAttemptSelection(taskDir) {
|
|
40
|
+
const file = path.join(taskDir, 'artifacts', 'latest-valid-recipe-run.json');
|
|
41
|
+
if (!existsSync(file)) return null;
|
|
42
|
+
const pointer = sanitizeLatestValidRecipeRunPointer(JSON.parse(readFileSync(file, 'utf8')));
|
|
43
|
+
if (!pointer) throw new Error('Invalid retained recipe attempt selection.');
|
|
44
|
+
return pointer;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = { readRecipeAttemptSelection, recordRecipeAttemptSelection };
|
|
48
|
+
if (require.main === module) recordRecipeAttemptSelection(process.argv[2], process.argv[3]);
|
|
@@ -391,7 +391,10 @@ function lintWorkerTemplateAgainstContract(templateContent, contract) {
|
|
|
391
391
|
const spec = contract.commands[/** @type {WorkerTerminalCommand} */ (command)];
|
|
392
392
|
if (!spec) continue;
|
|
393
393
|
for (const artifactPath of spec.artifacts) {
|
|
394
|
-
|
|
394
|
+
const reviewerFeedbackBinding =
|
|
395
|
+
artifactPath === 'artifacts/review-feedback.md' &&
|
|
396
|
+
templateContent.includes('{{REVIEW_FEEDBACK}}');
|
|
397
|
+
if (!templateContent.includes(artifactPath) && !reviewerFeedbackBinding) {
|
|
395
398
|
issues.push(
|
|
396
399
|
`missing checklist/reference to required artifact \`${artifactPath}\` for \`${command}\``,
|
|
397
400
|
);
|