feat(console): chat surface + Paper sidebar on block contract - #99
Conversation
|
ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR. |
|
Warning Review limit reached
Next review available in: 44 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. 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 ignored due to path filters (1)
📒 Files selected for processing (43)
📝 WalkthroughWalkthroughThe PR adds the console chat surface and material-register implementation, including ShaderSurface rendering, thread excerpts, empty-state causes, tier and hue tokens, contrast and radius gates, shell synchronization, deterministic E2E fixtures, and canonical plan shape identifiers. ChangesConsole chat and material system
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7871d7294c
ℹ️ 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".
| <ThreadExcerpt | ||
| kind="object" | ||
| excerptId={excerptId} | ||
| speaker={`object · ${kind}`} | ||
| summary={title} | ||
| defaultCollapsed |
There was a problem hiding this comment.
Load object excerpts when users expand them
Every object excerpt is initially collapsed, so ThreadExcerpt does not mount this child until after its toggle is used. The only paths that set expandedOnce are the unmounted child's ref and focus handler, while the header toggle never updates it; therefore the query effect never runs and expanding any referenced object leaves it permanently at “Loading through the object seam…”.
AGENTS.md reference: apps/console/AGENTS.md:L109-L109
Useful? React with 👍 / 👎.
| const localViewOverrides = new Map( | ||
| [...this.layout.values()] | ||
| .filter((node) => node.type === 'view-instance') | ||
| .map((node) => [node.id, { | ||
| title: node.properties.title, |
There was a problem hiding this comment.
Preserve only edits made while the remote layout is loading
This snapshots title and query from every local view instance after the fetch, including the ordinary seed layout or an old browser cache, and later applies every difference over the fetched remote layout. On a new device or after clearing local storage, a server-persisted reader target/title is consequently replaced by the seed values on each startup rather than being adopted; track mutations made during the request instead of treating all pre-adoption values as overrides.
AGENTS.md reference: apps/console/AGENTS.md:L132-L137
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
This PR advances the Console’s one-block contract tip by (1) reconciling the /chat surface into a multibuffer excerpt model (composer + thread excerpts + object pull-ins), and (2) landing the Material Register system (tiers, keylines, radii, kind hues, shader seam, empty-state primitives) with new/extended gates and updated fixtures.
Changes:
- Introduces Material Register primitives and enforcement: elevation tiers, radius scale, contrast gate extensions, kind hue ramp,
ShaderSurface(pinned Paper shaders), andEmptyRegionwith named causes. - Rebuilds the chat surface to the excerpt model:
ThreadExcerpt/ObjectExcerpt, jump strip, tokenized chip/composer metrics, and replaces the composer sheen canvas with a ShaderSurface “lit edge”. - Hardens layout/view wiring and tests: seed-layout adopt preservation, doc navigation stability, and refreshed Playwright expectations/fixture reset utilities.
Reviewed changes
Copilot reviewed 57 out of 81 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds pinned shader deps and dockview resolution updates. |
| packages/theorem-acp/src/plan-program.ts | Canonicalizes plan-task ShapeId and adds a ShapeId::parse-compatible parser. |
| docs/plans/material-register/SPEC-MATERIAL-REGISTER-1.0.md | Introduces the Material Register spec and measurable acceptance criteria. |
| docs/plans/material-register/report.md | Status report for which Material Register deliverables shipped vs deferred. |
| docs/plans/material-register/implementation-plan.md | Implementation checklist and verify-first findings for the material work. |
| docs/plans/console-chat-surface/README.md | Links chat surface plan to handoff/spec inputs. |
| docs/plans/console-chat-surface/implementation-plan.md | Detailed executable plan for chat composer + multibuffer thread implementation. |
| docs/plans/console-chat-surface/FOLLOWUP-FORME-DISCHARGE-TEXTURE.md | Documents the deferral of non-Deterministic receipt textures until backend support. |
| apps/console/src/views/ViewStates.tsx | Switches empty/unavailable rendering to EmptyRegion with named causes/actions. |
| apps/console/src/views/ViewStates.test.tsx | Updates tests for new empty/unavailable semantics and action labels. |
| apps/console/src/views/ThreadView.tsx | Replaces bubbles with excerpt primitives, adds tool/object excerpts, and jump strip. |
| apps/console/src/views/thread/ThreadExcerpt.tsx | New collapsible, sticky-header excerpt container component. |
| apps/console/src/views/thread/ThreadExcerpt.test.tsx | Adds unit tests for excerpt collapse/expand behavior. |
| apps/console/src/views/thread/ObjectExcerpt.tsx | Adds object pull-in excerpt via BlockHost seam with “Open” action. |
| apps/console/src/views/GalleyDocView.tsx | Reworks todo decoration to survive re-rendering via observer + event delegation. |
| apps/console/src/views/DocListView.tsx | Prefers docs editor region to avoid active-surface race during navigation. |
| apps/console/src/views/CodeFileView.tsx | Uses emptyCause="not-loaded" for unloaded files. |
| apps/console/src/views/CardView.tsx | Uses emptyCause="not-loaded" for missing full-card object. |
| apps/console/src/views/canvas/CanvasView.tsx | Replaces useSyncExternalStore store with effect subscription and improves empty state. |
| apps/console/src/views/canvas/CanvasPaperGround.tsx | Re-expresses canvas ground through ShaderSurface (removes shaders-react DotGrid). |
| apps/console/src/styles/token-manifest.json | Extends/updates manifest for new material/chat/sidebar tokens and tier mapping notes. |
| apps/console/src/styles/register-bridge.css | Adds tier + radius + kind hue + sidebar + chat/composer/excerpt tokens and elevation styling. |
| apps/console/src/styles/int-ui-register.css | Introduces tier tokens, maps structural surfaces onto tiers, adds radius scale + keyline tokens. |
| apps/console/src/styles/int-ui-register-light.css | Light-theme tier + keyline token mapping updates. |
| apps/console/src/styles/app.css | Adds responsive visibility rule for the thread jump strip. |
| apps/console/src/motion/motion-tokens.ts | Updates motion inventory and declared paint surfaces for ShaderSurface. |
| apps/console/src/lib/plan-program-shape.test.ts | Adds tests ensuring emitted ShapeIds are parseable and canonical. |
| apps/console/src/lib/material/materials.ts | Introduces material vocabulary/map and reachability rules. |
| apps/console/src/lib/material/kind-hues.ts | Adds kind hue var accessors + hue ramp constants. |
| apps/console/src/lib/material/kind-hues.test.ts | Verifies register contains every kind hue token and matches the fixed L/C ramp. |
| apps/console/src/lib/goal-stack-contract.test.ts | Ensures graph ports emit the canonical plan-task ShapeId. |
| apps/console/src/lib/console-host.ts | Preserves local view-instance overrides and local-only nodes across seed-layout adoption. |
| apps/console/src/lib/console-host.test.ts | Adds test for preserving in-flight doc navigation during seed adopt. |
| apps/console/src/components/shell/ViewInstanceHost.tsx | Prevents “empty” state for marker panes and avoids dependency on unstable instance identity. |
| apps/console/src/components/shell/Sidebar.tsx | Updates rail anatomy, shortcut glyphs, and activation/routing semantics. |
| apps/console/src/components/shell/MainToolbar.tsx | Clarifies surface switching behavior (activate without routing). |
| apps/console/src/components/shell/IntuiShell.tsx | Keeps data-shell mounted while resolving layout to stabilize activation/e2e oracles. |
| apps/console/src/components/material/ShaderSurface.tsx | Adds repo-owned Paper shader mount with context budget, reduced-motion, and token-derived colors. |
| apps/console/src/components/material/EmptyRegion.tsx | Adds a canonical empty-state primitive with named causes and optional resolving action. |
| apps/console/src/components/composer/ComposerSheenCanvas.tsx | Removes legacy 2D sheen canvas implementation. |
| apps/console/src/components/composer/Composer.tsx | Rebuilds composer chrome, metrics, and status handling; adds ShaderSurface lit edge and interrupt state. |
| apps/console/src/components/blocks/kind-glyph.tsx | Applies kind hue to glyphs and introduces edge-marker styling. |
| apps/console/src/components/blocks/BlockCanvas.tsx | Documents dockview follow-up for ground geometry while retaining dnd-kit for nested kanban. |
| apps/console/scripts/check-radius-lint.mjs | Adds radius scale lint gate to block raw px radius usage outside allowed folders. |
| apps/console/scripts/check-contrast.mjs | Extends contrast gate with rail pairs, selection two-of-four rule, and decorative keyline registry. |
| apps/console/package.json | Pins shaders(-react) versions, adds dockview, and adds gate:radius into gates. |
| apps/console/e2e/stub-data-api.mjs | Makes mention-candidate fixtures resettable and adds reset-domain endpoint. |
| apps/console/e2e/signatures.spec.ts | Updates composer assertions for ShaderSurface lit edge and revised screenshot flow. |
| apps/console/e2e/search-field.spec.ts | Adds stub reset and waits on data-layout-ready instead of fixed delays. |
| apps/console/e2e/filing-index.spec.ts | Waits for layout readiness before navigating surfaces. |
| apps/console/e2e/console-ia.spec.ts | Updates composer assertions for lit edge and new metric constraints. |
| apps/console/e2e/cards.spec.ts | Adds stub reset helpers, injected-surface activation path, and more robust assertions/screenshot tolerances. |
| apps/console/e2e/appearance.spec.ts | Adds stub reset + readiness waits and relaxes divider expectation under new one-block paint behavior. |
| apps/console/e2e/account.spec.ts | Increases timeout robustness for GitHub login disabled text assertion. |
| apps/console/docs/plans/console-block-system/FOLLOWUP-DOCKVIEW-GROUND.md | Records dockview adoption decision and constraints for the ground canvas follow-up. |
| apps/console/CLAUDE.md | Updates console component map to replace sheen canvas with ShaderSurface lit edge. |
| apps/console/AGENTS.md | Updates console component map to replace sheen canvas with ShaderSurface lit edge. |
| .harness/checklists/console-chat-surface--plan-local.json | Adds an executable checklist projection for chat surface work when harness plan minting is unavailable. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const PAIRS = [ | ||
| { name: 'ink on chrome', foreground: '--ij-ink', background: '--ij-chrome', target: 4.5 }, | ||
| { name: 'info on chrome', foreground: '--ij-ink-info', background: '--ij-chrome', target: 3 }, | ||
| { name: 'gold on chrome', foreground: '--ij-gold', background: '--ij-chrome', target: 4.5 }, | ||
| { name: 'accent on chrome', foreground: '--ij-accent', background: '--ij-chrome', target: 3 }, | ||
| { name: 'ink on editor', foreground: '--ij-ink', background: '--ij-editor', target: 4.5 }, | ||
| { name: 'bright ink on accent', foreground: '--ij-ink-bright', background: '--ij-accent', target: 3 }, | ||
| { name: 'keyline on chrome', foreground: '--ij-keyline', background: '--ij-chrome', target: 1.2 }, | ||
| /* HANDOFF-CONSOLE-BLOCK-SYSTEM choice 8: island surfaces vs frame floor. */ | ||
| { name: 'chrome island on frame', foreground: '--ij-chrome', background: '--ij-frame', target: 1.22 }, | ||
| { name: 'editor island on frame', foreground: '--ij-editor', background: '--ij-frame', target: 1.22 }, | ||
| /* Editor is sunken (material register D1): floor is the sunken-vs-ground step, not island-on-frame. */ | ||
| { name: 'editor sunken on frame', foreground: '--ij-editor', background: '--ij-frame', target: 1.08 }, |
| useEffect(() => { | ||
| const read = () => { | ||
| const roots = [...document.querySelectorAll<HTMLElement>('[data-thread-excerpt]')]; | ||
| setHeaders( | ||
| roots | ||
| .filter((node) => node.id) | ||
| .map((node) => ({ | ||
| id: node.id, | ||
| label: node.querySelector('[data-excerpt-speaker]')?.textContent?.trim() || node.dataset.threadExcerpt || 'excerpt', | ||
| })), | ||
| ); | ||
| }; | ||
| read(); | ||
| const observer = new MutationObserver(read); | ||
| observer.observe(document.body, { childList: true, subtree: true }); | ||
| return () => observer.disconnect(); | ||
| }, []); |
| if (LIVE_MOUNTS.size >= SHADER_CONTEXT_BUDGET) { | ||
| setFallback(true); | ||
| return; | ||
| } |
|
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: 12073362b9
ℹ️ 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 [interruptedFlag, setInterrupted] = useState(false); | ||
| // While a run is live, interrupt state is cleared without an effect. | ||
| const interrupted = isRunning ? false : interruptedFlag; |
There was a problem hiding this comment.
Reset interrupted state for each new run
After a user presses Stop, interruptedFlag is never cleared. A subsequent request temporarily renders as composing only while isRunning is true, then returns to the interrupted Presence mark when that request completes, so the sole agent activity indicator falsely reports the prior cancellation for the rest of the mounted composer session. Clear this flag when a new submission starts or when the next run begins.
AGENTS.md reference: apps/console/AGENTS.md:L104-L104
Useful? React with 👍 / 👎.
| u_colorStroke: nextFill, | ||
| }); | ||
| }); | ||
| observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme', 'class'] }); |
There was a problem hiding this comment.
Observe every appearance mutation for shader colors
Switching between IntelliJ and GitHub while staying in the same light or dark mode changes data-theme-preset, and the Navy preset also updates inline custom properties, but neither mutation is observed here. The mounted composer edge and canvas ground therefore retain the previous theme's WebGL uniforms until they are remounted, producing mismatched material after an in-app appearance change. Observe data-theme-preset and style changes, or subscribe directly to the appearance store.
AGENTS.md reference: apps/console/AGENTS.md:L36-L43
Useful? React with 👍 / 👎.
| this.replaceLayout(remote.objects); | ||
| for (const node of localOnly) { | ||
| this.layout.set(node.id, node); | ||
| } |
There was a problem hiding this comment.
Reattach local-only nodes to their restored parents
When a view instance is created and moved into an existing editor while the layout query is in flight, that editor exists in remote.objects but the new child does not. This restores the child object only; replaceLayout has already replaced the editor's children with the stale remote relation, so the new tab is detached and disappears from the UI despite being retained in the cache. Merge local parent-child relations for local-only nodes, or replay the pending move actions after adoption.
AGENTS.md reference: apps/console/AGENTS.md:L134-L136
Useful? React with 👍 / 👎.
| useEffect(() => { | ||
| const read = () => { | ||
| const roots = [...document.querySelectorAll<HTMLElement>('[data-thread-excerpt]')]; | ||
| setHeaders( | ||
| roots | ||
| .filter((node) => node.id) | ||
| .map((node) => ({ | ||
| id: node.id, | ||
| label: node.querySelector('[data-excerpt-speaker]')?.textContent?.trim() || node.dataset.threadExcerpt || 'excerpt', | ||
| })), | ||
| ); | ||
| }; | ||
| read(); | ||
| const observer = new MutationObserver(read); | ||
| observer.observe(document.body, { childList: true, subtree: true }); |
There was a problem hiding this comment.
Scope jump-strip discovery to its own thread surface
This collects excerpts from the entire document rather than this ThreadView. If the Chat surface's Thread companion is opened, both the full and compact views render the shared messages, so the strip receives duplicate entries and duplicate DOM ids; its duplicate React keys and fragment links then point at the first matching excerpt instead of the intended one. Query within a ref for this surface and give each view's excerpts distinct ids.
Useful? React with 👍 / 👎.
…ract Land chat composer ShaderSurface, multibuffer thread excerpts, and Paper sidebar anatomy on the one-block tip. Pin dockview for the ground canvas follow-up and keep nested kanban on dnd-kit. Co-authored-by: Cursor <cursoragent@cursor.com>
Derive interrupt state from isRunning, defer ShaderSurface fallback updates, and restore the canvas external-store subscription from the block-contract tip. Co-authored-by: Cursor <cursoragent@cursor.com>
1207336 to
699ebcd
Compare
|
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: 12
🧹 Nitpick comments (3)
apps/console/src/views/GalleyDocView.tsx (1)
15-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAlias name collides with the library's real
markdownLanguageexport.
markdownis aliased tomarkdownLanguagehere, but@codemirror/lang-markdownalso exports an actualmarkdownLanguage(a plainLanguage, not callable). Calling it asmarkdownLanguage()at Line 62 is correct today because it's really the aliasedmarkdown()factory, but the name will mislead anyone who checks the library docs and could tempt a future edit to drop the()call.♻️ Suggested rename
-import { markdown as markdownLanguage } from '`@codemirror/lang-markdown`'; +import { markdown as markdownExtension } from '`@codemirror/lang-markdown`';- markdownLanguage(), + markdownExtension(),Also applies to: 62-62
🤖 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/views/GalleyDocView.tsx` at line 15, Rename the aliased import from `@codemirror/lang-markdown` to a name that reflects the callable markdown factory, and update its invocation at the corresponding editor setup call site. Preserve the existing factory call behavior and avoid using the library’s exported markdownLanguage name for this alias.apps/console/e2e/stub-data-api.mjs (1)
175-182: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueShallow-cloned
relationscould leak mutations back into the seed.
cloneMentionCandidatesspreadsentry.relations, which only copies the top-level keys; any array values inside are still shared withMENTION_CANDIDATES_SEED. No current handler mutates a relations array in place (delete/update reassign or only touchproperties), so this isn't an active bug, but it's a trap for a future in-place mutation (e.g..push()) silently corrupting the reset seed across test runs.♻️ Suggested deep clone
-function cloneMentionCandidates() { - return MENTION_CANDIDATES_SEED.map((entry) => ({ - ...entry, - properties: { ...entry.properties }, - relations: { ...entry.relations }, - })); -} +function cloneMentionCandidates() { + return MENTION_CANDIDATES_SEED.map((entry) => structuredClone(entry)); +}🤖 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/stub-data-api.mjs` around lines 175 - 182, Update cloneMentionCandidates to deep-clone nested values within entry.relations, including array values, so cloned candidates never share mutable relation data with MENTION_CANDIDATES_SEED. Preserve the existing cloning of entry and properties and keep the function’s returned candidate shape unchanged.apps/console/src/components/composer/Composer.tsx (1)
132-142: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winReorder
markStateto drop the reset effect (and the eslint error).Because
interruptedis checked beforeisRunning, starting a new run whileinterruptedis stilltruerenders'interrupted'for one frame until the effect flips it, a brief wrong glyph. ESLint also flags the synchronoussetStatein this effect (react-hooks/set-state-in-effect). PrioritizingisRunningin the derivation and clearinginterruptedon submit removes the effect and the flash.Proposed change
- useEffect(() => { - if (isRunning) setInterrupted(false); - }, [isRunning]); - const mention = useObjectMentionAdapter(mentions, tenant); - const markState: MarkState = interrupted - ? 'interrupted' - : isRunning - ? 'composing' - : 'idle'; + const markState: MarkState = isRunning + ? 'composing' + : interrupted + ? 'interrupted' + : 'idle';Then clear on submit (Line 256):
- onSubmit={() => setCharacterCount(0)} + onSubmit={() => { setCharacterCount(0); setInterrupted(false); }}🤖 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/composer/Composer.tsx` around lines 132 - 142, Remove the useEffect that calls setInterrupted when isRunning changes, and reorder the markState derivation so isRunning takes precedence over interrupted, producing 'composing' during active runs. In the submit flow around the existing submit handler, clear interrupted explicitly when a new run is submitted.Source: Linters/SAST tools
🤖 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 @.harness/checklists/console-chat-surface--plan-local.json:
- Around line 10-16: Update the status_lead_not_done checklist to remove entries
whose corresponding work is marked done, including CH0, CH1a, CH1b, CH2, and
CH6, or explicitly label the list as historical baseline status if those entries
must remain.
In `@apps/console/package.json`:
- Around line 73-75: Update the dockview dependency entry in package.json from a
caret range to an exact pinned version, preserving the current 4.10.0 version so
it matches the repository’s pinned dependency style and ensures reproducible
builds.
In `@apps/console/scripts/check-contrast.mjs`:
- Around line 227-230: Replace the tautological DECORATIVE_KEYLINES membership
check with a lookup against the register declarations, resolving
--ij-keyline-decorative through the same declaration-based mechanism used by the
PAIRS and RAIL_PAIRS loops. Keep the existing error message and exit behavior
when the token is absent, and avoid using the locally defined
DECORATIVE_KEYLINES set for this validation.
In `@apps/console/scripts/check-radius-lint.mjs`:
- Around line 29-30: Update RAW_RADIUS in check-radius-lint to match React
camelCase borderRadius declarations and Tailwind arbitrary rounded-[Npx]
classes, while preserving detection of existing CSS and Tailwind forms. Ensure
SCALE_TOKEN exemptions remain unchanged.
In `@apps/console/src/components/shell/Sidebar.tsx`:
- Around line 557-578: Update the landmark controls wrapper in the landmark
rendering flow of Sidebar so its opacity becomes visible when either the parent
group is hovered or the Pin/Remove buttons receive keyboard focus. Preserve the
existing collapsed-state condition and hover transition behavior while adding an
appropriate focus-within visibility utility.
In `@apps/console/src/styles/app.css`:
- Around line 247-255: Restore the base html, body height rule in app.css before
the existing .thread-jump-strip styles, setting both elements to 100% height.
Leave the thread-jump-strip responsive display rules unchanged.
In `@apps/console/src/styles/int-ui-register-light.css`:
- Around line 47-53: Correct the lightness annotation in the tier comment above
--ij-tier-sunken and --ij-tier-ground so it reflects the existing hex values:
sunken is darker than ground, with sunken approximately ~88 and ground
approximately ~92. Leave the tier variable values and their ordering unchanged.
In `@apps/console/src/styles/int-ui-register.css`:
- Around line 47-53: Update the seam and keyline token definitions in the CSS
variable block: derive --ij-seam and --ij-seam-raised from darker tier values so
each is darker than its corresponding frame, editor, raised, and floating
surfaces. Keep --ij-keyline aligned with the corrected raised seam and preserve
the existing focus and decorative keyline behavior.
In `@apps/console/src/styles/register-bridge.css`:
- Around line 170-190: Update the semantic elevation selectors in the register
bridge so every host—ground, raised, floating, sunken, and scrim—receives its
corresponding tier fill via background. Preserve the existing border, radius,
corner-shape, and shadow declarations while adding the missing fills for ground,
raised, and floating using the established tier-fill variables.
In `@apps/console/src/views/canvas/CanvasView.tsx`:
- Around line 26-47: Update queryCanvas and the CanvasView initialization/effect
flow to resolve Promise results from host.query before storing or rendering the
ObjectSet, rather than permanently using the empty snapshot. Preserve
synchronous query handling and ensure async results update state when resolved;
avoid re-querying in createCanvasStore.subscribe because the live subscription
already manages updates.
In `@apps/console/src/views/GalleyDocView.tsx`:
- Around line 89-185: Update the useEffect dependency array in GalleyDocView so
it includes the document title value used to compute docTitle, such as
doc?.properties.title, alongside mode, text, and doc?.id. Preserve the existing
openFor behavior while ensuring title changes recreate the closure and refresh
the hand-off chip label.
In `@apps/console/src/views/ThreadView.tsx`:
- Line 9: Replace the direct theoremUri import and usage in ThreadView with the
designated console address API, reusing the existing address parser to derive
the needed theorem address. Remove the block-view addressing import while
preserving the current behavior at the call site.
---
Nitpick comments:
In `@apps/console/e2e/stub-data-api.mjs`:
- Around line 175-182: Update cloneMentionCandidates to deep-clone nested values
within entry.relations, including array values, so cloned candidates never share
mutable relation data with MENTION_CANDIDATES_SEED. Preserve the existing
cloning of entry and properties and keep the function’s returned candidate shape
unchanged.
In `@apps/console/src/components/composer/Composer.tsx`:
- Around line 132-142: Remove the useEffect that calls setInterrupted when
isRunning changes, and reorder the markState derivation so isRunning takes
precedence over interrupted, producing 'composing' during active runs. In the
submit flow around the existing submit handler, clear interrupted explicitly
when a new run is submitted.
In `@apps/console/src/views/GalleyDocView.tsx`:
- Line 15: Rename the aliased import from `@codemirror/lang-markdown` to a name
that reflects the callable markdown factory, and update its invocation at the
corresponding editor setup call site. Preserve the existing factory call
behavior and avoid using the library’s exported markdownLanguage name for this
alias.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1043ca8b-bde0-4c0f-afcc-2669ab829d38
⛔ Files ignored due to path filters (24)
apps/console/e2e/appearance.spec.ts-snapshots/workspace-1280-light-linux.pngis excluded by!**/*.pngapps/console/e2e/appearance.spec.ts-snapshots/workspace-1440-light-linux.pngis excluded by!**/*.pngapps/console/e2e/cards.spec.ts-snapshots/action-sheet-linux.pngis excluded by!**/*.pngapps/console/e2e/cards.spec.ts-snapshots/card-compact-inspector-linux.pngis excluded by!**/*.pngapps/console/e2e/cards.spec.ts-snapshots/cards-grid-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/chat-empty-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/chat-plan-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/chat-streaming-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/context-graph-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/files-projection-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/stripe-groups-linux.pngis excluded by!**/*.pngapps/console/e2e/hunk-review.spec.ts-snapshots/hunk-review-1440-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/proactivity.spec.ts-snapshots/proactivity-cards-1440-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/proactivity.spec.ts-snapshots/proactivity-graph-1440-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/search-field.spec.ts-snapshots/search-panel-expanded-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/composer-sheen-idle-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/composer-sheen-idle-light-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/composer-sheen-streaming-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/composer-sheen-streaming-light-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/workspace-1280-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/workspace-1440-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/workspace-goal-stack.spec.ts-snapshots/goal-stack-v2-1440-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/workspace-goal-stack.spec.ts-snapshots/workspace-substrate-v2-1440-dark-linux.pngis excluded by!**/*.pngpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (57)
.harness/checklists/console-chat-surface--plan-local.jsonapps/console/AGENTS.mdapps/console/CLAUDE.mdapps/console/docs/plans/console-block-system/FOLLOWUP-DOCKVIEW-GROUND.mdapps/console/e2e/account.spec.tsapps/console/e2e/appearance.spec.tsapps/console/e2e/cards.spec.tsapps/console/e2e/console-ia.spec.tsapps/console/e2e/filing-index.spec.tsapps/console/e2e/search-field.spec.tsapps/console/e2e/signatures.spec.tsapps/console/e2e/stub-data-api.mjsapps/console/package.jsonapps/console/scripts/check-contrast.mjsapps/console/scripts/check-radius-lint.mjsapps/console/src/components/blocks/BlockCanvas.tsxapps/console/src/components/blocks/kind-glyph.tsxapps/console/src/components/composer/Composer.tsxapps/console/src/components/composer/ComposerSheenCanvas.tsxapps/console/src/components/material/EmptyRegion.tsxapps/console/src/components/material/ShaderSurface.tsxapps/console/src/components/shell/IntuiShell.tsxapps/console/src/components/shell/MainToolbar.tsxapps/console/src/components/shell/Sidebar.tsxapps/console/src/components/shell/ViewInstanceHost.tsxapps/console/src/lib/console-host.test.tsapps/console/src/lib/console-host.tsapps/console/src/lib/goal-stack-contract.test.tsapps/console/src/lib/material/kind-hues.test.tsapps/console/src/lib/material/kind-hues.tsapps/console/src/lib/material/materials.tsapps/console/src/lib/plan-program-shape.test.tsapps/console/src/motion/motion-tokens.tsapps/console/src/styles/app.cssapps/console/src/styles/int-ui-register-light.cssapps/console/src/styles/int-ui-register.cssapps/console/src/styles/register-bridge.cssapps/console/src/styles/token-manifest.jsonapps/console/src/views/CardView.tsxapps/console/src/views/CodeFileView.tsxapps/console/src/views/DocListView.tsxapps/console/src/views/GalleyDocView.tsxapps/console/src/views/ThreadView.tsxapps/console/src/views/ViewStates.test.tsxapps/console/src/views/ViewStates.tsxapps/console/src/views/canvas/CanvasPaperGround.tsxapps/console/src/views/canvas/CanvasView.tsxapps/console/src/views/thread/ObjectExcerpt.tsxapps/console/src/views/thread/ThreadExcerpt.test.tsxapps/console/src/views/thread/ThreadExcerpt.tsxdocs/plans/console-chat-surface/FOLLOWUP-FORME-DISCHARGE-TEXTURE.mddocs/plans/console-chat-surface/README.mddocs/plans/console-chat-surface/implementation-plan.mddocs/plans/material-register/SPEC-MATERIAL-REGISTER-1.0.mddocs/plans/material-register/implementation-plan.mddocs/plans/material-register/report.mdpackages/theorem-acp/src/plan-program.ts
💤 Files with no reviewable changes (1)
- apps/console/src/components/composer/ComposerSheenCanvas.tsx
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 12
🧹 Nitpick comments (3)
apps/console/src/views/GalleyDocView.tsx (1)
15-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAlias name collides with the library's real
markdownLanguageexport.
markdownis aliased tomarkdownLanguagehere, but@codemirror/lang-markdownalso exports an actualmarkdownLanguage(a plainLanguage, not callable). Calling it asmarkdownLanguage()at Line 62 is correct today because it's really the aliasedmarkdown()factory, but the name will mislead anyone who checks the library docs and could tempt a future edit to drop the()call.♻️ Suggested rename
-import { markdown as markdownLanguage } from '`@codemirror/lang-markdown`'; +import { markdown as markdownExtension } from '`@codemirror/lang-markdown`';- markdownLanguage(), + markdownExtension(),Also applies to: 62-62
🤖 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/views/GalleyDocView.tsx` at line 15, Rename the aliased import from `@codemirror/lang-markdown` to a name that reflects the callable markdown factory, and update its invocation at the corresponding editor setup call site. Preserve the existing factory call behavior and avoid using the library’s exported markdownLanguage name for this alias.apps/console/e2e/stub-data-api.mjs (1)
175-182: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueShallow-cloned
relationscould leak mutations back into the seed.
cloneMentionCandidatesspreadsentry.relations, which only copies the top-level keys; any array values inside are still shared withMENTION_CANDIDATES_SEED. No current handler mutates a relations array in place (delete/update reassign or only touchproperties), so this isn't an active bug, but it's a trap for a future in-place mutation (e.g..push()) silently corrupting the reset seed across test runs.♻️ Suggested deep clone
-function cloneMentionCandidates() { - return MENTION_CANDIDATES_SEED.map((entry) => ({ - ...entry, - properties: { ...entry.properties }, - relations: { ...entry.relations }, - })); -} +function cloneMentionCandidates() { + return MENTION_CANDIDATES_SEED.map((entry) => structuredClone(entry)); +}🤖 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/stub-data-api.mjs` around lines 175 - 182, Update cloneMentionCandidates to deep-clone nested values within entry.relations, including array values, so cloned candidates never share mutable relation data with MENTION_CANDIDATES_SEED. Preserve the existing cloning of entry and properties and keep the function’s returned candidate shape unchanged.apps/console/src/components/composer/Composer.tsx (1)
132-142: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winReorder
markStateto drop the reset effect (and the eslint error).Because
interruptedis checked beforeisRunning, starting a new run whileinterruptedis stilltruerenders'interrupted'for one frame until the effect flips it, a brief wrong glyph. ESLint also flags the synchronoussetStatein this effect (react-hooks/set-state-in-effect). PrioritizingisRunningin the derivation and clearinginterruptedon submit removes the effect and the flash.Proposed change
- useEffect(() => { - if (isRunning) setInterrupted(false); - }, [isRunning]); - const mention = useObjectMentionAdapter(mentions, tenant); - const markState: MarkState = interrupted - ? 'interrupted' - : isRunning - ? 'composing' - : 'idle'; + const markState: MarkState = isRunning + ? 'composing' + : interrupted + ? 'interrupted' + : 'idle';Then clear on submit (Line 256):
- onSubmit={() => setCharacterCount(0)} + onSubmit={() => { setCharacterCount(0); setInterrupted(false); }}🤖 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/composer/Composer.tsx` around lines 132 - 142, Remove the useEffect that calls setInterrupted when isRunning changes, and reorder the markState derivation so isRunning takes precedence over interrupted, producing 'composing' during active runs. In the submit flow around the existing submit handler, clear interrupted explicitly when a new run is submitted.Source: Linters/SAST tools
🤖 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 @.harness/checklists/console-chat-surface--plan-local.json:
- Around line 10-16: Update the status_lead_not_done checklist to remove entries
whose corresponding work is marked done, including CH0, CH1a, CH1b, CH2, and
CH6, or explicitly label the list as historical baseline status if those entries
must remain.
In `@apps/console/package.json`:
- Around line 73-75: Update the dockview dependency entry in package.json from a
caret range to an exact pinned version, preserving the current 4.10.0 version so
it matches the repository’s pinned dependency style and ensures reproducible
builds.
In `@apps/console/scripts/check-contrast.mjs`:
- Around line 227-230: Replace the tautological DECORATIVE_KEYLINES membership
check with a lookup against the register declarations, resolving
--ij-keyline-decorative through the same declaration-based mechanism used by the
PAIRS and RAIL_PAIRS loops. Keep the existing error message and exit behavior
when the token is absent, and avoid using the locally defined
DECORATIVE_KEYLINES set for this validation.
In `@apps/console/scripts/check-radius-lint.mjs`:
- Around line 29-30: Update RAW_RADIUS in check-radius-lint to match React
camelCase borderRadius declarations and Tailwind arbitrary rounded-[Npx]
classes, while preserving detection of existing CSS and Tailwind forms. Ensure
SCALE_TOKEN exemptions remain unchanged.
In `@apps/console/src/components/shell/Sidebar.tsx`:
- Around line 557-578: Update the landmark controls wrapper in the landmark
rendering flow of Sidebar so its opacity becomes visible when either the parent
group is hovered or the Pin/Remove buttons receive keyboard focus. Preserve the
existing collapsed-state condition and hover transition behavior while adding an
appropriate focus-within visibility utility.
In `@apps/console/src/styles/app.css`:
- Around line 247-255: Restore the base html, body height rule in app.css before
the existing .thread-jump-strip styles, setting both elements to 100% height.
Leave the thread-jump-strip responsive display rules unchanged.
In `@apps/console/src/styles/int-ui-register-light.css`:
- Around line 47-53: Correct the lightness annotation in the tier comment above
--ij-tier-sunken and --ij-tier-ground so it reflects the existing hex values:
sunken is darker than ground, with sunken approximately ~88 and ground
approximately ~92. Leave the tier variable values and their ordering unchanged.
In `@apps/console/src/styles/int-ui-register.css`:
- Around line 47-53: Update the seam and keyline token definitions in the CSS
variable block: derive --ij-seam and --ij-seam-raised from darker tier values so
each is darker than its corresponding frame, editor, raised, and floating
surfaces. Keep --ij-keyline aligned with the corrected raised seam and preserve
the existing focus and decorative keyline behavior.
In `@apps/console/src/styles/register-bridge.css`:
- Around line 170-190: Update the semantic elevation selectors in the register
bridge so every host—ground, raised, floating, sunken, and scrim—receives its
corresponding tier fill via background. Preserve the existing border, radius,
corner-shape, and shadow declarations while adding the missing fills for ground,
raised, and floating using the established tier-fill variables.
In `@apps/console/src/views/canvas/CanvasView.tsx`:
- Around line 26-47: Update queryCanvas and the CanvasView initialization/effect
flow to resolve Promise results from host.query before storing or rendering the
ObjectSet, rather than permanently using the empty snapshot. Preserve
synchronous query handling and ensure async results update state when resolved;
avoid re-querying in createCanvasStore.subscribe because the live subscription
already manages updates.
In `@apps/console/src/views/GalleyDocView.tsx`:
- Around line 89-185: Update the useEffect dependency array in GalleyDocView so
it includes the document title value used to compute docTitle, such as
doc?.properties.title, alongside mode, text, and doc?.id. Preserve the existing
openFor behavior while ensuring title changes recreate the closure and refresh
the hand-off chip label.
In `@apps/console/src/views/ThreadView.tsx`:
- Line 9: Replace the direct theoremUri import and usage in ThreadView with the
designated console address API, reusing the existing address parser to derive
the needed theorem address. Remove the block-view addressing import while
preserving the current behavior at the call site.
---
Nitpick comments:
In `@apps/console/e2e/stub-data-api.mjs`:
- Around line 175-182: Update cloneMentionCandidates to deep-clone nested values
within entry.relations, including array values, so cloned candidates never share
mutable relation data with MENTION_CANDIDATES_SEED. Preserve the existing
cloning of entry and properties and keep the function’s returned candidate shape
unchanged.
In `@apps/console/src/components/composer/Composer.tsx`:
- Around line 132-142: Remove the useEffect that calls setInterrupted when
isRunning changes, and reorder the markState derivation so isRunning takes
precedence over interrupted, producing 'composing' during active runs. In the
submit flow around the existing submit handler, clear interrupted explicitly
when a new run is submitted.
In `@apps/console/src/views/GalleyDocView.tsx`:
- Line 15: Rename the aliased import from `@codemirror/lang-markdown` to a name
that reflects the callable markdown factory, and update its invocation at the
corresponding editor setup call site. Preserve the existing factory call
behavior and avoid using the library’s exported markdownLanguage name for this
alias.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 1043ca8b-bde0-4c0f-afcc-2669ab829d38
⛔ Files ignored due to path filters (24)
apps/console/e2e/appearance.spec.ts-snapshots/workspace-1280-light-linux.pngis excluded by!**/*.pngapps/console/e2e/appearance.spec.ts-snapshots/workspace-1440-light-linux.pngis excluded by!**/*.pngapps/console/e2e/cards.spec.ts-snapshots/action-sheet-linux.pngis excluded by!**/*.pngapps/console/e2e/cards.spec.ts-snapshots/card-compact-inspector-linux.pngis excluded by!**/*.pngapps/console/e2e/cards.spec.ts-snapshots/cards-grid-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/chat-empty-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/chat-plan-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/chat-streaming-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/context-graph-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/files-projection-linux.pngis excluded by!**/*.pngapps/console/e2e/console-ia.spec.ts-snapshots/stripe-groups-linux.pngis excluded by!**/*.pngapps/console/e2e/hunk-review.spec.ts-snapshots/hunk-review-1440-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/proactivity.spec.ts-snapshots/proactivity-cards-1440-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/proactivity.spec.ts-snapshots/proactivity-graph-1440-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/search-field.spec.ts-snapshots/search-panel-expanded-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/composer-sheen-idle-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/composer-sheen-idle-light-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/composer-sheen-streaming-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/composer-sheen-streaming-light-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/workspace-1280-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/signatures.spec.ts-snapshots/workspace-1440-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/workspace-goal-stack.spec.ts-snapshots/goal-stack-v2-1440-dark-linux.pngis excluded by!**/*.pngapps/console/e2e/workspace-goal-stack.spec.ts-snapshots/workspace-substrate-v2-1440-dark-linux.pngis excluded by!**/*.pngpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (57)
.harness/checklists/console-chat-surface--plan-local.jsonapps/console/AGENTS.mdapps/console/CLAUDE.mdapps/console/docs/plans/console-block-system/FOLLOWUP-DOCKVIEW-GROUND.mdapps/console/e2e/account.spec.tsapps/console/e2e/appearance.spec.tsapps/console/e2e/cards.spec.tsapps/console/e2e/console-ia.spec.tsapps/console/e2e/filing-index.spec.tsapps/console/e2e/search-field.spec.tsapps/console/e2e/signatures.spec.tsapps/console/e2e/stub-data-api.mjsapps/console/package.jsonapps/console/scripts/check-contrast.mjsapps/console/scripts/check-radius-lint.mjsapps/console/src/components/blocks/BlockCanvas.tsxapps/console/src/components/blocks/kind-glyph.tsxapps/console/src/components/composer/Composer.tsxapps/console/src/components/composer/ComposerSheenCanvas.tsxapps/console/src/components/material/EmptyRegion.tsxapps/console/src/components/material/ShaderSurface.tsxapps/console/src/components/shell/IntuiShell.tsxapps/console/src/components/shell/MainToolbar.tsxapps/console/src/components/shell/Sidebar.tsxapps/console/src/components/shell/ViewInstanceHost.tsxapps/console/src/lib/console-host.test.tsapps/console/src/lib/console-host.tsapps/console/src/lib/goal-stack-contract.test.tsapps/console/src/lib/material/kind-hues.test.tsapps/console/src/lib/material/kind-hues.tsapps/console/src/lib/material/materials.tsapps/console/src/lib/plan-program-shape.test.tsapps/console/src/motion/motion-tokens.tsapps/console/src/styles/app.cssapps/console/src/styles/int-ui-register-light.cssapps/console/src/styles/int-ui-register.cssapps/console/src/styles/register-bridge.cssapps/console/src/styles/token-manifest.jsonapps/console/src/views/CardView.tsxapps/console/src/views/CodeFileView.tsxapps/console/src/views/DocListView.tsxapps/console/src/views/GalleyDocView.tsxapps/console/src/views/ThreadView.tsxapps/console/src/views/ViewStates.test.tsxapps/console/src/views/ViewStates.tsxapps/console/src/views/canvas/CanvasPaperGround.tsxapps/console/src/views/canvas/CanvasView.tsxapps/console/src/views/thread/ObjectExcerpt.tsxapps/console/src/views/thread/ThreadExcerpt.test.tsxapps/console/src/views/thread/ThreadExcerpt.tsxdocs/plans/console-chat-surface/FOLLOWUP-FORME-DISCHARGE-TEXTURE.mddocs/plans/console-chat-surface/README.mddocs/plans/console-chat-surface/implementation-plan.mddocs/plans/material-register/SPEC-MATERIAL-REGISTER-1.0.mddocs/plans/material-register/implementation-plan.mddocs/plans/material-register/report.mdpackages/theorem-acp/src/plan-program.ts
💤 Files with no reviewable changes (1)
- apps/console/src/components/composer/ComposerSheenCanvas.tsx
🛑 Comments failed to post (12)
.harness/checklists/console-chat-surface--plan-local.json (1)
10-16: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Keep the checklist status fields consistent.
status_lead_not_donestill lists CH0, CH1a, CH1b, CH2, and CH6 work even though their corresponding items are markeddone. Remove completed entries or label this as historical baseline status.🤖 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 @.harness/checklists/console-chat-surface--plan-local.json around lines 10 - 16, Update the status_lead_not_done checklist to remove entries whose corresponding work is marked done, including CH0, CH1a, CH1b, CH2, and CH6, or explicitly label the list as historical baseline status if those entries must remain.apps/console/package.json (1)
73-75: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
dockviewuses a caret range while the PR claims it is pinned.Sibling deps here are exact-pinned (
zustand5.0.14,@paper-design/shaders0.0.77), and the PR objective says it "pinsdockview".^4.10.0still allows minor/patch drift. Pin it to a single version for reproducible builds.Proposed pin
- "dockview": "^4.10.0" + "dockview": "4.10.0"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements."zustand": "5.0.14", "`@paper-design/shaders`": "0.0.77", "dockview": "4.10.0"🤖 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/package.json` around lines 73 - 75, Update the dockview dependency entry in package.json from a caret range to an exact pinned version, preserving the current 4.10.0 version so it matches the repository’s pinned dependency style and ensures reproducible builds.apps/console/scripts/check-contrast.mjs (1)
227-230: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Decorative-keyline gate is tautological.
DECORATIVE_KEYLINESis a local constant defined with'--ij-keyline-decorative'(Lines 99-101), soDECORATIVE_KEYLINES.has('--ij-keyline-decorative')is always true and can never catch a register that fails to define the token. To make this a real registry check, resolve the token from the register declarations (as thePAIRS/RAIL_PAIRSloops do) instead of probing an in-file set.🤖 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 227 - 230, Replace the tautological DECORATIVE_KEYLINES membership check with a lookup against the register declarations, resolving --ij-keyline-decorative through the same declaration-based mechanism used by the PAIRS and RAIL_PAIRS loops. Keep the existing error message and exit behavior when the token is absent, and avoid using the locally defined DECORATIVE_KEYLINES set for this validation.apps/console/scripts/check-radius-lint.mjs (1)
29-30: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash # Find inline camelCase borderRadius with raw px in components (would evade current RAW_RADIUS). rg -nP --type=ts --type=tsx -g '!apps/console/src/styles/**' -g '!apps/console/src/motion/**' \ "borderRadius\s*:\s*['\"]?\d+(\.\d+)?px" apps/console/src || echo "none found" # Find Tailwind arbitrary radius classes. rg -nP --type=ts --type=tsx "rounded-\[\d+(\.\d+)?px\]" apps/console/src || echo "none found"Repository: Travis-Gilbert/CommonPlace
Length of output: 242
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "== file excerpt ==" sed -n '1,120p' apps/console/scripts/check-radius-lint.mjs echo echo "== repository files mentioning check-radius-lint ==" rg -n "check-radius-lint|radius|border-radius|borderRadius|rounded-" apps/console -g '!node_modules' -g '!dist' -g '!build' | head -200 || trueRepository: Travis-Gilbert/CommonPlace
Length of output: 44552
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "== pattern coverage probe ==" node - <<'JS' const p = /(?:border-radius|rounded(?:-[a-z]+)?)\s*[:=]\s*[^;\n]*\b\d+(?:\.\d+)?px\b/; const testCases = [ 'border-radius: 99px;', 'borderRadius: 8px;', "borderRadius: '8px'", 'borderRadius: 4.5px;', 'rounded-[12px]', 'rounded-[8px] bg-red', 'rounded-ij-arc', 'var(--ij-radius-md)', 'var(--ij-radius-xs) px', 'border-radius: var(--ij-radius-md);', ]; for (const s of testCases) { console.log(`${p.test(s) ? 'MATCH ' : 'MISS '}${s}`); } JS echo echo "== all non-exempt raw radius px candidates in apps/console/src ==" python3 - <<'PY' import os, re IGNORE = {'src/styles', 'src/motion'} root = 'apps/console/src' re_plain = re.compile(r'\bborder-radius\s*:\s*[^;\n]*\b\d+(?:\.\d+)?px\b') re_camel = re.compile(r'borderRadius\s*:\s*[^;\n]*\b\d+(?:\.\d+)?px\b') re_arb = re.compile(r'rounded-\[\d+(?:\.\d+)?px\]') re_rounded = re.compile(r'\b(?:border-radius|rounded(?:-[a-z]+)?)\s*[:=]\s*[^;\n]*\b\d+(?:\.\d+)?px\b') for name in ['plain/css', 'camel/jsx', 'arbitrary/class']: print(f'\n-- {name} --') hits = [] if name == 'plain/css': pat = re_plain elif name == 'camel/jsx': pat = re_camel else: pat = re_arb for fn in sorted(os.listdir(root)): dirpath = os.path.join(root, fn) if os.path.isdir(dirpath): if fn in IGNORE: continue for rel in sorted(os.listdir(dirpath) if os.path.isdir(dirpath) else [fn]): path = os.path.join(root, fn, rel) if os.path.isdir(dirpath) else os.path.join(root, fn) if os.path.isdir(path): continue try: text = open(path, encoding='utf-8', errors='ignore').read() except Exception: continue if rel.endswith(('.ts','.tsx','js','.jsx','.mjs','.cjs')): for i,line in enumerate(text.splitlines(),1): if pat.search(line): hits.append(f'{path}:{i}: {line.strip()[:120]}') elif rel.endswith('.css'): for i,line in enumerate(text.splitlines(),1): if path.startswith('src/styles') or path.startswith('src/motion'): continue if pat.search(line): hits.append(f'{path}:{i}: {line.strip()[:120]}') if hits: print('\n'.join(hits)) else: print('none') print('\n-- old lint pattern hits --') hits=[] for fn in sorted(os.listdir(root)): dirpath = os.path.join(root, fn) if os.path.isdir(dirpath) and fn in IGNORE: continue for rel in sorted(os.listdir(dirpath) if os.path.isdir(dirpath) else [fn]): path = os.path.join(root, fn, rel) if os.path.isdir(dirpath) else os.path.join(root, fn) if os.path.isdir(path): continue try: text = open(path, encoding='utf-8', errors='ignore').read() except Exception: continue if rel.endswith(('.ts','.tsx','js','.jsx','.mjs','.cjs')): for i,line in enumerate(text.splitlines(),1): if re_rounded.search(line): hits.append(f'{path}:{i}: {line.strip()[:120]}') else: for i,line in enumerate(text.splitlines(),1): if path.startswith('src/styles') or path.startswith('src/motion'): continue if re_rounded.search(line): hits.append(f'{path}:{i}: {line.strip()[:120]}') if hits: print('\n'.join(hits)) else: print('none') PYRepository: Travis-Gilbert/CommonPlace
Length of output: 657
Cover inline and Tailwind raw radius in the lint.
RAW_RADIUSmisses common.tsxforms: React inline styles use camelCaseborderRadius: '8px', and Tailwind arbitrary classes userounded-[12px]without[:=]. Add those cases to catch component-level raw-radius violations or confirm another merge gate covers them.🤖 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-radius-lint.mjs` around lines 29 - 30, Update RAW_RADIUS in check-radius-lint to match React camelCase borderRadius declarations and Tailwind arbitrary rounded-[Npx] classes, while preserving detection of existing CSS and Tailwind forms. Ensure SCALE_TOKEN exemptions remain unchanged.apps/console/src/components/shell/Sidebar.tsx (1)
557-578: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Hover-only landmark controls are invisible on keyboard focus.
The Pin/Remove buttons are focusable, but their wrapper is
opacity-0and only revealed viagroup-hover:opacity-100. A keyboard user who tabs onto Pin/Remove sees no visible control, which fails focus visibility. Reveal the controls on focus as well.♿ Reveal controls on keyboard focus
- <span className="flex shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100"> + <span className="flex shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100">📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.{!visuallyCollapsed ? ( <span className="flex shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100"> <button type="button" className="text-ij-ink-info hover:text-ij-ink" onClick={() => pinLandmark(landmark)} aria-label={`${landmark.properties.pinned === true ? 'Unpin' : 'Pin'} ${label}`} > {landmark.properties.pinned === true ? 'Unpin' : 'Pin'} </button> {removable ? ( <button type="button" className="text-ij-ink-info hover:text-ij-ink" onClick={() => removeLandmark(landmark)} aria-label={`Remove ${label}`} > Remove </button> ) : null} </span> ) : null}🤖 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 557 - 578, Update the landmark controls wrapper in the landmark rendering flow of Sidebar so its opacity becomes visible when either the parent group is hovered or the Pin/Remove buttons receive keyboard focus. Preserve the existing collapsed-state condition and hover transition behavior while adding an appropriate focus-within visibility utility.apps/console/src/styles/app.css (1)
247-255: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash rg -n 'html,\s*body|height:\s*100%' apps/console/src/styles/app.cssRepository: Travis-Gilbert/CommonPlace
Length of output: 164
🏁 Script executed:
#!/bin/bash set -euo pipefail printf 'Tracked file count:\n' git ls-files 'apps/console/src/styles/app.css' printf '\nRelevant searches:\n' rg -n '^(html,|body|\.thread-jump-strip)|height:\s*100%|100vh|min-height:\s*100%' apps/console/src/styles/app.css || true printf '\nApp.css line count:\n' wc -l apps/console/src/styles/app.css printf '\nLine 220-270:\n' sed -n '220,270p' apps/console/src/styles/app.cssRepository: Travis-Gilbert/CommonPlace
Length of output: 1689
Restore the viewport-height root rule.
apps/console/src/styles/app.cssno longer setshtml, body { height: 100%; }; it only has.thread-jump-stripbefore abodyrule withoutheight. Add that base rule back to keeph-full,min-h-0 flex-1, and viewport-height layouts from collapsing.🤖 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/app.css` around lines 247 - 255, Restore the base html, body height rule in app.css before the existing .thread-jump-strip styles, setting both elements to 100% height. Leave the thread-jump-strip responsive display rules unchanged.apps/console/src/styles/int-ui-register-light.css (1)
47-53: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Tier lightness comment inverts sunken vs ground.
The annotation says "After: sunken ~92, ground ~88", i.e. sunken lighter than ground. But
--ij-tier-sunken:#D2CEC5is darker than `--ij-tier-ground: `#D9D6CF(lower RGB → lower L*), which is also what the "editor sunken on frame" contrast pair assumes. The hex ordering is correct; the comment L% values are reversed and could mislead when the dark register or future tuning is derived from them. Please correct the annotated values.🤖 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/int-ui-register-light.css` around lines 47 - 53, Correct the lightness annotation in the tier comment above --ij-tier-sunken and --ij-tier-ground so it reflects the existing hex values: sunken is darker than ground, with sunken approximately ~88 and ground approximately ~92. Leave the tier variable values and their ordering unchanged.apps/console/src/styles/int-ui-register.css (1)
47-53: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Do not make seam and keyline tokens lighter than their surfaces.
--ij-seamis lighter than--ij-frameand--ij-editor;--ij-seam-raisedis also lighter than the raised and floating tiers. Since--ij-keylinealiases that value, this reintroduces light hairlines across elevated surfaces. Derive these seams from darker tier values instead.As per coding guidelines, seams must be darker than surfaces, with no light hairlines.
🤖 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/int-ui-register.css` around lines 47 - 53, Update the seam and keyline token definitions in the CSS variable block: derive --ij-seam and --ij-seam-raised from darker tier values so each is darker than its corresponding frame, editor, raised, and floating surfaces. Keep --ij-keyline aligned with the corrected raised seam and preserve the existing focus and decorative keyline behavior.Source: Coding guidelines
apps/console/src/styles/register-bridge.css (1)
170-190: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Apply tier fills for every semantic elevation host.
Only
sunkenandscrimreceive a background.ground,raised, andfloatinghosts retain their parent fill when consumers rely ondata-elevation, so their declared elevation is visually lost.Proposed fix
+[data-register="intui"] [data-elevation="ground"] { + background: var(--ij-tier-ground); +} + [data-register="intui"] [data-elevation="raised"], [data-register="intui"] [data-elevation="floating"] { + background: var(--ij-tier-raised); border: 1px solid var(--ij-keyline); border-radius: var(--ij-radius-md); corner-shape: var(--ij-corner-raised); } [data-register="intui"] [data-elevation="floating"] { + background: var(--ij-tier-floating); border-radius: var(--ij-radius-lg); box-shadow: var(--ij-floating-shadow); }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements./* Raised and above: keyline + continuous-curvature corner (Chromium). WebKit degrades to border-radius alone (named choice 3). */ [data-register="intui"] [data-elevation="ground"] { background: var(--ij-tier-ground); } [data-register="intui"] [data-elevation="raised"], [data-register="intui"] [data-elevation="floating"] { background: var(--ij-tier-raised); border: 1px solid var(--ij-keyline); border-radius: var(--ij-radius-md); corner-shape: var(--ij-corner-raised); } [data-register="intui"] [data-elevation="floating"] { background: var(--ij-tier-floating); border-radius: var(--ij-radius-lg); box-shadow: var(--ij-floating-shadow); } [data-register="intui"] [data-elevation="sunken"] { background: var(--ij-tier-sunken); border-radius: var(--ij-radius-sm); } [data-register="intui"] [data-elevation="scrim"] { background: var(--ij-scrim-fill);🤖 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/register-bridge.css` around lines 170 - 190, Update the semantic elevation selectors in the register bridge so every host—ground, raised, floating, sunken, and scrim—receives its corresponding tier fill via background. Preserve the existing border, radius, corner-shape, and shadow declarations while adding the missing fills for ground, raised, and floating using the established tier-fill variables.apps/console/src/views/canvas/CanvasView.tsx (1)
26-47: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash # Determine whether BlockHost.query can return a Promise in this codebase. rg -nP -C3 "\bquery\s*\(" packages/block-view/src/types.ts rg -nP -C2 "Promise<ObjectSet>|ObjectSet\s*\|\s*Promise" packages/block-view/srcRepository: Travis-Gilbert/CommonPlace
Length of output: 1235
🏁 Script executed:
#!/bin/bash set -euo pipefail echo "== CanvasView ==" cat -n apps/console/src/views/canvas/CanvasView.tsx echo echo "== HttpBlockHost query context ==" sed -n '1,180p' packages/block-view/src/host/HttpBlockHost.ts | cat -n echo echo "== MaybePromise definition and object set subscribe usages ==" rg -n -C3 "type MaybePromise|interface MaybePromise|Promise<ObjectSet>|ObjectSet \| Promise|subscribe\\(" packages/block-view apps/console/src/views/canvas -g '*.ts' -g '*.tsx' echo echo "== Similar MaybePromise query handling ==" rg -n -C4 "Promise\.resolve\\(host\.(query|get)?|await host\s*\?\.?\.query|query\\(" apps/console/src packages -g '*.ts' -g '*.tsx' | head -n 220Repository: Travis-Gilbert/CommonPlace
Length of output: 43341
Handle async
host.queryin the canvas store.
BlockHost.queryisMaybePromise<ObjectSet>, and bothHttpBlockHostand the live domain path return promises.queryCanvasreturns only an empty snapshot when the query is aPromise, so the canvas can render stuck. Await the promise before returning/consuming the result. Minor:createCanvasStore.subscribealso re-runsqueryCanvas, but the live subscribe path already handles that by construction.🧰 Tools
🪛 ESLint
[error] 45-45: Error: Calling setState synchronously within an effect can trigger cascading renders
Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:
- Update external systems with the latest state from React.
- Subscribe for updates from some external system, calling setState in a callback function when external state changes.
Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).
/home/jailuser/git/apps/console/src/views/canvas/CanvasView.tsx:45:5
43 | useEffect(() => {
44 | const current = queryCanvas(host);45 | setSet(current);
| ^^^^^^ Avoid calling setState() directly within an effect
46 | return current.subscribe(setSet);
47 | }, [host]);
48 |(react-hooks/set-state-in-effect)
🤖 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/views/canvas/CanvasView.tsx` around lines 26 - 47, Update queryCanvas and the CanvasView initialization/effect flow to resolve Promise results from host.query before storing or rendering the ObjectSet, rather than permanently using the empty snapshot. Preserve synchronous query handling and ensure async results update state when resolved; avoid re-querying in createCanvasStore.subscribe because the live subscription already manages updates.Source: Linters/SAST tools
apps/console/src/views/GalleyDocView.tsx (1)
89-185: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Stale
docTitleclosure: missing effect dependency.
openForcloses overdocTitle, but the effect's dependency array ([mode, text, doc?.id]) omitsdoc?.properties.title. If the title changes whiletext/doc.idstay the same, the hand-off chip label will use the stale title until something else re-triggers the effect. Confirmed by the ESLintreact-hooks/exhaustive-depswarning on Line 185.🐛 Suggested fix
- }, [mode, text, doc?.id]); + }, [mode, text, doc?.id, doc?.properties.title]);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.useEffect(() => { if (mode !== 'read') return; const root = scrollRef.current; const docId = doc?.id; const docTitle = typeof doc?.properties.title === 'string' ? doc.properties.title : docId; if (!root || !docId) return; const openFor = (todoText: string) => { useShellStore.getState().openActionSheet({ chips: [ objectChip(docId, 'doc', docTitle ?? docId), { id: `chip-selection-${docId}-${todoText.slice(0, 24)}`, kind: 'selection', label: todoText, text: todoText, source: 'origin', }, ], }); }; const decorate = () => { const items = [ ...root.querySelectorAll<HTMLElement>('li.task-list-item'), ...[...root.querySelectorAll<HTMLElement>('.galley li:not(.task-list-item)')].filter((li) => /^\[( |x)\]\s/.test((li.textContent ?? '').trimStart()), ), ]; for (const item of items) { if (item.querySelector('[data-todo-action]')) continue; const todoText = (item.textContent ?? '').trim(); const button = document.createElement('button'); button.type = 'button'; button.dataset.todoAction = ''; button.dataset.todoText = todoText; button.setAttribute('aria-label', 'Hand this todo to the agent'); button.textContent = '→'; button.className = 'ml-2 h-5 rounded-ij-arc px-1 text-ij-ink-info hover:bg-ij-hover-surface hover:text-ij-ink focus:outline-2 focus:outline-ij-accent'; item.tabIndex = 0; item.dataset.todoItem = ''; item.dataset.todoText = todoText; item.appendChild(button); } }; const onClick = (event: MouseEvent) => { const target = event.target as HTMLElement | null; const button = target?.closest<HTMLElement>('[data-todo-action]'); if (!button || !root.contains(button)) return; event.preventDefault(); openFor(button.dataset.todoText ?? ''); }; const onKey = (event: KeyboardEvent) => { if (!(event.altKey && event.key === 'Enter')) return; const target = event.target as HTMLElement | null; const item = target?.closest<HTMLElement>('[data-todo-item]'); if (!item || !root.contains(item)) return; event.preventDefault(); event.stopPropagation(); openFor(item.dataset.todoText ?? (item.textContent ?? '').trim()); }; let timer: ReturnType<typeof setTimeout> | null = null; let observer: MutationObserver; const scheduleDecorate = () => { if (timer) clearTimeout(timer); timer = setTimeout(() => { timer = null; observer.disconnect(); try { decorate(); } finally { observer.observe(root, { childList: true, subtree: true }); } }, 0); }; decorate(); observer = new MutationObserver(() => scheduleDecorate()); observer.observe(root, { childList: true, subtree: true }); root.addEventListener('click', onClick); root.addEventListener('keydown', onKey); return () => { if (timer) clearTimeout(timer); observer.disconnect(); root.removeEventListener('click', onClick); root.removeEventListener('keydown', onKey); root.querySelectorAll('[data-todo-action]').forEach((node) => node.remove()); root.querySelectorAll<HTMLElement>('[data-todo-item]').forEach((item) => { item.removeAttribute('tabindex'); delete item.dataset.todoItem; delete item.dataset.todoText; }); }; }, [mode, text, doc?.id, doc?.properties.title]);🧰 Tools
🪛 GitHub Check: Gates, unit tests, build
[warning] 185-185:
React Hook useEffect has a missing dependency: 'doc.properties.title'. Either include it or remove the dependency array🤖 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/views/GalleyDocView.tsx` around lines 89 - 185, Update the useEffect dependency array in GalleyDocView so it includes the document title value used to compute docTitle, such as doc?.properties.title, alongside mode, text, and doc?.id. Preserve the existing openFor behavior while ensuring title changes recreate the closure and refresh the hand-off chip label.Source: Linters/SAST tools
apps/console/src/views/ThreadView.tsx (1)
9-9: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash fd object-address.ts apps/console/src/lib --exec cat {} rg -n 'theoremUri|extractTheoremAddress' apps/console/srcRepository: Travis-Gilbert/CommonPlace
Length of output: 2998
🏁 Script executed:
#!/bin/bash set -euo pipefail sed -n '1,115p' apps/console/src/views/ThreadView.tsx printf '\n--- objectAddress usages ---\n' rg -n 'objectAddress\(|AddressableObject|extractTheoremAddress\(' apps/console/src/views/ThreadView.tsx apps/console/src/lib apps/console/srcRepository: Travis-Gilbert/CommonPlace
Length of output: 5980
Direct
theoremUricalls still bypass the console address helper.
apps/console/src/views/ThreadView.tsx:71callstheoremUri(address)directly; use the designated console address API, such as the existing address parser, instead of importing@commonplace/block-view/addressing.🤖 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/views/ThreadView.tsx` at line 9, Replace the direct theoremUri import and usage in ThreadView with the designated console address API, reusing the existing address parser to derive the needed theorem address. Remove the block-view addressing import while preserving the current behavior at the call site.Source: Coding guidelines
Post-#99: island gutter is 6px, Hide loses data-island-hide, companion chips sit on chrome not selection wash. Refresh linux snapshots from CI actuals and force companion/Files clicks so soft-nav races cannot hang the worker. Co-authored-by: Travis Gilbert <Travis-Gilbert@users.noreply.github.com>
Summary
dockviewand recordsFOLLOWUP-DOCKVIEW-GROUND.mdas the ground canvas upstream (replacing react-grid-layout); nested kanban stays on dnd-kit.Test plan
pnpm --filter console run gatespnpm --filter console exec tsc --noEmitDepends on / pairs with #98.
Summary by CodeRabbit