oxe-cc 1.8.0 → 1.9.1

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 (52) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +94 -0
  3. package/README.md +15 -12
  4. package/bin/lib/oxe-manifest.cjs +20 -13
  5. package/bin/lib/oxe-operational.cjs +305 -79
  6. package/bin/lib/oxe-project-health.cjs +79 -18
  7. package/bin/lib/oxe-rationality.cjs +9 -7
  8. package/bin/lib/oxe-release.cjs +26 -0
  9. package/bin/oxe-cc.js +224 -52
  10. package/docs/RELEASE-READINESS.md +6 -1
  11. package/lib/runtime/compiler/graph-compiler.js +1 -1
  12. package/lib/runtime/executor/action-tool-map.js +4 -0
  13. package/lib/runtime/executor/built-in-tools.js +27 -0
  14. package/lib/runtime/executor/llm-task-executor.d.ts +4 -1
  15. package/lib/runtime/executor/llm-task-executor.js +41 -5
  16. package/lib/runtime/executor/node-prompt-builder.d.ts +4 -1
  17. package/lib/runtime/executor/node-prompt-builder.js +13 -2
  18. package/lib/runtime/models/failure.d.ts +1 -1
  19. package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +39 -0
  20. package/lib/runtime/scheduler/multi-agent-coordinator.js +222 -13
  21. package/lib/runtime/scheduler/scheduler.d.ts +5 -1
  22. package/lib/runtime/scheduler/scheduler.js +82 -14
  23. package/lib/runtime/verification/verification-compiler.js +7 -5
  24. package/lib/runtime/workspace/strategies/git-worktree.js +18 -9
  25. package/lib/sdk/index.cjs +48 -44
  26. package/oxe/templates/PLAN.template.md +23 -9
  27. package/oxe/templates/SPEC.template.md +55 -22
  28. package/oxe/workflows/plan.md +18 -6
  29. package/oxe/workflows/spec.md +31 -9
  30. package/package.json +106 -100
  31. package/packages/runtime/package.json +18 -18
  32. package/packages/runtime/src/compiler/graph-compiler.ts +1 -1
  33. package/packages/runtime/src/evidence/evidence-store.ts +2 -2
  34. package/packages/runtime/src/executor/action-tool-map.ts +4 -0
  35. package/packages/runtime/src/executor/built-in-tools.ts +29 -0
  36. package/packages/runtime/src/executor/llm-task-executor.ts +46 -4
  37. package/packages/runtime/src/executor/node-prompt-builder.ts +18 -1
  38. package/packages/runtime/src/models/failure.ts +2 -0
  39. package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +320 -46
  40. package/packages/runtime/src/scheduler/scheduler.ts +93 -15
  41. package/packages/runtime/src/verification/verification-compiler.ts +7 -5
  42. package/packages/runtime/src/workspace/strategies/git-worktree.ts +24 -16
  43. package/vscode-extension/package.json +185 -185
  44. package/vscode-extension/oxe-agents-0.9.1.vsix +0 -0
  45. package/vscode-extension/oxe-agents-0.9.2.vsix +0 -0
  46. package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
  47. package/vscode-extension/oxe-agents-1.4.0.vsix +0 -0
  48. package/vscode-extension/oxe-agents-1.5.0.vsix +0 -0
  49. package/vscode-extension/oxe-agents-1.5.1.vsix +0 -0
  50. package/vscode-extension/oxe-agents-1.6.0.vsix +0 -0
  51. package/vscode-extension/oxe-agents-1.7.0.vsix +0 -0
  52. package/vscode-extension/oxe-agents-1.8.0.vsix +0 -0
package/bin/oxe-cc.js CHANGED
@@ -209,8 +209,8 @@ function buildInstallSummary(opts, fullLayout) {
209
209
  if (opts.copilotCli || opts.allAgents || anyGranularAgent(opts)) agentHint.push('CLIs / multi-agente');
210
210
  if (agentHint.length) {
211
211
  nextSteps.push({
212
- desc: `Mapear o código no agente (${agentHint.join(', ')}):`,
213
- cmd: '/oxe-scan',
212
+ desc: `Entrar no fluxo OXE no agente (${agentHint.join(', ')}) e deixar o router indicar o primeiro passo:`,
213
+ cmd: '/oxe',
214
214
  });
215
215
  } else if (opts.oxeOnly) {
216
216
  nextSteps.push({
@@ -220,7 +220,7 @@ function buildInstallSummary(opts, fullLayout) {
220
220
  } else {
221
221
  nextSteps.push({
222
222
  desc: 'Primeiro passo do fluxo no seu editor:',
223
- cmd: '/oxe-scan',
223
+ cmd: '/oxe',
224
224
  });
225
225
  }
226
226
 
@@ -252,6 +252,7 @@ function buildUninstallFooter(u) {
252
252
  const bullets = [];
253
253
  const p = u.dryRun ? '[simulação] ' : '';
254
254
  const rm = u.dryRun ? 'Seriam removidos' : 'Removidos';
255
+ const localIdeArtifacts = shouldAlsoRemoveLocalIdeArtifacts(u);
255
256
  const granularAgents = [
256
257
  u.agentOpenCode ? 'OpenCode' : null,
257
258
  u.agentGemini ? 'Gemini' : null,
@@ -277,9 +278,9 @@ function buildUninstallFooter(u) {
277
278
  } else if (granularAgents.length) {
278
279
  bullets.push(`${p}${rm} apenas as integrações selecionadas: ${granularAgents.join(', ')}.`);
279
280
  }
280
- if (u.ideLocal) {
281
+ if (localIdeArtifacts) {
281
282
  bullets.push(
282
- `${p}${rm} integrações OXE no repositório (.cursor, .github, .claude, .copilot, .opencode, … conforme flags).`
283
+ `${p}${rm} integrações OXE no repositório (.cursor, .github, .claude, .copilot, .opencode, … conforme flags ou artefatos locais detectados).`
283
284
  );
284
285
  }
285
286
  if (u.globalCli) bullets.push(`${p}${rm} também o pacote npm global oxe-cc do PATH.`);
@@ -1533,7 +1534,9 @@ function printOxeHealthDiagnostics(target, c, diagOpts = {}) {
1533
1534
  typeof r.planSelfEvaluation.confidence === 'number' ? `${r.planSelfEvaluation.confidence}%` : '—';
1534
1535
  console.log(` ${c ? dim : ''}Plano (autoavaliação):${c ? reset : ''} melhor=${best} | confiança=${conf}`);
1535
1536
  }
1536
- if (typeof r.executionRationalityReady === 'boolean') {
1537
+ if (r.executionRationality && r.executionRationality.applicable === false) {
1538
+ console.log(` ${c ? dim : ''}Prontidão racional:${c ? reset : ''} não aplicável ainda (PLAN.md ausente)`);
1539
+ } else if (typeof r.executionRationalityReady === 'boolean') {
1537
1540
  console.log(
1538
1541
  ` ${c ? dim : ''}Prontidão racional:${c ? reset : ''} implementation=${r.implementationPackReady ? 'ok' : 'pendente'} | anchors=${r.referenceAnchorsReady ? 'ok' : 'pendente'} | fixtures=${r.fixturePackReady ? 'ok' : 'pendente'}`
1539
1542
  );
@@ -1670,7 +1673,7 @@ function runStatusFull(target) {
1670
1673
 
1671
1674
  printSection('OXE ▸ status --full');
1672
1675
  console.log(` ${c ? green : ''}Projeto:${c ? reset : ''} ${c ? cyan : ''}${target}${c ? reset : ''}`);
1673
- console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || 'modo legado'}${c ? reset : ''}`);
1676
+ console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || ' (sem sessão ativa)'}${c ? reset : ''}`);
1674
1677
  console.log(` ${c ? green : ''}Workspace mode:${c ? reset : ''} ${report.workspaceMode || 'oxe_project'}`);
1675
1678
  console.log(` ${c ? green : ''}Fase:${c ? reset : ''} ${report.phase || '—'}`);
1676
1679
 
@@ -2102,10 +2105,18 @@ function runDoctor(target, options = {}) {
2102
2105
  .sort();
2103
2106
 
2104
2107
  if (!wfTgt) {
2105
- console.log(
2106
- `${yellow}AVISO${reset} Não oxe/workflows/ nem .oxe/workflows/ neste projeto — rode ${cyan}npx oxe-cc@latest${reset} para instalar.`
2107
- );
2108
- process.exit(1);
2108
+ // If the project has .oxe/runs/ it's a runtime-only project — workflows are optional
2109
+ const hasRuntimeRuns = fs.existsSync(path.join(target, '.oxe', 'runs'));
2110
+ if (hasRuntimeRuns) {
2111
+ console.log(`${green}OK${reset} Runtime-only project (.oxe/runs/ presente) — workflows não obrigatórios.`);
2112
+ console.log(`${c ? dim : ''} Para instalar workflows completos: ${cyan}npx oxe-cc@latest${reset}`);
2113
+ } else {
2114
+ console.log(
2115
+ `${yellow}AVISO${reset} Não há oxe/workflows/ nem .oxe/workflows/ neste projeto — rode ${cyan}npx oxe-cc@latest${reset} para instalar.`
2116
+ );
2117
+ process.exit(1);
2118
+ }
2119
+ return;
2109
2120
  }
2110
2121
 
2111
2122
  const actual = fs
@@ -2190,6 +2201,8 @@ function runDoctor(target, options = {}) {
2190
2201
  }
2191
2202
  }
2192
2203
 
2204
+ const report = oxeHealth.buildHealthReport(target);
2205
+
2193
2206
  // IDE health gates
2194
2207
  console.log('');
2195
2208
  const ideChecks = [];
@@ -2204,25 +2217,44 @@ function runDoctor(target, options = {}) {
2204
2217
 
2205
2218
  const claudeLocalDir = path.join(target, 'commands', 'oxe');
2206
2219
  const claudeGlobalDir = path.join(require('os').homedir(), '.claude', 'commands');
2207
- const claudeReady = fs.existsSync(claudeLocalDir) || fs.existsSync(claudeGlobalDir);
2208
- ideChecks.push({ label: 'Claude Code', ready: claudeReady, hint: 'commands/oxe/ ou ~/.claude/commands/' });
2220
+ const claudeLocalReady = fs.existsSync(claudeLocalDir);
2221
+ const claudeGlobalReady = fs.existsSync(claudeGlobalDir);
2222
+ ideChecks.push({
2223
+ label: 'Claude Code',
2224
+ ready: claudeLocalReady || claudeGlobalReady,
2225
+ hint: claudeLocalReady
2226
+ ? 'commands/oxe/'
2227
+ : claudeGlobalReady
2228
+ ? '~/.claude/commands/ (global do utilizador)'
2229
+ : 'commands/oxe/ ou ~/.claude/commands/',
2230
+ status: claudeLocalReady ? 'local' : claudeGlobalReady ? 'global_only' : 'missing',
2231
+ });
2209
2232
 
2210
2233
  const codexReport = oxeHealth.codexIntegrationReport(target);
2211
- ideChecks.push({ label: 'Codex', ready: codexReport.commandsReady, hint: '~/.codex/prompts/oxe.md' });
2234
+ ideChecks.push({
2235
+ label: 'Codex',
2236
+ ready: codexReport.commandsReady,
2237
+ hint: codexReport.promptSource === 'workspace'
2238
+ ? '.codex/prompts/oxe.md'
2239
+ : codexReport.promptSource === 'global'
2240
+ ? '~/.codex/prompts/oxe.md (global do utilizador)'
2241
+ : '.codex/prompts/oxe.md ou ~/.codex/prompts/oxe.md',
2242
+ status: codexReport.promptSource,
2243
+ });
2212
2244
 
2213
2245
  for (const ide of ideChecks) {
2214
2246
  if (ide.ready) {
2215
- console.log(`${c ? green : ''}OK${c ? reset : ''} ${ide.label} pronto (${ide.hint})`);
2247
+ const suffix = ide.status === 'global_only' || ide.status === 'global'
2248
+ ? ' — apenas global'
2249
+ : '';
2250
+ console.log(`${c ? green : ''}OK${c ? reset : ''} ${ide.label} pronto (${ide.hint})${suffix}`);
2216
2251
  } else {
2217
2252
  console.log(`${c ? dim : ''}Obs.:${c ? reset : ''} ${ide.label} não detectado — esperado ${ide.hint}`);
2218
2253
  }
2219
2254
  }
2220
2255
 
2221
2256
  // Runtime compilation check
2222
- const runtimeCompiledPath = path.join(target, 'lib', 'runtime', 'index.js');
2223
- const runtimeDistPath = path.join(target, 'packages', 'runtime', 'dist-tests');
2224
- const runtimeCompiled = fs.existsSync(runtimeCompiledPath) || fs.existsSync(runtimeDistPath);
2225
- if (runtimeCompiled) {
2257
+ if (report.runtimeMode && report.runtimeMode.enterprise_available) {
2226
2258
  console.log(`${c ? green : ''}OK${c ? reset : ''} Runtime compilado detectado — modo enterprise disponível`);
2227
2259
  } else {
2228
2260
  console.log(`${c ? dim : ''}Obs.:${c ? reset : ''} Runtime não compilado — operando em modo legado (sem perda de UX)`);
@@ -2230,7 +2262,7 @@ function runDoctor(target, options = {}) {
2230
2262
 
2231
2263
  // Readiness gate summary
2232
2264
  const stateFilePath = path.join(target, '.oxe', 'STATE.md');
2233
- let readinessCmd = '/oxe-scan';
2265
+ let readinessCmd = '/oxe';
2234
2266
  let readinessDesc = 'Nenhum STATE.md encontrado';
2235
2267
  if (fs.existsSync(stateFilePath)) {
2236
2268
  try {
@@ -2238,7 +2270,7 @@ function runDoctor(target, options = {}) {
2238
2270
  const phaseMatch = stateContent.match(/fase[:\s]+([a-z_]+)/i) || stateContent.match(/phase[:\s]+([a-z_]+)/i) || stateContent.match(/status[:\s]+([a-z_]+)/i);
2239
2271
  const phase = phaseMatch ? phaseMatch[1].toLowerCase() : 'init';
2240
2272
  const phaseMap = {
2241
- init: { cmd: '/oxe-scan', desc: 'Pronto para /oxe-scan' },
2273
+ init: { cmd: '/oxe', desc: 'Pronto para /oxe' },
2242
2274
  scan_complete: { cmd: '/oxe-spec', desc: 'Pronto para /oxe-spec' },
2243
2275
  spec_complete: { cmd: '/oxe-plan', desc: 'Pronto para /oxe-plan' },
2244
2276
  plan_complete: { cmd: '/oxe-execute', desc: 'Pronto para /oxe-execute' },
@@ -2260,7 +2292,6 @@ function runDoctor(target, options = {}) {
2260
2292
  }
2261
2293
 
2262
2294
  printOxeHealthDiagnostics(target, c);
2263
- const report = oxeHealth.buildHealthReport(target);
2264
2295
  const statusColor = report.healthStatus === 'healthy' ? green : report.healthStatus === 'warning' ? yellow : red;
2265
2296
  console.log(`\n ${statusColor}Diagnóstico ${report.healthStatus}${reset}`);
2266
2297
  if (report.healthStatus === 'broken') {
@@ -2275,7 +2306,7 @@ function runDoctor(target, options = {}) {
2275
2306
  `Saúde lógica: ${report.healthStatus}`,
2276
2307
  ],
2277
2308
  nextSteps: [
2278
- { desc: 'Mapear ou atualizar o codebase no agente:', cmd: '/oxe-scan' },
2309
+ { desc: 'Entrar no fluxo OXE e deixar o router apontar o primeiro passo:', cmd: '/oxe' },
2279
2310
  { desc: 'Ver ajuda e ordem dos passos OXE:', cmd: '/oxe-help' },
2280
2311
  { desc: 'Reinstalar ou atualizar arquivos do OXE:', cmd: 'npx oxe-cc@latest --force' },
2281
2312
  ],
@@ -2496,7 +2527,7 @@ ${cyan}oxe-cc${reset} — instala workflows OXE (núcleo .oxe/ + integrações:
2496
2527
  npx oxe-cc init-oxe [opções] [pasta-do-projeto]
2497
2528
  npx oxe-cc context <build|inspect> [opções] [pasta-do-projeto]
2498
2529
  npx oxe-cc dashboard [opções] [pasta-do-projeto]
2499
- npx oxe-cc runtime <status|start|pause|resume|replay|compile|verify|project|ci|promote|recover|gates|agents> [opções] [pasta-do-projeto]
2530
+ npx oxe-cc runtime <status|start|pause|resume|replay|compile|verify|project|ci|promote|recover|gates|agents|execute> [opções] [pasta-do-projeto]
2500
2531
  npx oxe-cc azure <status|doctor|auth|sync|find|servicebus|eventgrid|sql|operations> [opções] [pasta-do-projeto]
2501
2532
  npx oxe-cc capabilities <list|install|remove|update> [opções] [id]
2502
2533
  npx oxe-cc uninstall [opções] [pasta-do-projeto]
@@ -2695,7 +2726,19 @@ function runInstall(opts) {
2695
2726
  assertNotWslWindowsNode();
2696
2727
  const home = os.homedir();
2697
2728
  const prevManifest = oxeManifest.loadFileManifest(home);
2698
- oxeManifest.backupModifiedFromManifest(home, prevManifest, opts, { yellow, cyan, dim, reset });
2729
+ const backupScopeRoots = [target];
2730
+ const installAgentPaths = oxeAgentInstall.buildAgentInstallPaths(!opts.ideLocal, target);
2731
+ if (opts.cursor) backupScopeRoots.push(installCursorBase(opts));
2732
+ if (opts.copilot) backupScopeRoots.push(path.join(target, '.github'));
2733
+ if (opts.copilotCli || opts.allAgents) {
2734
+ backupScopeRoots.push(installClaudeBase(opts), installCopilotCliHome(opts));
2735
+ }
2736
+ if (opts.agentOpenCode || opts.allAgents) backupScopeRoots.push(...installAgentPaths.opencodeCommandDirs);
2737
+ if (opts.agentGemini || opts.allAgents) backupScopeRoots.push(installAgentPaths.geminiCommandsBase);
2738
+ if (opts.agentCodex || opts.allAgents) backupScopeRoots.push(installAgentPaths.codexPromptsDir, installAgentPaths.codexAgentsSkillsRoot);
2739
+ if (opts.agentWindsurf || opts.allAgents) backupScopeRoots.push(installAgentPaths.windsurfWorkflowsDir);
2740
+ if (opts.agentAntigravity || opts.allAgents) backupScopeRoots.push(installAgentPaths.antigravitySkillsRoot);
2741
+ oxeManifest.backupModifiedFromManifest(home, prevManifest, opts, { yellow, cyan, dim, reset }, { scopeRoots: backupScopeRoots });
2699
2742
 
2700
2743
  printSection('OXE ▸ Instalação no projeto');
2701
2744
  const c = useAnsiColors();
@@ -2735,7 +2778,7 @@ function runInstall(opts) {
2735
2778
  }
2736
2779
 
2737
2780
  const copyOpts = { dryRun: opts.dryRun, force: opts.force };
2738
- const agentPaths = oxeAgentInstall.buildAgentInstallPaths(!opts.ideLocal, target);
2781
+ const agentPaths = installAgentPaths;
2739
2782
 
2740
2783
  if (fullLayout) {
2741
2784
  copyDir(path.join(PKG_ROOT, 'oxe'), path.join(target, 'oxe'), copyOpts, false);
@@ -3145,6 +3188,31 @@ function uninstallLocalIdeFromProject(u, removedPaths) {
3145
3188
  }
3146
3189
  }
3147
3190
 
3191
+ /**
3192
+ * @param {UninstallOpts} u
3193
+ */
3194
+ function shouldAlsoRemoveLocalIdeArtifacts(u) {
3195
+ if (u.ideLocal) return true;
3196
+ if (u.noProject) return false;
3197
+ if (!(u.allAgents || anyGranularUninstallAgent(u) || u.cursor || u.copilot || u.copilotCli)) return false;
3198
+ const proj = path.resolve(u.dir);
3199
+ const localAgentPaths = oxeAgentInstall.buildAgentInstallPaths(false, proj);
3200
+ if (u.cursor && fs.existsSync(path.join(proj, '.cursor', 'commands'))) return true;
3201
+ if (u.copilot && (fs.existsSync(path.join(proj, '.github', 'prompts')) || fs.existsSync(path.join(proj, '.github', 'copilot-instructions.md')))) {
3202
+ return true;
3203
+ }
3204
+ if (u.copilotCli && (fs.existsSync(path.join(proj, '.claude', 'commands')) || fs.existsSync(path.join(proj, '.copilot', 'commands')))) {
3205
+ return true;
3206
+ }
3207
+ const selectedAll = u.allAgents || !anyGranularUninstallAgent(u);
3208
+ if ((selectedAll || u.agentOpenCode) && localAgentPaths.opencodeCommandDirs.some((dir) => fs.existsSync(dir))) return true;
3209
+ if ((selectedAll || u.agentGemini) && fs.existsSync(localAgentPaths.geminiCommandsBase)) return true;
3210
+ if ((selectedAll || u.agentCodex) && (fs.existsSync(localAgentPaths.codexPromptsDir) || fs.existsSync(localAgentPaths.codexAgentsSkillsRoot))) return true;
3211
+ if ((selectedAll || u.agentWindsurf) && fs.existsSync(localAgentPaths.windsurfWorkflowsDir)) return true;
3212
+ if ((selectedAll || u.agentAntigravity) && fs.existsSync(localAgentPaths.antigravitySkillsRoot)) return true;
3213
+ return false;
3214
+ }
3215
+
3148
3216
  /**
3149
3217
  * @param {string[]} argv
3150
3218
  * @returns {UninstallOpts}
@@ -3376,6 +3444,7 @@ function runUninstall(u) {
3376
3444
  if (u.dryRun) console.log(` ${c ? yellow : ''}(dry-run)${c ? reset : ''}`);
3377
3445
 
3378
3446
  const removedPaths = [];
3447
+ const removeLocalIdeArtifacts = shouldAlsoRemoveLocalIdeArtifacts(u);
3379
3448
 
3380
3449
  if (u.cursor) {
3381
3450
  const base = cursorUserDir(ideOpts);
@@ -3531,7 +3600,7 @@ function runUninstall(u) {
3531
3600
  }
3532
3601
  }
3533
3602
 
3534
- if (u.ideLocal) {
3603
+ if (removeLocalIdeArtifacts) {
3535
3604
  uninstallLocalIdeFromProject(u, removedPaths);
3536
3605
  }
3537
3606
 
@@ -3976,6 +4045,13 @@ function parseRuntimeArgs(argv) {
3976
4045
  fromEventId: '',
3977
4046
  writeReport: false,
3978
4047
  gateId: '',
4048
+ // execute flags
4049
+ provider: '',
4050
+ apiKey: '',
4051
+ model: '',
4052
+ baseUrl: '',
4053
+ maxTurns: null,
4054
+ recompile: false,
3979
4055
  decision: '',
3980
4056
  actor: '',
3981
4057
  targetKind: '',
@@ -4013,6 +4089,12 @@ function parseRuntimeArgs(argv) {
4013
4089
  else if (a === '--status' && argv[i + 1]) out.gateStatus = String(argv[++i]);
4014
4090
  else if (a === '--scope' && argv[i + 1]) out.gateScope = String(argv[++i]);
4015
4091
  else if (a === '--json') out.jsonOutput = true;
4092
+ else if (a === '--provider' && argv[i + 1]) out.provider = String(argv[++i]);
4093
+ else if (a === '--api-key' && argv[i + 1]) out.apiKey = String(argv[++i]);
4094
+ else if (a === '--model' && argv[i + 1]) out.model = String(argv[++i]);
4095
+ else if (a === '--base-url' && argv[i + 1]) out.baseUrl = String(argv[++i]);
4096
+ else if (a === '--max-turns' && argv[i + 1]) out.maxTurns = Number(argv[++i]);
4097
+ else if (a === '--recompile') out.recompile = true;
4016
4098
  else if (!a.startsWith('-')) positionals.push(a);
4017
4099
  else {
4018
4100
  out.parseError = true;
@@ -4155,7 +4237,7 @@ function runContext(opts) {
4155
4237
  return;
4156
4238
  }
4157
4239
  console.log(` ${c ? green : ''}Projeto:${c ? reset : ''} ${c ? cyan : ''}${opts.dir}${c ? reset : ''}`);
4158
- console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || 'modo legado'}${c ? reset : ''}`);
4240
+ console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || ' (sem sessão ativa)'}${c ? reset : ''}`);
4159
4241
  console.log(` ${c ? green : ''}Workflow:${c ? reset : ''} ${selectedWorkflow}`);
4160
4242
  console.log(` ${c ? green : ''}Tier:${c ? reset : ''} ${pack.context_tier}`);
4161
4243
  console.log(` ${c ? green : ''}Quality:${c ? reset : ''} ${pack.context_quality.score} (${pack.context_quality.status})`);
@@ -4222,7 +4304,7 @@ function runContext(opts) {
4222
4304
  return;
4223
4305
  }
4224
4306
  console.log(` ${c ? green : ''}Projeto:${c ? reset : ''} ${c ? cyan : ''}${opts.dir}${c ? reset : ''}`);
4225
- console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || 'modo legado'}${c ? reset : ''}`);
4307
+ console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || ' (sem sessão ativa)'}${c ? reset : ''}`);
4226
4308
  console.log(` ${c ? green : ''}Packs:${c ? reset : ''} ${packs.length}`);
4227
4309
  for (const pack of packs) {
4228
4310
  const qualityFlag = (pack.context_quality.score < 30 || pack.context_quality.status === 'critical') ? ` ${yellow}[CRÍTICO]${reset}` : '';
@@ -4287,7 +4369,7 @@ async function runRuntime(opts) {
4287
4369
  const activeSession = opts.activeSession || oxeHealth.parseActiveSession(stateText) || null;
4288
4370
  const p = oxeOperational.operationalPaths(opts.dir, activeSession);
4289
4371
  console.log(` ${c ? green : ''}Projeto:${c ? reset : ''} ${c ? cyan : ''}${opts.dir}${c ? reset : ''}`);
4290
- console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || 'modo legado'}${c ? reset : ''}`);
4372
+ console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || ' (sem sessão ativa)'}${c ? reset : ''}`);
4291
4373
 
4292
4374
  if (opts.action === 'status') {
4293
4375
  const current = oxeOperational.readRunState(opts.dir, activeSession);
@@ -4350,13 +4432,28 @@ async function runRuntime(opts) {
4350
4432
  console.log(` ${c ? green : ''}Runtime:${c ? reset : ''} ${runtimeMode.runtime_mode || 'legacy'} · fallback=${runtimeMode.fallback_mode || 'none'}`);
4351
4433
  }
4352
4434
  if (report.policyCoverage) {
4353
- console.log(` ${c ? green : ''}Policy coverage:${c ? reset : ''} ${report.policyCoverage.coveragePercent}% · uncovered=${report.policyCoverage.uncoveredMutations}`);
4435
+ const pctCov = report.policyCoverage.coveragePercent;
4436
+ const policyLabel = pctCov === 0
4437
+ ? `${c ? dim : ''}não configurada (opcional)${c ? reset : ''}`
4438
+ : `${pctCov}% · uncovered=${report.policyCoverage.uncoveredMutations}`;
4439
+ console.log(` ${c ? green : ''}Policy coverage:${c ? reset : ''} ${policyLabel}`);
4354
4440
  }
4355
4441
  if (report.promotionReadiness) {
4356
- console.log(` ${c ? green : ''}Promotion readiness:${c ? reset : ''} ${report.promotionReadiness.status}${Array.isArray(report.promotionReadiness.blockers) && report.promotionReadiness.blockers.length ? ` · ${report.promotionReadiness.blockers.join(', ')}` : ''}`);
4442
+ const promoStatus = report.promotionReadiness.status;
4443
+ const blockers = Array.isArray(report.promotionReadiness.blockers) ? report.promotionReadiness.blockers : [];
4444
+ // Only show blockers that are not solely due to unconfigured policy
4445
+ const meaningfulBlockers = blockers.filter(b => b !== 'policy_uncovered_mutations' || report.policyCoverage.coveragePercent > 0);
4446
+ const promoLabel = promoStatus === 'blocked' && meaningfulBlockers.length === 0
4447
+ ? `${c ? dim : ''}n/a (execução não concluída)${c ? reset : ''}`
4448
+ : `${promoStatus}${meaningfulBlockers.length ? ` · ${meaningfulBlockers.join(', ')}` : ''}`;
4449
+ console.log(` ${c ? green : ''}Promotion readiness:${c ? reset : ''} ${promoLabel}`);
4357
4450
  }
4358
4451
  if (report.recoveryState) {
4359
- console.log(` ${c ? green : ''}Recovery:${c ? reset : ''} ${report.recoveryState.status} · recoveries=${report.recoveryState.recoverCount ?? 0} · issues=${Array.isArray(report.recoveryState.issues) ? report.recoveryState.issues.length : 0}`);
4452
+ const recIssues = Array.isArray(report.recoveryState.issues) ? report.recoveryState.issues.length : 0;
4453
+ const recLabel = recIssues === 0
4454
+ ? `${report.recoveryState.status} · ok`
4455
+ : `${report.recoveryState.status} · issues=${recIssues} — rode ${c ? cyan : ''}runtime status --verbose${c ? reset : ''} para detalhes`;
4456
+ console.log(` ${c ? green : ''}Recovery:${c ? reset : ''} ${recLabel} · recoveries=${report.recoveryState.recoverCount ?? 0}`);
4360
4457
  }
4361
4458
  if (multiAgent) {
4362
4459
  console.log(` ${c ? green : ''}Multi-agent:${c ? reset : ''} ${multiAgent.enabled ? (multiAgent.mode || 'active') : 'disabled'} · agentes=${Array.isArray(multiAgent.agents) ? multiAgent.agents.length : 0} · ownership=${Array.isArray(multiAgent.ownership) ? multiAgent.ownership.length : 0}`);
@@ -4526,6 +4623,17 @@ async function runRuntime(opts) {
4526
4623
 
4527
4624
  if (opts.action === 'compile') {
4528
4625
  try {
4626
+ // --recompile: delete existing run state files so a fresh run_id is generated
4627
+ if (opts.recompile) {
4628
+ const runsDir = path.join(opts.dir, '.oxe', 'runs');
4629
+ if (require('fs').existsSync(runsDir)) {
4630
+ require('fs').readdirSync(runsDir).forEach(f => {
4631
+ if (f.endsWith('.json') && !f.includes('ci-results')) {
4632
+ require('fs').unlinkSync(path.join(runsDir, f));
4633
+ }
4634
+ });
4635
+ }
4636
+ }
4529
4637
  const compiled = oxeOperational.compileExecutionGraphFromArtifacts(opts.dir, activeSession);
4530
4638
  const suite = oxeOperational.compileVerificationSuiteFromArtifacts(opts.dir, activeSession, {
4531
4639
  runState: compiled.run,
@@ -4535,7 +4643,33 @@ async function runRuntime(opts) {
4535
4643
  console.log(` ${c ? green : ''}Graph:${c ? reset : ''} ${compiled.graph.metadata.node_count} nó(s) · ${compiled.graph.metadata.wave_count} onda(s)`);
4536
4644
  console.log(` ${c ? green : ''}Checks:${c ? reset : ''} ${Array.isArray(suite.suite.checks) ? suite.suite.checks.length : 0}`);
4537
4645
  if (compiled.validationErrors.length) {
4538
- console.log(` ${yellow}Validation:${reset} ${compiled.validationErrors.join(' | ')}`);
4646
+ // Bucket 1: static-analysis hints (HINT(...))
4647
+ const hints = compiled.validationErrors.filter(e => e.startsWith('HINT('));
4648
+ // Bucket 2: mutation-scope overlaps (info-only in single-agent)
4649
+ const mutationWarns = compiled.validationErrors.filter(e => e.includes('mutate the same paths in parallel'));
4650
+ // Bucket 3: structural errors (cycles, missing deps)
4651
+ const blocking = compiled.validationErrors.filter(e =>
4652
+ !e.startsWith('HINT(') && !e.includes('mutate the same paths in parallel')
4653
+ );
4654
+ if (blocking.length) {
4655
+ console.log(` ${yellow}Validation (erros):${reset} ${blocking.join(' | ')}`);
4656
+ }
4657
+ if (mutationWarns.length) {
4658
+ console.log(` ${c ? dim : ''}Info (single-agent — tarefas na mesma onda são sequenciais, sobreposição de arquivos não bloqueia):${c ? reset : ''}`);
4659
+ mutationWarns.forEach(w => console.log(` ${c ? dim : ''} · ${w}${c ? reset : ''}`));
4660
+ }
4661
+ if (hints.length) {
4662
+ console.log(` ${yellow}Dicas de spec/plan (detectadas em tempo de compilação):${reset}`);
4663
+ hints.forEach(h => {
4664
+ // Format: HINT(type): message
4665
+ const match = h.match(/^HINT\(([^)]+)\):\s*(.*)/s);
4666
+ if (match) {
4667
+ console.log(` ${yellow}⚑${reset} [${match[1]}] ${match[2]}`);
4668
+ } else {
4669
+ console.log(` ${yellow}⚑${reset} ${h}`);
4670
+ }
4671
+ });
4672
+ }
4539
4673
  }
4540
4674
  console.log(` ${c ? green : ''}Arquivo:${c ? reset : ''} ${path.join(p.runsDir, `${compiled.run.run_id}.json`)}`);
4541
4675
  return;
@@ -4585,7 +4719,7 @@ async function runRuntime(opts) {
4585
4719
  console.log(` ${c ? green : ''}✓${c ? reset : ''} Projeções geradas a partir do estado canônico.`);
4586
4720
  console.log(` ${c ? green : ''}Run:${c ? reset : ''} ${projected.run.run_id}`);
4587
4721
  console.log(` ${c ? green : ''}STATE:${c ? reset : ''} ${projected.paths.state}`);
4588
- console.log(` ${c ? green : ''}PLAN:${c ? reset : ''} ${projected.paths.plan}`);
4722
+ console.log(` ${c ? green : ''}PLAN-STATUS:${c ? reset : ''} ${projected.paths.plan.replace(/PLAN\.md$/, 'PLAN-STATUS.md')}`);
4589
4723
  console.log(` ${c ? green : ''}VERIFY:${c ? reset : ''} ${projected.paths.verify}`);
4590
4724
  console.log(` ${c ? green : ''}RUN-SUMMARY:${c ? reset : ''} ${projected.paths.runSummary}`);
4591
4725
  console.log(` ${c ? green : ''}PR-SUMMARY:${c ? reset : ''} ${projected.paths.prSummary}`);
@@ -4598,27 +4732,64 @@ async function runRuntime(opts) {
4598
4732
 
4599
4733
  if (opts.action === 'execute') {
4600
4734
  try {
4735
+ // Resolve provider: flag > env vars
4736
+ const apiKey = opts.apiKey || process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY || '';
4737
+ const model = opts.model || process.env.OXE_MODEL || 'claude-sonnet-4-6';
4738
+ const baseUrl = opts.baseUrl || process.env.OXE_BASE_URL || 'https://api.anthropic.com/v1';
4739
+ if (!apiKey) {
4740
+ console.error(`${red}Erro: executor LLM não configurado.${reset}`);
4741
+ console.error(` Use: --api-key <chave> ou exporte ANTHROPIC_API_KEY`);
4742
+ console.error(` Exemplo: oxe-cc runtime execute --api-key $ANTHROPIC_API_KEY --model claude-sonnet-4-6`);
4743
+ process.exit(1);
4744
+ }
4745
+ const providerConfig = { baseUrl, apiKey, model, maxTurns: opts.maxTurns || 10 };
4601
4746
  const result = await oxeOperational.runRuntimeExecute(opts.dir, activeSession, {
4602
4747
  runId: opts.runId || undefined,
4603
4748
  heartbeatTimeoutMs: opts.heartbeatTimeoutMs || undefined,
4749
+ providerConfig,
4750
+ onProgress: (event) => {
4751
+ if (event.type === 'turn_start') {
4752
+ const turn = event.detail?.turn ?? 0;
4753
+ if (turn === 0) process.stdout.write(` → ${event.nodeId} `);
4754
+ } else if (event.type === 'tool_call') {
4755
+ process.stdout.write('.');
4756
+ } else if (event.type === 'VerificationStarted') {
4757
+ process.stdout.write(' [verify]');
4758
+ } else if (event.type === 'WorkItemCompleted') {
4759
+ process.stdout.write(` ✓\n`);
4760
+ } else if (event.type === 'WorkItemBlocked') {
4761
+ process.stdout.write(` ✗\n`);
4762
+ } else if (event.type === 'RetryScheduled') {
4763
+ process.stdout.write(` ↺ retry ${event.payload?.next_attempt}\n → ${event.work_item_id} `);
4764
+ }
4765
+ },
4604
4766
  });
4605
- if (opts.jsonOutput) {
4606
- console.log(JSON.stringify(result, null, 2));
4607
- if (result.result && result.result.failed && result.result.failed.length > 0) process.exitCode = 1;
4608
- return;
4609
- }
4610
- const r = result.result || {};
4611
- const completed = Array.isArray(r.completed) ? r.completed : [];
4612
- const failed = Array.isArray(r.failed) ? r.failed : [];
4613
- const blocked = Array.isArray(r.blocked) ? r.blocked : [];
4614
- console.log(` ${c ? green : ''}✓${c ? reset : ''} Runtime execute concluído (modo: ${result.mode})`);
4615
- console.log(` ${c ? green : ''}Completados:${c ? reset : ''} ${completed.length}`);
4767
+ if (opts.jsonOutput) {
4768
+ console.log(JSON.stringify(result, null, 2));
4769
+ if (result.result && ((result.result.failed && result.result.failed.length > 0) || result.result.status === 'blocked')) process.exitCode = 1;
4770
+ return;
4771
+ }
4772
+ const r = result.result || {};
4773
+ const completed = Array.isArray(r.completed) ? r.completed : [];
4774
+ const failed = Array.isArray(r.failed) ? r.failed : [];
4775
+ const blocked = Array.isArray(r.blocked) ? r.blocked : [];
4776
+ const okColor = r.status === 'blocked' ? yellow : green;
4777
+ console.log(` ${c ? okColor : ''}${r.status === 'blocked' ? '!' : '✓'}${c ? reset : ''} Runtime execute concluído (modo: ${result.mode})`);
4778
+ if (result.preflight) {
4779
+ console.log(` ${c ? green : ''}Preflight:${c ? reset : ''} ${result.preflight.ok ? 'ready' : 'blocked'}`);
4780
+ if (Array.isArray(result.preflight.blockers) && result.preflight.blockers.length) {
4781
+ for (const blocker of result.preflight.blockers) {
4782
+ console.log(` ${yellow}BLOCKER${reset} ${blocker}`);
4783
+ }
4784
+ }
4785
+ }
4786
+ console.log(` ${c ? green : ''}Completados:${c ? reset : ''} ${completed.length}`);
4616
4787
  if (failed.length > 0)
4617
4788
  console.log(` ${c ? red : ''}Falhos:${c ? reset : ''} ${failed.length} — ${failed.join(', ')}`);
4618
4789
  if (blocked.length > 0)
4619
4790
  console.log(` ${c ? '\x1b[33m' : ''}Bloqueados:${c ? reset : ''} ${blocked.length} — ${blocked.join(', ')}`);
4620
- if (failed.length > 0) process.exitCode = 1;
4621
- return;
4791
+ if (failed.length > 0 || r.status === 'blocked') process.exitCode = 1;
4792
+ return;
4622
4793
  } catch (err) {
4623
4794
  console.error(`${red}${err && err.message ? err.message : 'Falha ao executar runtime.'}${reset}`);
4624
4795
  process.exit(1);
@@ -4794,7 +4965,7 @@ function runAzure(opts) {
4794
4965
  };
4795
4966
 
4796
4967
  console.log(` ${c ? green : ''}Projeto:${c ? reset : ''} ${c ? cyan : ''}${opts.dir}${c ? reset : ''}`);
4797
- console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || 'modo legado'}${c ? reset : ''}`);
4968
+ console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || ' (sem sessão ativa)'}${c ? reset : ''}`);
4798
4969
 
4799
4970
  try {
4800
4971
  if (opts.scope === 'status') {
@@ -5118,7 +5289,7 @@ function runPlanVisual(opts) {
5118
5289
  const planPath = sp.plan || oxeHealth.oxePaths(opts.dir).plan;
5119
5290
 
5120
5291
  console.log(` ${c ? green : ''}Projeto:${c ? reset : ''} ${c ? cyan : ''}${opts.dir}${c ? reset : ''}`);
5121
- console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || 'modo legado'}${c ? reset : ''}`);
5292
+ console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || ' (sem sessão ativa)'}${c ? reset : ''}`);
5122
5293
 
5123
5294
  if (!fs.existsSync(planPath)) {
5124
5295
  console.log(`\n ${yellow}PLAN.md não encontrado em ${planPath}${reset}`);
@@ -5172,7 +5343,7 @@ function runVerifyMatrix(opts) {
5172
5343
  const verifyPath = sp.verify || oxeHealth.oxePaths(opts.dir).verify;
5173
5344
 
5174
5345
  console.log(` ${c ? green : ''}Projeto:${c ? reset : ''} ${c ? cyan : ''}${opts.dir}${c ? reset : ''}`);
5175
- console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || 'modo legado'}${c ? reset : ''}`);
5346
+ console.log(` ${c ? green : ''}Sessão:${c ? reset : ''} ${c ? cyan : ''}${activeSession || ' (sem sessão ativa)'}${c ? reset : ''}`);
5176
5347
 
5177
5348
  const specMd = fs.existsSync(specPath) ? fs.readFileSync(specPath, 'utf8') : '';
5178
5349
  const planMd = fs.existsSync(planPath) ? fs.readFileSync(planPath, 'utf8') : '';
@@ -5556,7 +5727,8 @@ async function main() {
5556
5727
  nextSteps: [
5557
5728
  { desc: 'Validar o projeto:', cmd: 'npx oxe-cc doctor' },
5558
5729
  { desc: 'Instalar integrações IDE/CLI (se ainda não fez):', cmd: 'npx oxe-cc@latest' },
5559
- { desc: 'Começar o fluxo no agente:', cmd: '/oxe-scan' },
5730
+ { desc: 'Fluxo runtime criar spec (no agente):', cmd: '/oxe-spec → /oxe-plan → oxe-cc runtime compile → oxe-cc runtime execute' },
5731
+ { desc: 'Começar pelo scan do codebase (agente):', cmd: '/oxe-scan' },
5560
5732
  ],
5561
5733
  dryRun: opts.dryRun,
5562
5734
  });
@@ -8,6 +8,7 @@ Este é o contrato mínimo para publicar uma versão estável do OXE sem drift e
8
8
  npm test
9
9
  npm run scan:assets
10
10
  npm run build:vscode-ext
11
+ npm run release:pack-check
11
12
  npx oxe-cc doctor --release --write-manifest
12
13
  ```
13
14
 
@@ -21,6 +22,7 @@ O `doctor --release` deve bloquear a publicação quando encontrar:
21
22
  - wrappers dirty após `sync-runtime-metadata` e `sync:cursor`
22
23
  - drift semântico entre workflows canónicos e superfícies geradas
23
24
  - ausência ou falha dos relatórios obrigatórios da release
25
+ - tarball npm contendo `.tgz`, `.vsix`, `.oxe/` ou sem arquivos obrigatórios do pacote
24
26
 
25
27
  ## Relatórios obrigatórios
26
28
 
@@ -28,8 +30,10 @@ Todos os artefatos abaixo devem existir em `.oxe/release/`:
28
30
 
29
31
  - `release-manifest.json`
30
32
  - `runtime-smoke-report.json`
33
+ - `runtime-real-report.json`
31
34
  - `recovery-fixture-report.json`
32
35
  - `multi-agent-soak-report.json`
36
+ - `multi-agent-real-report.json` para versões `>=1.9.1`
33
37
 
34
38
  ## Defaults estáveis desta publicação
35
39
 
@@ -44,7 +48,8 @@ O pipeline de CI e o pipeline de release devem rodar o mesmo gate:
44
48
 
45
49
  1. `npm test`
46
50
  2. `npm run scan:assets`
47
- 3. `npm run release:doctor`
51
+ 3. `npm run release:pack-check`
52
+ 4. `npm run release:doctor`
48
53
 
49
54
  Se qualquer etapa falhar, a release não está pronta.
50
55
 
@@ -26,7 +26,7 @@ function compile(plan, spec, options = {}) {
26
26
  mutation_scope: task.files,
27
27
  actions: buildActions(task),
28
28
  verify: {
29
- must_pass: task.verifyCommand ? ['tests'] : [],
29
+ must_pass: task.verifyCommand ? (task.aceite.length > 0 ? task.aceite : ['tests']) : [],
30
30
  acceptance_refs: task.aceite,
31
31
  command: task.verifyCommand,
32
32
  },
@@ -37,5 +37,9 @@ function selectToolsForActions(actions) {
37
37
  }
38
38
  }
39
39
  }
40
+ // finish_task is always available so the LLM can signal authoritative completion
41
+ if (!seen.has('finish_task') && built_in_tools_1.BUILT_IN_TOOLS.finish_task) {
42
+ result.push(built_in_tools_1.BUILT_IN_TOOLS.finish_task.schema);
43
+ }
40
44
  return result;
41
45
  }
@@ -255,6 +255,32 @@ function runShell(command, cwd, timeoutMs) {
255
255
  proc.on('error', (err) => { clearTimeout(timer); resolve(`[error] ${err}`); });
256
256
  });
257
257
  }
258
+ // ─── finish_task ──────────────────────────────────────────────────────────────
259
+ const finishTask = {
260
+ idempotent: true,
261
+ schema: {
262
+ type: 'function',
263
+ function: {
264
+ name: 'finish_task',
265
+ description: 'Signal that the task is complete. Call this when ALL required actions have been performed.',
266
+ parameters: {
267
+ type: 'object',
268
+ properties: {
269
+ summary: { type: 'string', description: 'Summary of what was accomplished' },
270
+ evidence_paths: { type: 'array', items: { type: 'string' }, description: 'Paths to files created or modified' },
271
+ },
272
+ required: ['summary'],
273
+ },
274
+ },
275
+ },
276
+ async execute(args, _cwd) {
277
+ return JSON.stringify({
278
+ __finish_task__: true,
279
+ summary: String(args.summary || ''),
280
+ evidence_paths: Array.isArray(args.evidence_paths) ? args.evidence_paths : [],
281
+ });
282
+ },
283
+ };
258
284
  // ─── Registry ─────────────────────────────────────────────────────────────────
259
285
  exports.BUILT_IN_TOOLS = {
260
286
  read_file: readFile,
@@ -263,5 +289,6 @@ exports.BUILT_IN_TOOLS = {
263
289
  glob,
264
290
  grep,
265
291
  run_command: runCommand,
292
+ finish_task: finishTask,
266
293
  };
267
294
  exports.ALL_BUILT_IN_SCHEMAS = Object.values(exports.BUILT_IN_TOOLS).map((t) => t.schema);
@@ -18,12 +18,15 @@ export interface LlmExecutorEvent {
18
18
  attempt: number;
19
19
  detail?: Record<string, unknown>;
20
20
  }
21
+ export interface LlmExecuteOptions {
22
+ previousError?: string | null;
23
+ }
21
24
  export declare class LlmTaskExecutor implements TaskExecutor {
22
25
  private readonly provider;
23
26
  private readonly registry?;
24
27
  private readonly onProgress?;
25
28
  constructor(provider: LlmProviderConfig, registry?: PluginRegistry | undefined, onProgress?: ((event: LlmExecutorEvent) => void) | undefined);
26
- execute(node: GraphNode, lease: WorkspaceLease, runId: string, attempt: number): Promise<TaskResult>;
29
+ execute(node: GraphNode, lease: WorkspaceLease, runId: string, attempt: number, options?: LlmExecuteOptions): Promise<TaskResult>;
27
30
  private invokeToolCall;
28
31
  private emit;
29
32
  }