Conversation
There was a problem hiding this comment.
2 issues found across 42 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/desktop/src-tauri/tauri.conf.json">
<violation number="1" location="packages/desktop/src-tauri/tauri.conf.json:25">
P1: Production hardening regression: enabling Tauri devtools unconditionally in `tauri.conf.json` exposes webview developer tools in packaged builds, allowing arbitrary JS execution. Change `devtools` back to `false` or guard it behind a debug-only config.</violation>
</file>
<file name="packages/ui/src/components/app-layout/project-tab-bar.svelte">
<violation number="1" location="packages/ui/src/components/app-layout/project-tab-bar.svelte:66">
P2: Hidden absolute `+` button remains interactive because it is hidden only via `opacity-0`, enabling accidental clicks and invisible keyboard focus.</violation>
</file>
Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.
Re-trigger cubic
| "titleBarStyle": "Overlay", | ||
| "dragDropEnabled": true, | ||
| "devtools": false | ||
| "devtools": true |
There was a problem hiding this comment.
P1: Production hardening regression: enabling Tauri devtools unconditionally in tauri.conf.json exposes webview developer tools in packaged builds, allowing arbitrary JS execution. Change devtools back to false or guard it behind a debug-only config.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop/src-tauri/tauri.conf.json, line 25:
<comment>Production hardening regression: enabling Tauri devtools unconditionally in `tauri.conf.json` exposes webview developer tools in packaged builds, allowing arbitrary JS execution. Change `devtools` back to `false` or guard it behind a debug-only config.</comment>
<file context>
@@ -22,7 +22,7 @@
"titleBarStyle": "Overlay",
"dragDropEnabled": true,
- "devtools": false
+ "devtools": true
}
],
</file context>
| "devtools": true | |
| "devtools": false |
| {/if} | ||
| </button> | ||
| </button> | ||
| {#if project.sessionCount != null && onCreateSession} |
There was a problem hiding this comment.
P2: Hidden absolute + button remains interactive because it is hidden only via opacity-0, enabling accidental clicks and invisible keyboard focus.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/ui/src/components/app-layout/project-tab-bar.svelte, line 66:
<comment>Hidden absolute `+` button remains interactive because it is hidden only via `opacity-0`, enabling accidental clicks and invisible keyboard focus.</comment>
<file context>
@@ -30,52 +30,53 @@
{/if}
- </button>
+ </button>
+ {#if project.sessionCount != null && onCreateSession}
+ <button
+ type="button"
</file context>
15c7207 to
9aae19d
Compare
…zouh#199) ## Problem When starting a new session, the model selector shows a pre-filled model (e.g. GPT 5.4) based on saved preferences. However, if the user sends a message without explicitly re-clicking the selector, the backend ignores the displayed model and uses its own default (e.g. Claude Sonnet). ## Root Cause `getProvisionalModelId()` returned `null` when the user never interacted with the selector — even though `preferredDefaultModelId` was being used for display via `resolveToolbarModelId`. The session creation path then sent no `initialModelId`, letting the backend pick freely. ## Fix Fall back to `preferredDefaultModelId` when `provisionalModelId` is null: ```ts // Before getProvisionalModelId: () => provisionalModelId, // After getProvisionalModelId: () => provisionalModelId ?? preferredDefaultModelId, ``` This ensures the `initialModelId` sent during session creation matches what the user sees in the selector. The fallback is validated downstream (`session-connection-manager` checks against available models) and only applies to new sessions (`props.sessionId ? null : host.getProvisionalModelId()`). <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Fixes the “pre-filled” model being ignored when starting a new session and adds a mid-session Worktree switch confirmation so future turns can continue in a new worktree without silently moving existing changes. - New Features - Mid-session Worktree switch dialog in the agent panel (Continue-only path): existing changes stay in the source checkout; future turns run in the new worktree. Backed by a new `prepareMidSessionWorktreeSwitch` service. - Worktree toggle pill is now visible mid-session and after attach; terminal can render as a right-side trailing pane for better space use. - Bug Fixes - Model selector: when `provisionalModelId` is null, fall back to `preferredDefaultModelId` so `initialModelId` matches what the UI shows on new session creation. - Browser panel scroll-sync now subscribes to overflow ancestors before they become scrollable, fixing webview bleed during horizontal scrolling. <sup>Written for commit c240b4c. Summary will update on new commits. <a href="https://cubic.dev/pr/flazouh/acepe/pull/199?utm_source=github">Review in cubic</a></sup> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Why Acepe's marketing site had solid SEO bones (sitemap, robots.txt, per-page titles, baseline JSON-LD), but several signals were leaking value: - `app.html` declared a homepage title/description/OG/Twitter that appeared **on every route alongside** the per-page versions — duplicate meta confuses crawlers and previews. - JSON-LD claimed `aggregateRating: 5/1` with a single fake review (Google can flag this as spam). - Private surfaces (`/pitch`, `/dev/*`, `/login`) were both indexable and inconsistently blocked. - Several routes were missing OG/Twitter cards, canonical URLs, or structured data. - Sitemap referenced a nonexistent `/roadmap` and omitted `/privacy`, `/terms`, `/zeus`. This PR makes every route's SEO complete, consistent, and crawler-friendly. ## What ### Central `<Seo>` component Single source of truth in `packages/website/src/lib/components/seo/seo.svelte`: - Title with auto-suffix - Description, canonical (absolute, derived from `canonicalizePathname`) - Full Open Graph (`og:type`, `og:site_name`, `og:url`, `og:title`, `og:description`, `og:image`, `og:image:alt`, `og:locale`, optional dimensions, `article:published_time`/`modified_time`) - Full Twitter card (`summary_large_image` + title/desc/image/alt) - Configurable `robots` + `googlebot` (defaults include `max-image-preview:large`, `max-snippet:-1`, `max-video-preview:-1`) - `noindex` flag - Optional `keywords`, `author`, `imageWidth`/`imageHeight`, multiple JSON-LD blocks ### Stripped `app.html` Removed duplicated dynamic meta. Kept favicon, manifest, viewport, fonts, theme, and added `application-name`, `apple-mobile-web-app-*`, `format-detection`, `color-scheme`. ### Strengthened site-wide JSON-LD (`json-ld.svelte`) - Removed the fake `aggregateRating` - Added a separate `WebSite` schema (with publisher + language) - Structured `ImageObject` logo with dimensions - `sameAs` linking to the GitHub repo - `downloadUrl`, real `applicationSubCategory`, richer `featureList` ### Per-route structured data | Route | Schema | |-------|--------| | `/` | keywords + canonical | | `/pricing` | **FAQPage** from real FAQ items | | `/download` | `SoftwareApplication` offer with `availability: InStock` | | `/compare` | **ItemList** of all comparisons | | `/compare/[slug]` | **FAQPage + BreadcrumbList** (Home → Compare → tool) | | `/blog` | **Blog** schema listing all posts | | `/blog/*` (via `BlogPostLayout`) | **BlogPosting + BreadcrumbList** with publisher logo, `timeRequired`, `mainEntityOfPage`, `articleSection` | | `/changelog`, `/privacy`, `/terms`, `/zeus` | full meta + canonical | ### Indexing posture - `noindex` via `<Seo>` on `/pitch`, `/login`, and dev-only routes. - Removed `Disallow` for any route that relies on `noindex` meta (Google must fetch the page to see it; `Disallow` makes `noindex` invisible to the crawler). - `Disallow` reserved for surfaces we never want crawled: `/admin`, `/auth`, `/api`, legacy locale paths. - Full-block scraper user agents: `GPTBot`, `ClaudeBot`, `anthropic-ai`, `CCBot`, `Google-Extended`. ### Sitemap - Added `/privacy`, `/terms`, `/zeus` - Removed nonexistent `/roadmap` - Bumped `/download` priority - Test updated (23 expectations passing) ## Tests - `bun test src/routes/sitemap.xml/` — passes (23 expect calls) - `bun run check` — same pre-existing errors as baseline on `main`; no new errors in SEO files - Reviewed via `/review` skill; all four findings (GPTBot/ClaudeBot grouping semantics, `/zeus` indexing inconsistency, robots+noindex contradiction, hardcoded OG dimensions) addressed before merge ## Verifying manually After deploy, validate at: - https://search.google.com/test/rich-results — paste `https://acepe.dev/`, `/blog`, `/pricing`, `/compare/cursor`, `/blog/attention-queue` - https://www.opengraph.xyz/ — paste any route to inspect OG/Twitter rendering - View source of any page to confirm exactly one set of meta tags <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Unifies SEO with a single `<Seo>` component and adds complete, route-level structured data. Fixes duplicate meta, tightens indexing, corrects the sitemap, normalizes OG image URLs, and hardens SSR for reliable previews and tests. - New Features - Central `packages/website/src/lib/components/seo/seo.svelte` for title, description, canonical, OG/Twitter, `robots`/`googlebot`, `noindex`, keywords/author, optional image dims, article times, and JSON-LD. - Stronger site-wide JSON-LD: `Organization`, `WebSite`, and `SoftwareApplication` with structured logo, `sameAs`, `downloadUrl`, and a richer `featureList`. - Per-route SEO: homepage keywords; pricing `FAQPage`; download `SoftwareApplication` offer (`InStock`); compare `ItemList` + per-slug `FAQPage` and `BreadcrumbList`; blog index `Blog` + posts `BlogPosting`; full meta on changelog/privacy/terms/zeus. - `app.html` now only static head tags (favicon, manifest, fonts, theme, mobile web app). - Bug Fixes - Removed duplicate title/description/OG/Twitter across routes. - Normalized relative OG image paths to absolute URLs in meta and JSON-LD. - Dropped fake `aggregateRating` JSON-LD. - Corrected indexing posture: `noindex` on `/pitch` and `/login`; keep `robots.txt` Disallow for `/admin`, `/auth`, `/api`, `/es/`, `/en/`; block `GPTBot`, `ClaudeBot`, `anthropic-ai`, `CCBot`, `Google-Extended`. - Fixed sitemap: added `/privacy`, `/terms`, `/zeus`; removed `/roadmap`; increased `/download` priority; tests updated and passing. - Guarded `page.url` access in `<Seo>` for SSR/test contexts to prevent crashes. <sup>Written for commit 45a6b84. Summary will update on new commits. <a href="https://cubic.dev/pr/flazouh/acepe/pull/197?utm_source=github">Review in cubic</a></sup> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When the user enables the worktree toggle after a session is already active, surface a confirmation dialog instead of silently flipping pending state. Ships the Continue-in-new-worktree path; future agent turns run in the new worktree while existing changes remain in the source checkout. - New AgentPanelWorktreeSwitchDialog presentational component (@acepe/ui) - New prepareMidSessionWorktreeSwitch service wrapping the Tauri prepareWorktreeSessionLaunch call + background setup orchestration - Wire the dialog into agent-panel.svelte; the Move-session-changes branch is rendered disabled until the backend ownership-proof flow ships Also includes session UI polish picked up while implementing this: - Worktree pill stays visible mid-session and after attach - Browser pane subscribes scroll sync to overflow containers before they become scrollable, fixing webview bleed during horizontal scroll - Terminal opens as a right-side trailing pane instead of a bottom drawer; sidebar project card no longer duplicates terminal/browser icons Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
9aae19d to
5bdf133
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the pre-session worktree card wired without adding a packages/ui diff, so the worktree PR does not trigger unrelated website SEO tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Apply the repository formatter/import ordering for the desktop package so the PR passes the frontend CI gate without adding website or SEO changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This reverts commit 226f747.
## Summary Fixes a critical bug where hundreds of ghost agent panels accumulate on every app reload, plus three UI polish issues. ## Changes ### 🐛 Fix: Ghost panel flood on reload **Problem:** Every time the app reloads, `syncLiveSessionPanels` re-materializes panels for ALL live sessions because the suppression map (in-memory only) is lost on reload. This caused 200+ ghost tabs to reappear. **Fix:** Added an `initialSyncComplete` guard in `live-session-panel-sync.ts`. The first sync pass now seeds the suppression map with existing live sessions without materializing panels. Subsequent reactive updates materialize normally for genuinely new activity only. ### 🎨 Fix: Worktree toggle pill styling - Changed text from `text-[0.6875rem]` to `text-xs font-mono lowercase` to match branch name styling - Fixed toggle knob alignment: symmetric 2px padding instead of asymmetric 1px ### 🎨 Fix: Session list search bar sizing - Reduced height from `h-7` to `h-6` - Shrunk text to 11px - Added `pt-1` padding above the search container ## Testing - All 12 tests in `live-session-panel-sync.test.ts` pass (including new test for initial seed behavior) - TypeScript check passes - Manually verified: 0 panels after reload (was 207) <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Prevents ghost agent panels from reappearing on reload by seeding suppression on the first sync pass. Also tweaks the worktree toggle pill and session list search bar for better alignment and sizing. - **Bug Fixes** - First sync seeds suppression for existing live sessions without materializing panels; only new activity opens panels. - Added `resetLiveSessionPanelSync()` and tests for the initial seed behavior. - **UI Polish** - Worktree toggle pill: `text-xs` `font-mono` lowercase label; fixed knob translation for symmetric padding. - Session list search: height `h-6`, 11px text, added `pt-1`. <sup>Written for commit 3d6175d. Summary will update on new commits. <a href="https://cubic.dev/pr/flazouh/acepe/pull/200?utm_source=github">Review in cubic</a></sup> <!-- End of auto-generated description by cubic. --> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixed: set
Fixed: added |
## Problem As identified by cubic in flazouh#200, `initialSyncComplete` was set unconditionally after every `syncLiveSessionPanels` call — including when `inputs` is empty. If the first reactive `$effect` run in `app-queue-row.svelte` fires before sessions have loaded (`liveSessionSyncInputs` is empty), the guard is consumed immediately. The next non-empty call then treats all live sessions as genuinely new and materializes their panels — recreating the ghost-panel flood the guard was meant to prevent. ## Fix Gate the `initialSyncComplete = true` flip behind `inputs.length > 0`. An empty-inputs call is a no-op that must not advance the first-run state machine. ```diff -\tinitialSyncComplete = true; +\tif (inputs.length > 0) { +\t\tinitialSyncComplete = true; +\t} ``` Fixes the cubic finding from flazouh#200. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Prevent ghost panels by guarding the initial sync against an empty first call. `initialSyncComplete` now flips only when `syncLiveSessionPanels` receives non-empty inputs. - **Bug Fixes** - Gate `initialSyncComplete = true` behind `inputs.length > 0` so empty calls don’t advance the first-run guard. <sup>Written for commit f68c500. Summary will update on new commits. <a href="https://cubic.dev/pr/flazouh/acepe/pull/201?utm_source=github">Review in cubic</a></sup> <!-- End of auto-generated description by cubic. --> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
2 issues found across 35 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/desktop/src-tauri/src/acp/commands/session_commands.rs">
<violation number="1" location="packages/desktop/src-tauri/src/acp/commands/session_commands.rs:1248">
P1: Post-reconnect error paths in acp_switch_session_to_worktree leak replacement_client and worktree on failure</violation>
</file>
<file name="packages/desktop/src-tauri/src/acp/commands/interaction_commands.rs">
<violation number="1" location="packages/desktop/src-tauri/src/acp/commands/interaction_commands.rs:250">
P2: Blocking `acp_cancel` during session switch violates established design principle that cancellation must remain gated on connection status, not send readiness or temporary operation locks</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| } | ||
| }; | ||
|
|
||
| if let Some(capabilities) = previous_capabilities { |
There was a problem hiding this comment.
P1: Post-reconnect error paths in acp_switch_session_to_worktree leak replacement_client and worktree on failure
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop/src-tauri/src/acp/commands/session_commands.rs, line 1248:
<comment>Post-reconnect error paths in acp_switch_session_to_worktree leak replacement_client and worktree on failure</comment>
<file context>
@@ -1145,6 +1146,164 @@ pub async fn acp_new_session(
+ }
+ };
+
+ if let Some(capabilities) = previous_capabilities {
+ if let Some(model_state) = capabilities.models {
+ if let Some(model_id) = model_state.current_model_id {
</file context>
| expected_acp_command_result( | ||
| "acp_set_model", | ||
| async { | ||
| super::session_switch_gate::reject_if_session_switching(&session_id)?; |
There was a problem hiding this comment.
P2: Blocking acp_cancel during session switch violates established design principle that cancellation must remain gated on connection status, not send readiness or temporary operation locks
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/desktop/src-tauri/src/acp/commands/interaction_commands.rs, line 250:
<comment>Blocking `acp_cancel` during session switch violates established design principle that cancellation must remain gated on connection status, not send readiness or temporary operation locks</comment>
<file context>
@@ -247,6 +247,7 @@ pub(crate) async fn acp_set_model_for_handle<R: tauri::Runtime>(
expected_acp_command_result(
"acp_set_model",
async {
+ super::session_switch_gate::reject_if_session_switching(&session_id)?;
tracing::debug!(session_id = %session_id, model_id = %model_id, "acp_set_model called");
let session_registry = app.state::<SessionRegistry>();
</file context>
| super::session_switch_gate::reject_if_session_switching(&session_id)?; | |
| // Do NOT gate cancel on session switch; cancellation must remain | |
| // available based on connection status per design guidance. | |
| // (Remove this line; keep the rest of the function unchanged.) |
- Apply Biome formatting/import ordering after merging main - Remove autofocus from the worktree switch dialog action - Add an aria-label to the worktree toggle button Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A small batch of composer/voice UX tweaks made interactively while reviewing the app. ## Changes ### Composer prompt container - Bump interior padding to \`px-3 py-2.5\` so text and the send button no longer hug the borders. - Toolbar row remains flush with the container edges so the circular icon buttons can hit the bottom corners cleanly (the hover ring extends into the corner instead of being trapped behind extra padding). ### \`InputContainer\` / \`AgentPanelComposer\` shared API - Add an optional \`footerClass\` prop so hosts can opt into footer padding without touching shared defaults. Existing call sites are unaffected. ### Voice model menu - Group models by tier (\`Tiny / Base / Small / Medium / Large\`) with a one-line tradeoff description per tier (\`Fastest · least accurate\`, \`Balanced · recommended\`, …) and a separator between groups. - Rows now show only \`English\` / \`Multilingual\` since the tier is the section header — less repetition, easier to scan. - Align row heights for downloaded vs. not-downloaded models (\`min-h-7 + py-1\`) so the vertical rhythm is consistent regardless of whether a row shows a download button or just a size. - Robust to future catalog entries: unknown tiers fall back to the raw label with no description rather than disappearing. ### Mode pill (Plan / Build) - Replace the native \`title\` attribute with a rich \`Tooltip\` (label + muted description) explaining when to use each mode. - Descriptions are exposed as \`planDescription\` / \`buildDescription\` props for host overrides. ### Empty state heading - Reduce \"What do you want to build?\" font size by 4px (\`1.9rem\` → \`1.65rem\`, \`text-4xl\` → \`text-[2rem]\`) for a slightly less heavy welcome screen. Stays centered. ## Verification - \`bun run check\` (TypeScript) passes in \`packages/desktop\`. - Changes are presentational only; no store, transport, or canonical state touched. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Polishes the composer layout and upgrades the voice model menu for clearer choices and more consistent spacing. Adds a tooltip-based mode switch and lightens the empty state heading. - New Features - Composer: increased interior padding to px-3 py-2.5 so text and the send button don’t hug the edges; toolbar stays flush with the container. - `InputContainer` / `AgentPanelComposer`: added optional `footerClass` prop for opt‑in footer padding. - Voice model menu: grouped by tier with short tradeoff notes, rows show only “English” / “Multilingual,” consistent row heights, safe fallback for unknown tiers, and a wider menu for readability. - Mode pill (Plan / Build): replaced native title with a rich `Tooltip`; descriptions are overridable via `planDescription` / `buildDescription`. - Empty state: reduced “What do you want to build?” font size for a calmer first view. <sup>Written for commit cd5a60d. Summary will update on new commits. <a href="https://cubic.dev/pr/flazouh/acepe/pull/202?utm_source=github">Review in cubic</a></sup> <!-- End of auto-generated description by cubic. --> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This restores the autonomous toggle's active icon color to purple so the prompt container button matches its intended violet state again. The shared `@acepe/ui` toggle had drifted to `Colors.red`, which made an enabled autonomous mode read like a destructive state. --- [](https://github.com/EveryInc/compound-engineering-plugin)  <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Restores the autonomous toggle’s active icon to purple. Also fixes live session panel sync so an empty first call doesn’t flip the initial-sync flag and create ghost panels. - **Bug Fixes** - UI (`@acepe/ui`): Autonomous toggle now uses `Colors.purple` for the active icon and CSS variable. - Desktop: Only set `initialSyncComplete = true` when `inputs.length > 0` to prevent ghost panel materialization. <sup>Written for commit 340dd57. Summary will update on new commits. <a href="https://cubic.dev/pr/flazouh/acepe/pull/203?utm_source=github">Review in cubic</a></sup> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
What
When the user enables the worktree toggle after a session is already active, Acepe now treats Continue as a real backend-owned runtime switch instead of a frontend metadata flip.
The dialog remains the product surface, but the Continue path now asks Rust to move the active session runtime to a new worktree so future prompts/tool calls run from that cwd.
Why
The first version of this PR created the worktree and updated UI/session metadata, but existing-session sends still called
sendPrompt(sessionId, ...)on the already-registered provider client. That could make the UI say “worktree” while the live agent still operated in the original checkout.How
acp_switch_session_to_worktreeTauri command.worktreePath, then swaps the runtime inSessionRegistry.prepareWorktreeSessionLaunch,PreparedWorktreeLaunch, orpendingWorktreeEnabledfor mid-session Continue.docs/plans/2026-05-20-mid-session-worktree-runtime-rebind-plan.md.Also included from the original PR
Validation
cd packages/desktop && bun run checkcd packages/desktop/src-tauri && cargo check --quietcd packages/desktop/src-tauri && cargo clippy --quiet(passes with existing warnings)cd packages/desktop && bun test src/lib/acp/components/agent-panel/logic/__tests__/pre-session-worktree-card-visibility.test.tsDeferred
Move session changesremains disabled. It should build on the same backend switch command after adding ownership-proof and transfer preflight.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com