Skip to content

fix(go): fall back to the harness when the .ai() gates are unavailable - #67

Merged
AbirAbbas merged 1 commit into
Agent-Field:mainfrom
vbp1:fix/go-ai-gate-harness-fallback
Aug 8, 2026
Merged

fix(go): fall back to the harness when the .ai() gates are unavailable#67
AbirAbbas merged 1 commit into
Agent-Field:mainfrom
vbp1:fix/go-ai-gate-harness-fallback

Conversation

@vbp1

@vbp1 vbp1 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Problem

intake_phase and coverage_gate in the Go port ask the AI seam for a response_format schema and propagate every failure out of the reasoner. Two real configurations hit this:

  1. A node whose harness is not OpenRouter-backed. node.BuildAgent attaches AIConfig only when OPENROUTER_API_KEY is set (go/internal/node/node.go), so running with, say, PR_AF_PROVIDER=claude-code and no OpenRouter key fails the entire review at the first phase:

    review execution failed: AI not configured for this agent; set AIConfig in agent Config
    
  2. A provider that rejects structured output — the case fix: fall back to harness when .ai() structured output is unsupported #60 fixed on the Python side.

The Python implementation already handles both: harnesses.py wraps each .ai() call in try/except and falls through to the harness (commit 3c8eca9). The Go port does not, so the two implementations diverge on a failure path that takes down the whole pipeline.

Change

Restores parity with harnesses.py, nothing else:

  • intake.go — an unusable AI seam leaves the gate unconfident, so control falls through to the harness classifier already sitting below it (Python's except -> gate_result = None).
  • coverage.go — retries the same coverage prompt through the harness, returning {} when the harness result fails to parse (Python's gate.parsed.model_dump() if gate.parsed else {}).

Behaviour is unchanged whenever the AI seam works: the fallbacks only run on the path that previously raised.

Tests

Two new cases in reasoners_test.go:

  • TestIntakePhaseAIUnavailableFallsBackToHarness — table over a nil AI seam and a seam that rejects structured output; both must invoke the harness exactly once and return the full intake key set.
  • TestCoverageGateAIUnavailableFallsBackToHarness — asserts the harness receives the same coverage prompt, plus the parse-failure path returning {}.

go build ./... && go vet ./... && go test ./... all pass; gofmt clean.

Verification

Ran the full pipeline against a local repo/branch review with PR_AF_PROVIDER=claude-code, PR_AF_MODEL=sonnet and no OPENROUTER_API_KEY:

  • before: fails immediately in intake_phase;
  • after: HTTP 200 in 611s, 22 agent invocations, all phases completed (intakeanatomymeta_*review_dimensionevidence_verifiercompound_finder → synthesis), 7 findings on a diff with 3 planted defects.

Note, out of scope for this PR

Under claude-code the budget accounting stays at zero (total_cost_usd: 0, all per-phase entries 0), because the cost the CLI reports is not the OpenRouter spend PR-AF meters. The USD ceiling is therefore inert for that provider and only the wall-clock cap applies. Worth a separate issue; this PR deliberately does not touch it.

intake_phase and coverage_gate ask the AI seam for a response_format
schema. The Go port propagated every failure out of both, so a node whose
harness is not OpenRouter-backed failed the entire review with "AI not
configured for this agent" (BuildAgent only attaches AIConfig when
OPENROUTER_API_KEY is set), and a provider that rejects structured output
sank it the same way.

Mirror harnesses.py, which wraps both calls: an unusable AI seam leaves the
intake gate unconfident so control falls through to the harness classifier
already sitting below it, and coverage_gate retries the same prompt through
the harness, returning {} when the result fails to parse.

Verified end to end with PR_AF_PROVIDER=claude-code and no OpenRouter key:
the full pipeline completes instead of failing at the first phase.
@CLAassistant

CLAassistant commented Aug 7, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@AbirAbbas
AbirAbbas merged commit 8a8a4c6 into Agent-Field:main Aug 8, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants