ruvnet/ruflo · error

AIDefenceGate not attached. Call attachGuidance({ aiDefenceG

Error message

AIDefenceGate not attached. Call attachGuidance({ aiDefenceGate }) first.

What it means

Thrown by RuvBotGuidanceBridge.evaluateAIDefence(input) when no AIDefenceGate has been provided via attachGuidance({ aiDefenceGate }). The bridge wires ruvbot events independently of guidance attachment, so a manual defence evaluation explicitly verifies the gate exists before delegating to evaluateInput() and toGateResult(). It indicates incomplete bridge setup.

Source

Thrown at v3/@claude-flow/guidance/src/ruvbot-integration.ts:716

   */
  disconnect(): void {
    if (!this.ruvbot) return;

    for (const [event, handler] of this.boundHandlers) {
      this.ruvbot.off(event, handler);
    }

    this.boundHandlers.clear();
    this.ruvbot = null;
  }

  /**
   * Evaluate a ruvbot AIDefence result and return a GateResult-compatible
   * decision. Can be called independently of event wiring.
   */
  async evaluateAIDefence(input: string): Promise<GateResult> {
    if (!this.aiDefenceGate) {
      throw new Error(
        'AIDefenceGate not attached. Call attachGuidance({ aiDefenceGate }) first.',
      );
    }

    const result = await this.aiDefenceGate.evaluateInput(input);
    return this.aiDefenceGate.toGateResult(result, 'manual-evaluation');
  }

  /**
   * Get the proof chain for a specific session.
   */
  getSessionProofChain(sessionId: string): import('./proof.js').ProofChain | undefined {
    return this.sessionChains.get(sessionId);
  }

  /**
   * Get all active session IDs.
   */

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Call bridge.attachGuidance({ aiDefenceGate: gate }) once during setup, before any evaluateAIDefence() call
  2. If attachGuidance is optional in your flow, guard evaluation behind a check that guidance was attached
  3. After calling detach() (which nulls references), do not reuse the bridge for evaluation — create and re-attach a fresh bridge

Example fix

// before
const bridge = new RuvBotGuidanceBridge(ruvbot, config);
await bridge.evaluateAIDefence(userInput); // throws: gate not attached

// after
const bridge = new RuvBotGuidanceBridge(ruvbot, config);
bridge.attachGuidance({ aiDefenceGate });
await bridge.evaluateAIDefence(userInput);
Defensive patterns

Strategy: validation

Validate before calling

// Single setup path: attach guidance before exposing the bridge
function createBridge(ruvbot: RuvBot, gate: AIDefenceGate, config: RuvBotBridgeConfig) {
  const bridge = new RuvBotGuidanceBridge(ruvbot, config);
  bridge.attachGuidance({ aiDefenceGate: gate });
  return bridge;
}

Type guard

// aiDefenceGate is private; track it in your own wrapper
type EvaluableBridge = { evaluateAIDefence(i: string): Promise<GateResult> };
const evaluatable = new WeakSet<object>();
function isEvaluatable(b: object): b is EvaluableBridge {
  return evaluatable.has(b);
}
// after bridge.attachGuidance({ aiDefenceGate }): evaluatable.add(bridge);

Try / catch

try {
  const result = await bridge.evaluateAIDefence(input);
} catch (e) {
  if (e instanceof Error && e.message.includes('attachGuidance')) {
    // configuration gap — fail loudly, do not retry
    throw new Error('AIDefenceGate missing on bridge; attachGuidance was skipped', { cause: e });
  }
  throw e;
}

Prevention

When it happens

Trigger: Creating a RuvBotGuidanceBridge around a ruvbot instance (optionally with event wiring) and calling await bridge.evaluateAIDefence(text) before calling bridge.attachGuidance({ aiDefenceGate: gate }), or calling attachGuidance with an object that omits aiDefenceGate.

Common situations: Using the bridge purely for event translation and adding manual input screening later; setup code where attachGuidance is conditional (only when a gate was configured) but evaluateAIDefence is called unconditionally; partial init during application shutdown/re-initialization where detach() has set the gate reference to null.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/c6bd8c87e6480039. Report an issue: GitHub.