Skip to content

lazurio: unsent prompt draft by link from the shell - #36

Merged
agentrozjedemeai merged 3 commits into
mainfrom
agent/DEV-6639-prompt-draft
Oct 4, 2026
Merged

agentrozjedemeai merged 3 commits into
mainfrom
agent/DEV-6639-prompt-draft

Conversation

@immakermatty

@immakermatty immakermatty commented Oct 4, 2026 •

Copy link
Copy Markdown

Why

The Lazurio shell's "+ Nový modul" (new module) tile should open Chat (this fork) on the same Environment with a prepared prompt in a new thread's composer, not sent: the person reads it, may edit it, and sends it (#35, plan DEV-6639, root decision 0185 S16). Upstream T3 Code has no way to receive a prompt draft from outside, so the fork needs a small overlay entry point. It must never let an arbitrary link inject and run instructions.

Platform side: Lazurio/LazurioPlatform#160 (the Launchpad's GET /.lazurio/prompts/<id>?org=<login> and the tile's link).

What changes

  • The link carries only an id and a GitHub login, never text. The Launchpad opens Chat with lazurio-prompt=<id>&lazurio-org=<login> in the fragment. When it has a pairing link, the parameters come after the token (/pair#token=…&lazurio-prompt=new-module&lazurio-org=<login>); without one, they go on the plain origin. main.tsx takes both parameters off the address at boot (captureLazurioPromptLink), before the router or the pairing read it. The pairing token stays where upstream reads it.
  • The text comes only from this page's own origin. Once the primary environment's shell is live (its project list is complete and commands reach it; until then the link waits in memory), <LazurioPromptDraft /> in the _chat layout fetches /.lazurio/prompts/<id>?org=<login> on window.location.origin. The Environment's gateway proxies that path to the Launchpad behind the same sign-in (Machines Markdown file links are ambiguous and hide their destination pingdotgg/t3code#353). The fetch uses credentials: "same-origin" and redirect: "error". The overlay accepts only JSON lazurio.prompt.v1 with:
    • the same id;
    • a non-empty text of at most 16 KiB;
    • an absolute cwd.
  • Which project. The overlay opens a new thread in the primary environment's project whose root is exactly cwd, the Organization's root on the Environment. When there is no such project, it adds that folder as a project. This is what "Add project" does with that path, except that the folder is never created (createWorkspaceRootIfMissing: false). It is the least surprising safe behaviour: the person asked to found a module in that Organization, and the agent needs that folder as its cwd. Nothing runs and nothing is sent, and the project can be removed like any other. Opening a thread in some other project would give the agent the wrong cwd, and inserting nothing would leave the person stuck. Upstream's new-thread rule is kept: a draft the person already typed into is never reused, so a second click opens a fresh draft.
  • Nothing is ever sent. The overlay can only call setPrompt on the draft. It has no path to a turn or a queued message.
  • Anything unexpected inserts nothing and shows one error toast. This covers an unknown id, a non-Owner, a failed or redirected fetch, HTML (for example a T3 Code without the Launchpad behind it), a wrong schema or id, or a relative cwd. The toast reads "Could not open the prepared prompt — Nothing was added to the composer."
  • Seam and guard. The upstream files change in two places only: the capture call in apps/web/src/main.tsx and <LazurioPromptDraft /> in apps/web/src/routes/_chat.tsx. The rest lives in apps/web/src/lazurio/. All five files join allowed_upstream_changes under one reason comment. CI runs the overlay's tests (vp test run src/lazurio). The release contract test fails when:
    • a rebase drops the capture before the router;
    • a rebase drops the mount;
    • the text may come from anywhere but this origin, or redirects are followed;
    • the overlay gains a way to send.
  • Runbook. The overlay table gains a row, and a new section "Zadání z Launchpadu" describes the hand-off.

What does not change

  • Vanilla behaviour: without the two fragment parameters, nothing happens. A T3 Code without this overlay ignores them, because upstream reads only token from the fragment.
  • Desktop and mobile: they are upstream and never get such a link. In Electron's hash history the parameters cannot match, so the capture is a no-op.
  • No server, contract or wire change.
  • Who may get a prompt is decided by the Launchpad (today new-module only where the Environment's GitHub identity is an Owner of the Organization). The fork stays generic: a new prompt id needs no fork release.

Verified

  • vp test run src/lazurio (apps/web): 10 passed. Covered: id and login only, refusal of text/query/repeats/grammar, stripping, one-time capture, own origin with same-origin and redirect: "error", nothing on 404/network/HTML/bad JSON/schema/id/empty or over-long text/relative cwd/other origin/array, the existing project, the added project, a retry when another navigation overtook the thread, and nothing inserted when the text, project or thread is missing.
  • node --test scripts/lazurio-release-contract.test.mjs: 12 passed. The new seam test fails when the mount or the capture line is removed (checked by mutation).
  • tsc --noEmit for apps/web: clean. vp lint on the changed files: clean. vp fmt --check (whole repo): clean.
  • CI's allowlist guard reproduced locally: the upstream base 6c8fed35 is an ancestor, there are no merge commits, and no unexpected client or package path changed.
  • Browser (decision 0178), Chrome via Playwright. This fork's dev server ran with its own empty .t3. Its origin's /.lazurio/* was answered by a real hosted Launchpad preview from the Platform PR, emulating the gateway:
    • /pair#token=<one-time>&lazurio-prompt=new-module&lazurio-org=example: paired. One GET /.lazurio/prompts/new-module?org=example was sent. The Organization's folder was added as the project example_GEN3. A new thread draft opened (/draft/…) with the Czech prompt in the composer. The address carries no parameters. The server DB shows 0 messages, 0 turns and 0 server threads in that project.
    • An already paired browser with the plain-origin link: the existing project was found (no duplicate project) and a fresh draft holds the prompt.
    • lazurio-prompt=unknown-prompt: the Launchpad answered 404, nothing was inserted, and the error toast appeared.
    • No Launchpad behind /.lazurio/ (the dev server answers HTML): nothing was inserted and the error toast appeared.
    • After the review fix (wait for the primary environment's live shell), all of the above ran again in Chrome with the same results: 0 messages, 0 turns, one project per folder.
    • Screenshots: ws-d-chat-draft.png, ws-d-chat-existing-project.png, ws-d-chat-unknown.png, ws-d-chat-no-launchpad.png (synthetic Organization example).

Risks and follow-ups

  • Not yet verified on a deployed Environment: the real gateway route for /.lazurio/prompts/…?org=… from the T3 Code origin (Machines Markdown file links are ambiguous and hide their destination pingdotgg/t3code#353's grammar and query rule allow it) and a real Launchpad pairing link with the parameters. This needs a fork release with this commit, and a Platform release, on a canary Environment.
  • Release numbers. The Launchpad hands the prompt over by link only from the first fork release with this commit. Until then it uses the clipboard. It assumes 0.0.45-lazurio.2 (stable) and 0.0.45-preview.20261004.1 (preview), from chatPromptsSince in Lazurio/LazurioPlatform src/launchpad/chat.ts. If the first release with this commit gets other numbers, change that constant.
  • First-run onboarding: on a brand-new T3 Code where the welcome wizard shows, the prompt opens once the person reaches Chat in the same page load. A reload drops it, because the link is held in memory only.
  • The error toast is in English, like the rest of upstream's UI.

Refs #35. Plan DEV-6639, root decision 0185 (S16 and its addendum).

🤖 Generated with Claude Code

immakermatty and others added 2 commits October 4, 2026 10:22
The Lazurio Launchpad opens Chat with lazurio-prompt=<id> and
lazurio-org=<login> in the link's fragment (after the pairing token when
there is one). The overlay takes both off the address at boot, before the
router or the pairing read it, and accepts only an id and a GitHub login,
never text. Once the primary environment is loaded, it fetches the text from
its own origin's /.lazurio/prompts/<id>?org=<login> (the Environment's
gateway proxies that path to the Launchpad behind the same sign-in), with
same-origin credentials and redirects refused, and accepts only
lazurio.prompt.v1 with the same id, a non-empty text up to 16 KiB and an
absolute cwd.

It then opens a new thread in the primary environment's project rooted at
cwd, adding that folder as a project when there is none (as Add project
does, without creating the folder), and puts the text in the composer.
Nothing is sent: the overlay can only write the composer draft. An unknown
id, a failed or redirected fetch or an answer of another shape inserts
nothing and shows one error toast.

The seam in upstream files is two lines: the capture in main.tsx and
<LazurioPromptDraft /> in the chat layout. All five files join the
allowlist under one reason; CI runs the overlay's tests, and the release
contract test fails when a rebase drops either line, lets the text come from
anywhere but this origin, or gives the overlay a way to send.

Refs #35.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The overlay table gains the commit "lazurio: unsent prompt draft by link
from the shell" and a section "Zadání z Launchpadu" says what the link
carries, where the text comes from, which project the thread opens in, what
inserts nothing, who may get a prompt (the Launchpad decides), and which
release numbers the Launchpad treats as the first with the hand-off, to be
confirmed when that release is cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread apps/web/src/lazurio/LazurioPromptDraft.tsx Outdated
Comment thread apps/web/src/lazurio/LazurioPromptDraft.tsx
The overlay waited for every environment's shell to be bootstrapped, which
also turns true when the primary environment is disconnected without a
snapshot. Then its project list is empty, so the overlay would try to add
the Organization's folder as a new project (a duplicate when it already
exists) against an environment its commands cannot reach, and fail with the
link already taken.

It now waits until the primary environment's shell is live: its project
list is complete and commands reach it. Until then the link stays in
memory, and a reconnect in the same page load opens it.

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 APPROVED on exact head c175c2b. The link carries only prompt id and Organization login; capture strips them before router/pairing. Fetch is same-origin, redirect:error, no-store, and checks schema/id/text/cwd. The isolated overlay opens a project draft and calls setPrompt, never send. Local review ran 10 overlay tests, 12 release-contract tests and web typecheck; git diff --check clean. Required server/web compatibility and CLI archive checks are green; both review threads resolved. This approves the fork PR, not a release. The first release carrying it must match Platform chatPromptsSince (0.0.45-lazurio.2 or preview from 20261004) before enabling the Launchpad hand-off.

@agentrozjedemeai
agentrozjedemeai merged commit 6df0dfa into main Oct 4, 2026
7 checks passed
immakermatty added a commit to Lazurio/LazurioPlatform that referenced this pull request Oct 4, 2026
… the prompt hand-off

The threshold assumed the first fork release with Lazurio/t3code#35 would
be 0.0.45-lazurio.2. It now is: released on 2026-10-04 from source
1e4cf23d, which contains the overlay of Lazurio/t3code#36. The comment and
the docs say so; the threshold itself does not change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
immakermatty added a commit to Lazurio/LazurioPlatform that referenced this pull request Oct 4, 2026
… the prompt hand-off

The threshold assumed the first fork release with Lazurio/t3code#35 would
be 0.0.45-lazurio.2. It now is: released on 2026-10-04 from source
1e4cf23d, which contains the overlay of Lazurio/t3code#36. The comment and
the docs say so; the threshold itself does not change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
agentrozjedemeai pushed a commit to Lazurio/LazurioPlatform that referenced this pull request Oct 4, 2026
… the prompt hand-off

The threshold assumed the first fork release with Lazurio/t3code#35 would
be 0.0.45-lazurio.2. It now is: released on 2026-10-04 from source
1e4cf23d, which contains the overlay of Lazurio/t3code#36. The comment and
the docs say so; the threshold itself does not change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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