@llblab/pi-actors 0.37.1 → 0.38.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/BACKLOG.md +1 -1
- package/CHANGELOG.md +14 -0
- package/README.md +6 -5
- package/dist/index.js +23 -3
- package/dist/lib/async-runs.d.ts +5 -0
- package/dist/lib/async-runs.js +87 -8
- package/dist/lib/command-templates.d.ts +2 -0
- package/dist/lib/execution.d.ts +4 -0
- package/dist/lib/execution.js +154 -13
- package/dist/lib/model-context.d.ts +56 -0
- package/dist/lib/model-context.js +220 -0
- package/dist/lib/observability.d.ts +2 -0
- package/dist/lib/observability.js +32 -6
- package/dist/lib/preflight-diagnostics.d.ts +27 -0
- package/dist/lib/preflight-diagnostics.js +86 -0
- package/dist/lib/prompts.d.ts +1 -1
- package/dist/lib/prompts.js +2 -2
- package/dist/lib/recipes-context.d.ts +7 -0
- package/dist/lib/recipes-context.js +20 -2
- package/dist/lib/recipes-discovery.js +15 -0
- package/dist/lib/recipes-references.d.ts +2 -0
- package/dist/lib/recipes-references.js +10 -0
- package/dist/lib/tools-local.d.ts +2 -1
- package/dist/lib/tools-local.js +6 -4
- package/dist/lib/tools-response.js +22 -1
- package/dist/lib/tools-spawn.d.ts +2 -1
- package/dist/lib/tools-spawn.js +2 -1
- package/dist/recipes/lens-swarm.json +15 -2
- package/dist/recipes/pipeline-release-readiness.json +22 -3
- package/dist/recipes/pipeline-review-readiness.json +22 -3
- package/dist/recipes/subagent-judge.json +2 -1
- package/dist/recipes/subagent-merge.json +5 -2
- package/dist/recipes/subagent-normalize.json +2 -1
- package/dist/recipes/subagent-preflight.json +29 -0
- package/dist/recipes/subagent-review-coordinator.json +79 -7
- package/dist/recipes/subagent-review.json +2 -1
- package/dist/recipes/subagent-verify.json +2 -1
- package/dist/scripts/async-runner.mjs +84 -10
- package/dist/scripts/conformance.mjs +1 -0
- package/dist/skills/actors/SKILL.md +4 -4
- package/dist/skills/swarm/SKILL.md +2 -2
- package/docs/async-runs.md +3 -1
- package/docs/command-templates.md +4 -1
- package/docs/recipe-library.md +3 -2
- package/docs/template-recipes.md +2 -2
- package/index.ts +24 -3
- package/lib/async-runs.ts +157 -8
- package/lib/command-templates.ts +2 -0
- package/lib/execution.ts +218 -24
- package/lib/model-context.ts +359 -0
- package/lib/observability.ts +35 -6
- package/lib/preflight-diagnostics.ts +132 -0
- package/lib/prompts.ts +2 -2
- package/lib/recipes-context.ts +29 -2
- package/lib/recipes-discovery.ts +15 -0
- package/lib/recipes-references.ts +12 -0
- package/lib/tools-local.ts +22 -8
- package/lib/tools-response.ts +26 -1
- package/lib/tools-spawn.ts +6 -2
- package/package.json +1 -1
- package/recipes/lens-swarm.json +15 -2
- package/recipes/pipeline-release-readiness.json +22 -3
- package/recipes/pipeline-review-readiness.json +22 -3
- package/recipes/subagent-judge.json +2 -1
- package/recipes/subagent-merge.json +5 -2
- package/recipes/subagent-normalize.json +2 -1
- package/recipes/subagent-preflight.json +29 -0
- package/recipes/subagent-review-coordinator.json +79 -7
- package/recipes/subagent-review.json +2 -1
- package/recipes/subagent-verify.json +2 -1
- package/scripts/async-runner.mjs +84 -10
- package/scripts/conformance.mjs +1 -0
- package/skills/actors/SKILL.md +4 -4
- package/skills/swarm/SKILL.md +2 -2
|
@@ -30,6 +30,23 @@ export function compactNextActions(actions) {
|
|
|
30
30
|
function formatFailureCount(value) {
|
|
31
31
|
return Array.isArray(value) ? value.length : undefined;
|
|
32
32
|
}
|
|
33
|
+
function compactPolicyAxis(label, value) {
|
|
34
|
+
const axis = asRecord(value);
|
|
35
|
+
const source = typeof axis.source === "string" ? axis.source : undefined;
|
|
36
|
+
if (!source || source === "unused")
|
|
37
|
+
return undefined;
|
|
38
|
+
const renderedValue = typeof axis.value === "string" && axis.value.trim()
|
|
39
|
+
? `:${axis.value.trim()}`
|
|
40
|
+
: "";
|
|
41
|
+
return `${label}=${source}${renderedValue}`;
|
|
42
|
+
}
|
|
43
|
+
function compactModelPolicy(value) {
|
|
44
|
+
const policy = asRecord(value);
|
|
45
|
+
return [
|
|
46
|
+
compactPolicyAxis("model", policy.model),
|
|
47
|
+
compactPolicyAxis("thinking", policy.thinking),
|
|
48
|
+
].filter((token) => Boolean(token));
|
|
49
|
+
}
|
|
33
50
|
export function actorRunNextActions(run) {
|
|
34
51
|
const id = String(run ?? "").trim();
|
|
35
52
|
if (!id)
|
|
@@ -46,6 +63,7 @@ export function compactAsyncRunStatus(value) {
|
|
|
46
63
|
const result = asRecord(status.result);
|
|
47
64
|
const run = String(status.run ?? "<unknown>");
|
|
48
65
|
const tokens = [`run=${run}`, `status=${String(status.status ?? "unknown")}`];
|
|
66
|
+
tokens.push(...compactModelPolicy(status.model_policy ?? progress.model_policy));
|
|
49
67
|
if (status.tool)
|
|
50
68
|
tokens.push(`tool=${String(status.tool)}`);
|
|
51
69
|
if (status.recipe)
|
|
@@ -222,9 +240,12 @@ export function compactRecipeRegistry(summary) {
|
|
|
222
240
|
const recommendations = Array.isArray(summary.recommendations)
|
|
223
241
|
? summary.recommendations.length
|
|
224
242
|
: 0;
|
|
243
|
+
const currentPolicy = Array.isArray(summary.active)
|
|
244
|
+
? summary.active.filter((entry) => entry.current_policy).length
|
|
245
|
+
: 0;
|
|
225
246
|
const nextActions = Array.isArray(summary.next_actions)
|
|
226
247
|
? summary.next_actions
|
|
227
248
|
: [];
|
|
228
|
-
return `\nrecipes active=${active} drafts=${drafts} shadowed=${shadowed} invalid=${invalid} disabled=${disabled} recommendations=${recommendations} diagnostics=${diagnostics}${compactNextActions(nextActions)}`;
|
|
249
|
+
return `\nrecipes active=${active} drafts=${drafts} shadowed=${shadowed} invalid=${invalid} disabled=${disabled} current_policy=${currentPolicy} recommendations=${recommendations} diagnostics=${diagnostics}${compactNextActions(nextActions)}`;
|
|
229
250
|
}
|
|
230
251
|
export const DEFAULT_INSPECT_LINES = Limits.DEFAULT_INSPECT_LINES;
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Zones: actor launch, draft recipe capture, launch diagnostics
|
|
4
4
|
* Owns the public spawn execution path for run-backed actors
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
import * as ModelContext from "./model-context.ts";
|
|
7
|
+
export interface SpawnToolContext extends ModelContext.CurrentModelContext {
|
|
7
8
|
cwd: string;
|
|
8
9
|
sessionManager?: {
|
|
9
10
|
getSessionId?: () => string;
|
package/dist/lib/tools-spawn.js
CHANGED
|
@@ -7,6 +7,7 @@ import { mkdirSync, writeFileSync } from "node:fs";
|
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import * as AsyncRuns from "./async-runs.js";
|
|
9
9
|
import * as Messages from "./messages.js";
|
|
10
|
+
import * as ModelContext from "./model-context.js";
|
|
10
11
|
import * as Paths from "./paths.js";
|
|
11
12
|
import * as RecipesDiscovery from "./recipes-discovery.js";
|
|
12
13
|
import * as Rooms from "./rooms.js";
|
|
@@ -123,7 +124,7 @@ export function createSpawnToolDefinition() {
|
|
|
123
124
|
template: input.template,
|
|
124
125
|
}
|
|
125
126
|
: {}),
|
|
126
|
-
values: asRecord(input.values),
|
|
127
|
+
values: ModelContext.withCurrentModelValues(asRecord(input.values), ctx),
|
|
127
128
|
...(input.artifacts &&
|
|
128
129
|
typeof input.artifacts === "object" &&
|
|
129
130
|
!Array.isArray(input.artifacts)
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
"model:string",
|
|
11
11
|
"thinking:string",
|
|
12
12
|
"tools:string",
|
|
13
|
+
"subagent_ttl_ms:int",
|
|
14
|
+
"reviewer_concurrency:string",
|
|
15
|
+
"min_successful_reviewers:int",
|
|
16
|
+
"merge_policy:string",
|
|
13
17
|
"claim:string",
|
|
14
18
|
"evidence_policy:string",
|
|
15
19
|
"risk_policy:string",
|
|
@@ -21,12 +25,17 @@
|
|
|
21
25
|
"architecture",
|
|
22
26
|
"operator UX"
|
|
23
27
|
],
|
|
24
|
-
"
|
|
28
|
+
"model": "{current_model}",
|
|
29
|
+
"thinking": "{current_thinking}",
|
|
25
30
|
"tools": "",
|
|
31
|
+
"subagent_ttl_ms": 600000,
|
|
32
|
+
"reviewer_concurrency": "",
|
|
33
|
+
"min_successful_reviewers": 1,
|
|
34
|
+
"merge_policy": "Preserve partial reviewer reports, branch status, and degraded confidence markers. If reviewer evidence is below threshold, do not invent consensus.",
|
|
26
35
|
"claim": "The reviewed scope has clear, evidence-based findings, risks, and recommended next actions.",
|
|
27
36
|
"evidence_policy": "Cite inspected files, command outputs, or explicit uncertainty for every material claim.",
|
|
28
37
|
"risk_policy": "Preserve minority high-impact risks and ideas; separate confirmed issues from hypotheses.",
|
|
29
|
-
"output_format": "Markdown sections: Summary, Consensus Findings, Minority Findings, Verification, Judge Notes, Risks, Next Actions."
|
|
38
|
+
"output_format": "Markdown sections: Status (complete/degraded/insufficient_data), Summary, Consensus Findings, Minority Findings, Verification, Judge Notes, Risks, Next Actions."
|
|
30
39
|
},
|
|
31
40
|
"mailbox": {
|
|
32
41
|
"accepts": [
|
|
@@ -55,6 +64,10 @@
|
|
|
55
64
|
"judge_model": "{model}",
|
|
56
65
|
"thinking": "{thinking}",
|
|
57
66
|
"tools": "{tools}",
|
|
67
|
+
"subagent_ttl_ms": "{subagent_ttl_ms}",
|
|
68
|
+
"reviewer_concurrency": "{reviewer_concurrency}",
|
|
69
|
+
"min_successful_reviewers": "{min_successful_reviewers}",
|
|
70
|
+
"merge_policy": "{merge_policy}",
|
|
58
71
|
"evidence_policy": "{evidence_policy}",
|
|
59
72
|
"risk_policy": "{risk_policy}",
|
|
60
73
|
"output_format": "{output_format}"
|
|
@@ -20,7 +20,12 @@
|
|
|
20
20
|
"verifier_model:string",
|
|
21
21
|
"merger_model:string",
|
|
22
22
|
"judge_model:string",
|
|
23
|
-
"
|
|
23
|
+
"thinking:string",
|
|
24
|
+
"tools:string",
|
|
25
|
+
"subagent_ttl_ms:int",
|
|
26
|
+
"reviewer_concurrency:string",
|
|
27
|
+
"min_successful_reviewers:int",
|
|
28
|
+
"merge_policy:string"
|
|
24
29
|
],
|
|
25
30
|
"defaults": {
|
|
26
31
|
"scope": ".",
|
|
@@ -36,7 +41,16 @@
|
|
|
36
41
|
"documentation",
|
|
37
42
|
"packaged skills"
|
|
38
43
|
],
|
|
39
|
-
"
|
|
44
|
+
"reviewer_model": "{current_model}",
|
|
45
|
+
"verifier_model": "{current_model}",
|
|
46
|
+
"merger_model": "{current_model}",
|
|
47
|
+
"judge_model": "{current_model}",
|
|
48
|
+
"thinking": "{current_thinking}",
|
|
49
|
+
"tools": "",
|
|
50
|
+
"subagent_ttl_ms": 600000,
|
|
51
|
+
"reviewer_concurrency": "",
|
|
52
|
+
"min_successful_reviewers": 1,
|
|
53
|
+
"merge_policy": "Preserve partial reviewer reports, branch status, and degraded confidence markers. If reviewer evidence is below threshold, do not invent consensus."
|
|
40
54
|
},
|
|
41
55
|
"mailbox": {
|
|
42
56
|
"accepts": [
|
|
@@ -90,8 +104,13 @@
|
|
|
90
104
|
"verifier_model": "{verifier_model}",
|
|
91
105
|
"merger_model": "{merger_model}",
|
|
92
106
|
"judge_model": "{judge_model}",
|
|
107
|
+
"thinking": "{thinking}",
|
|
93
108
|
"tools": "{tools}",
|
|
94
|
-
"
|
|
109
|
+
"subagent_ttl_ms": "{subagent_ttl_ms}",
|
|
110
|
+
"reviewer_concurrency": "{reviewer_concurrency}",
|
|
111
|
+
"min_successful_reviewers": "{min_successful_reviewers}",
|
|
112
|
+
"merge_policy": "{merge_policy}",
|
|
113
|
+
"output_format": "Markdown sections: Status (complete/degraded/insufficient_data), Release Verdict, Blocking Issues, Package/Docs Risks, Validation Evidence, Publish Notes, Required Follow-up."
|
|
95
114
|
}
|
|
96
115
|
},
|
|
97
116
|
{
|
|
@@ -11,7 +11,12 @@
|
|
|
11
11
|
"verifier_model:string",
|
|
12
12
|
"merger_model:string",
|
|
13
13
|
"judge_model:string",
|
|
14
|
-
"
|
|
14
|
+
"thinking:string",
|
|
15
|
+
"tools:string",
|
|
16
|
+
"subagent_ttl_ms:int",
|
|
17
|
+
"reviewer_concurrency:string",
|
|
18
|
+
"min_successful_reviewers:int",
|
|
19
|
+
"merge_policy:string"
|
|
15
20
|
],
|
|
16
21
|
"defaults": {
|
|
17
22
|
"lenses": [
|
|
@@ -21,7 +26,16 @@
|
|
|
21
26
|
"operator UX"
|
|
22
27
|
],
|
|
23
28
|
"release_gate": "The scope is safe to ship or hand to the next release step.",
|
|
24
|
-
"
|
|
29
|
+
"reviewer_model": "{current_model}",
|
|
30
|
+
"verifier_model": "{current_model}",
|
|
31
|
+
"merger_model": "{current_model}",
|
|
32
|
+
"judge_model": "{current_model}",
|
|
33
|
+
"thinking": "{current_thinking}",
|
|
34
|
+
"tools": "",
|
|
35
|
+
"subagent_ttl_ms": 600000,
|
|
36
|
+
"reviewer_concurrency": "",
|
|
37
|
+
"min_successful_reviewers": 1,
|
|
38
|
+
"merge_policy": "Preserve partial reviewer reports, branch status, and degraded confidence markers. If reviewer evidence is below threshold, do not invent consensus."
|
|
25
39
|
},
|
|
26
40
|
"mailbox": {
|
|
27
41
|
"accepts": [
|
|
@@ -45,8 +59,13 @@
|
|
|
45
59
|
"verifier_model": "{verifier_model}",
|
|
46
60
|
"merger_model": "{merger_model}",
|
|
47
61
|
"judge_model": "{judge_model}",
|
|
62
|
+
"thinking": "{thinking}",
|
|
48
63
|
"tools": "{tools}",
|
|
49
|
-
"
|
|
64
|
+
"subagent_ttl_ms": "{subagent_ttl_ms}",
|
|
65
|
+
"reviewer_concurrency": "{reviewer_concurrency}",
|
|
66
|
+
"min_successful_reviewers": "{min_successful_reviewers}",
|
|
67
|
+
"merge_policy": "{merge_policy}",
|
|
68
|
+
"output_format": "Markdown sections: Status (complete/degraded/insufficient_data), Ship Verdict, Blocking Findings, Nonblocking Risks, Evidence, Required Follow-up."
|
|
50
69
|
}
|
|
51
70
|
}
|
|
52
71
|
}
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"rubric": "Judge evidence preservation, severity calibration, consensus purity, internal consistency, and merge bias.",
|
|
14
14
|
"evidence": "Use the provided raw outputs or artifact paths; mark any missing evidence.",
|
|
15
15
|
"output_format": "Markdown sections: Verdict, Issues, Evidence Preservation, Bias Risks, Required Fixes.",
|
|
16
|
-
"
|
|
16
|
+
"model": "{current_model}",
|
|
17
|
+
"thinking": "{current_thinking}",
|
|
17
18
|
"tools": ""
|
|
18
19
|
},
|
|
19
20
|
"mailbox": {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"args": [
|
|
4
4
|
"inputs:string",
|
|
5
5
|
"mode:enum(consensus-first,risk-first)",
|
|
6
|
+
"merge_policy:string",
|
|
6
7
|
"risk_policy:string",
|
|
7
8
|
"output_format:string",
|
|
8
9
|
"model:string",
|
|
@@ -11,9 +12,11 @@
|
|
|
11
12
|
],
|
|
12
13
|
"defaults": {
|
|
13
14
|
"mode": "consensus-first",
|
|
15
|
+
"merge_policy": "Preserve partial reviewer evidence, branch status, and degraded confidence markers.",
|
|
14
16
|
"risk_policy": "Preserve minority severe findings and mark merger-added claims explicitly.",
|
|
15
17
|
"output_format": "Markdown sections: Summary, Consensus, Minority Findings, Contradictions, Next Actions.",
|
|
16
|
-
"
|
|
18
|
+
"model": "{current_model}",
|
|
19
|
+
"thinking": "{current_thinking}",
|
|
17
20
|
"tools": ""
|
|
18
21
|
},
|
|
19
22
|
"mailbox": {
|
|
@@ -27,5 +30,5 @@
|
|
|
27
30
|
"run.failed"
|
|
28
31
|
]
|
|
29
32
|
},
|
|
30
|
-
"template": "pi -p --model {model} --thinking {thinking} {tools?--tools:--no-tools} {tools} Merge these subagent outputs using mode {mode}: {inputs}. Risk policy: {risk_policy}. Output format: {output_format}"
|
|
33
|
+
"template": "pi -p --model {model} --thinking {thinking} {tools?--tools:--no-tools} {tools} Merge these subagent outputs using mode {mode}: {inputs}. Merge policy: {merge_policy}. Risk policy: {risk_policy}. Output format: {output_format}"
|
|
31
34
|
}
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"defaults": {
|
|
12
12
|
"format": "Markdown sections: Summary, Findings, Evidence, Risks, Next Actions.",
|
|
13
13
|
"preservation_policy": "Do not change meaning, severity, evidence, or uncertainty while normalizing.",
|
|
14
|
-
"
|
|
14
|
+
"model": "{current_model}",
|
|
15
|
+
"thinking": "{current_thinking}",
|
|
15
16
|
"tools": ""
|
|
16
17
|
},
|
|
17
18
|
"mailbox": {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"async": true,
|
|
3
|
+
"args": [
|
|
4
|
+
"stage:string",
|
|
5
|
+
"model:string",
|
|
6
|
+
"thinking:string",
|
|
7
|
+
"tools:string",
|
|
8
|
+
"output_format:string"
|
|
9
|
+
],
|
|
10
|
+
"defaults": {
|
|
11
|
+
"stage": "subagent",
|
|
12
|
+
"model": "{current_model}",
|
|
13
|
+
"thinking": "{current_thinking}",
|
|
14
|
+
"tools": "",
|
|
15
|
+
"output_format": "Reply exactly: ACTOR_PREFLIGHT_OK"
|
|
16
|
+
},
|
|
17
|
+
"mailbox": {
|
|
18
|
+
"accepts": [
|
|
19
|
+
"control.kill"
|
|
20
|
+
],
|
|
21
|
+
"emits": [
|
|
22
|
+
"preflight.completed",
|
|
23
|
+
"command.done",
|
|
24
|
+
"run.done",
|
|
25
|
+
"run.failed"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"template": "pi -p --model {model} --thinking {thinking} {tools?--tools:--no-tools} {tools} Preflight check for stage {stage}. Confirm this model, thinking level, and tool policy can start before expensive fanout. Do not inspect files. {output_format}"
|
|
29
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"async": true,
|
|
3
3
|
"imports": {
|
|
4
|
+
"preflight": "subagent-preflight.json",
|
|
4
5
|
"reviewer": "subagent-review.json",
|
|
5
6
|
"verifier": "subagent-verify.json",
|
|
6
7
|
"merger": "subagent-merge.json",
|
|
@@ -17,6 +18,10 @@
|
|
|
17
18
|
"judge_model:string",
|
|
18
19
|
"thinking:string",
|
|
19
20
|
"tools:string",
|
|
21
|
+
"subagent_ttl_ms:int",
|
|
22
|
+
"reviewer_concurrency:string",
|
|
23
|
+
"min_successful_reviewers:int",
|
|
24
|
+
"merge_policy:string",
|
|
20
25
|
"evidence_policy:string",
|
|
21
26
|
"risk_policy:string",
|
|
22
27
|
"output_format:string"
|
|
@@ -28,11 +33,19 @@
|
|
|
28
33
|
"operator UX"
|
|
29
34
|
],
|
|
30
35
|
"claim": "The reviewed scope is ready for the next implementation or release step.",
|
|
31
|
-
"thinking": "
|
|
36
|
+
"thinking": "{current_thinking}",
|
|
32
37
|
"tools": "",
|
|
38
|
+
"subagent_ttl_ms": 600000,
|
|
39
|
+
"reviewer_concurrency": "",
|
|
40
|
+
"min_successful_reviewers": 1,
|
|
41
|
+
"merge_policy": "Preserve partial reviewer reports, branch status, and degraded confidence markers. If reviewer evidence is below threshold, do not invent consensus.",
|
|
33
42
|
"evidence_policy": "Cite inspected files, command output, or explicit uncertainty for every material claim.",
|
|
34
43
|
"risk_policy": "Preserve minority high-impact risks and separate confirmed issues from hypotheses.",
|
|
35
|
-
"output_format": "Markdown sections: Summary, Consensus Findings, Minority Findings, Verification, Judge Notes, Risks, Next Actions."
|
|
44
|
+
"output_format": "Markdown sections: Status (complete/degraded/insufficient_data), Summary, Consensus Findings, Minority Findings, Verification, Judge Notes, Risks, Next Actions.",
|
|
45
|
+
"reviewer_model": "{current_model}",
|
|
46
|
+
"verifier_model": "{current_model}",
|
|
47
|
+
"merger_model": "{current_model}",
|
|
48
|
+
"judge_model": "{current_model}"
|
|
36
49
|
},
|
|
37
50
|
"mailbox": {
|
|
38
51
|
"accepts": [
|
|
@@ -49,12 +62,65 @@
|
|
|
49
62
|
]
|
|
50
63
|
},
|
|
51
64
|
"template": [
|
|
65
|
+
{
|
|
66
|
+
"parallel": true,
|
|
67
|
+
"failure": "root",
|
|
68
|
+
"template": [
|
|
69
|
+
{
|
|
70
|
+
"label": "preflight:reviewer",
|
|
71
|
+
"name": "preflight",
|
|
72
|
+
"timeout": "{subagent_ttl_ms}",
|
|
73
|
+
"values": {
|
|
74
|
+
"stage": "reviewer",
|
|
75
|
+
"model": "{reviewer_model}",
|
|
76
|
+
"thinking": "{thinking}",
|
|
77
|
+
"tools": "{tools}"
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"label": "preflight:verifier",
|
|
82
|
+
"name": "preflight",
|
|
83
|
+
"timeout": "{subagent_ttl_ms}",
|
|
84
|
+
"values": {
|
|
85
|
+
"stage": "verifier",
|
|
86
|
+
"model": "{verifier_model}",
|
|
87
|
+
"thinking": "{thinking}",
|
|
88
|
+
"tools": "{tools}"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"label": "preflight:merger",
|
|
93
|
+
"name": "preflight",
|
|
94
|
+
"timeout": "{subagent_ttl_ms}",
|
|
95
|
+
"values": {
|
|
96
|
+
"stage": "merger",
|
|
97
|
+
"model": "{merger_model}",
|
|
98
|
+
"thinking": "{thinking}",
|
|
99
|
+
"tools": "{tools}"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"label": "preflight:judge",
|
|
104
|
+
"name": "preflight",
|
|
105
|
+
"timeout": "{subagent_ttl_ms}",
|
|
106
|
+
"values": {
|
|
107
|
+
"stage": "judge",
|
|
108
|
+
"model": "{judge_model}",
|
|
109
|
+
"thinking": "{thinking}",
|
|
110
|
+
"tools": "{tools}"
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
},
|
|
52
115
|
{
|
|
53
116
|
"parallel": true,
|
|
54
117
|
"repeat": "{lenses.length}",
|
|
118
|
+
"concurrency": "{reviewer_concurrency}",
|
|
119
|
+
"min_successful": "{min_successful_reviewers}",
|
|
55
120
|
"failure": "branch",
|
|
56
121
|
"template": {
|
|
57
122
|
"name": "reviewer",
|
|
123
|
+
"timeout": "{subagent_ttl_ms}",
|
|
58
124
|
"values": {
|
|
59
125
|
"scope": "{scope}",
|
|
60
126
|
"lens": "{lenses[index]}",
|
|
@@ -68,9 +134,10 @@
|
|
|
68
134
|
},
|
|
69
135
|
{
|
|
70
136
|
"name": "verifier",
|
|
137
|
+
"timeout": "{subagent_ttl_ms}",
|
|
71
138
|
"values": {
|
|
72
139
|
"claim": "{claim}",
|
|
73
|
-
"evidence": "Use previous reviewer outputs from stdin and named scope: {scope}.",
|
|
140
|
+
"evidence": "Use previous reviewer outputs from stdin and named scope: {scope}. Respect the parallel_status header and verify only against usable reviewer evidence.",
|
|
74
141
|
"model": "{verifier_model}",
|
|
75
142
|
"thinking": "{thinking}",
|
|
76
143
|
"tools": "{tools}",
|
|
@@ -79,32 +146,37 @@
|
|
|
79
146
|
},
|
|
80
147
|
{
|
|
81
148
|
"name": "merger",
|
|
149
|
+
"timeout": "{subagent_ttl_ms}",
|
|
82
150
|
"values": {
|
|
83
151
|
"inputs": "Use previous reviewer and verifier outputs from stdin.",
|
|
84
152
|
"mode": "consensus-first",
|
|
153
|
+
"merge_policy": "{merge_policy}",
|
|
85
154
|
"model": "{merger_model}",
|
|
86
|
-
"thinking": "
|
|
155
|
+
"thinking": "{thinking}",
|
|
87
156
|
"tools": "{tools}",
|
|
88
157
|
"risk_policy": "{risk_policy}"
|
|
89
158
|
}
|
|
90
159
|
},
|
|
91
160
|
{
|
|
92
161
|
"name": "judge",
|
|
162
|
+
"timeout": "{subagent_ttl_ms}",
|
|
93
163
|
"values": {
|
|
94
164
|
"report": "Use merged output from stdin.",
|
|
95
|
-
"evidence": "Use previous reviewer, verifier, and merger outputs from stdin.",
|
|
165
|
+
"evidence": "Use previous reviewer, verifier, and merger outputs from stdin. Preserve complete/degraded/insufficient_data status.",
|
|
96
166
|
"model": "{judge_model}",
|
|
97
|
-
"thinking": "
|
|
167
|
+
"thinking": "{thinking}",
|
|
98
168
|
"tools": "{tools}"
|
|
99
169
|
}
|
|
100
170
|
},
|
|
101
171
|
{
|
|
102
172
|
"name": "normalizer",
|
|
173
|
+
"timeout": "{subagent_ttl_ms}",
|
|
103
174
|
"values": {
|
|
104
175
|
"input": "Use merged and judged output from stdin.",
|
|
105
176
|
"format": "{output_format}",
|
|
177
|
+
"preservation_policy": "Preserve branch status and explicitly mark Status as complete, degraded, or insufficient_data.",
|
|
106
178
|
"model": "{merger_model}",
|
|
107
|
-
"thinking": "
|
|
179
|
+
"thinking": "{thinking}",
|
|
108
180
|
"tools": "{tools}"
|
|
109
181
|
}
|
|
110
182
|
}
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"evidence_policy": "Cite inspected files, command output, or explicit uncertainty for every material claim.",
|
|
18
18
|
"risk_policy": "Preserve minority high-impact risks and separate confirmed issues from hypotheses.",
|
|
19
19
|
"output_format": "Markdown sections: Findings, Evidence, Risks, Next Actions.",
|
|
20
|
-
"
|
|
20
|
+
"model": "{current_model}",
|
|
21
|
+
"thinking": "{current_thinking}",
|
|
21
22
|
"tools": ""
|
|
22
23
|
},
|
|
23
24
|
"mailbox": {
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"acceptance": "Separate proven, disproven, unknown, and missing evidence.",
|
|
15
15
|
"evidence_policy": "Do not infer beyond provided evidence or inspected artifacts.",
|
|
16
16
|
"output_format": "Markdown sections: Verdict, Evidence, Gaps, Confidence.",
|
|
17
|
-
"
|
|
17
|
+
"model": "{current_model}",
|
|
18
|
+
"thinking": "{current_thinking}",
|
|
18
19
|
"tools": ""
|
|
19
20
|
},
|
|
20
21
|
"mailbox": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* chasing a one-off lib entrypoint domain.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { appendFileSync, existsSync, readFileSync } from "node:fs";
|
|
11
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
12
12
|
import { dirname, join } from "node:path";
|
|
13
13
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
14
14
|
|
|
@@ -25,8 +25,10 @@ async function importRuntimeModule(name) {
|
|
|
25
25
|
);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const { appendRecipeContextToPiArgs } =
|
|
28
|
+
const { appendRecipeContextToPiArgs, materializePiPrintPromptArg } =
|
|
29
29
|
await importRuntimeModule("recipes-context");
|
|
30
|
+
const { buildReviewPreflightDiagnostic, formatReviewPreflightDiagnostic } =
|
|
31
|
+
await importRuntimeModule("preflight-diagnostics");
|
|
30
32
|
const { execCommandTemplate } = await importRuntimeModule("command-templates");
|
|
31
33
|
const { executeRegisteredTool } = await importRuntimeModule("execution");
|
|
32
34
|
const { writeJsonAtomic } = await importRuntimeModule("file-state");
|
|
@@ -75,6 +77,7 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
75
77
|
|
|
76
78
|
function progress(phase, extra = {}) {
|
|
77
79
|
writeJsonAtomic(progressPath, {
|
|
80
|
+
...(meta.model_policy ? { model_policy: meta.model_policy } : {}),
|
|
78
81
|
phase,
|
|
79
82
|
updatedAt: new Date().toISOString(),
|
|
80
83
|
...extra,
|
|
@@ -83,6 +86,7 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
83
86
|
|
|
84
87
|
let activeSubagents = 0;
|
|
85
88
|
let completedSubagents = 0;
|
|
89
|
+
let promptCounter = 0;
|
|
86
90
|
const subagentFailures = [];
|
|
87
91
|
|
|
88
92
|
function getCommandDoneDelivery(result) {
|
|
@@ -97,18 +101,65 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
97
101
|
});
|
|
98
102
|
}
|
|
99
103
|
|
|
104
|
+
function promptFilePath() {
|
|
105
|
+
promptCounter += 1;
|
|
106
|
+
const dir = join(stateDir, "prompts");
|
|
107
|
+
mkdirSync(dir, { recursive: true });
|
|
108
|
+
return join(dir, `command-${String(promptCounter).padStart(3, "0")}.md`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function readPromptText(promptFile) {
|
|
112
|
+
if (!promptFile) return undefined;
|
|
113
|
+
try {
|
|
114
|
+
return readFileSync(promptFile, "utf8");
|
|
115
|
+
} catch {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
100
120
|
async function observedExec(command, args, options) {
|
|
101
|
-
const
|
|
102
|
-
const execArgs = appendRecipeContextToPiArgs(
|
|
121
|
+
const contextArgs = appendRecipeContextToPiArgs(
|
|
103
122
|
command,
|
|
104
123
|
args,
|
|
105
124
|
meta.recipe_context_records,
|
|
106
125
|
options?.actorRecipeContext,
|
|
107
126
|
);
|
|
127
|
+
const materialized = materializePiPrintPromptArg(
|
|
128
|
+
command,
|
|
129
|
+
contextArgs,
|
|
130
|
+
promptFilePath,
|
|
131
|
+
);
|
|
132
|
+
const execArgs = materialized.args;
|
|
133
|
+
const commandDetail = formatCommandDetail(command, execArgs);
|
|
108
134
|
activeSubagents += 1;
|
|
109
|
-
event("command.start", {
|
|
135
|
+
event("command.start", {
|
|
136
|
+
activeSubagents,
|
|
137
|
+
command: commandDetail,
|
|
138
|
+
...(materialized.promptFile ? { prompt_file: materialized.promptFile } : {}),
|
|
139
|
+
...(materialized.promptBytes ? { prompt_bytes: materialized.promptBytes } : {}),
|
|
140
|
+
});
|
|
110
141
|
progressRunning();
|
|
111
|
-
|
|
142
|
+
let result = await execCommandTemplate(command, execArgs, options);
|
|
143
|
+
const preflightDiagnostic = result.code !== 0
|
|
144
|
+
? buildReviewPreflightDiagnostic({
|
|
145
|
+
args: execArgs,
|
|
146
|
+
code: result.code,
|
|
147
|
+
killed: result.killed,
|
|
148
|
+
...(materialized.promptFile ? { promptFile: materialized.promptFile } : {}),
|
|
149
|
+
promptText: readPromptText(materialized.promptFile),
|
|
150
|
+
stderr: result.stderr,
|
|
151
|
+
stdout: result.stdout,
|
|
152
|
+
})
|
|
153
|
+
: undefined;
|
|
154
|
+
if (preflightDiagnostic) {
|
|
155
|
+
result = {
|
|
156
|
+
...result,
|
|
157
|
+
stderr: [
|
|
158
|
+
result.stderr,
|
|
159
|
+
formatReviewPreflightDiagnostic(preflightDiagnostic),
|
|
160
|
+
].filter(Boolean).join("\n"),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
112
163
|
activeSubagents = Math.max(0, activeSubagents - 1);
|
|
113
164
|
completedSubagents += 1;
|
|
114
165
|
if (result.code !== 0) {
|
|
@@ -116,6 +167,8 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
116
167
|
code: result.code,
|
|
117
168
|
command: commandDetail,
|
|
118
169
|
killed: result.killed,
|
|
170
|
+
...(materialized.promptFile ? { prompt_file: materialized.promptFile } : {}),
|
|
171
|
+
...(preflightDiagnostic ? { preflight: preflightDiagnostic } : {}),
|
|
119
172
|
});
|
|
120
173
|
}
|
|
121
174
|
event("command.done", {
|
|
@@ -123,6 +176,9 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
123
176
|
code: result.code,
|
|
124
177
|
command: commandDetail,
|
|
125
178
|
killed: result.killed,
|
|
179
|
+
...(materialized.promptFile ? { prompt_file: materialized.promptFile } : {}),
|
|
180
|
+
...(materialized.promptBytes ? { prompt_bytes: materialized.promptBytes } : {}),
|
|
181
|
+
...(preflightDiagnostic ? { preflight: preflightDiagnostic } : {}),
|
|
126
182
|
});
|
|
127
183
|
outbox(
|
|
128
184
|
"command.done",
|
|
@@ -134,6 +190,9 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
134
190
|
code: result.code,
|
|
135
191
|
command: commandDetail,
|
|
136
192
|
killed: result.killed,
|
|
193
|
+
...(materialized.promptFile ? { prompt_file: materialized.promptFile } : {}),
|
|
194
|
+
...(materialized.promptBytes ? { prompt_bytes: materialized.promptBytes } : {}),
|
|
195
|
+
...(preflightDiagnostic ? { preflight: preflightDiagnostic } : {}),
|
|
137
196
|
},
|
|
138
197
|
getCommandDoneDelivery(result),
|
|
139
198
|
result.code === 0 ? "info" : "error",
|
|
@@ -163,6 +222,7 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
163
222
|
code: result.details.code,
|
|
164
223
|
command: result.details.command,
|
|
165
224
|
killed: result.details.killed,
|
|
225
|
+
...(meta.model_policy ? { model_policy: meta.model_policy } : {}),
|
|
166
226
|
truncated: result.details.truncated,
|
|
167
227
|
completedAt: new Date().toISOString(),
|
|
168
228
|
});
|
|
@@ -173,15 +233,29 @@ export async function runAsyncRunner(stateDir = process.argv[2]) {
|
|
|
173
233
|
event("run.done", { code: result.details.code });
|
|
174
234
|
} catch (error) {
|
|
175
235
|
const message = error instanceof Error ? error.message : String(error);
|
|
236
|
+
const details = error && typeof error === "object" ? error.details : undefined;
|
|
176
237
|
appendFileSync(stderrPath, `${message}\n`);
|
|
177
238
|
writeJsonAtomic(resultPath, {
|
|
178
|
-
code: 1,
|
|
239
|
+
code: typeof details?.code === "number" ? details.code : 1,
|
|
179
240
|
error: message,
|
|
180
|
-
killed:
|
|
241
|
+
killed: Boolean(details?.killed),
|
|
242
|
+
...(Array.isArray(details?.branches) ? { branches: details.branches } : {}),
|
|
243
|
+
...(details?.failureReason ? { failure_reason: details.failureReason } : {}),
|
|
244
|
+
...(meta.model_policy ? { model_policy: meta.model_policy } : {}),
|
|
245
|
+
...(details?.softQuorum ? { soft_quorum: details.softQuorum } : {}),
|
|
181
246
|
completedAt: new Date().toISOString(),
|
|
182
247
|
});
|
|
183
|
-
progress("failed", {
|
|
184
|
-
|
|
248
|
+
progress("failed", {
|
|
249
|
+
completed: 0,
|
|
250
|
+
failures: Array.isArray(details?.branches) && details.branches.length > 0
|
|
251
|
+
? details.branches
|
|
252
|
+
: [{ message }],
|
|
253
|
+
...(details?.failureReason ? { failureReason: details.failureReason } : {}),
|
|
254
|
+
});
|
|
255
|
+
event("run.failed", {
|
|
256
|
+
error: message,
|
|
257
|
+
...(details?.failureReason ? { failure_reason: details.failureReason } : {}),
|
|
258
|
+
});
|
|
185
259
|
throw error;
|
|
186
260
|
}
|
|
187
261
|
}
|
|
@@ -14,6 +14,7 @@ import { fileURLToPath } from "node:url";
|
|
|
14
14
|
const conformanceSuites = [
|
|
15
15
|
"tests/protocol-examples.test.ts",
|
|
16
16
|
"tests/recipes-discovery.test.ts",
|
|
17
|
+
"tests/review-swarm-dogfood.test.ts",
|
|
17
18
|
"tests/registry.test.ts",
|
|
18
19
|
"tests/runtime.test.ts",
|
|
19
20
|
"tests/async-runs.test.ts",
|