{"record":{"id":"508a14ad38632346","repo":"ruvnet/ruflo","slug":"worker-policy-denied-decision-reason-unknow","errorCode":null,"errorMessage":"worker policy denied: ${decision.reason ?? 'unknown reason'}","messagePattern":"worker policy denied: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/codex/src/dual-mode/orchestrator.ts","lineNumber":543,"sourceCode":"        type: 'swarm.worker.spawn',\n        resource: worker.worktreePath ?? this.config.projectPath,\n        tool: worker.platform,\n        concurrency: 1,\n        network: false,\n        destructive: false,\n      },\n      context: {\n        metadata: { childCapabilityEnvelope: envelope },\n      },\n    };\n    const raw = await this.runCommand(\n      'npx',\n      ['ruflo@latest', 'policy', 'evaluate', JSON.stringify(request)],\n      this.config.projectPath,\n    );\n    const decision = JSON.parse(raw) as { enforcedOutcome?: string; reason?: string };\n    if (decision.enforcedOutcome !== 'allowed') {\n      throw new Error(`worker policy denied: ${decision.reason ?? 'unknown reason'}`);\n    }\n    worker.capabilityEnvelope = envelope;\n  }\n\n  private defaultWorkerEnvelope(worker: WorkerConfig): WorkerCapabilityEnvelope {\n    return {\n      actions: ['*'],\n      resources: ['*'],\n      tools: ['*'],\n      maxConcurrency: 1,\n      network: false,\n      destructive: false,\n      delegationDepth: 0,\n      expiresAt: Date.now() + this.config.timeout,\n    };\n  }\n\n  private resolveWorkerEnvelope(worker: WorkerConfig): WorkerCapabilityEnvelope {","sourceCodeStart":525,"sourceCodeEnd":561,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/codex/src/dual-mode/orchestrator.ts#L525-L561","documentation":"Before spawning each worker, authorizeWorker shells out to `npx ruflo@latest policy evaluate` with the worker's identity, a swarm.worker.spawn action over its worktree/project path, and its capability envelope. The policy engine returns a decision object; any outcome other than enforcedOutcome === 'allowed' aborts the spawn with this error, including the engine's reason when present. Note this error specifically means the engine answered with a non-allowed decision — a missing ruflo binary or non-JSON output fails differently (command failure or JSON.parse error).","triggerScenarios":"A Ruflo policy in enforce mode denies swarm.worker.spawn for the worker's role, resource path, or platform; the requested capability envelope exceeds what policy grants to the principal; or the engine emits a deny/observe outcome with no reason field (message then shows 'unknown reason').","commonSituations":"Running a swarm in a repo whose policy config protects the paths the worker writes to; a session principal (CLAUDE_FLOW_PRINCIPAL_ID) not covered by any allow rule; upgrading ruflo so previously-tolerated actions now require explicit grants.","solutions":["Read the reason embedded in the message — it comes straight from the policy decision and usually names the failing rule or capability","Run `npx ruflo policy status` and `npx ruflo policy verify` in the project to inspect the active mode and rule set","Shrink the worker's capabilityEnvelope (no network/destructive, fewer actions/tools) or point the worker at a resource path the policy grants for its role","If the denial is correct, keep the policy and cancel dependent sibling work instead of trying to bypass the decision point"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"import { spawnSync } from 'node:child_process';\nfunction previewPolicyDecision(projectPath: string, request: object): { enforcedOutcome?: string; reason?: string } | null {\n  const res = spawnSync('npx', ['ruflo@latest', 'policy', 'evaluate', JSON.stringify(request)],\n    { cwd: projectPath, encoding: 'utf8' });\n  if (res.status !== 0) return null;\n  try { return JSON.parse(res.stdout); } catch { return null; }\n}","typeGuard":null,"tryCatchPattern":"try { await orchestrator.run(...); } catch (error) { if (error instanceof Error && error.message.startsWith('worker policy denied')) { const reason = error.message.slice('worker policy denied: '.length); /* cancel dependent siblings, surface reason to user */ } throw error; } — never catch-and-continue past a policy denial.","preventionTips":["Run `npx ruflo policy status` before starting a swarm in policy-governed repos","Keep worker envelopes minimal so the spawn action stays inside policy grants","Treat 'worker policy denied' as an authorization signal: cancel dependent work, do not retry the same request"],"tags":["policy","authorization","ruflo","orchestration","worker-spawn"],"backgroundTag":"authorization-policy-denied","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}