From a6baab7080e3cd1a73979fa0d7165faa00597ab2 Mon Sep 17 00:00:00 2001 From: Bernd Worsch Date: Fri, 10 Apr 2026 09:46:56 +0000 Subject: [PATCH] =?UTF-8?q?feat(WP-0016):=20build=20infrastructure=20?= =?UTF-8?q?=E2=80=94=20ghcid=20standalone=20script=20and=20error-fix=20loo?= =?UTF-8?q?p=20workplan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - scripts/compile-check: runs ghcid in isolation (no postgres/tailwind) for fast incremental compilation feedback; writes errors to /tmp/ihub-compile-errors.txt - .ghci: add -fkeep-going so GHC reports all module errors in one pass - WP-0016 workplan: documents module dependency layers, error-fix SOP, and autonomous ralph-loop approach for iterative error fixing Co-Authored-By: Claude Sonnet 4.6 --- .ghci | 3 + scripts/compile-check | 44 +++++ ...016-build-infrastructure-and-error-loop.md | 171 ++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100755 scripts/compile-check create mode 100644 workplans/IHUB-WP-0016-build-infrastructure-and-error-loop.md diff --git a/.ghci b/.ghci index 66c67a2..d6d04b7 100644 --- a/.ghci +++ b/.ghci @@ -4,4 +4,7 @@ -- Resource limit: override IHP's default -j (unlimited parallel) with -j1 -- on this constrained host (2 CPU / 3.8 GiB RAM). :set -j1 +-- Report errors from all modules in one pass (don't stop at first failure). +-- Critical for batch error fixing — see IHUB-WP-0016 C4. +:set -fkeep-going import IHP.Prelude \ No newline at end of file diff --git a/scripts/compile-check b/scripts/compile-check new file mode 100755 index 0000000..f108d46 --- /dev/null +++ b/scripts/compile-check @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# bin/compile-check — run ghcid standalone for fast compilation feedback. +# +# Does NOT start postgres or tailwind — just GHC. +# Relies on .ghci (sets -j1, loads IHP config). +# +# Usage: +# bin/compile-check # interactive: errors shown in terminal + log +# bin/compile-check --bg # log only (for Claude monitoring loop) +# +# Pre-requisite: run inside `devenv shell` (IHP_LIB must be set). +# Or: `devenv shell -- bin/compile-check` +# +# Log file: /tmp/ihub-compile-errors.txt (override with IHUB_COMPILE_LOG) + +set -euo pipefail + +LOGFILE="${IHUB_COMPILE_LOG:-/tmp/ihub-compile-errors.txt}" +MODE="${1:-}" + +# Ensure IHP_LIB is available +if [[ -z "${IHP_LIB:-}" ]]; then + echo "ERROR: IHP_LIB is not set. Run inside devenv shell:" >&2 + echo " devenv shell -- bin/compile-check" >&2 + exit 1 +fi + +: > "$LOGFILE" +echo "[compile-check] Log: $LOGFILE" +echo "[compile-check] Mode: ${MODE:-interactive}" + +if [[ "$MODE" == "--bg" ]]; then + # Background: write to log only, no colour/title + exec ghcid \ + --no-title \ + --outputfile "$LOGFILE" \ + --command "ghci" +else + # Interactive: show errors in terminal AND write to log + exec ghcid \ + --no-title \ + --outputfile "$LOGFILE" \ + --command "ghci" +fi diff --git a/workplans/IHUB-WP-0016-build-infrastructure-and-error-loop.md b/workplans/IHUB-WP-0016-build-infrastructure-and-error-loop.md new file mode 100644 index 0000000..aca06b8 --- /dev/null +++ b/workplans/IHUB-WP-0016-build-infrastructure-and-error-loop.md @@ -0,0 +1,171 @@ +--- +id: IHUB-WP-0016 +type: workplan +title: "Build Infrastructure: Incremental Compilation and Autonomous Error-Fix Loop" +domain: inter_hub +repo: inter-hub +status: open +owner: custodian +topic_slug: inter_hub +created: "2026-04-10" +updated: "2026-04-10" +depends_on: [] +--- + +# IHUB-WP-0016 — Build Infrastructure: Incremental Compilation and Autonomous Error-Fix Loop + +## Goal + +Make GHC compilation fast enough for iterative error fixing without blocking the +machine or requiring user involvement. The first full build is unavoidably slow +(Nix dep download + all 180+ modules), but subsequent rebuilds must be incremental +(seconds per changed file). An autonomous error-fix loop must allow Claude to iterate +on compilation errors independently. + +## Background + +### Why compilation is slow + +IHP compiles the entire project as one GHC executable target containing ~180 Haskell +modules (Generated types + Web.Types + 12 helpers + 59 controllers + 120 views + +FrontController/Routes). GHC compiles modules sequentially (`.ghci` enforces `-j1` +for this constrained host) and caches each module's `.o`/`.hi` files. Once a module +is compiled and its dependencies have not changed, it is NOT recompiled. + +**First build**: slow — GHC compiles all 180 modules from scratch, plus Nix fetches +deps. Unavoidable. Expected: 20–60 min on constrained hardware. + +**Subsequent incremental builds**: fast — only changed modules and their dependents +recompile. A single controller change: ~5–30 seconds. This is what we rely on. + +### Module dependency layers (compilation order, bottom-up) + +``` +Layer 1 (stable core — compile once, never touch during error loops): + build/Generated/*.hs IHP auto-generated from Schema.sql + Web/Types.hs 500-line controller type definitions + +Layer 2 (helpers — only touch if Layer 1 is clean): + Application/Helper/*.hs 12 files + Generated/ (IHP code-gen output, if present) + +Layer 3 (working surface — most errors will be here): + Web/Controller/*.hs 59 controllers + Web/View/**/*.hs 120 views + +Layer 4 (wiring — fix last): + Web/FrontController.hs + Web/Routes.hs +``` + +**Rule**: never modify Layer 1 during error-fix loops. Changes to Web/Types.hs or +Generated types invalidate all 59 controllers and 120 views simultaneously. + +### Why `devenv up` is overkill for error checking + +`devenv up` starts: PostgreSQL, file-change watcher, Tailwind CSS watcher, AND +ghcid. For compilation error fixing we only need ghcid. Running ghcid standalone +skips the database startup, port binding, and service orchestration overhead. + +## Tasks + +### C1 — Create `scripts/compile-check` script ✓ + +A shell script at `scripts/compile-check` that runs ghcid in isolation (no postgres, no tailwind): + +```bash +#!/usr/bin/env bash +# scripts/compile-check +# Run ghcid standalone for fast compilation feedback. +# Outputs errors to stdout AND to /tmp/ihub-compile-errors.txt for monitoring. +# Does NOT start postgres or tailwind. +# +# Usage: +# scripts/compile-check # interactive, shows errors in terminal +# scripts/compile-check --bg # write to log only (for Claude monitoring) +# +# Pre-requisite: be inside `devenv shell` or have IHP_LIB set. +set -euo pipefail +LOGFILE="${IHUB_COMPILE_LOG:-/tmp/ihub-compile-errors.txt}" +: > "$LOGFILE" # truncate on start +echo "[compile-check] Writing errors to $LOGFILE" +exec ghcid \ + --no-title \ + --outputfile "$LOGFILE" \ + --command "ghci" +``` + +This relies on `.ghci` (already present) which sets up `-j1` and loads the IHP config. + +### C2 — Verify GHC object cache persistence + +GHC stores compiled objects in IHP's `.devenv` or a project-local `dist-newstyle/` +equivalent. Verify the cache survives between `devenv up` restarts: + +```bash +# After first successful build, check cache location: +find /home/tegwick/inter-hub -name "*.o" -newer Main.hs 2>/dev/null | head -5 +``` + +If the cache is cleared on each `devenv up` restart, add `IHP_BUILD_CACHE` or +configure the Nix build dir to persist. Document the location here. + +### C3 — Autonomous error-fix loop (ralph-workplan) + +Configure a ralph-workplan loop: +1. `scripts/compile-check --bg` runs ghcid in background, writing to `/tmp/ihub-compile-errors.txt` +2. Monitor tool watches the log file for new error output +3. On error output: read errors → identify failing module → apply fix → ghcid auto-reloads +4. On "All good" output: loop exits, reports clean build + +**Loop discipline**: +- Fix errors bottom-up (Layer 1 → Layer 2 → Layer 3 → Layer 4) +- Fix one module at a time; wait for ghcid reload before fixing the next +- Do NOT make speculative changes to stable layers while fixing working-surface errors +- Maximum 3 fix attempts per module before escalating to user + +### C4 — Add GHC `-fwrite-interface` and `-keep-going` flags to `.ghci` + +``` +-- Continue past errors in other modules (report all errors in one pass) +:set -fkeep-going +-- Ensure interface files are written even on partial success +:set -fwrite-interface +``` + +`-fkeep-going` lets GHC report errors from all modules in one pass rather than +stopping at the first failure — critical for batch error fixing. + +### C5 — Document module surface constraints in CLAUDE.md + +Add a "Compilation Layers" section to CLAUDE.md noting: +- Never modify Layer 1 during error-fix loops +- Each layer's expected compile time after first build +- Cache location and how to verify it's warm + +## Error-Fix Loop SOP (Standard Operating Procedure) + +``` +1. Ensure devenv shell is active (IHP_LIB must be set) +2. Run: scripts/compile-check --bg +3. Monitor /tmp/ihub-compile-errors.txt +4. Parse errors: group by module, order by Layer (1 → 4) +5. Fix Layer 1 errors first (rare; usually type/import issues in Web/Types.hs) +6. For each failing module in Layer 2–3: + a. Read current module state + b. Apply targeted fix + c. Wait for ghcid "Reloading..." + result + d. If still failing: re-read error, apply next fix + e. If 3 attempts fail: note module name, move on +7. After Layer 3 clean: fix Layer 4 (FrontController/Routes) +8. "All good (N modules)" in log = build clean +9. Commit fixes, update WP-0014/A1 status +``` + +## Exit Criteria + +- `scripts/compile-check` script exists and runnable inside devenv shell +- `ghcid` produces output to `/tmp/ihub-compile-errors.txt` successfully +- GHC object cache location identified and documented +- ralph-workplan loop configuration in place +- Build reaches "All good" state without user intervention beyond starting the loop