Skip to content

fix(dashboard): fail closed on remote state reads #868

fix(dashboard): fail closed on remote state reads

fix(dashboard): fail closed on remote state reads #868

Workflow file for this run

name: Bun Parity
# Verifies bash-vs-bun byte-for-byte parity for the commands ported in
# Phase 2/3 of the bash->Bun migration (ADR-001). Codifies the parity
# invariant that has been hand-checked since v7.3.0.
#
# For every command in the matrix below this job:
# 1. Captures stdout from the Bun route (bin/loki <cmd>)
# 2. Captures stdout from the bash route (LOKI_LEGACY_BASH=1 bin/loki <cmd>)
# 3. For --json variants: jq -S sort then diff
# For text variants: direct diff
# 4. Fails the job if ANY command differs.
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
bun-parity:
name: bun-parity on ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.13
- name: Setup Python (for bash route fallthroughs)
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install jq (Linux)
if: runner.os == 'Linux'
run: |
if ! command -v jq >/dev/null 2>&1; then
sudo apt-get update
sudo apt-get install -y jq
fi
jq --version
- name: Install jq (macOS)
if: runner.os == 'macOS'
run: |
if ! command -v jq >/dev/null 2>&1; then
brew install jq
fi
jq --version
- name: Build loki-ts (Bun)
working-directory: loki-ts
run: |
bun install
bun run build
- name: Verify both routes are invokable
run: |
test -x bin/loki || { echo "FATAL: bin/loki missing or not executable"; exit 1; }
test -x autonomy/loki || { echo "FATAL: autonomy/loki missing or not executable"; exit 1; }
test -f loki-ts/dist/loki.js || { echo "FATAL: loki-ts/dist/loki.js missing after build"; exit 1; }
- name: Run parity matrix
id: parity
shell: bash
run: |
set -uo pipefail
# Command matrix. JSON variants get jq -S normalization; text
# variants get straight diff.
# Format: "<label>|<args>|<mode:text|json>"
MATRIX=(
"version|--version|text"
"provider-show|provider show|text"
"provider-list|provider list|text"
"memory-list|memory list|text"
"status|status|text"
"status-json|status --json|json"
"stats|stats|text"
"stats-json|stats --json|json"
# v7.4.10: re-enabled doctor text parity now that v7.4.9
# added Bun probe to bash cmd_doctor and confirmed both routes
# print Disk space + Summary + missing-prereq trailer.
"doctor|doctor|text"
"doctor-json|doctor --json|json"
)
mkdir -p /tmp/parity
FAILED=()
PASSED=()
for entry in "${MATRIX[@]}"; do
label="${entry%%|*}"
rest="${entry#*|}"
args="${rest%%|*}"
mode="${rest##*|}"
bun_out="/tmp/parity/${label}.bun"
bash_out="/tmp/parity/${label}.bash"
diff_out="/tmp/parity/${label}.diff"
# Capture both routes. Do not let a non-zero exit kill the job
# before we can diff -- record exit codes separately.
set +e
bin/loki $args >"$bun_out" 2>/dev/null
bun_ec=$?
LOKI_LEGACY_BASH=1 bin/loki $args >"$bash_out" 2>/dev/null
bash_ec=$?
set -e
if [ "$mode" = "json" ]; then
# Sort keys recursively before diffing so key-order changes
# do not register as parity violations.
# v7.4.12 also floors disk.available_gb because Python
# json.dumps emits 58.0 while JS JSON.stringify emits 58 --
# plus the underlying df read can drift by 1GB between two
# near-simultaneous calls on a busy CI runner.
JQ_NORM='if .disk?.available_gb? != null then .disk.available_gb = (.disk.available_gb | floor) else . end'
if ! jq -S "$JQ_NORM" "$bun_out" >"${bun_out}.sorted" 2>/dev/null; then
echo "FAIL [$label]: bun output is not valid JSON"
FAILED+=("$label (invalid bun JSON)")
continue
fi
if ! jq -S "$JQ_NORM" "$bash_out" >"${bash_out}.sorted" 2>/dev/null; then
echo "FAIL [$label]: bash output is not valid JSON"
FAILED+=("$label (invalid bash JSON)")
continue
fi
if diff -u "${bash_out}.sorted" "${bun_out}.sorted" >"$diff_out"; then
PASSED+=("$label")
else
echo "FAIL [$label]: JSON parity diff (bash exit=$bash_ec, bun exit=$bun_ec):"
cat "$diff_out"
FAILED+=("$label")
fi
else
# v7.4.12+ -- before diff, normalize jittery numeric values
# that drift between two near-simultaneous reads on busy CI:
# - Disk space: 88GB available -> Disk space: NGB available
# bash + Bun read `df` independently a few ms apart; on a CI
# runner where logs are being written, the value can drift by
# 1GB between the two reads and trigger a false parity fail.
# v7.5.6 (council R3 #1, 5-runs-red): mirror the
# scripts/local-ci.sh normalization that was added in
# v7.5.1 + v7.5.5 but never ported here:
# - strip the "Runtime route:" block (route-dependent;
# reports "Bash" on the bash route and "Bun" on Bun)
# - strip the "Phase 1 artifacts:" block (#204)
# Without these, doctor parity failed every release since
# v7.5.1 -- the local-only normalization masked it on
# developer Macs while CI was red.
#
# The summary "N passed/N failed/N warnings" COUNTS are
# intentionally KEPT (not blanked), matching parity-drift.yml.
# A real divergence that shifts a doctor check between
# pass/fail/warn between routes MUST surface as a parity
# failure here -- this is the exact class of bug that broke
# v7.58.0 (doctor crash off-TTY). The Runtime-route block drop
# already removes the one benign count-shifter (the
# LOKI_LEGACY_BASH-only WARN line), so counts match for
# genuinely-equivalent runs.
for src in "$bash_out" "$bun_out"; do
sed -E 's/Disk space: [0-9]+GB/Disk space: NGB/g' "$src" \
| sed -E '/Runtime route:/,/^$/d' \
| sed -E '/Phase 1 artifacts:/,/^$/d' \
| sed -E '/Cockpit:/,/^$/d' \
> "${src}.norm"
done
# COMMON-MODE FAILURE GUARD. Parity is a diff, and two routes that
# break IDENTICALLY diff clean. bun_ec/bash_ec were captured but
# never asserted, and stderr is discarded, so a command that exits
# 127 with empty stdout on BOTH routes was recorded as PASS and the
# job printed "All commands parity-verified". Both routes share the
# bin/loki shim, so a shim-level break is exactly the common-mode
# case this would wave through.
#
# Identical output is only evidence of parity when the commands
# actually RAN. The json branch is already protected -- an empty or
# invalid capture fails `jq -S` and lands in FAILED -- so this guard
# is the text branch's equivalent, not a duplicate.
#
# Deliberately narrow: only a matching-nonzero-exit-AND-empty-output
# pair fails here. A command that legitimately exits nonzero while
# still printing (a doctor run with blockers) keeps working, which
# is why the emptiness half of the condition is load-bearing.
if [ "$bun_ec" -ne 0 ] && [ "$bash_ec" -ne 0 ] \
&& [ ! -s "${bash_out}.norm" ] && [ ! -s "${bun_out}.norm" ]; then
echo "FAIL [$label]: BOTH routes failed identically (bash exit=$bash_ec, bun exit=$bun_ec) with no output -- identical breakage is not parity"
FAILED+=("$label (common-mode failure, exit $bash_ec/$bun_ec)")
continue
fi
if diff -u "${bash_out}.norm" "${bun_out}.norm" >"$diff_out"; then
PASSED+=("$label")
else
echo "FAIL [$label]: text parity diff (bash exit=$bash_ec, bun exit=$bun_ec):"
cat "$diff_out"
FAILED+=("$label")
fi
fi
done
echo ""
echo "================================================================"
echo "Bun Parity Summary"
echo "================================================================"
printf '%-20s %s\n' "COMMAND" "RESULT"
printf '%-20s %s\n' "-------" "------"
# bash 3.2 on macos triggers `unbound variable` under `set -u` when
# iterating an empty array, so guard with the :- expansion.
for p in "${PASSED[@]:-}"; do
[ -z "$p" ] && continue
printf '%-20s %s\n' "$p" "PASS"
done
for f in "${FAILED[@]:-}"; do
[ -z "$f" ] && continue
printf '%-20s %s\n' "$f" "FAIL"
done
echo "================================================================"
echo "Passed: ${#PASSED[@]} Failed: ${#FAILED[@]} Total: ${#MATRIX[@]}"
echo "================================================================"
if [ "${#FAILED[@]}" -gt 0 ]; then
echo "Bun parity check FAILED for ${#FAILED[@]} command(s)."
exit 1
fi
echo "All commands parity-verified."