@oisincoveney/pipeline 2.3.1 → 2.5.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/.agents/skills/orchestrate/SKILL.md +12 -0
- package/defaults/pipeline.yaml +7 -0
- package/dist/config/load.js +1 -0
- package/dist/config/schemas.d.ts +31 -9
- package/dist/config/schemas.js +41 -0
- package/dist/config/validate.js +16 -0
- package/dist/model-resolver.js +30 -9
- package/dist/moka-submit.d.ts +7 -7
- package/dist/pipeline-runtime.js +1 -0
- package/dist/planning/compile.d.ts +1 -0
- package/dist/planning/compile.js +4 -0
- package/dist/planning/generate.d.ts +4 -0
- package/dist/planning/generate.js +3 -1
- package/dist/runner-command-contract.d.ts +2 -2
- package/dist/runner-event-schema.d.ts +6 -6
- package/dist/runtime/agent-node/agent-node.js +106 -4
- package/dist/runtime/builtins/builtins.js +2 -0
- package/dist/runtime/handoff.d.ts +1 -0
- package/dist/runtime/handoff.js +91 -0
- package/dist/runtime/node-state-store.js +9 -0
- package/dist/runtime/opencode-session-executor.js +5 -2
- package/dist/runtime/parallel-node/parallel-node.js +36 -3
- package/dist/runtime/parallel-worktrees/parallel-worktrees.js +132 -0
- package/dist/runtime/scheduler.js +48 -1
- package/dist/runtime/select-candidate/select-candidate.js +58 -0
- package/dist/schedule/passes/candidates.js +42 -0
- package/dist/schedule/passes/index.js +1 -0
- package/dist/schedule/passes/models.js +8 -4
- package/dist/schedule/prompts.js +15 -0
- package/dist/token-estimator.js +23 -0
- package/package.json +2 -1
|
@@ -70,6 +70,18 @@ Whichever host you are on, run the same six steps:
|
|
|
70
70
|
5. **Learn** — Once the gates pass, run `MoKa Learner` to store durable lessons from the run (qdrant memory) when there is something worth reusing. This mirrors the canonical pipeline's LEARN phase; skip it only when the run produced nothing reusable.
|
|
71
71
|
6. **Synthesize** — Report only the evidence the agents actually returned: what passed, what the diff is, what the reviewers proved. Never fabricate or assume an outcome an agent did not report.
|
|
72
72
|
|
|
73
|
+
## Task sizing, reliability & token budget
|
|
74
|
+
|
|
75
|
+
Token usage is the dominant cost and quality lever — it explains the bulk of agent performance variance, and context degrades well before a model's window fills. But the first job of sizing is **reliable completion**: a lane an agent can't finish is worthless however cheap. Size the work accordingly:
|
|
76
|
+
|
|
77
|
+
- **Size for reliable completion first.** Each lane must be small enough that a single agent session finishes it cleanly. If an agent times out, stalls, or returns having only *planned* without producing its artifact, the lane was **too big** — split it into smaller lanes (one file, section, or concern each); do **not** just raise the timeout, that re-runs the same flake. **Slow is fine; flaky is not** — many small lanes that each reliably complete beat one big lane that gambles. Lanes that share a file run sequentially; only truly independent lanes fan out. Treat repeated stalls as a decomposition bug, not bad luck.
|
|
78
|
+
- **Under-timeouts and permission walls are the real flake sources — not a step cap.** Per opencode's docs, an agent with no `steps`/`maxSteps` set "will continue to iterate until the model chooses to stop or the user interrupts the session" — i.e. **no hard step budget by default** (the MoKa agents set none). So a Code Writer that returns having only *planned* was not hitting a step limit; it was killed by too short a dispatch timeout or blocked on a denied read (e.g. `external_directory: deny`). Fixes: give long multi-file authoring runs **generous wall-clock** (do not kill them early — they are slow, not capped); scope lanes so they don't need denied/external reads; and only if you must *bound* a runaway agent, set `steps` in its config. Smaller lanes still help (less work = faster, fewer surprises), but "multi-file authoring can't be delegated" is a timeout/scoping issue, not an opencode limit.
|
|
79
|
+
- **Scale fan-out to complexity, not ambition.** A trivial change is one agent (or just do it inline); a bounded change is 1–3 lanes; only go wide for genuinely independent breadth. Code parallelizes poorly — keep writer lanes narrow (the pipeline caps `green`/code fan-out at 2 for exactly this reason).
|
|
80
|
+
- **Keep each agent's context small and high-signal.** Pass context by path and hand over the distilled `research.json`, never raw repo dumps. A lane that needs half the repo in its context is mis-scoped — split it.
|
|
81
|
+
- **Distilled returns.** Expect each sub-agent to return a ~1–2k-token summary of its result, not its full transcript. Gather the summary; don't re-read the work.
|
|
82
|
+
- **Re-dispatch once, with evidence.** On a gate `FAIL`, re-dispatch the failing lane a *single* time with concentrated failure evidence — do not thrash. Each fresh `opencode run` re-pays the full cold-start context tax (~35k tokens of standup before any work), so a retry loop is expensive; fix the input, not the dice.
|
|
83
|
+
- **Smallest roster that covers the work.** Every extra lane is another cold standup. Default to the fewest specialists that close the task; add a lane only when it genuinely runs independently.
|
|
84
|
+
|
|
73
85
|
## Rules
|
|
74
86
|
|
|
75
87
|
- **Doctrine is host-neutral; only the Dispatch section is host-specific.** Do not leak `opencode run` syntax into an OpenCode run or Task-tool talk into a Claude run.
|
package/defaults/pipeline.yaml
CHANGED
|
@@ -2,6 +2,13 @@ version: 1
|
|
|
2
2
|
default_workflow: inspect
|
|
3
3
|
orchestrator:
|
|
4
4
|
profile: moka-orchestrator
|
|
5
|
+
token_budget:
|
|
6
|
+
default_context_window: 200000
|
|
7
|
+
max_context_pct: 50
|
|
8
|
+
fan_out_width:
|
|
9
|
+
default: 4
|
|
10
|
+
by_category:
|
|
11
|
+
green: 2
|
|
5
12
|
entrypoints:
|
|
6
13
|
quick:
|
|
7
14
|
schedule: quick-schedule
|
package/dist/config/load.js
CHANGED
|
@@ -51,6 +51,7 @@ function parsePipelineConfigParts(sources, projectRoot, sourcePaths = {
|
|
|
51
51
|
schedules: pipeline.schedules,
|
|
52
52
|
skills: profiles.skills,
|
|
53
53
|
...pipeline.task_context ? { task_context: pipeline.task_context } : {},
|
|
54
|
+
token_budget: pipeline.token_budget,
|
|
54
55
|
version: 1,
|
|
55
56
|
workflows: pipeline.workflows
|
|
56
57
|
}, projectRoot, options);
|
package/dist/config/schemas.d.ts
CHANGED
|
@@ -116,6 +116,7 @@ declare const workflowNodeBaseSchema: z.ZodObject<{
|
|
|
116
116
|
}, z.core.$strip>;
|
|
117
117
|
type WorkflowNodeBase = z.infer<typeof workflowNodeBaseSchema>;
|
|
118
118
|
type AgentWorkflowNode = WorkflowNodeBase & {
|
|
119
|
+
category?: string;
|
|
119
120
|
kind: "agent";
|
|
120
121
|
profile: string;
|
|
121
122
|
};
|
|
@@ -220,8 +221,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
220
221
|
policy: z.ZodOptional<z.ZodObject<{
|
|
221
222
|
commands: z.ZodOptional<z.ZodEnum<{
|
|
222
223
|
allow: "allow";
|
|
223
|
-
deny: "deny";
|
|
224
224
|
"trusted-only": "trusted-only";
|
|
225
|
+
deny: "deny";
|
|
225
226
|
}>>;
|
|
226
227
|
modules: z.ZodOptional<z.ZodEnum<{
|
|
227
228
|
allow: "allow";
|
|
@@ -245,8 +246,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
245
246
|
}, z.core.$strict>>>;
|
|
246
247
|
default_profile: z.ZodOptional<z.ZodString>;
|
|
247
248
|
mode: z.ZodEnum<{
|
|
248
|
-
local: "local";
|
|
249
249
|
hosted: "hosted";
|
|
250
|
+
local: "local";
|
|
250
251
|
}>;
|
|
251
252
|
provider: z.ZodLiteral<"toolhive">;
|
|
252
253
|
authorization_env: z.ZodDefault<z.ZodString>;
|
|
@@ -289,10 +290,10 @@ declare const configSchema: z.ZodObject<{
|
|
|
289
290
|
}, z.core.$strict>>;
|
|
290
291
|
output: z.ZodOptional<z.ZodObject<{
|
|
291
292
|
format: z.ZodEnum<{
|
|
292
|
-
json_schema: "json_schema";
|
|
293
293
|
text: "text";
|
|
294
294
|
json: "json";
|
|
295
295
|
jsonl: "jsonl";
|
|
296
|
+
json_schema: "json_schema";
|
|
296
297
|
}>;
|
|
297
298
|
repair: z.ZodOptional<z.ZodObject<{
|
|
298
299
|
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -310,7 +311,6 @@ declare const configSchema: z.ZodObject<{
|
|
|
310
311
|
skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
311
312
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
312
313
|
tools: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
313
|
-
task: "task";
|
|
314
314
|
read: "read";
|
|
315
315
|
list: "list";
|
|
316
316
|
grep: "grep";
|
|
@@ -318,6 +318,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
318
318
|
bash: "bash";
|
|
319
319
|
edit: "edit";
|
|
320
320
|
write: "write";
|
|
321
|
+
task: "task";
|
|
321
322
|
}>>>;
|
|
322
323
|
}, z.core.$strict>>>;
|
|
323
324
|
runner_command: z.ZodDefault<z.ZodObject<{
|
|
@@ -343,8 +344,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
343
344
|
rules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
344
345
|
path: z.ZodString;
|
|
345
346
|
source_root: z.ZodDefault<z.ZodEnum<{
|
|
346
|
-
project: "project";
|
|
347
347
|
package: "package";
|
|
348
|
+
project: "project";
|
|
348
349
|
}>>;
|
|
349
350
|
}, z.core.$strict>>>;
|
|
350
351
|
runners: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
@@ -361,15 +362,14 @@ declare const configSchema: z.ZodObject<{
|
|
|
361
362
|
disabled: "disabled";
|
|
362
363
|
}>>>;
|
|
363
364
|
output_formats: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
364
|
-
json_schema: "json_schema";
|
|
365
365
|
text: "text";
|
|
366
366
|
json: "json";
|
|
367
367
|
jsonl: "jsonl";
|
|
368
|
+
json_schema: "json_schema";
|
|
368
369
|
}>>>;
|
|
369
370
|
rules: z.ZodOptional<z.ZodBoolean>;
|
|
370
371
|
skills: z.ZodOptional<z.ZodBoolean>;
|
|
371
372
|
tools: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
372
|
-
task: "task";
|
|
373
373
|
read: "read";
|
|
374
374
|
list: "list";
|
|
375
375
|
grep: "grep";
|
|
@@ -377,6 +377,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
377
377
|
bash: "bash";
|
|
378
378
|
edit: "edit";
|
|
379
379
|
write: "write";
|
|
380
|
+
task: "task";
|
|
380
381
|
}>>>;
|
|
381
382
|
}, z.core.$strict>;
|
|
382
383
|
command: z.ZodOptional<z.ZodString>;
|
|
@@ -471,8 +472,8 @@ declare const configSchema: z.ZodObject<{
|
|
|
471
472
|
schedules: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
472
473
|
description: z.ZodOptional<z.ZodString>;
|
|
473
474
|
baseline: z.ZodEnum<{
|
|
474
|
-
quick: "quick";
|
|
475
475
|
execute: "execute";
|
|
476
|
+
quick: "quick";
|
|
476
477
|
}>;
|
|
477
478
|
max_parallel_nodes: z.ZodOptional<z.ZodNumber>;
|
|
478
479
|
node_catalog: z.ZodOptional<z.ZodString>;
|
|
@@ -484,13 +485,34 @@ declare const configSchema: z.ZodObject<{
|
|
|
484
485
|
skills: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
485
486
|
path: z.ZodString;
|
|
486
487
|
source_root: z.ZodDefault<z.ZodEnum<{
|
|
487
|
-
project: "project";
|
|
488
488
|
package: "package";
|
|
489
|
+
project: "project";
|
|
489
490
|
}>>;
|
|
490
491
|
}, z.core.$strict>>>;
|
|
491
492
|
task_context: z.ZodOptional<z.ZodObject<{
|
|
492
493
|
type: z.ZodString;
|
|
493
494
|
}, z.core.$loose>>;
|
|
495
|
+
best_of_n: z.ZodOptional<z.ZodObject<{
|
|
496
|
+
categories: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
497
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
498
|
+
n: z.ZodDefault<z.ZodNumber>;
|
|
499
|
+
}, z.core.$strict>>;
|
|
500
|
+
context_handoff: z.ZodOptional<z.ZodObject<{
|
|
501
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
502
|
+
model: z.ZodOptional<z.ZodString>;
|
|
503
|
+
}, z.core.$strict>>;
|
|
504
|
+
parallel_worktrees: z.ZodOptional<z.ZodObject<{
|
|
505
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
506
|
+
}, z.core.$strict>>;
|
|
507
|
+
token_budget: z.ZodDefault<z.ZodObject<{
|
|
508
|
+
default_context_window: z.ZodDefault<z.ZodNumber>;
|
|
509
|
+
max_context_pct: z.ZodDefault<z.ZodNumber>;
|
|
510
|
+
model_context_windows: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodNumber>>;
|
|
511
|
+
fan_out_width: z.ZodDefault<z.ZodObject<{
|
|
512
|
+
default: z.ZodDefault<z.ZodNumber>;
|
|
513
|
+
by_category: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodNumber>>;
|
|
514
|
+
}, z.core.$strict>>;
|
|
515
|
+
}, z.core.$strict>>;
|
|
494
516
|
version: z.ZodLiteral<1>;
|
|
495
517
|
workflows: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
496
518
|
description: z.ZodOptional<z.ZodString>;
|
package/dist/config/schemas.js
CHANGED
|
@@ -380,6 +380,7 @@ const workflowNodeBaseSchema = z.object({
|
|
|
380
380
|
});
|
|
381
381
|
const workflowNodeSchema = z.lazy(() => z.discriminatedUnion("kind", [
|
|
382
382
|
workflowNodeBaseSchema.extend({
|
|
383
|
+
category: z.string().min(1).optional(),
|
|
383
384
|
kind: z.literal("agent"),
|
|
384
385
|
profile: z.string()
|
|
385
386
|
}).strict(),
|
|
@@ -438,6 +439,38 @@ const profilesFileSchema = z.object({
|
|
|
438
439
|
skills: strictRecord(pathRefSchema).default({}),
|
|
439
440
|
version: z.literal(1)
|
|
440
441
|
}).strict();
|
|
442
|
+
const fanOutWidthSchema = z.object({
|
|
443
|
+
default: z.number().int().positive().default(4),
|
|
444
|
+
by_category: strictRecord(z.number().int().positive()).default({})
|
|
445
|
+
}).strict();
|
|
446
|
+
const tokenBudgetSchema = z.object({
|
|
447
|
+
default_context_window: z.number().int().positive().default(2e5),
|
|
448
|
+
max_context_pct: z.number().positive().max(100).default(50),
|
|
449
|
+
model_context_windows: strictRecord(z.number().int().positive()).default({}),
|
|
450
|
+
fan_out_width: fanOutWidthSchema.default({
|
|
451
|
+
default: 4,
|
|
452
|
+
by_category: {}
|
|
453
|
+
})
|
|
454
|
+
}).strict();
|
|
455
|
+
const DEFAULT_TOKEN_BUDGET = {
|
|
456
|
+
default_context_window: 2e5,
|
|
457
|
+
max_context_pct: 50,
|
|
458
|
+
model_context_windows: {},
|
|
459
|
+
fan_out_width: {
|
|
460
|
+
default: 4,
|
|
461
|
+
by_category: {}
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
const contextHandoffSchema = z.object({
|
|
465
|
+
enabled: z.boolean().default(false),
|
|
466
|
+
model: z.string().optional()
|
|
467
|
+
}).strict();
|
|
468
|
+
const parallelWorktreesSchema = z.object({ enabled: z.boolean().default(false) }).strict();
|
|
469
|
+
const bestOfNSchema = z.object({
|
|
470
|
+
categories: z.array(z.string()).default(["green"]),
|
|
471
|
+
enabled: z.boolean().default(false),
|
|
472
|
+
n: z.number().int().positive().default(1)
|
|
473
|
+
}).strict();
|
|
441
474
|
const pipelineFileSchema = z.object({
|
|
442
475
|
default_workflow: z.string(),
|
|
443
476
|
entrypoints: strictRecord(entrypointSchema).default({}),
|
|
@@ -459,6 +492,10 @@ const pipelineFileSchema = z.object({
|
|
|
459
492
|
}),
|
|
460
493
|
schedules: strictRecord(schedulePolicySchema).default({}),
|
|
461
494
|
task_context: taskContextResolverSchema.optional(),
|
|
495
|
+
best_of_n: bestOfNSchema.optional(),
|
|
496
|
+
context_handoff: contextHandoffSchema.optional(),
|
|
497
|
+
parallel_worktrees: parallelWorktreesSchema.optional(),
|
|
498
|
+
token_budget: tokenBudgetSchema.default(DEFAULT_TOKEN_BUDGET),
|
|
462
499
|
workflows: strictRecord(workflowSchema).default({}),
|
|
463
500
|
version: z.literal(1)
|
|
464
501
|
}).strict();
|
|
@@ -489,6 +526,10 @@ const configSchema = z.object({
|
|
|
489
526
|
schedules: strictRecord(schedulePolicySchema).default({}),
|
|
490
527
|
skills: strictRecord(pathRefSchema).default({}),
|
|
491
528
|
task_context: taskContextResolverSchema.optional(),
|
|
529
|
+
best_of_n: bestOfNSchema.optional(),
|
|
530
|
+
context_handoff: contextHandoffSchema.optional(),
|
|
531
|
+
parallel_worktrees: parallelWorktreesSchema.optional(),
|
|
532
|
+
token_budget: tokenBudgetSchema.default(DEFAULT_TOKEN_BUDGET),
|
|
492
533
|
version: z.literal(1),
|
|
493
534
|
workflows: strictRecord(workflowSchema).default({})
|
|
494
535
|
}).strict().superRefine(validateConfigReferences);
|
package/dist/config/validate.js
CHANGED
|
@@ -35,12 +35,28 @@ function validatePipelineConfig(rawConfig, projectRoot, options = {}) {
|
|
|
35
35
|
validateProfile(profileId, profile, runner, config, issues, projectRoot, options);
|
|
36
36
|
}
|
|
37
37
|
validateHookConfig(config, issues, projectRoot, options);
|
|
38
|
+
validateTokenBudget(config, issues);
|
|
38
39
|
for (const [ruleId, rule] of Object.entries(config.rules)) validatePath(`rules.${ruleId}.path`, rule, projectRoot, issues, options);
|
|
39
40
|
for (const [skillId, skill] of Object.entries(config.skills)) validatePath(`skills.${skillId}.path`, skill, projectRoot, issues, options);
|
|
40
41
|
for (const [workflowId, workflow] of Object.entries(config.workflows)) validateWorkflow(workflowId, workflow, config, issues, projectRoot, options);
|
|
41
42
|
if (issues.length > 0) throw validationError(issues);
|
|
42
43
|
return config;
|
|
43
44
|
}
|
|
45
|
+
function knownNodeCategories(config) {
|
|
46
|
+
const categories = /* @__PURE__ */ new Set();
|
|
47
|
+
for (const catalog of Object.values(config.scheduler.node_catalogs)) {
|
|
48
|
+
for (const category of catalog.required_categories) categories.add(category);
|
|
49
|
+
for (const node of Object.values(catalog.nodes)) categories.add(node.category);
|
|
50
|
+
}
|
|
51
|
+
return categories;
|
|
52
|
+
}
|
|
53
|
+
function validateTokenBudget(config, issues) {
|
|
54
|
+
const known = knownNodeCategories(config);
|
|
55
|
+
for (const category of Object.keys(config.token_budget.fan_out_width.by_category)) if (!known.has(category)) issues.push({
|
|
56
|
+
path: `token_budget.fan_out_width.by_category.${category}`,
|
|
57
|
+
message: `fan-out width cap references unknown node category '${category}'`
|
|
58
|
+
});
|
|
59
|
+
}
|
|
44
60
|
function validateRegistryIds(name, registry, issues) {
|
|
45
61
|
for (const id of Object.keys(registry)) if (!ID_RE.test(id)) issues.push({
|
|
46
62
|
path: `${name}.${id}`,
|
package/dist/model-resolver.js
CHANGED
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
//#region src/model-resolver.ts
|
|
2
2
|
const DISABLED_MODELS_ENV = "PIPELINE_DISABLED_MODELS";
|
|
3
|
-
function selectNodeModel(node) {
|
|
4
|
-
return fallbackModelSelection(node.models ?? []);
|
|
3
|
+
function selectNodeModel(node, options) {
|
|
4
|
+
return fallbackModelSelection(node.models ?? [], options);
|
|
5
5
|
}
|
|
6
|
-
function fallbackModelSelection(models) {
|
|
6
|
+
function fallbackModelSelection(models, options) {
|
|
7
7
|
if (models.length === 0) return {
|
|
8
8
|
reason: "node declares no model fallback array",
|
|
9
9
|
skipped: []
|
|
10
10
|
};
|
|
11
|
-
|
|
11
|
+
const disabled = disabledModels();
|
|
12
|
+
const enabled = models.filter((candidate) => !disabled.has(candidate));
|
|
13
|
+
const disabledSkipped = models.filter((candidate) => disabled.has(candidate));
|
|
14
|
+
if (!options) {
|
|
15
|
+
const model = enabled[0];
|
|
16
|
+
return {
|
|
17
|
+
model,
|
|
18
|
+
reason: selectionReason(model),
|
|
19
|
+
skipped: disabledSkipped
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
return sizedSelection(enabled, disabledSkipped, options);
|
|
12
23
|
}
|
|
13
|
-
function
|
|
14
|
-
const
|
|
24
|
+
function sizedSelection(enabled, disabledSkipped, options) {
|
|
25
|
+
const { estimatedTokens, budget } = options;
|
|
26
|
+
const required = estimatedTokens / (budget.max_context_pct / 100);
|
|
27
|
+
const tooSmall = [];
|
|
28
|
+
for (const candidate of enabled) {
|
|
29
|
+
const window = budget.model_context_windows[candidate] ?? budget.default_context_window;
|
|
30
|
+
if (window >= required) return {
|
|
31
|
+
model: candidate,
|
|
32
|
+
reason: `selected '${candidate}' (window ${window}) — holds estimated ${estimatedTokens} tokens within the ${budget.max_context_pct}% context cap`,
|
|
33
|
+
skipped: [...disabledSkipped, ...tooSmall]
|
|
34
|
+
};
|
|
35
|
+
tooSmall.push(candidate);
|
|
36
|
+
}
|
|
15
37
|
return {
|
|
16
|
-
model
|
|
17
|
-
|
|
18
|
-
skipped: models.filter((candidate) => disabled.has(candidate))
|
|
38
|
+
reason: `estimated context ${estimatedTokens} tokens exceeds ${budget.max_context_pct}% of every available model window`,
|
|
39
|
+
skipped: [...disabledSkipped, ...tooSmall]
|
|
19
40
|
};
|
|
20
41
|
}
|
|
21
42
|
function selectionReason(model) {
|
package/dist/moka-submit.d.ts
CHANGED
|
@@ -5,13 +5,13 @@ import { z } from "zod";
|
|
|
5
5
|
//#region src/moka-submit.d.ts
|
|
6
6
|
declare const mokaSubmitDirectHooksSchema: z.ZodRecord<z.ZodEnum<{
|
|
7
7
|
"workflow.start": "workflow.start";
|
|
8
|
+
"node.finish": "node.finish";
|
|
9
|
+
"node.start": "node.start";
|
|
8
10
|
"workflow.success": "workflow.success";
|
|
9
11
|
"workflow.failure": "workflow.failure";
|
|
10
12
|
"workflow.complete": "workflow.complete";
|
|
11
|
-
"node.start": "node.start";
|
|
12
13
|
"node.success": "node.success";
|
|
13
14
|
"node.error": "node.error";
|
|
14
|
-
"node.finish": "node.finish";
|
|
15
15
|
"gate.failure": "gate.failure";
|
|
16
16
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
17
17
|
failure: z.ZodDefault<z.ZodEnum<{
|
|
@@ -94,13 +94,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
94
94
|
}, z.core.$strict>>;
|
|
95
95
|
hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
96
96
|
"workflow.start": "workflow.start";
|
|
97
|
+
"node.finish": "node.finish";
|
|
98
|
+
"node.start": "node.start";
|
|
97
99
|
"workflow.success": "workflow.success";
|
|
98
100
|
"workflow.failure": "workflow.failure";
|
|
99
101
|
"workflow.complete": "workflow.complete";
|
|
100
|
-
"node.start": "node.start";
|
|
101
102
|
"node.success": "node.success";
|
|
102
103
|
"node.error": "node.error";
|
|
103
|
-
"node.finish": "node.finish";
|
|
104
104
|
"gate.failure": "gate.failure";
|
|
105
105
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
106
106
|
failure: z.ZodDefault<z.ZodEnum<{
|
|
@@ -160,8 +160,8 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
160
160
|
}, z.core.$strict>>;
|
|
161
161
|
serviceAccountName: z.ZodOptional<z.ZodString>;
|
|
162
162
|
mode: z.ZodEnum<{
|
|
163
|
-
full: "full";
|
|
164
163
|
quick: "quick";
|
|
164
|
+
full: "full";
|
|
165
165
|
}>;
|
|
166
166
|
schedulePath: z.ZodOptional<z.ZodString>;
|
|
167
167
|
scheduleYaml: z.ZodOptional<z.ZodString>;
|
|
@@ -206,13 +206,13 @@ declare const mokaSubmitOptionsSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
206
206
|
}, z.core.$strict>>;
|
|
207
207
|
hooks: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
|
|
208
208
|
"workflow.start": "workflow.start";
|
|
209
|
+
"node.finish": "node.finish";
|
|
210
|
+
"node.start": "node.start";
|
|
209
211
|
"workflow.success": "workflow.success";
|
|
210
212
|
"workflow.failure": "workflow.failure";
|
|
211
213
|
"workflow.complete": "workflow.complete";
|
|
212
|
-
"node.start": "node.start";
|
|
213
214
|
"node.success": "node.success";
|
|
214
215
|
"node.error": "node.error";
|
|
215
|
-
"node.finish": "node.finish";
|
|
216
216
|
"gate.failure": "gate.failure";
|
|
217
217
|
}> & z.core.$partial, z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
218
218
|
failure: z.ZodDefault<z.ZodEnum<{
|
package/dist/pipeline-runtime.js
CHANGED
|
@@ -628,6 +628,7 @@ async function executeNodeAttemptCycle(node, context, attempt, previous) {
|
|
|
628
628
|
const beforeSnapshot = context.nodeStateStore.getSnapshot(node.id);
|
|
629
629
|
if (beforeSnapshot) context.nodeStateStore.setSnapshot(node.id, diffChangedFiles(beforeSnapshot, afterSnapshot, context.worktreePath));
|
|
630
630
|
context.nodeStateStore.recordOutput(node.id, last.output);
|
|
631
|
+
context.nodeStateStore.recordHandoff(node.id, last.handoff);
|
|
631
632
|
emitNodeOutputRecorded(context, node, attempt, last.output);
|
|
632
633
|
recordNodeEvent(context, node.id, {
|
|
633
634
|
at: now(),
|
package/dist/planning/compile.js
CHANGED
|
@@ -185,10 +185,14 @@ function createWorkflowGraph(nodes, nodeIds = new Set(nodes.map((node) => node.i
|
|
|
185
185
|
function uniqueExistingNeeds(node, nodeIds) {
|
|
186
186
|
return uniqueStrings(node.needs.filter((need) => nodeIds.has(need)));
|
|
187
187
|
}
|
|
188
|
+
function agentNodeCategory(node) {
|
|
189
|
+
return node.kind === "agent" ? node.category : void 0;
|
|
190
|
+
}
|
|
188
191
|
function toPlannedNode(node, index) {
|
|
189
192
|
const planned = {
|
|
190
193
|
artifacts: node.artifacts,
|
|
191
194
|
builtin: "builtin" in node ? node.builtin : void 0,
|
|
195
|
+
category: agentNodeCategory(node),
|
|
192
196
|
command: "command" in node ? node.command : void 0,
|
|
193
197
|
children: node.kind === "parallel" ? node.nodes.map((child, childIndex) => toPlannedNode(child, childIndex)) : void 0,
|
|
194
198
|
dependents: [],
|
|
@@ -94,6 +94,7 @@ declare const scheduleArtifactSchema: z.ZodObject<{
|
|
|
94
94
|
} | undefined;
|
|
95
95
|
timeout_ms?: number | undefined;
|
|
96
96
|
} & {
|
|
97
|
+
category?: string;
|
|
97
98
|
kind: "agent";
|
|
98
99
|
profile: string;
|
|
99
100
|
}) | ({
|
|
@@ -478,6 +479,7 @@ declare const scheduleArtifactSchema: z.ZodObject<{
|
|
|
478
479
|
} | undefined;
|
|
479
480
|
timeout_ms?: number | undefined;
|
|
480
481
|
} & {
|
|
482
|
+
category?: string;
|
|
481
483
|
kind: "agent";
|
|
482
484
|
profile: string;
|
|
483
485
|
}) | ({
|
|
@@ -861,6 +863,7 @@ declare const scheduleArtifactSchema: z.ZodObject<{
|
|
|
861
863
|
} | undefined;
|
|
862
864
|
timeout_ms?: number | undefined;
|
|
863
865
|
} & {
|
|
866
|
+
category?: string;
|
|
864
867
|
kind: "agent";
|
|
865
868
|
profile: string;
|
|
866
869
|
}) | ({
|
|
@@ -1245,6 +1248,7 @@ declare const scheduleArtifactSchema: z.ZodObject<{
|
|
|
1245
1248
|
} | undefined;
|
|
1246
1249
|
timeout_ms?: number | undefined;
|
|
1247
1250
|
} & {
|
|
1251
|
+
category?: string;
|
|
1248
1252
|
kind: "agent";
|
|
1249
1253
|
profile: string;
|
|
1250
1254
|
}) | ({
|
|
@@ -5,6 +5,7 @@ import { createRunnerLaunchPlan, runLaunchPlan } from "../runner.js";
|
|
|
5
5
|
import { normalizeRunnerOutput } from "../runner-output.js";
|
|
6
6
|
import { loadBacklogPlanningContext } from "../schedule/backlog-context.js";
|
|
7
7
|
import { baselineScheduleArtifact } from "../schedule/baseline.js";
|
|
8
|
+
import { expandBestOfNCandidates } from "../schedule/passes/candidates.js";
|
|
8
9
|
import { dependentsByNeed, flattenNodes, hasReachableDependent } from "./graph.js";
|
|
9
10
|
import { isCoverageNode, isImplementationNode } from "../schedule/scheduling-roles.js";
|
|
10
11
|
import { addGeneratedImplementationCoverage } from "../schedule/passes/coverage.js";
|
|
@@ -91,7 +92,7 @@ async function generateScheduleArtifact(options) {
|
|
|
91
92
|
const planningContext = { ...loadBacklogPlanningContext(options.task, options.worktreePath) };
|
|
92
93
|
const generatedArtifact = await planScheduleArtifact(baseline, policy.planner_profile, options, planningContext);
|
|
93
94
|
assertSchedulePassOrder();
|
|
94
|
-
const artifact = hydrateScheduleTaskContexts(canonicalizeGeneratedScheduleIds(applyNodeCatalogModelFallbacks(options.config, policy.node_catalog, addGeneratedImplementationCoverage(options.config, generatedArtifact))), planningContext);
|
|
95
|
+
const artifact = hydrateScheduleTaskContexts(canonicalizeGeneratedScheduleIds(applyNodeCatalogModelFallbacks(options.config, policy.node_catalog, expandBestOfNCandidates(options.config, addGeneratedImplementationCoverage(options.config, generatedArtifact)))), planningContext);
|
|
95
96
|
validateScheduleArtifact(options.config, artifact, planningContext);
|
|
96
97
|
compileScheduleArtifact(options.config, artifact, options.worktreePath);
|
|
97
98
|
return {
|
|
@@ -102,6 +103,7 @@ async function generateScheduleArtifact(options) {
|
|
|
102
103
|
function assertSchedulePassOrder() {
|
|
103
104
|
if (SCHEDULE_PASS_ORDER.join("\0") !== [
|
|
104
105
|
"coverage",
|
|
106
|
+
"candidates",
|
|
105
107
|
"models",
|
|
106
108
|
"ids",
|
|
107
109
|
"references"
|
|
@@ -43,8 +43,8 @@ declare const runnerDeliverySchema: z.ZodObject<{
|
|
|
43
43
|
declare const mokaSubmissionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
44
44
|
kind: z.ZodLiteral<"graph">;
|
|
45
45
|
mode: z.ZodEnum<{
|
|
46
|
-
full: "full";
|
|
47
46
|
quick: "quick";
|
|
47
|
+
full: "full";
|
|
48
48
|
}>;
|
|
49
49
|
}, z.core.$strict>, z.ZodObject<{
|
|
50
50
|
argv: z.ZodArray<z.ZodString>;
|
|
@@ -104,8 +104,8 @@ declare const runnerCommandPayloadSchema: z.ZodObject<{
|
|
|
104
104
|
submission: z.ZodDefault<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
105
105
|
kind: z.ZodLiteral<"graph">;
|
|
106
106
|
mode: z.ZodEnum<{
|
|
107
|
-
full: "full";
|
|
108
107
|
quick: "quick";
|
|
108
|
+
full: "full";
|
|
109
109
|
}>;
|
|
110
110
|
}, z.core.$strict>, z.ZodObject<{
|
|
111
111
|
argv: z.ZodArray<z.ZodString>;
|
|
@@ -10,8 +10,8 @@ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
10
10
|
at: z.ZodOptional<z.ZodString>;
|
|
11
11
|
sequence: z.ZodNumber;
|
|
12
12
|
type: z.ZodEnum<{
|
|
13
|
-
"workflow.start": "workflow.start";
|
|
14
13
|
"workflow.planned": "workflow.planned";
|
|
14
|
+
"workflow.start": "workflow.start";
|
|
15
15
|
}>;
|
|
16
16
|
workflowPlan: z.ZodObject<{
|
|
17
17
|
edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -55,10 +55,10 @@ declare const runnerEventRecordSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
55
55
|
}>;
|
|
56
56
|
}, z.core.$strip>;
|
|
57
57
|
type: z.ZodEnum<{
|
|
58
|
-
"node.start": "node.start";
|
|
59
|
-
"node.finish": "node.finish";
|
|
60
58
|
"agent.finish": "agent.finish";
|
|
61
59
|
"agent.start": "agent.start";
|
|
60
|
+
"node.finish": "node.finish";
|
|
61
|
+
"node.start": "node.start";
|
|
62
62
|
}>;
|
|
63
63
|
}, z.core.$strip>, z.ZodObject<{
|
|
64
64
|
at: z.ZodOptional<z.ZodString>;
|
|
@@ -180,8 +180,8 @@ declare const runnerEventBatchSchema: z.ZodObject<{
|
|
|
180
180
|
at: z.ZodOptional<z.ZodString>;
|
|
181
181
|
sequence: z.ZodNumber;
|
|
182
182
|
type: z.ZodEnum<{
|
|
183
|
-
"workflow.start": "workflow.start";
|
|
184
183
|
"workflow.planned": "workflow.planned";
|
|
184
|
+
"workflow.start": "workflow.start";
|
|
185
185
|
}>;
|
|
186
186
|
workflowPlan: z.ZodObject<{
|
|
187
187
|
edges: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -225,10 +225,10 @@ declare const runnerEventBatchSchema: z.ZodObject<{
|
|
|
225
225
|
}>;
|
|
226
226
|
}, z.core.$strip>;
|
|
227
227
|
type: z.ZodEnum<{
|
|
228
|
-
"node.start": "node.start";
|
|
229
|
-
"node.finish": "node.finish";
|
|
230
228
|
"agent.finish": "agent.finish";
|
|
231
229
|
"agent.start": "agent.start";
|
|
230
|
+
"node.finish": "node.finish";
|
|
231
|
+
"node.start": "node.start";
|
|
232
232
|
}>;
|
|
233
233
|
}, z.core.$strip>, z.ZodObject<{
|
|
234
234
|
at: z.ZodOptional<z.ZodString>;
|