diff --git a/docs/reports/quality/1099-pipefail-sweep.md b/docs/reports/quality/1099-pipefail-sweep.md index 0519b72b..798356ba 100644 --- a/docs/reports/quality/1099-pipefail-sweep.md +++ b/docs/reports/quality/1099-pipefail-sweep.md @@ -69,4 +69,15 @@ All 22 baseline sites below are `FIXED`; the checked-in tranche fixture is passe | `tmux/test-send-message-socket.sh:37,38,44-46,68,72` | FIXED | capture commands complete before redirected grep assertions | | `tmux/test-send-message-verdict.sh:34` | FIXED | grep reads from a here-string | -Remaining wake-validation sites are intentionally deferred to the final review-sized tranche and are not yet assigned a safety verdict here. +## Tranche 3 — wake validation harnesses + +All 26 baseline occurrences (25 normalized identities; one preimage selector occurs twice) are `FIXED` and mechanically bound through the wake fixture and shared scanner. + +| Baseline site(s) | Verdict | Construction | +| --- | --- | --- | +| `wake/test-wake-digest-quarantine.sh:567` | FIXED | complete match populations are captured, then first line selected by parameter expansion | +| `wake/test-wake-preimage.sh:182-183,346-347` | FIXED | jq `first(...)` reads each JSONL file directly | +| `wake/validate-973/microtest-wake-assert.sh:153,170-171,176,204-209,233-234,251-252,286-287` | FIXED | scalar assertions use here-strings; diagnostics use non-early sed ranges; source line captured before matching | +| `wake/validate-973/validate-973.sh:110,119,180,182,187` | FIXED | scalar assertions use here-strings; diagnostic truncation uses consuming sed ranges | + +The scoped inventory is complete: 26 runtime/general + 22 non-wake tests + 26 wake tests fixed; 11 explicitly withdrawn or non-load-bearing sites retain their documented verdicts. diff --git a/docs/scratchpads/1099-pipefail-sweep.md b/docs/scratchpads/1099-pipefail-sweep.md index 30548805..e8040d77 100644 --- a/docs/scratchpads/1099-pipefail-sweep.md +++ b/docs/scratchpads/1099-pipefail-sweep.md @@ -25,6 +25,10 @@ Site-by-site verdicts: `docs/reports/quality/1099-pipefail-sweep.md`. Expanded the unconditional scanner over 11 non-wake test harnesses. RED named exactly 22 source lines; a second immutable-baseline fixture now asserts those 22 entries through the same scanner. Rewrites preserve command status by capturing producers before redirected assertions, use parameter expansion for line selection, and use complete `mapfile` populations where ordering matters. Current-tree finding count is zero for tranches 1 and 2. +## Tranche 3 TDD + +Expanded the shared scanner over four wake validation harnesses. RED named 26 occurrences. The wake fixture asserts 26 occurrences / 25 normalized identities through the same scanner; all scalar assertions now use redirection, direct jq selection, complete capture, or consuming diagnostic ranges. Current-tree finding count is zero across the full scoped population. + ## Verification so far - `bash -n` on every changed shell script: pass. @@ -33,5 +37,5 @@ Expanded the unconditional scanner over 11 non-wake test harnesses. RED named ex - `test-send-message-verdict.sh`: 3/3 pass. - `test-send-message-socket.sh`: pass. - Independent review 143 found two semantic regressions: a help-probe `|| true` changed the failure truth table, and an unguarded Git capture changed non-Git data-dir behavior from rc 0 + JSON to silent rc 128. Both received RED-first regressions before correction; help status is now separate and required, and Git status remains condition-guarded. -- Wake detector/reconcile/digest/preimage suites terminate at their existing fail-closed #973 `BASH_LINENO` environment probe (exit 97, observed `[3 5]`, expected `[3 4]`) before subject tests. No bypass or skip was used; canonical CI remains required. +- Wake static inventory remains aligned at 261/261 after line-neutral rewrites; no static-set mismatch. Wake detector/reconcile/digest/preimage suites terminate at their existing fail-closed #973 `BASH_LINENO` environment probe (exit 97, observed `[3 5]`, expected `[3 4]`) before subject tests. No bypass or skip was used; canonical CI remains required. - ShellCheck reports only pre-existing source-following, unused-variable, and untouched `ls | head` findings; no new diagnostic was introduced. diff --git a/packages/mosaic/framework/tools/wake/test-wake-digest-quarantine.sh b/packages/mosaic/framework/tools/wake/test-wake-digest-quarantine.sh index a51e0b23..8f9da158 100755 --- a/packages/mosaic/framework/tools/wake/test-wake-digest-quarantine.sh +++ b/packages/mosaic/framework/tools/wake/test-wake-digest-quarantine.sh @@ -564,7 +564,7 @@ echo "== Q16 (guard): Q2's ENUM-B fixture must STAY address-free — the reconci # Token concatenated so THIS guard's own source lines never contain the # literal fixture id and cannot self-match. enum_id='ENUM''-B' - fixture_line="$(has_match -F "\"id\":\"$enum_id\"" "$self" | has_match -F '"observed_seq":5' | head -n1)" + fixture_lines="$(has_match -F "\"id\":\"$enum_id\"" "$self")"; fixture_matches="$(has_match -F '"observed_seq":5' <<<"$fixture_lines")"; fixture_line="${fixture_matches%%$'\n'*}" [ -n "$fixture_line" ] || fail_msg "Q16: could not locate Q2's $enum_id fixture line (renamed/renumbered? update this guard)" fixture_json="$(printf '%s' "$fixture_line" | sed "s/.*'\({.*}\)'.*/\1/")" # Positive controls FIRST (blind-instrument rule): the extraction must yield diff --git a/packages/mosaic/framework/tools/wake/test-wake-preimage.sh b/packages/mosaic/framework/tools/wake/test-wake-preimage.sh index 913d6b05..ba8a021c 100755 --- a/packages/mosaic/framework/tools/wake/test-wake-preimage.sh +++ b/packages/mosaic/framework/tools/wake/test-wake-preimage.sh @@ -179,8 +179,8 @@ echo "== P3: detector orders the cause line BEFORE the delta it explains ==" printf 'r1 state v2\n' >"$fx/repo_r1" "$DET" poll-once >/dev/null 2>&1 || fail_msg "P3: second poll failed" sd="$(state_dir)" - pre_seq="$(jq -r 'select(.locators.kind == "preimage") | .observed_seq' "$sd/pending.jsonl" | head -n1)" - src_seq="$(jq -r 'select(.locators.kind == "repo") | .observed_seq' "$sd/pending.jsonl" | head -n1)" + pre_seq="$(jq -nr 'first(inputs | select(.locators.kind == "preimage") | .observed_seq) // empty' "$sd/pending.jsonl")" + src_seq="$(jq -nr 'first(inputs | select(.locators.kind == "repo") | .observed_seq) // empty' "$sd/pending.jsonl")" [ -n "$pre_seq" ] || fail_msg "P3: no preimage cause entry enqueued" [ -n "$src_seq" ] || fail_msg "P3: no source delta entry enqueued" if [ -n "$pre_seq" ] && [ -n "$src_seq" ]; then @@ -343,8 +343,8 @@ echo "== P11: reconcile surfaces the cause line before its enumerations ==" printf '# adapter changed while detector down\n' >>"$fx/adapter.sh" "$RECON" reconcile >/dev/null 2>&1 # rc 1 expected (unaccounted enumerated) sd="$(state_dir)" - pre_seq="$(jq -r 'select(.locators.kind == "preimage") | .observed_seq' "$sd/pending.jsonl" | head -n1)" - enum_seq="$(jq -r 'select(.locators.reconciled == true) | .observed_seq' "$sd/pending.jsonl" | head -n1)" + pre_seq="$(jq -nr 'first(inputs | select(.locators.kind == "preimage") | .observed_seq) // empty' "$sd/pending.jsonl")" + enum_seq="$(jq -nr 'first(inputs | select(.locators.reconciled == true) | .observed_seq) // empty' "$sd/pending.jsonl")" [ -n "$pre_seq" ] || fail_msg "P11: reconcile must enqueue the preimage cause line" [ -n "$enum_seq" ] || fail_msg "P11: reconcile must still enumerate the unaccounted source" if [ -n "$pre_seq" ] && [ -n "$enum_seq" ]; then diff --git a/packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh b/packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh index bec281ae..c48e817a 100755 --- a/packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh +++ b/packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh @@ -150,7 +150,7 @@ site_line() { # site_line FILE MARKER -> first physical line of that call local f="$1" marker="$2" ln ln="$(grep -n "# SITE:${marker}\$" "$f" | cut -d: -f1)" # continuation marker sits on the tail line; the call starts one line up - if ! sed -n "${ln}p" "$f" | grep -Eq 'has_match|count_lines'; then + source_line="$(sed -n "${ln}p" "$f")"; if ! grep -Eq 'has_match|count_lines' <<<"$source_line"; then ln=$((ln - 1)) fi printf '%s' "$ln" @@ -167,13 +167,13 @@ rcB=$? sort "$LEDGER" >"$TMP/got-c1" n_expected="$(grep -c . "$TMP/expected-c1")" if [ "$rcA" -eq 0 ] && [ "$rcB" -eq 0 ] && - printf '%s' "$outA" | grep -q 'mini-a: OK' && - printf '%s' "$outB" | grep -q 'mini-b: OK' && + grep -q 'mini-a: OK' <<<"$outA"&& + grep -q 'mini-b: OK' <<<"$outB"&& [ "$n_expected" -gt 1 ] && cmp -s "$TMP/expected-c1" "$TMP/got-c1"; then check C1 0 "" else - check C1 1 "rcA=$rcA rcB=$rcB expected($n_expected)/got diff: $(diff "$TMP/expected-c1" "$TMP/got-c1" 2>&1 | head -n 10 | tr '\n' ' ')" + check C1 1 "rcA=$rcA rcB=$rcB expected($n_expected)/got diff: $(diff "$TMP/expected-c1" "$TMP/got-c1" 2>&1 | sed -n '1,10p' | tr '\n' ' ')" fi # --- C2: early exit -> short ledger, comparison catches it ----------------- @@ -201,12 +201,12 @@ abort_case() { # abort_case NAME MARKER HELPER bash "$TMP/mini-a.sh" "$TMP" 2>&1)" rc=$? if [ "$rc" -ne 0 ] && - ! printf '%s' "$out" | grep -q 'mini-a: OK' && - ! printf '%s' "$out" | grep -q 'mini-a: FAILED' && - printf '%s' "$out" | grep -q "WAKE-ASSERT ARMED: forcing real grep error at $site" && - printf '%s' "$out" | grep -q "WAKE-ASSERT ABORT" && - printf '%s' "$out" | grep -q "$site" && - printf '%s' "$out" | grep -q "grep exit 2" && + ! grep -q 'mini-a: OK' <<<"$out"&& + ! grep -q 'mini-a: FAILED' <<<"$out"&& + grep -q "WAKE-ASSERT ARMED: forcing real grep error at $site" <<<"$out"&& + grep -q "WAKE-ASSERT ABORT" <<<"$out"&& + grep -q "$site" <<<"$out"&& + grep -q "grep exit 2" <<<"$out"&& grep -q "^${helper} ${site}\$" "$ledger"; then check "$name" 0 "" else @@ -230,8 +230,8 @@ if [ "$got" = "1" ]; then check C8 0 ""; else check C8 1 "env-prefix did not rea out="$(WAKE_ASSERT_FORCE_GREP_ERROR_AT="mini-a.sh:9999" bash "$TMP/mini-a.sh" "$TMP" 2>&1)" rc=$? if [ "$rc" -eq 0 ] && - printf '%s' "$out" | grep -q 'mini-a: OK' && - ! printf '%s' "$out" | grep -q 'WAKE-ASSERT ARMED'; then + grep -q 'mini-a: OK' <<<"$out"&& + ! grep -q 'WAKE-ASSERT ARMED' <<<"$out"; then check C9 0 "" else check C9 1 "rc=$rc out=$(printf '%s' "$out" | tail -n 3 | tr '\n' ' ')" @@ -248,8 +248,8 @@ chmod +x "$TMP/fake-bash" out="$(WAKE_ASSERT_PIN_BASH="$TMP/fake-bash" bash -c '. "$WAKE_COMMON" && wake_assert_init && echo REACHED-PAST-INIT' 2>&1)" rc=$? if [ "$rc" -ne 0 ] && - ! printf '%s' "$out" | grep -q 'REACHED-PAST-INIT' && - printf '%s' "$out" | grep -q 'WAKE-ASSERT INIT ABORT: BASH_LINENO convention violated'; then + ! grep -q 'REACHED-PAST-INIT' <<<"$out"&& + grep -q 'WAKE-ASSERT INIT ABORT: BASH_LINENO convention violated' <<<"$out"; then check C10 0 "" else check C10 1 "rc=$rc out=$(printf '%s' "$out" | tail -n 2 | tr '\n' ' ')" @@ -283,8 +283,8 @@ out="$(WAKE_ASSERT_LEDGER="$LEDGER" bash "$TMP/mini-c.sh" "$TMP" 2>&1)" rc=$? summary_ln="$(site_line "$TMP/mini-c.sh" c-summary)" if [ "$rc" -eq 1 ] && - printf '%s' "$out" | grep -q 'wake mini-c harness: FAILED (1 assertion(s))' && - ! printf '%s' "$out" | grep -q 'all invariants passed' && + grep -q 'wake mini-c harness: FAILED (1 assertion(s))' <<<"$out"&& + ! grep -q 'all invariants passed' <<<"$out"&& grep -q "^count_lines mini-c.sh:${summary_ln}\$" "$LEDGER"; then check C11 0 "" else diff --git a/packages/mosaic/framework/tools/wake/validate-973/validate-973.sh b/packages/mosaic/framework/tools/wake/validate-973/validate-973.sh index 177f535a..2b38d322 100755 --- a/packages/mosaic/framework/tools/wake/validate-973/validate-973.sh +++ b/packages/mosaic/framework/tools/wake/validate-973/validate-973.sh @@ -107,7 +107,7 @@ if cmp -s "$TMP/expected.txt" "$TMP/static.txt"; then echo "STATIC-INVENTORY equals expected set ($(grep -c . "$TMP/static.txt") rows from source text)" else flag "static inventory (source text) differs from expected set (artifact):" - diff "$TMP/expected.txt" "$TMP/static.txt" | head -n 20 | sed 's/^/ /' + diff "$TMP/expected.txt" "$TMP/static.txt" | sed -n '1,20p' | sed 's/^/ /' fi # --- 3: green instrumented run ---------------------------------------------- @@ -116,7 +116,7 @@ LEDGER="$TMP/ledger" for s in "${SUITES[@]}"; do out="$(WAKE_ASSERT_LEDGER="$LEDGER" bash "$WAKE/$s" 2>&1)" rc=$? - if printf '%s\n' "$out" | grep -Eq "$(sentinel_for "$s")"; then + if grep -Eq "$(sentinel_for "$s")" <<<"$out"; then sent="present" else sent="ABSENT" @@ -177,14 +177,14 @@ while read -r helper site form; do rc=$? bad="" [ "$rc" -ne 0 ] || bad="$bad exit=0" - printf '%s\n' "$out" | grep -q "WAKE-ASSERT ARMED: forcing real grep error at $site" || + grep -q "WAKE-ASSERT ARMED: forcing real grep error at $site" <<<"$out"|| bad="$bad no-ARMED-line" - printf '%s\n' "$out" | grep -q "WAKE-ASSERT ABORT: ${helper} at ${site}: grep exit" || + grep -q "WAKE-ASSERT ABORT: ${helper} at ${site}: grep exit" <<<"$out"|| bad="$bad no-ABORT-line" # AND-polarity check (a match is the defect): a grep error (rc>=2) must be # its own loud arm — it cannot fall through as "no sentinel = pass". rc_sent=0 - printf '%s\n' "$out" | grep -Eq "$(sentinel_for "$f")" || rc_sent=$? + grep -Eq "$(sentinel_for "$f")" <<<"$out"|| rc_sent=$? case "$rc_sent" in 0) bad="$bad sentinel-emitted" ;; 1) : ;; diff --git a/scripts/fixtures/pipefail-early-exit-wake-baseline.json b/scripts/fixtures/pipefail-early-exit-wake-baseline.json new file mode 100644 index 00000000..9f6b2dd5 --- /dev/null +++ b/scripts/fixtures/pipefail-early-exit-wake-baseline.json @@ -0,0 +1,28 @@ +[ + "packages/mosaic/framework/tools/wake/test-wake-digest-quarantine.sh:fixture_line=\"$(has_match -F \"\\\"id\\\":\\\"$enum_id\\\"\" \"$self\" | has_match -F '\"observed_seq\":5' | head -n1)\"", + "packages/mosaic/framework/tools/wake/test-wake-preimage.sh:pre_seq=\"$(jq -r 'select(.locators.kind == \"preimage\") | .observed_seq' \"$sd/pending.jsonl\" | head -n1)\"", + "packages/mosaic/framework/tools/wake/test-wake-preimage.sh:src_seq=\"$(jq -r 'select(.locators.kind == \"repo\") | .observed_seq' \"$sd/pending.jsonl\" | head -n1)\"", + "packages/mosaic/framework/tools/wake/test-wake-preimage.sh:pre_seq=\"$(jq -r 'select(.locators.kind == \"preimage\") | .observed_seq' \"$sd/pending.jsonl\" | head -n1)\"", + "packages/mosaic/framework/tools/wake/test-wake-preimage.sh:enum_seq=\"$(jq -r 'select(.locators.reconciled == true) | .observed_seq' \"$sd/pending.jsonl\" | head -n1)\"", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:if ! sed -n \"${ln}p\" \"$f\" | grep -Eq 'has_match|count_lines'; then", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:printf '%s' \"$outA\" | grep -q 'mini-a: OK' &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:printf '%s' \"$outB\" | grep -q 'mini-b: OK' &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:check C1 1 \"rcA=$rcA rcB=$rcB expected($n_expected)/got diff: $(diff \"$TMP/expected-c1\" \"$TMP/got-c1\" 2>&1 | head -n 10 | tr '\\n' ' ')\"", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:! printf '%s' \"$out\" | grep -q 'mini-a: OK' &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:! printf '%s' \"$out\" | grep -q 'mini-a: FAILED' &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:printf '%s' \"$out\" | grep -q \"WAKE-ASSERT ARMED: forcing real grep error at $site\" &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:printf '%s' \"$out\" | grep -q \"WAKE-ASSERT ABORT\" &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:printf '%s' \"$out\" | grep -q \"$site\" &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:printf '%s' \"$out\" | grep -q \"grep exit 2\" &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:printf '%s' \"$out\" | grep -q 'mini-a: OK' &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:! printf '%s' \"$out\" | grep -q 'WAKE-ASSERT ARMED'; then", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:! printf '%s' \"$out\" | grep -q 'REACHED-PAST-INIT' &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:printf '%s' \"$out\" | grep -q 'WAKE-ASSERT INIT ABORT: BASH_LINENO convention violated'; then", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:printf '%s' \"$out\" | grep -q 'wake mini-c harness: FAILED (1 assertion(s))' &&", + "packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh:! printf '%s' \"$out\" | grep -q 'all invariants passed' &&", + "packages/mosaic/framework/tools/wake/validate-973/validate-973.sh:diff \"$TMP/expected.txt\" \"$TMP/static.txt\" | head -n 20 | sed 's/^/ /'", + "packages/mosaic/framework/tools/wake/validate-973/validate-973.sh:if printf '%s\\n' \"$out\" | grep -Eq \"$(sentinel_for \"$s\")\"; then", + "packages/mosaic/framework/tools/wake/validate-973/validate-973.sh:printf '%s\\n' \"$out\" | grep -q \"WAKE-ASSERT ARMED: forcing real grep error at $site\" ||", + "packages/mosaic/framework/tools/wake/validate-973/validate-973.sh:printf '%s\\n' \"$out\" | grep -q \"WAKE-ASSERT ABORT: ${helper} at ${site}: grep exit\" ||", + "packages/mosaic/framework/tools/wake/validate-973/validate-973.sh:printf '%s\\n' \"$out\" | grep -Eq \"$(sentinel_for \"$f\")\" || rc_sent=$?" +] diff --git a/scripts/pipefail-early-exit.test.mjs b/scripts/pipefail-early-exit.test.mjs index 8de31293..3da7db3d 100644 --- a/scripts/pipefail-early-exit.test.mjs +++ b/scripts/pipefail-early-exit.test.mjs @@ -8,6 +8,7 @@ import test from 'node:test'; const ROOT = new URL('../', import.meta.url); const EXPECTED_BASELINE_SITES = 26; const EXPECTED_TEST_BASELINE_SITES = 22; +const EXPECTED_WAKE_BASELINE_SITES = 26; const TARGETS = [ 'tools/matrix-presence-harness/run.sh', 'tools/e2e-install-test.sh', @@ -37,6 +38,10 @@ const TARGETS = [ 'packages/mosaic/framework/tools/quality/scripts/test-upgrade-rollback.sh', 'packages/mosaic/framework/tools/tmux/test-send-message-socket.sh', 'packages/mosaic/framework/tools/tmux/test-send-message-verdict.sh', + 'packages/mosaic/framework/tools/wake/test-wake-digest-quarantine.sh', + 'packages/mosaic/framework/tools/wake/test-wake-preimage.sh', + 'packages/mosaic/framework/tools/wake/validate-973/microtest-wake-assert.sh', + 'packages/mosaic/framework/tools/wake/validate-973/validate-973.sh', ]; // These statuses are explicitly non-load-bearing or unreachable at designed input. @@ -106,6 +111,14 @@ test('the registered test baseline denominator is exactly 22 unsafe sites', asyn ); }); +test('the registered wake baseline denominator is exactly 26 unsafe sites', async () => { + await assertBaselineFixture( + 'scripts/fixtures/pipefail-early-exit-wake-baseline.json', + EXPECTED_WAKE_BASELINE_SITES, + 25, + ); +}); + test('load-bearing pipefail paths do not pipe into early-exiting consumers', async () => { assert.deepEqual(scan(await currentSources()), []); }); @@ -138,6 +151,40 @@ test('gateway verify capability preserves the complete help-probe truth table', } }); +test('wake JSONL selectors take the first match across the complete input stream', async () => { + const source = await readFile( + new URL('packages/mosaic/framework/tools/wake/test-wake-preimage.sh', ROOT), + 'utf8', + ); + assert.equal((source.match(/jq -nr 'first\(inputs \| select\(/g) ?? []).length, 4); + + const directory = await mkdtemp(path.join(tmpdir(), 'wake-jsonl-first-')); + const input = path.join(directory, 'pending.jsonl'); + const filter = 'first(inputs | select(.locators.kind == "preimage") | .observed_seq) // empty'; + try { + await writeFile( + input, + '{"locators":{"kind":"repo"},"observed_seq":1}\n' + + '{"locators":{"kind":"preimage"},"observed_seq":4}\n' + + '{"locators":{"kind":"preimage"},"observed_seq":9}\n', + ); + let result = spawnSync('jq', ['-nr', filter, input], { encoding: 'utf8' }); + assert.equal(result.status, 0, result.stderr); + assert.equal(result.stdout, '4\n'); + + await writeFile(input, '{"locators":{"kind":"repo"},"observed_seq":1}\n'); + result = spawnSync('jq', ['-nr', filter, input], { encoding: 'utf8' }); + assert.equal(result.status, 0, result.stderr); + assert.equal(result.stdout, ''); + + await writeFile(input, '{invalid json}\n'); + result = spawnSync('jq', ['-nr', filter, input], { encoding: 'utf8' }); + assert.notEqual(result.status, 0); + } finally { + await rm(directory, { recursive: true, force: true }); + } +}); + test('board-history preserves non-git data-dir as a non-detectable result', async () => { const directory = await mkdtemp(path.join(tmpdir(), 'reflect-board-non-git-')); try {