@zhixuan92/multi-model-agent-core 1.0.0 → 1.2.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 (61) hide show
  1. package/README.md +33 -93
  2. package/dist/config/schema.d.ts +1 -0
  3. package/dist/config/schema.d.ts.map +1 -1
  4. package/dist/config/schema.js +1 -1
  5. package/dist/config/schema.js.map +1 -1
  6. package/dist/delegate-with-escalation.d.ts.map +1 -1
  7. package/dist/delegate-with-escalation.js +54 -19
  8. package/dist/delegate-with-escalation.js.map +1 -1
  9. package/dist/effort-inference.d.ts +7 -0
  10. package/dist/effort-inference.d.ts.map +1 -0
  11. package/dist/effort-inference.js +22 -0
  12. package/dist/effort-inference.js.map +1 -0
  13. package/dist/review/aggregate-result.d.ts +1 -1
  14. package/dist/review/aggregate-result.d.ts.map +1 -1
  15. package/dist/review/aggregate-result.js.map +1 -1
  16. package/dist/review/quality-reviewer.d.ts +1 -1
  17. package/dist/review/quality-reviewer.d.ts.map +1 -1
  18. package/dist/review/quality-reviewer.js +4 -4
  19. package/dist/review/quality-reviewer.js.map +1 -1
  20. package/dist/review/spec-reviewer.d.ts +1 -1
  21. package/dist/review/spec-reviewer.d.ts.map +1 -1
  22. package/dist/review/spec-reviewer.js +3 -3
  23. package/dist/review/spec-reviewer.js.map +1 -1
  24. package/dist/run-tasks.d.ts.map +1 -1
  25. package/dist/run-tasks.js +58 -14
  26. package/dist/run-tasks.js.map +1 -1
  27. package/dist/runners/claude-runner.d.ts +2 -2
  28. package/dist/runners/claude-runner.d.ts.map +1 -1
  29. package/dist/runners/claude-runner.js +11 -6
  30. package/dist/runners/claude-runner.js.map +1 -1
  31. package/dist/runners/codex-runner.d.ts +2 -2
  32. package/dist/runners/codex-runner.d.ts.map +1 -1
  33. package/dist/runners/codex-runner.js +25 -3
  34. package/dist/runners/codex-runner.js.map +1 -1
  35. package/dist/runners/openai-runner.d.ts +2 -2
  36. package/dist/runners/openai-runner.d.ts.map +1 -1
  37. package/dist/runners/openai-runner.js +4 -4
  38. package/dist/runners/openai-runner.js.map +1 -1
  39. package/dist/runners/prevention.d.ts.map +1 -1
  40. package/dist/runners/prevention.js +7 -0
  41. package/dist/runners/prevention.js.map +1 -1
  42. package/dist/runners/supervision.d.ts +6 -1
  43. package/dist/runners/supervision.d.ts.map +1 -1
  44. package/dist/runners/supervision.js +12 -2
  45. package/dist/runners/supervision.js.map +1 -1
  46. package/dist/tools/claude-adapter.d.ts +2 -2
  47. package/dist/tools/claude-adapter.d.ts.map +1 -1
  48. package/dist/tools/claude-adapter.js +23 -5
  49. package/dist/tools/claude-adapter.js.map +1 -1
  50. package/dist/tools/definitions.d.ts +5 -0
  51. package/dist/tools/definitions.d.ts.map +1 -1
  52. package/dist/tools/definitions.js +25 -0
  53. package/dist/tools/definitions.js.map +1 -1
  54. package/dist/tools/openai-adapter.d.ts +4 -4
  55. package/dist/tools/openai-adapter.d.ts.map +1 -1
  56. package/dist/tools/openai-adapter.js +26 -3
  57. package/dist/tools/openai-adapter.js.map +1 -1
  58. package/dist/types.d.ts +13 -5
  59. package/dist/types.d.ts.map +1 -1
  60. package/dist/types.js.map +1 -1
  61. package/package.json +1 -1
package/README.md CHANGED
@@ -1,16 +1,8 @@
1
1
  # @zhixuan92/multi-model-agent-core
2
2
 
3
- **Runtime library for [`multi-model-agent`](https://github.com/zhixuan312/multi-model-agent) import it to run multi-provider agent tasks directly from your own Node program.**
3
+ **Runtime library for multi-model-agent.** Import it to run multi-provider agent tasks directly from your own Node program — same routing, supervision, and review pipeline, no MCP client needed.
4
4
 
5
- Use this package when you want to embed the same routing and dispatch logic inside your own process instead of going through an MCP client. It ships:
6
-
7
- - **Provider runners** — Claude (`@anthropic-ai/claude-agent-sdk`), Codex (OpenAI Responses API with `codex login` or `OPENAI_API_KEY`), and any OpenAI-compatible endpoint.
8
- - **Routing engine** — capability filter → quality tier filter → cheapest qualifying provider, with the full escalation chain walked automatically on failure.
9
- - **`runTasks`** — a single function that takes a task array and a config, runs them in parallel, and returns one result per task (usage, costUSD, savedCostUSD, files touched, status, escalation log).
10
- - **Config schema** — Zod-validated loader for `~/.multi-model/config.json` so callers get the same config contract as the MCP server.
11
- - **Sandboxed tool layer** — `readFile`, `writeFile`, `grep`, `glob`, `listFiles`, `runShell` with `cwd-only` confinement via `fs.realpath`, size caps, and per-call enforcement.
12
-
13
- > **If you just want a `delegate_tasks` tool in Claude Code / Claude Desktop / Codex CLI**, install [`@zhixuan92/multi-model-agent-mcp`](https://www.npmjs.com/package/@zhixuan92/multi-model-agent-mcp) instead — it wraps this library in an MCP stdio server. You don't need `-core` directly for that.
5
+ > **Just want your AI assistant to delegate work?** Install [`@zhixuan92/multi-model-agent-mcp`](https://www.npmjs.com/package/@zhixuan92/multi-model-agent-mcp) instead it wraps this library in an MCP server.
14
6
 
15
7
  ## Install
16
8
 
@@ -18,104 +10,52 @@ Use this package when you want to embed the same routing and dispatch logic insi
18
10
  npm install @zhixuan92/multi-model-agent-core
19
11
  ```
20
12
 
21
- Requires Node `>= 22`. ESM only.
13
+ Requires Node >= 22. ESM only.
22
14
 
23
- ## What's exported
15
+ ## Quick example
24
16
 
25
17
  ```ts
26
- import {
27
- // Config
28
- loadConfigFromFile,
29
- parseConfig,
30
- multiModelConfigSchema,
31
-
32
- // Provider factory + dispatch
33
- createProvider,
34
- runTasks,
35
-
36
- // Routing helpers
37
- selectProviderForTask,
38
- getProviderEligibility,
39
- getBaseCapabilities,
40
- resolveTaskCapabilities,
41
- findModelProfile,
42
- getEffectiveCostTier,
43
- } from '@zhixuan92/multi-model-agent-core';
44
-
45
- import type {
46
- MultiModelConfig,
47
- ProviderConfig,
48
- TaskSpec,
49
- RunResult,
50
- RunStatus,
51
- Tier,
52
- Capability,
53
- CostTier,
54
- Effort,
55
- SandboxPolicy,
56
- } from '@zhixuan92/multi-model-agent-core';
57
- ```
58
-
59
- Subpath exports are available for tree-shaking-friendly imports:
60
-
61
- | Subpath | What |
62
- | --- | --- |
63
- | `./config/schema` | `parseConfig`, `multiModelConfigSchema` |
64
- | `./config/load` | `loadConfigFromFile` |
65
- | `./routing/capabilities` | base provider capability table |
66
- | `./routing/model-profiles` | tier/cost defaults per model name prefix |
67
- | `./routing/select-provider-for-task` | routing decision |
68
- | `./routing/get-provider-eligibility` | per-provider eligibility breakdown with reasons |
69
- | `./routing/resolve-task-capabilities` | merges per-task overrides into provider capabilities |
70
- | `./provider` | `createProvider` factory |
71
- | `./run-tasks` | `runTasks` parallel dispatcher |
72
- | `./types` | all shared types |
18
+ import { loadConfigFromFile } from '@zhixuan92/multi-model-agent-core/config/load';
19
+ import { runTasks } from '@zhixuan92/multi-model-agent-core/run-tasks';
73
20
 
74
- ## Quick example
21
+ const config = await loadConfigFromFile();
75
22
 
76
- ```ts
77
- import { runTasks } from '@zhixuan92/multi-model-agent-core';
78
-
79
- const config = {
80
- providers: {
81
- claude: { type: 'claude', model: 'claude-sonnet-4-6' },
82
- codex: { type: 'codex', model: 'gpt-5-codex' },
83
- },
84
- defaults: { maxTurns: 200, timeoutMs: 600_000, tools: 'full' },
85
- };
86
-
87
- const results = await runTasks(
88
- [
89
- { prompt: 'Refactor auth.ts to use JWT.', tier: 'reasoning', requiredCapabilities: ['file_read', 'file_write'] },
90
- { prompt: 'List all .ts files.', tier: 'trivial', requiredCapabilities: ['glob'] },
91
- ],
92
- config,
93
- );
23
+ const results = await runTasks([
24
+ { prompt: 'Refactor auth.ts to use JWT.', agentType: 'complex' },
25
+ { prompt: 'Write unit tests for auth module.', agentType: 'standard' },
26
+ ], config);
94
27
 
95
28
  for (const r of results) {
96
- console.log(r.status, r.output);
29
+ console.log(r.status, r.usage.costUSD, r.output);
97
30
  }
98
31
  ```
99
32
 
100
- `runTasks` runs each task on the cheapest eligible provider in parallel and returns a result per task. Pin a task to a specific provider by adding `provider: 'claude'`.
101
-
102
- ## Sandbox
103
-
104
- File tools enforce `sandboxPolicy: 'cwd-only'` by default — paths must resolve (via `fs.realpath`) inside the task's `cwd`. `runShell` is hard-disabled under `cwd-only`. `readFile` rejects targets larger than 50 MiB and `writeFile` rejects content larger than 100 MiB before touching memory or disk.
105
-
106
- ## Updating
107
-
108
- Bump via `npm install @zhixuan92/multi-model-agent-core@latest` (or `npm update`). The package is on **0.x semver**: any MINOR bump (`0.2.x → 0.3.0`) may change the config schema, the `runTasks` task shape, or exported types. PATCH bumps (`0.3.0 → 0.3.1`) are strictly backwards-compatible bug fixes.
33
+ ## What's inside
109
34
 
110
- Always skim [`CHANGELOG.md`](https://github.com/zhixuan312/multi-model-agent/blob/HEAD/CHANGELOG.md) before picking up a new MINOR version if it calls out a schema change, update your config loader and any stored task specs before upgrading. Subpath exports listed above are part of the public API contract and are versioned together with the main entry point.
35
+ - **Provider runners**Claude, Codex, and any OpenAI-compatible endpoint
36
+ - **Routing engine** — capability filter → agent type → cheapest qualifier
37
+ - **`runTasks`** — parallel dispatch, returns per-task results with usage, cost, files touched, status, and escalation log
38
+ - **Reviewed lifecycle** — spec review + quality review by a different agent
39
+ - **Config schema** — Zod-validated, same contract as the MCP server
40
+ - **Sandboxed tools** — `readFile`, `writeFile`, `grep`, `glob`, `listFiles`, `runShell` with `cwd-only` confinement
111
41
 
112
- If you also depend on `@zhixuan92/multi-model-agent-mcp`, keep the two packages on matching MINOR versions — the MCP server declares a `^0.X.0` range on this library and mismatched versions can surface as type drift or schema validation errors.
42
+ ## Subpath exports
113
43
 
114
- ## Documentation
44
+ | Subpath | What |
45
+ |---|---|
46
+ | `./config/schema` | `parseConfig`, `multiModelConfigSchema` |
47
+ | `./config/load` | `loadConfigFromFile` |
48
+ | `./routing/select-provider-for-task` | Routing decision |
49
+ | `./routing/get-provider-eligibility` | Per-provider eligibility with reasons |
50
+ | `./routing/capabilities` | Base provider capability table |
51
+ | `./routing/model-profiles` | Cost/tier defaults per model |
52
+ | `./provider` | `createProvider` factory |
53
+ | `./run-tasks` | `runTasks` parallel dispatcher |
54
+ | `./types` | All shared types |
115
55
 
116
- Full docs, configuration reference, supported providers, and the routing matrix live in the project README:
56
+ ## Full documentation
117
57
 
118
- **<https://github.com/zhixuan312/multi-model-agent#readme>**
58
+ **[github.com/zhixuan312/multi-model-agent](https://github.com/zhixuan312/multi-model-agent)**
119
59
 
120
60
  ## License
121
61
 
@@ -173,6 +173,7 @@ export declare const multiModelConfigSchema: z.ZodObject<{
173
173
  maxTurns: z.ZodDefault<z.ZodNumber>;
174
174
  timeoutMs: z.ZodDefault<z.ZodNumber>;
175
175
  tools: z.ZodDefault<z.ZodEnum<{
176
+ readonly: "readonly";
176
177
  none: "none";
177
178
  full: "full";
178
179
  }>>;
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,gBAAgB,EACjB,MAAM,aAAa,CAAC;AA+DrB,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMjC,CAAC;AAEH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,gBAAgB,CAAA;IACxB,OAAO,EAAE,IAAI,CAAA;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,KAAK,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,GAAG,mBAAmB,CAAA;AAEzE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAE1D"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EACV,gBAAgB,EACjB,MAAM,aAAa,CAAC;AA+DrB,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMjC,CAAC;AAEH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,gBAAgB,CAAA;IACxB,OAAO,EAAE,IAAI,CAAA;CACd;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,KAAK,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,GAAG,mBAAmB,CAAA;AAEzE;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAE1D"}
@@ -47,7 +47,7 @@ const agentConfigSchema = z.discriminatedUnion('type', [
47
47
  const defaultsSchema = z.object({
48
48
  maxTurns: z.number().int().positive().default(200),
49
49
  timeoutMs: z.number().int().positive().default(600_000),
50
- tools: z.enum(['none', 'full']).default('full'),
50
+ tools: z.enum(['none', 'readonly', 'full']).default('full'),
51
51
  largeResponseThresholdChars: z.number().int().positive().optional(),
52
52
  }).default(() => ({ maxTurns: 200, timeoutMs: 600_000, tools: 'full' }));
53
53
  export const multiModelConfigSchema = z.object({
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"delegate-with-escalation.d.ts","sourceRoot":"","sources":["../src/delegate-with-escalation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EAER,aAAa,EACd,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,eAAe;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC7C;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,QAAQ,EAAE,EACjB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,SAAS,CAAC,CAuGpB"}
1
+ {"version":3,"file":"delegate-with-escalation.d.ts","sourceRoot":"","sources":["../src/delegate-with-escalation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EAER,aAAa,EACd,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,eAAe;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC7C;AAiBD,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,QAAQ,EAAE,EACjB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,SAAS,CAAC,CAmIpB"}
@@ -1,4 +1,18 @@
1
1
  import { retryableFor } from './error-codes.js';
2
+ const TRANSIENT_STATUSES = new Set(['api_error', 'network_error']);
3
+ const TIMEOUT_STATUS = 'timeout';
4
+ const MAX_RETRIES = 2;
5
+ const BASE_DELAY_MS = 1000;
6
+ function sleep(ms) {
7
+ return new Promise(resolve => setTimeout(resolve, ms));
8
+ }
9
+ function maxRetriesForStatus(status) {
10
+ if (TRANSIENT_STATUSES.has(status))
11
+ return MAX_RETRIES;
12
+ if (status === TIMEOUT_STATUS)
13
+ return 1;
14
+ return 0;
15
+ }
2
16
  export async function delegateWithEscalation(task, chain, options = {}) {
3
17
  if (chain.length === 0) {
4
18
  throw new Error('delegateWithEscalation called with empty chain');
@@ -26,24 +40,39 @@ export async function delegateWithEscalation(task, chain, options = {}) {
26
40
  }
27
41
  let initialPromptLengthChars = 0;
28
42
  let initialPromptHash = '';
29
- const result = await provider.run(task.prompt, {
30
- tools: task.tools,
31
- maxTurns: task.maxTurns,
32
- timeoutMs: task.timeoutMs,
33
- cwd: task.cwd,
34
- effort: task.effort,
35
- sandboxPolicy: task.sandboxPolicy,
36
- expectedCoverage: task.expectedCoverage,
37
- skipCompletionHeuristic: task.skipCompletionHeuristic,
38
- parentModel: task.parentModel,
39
- maxCostUSD: task.maxCostUSD,
40
- formatConstraints: task.formatConstraints,
41
- onProgress: safeSink,
42
- onInitialRequest: (meta) => {
43
- initialPromptLengthChars = meta.lengthChars;
44
- initialPromptHash = meta.sha256;
45
- },
46
- });
43
+ let result;
44
+ let cumulativeCostUSD = 0;
45
+ for (let attempt = 0;; attempt++) {
46
+ const adjustedMaxCostUSD = task.maxCostUSD !== undefined ? Math.max(0, task.maxCostUSD - cumulativeCostUSD) : undefined;
47
+ result = await provider.run(task.prompt, {
48
+ tools: task.tools,
49
+ maxTurns: task.maxTurns,
50
+ timeoutMs: task.timeoutMs,
51
+ cwd: task.cwd,
52
+ effort: task.effort,
53
+ sandboxPolicy: task.sandboxPolicy,
54
+ expectedCoverage: task.expectedCoverage,
55
+ skipCompletionHeuristic: task.skipCompletionHeuristic,
56
+ parentModel: task.parentModel,
57
+ maxCostUSD: adjustedMaxCostUSD,
58
+ formatConstraints: task.formatConstraints,
59
+ onProgress: safeSink,
60
+ onInitialRequest: (meta) => {
61
+ initialPromptLengthChars = meta.lengthChars;
62
+ initialPromptHash = meta.sha256;
63
+ },
64
+ });
65
+ const maxRetries = maxRetriesForStatus(result.status);
66
+ if (result.status === 'ok' || maxRetries === 0 || attempt >= maxRetries)
67
+ break;
68
+ const attemptCost = result.usage.costUSD ?? 0;
69
+ cumulativeCostUSD += attemptCost;
70
+ if (task.maxCostUSD !== undefined && cumulativeCostUSD >= task.maxCostUSD)
71
+ break;
72
+ const delayMs = BASE_DELAY_MS * Math.pow(2, attempt);
73
+ safeSink?.({ kind: 'retry', attempt: attempt + 1, previousStatus: result.status, delayMs });
74
+ await sleep(delayMs);
75
+ }
47
76
  const record = {
48
77
  provider: provider.name,
49
78
  status: result.status,
@@ -81,7 +110,13 @@ export async function delegateWithEscalation(task, chain, options = {}) {
81
110
  best = a.result;
82
111
  }
83
112
  }
84
- const finalStatus = best.status === 'ok' ? 'incomplete' : best.status;
113
+ const baseStatus = best.status === 'ok' ? 'incomplete' : best.status;
114
+ // C2: Promote incomplete → ok when agent self-assessed as done AND produced file artifacts
115
+ const finalStatus = baseStatus === 'incomplete' &&
116
+ best.workerStatus === 'done' &&
117
+ best.filesWritten.length > 0
118
+ ? 'ok'
119
+ : baseStatus;
85
120
  return {
86
121
  ...best,
87
122
  status: finalStatus,
@@ -1 +1 @@
1
- {"version":3,"file":"delegate-with-escalation.js","sourceRoot":"","sources":["../src/delegate-with-escalation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"delegate-with-escalation.js","sourceRoot":"","sources":["../src/delegate-with-escalation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Effort } from './types.js';
2
+ /**
3
+ * Infer effort from task prompt shape. Returns undefined when no heuristic
4
+ * matches (caller falls back to provider config default). Exported for testing.
5
+ */
6
+ export declare function inferEffort(prompt: string): Effort | undefined;
7
+ //# sourceMappingURL=effort-inference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effort-inference.d.ts","sourceRoot":"","sources":["../src/effort-inference.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAMzC;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAc9D"}
@@ -0,0 +1,22 @@
1
+ const CODE_BLOCK_RE = /```[\s\S]*?```/g;
2
+ const ACTION_VERB_RE = /\b(edit|modify|update|change|fix|refactor|replace)\b/i;
3
+ const FILE_PATH_RE = /\b[\w\-./]+\.(ts|js|tsx|jsx|py|rs|go|java|rb|cpp|c|h)\b/;
4
+ /**
5
+ * Infer effort from task prompt shape. Returns undefined when no heuristic
6
+ * matches (caller falls back to provider config default). Exported for testing.
7
+ */
8
+ export function inferEffort(prompt) {
9
+ // Heuristic 1: Large code block → exact-write task → low effort
10
+ const codeBlocks = prompt.match(CODE_BLOCK_RE) ?? [];
11
+ for (const block of codeBlocks) {
12
+ const lines = block.split('\n').length - 2; // subtract opening/closing fence lines
13
+ if (lines > 20)
14
+ return 'low';
15
+ }
16
+ // Heuristic 2: File references + action verbs → discovery task → medium effort
17
+ if (FILE_PATH_RE.test(prompt) && ACTION_VERB_RE.test(prompt)) {
18
+ return 'medium';
19
+ }
20
+ return undefined;
21
+ }
22
+ //# sourceMappingURL=effort-inference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effort-inference.js","sourceRoot":"","sources":["../src/effort-inference.ts"],"names":[],"mappings":"AAEA,MAAM,aAAa,GAAG,iBAAiB,CAAC;AACxC,MAAM,cAAc,GAAG,uDAAuD,CAAC;AAC/E,MAAM,YAAY,GAAG,yDAAyD,CAAC;AAE/E;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,gEAAgE;IAChE,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;IACrD,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,uCAAuC;QACnF,IAAI,KAAK,GAAG,EAAE;YAAE,OAAO,KAAK,CAAC;IAC/B,CAAC;IAED,+EAA+E;IAC/E,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7D,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import type { ParsedStructuredReport } from '../reporting/structured-report.js';
2
- export declare function aggregateResult(implReport: ParsedStructuredReport, specReport: ParsedStructuredReport | undefined, qualityReport: ParsedStructuredReport | undefined, specStatus: 'approved' | 'changes_required' | 'not_run', qualityStatus: 'approved' | 'changes_required' | 'not_run'): ParsedStructuredReport;
2
+ export declare function aggregateResult(implReport: ParsedStructuredReport, specReport: ParsedStructuredReport | undefined, qualityReport: ParsedStructuredReport | undefined, specStatus: 'approved' | 'changes_required' | 'skipped' | 'error', qualityStatus: 'approved' | 'changes_required' | 'skipped' | 'error'): ParsedStructuredReport;
3
3
  //# sourceMappingURL=aggregate-result.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate-result.d.ts","sourceRoot":"","sources":["../../src/review/aggregate-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAEhF,wBAAgB,eAAe,CAC7B,UAAU,EAAE,sBAAsB,EAClC,UAAU,EAAE,sBAAsB,GAAG,SAAS,EAC9C,aAAa,EAAE,sBAAsB,GAAG,SAAS,EACjD,UAAU,EAAE,UAAU,GAAG,kBAAkB,GAAG,SAAS,EACvD,aAAa,EAAE,UAAU,GAAG,kBAAkB,GAAG,SAAS,GACzD,sBAAsB,CA+BxB"}
1
+ {"version":3,"file":"aggregate-result.d.ts","sourceRoot":"","sources":["../../src/review/aggregate-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAEhF,wBAAgB,eAAe,CAC7B,UAAU,EAAE,sBAAsB,EAClC,UAAU,EAAE,sBAAsB,GAAG,SAAS,EAC9C,aAAa,EAAE,sBAAsB,GAAG,SAAS,EACjD,UAAU,EAAE,UAAU,GAAG,kBAAkB,GAAG,SAAS,GAAG,OAAO,EACjE,aAAa,EAAE,UAAU,GAAG,kBAAkB,GAAG,SAAS,GAAG,OAAO,GACnE,sBAAsB,CA+BxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate-result.js","sourceRoot":"","sources":["../../src/review/aggregate-result.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAC7B,UAAkC,EAClC,UAA8C,EAC9C,aAAiD,EACjD,UAAuD,EACvD,aAA0D;IAE1D,MAAM,MAAM,GACV,UAAU,KAAK,kBAAkB;QAC/B,CAAC,CAAC,0BAA0B;QAC5B,CAAC,CAAC,aAAa,KAAK,kBAAkB;YACpC,CAAC,CAAC,6BAA6B;YAC/B,CAAC,CAAC,aAAa,CAAC;IAEtB,OAAO;QACL,OAAO,EAAE,GAAG,MAAM,GAAG,UAAU,CAAC,OAAO,IAAI,EAAE,EAAE;QAC/C,YAAY,EAAE;YACZ,GAAG,UAAU,CAAC,YAAY;YAC1B,GAAG,CAAC,aAAa,EAAE,YAAY,IAAI,EAAE,CAAC;SACvC;QACD,sBAAsB,EAAE,UAAU,CAAC,sBAAsB;QACzD,cAAc,EAAE;YACd,GAAG,UAAU,CAAC,cAAc;YAC5B,GAAG,CAAC,UAAU,EAAE,cAAc,IAAI,EAAE,CAAC;YACrC,GAAG,CAAC,aAAa,EAAE,cAAc,IAAI,EAAE,CAAC;SACzC;QACD,mBAAmB,EAAE;YACnB,GAAG,CAAC,UAAU,CAAC,mBAAmB,IAAI,EAAE,CAAC;YACzC,GAAG,CAAC,UAAU,EAAE,mBAAmB,IAAI,EAAE,CAAC;YAC1C,GAAG,CAAC,aAAa,EAAE,mBAAmB,IAAI,EAAE,CAAC;SAC9C;QACD,UAAU,EAAE;YACV,GAAG,CAAC,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC;YAChC,GAAG,CAAC,UAAU,EAAE,UAAU,IAAI,EAAE,CAAC;YACjC,GAAG,CAAC,aAAa,EAAE,UAAU,IAAI,EAAE,CAAC;SACrC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"aggregate-result.js","sourceRoot":"","sources":["../../src/review/aggregate-result.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAC7B,UAAkC,EAClC,UAA8C,EAC9C,aAAiD,EACjD,UAAiE,EACjE,aAAoE;IAEpE,MAAM,MAAM,GACV,UAAU,KAAK,kBAAkB;QAC/B,CAAC,CAAC,0BAA0B;QAC5B,CAAC,CAAC,aAAa,KAAK,kBAAkB;YACpC,CAAC,CAAC,6BAA6B;YAC/B,CAAC,CAAC,aAAa,CAAC;IAEtB,OAAO;QACL,OAAO,EAAE,GAAG,MAAM,GAAG,UAAU,CAAC,OAAO,IAAI,EAAE,EAAE;QAC/C,YAAY,EAAE;YACZ,GAAG,UAAU,CAAC,YAAY;YAC1B,GAAG,CAAC,aAAa,EAAE,YAAY,IAAI,EAAE,CAAC;SACvC;QACD,sBAAsB,EAAE,UAAU,CAAC,sBAAsB;QACzD,cAAc,EAAE;YACd,GAAG,UAAU,CAAC,cAAc;YAC5B,GAAG,CAAC,UAAU,EAAE,cAAc,IAAI,EAAE,CAAC;YACrC,GAAG,CAAC,aAAa,EAAE,cAAc,IAAI,EAAE,CAAC;SACzC;QACD,mBAAmB,EAAE;YACnB,GAAG,CAAC,UAAU,CAAC,mBAAmB,IAAI,EAAE,CAAC;YACzC,GAAG,CAAC,UAAU,EAAE,mBAAmB,IAAI,EAAE,CAAC;YAC1C,GAAG,CAAC,aAAa,EAAE,mBAAmB,IAAI,EAAE,CAAC;SAC9C;QACD,UAAU,EAAE;YACV,GAAG,CAAC,UAAU,CAAC,UAAU,IAAI,EAAE,CAAC;YAChC,GAAG,CAAC,UAAU,EAAE,UAAU,IAAI,EAAE,CAAC;YACjC,GAAG,CAAC,aAAa,EAAE,UAAU,IAAI,EAAE,CAAC;SACrC;KACF,CAAC;AACJ,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import type { Provider } from '../types.js';
2
2
  import type { ParsedStructuredReport } from '../reporting/structured-report.js';
3
3
  export interface QualityReviewResult {
4
- status: 'approved' | 'changes_required' | 'not_run';
4
+ status: 'approved' | 'changes_required' | 'skipped' | 'error';
5
5
  report?: ParsedStructuredReport;
6
6
  findings: string[];
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"quality-reviewer.d.ts","sourceRoot":"","sources":["../../src/review/quality-reviewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAGhF,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,UAAU,GAAG,kBAAkB,GAAG,SAAS,CAAC;IACpD,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAsB,gBAAgB,CACpC,gBAAgB,EAAE,QAAQ,EAC1B,MAAM,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EAC5E,UAAU,EAAE,sBAAsB,EAClC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,WAAW,EAAE,MAAM,EAAE,EACrB,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,mBAAmB,CAAC,CA4C9B"}
1
+ {"version":3,"file":"quality-reviewer.d.ts","sourceRoot":"","sources":["../../src/review/quality-reviewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAGhF,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,UAAU,GAAG,kBAAkB,GAAG,SAAS,GAAG,OAAO,CAAC;IAC9D,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAsB,gBAAgB,CACpC,gBAAgB,EAAE,QAAQ,EAC1B,MAAM,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EAC5E,UAAU,EAAE,sBAAsB,EAClC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,WAAW,EAAE,MAAM,EAAE,EACrB,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,mBAAmB,CAAC,CA4C9B"}
@@ -3,7 +3,7 @@ import { buildQualityReviewPrompt } from './reviewer-prompt.js';
3
3
  import { parseStructuredReport } from '../reporting/structured-report.js';
4
4
  export async function runQualityReview(reviewerProvider, packet, implReport, fileContents, toolCallLog, filesWritten) {
5
5
  if (filesWritten.length === 0) {
6
- return { status: 'not_run', findings: [] };
6
+ return { status: 'skipped', findings: [] };
7
7
  }
8
8
  let result;
9
9
  try {
@@ -17,14 +17,14 @@ export async function runQualityReview(reviewerProvider, packet, implReport, fil
17
17
  }, [reviewerProvider], { explicitlyPinned: true });
18
18
  }
19
19
  catch {
20
- return { status: 'not_run', findings: [] };
20
+ return { status: 'error', findings: [] };
21
21
  }
22
22
  if (result.status !== 'ok') {
23
- return { status: 'not_run', findings: [] };
23
+ return { status: 'error', findings: [] };
24
24
  }
25
25
  const report = parseStructuredReport(result.output);
26
26
  if (!report.summary) {
27
- return { status: 'not_run', findings: [] };
27
+ return { status: 'error', findings: [] };
28
28
  }
29
29
  const summaryLower = report.summary.toLowerCase();
30
30
  if (summaryLower.includes('changes_required')) {
@@ -1 +1 @@
1
- {"version":3,"file":"quality-reviewer.js","sourceRoot":"","sources":["../../src/review/quality-reviewer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAQ1E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,gBAA0B,EAC1B,MAA4E,EAC5E,UAAkC,EAClC,YAAoC,EACpC,WAAqB,EACrB,YAAsB;IAEtB,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,YAAY,GAChB,gBAAgB,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;QAChE,MAAM,GAAG,MAAM,sBAAsB,CACnC;YACE,MAAM,EAAE,wBAAwB,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,CAAC;YAC/E,SAAS,EAAE,YAAY;YACvB,kBAAkB,EAAE,KAAK;YACzB,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,OAAO;SACnB,EACD,CAAC,gBAAgB,CAAC,EAClB,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAC3B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAElD,IAAI,YAAY,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC9C,OAAO;YACL,MAAM,EAAE,kBAAkB;YAC1B,MAAM;YACN,QAAQ,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;SAChF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"quality-reviewer.js","sourceRoot":"","sources":["../../src/review/quality-reviewer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAQ1E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,gBAA0B,EAC1B,MAA4E,EAC5E,UAAkC,EAClC,YAAoC,EACpC,WAAqB,EACrB,YAAsB;IAEtB,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,YAAY,GAChB,gBAAgB,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;QAChE,MAAM,GAAG,MAAM,sBAAsB,CACnC;YACE,MAAM,EAAE,wBAAwB,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,CAAC;YAC/E,SAAS,EAAE,YAAY;YACvB,kBAAkB,EAAE,KAAK;YACzB,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,OAAO;SACnB,EACD,CAAC,gBAAgB,CAAC,EAClB,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAC3B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC3C,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC3C,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAElD,IAAI,YAAY,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC9C,OAAO;YACL,MAAM,EAAE,kBAAkB;YAC1B,MAAM;YACN,QAAQ,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;SAChF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AACtD,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import type { Provider } from '../types.js';
2
2
  import type { ParsedStructuredReport } from '../reporting/structured-report.js';
3
3
  export interface SpecReviewResult {
4
- status: 'approved' | 'changes_required' | 'not_run';
4
+ status: 'approved' | 'changes_required' | 'error';
5
5
  report?: ParsedStructuredReport;
6
6
  findings: string[];
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"spec-reviewer.d.ts","sourceRoot":"","sources":["../../src/review/spec-reviewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAGhF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,GAAG,kBAAkB,GAAG,SAAS,CAAC;IACpD,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAsB,aAAa,CACjC,gBAAgB,EAAE,QAAQ,EAC1B,MAAM,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EAC5E,UAAU,EAAE,sBAAsB,EAClC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA0C3B"}
1
+ {"version":3,"file":"spec-reviewer.d.ts","sourceRoot":"","sources":["../../src/review/spec-reviewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAGhF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,UAAU,GAAG,kBAAkB,GAAG,OAAO,CAAC;IAClD,MAAM,CAAC,EAAE,sBAAsB,CAAC;IAChC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAsB,aAAa,CACjC,gBAAgB,EAAE,QAAQ,EAC1B,MAAM,EAAE;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EAC5E,UAAU,EAAE,sBAAsB,EAClC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA0C3B"}
@@ -15,14 +15,14 @@ export async function runSpecReview(reviewerProvider, packet, implReport, fileCo
15
15
  }, [reviewerProvider], { explicitlyPinned: true });
16
16
  }
17
17
  catch {
18
- return { status: 'not_run', findings: [] };
18
+ return { status: 'error', findings: [] };
19
19
  }
20
20
  if (result.status !== 'ok') {
21
- return { status: 'not_run', findings: [] };
21
+ return { status: 'error', findings: [] };
22
22
  }
23
23
  const report = parseStructuredReport(result.output);
24
24
  if (!report.summary) {
25
- return { status: 'not_run', findings: [] };
25
+ return { status: 'error', findings: [] };
26
26
  }
27
27
  const summaryLower = report.summary.toLowerCase();
28
28
  if (summaryLower.includes('changes_required')) {
@@ -1 +1 @@
1
- {"version":3,"file":"spec-reviewer.js","sourceRoot":"","sources":["../../src/review/spec-reviewer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAQ1E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,gBAA0B,EAC1B,MAA4E,EAC5E,UAAkC,EAClC,YAAoC,EACpC,WAAqB;IAErB,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAEpF,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,YAAY,GAChB,gBAAgB,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;QAChE,MAAM,GAAG,MAAM,sBAAsB,CACnC;YACE,MAAM;YACN,SAAS,EAAE,YAAY;YACvB,kBAAkB,EAAE,KAAK;YACzB,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,OAAO;SACnB,EACD,CAAC,gBAAgB,CAAC,EAClB,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAC3B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAElD,IAAI,YAAY,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC9C,OAAO;YACL,MAAM,EAAE,kBAAkB;YAC1B,MAAM;YACN,QAAQ,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;SAChF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"spec-reviewer.js","sourceRoot":"","sources":["../../src/review/spec-reviewer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAQ1E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,gBAA0B,EAC1B,MAA4E,EAC5E,UAAkC,EAClC,YAAoC,EACpC,WAAqB;IAErB,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAEpF,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,YAAY,GAChB,gBAAgB,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;QAChE,MAAM,GAAG,MAAM,sBAAsB,CACnC;YACE,MAAM;YACN,SAAS,EAAE,YAAY;YACvB,kBAAkB,EAAE,KAAK;YACzB,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,OAAO;SACnB,EACD,CAAC,gBAAgB,CAAC,EAClB,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAC3B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC3C,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC3C,CAAC;IAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC3C,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAElD,IAAI,YAAY,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC9C,OAAO;YACL,MAAM,EAAE,kBAAkB;YAC1B,MAAM;YACN,QAAQ,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,mBAAmB,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;SAChF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AACtD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"run-tasks.d.ts","sourceRoot":"","sources":["../src/run-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,eAAe,EAIhB,MAAM,YAAY,CAAC;AAepB,MAAM,MAAM,wBAAwB,GAAG,CACrC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,aAAa,KACjB,IAAI,CAAC;AAEV,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,wBAAwB,CAAC;IACtC,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAmRD,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,QAAQ,EAAE,EACjB,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,SAAS,EAAE,CAAC,CAyGtB"}
1
+ {"version":3,"file":"run-tasks.d.ts","sourceRoot":"","sources":["../src/run-tasks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,eAAe,EAIhB,MAAM,YAAY,CAAC;AAgBpB,MAAM,MAAM,wBAAwB,GAAG,CACrC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,aAAa,KACjB,IAAI,CAAC;AAEV,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,wBAAwB,CAAC;IACtC,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAqSD,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,QAAQ,EAAE,EACjB,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,SAAS,EAAE,CAAC,CAqItB"}
package/dist/run-tasks.js CHANGED
@@ -2,6 +2,7 @@ import { createProvider } from './provider.js';
2
2
  import { resolveAgent } from './routing/resolve-agent.js';
3
3
  import { delegateWithEscalation } from './delegate-with-escalation.js';
4
4
  import { expandContextBlocks } from './context/expand-context-blocks.js';
5
+ import { inferEffort } from './effort-inference.js';
5
6
  import { evaluateReadiness } from './readiness/readiness.js';
6
7
  import { normalizeBrief } from './readiness/normalize-brief.js';
7
8
  import { runSpecReview } from './review/spec-reviewer.js';
@@ -81,17 +82,34 @@ async function executeReviewedLifecycle(task, resolved, config, normResult, onPr
81
82
  const implResult = await delegateWithEscalation(task, [resolved.provider], { explicitlyPinned: true, onProgress });
82
83
  const implReport = implResult.status === 'ok' ? parseStructuredReport(implResult.output) : undefined;
83
84
  const workerStatus = extractWorkerStatus(implReport);
85
+ // C6a: Skip review when there are no file artifacts to review
86
+ const hasWorkProduct = implResult.filesWritten.length > 0;
87
+ if (!hasWorkProduct) {
88
+ return {
89
+ ...implResult,
90
+ workerStatus,
91
+ specReviewStatus: 'skipped',
92
+ qualityReviewStatus: 'skipped',
93
+ agents: {
94
+ normalizer: normResult && !normResult.skipped ? resolved.slot : 'skipped',
95
+ implementer: resolved.slot,
96
+ specReviewer: 'skipped',
97
+ qualityReviewer: 'skipped',
98
+ },
99
+ implementationReport: implReport,
100
+ };
101
+ }
84
102
  if (workerStatus === 'needs_context' || workerStatus === 'blocked') {
85
103
  return {
86
104
  ...implResult,
87
105
  workerStatus,
88
- specReviewStatus: 'not_run',
89
- qualityReviewStatus: 'not_run',
106
+ specReviewStatus: 'skipped',
107
+ qualityReviewStatus: 'skipped',
90
108
  agents: {
91
109
  normalizer: normResult && !normResult.skipped ? resolved.slot : 'skipped',
92
110
  implementer: resolved.slot,
93
- specReviewer: 'not_run',
94
- qualityReviewer: 'not_run',
111
+ specReviewer: 'skipped',
112
+ qualityReviewer: 'skipped',
95
113
  },
96
114
  };
97
115
  }
@@ -99,13 +117,13 @@ async function executeReviewedLifecycle(task, resolved, config, normResult, onPr
99
117
  return {
100
118
  ...implResult,
101
119
  workerStatus,
102
- specReviewStatus: 'not_run',
103
- qualityReviewStatus: 'not_run',
120
+ specReviewStatus: 'skipped',
121
+ qualityReviewStatus: 'skipped',
104
122
  agents: {
105
123
  normalizer: normResult && !normResult.skipped ? resolved.slot : 'skipped',
106
124
  implementer: resolved.slot,
107
- specReviewer: 'not_run',
108
- qualityReviewer: 'not_run',
125
+ specReviewer: 'skipped',
126
+ qualityReviewer: 'skipped',
109
127
  },
110
128
  implementationReport: implReport,
111
129
  };
@@ -118,13 +136,13 @@ async function executeReviewedLifecycle(task, resolved, config, normResult, onPr
118
136
  return {
119
137
  ...implResult,
120
138
  workerStatus,
121
- specReviewStatus: 'not_run',
122
- qualityReviewStatus: 'not_run',
139
+ specReviewStatus: 'skipped',
140
+ qualityReviewStatus: 'skipped',
123
141
  agents: {
124
142
  normalizer: normResult && !normResult.skipped ? resolved.slot : 'skipped',
125
143
  implementer: resolved.slot,
126
- specReviewer: 'not_run',
127
- qualityReviewer: 'not_run',
144
+ specReviewer: 'skipped',
145
+ qualityReviewer: 'skipped',
128
146
  },
129
147
  };
130
148
  }
@@ -156,7 +174,7 @@ async function executeReviewedLifecycle(task, resolved, config, normResult, onPr
156
174
  break;
157
175
  }
158
176
  }
159
- let qualityResult = { status: 'not_run', report: undefined, findings: [] };
177
+ let qualityResult = { status: 'skipped', report: undefined, findings: [] };
160
178
  if (reviewPolicy === 'full') {
161
179
  qualityResult = await runQualityReview(otherProvider, packet, specReport ?? finalImplReport, fileContents, finalImplResult.toolCalls, finalImplResult.filesWritten);
162
180
  if (qualityResult.status === 'changes_required' && maxRounds > 0) {
@@ -188,7 +206,7 @@ async function executeReviewedLifecycle(task, resolved, config, normResult, onPr
188
206
  normalizer: normResult && !normResult.skipped ? resolved.slot : 'skipped',
189
207
  implementer: resolved.slot,
190
208
  specReviewer: otherSlot,
191
- qualityReviewer: reviewPolicy === 'full' ? otherSlot : 'not_run',
209
+ qualityReviewer: reviewPolicy === 'full' ? otherSlot : 'skipped',
192
210
  },
193
211
  };
194
212
  }
@@ -268,6 +286,32 @@ export async function runTasks(tasks, config, options = {}) {
268
286
  };
269
287
  }
270
288
  });
289
+ // C5: Apply effort default when not explicitly set
290
+ for (const r of resolved) {
291
+ if ('error' in r)
292
+ continue;
293
+ if (r.task.effort === undefined) {
294
+ const inferred = inferEffort(r.task.prompt);
295
+ if (inferred !== undefined) {
296
+ r.task = { ...r.task, effort: inferred };
297
+ }
298
+ }
299
+ }
300
+ // C3: Inject parallel-safety suffix when dispatching 2+ tasks
301
+ if (resolved.length > 1) {
302
+ const PARALLEL_SAFETY_SUFFIX = '\n\nYou are running in parallel with other tasks. ' +
303
+ 'Do NOT run full-project build commands (`npm run build`, `tsc`, `cargo build`). ' +
304
+ 'Only run task-specific test commands if provided.';
305
+ for (const r of resolved) {
306
+ if ('error' in r)
307
+ continue;
308
+ r.task = {
309
+ ...r.task,
310
+ prompt: r.task.prompt + PARALLEL_SAFETY_SUFFIX +
311
+ (r.task.testCommand ? `\nTo verify your work, run: \`${r.task.testCommand}\`` : ''),
312
+ };
313
+ }
314
+ }
271
315
  return Promise.all(resolved.map((r, index) => {
272
316
  if ('error' in r) {
273
317
  return Promise.resolve({ ...errorResult(r.error), errorCode: r.errorCode });