🤖 feat: Instructions tab in right sidebar#3262
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 85d041ff33
ℹ️ 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".
Adds an Instructions tab that shows every AGENTS.md / CLAUDE.md / AGENTS.local.md loaded into the system prompt, grouped by scope, with per-file token counts and click-to-expand previews. Internal restructure: the instruction context is now a typed InstructionFile/InstructionSet/InstructionSources tree shared between buildSystemMessage and the IPC payload, so the panel cannot drift from what the agent actually sees.
…ault layout
Adds the Instructions tab to the default right-sidebar layout (auto-injected
into existing persisted layouts via `ensureDefaultLayoutTabs` migration so
existing users see it after upgrade) and consolidates the per-tab bookkeeping
into a single declarative registry.
Adding a non-terminal tab is now a one-line entry in
`src/browser/features/RightSidebar/Tabs/tabRegistry.tsx`:
instructions: {
name: "Instructions",
contentClassName: "overflow-hidden p-0",
inDefaultLayout: true,
defaultOrder: 30,
Label: ({ workspaceId }) => <InstructionsTabLabel />,
renderPanel: (ctx) => <InstructionsTab workspaceId={ctx.workspaceId} />,
},
That single registration now drives:
- The static tab-id union (`BaseTabType` derived from `keyof typeof TAB_REGISTRY`)
- The default layout for new workspaces (via `inDefaultLayout` + `defaultOrder`)
- The migration that auto-adds new default tabs to existing persisted layouts
- The label and panel rendering inside `RightSidebar.tsx`
- The Add-Tool command-palette picker
- The generic `Hide/Show <Name>` toggle commands (one factory, no per-tab CommandIds)
Removed scattered ledger entries:
- `RIGHT_SIDEBAR_TABS` array in `types/rightSidebar.ts` (now derived)
- `TAB_CONFIGS` Record key union & `getTabConfig` literal chain
- Per-tab `else if` label branches in `RightSidebar.tsx`
- Per-tab `panelId` / `tabId` constants
- Per-tab panel `activeTab === "..."` blocks
- Hardcoded `["costs", "review"]` default-tab list
- Bespoke `navToggleOutput` / `navToggleInstructions` CommandIds + handlers
- Hardcoded Add-Tool option list
…s expand layout Two fixes against the new Instructions tab + the long-standing prompt builder: 1. Sub-project workspaces missed the parent project's AGENTS.md. The prompt builder and the Instructions panel both received the workspace *execution* path (root + subProjectRelativePath) and treated it as the workspace root, joining the sub-project segment a second time. The result: the parent AGENTS.md was never read, and the sub-project AGENTS.md ended up labeled WORKSPACE. Fix: split out resolveWorkspaceRootPath in runtimeHelpers and have loadInstructionSources / readToolInstructions / instructionsService anchor at the workspace root explicitly. 2. Instructions FileRow expansion shifted the preview horizontally because the collapsed preview lived inside the indented column inside the <button>, while the expanded <pre> was a row-level sibling at px-3. Fix: move the preview/expanded body into a single sibling container with pl-[26px] and matching px-2 py-1 on both <pre>s, so the text starts at the same x/y position regardless of state. The body is now outside the <button>, so users can scroll/select long files without collapsing the row. --- _Generated with `mux` • Model: `anthropic:claude-opus-4-7` • Thinking: `high` • Cost: `$31.21`_ <!-- mux-attribution: model=anthropic:claude-opus-4-7 thinking=high costs=31.21 -->
|
@codex review Rebased onto latest main and re-ran local validation:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d881d1c943
ℹ️ 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".
- Split lightweight right-sidebar tab metadata into tabConfig.ts so layout/types/commands can read default-layout policy without importing React panel renderers. - Keep Instructions in the default-layout config and persist parsed layout migrations back to storage so existing workspaces retain the injected default tab across reloads. - Add regression coverage that the default layout and RightSidebar UI include Instructions by default. - Preserve AGENTS.local.md content when the tracked base instruction file strips to empty, addressing the Codex review thread. - Avoid eager noVNC imports in the VS Code extension bundle by keeping non-UI helpers off the React tab registry. Validation: - make static-check - make vscode-ext - bun test src/node/utils/main/instructionFiles.test.ts src/browser/utils/rightSidebarLayout.test.ts src/node/services/systemMessage.test.ts src/node/runtime/runtimeHelpers.test.ts ./tests/ui/layout/rightSidebar.test.ts --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$49.18`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=49.18 -->
|
@codex review Updated after the rebase and feedback:
Local validation passing:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 00a958e353
ℹ️ 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".
|
@codex review Updated per latest feedback:
Local validation passing:
|
- Add a per-workspace additional system context scratchpad stored in the workspace session directory. - Inject scratchpad content into the existing additional-instructions system prompt path for every send, ahead of request-specific additional instructions. - Show the auto-saving, auto-growing scratchpad at the top of the Instructions tab. - Show a collapsed chat decoration when scratchpad content exists; expanding it opens the same editable scratchpad. - Copy the scratchpad file when a workspace is forked so forks inherit the extra context. - Remove Hide/Show commands for auto-restored default tabs, keeping those commands only for optional tabs. Validation: - make static-check - make vscode-ext - bun test src/node/services/additionalSystemContext.test.ts src/node/utils/main/instructionFiles.test.ts src/browser/utils/rightSidebarLayout.test.ts src/node/services/systemMessage.test.ts src/node/runtime/runtimeHelpers.test.ts ./tests/ui/layout/rightSidebar.test.ts --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$62.84`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=62.84 -->
|
@codex review Re-pushed after resolving all existing Codex threads so checks restart on the latest SHA. Local validation remains green:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 07501b1b59
ℹ️ 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".
Add the new workspace additional-system-context routes to the Storybook ORPC mock so stories that mount ChatPane/Instructions can fetch and edit the scratchpad. Validation: - make static-check - make vscode-ext - bun test src/node/services/additionalSystemContext.test.ts src/node/utils/main/instructionFiles.test.ts src/browser/utils/rightSidebarLayout.test.ts --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$62.84`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=62.84 -->
|
@codex review Pushed a Storybook mock fix for the new additional-system-context workspace routes. Local validation remains green:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d9c68b88e1
ℹ️ 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".
- Mirror scratchpad edits into a renderer-side workspace snapshot immediately, so a message sent right after typing includes the latest visible context even if the disk write is still in flight. - Merge that live snapshot into send options; backend merge logic de-duplicates it against the durable scratchpad file when both are present. - Filter default-layout and feature-flagged tabs out of generic hide/add palette entries so disabled/default-restored tabs are not advertised as user-toggleable. Validation: - make static-check - make vscode-ext - bun test src/node/services/additionalSystemContext.test.ts src/node/utils/main/instructionFiles.test.ts src/browser/utils/rightSidebarLayout.test.ts --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$62.84`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=62.84 -->
|
@codex review Addressed the latest review comments:
Local validation passing:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8b2b643c7b
ℹ️ 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".
Guard scratchpad save completions with a per-workspace generation so stale in-flight writes from a previous workspace cannot clear or flush pending content for the current workspace after navigation. Validation: - make static-check - make vscode-ext - bun test src/node/services/additionalSystemContext.test.ts --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$62.84`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=62.84 -->
|
@codex review Addressed the stale scratchpad save race: save completions are now guarded by a per-workspace generation so old in-flight writes cannot flush or clear pending content for a newly selected workspace. Local validation passing:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0e9b898dea
ℹ️ 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".
Thread the renderer's live additional-system-context snapshot through send options separately from request-specific additional instructions. The backend uses that live value when present instead of reading the durable file, so immediate sends cannot prepend stale on-disk scratchpad content while a save is still in flight. Validation: - make static-check - make vscode-ext - bun test src/node/services/additionalSystemContext.test.ts --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$62.84`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=62.84 -->
|
@codex review Addressed stale durable scratchpad prepending by threading the renderer's live scratchpad snapshot through a separate send option. When present, backend uses the live value instead of reading the file, so a just-edited scratchpad cannot be combined with stale on-disk content. Local validation passing:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f42cdaa26a
ℹ️ 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".
Move scratchpad save coalescing into the shared renderer store so pending edits remain queued per workspace even if the editor unmounts or the user switches workspaces before an earlier save completes. Validation: - make static-check - make vscode-ext - bun test src/node/services/additionalSystemContext.test.ts --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$62.84`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=62.84 -->
|
@codex review Moved scratchpad save coalescing into the shared renderer store so pending edits remain queued per workspace even if the editor unmounts or the selected workspace changes before an earlier save completes. Local validation passing:
|
Track per-workspace scratchpad hydration/version in the renderer store. Chat sends only include the live scratchpad override after the renderer has loaded or edited it, so startup sends still fall back to the durable file; concurrent loaders also skip stale responses if another editor has already updated the shared snapshot. Validation: - make static-check - make vscode-ext - bun test src/node/services/additionalSystemContext.test.ts --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$62.84`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=62.84 -->
|
@codex review Addressed the hydration/version issues:
Local validation passing:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 02ad1088a6
ℹ️ 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".
When a newer scratchpad edit is queued while an older save is still in flight, ignore the older save response instead of writing it back into the shared live snapshot. The pending newer save will flush next and remains the value ChatInput sends. Validation: - make static-check - make vscode-ext - bun test src/node/services/additionalSystemContext.test.ts --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$62.84`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=62.84 -->
|
@codex review Addressed the stale save response issue: older save responses are ignored when a newer scratchpad edit is already pending, so the shared live snapshot remains the newest typed value until the pending save flushes. Local validation passing:
|
|
Codex Review: Didn't find any major issues. Another round soon, please! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Account for the default Instructions tab being restored by the right-sidebar layout migration when terminal tabs are stripped during archive cleanup. Validation: - make static-check - bun test src/browser/contexts/WorkspaceContext.test.tsx -t 'strips terminal tabs' --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$62.84`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=62.84 -->
|
@codex review Pushed a test-only update for the default Instructions tab migration expectation after archive cleanup. Local validation:
|
|
Codex Review: Didn't find any major issues. Another round soon, please! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Update the split-layout E2E expectation for the default Instructions tab injected into the first tabset by the right-sidebar layout migration. Validation: - make static-check --- _Generated with `mux` • Model: `openai:gpt-5.5` • Thinking: `xhigh` • Cost: `$62.84`_ <!-- mux-attribution: model=openai:gpt-5.5 thinking=xhigh costs=62.84 -->
|
@codex review Pushed an E2E expectation update for the default Instructions tab in split sidebar layouts. Local validation:
|
|
Codex Review: Didn't find any major issues. Another round soon, please! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
CI update: all GitHub Actions jobs and Codex are passing on the latest push. The only remaining pending checks are Chromatic |
Replace the BookOpen icon on the Instructions tab strip with a count badge to match the Stats and Review tabs. The badge picks up the accent color when the per-workspace scratchpad has any user content, giving a quick visual cue that this workspace is sending additional system context to the agent. A small workspaceInstructionsStore caches the file count per workspace so the label can render immediately once data is available, and triggers a one-shot getInstructions fetch on first mount when the panel itself isn't rendered yet (e.g. another tab is active in the same tabset). --- _Generated with \`mux\` • Model: \`anthropic:claude-opus-4-7\` • Thinking: \`high\` • Cost: \`$237.75\`_ <!-- mux-attribution: model=anthropic:claude-opus-4-7 thinking=high costs=237.75 -->
Summary
Adds an Instructions tab to the right sidebar that lists every instruction file (AGENTS.md, CLAUDE.md, AGENTS.local.md, …) loaded into the workspace's system prompt, grouped by scope, with per-file approximate token counts and click-to-expand previews. The panel scales gracefully when there are many files: each row is a one-liner with a 3-line preview, and the full content is rendered only on demand. The tab ships in the default layout for new workspaces and is auto-injected into existing persisted layouts on first load so upgrading users see it immediately.
This PR also restructures internals on two axes:
InstructionFile/InstructionSet/InstructionSourcestree shared betweenbuildSystemMessageand the IPC payload — the panel cannot drift from what the agent actually sees.Background
Until now, the only signal that AGENTS.md/CLAUDE.md/AGENTS.local.md was actually being loaded was indirect (system-prompt token totals or behavioral changes). Users had no way to inspect which instruction files the agent was seeing for a given workspace, where they came from, or how much of the context budget they were consuming.
Internally, instruction context flowed through the codebase as bare strings, and adding a new sidebar tab required edits in 8+ places (tab-id list,
TAB_CONFIGSrecord +getTabConfigliteral chain, label switch, panel-id constants, panel render switch, default-layout list, command-palette picker, per-tab toggle CommandIds + handlers). Both made it easy for the panel and the prompt builder to drift, and discouraged adding tabs.Implementation
Typed instruction context (single source of truth)
New Zod schemas in
src/common/orpc/schemas/instructions.ts, with TS typesz.infer'd insrc/common/types/instructions.ts:buildSystemMessageand the newworkspace.getInstructionsIPC route consume the same types — the panel can never drift from what the agent actually sees.Right-sidebar tab registry (single source of truth)
src/browser/features/RightSidebar/Tabs/tabRegistry.tsxnow declares every static tab in one object:That single registration drives:
BaseTabTypeunion (derived fromkeyof typeof TAB_REGISTRY).getDefaultLayoutTabIds()filters byinDefaultLayout).ensureDefaultLayoutTabsmigration inparseRightSidebarLayoutStatethat auto-injects missing default tabs into existing persisted layouts (so users see Instructions after upgrade without manual setup).RightSidebar.tsx(oneRegistryTabPanelcomponent replaces 6 per-tabactiveTab === "…"blocks).getOrderedBaseTabIds()instead of a hardcoded list).Hide/Show <Name>toggle command per tab (buildToggleTabCommand) that replaces hand-rollednavToggleOutput/navToggleInstructionsentries.Terminal tabs intentionally remain outside the registry — they're multi-instance (
terminal:<sessionId>), keep-alive, and need session-aware wiring that doesn't fit the static "one panel per id" shape.Backend (instruction loader)
src/node/utils/main/instructionFiles.ts—readInstructionSet/readInstructionSetFromRuntime/gatherInstructionSetsnow return structuredInstructionSetobjects with per-filepath,bytes,isLocal,scope,projectName.combinedContentis still produced (so prompt output is byte-identical) but each file is also addressable on its own.src/node/services/systemMessage.ts— formerly-privatereadInstructionSourcesis now exported asloadInstructionSourcesreturningInstructionSources.buildSystemMessagederives the strings it needs from the structured tree, leaving the prompt body unchanged.src/node/services/instructionsService.ts(new) — composesloadInstructionSources+ per-filetokenizerService.countTokens(LRU-cached, model-aware). Tokenizer failures degrade gracefully totokens: null.workspace.getInstructionsroute; service wired intoORPCContextandServiceContainer.Frontend (panel)
src/browser/components/InstructionsTab/InstructionsTab.tsx— fetches viaapi.workspace.getInstructionsand renders rows grouped by scope (Global / Workspace / Sub-project / Projects). Each row shows filename, scope badge, full path, byte size,~N tokensbadge, and a 3-line preview. Click to expand the full content inline. A refresh button re-reads from disk.Validation
make static-check— clean (eslint, tsc, prettier, shellcheck, hadolint, doc-link checks all pass).bun test src/browser/features/RightSidebar/ src/browser/utils/— 1138 / 1138 pass.bun test src/node/services/systemMessage.test.ts src/node/utils/main/instructionFiles.test.ts— 29 / 29 pass.parseRightSidebarLayoutState auto-adds missing default-layout tabs from the registrycovers the upgrade migration.inDefaultLayoutregistry additions automatically.Risks
This change touches:
buildSystemMessagetest matrix (model-section extraction, multi-project layering, agent-prompt scoping, sub-project handling) still passes — the prompt output is byte-identical because the samecombinedContentstrings flow into it.nav:toggle-tab:<id>id instead of the previous hand-rolled CommandIds; user keybindings configured against those legacy ids would need to be re-bound, but the default keybindings continue to work.Worst case if the structured loader regresses: the Instructions tab shows stale or missing files. The system prompt itself is byte-identical to
mainbecause the samecombinedContentstrings flow into it.Generated with
mux• Model:anthropic:claude-opus-4-7• Thinking:high• Cost:$17.30