oxe-cc 1.7.0 → 1.8.3

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 (44) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +37 -37
  3. package/bin/lib/oxe-agent-install.cjs +24 -8
  4. package/bin/lib/oxe-manifest.cjs +20 -13
  5. package/bin/lib/oxe-operational.cjs +234 -41
  6. package/bin/lib/oxe-project-health.cjs +219 -52
  7. package/bin/lib/oxe-rationality.cjs +9 -7
  8. package/bin/oxe-cc.js +443 -236
  9. package/lib/runtime/compiler/graph-compiler.js +1 -1
  10. package/lib/runtime/executor/action-tool-map.js +4 -0
  11. package/lib/runtime/executor/built-in-tools.js +27 -0
  12. package/lib/runtime/executor/llm-task-executor.d.ts +4 -1
  13. package/lib/runtime/executor/llm-task-executor.js +41 -5
  14. package/lib/runtime/executor/node-prompt-builder.d.ts +4 -1
  15. package/lib/runtime/executor/node-prompt-builder.js +13 -2
  16. package/lib/runtime/models/failure.d.ts +1 -1
  17. package/lib/runtime/scheduler/scheduler.d.ts +5 -1
  18. package/lib/runtime/scheduler/scheduler.js +82 -14
  19. package/lib/runtime/verification/verification-compiler.js +7 -5
  20. package/lib/sdk/index.cjs +48 -44
  21. package/oxe/templates/PLAN.template.md +23 -9
  22. package/oxe/templates/SPEC.template.md +55 -22
  23. package/oxe/workflows/plan.md +18 -6
  24. package/oxe/workflows/spec.md +31 -9
  25. package/package.json +103 -100
  26. package/packages/runtime/package.json +14 -14
  27. package/packages/runtime/src/compiler/graph-compiler.ts +1 -1
  28. package/packages/runtime/src/evidence/evidence-store.ts +2 -2
  29. package/packages/runtime/src/executor/action-tool-map.ts +4 -0
  30. package/packages/runtime/src/executor/built-in-tools.ts +29 -0
  31. package/packages/runtime/src/executor/llm-task-executor.ts +46 -4
  32. package/packages/runtime/src/executor/node-prompt-builder.ts +18 -1
  33. package/packages/runtime/src/models/failure.ts +2 -0
  34. package/packages/runtime/src/scheduler/scheduler.ts +93 -15
  35. package/packages/runtime/src/verification/verification-compiler.ts +7 -5
  36. package/vscode-extension/package.json +184 -184
  37. package/vscode-extension/oxe-agents-0.9.1.vsix +0 -0
  38. package/vscode-extension/oxe-agents-0.9.2.vsix +0 -0
  39. package/vscode-extension/oxe-agents-1.0.0.vsix +0 -0
  40. package/vscode-extension/oxe-agents-1.4.0.vsix +0 -0
  41. package/vscode-extension/oxe-agents-1.5.0.vsix +0 -0
  42. package/vscode-extension/oxe-agents-1.5.1.vsix +0 -0
  43. package/vscode-extension/oxe-agents-1.6.0.vsix +0 -0
  44. package/vscode-extension/oxe-agents-1.7.0.vsix +0 -0
@@ -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
  }
@@ -6,15 +6,15 @@ const built_in_tools_1 = require("./built-in-tools");
6
6
  const action_tool_map_1 = require("./action-tool-map");
7
7
  const node_prompt_builder_1 = require("./node-prompt-builder");
8
8
  const DEFAULT_SYSTEM_PROMPT = 'You are a precise software engineering agent. Use the tools provided to complete the task. ' +
9
- 'When the task is done, summarize what was accomplished in your final message without calling any tools.';
9
+ 'When all actions are done, call finish_task with a summary of what was accomplished.';
10
10
  class LlmTaskExecutor {
11
11
  constructor(provider, registry, onProgress) {
12
12
  this.provider = provider;
13
13
  this.registry = registry;
14
14
  this.onProgress = onProgress;
15
15
  }
16
- async execute(node, lease, runId, attempt) {
17
- const prompt = (0, node_prompt_builder_1.buildNodePrompt)(node, lease, runId, attempt);
16
+ async execute(node, lease, runId, attempt, options = {}) {
17
+ const prompt = (0, node_prompt_builder_1.buildNodePrompt)(node, lease, runId, attempt, { previousError: options.previousError ?? null });
18
18
  const tools = (0, action_tool_map_1.selectToolsForActions)(node.actions);
19
19
  const cwd = lease.root_path;
20
20
  const maxTurns = this.provider.maxTurns ?? 10;
@@ -25,7 +25,10 @@ class LlmTaskExecutor {
25
25
  ];
26
26
  let finalOutput = '';
27
27
  const evidencePaths = [];
28
- for (let turn = 0; turn < maxTurns; turn++) {
28
+ let completedByFinishTask = false;
29
+ let finishTaskSummary = '';
30
+ let turn = 0;
31
+ for (; turn < maxTurns; turn++) {
29
32
  this.emit({ type: 'turn_start', nodeId: node.id, attempt, detail: { turn } });
30
33
  let response;
31
34
  try {
@@ -60,12 +63,45 @@ class LlmTaskExecutor {
60
63
  serialResults.push(await this.invokeToolCall(tc, cwd, node, evidencePaths));
61
64
  }
62
65
  messages.push(...concurrentResults, ...serialResults);
66
+ // Detect finish_task call — authoritative completion signal
67
+ const allResults = [...concurrentResults, ...serialResults];
68
+ const finishResult = allResults.find((r) => r.name === 'finish_task');
69
+ if (finishResult) {
70
+ try {
71
+ const parsed = JSON.parse(finishResult.content);
72
+ if (parsed.__finish_task__) {
73
+ completedByFinishTask = true;
74
+ finishTaskSummary = parsed.summary || '';
75
+ if (Array.isArray(parsed.evidence_paths)) {
76
+ evidencePaths.push(...parsed.evidence_paths.filter((p) => typeof p === 'string'));
77
+ }
78
+ }
79
+ }
80
+ catch { /* ignore parse errors */ }
81
+ if (completedByFinishTask)
82
+ break;
83
+ }
84
+ }
85
+ const completedBy = completedByFinishTask
86
+ ? 'finish_task'
87
+ : turn < maxTurns
88
+ ? 'no_tool_call'
89
+ : 'turn_limit_exhausted';
90
+ if (completedBy === 'turn_limit_exhausted') {
91
+ return {
92
+ success: false,
93
+ failure_class: 'llm',
94
+ evidence: evidencePaths,
95
+ output: finalOutput || `Task exhausted ${maxTurns} turns without calling finish_task`,
96
+ completed_by: completedBy,
97
+ };
63
98
  }
64
99
  return {
65
100
  success: true,
66
101
  failure_class: null,
67
102
  evidence: evidencePaths,
68
- output: finalOutput,
103
+ output: completedByFinishTask ? (finishTaskSummary || finalOutput) : finalOutput,
104
+ completed_by: completedBy,
69
105
  };
70
106
  }
71
107
  async invokeToolCall(tc, cwd, node, evidencePaths) {
@@ -1,3 +1,6 @@
1
1
  import type { GraphNode } from '../compiler/graph-compiler';
2
2
  import type { WorkspaceLease } from '../models/workspace';
3
- export declare function buildNodePrompt(node: GraphNode, lease: WorkspaceLease, runId: string, attempt: number): string;
3
+ export interface NodePromptOptions {
4
+ previousError?: string | null;
5
+ }
6
+ export declare function buildNodePrompt(node: GraphNode, lease: WorkspaceLease, runId: string, attempt: number, options?: NodePromptOptions): string;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildNodePrompt = buildNodePrompt;
4
- function buildNodePrompt(node, lease, runId, attempt) {
4
+ function buildNodePrompt(node, lease, runId, attempt, options = {}) {
5
5
  const lines = [
6
6
  `# Tarefa: ${node.title}`,
7
7
  '',
@@ -11,6 +11,14 @@ function buildNodePrompt(node, lease, runId, attempt) {
11
11
  if (node.mutation_scope.length > 0) {
12
12
  lines.push(`**Escopo de mutação:** ${node.mutation_scope.join(', ')}`);
13
13
  }
14
+ if (attempt > 1 && options.previousError) {
15
+ lines.push('', '## Contexto da tentativa anterior');
16
+ lines.push(`Esta é a tentativa **${attempt}**. A tentativa anterior falhou:`);
17
+ lines.push('', '```');
18
+ lines.push(String(options.previousError).slice(0, 2000));
19
+ lines.push('```', '');
20
+ lines.push('Analise o erro e tente uma abordagem diferente.');
21
+ }
14
22
  if (node.actions.length > 0) {
15
23
  lines.push('', '## Ações requeridas');
16
24
  for (const action of node.actions) {
@@ -31,6 +39,9 @@ function buildNodePrompt(node, lease, runId, attempt) {
31
39
  if (node.verify.command) {
32
40
  lines.push('', `**Verificação:** \`${node.verify.command}\``);
33
41
  }
34
- lines.push('', 'Execute as ações acima usando as ferramentas disponíveis e confirme o resultado.');
42
+ lines.push('', '## Conclusão da tarefa');
43
+ lines.push('Quando **todas** as ações estiverem concluídas, chame `finish_task` com um resumo do que foi realizado.');
44
+ lines.push('NÃO chame `finish_task` antes de completar todas as ações requeridas.');
45
+ lines.push('', 'Execute as ações acima usando as ferramentas disponíveis.');
35
46
  return lines.join('\n');
36
47
  }
@@ -2,4 +2,4 @@
2
2
  * Canonical failure classification used by TaskResult and VerificationManifest.
3
3
  * Both must import from this file — never redefine inline.
4
4
  */
5
- export type FailureClass = 'env' | 'policy' | 'test' | 'timeout' | 'evidence_missing' | null;
5
+ export type FailureClass = 'env' | 'policy' | 'test' | 'timeout' | 'evidence_missing' | 'verify' | 'llm' | null;
@@ -14,9 +14,12 @@ export interface TaskResult {
14
14
  failure_class: FailureClass;
15
15
  evidence: string[];
16
16
  output: string;
17
+ completed_by?: string;
17
18
  }
18
19
  export interface TaskExecutor {
19
- execute(node: GraphNode, lease: WorkspaceLease, runId: string, attemptNumber: number): Promise<TaskResult>;
20
+ execute(node: GraphNode, lease: WorkspaceLease, runId: string, attemptNumber: number, options?: {
21
+ previousError?: string | null;
22
+ }): Promise<TaskResult>;
20
23
  }
21
24
  export interface SchedulerOptions {
22
25
  maxRunDurationMs?: number;
@@ -70,6 +73,7 @@ export declare class Scheduler {
70
73
  getJournal(): RunJournal | null;
71
74
  static loadJournal(projectRoot: string, runId: string): RunJournal | null;
72
75
  private executeNode;
76
+ private verifyNode;
73
77
  private evaluatePolicyForNode;
74
78
  private requestGateForNode;
75
79
  private blockNode;
@@ -12,6 +12,7 @@ const audit_trail_1 = require("../audit/audit-trail");
12
12
  const run_journal_1 = require("./run-journal");
13
13
  const decision_memo_1 = require("../decision/decision-memo");
14
14
  const capability_adapter_1 = require("../plugins/capability-adapter");
15
+ const verification_compiler_1 = require("../verification/verification-compiler");
15
16
  class Scheduler {
16
17
  constructor() {
17
18
  this.cancelled = false;
@@ -350,6 +351,7 @@ class Scheduler {
350
351
  });
351
352
  let lease = null;
352
353
  let lastResult = null;
354
+ let lastError = null;
353
355
  const maxAttempts = node.policy.max_retries + 1;
354
356
  const quotaBlocked = this.consumeQuotaForNode(ctx, node);
355
357
  if (quotaBlocked) {
@@ -408,19 +410,31 @@ class Scheduler {
408
410
  attempt_id: attemptId,
409
411
  payload: { workspace_id: lease.workspace_id, strategy: lease.strategy },
410
412
  });
411
- lastResult = await this.executeNode(node, lease, ctx, attempt, attemptId);
413
+ lastResult = await this.executeNode(node, lease, ctx, attempt, attemptId, { previousError: lastError });
412
414
  if (lastResult.success) {
413
- this.emit(ctx, {
414
- type: 'WorkItemCompleted',
415
- work_item_id: nodeId,
416
- attempt_id: attemptId,
417
- payload: { attempt_number: attempt, evidence: lastResult.evidence },
418
- });
419
- status.set(nodeId, 'completed');
420
- completed.push(nodeId);
421
- this.recordProgress();
422
- return;
415
+ const verifyResult = await this.verifyNode(node, lease, ctx, attemptId, attempt);
416
+ if (verifyResult && verifyResult.status === 'failed') {
417
+ lastResult = {
418
+ success: false,
419
+ failure_class: 'verify',
420
+ evidence: lastResult.evidence,
421
+ output: `Verification failed: ${(verifyResult.gaps || []).join('; ') || 'checks did not pass'}`,
422
+ };
423
+ }
424
+ else {
425
+ this.emit(ctx, {
426
+ type: 'WorkItemCompleted',
427
+ work_item_id: nodeId,
428
+ attempt_id: attemptId,
429
+ payload: { attempt_number: attempt, evidence: lastResult.evidence },
430
+ });
431
+ status.set(nodeId, 'completed');
432
+ completed.push(nodeId);
433
+ this.recordProgress();
434
+ return;
435
+ }
423
436
  }
437
+ lastError = lastResult.output || (lastResult.failure_class ?? 'unknown error');
424
438
  if (lastResult.failure_class === 'policy')
425
439
  break;
426
440
  if (attempt < maxAttempts) {
@@ -454,6 +468,7 @@ class Scheduler {
454
468
  evidence: [],
455
469
  output: `[error_boundary] ${message}`,
456
470
  };
471
+ lastError = lastResult.output;
457
472
  if (attempt < maxAttempts) {
458
473
  const backoffMs = Math.min(1000 * Math.pow(2, attempt - 1) + Math.random() * 500, 30000);
459
474
  await new Promise(resolve => setTimeout(resolve, backoffMs));
@@ -509,11 +524,11 @@ class Scheduler {
509
524
  static loadJournal(projectRoot, runId) {
510
525
  return (0, run_journal_1.loadJournal)(projectRoot, runId);
511
526
  }
512
- async executeNode(node, lease, ctx, attempt, attemptId) {
527
+ async executeNode(node, lease, ctx, attempt, attemptId, options = {}) {
513
528
  const primaryAction = pickPrimaryAction(node, ctx.pluginRegistry);
514
529
  const provider = primaryAction ? ctx.pluginRegistry?.toolProviderFor(primaryAction.type) : null;
515
530
  if (!provider || !primaryAction) {
516
- return ctx.executor.execute(node, lease, ctx.runId, attempt);
531
+ return ctx.executor.execute(node, lease, ctx.runId, attempt, options);
517
532
  }
518
533
  ctx.auditTrail?.record('plugin_invoked', ctx.policyActor ?? 'runtime', {
519
534
  runId: ctx.runId,
@@ -573,6 +588,57 @@ class Scheduler {
573
588
  output: result.output,
574
589
  };
575
590
  }
591
+ async verifyNode(node, lease, ctx, attemptId, attempt) {
592
+ if (!node.verify?.command)
593
+ return null;
594
+ this.emit(ctx, {
595
+ type: 'VerificationStarted',
596
+ work_item_id: node.id,
597
+ payload: { command: node.verify.command, attempt_number: attempt },
598
+ });
599
+ const suite = {
600
+ checks: [{
601
+ id: `inline-${node.id}`,
602
+ type: 'custom',
603
+ command: node.verify.command,
604
+ evidence_type_expected: 'stdout',
605
+ acceptance_ref: null,
606
+ description: `Verify ${node.id}`,
607
+ }],
608
+ compiled_at: new Date().toISOString(),
609
+ spec_hash: '',
610
+ plan_hash: '',
611
+ };
612
+ let result;
613
+ try {
614
+ result = await (0, verification_compiler_1.verifyRun)({
615
+ suite,
616
+ cwd: lease.root_path,
617
+ timeoutMs: ctx.options?.verifyTimeoutMs ?? 60000,
618
+ runId: ctx.runId,
619
+ workItemId: node.id,
620
+ attemptNumber: attempt,
621
+ projectRoot: ctx.projectRoot,
622
+ pluginRegistry: ctx.pluginRegistry,
623
+ });
624
+ }
625
+ catch (err) {
626
+ this.emit(ctx, {
627
+ type: 'VerificationCompleted',
628
+ work_item_id: node.id,
629
+ attempt_id: attemptId,
630
+ payload: { status: 'error', error: String(err) },
631
+ });
632
+ return null;
633
+ }
634
+ this.emit(ctx, {
635
+ type: 'VerificationCompleted',
636
+ work_item_id: node.id,
637
+ attempt_id: attemptId,
638
+ payload: { status: result.status },
639
+ });
640
+ return result;
641
+ }
576
642
  evaluatePolicyForNode(node, ctx) {
577
643
  if (!ctx.policyEngine)
578
644
  return null;
@@ -603,8 +669,10 @@ class Scheduler {
603
669
  return persisted;
604
670
  }
605
671
  async requestGateForNode(node, ctx, decision) {
606
- if (!ctx.gateManager)
672
+ if (!ctx.gateManager) {
673
+ console.warn('[scheduler] ctx.gateManager not configured — gates will not be persisted');
607
674
  return 'gate-missing-manager';
675
+ }
608
676
  const scope = inferGateScope(node);
609
677
  const primaryAction = pickPrimaryAction(node, ctx.pluginRegistry);
610
678
  const gate = await ctx.gateManager.request(scope, {
@@ -92,15 +92,17 @@ async function runCheck(check, cwd, timeoutMs = 60000) {
92
92
  }
93
93
  const start = Date.now();
94
94
  try {
95
- // Split command into program + args (simple split; no shell expansion)
96
- const parts = check.command.split(/\s+/);
97
- const prog = parts[0];
98
- const args = parts.slice(1);
99
- const result = (0, child_process_1.spawnSync)(prog, args, {
95
+ // Use shell so the full command string is interpreted (handles quotes, &&, node -e "...")
96
+ const isWin = process.platform === 'win32';
97
+ const shell = isWin ? 'cmd' : 'sh';
98
+ const shellArgs = isWin ? ['/c', check.command] : ['-c', check.command];
99
+ const result = (0, child_process_1.spawnSync)(shell, shellArgs, {
100
100
  cwd,
101
101
  encoding: 'utf8',
102
102
  timeout: timeoutMs,
103
103
  maxBuffer: 2 * 1024 * 1024,
104
+ // On Windows, prevent Node from re-quoting the args (preserves double-quotes inside node -e "...")
105
+ windowsVerbatimArguments: isWin,
104
106
  });
105
107
  const duration_ms = Date.now() - start;
106
108
  const status = result.status === 0 ? 'pass' : 'fail';
package/lib/sdk/index.cjs CHANGED
@@ -17,10 +17,10 @@ const plugins = require('../../bin/lib/oxe-plugins.cjs');
17
17
  const dashboard = require('../../bin/lib/oxe-dashboard.cjs');
18
18
  const operational = require('../../bin/lib/oxe-operational.cjs');
19
19
  const azure = require('../../bin/lib/oxe-azure.cjs');
20
- const context = require('../../bin/lib/oxe-context-engine.cjs');
21
- const runtimeSemantics = require('../../bin/lib/oxe-runtime-semantics.cjs');
22
- const release = require('../../bin/lib/oxe-release.cjs');
23
- const rationality = require('../../bin/lib/oxe-rationality.cjs');
20
+ const context = require('../../bin/lib/oxe-context-engine.cjs');
21
+ const runtimeSemantics = require('../../bin/lib/oxe-runtime-semantics.cjs');
22
+ const release = require('../../bin/lib/oxe-release.cjs');
23
+ const rationality = require('../../bin/lib/oxe-rationality.cjs');
24
24
 
25
25
  const PACKAGE_ROOT = path.join(__dirname, '..', '..');
26
26
 
@@ -94,8 +94,12 @@ function parsePlan(planMd) {
94
94
  ? filesMatch[1].match(/`([^`]+)`/g)?.map((s) => s.replace(/`/g, '')) || []
95
95
  : [];
96
96
 
97
- const verifyCmdMatch = rest.match(/Comando:\s*`([^`]+)`/i);
98
- const verifyCommand = verifyCmdMatch ? verifyCmdMatch[1] : null;
97
+ // Accept: "Comando: `...`" (PT), "**Verify command:** `...`", "**Verificação:** `...`", "**Verification:** `...`"
98
+ // Use [^`]+ with dotAll so multiline commands inside backticks are captured
99
+ const verifyCmdMatch = rest.match(
100
+ /(?:Comando|Verify\s+command|Verificação|Verification):\s*`([^`]+)`/is
101
+ );
102
+ const verifyCommand = verifyCmdMatch ? verifyCmdMatch[1].trim() : null;
99
103
 
100
104
  const aceiteMatch = rest.match(/\*\*Aceite\s+vinculado:\*\*\s*([^\n]+)/i);
101
105
  const aceite = aceiteMatch
@@ -542,23 +546,23 @@ module.exports = {
542
546
  /** Parsing de artefatos OXE (PLAN, SPEC, STATE, hypotheses, confidence, lessons). */
543
547
  parsePlan,
544
548
  parseSpec,
545
- parseHypotheses: context.parseHypotheses,
546
- parseConfidenceVector: context.parseConfidenceVector,
547
- parseExecutionPlanTasks: rationality.parsePlanTasks,
548
- parseState,
549
+ parseHypotheses: context.parseHypotheses,
550
+ parseConfidenceVector: context.parseConfidenceVector,
551
+ parseExecutionPlanTasks: rationality.parsePlanTasks,
552
+ parseState,
549
553
  validateDecisionFidelity,
550
554
  parseLessonsMetrics,
551
555
  updateLessonMetric,
552
556
  deprecateLowEffectiveness,
553
557
 
554
558
  /** Estado do projeto, SPEC/PLAN, fase, config. */
555
- health: {
556
- loadOxeConfigMerged: health.loadOxeConfigMerged,
557
- validateConfigShape: health.validateConfigShape,
558
- buildHealthReport: health.buildHealthReport,
559
- detectWorkspaceMode: health.detectWorkspaceMode,
560
- shouldSuppressExecutionWorkspaceGates: health.shouldSuppressExecutionWorkspaceGates,
561
- suggestNextStep: health.suggestNextStep,
559
+ health: {
560
+ loadOxeConfigMerged: health.loadOxeConfigMerged,
561
+ validateConfigShape: health.validateConfigShape,
562
+ buildHealthReport: health.buildHealthReport,
563
+ detectWorkspaceMode: health.detectWorkspaceMode,
564
+ shouldSuppressExecutionWorkspaceGates: health.shouldSuppressExecutionWorkspaceGates,
565
+ suggestNextStep: health.suggestNextStep,
562
566
  oxePaths: health.oxePaths,
563
567
  parseStatePhase: health.parseStatePhase,
564
568
  parseLastScanDate: health.parseLastScanDate,
@@ -572,11 +576,11 @@ module.exports = {
572
576
  planAgentsWarnings: health.planAgentsWarnings,
573
577
  phaseCoherenceWarnings: health.phaseCoherenceWarnings,
574
578
  specSectionWarnings: health.specSectionWarnings,
575
- planWaveWarningsFixed: health.planWaveWarningsFixed,
576
- planTaskAceiteWarnings: health.planTaskAceiteWarnings,
577
- buildExecutionRationality: health.buildExecutionRationality,
578
- executionRationalityWarningsFromSummary: health.executionRationalityWarningsFromSummary,
579
- verifyGapsWithoutSummaryWarning: health.verifyGapsWithoutSummaryWarning,
579
+ planWaveWarningsFixed: health.planWaveWarningsFixed,
580
+ planTaskAceiteWarnings: health.planTaskAceiteWarnings,
581
+ buildExecutionRationality: health.buildExecutionRationality,
582
+ executionRationalityWarningsFromSummary: health.executionRationalityWarningsFromSummary,
583
+ verifyGapsWithoutSummaryWarning: health.verifyGapsWithoutSummaryWarning,
580
584
  expandExecutionProfile: health.expandExecutionProfile,
581
585
  ALLOWED_CONFIG_KEYS: health.ALLOWED_CONFIG_KEYS,
582
586
  EXECUTION_PROFILES: health.EXECUTION_PROFILES,
@@ -643,28 +647,28 @@ module.exports = {
643
647
  },
644
648
 
645
649
  /** Dashboard local: contexto consolidado e persistência de revisão do plano. */
646
- dashboard: {
647
- loadDashboardContext: dashboard.loadDashboardContext,
648
- savePlanReviewStatus: dashboard.savePlanReviewStatus,
649
- addPlanReviewComment: dashboard.addPlanReviewComment,
650
- updatePlanReviewCommentStatus: dashboard.updatePlanReviewCommentStatus,
651
- },
652
-
653
- /** Release readiness: manifest, smoke matrix e checks de consistência antes de publicar. */
654
- release: {
655
- REQUIRED_RUNTIMES: release.REQUIRED_RUNTIMES,
656
- WRAPPER_TARGETS: release.WRAPPER_TARGETS,
657
- releasePaths: release.releasePaths,
658
- collectWrapperHashes: release.collectWrapperHashes,
659
- loadRuntimeSmokeReport: release.loadRuntimeSmokeReport,
660
- loadRecoveryFixtureReport: release.loadRecoveryFixtureReport,
661
- loadMultiAgentSoakReport: release.loadMultiAgentSoakReport,
662
- buildReleaseManifest: release.buildReleaseManifest,
663
- inspectCanonicalSource: release.inspectCanonicalSource,
664
- evaluateReleaseManifest: release.evaluateReleaseManifest,
665
- inspectReleaseReadiness: release.inspectReleaseReadiness,
666
- checkReleaseConsistency: release.checkReleaseConsistency,
667
- },
650
+ dashboard: {
651
+ loadDashboardContext: dashboard.loadDashboardContext,
652
+ savePlanReviewStatus: dashboard.savePlanReviewStatus,
653
+ addPlanReviewComment: dashboard.addPlanReviewComment,
654
+ updatePlanReviewCommentStatus: dashboard.updatePlanReviewCommentStatus,
655
+ },
656
+
657
+ /** Release readiness: manifest, smoke matrix e checks de consistência antes de publicar. */
658
+ release: {
659
+ REQUIRED_RUNTIMES: release.REQUIRED_RUNTIMES,
660
+ WRAPPER_TARGETS: release.WRAPPER_TARGETS,
661
+ releasePaths: release.releasePaths,
662
+ collectWrapperHashes: release.collectWrapperHashes,
663
+ loadRuntimeSmokeReport: release.loadRuntimeSmokeReport,
664
+ loadRecoveryFixtureReport: release.loadRecoveryFixtureReport,
665
+ loadMultiAgentSoakReport: release.loadMultiAgentSoakReport,
666
+ buildReleaseManifest: release.buildReleaseManifest,
667
+ inspectCanonicalSource: release.inspectCanonicalSource,
668
+ evaluateReleaseManifest: release.evaluateReleaseManifest,
669
+ inspectReleaseReadiness: release.inspectReleaseReadiness,
670
+ checkReleaseConsistency: release.checkReleaseConsistency,
671
+ },
668
672
 
669
673
  /** Runtime operacional: tracing, active run, catálogo de capabilities e memória em camadas. */
670
674
  operational: {
@@ -24,12 +24,14 @@ evidence_expectation: manifest | command | manual | mixed
24
24
 
25
25
  > Gerado a partir de `.oxe/SPEC.md`. Cada tarefa deve ter bloco **Verificar**.
26
26
 
27
- ## Resumo
28
-
29
- - **Spec vinculada:** (data ou versão informal)
30
- - **Ondas:** (número)
31
- - **Tarefas:** (número)
32
- - **Artefatos racionais:** `IMPLEMENTATION-PACK`, `REFERENCE-ANCHORS`, `FIXTURE-PACK`
27
+ ## Resumo
28
+
29
+ - **Spec vinculada:** (data ou versão informal)
30
+ - **Ondas:** (número)
31
+ - **Tarefas:** (número)
32
+ - **Artefatos racionais:** `IMPLEMENTATION-PACK`, `REFERENCE-ANCHORS`, `FIXTURE-PACK`
33
+ - **Público / outcome da spec:** …
34
+ - **Padrão de validação dominante:** testes | smoke | manual guiado | mixed
33
35
 
34
36
  ## Autoavaliação do Plano
35
37
 
@@ -48,6 +50,7 @@ evidence_expectation: manifest | command | manual | mixed
48
50
  - **Alternativas descartadas:** (1–2 linhas)
49
51
  - **Condição para replanejar:** (critério objetivo)
50
52
  - **Bloqueadores de execução:** nenhum | listar gaps críticos
53
+ - **Densidade operacional mínima confirmada:** paths | symbols | fixtures | anchors | checks
51
54
 
52
55
  <confidence_vector cycle="C-NN" generated_at="YYYY-MM-DDTHH:MM:SSZ">
53
56
  <dim name="requirements" score="0.92" weight="25" note="completude dos requisitos" />
@@ -80,9 +83,17 @@ evidence_expectation: manifest | command | manual | mixed
80
83
  </hypothesis>
81
84
  -->
82
85
 
83
- ## Dependências globais
84
-
85
- - (ex.: branch base, feature flags, migrations)
86
+ ## Dependências globais
87
+
88
+ - (ex.: branch base, feature flags, migrations)
89
+
90
+ ## Contrato operacional da solução
91
+
92
+ - **Write-set principal:** módulos/paths que concentram a mutação
93
+ - **Modelo de conteúdo / dados a materializar:** …
94
+ - **Interações ou fluxos obrigatórios:** …
95
+ - **Persistência local/remota:** none | localStorage | API | outro
96
+ - **Responsividade / acessibilidade obrigatória:** …
86
97
 
87
98
  ## Artefatos racionais de execução
88
99
 
@@ -118,18 +129,21 @@ evidence_expectation: manifest | command | manual | mixed
118
129
  ### T1 — (título)
119
130
 
120
131
  - **Arquivos alvo:** `src/exato.ts`
132
+ - **Símbolos alvo:** `função`, `classe`, `componente`, `builder`, `schema`
121
133
  - **Depende de:** —
122
134
  - **Onda:** 1
123
135
  - **Complexidade:** S
124
136
  - **Risco:** low | medium | high | critical
125
137
  - **Evidência de entrada:** SPEC A1 | DISCUSS D-01 | RESEARCH RA-01 | codebase path
126
138
  - **Checkpoint:** nenhum | CHK-01
139
+ - **Estado/fluxo coberto:** loading | empty | success | error | interação X
127
140
  - **Verificar:**
128
141
  - Comando: `…`
129
142
  - Manual: (opcional) …
130
143
  - **Implementar:** o mínimo para fazer a verificação acima passar.
131
144
  - **Aceite vinculado:** A1, A2 (IDs da tabela de critérios em SPEC.md)
132
145
  - **Contrato racional:** ver `IMPLEMENTATION-PACK.json` (task `T1`)
146
+ - **Fixture/anchor obrigatório:** FX-01 | RA-01 | not_applicable
133
147
  - **Rollback/contensão:** obrigatório para risco high/critical; `not_applicable` se low/medium.
134
148
 
135
149
  ---