Skip to content

Buddy: Seznamte se s Buddym in Začínáme and Nastavení → Buddy, over his sign-in and persona (DEV-6676 PR 3, F65) - #637

Merged
immakermatty merged 7 commits into
mainfrom
agent/DEV-6676-buddy-onboarding-ui
Oct 25, 2026
Merged

immakermatty merged 7 commits into
mainfrom
agent/DEV-6676-buddy-onboarding-ui

Conversation

@immakermatty

@immakermatty immakermatty commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Base: main; the diff is only PR 3

#635 (F63) and #636 (F64) are merged into main as 4a28b43e and f85309d8. This branch is rebased onto main at f85309d8 without the integration merge it used to carry, so its diff is only PR 3: seven commits, from c9876c84 (the route and its core) to ad7fb96a. #635's and #636's code is exactly as on main; under src/buddy/ the only difference is the new persona-save.ts. The rebase had no conflict with #633 (no sentence under a page title), #630 or #638. Following #633's rule, Nastavení → Buddy keeps only a state under its title (ad7fb96a).

Why

Root decision 0210 (night addendum, point 10) starts the onboarding of an Osobní Prostředí with Buddy: his own ChatGPT sign-in, apart from the agents', then his introduction. #635 gave the Launchpad his sign-in and state, #636 made the Platform the one deriver of his persona. Nobody could see or use either: there was no step in Začínáme and no Nastavení → Buddy.

This is PR 3 of Buddy's onboarding (plan DEV-6676, the Buddy lead's shaping of 2026-10-25, §3.2, §3.4–§3.6, §3.9, §3.10 and §5; the wireframe of prototypes-lazurio #90). It is the Monday slice: sign-in, introduction and status, in Začínáme and in Nastavení → Buddy.

What changes

All of it appears only on an Osobní Prostředí whose recorded entry names Buddy's origin. Elsewhere nothing is drawn and the routes answer 404 buddy-absent.

  • Začínáme, step 1 "Seznamte se s Buddym" (first-run.ts, start-view.ts, start-panel.ts, buddy-view.ts):
    • a fourth basic, first;
    • done only when Hermes's card says he is signed in and the person confirmed his names;
    • two quiet parts (Přihlášení k ChatGPT, Jméno a oslovení) and one action at a time: Přihlásit Buddyho, Zrušit + Pokračovat, Nový kód, Pokračovat, Upravit;
    • "Hotovo X ze 4 kroků.", "X/4" in the navigation, and "Dokončit nastavení (X ze 4)" in the shell's column through an additive setup.buddy in lazurio.shell.v1.
  • The order and the gate (Q4). The tour, the line in Apps ("Buddy na vás čeká." · Seznámit se) and the shell's prompt lead to Buddy first. The agents' AI step stays offered beside him, not locked: his sign-in can fail on the account's side, and a hard gate would lock the person out of the agents, GitHub and the Personal Workspace. That is the shaping's recommendation and stays Matěj's to decide: the order is buddyBasics and the gate is buddyGate (offered | after-buddy), both in first-run.ts.
  • The dialog "Seznamte se s Buddym" (buddy-dialog.ts), the wireframe's three screens:
    1. his sign-in through Buddy: his ChatGPT sign-in and state through his own Hermes gateway, in the Launchpad and lazurio buddy (DEV-6676 PR 1, F63) #635's routes: OpenAI's page, the code with Kopírovat, the time it still holds from expiresAt (ticking in place, never redrawing), Čekám na přihlášení…, Nový kód, then Připojeno;
    2. his introduction in his own words, which switch at once with Tykej mi: his name, ty or vy, the person's name with "Buddy za Boba" / "Výsledek pošli Bobovi" guessed by the wireframe's czechNames and Opravit; Pokračovat saves with the confirmation. English asks for one form;
    3. Telegram with only "Teď ne" for now (PR 5 adds it).
  • Buddy: his ChatGPT sign-in and state through his own Hermes gateway, in the Launchpad and lazurio buddy (DEV-6676 PR 1, F63) #635's closed reasons as plain lines:
    • hermes-outdated: "Buddy potřebuje aktualizaci, než se tu dá přihlásit." and no code;
    • refused: one line and a "?" that explains the account's setting;
    • expired: "Kód vypršel." with Nový kód;
    • sign-in-running: the code already shown stays on screen (a Nový kód or a Zrušit that Hermes did not confirm changes nothing);
    • no gateway: "Buddy teď neběží.".
  • Nastavení → Buddy (buddy-panel.ts, the last Settings section, only with Buddy):
    • Stav: his name, then Pracuje / Čeká na přihlášení / "Buddy teď neběží"; his sign-in with ⋯ → Přihlásit znovu and Odhlásit (behind a confirm dialog);
    • Jméno a oslovení: his name, Vyká vám / Tyká vám, your name with Opravit, and Uložit; while the change waits for him, one line: "Projeví se, až Buddy dokončí, co právě dělá.";
    • no model ids anywhere.
  • POST /api/buddy/persona (buddy-routes.ts over src/buddy/persona-save.ts):
    • takes {buddyName, address, user: {nominative, accusative, dative}, revision, confirm?};
    • has Buddy: his ChatGPT sign-in and state through his own Hermes gateway, in the Launchpad and lazurio buddy (DEV-6676 PR 1, F63) #635's admission (404 buddy-absent, the same-origin POST, 413, 415, 405, no query);
    • checks the members as the installer does (400 invalid-<member>, named whatever the file), then F64's writer writes only over revision (409 persona-changed with the persona as it is now), then F64's apply runs; it answers within 20 s with applied: {state, reason?, restart?, prompts?};
    • GET /api/buddy now also names the persona with confirmed, revision and pending.
  • What waits for Buddy, the Launchpad finishes. F64's apply restarts his gateway only once he is idle. The Launchpad applies again every 15 s while it answers waiting, later and later after a failure, and a reading that finds F64's owed prompt refresh takes it up again after a Launchpad restart. No record of its own.
  • Journal. buddy-persona lines carry the operation, outcome and reason only, never a name, a value or a revision, and one line per changed outcome.
  • Texts in messages.ts, cs and en, and the "?" of both pages (four stops in Začínáme with Buddy, two in Nastavení → Buddy).
  • docs/decisions.md: F65, with the alternatives and the honest limits.

Review of 059d6f5b (Pablo), addressed in a65f0066 (fix and tests) and d5dfabee (F65)

Blocking: an older reading took back a saved persona. A GET /api/buddy already under way could answer after a save had installed the new persona, or after a 409 had installed current. readOnce took the older answer: the name, confirmation, pending state and revision went back, and the next save sent the old revision and got an avoidable 409. The same pattern hit a sign-out Hermes confirmed, a sign-in that finished and one the Launchpad no longer held. read()'s single flight let the sign-out wait on exactly that older reading.

Now (buddy-client.ts, F65 point 10):

  • What the page learns from its own operations moves one epoch.
  • A reading begun before the epoch moved is dropped on arrival and asked again, at most three times; whoever joined it waits for the fresh answer.
  • A save's answer installs only when no later save's answer did.
  • A counter because the persona's revisions are unordered sha256s and the sign-in has no revision.
  • The server keeps no state from a reading and re-applies one at a time, so it has nothing alike.

Tests race a deferred GET against a save (Pablo's reproduction), a 409, a sign-out and a finished sign-in; answer two saves out of order; and overtake a reading every time. Removing each part of the fix fails its test.

Texts adapted from the wireframe, and why

Wireframe Here Why
"Kód platí 15 minut, zbývá 14:32." "Kód platí ještě 14:32." The page knows when the code stops working (expiresAt), not its whole lifetime
"Připojeno: ChatGPT, <e-mail>" "Připojeno" Hermes's card has no account e-mail (the shaping's H-d)
Telegram as a third part of the step, "Nepřipojeno" Not shown yet The installer may have connected his bot, and the page cannot read Hermes's Telegram state before PR 5
"Vyžaduje pozornost", "Přihlášení přestalo platit" Not used; "Buddy teď neběží" added A refused refresh cannot be told apart yet (H-a); a stopped gateway can
Settings change on every keystroke Uložit Each change is an apply, which may restart his gateway
"Přihlaste ho a řekněte mu, jak vám má říkat" (tour) "Přihlaste ho a řekněte, jak vám má říkat." A tour stop stays within a dozen words
"?" stop: what Buddy does "Buddy se přihlásí vlastním účtem a představí se" A guide step stays within nine words
— One plain line per closed reason, the "?" for a refused sign-in by code, the save errors The wireframe draws only the happy path

Lazurio's own lines say vy; only Buddy's own lines follow his ty or vy (pairs buddy…Ty / buddy…Vy). No "pomocník", no Hermes, gateway, token, model or reason code.

What deliberately does not change

Verification (at head ad7fb96a, rebased on main f85309d8)

  • bun run lint, bun run typecheck, bun run check:public: pass.
  • New tests:
    • tests/buddy-persona-save.test.ts (8): the core; read, write, 409, 400 per member, waiting retried, joined applies, an owed refresh after a restart, failures backing off, the journal without names or revisions;
    • tests/launchpad-buddy.test.ts (+2 and the persona route in admission and 404): the route over HTTP, with F64's real apply in a fixture without Hermes;
    • tests/first-run-buddy.test.ts (7): four basics with Buddy, three elsewhere; done only signed in and confirmed; the order and the not-locked AI step; tour stops, the line in Apps, the shell's "(X ze 4)" and the "?" stops;
    • tests/buddy-view.test.ts (11): the wireframe's czechNames cases; the step, the dialog's screens and Nastavení → Buddy (Stav, Jméno a oslovení) for every state and reason; a countdown that never redraws;
    • tests/buddy-client.test.ts (15): the page's sign-in and persona flows against faked routes, and readings under way that answer after a save, a 409, a sign-out or a finished sign-in;
    • tests/buddy-voice.test.ts (4): vy in Lazurio's lines, ty or vy only in Buddy's own pairs, no developer word, no "pomocník".
  • Mutation checks: 12 of 12 targeted mutations caught (the done rule, the gate, the order, the kept code, the cancel, the revision shape, the member pre-check, the retry, the read's back-off, Buddy's address, expiry, the shell total), plus 5 of 5 for the review's fix (the epoch check; the epoch move on sign-out, on a finished sign-in and on a save; the save ordering).
  • Full bun test once at ad7fb96a: 4902 pass, 10 skip, 0 fail; none of the known flakes appeared.
  • Buddy, Začínáme, routes, guide and wording test files by name at the rebased head: 541 pass, 0 fail, across 22 files.
  • Before the rebase: the full suite at b617a61c found one real failure (the Settings navigation test, fixed in 059d6f5b), and at fd120ccc only the known timeouts Flaky under a loaded full run: recover "the supervised unit through systemctl --user, and its health socket" hits the 5 s test timeout #409 and Flaky under a loaded full run: install-script "a download that differs from its manifest" hits the 5 s test timeout #191.
  • Browser check (0178), without access to Bob's Environment, run again after the rebase (Začínáme, the code dialog and Nastavení → Buddy, cs, light, 1440 px): the worktree's Launchpad in hosted mode with a personal entry that names Buddy, Buddy: his ChatGPT sign-in and state through his own Hermes gateway, in the Launchpad and lazurio buddy (DEV-6676 PR 1, F63) #635's fake gateway, and a local proxy for the gateway's Host, cookie and same-origin, driven by headless Chrome.
    • Covered: cs and en, light and dark, 1440 px and 390 px.
    • The whole path: Přihlásit Buddyho → code and countdown → Připojeno → introduction → Tykej mi switches every line → Opravit → Pokračovat → Teď ne → step done ("Upravit"), then Nastavení → Buddy → ⋯ → Odhlásit with its confirm → "Čeká na přihlášení" → rename and Uložit.
    • No error of the page in the console. The only failed loads were the harness's: update status, the latest content job, the Dashboard's account list, and Buddy's picture on his unresolvable origin, which the shell's own launcher requests too and which falls back to his initial.
    • The Launchpad is light-only by design (the design system has no dark mode yet), so dark looks like light.

Risks

  • In production, the route runs F64's apply with the real systemctl and hermes. F64's own tests cover those, and Ring 0 has not run them yet.
  • GET /api/buddy also reads persona.json and the owed marker each time: two small file reads.
  • Older shells ignore setup.buddy and keep counting three.

Follow-ups

🤖 Generated with Claude Code

@immakermatty
immakermatty marked this pull request as ready for review October 25, 2026 05:55

@agentrozjedemeai agentrozjedemeai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of PR 3 only (19623db4..059d6f5b0e109fb94a1b7b6eafe6d21aef650d80).

Blocking — src/launchpad/buddy-client.ts:103-131,261-304: a GET already in flight can finish after savePersona has accepted a new persona (or after the 409 handler has installed current). readOnce unconditionally assigns the older response to reading, reverting the newly acknowledged name, confirmation, pending state and revision in the UI. The next Save then submits the old revision and gets an avoidable 409. I reproduced this on this exact head with a deferred GET: initial revision A, acknowledged POST returns revision B, release the earlier GET with A; client.reading().persona.revision becomes A (expected B). Please guard a read against intervening persona writes/conflicts (or follow it with a fresh read), and add a test for both the successful save and the 409-current path.

Other scoped checks: route admission/validation and journal shape, bounded retry/backoff, the four-step order and non-blocking AI, closed sign-in reasons, and cs/en copy were reviewed. Focused 50/50 tests, lint, typecheck and check:public passed locally under the host lock; the extra race regression failed as described. No merge or release requested.

immakermatty added a commit that referenced this pull request Oct 25, 2026
… newer is dropped and asked again (#637 review)

Pablo's review of 059d6f5: a GET /api/buddy already under way could answer
after a save had installed the new persona, or after a 409 had installed the
current one, and readOnce took the older answer: the saved name, its
confirmation, pending and revision went back, and the next save sent the old
revision and got an avoidable 409. The same held for a sign-out Hermes
confirmed, a sign-in that finished and one the Launchpad no longer held, and
read()'s single flight let the sign-out wait on that older reading.

What the page learns from its own operations now moves one epoch. A reading
begun before it moved is dropped on arrival and asked again, at most three
times, and whoever joined it waits for the fresh answer. A save's answer is
installed only when no later save's answer was. A counter because the
persona's revisions have no order and the sign-in has no revision.

Tests race a deferred GET against a save, a 409, a sign-out and a finished
sign-in, answer two saves out of order, and overtake a reading every time;
each part of the fix removed fails its test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty added a commit that referenced this pull request Oct 25, 2026
…knows, and why a counter (#637 review)

Point 10: what the page learns from its own operations (a saved persona, a
409's current one, a finished sign-in, one the Launchpad holds no more, a
confirmed sign-out) moves one epoch; a reading begun before it is dropped and
asked again, at most three times, and a save's answer installs only when no
later save's answer did. A counter is the simplest sound order: revisions are
sha256 and unordered, the sign-in has none, and the server keeps no order of
the page's requests. The server reads files fresh and keeps no state from a
reading, so it has nothing alike. Alternatives and verification follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@immakermatty

Copy link
Copy Markdown
Contributor Author

Thanks, @agentrozjedemeai: the finding was real, and it reached further than the persona. Fixed at fd120ccc (d54a9ee2 the fix and tests, fd120ccc F65), PR 3 only, on the same base 19623db4.

What was wrong. readOnce installed whatever a GET /api/buddy answered, so an older reading could take back what the page already knew. And read() is single-flight, so a later caller could join that older reading instead of getting a fresh one. Besides your two cases (a save's persona, a 409's current), the same pattern hit three sign-in paths:

  • A sign-out Hermes confirmed: a reading begun before it brought "connected" back, and signOut() awaited exactly that reading.
  • A sign-in that finished: a reading begun before it answered none, which also ended "Připojeno" early.
  • A sign-in the Launchpad holds no more: a poll that answers none.

The fix (src/launchpad/buddy-client.ts):

  • One epoch. What the page learns from its own operations moves it: a saved persona, a 409's current, a finished sign-in, one the Launchpad holds no more, a sign-out Hermes confirmed. A reading captures the epoch when it begins. If the epoch moved before the answer arrives, the answer is dropped and the reading asked again, at most 3 times. Whoever joined the reading (the sign-out does) waits for the fresh answer.
  • Save answers are ordered. A save's answer is installed only when no later save's answer was, since two can arrive out of order.
  • Why a counter rather than the revision: revisions have no order (each is a sha256), the sign-in has no revision at all, and the server keeps no order of the page's requests. F65 point 10 records this.
  • "Signed in here" now ends only on a reading that says connected, rather than any known one.

Other state checked:

  • The 10-second re-read while a change is pending goes through the same guarded read.
  • The server side has no such pattern. persona-save.ts reads the files on every request and keeps no state from a reading, and its re-applies run one at a time and settle in start order.
  • The settings form rebuilds from the client's persona, so it no longer reverts either.

Tests (tests/buddy-client.test.ts, +6):

  • your reproduction: initial revision A, acknowledged POST returns B, the earlier GET released with A → the revision stays B, the reading is asked again, and the next save sends B;
  • the same race with the 409's current (C);
  • a deferred GET racing a confirmed sign-out, and one racing a finished sign-in;
  • two saves answered out of order;
  • a reading overtaken every time, which stops after 3 tries and keeps what the page knows.

Mutation check: I removed each part of the fix in turn (the epoch check; the epoch move on sign-out, on a finished sign-in and on a save; the save ordering). Each removal fails exactly the tests aimed at it.

Checks at fd120ccc:

No review requested and nothing merged; the PR description is updated to this head.

immakermatty and others added 7 commits October 25, 2026 12:26
… waits for him to be idle (DEV-6676 PR 3, F65)

POST /api/buddy/persona takes the page's change ({buddyName, address,
user: {nominative, accusative, dative}, revision, confirm?}) behind the same
admission as the sign-in routes (404 buddy-absent, same-origin POST, 413,
415, 405), writes it with F64's writer only over the revision the page read
(409 persona-changed with the persona as it is now; 400 invalid-<member> for
what the installer would refuse) and brings it to Buddy with F64's apply,
as lazurio buddy persona --apply does. GET /api/buddy now names his persona:
the names, whether the person confirmed them, the revision and whether a
change is still on its way (pending).

The apply restarts his gateway only once he is idle, so the Launchpad
finishes what it could not: it applies again every 15 s while he is busy,
later and later after a failure, and a reading that finds F64's owed prompt
refresh takes it up again after a Launchpad restart. Nothing is stored
beside F64's own record. The journal names the operation, the outcome and
the reason, never a name, a value or a revision.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…V-6676 PR 3, F65)

On an Osobní Prostředí whose entry names Buddy, Začínáme gets a fourth
basic first: "Seznamte se s Buddym", done only when he is signed in and the
person confirmed his names. Its dialog has the prototype's three screens:
his own ChatGPT sign-in (OpenAI's page, the code with Kopírovat, the time it
still holds, Čekám na přihlášení…, Nový kód, Připojeno), his introduction in
his own words that switch with Tykej mi (his name, ty or vy, the person's
name with the guessed forms and Opravit; Pokračovat saves with the
confirmation), and Telegram with only Teď ne for now. The tour, the line in
Apps and the shell's prompt ("Dokončit nastavení (X ze 4)") lead to Buddy
first, but the agents' AI is offered beside him, not locked (buddyGate, the
one place that decides it). Elsewhere the basics stay three.

Nastavení → Buddy shows his state (Pracuje, Čeká na přihlášení, Buddy teď
neběží) and his sign-in with ⋯ → Přihlásit znovu and Odhlásit behind a
confirm, and his name and address with Uložit, which says "Projeví se, až
Buddy dokončí, co právě dělá." while the change waits for him. The sign-in's
closed reasons get plain lines (an update first, a "?" for a sign-in by code
the account does not allow, Kód vypršel with Nový kód, a code kept on screen
while Hermes still holds it). Lazurio's words say vy, Buddy's own follow his
address; no model, command or reason code reaches the page. czechNames is
the prototype's, with its cases. The "?" of both pages explains them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st, his persona changed in place, the agents' AI not locked behind him (DEV-6676)

Records PR 3 of the Buddy onboarding: where Buddy's step, its dialog and
Nastavení → Buddy appear, when his step is done, the order that leads to him
first and the gate that keeps the agents' AI offered beside him (Q4, set as
recommended and Matěj's to decide), the persona's route over F64's writer and
apply, how the Launchpad finishes what waits for Buddy to be idle without a
record of its own, the rules of the words, and the honest limits of a check
that ran on a local harness, not yet on Ring 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(DEV-6676 PR 3, F65)

The page's Settings navigation now ends with Buddy's section, which the
page shows only on an Osobní Prostředí with Buddy; the test that checks the
navigation no longer lists Trezor names it too. The full suite found it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… newer is dropped and asked again (#637 review)

Pablo's review of 059d6f5: a GET /api/buddy already under way could answer
after a save had installed the new persona, or after a 409 had installed the
current one, and readOnce took the older answer: the saved name, its
confirmation, pending and revision went back, and the next save sent the old
revision and got an avoidable 409. The same held for a sign-out Hermes
confirmed, a sign-in that finished and one the Launchpad no longer held, and
read()'s single flight let the sign-out wait on that older reading.

What the page learns from its own operations now moves one epoch. A reading
begun before it moved is dropped on arrival and asked again, at most three
times, and whoever joined it waits for the fresh answer. A save's answer is
installed only when no later save's answer was. A counter because the
persona's revisions have no order and the sign-in has no revision.

Tests race a deferred GET against a save, a 409, a sign-out and a finished
sign-in, answer two saves out of order, and overtake a reading every time;
each part of the fix removed fails its test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…knows, and why a counter (#637 review)

Point 10: what the page learns from its own operations (a saved persona, a
409's current one, a finished sign-in, one the Launchpad holds no more, a
confirmed sign-out) moves one epoch; a reading begun before it is dropped and
asked again, at most three times, and a save's answer installs only when no
later save's answer did. A counter is the simplest sound order: revisions are
sha256 and unordered, the sign-in has none, and the server keeps no order of
the page's requests. The server reads files fresh and keeps no state from a
reading, so it has nothing alike. Alternatives and verification follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
 has every page (DEV-6676 PR 3, F65)

F56's addendum (6) (#633, rebased onto here) lets only a state stand under a
page's title and gives an empty head no room. Nastavení → Buddy had no
explanatory sentence; its one line, that there is nothing to set up without
Buddy, now sits in the page's head like Začínáme's, so with Buddy the head
takes no room. F65 point 5 says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@immakermatty
immakermatty force-pushed the agent/DEV-6676-buddy-onboarding-ui branch from fd120cc to ad7fb96 Compare October 25, 2026 11:53
@immakermatty

Copy link
Copy Markdown
Contributor Author

Rebased onto main (f85309d8, with #635 and #636 merged) and dropped the integration merge. The new head is ad7fb96a: seven commits, and the diff is only PR 3.

Conflicts: none. The hunks of #633, #630 and #638 don't overlap PR 3's. Checked after the rebase:

#633's rule (no sentence under a page title):

The stale-read fix (Pablo's review of 059d6f5b) is unchanged, now a65f0066 (fix and tests) and d5dfabee (F65 point 10).

Checks at ad7fb96a:

  • lint, typecheck, check:public: pass;
  • the Buddy, Začínáme, routes, guide and wording test files by name: 541 pass / 0 fail across 22 files;
  • full bun test once: 4902 pass, 10 skip, 0 fail; none of the known flakes appeared;
  • the browser check retaken (Začínáme, the code dialog, Nastavení → Buddy; cs, light, 1440 px). Only the harness's own resources failed to load.

The PR description now says the base is main and the diff is only PR 3. No review requested and nothing merged.

@agentrozjedemeai agentrozjedemeai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head ad7fb96. The epoch guard discards and retries an in-flight GET overtaken by a save/409/sign-in/sign-out, while single-flight callers await the fresh result; the save sequence prevents a late older answer from replacing an installed newer one. The focused race tests reproduce the prior stale-persona case and the adjacent paths. I independently ran 87 focused tests (0 failures), lint, typecheck, check:public, and git diff --check. Range-diff against the pre-rebase series preserves the four earlier PR 3 commits (only guides.ts context changed); f85309d..head changes src/buddy/ only by adding persona-save.ts, and F65 follows F64. The ad7fb96 title-state wrapper follows the existing section-head-text rule and is hidden when Buddy is present. Exact-head CI rollup is green; no unresolved threads. Note: main has since advanced to d60e511 (#629), so merge-time integration/check gates must be evaluated against that live base; this is review approval only, not a merge or release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants