Skip to content

Pipeline Plan 242

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

Plan: Fix Misleading "jq not available" Warning (#242)

Root Cause Analysis

Evidence Gathered

File: scripts/sw-loop.sh:561-608_extract_text_from_json() function

The execution path when Claude outputs a JSON object ({...}) instead of an array ([...]):

  1. Line 579 — Case 2 checks first_char == "["false (it's {). The entire jq extraction block is skipped, even though jq is available.
  2. Line 599 — Case 3 catches first_char == "{" and unconditionally prints "JSON output but jq not available". This is misleading because jq was never tried — the condition above only checked for arrays.

Root Cause Hypothesis (ranked)

  1. Most likely (confirmed): Case 2 only handles JSON arrays ([). When Claude's --output-format json outputs an object ({...}), the code falls through to Case 3 which prints a misleading "jq not available" warning regardless of whether jq is installed.
  2. Less likely: Claude always outputs arrays and the { case never fires. Disproved — the issue reporter observed this in practice.
  3. Unlikely: jq is actually unavailable. Disproved — the warning text itself is the problem, not jq availability.

Alternatives Considered

Option A: Extend Case 2 to handle both JSON arrays and objects (CHOSEN)

  • Pros: Actually parses the JSON object and extracts .result, providing the correct text output. Fixes both the misleading warning AND extracts useful content.
  • Cons: Slightly more code, but the logic is straightforward.
  • Blast radius: Minimal — only changes the _extract_text_from_json function. The fallback behavior (Case 3) still exists for the rare case where jq is truly unavailable.
  • Complexity: Low — adds one elif branch with a parallel jq extraction for objects.

Option B: Just fix the warning message in Case 3

  • Pros: Smallest possible change (1-2 lines).
  • Cons: Doesn't actually parse the JSON object — still uses raw output even when jq could extract .result. Fixes the symptom but not the underlying limitation.
  • Blast radius: Trivial.

Decision: Option A

Option A is the right fix because it's still a small change (10-15 lines) and it actually solves the problem properly — extracting .result from JSON objects the same way we extract from arrays. The warning fix in Case 3 comes along as part of the change.

Risk Analysis

Risk Impact Mitigation
New jq extraction path breaks on unexpected JSON shapes Low — 2>/dev/null and `
Change affects JSON array handling None — array path (Case 2) is unchanged Only adding a new elif for objects
Test suite expectations break Low — existing tests only cover arrays and plain text Add new test for JSON object input
Bash 3.2 incompatibility None — using only if/elif, [[, and pipes No new syntax

Files to Modify

  1. scripts/sw-loop.sh — Fix _extract_text_from_json() to handle JSON objects
  2. scripts/sw-loop-test.sh — Add test case for JSON object extraction

Implementation Steps

Step 1: Modify _extract_text_from_json() in sw-loop.sh (lines 578-603)

Restructure Cases 2 and 3 to:

  • Case 2a: JSON array ([) with jq → extract .[-1].result (unchanged)
  • Case 2b: JSON object ({) with jq → extract .result directly
  • Case 3: JSON but no jq → accurate warning message
# Case 2: Valid JSON — extract .result with jq
if [[ "$first_char" == "[" ]] && command -v jq >/dev/null 2>&1; then
    # ... existing array extraction (unchanged) ...

elif [[ "$first_char" == "{" ]] && command -v jq >/dev/null 2>&1; then
    local extracted
    extracted=$(jq -r '.result // empty' "$json_file" 2>/dev/null) || true
    if [[ -n "$extracted" ]]; then
        echo "$extracted" > "$log_file"
        return 0
    fi
    # Try .content fallback for objects too
    extracted=$(jq -r '.content // empty' "$json_file" 2>/dev/null) || true
    if [[ -n "$extracted" ]]; then
        echo "$extracted" > "$log_file"
        return 0
    fi
    warn "JSON object output has no .result field — check $json_file"
    echo "(no text result in JSON output)" > "$log_file"
    return 0
fi

# Case 3: Looks like JSON but no jq — can't parse, use raw
if [[ "$first_char" == "[" || "$first_char" == "{" ]]; then
    warn "JSON output but jq not available — using raw output"
    cp "$json_file" "$log_file"
    return 0
fi

Key: Case 3's warning is now accurate — it only fires when jq is genuinely unavailable (both Case 2 branches check command -v jq first).

Step 2: Add test case in sw-loop-test.sh

Add a new test in the "json extraction robustness" section (after Test 19, around line 299) that tests JSON object input:

# Test: JSON object → extracts .result
echo '{"type":"result","subtype":"success","result":"Object extraction works"}' > '$tmpdir/obj.json'
_extract_text_from_json '$tmpdir/obj.json' '$tmpdir/out_obj.log' ''

Then assert grep -q "Object extraction works" "$tmpdir/out_obj.log".

Step 3: Run affected test suite

./scripts/sw-loop-test.sh

Task Checklist

  • Task 1: Read and understand the current _extract_text_from_json function (lines 561-608)
  • Task 2: Add elif branch for JSON objects ({) with jq extraction in sw-loop.sh
  • Task 3: Verify Case 3 warning now only fires when jq is genuinely unavailable
  • Task 4: Add test case for JSON object extraction in sw-loop-test.sh
  • Task 5: Run sw-loop-test.sh and verify all tests pass
  • Task 6: Manually verify the fix handles edge cases (empty .result, missing .result)

Task dependencies: Task 1 → Task 2 → Task 3 (sequential). Task 4 depends on Task 2. Task 5 depends on Tasks 2-4. Task 6 depends on Task 5.

Testing Approach

  1. Existing tests — Run sw-loop-test.sh to ensure no regressions in array extraction, empty file handling, plain text pass-through, nested JSON, and binary input.
  2. New test — JSON object with .result field → verify extraction works.
  3. Edge cases covered by existing fallbacks:
    • JSON object without .result → warning + placeholder (same behavior as array without .result)
    • No jq available → accurate "jq not available" warning + raw output
    • Non-JSON input → pass-through (unchanged Case 4)

Definition of Done

  • _extract_text_from_json correctly extracts .result from JSON objects ({...})
  • _extract_text_from_json still correctly extracts .result from JSON arrays ([...])
  • The misleading "jq not available" warning no longer fires when jq IS available
  • The "jq not available" warning still fires when jq is genuinely not installed
  • New test case for JSON object extraction passes
  • All existing sw-loop-test.sh tests pass
  • No Bash 3.2 incompatibilities introduced

Verification Plan

  1. Run ./scripts/sw-loop-test.sh — all tests pass including the new JSON object test
  2. Confirm the warning text change: grep for the old misleading message to ensure it's gone from the jq-available path
  3. Confirm Case 3 only fires when command -v jq fails (structural code review)

Endpoint Specification

Not applicable — this is a bash function fix, not an API change.

Error Codes

Not applicable — no API endpoints.

Rate Limiting

Not applicable.

Versioning

Not applicable — internal function change, no public API.

Clone this wiki locally