Files
a46f28a63e fix(cli): keep doctor --json stdout clean — v123 migration handler printed to stdout (#3019)
The v123 configurable-FTS migration (#2941) logged its completion notice
via console.log. Migrations run lazily inside any command's first DB
connect, so on the nightly heavy run (fresh Postgres service DB) the
line landed as the first line of `gbrain doctor --json` stdout and broke
the fm_wallclock jq parse ("Invalid numeric literal at line 1, column 7",
run 29731426470). runMigrations' contract routes all migration noise to
stderr; move the v123 prints (and the pre-existing v2 slug-rename print)
there.

Also un-vacuous the fm_wallclock harness: its register-source step used
`bun run -e` (bun dumps usage with exit 0 instead of running the code)
and `connect({})` (in-memory), so the source was never registered and
doctor scanned nothing. It now resolves the engine the way the CLI does
and registers the source in the DB doctor actually reads.

Regression test: test/migrate-stdout-clean.test.ts re-runs migrations
from v122 asserting zero stdout writes, plus a source-level guard that
migrate.ts contains no console.log.

Co-authored-by: Garry Tan <garrytan@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 10:33:27 -07:00
..

tests/heavy/

Heavy ops-shape tests. Shell scripts that exercise gbrain end-to-end against real infrastructure (Postgres, large fixtures, concurrent processes). Cost minutes per run; NOT in default bun test.

When to add a script here

Put a test here if it:

  • Costs more than ~30s wallclock per run
  • Needs real Postgres (not PGLite in-memory)
  • Spins up multiple processes or measures concurrency
  • Measures system metrics (RSS, latency under load, lock contention)
  • Tests an upgrade / migration matrix against committed historical states

When to use *.slow.test.ts instead

Put a slow test in test/ with the .slow.test.ts suffix if it:

  • Runs under bun test (TypeScript, uses bun:test imports)
  • Is correctness-shaped, not ops-shaped (asserts behavior of one function)
  • Can stub external dependencies

The two patterns coexist intentionally. *.slow.test.ts is per-file correctness for cold paths; tests/heavy/ is ops-shape scripts that don't fit bun's test runner.

How to run

# Run every script in this directory, sequentially:
bun run test:heavy

# Run a single script:
tests/heavy/<script>.sh

The runner is scripts/run-heavy.sh. It discovers every tests/heavy/*.sh file at this directory's top level (NOT recursive), runs them in lexical order, fails on the first non-zero exit.

Naming convention

  • tests/heavy/<name>.sh — top-level test script, picked up by the runner.
  • tests/heavy/_<name>.sh — library/helper invoked by a sibling test. The leading underscore tells the runner to SKIP this file. Use this pattern for fixture builders, shared setup, anything that needs a required argument or isn't standalone-runnable.
  • tests/heavy/fixtures/<name> — committed input data (SQL, JSON, etc).

CI scheduling

Heavy tests run nightly at 08:17 UTC via .github/workflows/heavy-tests.yml, and on PRs labeled heavy-tests. They are NOT part of the default PR CI matrix — that gate stays fast.

Failure output convention

Each script writes a per-run log to ~/.gbrain/audit/heavy-<script>-<ts>.log containing subprocess stdout/stderr, environment state, and any captured metrics. The CI workflow uploads these as artifacts on failure for triage without re-running locally.

Style

  • #!/usr/bin/env bash
  • set -euo pipefail
  • Explicit array argv for execs (no eval, no unquoted globs)
  • Print a one-line [<script>] <action> log per major step
  • Exit non-zero on any failure path; print enough context to diagnose
  • Honor $GBRAIN_HOME / $TMP_ROOT env overrides where relevant

See scripts/check-jsonb-pattern.sh and scripts/run-slow-tests.sh for the in-tree style reference.