feat(console): surface workspace readiness in shell - #160
Conversation
Carry workspace index degradation through scatter and the global shell so reduced search capability stays visible outside the workspace view.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
📝 WalkthroughWalkthroughThe PR adds workspace degradation metadata to readiness and scatter responses. The console polls readiness, stores degradation state, synchronizes search results, and displays workspace readiness labels and missing-index details. ChangesWorkspace readiness and degradation
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant IntuiShell
participant WorkspaceReadiness
participant ShellStore
participant StatusBar
IntuiShell->>WorkspaceReadiness: poll readiness
WorkspaceReadiness-->>IntuiShell: return capabilities
IntuiShell->>ShellStore: setWorkspaceDegradation
ShellStore-->>StatusBar: provide degradation state
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Pull request overview
This PR surfaces workspace readiness in the Console shell status bar by projecting readiness/scatter “degraded / missingIndexes” signals through the search-stack and into shell state, and adds assertions to ensure the UI reflects degraded→ready transitions.
Changes:
- Extend search-stack scatter/expand contracts to include
degradedandmissingIndexes, and propagate them through expansion/splice and fixtures. - Add shell-level workspace degradation state and poll workspace readiness so the StatusBar can render a readiness chip.
- Add unit/API/e2e assertions to ensure
degraded/missingIndexesare carried through and rendered.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/theorem-acp/src/workspace-state.ts | Adds WorkspaceDegradation and a projection helper from readiness capabilities. |
| packages/search-stack/src/state.ts | Carries degradation fields through spliceExpansion. |
| packages/search-stack/src/tests/fixtures.ts | Updates test scatter fixture to include degradation fields. |
| packages/block-view-contracts/src/search-stack.ts | Extends scatter response contract with degraded / missingIndexes. |
| apps/console/src/views/search/SearchStackView.tsx | Pushes scatter degradation into shell state. |
| apps/console/src/lib/workspace-state.test.ts | Adds coverage for readiness→degradation projection. |
| apps/console/src/lib/state/shell-state.ts | Adds workspaceDegradation to shell state and exposes a setter. |
| apps/console/src/components/shell/StatusBar.tsx | Renders workspace readiness chip with degraded detail. |
| apps/console/src/components/shell/IntuiShell.tsx | Polls workspace readiness and wires status bar readiness. |
| apps/console/src/app/api/search/search-routes.test.ts | Asserts scatter GraphQL query includes degradation fields. |
| apps/console/src/app/api/search/_graphql.ts | Adds degraded / missingIndexes to scatter GraphQL field selection. |
| apps/console/e2e/workspace-goal-stack.spec.ts | Adds degraded→ready readiness chip assertions in the workspace flow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| setWorkspaceDegradation: (degradation) => | ||
| shellStore.set(workspaceDegradationAtom, degradation), |
| const missingIndexes = readiness.capabilities.flatMap((capability) => ( | ||
| capability.missing.length > 0 | ||
| ? capability.missing | ||
| : capability.state.toLowerCase() === 'ready' | ||
| ? [] | ||
| : [capability.capability] | ||
| )); |
| const workspaceDegradation = useShellStore( | ||
| (state) => state.workspaceDegradation, | ||
| ); | ||
| const setWorkspaceDegradation = useShellStore( | ||
| (state) => state.setWorkspaceDegradation, |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/console/src/lib/workspace-state.test.ts (1)
65-77: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winCover the remaining degradation branches.
The test covers explicit missing indexes. It does not cover the fallback at
workspaceDegradationOfLine 245 when a building capability reports no indexes. It also does not cover an all-ready workspace.Add cases for
buildingwithmissing: [], which should report the capability name, and for all-ready capabilities, which should returndegraded: falsewith an empty list.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/console/src/lib/workspace-state.test.ts` around lines 65 - 77, Add test cases for workspaceDegradationOf covering a building capability with missing: [] and assert degraded is true with that capability name in missingIndexes, plus an all-ready capabilities case asserting degraded is false and missingIndexes is empty; keep the existing explicit-index coverage unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/console/src/components/shell/IntuiShell.tsx`:
- Line 65: Move the readiness polling duration from the local READINESS_POLL_MS
declaration in IntuiShell.tsx into the shared src/motion/motion-tokens.ts file,
export it there, and import and reuse that token in IntuiShell.tsx instead of
defining the literal locally.
- Around line 344-375: Update the readiness polling effect in IntuiShell to
obtain workspace readiness through the Console MCP GraphQL helper/tool path,
specifically routing the query via graphql_query instead of calling
fetchWorkspaceReadiness directly. Preserve the existing abort handling,
degradation updates, polling interval, and cleanup behavior.
---
Nitpick comments:
In `@apps/console/src/lib/workspace-state.test.ts`:
- Around line 65-77: Add test cases for workspaceDegradationOf covering a
building capability with missing: [] and assert degraded is true with that
capability name in missingIndexes, plus an all-ready capabilities case asserting
degraded is false and missingIndexes is empty; keep the existing explicit-index
coverage unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: a33e3c01-8af2-41f4-b70d-50892df751bf
📒 Files selected for processing (12)
apps/console/e2e/workspace-goal-stack.spec.tsapps/console/src/app/api/search/_graphql.tsapps/console/src/app/api/search/search-routes.test.tsapps/console/src/components/shell/IntuiShell.tsxapps/console/src/components/shell/StatusBar.tsxapps/console/src/lib/state/shell-state.tsapps/console/src/lib/workspace-state.test.tsapps/console/src/views/search/SearchStackView.tsxpackages/block-view-contracts/src/search-stack.tspackages/search-stack/src/__tests__/fixtures.tspackages/search-stack/src/state.tspackages/theorem-acp/src/workspace-state.ts
| const SIDEBAR_COLLAPSED_PX = 48; | ||
| const OVERLAY_BREAKPOINT = 1100; | ||
| const LAYOUT_READY_EVENT = 'commonplace:layout-ready'; | ||
| const READINESS_POLL_MS = 1_500; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Move the poll interval to the shared token file.
Line 65 defines the literal duration 1_500 outside src/motion/motion-tokens.ts. Move the readiness polling duration to that file and import it here.
As per coding guidelines, "Do not use ... literal durations outside src/motion/motion-tokens.ts."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/console/src/components/shell/IntuiShell.tsx` at line 65, Move the
readiness polling duration from the local READINESS_POLL_MS declaration in
IntuiShell.tsx into the shared src/motion/motion-tokens.ts file, export it
there, and import and reuse that token in IntuiShell.tsx instead of defining the
literal locally.
Source: Coding guidelines
| useEffect(() => { | ||
| const controller = new AbortController(); | ||
| let stopped = false; | ||
| let timer: ReturnType<typeof setTimeout> | undefined; | ||
| const poll = async () => { | ||
| try { | ||
| const readiness = await fetchWorkspaceReadiness({ | ||
| signal: controller.signal, | ||
| }); | ||
| if (!stopped) { | ||
| setWorkspaceDegradation(workspaceDegradationOf(readiness)); | ||
| } | ||
| } catch { | ||
| if (!stopped && !controller.signal.aborted) { | ||
| setWorkspaceDegradation({ | ||
| degraded: true, | ||
| missingIndexes: ['status_graphql'], | ||
| }); | ||
| } | ||
| } finally { | ||
| if (!stopped) { | ||
| timer = setTimeout(() => void poll(), READINESS_POLL_MS); | ||
| } | ||
| } | ||
| }; | ||
| void poll(); | ||
| return () => { | ||
| stopped = true; | ||
| controller.abort(); | ||
| if (timer) clearTimeout(timer); | ||
| }; | ||
| }, [setWorkspaceDegradation]); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
ast-grep outline packages/theorem-acp/src/workspace-state.ts --items all
rg -n -C 5 'fetchWorkspaceReadiness|graphql_query|THEOREM_GRAPHQL_URL|/mcp|function graphql|const graphql' \
packages/theorem-acp/src apps/console/srcRepository: Travis-Gilbert/CommonPlace
Length of output: 25927
🏁 Script executed:
#!/bin/bash
set -euo pipefail
cat -n packages/theorem-acp/src/workspace-state.ts | sed -n '88,135p;254,280p'
nl -ba apps/console/src/components/shell/IntuiShell.tsx | sed -n '330,355p'
nl -ba apps/console/src/lib/state/thread-state.ts | sed -n '230,255p'
nl -ba apps/console/src/views/workspace/WorkspaceSubstrateView.tsx | sed -n '70,85p'
rg -n "graphql_query|fetchWorkspaceReadiness|fetchWorkspaceSurface|callHarnessMcp" apps/console --glob '*.{ts,tsx}'Repository: Travis-Gilbert/CommonPlace
Length of output: 2891
Route readiness polling through graphql_query.
fetchWorkspaceReadiness() sends the readiness query directly to /api/workspace, bypassing the configured harness /mcp door. Use the Console MCP GraphQL helper/tool path here so readiness polling follows the graphql_query requirement.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/console/src/components/shell/IntuiShell.tsx` around lines 344 - 375,
Update the readiness polling effect in IntuiShell to obtain workspace readiness
through the Console MCP GraphQL helper/tool path, specifically routing the query
via graphql_query instead of calling fetchWorkspaceReadiness directly. Preserve
the existing abort handling, degradation updates, polling interval, and cleanup
behavior.
Source: Coding guidelines
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1424824339
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| degraded | ||
| missingIndexes |
There was a problem hiding this comment.
Add degradation fields to the scatter GraphQL schema
Every scatter and aspect-expansion request now selects these fields, but the checked apps/commonplace-api/src/schema/scatter.rs ScatterResponseGql exposes neither degraded nor missingIndexes. The upstream GraphQL server will therefore reject both queries during validation, and searchGraphql will return a 502 instead of any search results. Add the fields to the API schema and populate them before requesting them from both routes.
Useful? React with 👍 / 👎.
| setWorkspaceDegradation({ | ||
| degraded: true, | ||
| missingIndexes: ['status_graphql'], | ||
| }); |
There was a problem hiding this comment.
Keep transport failures out of the reduced-readiness state
When /api/workspace answers 401, 403, or 502, or cannot reach the data API, fetchWorkspaceReadiness throws and this catch converts every failure into an index-degradation envelope. StatusBar then renders Workspace reduced: Status reporting is incomplete even though no readiness response was obtained, masking the sign-in, workspace-claim, credential, and transport failures that the route explicitly returns. Preserve the error and HTTP status and render an unavailable or checking state instead of fabricating a missing status_graphql index.
Useful? React with 👍 / 👎.
| setWorkspaceDegradation({ | ||
| degraded: scatter.degraded, | ||
| missingIndexes: [...scatter.missingIndexes], |
There was a problem hiding this comment.
Merge scatter readiness without clearing other workspace gaps
When workspace readiness reports a non-scatter capability as missing but a scatter response is healthy, this assignment replaces the entire shell envelope with degraded: false, so the status bar temporarily claims Workspace ready despite the remaining readiness gap. The scatter contract covers only indexes required by scatter, while workspaceDegradationOf covers every readiness capability; keep source-specific envelopes or union them instead of making the last writer win.
Useful? React with 👍 / 👎.
| useEffect(() => { | ||
| if (!scatter) return; |
There was a problem hiding this comment.
Retain degradation metadata for empty scatter responses
When scatter returns zero aspects, the controller stores asyncState.empty() and discards the response object, so scatterOf(state) is undefined and this early return prevents its degraded and missingIndexes metadata from reaching the shell. This is especially problematic when unavailable indexes produce no admitted aspects, and it also leaves a previous degraded marker stale when a later healthy query is merely empty. Preserve the response envelope in the empty state or synchronize degradation before reducing the response to an empty UI state.
Useful? React with 👍 / 👎.
Summary
degraded/missingIndexesthrough scatter and expand contracts into shell stateTest plan
pnpm --filter @commonplace/search-stack run check && pnpm --filter @commonplace/search-stack run test(42 tests)pnpm --filter @commonplace/block-view-contracts run check && pnpm --filter @commonplace/theorem-acp run checkpnpm --filter @commonplace/console exec vitest run src/lib/workspace-state.test.ts src/app/api/search/search-routes.test.ts(10 tests)npm --prefix apps/console run test:e2e -- workspace-goal-stack: attempted twice after building/installingtwenty-ui; repository-wide global setup timed out on unrelated/appearanceand/loginroute prewarming before the selected test beganSummary by CodeRabbit
New Features
Bug Fixes