-
Notifications
You must be signed in to change notification settings - Fork 1
Pipeline Design 242
Good — I've confirmed the full code flow. Here's the ADR.
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:
- Empty/missing file — write placeholder
-
JSON array (
[) with jq available — extract.[-1].result -
JSON-like (
[or{) without jq — copy raw, warn "jq not available" - 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.
Root Cause Hypothesis (ranked):
-
(Confirmed, 99%) Case 2 condition
first_char == "["excludes objects — control falls through to Case 3 which prints wrong warning -
(Ruled out) jq is actually missing —
command -v jqwould fail, but the warning fires even when jq is present - (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 invokesclaude -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
Extend Case 2 to handle both [ and { first characters. Branch internally on array vs object for jq queries:
-
Array (
[):.[-1].result // emptythen.[].content // empty(existing behavior) -
Object (
{):.result // emptythen.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.
-
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. -
Normalize objects to arrays before parsing — Wrap
{...}in[...]viajq '[.]', 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. -
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
.resultfrom objects, so operators lose useful output; treats the symptom not the cause. Rejected.
- 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 // emptyon a bare object is valid jq. No risk. -
Unexpected JSON structures: Objects without
.resultor.contentalready hit the placeholder path — no change in behavior. -
Bash 3.2 compatibility: The fix uses only
[[ ]],||, and variable expansion — all Bash 3.2 safe.
-
jq query correctness for objects:
-
_extract_text_from_jsonextracts.resultfrom{"type":"result","result":"..."}intolog_file -
_extract_text_from_jsonextracts.contentfrom{"content":"..."}when.resultis 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.shsuite passes with zero regressions - All code is Bash 3.2 compatible (no associative arrays, no
readarray, no${var,,})