Status: planning
Date: 2026-08-06
Audience: maintainers shipping Desktop + VS Code from one UI and one host
This plan turns the “cannot finish from altai-vscode alone” list into a
sequenced, multi-repo program with owners, deliverables, acceptance gates,
and explicit dependency order. It does not allow placeholder buttons, UI forks,
or secrets in the Webview.
Related:
- ENGINEERING_PLAN.md (architecture rules)
- ALTAI_ARCHITECTURE_OVERVIEW.md (component map)
- PROTOCOL_COMPATIBILITY.md (version pins)
- RELEASE.md (channels / checklist)
- FEATURE_MATRIX.md (current G/Y/R)
| Symptom in VS Code | Real missing piece | Not fixed by… |
|---|---|---|
| Apply / Deny on edits | Rust host must write (or reject) file changes with a stable proposal id | Webview-only buttons |
| Desktop-identical Chat | Full AiSidePanel tree must live in @altai/agent-ui and Desktop must use it |
Copying Desktop JSX into vscode |
| Skills install UI | Host RPC: list / install / enable skills | Fake settings toggles |
| Real token numbers | Host already emits usage events; hosts must map + UI must accumulate | Hard-coded “live / n/a” forever |
| Multi-project switch | Product model: project/workspace target (Desktop has it; stdio host does not export it fully) | Chip that only reveals Explorer |
| Full markdown | Shared renderer in @altai/agent-ui (or agreed host message segments) |
One-off VS Code markdown parser |
npm @altai/* packages |
Org NPM_TOKEN + publish job in altai-app |
Keeping eternal file: siblings |
| Marketplace + signed host | VSCE_PAT, release soak, optional signing beyond sha256 | Local VSIX only |
| CI queued / flaky Actions | Org runners, budget, status API health | Admin-merging forever |
Rule: each wave ends with capability advertised only when the backend exists, then VS Code enables the control. Never enable first.
- Desktop and VS Code render the same
@altai/agent-uiChat/Operations/Settings tree from published (or pin-tracked) packages. - Every PRODUCT control below works end-to-end on Desktop and
altai-cli serve --stdiowith the same protocol major. - VS Code is only: trust, spawn host, VS Code editor adapters, Webview bridge — no second chat.
- Internal → alpha → beta → stable follows RELEASE.md; FEATURE_MATRIX yellows become green where in scope.
- Ownership
- Product UI, protocol, Rust host, IsanAgent integration →
altai-app - VS Code adapter + packaging pin →
altai-vscode - Tokens, Marketplace, Actions runners → org / release engineering
- Product UI, protocol, Rust host, IsanAgent integration →
- One PR / one acceptance gate per wave step (same as current cadence).
- Capabilities before controls (ENGINEERING_PLAN §3.3).
- Desktop must stay green after every extract or protocol change.
- Stdio parity: if Desktop can do it,
serve --stdioeither supports it or explicitly advertisementsdeferred— never silent “almost”.
Wave 0 Org foundations (tokens, CI health)
│
Wave 1 Protocol + host: edit proposals (Apply/Deny)
│
Wave 2 Protocol + host: usage meters, MCP/skills surfaces
│
Wave 3 Protocol + host: project targets (multi-project)
│
Wave 4 Shared UI extract: AiSidePanel → @altai/agent-ui (pixel path)
│
Wave 5 VS Code thin host: wire capabilities + drop dual chrome
│
Wave 6 Rich content (markdown) inside shared UI
│
Wave 7 Publish packages + Marketplace + release soak
Waves 0 can start in parallel with 1.
Waves 1–3 are host-first.
Wave 4 is mostly altai-app.
Wave 5 is altai-vscode (short once capabilities + UI exist).
Wave 6 can partially run after 4 is stable.
Wave 7 needs 4+5 green + Wave 0 secrets.
Owner: release engineering / org admin
Repos: altai-app, altai-vscode, GitHub org, npmjs / VS Marketplace
| Secret | Where | Used for |
|---|---|---|
NPM_TOKEN |
altai-app repo + org |
Publish @altai/host-contract, @altai/agent-ui, protocol packages |
VSCE_PAT |
altai-vscode repo |
vsce publish --pre-release / stable |
| GitHub Actions billing / concurrency | org | Unblock long queued jobs and failed action downloads |
Acceptance:
- A dry-run publish workflow authenticates to npm (no public tag required).
- A private PAT can list
vscepublishers foraltaidevorg. - Sample PR CI leaves
queuedwithin budget (e.g. < 10 min start).
- Pin official
actions/*to SHAs; retry policy on transient GitHub 502. - Separate required checks:
quality+verifyonly; smoke optional until host matrix is green. - Document “local verify is source of truth when GitHub Actions API is down” for maintainers — temporary; not a substitute for required checks after 0.1.
Acceptance: three consecutive PRs to altai-vscode have non-flaky quality green without admin force-merge.
Owner: altai-app (Rust + protocol + Desktop bridge)
Consumer later: altai-vscode Chat change-review panel
VS Code can open and dismiss edit diffs. Apply is withheld because
capability review.editProposal is deferred and applyEditProposal /
denyEditProposal are not wired to a durable host operation.
Deliver:
- Stable types, e.g.
EditProposal { id, chatId, runId?, path, kind, originalHash?, proposedContent or ref }. - Methods already sketched:
review.applyEditProposal(id),review.denyEditProposal(id). - Capability
review.editProposal: availableonly when both RPCs exist.
JSON-RPC (illustrative names — match final protocol table):
| Method | Direction | Notes |
|---|---|---|
review/proposals/list |
client → host | Optional; or proposals stream via run/event |
review/proposals/apply |
client → host | Idempotent by proposal id |
review/proposals/deny |
client → host | Idempotent |
Acceptance: contract tests green; capability matrix updated; no desktop-only types.
Deliver:
- Create proposal records from agent edit tools / plan queue (same source Desktop uses).
- Apply: write workspace file under policy + permission mode; record checkpoint/snapshot side-effect; emit lifecycle/journal event.
- Deny: drop proposal; optional journal marker.
- Reject duplicate apply/deny with stable error codes (
already_applied,unknown_proposal). - Permission modes: plan / ask / allow respect existing policy (no bypass without confirmation path).
Acceptance:
- Stdio integration fixture: start run → proposal event → apply → file on disk matches → deny path covered.
- Desktop uses the same service path (not a second Tauri write path).
-
capabilitiesdocument advertisesreview.editProposalonly after methods respond.
- Map UI Apply/Deny to ReviewPort (not direct FS).
- Screenshots / regression on review centre.
Repo: altai-vscode
- Implement
applyEditProposal/denyEditProposalincreateVsCodeHostPorts. - Advertise capability when native methods present.
- Mount PlanDiff / existing panel with Apply/Deny only when capability is on.
- Remove “requires future capability” copy; keep dismiss as local UX.
Acceptance: one trusted-workspace smoke: agent proposes edit → Apply → file open in VS Code reflects content; reload does not re-apply.
Unlocks: product review workflow (TASK-011 remainder).
Owner: altai-app host + event bridge; thin VS Code follow-up
Fact: journal / serve already carries usage payloads (prompt_tokens,
completion_tokens, total_tokens, cache fields). Gap is mapping + UI.
Deliver:
- Stdio: ensure every IsanAgent usage event is forwarded as
run/eventwith typeusage(no drop under serve). - host-contract: ensure
AgentEventtype includes usage; document fields. - agent-ui / Desktop: shared run meter accumulation (mirror Desktop
agentEventBridgeusage case). - VS Code:
- map usage in
mapRunEvent; - accumulate into Run details (
RunOverviewCardtoken label); - never invent totals when events missing.
- map usage in
Acceptance: live run shows non-zero total tokens on Desktop and VS Code for the same model call; reload restores last totals if journal replay is used.
Deliver:
- Finalize stdio methods:
mcp/servers/list, configure, enable, restart (and tools visibility if product needs it). - Advertise
mcp.list/mcp.configureconsistently. - Shared Settings or inspector for MCP (prefer extract into agent-ui Settings later).
- VS Code: keep capability-gated
ChatMcpStatusChrome; add Settings page when shared Settings exists (Wave 4/5).
Acceptance: list ≥1 server on a fixture host; restart does not leak secrets into logs.
Deliver:
- Stdio:
skills/list(and install / enable if Desktop has them). - Capability
skills.list/skills.install. - Ports: implement
listSkills,installSkill,setSkillEnabledon both Tauri and stdio adapters. - UI: skill chips / install only when capabilities available (shared Settings preferred).
Acceptance: list skills on Desktop and VS Code; install path tested with a safe fixture skill; untrusted workspace cannot install.
Unlocks: real tokens; MCP/skills product status (TASK-012 portions).
Owner: product + altai-app host; VS Code uses single open folder as default
Decide in writing:
- A — VS Code first: project target is the trusted workspace folder set (no GitHub clone picker in v1).
- B — Desktop parity: host stores “ALTAI project” (local path or GitHub) independent of editor folders.
Recommendation for first unlock: A, then optional B as later epic.
- Extend
WorkspaceInfoor addProjectTarget { kind: local|github, name, path?, remote? }. - RPC optional:
workspace/setTargetonly if B ships; otherwise read-only from VS CodeworkspaceFolders.
- Chip stays informational + reveal (already shipped).
- Multi-root: target = first folder or user-picked folder via QuickPick (Extension Host only); host root list kept in sync on folder change.
- Events:
workspace.folderschanged → re-initializeor notify host of roots.
- Keep existing project UI; implement via shared ports so VS Code can later attach remote projects only when remote FS + host support exist.
Acceptance (A): multi-root workspace: user picks target root; agent runs relative to that root; change folders refreshes chip without dead controls.
Unlocks: honest multi-folder UX; foundation for GitHub projects if B is approved.
Owner: altai-app (TASK-007)
This is the longest critical path for “feels like Desktop”.
Move / finish ownership inside packages:
| Package | Content |
|---|---|
@altai/host-contract |
ports, capabilities, types (already) |
@altai/agent-ui |
full Ai side panel tree: chat, composer, history, Work, Inbox, settings slices, inspector, review centre |
(optional) @altai/agent-protocol |
framing if not already published |
Rules from ENGINEERING_PLAN:
- Desktop imports package source, no leftover dual tree.
- No
vscode/@tauri-appsimports insideagent-ui. - Stores either: (a) live entirely behind ports, or (b) thin package stores fed only by host adapters.
- Leaves already partially shared (composer shells, banners, review rows) — done-ish.
- Transcript + event store behind adapter interfaces.
- AiInputBar (attachments, slash, voice optional).
- AiChat / side panel chrome (tabs, history, empty states).
- Work / Inbox / Settings panels already partly on ports — complete settings MCP/skills pages.
- Visual regression Desktop: light/dark/HC + key chat states.
- Desktop build uses only package paths for panel.
- Desktop test + manual smoke green.
- Package version bumps with changelog.
- No second chat component remains in Desktop app sources for side panel.
Unlocks: true pixel-parity path for VS Code (TASK-008 becomes “thin host mount”, not reimplement).
Owner: altai-vscode
Depends on: Waves 1–4 for full product; partial mounts can land earlier.
- Replace/keep
file:links initially; switch to npm versions after Wave 7.1. - Delete VS Code-only chat widgets that duplicate shared surfaces once package exports a full shell (progressive: do not leave two composers).
| Port area | Must be parity with Desktop |
|---|---|
| runtime | start/steer/cancel/retry/queue/compact/replay/approvals |
| sessions | full list/create/rename/archive/delete/messages/truncate |
| workspace | info, files, selection, search, open, diff, git, terminal, external |
| review | checkpoints + edit proposals |
| settings | providers, models, permission, MCP, skills |
| work / inbox | existing Operations |
| events | including usage |
createVsCodeHostPortsadvertises only what native supports.- Visual inventory: no button without capability test.
- Optional snapshot test: capabilities JSON fixture.
- Shared tokens already map to VS Code CSS variables — re-verify after full shell mount.
- Light/dark/high-contrast smoke checklist.
Acceptance: side panel entry points to shared AgentUiShell / equivalent package root; chrome-only stubs gone for Chat; Operations remain capability-gated.
Owner: @altai/agent-ui (prefer), both hosts auto-benefit
- Assistant/user message bodies: headings, lists, tables, italics, safe links, code fences (sanitized).
- Keep existing path/
file:///openExternalsegmentation or fold into one renderer with host callbacks for open. - XSS: render in sandbox / sanitize; no raw HTML execute.
- Full mail client / arbitrary remote image fetch without CSP plan.
Acceptance: shared snapshot tests; Desktop + VS Code screenshot of sample messages match within theme difference only.
Owner: release eng; depends Wave 0 + packages stable
- Semver:
host-contractfirst, thenagent-uidepending on it. - CI job
publish-packageson tagspackages-v*. - Document consumption in PROTOCOL_COMPATIBILITY.
altai-vscodePR:file:→^x.y.z+ lockfile.
Acceptance: clean machine npm i + npm run verify without sibling checkout.
- Already sketched in
release.yml/ PIN: buildaltai-cli --releaseper target; stage sha256. - Optional: detached signatures beyond sha256 (Y status).
| Channel | Action |
|---|---|
| pre-release / alpha | vsce publish --pre-release with VSCE_PAT |
| stable | drop "preview": true only after matrix green |
Follow RELEASE.md checklists (trust, remote smoke, secrets).
- Required checks without admin merge exception.
- Nightly remote SSH job (optional runner labels).
Unlocks: yellow FEATURE_MATRIX cells for org publish; external install without local sibling.
Assuming one engineer on host/UI and 0.25 FTE org:
| Wave | Rough order | Relative effort |
|---|---|---|
| 0 Org + CI | week 0 (parallel) | small / external |
| 1 Edit proposals | weeks 1–2 | medium–large |
| 2 Usage + MCP/skills host | weeks 2–3 | medium |
| 3 Project target decision + multi-root | week 3 | small–medium |
| 4 Full UI extract | weeks 4–7 | large |
| 5 VS Code thin mount | weeks 7–8 | medium |
| 6 Rich markdown | week 8–9 | small–medium |
| 7 Publish + Marketplace | week 9+ | org + release |
Two engineers (host + UI): compress Wave 4 with Wave 1–2 parallelization after contracts freeze.
[ ] Repo ownership correct (altai-app vs altai-vscode vs org)
[ ] Host RPC or package first; UI second
[ ] Capability advertised only when RPC green
[ ] Desktop smoke still green (if altai-app)
[ ] npm run verify / cargo test relevant
[ ] CHANGELOG + PROTOCOL_COMPATIBILITY if version pin moves
[ ] VS Code pin update only after host pin staged
[ ] No secrets in Webview / logs
[ ] One acceptance gate in PR body
| Unblock item | Wave | Primary repo | Status |
|---|---|---|---|
| CI Actions reliability | 0 | org + both | open |
| NPM_TOKEN / package publish | 0 + 7 | org + altai-app | open |
| VSCE_PAT / Marketplace | 0 + 7 | org + altai-vscode | open |
| edit Apply/Deny | 1 | altai-app → vscode | in progress — review/proposals/* on stdio host; VS Code Apply/Deny when capability present |
| Real token meters | 2 | altai-app → vscode | in progress — vscode accumulates usage events into Run details |
| MCP full product surface | 2 + 4/5 | altai-app → vscode | open (list cap partial) |
| Skills install UI | 2 + 4/5 | altai-app → vscode | open |
| Multi-project / multi-root target | 3 | product + both | open (reveal-only today) |
| Full AiChat pixel parity | 4 + 5 | altai-app → vscode | open |
| Rich markdown | 6 | agent-ui | open (light segments today) |
| Signed host beyond sha256 | 7 | org | open (optional) |
- Land Wave 1 PRs:
altai-appreview/proposals/*+ protocol allow-list; thenaltai-vscodeApply/Deny wire-up against a host binary that advertises the methods (rebuildaltai-clifrom the Wave 1 branch). - Org: create
NPM_TOKEN+VSCE_PAT; fix Actions concurrency (Wave 0). - altai-app: Desktop PlanDiffReview →
ReviewPort.applyEditProposal(stop writing files only from the frontend plan store). - altai-app: inventory AiSidePanel import graph for Wave 4 extract.
- altai-vscode: no large chrome PRs until Wave 2 usage/MCP/skills caps land, except small host mapper prep.
vscode.devpure web (no native host) — FEATURE_MATRIX R- Second chat frontend in VS Code
- Bypass permission mode without product policy
- Shipping Apply before host apply is real
When this plan completes, installing the Marketplace extension starts a pinned
altai-cli serve host, loads shared @altai/agent-ui, and runs the same
Chat/Work/Inbox/Settings experience as Desktop: edits can be applied with
durable proposals, tokens are real, MCP and skills are manageable, multi-root
targets are honest, packages come from npm, and CI + release channels no longer
require maintainer admin merges or sibling checkouts.