FABRIC-2.md §I.9: fix the terminal phantom-linebreak defect
console_ensure_line_start() (hal/console.c) used to emit its newline
immediately via a path that deliberately skipped the tx-byte counter, so
that sk_repl_idle()'s unconditional per-beat call to it (repl.c, ~1s idle
heartbeat) could force a real newline the REPL's own prompt-reanchor logic
never noticed -- the prompt was never reprinted, and the next real
keystroke echoed onto the now-blank line, indistinguishable from Enter
having already been pressed at a bare prompt. Root-caused in the previous
commit (704573b); this commit applies the fix per explicit go-ahead.
Fix: defer the newline instead of emitting it eagerly.
console_ensure_line_start() now only sets a flag (g_pending_line_close);
the newline is realized -- for real, and counted by g_console_tx_count
like any other output -- on the next actual console_putc() call, or
silently discarded via the new console_cancel_deferred_line_start() if the
caller decides nothing was actually printed. sk_repl_idle() captures
tx_before_idle right after its console_ensure_line_start() call and cancels
the deferred newline at both of its exit points when console_tx_count()
hasn't moved. A beat with nothing to report now leaves the console
untouched; a beat that does print still closes the dangling prompt line
first, properly counted this time. The pre-existing n > 0 mid-edit gate in
sk_console_readline() is untouched -- independent purpose, not the bug.
Verified via the mandatory foreground 3-arch QEMU acceptance boot
(clean qemu, amd64 -> aarch64 -> riscv64, one at a time): all three reached
(zuse) ok>, all echoed the first real input on the same log line as the
prompt rather than a fresh line, all shut down cleanly via BYE. amd64's log
additionally shows live human backspace-correction still glued to the same
prompt line. Logs: logs/20260905-015854 (amd64), logs/20260905-020248
(aarch64), logs/20260905-020552 (riscv64); logs/20260905-015813 is a
foreground-rule-violation retry killed and redone correctly, kept per this
project's "never delete logs/" convention.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
704573bdfc
commit
8edb95b65d
@@ -260,16 +260,33 @@ static void emit_prefix(void) {
|
||||
* Also mirrors output to the framebuffer VT100 terminal when available.
|
||||
* Serial output is ALWAYS active regardless of framebuffer state.
|
||||
*
|
||||
* console_putc_inner(): the same body minus the tx-counter increment.
|
||||
* console_ensure_line_start() uses the inner form so its format-only
|
||||
* newline does not read as "real output" to the REPL's prompt re-anchor
|
||||
* (repl.c) -- a silent idle beat that merely closes a dangling prompt line
|
||||
* must not be mistaken for chatter and trigger a prompt repaint. The
|
||||
* counter counts characters the caller actually intended to emit.
|
||||
* console_putc_inner(): the same body minus the tx-counter increment --
|
||||
* used internally for the newline console_putc() itself realizes out of
|
||||
* g_pending_line_close below (see console_ensure_line_start()), so that
|
||||
* one real character write emits at most one counted "start" (the '\n'
|
||||
* plus the character together read as a single unit of real output, not
|
||||
* two, to console_tx_count()'s callers).
|
||||
*/
|
||||
static void console_putc_inner(char c);
|
||||
|
||||
/* FABRIC-2.md §I.9 fix, 2026-09-05: set by console_ensure_line_start(),
|
||||
* cleared either by console_cancel_deferred_line_start() (no output
|
||||
* followed -- drop the newline silently) or here in console_putc() (real
|
||||
* output followed -- realize it for real, counted, immediately before the
|
||||
* character that triggered it). See console.h's doc comments on both
|
||||
* functions for the full rationale; the short version is that the old
|
||||
* unconditional-and-immediate version of this newline fired every idle
|
||||
* heartbeat regardless of whether anything was actually about to be
|
||||
* printed, visibly snapping a bare REPL prompt to a fresh blank line on
|
||||
* its own. */
|
||||
static int g_pending_line_close = 0;
|
||||
|
||||
void console_putc(char c) {
|
||||
if (g_pending_line_close) {
|
||||
g_pending_line_close = 0;
|
||||
g_console_tx_count++;
|
||||
console_putc_inner('\n');
|
||||
}
|
||||
g_console_tx_count++;
|
||||
console_putc_inner(c);
|
||||
}
|
||||
@@ -313,10 +330,15 @@ void console_ensure_line_start(void)
|
||||
{
|
||||
if (!g_line_start)
|
||||
{
|
||||
console_putc_inner('\n');
|
||||
g_pending_line_close = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void console_cancel_deferred_line_start(void)
|
||||
{
|
||||
g_pending_line_close = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string with newline to serial console
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user