Files
inter-hub/workplans/IHUB-WP-0016-build-infrastructure-and-error-loop.md
Bernd Worsch a6baab7080 feat(WP-0016): build infrastructure — ghcid standalone script and error-fix loop workplan
- 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 <noreply@anthropic.com>
2026-04-10 09:46:56 +00:00

6.4 KiB
Raw Blame History

id, type, title, domain, repo, status, owner, topic_slug, created, updated, depends_on
id type title domain repo status owner topic_slug created updated depends_on
IHUB-WP-0016 workplan Build Infrastructure: Incremental Compilation and Autonomous Error-Fix Loop inter_hub inter-hub open custodian inter_hub 2026-04-10 2026-04-10

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: 2060 min on constrained hardware.

Subsequent incremental builds: fast — only changed modules and their dependents recompile. A single controller change: ~530 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):

#!/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:

# 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 23:
   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