feat: Execution Engine — Post-Execution Protocol (PEP)#595
feat: Execution Engine — Post-Execution Protocol (PEP)#595torriani wants to merge 1 commit intoSynkraAI:mainfrom
Conversation
Adiciona sistema de compliance auditing, next-step routing e blind spot detection para todos os agents AIOS. Componentes: - ExecutionContract: extrai contrato de execução de tasks/workflows - ComplianceAuditor: audita aderência ao processo (feito vs esperado) - BlindSpotDetector: detecta gaps sistêmicos em múltiplas execuções - NextStepRouter: roteia próximo passo após cada comando - POST-EXECUTION-PROTOCOL.md: protocolo obrigatório para agents - Self-test completo (6 testes, todos passam) Resolve dois problemas: 1. Agents nunca mostravam o próximo passo após execução 2. Não existia verificação se o workflow completo foi seguido Inspirado no Copy Blind Spot Detection System. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@torriani is attempting to deploy a commit to the Pedro Valério Lopez's projects Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughIntroduces a comprehensive Post-Execution Protocol (PEP) system enabling automated compliance auditing, execution validation, and next-step routing. Adds four JavaScript modules for contract extraction, compliance reporting, blind-spot detection, and workflow routing, plus documentation and a self-test script. Changes
Sequence Diagram(s)sequenceDiagram
participant Agent as Agent/Task
participant ContractBuilder as ContractBuilder
participant ExecutionResult as ExecutionResult
participant ComplianceAuditor as ComplianceAuditor
participant NextStepRouter as NextStepRouter
participant Report as ComplianceReport
Agent->>ContractBuilder: build(filePath)
activate ContractBuilder
ContractBuilder->>ContractBuilder: Extract phases, gates, vetos, nextStep
ContractBuilder-->>Agent: ExecutionContract
deactivate ContractBuilder
Agent->>ExecutionResult: new ExecutionResult(contract)
activate ExecutionResult
Agent->>ExecutionResult: markPhase(), markGate(), triggerVeto()
Agent->>ExecutionResult: complete()
ExecutionResult-->>Agent: ExecutionResult (completed)
deactivate ExecutionResult
Agent->>ComplianceAuditor: audit(contract, result)
activate ComplianceAuditor
ComplianceAuditor->>ComplianceAuditor: Count phases, evaluate gates, score adherence
ComplianceAuditor->>ComplianceAuditor: Detect gaps, vetos, infer nextStep
ComplianceAuditor-->>Report: ComplianceReport (PASS/PARTIAL/FAIL)
deactivate ComplianceAuditor
Agent->>Report: toTerminal() / toMarkdown()
activate Report
Report-->>Agent: Formatted compliance output
deactivate Report
Agent->>NextStepRouter: route(contract, report)
activate NextStepRouter
NextStepRouter->>NextStepRouter: Evaluate report gaps, handoffs, defaults
NextStepRouter-->>Agent: NextStep (command + rationale)
deactivate NextStepRouter
Agent-->>Agent: Display Compliance Report + Next Step
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip CodeRabbit can use Trivy to scan for security misconfigurations and secrets in Infrastructure as Code files.Add a .trivyignore file to your project to customize which findings Trivy reports. |
There was a problem hiding this comment.
Welcome to aiox-core! Thanks for your first pull request.
What happens next?
- Automated checks will run on your PR
- A maintainer will review your changes
- Once approved, we'll merge your contribution!
PR Checklist:
- Tests pass (
npm test) - Linting passes (
npm run lint) - Commit messages follow Conventional Commits
Thanks for contributing!
There was a problem hiding this comment.
Actionable comments posted: 12
🧹 Nitpick comments (5)
.aiox-core/core/execution/next-step-router.js (1)
178-179: Consider hoisting thejs-yamlrequire outside the method.Requiring
js-yamlinsidefindPositionmeans the module resolution happens on every call. While the cost is minimal after the first load (due to Node.js caching), hoisting it to module scope with the existing fallback pattern would be cleaner and consistent with how it's done elsewhere.♻️ Suggested refactor
+let yaml; +try { yaml = require('js-yaml'); } catch { yaml = null; } // Inside findPosition: - let yaml; - try { yaml = require('js-yaml'); } catch { return null; } + if (!yaml) return null;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aiox-core/core/execution/next-step-router.js around lines 178 - 179, The require('js-yaml') call should be moved out of the findPosition function and hoisted to module scope to avoid repeated module resolution; create a top-level variable (e.g., let yaml) and use the same try/catch fallback pattern used elsewhere, then update findPosition to use that module-scoped yaml variable (or return null if it's not available) so the require only runs once and the function body stays tidy..aiox-core/core/execution/self-test.js (2)
92-103: Test 6 should verify 100% adherence score.The "perfect execution" test creates an ExecutionResult with all phases and gates marked as done, but doesn't verify that the resulting compliance score is actually 100%.
♻️ Add assertion for perfect compliance
const perfectReport = ComplianceAuditor.audit(contract, perfectResult); +if (perfectReport.adherenceScore !== 100 || perfectReport.status !== 'PASS') { + console.error(` ❌ Expected 100% PASS, got ${perfectReport.adherenceScore}% ${perfectReport.status}`); +} console.log(perfectReport.toTerminal());🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aiox-core/core/execution/self-test.js around lines 92 - 103, The test creates a perfect ExecutionResult but never asserts the compliance score; add an assertion after computing perfectReport to verify 100% compliance (e.g., check perfectReport.score or perfectReport.getCompliancePercentage() equals 100 or perfectReport.isPerfect() depending on available API). Locate the block that builds perfectResult (uses ExecutionResult.markPhase, markGate, and complete) and insert a single assertion against perfectReport (the result of ComplianceAuditor.audit) to ensure the audit yields exactly 100% adherence.
1-107: Self-test lacks programmatic assertions and proper exit codes.The self-test script runs through the modules but doesn't verify expected outcomes. All tests "pass" regardless of actual results. For CI/CD integration and reliable testing, consider adding assertions and proper exit codes.
♻️ Proposed improvements for test reliability
+let testsPassed = 0; +let testsFailed = 0; + +function assert(condition, message) { + if (!condition) { + console.error(` ❌ Assertion failed: ${message}`); + testsFailed++; + return false; + } + testsPassed++; + return true; +} // ─── Test 1: Criar contrato manualmente ─── console.log('Test 1: Criar ExecutionContract...'); const contract = new ExecutionContract('test/create-carousel.md'); // ... existing setup ... -console.log(` ✅ Contrato criado: ${contract.phases.length} fases, ${contract.qualityGates.length} gates\n`); +assert(contract.phases.length === 7, 'Contract should have 7 phases'); +assert(contract.qualityGates.length === 3, 'Contract should have 3 quality gates'); +console.log(` ✅ Test 1 complete\n`); // At the end of the file: -console.log(' Todos os testes passaram ✅'); +console.log(`Tests: ${testsPassed} passed, ${testsFailed} failed`); +process.exit(testsFailed > 0 ? 1 : 0);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aiox-core/core/execution/self-test.js around lines 1 - 107, The self-test currently only prints results; add programmatic assertions and proper exit codes so CI can fail on regressions: after each logical step assert expected values (e.g., for Test 2 assert result phases/gates statuses and for Test 3 assert ComplianceAuditor.audit(contract, result) returns expected flags/violations, for Test 4 assert NextStepRouter.route(...) yields the expected nextStep, for Test 5 assert BlindSpotDetector.analyze(reports) contains the expected metrics, and for Test 6 assert perfectReport shows full compliance), wrap the entire run in try/catch and call process.exit(0) on success or process.exit(1) on any assertion failure or thrown error; use the existing symbols ExecutionContract, ExecutionResult, ComplianceAuditor.audit, NextStepRouter.route, BlindSpotDetector.analyze and their .toTerminal outputs only for human-readable logs while failing programmatically on mismatches..aiox-core/core/execution/compliance-auditor.js (1)
283-298: Unchecked gates count as failures — consider documenting or handling differently.When a gate has no corresponding result entry (
gateResultis undefined), it's counted as failed. This may be intentional (unchecked gates should fail), but it could surprise consumers who expect only explicitly failed gates to be counted.💡 Consider adding a distinct state for unchecked gates
for (const gate of contract.qualityGates) { const gateResult = result.gateResults[gate.id]; if (gateResult && gateResult.passed) { report.gatesPassed++; - } else { + } else if (gateResult && !gateResult.passed) { report.gatesFailed++; if (gate.type === 'blocking') { report.gaps.push({ phase: `Quality Gate: ${gate.name}`, status: 'failed', reference: null, - impact: gateResult ? gateResult.details : 'Gate não verificado', + impact: gateResult.details || 'Gate failed without details', }); } + } else { + // Gate not checked - could track separately or treat as failed + report.gatesFailed++; + if (gate.type === 'blocking') { + report.gaps.push({ + phase: `Quality Gate: ${gate.name}`, + status: 'unchecked', + reference: null, + impact: 'Gate não verificado', + }); + } } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aiox-core/core/execution/compliance-auditor.js around lines 283 - 298, Currently loops over contract.qualityGates and treats a missing gateResult as a failure (increments report.gatesFailed and, for blocking gates, adds a failed gap with impact 'Gate não verificado'); change this to distinguish "unchecked" from "failed" by checking gateResult === undefined separately in the loop (use the existing variables contract.qualityGates, gateResult, report.gatesPassed/gatesFailed/gaps) and either (a) add a new counter like report.gatesUnchecked and push a gap with status 'unchecked' and impact 'Gate não verificado' for blocking gates, or (b) only increment report.gatesFailed when gateResult exists and passed === false while treating undefined as unchecked (document via the gap/status); implement one of these paths so unchecked gates are not silently counted as failures..aiox-core/core/execution/POST-EXECUTION-PROTOCOL.md (1)
27-47: Add language specifier to fenced code blocks.Static analysis (markdownlint) flags these code blocks for missing language specifiers. For terminal output examples, use
textorplaintextto satisfy the linter while preserving readability.📝 Example fix for code blocks
-``` +```text ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📊 Compliance Report: {comando}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aiox-core/core/execution/POST-EXECUTION-PROTOCOL.md around lines 27 - 47, The fenced code block examples in POST-EXECUTION-PROTOCOL.md are missing a language specifier and trigger markdownlint; update each triple-backtick block (the compliance report example) to use a plain-text specifier (e.g., ```text or ```plaintext) so terminal output remains readable and the linter passes; ensure all similar fenced blocks in the file are changed consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.aiox-core/core/execution/compliance-auditor.js:
- Around line 250-251: The static audit method currently assumes valid inputs;
add input validation at the start of ComplianceAuditor.audit to ensure
`contract` is a non-null object with required properties (`command` and `squad`,
both non-empty strings) and that `result` is a non-null object (or whatever
shape your code expects), and throw a clear TypeError (or return an error value
consistent with the project) if checks fail; update the method before creating a
new ComplianceReport(contract.command, contract.squad) so you avoid accessing
undefined properties and make any downstream code (that uses `result`) guarded
as well.
- Around line 341-368: The postMortem static method should validate its input
before using it: at the start of ComplianceAuditor.postMortem(check for
contract) verify that contract is non-null/undefined and has the expected shape
(e.g., contract.source and contract.phases as an array); if validation fails,
throw a clear TypeError (e.g., "contract is required") or return an appropriate
error value, and guard downstream usage of contract.phases and contract.source
(used to construct ExecutionResult and iterate phases) so you don't dereference
properties of an undefined contract.
In @.aiox-core/core/execution/execution-contract.js:
- Around line 82-100: The fromYaml static method (ExecutionContract.fromYaml)
must validate the input before parsing: ensure the incoming content parameter is
a non-empty string (not undefined, null, or only whitespace) and throw a clear
TypeError if invalid; then proceed to parse using the existing yaml ?
yaml.load(content) : JSON.parse(content) logic. Add this guard at the start of
fromYaml, referencing the content parameter and keeping existing behavior for
yaml/JSON parsing and subsequent object mapping to ExecutionContract.
- Around line 116-117: The fromTask method calls fs.readFileSync(taskPath,
'utf8') without error handling; wrap the file read in a try/catch inside the
static fromTask(taskPath) method, catch filesystem errors (ENOENT, EACCES,
etc.), and rethrow or throw a new Error with contextual information including
taskPath and the original error message; ensure the catch returns/propagates a
clear, descriptive error so callers of ExecutionContract.fromTask can
distinguish file-read failures from other parsing errors.
- Around line 239-241: The fromWorkflow method lacks try/catch around the file
read and YAML parse and throws an error without context; wrap the
fs.readFileSync and yaml parsing logic in a try/catch (mirroring fromTask),
validate that yaml is available before parsing, and on error throw or log a new
Error that includes the workflowPath and the original error message/stack so
callers have full context (refer to fromWorkflow, workflowPath, fs.readFileSync,
and yaml).
- Around line 123-125: The YAML parse error is being swallowed in the empty
catch, so modify the try/catch around yaml.load(yamlMatch[1]) (the block that
assigns taskDef) to catch the error as e and log a clear message containing the
offending YAML snippet (yamlMatch[1]) and the error (e) instead of ignoring it;
ensure taskDef fallback remains (e.g., {} ) after logging so behavior is
unchanged but parsing failures are visible for debugging.
- Around line 243-262: The workflow parsing should read the top-level workflow
name and handle singular phase tasks: update the contract.command assignment to
prefer wf.workflow.name, then wf.name, wf.workflow_name, and lastly the filename
(keep ExecutionContract/workflowPath usage), and change the phases mapping to
iterate wf.phases and, for each phase object p, use tasks derived from the
singular p.task (e.g. (p.task ? [p.task] : [])) instead of p.tasks; keep
existing fields like id, name, required, status, agent, checkpoint and checklist
and leave ContractBuilder._detectSquad(workflowPath) as-is.
In @.aiox-core/core/execution/next-step-router.js:
- Around line 68-80: The code currently picks the first entry from
contract.handoffs without evaluating its condition; update the logic in the
next-step-router to iterate contract.handoffs and evaluate each handoff.when
against the current report/state, selecting the first handoff whose when
condition passes (use or add a small evaluator function like
evaluateCondition(state, expression) to test handoff.when), then return the same
object populated with handoff.to, handoff.context, reason 'HANDOFF_CONDITIONAL',
urgency and suggestion using handoff.to and handoff.when; if no handoff.when
matches, fall back to the previous behavior or return null as appropriate.
- Around line 43-56: The static method route(contract, report) currently assumes
contract and report exist and that report.status and report.gaps are present;
add input validation at the start of route to guard against null/undefined or
malformed inputs by checking that report is an object, report.status is a
string, and report.gaps is an array (and validate contract if later code uses
it), and if validation fails either throw a clear TypeError (e.g. "route:
invalid report input") or return a standardized error routing object (e.g.
reason 'INVALID_INPUT'); update references to report.status and report.gaps in
the method to rely on these validated values.
In @.claude/CLAUDE.md:
- Around line 186-194: Add a blank line before the markdown table that starts
with "| Módulo | Path | Função |" under the "### Módulos técnicos" header so the
table renders correctly; locate the "### Módulos técnicos" header and the
subsequent table rows (and the following block starting with "> **Self-test:**")
and insert a single empty line between the header (or preceding paragraph) and
the table to fix the formatting.
- Around line 158-179: Add a language identifier to each fenced code block that
shows terminal/console output: update the three code fences that start with the
box lines "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" (the Compliance Report
block), the block that begins with "▶ PRÓXIMO PASSO:" (next step block), and the
block that begins with "📍 Posição:" (workflow position block) to use ```text
instead of plain ``` so markdown linters and syntax highlighters treat them as
terminal text.
- Around line 180-185: The doc section "Regras PEP" is inconsistent with
compliance-auditor.js: either update the docs or change the code; to fix, decide
which behavior is intended and apply one of two fixes: (A) If keeping code, edit
the .claude/CLAUDE.md rules to state "Se aderência < 60% → ALERTAR" and change
"Se veto condition disparada → registrar veto (vetoTriggered) sem HALT" to match
current behavior; (B) If enforcing doc rules, update compliance-auditor.js so
the adherence threshold used where PARTIAL status is set (the logic that
currently uses 60%) becomes 70%, and modify triggerVeto() so it not only appends
to vetoTriggered but also invokes the existing abort/stop mechanism (e.g., call
the process halt function used elsewhere) to immediately halt execution; ensure
you update or add tests covering the new threshold and immediate halt behavior.
---
Nitpick comments:
In @.aiox-core/core/execution/compliance-auditor.js:
- Around line 283-298: Currently loops over contract.qualityGates and treats a
missing gateResult as a failure (increments report.gatesFailed and, for blocking
gates, adds a failed gap with impact 'Gate não verificado'); change this to
distinguish "unchecked" from "failed" by checking gateResult === undefined
separately in the loop (use the existing variables contract.qualityGates,
gateResult, report.gatesPassed/gatesFailed/gaps) and either (a) add a new
counter like report.gatesUnchecked and push a gap with status 'unchecked' and
impact 'Gate não verificado' for blocking gates, or (b) only increment
report.gatesFailed when gateResult exists and passed === false while treating
undefined as unchecked (document via the gap/status); implement one of these
paths so unchecked gates are not silently counted as failures.
In @.aiox-core/core/execution/next-step-router.js:
- Around line 178-179: The require('js-yaml') call should be moved out of the
findPosition function and hoisted to module scope to avoid repeated module
resolution; create a top-level variable (e.g., let yaml) and use the same
try/catch fallback pattern used elsewhere, then update findPosition to use that
module-scoped yaml variable (or return null if it's not available) so the
require only runs once and the function body stays tidy.
In @.aiox-core/core/execution/POST-EXECUTION-PROTOCOL.md:
- Around line 27-47: The fenced code block examples in
POST-EXECUTION-PROTOCOL.md are missing a language specifier and trigger
markdownlint; update each triple-backtick block (the compliance report example)
to use a plain-text specifier (e.g., ```text or ```plaintext) so terminal output
remains readable and the linter passes; ensure all similar fenced blocks in the
file are changed consistently.
In @.aiox-core/core/execution/self-test.js:
- Around line 92-103: The test creates a perfect ExecutionResult but never
asserts the compliance score; add an assertion after computing perfectReport to
verify 100% compliance (e.g., check perfectReport.score or
perfectReport.getCompliancePercentage() equals 100 or perfectReport.isPerfect()
depending on available API). Locate the block that builds perfectResult (uses
ExecutionResult.markPhase, markGate, and complete) and insert a single assertion
against perfectReport (the result of ComplianceAuditor.audit) to ensure the
audit yields exactly 100% adherence.
- Around line 1-107: The self-test currently only prints results; add
programmatic assertions and proper exit codes so CI can fail on regressions:
after each logical step assert expected values (e.g., for Test 2 assert result
phases/gates statuses and for Test 3 assert ComplianceAuditor.audit(contract,
result) returns expected flags/violations, for Test 4 assert
NextStepRouter.route(...) yields the expected nextStep, for Test 5 assert
BlindSpotDetector.analyze(reports) contains the expected metrics, and for Test 6
assert perfectReport shows full compliance), wrap the entire run in try/catch
and call process.exit(0) on success or process.exit(1) on any assertion failure
or thrown error; use the existing symbols ExecutionContract, ExecutionResult,
ComplianceAuditor.audit, NextStepRouter.route, BlindSpotDetector.analyze and
their .toTerminal outputs only for human-readable logs while failing
programmatically on mismatches.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4d8fcd11-75ea-4ee4-bfa6-1e8890f6918f
📒 Files selected for processing (6)
.aiox-core/core/execution/POST-EXECUTION-PROTOCOL.md.aiox-core/core/execution/compliance-auditor.js.aiox-core/core/execution/execution-contract.js.aiox-core/core/execution/next-step-router.js.aiox-core/core/execution/self-test.js.claude/CLAUDE.md
| static audit(contract, result) { | ||
| const report = new ComplianceReport(contract.command, contract.squad); |
There was a problem hiding this comment.
Add input validation for audit method.
The audit method accesses properties on contract and result without validation. This is a public API entry point that should guard against invalid inputs.
As per coding guidelines: "Check for proper input validation on public API methods."
🛡️ Proposed fix
static audit(contract, result) {
+ if (!contract) {
+ throw new Error('audit() requires a valid ExecutionContract');
+ }
+ if (!result) {
+ throw new Error('audit() requires a valid ExecutionResult');
+ }
const report = new ComplianceReport(contract.command, contract.squad);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| static audit(contract, result) { | |
| const report = new ComplianceReport(contract.command, contract.squad); | |
| static audit(contract, result) { | |
| if (!contract) { | |
| throw new Error('audit() requires a valid ExecutionContract'); | |
| } | |
| if (!result) { | |
| throw new Error('audit() requires a valid ExecutionResult'); | |
| } | |
| const report = new ComplianceReport(contract.command, contract.squad); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/execution/compliance-auditor.js around lines 250 - 251, The
static audit method currently assumes valid inputs; add input validation at the
start of ComplianceAuditor.audit to ensure `contract` is a non-null object with
required properties (`command` and `squad`, both non-empty strings) and that
`result` is a non-null object (or whatever shape your code expects), and throw a
clear TypeError (or return an error value consistent with the project) if checks
fail; update the method before creating a new ComplianceReport(contract.command,
contract.squad) so you avoid accessing undefined properties and make any
downstream code (that uses `result`) guarded as well.
| static postMortem(contract, observations = {}) { | ||
| const result = new ExecutionResult(contract.source); | ||
|
|
||
| const observedPhases = observations.phases_observed || []; | ||
| const observedOutputs = observations.outputs_found || []; | ||
|
|
||
| // Marcar fases baseado nas observações | ||
| for (const phase of contract.phases) { | ||
| const phaseName = phase.name.toLowerCase(); | ||
| const wasObserved = observedPhases.some(op => | ||
| op.toLowerCase().includes(phaseName) || phaseName.includes(op.toLowerCase()) | ||
| ); | ||
|
|
||
| if (wasObserved) { | ||
| result.markPhase(phase.id, 'done'); | ||
| } else { | ||
| result.markPhase(phase.id, 'skipped'); | ||
| } | ||
| } | ||
|
|
||
| // Marcar outputs | ||
| for (const output of observedOutputs) { | ||
| result.addOutput(path.basename(output), output); | ||
| } | ||
|
|
||
| result.complete(); | ||
| return ComplianceAuditor.audit(contract, result); | ||
| } |
There was a problem hiding this comment.
Add input validation to postMortem method.
The postMortem method should validate that contract is provided before proceeding.
🛡️ Proposed fix
static postMortem(contract, observations = {}) {
+ if (!contract) {
+ throw new Error('postMortem() requires a valid ExecutionContract');
+ }
const result = new ExecutionResult(contract.source);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| static postMortem(contract, observations = {}) { | |
| const result = new ExecutionResult(contract.source); | |
| const observedPhases = observations.phases_observed || []; | |
| const observedOutputs = observations.outputs_found || []; | |
| // Marcar fases baseado nas observações | |
| for (const phase of contract.phases) { | |
| const phaseName = phase.name.toLowerCase(); | |
| const wasObserved = observedPhases.some(op => | |
| op.toLowerCase().includes(phaseName) || phaseName.includes(op.toLowerCase()) | |
| ); | |
| if (wasObserved) { | |
| result.markPhase(phase.id, 'done'); | |
| } else { | |
| result.markPhase(phase.id, 'skipped'); | |
| } | |
| } | |
| // Marcar outputs | |
| for (const output of observedOutputs) { | |
| result.addOutput(path.basename(output), output); | |
| } | |
| result.complete(); | |
| return ComplianceAuditor.audit(contract, result); | |
| } | |
| static postMortem(contract, observations = {}) { | |
| if (!contract) { | |
| throw new Error('postMortem() requires a valid ExecutionContract'); | |
| } | |
| const result = new ExecutionResult(contract.source); | |
| const observedPhases = observations.phases_observed || []; | |
| const observedOutputs = observations.outputs_found || []; | |
| // Marcar fases baseado nas observações | |
| for (const phase of contract.phases) { | |
| const phaseName = phase.name.toLowerCase(); | |
| const wasObserved = observedPhases.some(op => | |
| op.toLowerCase().includes(phaseName) || phaseName.includes(op.toLowerCase()) | |
| ); | |
| if (wasObserved) { | |
| result.markPhase(phase.id, 'done'); | |
| } else { | |
| result.markPhase(phase.id, 'skipped'); | |
| } | |
| } | |
| // Marcar outputs | |
| for (const output of observedOutputs) { | |
| result.addOutput(path.basename(output), output); | |
| } | |
| result.complete(); | |
| return ComplianceAuditor.audit(contract, result); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/execution/compliance-auditor.js around lines 341 - 368, The
postMortem static method should validate its input before using it: at the start
of ComplianceAuditor.postMortem(check for contract) verify that contract is
non-null/undefined and has the expected shape (e.g., contract.source and
contract.phases as an array); if validation fails, throw a clear TypeError
(e.g., "contract is required") or return an appropriate error value, and guard
downstream usage of contract.phases and contract.source (used to construct
ExecutionResult and iterate phases) so you don't dereference properties of an
undefined contract.
| static fromYaml(content) { | ||
| const data = yaml ? yaml.load(content) : JSON.parse(content); | ||
| const ec = data.execution_contract || data; | ||
| const contract = new ExecutionContract(ec.source); | ||
| Object.assign(contract, { | ||
| command: ec.command || '', | ||
| squad: ec.squad || '', | ||
| phases: ec.phases || [], | ||
| qualityGates: ec.quality_gates || [], | ||
| vetoConditions: ec.veto_conditions || [], | ||
| nextStep: ec.next_step || null, | ||
| handoffs: ec.handoffs || [], | ||
| expectedOutputs: ec.expected_outputs || [], | ||
| checklists: ec.checklists || [], | ||
| estimatedTime: ec.estimated_time || null, | ||
| createdAt: ec.created_at || new Date().toISOString(), | ||
| }); | ||
| return contract; | ||
| } |
There was a problem hiding this comment.
Add input validation to fromYaml static method.
The fromYaml method doesn't validate that content is a non-empty string before attempting to parse it.
🛡️ Proposed fix
static fromYaml(content) {
+ if (!content || typeof content !== 'string') {
+ throw new Error('fromYaml requires a non-empty string');
+ }
const data = yaml ? yaml.load(content) : JSON.parse(content);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/execution/execution-contract.js around lines 82 - 100, The
fromYaml static method (ExecutionContract.fromYaml) must validate the input
before parsing: ensure the incoming content parameter is a non-empty string (not
undefined, null, or only whitespace) and throw a clear TypeError if invalid;
then proceed to parse using the existing yaml ? yaml.load(content) :
JSON.parse(content) logic. Add this guard at the start of fromYaml, referencing
the content parameter and keeping existing behavior for yaml/JSON parsing and
subsequent object mapping to ExecutionContract.
| static fromTask(taskPath) { | ||
| const content = fs.readFileSync(taskPath, 'utf8'); |
There was a problem hiding this comment.
Add error handling for file read operations.
The fromTask method reads files synchronously without a try/catch wrapper. If the file doesn't exist or is unreadable, this will throw an unhandled exception with limited context.
As per coding guidelines for .aiox-core/core/**: "Verify error handling is comprehensive with proper try/catch and error context."
🛡️ Proposed fix
static fromTask(taskPath) {
+ if (!taskPath || typeof taskPath !== 'string') {
+ throw new Error('fromTask requires a valid file path string');
+ }
+ if (!fs.existsSync(taskPath)) {
+ throw new Error(`Task file not found: ${taskPath}`);
+ }
+ let content;
+ try {
+ content = fs.readFileSync(taskPath, 'utf8');
+ } catch (err) {
+ throw new Error(`Failed to read task file "${taskPath}": ${err.message}`);
+ }
- const content = fs.readFileSync(taskPath, 'utf8');
const contract = new ExecutionContract(taskPath);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| static fromTask(taskPath) { | |
| const content = fs.readFileSync(taskPath, 'utf8'); | |
| static fromTask(taskPath) { | |
| if (!taskPath || typeof taskPath !== 'string') { | |
| throw new Error('fromTask requires a valid file path string'); | |
| } | |
| if (!fs.existsSync(taskPath)) { | |
| throw new Error(`Task file not found: ${taskPath}`); | |
| } | |
| let content; | |
| try { | |
| content = fs.readFileSync(taskPath, 'utf8'); | |
| } catch (err) { | |
| throw new Error(`Failed to read task file "${taskPath}": ${err.message}`); | |
| } | |
| const contract = new ExecutionContract(taskPath); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/execution/execution-contract.js around lines 116 - 117, The
fromTask method calls fs.readFileSync(taskPath, 'utf8') without error handling;
wrap the file read in a try/catch inside the static fromTask(taskPath) method,
catch filesystem errors (ENOENT, EACCES, etc.), and rethrow or throw a new Error
with contextual information including taskPath and the original error message;
ensure the catch returns/propagates a clear, descriptive error so callers of
ExecutionContract.fromTask can distinguish file-read failures from other parsing
errors.
| if (yamlMatch && yaml) { | ||
| try { taskDef = yaml.load(yamlMatch[1]) || {}; } catch { /* ignore */ } | ||
| } |
There was a problem hiding this comment.
Avoid silently swallowing YAML parsing errors.
The empty catch block hides parsing failures, making debugging difficult when task definitions contain malformed YAML.
🔧 Proposed fix to log parse errors
if (yamlMatch && yaml) {
- try { taskDef = yaml.load(yamlMatch[1]) || {}; } catch { /* ignore */ }
+ try {
+ taskDef = yaml.load(yamlMatch[1]) || {};
+ } catch (err) {
+ console.warn(`Warning: Failed to parse YAML frontmatter in ${taskPath}: ${err.message}`);
+ }
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/execution/execution-contract.js around lines 123 - 125, The
YAML parse error is being swallowed in the empty catch, so modify the try/catch
around yaml.load(yamlMatch[1]) (the block that assigns taskDef) to catch the
error as e and log a clear message containing the offending YAML snippet
(yamlMatch[1]) and the error (e) instead of ignoring it; ensure taskDef fallback
remains (e.g., {} ) after logging so behavior is unchanged but parsing failures
are visible for debugging.
| static route(contract, report) { | ||
|
|
||
| // Regra 1: Se report FAIL e há gaps críticos → sugere corrigir gaps | ||
| if (report.status === 'FAIL' && report.gaps.length > 0) { | ||
| const criticalGap = report.gaps[0]; | ||
| return { | ||
| command: null, | ||
| agent: null, | ||
| context: `Corrigir gap: "${criticalGap.phase}"`, | ||
| reason: 'COMPLIANCE_FAIL', | ||
| urgency: 'HIGH', | ||
| suggestion: `Re-executar com foco em: ${criticalGap.phase}`, | ||
| }; | ||
| } |
There was a problem hiding this comment.
Add input validation for route method.
The route method accesses properties on contract and report without validating they exist. Null/undefined inputs will cause runtime errors.
As per coding guidelines: "Check for proper input validation on public API methods."
🛡️ Proposed fix
static route(contract, report) {
+ if (!contract || !report) {
+ throw new Error('route() requires both contract and report parameters');
+ }
// Regra 1: Se report FAIL e há gaps críticos → sugere corrigir gaps
- if (report.status === 'FAIL' && report.gaps.length > 0) {
+ if (report.status === 'FAIL' && report.gaps?.length > 0) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| static route(contract, report) { | |
| // Regra 1: Se report FAIL e há gaps críticos → sugere corrigir gaps | |
| if (report.status === 'FAIL' && report.gaps.length > 0) { | |
| const criticalGap = report.gaps[0]; | |
| return { | |
| command: null, | |
| agent: null, | |
| context: `Corrigir gap: "${criticalGap.phase}"`, | |
| reason: 'COMPLIANCE_FAIL', | |
| urgency: 'HIGH', | |
| suggestion: `Re-executar com foco em: ${criticalGap.phase}`, | |
| }; | |
| } | |
| static route(contract, report) { | |
| if (!contract || !report) { | |
| throw new Error('route() requires both contract and report parameters'); | |
| } | |
| // Regra 1: Se report FAIL e há gaps críticos → sugere corrigir gaps | |
| if (report.status === 'FAIL' && report.gaps?.length > 0) { | |
| const criticalGap = report.gaps[0]; | |
| return { | |
| command: null, | |
| agent: null, | |
| context: `Corrigir gap: "${criticalGap.phase}"`, | |
| reason: 'COMPLIANCE_FAIL', | |
| urgency: 'HIGH', | |
| suggestion: `Re-executar com foco em: ${criticalGap.phase}`, | |
| }; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/execution/next-step-router.js around lines 43 - 56, The
static method route(contract, report) currently assumes contract and report
exist and that report.status and report.gaps are present; add input validation
at the start of route to guard against null/undefined or malformed inputs by
checking that report is an object, report.status is a string, and report.gaps is
an array (and validate contract if later code uses it), and if validation fails
either throw a clear TypeError (e.g. "route: invalid report input") or return a
standardized error routing object (e.g. reason 'INVALID_INPUT'); update
references to report.status and report.gaps in the method to rely on these
validated values.
| // Regra 3: Se tem handoffs condicionais → avaliar | ||
| if (contract.handoffs.length > 0) { | ||
| // Por padrão, pegar o primeiro handoff aplicável | ||
| const handoff = contract.handoffs[0]; | ||
| return { | ||
| command: null, | ||
| agent: handoff.to, | ||
| context: handoff.context, | ||
| reason: 'HANDOFF_CONDITIONAL', | ||
| urgency: 'NORMAL', | ||
| suggestion: `Ativar agente: ${handoff.to} — ${handoff.when}`, | ||
| }; | ||
| } |
There was a problem hiding this comment.
Handoff evaluation doesn't check conditions.
The comment says "Se tem handoffs condicionais → avaliar", but the code simply takes the first handoff without evaluating the when condition against the actual report state.
💡 Suggestion
Consider implementing actual condition evaluation, or update the comment to reflect current behavior:
// Regra 3: Se tem handoffs condicionais → avaliar
if (contract.handoffs.length > 0) {
- // Por padrão, pegar o primeiro handoff aplicável
+ // TODO: Evaluate handoff.when conditions against report
+ // Currently defaults to first handoff
const handoff = contract.handoffs[0];📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Regra 3: Se tem handoffs condicionais → avaliar | |
| if (contract.handoffs.length > 0) { | |
| // Por padrão, pegar o primeiro handoff aplicável | |
| const handoff = contract.handoffs[0]; | |
| return { | |
| command: null, | |
| agent: handoff.to, | |
| context: handoff.context, | |
| reason: 'HANDOFF_CONDITIONAL', | |
| urgency: 'NORMAL', | |
| suggestion: `Ativar agente: ${handoff.to} — ${handoff.when}`, | |
| }; | |
| } | |
| // Regra 3: Se tem handoffs condicionais → avaliar | |
| if (contract.handoffs.length > 0) { | |
| // TODO: Evaluate handoff.when conditions against report | |
| // Currently defaults to first handoff | |
| const handoff = contract.handoffs[0]; | |
| return { | |
| command: null, | |
| agent: handoff.to, | |
| context: handoff.context, | |
| reason: 'HANDOFF_CONDITIONAL', | |
| urgency: 'NORMAL', | |
| suggestion: `Ativar agente: ${handoff.to} — ${handoff.when}`, | |
| }; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/core/execution/next-step-router.js around lines 68 - 80, The code
currently picks the first entry from contract.handoffs without evaluating its
condition; update the logic in the next-step-router to iterate contract.handoffs
and evaluate each handoff.when against the current report/state, selecting the
first handoff whose when condition passes (use or add a small evaluator function
like evaluateCondition(state, expression) to test handoff.when), then return the
same object populated with handoff.to, handoff.context, reason
'HANDOFF_CONDITIONAL', urgency and suggestion using handoff.to and handoff.when;
if no handoff.when matches, fall back to the previous behavior or return null as
appropriate.
| ``` | ||
| ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
| 📊 Compliance Report: {comando} | ||
| ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
| Aderência: {X}% ({N}/{total} completos) | ||
| ❌ GAPS: {fases puladas ou parciais} | ||
| ✅ QUALITY GATES: {gates passados} | ||
| ``` | ||
|
|
||
| **2. Próximo Passo** — Sempre mostrar o que vem depois: | ||
| ``` | ||
| ▶ PRÓXIMO PASSO: | ||
| Comando: {próximo comando} | ||
| Contexto: {motivo} | ||
| ``` | ||
|
|
||
| **3. Posição no Workflow** — Se faz parte de um workflow maior: | ||
| ``` | ||
| 📍 Posição: {workflow} — Fase {N}/{total} | ||
| → Próxima fase: {nome} | ||
| ``` | ||
|
|
There was a problem hiding this comment.
Add language identifiers to fenced code blocks.
The example code blocks are missing language specifications, which triggers markdown linting warnings and reduces clarity for syntax highlighters.
📝 Proposed fix to add language identifiers
**1. Compliance Report** — Comparar steps executados vs definidos na task/workflow:
-```
+```text
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 Compliance Report: {comando}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━Apply similar changes to lines 168 and 175, using text as the language identifier for terminal output examples.
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 158-158: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 168-168: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
[warning] 175-175: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.claude/CLAUDE.md around lines 158 - 179, Add a language identifier to each
fenced code block that shows terminal/console output: update the three code
fences that start with the box lines "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
(the Compliance Report block), the block that begins with "▶ PRÓXIMO PASSO:"
(next step block), and the block that begins with "📍 Posição:" (workflow
position block) to use ```text instead of plain ``` so markdown linters and
syntax highlighters treat them as terminal text.
| ### Regras PEP | ||
| - **NUNCA** terminar execução sem Compliance Report | ||
| - **NUNCA** omitir o Próximo Passo | ||
| - Se aderência < 70% → ALERTAR antes de prosseguir | ||
| - Se veto condition disparada → HALT imediato | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify adherence threshold and veto handling in compliance-auditor.js
echo "=== Adherence threshold check ==="
rg -n -A2 -B2 "adherenceScore\s*>=\s*\d+" .aiox-core/core/execution/compliance-auditor.js
echo -e "\n=== Veto handling check ==="
rg -n -A5 "triggerVeto" .aiox-core/core/execution/compliance-auditor.jsRepository: SynkraAI/aiox-core
Length of output: 913
Reconcile documented and implemented PEP rules in documentation.
The PEP rules documented in lines 180-185 do not match the implementation in compliance-auditor.js:
-
Adherence threshold (Line 183): Documentation specifies "Se aderência < 70% → ALERTAR" but the implementation uses 60% as the threshold for PARTIAL status (line 312).
-
Veto handling (Line 184): Documentation specifies "Se veto condition disparada → HALT imediato" but
triggerVeto()only appends to thevetoTriggeredarray without halting execution.
Update the documentation to reflect the actual implementation, or adjust the code to match the intended 70% threshold and halt behavior.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.claude/CLAUDE.md around lines 180 - 185, The doc section "Regras PEP" is
inconsistent with compliance-auditor.js: either update the docs or change the
code; to fix, decide which behavior is intended and apply one of two fixes: (A)
If keeping code, edit the .claude/CLAUDE.md rules to state "Se aderência < 60% →
ALERTAR" and change "Se veto condition disparada → registrar veto
(vetoTriggered) sem HALT" to match current behavior; (B) If enforcing doc rules,
update compliance-auditor.js so the adherence threshold used where PARTIAL
status is set (the logic that currently uses 60%) becomes 70%, and modify
triggerVeto() so it not only appends to vetoTriggered but also invokes the
existing abort/stop mechanism (e.g., call the process halt function used
elsewhere) to immediately halt execution; ensure you update or add tests
covering the new threshold and immediate halt behavior.
| ### Módulos técnicos | ||
| | Módulo | Path | Função | | ||
| |--------|------|--------| | ||
| | ExecutionContract | `core/execution/execution-contract.js` | Extrai contrato de task/workflow | | ||
| | ComplianceAuditor | `core/execution/compliance-auditor.js` | Audita execução + Blind Spot Detection | | ||
| | NextStepRouter | `core/execution/next-step-router.js` | Roteia próximo passo | | ||
|
|
||
| > **Self-test:** `node .aiox-core/core/execution/self-test.js` | ||
|
|
There was a problem hiding this comment.
Add blank line before table for proper markdown formatting.
The technical modules table is missing a blank line before it, which violates markdown best practices.
📝 Proposed fix to add blank line
### Módulos técnicos
+
| Módulo | Path | Função |
|--------|------|--------|📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ### Módulos técnicos | |
| | Módulo | Path | Função | | |
| |--------|------|--------| | |
| | ExecutionContract | `core/execution/execution-contract.js` | Extrai contrato de task/workflow | | |
| | ComplianceAuditor | `core/execution/compliance-auditor.js` | Audita execução + Blind Spot Detection | | |
| | NextStepRouter | `core/execution/next-step-router.js` | Roteia próximo passo | | |
| > **Self-test:** `node .aiox-core/core/execution/self-test.js` | |
| ### Módulos técnicos | |
| | Módulo | Path | Função | | |
| |--------|------|--------| | |
| | ExecutionContract | `core/execution/execution-contract.js` | Extrai contrato de task/workflow | | |
| | ComplianceAuditor | `core/execution/compliance-auditor.js` | Audita execução + Blind Spot Detection | | |
| | NextStepRouter | `core/execution/next-step-router.js` | Roteia próximo passo | | |
| > **Self-test:** `node .aiox-core/core/execution/self-test.js` |
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 187-187: Tables should be surrounded by blank lines
(MD058, blanks-around-tables)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.claude/CLAUDE.md around lines 186 - 194, Add a blank line before the
markdown table that starts with "| Módulo | Path | Função |" under the "###
Módulos técnicos" header so the table renders correctly; locate the "### Módulos
técnicos" header and the subsequent table rows (and the following block starting
with "> **Self-test:**") and insert a single empty line between the header (or
preceding paragraph) and the table to fix the formatting.
|
Módulo robusto e bem pensado. O Post-Execution Protocol preenche um gap real — agents que executam sem verificar compliance é um problema recorrente. Observações:
Ótima adição ao core. O compliance automático vai elevar a qualidade de execução dos agents significativamente. |
Summary
Componentes
execution-contract.jscompliance-auditor.jscompliance-auditor.jsnext-step-router.jsnext-step-router.jsExemplo de output
Test plan
node .aiox-core/core/execution/self-test.js🤖 Generated with Claude Code
Summary by CodeRabbit