Skip to content

feat: post-scan Workspaces prompt + altimate-code link subcommand - #1099

Draft
sahrizvi wants to merge 2 commits into
mainfrom
feat/agent-workspaces
Draft

feat: post-scan Workspaces prompt + altimate-code link subcommand#1099
sahrizvi wants to merge 2 commits into
mainfrom
feat/agent-workspaces

Conversation

@sahrizvi

@sahrizvi sahrizvi commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the CLI half of Workspaces (server-side epic AI-8390): after a project scan completes, the TUI offers to create or link an Altimate workspace. Also adds an on-demand altimate-code link subcommand for the same flow at any time.

  • TUI plugin (packages/opencode/src/plugin/tui/altimate/workspace.tsx) — fork-owned single file, wired through the existing altimateTuiPlugins() aggregator. Renders three dialogs: Create-or-Link-or-Skip, Already-linked (with drift + unverified-cache flags), and a picker over the user's workspaces. Post-scan trigger uses a one-shot session.idle listener so the dialog opens after the LLM's onboarding menu finishes streaming (not while it's still generating).
  • altimate-code link subcommand — picker-first UX (currently-linked row marked, "+ Create new" as the first row, auto-named from the git repo or directory basename). Shares the WorkspaceApi client + state cache + project-identifier detection with the plugin so the two entry points can't drift.
  • Project identity is repo_remote when a git remote is present (stronger — survives directory moves), else the absolute symlink-resolved project_path. Neither is required to be non-null in isolation, but at least one must be present.
  • Local binding cache at ~/.local/share/altimate-code/altimate-workspace-bindings.json, chmod 0o600, scoped to (tenant, apiUrl) so an account switch invalidates the file. Server is always authoritative; the cache is offline fallback with a mandatory "unverified" render flag.
  • Skip latch persists across sessions via TuiPluginApi.kv — 7-day rolling suppression keyed on sha1(repoRemote ?? projectPath). The subcommand deliberately bypasses it (user-initiated).
  • Feature flag Flag.ALTIMATE_WORKSPACE — off by default; existing onboarding behavior is unchanged when unset.

Talks to datamate-project-bindings/* endpoints on altimate-backend (see the paired backend PR).

Test plan

  • bun turbo typecheck — clean
  • bun test test/altimate/plugin/workspace.test.ts — 18/18 (including the new path-only latch case)
  • bun test test/altimate — 4047 pass, 10 pre-existing sample_setup timeout failures unrelated to this change
  • Manual smoke against a real backend for both the post-scan and on-demand paths
  • Manual smoke against a project with no git remote (the reason for the path-based fallback identifier)

Fork markers

All fork-only code is wrapped in altimate_change start / altimate_change end markers or altimate_change - new file, per the ADR at docs/internal/2026-06-23-tui-fork-features-as-plugins-adr.md. Zero edits to packages/tui/**.

🤖 Generated with Claude Code

https://claude.ai/code/session_016H42Vt4pt5dcD7opRqckeM


Summary by cubic

Adds a post-scan TUI prompt to create or link an Altimate workspace and a new altimate-code link subcommand for the same flow on demand. Previously there was no linking flow; now, when Flag.ALTIMATE_WORKSPACE is enabled and Altimate is configured, the dialog opens after the session goes idle; existing onboarding is unchanged when the flag is off.

  • Review notes

    • Feature flag: Flag.ALTIMATE_WORKSPACE (off by default). packages/opencode/src/altimate/plugin/onboarding-telemetry.ts arms a one-shot listener and publishes altimate.workspace.postScan after session.idle via EventV2Bridge to avoid racing LLM streaming.
    • TUI plugin: packages/opencode/src/plugin/tui/altimate/workspace.tsx registers altimate.workspace.postScan and altimate.workspace.link. Dialogs: Offer (Create/Link/Skip with 7‑day latch in api.kv keyed by repo remote or project path), AlreadyLinked (drift + unverified flags), and Picker. No changes to packages/tui/**.
    • CLI: packages/opencode/src/cli/cmd/link.ts and registration in packages/opencode/src/index.ts. Picker-first UX with “+ Create new” and a marker on the currently linked workspace; opens the manage URL on create.
    • Shared modules under packages/opencode/src/altimate/workspace/: api-client.ts (typed errors, 15s timeout, per-call credentials), detect.ts (project identity {repoRemote?, projectPath}; reuses exported stripGitRemoteCredentials), and state.ts (local cache scoped to tenant+apiUrl under Global.Path.state, chmod 0600). Server is authoritative; cache is offline fallback and renders “unverified”.
    • Backend contract: /datamate-project-bindings/* (create/bind/rebind/get-by-remote-or-path) and /datamates/ list. Handles 409/412/404/403 with typed errors; rebinds use remote-first identity.
  • Rollout

    • Enable by setting the experimental flag ALTIMATE_WORKSPACE.
    • Requires backend endpoints /datamate-project-bindings/* and /datamates/.
    • No migrations. BYOK users must be signed in to Altimate; otherwise the feature is skipped.
    • Manual smoke: post-scan prompt and altimate-code link in projects with and without a git remote.

Written for commit 76de5a9. Summary will update on new commits.

Review in cubic

Haider and others added 2 commits August 12, 2026 23:06
Adds the CLI half of the Workspaces pilot: after the first-run scan
completes and the CLI is authenticated with Altimate, prompt the user
once to create a new workspace or attach the project to an existing one.
The link is a direct authenticated call — no device flow — and the
browser opens after create so the user can configure integrations /
knowledge in the SaaS.

Fork-owned TuiPlugin per docs/internal/2026-06-23-tui-fork-features-
as-plugins-adr.md: single file at
`packages/opencode/src/plugin/tui/altimate/workspace.tsx`, added to
the existing `altimateTuiPlugins()` aggregator. Upstream
`packages/tui/**` stays byte-for-byte upstream. Uses the real
`api.ui.*` / `api.keymap.registerLayer` / `api.state.path.directory`
/ `api.kv` (persistent) surface.

Shared modules under `packages/opencode/src/altimate/workspace/` so
the plugin and the `altimate link` subcommand can't drift on request
shape or error handling:

- `api-client.ts` — typed errors (Conflict/Precondition/NotFound/
  Forbidden/NotConfigured/Api), FastAPI `{"detail": {...}}` parsing,
  15s abort timeout, credentials re-read on every call so an account
  switch is picked up without restart.
- `detect.ts` — `detectProjectRemote` + `projectNameFromRemote`;
  reuses `stripGitRemoteCredentials` (now exported from
  `project-scan.ts` so the two callers can't drift).
- `state.ts` — local binding cache scoped to (tenant, apiUrl) with
  atomic write + post-write `chmod 0o600` + corruption recovery.

Trigger: `onboarding-telemetry.ts` `tool.execute.after` hook publishes
`TuiEvent.CommandExecute` with `"altimate.workspace.postScan"` when
`project_scan` completes, gated on the new `Flag.ALTIMATE_WORKSPACE`
and `AltimateApi.isConfigured()` (BYOK users are silently skipped —
no place to send them). Never blocks onboarding on a publish failure.

Server-authoritative pre-check via `GET /datamate-project-bindings/
by-remote`; local cache used only as an offline fallback, and the
fallback path renders a mandatory "unverified" banner rather than
silently trusting stale data. Browser-open failure surfaces a
copyable-URL toast rather than swallowing silently.

7-day Skip latch lives in `api.kv` keyed by SHA-1(remote) — UTC
rolling window; `altimate link` (user-initiated) deliberately
bypasses the latch.

New `altimate-code link` subcommand runs the same three-way flow
outside a TUI session via `@clack/prompts` for scripting / catch-up
after a Skip. Bails early with helpful messages when credentials
are missing or no git remote is set.

Tests: 17 unit tests covering project-name parsing, git detection
graceful failure, cache read/write + chmod + tenant-scoping (account-
switch invalidation), and Skip latch TTL semantics with UTC boundary.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q8FGy89Qpr39k8nCSpCcK2
…prompt

Two user-flagged issues on the Workspaces post-scan prompt landed in
7c7e17f:

1. Post-scan dialog raced the LLM's onboarding-menu streaming — the
   dialog painted while text was still generating, and Enter didn't
   register until streaming finished. Fix: arm a one-shot `session.idle`
   listener via `EventV2Bridge` from `onboarding-telemetry.ts` and
   publish `TuiEvent.CommandExecute` only after the session settles.
   Costs a few seconds of latency; kills the race.

2. `resolveProjectRemote` returned undefined for projects without a git
   remote (materialized sample dbt scaffolds, fresh scratch dirs), so
   the post-scan prompt and `altimate-code link` both bailed silently.
   Fix: new `resolveProjectIdentifier` in `workspace/detect.ts` always
   returns a `{repoRemote?, projectPath}` pair (path is symlink-resolved
   `realpath`). `ProjectIdentifier` type threads through `WorkspaceApi`,
   the TuiPlugin dialogs, and the `link` subcommand — remote is
   preferred when available (stronger identity, survives directory
   moves); path is the fallback the backend indexes symmetrically.

Also: `projectNameFromPath` fallback for auto-naming (derives from
directory basename when no remote); Skip-latch key hashes remote-or-path
so path-only projects also get the 7-day suppression; `runFlow` and
`runOnDemandPicker` reworked to use `WorkspaceApi.getBindingForProject`
(tries remote first, then path); `CachedBinding` in state.ts extended
with `projectPath: string | null`.

Tests updated + one new latch test covers the path-only case. `bun test
test/altimate/plugin/workspace.test.ts` → 18/18.
@gitguardian

gitguardian Bot commented Aug 13, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
33124345 Triggered Basic Auth String 7c7e17f packages/opencode/src/altimate/workspace/detect.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b53dfcf2-f479-415c-a3d7-dd11c8b31faf

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@github-actions

Copy link
Copy Markdown
- - - - - - - - - - - - - - - - - - - - - - - - -
                    AIRECEIPTS                    
             1 session behind this PR             

claude-opus-4-7.................333,962,152 tokens
  session slice: turns 1–570 of 663
  SUBAGENTS (3)...................7,484,806 tokens
--------------------------------------------------
TOTAL unpriced..................341,446,958 tokens
  counted: 1 session + 3 subagents
  cache served 98% of input tokens
  full receipts + session ids: section below
- - - - - - - - - - - - - - - - - - - - - - - - -
                npx aireceipts-cli                
         github.com/anandgupta42/receipts         
- - - - - - - - - - - - - - - - - - - - - - - - -
full receipts (1 session)
session id scope turns time tokens in / out cached
orchestrator 58386076 turns 1–570 of 663 570 41h 06m 6.2k / 554k 98%

orchestrator · 58386076

- - - - - - - - - - - - - - - - - - - - - - - - -
                    AIRECEIPTS                    
           “post-scan-workspace-prompt”           
  Claude Code · Aug 12 2026 04:01 UTC · 41h 06m   
               claude-opus-4-7 100%               
         cache served 98% of input tokens         

pre-edit: 1% of tokens (26/570 turns)
  (share before the first named edit tool)

Bash..................169,214,620 tok  (313 calls)
(thinking/reply)........46,778,616 tok  (74 turns)
Read....................43,324,840 tok  (94 calls)
Edit....................40,936,519 tok  (94 calls)
Write...................13,693,270 tok  (32 calls)
SendUserFile..............7,036,889 tok  (8 calls)
TaskUpdate...............4,881,554 tok  (31 calls)
ToolSearch...............3,752,181 tok  (11 calls)
TaskCreate...............2,005,815 tok  (19 calls)
mcp__atlassian__getJiraI…...709,952 tok  (3 calls)
AskUserQuestion.............565,590 tok  (3 calls)
ExitPlanMode................395,484 tok  (2 calls)
Agent.......................322,793 tok  (3 calls)
TaskStop.....................187,859 tok  (1 call)
EnterPlanMode................156,170 tok  (1 call)
--------------------------------------------------
TOTAL..............................333,962,152 tok
no price table matched
- - - - - - - - - - - - - - - - - - - - - - - - -
                npx aireceipts-cli                
         github.com/anandgupta42/receipts         
- - - - - - - - - - - - - - - - - - - - - - - - -
subagents (3)
subagent cost
Explore the altimate-code CLI (cwd: /Users/haider/code/altimateai/altimate-code… 3,139,006 tokens
Explore /Users/haider/code/altimateai/vscode-dbt-power-user (a TypeScript VSCod… 2,210,569 tokens
Design an implementation plan for Jira ticket AI-8398 "CLI: Post-scan prompt to… 2,135,231 tokens

Generated by aireceipts

@github-actions

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant