Skip to content

Přestavba na upstream T3 Code v0.1.3 - #137

Open
immakermatty wants to merge 548 commits into
mainfrom
lazurio/rebuild-v0.1.3
Open

immakermatty wants to merge 548 commits into
mainfrom
lazurio/rebuild-v0.1.3

Conversation

@immakermatty

@immakermatty immakermatty commented Oct 28, 2026 •

Copy link
Copy Markdown

Status: ready for review / approved. Pablo APPROVED head 6f04174a49 in round 2 (2026-10-28 16:16:53 UTC, after the head commit). The swap waits for the macOS arm64 archive job: it has had no GitHub runner in three attempts; attempt 4 is queued in run 40715377422. Then main swap (stage 6), preview and Ring 0 (stage 7) after the Example canary.

Rebuild of the Lazurio overlay onto upstream T3 Code v0.1.3 (d2c44031). Tracking issue with the decision table: #136.

What it is

This branch replaces main at the swap (stage 6 of the runbook); it is never merged.

  • It is the exact upstream v0.1.3 tag, followed by one commit per overlay row in target-stack order, with row 5 last.
  • The old main (697648c0) is captured exactly by the immutable stable v0.1.2-lazurio.6.

What changes on the new base

Review round 1 fixes (head 6f04174a49)

Both defects also existed on the old main. They are fixed here, in the rows that own the files, with tests that fail on the old code.

  • The day pane can no longer point at an invisible Delegace wake (row 27).
    • Days, counts, previews and the first message now come only from messages the person sees.
    • The rule lives in one predicate, actingSenderVisibility.ts. It has identical server and web copies, and the contract test keeps them equal.
    • A day with only wakes is not listed.
  • A direct link to another thread no longer bypasses Buddy's one conversation (rows 25 and 28).
    • In Buddy mode, a thread on the primary Environment other than Buddy's redirects to Buddy's thread, as / does.
    • Buddy's presentation in ChatView, the thread details panel and the error banner is scoped to the thread's own Environment, so a secondary Environment keeps T3's normal behaviour.
    • A browser test opens a thread link directly.

What does not change

  • The t3 CLI surface.
  • The capabilities, model and providers outputs.
  • Session scopes and pairing; nobody pairs again.
  • Orchestration protocol 2.
  • Launcher protocol 3.
  • Node 26.12.1 and pnpm 12.14.0.

Verification (local, on this head)

  • Contract test: passes 47 of 47.
  • Allowlist guard: emulated, with no unexpected or stale entries. pnpm-workspace.yaml and pnpm-lock.yaml equal v0.1.3.
  • Typecheck: clean for server and web, and for provider-acp, client-runtime, contracts and shared.
  • Lint: clean over every changed file, with the new rules.
  • Overlay test gate, emulated:
    • server: 934 passed and 14 skipped (CDP tests need a real browser endpoint);
    • web: 1,924 passed, with browser tests on Playwright's bundled Chromium.
  • Owed on the Ring 0 canary (runbook stage 7), from the decision table:
    • the 127.0.0.1 bind;
    • the rail under the Settings modal;
    • the agent-browser tabs surviving the end of an agent;
    • the dark-mode tokens;
    • Chat through the gateway with route-bound WebSocket tickets;
    • a live Codex turn asking through request_user_input;
    • migration 069's first start.

Risks

  • Codex questions: whether the override in row 22 beats Codex's own Default-mode text is only provable on a live turn.
  • Database: migration 069 fills a message search index on first start, so a large database may start slower once.
  • Upstream workflows: three new ones (relay-preview.yml, relay-preview-cleanup.yml, stale-needs-more-info.yml) are disabled right after the swap, per the runbook.

🤖 Generated with Claude Code

Note

Rebuild on upstream T3 Code v0.1.3 with fx provider and shared source-control registry

  • Replaces GitHub-specific pull-request terminology, URL parsing, and media handling across web and mobile with the provider-agnostic sourceControlClients registry; the new source-control-definitions package aggregates the six built-in host definitions
  • Adds the fx provider package and registers its driver, client, and model defaults; adds the Muse usage reader with the Muse Code label
  • Adds the infra/task-cache build/deploy package with a remote cache (admission limits of 2 stores / 4 reads, Basic-auth developer identity, D1-backed) plus CI wiring through setup-ci-deps
  • Restructures web settings into per-page _chat.settings.* routes (beta → labs, storage → maintenance, integrations → browser) and adds guest-share flows, an inspector-based thread navigation path on iOS, and native terminal output replay (512 KiB buffer) on mobile
  • Replaces Shiki with the new t3-highlights native module (Android JNI + iOS) and the highlights engine on web
  • Risk: many package exports are removed or moved (./client/definition → ./shared/definition on all source-control packages, provider-acp drops server/coreRuntimeEvents, shared drops ./githubMarkdownLinks and four other subpaths); ThreadPullRequestWatch, TracingResource, and the terminal module interface gain required/changed fields — check in-tree consumers compile against the new shapes

Macroscope summarized 6f04174.

RetriggerView in GreptileConfidence Score: 5/5

No blocking code issue was established; the inspected changes appear safe to merge.

Summary

Rebuilds the Lazurio overlay on upstream v0.1.3, adapting updates, agent commands, and Buddy’s conversation to the new upstream APIs.

  • T3 Code now includes the v0.1.3 upstream feature set.
  • Each Lazurio thread now keeps its own browser tabs.
  • Buddy now has one focused conversation with page context.
  • Message search now uses an index for matching text.
  • Lazurio now has its own build and release path.

Acknowledged by immakermatty: macOS archive verification awaits an available runner; migration 069 may slow the first start of a large database; live Codex questions and the listed Ring 0 checks remain deferred to the canary; three new upstream workflows will be disabled after the swap.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  U["Upstream v0.1.3"] --> O["Rebuilt Lazurio overlay"]
  O --> S["Server"]
  O --> W["Web client"]
  S --> A["Advertised release"]
  A --> B["Sidebar update button"]
  B --> I["Exact-version install"]
  W --> C["Buddy conversation"]
  S --> D["Visible messages by day"]
  D --> C
Loading

Reviews (1) · Last reviewed commit: "release: Lazurio distribution" · Reviewed by Greptile

juliusmarminge and others added 30 commits October 25, 2026 17:23
…ffects (pingdotgg#25079)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…a a shared deadline clock (pingdotgg#25005)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…the budget (pingdotgg#25163)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ers (pingdotgg#25011)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ects (pingdotgg#25070)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…een effects (pingdotgg#25071)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…buses and mirrors (pingdotgg#25073)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…tView effects (pingdotgg#25006)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty and others added 13 commits October 28, 2026 07:34
…file

Each T3 Code thread keeps its tabs of the Environment browser only in its
holder file, $XDG_RUNTIME_DIR/lazurio-browser/holders/t3-<thread>.json, the
file the view's hub reads to keep a remote tab alive. The server reconciles
every file with the hub's list of live tabs (at start, on change, every 30 s
and before every write), serializes writes through one queue and never
overwrites a file it cannot read, so a restart finds the tabs intact and T3's
database stays upstream's. The web reaches a thread's tabs through
/api/lazurio/thread-tabs (snapshot, event stream, hold, release) under
upstream's preview scopes. holders.ts copies the Platform's holder helpers,
and holders.test.ts runs the Platform's vectors against the copy. One line in
server.ts joins the overlay's layer into layerMakeRoutes, where it shares the
routes' one preview broker.

On v0.1.3 the row merges cleanly: layerMakeRoutes gained GuestHttp (pingdotgg#24104)
and the PreviewAgentActivity provide (pingdotgg#25184), and the overlay line still sits
before the preview broker. Guest tokens never reach this route. ThreadTabs'
methods use Effect.fn for the new Effect diagnostics, and comments are cut to
the four-line limit; the holders.ts provenance line the contract pins stays.
threadTabs.ts and the overlay layer import row 12's threadLifecycle.ts, so
this row alone does not typecheck.
…stops its agent's daemon

threadLifecycle.ts is the one adapter between the threads' tabs and T3's
orchestration: archiving or deleting a thread retires it, which removes its
holder file and stops its agent-browser daemon over the session's socket;
unarchiving restores none of its ended tabs; at startup, files and daemons of
threads that are no longer live go too. The domain-event stream is a live
tail that can fail, so the adapter resubscribes after a failure.

On v0.1.3 the orchestrator's getShellSnapshot, getThreadShell and
streamDomainEvents keep their signatures, and getShellSnapshot({location:
"active"}) is still unpaged, which the startup sweep relies on. The new
thread.guest-share-updated event is ignored. pingdotgg#21299 now reaps the daemons of
exited Claude, ACP, Pi and Muse agents through their systemd scope, but
upstream still does nothing on archive or delete, for Codex's shared scope,
for terminals, or without systemd, and never touches holder files, so the row
stays whole. liveThread uses Effect.fn and the header comment is cut to the
four-line limit.
Where the Environment's shell defines <lazurio-new-tab> and the server keeps
the thread's tabs, "+", Mod+T and the empty right panel open Nová karta, a
tab that frames the Launchpad's /new-tab, instead of upstream's "+" menu and
empty list. A choice turns the tab into a page of the Environment browser,
which the thread holds, or opens one of T3 Code's own surfaces through
upstream's action. Its tools are upstream's "+" actions without Browser, with
the same letters, blocked under any open or closing popup; elsewhere
upstream's menu and empty state stay.

On v0.1.3 the row merges cleanly: onNewSurfaceKeyDown, the "+" action labels
and shortcuts, LAUNCHER_SHORTCUT_BLOCKING_LAYERS and the composer's
data-surface-launcher-keys contract are unchanged, and the new Settings modal
is a dialog popup, so Nová karta's letters do not fire under it. The header
comment is cut to the four-line limit, bare upstream issue numbers are
dropped, and the file's three effects (publishing the tools, the element's
choice event, the letters' keydown listener) carry justified
react-effect-budget suppressions.
…nciliation

With T3CODE_LAZURIO_FOLDER a hosted Environment's Chat starts in its Lazurio
Folder: decorators over the services orchestration-v2/runtimeLayer.ts builds
keep projects, commands and agent sessions in the Folder and offer no Scratch,
the startup adopts or creates the Folder's project through ProjectService, and
`t3 lazurio model` writes the Platform's recommended model as the Folder
project's own override. The web leaves "Add project" and "Copy prompt link"
out when every Environment is managed.

On v0.1.3 every upstream seam merges cleanly: useHandleNewThread moved into
createNewThreadHandler (pingdotgg#25366) and the managedNewThread seam moved with it;
runtimeLayer gained GuestShareService and PreviewAgentActivity (pingdotgg#24104,
pingdotgg#25184) without touching the guards. useHandleNewThread.test.ts keeps both
upstream's offline-machine block (pingdotgg#23967) and the overlay's managed-entry
block. For the new lint rules (pingdotgg#21514, pingdotgg#25099) the overlay's long comments are
cut to four lines, a bare issue number is dropped, and the guard decorators
use Effect.fn("LazurioManagedFolder.<op>") like the existing update guard.
This also adds lazurioFolder to ServerConfig, which row 6's prompt draft reads.
Root decision 0200, point 2: inside the app the distribution is "T3 Code
(Lazurio)". The build's stage label is "Lazurio", a "Lazurio" label with the
approved symbol stands beside the wordmark, previews are not called
"Nightly", and the web manifest and index.html carry the name.

On v0.1.3 branding.ts, branding.logic.ts and the manifest are unchanged
upstream; the document title moved to appInit.tsx (pingdotgg#25004) and still reads
APP_DISPLAY_NAME. Upstream's new "failed to start" screen (lib/bootError.ts,
pingdotgg#25317, pingdotgg#25345) now names the app with APP_DISPLAY_NAME in its heading and its
triage hint; its issue link and the `npx t3 triage` fallback stay upstream's,
as decided. bundledDev.test.ts copies branding.ts and branding.logic.ts beside
bootError.ts, which now imports them. The badge's comment is cut to the
four-line limit.
Root decision 0200, point 4: in the standard look the web client takes the
design system's colours, type and radii from the --lz-* tokens the
Environment's shell declares (LazurioPlatform F36). One file,
apps/web/src/lazurio/theme.css, imported right after index.css in main.tsx;
without the shell nothing matches.

On v0.1.3 the row applies cleanly. main.tsx now imports the Inter font before
index.css, and the theme import still follows index.css directly. index.css
(pingdotgg#25323, pingdotgg#25251, pingdotgg#24865 and others) removed no token the file maps; it added
guest and diff-icon tokens, which stay T3's. The default "New design"
(pingdotgg#24865) maps none of these tokens in light mode; its dark-mode surfaces stay
T3's, to be checked on canary for Environment themes with a dark variant.
…urns them on

Root decision 0201, point 4 (#46): with T3CODE_LAZURIO_FOLDER,
Codex and Claude sign in with their own CLIs from the Launchpad's Getting
started page (T3CODE_LAZURIO_TOOLS_URL). Where the web offered its own
"Continue with ChatGPT" it links to that page, the server refuses T3's own
Codex sign-in and profile import for every client, and `t3 lazurio
providers` turns the providers on and reads their sign-in again at once.

On v0.1.3 ProviderAuthService keeps the same methods, and no new way into
Codex's own sign-in appeared. CodexSetupSection.tsx moved its logic into
CodexSetupSection.logic.ts (pingdotgg#25524); the only conflict was that import
beside the overlay's, and both stay. The guard's start and importProfile
overrides use Effect.fn for the new effectFnOpportunity diagnostic (pingdotgg#25099),
and the overlay's comments are cut to four lines without bare issue numbers
(pingdotgg#21514).
The Admin's decision of 2026-10-17: a page without a T3 session asks its own
origin for a pairing credential (GET /.lazurio/chat/pairing), which the
Launchpad issues with `t3 lazurio pairing` and the operator's scopes (T3's
standard client scopes without relay:write), and exchanges it, so the person
never sees a token and a deep link keeps its place.

On v0.1.3 the row applies cleanly: bootstrapServerAuth keeps its order of
credential sources (only comments changed, pingdotgg#21514), and the scope literals,
AuthStandardClientScopes and sessionHasLegacyPermissions are identical, so
no browser paired on v0.1.2 pairs again. WebSocket tickets now name their
route (pingdotgg#24554), which pairing does not touch. The overlay's comments are cut
to the four-line limit.
… ceiling

Root decision 0210, addendum 3: an agent without a browser (Buddy over SSH,
a script) gets an MCP session with the runtime-mode ceiling that only an
approved MCP sign-in gives otherwise. `t3 auth session issue --subject
mcp-client --runtime-mode-ceiling <mode>` issues it; without the flag such a
session stays capped at approval-required.

On v0.1.3 issueSession, authenticateMcpClient and issueMcpClientSession keep
their shapes; WebSocket tickets gained a route audience (pingdotgg#24554), which does
not touch the seam. The only conflict was the comment above
MCP_CLIENT_SUBJECT, shortened upstream (pingdotgg#21514): upstream's one-line comment
stays, and the constant keeps the overlay's export, which the agent CLI and
the release contract use.
…quest, queue and events

Root decision 0210, addendum 3: Buddy, and with it every agent in an
Environment, works with T3's threads as their owner. It reads and summarizes
them, launches, messages, steers and stops them, answers their questions,
decides their permission requests and follows their changes, through `t3
thread`, `t3 request`, `t3 queue` and `t3 events`. Each command is a thin
client of the running server: T3's own MCP tools where one exists, the
person's client surface only where none does.

On v0.1.3 upstream merged its thread tools into action tools (pingdotgg#25423). The
commands keep their surface, sessions, labels and exit codes; only their MCP
calls move: `t3 queue *` calls t3_queue with list, read, edit, cancel,
reorder or promote_to_steer, `t3 request respond` calls t3_pending_request
with respond, and `t3 thread fork` calls t3_thread_transfer with fork. The
tool names are strings the compiler cannot check, so agentCli.test.ts gains a
case that drives every queue action and the fork through the real thread
toolkit; with the old names it and the respond case fail. Upstream's shell
snapshot now takes a query (pingdotgg#24648, pingdotgg#24723) and a WebSocket upgrade names its route
(pingdotgg#24554), so the connection passes an empty query and the test's /ws passes
"rpc". `send --wait` uses Effect.filterOrElse for the new
flatMapConditionalToFilterOrFail diagnostic, and the long header comments are
cut to four lines (pingdotgg#21514).
Root decision 0211: an agent asks the person through the question tool, not
only in prose. Codex offers request_user_input in Default mode only with its
feature default_mode_request_user_input; T3 turns it on for the app-servers
it starts for its threads (-c ahead of the launch arguments, so their own -c
or --disable still wins), and every turn's additional context tells the
agent to ask with it. The user's ~/.codex/config.toml is not touched (0161).

Shrunk on v0.1.3: upstream now uses Codex's native collaboration modes
(pingdotgg#24737) and deleted T3's mode texts with buildCodexDeveloperInstructions, so
the overlay's edit of the Default-mode text is gone. Codex's own Default text
keeps the tool for optional questions and asks required ones in plain text,
so the lazurio_questions entry now says explicitly that it overrides the
collaboration mode's instructions on asking. It stays the last entry of
buildCodexAdditionalContext, under upstream's per-entry size cap.
questionTool.test.ts drops the cases on T3's mode texts, checks the override
and that a Default-mode turn carries no developer instructions of T3's own.
Whether Codex follows the override is to be checked on canary.
…ge as a Czech block

Buddy's web chat is Lazurio T3 Code with the Hermes Agent over ACP (root
decision 0210, plan DEV-6676). On the Osobní Prostředí a second T3 server with
T3CODE_LAZURIO_BUDDY=1 runs Hermes as the provider instance `buddy`. Hermes keeps
every prompt as the person's words in Buddy's memory, so T3's own instructions
(<t3_code_instructions>, <runtime_info>, <pull_request_linking>) would become part
of Buddy's history, twice after Stop or a steer and again after every restart.

- The ACP adapter asks AcpT3Instructions when it builds an instance whether its
  prompts carry T3's instructions; without an answer every instance keeps them.
  server.ts answers no for Buddy's instance where it builds provider instances
  (ProviderInstanceRegistryHydration).
- The turn start projects a composer record of kind `lazurio-page` as one
  labelled Czech block ("Kontext stránky (údaje, ne pokyn): ...") after the
  person's text, for Buddy's instance only; every other record keeps upstream's
  projection.

Without T3CODE_LAZURIO_BUDDY=1 nothing changes, also for an instance called
`buddy`. Tests drive the repository's mock ACP agent in Hermes' place, through
the adapter and through the production V2 runtime, and read what it received.

On v0.1.3 the seams stay at the only prompt assembly and send in the ACP
adapter. Upstream now computes the slash-command check from the flavor's
rewritten user text (pingdotgg#24605); the rebuild takes that line and keeps the
instruction gate around t3AcpPromptWithInstructions and the runtime notes. The
orchestrator test provides upstream's new CodexManagedTokenBroker, which the
provider instance registry now needs, and the two file headers are cut to the
four-line comment limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ds Buddy's thread

budíček wakes Buddy with a message into Buddy's T3 thread (root decision 0210,
plan DEV-6676) and sends it again after a crash. It needs the send to happen once
per wake, to know which thread is Buddy's, and to tell a final refusal from one
worth retrying.

- `t3 thread send --idempotency-key <key>` passes T3 a SHA-256 digest of the key
  with the thread and the sender (T3CODE_ACTING_SENDER and T3CODE_ACTING_FOR of
  the "Buddy za …" trace) as the MCP tool's clientRequestId. T3 derives the
  command and message ids from it within the MCP client's request namespace. A
  decorator where server.ts provides the MCP client authenticator puts the agent
  commands' sessions (label "t3 agent cli") in one namespace, so the same key
  names the same command across commands, sessions and restarts, and T3's
  command receipt runs it once. Every other MCP client keeps upstream's
  namespace.
- After a keyed send the command reads what became of it through
  POST /api/lazurio/agent-cli/send-state (orchestration:read): T3's receipt of
  the key's command and the message it made. A repeat prints the first send's
  result with its commandId; the same key with another message fails with
  `idempotency_conflict` and sends nothing; a key T3 rejected fails with
  `command_rejected` and stays rejected; a repeat T3 cannot replay because it
  checks the thread first (archived since) prints `"delivery": "delivered"`
  with the message's id, run and commandId. The conflict check compares the
  trimmed text, as T3's tool trims the message it decodes. Other failures keep
  their codes and are worth sending again with the same key.
- `POST /api/lazurio/buddy/thread` finds or makes Buddy's one thread: thread
  `buddy` on the instance `buddy` in Buddy's project (~/Lazurio/.agents/buddy),
  made by a fixed command so two first asks make one thread, and brought back if
  it was archived. A thread `buddy` in another project or on another instance
  is never taken: the route answers 409 `thread-conflict`. 404 outside Buddy's
  T3 Code, 409 without Buddy's project. `t3 lazurio buddy thread --json` asks it
  as an agent command.
- `t3 lazurio capabilities` says so with "threadSendIdempotency",
  "threadSendOutcome" and "buddyThread".

The "budíček" label on the message is a claim of the "Buddy za ..." trace and
not part of this change. The end-to-end test runs separate `t3 thread send`
commands against T3's own MCP tool over the production runtime; with the raw
key, without the shared namespace, or without the conflict, rejection or
delivered branches, it fails.

On v0.1.3 the key keeps its place in row 21's `send`: the key is evaluated
first, then the message is sent through `t3_thread_send`, and `--wait` waits
only on the run of that send or of the receipt T3 replays. That replaces the
rebuilt row 21's `Effect.filterOrElse` around the send. Command ids still come
from the MCP client's request namespace and the key (stableCommandId is
unchanged), and `t3_thread_send`'s new `link` field (pingdotgg#24784) is ignored by the
result schema. The namespace decorator's `authenticate` is an `Effect.fn`, as
upstream's McpOAuth.authenticate now is (pingdotgg#25099, effectFnOpportunity is an
error), the Buddy test runtime provides upstream's new CodexManagedTokenBroker,
and the file headers are cut to the four-line comment limit.

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

@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.

@immakermatty — exact-head review of bd911a3de4ede82878610bd1c952fff653901f18. The patch stack is based on v0.1.3, the old main and stable tag match, git diff --check is clean, and the manually dispatched Lazurio Fork CI run 40652295524 is green on this SHA. Two Buddy conversation regressions still need a fix and regression coverage before the swap:

  1. [P2] Day pane can point at an invisible Delegace wake. apps/server/src/lazurio/buddySurfaceDays.ts:108-111 fetches every user-role message and :70-89 chooses the first message of each local day without excluding agent-sent wakes. But apps/web/src/lazurio/actingSender.ts:152-174 removes Delegace wakes from the timeline, while apps/web/src/lazurio/BuddySurface.tsx:559-565 jumps to that first message ID. useBuddyDayJump at BuddySurface.tsx:230-245 cannot find it and clears the request when history is exhausted. If a Delegace wake precedes the person's message that day, clicking the day never reaches the visible conversation; a wake-only day becomes a dead entry. Derive days from the same visible-person predicate (and cover wake-first/wake-only cases) rather than selecting all role=user records.

  2. [P2] A linked thread bypasses Buddy's one-conversation route. apps/web/src/routes/_chat.tsx:38-43 and apps/web/src/components/ThreadRouteView.tsx:139-146 render any ready thread route, even while the primary server is in Buddy mode. apps/web/src/components/ChatView.tsx:579 then uses unscoped useBuddySurfaceMode() to apply Buddy's steer/composer behavior to that thread; other Buddy wrappers similarly hide thread details. The mode helper explicitly scopes by environmentId when passed one (BuddySurface.tsx:58-67), and the server guard only refuses new threads/forks, not read-only navigation to a pre-existing or secondary-environment thread (buddySurfaceGuards.ts:32-59). Redirect non-Buddy targets to the canonical Buddy thread, or consistently scope all presentation/behavior to the target environment and thread ID; add a direct-URL regression test.

I did not merge, push, dispatch, or touch Ring 0. The local contract test ran 45/46 in this dependency-free temporary clone; the sole failure was module resolution (@t3tools/shared absent because node_modules was not installed), not a source assertion. CI on this exact SHA did complete successfully. The intentional rebuild conflict with main is not a finding. Ring 0 browser/runtime checks remain stage-7 work.

immakermatty and others added 8 commits October 28, 2026 16:17
… the bubble

Root decision 0210, plan DEV-6676 (row 25). With T3CODE_LAZURIO_BUDDY=1 the web
client is Buddy's surface: a header with Mattyčus, the conversation's days in a
pane where the window has room and a date line above each day's first message,
and no thread list, new thread, fork, rollback or thread details card. `/`
opens Buddy's one thread through the thread route, and a message sent during a
turn steers it; queueing is the explicit alternative. In Buddy's bubble the
surface speaks the frame's side of lazurio.buddy.* v1, written from the
protocol's description: it says it is ready, keeps the last valid page context
from its parent on the host's exact origin, and asks for its window's size from
its header and on Escape, which asks for the panel unless a dialog, menu or
list is open in the surface or something inside stopped the key (the editor
marks every Escape as handled). A day in the pane turns off following the end
first, as the timeline's minimap does, so the jump stays.

The server holds the same for every client and agent. Decorators where it builds
the orchestrator and the checkpoint store refuse forks, rollbacks, other threads
and deleting Buddy's thread, and take no checkpoints in Buddy's project, which is
the managed Folder's (T3CODE_LAZURIO_FOLDER=<Folder>/.agents/buddy) and else
~/Lazurio/.agents/buddy. A thread.create with Buddy's thread id passes only
while Buddy's thread route makes the thread (MakingBuddysThread), so a client
cannot spend the route's fixed command on a thread of its own. A startup phase
before recovery turns off continuing threads after an update, the agent
browser, and Codex and Claude, once, recorded in
<state>/lazurio/buddy-surface.json so that later choices stay.
`GET /api/lazurio/buddy/days` lists the conversation's days for the pane. The
day lines and the day jump check Buddy mode once per timeline, for the
timeline's own Environment, and the rows read it from the timeline's shared
state, so no other Environment's timeline does that work or takes a jump.

On v0.1.3 two web seams are rebuilt and one server refusal is added.

- Upstream installs the chat route's shortcuts once at app start (pingdotgg#25366
  removed ChatRouteGlobalShortcuts), so Buddy's condition joins their `when`
  in shortcuts/chatRouteCommands.ts: `isBuddySurfaceNow()` reads the primary
  server config from the app's atom registry when a key is pressed. Without it
  Shift+Mod+N on Buddy's surface would try a new thread that the server then
  refuses.
- The timeline no longer takes onManualNavigation (pingdotgg#25463); the day jump is
  called below the timeline's own navigateTimeline and passes it, and the day
  line sits beside upstream's AudioPreviewUnmountContext (pingdotgg#21363).
- Upstream's guest share of a thread (pingdotgg#24104) is refused in Buddy's T3 Code:
  thread.guest-share.open, .redeem and thread.guest-message.submit fail in the
  command guard, because Buddy's conversation belongs to a Personalspace, which
  is never shared (root decision 0091); closing a share stays possible. The
  root renders no GuestShareDialogHost on Buddy's surface. A test drives a
  guest share of Buddy's thread through the server's orchestrator.

Settings and Usage are modals over the thread now (pingdotgg#24847); the prompt-link
draft stays off Buddy's surface inside the rewritten ChatRouteLayout, and the
first-run gate stays off on NEW's slimmer root. The guards are Effect.fn
decorators (effectFnOpportunity), the two effects of BuddySurface.tsx carry
justified react-effect-budget suppressions, and the file headers are cut to
the four-line comment limit.

Any other thread of Buddy's Environment, opened by a link or a typed address,
leads to Buddy's thread as `/` does: the chat layout shows BuddySurfaceIndex,
which asks the server for Buddy's thread and replaces the address, so that
thread never renders under Buddy's presentation. A thread of another
Environment stays T3's, and ChatView and the thread details ask about the
thread's own Environment. A browser test opens such an address directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…son can remove

Root decision 0210, plan DEV-6676 (row 26). Buddy's surface shows the host
page's last valid lazurio.buddy.context as a chip above the composer, for
example "Apps /apps", with a button that removes it. While the chip is there,
a message the person writes carries the page as a composer record of kind
`lazurio-page` with a reference in its text. Buddy's T3 Code projects it for
Hermes as the labelled Czech block of row 23. An empty message carries
nothing. A removed chip stays removed for its page, also after the host visits
another page and comes back; another page brings its own chip. The page hook
takes the chat's Environment (useBuddyPage(environmentId)), so a thread of
another Environment never carries Buddy's page record.

The record is the contracts' generic UnknownContextRecord with the payload
buddyPrompt.ts reads, so no contract changes. The reference joins only the
regular send's text, and that send's context takes the record from that same
text; the queued-message edit and the plan follow-up carry no page, and the
chip is hidden while a queued message is edited. The person's words stay T3's
messageTextForSend, and the page joins a text of its own, pageTextForSend,
which only the record and the texts on the wire read: a failed send, single or
multi-model, gives the composer back the words, and the retry carries the page
the chip shows then, or none. The composer's and the sent message's
presentation registries show a page reference as a page chip in their
fallback, where T3 would call an unknown context unavailable.
buddySurfacePage.test.ts covers the record, its id, its label, the wire schema
and the empty message.

On v0.1.3 the row applies as it is. The send's snapshot still keeps
messageTextForSend as the person's words (pingdotgg#25710 touched the optimistic message
path, not the snapshot), and upstream's new approval-feedback send (pingdotgg#23657)
sends the person's words without the page, which suits approvals that Buddy
with full access rarely asks for. The chip stays above ChatComposer after the
queue moved to the timeline's end (pingdotgg#25401). Only ChatView's imports conflicted,
beside upstream's new canvas and preview-source imports, and the record's file
header is cut to the four-line comment limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r decided a request

Root decision 0210, evening addendum, point 5 (plan DEV-6676, row 27): what
Buddy writes or decides in a thread carries the visible mark „Buddy za <user>“
("Buddy for <user>"). Delegace's wake in Buddy's own thread is not shown at all,
as on Telegram (decided 2026-10-22), so the person sees only Buddy's reply.

Who a session acts as is a claim signed into its token beside the runtime-mode
ceiling (`act`), from a closed set of kinds: buddy with the user's name, or
delegace; budicek is no alias. The agent commands issue their sessions with it
when T3CODE_ACTING_SENDER (with T3CODE_ACTING_FOR and
T3CODE_ACTING_FOR_ACCUSATIVE) names one, and refuse any other value before they
read anything. The server reads it from the session alone: an MCP client's
invocation carries it, the client surface runs a dispatch as its session, and a
decorator of the orchestrator records the message or the request's resolution
in a file per thread in the T3 home, only when its own dispatch committed that
step. A replayed command id, an overlapping dispatch of the same id or a retry
takes no one else's step, and a step's first record stands. The web reads
/api/lazurio/acting-senders. The thread's rows leave out Delegace's wake and
hold an agent's message from outside the thread until the answer covers it,
five seconds at most; a server without the route, or an error, shows the thread
at once as upstream does. Buddy's message and a request Buddy decided show
„Buddy za …“. The person's own steps, T3's messages, automations and other
threads' agents get no mark and never wait. Tests: rejections before
successes, the real CLI against /mcp and the client surface through to the
route the web reads, replays on upstream's own orchestrator, the claim in the
token, and the web's label, parse and loader.

On v0.1.3 three small conflicts are resolved by intent. Upstream computes the
folded agent message's sender label once (pingdotgg#24104) and also reads it out in
the accessible heading (pingdotgg#23780); the overlay wraps that senderLabel in
LazurioActingSenderLabel on the visible fold, which is the one place the
mark goes. McpOAuth's authenticate is upstream's Effect.fn now (pingdotgg#25099), and
the client gets the one actingSender spread line there. EnvironmentAuth keeps
row 20's MCP_CLIENT_SUBJECT export. Upstream's guest attribution (pingdotgg#24104)
is a message-context record of its own and does not mark who acted for a
person, so the overlay's session claim stays. The orchestrator decorator's
dispatch is an Effect.fn (effectFnOpportunity), the two effects that ask
the server's record carry justified react-effect-budget suppressions, the
agent CLI test keeps row 21's queue and fork case beside this row's cases,
and long comments are cut to the four-line limit.

Buddy's day pane counts the messages the timeline shows: the server's day list
(buddySurfaceDays.ts) leaves out Delegace's wake and an agent's message the
record has not answered yet, by the predicate in actingSenderVisibility.ts,
which the server and the web hold as one identical file that the release
contract test keeps equal. A day that opens with a wake jumps to the person's
first message, and a day of wakes alone is not listed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Root decision 0210, addendum of 2026-10-22, point 1, and its plain-chat
addendum (HumanAndMachines/Lazurio#648; plan DEV-6676, row 28): the person
sees and hears only what Buddy writes in human words. In Buddy's surface
(lazurioBuddy) only:

- The timeline keeps the messages and what the person acts on; T3's record
  of the work stays out. While a turn runs, or work still runs after it, one
  quiet static line says "Buddy na tom pracuje…" / "Buddy is on it…". A
  failed turn shows one human line, and the thread's error banner says
  "Něco se nepovedlo. Zkuste to prosím znovu." instead of T3's text.
- None of the turn's work shows at the end of the timeline, and Buddy's
  queue holds and counts only the person's own messages, never an agent's
  such as Delegace's wake.
- The composer is a message box ("Napište Buddymu…") whose only choice is
  Hermes's Normal / Fast switch; T3 applies no model or effort to Buddy's
  sessions (AcpT3Selection) and Buddy's thread keeps full access, which the
  server guard also holds.
- The surface never shows T3's terminal or right panel, their keys stay the
  browser's, and a link in the conversation opens in a new browser tab.
- In the bubble the surface wears the host page's appearance, also over a
  saved single-appearance theme. Outside it, the composer keeps the corner
  of Buddy's launcher free (index.html, --lazurio-buddy-clearance).

The terminal and right-panel states are read inside the store selectors, so
the React Compiler keeps ChatView's panel presence values memoized
(chatViewPanelPresence.test.ts guards it, #134).

On v0.1.3 upstream moved the work banners and the queue to the end of the
timeline and removed the composer's task list (pingdotgg#25401). The work items
(childInputNow, goalNow, backgroundWorkNow) are masked on Buddy's surface
with inline conditionals in ChatView's body, where hasThreadNow, ThreadNow
and the scroll button's summary read them, so no plain function wraps a
hook result in render. buddyBackgroundWork is whether backgroundWorkNow
exists. useBuddyQueuedRunCount drops an agent's queued message from the
footer's count, which upstream's getUserQueuedThreadRuns keeps, and
buddyWorkBanners and the task-list seam are gone. useBuddyChatShortcuts
takes upstream's `!backgroundThread` condition (pingdotgg#24847), ChatTerminalDrawers
lost focusRequestId (pingdotgg#25009), the placeholder falls back to
DEFAULT_COMPOSER_PLACEHOLDER, and ReopenClosedViewShortcut stays off on the
slimmer root. T3 no longer re-applies its theme from useTheme's effect
(pingdotgg#25007, pingdotgg#25461), so the host-appearance stand-in follows every application
of T3's saved theme through subscribeRenderedAppearance; the theme tests
apply T3's stored appearance as app start does. The ACP adapter keeps the
selection gate beside upstream's flavor hook (pingdotgg#24605). Effects carry
justified react-effect-budget suppressions and comments are cut to the
four-line limit.

The error banner asks about the thread's own Environment (ChatBannerLane
passes it), so a thread of another Environment keeps T3's own text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on the person

A message sent to a thread with mode auto (t3_thread_send, t3 thread send)
always steered into a running turn. When that turn waited on the person's
answer to a question (AskUserQuestion) or an approval, steering aborted the
provider's pending permission callback; the Claude adapter then denies the
request, and the question disappeared before the person saw it
(#119).

sendToThread now loads the thread's runtime requests too, and in auto mode a
pending request makes the message queue behind the turn
(queue_after_active), the same pending-request test the orchestrator uses
before snoozing. An explicit steer or restart still goes into the turn. The
agent CLI guide says so.

On v0.1.3 the row applies as it is: sendToThread is byte-identical to
v0.1.2's, still loads runs and provider turns and still steers an `auto`
send into a steerable run, and no upstream path checks pending runtime
requests before steering (pingdotgg#21158 is still open).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ion closes

Effect RPC interrupts every fiber of a client whose socket closes. The git
stacked action ran in its stream's fiber, so a dropped connection stopped it
halfway: a commit without its push, a push without its pull request. It now
runs detached from the socket, the same pattern upstream pingdotgg#18980 gave the
server update, and the pull request link and git status refresh still run
after it. The client reports a lost transport as a lost connection rather than
a failed action; the result shows through the git status and thread pull
request link it already resyncs.

Row 31 of the patch stack (#125): allowlisted in
lazurio-fork-ci.yml and listed in the release runbook.

On v0.1.3 the row applies as it is: the gitRunStackedAction handler still
runs gitWorkflow.runStackedAction inside the RPC stream's fiber (it moved
within ws.ts), effect is still 4.0.5, and upstream's only detached progress
stream is still the self-update one. The allowlist entry and the runbook
note go to the distribution row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Row 10's gate (LazurioServerBrowser.gate, a Layer.unwrap around upstream's
ServerBrowser.layer) must keep upstream's layer memoization off a Lazurio
Environment: ServerBrowser and RunExecutionService share one
PreviewAgentActivity (pingdotgg#25184). "registers as before elsewhere" now counts
the activity's builds through a memoized sibling layer beside the gate, as
RunExecutionService uses it, and asserts one build. Layer.tap is not
memoized in effect 4.0.5 and would count every use, so the counter is a
Layer.effectDiscard merged with the activity layer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The distribution's files on the new base, upstream T3 Code v0.1.3
(d2c4403), last in the stack: CI, the
CLI archive, release and upstream watch workflows, the image, the issue
form, README, SECURITY.md, the runbook, the overlay spec, the contract
test and the rebuild's skill. They are main's files, made current for
v0.1.3 (#136).

On v0.1.3:

- CI and the contract test pin v0.1.3 and build 0.1.3-lazurio.0; the
  issue form's version example is 0.1.3-lazurio.1. Node 26.12.1 and pnpm
  12.14.0 are unchanged, so the toolchain pins hold. SECURITY.md's
  upstream section equals the new tag's policy.
- Row 29 (the backport of pingdotgg#23798) is gone: v0.1.3 contains it, and
  pnpm-workspace.yaml and pnpm-lock.yaml are upstream's. It had no
  allowlist entries.
- The allowlist is exactly what the overlay changes on v0.1.3 (101 -> 106
  entries; the emulated guard reports no unexpected and no stale entry).
  In: updateEverything.logic.ts and useUpdateEverything.ts (row 4, the
  sidebar update button now offers the advertised release, since pingdotgg#25401
  removed the composer's notice), lib/bootError.ts and bundledDev.test.ts
  (row 16, the new "failed to start" screen takes the distribution's name)
  and shortcuts/chatRouteCommands.ts (row 25, the chat route's shortcuts
  are installed at app start since pingdotgg#25366). Each has its reason in the
  group's comment.
- The fixed test gate keeps its paths, which all exist at v0.1.3;
  apps/web/src/lazurio, which it runs whole, holds
  chatViewPanelPresence.test.ts.
- The contract test's pins follow the seams that moved: the prompt link
  is captured before startAppServices() (row 6), the Settings sidebar pin
  is gone because Settings is a modal (pingdotgg#24847, row 7), the server-browser
  gate merges PreviewAgentActivity (pingdotgg#25184, row 10), the managed Folder's
  and sign-in decorators are Effect.fn (rows 15 and 18), the question
  tool's context says it overrides the mode text (pingdotgg#24737, row 22), the
  update offers pin the sidebar's advertised target (row 4), and the Buddy
  rows pin the shortcuts' condition, the guest-share refusal, the day
  jump's navigateTimeline, the folded label's senderLabel, the masked work
  items, the queue count, the composer placeholder and the host theme's
  subscription (rows 25, 27 and 28). Its comments are cut to upstream's
  four-line rule, with upstream numbers written pingdotgg/t3code#N.
- The runbook's Overlay table describes every row on v0.1.3 and notes
  row 29's removal, the Cílový stack names each row's new commit, and the
  swap step names the three new upstream workflows to disable afterwards
  (relay-preview.yml, relay-preview-cleanup.yml, stale-needs-more-info.yml).
  The overlay spec names preview_act and the queue's new place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@immakermatty
immakermatty force-pushed the lazurio/rebuild-v0.1.3 branch from bd911a3 to 6f04174 Compare October 28, 2026 15:22
@immakermatty

Copy link
Copy Markdown
Author

Thanks. Both findings are fixed on head 6f04174a492ee54d760e7942bafa816a672cffca, folded into the rows that own the files. They existed on the old main too, so this also fixes the current stable's behaviour.

  1. Delegace wake in the day pane (row 27).
    • buddySurfaceDays.ts now filters through the same visibility predicate as the timeline: actingSenderVisibility.ts, with identical server and web copies held equal by the contract test.
    • Wake-first days start at the person's message, and wake-only days are not listed.
    • Unanswered agent messages are left out, as the timeline does.
    • New cases in buddySurfaceDays.test.ts cover wake-first, wake-only and unanswered days.
  2. A linked thread bypassing Buddy's route (rows 25 and 28).
    • In Buddy mode, any thread on the primary Environment other than Buddy's renders BuddySurfaceIndex, the same path as /, which redirects to Buddy's thread.
    • The Buddy checks in ChatView, the thread details panel and the error banner are scoped to the thread's environmentId, so a secondary Environment keeps normal T3 behaviour.
    • buddySurfaceRoute.browser.test.tsx opens a thread URL directly; the redirect case fails on the old _chat.tsx.
    • Not covered: /draft/<id> on Buddy's Environment is still not redirected. The server already refuses creating threads there.

Local checks on the new head:

  • contract test 47/47;
  • t3 and web typecheck 0;
  • the allowlist guard emulation finds nothing unexpected or stale;
  • the new tests pass.

Lazurio Fork CI on the exact head: run 40715377422. Please re-review on 6f04174a492ee54d760e7942bafa816a672cffca.

@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.

@immakermatty — APPROVED on exact head 6f04174a492ee54d760e7942bafa816a672cffca (review round 2). I checked the v0.1.3 patch-stack base and target order, git diff --check, the immutable v0.1.2-lazurio.6 tag against old main, and the changed Buddy day/route logic and regression tests. The day pane now excludes recorded Delegace wakes from day/first-message selection, and a direct primary-Environment thread URL redirects to Buddy while a secondary-Environment thread keeps its own chat behavior. No unresolved review threads were present. In my isolated dependency-free clone the release contract ran 46/47; the sole failure was missing workspace package resolution (@t3tools/shared, no node_modules), not an assertion. The exact-head CI has green server/web compatibility and linux-x64 archive jobs; darwin-arm64 is still queued, so this approval is not a swap/release gate. Complete that job and the remaining runbook/Ring 0 checks before any main swap. I did not merge, push, or dispatch.

This branch has not been deployed

No deployments
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.