oxe-cc 1.4.1 → 1.5.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 (63) hide show
  1. package/.cursor/commands/oxe-dashboard.md +2 -2
  2. package/.cursor/commands/oxe-execute.md +2 -2
  3. package/.cursor/commands/oxe-plan.md +2 -2
  4. package/.cursor/commands/oxe-verify-audit.md +46 -0
  5. package/.cursor/commands/oxe-workflow-authoring.md +47 -0
  6. package/.github/prompts/oxe-compact.prompt.md +1 -1
  7. package/.github/prompts/oxe-dashboard.prompt.md +2 -2
  8. package/.github/prompts/oxe-execute.prompt.md +2 -2
  9. package/.github/prompts/oxe-plan-agent.prompt.md +1 -0
  10. package/.github/prompts/oxe-plan.prompt.md +2 -2
  11. package/.github/prompts/oxe-verify-audit.prompt.md +46 -0
  12. package/.github/prompts/oxe-workflow-authoring.prompt.md +47 -0
  13. package/.github/workflows/ci.yml +1 -0
  14. package/.github/workflows/release.yml +1 -0
  15. package/AGENTS.md +3 -1
  16. package/CHANGELOG.md +50 -0
  17. package/QUICKSTART.md +99 -0
  18. package/README.md +20 -11
  19. package/bin/lib/oxe-context-engine.cjs +9 -4
  20. package/bin/lib/oxe-dashboard.cjs +119 -53
  21. package/bin/lib/oxe-install-resolve.cjs +10 -0
  22. package/bin/lib/oxe-operational.cjs +34 -28
  23. package/bin/lib/oxe-project-health.cjs +407 -118
  24. package/bin/lib/oxe-rationality.cjs +385 -0
  25. package/bin/lib/oxe-release.cjs +423 -0
  26. package/bin/oxe-cc.js +446 -325
  27. package/commands/oxe/dashboard.md +2 -2
  28. package/commands/oxe/execute.md +2 -2
  29. package/commands/oxe/plan.md +2 -2
  30. package/commands/oxe/verify-audit.md +50 -0
  31. package/commands/oxe/workflow-authoring.md +50 -0
  32. package/docs/INCIDENT-PLAYBOOK.md +181 -0
  33. package/docs/RELEASE-READINESS.md +46 -0
  34. package/docs/ROLES.md +129 -0
  35. package/docs/RUNTIME-SMOKE-MATRIX.md +128 -0
  36. package/docs/TEAM-ADOPTION.md +153 -0
  37. package/docs/WALKTHROUGH.md +241 -0
  38. package/lib/runtime/scheduler/multi-agent-coordinator.d.ts +28 -0
  39. package/lib/runtime/scheduler/multi-agent-coordinator.js +152 -26
  40. package/lib/sdk/README.md +2 -0
  41. package/lib/sdk/index.cjs +32 -14
  42. package/lib/sdk/index.d.ts +138 -40
  43. package/oxe/templates/CONFIG.md +1 -1
  44. package/oxe/templates/EXECUTION-RUNTIME.template.md +1 -1
  45. package/oxe/templates/FIXTURE-PACK.template.json +34 -0
  46. package/oxe/templates/FIXTURE-PACK.template.md +21 -0
  47. package/oxe/templates/IMPLEMENTATION-PACK.template.json +52 -0
  48. package/oxe/templates/IMPLEMENTATION-PACK.template.md +36 -0
  49. package/oxe/templates/PLAN.template.md +46 -37
  50. package/oxe/templates/REFERENCE-ANCHORS.template.md +24 -0
  51. package/oxe/templates/config.template.json +2 -1
  52. package/oxe/workflows/execute.md +36 -20
  53. package/oxe/workflows/next.md +1 -1
  54. package/oxe/workflows/plan.md +80 -22
  55. package/oxe/workflows/references/flow-robustness-contract.md +3 -3
  56. package/oxe/workflows/references/workflow-runtime-contracts.json +127 -95
  57. package/oxe/workflows/verify.md +4 -4
  58. package/package.json +28 -20
  59. package/packages/runtime/package.json +1 -1
  60. package/packages/runtime/src/scheduler/multi-agent-coordinator.ts +357 -193
  61. package/vscode-extension/oxe-agents-1.5.0.vsix +0 -0
  62. package/vscode-extension/oxe-agents-1.5.1.vsix +0 -0
  63. package/vscode-extension/package.json +1 -1
@@ -152,35 +152,55 @@ function parseVerify(md) {
152
152
  return { criteria, mentionedCriteria: Array.from(new Set((md.match(/\bA\d+\b/g) || []).map((x) => x.toUpperCase()))), failed: /\b(verify_failed|falhou|falha|reprovad)\b/i.test(md), passed: /\b(verify_complete|aprovad|passou|sucesso)\b/i.test(md) };
153
153
  }
154
154
 
155
- function confidenceBand(confidence, threshold) {
156
- if (confidence == null) return 'unknown';
157
- if (confidence >= 85) return 'ready';
158
- if (confidence >= threshold) return 'controlled';
159
- if (confidence >= 50) return 'needs_refinement';
160
- return 'do_not_execute';
161
- }
162
-
163
- function computeReadiness(ctx, threshold) {
164
- const blockers = [];
165
- const warnings = [...ctx.diagnostics.reviewWarnings, ...ctx.diagnostics.runtimeWarnings, ...ctx.diagnostics.planWarnings];
166
- if (ctx.planReviewStatus !== 'approved') blockers.push(`review_status:${ctx.planReviewStatus || 'draft'}`);
167
- if (ctx.plan.selfEvaluation.bestPlan === 'não') blockers.push('best_plan:no');
168
- if (ctx.plan.selfEvaluation.confidence == null) blockers.push('confidence:missing');
169
- else if (ctx.plan.selfEvaluation.confidence < threshold) blockers.push(`confidence:${ctx.plan.selfEvaluation.confidence}%<${threshold}%`);
170
- if (ctx.checkpoints.parsed.some((x) => /pending_approval/i.test(x.status))) blockers.push('checkpoint:pending_approval');
171
- if (ctx.runtime.parsed.status === 'blocked') blockers.push('runtime:blocked');
172
- if (ctx.spec.uncoveredCriteria.length) warnings.push(`${ctx.spec.uncoveredCriteria.length} critérios sem cobertura no plano`);
173
- return {
174
- go: blockers.length === 0,
175
- decision: blockers.length === 0 ? 'go' : 'no-go',
176
- threshold,
177
- confidence: ctx.plan.selfEvaluation.confidence,
178
- confidenceBand: confidenceBand(ctx.plan.selfEvaluation.confidence, threshold),
179
- checkpointPending: blockers.includes('checkpoint:pending_approval'),
180
- blockers,
181
- warnings,
182
- };
183
- }
155
+ function confidenceBand(confidence, threshold) {
156
+ const normalizedThreshold = health.normalizePlanConfidenceThreshold(threshold);
157
+ if (confidence == null) return 'unknown';
158
+ if (health.isExecutablePlanConfidence(confidence, normalizedThreshold)) return 'ready';
159
+ if (confidence >= Math.max(80, normalizedThreshold - 10)) return 'rational_but_not_ready';
160
+ if (confidence >= 50) return 'needs_refinement';
161
+ return 'do_not_execute';
162
+ }
163
+
164
+ function computeReadiness(ctx, threshold) {
165
+ const normalizedThreshold = health.normalizePlanConfidenceThreshold(threshold);
166
+ const blockers = [];
167
+ const warnings = [...ctx.diagnostics.reviewWarnings, ...ctx.diagnostics.runtimeWarnings, ...ctx.diagnostics.planWarnings];
168
+ if (!ctx.plan.selfEvaluation || !ctx.plan.selfEvaluation.hasSection) blockers.push('self_evaluation:missing');
169
+ if (ctx.plan.selfEvaluation && Array.isArray(ctx.plan.selfEvaluation.warnings) && ctx.plan.selfEvaluation.warnings.length) {
170
+ blockers.push(`self_evaluation:warnings:${ctx.plan.selfEvaluation.warnings.length}`);
171
+ }
172
+ if (ctx.planReviewStatus !== 'approved') blockers.push(`review_status:${ctx.planReviewStatus || 'draft'}`);
173
+ if (ctx.plan.selfEvaluation.bestPlan === 'não') blockers.push('best_plan:no');
174
+ if (ctx.plan.selfEvaluation.confidence == null) blockers.push('confidence:missing');
175
+ else if (!health.isExecutablePlanConfidence(ctx.plan.selfEvaluation.confidence, normalizedThreshold)) {
176
+ blockers.push(`confidence:${ctx.plan.selfEvaluation.confidence}%<=${normalizedThreshold}%`);
177
+ }
178
+ if (!ctx.executionRationality || !ctx.executionRationality.implementationPackReady) {
179
+ blockers.push('implementation_pack:not_ready');
180
+ }
181
+ if (!ctx.executionRationality || !ctx.executionRationality.referenceAnchorsReady) {
182
+ blockers.push('reference_anchors:not_ready');
183
+ }
184
+ if (!ctx.executionRationality || !ctx.executionRationality.fixturePackReady) {
185
+ blockers.push('fixture_pack:not_ready');
186
+ }
187
+ if (ctx.checkpoints.parsed.some((x) => /pending_approval/i.test(x.status))) blockers.push('checkpoint:pending_approval');
188
+ if (ctx.runtime.parsed.status === 'blocked') blockers.push('runtime:blocked');
189
+ if (ctx.spec.uncoveredCriteria.length) warnings.push(`${ctx.spec.uncoveredCriteria.length} critérios sem cobertura no plano`);
190
+ if (ctx.executionRationality && Array.isArray(ctx.executionRationality.criticalExecutionGaps)) {
191
+ warnings.push(...ctx.executionRationality.criticalExecutionGaps);
192
+ }
193
+ return {
194
+ go: blockers.length === 0,
195
+ decision: blockers.length === 0 ? 'go' : 'no-go',
196
+ threshold: normalizedThreshold,
197
+ confidence: ctx.plan.selfEvaluation.confidence,
198
+ confidenceBand: confidenceBand(ctx.plan.selfEvaluation.confidence, normalizedThreshold),
199
+ checkpointPending: blockers.includes('checkpoint:pending_approval'),
200
+ blockers,
201
+ warnings,
202
+ };
203
+ }
184
204
 
185
205
  function buildCoverageMatrix(spec, plan, verify) {
186
206
  const taskMap = new Map();
@@ -202,18 +222,27 @@ function buildCoverageMatrix(spec, plan, verify) {
202
222
  }));
203
223
  }
204
224
 
205
- function computeCalibration(phase, confidence, verify) {
206
- if (confidence == null) return { status: 'pending', summary: 'Calibração indisponível antes do verify.' };
207
- const low = String(phase || '').toLowerCase();
208
- const completed = low === 'verify_complete' || verify.passed;
209
- const failed = low === 'verify_failed' || verify.failed;
210
- if (!completed && !failed) return { status: 'pending', summary: 'Calibração só fecha após verify.' };
211
- if (confidence >= 85 && failed) return { status: 'overconfident', summary: `Confiança ${confidence}% alta, mas o verify falhou.` };
212
- if (confidence < 70 && failed) return { status: 'calibrated-risk', summary: `O plano já sinalizava risco (${confidence}%) e o verify confirmou a fragilidade.` };
213
- if (confidence < 70 && completed) return { status: 'underconfident', summary: `O resultado final foi melhor que a confiança inicial (${confidence}%).` };
214
- if (confidence >= 85 && completed) return { status: 'well-calibrated', summary: `Alta confiança (${confidence}%) e verify coerente com a expectativa.` };
215
- return { status: 'acceptable', summary: `Confiança ${confidence}% e verify dentro da faixa esperada.` };
216
- }
225
+ function computeCalibration(phase, confidence, verify, threshold) {
226
+ const normalizedThreshold = health.normalizePlanConfidenceThreshold(threshold);
227
+ if (confidence == null) return { status: 'pending', summary: 'Calibração indisponível antes do verify.' };
228
+ const low = String(phase || '').toLowerCase();
229
+ const completed = low === 'verify_complete' || verify.passed;
230
+ const failed = low === 'verify_failed' || verify.failed;
231
+ if (!completed && !failed) return { status: 'pending', summary: 'Calibração fecha após verify.' };
232
+ if (health.isExecutablePlanConfidence(confidence, normalizedThreshold) && failed) {
233
+ return { status: 'overconfident', summary: `Confiança ${confidence}% acima do gate executável, mas o verify falhou.` };
234
+ }
235
+ if (!health.isExecutablePlanConfidence(confidence, normalizedThreshold) && failed) {
236
+ return { status: 'calibrated-risk', summary: `O plano já sinalizava risco (${confidence}%) abaixo do gate executável e o verify confirmou a fragilidade.` };
237
+ }
238
+ if (!health.isExecutablePlanConfidence(confidence, normalizedThreshold) && completed) {
239
+ return { status: 'underconfident', summary: `O resultado final foi melhor que a confiança inicial (${confidence}%), mas o plano ainda não superava o gate executável.` };
240
+ }
241
+ if (health.isExecutablePlanConfidence(confidence, normalizedThreshold) && completed) {
242
+ return { status: 'well-calibrated', summary: `Alta confiança executável (${confidence}%) e verify coerente com a expectativa.` };
243
+ }
244
+ return { status: 'acceptable', summary: `Confiança ${confidence}% e verify dentro da faixa esperada.` };
245
+ }
217
246
 
218
247
  function readRepositoryContext(codebaseDir) {
219
248
  const names = ['OVERVIEW.md', 'STACK.md', 'STRUCTURE.md', 'TESTING.md', 'CONCERNS.md', 'INTEGRATIONS.md'];
@@ -353,8 +382,9 @@ function loadDashboardContext(projectRoot, opts = {}) {
353
382
  planReviewStatus: report.planReviewStatus || 'draft',
354
383
  state: { path: globalPaths.state, raw: stateText, parsed: { phase: health.parseStatePhase(stateText), activeSession, runtimeStatus: firstMatch(stateText, /\*\*runtime_status:\*\*\s*([^\n]+)/i) } },
355
384
  spec: { path: p.spec, raw: specText, objective: spec.objective, criteria: spec.criteria, uncoveredCriteria: spec.criteria.filter((c) => !plan.tasks.some((t) => (t.aceite || []).includes(c.id))) },
356
- plan: { path: p.plan, raw: planText, tasks: plan.tasks, waves: plan.waves, totalTasks: plan.totalTasks, selfEvaluation: report.planSelfEvaluation },
357
- runtime: { path: p.runtime, raw: runtimeText, summary: summarizeText(runtimeText, 800), parsed: runtime },
385
+ plan: { path: p.plan, raw: planText, tasks: plan.tasks, waves: plan.waves, totalTasks: plan.totalTasks, selfEvaluation: report.planSelfEvaluation },
386
+ executionRationality: report.executionRationality || null,
387
+ runtime: { path: p.runtime, raw: runtimeText, summary: summarizeText(runtimeText, 800), parsed: runtime },
358
388
  activeRun: activeRunState,
359
389
  runtimeCanonical: activeRunState && activeRunState.canonical_state ? activeRunState.canonical_state : null,
360
390
  compiledGraph: activeRunState && activeRunState.compiled_graph ? activeRunState.compiled_graph : null,
@@ -374,9 +404,14 @@ function loadDashboardContext(projectRoot, opts = {}) {
374
404
  promotionReadiness: report.promotionReadiness || null,
375
405
  recoveryState: report.recoveryState || null,
376
406
  multiAgent: report.multiAgent || null,
377
- providerCatalog: report.providerCatalog || null,
378
- warnings: report.enterpriseWarn || [],
379
- },
407
+ providerCatalog: report.providerCatalog || null,
408
+ implementationPackReady: report.implementationPackReady,
409
+ referenceAnchorsReady: report.referenceAnchorsReady,
410
+ fixturePackReady: report.fixturePackReady,
411
+ executionRationalityReady: report.executionRationalityReady,
412
+ criticalExecutionGaps: report.criticalExecutionGaps || [],
413
+ warnings: report.enterpriseWarn || [],
414
+ },
380
415
  tracing: { path: operational.operationalPaths(projectRoot, activeSession || null).events, events: traceEvents, summary: traceSummary },
381
416
  checkpoints: { path: p.checkpoints, raw: checkpointsText, parsed: checkpoints },
382
417
  verify: { path: p.verify, raw: verifyText, summary: summarizeText(verifyText, 800), parsed: verify },
@@ -422,13 +457,44 @@ function loadDashboardContext(projectRoot, opts = {}) {
422
457
  summary: `login=${ctx.azure.authStatus && ctx.azure.authStatus.login_active ? 'ativo' : 'ausente'} · subscription=${ctx.azure.profile && (ctx.azure.profile.subscription_name || ctx.azure.profile.subscription_id) || '—'} · total=${inventorySummary.total} · sb=${inventorySummary.servicebus || 0} · eg=${inventorySummary.eventgrid || 0} · sql=${inventorySummary.sql || 0}`,
423
458
  };
424
459
  }
425
- ctx.readiness = computeReadiness(ctx, 70);
426
- ctx.coverage = buildCoverageMatrix(ctx.spec, ctx.plan, verify);
427
- ctx.calibration = computeCalibration(ctx.phase, ctx.plan.selfEvaluation.confidence, verify);
428
- ctx.visual = {
429
- flow: { nodes: [{ label: 'STATE', status: 'done' }, { label: 'SPEC', status: ctx.spec.raw ? 'done' : 'pending' }, { label: 'PLAN', status: ctx.plan.raw ? 'done' : 'pending' }, { label: 'REVIEW', status: ctx.planReviewStatus === 'approved' ? 'done' : /(rejected|needs_revision)/i.test(ctx.planReviewStatus) ? 'blocked' : 'active' }, { label: 'EXECUTE', status: ctx.runtime.parsed.status === 'running' ? 'active' : ctx.runtime.raw ? 'done' : 'pending' }, { label: 'CHECKPOINTS', status: ctx.readiness.checkpointPending ? 'active' : ctx.checkpoints.parsed.length ? 'done' : 'pending' }, { label: 'VERIFY', status: ctx.verify.raw ? 'done' : 'pending' }, { label: 'LESSONS', status: 'pending' }] },
430
- artifactGraph: [{ id: 'state', label: 'STATE', path: ctx.state.path, detail: ctx.phase || 'índice global', status: 'done' }, { id: 'spec', label: 'SPEC', path: ctx.spec.path, detail: ctx.spec.objective || 'contrato', status: ctx.spec.raw ? 'done' : 'pending' }, { id: 'plan', label: 'PLAN', path: ctx.plan.path, detail: `${ctx.plan.totalTasks} tarefas`, status: ctx.plan.raw ? 'done' : 'pending' }, { id: 'review', label: 'PLAN REVIEW', path: ctx.review.markdownPath, detail: ctx.planReviewStatus, status: ctx.planReviewStatus === 'approved' ? 'done' : 'active' }, { id: 'runtime', label: 'RUNTIME', path: ctx.runtime.path, detail: ctx.runtime.parsed.status || 'sem status', status: ctx.runtime.raw ? 'active' : 'pending' }, { id: 'active-run', label: 'ACTIVE RUN', path: operational.operationalPaths(projectRoot, activeSession || null).activeRun, detail: ctx.activeRun && ctx.activeRun.run_id ? `${ctx.activeRun.run_id} · ${ctx.activeRun.status}` : 'sem run ativo', status: ctx.activeRun ? 'active' : 'pending' }, { id: 'events', label: 'TRACE', path: operational.operationalPaths(projectRoot, activeSession || null).events, detail: `${ctx.tracing.summary.total} evento(s)`, status: ctx.tracing.summary.total ? 'done' : 'pending' }, { id: 'checkpoints', label: 'CHECKPOINTS', path: ctx.checkpoints.path, detail: `${ctx.checkpoints.parsed.length} gates`, status: ctx.readiness.checkpointPending ? 'active' : 'pending' }, { id: 'verify', label: 'VERIFY', path: ctx.verify.path, detail: ctx.calibration.status, status: ctx.verify.raw ? 'done' : 'pending' }],
431
- };
460
+ ctx.readiness = computeReadiness(ctx, report.planConfidenceThreshold || 90);
461
+ ctx.coverage = buildCoverageMatrix(ctx.spec, ctx.plan, verify);
462
+ ctx.calibration = computeCalibration(ctx.phase, ctx.plan.selfEvaluation.confidence, verify, ctx.readiness.threshold);
463
+ ctx.visual = {
464
+ flow: { nodes: [{ label: 'STATE', status: 'done' }, { label: 'SPEC', status: ctx.spec.raw ? 'done' : 'pending' }, { label: 'PLAN', status: ctx.plan.raw ? 'done' : 'pending' }, { label: 'REVIEW', status: ctx.planReviewStatus === 'approved' ? 'done' : /(rejected|needs_revision)/i.test(ctx.planReviewStatus) ? 'blocked' : 'active' }, { label: 'EXECUTE', status: ctx.runtime.parsed.status === 'running' ? 'active' : ctx.runtime.raw ? 'done' : 'pending' }, { label: 'CHECKPOINTS', status: ctx.readiness.checkpointPending ? 'active' : ctx.checkpoints.parsed.length ? 'done' : 'pending' }, { label: 'VERIFY', status: ctx.verify.raw ? 'done' : 'pending' }, { label: 'LESSONS', status: 'pending' }] },
465
+ artifactGraph: [
466
+ { id: 'state', label: 'STATE', path: ctx.state.path, detail: ctx.phase || 'índice global', status: 'done' },
467
+ { id: 'spec', label: 'SPEC', path: ctx.spec.path, detail: ctx.spec.objective || 'contrato', status: ctx.spec.raw ? 'done' : 'pending' },
468
+ { id: 'plan', label: 'PLAN', path: ctx.plan.path, detail: `${ctx.plan.totalTasks} tarefas`, status: ctx.plan.raw ? 'done' : 'pending' },
469
+ {
470
+ id: 'implementation-pack',
471
+ label: 'IMPLEMENTATION PACK',
472
+ path: ctx.executionRationality && ctx.executionRationality.implementationPack ? ctx.executionRationality.implementationPack.path : '—',
473
+ detail: ctx.executionRationality && ctx.executionRationality.implementationPack ? `${ctx.executionRationality.implementationPack.taskCount || 0} contratos` : 'sem contrato',
474
+ status: ctx.executionRationality && ctx.executionRationality.implementationPackReady ? 'done' : 'blocked',
475
+ },
476
+ {
477
+ id: 'reference-anchors',
478
+ label: 'REFERENCE ANCHORS',
479
+ path: ctx.executionRationality && ctx.executionRationality.referenceAnchors ? ctx.executionRationality.referenceAnchors.path : '—',
480
+ detail: ctx.executionRationality && ctx.executionRationality.referenceAnchors ? `${ctx.executionRationality.referenceAnchors.anchors ? ctx.executionRationality.referenceAnchors.anchors.length : 0} âncoras` : 'sem âncoras',
481
+ status: ctx.executionRationality && ctx.executionRationality.referenceAnchorsReady ? 'done' : 'blocked',
482
+ },
483
+ {
484
+ id: 'fixture-pack',
485
+ label: 'FIXTURE PACK',
486
+ path: ctx.executionRationality && ctx.executionRationality.fixturePack ? ctx.executionRationality.fixturePack.path : '—',
487
+ detail: ctx.executionRationality && ctx.executionRationality.fixturePack ? `${ctx.executionRationality.fixturePack.fixtureCount || 0} fixtures` : 'sem fixtures',
488
+ status: ctx.executionRationality && ctx.executionRationality.fixturePackReady ? 'done' : 'blocked',
489
+ },
490
+ { id: 'review', label: 'PLAN REVIEW', path: ctx.review.markdownPath, detail: ctx.planReviewStatus, status: ctx.planReviewStatus === 'approved' ? 'done' : 'active' },
491
+ { id: 'runtime', label: 'RUNTIME', path: ctx.runtime.path, detail: ctx.runtime.parsed.status || 'sem status', status: ctx.runtime.raw ? 'active' : 'pending' },
492
+ { id: 'active-run', label: 'ACTIVE RUN', path: operational.operationalPaths(projectRoot, activeSession || null).activeRun, detail: ctx.activeRun && ctx.activeRun.run_id ? `${ctx.activeRun.run_id} · ${ctx.activeRun.status}` : 'sem run ativo', status: ctx.activeRun ? 'active' : 'pending' },
493
+ { id: 'events', label: 'TRACE', path: operational.operationalPaths(projectRoot, activeSession || null).events, detail: `${ctx.tracing.summary.total} evento(s)`, status: ctx.tracing.summary.total ? 'done' : 'pending' },
494
+ { id: 'checkpoints', label: 'CHECKPOINTS', path: ctx.checkpoints.path, detail: `${ctx.checkpoints.parsed.length} gates`, status: ctx.readiness.checkpointPending ? 'active' : 'pending' },
495
+ { id: 'verify', label: 'VERIFY', path: ctx.verify.path, detail: ctx.calibration.status, status: ctx.verify.raw ? 'done' : 'pending' },
496
+ ],
497
+ };
432
498
  if (ctx.azure) {
433
499
  ctx.visual.artifactGraph.push(
434
500
  {
@@ -36,6 +36,16 @@ function resolveInstallOptionsFromConfig(projectRoot, optsIn) {
36
36
  opts.explicitScope = true;
37
37
  }
38
38
 
39
+ if (!opts.explicitIdeScope && !opts.oxeOnly && typeof inst.ide_scope === 'string') {
40
+ if (inst.ide_scope === 'local') {
41
+ opts.ideLocal = true;
42
+ opts.explicitIdeScope = true;
43
+ } else if (inst.ide_scope === 'global') {
44
+ opts.ideLocal = false;
45
+ opts.explicitIdeScope = true;
46
+ }
47
+ }
48
+
39
49
  if (!opts.oxeOnly && inst.vscode === true) {
40
50
  opts.vscode = true;
41
51
  }
@@ -637,11 +637,11 @@ async function resolveRuntimeGate(projectRoot, activeSession, options = {}) {
637
637
  };
638
638
  }
639
639
 
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) {
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) {
645
645
  return {
646
646
  path: null,
647
647
  enabled: false,
@@ -649,34 +649,40 @@ function readRuntimeMultiAgentStatus(projectRoot, activeSession, options = {}) {
649
649
  mode: null,
650
650
  workspaceIsolationEnforced: false,
651
651
  agents: [],
652
- ownership: [],
653
- orphanReassignments: [],
654
- handoffs: [],
655
- arbitrationResults: [],
656
- };
657
- }
658
- const runDir = path.join(projectRoot, '.oxe', 'runs', runId);
659
- const statePath = path.join(runDir, 'multi-agent-state.json');
660
- const handoffsPath = path.join(runDir, 'handoffs.json');
661
- const arbitrationPath = path.join(runDir, 'arbitration-results.json');
662
- const state = runtime && typeof runtime.loadMultiAgentState === 'function'
663
- ? runtime.loadMultiAgentState(projectRoot, runId)
664
- : readJsonIfExists(statePath);
665
- const handoffs = readJsonIfExists(handoffsPath);
666
- const arbitrationResults = readJsonIfExists(arbitrationPath);
667
- return {
668
- path: statePath,
669
- enabled: Boolean(state),
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),
670
675
  runId,
671
676
  mode: state && state.mode ? state.mode : null,
672
677
  workspaceIsolationEnforced: Boolean(state && state.workspace_isolation_enforced),
673
678
  agents: state && Array.isArray(state.agent_results) ? state.agent_results : [],
674
679
  ownership: state && Array.isArray(state.ownership) ? state.ownership : [],
675
- orphanReassignments: state && Array.isArray(state.orphan_reassignments) ? state.orphan_reassignments : [],
676
- handoffs: Array.isArray(handoffs) ? handoffs : [],
677
- arbitrationResults: Array.isArray(arbitrationResults) ? arbitrationResults : [],
678
- };
679
- }
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
+ }
680
686
 
681
687
  function loadRuntimeVerificationArtifacts(projectRoot, runState) {
682
688
  const runtime = loadRuntimeModule();