Chat as the product surface: redesign + Capability Bus + local Coding Agent - #39
Open
monatruong wants to merge 146 commits into
Open
Chat as the product surface: redesign + Capability Bus + local Coding Agent#39monatruong wants to merge 146 commits into
monatruong wants to merge 146 commits into
Conversation
Centered hero + elevated composer + Ask/Plan/Build modes; view refactor + restyle only, no backend/fake-affordance changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5 TDD tasks: ChatMode + ChatComposer + ChatEmptyState + wire-in (delete old input/greeting/lets-build) + bubble restyle & light/dark verify. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-build Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-assert keyboard focus at the end of send() so the docked composer's TextField (which SwiftUI rebuilds when chatMessages flips empty→non-empty) doesn't drop focus after the first message. Also give the composer's outer container the theme's floatingShadow so it reads as elevated per spec §2, instead of a flat bordered card. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch the + quick-actions and mode menus from .borderlessButton (which draws a system disclosure chevron .menuIndicator(.hidden) doesn't suppress on macOS) to .menuStyle(.button)+.buttonStyle(.plain), leaving only the mode control's own chevron.down after the label. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ns, icon pills - CompanionOrb: reusable luminous gradient sphere (angular accent gradient + glossy highlight + depth shading), used as hero focal, message avatar, and thinking indicator. Glow gated on accessibilityReduceTransparency. - QuickAction: small Identifiable model (title + systemImage) so quick-action pills/menu carry an icon without breaking localization. - ChatComposer: quickActionsMenu items now render as Label(title, systemImage); sendButton fills a purple→pink LinearGradient + accent glow when canSend; the composer's outer container gets a subtle ambient accent glow layered under the existing floatingShadow. - ChatEmptyState: CompanionOrb(78) now anchors the hero above the greeting (replacing the old greeting-only radial glow); pills show an icon + title. - CopilotChatView: quickActions rebuilt as [QuickAction] (checklist/map/ square.grid.2x2/doc.text); typingRow replaced with an orb + "Thinking…" row; producingRow gets a leading orb; CopilotBubble's textBubble now branches — the `me` bubble is untouched, the companion bubble gains a 28pt orb avatar and a Copy + Regenerate action row (Regenerate is a pure client-side resend of the last `me` message through the existing sendChat path, no backend change). Verified: xcodebuild build (CODE_SIGNING_ALLOWED=NO) → BUILD SUCCEEDED. Full test suite: 303 tests pass; the 2 known CompanyStoreScaffordOnboardingTests Firebase-init flakes crash-and-retry as expected (no new regressions). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make chat the full-width default page; retire Overview; split Roadmap/Second Brain into two pages; keep onboarding + top-bar look. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nd Brain tabs Codepet.select(.chat) is now the store's default/reset view and the wordmark's Home action; AppShellView drops the 50% copilot side panel and floating chat toggle so `content` fills the shell full-width. AppView retires `.overview` and gains `.chat`/`.secondBrain`, with Roadmap and Second Brain promoted to their own top-bar tabs (extracted views from Task IA-1). OverviewView.swift deleted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CopilotChatView now renders full-width as the app's main page, so message
bubbles and the composer were stretching edge-to-edge. Wrap the message
list VStack and the docked composer each in an HStack{Spacer;content
.frame(maxWidth:720);Spacer} so they read as a centered ~720pt column
(matching Axora/LIX/DeepThink-style reference layouts) while the full
ScrollView/background stays full-width. Per-message me/companion alignment
is unchanged inside the column. Bumped ChatEmptyState's composer cap from
680 to 720 to match the docked composer width for a consistent column edge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ick-action cards Chat v3: time-of-day + founder-name greeting with a purple-gradient second line, a soft purple brand wash behind the empty state, a purple-forward CompanionOrb, a purple-gradient composer border, and quick-action cards (icon + title + muted helper detail + purple accent bar) replacing the old pills. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Top bar -> left SidebarView (brand, New chat, Recent/History, Workspace nav, Upgrade/account); remove the Your-team chat header. 3 build-green tasks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sidebar (SB-1/SB-2) now owns nav, brand, and chat history (Recent), so
CopilotChatView's redundant "Your team / guiding · {company}" header
and its History toggle -> ThreadListView switcher are dead chrome.
Removes header, showHistory state, and the now-unreferenced
ThreadListView struct; body simplifies to empty-state vs
messageList+composer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Full status, commit map, resume instructions, gotchas, and the human-GUI punch-list so a fresh session can pick up cleanly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Post-restructure cleanup on files that outran their own docs/dead code: - AppShellView: drop the now-unused `accent` computed prop (and the `appState` EnvironmentObject only it read) — the companion-accented Copilot side panel it fed is gone (chat is the full-width content). Refresh the type doc to describe the sidebar+content shell it actually is, not the old "sidebar + placeholder Copilot panel". - SidebarView: the "NOT WIRED YET / SB-2 will own the binding" header and `collapsed` doc are false — the view IS wired in AppShellView, which owns `sidebarCollapsed`. Rewrite both to match reality. - SidebarView: the thread-row ellipsis Menu still used .menuStyle(.borderlessButton), which paints a stray system disclosure chevron next to the ellipsis on macOS — the exact bug the composer menus fixed in df83ef8. Switch to .button + .plain + .menuIndicator(.hidden). No behavior change. xcodebuild build (CODE_SIGNING_ALLOWED=NO) SUCCEEDED; full suite 303 tests / 0 failures (the overall TEST FAILED is the known CompanyStoreScaffordOnboarding Firebase-init flake, fixed on PR #40). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contain the active-conversation composer in the 720 column (fix the edge-to-edge sprawl), share one ambient purple backdrop behind both the empty and active states, and drop the full-width divider. Structure- preserving containment/cohesion pass — no composer/logic rewrite. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two tasks: (1) extract ChatBackdrop + share it behind empty+active, (2) contain the docked composer in the 720 column and drop the divider. Build-gate test cycle (no new pure logic); suite stays 303/0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract ChatEmptyState.brandWash into a reusable ChatBackdrop and hang it once behind CopilotChatView so the empty hero and the active conversation read as one continuous purple-washed surface. ChatEmptyState drops its private brandWash (and the reduceTransparency env only it used); no visual change to the empty state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The active-conversation composer rendered full-width (composerView.padding (10)); wrap it in the same Spacer/maxWidth:720/Spacer column the message list uses so its edges track the bubbles at every width. Drop the full-width Divider() — the composer's floatingShadow carries the separation over the shared ChatBackdrop. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The docked composer's centering HStack omitted spacing: 0 that messageList uses, so default ~8pt spacing shrank the composer column and the two 720 columns diverged at some window widths. Add spacing: 0 for a byte-identical centering container. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The ambient wash moved to ChatBackdrop (applied by CopilotChatView) in 57e34e6; the struct doc still listed it as something ChatEmptyState renders. Comment-only; no code change. (Final-review M1.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ntained 720 left only ~15pt margins on a ~1000pt window (sidebar takes 250), so the composer still read as full-width. Drop the shared column (active composer, empty-state composer, empty-state cards, message list) to 600 so containment is clear on a laptop-sized window while staying generous on wide ones. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dmark The 22pt gradient square read as a second, competing brand next to the pixel wordmark. The row is now just "Codepet" (still the home button). newChatGradient stays — the New chat button and Upgrade CTA still use it.
Adapts Phase 2 chat spec §1/§2/§4/§8 to feat/chat-redesign: reimplement
CompanionOrb as a luminous companion-tinted sphere (breathe on isWorking)
+ a ChatThinkingRow that names the work ("Drafting {title}…" / "Working on
it…") with a subtle shimmer. Second-hue per companion + chatCanvas/chatOrbCore
tokens. Orb perf (Canvas) is the schedule risk; Metal fallback budgeted.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
handleDoneAction applies re_plan inline (→ generateRoadmap) and RETURNS the walkthrough task id; sendMessage drains it after the send completes (isStreaming == false), because a guided turn starts a new send that the in-flight send's busy-guard would otherwise block. cid-guarded, no-op on an unknown/stale id. Fallback path carries the new verbs too. A dispatch test caught the busy-guard blocking synchronous walkthrough dispatch — hence the deferred drain (design deviation from the plan's inline call). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Lets `-CODEPET_MOCK_CHAT YES` drive a real walkthrough dispatch end to end without the (other-repo) companyChat CF. Triggers on the token "walkthrough" (not "walk me through") so it can't match walkThroughTask's own composed "Walk me through …" message and loop. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A reply carrying both verbs: re_plan replaces tasks first, then the walkthrough id resolves against the POST-replan set and starts the guided turn. Pins the deliberate ordering in handleDoneAction. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Closes Part 1's implementation: Tasks board obeys the "work lands in chat" rule (Layer 4 gap); run-task grounding routed through CompanyContext (Layer 1 done). Layer 3 (unified lifecycle) deferred to Part 2 — only one backend today; unifying now = engine-ahead-of-plays. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The board dispatched runTask/walkThroughTask without navigating, so the founder watched nothing happen while the work streamed into chat. Now it uses the same RoadmapDispatch.navigatesToChat rule the roadmap uses: work-producing taps land in chat; approve + open stay in place. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…us Layer 1) Adds runTaskGroundingString (brief+tasks+decisions, byte-identical to the old inline call — no library grounding, no payload change) and migrates the run-task site to it. ChatContext.compose is now called only inside CompanyContext — the single Layer-1 read-surface. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
First of four Part-2 sub-plans. ProjectLink model + .git/CLAUDE.md probe, CLAUDE.md bootstrap from brief+decisions, CompanyStore.linkProject + active link + client-only project-slice wiring. Picker UI deferred pending a UI design discussion; subprocess/edit/commit are 2B/2C. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pure ProjectLink value type + ProjectProbe (.git / CLAUDE.md detection) with its client-only CompanyContext.ProjectSlice mapping, and ClaudeMdBootstrap — a pure seed-markdown composer from brief + decisions for a linked project with no CLAUDE.md. No subprocess yet. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ring (Part 2A) linkProject(path:) probes a folder, sets activeProjectLink, persists a security-scoped bookmark, bootstraps CLAUDE.md when absent (never clobbers, re-probes), and feeds the client-only project slice into the chat-send CompanyContext (cloud payload unchanged — regression test added). Picker UI deferred pending a UI-design discussion. ProjectLinkTests 6/6, CompanyContextTests 7/7, build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Final-review Important: activeProjectLink + its bookmark key were added to the per-account @published cluster but not cleared in hydrate's accountChanged branch or reset() — a cross-account leak of local project data once a UI wires it. Now cleared in both (bookmark key extracted to a constant). Plus: tighten hasClaudeMd to reject a dir named CLAUDE.md; note the bookmark is best-effort/untested (2B revisits). Test locks the account-switch clear. ProjectLinkTests 7/7, build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CodeCommitService: git path (throwaway codepet/<slug> branch off HEAD, stash dirty work, commit-on-approve / abort-restores) + shadow path (temp copy, apply-with-backup / undo) + GitRunner. ClaudeCodeRunner reused unchanged. Orchestration + approval gate + chat UI deferred to 2C. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Synchronous /usr/bin/git wrapper (stdout/stderr/exit, never throws) + a pure kebab CommitSlug. Foundation for CodeCommitService. 3/3 tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…it engine (Part 2B) Git path: stash dirty work → throwaway codepet/<slug> off HEAD → commit accepted files on approve (never main/merge/push) → abort hard-resets + deletes branch + restores stash. Shadow path (non-git): temp copy (heavy dirs excluded) → apply accepted files to real tree with backup (tombstoning new files) → undo restores exact pre-apply state. ClaudeCodeRunner reused unchanged. 8/8 tests (real git in temp repos + shadow file IO). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…al review) Opus final review (1 Critical + 5 Important), all fixed: - CRITICAL: applyShadow no longer overwrites an original whose backup failed (backup is now a hard precondition — skip apply, no data loss). - abortGit runs `git clean -fd` so run-created untracked files are removed (reject is a full undo), and gates branch -D / stash pop on the checkout actually switching back. - commitGit returns GitCommitResult; on an overlapping stash-pop conflict it resets to the clean commit and retains the founder's work in the stash (stashRestored=false) instead of leaving conflict markers + lying. - commitGit no longer pops on commit failure (avoids double-pop). - GitRunner drains stdout/stderr concurrently (no pipe-buffer deadlock on chatty hooks). - `stashed` set from the stash push result, not just a dirty tree. Plus: beginShadow cleans its temp dir on failure; nested-node_modules note. Tests added for untracked-abort + overlap-conflict. 13/13, build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Testable logic core, no UI: edit_code reply verb (client parse), pure EditCodePlanner/EditCodeRun (preview gate + git/shadow backend), and CodingRunCoordinator driving propose→execute→approve/reject over an injected CodeRunning seam + the real CodeCommitService (fake runner + temp repos in tests). 2C-2 (card UI), 2C-3 (Environment link UI), 2C-server (CF tool) follow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Additive EditCodeAction {ask, planned_files, needs_bash} on the reply
contract + SSE done frame; executed locally, never sent to the cloud.
16/16 CompanyChatClientTests (2 new + no regression).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…C-1) Pure lifecycle phases + preview-gate (multi-file/Bash → preview) + backend selection (git branch vs shadow) from the linked project. 3/3 tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…C-1) Drives a coding run over a CodeRunning seam (ClaudeCodeRunAdapter in prod, fake in tests) + the real CodeCommitService: propose (preview gate + backend select), execute (begin session → run → reviewing/failed with teardown), approve (commit git / apply shadow), reject (abort/discard). CompanyStore routes edit_code from the reply to codingRun.propose. 5/5 coordinator tests (fake runner + real temp git repos); build green. UI is 2C-2. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Opus final review (2 Critical + 3 Important), all fixed: - CRITICAL: ClaudeCodeRunner published `.finished` BEFORE computing diffs, so the adapter always read an empty fileDiffs → commits nothing. Now diffs are published and `.finished` flips together (also cleaner for the exercise flow). - CRITICAL: the adapter reused one runner; @published replayed a stale `.finished`, so every run after the first resumed instantly with old diffs + orphaned a live subprocess. Now a fresh ClaudeCodeRunner per run() call. - propose() tears down any un-resolved prior session (no orphaned branch/shadow) and refuses to clobber an in-flight run. - approve() honors commitGit/applyShadow results → routes to .failed + abortGit on failure (no false "committed", stash restored) instead of lying. - phase guards on execute (.readyToRun/.previewing), approve/reject (.reviewing). - relPath standardizes the root so nested paths don't flatten. Tests added for teardown, failed-commit, and phase-guard. 8/8 coordinator tests, build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Stream live run steps (seam onStep + pure CodeExecSteps mapping, testable), CodeRunCardView (the agreed evolving card: preview → steps → inline per-file diff review → Reject/Approve, honest 0-credits/branch/undo labels), wired into the transcript like AgentsWorkingRow + MockChat exercise. Views are build-verified + the founder's visual pass. 2C-3 (Environment link UI), 2C-server (CF tool), full-diff sheet deferred. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CodeRunning seam gains an onStep callback; ClaudeCodeRunAdapter forwards tool-use events (append-only $events) via a pure CodeExecSteps mapping; CodingRunCoordinator republishes them as @published steps for the card (cleared per propose). Pure mapping + coordinator step-collection tested (12/12 across CodeExecSteps + CodingRunCoordinator); build green. Card views (Tasks 2-3) are the founder's to build/verify visually. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Testable suggestion helper (I execute) + the Environment 'Linked project' section, .noProject inline offer, and composer chip (founder's SwiftUI + visual pass). Reuses 2A linkProject; matches the agreed 2C UI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pure ProjectLinkSuggestions.suggest over ProjectStore.sortedProjects (excludes the active link, capped) for the Environment link chips. 3/3 tests, build green. Environment section / .noProject offer / composer chip (Tasks 2-3) are the founder's SwiftUI + visual pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adaptive: Engineering routes to local edit_code only when a project is linked, else cloud run_task (zero disruption). Pure routing rules (RoadmapDispatch .editCode + EditCodeRouting) + roadmap/tasks/composer dispatch wiring. Overnight trigger foundation-only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adaptive: Engineering .codepetCanDo tasks and the Engineering composer pill route to the LOCAL coding agent (codingRun.propose → edit_code) ONLY when a project is linked; with no link they keep today's cloud run_task behavior (zero disruption). Pure rules (RoadmapDispatch .editCode via action(for:isEngineering:projectLinked:) + EditCodeRouting) are tested; roadmap/tasks/composer dispatch wiring is build-verified. edit_code navigates to chat (Layer 4). Overnight trigger stays foundation-only. 10/10 routing tests, full build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ask (2D review) Final review (1 Important + 1 Minor), fixed: - IMPORTANT: sendChat's Engineering-pill route returned early without appending the founder's message, so their ask vanished from the transcript (the run card that'd show it is 2C-2, not built) — a visible regression if 2D ships first. Now echoes the ask as a .me message before staging the run. Two store tests lock it: eng+link → run staged + ask echoed + NO cloud turn; no-link → normal cloud turn (guard can't mis-fire). - MINOR: hoisted the duplicated task→ask construction to RoadmapDispatch.editCodeAsk (used by all 3 dispatch sites). 16/16 routing+dispatch tests, full build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sks 2-3)
One evolving in-chat card renders every phase of CodingRunCoordinator.run:
- previewing → ask + "may run terminal commands · you review everything" + Run/Cancel
- running → avatar + ENGINEERING kicker + "0 credits" + live step checklist
- reviewing → branch chip, "N files changed", per-file accept toggles (deselected
files dim + drop from the commit), monospace unified diff (+/- tints,
capped 40 lines/file), Open-full-diff stub, Approve N / Reject
- committed → git branch + "nothing pushed/merged"; shadow "Applied · Undo" stub
- discarded / noProject / failed (with the install-&-sign-in enablement line)
Bilingual, CodepetTheme tokens only, #Preview across all phases for visual QA.
Wiring: CopilotChatView renders the card at the transcript level when a run is
active (beside AgentsWorkingRow) + auto-scroll; MockChat "edit code"/"code:" route
stages a run so the card is exercisable under -CODEPET_MOCK_CHAT YES.
Coordinator: cancel() (dismiss a not-yet-running/finished card — reject() only
covers .reviewing) + a DEBUG-only .preview(_:steps:) factory for the #Preview.
18/18 (CodeExecSteps + CodingRunCoordinator + verb-dispatch), build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…, composer chip (Part 2C-3 Tasks 2-3) - ProjectLinker (shared): native directory picker → CLAUDE.md-bootstrap CONSENT prompt (never writes without a yes) → CompanyStore.linkProject. One home for the flow so both surfaces ask consent identically. - EnvironmentView "Linked project" section: linked → folder name + path + git / CLAUDE.md badges + Change…; unlinked → value line + "Link a project folder" + one-tap recent-project chips (ProjectLinkSuggestions). Built in the view's own CodepetCard/.pixelSystem idiom. #Preview (unlinked). - CodeRunCardView .noProject: real "Link a project" button that runs the shared flow and re-proposes THIS run's ask (no retype). - ChatComposer: quiet active-project chip (⑂/folder + name) → Environment, so the founder always sees which folder the agent will touch. Store injected; preview host updated. 25/25 (ProjectLinkSuggestions + ProjectLink + CodingRunCoordinator + verb-dispatch), build green. Views — need founder visual pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hardening + correctness from a full interactive test of the coding-agent flow (link → chat edit_code → run → diff → Approve → commit on a codepet/* branch). Five real bugs found and fixed, each with a regression test: 1. `.readyToRun` never executed — a chat-triggered run sat at "Getting started…" forever (nothing called execute()). The card now auto-runs a readyToRun job. 2. Double-send race — a rapid duplicate proposal superseded an in-flight run mid-launch and stranded it. propose() now refuses to clobber a .running/ .readyToRun run (test_propose_ignoresDuplicateWhileInFlight). 3. Branch orphaning / data loss — abortGit deleted the codepet/* branch unconditionally (reject / supersede / failed-approve), destroying committed work. It now NEVER deletes a branch that carries commits (test_abortGit_keepsBranchThatHasCommits). 4. False "Committed" — "nothing to commit" was treated as success. commitGit now distinguishes nothingToCommit / alreadyOnBranch; approve only reports committed when a commit truly exists (test_commitGit_flagsNothingToCommit). 5. Card stuck until a tab switch — @published fires in willSet, so a synchronous re-render read the pre-assignment value; deferring the refresh one runloop turn makes running→reviewing→committed update live. Also lands the card's "Open full diff" sheet (was a dead stub), inline card placement (renders after the ask, not pinned to the transcript bottom), and a MockCodeRunner behind CODEPET_MOCK_CHAT so the whole flow is exercisable offline with zero Claude usage. 31/31 coding-agent tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Native chat redesign → chat as the product surface: Capability Bus + local Coding Agent
Base:
main· Head:feat/chat-redesign· ~145 commits · 137 files · +16.5k / −0.6kThe Coding Agent's cloud piece (the
edit_codeAnthropic tool incompanyChat, repoMurror/CodePet-Clean→devpet-8f4b1) is built but deployed separately and currently held. The client and the function must ship together: if the function announcesedit_codebefore the client can render the run card, prod users get "byte promises, nothing happens"; if the client ships first, Engineering asks silently fall back to a cloud turn. Merge this PR and deploy thecompanyChatchange in the same window.Also note: 38 commits on the local branch are unpushed (the Capability Bus + Coding Agent work, held per the review gate). Push before merging.
What's in this PR
1. Chat, redesigned into the home surface
RoadmapEngine.nextMovesplanner +CompanyStorefan-out engine + the inlineAgentsWorkingRow(Codex-style live multi-agent view).-CODEPET_MOCK_CHAT YES+ an in-app gallery, so every chat surface is demoable/testable with no API key.2. Capability Bus (Part 1) — chat ⇄ everything
One integration layer so a chat turn can drive the rest of the app coherently:
CompanyContext— a typed read-surface all grounding flows through (groundingStringfor chat, a leanrunTaskGroundingStringfor run-task). Byte-parity preserved.run_task/nav/setup/rememberplus newre_planandwalkthroughreply verbs (parsed + dispatched, with ordering locked by tests).projectslice (path, CLAUDE.md, diffs) is a real type but is never included in any cloud grounding string. Locked bytest_context_lockClientOnlyProjectSlice.3. Coding Agent (Part 2) — Engineering makes real code changes
The PRD "agent coding" feature: link a real project, run the user's own
claudeCLI locally, review a diff, commit to a throwaway git branch or safe-apply. The user's code never leaves the machine.ProjectLink+ProjectProbe(git / CLAUDE.md detection) +CompanyStore.linkProjectwith consent-gated CLAUDE.md bootstrap (never clobbers an existing one); cleared on account switch.GitRunner+CodeCommitService. Git path: stash dirty → throwawaycodepet/<slug>branch off HEAD → commit accepted files, or abort-and-restore. Shadow path: temp copy → apply-with-backup / undo. Never merges, pushes, or deploys.CodingRunCoordinatorover aCodeRunningseam;ClaudeCodeRunAdapterbridges the realClaudeCodeRunner(spawnsclaude -p --output-format stream-jsonvia a login shell) to an async outcome. Runs on the user's Claude subscription — 0 Codepet credits.CodeRunCardView— one evolving in-chat card: plan-preview → live step checklist → per-file diff review with accept toggles → committed / failed. Streams live tool-use steps..noProjectlink offer, and a composer chip showing which folder the agent will touch. SharedProjectLinker(picker + consent) so both surfaces behave identically.edit_codeAnthropic tool + validator incompanyChat(held; see above).Security / trust model
edit_codereturns only the intent (ask,planned_files,needs_bash). All code access is client-side.claude(their auth, their PATH), not a Codepet key — 0 credits.Testing
CompanyContext,CompanyChatClient,CompanyStoreVerbDispatch,RoadmapDispatch,EditCodeRouting,EditCodeRun,CodingRunCoordinator,CodeExecSteps,ProjectLink,ProjectLinkSuggestions,GitRunner,CodeCommitService— plus the chat fan-out suites. All green.claudeon a scratch repo → editedhello.js→ run reached.reviewingwith the diff → approve → committed tocodepet/…branch, nothing pushed. Confirms the seam that carried the 2C-1 critical bugs against reality.#Previews across states; founder visual pass pending (no screen-recording in CI).Not in this PR / follow-ons
companyChatedit_codetool (paired deploy — see top).Suggested retitle