Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions apps/console/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ the primary CommonPlace product surface.
Railway must deploy this app with `railway.console.toml`; the root
`railway.toml` belongs to the legacy web service.

Workspace imports require matching path-separator-delimited allowlists on both
services: `CONSOLE_WORKSPACE_ALLOWED_ROOTS` on this Console and the JSON tenant
map `COMMONPLACE_WORKSPACE_TENANT_ALLOWED_ROOTS` on commonplace-api. Each API
map key is the identity-derived tenant and each value is that tenant's array of
owned roots. The API canonicalizes requested directories, rejects overlapping
roots across tenants, and prevents symlink escapes. The legacy
`COMMONPLACE_WORKSPACE_ALLOWED_ROOTS` variable is a single-tenant development
fallback only. Production must configure the Console list and tenant map.

## Composition doctrine

One material system. Two structural sources. Bridged, not blended.
Expand Down Expand Up @@ -76,6 +85,7 @@ asks for inspiration, reference, mood, or direction.
|---|---|---|
| Split layout, tool window panels | `react-resizable-panels` | split geometry, persisted sizes, 1px `--ij-divider` handles |
| Search everywhere, palettes | `cmdk` | command list, filtering, keyboard nav |
| Approval dialog | `cmdk` Dialog | focus-managed, keyboard-selectable one-shot Plan approval and rejection |
| Tabular lenses | tablecn structure on `@tanstack/react-table` | record.table sorting, filtering, column model |
| Row virtualization | `@tanstack/react-virtual` | large record sets |
| Thread and messages | `@assistant-ui/react` 0.12 | message list, streaming, message state |
Expand All @@ -97,6 +107,8 @@ asks for inspiration, reference, mood, or direction.
| Agent plan | `@assistant-ui/react` plus 21st.dev `isaiahbjork/agent-plan` structure extraction | in-thread plan rows, tool labels, and run status |
| Graph canvas | `@xyflow/react` (React Flow) over `@dagrejs/dagre` (layered ranking) | the proactivity graph, per SPEC-PROACTIVITY-GRAPH-WIRING: dagre computes the layered join topology (roots rank first, sinks last), React Flow owns pan, zoom, selection, and edge routing; nodes and edges are register-styled (base CSS only, `--xy-*` mapped to the register in app.css), dynamic-imported so the sentence and card altitudes load no graph bundle |
| Graph node and sentence card building blocks | jalco-ui `commit-graph` and `repo-card` (ui.justinlevine.me), structure extraction | the commit-entry node (a response is a stack of agent-action steps a person builds) and the RepoCard sentence card; the jalco layouts are reproduced and every shadcn token re-skinned to the register |
| Goal Stack canvas | `@xyflow/react` plus `@dagrejs/dagre`, `cmdk`, and `@dnd-kit/core` | DAG canvas and progress edges, named left-to-right layout, searchable capability palette and approval dialog, deferred-affordance drag and drop |
| Workspace substrate | `@tanstack/react-virtual`, CodeMirror 6 merge, `cmdk`, and Radix Popover | semantic workspace entity tree, virtual rows, local-history revision diff, project Find, readiness detail |

glide-data-grid is the escalation path for spreadsheet-scale grids only and is
not used in this round.
Expand Down
12 changes: 12 additions & 0 deletions apps/console/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ the primary CommonPlace product surface.
Railway must deploy this app with `railway.console.toml`; the root
`railway.toml` belongs to the legacy web service.

Workspace imports require matching path-separator-delimited allowlists on both
services: `CONSOLE_WORKSPACE_ALLOWED_ROOTS` on this Console and the JSON tenant
map `COMMONPLACE_WORKSPACE_TENANT_ALLOWED_ROOTS` on commonplace-api. Each API
map key is the identity-derived tenant and each value is that tenant's array of
owned roots. The API canonicalizes requested directories, rejects overlapping
roots across tenants, and prevents symlink escapes. The legacy
`COMMONPLACE_WORKSPACE_ALLOWED_ROOTS` variable is a single-tenant development
fallback only. Production must configure the Console list and tenant map.

## Composition doctrine

One material system. Two structural sources. Bridged, not blended.
Expand Down Expand Up @@ -70,6 +79,7 @@ gap: add the row, with a named source, before writing code.
|---|---|---|
| Split layout, tool window panels | `react-resizable-panels` | split geometry, persisted sizes, 1px `--ij-divider` handles |
| Search everywhere, palettes | `cmdk` | command list, filtering, keyboard nav |
| Approval dialog | `cmdk` Dialog | focus-managed, keyboard-selectable one-shot Plan approval and rejection |
| Tabular lenses | tablecn structure on `@tanstack/react-table` | record.table sorting, filtering, column model |
| Row virtualization | `@tanstack/react-virtual` | large record sets |
| Thread and messages | `@assistant-ui/react` 0.12 | message list, streaming, message state |
Expand All @@ -90,6 +100,8 @@ gap: add the row, with a named source, before writing code.
| Context graph | D3 | deterministic ego graph layout and relation geometry |
| Agent plan | `@assistant-ui/react` plus 21st.dev `isaiahbjork/agent-plan` structure extraction | in-thread plan rows, tool labels, and run status |
| Graph canvas | `@xyflow/react` (React Flow) over `@dagrejs/dagre` (layered ranking) | the proactivity graph, per SPEC-PROACTIVITY-GRAPH-WIRING: dagre computes the layered join topology (roots rank first, sinks last), React Flow owns pan, zoom, selection, and edge routing; nodes and edges are register-styled (base CSS only, `--xy-*` mapped to the register in app.css), dynamic-imported so the sentence and card altitudes load no graph bundle |
| Goal Stack canvas | `@xyflow/react` plus `@dagrejs/dagre`, `cmdk`, and `@dnd-kit/core` | DAG canvas and progress edges, named left-to-right layout, searchable capability palette and approval dialog, deferred-affordance drag and drop |
| Workspace substrate | `@tanstack/react-virtual`, CodeMirror 6 merge, `cmdk`, and Radix Popover | semantic workspace entity tree, virtual rows, local-history revision diff, project Find, readiness detail |
| Graph node and sentence card building blocks | jalco-ui `commit-graph` and `repo-card` (ui.justinlevine.me), structure extraction | the commit-entry node (a response is a stack of agent-action steps a person builds) and the RepoCard sentence card; the jalco layouts are reproduced and every shadcn token re-skinned to the register |

glide-data-grid is the escalation path for spreadsheet-scale grids only and is
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions apps/console/e2e/cards.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ test.describe('cards, actions, mentions', () => {
test('the surface rail is the primary nav: far-left, switches screens', async ({ page }) => {
const rail = page.locator('[data-surface-rail]');
await expect(rail).toBeVisible();
// The exact five primary surfaces form an APG radio group.
await expect(rail.locator('[data-surface-nav]')).toHaveCount(5);
// The exact six primary surfaces form an APG radio group.
await expect(rail.locator('[data-surface-nav]')).toHaveCount(6);
await expect(rail.locator('[data-surface-nav="console-chat"]')).toHaveAttribute(
'aria-checked',
'true',
Expand Down
17 changes: 9 additions & 8 deletions apps/console/e2e/console-ia.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ async function openSurface(page: Page, id: string) {
test.describe('Console information architecture', () => {
test.beforeEach(async ({ page }) => freshLoad(page));

test('separates five surface radios from three companion toggles', async ({ page }) => {
test('separates six surface radios from three companion toggles', async ({ page }) => {
await expect(page.locator('[data-shell]')).toHaveAttribute('data-active-surface', 'console-chat');
const surfaces = page.getByRole('radiogroup', { name: 'Surfaces' }).getByRole('radio');
await expect(surfaces).toHaveCount(5);
await expect(surfaces).toHaveCount(6);
expect(await surfaces.evaluateAll((nodes) => nodes.map((node) => node.getAttribute('aria-label')))).toEqual([
'Chat surface', 'Workspace surface', 'Index surface', 'Documents surface', 'Cards surface',
'Chat surface', 'Workspace surface', 'Goal Stack surface', 'Index surface', 'Documents surface', 'Cards surface',
]);
await expect(surfaces.first()).toHaveAttribute('aria-checked', 'true');
const companions = page.locator('[data-companion-nav]');
Expand All @@ -40,9 +40,10 @@ test.describe('Console information architecture', () => {
await expect(page.locator('[data-companion-nav="files"]')).toHaveAttribute('aria-pressed', 'true');
for (const [shortcut, surfaceId] of [
['2', 'console-workspace'],
['3', 'console-index'],
['4', 'console-docs'],
['5', 'console-cards'],
['3', 'console-goals'],
['4', 'console-index'],
['5', 'console-docs'],
['6', 'console-cards'],
['1', 'console-chat'],
] as const) {
await page.keyboard.press(`Alt+${shortcut}`);
Expand Down Expand Up @@ -188,12 +189,12 @@ test.describe('Console information architecture', () => {
expect((bounds?.x ?? 390) + (bounds?.width ?? 0)).toBeLessThanOrEqual(390);
});

test('seeds Workspace with document, code, and compact Thread but no table rail', async ({ page }) => {
test('seeds Workspace with the substrate, reference tabs, and compact Thread', async ({ page }) => {
await openSurface(page, 'console-workspace');
await expect(page.locator('[data-workspace-substrate]')).toBeVisible();
await expect(page.getByRole('tab', { name: 'Console brief' })).toBeVisible();
await expect(page.getByRole('tab', { name: 'surface-tree.ts' })).toBeVisible();
await expect(page.locator('[data-composer-density="compact"]')).toBeVisible();
await expect(page.locator('.galley p').first()).toHaveCSS('font-size', '15px');
await expect(page.locator('tbody')).toHaveCount(0);
});

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading