Console rail: OWOX canvas, twenty-ui insights and actions, flat full-bleed shell - #174
Conversation
Kills SPEC-COMMONPLACE-TWENTY-UI-FORK-1.0's token law on owner direction: Twenty's design language now drives the console, and --ij-* aliases --t-* rather than the reverse. The contrast gate was falsely green. It read only the Int UI registers, which stopped deciding the paint when the inversion landed, so it kept measuring a palette that was no longer on screen. It now reads the shipped cascade in app.css order, including the fork's --t-* layer, and resolves color(display-p3 ...) through the P3 primaries instead of the sRGB matrix. Pointing it at reality surfaced four real leaks, all the same shape: a token re-pinned downstream of the alias layer by an index rather than a role. - register-bridge pinned --ij-ink-info to gray-8 / gray-6. Those indexes named Int UI greys; under Twenty's ladder (numbered background to foreground) light gray-6 is 0.8, giving 1.54:1 secondary ink. Now Twenty's font-color-secondary. - --ij-gold and the island header bands carried Int UI and Zed-era literals. - The Primer presets pin their own surfaces but never pinned a header band, so it fell through to a base register that is no longer theirs. - The alias layer was one attribute selector deep, so int-ui-register-light.css outranked it and light mode silently kept the whole Int UI palette. The register now names both modes explicitly at matching weight. Elevation follows the owner's direction (sidebar lifts, centre sinks) and the arithmetic. Twenty's dark background ladder spans 1.126 end to end, and the old floors wanted 1.08 * 1.05 = 1.134 around one frame. That does not fit, and the only step above bg-quaternary is gray6 at 1.74 against the frame: heavier than Int UI ever was, and the opposite of this round. One symmetric 1.05 floor fits inside the ladder with room, and both islands keep a measured step. MaterialLayer read every surface through a digit scan of the computed colour. Computed colour preserves its space rather than normalising to rgb(), so the "3" of "display-p3" became the red channel: all surfaces resolved near black, every caller fell through to a `?? dark` fallback, and light mode rendered as a dark wash. It now parses the colour function and converts P3 to sRGB. Proportions move to Twenty's grid: metrics resolve through --t-spacing-*, so the 4px grid is the single dimensional source as the palette is the single colour source. Controls 28 -> 32 and rows 24 -> 32 are Twenty's medium button and record row. The IDE-density argument retires with the job, now that the VS Code fork is the IDE. Grain and shadow come down per owner direction: shader ground 0.014 -> 0.005, body tile 0.10 -> 0.075, and lifted drops to a single hairline pass now that tone states the boundary twice. Also fixes the Twenty fence, which judged relative imports by name and so rejected the console's own twenty-register.css. It now resolves the path first; verified it still catches a planted escape into packages/twenty-front.
…enty-ui-spec-d0ae2a
Cherry-picks the console rails work from origin/codex/capture-voice-followup (c50623f) onto the Twenty inversion, then makes it coherent with the register that landed after that branch forked. The retoken is a correctness fix, not a style pass. register-bridge.css resets --color-*, --radius-*, and --font-* to initial so the register is the only paint, which means the published 21st file's text-neutral-50, rounded-lg, font-['Lexend:...'], and text-[14px] emitted no CSS at all. The sidebar was not mis-colored, it was uncolored, inheriting whatever an ancestor happened to set. Paint, arc, face, and motion now resolve through --ij-*; duration-500 becomes duration-(--ij-motion) ease-(--ij-ease), so the component settles with the rest of the surface under reduced motion instead of running a 500ms spring. Elevation reads off Twenty's background ladder, closing the DOM half of "sidebar lifted, center sunk": the icon rail paints --ij-chrome, the detail panel --ij-frame, and wells --ij-editor. Measured live at 1.0 / 0.976 / 0.922 in light and 0.133 / 0.114 / 0.09 in dark, so the ladder reverses direction with the mode and the three planes stay distinct in both. Icons follow the ledger row. The product rail and the inspector nav now paint Noun Project marks from src/components/shell/icons.tsx; the vendored carbon and lucide glyphs remain only in the demo trees no product surface renders. The inspector edge control drops its noun-layers PNG for IconLayers, because a raster mark cannot take currentColor and so could not follow ink through hover, theme, or mode. NavIcon widens the published LucideIcon slot to admit both. TwoLevelSidebarShell gains panelBrand next to the existing brand slot, so the chat sidebar stops advertising the vendor's "Interfaces" demo brand. Two defects found while verifying on the dev server: - JsonCanvasLayer's boot effect used a bare `void boot()`, so an objects API that is down turned a canvas failure into an unhandled rejection and the whole inspector rail read as broken. It now degrades to an empty canvas and says why. - The canvas overlays were pinned to top-3 and bottom-3 inside a full-bleed layer under the rail's nav, landing the error banner on the workspace switcher and the hint on the Settings row, both translucent enough to read through each other. They now clear the chrome rows and paint opaque. Verified at /dev/chrome-preview in light and dark. Seven gates pass, 571 unit tests pass, typecheck is clean apart from the document-store.test.ts error that is already on main.
The console carried two left chromes: the IDE surfaces wore IntuiShell's own stripe, while chat wore the 21st TwoLevelSidebarShell landed in c7b26b0. They shared a palette but not a structure, so /workspace and /chat did not look like the same product. This makes the 21st rail plus detail panel the console's one sidebar. shell/Sidebar keeps its public props, so IntuiShell's mount is unchanged. What moves is the composition: the five Places become the icon rail, and Blocks, Objects, Pins, and the tenant row become the detail panel. LayoutSwitcher is the panel's brand row. Account and collapse sit on the rail, because both have to survive a collapse. The published component needed three seams to carry the console's contract without being forked, each generic rather than console-specific: - TwoLevelSidebarItem.buttonProps, spread onto the rail button. The stripe's radio semantics, Cmd/Ctrl 1-5 shortcuts, and the data-surface-nav selectors the e2e specs assert ride through it. - TwoLevelSidebarShell.railProps and a rest spread on the root, for data-surface-rail on the rail and data-paint-region on the wrapper, which is where the gates and specs already look. - DetailSidebar now narrows the injected panel to zero width instead of unmounting it. Unmounting drops it out of the accessibility tree, and console-sidebar.spec asserts the Pins region is still reachable after a collapse and a reload. Verified live at /workspace: the rail holds exactly five data-surface-nav radios with console-workspace checked, 11 block buttons, one Pins region, and the account trigger visible. Collapse flips data-sidebar-collapsed to true, narrows the aside 384 to 128, and keeps both Pins and the account trigger. Elevation still reads lifted rail 1.0, frame panel 0.976, sunken editor. Also corrects a drift the earlier proportions pass left behind: --ij-control-h resolves to Twenty's --t-spacing-8, so the account trigger is 32px, not the Int UI 28px two specs still asserted. Those assertions were already wrong at c7b26b0; e2e had not been run against them. Seven gates pass, 571 unit tests pass, typecheck clean apart from the document-store.test.ts error already on main.
Two things made the centre read as a card floating on the ground, which is the opposite of the sidebar-lifted, centre-sunk arrangement the register encodes. The editor region declares one island for its tab strip and well, and the BlockShell it hosts declares another inside it. MaterialLayer collected both, so the shader drew a rim inside a rim about 40px apart: a card on a card. CS2 already says a child never repeats its parent's radius, because two arcs a pixel apart antialias into a chipped corner. This is the same rule for the material, applied where island painting is actually owned: nested islands are filtered out and the parent owns the plane. The remaining rim was still a lift. The shader cast one for every island, and a cast rim is the single thing that makes a recess read as a card sitting on the ground, so the editor class is now exempt from the shadow pass. Tool windows keep theirs, which is what carries the lifted reading on the sides. Tone still makes the boundary; there is simply no shadow arguing the other way. The bottom status strip is removed from the shell. This is not a new opinion: signatures.spec has asserted [data-paint-region="status-bar"] and [data-connection-owner="status-bar"] at count 0 since the signature round, and the shell had grown one back under the test. Verified live at both counts 0. Capability note, deliberately not papered over: the strip held the only Reconnect control and the only workspace-degradation badge, and neither has a new home yet. The readiness poll still writes degradation into the shell store, so whatever re-homes the affordance binds to that atom rather than re-fetching. Seven gates pass, 571 unit tests pass, typecheck clean apart from the document-store.test.ts error already on main.
The detail panel inherited the vendor's w-80. Measured live, the widest thing it holds is the empty-state line at 144px, so a third of the panel was margin. It now takes the register's own --ij-sidebar-expanded-w (240), which is the token that has always described this width, and the shell aside follows at 304 open. The centre gets the 80px back. Narrowing exposed a layout bug the extra width had been hiding: a pin row's Unpin and Remove controls are opacity-0 at rest but were still laid out, costing the label 96px of a 193px row, so "Console brief" and "surface-tree.ts" truncated at 45px of the 88 they needed. They are overlaid now and only take room on hover. Label measures 151 of 151 needed, nothing truncates. Seven gates pass, 571 unit tests pass, typecheck clean apart from the document-store.test.ts error already on main. One test run reported 569 with an error while the machine was loaded (97s against a normal 11s); the re-run is clean, so that was contention rather than a regression.
The rail was chrome with a fixed panelWidth of 260 animating to zero. It could shut but not size, which is half of what a right rail owes you. It is a collapsible react-resizable-panels Panel now, so drag, keyboard resize on the separator, the collapsed state, and persistence across reload are all the library's. Width leaves the component entirely: InspectorRail fills whatever container it is given, which is a Panel in the shell and a fixed column on the chrome preview. The rail sits in its own group beside the well rather than joining the surface group. The surface group persists sizes by region id through the host, and the rail is chrome with no region of its own; autoSaveId keeps its layout instead. Collapse is collapsedSize 0, and a Panel clips its overflow, so a toggle left inside a zero-width rail is unclickable while still sitting in the accessibility tree. The rail therefore carries collapse only while open, and whoever owns the collapsed state renders InspectorRailReopen. Exactly one toggle is on screen, and in the DOM, in either state. Also drops a pre-existing react-hooks/set-state-in-effect error in the rail: route-to-selection sync moves to the render-phase adjustment the shell already uses for the sidebar's collapsed flag. Verified at 1440x900: rail 245 default against an 867 well, collapse to 0 with the well taking 1112, reopen to 245, keyboard resize to 667, layout written to react-resizable-panels:console.inspector-dock. Seven gates pass, 571 unit tests pass, typecheck clean but for the pre-existing document-store.test error.
DiagramCanvas.tsx was the pre-fork model canvas, back in the tree with no importer, no barrel export, and no e2e reference, inside the directory whose own ORPHAN.md says the OWOX fork supersedes it. The live surface is ForkDiagramCanvas over @commonplace/model-canvas. Leaving it there invites the next session to extend the canvas the fork retired. collapsible.tsx hand-built Radix Collapsible: context, controlled and uncontrolled open reconciliation, an aria-expanded trigger, content that unmounts on close. @radix-ui/react-collapsible was never installed, the ledger carries no collapsible row, and nothing imported the file. It also lost what Radix gives: aria-controls wiring, forceMount for exit motion, disabled. Its header claimed native details/summary; the body used div plus button plus context, so the comment was wrong about its own implementation. gate:sourcing ok (23 descriptors). eslint 0 errors. The one tsc error is in document-store.test.ts, identical to main and unrelated.
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 35660538 | Triggered | Generic High Entropy Secret | 9d4f9ce | apps/chat-server/src/agent-context-cloud-probe.test.ts | View secret |
| 35660539 | Triggered | Generic High Entropy Secret | 9d4f9ce | apps/chat-server/src/agent-context-diagnostics.schema.test.ts | View secret |
| 35660540 | Triggered | JSON Web Token | 9d4f9ce | apps/chat-server/src/cloud-mcp-health.test.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 secrets safely. Learn here the best practices.
- Revoke and rotate these secrets.
- 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.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
|
Warning Review limit reached
Next review available in: 36 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThe PR introduces two-level navigation and an inspector rail, adds JSON Canvas and model-canvas surfaces, migrates workspace layouts, updates Twenty-based theme generation and validation, and propagates tenant credentials through principal and ACP session flows. ChangesConsole shell and canvas surfaces
Principal and ACP credential flow
Twenty theme and validation system
Console supporting contracts
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
🧪 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 advances the “CommonPlace Twenty UI” fork by inverting the styling token direction (Twenty palette drives the console), replacing/augmenting shell chrome (TwoLevelSidebar + new InspectorRail), adding a chrome-owned Obsidian JSON Canvas rail layer, and tightening ACP session isolation + principal redirect behavior.
Changes:
- Invert token sourcing so
--ij-*aliases Twenty’s--t-*(newtwenty-register.css), plus accompanying contrast gate + theme generator support. - Introduce new chrome surfaces: TwoLevelSidebarShell-backed left rail, a react-resizable-panels InspectorRail dock, and a persisted Obsidian JSON Canvas rail Z-layer.
- Harden tenancy/credential isolation for ACP process caching and route principal failures through a non-looping redirect helper.
Reviewed changes
Copilot reviewed 53 out of 56 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks new dependency graph including @carbon/icons-react and transitive updates. |
| packages/twenty-ui/src/theme/generator/palette/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seq | Theorem run sequence stamp update. |
| packages/twenty-ui/src/theme/generator/emit.ts | Adds palette selection + upstream palette parsing for --t-* generation. |
| packages/twenty-ui/src/theme-constants/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seq | Theorem run sequence stamp update. |
| packages/twenty-ui/src/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seq | Theorem run sequence stamp update. |
| packages/twenty-ui/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seq | Theorem run sequence stamp update. |
| packages/theorem-acp/src/state.ts | Extends ACP process identity with optional tenant/auth fields. |
| packages/theorem-acp/src/session-manager.ts | Uses a credential fingerprint in process cache keys and forwards bearer auth to hosted ACP. |
| packages/theorem-acp/src/session-manager.test.ts | Adds tests asserting tenant/credential isolation without leaking token material. |
| packages/theorem-acp/src/bridge.ts | Accepts/validates tenant and authToken from bridge requests. |
| docs/plans/data-canvas-graph-native/SPEC-DATA-CANVAS-GRAPH-NATIVE-1.0.md | Updates spec to clarify pane-only CanvasView and chrome-owned inspector rail canvas. |
| apps/console/src/views/registry.tsx | Adds generator for declared record palette descriptors. |
| apps/console/src/views/canvas/CanvasView.tsx | Adds embedded rendering mode and refactors flow surface UI. |
| apps/console/src/styles/twenty-register.css | New register inversion layer: --ij-* aliases Twenty --t-* plus elevation mapping. |
| apps/console/src/styles/register-bridge.css | Retunes bridge tokens for Twenty palette + grain adjustments, removes obsolete overrides. |
| apps/console/src/styles/primer-register.css | Pins header-band tokens for Primer preset under new base register behavior. |
| apps/console/src/styles/geometry.css | Retunes shadow budget for the Twenty pass. |
| apps/console/src/styles/app.css | Reorders imports so Twenty --t-* precedes alias layer and clarifies paint-source intent. |
| apps/console/src/styles/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seq | Theorem run sequence stamp update. |
| apps/console/src/motion/motion-tokens.ts | Updates interaction inventory text (dock → icon rail hover). |
| apps/console/src/lib/server/principal-redirect.ts | New helper to redirect failed principal resolution without loops (login vs onboarding). |
| apps/console/src/components/ui/json-canvas-layer.tsx | Adds Obsidian JSON Canvas rail Z-layer with persistence through canvas.apply_json. |
| apps/console/src/components/ui/dashboard-sidebar.tsx | Adds/extends 21st sidebar UI with workspace/nav integration and JSON canvas feature layer. |
| apps/console/src/components/ui/dock.tsx | Removes the prior motion-primitives dock implementation. |
| apps/console/src/components/ui/badge.tsx | Adds a register-skinned badge component (blocks.so-sourced). |
| apps/console/src/components/shell/Sidebar.tsx | Switches console sidebar to TwoLevelSidebarShell-based rail/panel architecture. |
| apps/console/src/components/shell/IntuiShell.tsx | Adds collapsible InspectorRail PanelGroup; removes bottom StatusBar usage. |
| apps/console/src/components/shell/InspectorRail.tsx | Adds right inspector rail host + reopen affordance + identity workspace selection. |
| apps/console/src/components/shell/icons.tsx | Adds IconLayers used by the inspector rail affordance. |
| apps/console/src/components/ground/MaterialLayer.tsx | Improves CSS color parsing (P3/sRGB) and avoids nested-island double rims; tweaks rim logic. |
| apps/console/src/components/ground/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seq | Theorem run sequence stamp update. |
| apps/console/src/components/chat/ChatSidebar.tsx | Replaces chat dock with TwoLevelSidebarShell; retokens panel chrome and surfaces. |
| apps/console/src/app/workspace/[workspaceSlug]/chat/page.tsx | Routes principal failures through redirectForFailedPrincipal. |
| apps/console/src/app/workspace/[workspaceSlug]/chat/page.test.tsx | Updates redirect expectations for encoded callback URL behavior. |
| apps/console/src/app/page.tsx | Uses redirectForFailedPrincipal on root principal failure. |
| apps/console/src/app/dev/chrome-preview/page.tsx | Adds a dev preview page for left chrome + inspector rail + material layer. |
| apps/console/src/app/chat/page.tsx | Uses redirectForFailedPrincipal on chat-index principal failure. |
| apps/console/src/app/chat/page.test.tsx | Adds onboarding redirect coverage and updates login redirect expectations. |
| apps/console/src/app/api/proactivity/compile/route.ts | Resolves upstream credentials per principal and forwards tenant/auth into ACP bridge session. |
| apps/console/src/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seq | Theorem run sequence stamp update. |
| apps/console/scripts/check-twenty-fence.mjs | Adjusts fence logic to treat relative CSS imports by resolved path. |
| apps/console/scripts/check-contrast.mjs | Updates contrast gate to reflect new import order + P3 parsing + selector specificity. |
| apps/console/package.json | Adds @carbon/icons-react dependency. |
| apps/console/e2e/signatures.spec.ts | Updates UI signature assertions for new sidebar geometry and no status bar. |
| apps/console/e2e/console-ia.spec.ts | Updates IA assertions for new inspector rail selectors and no status-bar connection owner. |
| apps/console/e2e/appearance.spec.ts | Updates appearance assertions for Twenty control height (32px). |
| apps/console/components.json | Adds shadcn registries (blocks.so and jalco). |
| apps/console/CLAUDE.md | Updates UI ledger and decisions for inspector rail + installed sidebar-component usage. |
| apps/console/AGENTS.md | Mirrors CLAUDE ledger updates for inspector rail + left chrome component source. |
| apps/console/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seq | Theorem run sequence stamp update. |
| .cursor/rules/no-hand-roll-components.mdc | Adds “no hand-rolled components” rule for using catalog/registry components. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (1)
apps/console/src/components/ui/json-canvas-layer.tsx:278
- Node add/remove changes aren’t persisted:
onNodesChangeupdates localnodesonly, so delete-key removals (and any programmatic adds/removes) won’t updatedocumentor callcanvas.apply_json.
const onNodesChange: OnNodesChange<JsonCanvasFlowNode> = useCallback((changes) => {
setNodes((current) => applyNodeChanges(changes, current));
}, []);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Later declarations win, matching the cascade, except that the @supports | ||
| // squircle block must not override the base radii: the console rules round. | ||
| if (!values.has(name)) values.set(name, value); |
| export function CanvasView({ | ||
| host, | ||
| /** Hide Import/Export chrome — used when the canvas is a capability inside another shell. */ | ||
| embedded = false, | ||
| }: Pick<ViewRenderProps, 'host'> & { embedded?: boolean; set?: ObjectSet }) { | ||
| const set = useCanvasObjectSet(host); | ||
| const [message, setMessage] = useState<string | null>(null); |
| // SOURCING: none. Map failed harness principal resolution to a non-looping route. | ||
|
|
||
| import { redirect } from 'next/navigation'; | ||
| import type { HarnessPrincipalResolution } from '@/lib/server/harness-principal'; |
| void host.emit({ | ||
| kind: 'invoke_tool', | ||
| tool: 'canvas.apply_json', | ||
| args: { | ||
| canvasId, | ||
| document: next as unknown as JsonValue, | ||
| }, | ||
| }).then((result) => { | ||
| const error = receiptFailed(result); | ||
| if (error) { | ||
| setPersistError(error); | ||
| applyLocal(lastReceiptedRef.current); | ||
| return; | ||
| } | ||
| lastReceiptedRef.current = next; | ||
| setPersistError(null); | ||
| }); |
| <div | ||
| className={`group pointer-events-auto flex items-center justify-between px-2.5 py-[7px] rounded-[6px] cursor-pointer transition-all duration-200 select-none | ||
| ${isActive | ||
| ? 'bg-card/90 dark:bg-white/10 text-foreground font-medium backdrop-blur-[1px]' | ||
| : 'bg-card/55 text-muted-foreground hover:bg-card/80 hover:text-foreground/90 backdrop-blur-[1px]' | ||
| } | ||
| `} | ||
| style={{ paddingLeft: `${level * 12 + 10}px` }} | ||
| onClick={handleClick} | ||
| > |
| tenant: 'Travis-Gilbert', | ||
| authToken: 'thk_owner_secret-material', | ||
| ...overrides, | ||
| }; | ||
| } | ||
|
|
||
| describe('ACP process isolation', () => { | ||
| it('separates tenants and credentials without rendering bearer material', () => { | ||
| const owner = agentProcessCacheKey(key()); | ||
| const anotherTenant = agentProcessCacheKey(key({ tenant: 'Another-Tenant' })); | ||
| const rotatedCredential = agentProcessCacheKey(key({ | ||
| authToken: 'thk_owner_rotated-secret', | ||
| })); | ||
|
|
||
| expect(owner).not.toBe(anotherTenant); | ||
| expect(owner).not.toBe(rotatedCredential); | ||
| expect(owner).not.toContain('thk_owner_secret-material'); | ||
| expect(owner).not.toContain('rotated-secret'); |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 83b2980f39
ℹ️ 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".
| const onNodesChange: OnNodesChange<JsonCanvasFlowNode> = useCallback((changes) => { | ||
| setNodes((current) => applyNodeChanges(changes, current)); | ||
| }, []); |
There was a problem hiding this comment.
Persist inspector canvas node removals
When a user selects a canvas node and presses Backspace or Delete, React Flow sends a remove change to onNodesChange, but this handler only updates local React state and never calls commitFlow. Consequently canvas.apply_json retains the node, and it reappears after the rail remounts or the page reloads; node removals should be committed just like edge removals.
AGENTS.md reference: apps/console/AGENTS.md:L138-L138
Useful? React with 👍 / 👎.
| panelOpen={!visuallyCollapsed} | ||
| onPanelOpenChange={(open) => onCollapsedChange(!open)} |
There was a problem hiding this comment.
Restore the Cmd/Ctrl+B keyboard listener
When the console has focus and the user presses Cmd+B or Ctrl+B, nothing now toggles the sidebar: the previous window keydown effect was removed, while this new controlled binding is invoked only by the sidebar component's pointer controls. The changed signatures.spec.ts still presses Meta+B and expects data-panel-open to flip, so that interaction and test will fail until the shortcut is registered again.
Useful? React with 👍 / 👎.
| .map((edge) => ({ | ||
| id: edge.id, | ||
| fromNode: edge.source, | ||
| toNode: edge.target, | ||
| label: typeof edge.label === 'string' ? edge.label : undefined, | ||
| })); |
There was a problem hiding this comment.
Preserve JSON Canvas edge metadata during saves
When a loaded canvas contains standard edge metadata such as fromSide, fromEnd, toSide, toEnd, color, or CommonPlace provenance, moving any node calls commitFlow and this reconstruction silently drops every one of those fields from every edge. The truncated document is then persisted through canvas.apply_json, permanently corrupting imported canvas routing and styling even though the user changed only a node position; merge each flow edge with its previous CanvasEdge before saving.
AGENTS.md reference: apps/console/AGENTS.md:L138-L138
Useful? React with 👍 / 👎.
| <article | ||
| className="h-full min-h-[72px] rounded-lg border border-border/60 bg-card/90 px-3 py-2 text-ij-ink shadow-sm" | ||
| data-json-canvas-node={data.kind} |
There was a problem hiding this comment.
Add connection handles to inspector canvas nodes
For text, file, and link nodes rendered by this custom node component, there is no React Flow Handle element, so users have no source or target from which to initiate a connection. As a result nodesConnectable and onConnect are effectively unreachable for the notes users can add by double-clicking, preventing creation of new JSON Canvas edges.
Useful? React with 👍 / 👎.
| const handleWorkspaceSelect = (workspaceId: string) => { | ||
| const selected = workspaces.find((workspace) => workspace.id === workspaceId); | ||
| setActiveWorkspaceId(workspaceId); | ||
| if (selected) setActiveWorkspaceName(selected.name); | ||
| void selectIdentityWorkspace(workspaceId).catch(() => { | ||
| // Keep local selection; principal cookie update is best-effort for the rail. | ||
| }); |
There was a problem hiding this comment.
Reload the tenant-scoped host after workspace selection
When a multi-workspace user selects another workspace, this handler immediately changes the displayed selection, swallows any failed mutation, and on success only updates the server cookie without navigating or refreshing. The mounted ConsoleApp and ConsoleBlockHost therefore retain the old tenant's proactivity state while subsequent same-origin object requests carry the new workspace cookie; unlike the existing settings and onboarding selectors, this can leave the UI presenting mixed workspace state until a manual reload.
Useful? React with 👍 / 👎.
| --ij-seam: var(--t-border-color-medium); | ||
| --ij-seam-raised: var(--t-border-color-strong); | ||
| --ij-divider: var(--t-border-color-medium); | ||
| --ij-control-border: var(--t-border-color-strong); | ||
| --ij-keyline: var(--t-border-color-strong); |
There was a problem hiding this comment.
Keep seams darker than their surfaces
In dark mode these aliases replace the required inverted seams with Twenty's ordinary light-on-dark borders: for example --t-border-color-medium is lighter than the editor background, while the strong border is substantially lighter than every dark surface. Because --ij-seam, dividers, controls, and keylines are global chrome tokens, this introduces the light hairlines that the console constitution explicitly forbids in every mode.
AGENTS.md reference: apps/console/AGENTS.md:L49-L51
Useful? React with 👍 / 👎.
| --ij-control-h: var(--t-spacing-8); | ||
| --ij-control-min-w: var(--t-spacing-18); | ||
| --ij-row-h: var(--t-spacing-8); |
There was a problem hiding this comment.
Restore the canonical chrome control and row heights
These aliases change every h-ij-control and h-ij-nav-row consumer from the console's required 28px controls and 24px rows to 32px. That globally replaces the documented IDE-density contract with CRM-density spacing, and updating the appearance assertions to expect 32px merely masks the regression rather than preserving the console geometry.
AGENTS.md reference: apps/console/AGENTS.md:L53-L54
Useful? React with 👍 / 👎.
| /* Corner radius is design language, so it moves with the palette. */ | ||
| --ij-arc: var(--t-border-radius-sm); | ||
| --ij-arc-underline: var(--t-border-radius-xs); | ||
| --ij-radius-xs: var(--t-border-radius-xs); |
There was a problem hiding this comment.
Keep the canonical 8px chrome arc
Mapping --ij-arc to Twenty's --t-border-radius-sm changes the shared chrome arc from the required 8px to 4px, affecting controls, rows, badges, and shell affordances throughout the console. The constitution fixes IDE chrome at arc 8, so the general Twenty radius should not replace that structural metric.
AGENTS.md reference: apps/console/AGENTS.md:L53-L54
Useful? React with 👍 / 👎.
| {isOpen && ( | ||
| <> | ||
| <div className="fixed inset-0 z-40" onClick={() => setIsOpen(false)} /> | ||
| <div className="absolute top-[52px] left-0 w-full bg-card border border-border/50 rounded-lg shadow-xl z-50 py-1 flex flex-col gap-0.5 animate-in fade-in zoom-in-95 duration-100"> |
There was a problem hiding this comment.
Route dashboard motion through the reduced-motion tokens
When a user enables reduced motion, this production workspace switcher still runs Tailwind's animate-in, fade, zoom, and literal duration-100 animation because none of those values resolve through --ij-motion. The same new file adds literal 200ms and 300ms navigation animations, so reduced motion no longer renders the inspector settled and static; use the governed motion tokens and transform/opacity inventory instead.
AGENTS.md reference: apps/console/AGENTS.md:L164-L169
Useful? React with 👍 / 👎.
| authToken: | ||
| resolvedCredential.credential.kind === 'service_key' | ||
| ? resolvedCredential.credential.key | ||
| : resolvedCredential.credential.token, |
There was a problem hiding this comment.
Keep object-seam service keys out of ACP authentication
In deployments where CONSOLE_DATA_API_KEY differs from the hosted ACP bearer, the service-key fallback from resolveUpstreamCredential selects that object API key and these lines force it into HostedAcpClient as a Bearer token. This overrides the hosted client's existing THEOREM_API_TOKEN, agent bearer, or THEOREM_API_KEY resolution, so proactivity compilation opens its WebSocket with the wrong credential and returns 502; ACP authentication needs its own credential resolution rather than reusing the consumer object-seam key.
Useful? React with 👍 / 👎.
Connecting is a property of being signed in. No product asks a logged-in person to establish their own session, and the rail round settled that the control is gone for good, not relocated. It was not gone. Four live sites still offered it. EmptyRegion's not-connected cause defaulted its button to Reconnect, which is what ViewStates renders for every unavailable view that passes onRetry, so it was reachable from any surface whose capability was down. degradation.ts's console_data_api_unreachable row was the only entry in that map not already saying Retry. The transcript told the reader to reconnect to continue the thread, and the composer said sending was paused until reconnect. Naming the cause is still right, so the titles and details stay: the reader should know the data API is unreachable. What goes is asking them to fix it. Every one becomes Retry, which is another attempt at the read that failed and is what the sibling rows already offered. The ViewStates test now asserts the absence as well as the label, so reintroducing the control fails there rather than in review. Not touched: StatusBar.tsx still carries a Reconnect action, but the shell dropped the bottom strip in dc4771d and nothing imports the file any more, so it is pre-existing dead code rather than an affordance. Flagged for its own removal along with the two comments that still describe it as live.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 75d0338d72
ℹ️ 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".
| return () => { | ||
| cancelled = true; | ||
| if (persistTimer.current) clearTimeout(persistTimer.current); | ||
| }; |
There was a problem hiding this comment.
Flush pending canvas writes before unmounting
When a user adds or moves a node and collapses the inspector within the 250 ms debounce window, closing the rail unmounts JsonCanvasLayer and this cleanup cancels the only scheduled canvas.apply_json call. Reopening the rail hydrates the previous document, so the latest edit is lost; flush the pending document during cleanup rather than discarding the timer.
AGENTS.md reference: apps/console/AGENTS.md:L138-L138
Useful? React with 👍 / 👎.
| const error = receiptFailed(result); | ||
| if (error) { | ||
| setPersistError(error); | ||
| applyLocal(lastReceiptedRef.current); | ||
| return; | ||
| } | ||
| lastReceiptedRef.current = next; |
There was a problem hiding this comment.
Prevent failed older saves from rolling back newer edits
If one persistence request fails after the user has already made another edit, this callback restores lastReceiptedRef even though a newer document is queued for persistence. The queued write can subsequently succeed, but its success handler never reapplies that document locally, leaving the visible canvas stale until remount or reload; guard rollback with a request/version check or serialize the local reconciliation with the saves.
AGENTS.md reference: apps/console/AGENTS.md:L138-L138
Useful? React with 👍 / 👎.
| <div | ||
| className={`flex min-h-0 flex-1 flex-col overflow-hidden transition-all duration-(--ij-motion) ease-(--ij-ease) ${ | ||
| isCollapsed ? 'w-0 opacity-0' : 'w-full opacity-100' | ||
| }`} |
There was a problem hiding this comment.
Remove collapsed panel controls from keyboard focus
When the sidebar is collapsed, this only reduces the injected panel to zero width and opacity while leaving all of its buttons, inputs, and links mounted and focusable. Keyboard and screen-reader users can therefore tab through invisible panel controls before reaching visible content; apply an accessibility-hiding mechanism such as inert while collapsed, or conditionally unmount/disable the interactive subtree.
Useful? React with 👍 / 👎.
| if (item.scope.kind === 'workspace') return true; | ||
| if (!viewerUserId) return true; | ||
| return item.scope.userId === viewerUserId; |
There was a problem hiding this comment.
Hide user-scoped navigation until identity resolves
While useSession() is still loading, or whenever the session lacks both harnessIdentity and githubLogin, viewerUserId is empty and this branch admits every user-scoped nav-item returned by the workspace host. In a multi-user workspace, another member's private navigation labels can therefore appear and be selectable until identity resolves; workspace-scoped rows may be shown immediately, but user-scoped rows should be withheld unless their userId matches a verified viewer ID.
Useful? React with 👍 / 👎.
| /* The readiness poll below still writes degradation into the shell store; | ||
| only the status-bar reader is gone. Whatever re-homes the reconnect | ||
| affordance binds to that atom rather than re-fetching. */ | ||
| const setWorkspaceDegradation = useShellStore( | ||
| (state) => state.setWorkspaceDegradation, |
There was a problem hiding this comment.
Stop polling readiness after removing its only consumer
The status-bar reader was removed, and a repo-wide search shows no remaining mounted consumer of workspaceDegradation, but the shell still fetches workspace readiness every 1.5 seconds and writes the result into that unread atom. Each open console consequently generates about 40 unnecessary readiness requests per minute indefinitely; remove or suspend the poll until the replacement degradation affordance actually subscribes to this state.
Useful? React with 👍 / 👎.
Two of the three things the rail round asked for, against the OpenHuman reference. The canvas. The rail carried JsonCanvasLayer, a second canvas language, which is why a node in the rail and a node on the Data model surface did not look or behave alike. SPEC-COMMONPLACE-MODEL-CANVAS-FORK-1.0 makes the OWOX fork the one canvas, so the rail now mounts the same ForkDiagramCanvas the surface mounts rather than a rail-flavoured copy: MartNode, RelEdge and the substrate edge language arrive already shared. Pin and unpin post to the routes the surface posts to, because a canvas that draws ghosts and then refuses to adopt one is a picture of an affordance rather than the affordance. The frame. The reference rail is inset on all four sides with its own radius, so the ground runs behind and around it and the panel reads as an object. Ours was a full-bleed aside with a single left hairline, which reads as the window getting narrower instead. The inset is also what makes collapse legible: a card can leave, an edge can only shrink. Ledger first, per the constitution: seven rows added naming twenty-ui's Card, MenuItemNavigate, Tag/Status, RoundedIconButton, LightIconButton and Pill as the sources for the rail's frame, activity rows, step state, action cluster and meta footer, plus @commonplace/model-canvas for the canvas body. Nothing here is hand-rolled that the fork already owns. Not done, and visible rather than quietly dropped: the activity list, action cluster and meta footer are ledgered but not yet built, so the rail does not yet match the reference's composition. The canvas takes its scope through canvasTopicId, which the shell does not pass yet, so it renders empty until that wire lands rather than guessing a topic. Caught while writing this: rounded-(--radius-island) is not a token. The register defines --radius-ij-island, and the lint passes either way because the syntax is legal, so the corner would have stayed square.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 189f5aaddc
ℹ️ 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".
| const authToken = body.authToken; | ||
| if ( | ||
| authToken !== undefined | ||
| && (typeof authToken !== 'string' || authToken.trim() === '') |
There was a problem hiding this comment.
Reject client-supplied ACP bearer credentials
When a signed-in caller includes authToken in a POST to /api/chat/transport, validateBridgePayload preserves it, the route passes the full body to resolveBridgeSession, and the session manager forwards this value as the hosted ACP Authorization bearer. This lets the caller override the server-owned ACP credential after configuredServiceTenantMatches has checked only the signed-in principal, breaking the binding between that principal and the credential used upstream; accept credentials only through a trusted server-side API rather than this client-controlled bridge payload.
Useful? React with 👍 / 👎.
| {jsonCanvas ? ( | ||
| <div className="absolute inset-0 z-0 overflow-hidden"> | ||
| <RailModelCanvas topicId={canvasTopicId} /> | ||
| </div> |
There was a problem hiding this comment.
Mount the configured inspector canvas
In the production IntuiShell mount, InspectorRail never supplies canvasTopicId, so this always passes the default empty string to RailModelCanvas; its effect takes the empty-model branch and never fetches any graph. The enabled inspector canvas is consequently blank, and the newly added JsonCanvasLayer that should hydrate and persist canvas.inspector.rail is never mounted anywhere. Mount that configured layer here instead of the unscoped model canvas.
AGENTS.md reference: apps/console/AGENTS.md:L138-L138
Useful? React with 👍 / 👎.
| // Published jshguo: icon rail (w-16=64) + expanded detail (w-80=320). | ||
| expect(geometry.sidebar?.width).toBe(384); |
There was a problem hiding this comment.
Expect the sidebar width implemented by the shell
The production sidebar is explicitly constrained to 304px, and its expanded children now resolve to a 64px icon rail plus --ij-sidebar-expanded-w at 240px. The measured [data-jshguo-sidebar] width is therefore 304px rather than 384px, so this assertion fails in every desktop signature run; update the expectation and stale w-80 comment, or restore a 320px detail panel if that was intended. This test is part of the required Playwright merge gate.
AGENTS.md reference: apps/console/AGENTS.md:L197-L197
Useful? React with 👍 / 👎.
| @@ -0,0 +1,685 @@ | |||
| 'use client'; | |||
|
|
|||
| // SOURCING: 21st/@arunjdass/dashboard-sidebar — installed as published, then | |||
There was a problem hiding this comment.
Remove prohibited dash characters from console files
This added comment contains an em dash, and the same prohibited character is introduced elsewhere in the console patch, including json-canvas-layer.tsx and CanvasView.tsx. The console writing rule explicitly bans em and en dashes even in code comments, so replace these characters throughout the changed console files with permitted punctuation.
AGENTS.md reference: apps/console/AGENTS.md:L173-L174
Useful? React with 👍 / 👎.
| } | ||
| `} | ||
| style={{ paddingLeft: `${level * 12 + 10}px` }} | ||
| onClick={handleClick} |
There was a problem hiding this comment.
Render inspector navigation rows as keyboard controls
When a keyboard user reaches the inspector, these production Places and Objects rows cannot receive focus or be activated because the click handler is attached to a plain div with no role, tabIndex, or key handler. As a result the right-rail navigation is pointer-only; render each row as a button or provide equivalent keyboard semantics.
Useful? React with 👍 / 👎.
Both from twenty-ui, per the ledger rows added with the canvas: rows are MenuItemNavigate, the tool chip is Tag, the primary is RoundedIconButton and the secondaries are LightIconButton, the meta line is Pill. Nothing here reimplements something the fork already owns. The steps are real. useThreadStore().plan is the live AgentPlanStep list the chat rail already renders, so the rail is a second reading of one run rather than a second source of truth, and there is no fixture behind it. The status enum already carries the three weights the reference distinguishes: the step running now takes the accent, finished steps settle into full ink, steps not yet reached stay muted. Each row also stamps data-step-status, so the distinction is assertable and a restyle cannot quietly drop it. Empty renders nothing, and that is the test that matters. The rail is always on screen, so a heading over an empty plan would tell the reader an agent is working every time they open it. The cluster keeps the reference's shape, one round primary with smaller secondaries and a line of hint text, and not its particular buttons. Theirs is push-to-talk and this product has no voice input, so a microphone would be a picture of a feature. The primary opens the canvas surface, the secondary collapses the rail, and the palette secondary does not render at all unless a handler is passed. The meta line carries whether a run is in flight, because the reference's context window and spend figure have no reading at the rail and inventing them would be worse than a shorter footer. fork-icon bridges one real type disagreement: Noun marks take size?: number and the fork passes number | string, which no cast should paper over. The first version restated IconComponentProps by hand and drifted immediately, missing that stroke is number | string and that aria-hidden is in the shape, so it imports the fork's type instead. Built at module scope: an identity minted in render remounts the icon. tsc clean against the one inherited baseline error. gate:register, gate:fence, gate:twenty and gate:icons all pass. Not visually verified in a browser yet.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
There was a problem hiding this comment.
Note
Due to the large number of review comments, Critical severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/console/src/components/chat/ChatSidebar.tsx (1)
242-254: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winRemove arbitrary Tailwind classes.
The changed classes use
border-[...],bg-[...], androunded-[...]. These bypass the named register utilities and fail the console fence. Replace them with approved named token utilities or registered semantic classes.As per coding guidelines,
apps/consoleTSX must not use arbitrary-value Tailwind classes.Also applies to: 294-297, 319-322, 431-469
🤖 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/chat/ChatSidebar.tsx` around lines 242 - 254, Replace all arbitrary-value Tailwind classes throughout ChatSidebar that use bracket syntax (border-[...], bg-[...], rounded-[...]) with approved named token utilities or registered semantic classes from the design system. This includes the border-[color:var(...)] classes wrapping CSS variables in the sidebar brand and search sections, the bg-[color:var(...)] class in the search label, and the rounded-[var(...)] class in the control radius definition. Remove the bracket notation entirely and substitute with the corresponding named utility classes that reference the same design tokens, ensuring compliance with the console fence validation rules.Source: Coding guidelines
🟠 Major comments (24)
apps/console/src/components/ui/sidebar-component.tsx-89-90 (1)
89-90: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winReplace the arbitrary-value Tailwind utilities.
The classes
aspect-[24/24],aspect-[24/16],py-[1px], andh-[800px]violate the console fence. Replace them with named Twenty structural tokens or ledger-approved structural classes.As per coding guidelines, arbitrary-value Tailwind classes are forbidden in
apps/console. <coding_guidelines>Also applies to: 943-943, 1019-1019
🤖 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/ui/sidebar-component.tsx` around lines 89 - 90, Replace the arbitrary-value Tailwind utilities in the sidebar component, including aspect-[24/24], aspect-[24/16], py-[1px], and h-[800px], with existing named Twenty structural tokens or ledger-approved structural classes. Update the affected markup around the visible container elements and the additional referenced locations, preserving the current layout dimensions and behavior without introducing new arbitrary values.Source: Coding guidelines
apps/console/src/components/ui/sidebar-component.tsx-143-165 (1)
143-165: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftMove sidebar animation to
motion/react.These ranges use CSS transitions for width, padding, color, and other properties. The console motion contract permits only transform and opacity animation through
motion/react.Replace the lifecycle transitions with motion variants. Use tokens from
src/motion/motion-tokens.ts. Add each interaction to the motion inventory.As per coding guidelines, all console animation must use
motion/react, animate only transform and opacity, honor reduced motion, and appear in the interaction inventory. <coding_guidelines>Also applies to: 615-616, 725-755, 808-827, 900-932, 972-974
🤖 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/ui/sidebar-component.tsx` around lines 143 - 165, Replace the CSS transition-based sidebar animations surrounding the search area and the referenced ranges with motion/react components and variants, using tokens from src/motion/motion-tokens.ts. Restrict animated properties to transform and opacity, preserve the expanded/collapsed interaction states, honor reduced-motion behavior, and register each converted interaction in the console motion inventory.Source: Coding guidelines
apps/console/src/components/ui/sidebar-component.tsx-808-830 (1)
808-830: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRemove collapsed panel controls from keyboard navigation.
The collapsed panel has zero width and zero opacity, but its interactive descendants remain focusable. Keyboard users can move focus into controls that they cannot see.
Apply
inertandaria-hiddenwhileisCollapsedis true. Keep the visible reopen control outside the inert subtree.Proposed fix
<div + aria-hidden={isCollapsed} + inert={isCollapsed ? true : undefined} className={`flex min-h-0 flex-1 flex-col overflow-hidden transition-all duration-(--ij-motion) ease-(--ij-ease) ${ isCollapsed ? 'w-0 opacity-0' : 'w-full opacity-100' }`}🤖 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/ui/sidebar-component.tsx` around lines 808 - 830, Update the collapsed panel wrapper around the injected panel content to apply inert and aria-hidden whenever isCollapsed is true, removing its interactive descendants from keyboard navigation and the accessibility tree. Keep both attributes disabled or absent when expanded, and leave SectionTitle’s visible reopen control outside this inert subtree.apps/console/src/styles/twenty-register.css-196-197 (1)
196-197: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winKeep IntelliJ UI metrics for Console chrome.
--ij-control-h,--ij-control-min-w,--ij-tab-h,--ij-toolbar-h,--ij-statusbar-h, and--ij-tree-insetare chrome metrics. This range replaces them with Twenty spacing tokens.Restore the IntelliJ UI metric values. Use Twenty structural metrics only for record surfaces.
As per coding guidelines, "Use IntelliJ UI metrics for chrome and Twenty structural metrics for record surfaces. Do not blend the two systems."
Also applies to: 199-203
🤖 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/styles/twenty-register.css` around lines 196 - 197, Restore the IntelliJ UI metric values for the chrome variables --ij-control-h, --ij-control-min-w, --ij-tab-h, --ij-toolbar-h, --ij-statusbar-h, and --ij-tree-inset instead of mapping them to Twenty spacing tokens. Keep Twenty structural metrics limited to record surfaces and do not mix the two metric systems.Source: Coding guidelines
packages/twenty-ui/src/theme-constants/theme-dark.css-72-155 (1)
72-155: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRestore the generated-theme parity contract.
The parity test rejects
display-p3and hexadecimal values. It also requiresvar(--ij-*)semantic slots and shared radius variables. This range emits all of the rejected forms. The current parity test will fail.Update the test and every dependent output contract in the same change, or retain the existing generated representation.
Also applies to: 166-247, 1005-1005
🤖 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 `@packages/twenty-ui/src/theme-constants/theme-dark.css` around lines 72 - 155, The parity test rejects display-p3 color format and hexadecimal notation values, but the current theme-dark.css file (in lines 72-155, 166-247, and 1005-1005) uses these formats exclusively. Either update the parity test to accept display-p3 and hexadecimal color values and update all dependent output contracts that validate against it, or revert the CSS custom properties throughout theme-dark.css to use var(--ij-*) semantic slots and shared radius variables that match the existing generated representation.apps/console/src/styles/twenty-register.css-40-161 (1)
40-161: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftKeep the Int UI register as the Console color source.
This block assigns hue, seam, ink, accent, status, and domain colors from
--t-*palette values. The--ij-*names do not preserve the required source because Twenty supplies the color values.Keep Console colors in the Int UI register. Restrict Twenty tokens to structural use.
As per coding guidelines, "Use only the Int UI register for color and the Twenty structural tokens for structure."
🤖 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/styles/twenty-register.css` around lines 40 - 161, The Int UI register variables like --ij-blue-1 through --ij-program-shape-artifact are currently sourcing their color values from Twenty palette tokens (--t-color-*, --t-tag-*, --t-snack-bar-*, etc.), which violates the guideline to use only the Int UI register for color. Update this block to establish the Int UI register as the authoritative color source by either defining the color values directly in the --ij-* variables or by reversing the dependency so that Twenty structural tokens reference Int UI values instead of the other way around, ensuring that color assignments remain within the Int UI register and Twenty tokens are restricted to structural use only.Source: Coding guidelines
apps/console/scripts/check-twenty-fence.mjs-84-92 (1)
84-92: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftCanonicalize the module target before allowing the relative import.
path.resolve()follows the lexical path, andapps/console/node_modules/twenty-uipoints atpackages/twenty-ui. A relative import such as../../node_modules/twenty-ui/componentcan bypass thepackages/twenty-test while importing forked AGPL code. Usefs.realpathor a resolver that follows symlinks before the/packages/twenty-/guard.🤖 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/scripts/check-twenty-fence.mjs` around lines 84 - 92, Update the relative-specifier handling in the module-check logic around the spec and resolved variables to canonicalize the target through symlinks before applying the packages/twenty- path guard. Use the existing filesystem or resolver APIs to realpath the resolved target, then continue only when the canonical path does not point into packages/twenty-; preserve the current behavior for ordinary relative files and ensure unresolved targets are handled consistently with the check’s existing error flow.Source: Learnings
apps/console/src/styles/geometry.css-40-46 (1)
40-46: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winReplace raw shadow colors with approved tokens.
Lines 40 to 46 use literal
rgb()colors. Resolve these shadows through approved Int UI or Twenty tokens instead.As per coding guidelines,
apps/console/**/*.{ts,tsx,css}must “Use only the Int UI register for color and the Twenty structural tokens for structure.”🤖 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/styles/geometry.css` around lines 40 - 46, Update the shadow variables --shadow-lifted and --shadow-docked-right/left/top/bottom to use approved Int UI or Twenty color tokens instead of literal rgb() values, while preserving their existing offsets, blur, spread, and opacity.Source: Coding guidelines
apps/console/scripts/check-contrast.mjs-120-122 (1)
120-122: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winReject translucent
rgba()values.Lines 120 to 122 parse an alpha channel but discard it. A token such as
rgba(0, 0, 0, 0.03)reacheswcagContrastas opaque black. This can make the contrast gate pass an actual translucent color.Return
nullunless the parsed alpha is exactly opaque.🤖 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/scripts/check-contrast.mjs` around lines 120 - 122, Update the rgb match handling to extract and validate the alpha channel from the rgba regex capture. After confirming the rgb pattern matches, check that the captured alpha component (if present) represents full opacity; return null if the alpha indicates any transparency, otherwise proceed with the existing return statement that provides the srgb space and mapped RGB values. This ensures translucent colors like rgba(0, 0, 0, 0.03) are rejected rather than treated as opaque black.apps/console/src/components/shell/Sidebar.tsx-656-680 (1)
656-680: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winMake pin actions reachable without hover.
At rest, this overlay has
opacity-0andpointer-events-none. Onlygroup-hoverexposes it. Touch users cannot hover, so they cannot invoke Pin, Unpin, or Remove. Keyboard focus can also enter an invisible action button.Add an always reachable action trigger or a click-controlled menu. Reveal the actions on keyboard focus as well as pointer interaction.
🤖 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/Sidebar.tsx` around lines 656 - 680, Update the landmark action overlay surrounding the Pin/Unpin and Remove buttons so the actions are reachable without hover, using an always-available trigger or click-controlled menu. Ensure pointer interaction and keyboard focus reveal the actions, and remove the possibility of keyboard focus entering buttons while they remain visually hidden.apps/console/CLAUDE.md-140-140 (1)
140-140: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winDefine one canonical inspector canvas.
ModelCanvasShellis documented as supersedingJsonCanvasLayerfor the rail, but the other entries still assigncanvas.inspector.railtoJsonCanvasLayerandcanvas.apply_json. This leaves two implementation contracts for one visual need.
apps/console/CLAUDE.md#L140-L140: define the single rail canvas source and its persistence contract.apps/console/CLAUDE.md#L134-L134: remove or re-scope theJsonCanvasLayerrail assignment.apps/console/CLAUDE.md#L190-L190: align the durability test guidance with the selected implementation.apps/console/AGENTS.md#L138-L138: mirror the canonical source and scope.As per coding guidelines, every console visual and behavioral need must resolve to a named ledger source before implementation.
🤖 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/CLAUDE.md` at line 140, Define one canonical inspector rail canvas and its persistence contract at apps/console/CLAUDE.md:140-140, using ModelCanvasShell rather than maintaining parallel JsonCanvasLayer and canvas.apply_json contracts. Remove or re-scope the JsonCanvasLayer rail assignment at apps/console/CLAUDE.md:134-134, align durability-test guidance with the selected implementation at apps/console/CLAUDE.md:190-190, and mirror the canonical source and scope in apps/console/AGENTS.md:138-138.Source: Coding guidelines
apps/console/src/components/chat/ChatSidebar.tsx-280-291 (1)
280-291: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winUse the approved tag primitive for capability badges.
These styled
spanelements recreate a badge surface. The ledger already provides TwentyTagandPillprimitives. Render each capability through the approved primitive instead of restating its border, radius, and text treatment.As per coding guidelines, when a matching catalog component exists, install and mount it instead of implementing a local lookalike.
🤖 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/chat/ChatSidebar.tsx` around lines 280 - 291, Replace the manually styled span elements in the capabilities.map callback within ChatSidebar with the approved Tag or Pill primitive from the Twenty design system. Update the JSX to render each capability through the catalog component instead of maintaining custom border, radius, and text styling on the span element. Preserve the capability.id key and capability.name content while removing the className and style prop from the span.Source: Coding guidelines
apps/console/src/components/chat/ChatSidebar.tsx-134-164 (1)
134-164: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winProvide a supported rail footer.
TwoLevelSidebarShellreceives nofooter. The installed shell then renders its default Settings and Avatar controls. A click on Settings passes"settings"through Line 147, can store an invalidChatDockSurfacein uncontrolled mode, and matches no route ingoSurface.Pass an explicit footer that contains only supported Noun controls and supported routes. As per coding guidelines, product and domain icons must use normalized Noun Project SVGs from
src/components/shell/icons.tsx.🤖 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/chat/ChatSidebar.tsx` around lines 134 - 164, Add an explicit footer prop to the TwoLevelSidebarShell component that contains only Noun controls mapped to supported ChatDockSurface values. The footer must avoid passing unsupported surface identifiers like "settings" through the onSectionChange handler and goSurface function. Use normalized Noun Project SVGs imported from src/components/shell/icons.tsx for all product and domain icons in the footer controls, following the established coding guidelines for icon usage.Source: Coding guidelines
apps/console/src/components/shell/Sidebar.tsx-657-661 (1)
657-661: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winRemove CSS transitions from the shell.
These transitions do not use
motion/react. The transition at Line 747 also animatesbackground-colorandcolor, which are not permitted animation properties. Remove these transitions, or implement retained transform or opacity motion throughmotion/react, reduced-motion handling, and the interaction inventory. Keep color state changes immediate.As per coding guidelines, React lifecycle motion must use
motion/react, use only transform and opacity, honor reduced motion, and appear in the interaction inventory.Also applies to: 739-749, 784-794
🤖 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/Sidebar.tsx` around lines 657 - 661, Remove all CSS transition classes (such as transition-opacity in the span at line 657) from the Sidebar component, including the similar elements at lines 739-749 and 784-794. If animations are needed for hover or interactive states, implement them using motion/react with only transform or opacity properties, ensure reduced-motion is honored, add entries to the interaction inventory, and keep color state changes (background-color, color) as immediate non-animated updates. Preserve the immediate opacity and hover state changes while eliminating the non-motion/react CSS transitions.Source: Coding guidelines
apps/console/e2e/signatures.spec.ts-206-214 (1)
206-214: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftKeep the account control on the chrome metric.
This test locks a 32px rail control because
--ij-control-hinherits--t-spacing-8. The account trigger is console chrome and must use the 28px IntelliJ control metric. Repair the register bridge, then restore this assertion to28px. Do not accept a Twenty spacing value for rail chrome.As per coding guidelines, console chrome must use IntelliJ UI metrics and must not blend Twenty structural metrics.
🤖 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/e2e/signatures.spec.ts` around lines 206 - 214, The test assertion expects a 32px height for the account trigger element using the data-account-trigger selector, but this value comes from an incorrect register bridge where the --ij-control-h CSS variable is inheriting Twenty's --t-spacing-8 instead of the proper IntelliJ control metric. Fix the register bridge configuration so that --ij-control-h correctly resolves to 28px (the IntelliJ UI standard for controls), then update the height assertion in the test from 32px to 28px to reflect the correct console chrome metric. Ensure the account trigger element uses IntelliJ UI metrics exclusively and does not blend Twenty spacing values.Source: Coding guidelines
apps/console/src/components/shell/InspectorRail.tsx-59-60 (1)
59-60: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRemove CSS-driven inspector rail animation.
RAIL_EDGE_CLASSstarts a CSS transition fortransformandcolor, and the panel frame starts a CSS opacity transition. These transitions bypassmotion/react, have no interaction-inventory entry, and do not settle for reduced-motion users. The color transition also violates the transform-and-opacity-only rule.Use static states, or implement the effect with
motion/react, registered motion tokens, an inventory entry, and a reduced-motion branch.As per coding guidelines, all animation must use
motion/reactand reduced-motion output must be static.Also applies to: 214-218
🤖 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/InspectorRail.tsx` around lines 59 - 60, Remove CSS-driven animation from RAIL_EDGE_CLASS by deleting transition, transform-hover, and color-transition utilities, and remove the panel frame’s opacity transition at the referenced location. Keep the inspector rail visuals static unless replacing them through motion/react with registered tokens, inventory coverage, and a reduced-motion static branch.Source: Coding guidelines
apps/console/src/components/shell/RailInsights.tsx-42-42 (1)
42-42: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winUse an approved failure-ink utility.
text-[color:var(--hue-status-failed)]is an arbitrary Tailwind value and bypasses the Int UI color register. Define or bridge a semantic failure-ink token, then use its namedtext-ij-*utility.As per coding guidelines, arbitrary-value Tailwind classes are forbidden. Based on learnings, the Twenty fence and register lint must pass.
🤖 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/RailInsights.tsx` at line 42, Replace the arbitrary Tailwind class in the RailInsights status-color logic with an approved semantic failure-ink token and its named text-ij-* utility. Define or bridge the token through the Int UI color register as needed, while preserving the existing failed-status styling and ensuring Twenty fence and register lint pass.Sources: Coding guidelines, Learnings
apps/console/src/components/shell/RailModelCanvas.tsx-52-76 (1)
52-76: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winPrevent a topic switch from mutating through stale diagram data.
When
topicIdchanges,scopechanges immediately, butobservedanddeclaredremain from the prior topic until the new fetch resolves.handlePinandhandleUnpincan then send prior-topic identifiers topostPinorpostUnpinwith the new topic.Track the loaded topic ID. Do not render or mutate stale model data while the new topic loads. Reset pending state, selection, and layout for a new topic. Add topic-switch pin and unpin regression coverage.
Also applies to: 83-113
🤖 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/RailModelCanvas.tsx` around lines 52 - 76, Update the model-loading state around the useEffect and handlePin/handleUnpin flows to track the topic ID associated with the loaded observed and declared data. On topic changes, immediately clear or invalidate prior model data, reset pending state, selection, and layout, and prevent rendering or mutation until the fetch for the current topic resolves; ensure pin and unpin use only data loaded for the active topic. Add regression coverage for switching topics before the fetch completes and verify stale identifiers are never sent.apps/console/src/components/shell/RailModelCanvas.tsx-48-48 (1)
48-48: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy liftPersist rail layout through authenticated state.
positionsis the only storage for rail layout.onLayoutChangewrites only React state, so a remount or reload loses user-directed canvas layout. A separate rail-owned layout object can avoid conflicts with the Data model surface while still preserving each authenticated scope.Persist this state through the authenticated object seam, or make the rail layout non-editable.
Based on learnings, canvas state must persist through the authenticated object seam.
Also applies to: 127-128
🤖 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/RailModelCanvas.tsx` at line 48, Replace the local-only positions state in RailModelCanvas with persistence through the authenticated object seam. Update onLayoutChange to read and write the rail-owned layout object while preserving each authenticated scope, and initialize positions from that persisted state so remounts and reloads retain user-directed layout without altering the Data model surface.Source: Learnings
apps/console/src/components/shell/InspectorRail.tsx-163-169 (1)
163-169: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy liftSerialize workspace selection updates.
handleWorkspaceSelectimmediately commitsactiveWorkspaceIdwhileselectIdentityWorkspaceresolves out of order. If workspace A and B requests return after the user clicked both, the older A response can make the rail display A while the latest click selected B. A rejected update can also leave the rail showing a workspace that is not the principal’s current active workspace. Serialize the requests or attach a version to the pending selection and reconcileDashboardSidebarfrom the final accepted identity session.🤖 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/InspectorRail.tsx` around lines 163 - 169, Update handleWorkspaceSelect so workspace identity updates are serialized or versioned, ensuring only the latest selection can reconcile the rail and DashboardSidebar with the accepted identity session. Prevent stale responses from restoring an older workspace, and reconcile local active workspace state after the final selectIdentityWorkspace result, including rejected updates.apps/console/src/components/ui/json-canvas-layer.tsx-85-90 (1)
85-90: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winPreserve JSON Canvas edge metadata during persistence.
The flow conversion drops fields such as
fromSide,toSide, andcolor. Every later persist rebuilds all edges with only IDs, endpoints, and labels. A drag or connection edit can therefore remove imported edge routing and color metadata. Preserve the matching prior edge fields by ID, and add a round-trip regression test.Proposed fix
function jsonCanvasFromFlow( previous: JSONCanvas, nodes: readonly JsonCanvasFlowNode[], edges: readonly Edge[], ): JSONCanvas { const previousById = new Map(previous.nodes.map((node) => [node.id, node])); + const previousEdgesById = new Map(previous.edges.map((edge) => [edge.id, edge])); const nextNodes: CanvasNode[] = nodes.map((node) => { // ... }); const nextEdges: CanvasEdge[] = edges .filter((edge) => edge.source && edge.target) - .map((edge) => ({ - id: edge.id, - fromNode: edge.source, - toNode: edge.target, - label: typeof edge.label === 'string' ? edge.label : undefined, - })); + .map((edge) => { + const prior = previousEdgesById.get(edge.id); + return { + ...prior, + id: edge.id, + fromNode: edge.source, + toNode: edge.target, + label: typeof edge.label === 'string' ? edge.label : prior?.label, + }; + }); return { nodes: nextNodes, edges: nextEdges }; }Also applies to: 94-131
🤖 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/ui/json-canvas-layer.tsx` around lines 85 - 90, Update the edge conversion and persistence flow around the visible `edges` mapping to retain metadata from the matching prior `CanvasEdge` by edge ID, including `fromSide`, `toSide`, and `color`, while preserving updated IDs, endpoints, and labels. Ensure newly created edges still work without prior metadata, and add a regression test covering persistence round-tripping of imported edge metadata.apps/console/src/components/ui/dashboard-sidebar.tsx-651-680 (1)
651-680: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftReplace the custom search popup with
cmdk.This code implements a search palette with a manually managed overlay and input. The console assigns search and palette behavior to
cmdk. Mount the configuredcmdkcomponent instead of retaining a parallel dialog.As per coding guidelines: "use
cmdkfor search and palettes."🤖 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/ui/dashboard-sidebar.tsx` around lines 651 - 680, Replace the manually managed search overlay in the isSearchOpen rendering block with the console’s configured cmdk component, reusing its existing search/palette behavior and configuration. Remove the custom input, backdrop, close controls, and placeholder content rather than maintaining a parallel dialog, while preserving the existing trigger state integration.Source: Coding guidelines
apps/console/src/components/ui/badge.tsx-8-23 (1)
8-23: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftMove CSS animation into the approved motion system.
These components use Tailwind
transition-*,animate-in, andduration-*utilities. They animate colors and grid rows, use literal durations, and provide no reduced-motion path. Usemotion/reactwith tokens fromsrc/motion/motion-tokens.ts, record the interactions, and limit animated properties to transform and opacity.
apps/console/src/components/ui/badge.tsx#L8-L23: remove the CSS transition unless the badge has a required Motion interaction.apps/console/src/components/ui/dashboard-sidebar.tsx#L168-L203: move workspace menu motion to the approved interaction system.apps/console/src/components/ui/dashboard-sidebar.tsx#L274-L340: replace navigation and expansion transitions.apps/console/src/components/ui/dashboard-sidebar.tsx#L577-L681: replace preview sidebar and search-popup transitions.As per coding guidelines: "All animation must use
motion(motion/react) and tokens fromsrc/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/ui/badge.tsx` around lines 8 - 23, Remove the CSS transition from badgeVariants in apps/console/src/components/ui/badge.tsx at lines 8-23 unless a required Motion interaction is added. In apps/console/src/components/ui/dashboard-sidebar.tsx, update lines 168-203, 274-340, and 577-681 to use motion/react with tokens from src/motion/motion-tokens.ts, animate only transform and opacity, record the interactions, and provide reduced-motion behavior; replace the existing transition, animate-in, and duration utilities without introducing literal durations.Source: Coding guidelines
apps/console/src/components/ui/json-canvas-layer.tsx-276-291 (1)
276-291: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winPersist node removals from React Flow.
React Flow’s Delete and Backspace removals call
onNodesChange, but this handler only updates local state while edge removals callcommitFlow. Set the derived node list and persist it throughcommitFlowso deleted cards do not return after hydration. Add a delete-and-reload regression test.🤖 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/ui/json-canvas-layer.tsx` around lines 276 - 291, Update onNodesChange to derive the next node list with applyNodeChanges, return it through setNodes, and call commitFlow with the current edges when hydrated and changes include a removal. Add a regression test that deletes a node, reloads or rehydrates the canvas, and verifies the deleted card remains absent.
🟡 Minor comments (8)
packages/twenty-ui/src/theme/generator/palette/twenty-dark.css-171-171 (1)
171-171: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winQuote the font family names so the Stylelint gate passes.
Stylelint reports
value-keyword-caseerrors for unquotedInterandDM Mono. Quote the names in the palette sources, then regenerate the generated theme file.
packages/twenty-ui/src/theme/generator/palette/twenty-dark.css#L171-L171: quoteInter.packages/twenty-ui/src/theme/generator/palette/twenty-dark.css#L248-L248: quoteDM Mono.packages/twenty-ui/src/theme/generator/palette/twenty-light.css#L175-L175: quoteInter.packages/twenty-ui/src/theme/generator/palette/twenty-light.css#L252-L252: quoteDM Mono.packages/twenty-ui/src/theme-constants/theme-dark.css#L166-L166: regenerate the quotedIntervalue.packages/twenty-ui/src/theme-constants/theme-dark.css#L243-L243: regenerate the quotedDM Monovalue.Proposed CSS change
- --t-font-family: Inter, sans-serif; + --t-font-family: "Inter", sans-serif; - --t-code-font-family: DM Mono; + --t-code-font-family: "DM Mono";🤖 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 `@packages/twenty-ui/src/theme/generator/palette/twenty-dark.css` at line 171, Quote the Inter and DM Mono font family names in packages/twenty-ui/src/theme/generator/palette/twenty-dark.css at lines 171 and 248 and packages/twenty-ui/src/theme/generator/palette/twenty-light.css at lines 175 and 252, then regenerate the corresponding quoted values in packages/twenty-ui/src/theme-constants/theme-dark.css at lines 166 and 243.Source: Linters/SAST tools
packages/twenty-ui/src/theme-constants/theme-light.css-166-166 (1)
166-166: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winQuote the font family names.
Lines 166 and 243 fail
value-keyword-case. QuoteInterandDM Monoso Stylelint treats them as font-family strings.Proposed fix
- --t-font-family: Inter, sans-serif; + --t-font-family: "Inter", sans-serif; ... - --t-code-font-family: DM Mono; + --t-code-font-family: "DM Mono";Also applies to: 243-243
🤖 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 `@packages/twenty-ui/src/theme-constants/theme-light.css` at line 166, Update the --t-font-family custom property to quote the font family names so Stylelint processes them as strings instead of keywords. Wrap Inter in quotes on line 166 and wrap DM Mono in quotes on line 243 to resolve the value-keyword-case violations, preserving the comma-separated format and the generic fallback font keywords like sans-serif.Source: Linters/SAST tools
apps/console/scripts/check-contrast.mjs-20-28 (1)
20-28: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winInclude the
twenty-ui/style.csssource inregisterSources.
apps/console/src/styles/app.cssimportstwenty-ui/style.css, butregisterSourcesomits it. Any relevant--ij-*,--cp-*, or--t-*declarations in that sheet bypass this contrast gate.🤖 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/scripts/check-contrast.mjs` around lines 20 - 28, Add the twenty-ui/style.css source to the registerSources list in the contrast-check script, using the correct relative path from the console app. Keep it processed through the existing readFileSync and comment-removal mapping so its declarations are included in contrast validation.apps/console/src/components/shell/InspectorRail.tsx-150-160 (1)
150-160: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReconcile navigation selection after a rejected navigation.
handleSelectupdatesactiveIdbeforesoftNavigateresolves. If navigation rejects, the pathname does not change, so the render-time reconciliation does not run. The rail then marks an unopened destination as active.Handle rejection and restore selection from the current pathname. Guard the restore so an older failed navigation cannot overwrite a newer successful navigation.
🤖 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/InspectorRail.tsx` around lines 150 - 160, Update handleSelect so rejected softNavigate calls restore activeId based on the current pathname, while preserving the existing object-type and path navigation behavior. Track the navigation attempt or otherwise guard the rejection handler so an older failed navigation cannot overwrite selection from a newer successful navigation.docs/plans/data-canvas-graph-native/SPEC-DATA-CANVAS-GRAPH-NATIVE-1.0.md-224-226 (1)
224-226: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winUse the registered placement vocabulary.
apps/console/src/views/registry.tsxdeclaresplacements: ['ground', 'full']. This acceptance criterion requiressurface / full, which implementation cannot satisfy. Changesurfacetoground, or update the descriptor and all consumers together.🤖 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 `@docs/plans/data-canvas-graph-native/SPEC-DATA-CANVAS-GRAPH-NATIVE-1.0.md` around lines 224 - 226, Update the acceptance criterion describing the pane placement to use the registered vocabulary `ground / full` instead of `surface / full`. Keep the existing `canvas.inspector.rail` reference and graph-query behavior unchanged.apps/console/src/components/ui/dashboard-sidebar.tsx-3-6 (1)
3-6: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winRemove forbidden em dashes from console comments.
Replace each em dash with a colon, comma, or parentheses.
apps/console/src/components/ui/dashboard-sidebar.tsx#L3-L6: replace the sourcing-comment punctuation.apps/console/src/views/canvas/CanvasView.tsx#L65-L69: replace the embedded-mode comment punctuation.As per coding guidelines: "Do not use em or en dashes in comments, UI strings, or Markdown."
🤖 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/ui/dashboard-sidebar.tsx` around lines 3 - 6, Replace the em-dash punctuation in the sourcing comment near apps/console/src/components/ui/dashboard-sidebar.tsx lines 3-6 with a colon, comma, or parentheses. Apply the same punctuation-only change to the embedded-mode comment in apps/console/src/views/canvas/CanvasView.tsx lines 65-69; do not alter the comment content.Source: Coding guidelines
apps/console/src/app/dev/chrome-preview/page.tsx-46-49 (1)
46-49: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winCreate the preview host once.
hostis inDashboardSidebar’s effect dependencies, so everyinspectorOpenstate update unregisters the existing nav subscription and subscribes the new per-renderConsoleBlockHost. Move the host creation intouseMemoor keep it outside the component to avoid losing and recreating the subscription on each render.🤖 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/app/dev/chrome-preview/page.tsx` around lines 46 - 49, Update ChromePreviewPage’s ConsoleBlockHost creation so it remains stable across renders, using useMemo or a module-level instance instead of constructing it directly in the component. Preserve the existing CONSOLE_VIEW_REGISTRY initialization while ensuring DashboardSidebar’s effect dependencies no longer receive a new host when inspectorOpen changes.apps/console/src/components/shell/fork-icon.tsx-33-38 (1)
33-38: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winPreserve CSS string sizes instead of parsing them.
Number.parseFloatchanges validIconComponentProps.sizevalues such as"1rem","1.25em", and"100%"into pixel numbers. Keep numeric values for the SVGsize, and pass string sizes throughstyle.widthandstyle.heightin this adapter.🤖 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/fork-icon.tsx` around lines 33 - 38, Update the size handling in the fork icon component to preserve string CSS sizes such as rem, em, and percentage values instead of parsing them. Pass numeric sizes through the Icon size prop, while applying string sizes to both style.width and style.height, preserving the existing color and style merging behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 07a1dff0-7d91-439d-8a80-985b9715a4f0
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (65)
.cursor/rules/no-hand-roll-components.mdcapps/console/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seqapps/console/AGENTS.mdapps/console/CLAUDE.mdapps/console/components.jsonapps/console/e2e/appearance.spec.tsapps/console/e2e/console-ia.spec.tsapps/console/e2e/signatures.spec.tsapps/console/package.jsonapps/console/scripts/check-contrast.mjsapps/console/scripts/check-twenty-fence.mjsapps/console/src/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seqapps/console/src/app/api/proactivity/compile/route.tsapps/console/src/app/chat/page.test.tsxapps/console/src/app/chat/page.tsxapps/console/src/app/dev/chrome-preview/page.tsxapps/console/src/app/page.tsxapps/console/src/app/workspace/[workspaceSlug]/chat/page.test.tsxapps/console/src/app/workspace/[workspaceSlug]/chat/page.tsxapps/console/src/components/chat/ChatSidebar.tsxapps/console/src/components/chat/Composer.tsxapps/console/src/components/chat/Transcript.tsxapps/console/src/components/ground/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seqapps/console/src/components/ground/MaterialLayer.tsxapps/console/src/components/material/EmptyRegion.tsxapps/console/src/components/shell/InspectorRail.tsxapps/console/src/components/shell/IntuiShell.tsxapps/console/src/components/shell/RailActionCluster.tsxapps/console/src/components/shell/RailInsights.test.tsxapps/console/src/components/shell/RailInsights.tsxapps/console/src/components/shell/RailModelCanvas.tsxapps/console/src/components/shell/Sidebar.tsxapps/console/src/components/shell/fork-icon.tsxapps/console/src/components/shell/icons.tsxapps/console/src/components/ui/badge.tsxapps/console/src/components/ui/dashboard-sidebar.tsxapps/console/src/components/ui/dock.tsxapps/console/src/components/ui/json-canvas-layer.tsxapps/console/src/components/ui/sidebar-component.tsxapps/console/src/lib/degradation.tsapps/console/src/lib/server/principal-redirect.tsapps/console/src/motion/motion-tokens.tsapps/console/src/styles/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seqapps/console/src/styles/app.cssapps/console/src/styles/geometry.cssapps/console/src/styles/primer-register.cssapps/console/src/styles/register-bridge.cssapps/console/src/styles/twenty-register.cssapps/console/src/views/ViewStates.test.tsxapps/console/src/views/canvas/CanvasView.tsxapps/console/src/views/registry.tsxdocs/plans/data-canvas-graph-native/SPEC-DATA-CANVAS-GRAPH-NATIVE-1.0.mdpackages/theorem-acp/src/bridge.tspackages/theorem-acp/src/session-manager.test.tspackages/theorem-acp/src/session-manager.tspackages/theorem-acp/src/state.tspackages/twenty-ui/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seqpackages/twenty-ui/src/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seqpackages/twenty-ui/src/theme-constants/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seqpackages/twenty-ui/src/theme-constants/theme-dark.csspackages/twenty-ui/src/theme-constants/theme-light.csspackages/twenty-ui/src/theme/generator/emit.tspackages/twenty-ui/src/theme/generator/palette/.theorem/runs/fe40c00e-6cc7-4515-93b7-cdde99e6c51e.seqpackages/twenty-ui/src/theme/generator/palette/twenty-dark.csspackages/twenty-ui/src/theme/generator/palette/twenty-light.css
💤 Files with no reviewable changes (1)
- apps/console/src/components/ui/dock.tsx
Found by looking at it. The reference's cluster has a whole window to spread across and the rail has about 250px, so laying the primary, the secondaries and the hint out in one row pushed the label past the rail's right edge, where it landed on top of the canvas layer's own add-note affordances. The buttons keep their row and the hint drops beneath them, beside the run-state pill. Same components, same reading order, a column that fits. Verified in the browser against a dev server wired to the e2e stub, so nothing reached a real backend. The OWOX canvas is confirmed mounted in the rail from the same shot: React Flow's zoom controls render inside the panel.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1cc1aa86ef
ℹ️ 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".
| insights list shrinks to nothing when it has nothing true to | ||
| show, so the canvas keeps the height rather than the rail | ||
| reserving space for an empty heading. */} | ||
| <RailInsights className="max-h-1/3 px-1 pt-2" /> |
There was a problem hiding this comment.
Wire the insight rows before showing navigation affordances
When an agent plan contains steps, this production mount omits onOpenStep, so every MenuItemNavigate receives an undefined onClick. The rows still display a trailing chevron and pointer cursor, but clicking them does nothing and the underlying div is not keyboard-focusable; either wire the rows to the owning thread/plan surface or render them with non-navigational anatomy.
Useful? React with 👍 / 👎.
| key={step.id} | ||
| data-rail-insight-step={step.id} | ||
| data-step-status={step.status} | ||
| className={cn('flex items-center gap-1', inkFor(step.status))} |
There was a problem hiding this comment.
Apply status colors to the menu item itself
When the plan mixes running, complete, and pending steps, inkFor(step.status) is applied only to this outer wrapper, while MenuItemNavigate sets its own color: var(--t-font-color-secondary) on the nested menu row and passes explicit colors to its icons. Those declarations prevent the wrapper color from being inherited, so the intended gold, full-ink, and muted status distinction is not visible even though the tests can see the data-step-status attributes.
Useful? React with 👍 / 👎.
| const rgb = value.match(/^rgba?\(\s*([\d.]+)[\s,]+([\d.]+)[\s,]+([\d.]+)\s*(?:[,/]\s*[\d.%]+\s*)?\)$/i); | ||
| if (rgb) { | ||
| return { space: 'srgb', rgb: rgb.slice(1, 4).map((n) => toLinear(Number(n) / 255)) }; |
There was a problem hiding this comment.
Reject alpha colors instead of measuring them as opaque
When any contrast-governed token resolves to rgba(...) with alpha, this regex accepts the value but the returned color discards the alpha channel, so a value such as nearly transparent white on a dark surface is measured as opaque white and can falsely pass the merge gate. This also contradicts resolveToken's stated policy that translucent values must be rejected unless their backing surface is known; capture and reject non-opaque alpha or composite it against the tested background.
AGENTS.md reference: apps/console/AGENTS.md:L49-L51
Useful? React with 👍 / 👎.
Two asks from looking at the running app. Editor no longer seeds a Thread companion. It was the only surface seeding one open, and the exclusion argument the Files surface already uses covers it, so this is one argument rather than a new mechanism. A layout persisted before the change keeps its own copy, so console-host gains a migration step in the same shape as its neighbours: drop the child, drop the orphaned view instance, bump seed_revision. The shell fills the screen. The lift was never an outer frame; the shell root and every ancestor already measured full-bleed at zero radius. It came from the island treatment inside: the ground's inset padding, the editor island's corners, every block island's corners, and the sidebar's outer corners. All four are gone, so content meets the window edge and reads as the base of the screen rather than a card lying on it. The gap between stacked regions stays; that separates regions from each other rather than lifting them off the ground. launch.json gains console-signed-in, which runs the dev server against the e2e stub with the non-production principal fixture. The plain console config inherits .env.local, which points at a real harness, and that is not something to hand a browser session doing UI work. Verified in the browser: workspace.region-thread absent from the DOM, shell flush to all four edges. tsc clean against the one inherited baseline error; gate:register, gate:fence, gate:icons pass; 33 tests. The thread panel survived the first three checks because .next served a stale bundle, not because the change was wrong.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f889e21a6
ℹ️ 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".
| 'active_workspace_configuration_missing', | ||
| 'active_workspace_claim_unavailable', | ||
| 'active_workspace_contract_mismatch', |
There was a problem hiding this comment.
Preserve operational principal failures instead of onboarding
Do not classify active_workspace_configuration_missing, active_workspace_claim_unavailable, or active_workspace_contract_mismatch as onboarding conditions. These represent server configuration, cookie-store, or upstream contract failures (503/502), so creating or selecting a workspace cannot resolve them; redirecting signed-in users to /onboarding hides the actual failure and leaves them retrying workspace actions that still cannot establish a principal. Limit this redirect to missing/refused workspace claims or surface the original operational error.
Useful? React with 👍 / 👎.
| [data-register="intui"][data-theme="dark"], | ||
| [data-register="intui"][data-theme="light"] { | ||
| /* Hue ramps. The console names seven; Twenty carries twelve shades of each. */ | ||
| --ij-blue-1: var(--t-color-blue1); |
There was a problem hiding this comment.
Register the Twenty alias file with the token gate
Add this new register to REGISTER_PROVENANCE and regenerate the checked-in token manifest before merging. Running node apps/console/scripts/check-token-manifest.mjs rejects every --ij-* declaration in this file as minted outside a register and also reports manifest ownership drift, so the console's gate:tokens step fails deterministically for this commit.
Useful? React with 👍 / 👎.
| {!compact && !railOpen ? ( | ||
| <InspectorRailReopen onOpen={() => toggleRail(true)} /> |
There was a problem hiding this comment.
Keep the inspector reachable in compact layouts
When the shell becomes compact below OVERLAY_BREAKPOINT (1100px), the compact branch omits the new inspector Panel entirely, and this condition also suppresses its only reopen affordance. Users in a 1024px window therefore have no way to reach the inspector navigation, model canvas, insights, or actions; render an overlay/drawer equivalent in the compact branch or keep a compact reopen control available.
AGENTS.md reference: apps/console/AGENTS.md:L101-L102
Useful? React with 👍 / 👎.
The rail took a column out of the surface. Now it lies on top of it. The Panel stays, so width, drag, collapse and the persisted size are still react-resizable-panels' job and the ledger row holds. What changes is what the editor measures itself against: the editor group is absolute to the outer group rather than filling its own Panel, so it spans the whole width and the rail paints above it. Measured on the running app: the well Panel still computes 931px, the editor region spans 1199px, and it runs 262px under the rail, which is the rail's full width. Overlay, not a resized column. gate:register and gate:fence pass, 33 tests, tsc clean against the one inherited baseline error.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 @.claude/launch.json:
- Around line 18-23: Update the console-signed-in runtime command to capture the
stub-data-api.mjs background PID, poll port 40999 readiness instead of relying
on sleep 3, and fail before starting next dev if the stub exits or never becomes
ready. Add an exit trap that terminates and waits for the captured stub process
so it cannot remain stale after the console process exits.
- Line 23: Update the console-signed-in launch environment to define
NEXT_PUBLIC_CONSOLE_CHAT_URL and THEOREM_PROACTIVITY_CHANGEFEED_URL using the
local stub endpoints required by the E2E contract, alongside
CONSOLE_E2E_PROACTIVITY_FIXTURE. Ensure the configured URLs target the running
stub data API so chat and live proactivity feeds do not return 404.
- Around line 23-26: Remove autoPort from the signed-in console launch
configuration, or wire the dynamically selected port into the Next --port
argument; ensure the configured launch port and the port reported by the
launcher remain consistent.
In `@apps/console/src/lib/console-host.ts`:
- Around line 443-455: Extend the remote layout adoption flow around
replaceLayout and retiredIds to remove workspace.region-thread and
workspace.region-thread.view before replacing the local layout. Filter
corresponding CONTAINS_EDGE relations, add the removed remote objects to
retiredIds, and pass them through retireRemoteLayoutObjects(); add a regression
test covering adoption of a remote layout containing these retired Thread
objects.
🪄 Autofix
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: 2b651f23-9007-4ca8-bcd1-40cf526f4484
📒 Files selected for processing (9)
.claude/launch.jsonapps/console/src/components/blocks/BlockShell.tsxapps/console/src/components/shell/EditorTabs.tsxapps/console/src/components/shell/IntuiShell.tsxapps/console/src/components/shell/RailActionCluster.tsxapps/console/src/components/ui/sidebar-component.tsxapps/console/src/lib/console-host.test.tsapps/console/src/lib/console-host.tsapps/console/src/lib/workspace-seed.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/console/src/components/shell/IntuiShell.tsx
- apps/console/src/components/ui/sidebar-component.tsx
| { | ||
| "name": "console-signed-in", | ||
| "runtimeExecutable": "sh", | ||
| "runtimeArgs": [ | ||
| "-c", | ||
| "cd apps/console && STUB_DATA_API_PORT=40999 node e2e/stub-data-api.mjs & sleep 3; cd apps/console && AUTH_SECRET=console-local-not-for-production CONSOLE_DATA_API_URL=http://localhost:40999 CONSOLE_DATA_API_KEY=dev-key CONSOLE_HARNESS_URL=http://localhost:40999 CONSOLE_HARNESS_TOKEN=dev-key CONSOLE_HARNESS_TENANT=Travis-Gilbert CONSOLE_E2E_GITHUB_LOGIN=Travis-Gilbert CONSOLE_E2E_HARNESS_IDENTITY=github:e2e-owner CONSOLE_PRINCIPAL_TOKENS_JSON='{\"Travis-Gilbert\":\"dev-key\"}' CONSOLE_E2E_PROACTIVITY_FIXTURE=1 CONSOLE_E2E_FILING_FIXTURE=1 THEOREM_GRAPHQL_URL=http://localhost:40999/graphql THEOREM_API_KEY=dev-key pnpm exec next dev --webpack --port 3010" |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Make stub startup fail-fast and lifecycle-safe.
The background command ignores whether stub-data-api.mjs exits and uses sleep 3 as the readiness check. A slow startup can make next dev run before port 40999 is ready. A failed or stale process can leave the console connected to an unavailable or wrong API. Capture the background PID, poll the stub’s readiness signal, propagate startup failure, and stop the stub in an exit trap.
🤖 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 @.claude/launch.json around lines 18 - 23, Update the console-signed-in
runtime command to capture the stub-data-api.mjs background PID, poll port 40999
readiness instead of relying on sleep 3, and fail before starting next dev if
the stub exits or never becomes ready. Add an exit trap that terminates and
waits for the captured stub process so it cannot remain stale after the console
process exits.
| "runtimeExecutable": "sh", | ||
| "runtimeArgs": [ | ||
| "-c", | ||
| "cd apps/console && STUB_DATA_API_PORT=40999 node e2e/stub-data-api.mjs & sleep 3; cd apps/console && AUTH_SECRET=console-local-not-for-production CONSOLE_DATA_API_URL=http://localhost:40999 CONSOLE_DATA_API_KEY=dev-key CONSOLE_HARNESS_URL=http://localhost:40999 CONSOLE_HARNESS_TOKEN=dev-key CONSOLE_HARNESS_TENANT=Travis-Gilbert CONSOLE_E2E_GITHUB_LOGIN=Travis-Gilbert CONSOLE_E2E_HARNESS_IDENTITY=github:e2e-owner CONSOLE_PRINCIPAL_TOKENS_JSON='{\"Travis-Gilbert\":\"dev-key\"}' CONSOLE_E2E_PROACTIVITY_FIXTURE=1 CONSOLE_E2E_FILING_FIXTURE=1 THEOREM_GRAPHQL_URL=http://localhost:40999/graphql THEOREM_API_KEY=dev-key pnpm exec next dev --webpack --port 3010" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -C 8 'THEOREM_(ITEM|PROACTIVITY)_CHANGEFEED_URL|NEXT_PUBLIC_CONSOLE_CHAT_URL|CONSOLE_E2E_(PROACTIVITY|FILING)_FIXTURE' apps/consoleRepository: Travis-Gilbert/CommonPlace
Length of output: 25738
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- .claude/launch.json ---\n'
if [ -f .claude/launch.json ]; then
cat -n .claude/launch.json
else
fd -a 'launch\.json$' . | sed 's#^\./##'
fi
printf '\n--- Console host changefeed construction ---\n'
rg -n -C 5 'changefeedUrl|proactivityTenant|onChangefeedStatus|harness_changefeed|proactivity_changefeed|THEOREM_(ITEM|PROACTIVITY)_CHANGEFEED_URL|CONSOLE_E2E_FILING_FIXTURE|CONSOLE_E2E_PROACTIVITY_FIXTURE' apps/console/src apps/console/playwright.config.ts .claude/launch.json
printf '\n--- Server route snippets ---\n'
sed -n '1,80p' apps/console/src/app/api/proactivity/stream/route.ts
printf '\n'
sed -n '1,60p' apps/console/src/app/api/harness/memory/stream/route.tsRepository: Travis-Gilbert/CommonPlace
Length of output: 255
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- .claude/launch.json ---'
if [ -f .claude/launch.json ]; then
cat -n .claude/launch.json
else
fd -a 'launch\.json$' . | sed 's#^\./##'
fi
printf '%s\n' ''
printf '%s\n' '--- Console host changefeed construction ---'
rg -n -C 5 'changefeedUrl|proactivityTenant|onChangefeedStatus|harness_changefeed|proactivity_changefeed|THEOREM_(ITEM|PROACTIVITY)_CHANGEFEED_URL|CONSOLE_E2E_FILING_FIXTURE|CONSOLE_E2E_PROACTIVITY_FIXTURE' apps/console/src apps/console/playwright.config.ts .claude/launch.json || true
printf '%s\n' ''
printf '%s\n' '--- Server route snippets ---'
sed -n '1,80p' apps/console/src/app/api/proactivity/stream/route.ts
printf '%s\n' ''
sed -n '1,90p' apps/console/src/app/api/harness/memory/stream/route.tsRepository: Travis-Gilbert/CommonPlace
Length of output: 21558
Add the Chat and Proactivity feed environments to console-signed-in.
console-signed-in sets CONSOLE_E2E_PROACTIVITY_FIXTURE, but that only controls the server proactivity graph read. The chat composer still needs NEXT_PUBLIC_CONSOLE_CHAT_URL, and the live SSE relay still needs THEOREM_PROACTIVITY_CHANGEFEED_URL; without them, live feeds return 404. Set local stub values matching the E2E contract, or document why this profile intentionally keeps those surfaces unavailable.
🤖 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 @.claude/launch.json at line 23, Update the console-signed-in launch
environment to define NEXT_PUBLIC_CONSOLE_CHAT_URL and
THEOREM_PROACTIVITY_CHANGEFEED_URL using the local stub endpoints required by
the E2E contract, alongside CONSOLE_E2E_PROACTIVITY_FIXTURE. Ensure the
configured URLs target the running stub data API so chat and live proactivity
feeds do not return 404.
Source: Coding guidelines
| // Editor drops the Thread companion. The seed stopped emitting it, but a | ||
| // layout persisted before that keeps its own copy, so the panel survives | ||
| // the seed change until this removes it. The view instance goes too; | ||
| // leaving it orphans a view-instance object no surface can reach. | ||
| if (workspaceSurface && workspaceSurface.children.includes('workspace.region-thread')) { | ||
| workspaceSurface.children = workspaceSurface.children.filter( | ||
| (child) => child !== 'workspace.region-thread', | ||
| ); | ||
| workspaceSurface.properties.seed_revision = 8; | ||
| this.layout.delete('workspace.region-thread'); | ||
| this.layout.delete('workspace.region-thread.view'); | ||
| added = true; | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Apply the Thread migration to remote layouts.
This block updates only the local layout map. The remote adoption path in Lines 631-681 does not add workspace.region-thread or workspace.region-thread.view to retiredIds. It can replace the migrated local layout with a remote layout that still contains the retired Thread panel.
Apply the same ID removal before replaceLayout(...). Filter the CONTAINS_EDGE relations and pass the removed remote objects to retireRemoteLayoutObjects(). Add a regression test for remote layout adoption.
Suggested fix
const retiredIds = new Set<string>([
...retiredViewIds,
...(removeLegacyConsole ? LEGACY_CONSOLE_LAYOUT_IDS : []),
+ ...withoutSeedViews
+ .filter(({ id }) =>
+ id === 'workspace.region-thread' ||
+ id === 'workspace.region-thread.view',
+ )
+ .map(({ id }) => id),
]);🤖 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/console-host.ts` around lines 443 - 455, Extend the
remote layout adoption flow around replaceLayout and retiredIds to remove
workspace.region-thread and workspace.region-thread.view before replacing the
local layout. Filter corresponding CONTAINS_EDGE relations, add the removed
remote objects to retiredIds, and pass them through retireRemoteLayoutObjects();
add a regression test covering adoption of a remote layout containing these
retired Thread objects.
The rail floated with a margin on all four sides. Against a shell that now runs full bleed that read as a card someone had left on the surface rather than a panel belonging to the edge. It meets the window on its right and along both long sides now, and only its left corners are round, so the curve reads as the edge it came out of. Measured on the running app: zero gap right, top and bottom, radius 16px 0 0 16px. The nav rows were white because they still carried the vendor's neutrals: bg-card/55 at rest, bg-card/90 with dark:bg-white/10 active. Over the rail's dark canvas every row painted a pale filled pill and the nav read as a stack of white blocks. The raw white utility is banned in this app besides. They use register ink and surfaces now, in the row language the left stripe already speaks: at rest ink alone with no fill, hover and active earn bg-ij-raised. Icons follow the same three weights. The arbitrary rounded-[6px] and backdrop-blur-[1px] go with them; the blur was doing nothing once the translucent fill was gone. tsc clean against the one inherited baseline error. gate:register, gate:fence and gate:icons pass.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
…e rail Collapsed left a 64px column holding one chevron. The panel could not go narrower because the control that reopens it lived inside it, so closing it any further closed the way back. The toggle moves to the icon rail's brand mark, which is the one part of the sidebar always on screen, and the panel then collapses to zero. The mark carries aria-expanded and swaps its label between Collapse sidebar and Expand sidebar, so it reads as the disclosure it now is. The panel is inert while collapsed. Zero width clips its controls but leaves them focusable and announced, which measured as fifteen buttons a keyboard could reach and a screen reader would offer with none of them on screen. One attribute takes the subtree out of both. The published component kept the content mounted on purpose, for the Pins region, and inert preserves that intent rather than unmounting it. Verified in the browser both directions: collapsed measures width 0, inert true, zero focusable descendants; expanded restores the panel and the mark flips its label. gate:register and gate:fence pass, 33 tests, tsc clean against the one inherited baseline error.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dbe3594cc2
ℹ️ 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".
| }, [navItems]); | ||
|
|
||
| const bottomItems: NavItemData[] = [ | ||
| { id: '/account', title: 'Settings', icon: IconAccount, shortcut: '⌘,' }, |
There was a problem hiding this comment.
Point Settings at an existing route
When a user clicks the new inspector Settings row, handleSelect passes this ID to softNavigate, so the console navigates to /account; the app route tree contains /settings and workspace-scoped settings but no /account page or rewrite, making this control land on a 404 every time. Use the existing settings route or activate the account surface without routing to a nonexistent path.
Useful? React with 👍 / 👎.
| authRequest: key.authToken | ||
| ? new Request('http://localhost', { | ||
| headers: { Authorization: `Bearer ${key.authToken}` }, | ||
| }) | ||
| : undefined, | ||
| }); |
There was a problem hiding this comment.
Forward the selected credential to local ACP processes
When THEOREM_ACP_TRANSPORT=local or THEOREM_ACP_BIN selects the supported local transport, the newly resolved principal credential is ignored: key.authToken is converted to an authRequest only in the hosted branch, while AcpClient.spawn receives only the backend and binding environment and therefore falls back to a global credential or none. In multi-tenant local or desktop runs, proactivity compilation can consequently authenticate as the wrong tenant or fail even though credential resolution succeeded; forward the selected credential through the local client's supported authentication channel as well.
Useful? React with 👍 / 👎.
| @@ -182,7 +182,7 @@ export function BlockShell({ | |||
| data-descriptor={descriptor.id} | |||
| data-paint-region="island-shell" | |||
| aria-label={headerTitle} | |||
There was a problem hiding this comment.
Restore radius clipping on island containers
When a block body paints an opaque surface, such as EmptyRegion with bg-ij-editor, removing the radius here means overflow-hidden clips only to a rectangle. The MaterialLayer can draw a rounded background but cannot clip descendant DOM, so those bodies cover the shader's rounded corners with square ones; the same removal on EditorTabs affects full-pane islands. Keep the shell fill transparent if desired, but retain the matching border radius on the clipping container.
Useful? React with 👍 / 👎.
Three conflicts. Composer.tsx and Transcript.tsx were deleted on main and modified here. The only edits were the reconnect copy, so the deletion wins; the user-reachable connect affordances this branch removed live in EmptyRegion, degradation.ts and ViewStates, and those survived. workspace/[workspaceSlug]/chat/page.test.tsx and page.tsx both went to main's version. Auto-merge had blended this branch's redirectForFailedPrincipal with main's inline redirect and imported only one of them, so the merged file called a name it never imported. Main's version carries the newer GL6 decision to collapse the workspace chat URL onto /chat. The helper stays: app/page.tsx and app/chat/page.tsx still use it. Merged tree: 41 tests pass, gate:fence passes, tsc reports one error and it is main's, `@rerun-io/web-viewer` unresolved because that dependency landed in #178 and is not installed in this worktree. gate:register also fails on main alone, three arbitrary-value classes in PrototypeStageView.tsx from the same PR. Neither is this branch's and neither is fixed here.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
apps/console/src/components/ui/dashboard-sidebar.tsx (3)
518-537: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftReserve a safe area for canvas controls.
RailModelCanvasis mounted withabsolute inset-0behind a transparent, pointer-pass-through sidebar. The current layout allows the Add Note and Add Browser controls to overlap the rail action cluster. Constrain the canvas control cluster or add an explicit inset so both control groups remain reachable.🤖 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/ui/dashboard-sidebar.tsx` around lines 518 - 537, Update the jsonCanvas layout around RailModelCanvas and SidebarNav so the canvas action cluster has an explicit safe-area inset that prevents overlap with the sidebar’s Add Note and Add Browser controls. Preserve pointer pass-through behavior and ensure both control groups remain reachable.
251-348: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftReuse the shared two-level sidebar implementation.
This file defines a second hand-rolled navigation tree with its own expansion state, active styling, shortcuts, and nested layout.
apps/console/src/components/shell/Sidebar.tsxalready importsTwoLevelSidebarShellandTwoLevelSidebarItemat Lines [34-37]. Move this navigation onto the shared shell instead of maintaining two sidebar implementations.As per coding guidelines, do not create a second hand-rolled sidebar implementation.
🤖 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/ui/dashboard-sidebar.tsx` around lines 251 - 348, Replace the hand-rolled NavItem tree in dashboard-sidebar.tsx with the shared TwoLevelSidebarShell and TwoLevelSidebarItem components already used by Sidebar.tsx. Adapt the existing navigation data, active selection, nesting, and item actions to the shared API, removing NavItem’s local expansion state and custom nested layout while preserving current navigation behavior.Source: Coding guidelines
274-291: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winUse a keyboard-operable control for each navigation row.
NavItemattachesonClickto a<div>at Line [276]. The element has norole,tabIndex, or keyboard handler. Keyboard users cannot activate leaf items or expand parent items. Render a<button type="button">and exposearia-expandedfor parent items andaria-currentfor the active item.🤖 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/ui/dashboard-sidebar.tsx` around lines 274 - 291, Update the navigation row in NavItem from a clickable div to a button type="button" so it is keyboard-operable. Preserve the existing styling, click behavior, and indentation, and add aria-expanded for parent items plus aria-current for the active item.apps/console/src/components/shell/Sidebar.tsx (1)
657-685: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winKeep Pin and Remove reachable from keyboard focus.
The overlay is only enabled on
group-hover, so keyboard users cannot discoverPin/UnpinorRemove. Mirror the:focus-withinstate or remove the hidden buttons from the tab order if they stay mounted while collapsed.🤖 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/Sidebar.tsx` around lines 657 - 685, Update the overlay containing the Pin/Unpin and Remove buttons in the landmark row rendering to become visible and interactive on keyboard focus, mirroring the existing group-hover behavior with a focus-within state. Ensure both buttons remain reachable and discoverable when navigating via keyboard without changing the hover behavior.
🤖 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/ui/dashboard-sidebar.tsx`:
- Line 283: Update the sidebar row element’s className to replace the arbitrary
py-[7px] padding with the existing sidebar row utility or a registered Int UI
spacing variable, while preserving the other layout and interaction classes.
- Line 283: Remove the unregistered transition classes from the sidebar row and
expansion path around the dashboard sidebar item, including transition-colors,
transition-transform, and transition-[grid-template-rows,opacity]. Replace
required motion with the registered implementation using only transform and
opacity, referencing duration and easing tokens from motion-tokens.ts; ensure
the resulting animations are inventory-listed.
---
Outside diff comments:
In `@apps/console/src/components/shell/Sidebar.tsx`:
- Around line 657-685: Update the overlay containing the Pin/Unpin and Remove
buttons in the landmark row rendering to become visible and interactive on
keyboard focus, mirroring the existing group-hover behavior with a focus-within
state. Ensure both buttons remain reachable and discoverable when navigating via
keyboard without changing the hover behavior.
In `@apps/console/src/components/ui/dashboard-sidebar.tsx`:
- Around line 518-537: Update the jsonCanvas layout around RailModelCanvas and
SidebarNav so the canvas action cluster has an explicit safe-area inset that
prevents overlap with the sidebar’s Add Note and Add Browser controls. Preserve
pointer pass-through behavior and ensure both control groups remain reachable.
- Around line 251-348: Replace the hand-rolled NavItem tree in
dashboard-sidebar.tsx with the shared TwoLevelSidebarShell and
TwoLevelSidebarItem components already used by Sidebar.tsx. Adapt the existing
navigation data, active selection, nesting, and item actions to the shared API,
removing NavItem’s local expansion state and custom nested layout while
preserving current navigation behavior.
- Around line 274-291: Update the navigation row in NavItem from a clickable div
to a button type="button" so it is keyboard-operable. Preserve the existing
styling, click behavior, and indentation, and add aria-expanded for parent items
plus aria-current for the active item.
🪄 Autofix
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: 5fd0ff62-6992-48df-a13e-36c84c5df29f
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (10)
apps/console/package.jsonapps/console/src/app/chat/page.test.tsxapps/console/src/app/chat/page.tsxapps/console/src/components/blocks/BlockShell.tsxapps/console/src/components/shell/InspectorRail.tsxapps/console/src/components/shell/IntuiShell.tsxapps/console/src/components/shell/Sidebar.tsxapps/console/src/components/ui/dashboard-sidebar.tsxapps/console/src/components/ui/sidebar-component.tsxapps/console/src/views/registry.tsx
🚧 Files skipped from review as they are similar to previous changes (8)
- apps/console/package.json
- apps/console/src/app/chat/page.tsx
- apps/console/src/components/ui/sidebar-component.tsx
- apps/console/src/views/registry.tsx
- apps/console/src/app/chat/page.test.tsx
- apps/console/src/components/blocks/BlockShell.tsx
- apps/console/src/components/shell/InspectorRail.tsx
- apps/console/src/components/shell/IntuiShell.tsx
| // the whole nav read as white blocks. The raw white utility is banned | ||
| // here besides. This is the same row language the left stripe already | ||
| // uses: rest is ink alone, hover and active earn the raised surface. | ||
| className={`group pointer-events-auto flex items-center justify-between px-2.5 py-[7px] rounded-ij-arc cursor-pointer transition-colors duration-(--ij-motion) ease-(--ij-ease) select-none |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Replace the arbitrary padding with a registered Int UI metric.
py-[7px] is an arbitrary-value Tailwind class. Use the existing sidebar row utility or an Int UI register variable instead.
As per coding guidelines, Console code must not use arbitrary-value Tailwind classes.
🤖 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/ui/dashboard-sidebar.tsx` at line 283, Update the
sidebar row element’s className to replace the arbitrary py-[7px] padding with
the existing sidebar row utility or a registered Int UI spacing variable, while
preserving the other layout and interaction classes.
Source: Coding guidelines
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Remove off-list navigation animations.
The row uses transition-colors, and the expansion path uses transition-transform plus transition-[grid-template-rows,opacity] with hardcoded timings. Console motion must use only transform and opacity, with durations and easings defined in src/motion/motion-tokens.ts. Remove these transitions or replace them with a registered motion implementation.
As per coding guidelines, Console animations must be inventory-listed and limited to transform and opacity.
Also applies to: 315-327
🤖 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/ui/dashboard-sidebar.tsx` at line 283, Remove the
unregistered transition classes from the sidebar row and expansion path around
the dashboard sidebar item, including transition-colors, transition-transform,
and transition-[grid-template-rows,opacity]. Replace required motion with the
registered implementation using only transform and opacity, referencing duration
and easing tokens from motion-tokens.ts; ensure the resulting animations are
inventory-listed.
Source: Coding guidelines
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2231bea9c
ℹ️ 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".
| // ponytail: Editor drops the Thread companion. It was the only surface | ||
| // seeding it open, and the same exclusion the Files surface already uses | ||
| // covers it. seed_revision bumped so persisted layouts re-seed. | ||
| ...companionSeeds('workspace', false, ['thread']), |
There was a problem hiding this comment.
Restore the Workspace thread companion
With the Workspace seed now excluding thread, opening console-workspace no longer creates workspace.region-thread or its compact chat view. The still-enabled Playwright suite continues to assert that the Workspace surface shows [data-composer-density="compact"], and the signatures suite toggles all three companions including thread, so npm run test:e2e will fail deterministically for this commit unless the thread companion is kept or those Workspace contracts are updated together.
AGENTS.md reference: apps/console/AGENTS.md:L189-L197
Useful? React with 👍 / 👎.
| <div className="relative pointer-events-auto"> | ||
| <div | ||
| onClick={() => setIsOpen(!isOpen)} | ||
| className="flex items-center justify-between px-2 py-2 mb-4 rounded-lg bg-card/85 hover:bg-black/5 dark:hover:bg-white/5 cursor-pointer transition-colors select-none group backdrop-blur-[1px]" |
There was a problem hiding this comment.
Retokenize the dashboard rail chrome
This production Workspace switcher ships raw stock palette and arbitrary-value Tailwind classes (hover:bg-black/5, dark:hover:bg-white/5, backdrop-blur-[1px]) directly in the console shell. The console fence requires those visual states to resolve through the register instead of raw palette or arbitrary utilities, so the new rail chrome bypasses the shared theme and audit contract; replace these states with registered ij/t tokens.
AGENTS.md reference: apps/console/AGENTS.md:L83-L85
Useful? React with 👍 / 👎.
Two CI failures, both mine. eslint: RailModelCanvas reset to empty models inside the effect body, a synchronous setState that cascades a second render and that the react-hooks rule rejects. The fetched payload now carries the topic it was fetched for and empty is derived, so no write is needed to clear it. That also fixes a real bug: a response landing after the topic changed used to paint the previous topic's model, because nothing compared what arrived against what had been asked for. GitGuardian: the console-signed-in launch config assigned AUTH_SECRET, CONSOLE_HARNESS_TOKEN and THEOREM_API_KEY. Local dummies every one, but a committed file of SECRET= and TOKEN= lines teaches the eye to skip them, and this was scaffolding for my own browser verification rather than product code. Reverted to main's version. Left alone: PrototypeStageView.tsx fails eslint twice and gate:register three times. That file arrived with #178, this branch does not touch it, and it fails the same way on main.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
…enty-ui-spec-d0ae2a
Not this branch's file, but they fail eslint on the merge base and so they block anything that merges main. Behaviour is preserved. pathToExprRef was assigned during render. React may render without committing, and the selection handler would then read a mapping for a tree that never mounted. Moved into an effect keyed on the value. The missing-configuration branch set error and status from inside the effect body. It is a property of the props, so it is derived now and the render reads the derived values. The remaining pair moved into the import callback: the label appears when the viewer module resolves, which is when loading actually starts. Left alone: the three arbitrary-value classes gate:register flags in the same file. Swapping them needs three real spacing tokens in the register and inventing names produces classes that silently resolve to nothing, which is worse than the lint failure. That belongs with whoever owns prototype.stage. eslint clean, 586 tests, tsc reports only the uninstalled @rerun-io/web-viewer in this worktree.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
gate:register flagged four raw values in this view, and the constitution says a token gap routes to the token specification rather than to a component edit. So the metrics are declared once and the classes read them: --ij-stage-min-h, --ij-stage-body-min-h and --ij-measure-w in the int-ui register, aliased to spacing in the bridge so min-h-ij-stage, min-h-ij-stage-body and max-w-ij-measure resolve. The fourth was a raw 10px on a muted mono label, which is what text-ij-island-meta already names. The first attempt at this invented min-h-ij-stage without declaring anything, which produces a class that resolves to nothing while the lint passes, because the syntax is legal either way. Checked here: each token is defined, aliased, and used. twenty-register overrides only a subset of these metrics and layers over int-ui, so both modes resolve. gate:register clean, eslint clean, gate:fence, gate:twenty and gate:icons pass.
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
The token manifest gate wants every register-defined token listed, and --ij-stage-min-h, --ij-stage-body-min-h and --ij-measure-w were new. Regenerated with tokens:manifest. The gate still reports 162 violations. All of them predate this branch: checked out main's src/styles/ alone and counted the same 162, mostly twenty-register.css minting --ij-blue-* and --ij-error outside what the gate treats as a register file. Not this branch's to sweep.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
Review pass, and what remains redFixed on this branch:
Still red, all pre-existing:
Local: eslint clean, |
Rebuilds the console right rail against the OpenHuman reference, and flattens the shell around it.
Rail
JsonCanvasLayer, a second canvas language, so a node in the rail and a node on the Data model surface did not look or behave alike. It now mounts the sameForkDiagramCanvasthe surface mounts, sharingMartNode/RelEdge/ the substrate edge language. Pin and unpin post to the routes the surface posts to.MenuItemNavigaterows,Tagtool chips,RoundedIconButton+LightIconButton,Pill. Steps are real (useThreadStore().plan, the liveAgentPlanSteplist the chat rail already renders), not a fixture. Empty plan renders nothing, which is the test that matters: the rail is always on screen.Panelkeeps its width so drag/collapse/persistence stayreact-resizable-panels', while the editor group is absolute to the outer group.EmptyRegion'snot-connecteddefault thatViewStatesrenders for any unavailable view. All sayRetry; the test asserts the absence.Shell
console-hostmigration for layouts persisted before the change.inert, and the icon rail's brand mark carries the toggle. Previously it could not collapse further because the reopen control lived inside it; zero width also left 15 buttons focusable and announced.bg-card/55/dark:bg-white/10(a banned raw white utility) onto register ink andbg-ij-raised.Validation
tscclean against one inherited baseline error (document-store.test.ts:148, byte-identical to main).gate:register,gate:fence,gate:twenty,gate:iconspass.Known, not fixed
The canvas layer's "Add Note" / "Add Browser" controls are absolutely positioned at the rail's bottom-right and overlap the action cluster. Two things want the same corner; which one moves is a composition decision.
Summary by CodeRabbit
New Features
Bug Fixes