Add pre-push hook: compilation + test gate (#354) - #427
Conversation
Replaces placeholder with actual validation: 1. TypeScript compilation (npm run build:ts) 2. Rust compilation (cargo check) 3. Rust tests (cargo test --lib) Blocks push on failure. Skip with --no-verify when needed. The .git/hooks/pre-push delegates to src/scripts/git-prepush.sh.
There was a problem hiding this comment.
Pull request overview
Adds a real pre-push validation gate to prevent pushing code that doesn’t compile or pass core tests, complementing existing hook tooling in src/scripts/.
Changes:
- Run TypeScript compilation via
npm run build:tsbefore push. - Run Rust compilation via
cargo checkforsrc/workers/continuum-core. - Run Rust library tests via
cargo test --liband block push on failures.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if cd "$SRC_DIR" && npm run build:ts > /dev/null 2>&1; then | ||
| echo "✅ TypeScript: clean ($(( $(date +%s) - TS_START ))s)" | ||
| else | ||
| echo "❌ TypeScript compilation FAILED" | ||
| echo " Run: cd src && npm run build:ts" |
There was a problem hiding this comment.
The TypeScript gate suppresses all output (> /dev/null 2>&1), so when it fails the hook provides no actionable diagnostics and forces a rerun. Consider letting stdout/stderr through, or capturing output and only printing it on failure (while keeping the success path quiet).
| if cd "$SRC_DIR" && npm run build:ts > /dev/null 2>&1; then | |
| echo "✅ TypeScript: clean ($(( $(date +%s) - TS_START ))s)" | |
| else | |
| echo "❌ TypeScript compilation FAILED" | |
| echo " Run: cd src && npm run build:ts" | |
| TS_OUTPUT=$(cd "$SRC_DIR" && npm run build:ts 2>&1) | |
| TS_STATUS=$? | |
| if [ "$TS_STATUS" -eq 0 ]; then | |
| echo "✅ TypeScript: clean ($(( $(date +%s) - TS_START ))s)" | |
| else | |
| echo "❌ TypeScript compilation FAILED" | |
| echo " Run: cd src && npm run build:ts" | |
| echo "" | |
| echo "$TS_OUTPUT" |
| if cd "$RUST_DIR" && cargo check 2>/dev/null; then | ||
| echo "✅ Rust: clean ($(( $(date +%s) - RUST_START ))s)" | ||
| else | ||
| echo "❌ Rust compilation FAILED" | ||
| echo " Run: cd src/workers/continuum-core && cargo check" | ||
| FAILED=1 | ||
| fi |
There was a problem hiding this comment.
cargo check 2>/dev/null discards compiler warnings and (more importantly) error messages. If the check fails, developers won't see why from the hook output. Prefer showing cargo output, or capturing and printing it only on failure.
| if cd "$RUST_DIR" && cargo test --lib 2>/dev/null | tail -1 | grep -q "^test result: ok"; then | ||
| echo "✅ Rust tests: passed ($(( $(date +%s) - TEST_START ))s)" | ||
| else | ||
| echo "❌ Rust tests FAILED" | ||
| echo " Run: cd src/workers/continuum-core && cargo test --lib" | ||
| FAILED=1 |
There was a problem hiding this comment.
The Rust test gate is fragile: it ignores cargo test's exit status and instead checks whether the last line matches ^test result: ok. Cargo output isn't guaranteed to end with that line (e.g., doc-tests or other trailing output), which can falsely fail and block pushes. Prefer relying on cargo test --lib's exit code (and avoid the tail|grep pipeline), or add set -o pipefail and parse output without assuming the last line.
…State reaches minds via the ViewState pipe (#426) (#2298) The renderable existed with a doctrine-citing comment ("a citizen standing in the run's room can perceive the run's state through the same pipe the human's screen uses") and was NEVER BOUND — supervisor bound only the Roster. Worse, binding alone would have read an empty store: the bench emitter published only into the websocket substrate, so the mind-side had no data to read. Citizens' only route to run state was the benchmark/runs command, whose implementation scrapes the progress dir — the exact acceptance-test failure BENCHMARKS-ARE-ADAPTERS-NOT-A-RUNNER.md names. The fix is the roster repair's one-definition-two-render-targets contract applied to the bench outlier: - ipc::global_bench_substrate() — the ONE mind-side handle. The bench board is a single global fold (unlike the per-room roster), so its handle is one substrate, not PerRoomSubstrates. - spawn_bench_emitter dual-publishes the SAME builder.session(view) revision into the websocket substrate (human eyes) and the global bench substrate (citizen minds) — a screen and a mind can never disagree about the board. - PersonaCognition gains bench_source + set_bench_source (same capture-sink decoration as roster/doctrine — deliveries recorded + replayable), pushed through THE budgeter in compose_for_turn; budget rides the generic floor_tokens arm (the renderable's own 18-token floor), no new constants. - supervisor binds ViewStateRagSource::<BenchViewState> at persona boot. // what this catches (new test): a bound bench source delivers REAL run rows through the same compose path as every other source — if the push or setter regresses, minds go blind to the board again and only this fails. Found by the 2026-08-14 citizenship audit (AXIS 1c). Siblings tracked: #425 (retire the detached-runner auto-dispatch, Joel's timing call), #427 (L1 fork capture contamination), #428 (doc/dead-wire hygiene). Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
#427) (#2299) Benchmark/eval forks (fork_eval_cycle) keep cfg.persona_id, so their tick captures append to the SAME workspace-traces file as the citizen's live turns — with room_id = the nil UUID. dataset/from-captures ingested them unlabeled, contaminating L1 training data with detached eval traffic. Guard: when no explicit room_id filter is given, records whose room_id is the nil UUID are skipped. include_forks=true is the explicit opt-in for deliberately training on fork traces. An explicit room_id filter is unchanged (nil never matches a real room anyway). Regression test seeds one live-room + one nil-room capture: default sees 1 example, include_forks sees 2. ts-rs binding regenerated. Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Summary
Replaces placeholder pre-push hook with real validation:
npm run build:ts(~15s)cargo check(~20s cached)cargo test --lib(~30s cached)Blocks push on failure. Skip with
git push --no-verifywhen needed.Note:
.git/hooks/pre-pushmust be installed locally (not tracked by git).The script at
src/scripts/git-prepush.shIS tracked. Installation:Test plan
🤖 Generated with Claude Code