Skip to content

Pipeline Plan 4

Seth Ford edited this page Feb 12, 2026 · 2 revisions

Now I have all the context I need. Let me write the implementation plan.

Implementation Plan: Add --json flag to shipwright status

Files to Modify

File Action Purpose
scripts/sw-status.sh Modify Add --json flag parsing, refactor data collection into functions, emit JSON or human-readable output
scripts/sw-status-test.sh Create Test suite for status command with JSON and human-readable output
scripts/sw Modify Update help text for status command to mention --json
package.json Modify Register new test suite in npm test script

Implementation Steps

1. Restructure sw-status.sh to separate data collection from rendering

The current script interleaves data-gathering (tmux queries, JSON reads, curl calls) with echo statements. The plan is to:

  • Add argument parsing at the top (--json flag, --help)
  • Wrap each section's data collection into functions that populate variables
  • Gate all echo output behind an if [[ "$JSON_OUTPUT" != "true" ]] check
  • At the end, if --json, build a single JSON object with jq -n and output it

2. Add argument parsing block (after the compat.sh source, before the Header)

JSON_OUTPUT=false
while [[ $# -gt 0 ]]; do
    case "$1" in
        --json)  JSON_OUTPUT=true; shift ;;
        --help|-h|help) show_help; exit 0 ;;
        *)       shift ;;
    esac
done

3. Refactor into data-collection functions

Create these functions that populate result variables without printing:

  • collect_tmux_windows → populates WINDOWS_JSON (array of {name, session_window, pane_count, active})
  • collect_team_configs → populates TEAMS_JSON (array of {name, members, member_names})
  • collect_task_lists → populates TASKS_JSON (array of {team, total, completed, in_progress, pending, pct})
  • collect_daemon_pipelines → populates DAEMON_JSON (object with running, pid, uptime_s, active_jobs[], queued[], completed[], recent_activity[])
  • collect_issue_tracker → populates TRACKER_JSON (object with provider, url)
  • collect_heartbeats → populates HEARTBEATS_JSON (array of {job_id, pid, alive, stage, issue, iteration, activity, updated_at, age_s, memory_mb})
  • collect_remote_machines → populates MACHINES_JSON (array of {name, host, cores, memory_gb, max_workers})
  • collect_connected_developers → populates DEVELOPERS_JSON (object with reachable, dashboard_url, total_online, developers[])

4. Human-readable rendering functions

Move existing echo-based rendering into render_* functions that are only called when JSON_OUTPUT is false. This preserves 100% of current output behavior.

5. JSON output assembly

When JSON_OUTPUT is true, assemble all collected data into a single JSON object:

if [[ "$JSON_OUTPUT" == "true" ]]; then
    jq -n \
        --argjson tmux_windows "$WINDOWS_JSON" \
        --argjson teams "$TEAMS_JSON" \
        --argjson tasks "$TASKS_JSON" \
        --argjson daemon "$DAEMON_JSON" \
        --argjson tracker "$TRACKER_JSON" \
        --argjson heartbeats "$HEARTBEATS_JSON" \
        --argjson machines "$MACHINES_JSON" \
        --argjson developers "$DEVELOPERS_JSON" \
        --arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
        --arg version "$VERSION" \
        '{
            version: $version,
            timestamp: $timestamp,
            tmux_windows: $tmux_windows,
            teams: $teams,
            tasks: $tasks,
            daemon: $daemon,
            tracker: $tracker,
            heartbeats: $heartbeats,
            remote_machines: $machines,
            connected_developers: $developers
        }'
    exit 0
fi

6. Update CLI router help text in scripts/sw

Change line 70:

  ${CYAN}status${RESET} [--json]        Show dashboard of running teams and agents

7. Create test suite scripts/sw-status-test.sh

Following the existing test harness pattern (mock environment, PASS/FAIL counters, ERR trap):

  • Mock tmux, jq, curl, kill binaries
  • Create fixture data (daemon-state.json, team configs, task files, heartbeat files, machines.json)
  • Test cases:
    • --json produces valid JSON
    • JSON contains all expected top-level keys
    • Human-readable output (no --json) contains expected section headers
    • Empty state (no teams, no daemon) produces empty arrays in JSON
    • Active daemon with jobs renders correctly in JSON
    • Heartbeat data appears in JSON output
    • --help shows usage

8. Register test suite in package.json

Add && bash scripts/sw-status-test.sh to the npm test script.

Task Checklist

  • Task 1: Add argument parsing for --json and --help flags to sw-status.sh
  • Task 2: Refactor tmux windows section into collect_tmux_windows + render_tmux_windows
  • Task 3: Refactor team configs section into collect_team_configs + render_team_configs
  • Task 4: Refactor task lists section into collect_task_lists + render_task_lists
  • Task 5: Refactor daemon pipelines section into collect_daemon + render_daemon
  • Task 6: Refactor issue tracker section into collect_tracker + render_tracker
  • Task 7: Refactor heartbeats section into collect_heartbeats + render_heartbeats
  • Task 8: Refactor remote machines section into collect_machines + render_machines
  • Task 9: Refactor connected developers section into collect_developers + render_developers
  • Task 10: Add JSON assembly and output when --json flag is set
  • Task 11: Update CLI help text in scripts/sw for the status subcommand
  • Task 12: Create sw-status-test.sh test suite with mock environment
  • Task 13: Register sw-status-test.sh in package.json test script
  • Task 14: Run test suite and verify all tests pass

Testing Approach

  1. Unit tests (sw-status-test.sh): Mock tmux, curl, kill, create fixture JSON files under a temp directory, override HOME and DAEMON_DIR to point at fixtures. Validate:

    • --json output parses as valid JSON via jq empty
    • All top-level keys present: version, timestamp, tmux_windows, teams, tasks, daemon, tracker, heartbeats, remote_machines, connected_developers
    • Correct counts (e.g., 2 tmux windows → JSON array length 2)
    • Empty state → empty arrays, not missing keys
    • Human-readable output contains expected section headers (TMUX WINDOWS, TEAM CONFIGS, etc.)
  2. Manual verification: Run shipwright status (no flag) to confirm existing output is unchanged. Run shipwright status --json and pipe through jq . to verify valid, well-structured JSON.

  3. Integration: Run shipwright status --json | jq .tmux_windows to verify subsections are independently queryable.

Definition of Done

  • shipwright status produces identical output to current (no regression)
  • shipwright status --json outputs valid JSON to stdout with zero ANSI escape codes
  • JSON schema includes all 8 dashboard sections as top-level keys
  • Empty state (no daemon, no teams, etc.) produces [] / {} — not errors
  • shipwright status --help shows usage with --json documented
  • sw CLI help mentions --json for the status command
  • Test suite sw-status-test.sh passes with all tests green
  • Test suite registered in package.json
  • Bash 3.2 compatible (no associative arrays, no readarray, no ${var,,})
  • set -euo pipefail maintained throughout
  • Pattern matches existing --json implementations (sw-cost.sh, sw-fleet.sh, sw-pipeline-vitals.sh)

Clone this wiki locally