file-presentation.tsMerge remote-tracking branch 'origin/staging' into refactor/agent-files-sections
# Conflicts:
# apps/mail/modules/agents/components/AgentConversationFilesFolder.tsx
# apps/mail/modules/conversations/components/files/ConversationFileTree.tsx
# apps/mail/modules/files/components/list/FileListColumns.tsx
# apps/mail/modules/files/components/list/index.ts
# apps/mail/modules/files/components/list/types.ts
# apps/mail/tests/modules/files/brain-explorer.test.tsx
# apps/mail/tests/modules/files/list/FileListRow.test.tsx
# apps/server/src/mastra/tools/debug/debugTool.ts
# apps/server/src/services/playbook/playbook-execution-triggers.ts
# apps/server/src/services/playbook/playbook-renderers.ts
# apps/server/src/services/playbook/resolve-playbook-context.ts
# apps/server/src/services/playbook/write-document-guarded.ts
# apps/server/src/trpc/routes/documents.tsSep 9, 2026, 9:26 AMformat-file-size.tsfeat(files): the Files kit — one row, one surface, one set of columns (design: unified-files-ui phase 2)
Ten row renderers across three surfaces each re-decided indentation, icon
chrome, type size, selected colour and separators independently, which is why
the same file in /brain and in a conversation looked like two different objects.
This is the one place those decisions now live.
Structure is Google Drive's — tile, name, then right-aligned columns. Identity
is Linear's, read off the two files that already encode it: settings.tsx for the
inset hairline and the single card, field.tsx for the no-class-strings rule.
The columns declare the container width they need and drop themselves; the list
is an @container, not a viewport breakpoint, because the conversation panel is
narrow while the window is wide and a `md:` rule would put four columns in a
380px pane. Widths are fixed so a column's x-position never moves between rows.
`as="link"` exists so a Drive row can be a real anchor with its actions as
siblings rather than buttons nested inside it — a constraint DriveSection states
three times and a test now holds.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 31, 2026, 9:52 PMrelative-time.tsfeat(files): the Files kit — one row, one surface, one set of columns (design: unified-files-ui phase 2)
Ten row renderers across three surfaces each re-decided indentation, icon
chrome, type size, selected colour and separators independently, which is why
the same file in /brain and in a conversation looked like two different objects.
This is the one place those decisions now live.
Structure is Google Drive's — tile, name, then right-aligned columns. Identity
is Linear's, read off the two files that already encode it: settings.tsx for the
inset hairline and the single card, field.tsx for the no-class-strings rule.
The columns declare the container width they need and drop themselves; the list
is an @container, not a viewport breakpoint, because the conversation panel is
narrow while the window is wide and a `md:` rule would put four columns in a
380px pane. Widths are fixed so a column's x-position never moves between rows.
`as="link"` exists so a Drive row can be a real anchor with its actions as
siblings rather than buttons nested inside it — a constraint DriveSection states
three times and a test now holds.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 31, 2026, 9:52 PMworkspace-visibility.tsdocs(brain): why the agent-namespace match is a UUID, checked rather than assumed
Greptile's second pass argued the pattern should not assume a UUID, on the grounds that
`aop_agents.id` is a `text` column. True of the schema; not true of the data. Production
holds 2215 agents and 414 distinct `agent-*` root segments, and none of them is anything but
a UUID or `agent-instructions`.
There is also no second signal available: a namespace root is a plain `folder` row, the same
document type a person's own folder has. So it is a choice between two regexes whose failure
modes are not comparable — too loose loses a folder someone MADE from the tree, the search and
the graph at once; too strict shows one extra row. Kept strict, with the numbers and the
reasoning written down, and the assumption pinned by a test so the day agent ids stop being
UUIDs it goes red there first.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Sep 7, 2026, 6:19 PM