feat(workspace): one-line attach toast, and a /workspace Status view for the detail - #1312
Draft
ralphstodomingo wants to merge 28 commits into
Draft
ralphstodomingo wants to merge 28 commits into
ralphstodomingo wants to merge 28 commits into
Conversation
…clared vs delivered The MCP catalog now keeps the `_meta` of a server's last tools/list page per client, exposed as `MCP.listMeta(name)`. On attach, the gaps come from the engine's `ai.altimate/unfulfilled` report, grouped by reason in the toast and headless line with the engine's detail (e.g. `spawn docker ENOENT`); `no-bridge` entries stay out of the missing set as before. The attached outcome carries the full report. `MIN_ENGINE_VERSION` moves to 0.7.2, the first engine that emits it; an engine that sends none claims no gaps rather than inventing them. Closes #1307 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
Env-guarded (`ALTIMATE_ENGINE_E2E_ROOT`), skipped otherwise: spawns a built engine over stdio the way the overlay does, against a fake Altimate API and a real second MCP server, and reads the `ai.altimate/unfulfilled` report through `MCP.listMeta` into the attach toast text. The engine is a node shebang script, so the test spawns node rather than the bun test runner. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
Marker Guard flagged the changed lines in the upstream-shared catalog; the single-line marker comments did not count as a wrapped block. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
Custom (tenant-created) integrations carry numeric ids; the parser treated the whole report as malformed over that one field and the attach announced no gaps at all. Take the id as a string. Found by the engine-to-CLI run against a local backend with a custom MCP integration. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…ome settles When an attach settles — attached, engine missing, engine too old, or the engine failed to start — the CLI posts what the session received to the backend: binding identity (the same remote or path the server row holds), CLI and engine versions, bridge state, declared and delivered keys, and the engine's unfulfilled report. Once per distinct report, fire-and-forget, never on the turn's path. Engine detail strings never leave the machine: each is reduced to a code plus, for spawn failures, the command's basename. Closes #1309 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Merged
4 tasks
ralphstodomingo
changed the base branch from
feat/workspace-followups
to
feat/workspace-sidebar-status
September 15, 2026 07:58
sahrizvi
force-pushed
the
feat/workspace-sidebar-status
branch
from
September 15, 2026 09:53
313a808 to
c6f2d15
Compare
…at/workspace-status-dialog Rebuilt on 1279's rebased head (main + the 1278 squash): 1310, which carries 1308, merged first; this branch's own commits follow. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…for the detail The attach toast carried the whole engine report — every undelivered key grouped by reason, with the engine's detail — and on a workspace with a few gaps it read as noise (review of the first cut, #1311). Numbers belong in the toast; the keys and reasons belong somewhere they can be read again. - The toast says `2 of 9 integration tools available · 7 need attention. Details: /workspace` and nothing more; extension tools a live bridge serves add `· N more via VS Code`. `describeMissing` / `describeExtensionServed` go; `reasonPhrase` keeps the wording for the view. - The overlay keeps an attach snapshot per directory — workspace, engine version, the allowlist, what the engine served, its report — in memory and in `altimate-attach-snapshots.json` under the state directory, because the TUI plugin runs in another process than the overlay (the same reason the binding cache is a file). Bounded to 64 directories; a test seam keeps the suite out of the real state directory. - `status-view.ts`, transport-agnostic like `manage.ts`: the snapshot joined to the workspace's selection and the catalog, one row per integration — served / partial / missing with reasons / idle for an extension without a window — attention first, keys beyond the allowlist as extras, and the headline the toast, the menu row and the sidebar share. - `/workspace` gains a Status row (its description is the headline, read from the snapshot so the menu opens without a network call) that opens the view: one row per integration with counts and the reason, the keys and reasons as the row's footer, and "Open on the web" / "Re-read" / "Done" as action rows. A snapshot from a workspace this project was since re-linked away from is ignored. - The sidebar's Workspace tile shows the headline under the name once a session has attached, with the same staleness guard. Tests: the snapshot file round-trip, cap and corrupt-file recovery; the status view (rows, ordering, name fallback, counts matching the toast, partial and bridged states, reports for integrations no longer selected, no allowlist); the overlay's toast wording, snapshot and persistence; the e2e engine report checked through `reasonPhrase`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
The plugin's DialogSelect renders an option's footer inline with its title, which left three characters of "Altimate", and it filters `disabled` rows out entirely, so the keys under each integration never appeared. The keys are now ordinary indented rows — choosing one keeps the view open — and the engine version moves off the title (which wrapped) onto the Re-read row. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…e mode Under "What is Altimate Code", three lines that only exist in workspace mode: the mode and the workspace this project is linked to, the slash commands the mode adds (/workspace, /skills), and what the last session got from the workspace — "attach on your first message" before one, the toast's numbers with a pointer at /workspace after. - A `welcome_extra` slot inside the boot box (medium and full variants); the panel asks for the plugin runtime without throwing, so its unit tests and any provider-less render simply omit the slot. - `welcome-lines.ts`: the three lines as a pure function of the binding and the attach snapshot (unlinked, linked-before-a-session, after a session, and a snapshot from another workspace ignored), tested. - `workspace-welcome.tsx`: the plugin that fills the slot, registered only under the workspace flag like the sidebar tile, reading the two cache files on a short poll so the integrations line follows the attach. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
ralphstodomingo
force-pushed
the
feat/workspace-status-dialog
branch
from
September 15, 2026 10:00
191c091 to
a34daca
Compare
…nto feat/workspace-status-dialog Picks up 1279's review fixes: no notification on a failed cache write, poll ticks dropped mid-refresh, status reuses the resolved binding. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…hat a gap is with its own detail Answers the multi-model review of the unfulfilled report, client half. - the tools of a listing and its _meta are committed in one statement (State.meta beside State.defs) and read through one accessor, MCP.snapshot(name): a refresh that is pending or that failed leaves the last good pair standing, and the overlay can no longer pair one listing's tools with another's report - the catalog commits _meta when a listing completes — the last page that carries one wins, a listing with none clears it — instead of clearing at the start - served counts compare the declared keys in the catalog's sanitised key space, so the headline cannot undercount a served tool whose raw key the MCP layer renamed - the missing line groups by reason AND integration, so one integration's error is never printed as another's - spawn-failed reads 'server could not be started or reached', which is what the engine records under it Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
… feat/attach-report-post Picks up the multi-model review fixes on the unfulfilled report: tools and _meta committed together (MCP.snapshot), sanitised served counts, per-integration gap details, the spawn-failed phrase. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…at/workspace-status-dialog Carries 1308's review fixes through 1310. This branch keeps its own presentation (reasonPhrase and the Status view; no describeMissing), so the conflicts resolve to this side; the spawn-failed phrase and the sanitised served counts are taken up here too, in the welcome lines, the status view, the sidebar and the attach report. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…er counts a reported key Answers the Codex round on the report fixes: - McpCatalog.defsWithMeta returns the listing and its _meta as one value, and every commit of a listing stores that pair — not a per-client value another refresh may have overwritten while this one was awaiting - served counts exclude keys the engine reports unfulfilled, so two raw keys that sanitise to one catalog name cannot both count as served - parseUnfulfilled rejects an entry whose detail is present but not a string, failing closed like the other fields Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
… feat/attach-report-post Picks up the Codex round on the report fixes: a listing carries its own _meta, the headline never counts a reported key, and a malformed detail fails the report closed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…at/workspace-status-dialog Carries 1308's Codex round through 1310, and applies its rule here too: a served count never includes a key the engine reports unfulfilled — in the welcome lines, the status view, the sidebar and the attach report. The merged headline test is restated for this branch's one-line toast, whose 'needs attention' now agrees in number. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
Two raw keys that sanitise to one catalog name are one callable tool however many the engine lists; served and extension counts are the number of distinct sanitised entries that are present and unreported. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
… feat/attach-report-post Picks up the per-entry served count from 1308's final Codex round. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…at/workspace-status-dialog Carries 1308's final Codex round: served counts are per catalog entry, here too in the welcome lines, the status view and the sidebar. The merged collision test is restated for this branch's one-line toast. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…nd extension groups Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
… feat/attach-report-post Picks up the cross-group collision count from 1308's last Codex round. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…at/workspace-status-dialog Carries the cross-group collision count from 1308's last Codex round; the merged test is restated for this branch's one-line toast. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…kers Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
… feat/attach-report-post Marker wrap only. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…at/workspace-status-dialog Marker wrap only. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…w as bare Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
… feat/attach-report-post Marker wrap only. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
…at/workspace-status-dialog Marker wrap only. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue for this PR
Closes #1311
Type of change
Stacking
Base is
feat/workspace-sidebar-status(#1279, the sidebar's memory and skill-sync lines), which now sits onmainwith #1278 (the/workspacemenu) merged. The sidebar tile here carries both #1279's lines and this branch's attach line, in that order under the name: integrations, memories, skills, pinned hint, URL. The branch also carries #1308 and #1310 (the engine's unfulfilled report and the attach report), because the view reads that report; their commits show in this diff until they merge tomain, after which this rebases to its own commits.What does this PR do?
The attach toast carried the whole engine report — every undelivered key grouped by reason, with the engine's detail — and on a workspace with a few gaps it read as noise. Numbers belong in the toast; the keys and reasons belong somewhere they can be read again.
2 of 9 integration tools available · 7 need attention. Details: /workspace, with· N more via VS Codewhen a live bridge serves extension tools.describeMissing/describeExtensionServedare gone;reasonPhrasekeeps the wording for the view.altimate-attach-snapshots.jsonunder the state directory, because the TUI plugin runs in a different process from the overlay (the same reason the binding cache is a file). Bounded to 64 directories; written best-effort; a test seam keeps the suite out of the real state directory.status-view.ts, transport-agnostic likemanage.ts: the snapshot joined to the workspace's selection and the catalog gives one row per integration — served / partial / missing with reasons / idle for an extension without a window — attention first, keys beyond the allowlist as extras, and a headline the toast, the menu row and the sidebar share. If the API cannot be reached the view still renders from the snapshot alone, rows named by id./workspace→ Status: the menu's first row, whose description is the headline read from the snapshot (no network before the menu opens). It opens the view: an integration row with counts and the reason, muted sub-rows for its keys (gaps with reasons first, then what is available, capped), and Open on the web / Re-read / Done as action rows. A snapshot from a workspace this project was since re-linked away from is ignored.welcome_extraslot — the mode and the linked workspace, the slash commands the mode adds (/workspace,/skills), and the integrations line: "attach on your first message" before a session, the toast's numbers with a pointer at/workspaceafter. Unlinked projects get the link command instead. The panel asks for the plugin runtime without throwing, so provider-less renders (its unit tests) omit the slot.Claims
engine-overlay.test.ts, every announce case).statusHeadlineandattachSummaryderive served / declared / gaps / extServed the same way from the same snapshot (status-view.test.ts"counts match the toast").attach-snapshot.test.ts; verified live: the menu row shows the counts in the TUI process).welcome_extrais registered only under the workspace flag, and an empty slot renders nothing.Residuals
Integration N: the catalog read is the built-in list; the custom list is a second call not made here.runprints nothing on a settled attach, as before; the one-line summary is the TUI's.How did you verify your code works?
bun run typecheckclean inpackages/opencode,packages/tuiandpackages/plugin;test/altimate/workspace+test/mcp/engine-unfulfilled.e2e.test.ts: 486 pass (new:attach-snapshot.test.ts,status-view.test.ts,welcome-lines.test.ts; updated: the overlay announce cases,engine-types, the e2e report check);packages/tuiwelcome-panel.test.tsxstill passes without a plugin runtime.2 of 7 integration tools available · 5 need attention. Details: /workspace; snapshot file written;/workspace→Status 2 of 7 integration tools available · 5 need attention; the view lists GitHub and Jira (no usable connection), the custom and retired integrations (no longer in the catalog), Altimate (available keys), Power User (via VS Code); the sidebar tile shows the same line under the workspace name.Screenshots / recordings
Terminal captures from the local run (200-column window).
The toast on the first prompt:
/workspace, with the Status row first:Status:
The boot box in workspace mode, before and after the first message (right column):
The sidebar's Workspace tile after the attach:
Checklist
🤖 Generated with Claude Code
https://claude.ai/code/session_01GHBUvb843k1R7UAGi8Ya9b
Summary by cubic
Replaces the attach toast’s full engine report with a one-line summary and adds a
/workspaceStatus view for integration details. Attach gaps now come from the engine’sai.altimate/unfulfilledreport, requiring engine version 0.7.2; older engines receive the upgrade offer instead of attaching without gap data. Closes #1307, #1309, and #1311.Details
MCP.snapshot, counts distinct sanitized tools once, and accepts numeric integration IDs.Written for commit dc155e2. Summary will update on new commits.