Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Pipeline Design 242

Seth Ford edited this page Mar 10, 2026 · 5 revisions

Good — I've confirmed the full code flow. Here's the ADR.


Design: Misleading "jq not available" warning when Claude outputs JSON object instead of array

Context

The _extract_text_from_json() function in scripts/sw-loop.sh:561-608 extracts plain text from Claude's --output-format json output. It handles four cases:

  1. Empty/missing file — write placeholder
  2. JSON array ([) with jq available — extract .[-1].result
  3. JSON-like ([ or {) without jq — copy raw, warn "jq not available"
  4. Plain text — copy as-is

The bug: Case 2 (line 579) only checks first_char == "[", so JSON objects ({...}) skip Case 2 entirely and fall into Case 3 (line 599). Case 3 then prints warn "JSON output but jq not available" — even though jq IS available. It was never tried.

This is purely cosmetic (the raw JSON is copied and the loop continues), but the misleading warning confuses operators and could mask real jq availability issues.

Constraint: Claude's --output-format json can produce either a JSON array (multiple conversation turns) or a single JSON object (e.g., {"type":"result","result":"..."}). The function must handle both.

Systematic Debugging: Root Cause Verification

Root Cause Hypothesis (ranked):

  1. (Confirmed, 99%) Case 2 condition first_char == "[" excludes objects — control falls through to Case 3 which prints wrong warning
  2. (Ruled out) jq is actually missing — command -v jq would fail, but the warning fires even when jq is present
  3. (Ruled out) Claude changed output format — irrelevant; the code was always wrong for objects

Evidence Gathered:

  • sw-loop.sh:579: if [[ "$first_char" == "[" ]] && command -v jq — confirmed array-only gate
  • sw-loop.sh:599-602: if [[ "$first_char" == "[" || "$first_char" == "{" ]] — catches objects, prints wrong message
  • sw-loop.sh:1883: caller invokes claude -p "$PROMPT" $CLAUDE_FLAGS > "$JSON_FILE" — output format depends on Claude's response
  • No existing test covers JSON object input to _extract_text_from_json

Decision

Extend Case 2 to handle both [ and { first characters. Branch internally on array vs object for jq queries:

  • Array ([): .[-1].result // empty then .[].content // empty (existing behavior)
  • Object ({): .result // empty then .content // empty (new)

Case 3 becomes a true "jq not available" fallback — only reachable when command -v jq fails.

This is the minimal fix: one condition change ("[""[" || "$first_char" == "{") plus internal branching. No new functions, no architectural changes, no new dependencies.

Alternatives Considered

  1. Separate Case for objects (new Case 2b) — Pros: no nesting, each case is self-contained / Cons: duplicates jq parsing logic (.result, .content, placeholder) across two cases; harder to maintain; violates DRY for no benefit. Rejected.

  2. Normalize objects to arrays before parsing — Wrap {...} in [...] via jq '[.]', then use the existing array logic unchanged. Pros: no branching inside Case 2 / Cons: unnecessary extra jq invocation; creates a temp file or pipe; fragile if the input is large; over-engineered for a two-branch condition. Rejected.

  3. Just fix the warning message — Change Case 3's message from "jq not available" to "JSON format not fully supported". Pros: one-line fix / Cons: doesn't actually extract .result from objects, so operators lose useful output; treats the symptom not the cause. Rejected.

Implementation Plan

  • Files to create: None
  • Files to modify:
    • scripts/sw-loop.sh — Lines 578-603: extend Case 2 condition and add array/object branching
    • scripts/sw-loop-test.sh — After line 368 (Test 21): add two test cases for JSON object handling
  • Dependencies: None (jq is already a dependency)
  • Risk areas:
    • jq query correctness for objects: .result // empty on a bare object is valid jq. No risk.
    • Unexpected JSON structures: Objects without .result or .content already hit the placeholder path — no change in behavior.
    • Bash 3.2 compatibility: The fix uses only [[ ]], ||, and variable expansion — all Bash 3.2 safe.

Validation Criteria

  • _extract_text_from_json extracts .result from {"type":"result","result":"..."} into log_file
  • _extract_text_from_json extracts .content from {"content":"..."} when .result is absent
  • "jq not available" warning is NOT emitted when jq IS installed and input is a JSON object
  • "jq not available" warning IS still emitted when jq is genuinely missing (Case 3 still works)
  • Existing array extraction tests (Test 20-21 in sw-loop-test.sh) pass unchanged
  • Full sw-loop-test.sh suite passes with zero regressions
  • All code is Bash 3.2 compatible (no associative arrays, no readarray, no ${var,,})

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /