feat: post-scan Workspaces prompt + altimate-code link subcommand - #1099
feat: post-scan Workspaces prompt + altimate-code link subcommand#1099sahrizvi wants to merge 2 commits into
altimate-code link subcommand#1099Conversation
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 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
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- 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
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 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.
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
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. |
full receipts (1 session)
orchestrator ·
|
| 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
|
👋 This PR was automatically closed by our quality checks. Common reasons:
If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you. |
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 linksubcommand for the same flow at any time.packages/opencode/src/plugin/tui/altimate/workspace.tsx) — fork-owned single file, wired through the existingaltimateTuiPlugins()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-shotsession.idlelistener so the dialog opens after the LLM's onboarding menu finishes streaming (not while it's still generating).altimate-code linksubcommand — picker-first UX (currently-linked row marked, "+ Create new" as the first row, auto-named from the git repo or directory basename). Shares theWorkspaceApiclient + state cache + project-identifier detection with the plugin so the two entry points can't drift.repo_remotewhen a git remote is present (stronger — survives directory moves), else the absolute symlink-resolvedproject_path. Neither is required to be non-null in isolation, but at least one must be present.~/.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.TuiPluginApi.kv— 7-day rolling suppression keyed onsha1(repoRemote ?? projectPath). The subcommand deliberately bypasses it (user-initiated).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— cleanbun test test/altimate/plugin/workspace.test.ts— 18/18 (including the new path-only latch case)bun test test/altimate— 4047 pass, 10 pre-existingsample_setuptimeout failures unrelated to this changeFork markers
All fork-only code is wrapped in
altimate_change start/altimate_change endmarkers oraltimate_change - new file, per the ADR atdocs/internal/2026-06-23-tui-fork-features-as-plugins-adr.md. Zero edits topackages/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 linksubcommand for the same flow on demand. Previously there was no linking flow; now, whenFlag.ALTIMATE_WORKSPACEis enabled and Altimate is configured, the dialog opens after the session goes idle; existing onboarding is unchanged when the flag is off.Review notes
Flag.ALTIMATE_WORKSPACE(off by default).packages/opencode/src/altimate/plugin/onboarding-telemetry.tsarms a one-shot listener and publishesaltimate.workspace.postScanaftersession.idleviaEventV2Bridgeto avoid racing LLM streaming.packages/opencode/src/plugin/tui/altimate/workspace.tsxregistersaltimate.workspace.postScanandaltimate.workspace.link. Dialogs: Offer (Create/Link/Skip with 7‑day latch inapi.kvkeyed by repo remote or project path), AlreadyLinked (drift + unverified flags), and Picker. No changes topackages/tui/**.packages/opencode/src/cli/cmd/link.tsand registration inpackages/opencode/src/index.ts. Picker-first UX with “+ Create new” and a marker on the currently linked workspace; opens the manage URL on create.packages/opencode/src/altimate/workspace/:api-client.ts(typed errors, 15s timeout, per-call credentials),detect.ts(project identity{repoRemote?, projectPath}; reuses exportedstripGitRemoteCredentials), andstate.ts(local cache scoped to tenant+apiUrl underGlobal.Path.state, chmod 0600). Server is authoritative; cache is offline fallback and renders “unverified”./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
ALTIMATE_WORKSPACE./datamate-project-bindings/*and/datamates/.altimate-code linkin projects with and without a git remote.Written for commit 76de5a9. Summary will update on new commits.