| Age | Commit message (Collapse) | Author |
|
Clarify that the mutex protects against ncurses thread-safety issues
that cause segfaults during concurrent builds.
This commit also forces a new Nix derivation hash to ensure the
mutex fix is actually used (previous builds were cached with the
old version).
|
|
Problem: Intermittent segfaults when running `bild --time 0 **/*` with
many concurrent builds. Core dumps showed crashes in libncursesw's
free() function during terminal cleanup.
Root cause: ANSI.getTerminalSize and other ANSI terminal library
calls are not thread-safe. With mapConcurrentlyBounded running up to
8 analyses concurrently, multiple threads were calling ANSI functions
simultaneously, causing memory corruption in the ncurses library.
Solution: Add global MVar terminalLock to serialize all ANSI terminal
operations. Wrap all ANSI function calls (cursor movement, line
clearing, etc.) with withMVar terminalLock.
Changes: - Add terminalLock :: MVar () in Omni/Log/Concurrent.hs -
Wrap all ANSI calls in withMVar terminalLock:
- initializeLines: cursor column, clear line - updateLine: cursor
up/down, column set, clear line - updateLineState: cursor up/down,
column set, clear line - withLineManager: cursor up
Tested: 5 consecutive runs of `bild --time 0 **/*` complete without
segfaults (previously failed 1-2 out of 3 runs).
|
|
Problem: Calling bild.run inside NixOS configs triggered IFD during
OS evaluation. ANSI escape codes from bild broke JSON parsing in Nix
sandbox, causing build failures.
Root cause: bild.run uses IFD (Import From Derivation) which runs
bild --plan during Nix evaluation. When this happened inside NixOS
service definitions, it ran recursively and bild output ANSI codes
that corrupted the JSON analysis output.
Solution: Two-phase architecture + NO_COLOR support
1. Biz/Packages.nix: Pre-builds all packages outside NixOS context
2. Biz.nix: Accepts packages as function argument (default:
Packages.nix) 3. Omni/Bild.nix: Sets NO_COLOR=1 in analysis
derivation 4. Omni/Log/Terminal.hs: Respects NO_COLOR env var
5. Omni/Log/Terminal.hs: Skip getTerminalSize when NO_COLOR set
to avoid
escape code output
6. Omni/Log/Concurrent.hs: Skip line initialization without ANSI
support
Now NixOS builds succeed: - Package IFD happens once at top level -
No recursive builds during service evaluation - Clean JSON output
from bild --plan in Nix sandbox - NixOS configs reference pre-analyzed
packages
Changes: - Add Biz/Packages.nix - standalone package builder - Update
Biz.nix to accept packages argument - Update Biz/Dragons/Analysis.nix
to use Packages.nix - Remove Biz/Targets.nix (replaced by
Packages.nix) - Add NO_COLOR support throughout logging stack -
Fix ANSI.getTerminalSize outputting escape codes when NO_COLOR set
Amp-Thread-ID:
https://ampcode.com/threads/T-bc0f6fc7-46bf-4aa2-892e-dd62e7251d4b
Co-authored-by: Amp <amp@ampcode.com>
|
|
ANSI.getTerminalSize queries the terminal by writing escape codes and
reading the response from stdin. When stdin is unavailable or at EOF
(common in non-interactive contexts), this causes "hWaitForInput:
end of file" errors.
Additionally, Conduit.streamingProcess returns a stdin handle that
was never being closed, which could cause child processes to block
waiting for input.
Fixes: - Catch IOException in detectTerminal when getTerminalSize
fails - Close subprocess stdin handle immediately after spawn -
Fallback to default terminal size (80x24) when detection fails
This unblocks all bild commands that were failing with stdin errors.
|
|
- Remove BILD_OUTPUT_MODE environment variable - Simplify to 2
modes: MultiLine (≥80 cols) and SingleLine (<80) - Use existing
--loud flag to disable concurrent UI entirely - When --loud: show
all compiler output line-by-line (for debugging) - When not --loud:
adaptive concurrent UI based on terminal width
This is simpler and uses the existing --loud flag instead of adding
new configuration. The --loud flag was already meant for debugging,
so it makes sense to use it to show all output.
Note: Omni/Bild.nix updated to include new Omni/Log/Terminal.hs module.
Blocked by: stdin bug (see _/llm/STDIN_BUG.md) - cannot test build yet.
|
|
- Add Omni/Log/Terminal module to detect terminal capabilities -
Implement 3 output modes: RichMultiLine (≥80 cols), SingleLine
(40-79),
SimpleFallback (<40 or dumb terminals)
- Terminal width auto-detection via System.Console.ANSI.getTerminalSize
- Text truncation with ellipsis to prevent line wrapping - Manual
override via BILD_OUTPUT_MODE env var (simple|single|rich|auto)
Fixes UI corruption on small terminals (mobile SSH, narrow windows).
Wide terminals keep existing multi-line behavior but with truncation.
Design doc: _/llm/CONCURRENT_LOG_DESIGN.md
|
|
- Add Analyzing state to BuildState enum - Refactor from sequential
foldM analyze to concurrent analyzeAll - Initialize all lines with
[+] during analysis phase - Update to [...] (Pending) after each
analysis completes - Uses mapConcurrentlyBounded with concurrency of
8 for analysis - Remove Log.info from analyzeOne (now handled by line
state) - Analysis now runs in parallel, improving efficiency - Flow:
[+] analyzing → [...] pending → [~] building → [✓]/[x] complete
|
|
- Replace cursor down movement with single newline at end - Cursor
now stays at bottom of status lines - No extra blank space between
build output and next prompt
|
|
- Remove save/restore cursor in favor of explicit movement - Always
move up from bottom position, update line, move back down - Simplify
initializeLines to just print lines sequentially - Cursor now stays
at bottom and moves up/down for each update - Fixes issue where lines
were being updated far up the terminal
|
|
- Use hCursorDown in initializeLines instead of hCursorUp - Simplify
updateLine and updateLineState cursor movement - Cursor now moves up
from bottom position correctly - Shell prompt no longer gets erased
|
|
- Allocate one line per namespace (not per concurrent job) - Add
Pending state shown as [...] when build hasn't started - Initialize all
namespace lines at start showing [...] - Update to [~] when building,
[✓]/[x] when complete - Each namespace keeps its line throughout
the build - At end, all namespaces show their final status - --jobs
controls concurrency, not line count
|
|
- Remove [+] display from reserveLine (was causing mangled output
from concurrent writes) - Add [+] display in analyze function where
it's single-threaded - Simplify cleanup to just move cursor down
without clearing lines - This eliminates race conditions and terminal
clearing issues
|
|
- Add initial newline to preserve terminal prompt - Clear each line
individually at end instead of just moving cursor - This prevents
extra blank lines from remaining on screen
|
|
- Remove initial blank line before build starts - Remove trailing blank
line after build completes - Remove newlines from status indicators
in releaseLine - Status lines now stay on their reserved lines without
extra spacing
|
|
- Remove all label prefixes from build logs (bild:, nix:, etc) -
Show [+] Namespace when first reserving a line (analyzing) - Show [~]
Namespace: output when building with subprocess output - Show [✓]
Namespace (green) on success - Show [x] Namespace (red) on failure
|
|
- Add initial line break to preserve terminal prompt - Change format
to [✓]/[x]/[~] Namespace: output - Add colors: green for success,
red for failure - Fix extra lines by adding newlines in releaseLine -
Fix currentLine initialization to 0 instead of maxLines
Amp-Thread-ID:
https://ampcode.com/threads/T-39671965-c412-4a2e-8084-9d09128fd865
Co-authored-by: Amp <amp@ampcode.com>
|
|
- Fix BuildStatus to use newtype with single field - Clean up unused
imports and fields - logs function now uses updateCurrentLine
for LineManager support - Fallback to single-line output when no
LineManager
All tests passing. Ready to test with different terminal types.
Tasks: t-1a1Eiay
|
|
- Add global IORef for currentLineManager and namespaceLines
mapping - Update logs function to use LogC.updateCurrentLine -
Add updateCurrentLine and releaseCurrentLine helpers - Fallback to
normal printing when no LineManager active - Simplify buildTarget to
use global helpers instead of threading
Tasks: t-1a1EaJy
|
|
- Reserve line for each concurrent build - Release line on completion
with success/failed state - Fix hlint eta reduce warning
Task: t-1a1E3j1
|
|
- Implement LineManager abstraction with IORef state - Line
reservation/update/release functions - ANSI cursor positioning for
concurrent updates - Terminal capability detection (ANSI vs dumb) -
Graceful fallback for non-ANSI terminals
Tasks: t-1a1DzES, t-1a1DGY0, t-1a1DOev, t-1a1DVM5
|