AgendaDocDebuggerTab.tsxfix(agenda): the opening divider is a node now, not a decoration
The rule between the agenda's opening and its first section was a widget
decoration anchored to whatever the first heading happened to be. Pressing
Enter at the start of a heading splits it into an empty paragraph plus the
heading, the decoration re-anchored, and the new line landed ABOVE the rule;
Backspace could never remove it, because there was nothing in the document to
remove.
It is a real `horizontalRule` node now — `---` in the grammar, both directions,
on the client and the server. The PARSER writes it rather than the agent, which
keeps the reason it was derived in the first place (one less token to forget,
misplace or emit twice) while making it something the user owns: the caret sits
beside it, Enter splits below it, Backspace deletes it, and a deletion sticks.
Opt-in per surface, because the conversation agenda shares this grammar and has
no opening half for a seam to separate. The three no-rule cases still fall out
rather than being special-cased. Existing agendas gain it the next time markdown
becomes JSON — the round-trip is the migration, as it is for taskGroupSection.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Sep 2, 2026, 3:13 PMAgentCanvasDebuggerTab.tsxfix(types): close 205 typecheck errors by repairing real client/server drift
apps/mail typechecked against a stale apps/server/dist d.ts (the server's
package.json points "types" at dist), so a chunk of the reported drift was
phantom. Rebuilt it and fixed the four script errors that blocked `tsc -b`
in server, which is what regenerates it.
The rest was genuine contract drift, fixed at the source rather than cast
away — routes that dropped fields their callers still read (agentExecutions,
getUpcomingCalendarEvents' conversationId, createCanvas' description),
schema splits the UI never followed (conversationUsers vs
conversationContacts), and enums that grew server-side but not client-side
(TASK_TYPES, ActionStatus, DateFilterOperator).
Also deletes code that was already dead: an unreferenced sort popover whose
store API is gone, a panel importing a deleted module, the system-skill
metadata UI whose mutation was removed deliberately, and a test asserting a
store method that no longer exists.
apps/server: 4 -> 0. apps/mail: 228 -> 23, all remaining errors being
dependency resolution (zod v3/v4, react-router dev/runtime skew, tiptap
v2 via novel) rather than code.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 2, 2026, 7:45 PMAgentContextDebuggerTab.tsxrefactor: delete viewStack; derive open flags from selectedArtifact (design: url-driven-layout phase 4/6/7)
Removes the viewStack field + pushView/popView/clearViews. isThreadOpen/
isConversationOpen now derive from the active thread's selectedArtifact (set in
setSelectedArtifact); isGlobalCanvasOpen is a standalone flag set directly by the
canvas overlay actions. getActiveView/getNonCanvasActiveView/isViewInStack/
isViewOnTop are kept as flag-derived selectors (precedence canvas > conversation
> thread) so their ~30 consumers are untouched.
Migrated all writers/readers: open*/setIs* actions → setSelectedArtifact;
draft-review + canvas isViewInStack('conversation') → isConversationOpen; meetings
pushView → setIsConversationOpen; viewStack.at(-1) readers → getActiveView();
EmbeddedCedarChat + debugger tabs off viewStack. GlobalCanvas kept (still used).
Divergence: kept the getActiveView/isViewInStack/isViewOnTop read API (flag-derived)
rather than deleting them, to minimize blast radius. Escape stays on the per-view
handlers (now = setSelectedArtifact(null)); Escape=navigate(-1) deferred.
Tests: rewrote uxSlice viewStack tests to the derived selectors; deleted
view-stack.test.ts. RUNTIME-VERIFY in-app: draft review, canvas layering, Escape,
hotkey scopes.
Co-Authored-By: Claude Opus 4.8 (1M context) <<email>>Jul 13, 2026, 9:36 PMAgentExecutionsDebuggerTab.tsxfeat: the trace viewer — an Axiom-style waterfall over agent runs (design: curated-agenda phase 7)
A run reads like a distributed trace: an execution is a span, a dispatched
subagent is a child span, a tool call is a leaf span, all on one time axis
scaled to the root's window so overlapping siblings read as genuinely parallel
and a serialized fan-out reads as a staircase. Route at
/settings/agentExecutions/:runId, reachable from every execution list row and
from a paste-a-run-id box.
Zero-duration tool spans are drawn honestly. agent_tool_calls records no
completion timestamp, so every tool span has durationMs 0; rather than floor it
into a bar that implies a duration nobody measured, it renders as a point marker
with the duration column showing an em dash and the reason stated on hover. The
minimum-bar-width floor still exists, but for genuinely short executions, which
is the real sub-pixel case.
Gap indicators mark dead time inside a parent not covered by any child — usually
the model thinking, and where a run's latency actually goes. Tool-call points
cover nothing, so they cannot fake a gap away.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 9, 2026, 5:21 PMAOPDebuggerTab.tsxrefactor(debugger): suffix all debugger tabs with DebuggerTab
Rename every tab in the debugger module from XxxTab to XxxDebuggerTab so
they no longer collide by name with real feature tabs (e.g. the
conversations timeline TimelineTab).
Co-Authored-By: Claude Opus 4.8 (1M context) <<email>>Jun 15, 2026, 1:02 PMCalendarDebuggerTab.tsxMerge origin/staging into feat/task-groups
Reconciles two divergent refactors of the agent subsystem. Per decision,
adopted staging's subagent-document architecture and removed the
agent state-overview feature entirely (on top of staging keeping it).
Key resolutions:
- Agent subsystem -> staging (subagent documents; legacy aop_agents CRUD +
agentConfig dropped); state-overview (agentConversationStates, stateOverviewConfig,
listStatesForConversation, CRM state SQL + post-processing) excised throughout.
- Preserved HEAD-only features that a wholesale take-staging would have dropped:
task-groups schema, strategic-overview config, crm/conversations fetchStageChangeHistory,
the iMessage connections tab, and the agent-doc-type model/fillInstructions fields.
- Deleted 6 orphaned HEAD-only files for the legacy Strategist-via-aop_agents
seeding path (superseded by staging's doc-based seeding; unwired).
- chat.ts: unioned both branches' new tRPC procedures (context items + pending mutations).
- chat-agent: kept HEAD's manage-context migration inside staging's helper refactor.
- Migrations: unioned the 0048/0049 journal collision with stable tags.
- Frontend: WhatsApp/Unipile onboarding+connections from staging; iMessage tab re-added.
Verified: server 538 type errors vs 539 pre-merge baseline (zero resolution-attributable
regressions); frontend touched-file errors all confirmed pre-existing via baseline diff.
Co-Authored-By: Claude Opus 4.8 (1M context) <<email>>Jul 26, 2026, 12:38 PMChatThreadsDebuggerTab.tsxfix(ci): green the PR — test drift, a nav-name collision, and lint
Repairs every failing check on the branch:
- threadSlice mail nav regression: the new chat-thread nav in messagesSlice
(navigateToNext/PreviousThread) shadowed the mail-thread nav of the same
name and broke inbox keyboard navigation. Renamed the chat ones to
navigateToNext/PreviousChatThread (only their own test referenced them).
- createTaskTool tests: stub the new routeTaskToGroup service (its DB/LLM
calls aren't part of these unit tests).
- channel-deal-binding test: add the new risk/conversation_index/overview_items
columns to the hand-built crm_conversations table.
- approval-flag-guard allowlist: setChatContextTool → resolveAndAttachTool
rename + new manageContextTool (both stream chat-context, not approvals).
- DisplayArtifactPanel test: default panel is Top Deals now, not agenda;
mock canvas.ensureTopDeals + CardListCanvasView.
- shellRoutes / uxSlice tests: match intentional source changes (inbox+tasks
shell segments; cut shortcut-mastery tracking).
- oxlint --deny-warnings: delete unused imports/vars, drop useless spread
fallbacks, fix unsafe optional chaining; wire InboxRow's displayName.
Co-Authored-By: Claude Opus 4.8 (1M context) <<email>>Jul 28, 2026, 11:38 PMConversationDocsDebuggerTab.tsxfeat: merge DocDebug into Docs tab + add Chat Threads slice debugger
Fold the Y.js save-log timeline into each document's expanded row as a
"saves" view so content and save history live together, and drop the
standalone DocDebug tab. Add a Chat Threads tab that inspects the
cedar-os threadMap / mainThreadId / activeThreadId slice.
Co-Authored-By: Claude Opus 4.8 (1M context) <<email>>Jul 12, 2026, 10:25 PMConversationsDebuggerTab.tsxfix(types): close 205 typecheck errors by repairing real client/server drift
apps/mail typechecked against a stale apps/server/dist d.ts (the server's
package.json points "types" at dist), so a chunk of the reported drift was
phantom. Rebuilt it and fixed the four script errors that blocked `tsc -b`
in server, which is what regenerates it.
The rest was genuine contract drift, fixed at the source rather than cast
away — routes that dropped fields their callers still read (agentExecutions,
getUpcomingCalendarEvents' conversationId, createCanvas' description),
schema splits the UI never followed (conversationUsers vs
conversationContacts), and enums that grew server-side but not client-side
(TASK_TYPES, ActionStatus, DateFilterOperator).
Also deletes code that was already dead: an unreferenced sort popover whose
store API is gone, a panel importing a deleted module, the system-skill
metadata UI whose mutation was removed deliberately, and a test asserting a
store method that no longer exists.
apps/server: 4 -> 0. apps/mail: 228 -> 23, all remaining errors being
dependency resolution (zod v3/v4, react-router dev/runtime skew, tiptap
v2 via novel) rather than code.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 2, 2026, 7:45 PMCurrentThreadDebuggerTab.tsxfix(types): close 205 typecheck errors by repairing real client/server drift
apps/mail typechecked against a stale apps/server/dist d.ts (the server's
package.json points "types" at dist), so a chunk of the reported drift was
phantom. Rebuilt it and fixed the four script errors that blocked `tsc -b`
in server, which is what regenerates it.
The rest was genuine contract drift, fixed at the source rather than cast
away — routes that dropped fields their callers still read (agentExecutions,
getUpcomingCalendarEvents' conversationId, createCanvas' description),
schema splits the UI never followed (conversationUsers vs
conversationContacts), and enums that grew server-side but not client-side
(TASK_TYPES, ActionStatus, DateFilterOperator).
Also deletes code that was already dead: an unreferenced sort popover whose
store API is gone, a panel importing a deleted module, the system-skill
metadata UI whose mutation was removed deliberately, and a test asserting a
store method that no longer exists.
apps/server: 4 -> 0. apps/mail: 228 -> 23, all remaining errors being
dependency resolution (zod v3/v4, react-router dev/runtime skew, tiptap
v2 via novel) rather than code.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 2, 2026, 7:45 PMFreezesDebuggerTab.tsxrefactor(debugger): suffix all debugger tabs with DebuggerTab
Rename every tab in the debugger module from XxxTab to XxxDebuggerTab so
they no longer collide by name with real feature tabs (e.g. the
conversations timeline TimelineTab).
Co-Authored-By: Claude Opus 4.8 (1M context) <<email>>Jun 15, 2026, 1:02 PMInboxDebuggerTab.tsxfeat(inbox): compose the unified feed in the client (design: inbox-triage phase 8)
The unibox is now assembled in the browser from one query per channel instead of
one server-merged page, so a `mail.listThreads` refetch updates its email rows
without re-fetching Slack, LinkedIn and WhatsApp alongside them.
- inboxSlice holds per-channel `ChannelFeedSlice`s; `selectMergedFeed` runs the
shared `mergeChannelFeeds` watermark. `setChannelFeeds` writes the whole map at
ONE commit point: `setInboxFeed` reconciled `focusedIndex`, and four queries
settling independently would have jittered the keyboard cursor once per settle.
Lookup selectors keep every loaded row, so a deep link below the watermark still
resolves.
- useInboxItems issues four gated infinite queries and keeps its public shape.
`fetchNextPage` pages ONLY the gating channels — fetching any other loads rows
that stay held. Participation comes from `inbox.getFeedScope`, already resolved
server-side; the client re-derives nothing.
- `linkedOnly` reaches `listChannelItems` so the dedicated Slack/WhatsApp tabs keep
showing unlinked containers. Hard-coding the unified feed's semantic had emptied
them.
Verified headlessly as the operator against this checkout (:8790) with
`mail-admin compose-feed`, over the plain unibox, a mail-only split and a
CRM-filtered inbox: no server row lost, correct ordering, and the CRM rule
narrowing every channel without ever reaching the client.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 31, 2026, 4:02 PMJsonTreeView.tsxfix: email participants, and better debugger displayApr 22, 2026, 6:25 PMMailDebuggerPanel.tsxfeat(inbox): compose the unified feed in the client (design: inbox-triage phase 8)
The unibox is now assembled in the browser from one query per channel instead of
one server-merged page, so a `mail.listThreads` refetch updates its email rows
without re-fetching Slack, LinkedIn and WhatsApp alongside them.
- inboxSlice holds per-channel `ChannelFeedSlice`s; `selectMergedFeed` runs the
shared `mergeChannelFeeds` watermark. `setChannelFeeds` writes the whole map at
ONE commit point: `setInboxFeed` reconciled `focusedIndex`, and four queries
settling independently would have jittered the keyboard cursor once per settle.
Lookup selectors keep every loaded row, so a deep link below the watermark still
resolves.
- useInboxItems issues four gated infinite queries and keeps its public shape.
`fetchNextPage` pages ONLY the gating channels — fetching any other loads rows
that stay held. Participation comes from `inbox.getFeedScope`, already resolved
server-side; the client re-derives nothing.
- `linkedOnly` reaches `listChannelItems` so the dedicated Slack/WhatsApp tabs keep
showing unlinked containers. Hard-coding the unified feed's semantic had emptied
them.
Verified headlessly as the operator against this checkout (:8790) with
`mail-admin compose-feed`, over the plain unibox, a mail-only split and a
CRM-filtered inbox: no server row lost, correct ordering, and the CRM rule
narrowing every channel without ever reaching the client.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 31, 2026, 4:02 PMMeetingsDebuggerTab.tsxrefactor(debugger): suffix all debugger tabs with DebuggerTab
Rename every tab in the debugger module from XxxTab to XxxDebuggerTab so
they no longer collide by name with real feature tabs (e.g. the
conversations timeline TimelineTab).
Co-Authored-By: Claude Opus 4.8 (1M context) <<email>>Jun 15, 2026, 1:02 PMTestDebuggerTab.tsxfix(types): close 205 typecheck errors by repairing real client/server drift
apps/mail typechecked against a stale apps/server/dist d.ts (the server's
package.json points "types" at dist), so a chunk of the reported drift was
phantom. Rebuilt it and fixed the four script errors that blocked `tsc -b`
in server, which is what regenerates it.
The rest was genuine contract drift, fixed at the source rather than cast
away — routes that dropped fields their callers still read (agentExecutions,
getUpcomingCalendarEvents' conversationId, createCanvas' description),
schema splits the UI never followed (conversationUsers vs
conversationContacts), and enums that grew server-side but not client-side
(TASK_TYPES, ActionStatus, DateFilterOperator).
Also deletes code that was already dead: an unreferenced sort popover whose
store API is gone, a panel importing a deleted module, the system-skill
metadata UI whose mutation was removed deliberately, and a test asserting a
store method that no longer exists.
apps/server: 4 -> 0. apps/mail: 228 -> 23, all remaining errors being
dependency resolution (zod v3/v4, react-router dev/runtime skew, tiptap
v2 via novel) rather than code.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 2, 2026, 7:45 PMThreadsDebuggerTab.tsxrefactor(debugger): suffix all debugger tabs with DebuggerTab
Rename every tab in the debugger module from XxxTab to XxxDebuggerTab so
they no longer collide by name with real feature tabs (e.g. the
conversations timeline TimelineTab).
Co-Authored-By: Claude Opus 4.8 (1M context) <<email>>Jun 15, 2026, 1:02 PMTimelineDebuggerTab.tsxrefactor(debugger): suffix all debugger tabs with DebuggerTab
Rename every tab in the debugger module from XxxTab to XxxDebuggerTab so
they no longer collide by name with real feature tabs (e.g. the
conversations timeline TimelineTab).
Co-Authored-By: Claude Opus 4.8 (1M context) <<email>>Jun 15, 2026, 1:02 PMUserTasksDebuggerTab.tsxrefactor(tasks): retire task_channel onto task_output.kind (design: task-cleanup phase 5)
`multi-action` was never a channel. It meant "this task has several possible
actions", which is not a place a message is sent — and TASK_OUTPUT_KINDS omits
it deliberately for that reason. Only two sites wrote it, both CRM approvals
that already pass an explicit task_output, so the value was legacy filler.
Removing it forced the question the column had been dodging: task_channel was
NOT NULL DEFAULT 'email', so those rows had to become either a lie or nothing. A
CRM approval sends nothing. Migration 0059 makes the column nullable, drops the
default, narrows the CHECK to real channels, and nulls the 7,200 multi-action
rows. Relaxing the constraint is itself a step toward the drop — constraints
come off before columns do, so a newer server can stop writing it first.
Moving the readers is NOT a rename. The two axes disagree on ~12,000 rows and
the output axis is the correct one, so each site is a decision: does it want the
declared channel, or what the task actually produces? It is the artifact, and
that changes which rows match. On open tasks, 49 stop matching the email filter
and 9 start — a calendar task or a pure reminder no longer auto-completes
because an email thread synced, and a task whose channel says slack but whose
payload holds an email draft now does.
Two traps worth recording:
- The migration ordered `UPDATE ... SET NULL` before `DROP NOT NULL` and was
rejected by the constraint it had not yet dropped.
- createUserTaskWithExecutionUpdate had `taskChannel || 'email'`. Left alone it
would have silently converted every "no channel" back into "email" on write,
undoing the migration for new rows while backfilled ones stayed correct.
Two latent bugs surfaced by the sweep:
- The crm/conversations.ts task aggregates omitted task_output entirely despite
HydratedConversation.userTasks being typed as the full row, so nothing
downstream could read the output axis off that path.
- The task board's `keyOf` defaulted a null output to 'email', so an undecided
task would have vanished from the board when grouping by channel. There is now
an explicit Undecided bucket.
Frontend gets a shared task-output module mirroring the server kinds; the
Multi-action column, badge and icon are replaced by real output kinds.
Co-Authored-By: Claude Opus 5 <<email>>Aug 15, 2026, 6:28 PMUXDebuggerTab.tsxrefactor: delete viewStack; derive open flags from selectedArtifact (design: url-driven-layout phase 4/6/7)
Removes the viewStack field + pushView/popView/clearViews. isThreadOpen/
isConversationOpen now derive from the active thread's selectedArtifact (set in
setSelectedArtifact); isGlobalCanvasOpen is a standalone flag set directly by the
canvas overlay actions. getActiveView/getNonCanvasActiveView/isViewInStack/
isViewOnTop are kept as flag-derived selectors (precedence canvas > conversation
> thread) so their ~30 consumers are untouched.
Migrated all writers/readers: open*/setIs* actions → setSelectedArtifact;
draft-review + canvas isViewInStack('conversation') → isConversationOpen; meetings
pushView → setIsConversationOpen; viewStack.at(-1) readers → getActiveView();
EmbeddedCedarChat + debugger tabs off viewStack. GlobalCanvas kept (still used).
Divergence: kept the getActiveView/isViewInStack/isViewOnTop read API (flag-derived)
rather than deleting them, to minimize blast radius. Escape stays on the per-view
handlers (now = setSelectedArtifact(null)); Escape=navigate(-1) deferred.
Tests: rewrote uxSlice viewStack tests to the derived selectors; deleted
view-stack.test.ts. RUNTIME-VERIFY in-app: draft review, canvas layering, Escape,
hotkey scopes.
Co-Authored-By: Claude Opus 4.8 (1M context) <<email>>Jul 13, 2026, 9:36 PM