oxe-cc 1.7.0 → 1.8.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/CHANGELOG.md CHANGED
@@ -4,6 +4,49 @@ Todas as versões seguem [Semantic Versioning](https://semver.org/). As mudança
4
4
 
5
5
  ---
6
6
 
7
+ ## [1.8.0] — 2026-04-29
8
+
9
+ ### Autonomous Execution — 5 Critical Gaps Resolved
10
+
11
+ Esta release eleva a autonomia do runtime de ~65% para ~85%+ em projetos de baixo a médio risco, tornando o OXE capaz de transformar um input bem estruturado em entrega verificada com mínima intervenção humana.
12
+
13
+ #### Gap 1 — GateManager Wiring
14
+ - `createExecutionContext()` exportada de `oxe-operational.cjs`: instancia `GateManager` real sempre que o runtime estiver disponível, eliminando o deadlock silencioso de `'gate-missing-manager'`
15
+ - `scheduler.js`: warning explícito quando `ctx.gateManager` ausente em vez de falha silenciosa
16
+ - Novo subcomando `oxe-cc runtime execute` com roteamento automático single-agent / multi-agent
17
+
18
+ #### Gap 2 — Verificação Inline após cada tarefa
19
+ - `Scheduler.verifyNode()`: executa o `verify.command` do nó logo após execução bem-sucedida, antes de emitir `WorkItemCompleted`
20
+ - Falha de verificação → tarefa reentrada no loop de retry com `failure_class: 'verify'`
21
+ - Falha de infraestrutura de verificação (comando inexistente, timeout) → não bloqueia progresso
22
+ - Eventos `VerificationStarted` / `VerificationCompleted` emitidos por tarefa (reducer já existia)
23
+
24
+ #### Gap 3 — Retry Inteligente com Contexto do Erro Anterior
25
+ - `node-prompt-builder.js`: seção "Contexto da tentativa anterior" injetada automaticamente nas tentativas 2+ com stderr/output truncado em 2000 chars
26
+ - `llm-task-executor.js`: aceita `options.previousError`; repassado para o prompt builder
27
+ - `scheduler.js`: `lastError` rastreado e propagado entre tentativas via `executeNode(options)`
28
+
29
+ #### Gap 4 — Sinal Autoritativo de Conclusão (`finish_task`)
30
+ - Nova tool built-in `finish_task` (idempotente) registrada em `BUILT_IN_TOOLS` e `ALL_BUILT_IN_SCHEMAS`
31
+ - `selectToolsForActions()`: `finish_task` injetada universalmente em todos os tipos de ação
32
+ - `node-prompt-builder.js`: instrução explícita de chamar `finish_task` ao concluir
33
+ - `llm-task-executor.js`: detecta chamada de `finish_task` → `completed_by: 'finish_task'`; turns esgotados sem `finish_task` → `success: false, failure_class: 'llm'`
34
+
35
+ #### Gap 5 — MultiAgentCoordinator Wiring
36
+ - `runRuntimeExecute()` exportada de `oxe-operational.cjs`: detecta `plan-agents.json` (sessão > raiz) e roteia para `MultiAgentCoordinator` (parallel/competitive/cooperative) ou `Scheduler` single-agent
37
+ - `oxe-cc runtime execute`: novo subcomando CLI com output formatado e exit code em falhas
38
+
39
+ #### Testes
40
+ - 5 novos arquivos de teste cobrindo cada gap: `gap1-gate-manager`, `gap2-inline-verify`, `gap3-retry-context`, `gap4-finish-task`, `gap5-multi-agent`
41
+ - Suite total: **543 testes passando**, 0 falhas
42
+
43
+ ### Validation
44
+
45
+ - `node --test tests/*.cjs tests/*.test.js`
46
+ - `node bin/oxe-cc.js --version`
47
+
48
+ ---
49
+
7
50
  ## [1.7.0] — 2026-04-23
8
51
 
9
52
  ### OXE-native Agent Catalog
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![npm](https://img.shields.io/npm/v/oxe-cc.svg?style=flat-square)](https://www.npmjs.com/package/oxe-cc)
8
8
  [![license](https://img.shields.io/npm/l/oxe-cc.svg?style=flat-square)](LICENSE)
9
9
 
10
- **Versão:** `1.7.0` · [package.json](package.json)
10
+ **Versão:** `1.8.0` · [package.json](package.json)
11
11
 
12
12
  **Framework OXE — Orchestrated eXperience Engineering**
13
13
 
@@ -52,7 +52,7 @@ O OXE agora distingue cinco famílias de raciocínio:
52
52
  - `review` — findings primeiro, severidade, evidência e risco residual
53
53
  - `status` — leitura curta do estado, recomendação única e motivo
54
54
 
55
- Essas regras vivem no núcleo canónico em `oxe/workflows/references/reasoning-*.md`, sobem para os workflows em `oxe/workflows/` e são renderizadas para cada runtime em `.github/prompts/`, `.cursor/commands/`, `commands/oxe/`, `.codex/prompts/` e skills multiagente. Agentes especializados vivem em `oxe/agents/` e são instalados como agentes/skills OXE-native quando o runtime suporta esse conceito. Nesta linha, `oxe/workflows/**`, `oxe/agents/**` e `workflow-runtime-contracts.json` são contratos obrigatórios da release; superfícies geradas permanecem derivadas e sincronizadas.
55
+ Essas regras vivem no núcleo canónico em `oxe/workflows/references/reasoning-*.md`, sobem para os workflows em `oxe/workflows/` e são renderizadas para cada runtime em `.github/prompts/`, `.cursor/commands/`, `commands/oxe/`, `.codex/prompts/` e skills multiagente. Agentes especializados vivem em `oxe/agents/` e são instalados como agentes/skills OXE-native quando o runtime suporta esse conceito. Nesta linha, `oxe/workflows/**`, `oxe/agents/**` e `workflow-runtime-contracts.json` são contratos obrigatórios da release; superfícies geradas permanecem derivadas e sincronizadas.
56
56
 
57
57
  ---
58
58
 
@@ -94,10 +94,10 @@ Contrato estável desta release:
94
94
  | Primeiros 15 minutos | [QUICKSTART.md](QUICKSTART.md) |
95
95
  | Guia por papel (executor / reviewer / operador) | [docs/ROLES.md](docs/ROLES.md) |
96
96
  | Fluxo recomendado para times | [docs/TEAM-ADOPTION.md](docs/TEAM-ADOPTION.md) |
97
- | Exemplo completo reproduzível | [docs/WALKTHROUGH.md](docs/WALKTHROUGH.md) |
98
- | Incidentes e gates | [docs/INCIDENT-PLAYBOOK.md](docs/INCIDENT-PLAYBOOK.md) |
99
- | Suporte por runtime (Cursor, Copilot, Claude Code…) | [docs/RUNTIME-SMOKE-MATRIX.md](docs/RUNTIME-SMOKE-MATRIX.md) |
100
- | Release readiness e publicação | [docs/RELEASE-READINESS.md](docs/RELEASE-READINESS.md) |
97
+ | Exemplo completo reproduzível | [docs/WALKTHROUGH.md](docs/WALKTHROUGH.md) |
98
+ | Incidentes e gates | [docs/INCIDENT-PLAYBOOK.md](docs/INCIDENT-PLAYBOOK.md) |
99
+ | Suporte por runtime (Cursor, Copilot, Claude Code…) | [docs/RUNTIME-SMOKE-MATRIX.md](docs/RUNTIME-SMOKE-MATRIX.md) |
100
+ | Release readiness e publicação | [docs/RELEASE-READINESS.md](docs/RELEASE-READINESS.md) |
101
101
 
102
102
  ---
103
103
 
@@ -459,18 +459,18 @@ O `status --full` mostra em ANSI: readiness do ciclo, autoavaliação do plano,
459
459
 
460
460
  O pacote está pronto para uma publicação robusta quando estes sinais estiverem verdes no repositório da release:
461
461
 
462
- - `npm test`
463
- - `npm run scan:assets`
464
- - `npm run build:vscode-ext`
465
- - `node bin/oxe-cc.js doctor --release --write-manifest`
466
- - `node bin/oxe-cc.js status --full`
467
-
468
- Artefatos obrigatórios desta fase:
469
-
470
- - `.oxe/release/release-manifest.json`
471
- - `.oxe/release/runtime-smoke-report.json`
472
- - `.oxe/release/recovery-fixture-report.json`
473
- - `.oxe/release/multi-agent-soak-report.json`
462
+ - `npm test`
463
+ - `npm run scan:assets`
464
+ - `npm run build:vscode-ext`
465
+ - `node bin/oxe-cc.js doctor --release --write-manifest`
466
+ - `node bin/oxe-cc.js status --full`
467
+
468
+ Artefatos obrigatórios desta fase:
469
+
470
+ - `.oxe/release/release-manifest.json`
471
+ - `.oxe/release/runtime-smoke-report.json`
472
+ - `.oxe/release/recovery-fixture-report.json`
473
+ - `.oxe/release/multi-agent-soak-report.json`
474
474
 
475
475
  Não há outro bloqueador funcional do plano runtime core para esta publicação. O que sobra depois dela é evolução de ergonomia e expansão de targets, não correção estrutural do contrato atual.
476
476
 
@@ -522,23 +522,23 @@ npx oxe-cc@latest
522
522
  | Flag | Efeito |
523
523
  |------|--------|
524
524
  | `--cursor` / `--copilot` | Só uma das stacks da IDE |
525
- | `--copilot-cli` | Skills globais do Copilot CLI em `~/.copilot/skills/` |
526
- | `--all-agents` | Cursor + Copilot + Claude + OpenCode + Gemini + Codex + Windsurf + Antigravity |
527
- | `--global` | Layout clássico: `oxe/` na raiz + `.oxe/` |
528
- | `--local` | Layout do repositório: mínimo, só `.oxe/` (padrão). Não controla onde a integração da IDE é instalada. |
529
- | `--ide-local` | Instala a integração no próprio repositório (`.cursor/`, `.github/`, `.claude/`, `.codex/` etc.) |
530
- | `--ide-global` | Instala a integração no HOME do utilizador quando o runtime suportar esse escopo |
531
- | `--force` / `-f` | Sobrescreve arquivos existentes (use para atualizar) |
532
- | `--dry-run` | Lista ações sem escrever |
533
- | `--oxe-only` | Só workflows em `.oxe/`, sem integrações IDE |
534
- | `--no-global-cli` / `-l` | Não instala `oxe-cc` globalmente (útil em CI) |
525
+ | `--copilot-cli` | Skills globais do Copilot CLI em `~/.copilot/skills/` |
526
+ | `--all-agents` | Cursor + Copilot + Claude + OpenCode + Gemini + Codex + Windsurf + Antigravity |
527
+ | `--global` | Layout clássico: `oxe/` na raiz + `.oxe/` |
528
+ | `--local` | Layout do repositório: mínimo, só `.oxe/` (padrão). Não controla onde a integração da IDE é instalada. |
529
+ | `--ide-local` | Instala a integração no próprio repositório (`.cursor/`, `.github/`, `.claude/`, `.codex/` etc.) |
530
+ | `--ide-global` | Instala a integração no HOME do utilizador quando o runtime suportar esse escopo |
531
+ | `--force` / `-f` | Sobrescreve arquivos existentes (use para atualizar) |
532
+ | `--dry-run` | Lista ações sem escrever |
533
+ | `--oxe-only` | Só workflows em `.oxe/`, sem integrações IDE |
534
+ | `--no-global-cli` / `-l` | Não instala `oxe-cc` globalmente (útil em CI) |
535
535
  | `OXE_NO_PROMPT=1` | Modo não-interativo (CI) |
536
536
 
537
537
  </details>
538
538
 
539
- GitHub Copilot no VS Code é **workspace-first**: o OXE instala prompt files em `.github/prompts/*.prompt.md` e mescla instruções em `.github/copilot-instructions.md`. `~/.copilot/` fica reservado ao legado detectável e ao runtime do Copilot CLI.
540
-
541
- Claude Code recebe comandos em `.claude/commands` e agentes especializados em `.claude/agents`. Codex recebe prompts em `.codex/prompts` e skills OXE em `.agents/skills`, incluindo os agentes especializados derivados de `oxe/agents/`.
539
+ GitHub Copilot no VS Code é **workspace-first**: o OXE instala prompt files em `.github/prompts/*.prompt.md` e mescla instruções em `.github/copilot-instructions.md`. `~/.copilot/` fica reservado ao legado detectável e ao runtime do Copilot CLI.
540
+
541
+ Claude Code recebe comandos em `.claude/commands` e agentes especializados em `.claude/agents`. Codex recebe prompts em `.codex/prompts` e skills OXE em `.agents/skills`, incluindo os agentes especializados derivados de `oxe/agents/`.
542
542
 
543
543
  <details>
544
544
  <summary><strong>Atualizar e desinstalar</strong></summary>
@@ -571,11 +571,11 @@ node bin/oxe-cc.js --help
571
571
  | Comando | O que faz |
572
572
  |---------|-----------|
573
573
  | `oxe-cc` / `oxe-cc install` | Instala workflows e integrações |
574
- | `oxe-cc doctor` | Diagnóstico completo: Node, workflows, config, bootstrap `.oxe/`, sessão ativa, autoavaliação do plano, saúde lógica (`healthy` \| `warning` \| `broken`), drift semântico multi-runtime e workflows sem contrato no registry |
575
- | `oxe-cc doctor --release --write-manifest` | Gate de publicação: valida árvore canónica `oxe/`, `workflow-runtime-contracts.json`, versões, topo do `CHANGELOG`, runtime compilado, wrapper sync e relatórios obrigatórios; persiste `release-manifest.json` |
576
- | `oxe-cc status` | Próximo passo sugerido + saúde lógica do fluxo |
577
- | `oxe-cc status --full` | Coverage matrix + readiness gate + active run no terminal (ANSI); em repositório do pacote, troca para release readiness em vez de plan readiness |
578
- | `oxe-cc status --json` | Mesmo, em JSON (schema v5), com `workspaceMode`, `releaseReadiness`, `healthStatus`, `activeSession`, `planSelfEvaluation`, `contextPacks`, `contextQuality`, `semanticsDrift`, `verificationSummary`, `residualRiskSummary`, `evidenceCoverage`, `pendingGates`, `policyDecisionSummary`, `quotaSummary`, `auditSummary`, `promotionSummary`, `runtimeMode`, `fallbackMode`, `gateQueue`, `policyCoverage`, `promotionReadiness`, `recoveryState`, `multiAgent` e `providerCatalog` |
574
+ | `oxe-cc doctor` | Diagnóstico completo: Node, workflows, config, bootstrap `.oxe/`, sessão ativa, autoavaliação do plano, saúde lógica (`healthy` \| `warning` \| `broken`), drift semântico multi-runtime e workflows sem contrato no registry |
575
+ | `oxe-cc doctor --release --write-manifest` | Gate de publicação: valida árvore canónica `oxe/`, `workflow-runtime-contracts.json`, versões, topo do `CHANGELOG`, runtime compilado, wrapper sync e relatórios obrigatórios; persiste `release-manifest.json` |
576
+ | `oxe-cc status` | Próximo passo sugerido + saúde lógica do fluxo |
577
+ | `oxe-cc status --full` | Coverage matrix + readiness gate + active run no terminal (ANSI); em repositório do pacote, troca para release readiness em vez de plan readiness |
578
+ | `oxe-cc status --json` | Mesmo, em JSON (schema v5), com `workspaceMode`, `releaseReadiness`, `healthStatus`, `activeSession`, `planSelfEvaluation`, `contextPacks`, `contextQuality`, `semanticsDrift`, `verificationSummary`, `residualRiskSummary`, `evidenceCoverage`, `pendingGates`, `policyDecisionSummary`, `quotaSummary`, `auditSummary`, `promotionSummary`, `runtimeMode`, `fallbackMode`, `gateQueue`, `policyCoverage`, `promotionReadiness`, `recoveryState`, `multiAgent` e `providerCatalog` |
579
579
  | `oxe-cc context build [--workflow <slug>] [--tier <minimal\|standard\|full>]` | Gera context pack(s) em `.oxe/context/packs/` — seleção determinística de artefatos por contrato de workflow |
580
580
  | `oxe-cc context inspect [--workflow <slug>]` | Inspeciona um context pack existente ou resolve sob demanda (sem escrita); útil para diagnóstico antes de iniciar um passo |
581
581
  | `oxe-cc update` | Atualiza workflows para a versão mais recente |
@@ -603,7 +603,7 @@ Arquivo `.oxe/config.json`. Principais opções:
603
603
  |-------|--------|-----------|
604
604
  | `profile` | `"balanced"` | `strict` / `balanced` / `fast` / `legacy` |
605
605
  | `verification_depth` | `"standard"` | `"thorough"` ativa gaps automático no verify (Camada 5) |
606
- | `plan_confidence_threshold` | `90` | Limiar canónico para `execute` aceitar um `PLAN.md`; a confiança precisa ser **maior que** esse valor |
606
+ | `plan_confidence_threshold` | `90` | Limiar canónico para `execute` aceitar um `PLAN.md`; a confiança precisa ser **maior que** esse valor |
607
607
  | `security_in_verify` | `false` | `true` ativa OWASP automático no verify (Camada 6) |
608
608
  | `discuss_before_plan` | `false` | Exige aprovação de decisões antes do plano |
609
609
  | `scale_adaptive` | `true` | Scan sugere o profile pelo tamanho do projeto |
@@ -95,14 +95,30 @@ function parseCursorCommandFrontmatter(text) {
95
95
  if (end === -1) {
96
96
  return { description: '', body: normalized.trim(), frontmatter: {} };
97
97
  }
98
- const yamlBlock = normalized.slice(4, end);
99
- const frontmatter = {};
100
- let description = '';
101
- for (const line of yamlBlock.split('\n')) {
102
- const m = line.match(/^description:\s*(.+)$/);
103
- if (m) {
104
- description = m[1].trim().replace(/^["']|["']$/g, '');
105
- }
98
+ const yamlBlock = normalized.slice(4, end);
99
+ const frontmatter = {};
100
+ let description = '';
101
+ const yamlLines = yamlBlock.split('\n');
102
+ for (let i = 0; i < yamlLines.length; i++) {
103
+ const line = yamlLines[i];
104
+ const foldedDescription = line.match(/^description:\s*[>|]\s*$/);
105
+ if (foldedDescription) {
106
+ const parts = [];
107
+ let j = i + 1;
108
+ while (j < yamlLines.length && /^\s+/.test(yamlLines[j])) {
109
+ const value = yamlLines[j].trim();
110
+ if (value) parts.push(value);
111
+ j += 1;
112
+ }
113
+ description = parts.join(' ').trim();
114
+ frontmatter.description = description;
115
+ i = j - 1;
116
+ continue;
117
+ }
118
+ const m = line.match(/^description:\s*(.+)$/);
119
+ if (m) {
120
+ description = m[1].trim().replace(/^["']|["']$/g, '');
121
+ }
106
122
  const kv = line.match(/^([A-Za-z0-9_-]+):\s*(.+)$/);
107
123
  if (kv) frontmatter[kv[1]] = kv[2].trim().replace(/^["']|["']$/g, '');
108
124
  }
@@ -79,6 +79,31 @@ function loadRuntimeModule() {
79
79
  }
80
80
  }
81
81
 
82
+ // Gap 1: factory that always wires GateManager into ctx
83
+ function createExecutionContext(projectRoot, activeSession, options = {}) {
84
+ const runtime = loadRuntimeModule();
85
+ const runId = options.runId || makeRunId();
86
+ const gateManager = (runtime && typeof runtime.GateManager === 'function')
87
+ ? new runtime.GateManager(projectRoot, activeSession || null, runId)
88
+ : null;
89
+ return {
90
+ projectRoot,
91
+ sessionId: activeSession || null,
92
+ runId,
93
+ executor: options.executor || null,
94
+ workspaceManager: options.workspaceManager || null,
95
+ gateManager,
96
+ policyEngine: options.policyEngine || null,
97
+ policyActor: options.policyActor || 'runtime',
98
+ quota: options.quota || null,
99
+ pluginRegistry: options.pluginRegistry || null,
100
+ auditTrail: options.auditTrail || null,
101
+ evidenceStore: options.evidenceStore || null,
102
+ onEvent: options.onEvent || null,
103
+ options: options.schedulerOptions || {},
104
+ };
105
+ }
106
+
82
107
  function buildRuntimePluginRegistry(projectRoot) {
83
108
  const runtime = loadRuntimeModule();
84
109
  if (!runtime || typeof runtime.PluginRegistry !== 'function') return null;
@@ -637,11 +662,91 @@ async function resolveRuntimeGate(projectRoot, activeSession, options = {}) {
637
662
  };
638
663
  }
639
664
 
640
- function readRuntimeMultiAgentStatus(projectRoot, activeSession, options = {}) {
641
- const runtime = loadRuntimeModule();
642
- const current = readRunState(projectRoot, activeSession);
643
- const runId = options.runId || (current && current.run_id) || null;
644
- if (!runId) {
665
+ // Gap 5: route execution to MultiAgentCoordinator when plan-agents.json exists
666
+ async function runRuntimeExecute(projectRoot, activeSession, options = {}) {
667
+ const runtime = loadRuntimeModule();
668
+ if (!runtime) throw new Error('Runtime package não está disponível. Rode npm run build:runtime.');
669
+ const parsers = loadSdkParsers();
670
+ if (!parsers) throw new Error('SDK parsers não disponíveis.');
671
+
672
+ // Resolve compiled graph from run state or compile on demand
673
+ let current = options.runState || readRunState(projectRoot, activeSession);
674
+ if (!current || !current.compiled_graph) {
675
+ current = compileExecutionGraphFromArtifacts(projectRoot, activeSession, { runState: current }).run;
676
+ }
677
+ if (!current || !current.compiled_graph) {
678
+ throw new Error('Nenhum grafo compilado encontrado. Execute oxe-cc runtime compile primeiro.');
679
+ }
680
+ const graph = runtime.fromSerializable
681
+ ? runtime.fromSerializable(current.compiled_graph)
682
+ : current.compiled_graph;
683
+
684
+ // Detect plan-agents.json (session path takes priority over root)
685
+ const rootAgentPlan = path.join(projectRoot, '.oxe', 'plan-agents.json');
686
+ const sessAgentPlan = activeSession
687
+ ? path.join(projectRoot, '.oxe', activeSession, 'plan', 'plan-agents.json')
688
+ : null;
689
+ const agentPlanPath = (sessAgentPlan && fs.existsSync(sessAgentPlan))
690
+ ? sessAgentPlan
691
+ : (fs.existsSync(rootAgentPlan) ? rootAgentPlan : null);
692
+
693
+ // Build ctx with GateManager (Gap 1)
694
+ const ctx = createExecutionContext(projectRoot, activeSession, {
695
+ runId: current.run_id,
696
+ executor: options.executor || null,
697
+ workspaceManager: options.workspaceManager || null,
698
+ pluginRegistry: options.pluginRegistry || buildRuntimePluginRegistry(projectRoot),
699
+ schedulerOptions: options.schedulerOptions || {},
700
+ onEvent: (event) => appendEvent(projectRoot, activeSession, event),
701
+ });
702
+
703
+ // Gap 5: multi-agent path if plan-agents.json exists
704
+ if (agentPlanPath) {
705
+ let agentPlan;
706
+ try {
707
+ agentPlan = JSON.parse(fs.readFileSync(agentPlanPath, 'utf8'));
708
+ } catch (err) {
709
+ throw new Error(`plan-agents.json inválido: ${err.message}`);
710
+ }
711
+ if (!Array.isArray(agentPlan.agents) || agentPlan.agents.length === 0) {
712
+ throw new Error('plan-agents.json não contém agentes válidos (campo "agents" vazio ou ausente).');
713
+ }
714
+ if (typeof runtime.MultiAgentCoordinator !== 'function') {
715
+ throw new Error('Runtime não exporta MultiAgentCoordinator. Verifique a versão do runtime.');
716
+ }
717
+ const agents = agentPlan.agents.map((spec) => ({
718
+ id: spec.id,
719
+ executor: options.executorFactory ? options.executorFactory(spec) : (options.executor || null),
720
+ workspaceManager: options.workspaceManager || null,
721
+ assignedTaskIds: Array.isArray(spec.tasks) ? spec.tasks : [],
722
+ }));
723
+ const coordinator = new runtime.MultiAgentCoordinator();
724
+ const result = await coordinator.run(graph, {
725
+ mode: agentPlan.mode || 'parallel',
726
+ agents,
727
+ projectRoot,
728
+ sessionId: activeSession || null,
729
+ runId: current.run_id,
730
+ heartbeatTimeoutMs: options.heartbeatTimeoutMs ?? 120000,
731
+ onEvent: ctx.onEvent,
732
+ });
733
+ return { mode: agentPlan.mode || 'parallel', agentPlan, result, run: current };
734
+ }
735
+
736
+ // Single-agent fallback
737
+ if (typeof runtime.Scheduler !== 'function') {
738
+ throw new Error('Runtime não exporta Scheduler. Verifique a versão do runtime.');
739
+ }
740
+ const scheduler = new runtime.Scheduler();
741
+ const result = await scheduler.run(graph, ctx);
742
+ return { mode: 'single', agentPlan: null, result, run: current };
743
+ }
744
+
745
+ function readRuntimeMultiAgentStatus(projectRoot, activeSession, options = {}) {
746
+ const runtime = loadRuntimeModule();
747
+ const current = readRunState(projectRoot, activeSession);
748
+ const runId = options.runId || (current && current.run_id) || null;
749
+ if (!runId) {
645
750
  return {
646
751
  path: null,
647
752
  enabled: false,
@@ -649,40 +754,40 @@ function readRuntimeMultiAgentStatus(projectRoot, activeSession, options = {}) {
649
754
  mode: null,
650
755
  workspaceIsolationEnforced: false,
651
756
  agents: [],
652
- ownership: [],
653
- orphanReassignments: [],
654
- handoffs: [],
655
- arbitrationResults: [],
656
- summary: null,
657
- };
658
- }
659
- const runDir = path.join(projectRoot, '.oxe', 'runs', runId);
660
- const statePath = path.join(runDir, 'multi-agent-state.json');
661
- const summaryPath = path.join(runDir, 'multi-agent-summary.json');
662
- const handoffsPath = path.join(runDir, 'handoffs.json');
663
- const arbitrationPath = path.join(runDir, 'arbitration-results.json');
664
- const state = runtime && typeof runtime.loadMultiAgentState === 'function'
665
- ? runtime.loadMultiAgentState(projectRoot, runId)
666
- : readJsonIfExists(statePath);
667
- const summary = runtime && typeof runtime.loadMultiAgentSummary === 'function'
668
- ? runtime.loadMultiAgentSummary(projectRoot, runId)
669
- : readJsonIfExists(summaryPath);
670
- const handoffs = readJsonIfExists(handoffsPath);
671
- const arbitrationResults = readJsonIfExists(arbitrationPath);
672
- return {
673
- path: statePath,
674
- enabled: Boolean(state),
757
+ ownership: [],
758
+ orphanReassignments: [],
759
+ handoffs: [],
760
+ arbitrationResults: [],
761
+ summary: null,
762
+ };
763
+ }
764
+ const runDir = path.join(projectRoot, '.oxe', 'runs', runId);
765
+ const statePath = path.join(runDir, 'multi-agent-state.json');
766
+ const summaryPath = path.join(runDir, 'multi-agent-summary.json');
767
+ const handoffsPath = path.join(runDir, 'handoffs.json');
768
+ const arbitrationPath = path.join(runDir, 'arbitration-results.json');
769
+ const state = runtime && typeof runtime.loadMultiAgentState === 'function'
770
+ ? runtime.loadMultiAgentState(projectRoot, runId)
771
+ : readJsonIfExists(statePath);
772
+ const summary = runtime && typeof runtime.loadMultiAgentSummary === 'function'
773
+ ? runtime.loadMultiAgentSummary(projectRoot, runId)
774
+ : readJsonIfExists(summaryPath);
775
+ const handoffs = readJsonIfExists(handoffsPath);
776
+ const arbitrationResults = readJsonIfExists(arbitrationPath);
777
+ return {
778
+ path: statePath,
779
+ enabled: Boolean(state),
675
780
  runId,
676
781
  mode: state && state.mode ? state.mode : null,
677
782
  workspaceIsolationEnforced: Boolean(state && state.workspace_isolation_enforced),
678
783
  agents: state && Array.isArray(state.agent_results) ? state.agent_results : [],
679
784
  ownership: state && Array.isArray(state.ownership) ? state.ownership : [],
680
- orphanReassignments: state && Array.isArray(state.orphan_reassignments) ? state.orphan_reassignments : [],
681
- handoffs: Array.isArray(handoffs) ? handoffs : [],
682
- arbitrationResults: Array.isArray(arbitrationResults) ? arbitrationResults : [],
683
- summary: summary || null,
684
- };
685
- }
785
+ orphanReassignments: state && Array.isArray(state.orphan_reassignments) ? state.orphan_reassignments : [],
786
+ handoffs: Array.isArray(handoffs) ? handoffs : [],
787
+ arbitrationResults: Array.isArray(arbitrationResults) ? arbitrationResults : [],
788
+ summary: summary || null,
789
+ };
790
+ }
686
791
 
687
792
  function loadRuntimeVerificationArtifacts(projectRoot, runState) {
688
793
  const runtime = loadRuntimeModule();
@@ -2138,6 +2243,8 @@ module.exports = {
2138
2243
  buildRecoveryConsistency,
2139
2244
  readRuntimeGates,
2140
2245
  resolveRuntimeGate,
2246
+ createExecutionContext,
2247
+ runRuntimeExecute,
2141
2248
  runRuntimeVerify,
2142
2249
  projectRuntimeArtifacts,
2143
2250
  runRuntimeCiChecks,