commit - c227bd7f6c0f7d41565ed3a1fd4a788ff9476e76
commit + 00df5eedf8e92b78e7db6d28f85cce5988525b62
blob - f61986f71509bbd3138c9bcdb0c69c885e25cd03
blob + 63d38c4b7f71a7c9c93672e2e0b57dd4c8497a52
--- handoff/verification.md
+++ handoff/verification.md
and matching input-cursor width, narrow-pane fallback, drawer clipping, and
resize reflow. The curses pty path exercises the styled input and transcript
through wide curses while retaining clean terminal-mode startup and teardown.
-- **Empty-transcript welcome:** a pure suite pins the exact copy, centering in
+- **Empty-transcript welcome:** a pure suite pins the exact copy, centered
+ copy rows and shared help-column alignment in
full and drawer-narrowed viewports, ASCII punctuation, whole-row omission on
short/narrow terminals, nonoverlapping status captions, and one-way
dismissal. Pure geometry checks keep tiny picker overlays above the status
blob - 4aa6cbfc990bfd2484d1c0005273f56e13d04b82
blob + 6ce6fbd248b4ec24efb550d290158c225e01152a
--- regress/turn/run.sh
+++ regress/turn/run.sh
ok "curses: the typed prompt reached the provider" $?
grep -a -Fq "OWNER-BLOCK-MARKER" "$dir/cursesout"
ok "curses: Owner marker renders over a monochrome pty" $?
- grep -a -Fq "I like Fugu" "$dir/welcome-stage.0" &&
+ grep -a -Fq "Fugu - Japanese for pufferfish" "$dir/welcome-stage.0" &&
grep -a -Fq "by Isaac Meerleo" "$dir/welcome-stage.0" &&
grep -a -Fq "git ssh://anonymous@got.fugu.farm" \
"$dir/welcome-stage.0"
grep -a -Fq "context used / limit" "$dir/welcome-stage.0"
ok "curses: welcome captions label the live status fields" $?
grep -a -Fq "conversations" "$dir/welcome-stage.1" &&
- grep -a -Fq "I like Fugu" "$dir/welcome-stage.1"
+ grep -a -Fq "Fugu - Japanese for pufferfish" "$dir/welcome-stage.1"
ok "curses: drawer overlays the undismissed welcome" $?
- grep -a -Fq "I like Fugu" "$dir/welcome-stage.2" &&
+ grep -a -Fq "Fugu - Japanese for pufferfish" "$dir/welcome-stage.2" &&
grep -a -Fq "agent state" "$dir/welcome-stage.2"
ok "curses: closing the drawer restores the welcome" $?
picker_stage=''
done
test -n "$picker_stage"
ok "curses: model picker overlays the undismissed welcome" $?
- grep -a -Fq "I like Fugu" "$dir/welcome-stage.5" &&
+ grep -a -Fq "Fugu - Japanese for pufferfish" "$dir/welcome-stage.5" &&
grep -a -Fq "context used / limit" "$dir/welcome-stage.5" &&
! grep -a -Fq "model: stub-model-a" "$dir/welcome-stage.5"
ok "curses: selecting from m restores welcome without scrollback" $?
done
test -n "$picker_stage"
ok "curses: model picker can reopen before Owner input" $?
- grep -a -Fq "I like Fugu" "$dir/welcome-stage.8" &&
+ grep -a -Fq "Fugu - Japanese for pufferfish" "$dir/welcome-stage.8" &&
grep -a -Fq "context used / limit" "$dir/welcome-stage.8"
ok "curses: cancelling the model picker restores the welcome" $?
test -s "$dir/welcome-stage.9" &&
grep -a -Fq "OWNER-BLOCK-MARKER" "$dir/welcome-stage.9" &&
- ! grep -a -Fq "I like Fugu" "$dir/welcome-stage.9" &&
+ ! grep -a -Fq "Fugu - Japanese for pufferfish" "$dir/welcome-stage.9" &&
! grep -a -Fq "agent state" "$dir/welcome-stage.9" &&
! grep -a -Fq "context used / limit" "$dir/welcome-stage.9"
ok "curses: forced repaint after first edit omits welcome and captions" $?
ok "curses: pre-input picker selection drives the request" $?
grep -a -Fq "Context 46k/111k 41%" "$dir/cursesout"
ok "curses: status shows Lead cache plus session context" $?
- grep -q "I like Fugu" "$dir/reqout" 2>/dev/null
+ grep -q "Fugu - Japanese for pufferfish" "$dir/reqout" 2>/dev/null
ok "curses: welcome is absent from the Provider request" \
$([ $? -ne 0 ]; echo $?)
- grep -q "I like Fugu" "$sessions"/*.ndjson 2>/dev/null
+ grep -q "Fugu - Japanese for pufferfish" "$sessions"/*.ndjson 2>/dev/null
ok "curses: welcome is absent from the Journal" \
$([ $? -ne 0 ]; echo $?)
n=$(grep -c '"outcome":"ok"' "$sessions"/*.ndjson 2>/dev/null || echo 0)
"$dir/profileout"
ok "curses: $profile subscription warning is not transcript" \
$([ $? -ne 0 ]; echo $?)
- grep -a -Fq "I like Fugu" "$dir/profileout"
+ grep -a -Fq "Fugu - Japanese for pufferfish" "$dir/profileout"
ok "curses: $profile subscription profile retains welcome" $?
done
else
blob - faff7f7a2086a2eaa36bae5ff1a68a662739a4db
blob + 4eacb92d89e483fcaa0099d7acf235e78fd4b52a
--- regress/welcome/welcome_test.c
+++ regress/welcome/welcome_test.c
return (NULL);
}
+static int
+text_col(const struct welcome_row *row, const char *text)
+{
+ const char *at = strstr(row->text, text);
+
+ return (at == NULL ? -1 : row->col + (int)(at - row->text));
+}
+
int
main(void)
{
welcome_build(&view, 0, 100, 30, 0);
CHECK(view.nrows == 8);
CHECK(strcmp(view.rows[0].text,
- "I like Fugu \xe2\x80\x94 Japanese for pufferfish.") == 0);
+ "Fugu - Japanese for pufferfish") == 0);
CHECK(view.rows[0].kind == WELCOME_ROW_TITLE);
CHECK(strcmp(view.rows[1].text, "by Isaac Meerleo") == 0);
CHECK(view.rows[1].kind == WELCOME_ROW_DIM);
"press Esc, then v to compose in your editor") == 0);
CHECK(strcmp(view.rows[7].text,
"type /quit<Enter> to exit") == 0);
+ for (i = 5; i <= 7; i++)
+ CHECK(text_col(&view.rows[i], "to ") ==
+ text_col(&view.rows[4], "to "));
CHECK(view.rows[4].row == view.rows[3].row + 2);
for (i = 0; i < view.nrows; i++)
CHECK(view.rows[i].col >= 0 &&
view.rows[i].col + view.rows[i].width <= 100);
- /* ASCII mode folds only the em dash, consistently with markdown. */
+ /* The title is already ASCII and remains byte-identical in ASCII mode. */
welcome_build(&view, 0, 100, 30, 1);
CHECK(strcmp(view.rows[0].text,
- "I like Fugu -- Japanese for pufferfish.") == 0);
+ "Fugu - Japanese for pufferfish") == 0);
/* Drawer offset and resize recenter without changing the copy. */
welcome_build(&view, 31, 69, 20, 0);
for (i = 0; i < view.nrows; i++)
CHECK(view.rows[i].col >= 31 &&
view.rows[i].col + view.rows[i].width <= 100);
+ for (i = 5; i <= 7; i++)
+ CHECK(text_col(&view.rows[i], "to ") ==
+ text_col(&view.rows[4], "to "));
row = find_row(&view, "by Isaac Meerleo");
CHECK(row != NULL && row->col == 31 + (69 - row->width) / 2);
welcome_build(&view, 0, 100, 4, 0);
CHECK(view.nrows == 4);
CHECK(strcmp(view.rows[0].text,
- "I like Fugu \xe2\x80\x94 Japanese for pufferfish.") == 0);
+ "Fugu - Japanese for pufferfish") == 0);
CHECK(strcmp(view.rows[1].text, "by Isaac Meerleo") == 0);
CHECK(strcmp(view.rows[2].text,
"git ssh://anonymous@got.fugu.farm") == 0);
blob - 08bf7571eb0a391928f20d47fc251059e0f3d4f0
blob + bd8d8b8a52b9c15aa981574aa6a339e26038115e
--- src/fugu-tty/welcome.c
+++ src/fugu-tty/welcome.c
};
static const struct welcome_candidate candidates[WELCOME_ROWS_MAX] = {
- { "I like Fugu \xe2\x80\x94 Japanese for pufferfish.",
- "I like Fugu -- Japanese for pufferfish.", WELCOME_ROW_TITLE, 0, 0 },
+ { "Fugu - Japanese for pufferfish", NULL, WELCOME_ROW_TITLE, 0, 0 },
{ "by Isaac Meerleo", NULL, WELCOME_ROW_DIM, 0, 1 },
{ "git ssh://anonymous@got.fugu.farm", NULL, WELCOME_ROW_DIM, 0, 2 },
{ "Fugu is open source and freely available!", NULL,
{
const char *text[WELCOME_ROWS_MAX];
int cells[WELCOME_ROWS_MAX], keep[WELCOME_ROWS_MAX];
- int count, gap, groups, i, last_group, row, total, victim;
+ int count, gap, groups, help_width = 0, i, last_group;
+ int row, total, victim;
memset(view, 0, sizeof(*view));
if (xoff < 0 || width <= 0 || height <= 0)
}
if (count == 0)
return;
+ /* The padded help text is one two-column block. Center its widest
+ * retained row once so every row's second column remains aligned. */
+ for (i = 0; i < WELCOME_ROWS_MAX; i++)
+ if (keep[i] && candidates[i].group == 1 &&
+ cells[i] > help_width)
+ help_width = cells[i];
row = (height - total) / 2;
last_group = -1;
out->kind = candidates[i].kind;
out->row = row++;
out->width = cells[i];
- out->col = xoff + (width - cells[i]) / 2;
+ out->col = xoff + (width - (candidates[i].group == 1 ?
+ help_width : cells[i])) / 2;
last_group = candidates[i].group;
}
}