@llblab/pi-actors 0.37.0 → 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.
Files changed (74) hide show
  1. package/BACKLOG.md +1 -1
  2. package/CHANGELOG.md +19 -0
  3. package/README.md +6 -5
  4. package/dist/index.js +23 -3
  5. package/dist/lib/async-runs.d.ts +5 -0
  6. package/dist/lib/async-runs.js +87 -8
  7. package/dist/lib/command-templates.d.ts +2 -0
  8. package/dist/lib/execution.d.ts +4 -0
  9. package/dist/lib/execution.js +154 -13
  10. package/dist/lib/model-context.d.ts +56 -0
  11. package/dist/lib/model-context.js +220 -0
  12. package/dist/lib/observability.d.ts +2 -0
  13. package/dist/lib/observability.js +32 -6
  14. package/dist/lib/preflight-diagnostics.d.ts +27 -0
  15. package/dist/lib/preflight-diagnostics.js +86 -0
  16. package/dist/lib/prompts.d.ts +1 -1
  17. package/dist/lib/prompts.js +2 -2
  18. package/dist/lib/recipes-context.d.ts +7 -0
  19. package/dist/lib/recipes-context.js +75 -5
  20. package/dist/lib/recipes-discovery.js +15 -0
  21. package/dist/lib/recipes-references.d.ts +2 -0
  22. package/dist/lib/recipes-references.js +10 -0
  23. package/dist/lib/tools-local.d.ts +2 -1
  24. package/dist/lib/tools-local.js +6 -4
  25. package/dist/lib/tools-response.js +22 -1
  26. package/dist/lib/tools-spawn.d.ts +2 -1
  27. package/dist/lib/tools-spawn.js +2 -1
  28. package/dist/recipes/lens-swarm.json +15 -2
  29. package/dist/recipes/pipeline-release-readiness.json +22 -3
  30. package/dist/recipes/pipeline-review-readiness.json +22 -3
  31. package/dist/recipes/subagent-judge.json +2 -1
  32. package/dist/recipes/subagent-merge.json +5 -2
  33. package/dist/recipes/subagent-normalize.json +2 -1
  34. package/dist/recipes/subagent-preflight.json +29 -0
  35. package/dist/recipes/subagent-review-coordinator.json +79 -7
  36. package/dist/recipes/subagent-review.json +2 -1
  37. package/dist/recipes/subagent-verify.json +2 -1
  38. package/dist/scripts/async-runner.mjs +84 -10
  39. package/dist/scripts/conformance.mjs +1 -0
  40. package/dist/skills/actors/SKILL.md +5 -3
  41. package/dist/skills/swarm/SKILL.md +2 -2
  42. package/docs/async-runs.md +3 -1
  43. package/docs/command-templates.md +4 -1
  44. package/docs/recipe-library.md +5 -2
  45. package/docs/template-recipes.md +2 -2
  46. package/index.ts +24 -3
  47. package/lib/async-runs.ts +157 -8
  48. package/lib/command-templates.ts +2 -0
  49. package/lib/execution.ts +218 -24
  50. package/lib/model-context.ts +359 -0
  51. package/lib/observability.ts +35 -6
  52. package/lib/preflight-diagnostics.ts +132 -0
  53. package/lib/prompts.ts +2 -2
  54. package/lib/recipes-context.ts +86 -5
  55. package/lib/recipes-discovery.ts +15 -0
  56. package/lib/recipes-references.ts +12 -0
  57. package/lib/tools-local.ts +22 -8
  58. package/lib/tools-response.ts +26 -1
  59. package/lib/tools-spawn.ts +6 -2
  60. package/package.json +1 -1
  61. package/recipes/lens-swarm.json +15 -2
  62. package/recipes/pipeline-release-readiness.json +22 -3
  63. package/recipes/pipeline-review-readiness.json +22 -3
  64. package/recipes/subagent-judge.json +2 -1
  65. package/recipes/subagent-merge.json +5 -2
  66. package/recipes/subagent-normalize.json +2 -1
  67. package/recipes/subagent-preflight.json +29 -0
  68. package/recipes/subagent-review-coordinator.json +79 -7
  69. package/recipes/subagent-review.json +2 -1
  70. package/recipes/subagent-verify.json +2 -1
  71. package/scripts/async-runner.mjs +84 -10
  72. package/scripts/conformance.mjs +1 -0
  73. package/skills/actors/SKILL.md +5 -3
  74. package/skills/swarm/SKILL.md +2 -2
@@ -4,6 +4,7 @@
4
4
  * Owns compact actor recipe context records appended to child-agent prompts.
5
5
  */
6
6
 
7
+ import { writeFileSync } from "node:fs";
7
8
  import { basename } from "node:path";
8
9
 
9
10
  import type { CommandTemplateActorRecipeContext } from "./command-templates.ts";
@@ -22,14 +23,68 @@ function isPiCommand(command: string): boolean {
22
23
  return commandName(command) === "pi";
23
24
  }
24
25
 
25
- function findPrintPromptIndex(args: string[]): number | undefined {
26
+ const PI_PRINT_FLAGS = new Set(["-p", "--print"]);
27
+ const PI_VALUE_OPTIONS = new Set([
28
+ "--api-key",
29
+ "--append-system-prompt",
30
+ "--exclude-tools",
31
+ "--extension",
32
+ "--fork",
33
+ "--mode",
34
+ "--model",
35
+ "--models",
36
+ "--name",
37
+ "--prompt-template",
38
+ "--provider",
39
+ "--session",
40
+ "--session-dir",
41
+ "--skill",
42
+ "--system-prompt",
43
+ "--theme",
44
+ "--thinking",
45
+ "--tools",
46
+ ]);
47
+ const PI_SHORT_VALUE_OPTIONS = new Set(["-e", "-n", "-t", "-xt"]);
48
+
49
+ function isPiPrintFlag(arg: string): boolean {
50
+ return PI_PRINT_FLAGS.has(arg);
51
+ }
52
+
53
+ function isPiOption(arg: string): boolean {
54
+ return arg.startsWith("-") && arg !== "-";
55
+ }
56
+
57
+ function piOptionConsumesNextArg(arg: string): boolean {
58
+ if (arg.includes("=")) return false;
59
+ return PI_VALUE_OPTIONS.has(arg) || PI_SHORT_VALUE_OPTIONS.has(arg);
60
+ }
61
+
62
+ function isPiFileArgument(arg: string): boolean {
63
+ return arg.startsWith("@") && arg.length > 1;
64
+ }
65
+
66
+ export function findPiPrintPromptIndex(args: string[]): number | undefined {
67
+ let printMode = false;
68
+ let positionalOnly = false;
69
+ let promptIndex: number | undefined;
26
70
  for (let index = 0; index < args.length; index += 1) {
27
71
  const arg = args[index];
28
- if ((arg === "-p" || arg === "--print") && index + 1 < args.length) {
29
- return index + 1;
72
+ if (!positionalOnly && arg === "--") {
73
+ positionalOnly = true;
74
+ continue;
30
75
  }
76
+ if (!positionalOnly && isPiPrintFlag(arg)) {
77
+ printMode = true;
78
+ continue;
79
+ }
80
+ if (!positionalOnly && isPiOption(arg)) {
81
+ if (piOptionConsumesNextArg(arg)) index += 1;
82
+ continue;
83
+ }
84
+ if (!printMode || isPiFileArgument(arg)) continue;
85
+ promptIndex = index;
31
86
  }
32
- return undefined;
87
+ return promptIndex;
33
88
  }
34
89
 
35
90
  function matchesActorContext(
@@ -99,7 +154,7 @@ export function appendRecipeContextToPiArgs(
99
154
  context?: CommandTemplateActorRecipeContext,
100
155
  ): string[] {
101
156
  if (!records || records.length === 0 || !isPiCommand(command)) return args;
102
- const promptIndex = findPrintPromptIndex(args);
157
+ const promptIndex = findPiPrintPromptIndex(args);
103
158
  if (promptIndex === undefined) return args;
104
159
  const block = buildRecipeContextPromptBlock(records, context);
105
160
  if (!block) return args;
@@ -107,3 +162,29 @@ export function appendRecipeContextToPiArgs(
107
162
  next[promptIndex] = `${next[promptIndex]}\n\n${block}`;
108
163
  return next;
109
164
  }
165
+
166
+ export interface MaterializedPiPrintPromptArgs {
167
+ args: string[];
168
+ promptBytes?: number;
169
+ promptFile?: string;
170
+ }
171
+
172
+ export function materializePiPrintPromptArg(
173
+ command: string,
174
+ args: string[],
175
+ promptFile: string | (() => string),
176
+ ): MaterializedPiPrintPromptArgs {
177
+ if (!isPiCommand(command)) return { args };
178
+ const promptIndex = findPiPrintPromptIndex(args);
179
+ if (promptIndex === undefined) return { args };
180
+ const prompt = args[promptIndex];
181
+ const path = typeof promptFile === "function" ? promptFile() : promptFile;
182
+ writeFileSync(path, prompt, "utf8");
183
+ const next = [...args];
184
+ next[promptIndex] = `@${path}`;
185
+ return {
186
+ args: next,
187
+ promptBytes: Buffer.byteLength(prompt),
188
+ promptFile: path,
189
+ };
190
+ }
@@ -10,6 +10,7 @@ import { join } from "node:path";
10
10
 
11
11
  import * as CommandTemplates from "./command-templates.ts";
12
12
  import type { RegisteredTool } from "./config.ts";
13
+ import * as ModelContext from "./model-context.ts";
13
14
  import type { TemplateRecipeConfig } from "./recipes-references.ts";
14
15
  import * as RecipesReferences from "./recipes-references.ts";
15
16
  import * as Schema from "./schema.ts";
@@ -701,6 +702,20 @@ export function summarizeDiscovery(
701
702
  invalid: entry.invalid,
702
703
  shadows: entry.shadows,
703
704
  ...(entry.riskLabels.length ? { risk_labels: entry.riskLabels } : {}),
705
+ ...(entry.config &&
706
+ ModelContext.describeRecipeCurrentPolicy({
707
+ args: entry.config.args,
708
+ defaults: entry.config.defaults,
709
+ template: entry.config.template,
710
+ })
711
+ ? {
712
+ current_policy: ModelContext.describeRecipeCurrentPolicy({
713
+ args: entry.config.args,
714
+ defaults: entry.config.defaults,
715
+ template: entry.config.template,
716
+ }),
717
+ }
718
+ : {}),
704
719
  ...(entry.config?.imports ? { imports: entry.config.imports } : {}),
705
720
  ...(recipeUsage(entry.config)
706
721
  ? { usage: recipeUsage(entry.config) }
@@ -52,6 +52,8 @@ export interface TemplateRecipeDefinition {
52
52
  args?: string[];
53
53
  defaults?: Record<string, unknown>;
54
54
  parallel?: boolean;
55
+ concurrency?: number | string;
56
+ min_successful?: number | string;
55
57
  label?: string;
56
58
  when?: boolean | string;
57
59
  timeout?: number | string;
@@ -255,6 +257,8 @@ function getRecipeCommandTemplate(
255
257
  "args",
256
258
  "defaults",
257
259
  "parallel",
260
+ "concurrency",
261
+ "min_successful",
258
262
  "label",
259
263
  "when",
260
264
  "timeout",
@@ -1013,6 +1017,14 @@ export function readResolvedRecipeConfig(
1013
1017
  ...(typeof substituted.parallel === "boolean"
1014
1018
  ? { parallel: substituted.parallel }
1015
1019
  : {}),
1020
+ ...(typeof substituted.concurrency === "number" ||
1021
+ typeof substituted.concurrency === "string"
1022
+ ? { concurrency: substituted.concurrency }
1023
+ : {}),
1024
+ ...(typeof substituted.min_successful === "number" ||
1025
+ typeof substituted.min_successful === "string"
1026
+ ? { min_successful: substituted.min_successful }
1027
+ : {}),
1016
1028
  ...(typeof substituted.label === "string"
1017
1029
  ? { label: substituted.label }
1018
1030
  : {}),
@@ -7,6 +7,7 @@
7
7
  import * as Rooms from "./rooms.ts";
8
8
  import * as AsyncRuns from "./async-runs.ts";
9
9
  import * as CommandTemplates from "./command-templates.ts";
10
+ import * as ModelContext from "./model-context.ts";
10
11
  import type { RegisteredTool } from "./config.ts";
11
12
  import * as Execution from "./execution.ts";
12
13
  import * as Prompts from "./prompts.ts";
@@ -17,7 +18,7 @@ import * as ToolsResponse from "./tools-response.ts";
17
18
 
18
19
  type JsonSchema = Schema.JsonSchema;
19
20
 
20
- export interface RuntimeToolContext {
21
+ export interface RuntimeToolContext extends ModelContext.CurrentModelContext {
21
22
  cwd: string;
22
23
  sessionManager?: { getSessionId?: () => string };
23
24
  }
@@ -178,8 +179,15 @@ export function createRuntimeToolDefinition(
178
179
  ownerId: getRunOwnerId(ctx),
179
180
  run_id: runId,
180
181
  tool: cfg.name,
182
+ policy_values: ModelContext.withCurrentModelValues(
183
+ { ...(cfg.recipe?.values ?? {}), ...values },
184
+ ctx,
185
+ ),
181
186
  values: Schema.normalizeRuntimeValues(
182
- { ...(cfg.recipe?.values ?? {}), ...cfg.defaults, ...values },
187
+ ModelContext.withCurrentModelValues(
188
+ { ...(cfg.recipe?.values ?? {}), ...cfg.defaults, ...values },
189
+ ctx,
190
+ ),
183
191
  cfg.argTypes,
184
192
  ),
185
193
  },
@@ -198,11 +206,14 @@ export function createRuntimeToolDefinition(
198
206
  };
199
207
  }
200
208
  if (isRecipe && recipeTemplate) {
201
- const paramsWithDefaults = {
202
- ...(cfg.recipe?.values ?? {}),
203
- ...cfg.defaults,
204
- ...(params as Record<string, unknown>),
205
- };
209
+ const paramsWithDefaults = ModelContext.withCurrentModelValues(
210
+ {
211
+ ...(cfg.recipe?.values ?? {}),
212
+ ...cfg.defaults,
213
+ ...(params as Record<string, unknown>),
214
+ },
215
+ ctx,
216
+ );
206
217
  return await Execution.executeRegisteredTool(
207
218
  { ...cfg, template: recipeTemplate },
208
219
  Schema.normalizeRuntimeValues(paramsWithDefaults, cfg.argTypes),
@@ -214,7 +225,10 @@ export function createRuntimeToolDefinition(
214
225
  return await Execution.executeRegisteredTool(
215
226
  cfg,
216
227
  Schema.normalizeRuntimeValues(
217
- params as Record<string, unknown>,
228
+ ModelContext.withCurrentModelValues(
229
+ params as Record<string, unknown>,
230
+ ctx,
231
+ ),
218
232
  cfg.argTypes,
219
233
  ),
220
234
  exec,
@@ -40,6 +40,25 @@ function formatFailureCount(value: unknown): number | undefined {
40
40
  return Array.isArray(value) ? value.length : undefined;
41
41
  }
42
42
 
43
+ function compactPolicyAxis(label: string, value: unknown): string | undefined {
44
+ const axis = asRecord(value);
45
+ const source = typeof axis.source === "string" ? axis.source : undefined;
46
+ if (!source || source === "unused") return undefined;
47
+ const renderedValue =
48
+ typeof axis.value === "string" && axis.value.trim()
49
+ ? `:${axis.value.trim()}`
50
+ : "";
51
+ return `${label}=${source}${renderedValue}`;
52
+ }
53
+
54
+ function compactModelPolicy(value: unknown): string[] {
55
+ const policy = asRecord(value);
56
+ return [
57
+ compactPolicyAxis("model", policy.model),
58
+ compactPolicyAxis("thinking", policy.thinking),
59
+ ].filter((token): token is string => Boolean(token));
60
+ }
61
+
43
62
  export function actorRunNextActions(run: unknown): string[] {
44
63
  const id = String(run ?? "").trim();
45
64
  if (!id) return [];
@@ -56,6 +75,7 @@ export function compactAsyncRunStatus(value: unknown): string {
56
75
  const result = asRecord(status.result);
57
76
  const run = String(status.run ?? "<unknown>");
58
77
  const tokens = [`run=${run}`, `status=${String(status.status ?? "unknown")}`];
78
+ tokens.push(...compactModelPolicy(status.model_policy ?? progress.model_policy));
59
79
  if (status.tool) tokens.push(`tool=${String(status.tool)}`);
60
80
  if (status.recipe) tokens.push(`recipe=${String(status.recipe)}`);
61
81
  if (status.retire_when)
@@ -272,10 +292,15 @@ export function compactRecipeRegistry(
272
292
  const recommendations = Array.isArray(summary.recommendations)
273
293
  ? summary.recommendations.length
274
294
  : 0;
295
+ const currentPolicy = Array.isArray(summary.active)
296
+ ? (summary.active as Array<Record<string, unknown>>).filter(
297
+ (entry) => entry.current_policy,
298
+ ).length
299
+ : 0;
275
300
  const nextActions = Array.isArray(summary.next_actions)
276
301
  ? (summary.next_actions as string[])
277
302
  : [];
278
- return `\nrecipes active=${active} drafts=${drafts} shadowed=${shadowed} invalid=${invalid} disabled=${disabled} recommendations=${recommendations} diagnostics=${diagnostics}${compactNextActions(nextActions)}`;
303
+ return `\nrecipes active=${active} drafts=${drafts} shadowed=${shadowed} invalid=${invalid} disabled=${disabled} current_policy=${currentPolicy} recommendations=${recommendations} diagnostics=${diagnostics}${compactNextActions(nextActions)}`;
279
304
  }
280
305
 
281
306
  export const DEFAULT_INSPECT_LINES = Limits.DEFAULT_INSPECT_LINES;
@@ -9,13 +9,14 @@ import { join } from "node:path";
9
9
 
10
10
  import * as AsyncRuns from "./async-runs.ts";
11
11
  import * as Messages from "./messages.ts";
12
+ import * as ModelContext from "./model-context.ts";
12
13
  import * as Paths from "./paths.ts";
13
14
  import * as RecipesDiscovery from "./recipes-discovery.ts";
14
15
  import * as Rooms from "./rooms.ts";
15
16
  import * as Schema from "./schema.ts";
16
17
  import * as ToolsResponse from "./tools-response.ts";
17
18
 
18
- export interface SpawnToolContext {
19
+ export interface SpawnToolContext extends ModelContext.CurrentModelContext {
19
20
  cwd: string;
20
21
  sessionManager?: { getSessionId?: () => string };
21
22
  }
@@ -196,7 +197,10 @@ export function createSpawnToolDefinition<
196
197
  input.template as AsyncRuns.AsyncRunStartParams["template"],
197
198
  }
198
199
  : {}),
199
- values: asRecord(input.values),
200
+ values: ModelContext.withCurrentModelValues(
201
+ asRecord(input.values),
202
+ ctx,
203
+ ),
200
204
  ...(input.artifacts &&
201
205
  typeof input.artifacts === "object" &&
202
206
  !Array.isArray(input.artifacts)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-actors",
3
- "version": "0.37.0",
3
+ "version": "0.38.0",
4
4
  "private": false,
5
5
  "description": "Local Actor Kernel for Pi",
6
6
  "keywords": [
@@ -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
- "thinking": "off",
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
- "tools:string"
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
- "tools": ""
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
- "output_format": "Markdown sections: Release Verdict, Blocking Issues, Package/Docs Risks, Validation Evidence, Publish Notes, Required Follow-up."
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
- "tools:string"
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
- "tools": ""
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
- "output_format": "Markdown sections: Ship Verdict, Blocking Findings, Nonblocking Risks, Evidence, Required Follow-up."
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
- "thinking": "medium",
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
- "thinking": "medium",
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
- "thinking": "off",
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
+ }