-
Notifications
You must be signed in to change notification settings - Fork 1
Pipeline Plan 242
-
Case 2 only handles JSON arrays, not objects (99% confidence) — The
_extract_text_from_jsonfunction atscripts/sw-loop.sh:579checksfirst_char == "["before attempting jq parsing. When Claude outputs a JSON object ({...}), this condition is false, so jq is never tried. Control falls through to Case 3 (line 599), which catches both[and{and unconditionally prints "jq not available" — even though jq was never attempted for objects. -
Claude
--output-format jsonchanged output format — Claude's JSON output mode may now sometimes emit a single JSON object instead of an array. The original code was written assuming arrays only. -
Warning message is simply wrong — Even if we don't want to parse objects, the message should distinguish "jq not available" from "unexpected JSON format".
-
File:line:
scripts/sw-loop.sh:579-603 -
Case 2 (line 579):
if [[ "$first_char" == "[" ]] && command -v jq >/dev/null 2>&1— only enters jq parsing for arrays -
Case 3 (line 599):
if [[ "$first_char" == "[" || "$first_char" == "{" ]]— catches objects BUT prints misleading "jq not available" warning - Impact: Cosmetic only — the raw JSON is copied to the log file and the loop continues correctly
- No previous failed attempt — plan.md was empty, this is the first plan
Option A (recommended): Extend Case 2 to handle both JSON arrays and objects with jq. When first_char is {, extract .result // empty directly (no array indexing). This gives proper text extraction for both formats. Case 3 becomes a true "jq not available" fallback.
This is the minimal, targeted fix that:
- Properly extracts
.resultfrom JSON objects (not just arrays) - Keeps the "jq not available" warning accurate (only shown when jq is genuinely missing)
- Maintains backward compatibility for all existing cases
| File | Action | Purpose |
|---|---|---|
scripts/sw-loop.sh |
Modify | Fix _extract_text_from_json() Case 2 to handle JSON objects |
scripts/sw-loop-test.sh |
Modify | Add test for JSON object extraction + misleading warning regression |
Modify lines 578-603 to handle both [ and { first characters when jq is available:
# Case 2: Valid JSON (array or object) — extract .result with jq if [[ "$first_char" == "[" || "$first_char" == "{" ]] && command -v jq >/dev/null 2>&1; then local extracted if [[ "$first_char" == "[" ]]; then extracted=$(jq -r '.[-1].result // empty' "$json_file" 2>/dev/null) || true else extracted=$(jq -r '.result // empty' "$json_file" 2>/dev/null) || true fi if [[ -n "$extracted" ]]; then echo "$extracted" > "$log_file" return 0 fi # jq succeeded but result was null/empty — try .content or raw text if [[ "$first_char" == "[" ]]; then extracted=$(jq -r '.[].content // empty' "$json_file" 2>/dev/null | head -500) || true else extracted=$(jq -r '.content // empty' "$json_file" 2>/dev/null | head -500) || true fi if [[ -n "$extracted" ]]; then echo "$extracted" > "$log_file" return 0 fi # JSON parsed but no text found — write placeholder warn "JSON 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 changes:
- Case 2 condition:
"$first_char" == "["→"$first_char" == "[" || "$first_char" == "{" - Inside Case 2: branch on
first_charto use.[-1].resultfor arrays vs.resultfor objects - Same branching for the
.contentfallback - Case 3 is now only reachable when jq is genuinely not installed
Add two new test cases after the existing Test 21 block (after line 368):
-
JSON object extraction: Verify
_extract_text_from_jsoncorrectly extracts.resultfrom a JSON object{"type":"result","result":"Object extraction works"} - No misleading warning: Verify that when jq IS available and input is a JSON object, the "jq not available" warning is NOT emitted
- Task 1: Modify Case 2 condition in
_extract_text_from_json()to accept both[and{ - Task 2: Add array vs object branching for
.resultextraction inside Case 2 - Task 3: Add array vs object branching for
.contentfallback inside Case 2 - Task 4: Add test: JSON object
.resultextraction works - Task 5: Add test: no misleading "jq not available" warning for JSON objects when jq is present
- Task 6: Run
sw-loop-test.shto verify all tests pass - Task 7: Verify existing tests still pass (no regression)
-
Unit test — JSON object extraction: Create a temp file with
{"type":"result","result":"Object extraction works"}, run_extract_text_from_json, verify output contains "Object extraction works" -
Unit test — warning suppression: Run
_extract_text_from_jsonon a JSON object withwarn()that captures output, verify "jq not available" is NOT in the output -
Regression: Run full
sw-loop-test.sh— all existing tests (15-21) must still pass -
Manual verification: If possible, run a real
shipwright loopiteration that produces JSON object output and confirm no misleading warning
-
_extract_text_from_json()correctly extracts.resultfrom both JSON arrays and JSON objects - "jq not available" warning only appears when jq is genuinely not installed
- New test cases cover JSON object extraction
- All existing
sw-loop-test.shtests pass (no regression) - Code follows Bash 3.2 compatibility requirements
- No unnecessary changes outside the bug scope
# Run the loop test suite ./scripts/sw-loop-test.sh # Verify specific new behavior manually tmpdir=$(mktemp -d) echo '{"type":"result","result":"Object works"}' > "$tmpdir/obj.json" # Extract the function and test it _extract_fn=$(sed -n '/^_extract_text_from_json()/,/^}/p' scripts/sw-loop.sh) bash -c " warn() { echo \"WARN: \$*\" >&2; } $_extract_fn _extract_text_from_json '$tmpdir/obj.json' '$tmpdir/obj_out.log' '' " 2>"$tmpdir/warnings.txt" cat "$tmpdir/obj_out.log" # Should contain "Object works" cat "$tmpdir/warnings.txt" # Should be empty (no misleading warning) rm -rf "$tmpdir"