Skip to content

Add Amp to the Vault (Session Index) sidebar - #5420

Closed
comp615 wants to merge 32 commits into
manaflow-ai:mainfrom
comp615:charlie/amp-vault-session-index-v2
Closed

comp615 wants to merge 32 commits into
manaflow-ai:mainfrom
comp615:charlie/amp-vault-session-index-v2

Conversation

@comp615

@comp615 comp615 commented Jun 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds Amp (Sourcegraph Amp CLI) to the Vault (Session Index) sidebar, so Amp threads can be browsed, searched, and resumed alongside Claude Code, Codex, Grok, OpenCode, Rovo Dev, and Hermes. Amp was already a restorable agent (auto-relaunch on app start); this brings it to parity in the past-sessions UI.

image

Demo image illustrates the progression from fallback -> first message -> title observing

Why the hook store (not Amp's thread files)

Amp threads now live server-side. The legacy ~/.local/share/amp/threads/*.json store is abandoned (stale for over a month locally), so this reads Amp sessions from cmux's own hook store ~/.cmuxterm/amp-hook-sessions.json — written by the bundled Amp plugin via cmux hooks amp. That store is current, cmux-owned, and already powers the restore flow.

Titles

The hook store carries no conversation title on its own, so the bundled Amp plugin supplies one. It reads the real thread title from the Amp plugin API (ctx.thread.title) and subscribes to it, so a title that Amp generates asynchronously reaches cmux even for single-turn threads. It falls back to the first user message on older Amp versions whose plugin API predates thread.title, and finally to a cwd-derived label (Amp session in <dir>). The CLI persists whatever title it receives and the Vault prefers it — where the title comes from is the plugin's concern. This avoids parsing Amp's unstable debug logs.

Changes

  • Sources/AmpSessionIndex.swift — read-only scanner for the Amp hook store (sort, needle + cwd filtering, pagination), preferring the stored title and synthesizing a cwd label otherwise
  • SessionAgent.amp + AgentSpecifics.amp with resume amp threads continue <id>
  • Store dispatch, presentation (display name + official Amp icon asset), localized strings (en/ja)
  • CLI/CMUXCLI+AmpExtension.swift — plugin resolves the thread title via ctx.thread.title (get + subscribe) with first-message/cwd fallback, and prefers the app-bundled cmux for hooks
  • CLI/cmux.swift — persists a generic title field on the hook session record without clobbering an existing one
  • Tests: scanner parsing/sorting/cwd-filter/resume/malformed-store (cmuxTests/AmpSessionIndexTests.swift) and end-to-end title persistence (cmuxTests/CLIGenericHookPersistenceTests.swift)

Verification

  • Rebased on latest main; cmux app target and cmux-unit test target both compile (build-for-testing → TEST BUILD SUCCEEDED).
  • Title flow (real title, subscription upgrade for single-turn threads, and cwd fallback) verified end-to-end in a local tagged dev build.
  • Tests not run locally per repo policy — relying on CI.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Adds Amp to the Vault (Session Index) so you can browse, search, preview, and resume Amp threads alongside other agents. Sessions are read from ~/.cmuxterm/amp-hook-sessions.json, and titles update live via the plugin when available.

  • New Features

    • Amp appears in the sidebar with icon and localized name (en/ja).
    • Lists sessions from the hook store with search, CWD filter, stable sort, and pagination.
    • Resume preserves captured launch context (cwd/env/flags); otherwise falls back to: amp threads continue .
    • Titles resolve via ctx.thread.title (get + subscribe) with fallback to the first user message, then a CWD label. CLI persists title; the plugin prefers the app-bundled cmux (fallback to PATH).
  • Bug Fixes

    • New title-update hook; updates are debounced, length-capped, timeout-guarded (stale results ignored), epoch- and turn-gated, sent monotonically, never replace with empty values; observers cleaned up on stop/exit; pending titles flush at turn end.
    • Deterministic listing via secondary sort by sessionId; Amp CWDs normalized; per-record decode skips bad entries; store-read errors are sanitized and localized; fixed directory-title placeholder rendering; reject integer keys in the hook store.
    • Amp session transcript previews now parse and render in the Session Index.

Written for commit 66f1425. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Amp added as a supported session agent with icon and localized UI strings.
    • Session indexing, search, and resume support for Amp sessions; listings show persisted or synthesized titles and cwd-derived context.
    • Session titles can be resolved live, captured, and included in session start/resume payloads while a turn is active.
  • Bug Fixes / Improvements

    • Title updates avoid overwriting existing titles with empty values.
  • Tests

    • Added tests for Amp indexing, persistence, resume, and title handling.

@vercel

vercel Bot commented Jun 5, 2026

Copy link
Copy Markdown

@comp615 is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds end-to-end Amp session support: agent modeling/presentation, hook-store indexing, optional title capture/persistence in CLI hook flows, transcript parsing alignment, localization and icon asset, tests, and Xcode wiring.

Changes

Amp session support across CLI, index, and UI

Layer / File(s) Summary
Agent contracts and presentation
Sources/SessionIndexModels.swift, Sources/SessionAgentPresentation.swift, Resources/Localizable.xcstrings, Assets.xcassets/AgentIcons/Amp.imageset/Contents.json, cmuxTests/SessionIndexViewTests.swift
Registers .amp in session models/specifics and resume-command generation; maps display name and asset for Amp, adds localization keys, asset metadata, and updates test defaults.
Hook title capture and conditional persistence
CLI/CMUXCLI+AmpExtension.swift, CLI/cmux.swift, cmuxTests/CLIGenericHookPersistenceTests.swift
Adds cmuxBin() resolution, observes and resolves per-thread titles, caches and subscribes to title updates, emits guarded session-start/prompt-submit hooks with optional title only while a turn is active, propagates title through Claude hook parsing and record updates, and ensures only non-empty normalized titles overwrite stored titles; includes persistence test.
Amp hook-store indexing and search
Sources/AmpSessionIndex.swift, Sources/SessionIndexStore.swift, cmuxTests/AmpSessionIndexTests.swift, cmux.xcodeproj/project.pbxproj
Implements loadAmpEntries reading amp-hook-sessions.json: tolerant decoding, cwd normalization, modified-date derivation, sorting, needle/cwd filtering, pagination, title synthesis/fallback, DEBUG test helper, unit tests, and Xcode target wiring.
Amp transcript parsing alignment
Sources/SessionIndexView.swift
Routes .amp to the same generic transcript parsing, raw-line parsing eligibility, and inferred-role behavior as .hermesAgent.

Sequence Diagram(s)

sequenceDiagram
  participant AmpExtension
  participant CmuxCLI
  participant SessionIndexStore
  participant HookStoreFile
  AmpExtension->>CmuxCLI: emit prompt-submit / session-start (may include title)
  CmuxCLI->>SessionIndexStore: parse hook input and update record (title optional)
  SessionIndexStore->>HookStoreFile: read amp-hook-sessions.json
  SessionIndexStore->>HookStoreFile: derive modified, normalize cwd
  CmuxCLI->>SessionIndexStore: loadAmpEntries (search/pagination)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I found an Amp trail bright and new,
with titles tucked in morning dew.
I hopped through hooks and JSON streams,
and sorted sessions into dreams.
“Continue the thread!” I hum, with cheery schemes.


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Cmux Swift Actor Isolation ❓ Inconclusive No result was produced after verification. Marking as INCONCLUSIVE. Re-run the check or adjust instructions to produce a final result.
✅ Passed checks (17 passed)
Check name Status Explanation
Title check ✅ Passed The PR title directly and clearly summarizes the primary change: adding Amp to the Vault session index sidebar for browsing and resuming Amp threads.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Blocking Runtime ✅ Passed No new blocking/timing synchronization introduced. AmpSessionIndex has no blocking patterns, title handling is non-blocking, pre-existing Task.sleep/locks allowed per rules.
Cmux No Hacky Sleeps ✅ Passed PR modifies only Swift source/test files, Xcode project wiring, asset JSON, and localization; no TypeScript, JavaScript, shell, or Python runtime changes. Check excludes Swift per rule scope.
Cmux Algorithmic Complexity ✅ Passed loadAmpEntries uses O(n log n) sorting on bounded sessions; no nested scans, per-target rescans, or unbounded operations violating algorithmic-complexity.md rules.
Cmux Swift Concurrency ✅ Passed PR introduces no legacy async patterns: new AmpSessionIndex uses synchronous nonisolated methods, cmux.swift changes only add title parameters, and all test code follows standard patterns.
Cmux Swift @Concurrent ✅ Passed loadAmpEntries follows existing pattern of loadOpenCodeEntries/loadRovoDevEntries: nonisolated sync file I/O called from searchAgent. No new @concurrent violations introduced by this PR.
Cmux Swift File And Package Boundaries ✅ Passed AmpSessionIndex.swift (210 lines) has single responsibility matching RovoDevIndex precedent. CMUXCLI+AmpExtension uses embedded TypeScript. All PR files comply with boundary rules.
Cmux Swift Logging ✅ Passed All print statements in CLI/CMUXCLI+AmpExtension.swift are CLI output for hook setup commands (allowed). No unguarded logging in runtime code; no secrets exposed; DEBUG helpers properly guarded.
Cmux User-Facing Error Privacy ✅ Passed All user-facing error messages comply: sanitized text with no internal details, env vars only in plugin code, secrets stripped, file paths appropriate for user-initiated commands.
Cmux Full Internationalization ✅ Passed New Localizable.xcstrings keys have en/ja translations following CLAUDE.md standard; String(localized:defaultValue:) API used correctly throughout.
Cmux Swiftui State Layout ✅ Passed No SwiftUI state violations: AmpSessionIndex is data-only, CLI changes are data models only, and SessionIndexView adds .amp cases to existing switch statements with no new state patterns.
Cmux Architecture Rethink ✅ Passed PR introduces legitimate required platform bridge (Amp plugin→cmux hook) with clear ownership, single source of truth, and documented invariants. No timing repairs or split state ownership.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR adds Amp session indexing. Only NSWindow found is a test-only fixture in cmuxTests/SessionIndexViewTests.swift (allowed). No production windows without cmux.* identifiers. Lint script passed.
Cmux Source Artifacts ✅ Passed All 13 changed files are hand-written source/test code, build configs, or localization catalogs—no generated artifacts, local tool output, caches, or temp folders detected.
Description check ✅ Passed The pull request description includes a comprehensive summary, clear motivation (why the hook store vs. legacy files), detailed change list, and verification steps. All major sections of the template are addressed.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 5, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds Amp (Sourcegraph Amp CLI) as a first-class agent in the Vault sidebar, reading sessions from cmux's own hook store (~/.cmuxterm/amp-hook-sessions.json) rather than Amp's now-abandoned local thread files. The Amp plugin is upgraded to v3 to push live thread titles via a new title-update hook subcommand, with debouncing, subscription-based updates, and epoch-guarded cancellation so late async lookups cannot revive a finished turn as "running."

  • New session index: AmpSessionIndex.swift (+ 5 supporting model files) reads, sorts, filters, and paginates Amp hook-store records; per-record decode skips type-drifted entries without blanking the listing; trustedAmpLaunchCommand validates the captured launch context before building enriched resume commands.
  • Title pipeline: the Amp plugin subscribes to ctx.thread.title, debounces updates at 250 ms, guards against stale async lookups via turnEpoch/sessionStartEpoch counters, and flushes/cleans up on stop; the Swift side persists only non-empty titles, never overwriting an existing title with nil.
  • Parity wiring: SessionAgent.amp, AgentSpecifics.amp, icon asset, and localized strings (en + ja) registered across presentation, transcript-preview, and resume-command paths.

Confidence Score: 5/5

Safe to merge — all three bugs flagged in earlier rounds are confirmed fixed, and the new title pipeline is well-guarded against late async races.

The epoch-based cancellation, debounce, subscription cleanup, per-record resilient JSON decoding, and explicit nil-guards on title persistence each close a specific failure mode. The normalizedTitleUpdate Swift side mirrors the TypeScript truncation limits. Localization is complete for both supported locales. Tests cover store parsing, cwd filtering, untrusted launch command rejection, title preference, type-drifted record skipping, and end-to-end CLI title persistence.

No files require special attention. CLI/CMUXCLI+AmpExtension.swift at 824 lines just crosses the 800-line budget threshold but is explicitly tracked and updated in the budget TSV.

Important Files Changed

Filename Overview
CLI/CMUXCLI+AmpExtension.swift Grows from 520→824 lines (tracked in budget); adds title tracking with debouncing (250ms), subscription-based live updates, epoch-based cancellation guards, and cmuxBin() helper that prefers CMUX_BUNDLED_CLI_PATH over PATH.
Sources/AmpSessionIndex.swift New 164-line nonisolated scanner for the Amp hook store; synchronous disk read follows the same pattern as loadOpenCodeEntries/loadRovoDevEntries; per-record decoding skips bad entries without blanking the list.
CLI/cmux.swift Adds title field to ClaudeHookSessionRecord and ClaudeHookParsedInput; adds .titleUpdate case that upserts title without touching lifecycle or runtimeStatus; normalizedTitleUpdate mirrors TypeScript truncation at 200 chars.
Sources/AmpHookSessionStoreFile.swift Resilient per-record JSON decode that skips type-drifted entries without blanking the whole listing; AmpHookSessionStoreKey rejects integer keys via init?(intValue:) returning nil.
Sources/SessionIndexModels.swift Adds .amp case to SessionAgent and AgentSpecifics; resume command prefers AgentResumeCommandBuilder with captured launch context, falls back to plain amp threads continue <id>.
cmuxTests/AmpSessionIndexTests.swift Covers store parsing, sort order, cwd filter, resume command building, untrusted launch command rejection, record title preference, type-drifted record skip, and missing/malformed store.
cmuxTests/AmpHookTitlePersistenceTests.swift End-to-end test that runs the actual CLI binary against a mock Unix socket server and verifies title is persisted to amp-hook-sessions.json.
tests/test_amp_extension_install.py Adds title subscription and await new Promise(resolve => setTimeout(resolve, 350)) to let the 250ms debounce fire; verifies that subscribed title takes precedence over async get() result.
Resources/Localizable.xcstrings Adds sessionIndex.agent.amp, sessionIndex.amp.title, sessionIndex.amp.titleInDirectory, and sessionIndex.error.ampStoreRead, each with en and ja translations matching the catalog's supported locales.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Amp as Amp Process
    participant Plugin as Amp Plugin (TS)
    participant CLI as cmux CLI
    participant Store as amp-hook-sessions.json
    participant Vault as Session Index (Swift)

    Amp->>Plugin: session.start event
    Plugin->>Plugin: watchThreadTitle(sessionId)
    Plugin->>CLI: "hooks amp session-start {session_id, title?}"
    CLI->>Store: upsert(agentLifecycle: .unknown, title?)

    Amp->>Plugin: agent.start event
    Plugin->>CLI: "hooks amp prompt-submit {session_id, title?}"
    CLI->>Store: upsert(agentLifecycle: .running, title?)
    Plugin-->>Plugin: resolveSessionTitleBestEffort() [async, epoch-guarded]

    Note over Plugin: thread.title observable fires
    Plugin->>Plugin: debounce 250ms
    Plugin->>CLI: "hooks amp title-update {session_id, title}"
    CLI->>Store: upsert(title only, no lifecycle change)

    Amp->>Plugin: agent.end event
    Plugin->>Plugin: "turnActive=false, turnEpoch++, sessionStartEpoch++"
    Plugin->>CLI: "hooks amp stop {session_id}"
    Plugin-->>Plugin: resolveSessionTitleBestEffort() [final, if no observed title]
    Plugin->>CLI: "hooks amp title-update {session_id, title} [if new]"
    Plugin->>Plugin: cleanupThreadTitle(sessionId)

    Note over Vault: User opens Vault sidebar
    Vault->>Store: loadAmpEntries(needle, cwdFilter, offset, limit)
    Store-->>Vault: [AmpIndexedSession]
    Vault->>Vault: sort by updatedAt desc, sessionId asc
    Vault-->>Vault: render SessionEntry list
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Amp as Amp Process
    participant Plugin as Amp Plugin (TS)
    participant CLI as cmux CLI
    participant Store as amp-hook-sessions.json
    participant Vault as Session Index (Swift)

    Amp->>Plugin: session.start event
    Plugin->>Plugin: watchThreadTitle(sessionId)
    Plugin->>CLI: "hooks amp session-start {session_id, title?}"
    CLI->>Store: upsert(agentLifecycle: .unknown, title?)

    Amp->>Plugin: agent.start event
    Plugin->>CLI: "hooks amp prompt-submit {session_id, title?}"
    CLI->>Store: upsert(agentLifecycle: .running, title?)
    Plugin-->>Plugin: resolveSessionTitleBestEffort() [async, epoch-guarded]

    Note over Plugin: thread.title observable fires
    Plugin->>Plugin: debounce 250ms
    Plugin->>CLI: "hooks amp title-update {session_id, title}"
    CLI->>Store: upsert(title only, no lifecycle change)

    Amp->>Plugin: agent.end event
    Plugin->>Plugin: "turnActive=false, turnEpoch++, sessionStartEpoch++"
    Plugin->>CLI: "hooks amp stop {session_id}"
    Plugin-->>Plugin: resolveSessionTitleBestEffort() [final, if no observed title]
    Plugin->>CLI: "hooks amp title-update {session_id, title} [if new]"
    Plugin->>Plugin: cleanupThreadTitle(sessionId)

    Note over Vault: User opens Vault sidebar
    Vault->>Store: loadAmpEntries(needle, cwdFilter, offset, limit)
    Store-->>Vault: [AmpIndexedSession]
    Vault->>Vault: sort by updatedAt desc, sessionId asc
    Vault-->>Vault: render SessionEntry list
Loading

Reviews (16): Last reviewed commit: "fix: guard Amp title lookup timeouts" | Re-trigger Greptile

Comment thread CLI/CMUXCLI+AmpExtension.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/AmpSessionIndex.swift`:
- Around line 89-90: Sorting only by modified in indexed.sort { $0.modified >
$1.modified } is unstable when timestamps tie; update the comparator to add a
deterministic secondary key (e.g., compare sessionId) so equal modified values
are ordered consistently (for example: if $0.modified == $1.modified then
compare $0.sessionId and $1.sessionId). Ensure the comparator preserves the
intended descending modified order and uses a stable tie-breaker like sessionId
to prevent pagination (offset/limit) skips/duplicates.

In `@Sources/SessionIndexView.swift`:
- Around line 1499-1500: The .amp case is currently returning nil in the
parser/inference branch, which causes Amp lines to be rejected
(shouldParseRawLine == false, parseLine == nil, inferredRole == nil) and empty
previews; fix by either (A) removing .amp from the case that returns nil so .amp
falls through to the generic parser/inference path used by
loadSynchronously(...) (ensuring shouldParseRawLine, parseLine and inferredRole
are populated), or (B) add an Amp-specific loading path in load(entry:) before
the hermesAgent routing so .amp is handled by its own loader; update the
switch/case handling and load(entry:) routing accordingly (referencing case
.amp, case .hermesAgent, load(entry:), loadSynchronously(...),
shouldParseRawLine, parseLine, inferredRole).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8c112ee1-1311-4a64-85db-491b44416433

📥 Commits

Reviewing files that changed from the base of the PR and between 087309a and e35caa7.

⛔ Files ignored due to path filters (1)
  • Assets.xcassets/AgentIcons/Amp.imageset/Amp.svg is excluded by !**/*.svg
📒 Files selected for processing (13)
  • Assets.xcassets/AgentIcons/Amp.imageset/Contents.json
  • CLI/CMUXCLI+AmpExtension.swift
  • CLI/cmux.swift
  • Resources/Localizable.xcstrings
  • Sources/AmpSessionIndex.swift
  • Sources/SessionAgentPresentation.swift
  • Sources/SessionIndexModels.swift
  • Sources/SessionIndexStore.swift
  • Sources/SessionIndexView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/AmpSessionIndexTests.swift
  • cmuxTests/CLIGenericHookPersistenceTests.swift
  • cmuxTests/SessionIndexViewTests.swift

Comment thread Sources/AmpSessionIndex.swift Outdated
Comment thread Sources/SessionIndexView.swift Outdated
comp615 added a commit to comp615/cmux that referenced this pull request Jun 5, 2026
- Guard turnActive after title resolution in agent.start so a late
  prompt-submit can't revive a finished session as running (greptile P1)
- Stable secondary sort by sessionId for equal modified timestamps to
  keep Vault pagination deterministic (coderabbit)
- Localize the Amp store-read error via xcstrings (en/ja)

Amp-Thread-ID: https://ampcode.com/threads/T-019e93a5-4b13-747c-9098-5f3117736ab0
Co-authored-by: Amp <amp@ampcode.com>
@comp615

comp615 commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai help

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

CodeRabbit commands

These commands are invoked using PR/Issue comments.

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai rate limit to show your current review rate limit status.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai evaluate custom pre-merge check --instructions <custom-checks-instructions> --name <custom-checks-title> [--mode <error|warning>] to validate the custom pre-merge checks instructions. Defaults to error when --mode is omitted.
  • @coderabbitai ignore pre-merge checks to override pre-merge checks and get an approval on PR.
  • @coderabbitai run pre-merge checks to run pre-merge checks on the pull request.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai emit path instructions to emit generated path-specific review instructions for this repository.
  • @coderabbitai resolve merge conflict to automatically resolve merge conflicts.
  • @coderabbitai autofix to automatically fix issues identified in unresolved review comments.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai generate configuration to create a PR that adds the current resolved configuration as .coderabbit.yaml (or show it if already present).
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, support, documentation and community

  • Visit our status page to check the current availability of CodeRabbit.
  • Create a ticket on our support page for assistance with any issues or questions.
  • Visit our documentation site for detailed information on how to use CodeRabbit.
  • Join our Discord community to connect with other users and get help from the community.
  • Follow us on X/Twitter for updates and announcements.

comp615 and others added 7 commits June 5, 2026 10:09
Amp threads now live server-side, so the legacy ~/.local/share/amp/threads
JSON store is abandoned. Read Amp sessions from cmux's own hook store
(~/.cmuxterm/amp-hook-sessions.json, written by the bundled Amp plugin)
so they appear in the Vault alongside Claude, Codex, Grok, etc.

- New Sources/AmpSessionIndex.swift scanner + AmpSessionIndexTests
- SessionAgent.amp + AgentSpecifics.amp (resume: amp threads continue <id>)
- Store dispatch, presentation, icon asset, localized strings (en/ja)
- Titles are synthesized from the cwd since Amp exposes no local title

Amp-Thread-ID: https://ampcode.com/threads/T-019e93a5-4b13-747c-9098-5f3117736ab0
Co-authored-by: Amp <amp@ampcode.com>
Prefer the real thread title via the Amp plugin API (ctx.thread.title),
subscribing so async title generation reaches cmux even for single-turn
threads. Falls back to the first user message on older Amp versions whose
plugin API predates thread.title.

Amp-Thread-ID: https://ampcode.com/threads/T-019e93a5-4b13-747c-9098-5f3117736ab0
Co-authored-by: Amp <amp@ampcode.com>
- Don't revive an idle session: gate the title-change subscription on
  turnActive so a title that finalizes after the turn ends can't re-fire
  the session-start hook (which marks the session running).
- Normalize Amp cwd with standardizingPath to match
  SessionIndexStore.normalizedDirectory, so entries bucket/scope-filter
  consistently with other agents.
- Drop the absolute store path from the user-facing read error (filename
  only), matching the OpenCode/Codex error style.
- Tests: assert shell-quoting with a whitespace-containing id instead of
  echoing SessionEntry.shellQuote; fail fast on unexpected mock RPC
  methods.

Amp-Thread-ID: https://ampcode.com/threads/T-019e93a5-4b13-747c-9098-5f3117736ab0
Co-authored-by: Amp <amp@ampcode.com>
The Vault renders SessionIndex errors in-UI, so per
.github/review-bot-rules/user-facing-errors.md the message must not carry
raw decode details. Drop error.localizedDescription; keep the filename
(no absolute path).

Amp-Thread-ID: https://ampcode.com/threads/T-019e93a5-4b13-747c-9098-5f3117736ab0
Co-authored-by: Amp <amp@ampcode.com>
- Guard turnActive after title resolution in agent.start so a late
  prompt-submit can't revive a finished session as running (greptile P1)
- Stable secondary sort by sessionId for equal modified timestamps to
  keep Vault pagination deterministic (coderabbit)
- Localize the Amp store-read error via xcstrings (en/ja)

Amp-Thread-ID: https://ampcode.com/threads/T-019e93a5-4b13-747c-9098-5f3117736ab0
Co-authored-by: Amp <amp@ampcode.com>
User-facing copy shouldn't leak the internal hook-store filename
(.github/review-bot-rules/user-facing-errors.md). State the failure in
product terms instead.

Amp-Thread-ID: https://ampcode.com/threads/T-019e93a5-4b13-747c-9098-5f3117736ab0
Co-authored-by: Amp <amp@ampcode.com>
@comp615
comp615 force-pushed the charlie/amp-vault-session-index-v2 branch from df06bbf to 8f34725 Compare June 5, 2026 14:14
Comment thread Sources/AmpSessionIndex.swift
String(localized:defaultValue:) returns the catalog value as-is, so the
%@ placeholder was never substituted outside unit tests (where the
defaultValue's Swift interpolation masked it). Wrap with String(format:)
like other %@ catalog callers.

Amp-Thread-ID: https://ampcode.com/threads/T-019e93a5-4b13-747c-9098-5f3117736ab0
Co-authored-by: Amp <amp@ampcode.com>
@comp615

comp615 commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

All review threads (Greptile P1s + CodeRabbit findings) are resolved as of 015711270. One open item to flag for the pre-merge "Full Internationalization" check:

Localization scope — en/ja is the documented standard, not all 20 catalog locales. The repo's own agent guidance in AGENTS.md / CLAUDE.md (line 242) states:

"Keys go in Resources/Localizable.xcstrings with translations for all supported languages (currently English and Japanese)."

The other ~18 locales present in the catalog are partial legacy backfills (e.g. de 1208/2707, km 255/2707 keys), not officially supported. The most recent merged precedent (60256915a, "localize notif strings") added new keys en/ja-only, same as this PR. Backfilling all locales is done as separate, dedicated commits when someone opts in (e.g. 350d87d29), not as a per-PR requirement.

So the 4 new Amp keys are fully localized per the project standard. Could you please treat the "all catalog locales" requirement as satisfied by en/ja here, consistent with AGENTS.md?

🤖 (comment drafted by an AI assistant)

@coderabbitai

coderabbitai Bot commented Jun 5, 2026 •

Copy link
Copy Markdown

The PR description image shows the Vault sidebar ("By agent" view) with three collapsed sections — Claude Code, Codex, and Amp — each displaying session titles and recency timestamps. The Amp section lists five entries ("Successful test thread", "Debug AMP titles in Vault UI", "Can you set a test title for this?", "Amp session in cmux-fork", "Amp session in android-register") with red/orange Amp icons, confirming end-to-end title resolution and display is working correctly.


@comp615 Understood — and your argument is exactly consistent with the long-term learnings already in my knowledge base for this repo:

In Resources/Localizable.xcstrings, the only required locales for newly added keys are English (en) and Japanese (ja), as documented in CLAUDE.md. Keys with additional locales are populated by a separate batch-translation pass and are NOT a requirement for newly added keys.

The 4 new Amp keys (sessionIndex.agent.amp, sessionIndex.amp.title, sessionIndex.amp.titleInDirectory, sessionIndex.error.ampStoreRead) with en+ja entries satisfy the project's localization standard. I'll treat the "all catalog locales" pre-merge check as satisfied here.

Triggering a full review now with that localization scope in mind.

Please treat the new Resources/Localizable.xcstrings entries (sessionIndex.agent.amp, sessionIndex.amp.title, sessionIndex.amp.titleInDirectory, sessionIndex.error.ampStoreRead) as fully localized — en+ja is the project-documented standard per CLAUDE.md and established catalog precedent. The "full internationalization" pre-merge check should pass for these keys.


🧠 Learnings used
Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-02T22:33:31.386Z
Learning: Applies to **/{*.swift,*.plist,**/*.{ts,tsx,js,jsx},*.md,web/i18n/routing.ts,web/messages/**} : Fail when diffs to production changes violate `.github/review-bot-rules/full-internationalization.md`: user-facing Swift text must use `String(localized:defaultValue:)` or an equivalent localized API with a matching translated string-catalog entry, app string catalog or Info.plist additions and edits must include translated entries for every locale already supported by the touched catalog, and web UI, metadata, API response, rendered markdown, changelog, or user-facing data changes must read from `next-intl` or another locale-specific source and update every locale listed in `web/i18n/routing.ts` with matching `web/messages/` entries

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-05T06:21:41.655Z
Learning: Applies to **/*.{swift,ts,tsx,js,jsx,plist} : For production changes, fail when diffs violate `.github/review-bot-rules/full-internationalization.md`: user-facing Swift text must use `String(localized:defaultValue:)` or equivalent localized API with matching translated string-catalog entry, app string catalog or Info.plist additions and edits must include translated entries for every locale already supported, and web UI, metadata, API response, rendered markdown, changelog, or user-facing data changes must read from `next-intl` or locale-specific source and update every locale listed in `web/i18n/routing.ts` with matching `web/messages/` entries

Learnt from: nanami-he
Repo: manaflow-ai/cmux PR: 4633
File: Resources/Localizable.xcstrings:38310-38310
Timestamp: 2026-05-23T08:40:54.816Z
Learning: In the manaflow-ai/cmux repository, the only required locales for newly added keys in `Resources/Localizable.xcstrings` are **English (`en`) and Japanese (`ja`)**. This is explicitly documented in `CLAUDE.md`: "Keys go in `Resources/Localizable.xcstrings` with translations for all supported languages (currently English and Japanese)." Approximately 42% of catalog keys (886 of 2086) carry only `en`+`ja`. Keys with additional locales (up to ~19) are populated by a separate batch-translation pass and are NOT a requirement for newly added keys. Do NOT flag `en`+`ja`-only entries as incomplete or partial localization.

Learnt from: nanami-he
Repo: manaflow-ai/cmux PR: 4633
File: Resources/Localizable.xcstrings:38310-38310
Timestamp: 2026-05-23T08:40:54.816Z
Learning: In the manaflow-ai/cmux repository, the only required locales for newly added keys in `Resources/Localizable.xcstrings` are **English (`en`) and Japanese (`ja`)**. This is explicitly documented in `CLAUDE.md` ("Keys go in `Resources/Localizable.xcstrings` with translations for all supported languages (currently English and Japanese)"). Approximately 42% of catalog keys carry only `en`+`ja`. Keys with additional locales (up to 19) are populated by a separate batch-translation pass and are NOT a requirement for newly added keys. Do NOT flag `en`+`ja`-only entries as incomplete localization.

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-06-05T05:21:04.581Z
Learning: Applies to Resources/Localizable.xcstrings : Localization audit is required for every user-facing change. Before finishing a task that changes UI, Settings rows, menus, shortcut metadata, schema/config text, docs, command/help text, alerts, or tooltips, enumerate the changed surfaces and verify each one has entries for every supported locale. `defaultValue`, English fallback text, schema descriptions, or copied English strings do not count as localization. For Swift/AppKit strings, update `Resources/Localizable.xcstrings`. For localized web/docs content, update `web/messages/en.json` and `web/messages/ja.json`. Parse touched localization files, compare changed keys across locales, and use `rg` to find newly introduced bare English. The final handoff must state what localization audit was performed.

Learnt from: HamptonMakes
Repo: manaflow-ai/cmux PR: 4443
File: Sources/cmuxApp.swift:6678-6695
Timestamp: 2026-05-22T15:04:55.554Z
Learning: In manaflow-ai/cmux, agent/automation settings strings (settings.automation.*) follow AGENTS.md, which scopes supported locales to English and Japanese; sibling toggles on main (Cursor/Gemini) also include Korean. For new entries like settings.automation.amp.*, matching en/ja/ko is acceptable and we should not require expansion to all app locales in the touched catalog unless maintainers request it.

Learnt from: austinywang
Repo: manaflow-ai/cmux PR: 5178
File: web/data/cmux-shortcuts.ts:223-227
Timestamp: 2026-06-02T08:18:29.897Z
Learning: In the manaflow-ai/cmux project, `LocalizedText` in `web/data/cmux-shortcuts.ts` is intentionally typed as `{ en: string; ja: string }` — every shortcut entry in that file provides only English and Japanese descriptions. The keyboard-shortcuts docs renderer has an explicit English fallback for all other locales. This is the established design for the entire shortcuts data file. Reviewers should NOT flag individual shortcut entries for missing locale coverage beyond en/ja in this file; extending to additional locales would require a separate project-wide change to the shortcuts i18n system. The native macOS Settings UI label localization (via Localizable.xcstrings) is separate and does cover all supported catalog locales.

Learnt from: gaelic-ghost
Repo: manaflow-ai/cmux PR: 2262
File: Resources/Localizable.xcstrings:84820-84835
Timestamp: 2026-03-27T22:00:27.420Z
Learning: Repo: manaflow-ai/cmux — In `Resources/Localizable.xcstrings`, it is intentional for lower-confidence locales (e.g., ar, bs, da, pl, th, km, tr) to carry English-language fallback `stringUnit.value` strings with `state: "translated"` for newly added keys. This matches the existing `.xcstrings` catalog convention for the project; do not flag English values with state "translated" in these locales as a localization bug or suggest changing the state to "needs review" / "untranslated".

Learnt from: atani
Repo: manaflow-ai/cmux PR: 819
File: Sources/AppDelegate.swift:3491-3493
Timestamp: 2026-03-04T14:06:16.241Z
Learning: For manaflow-ai/cmux PR `#819` (Japanese i18n), keep scope limited to localization changes; UX enhancements like preferring workspace.customTitle in workspaceDisplayName() or altering move-target labels should be handled in a separate follow-up issue.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3393
File: web/messages/zh-TW.json:0-0
Timestamp: 2026-05-01T08:41:57.216Z
Learning: Repo: manaflow-ai/cmux — In `web/messages/*.json` locale files, the `docs.dock.agentPrompt` key is intentionally kept in English across all locales (including high-confidence locales like zh-TW, ja, ko, de, fr, etc.) because it is a verbatim prompt designed to be copied into coding agents. Do not flag the English value of `agentPrompt` as a missing translation for any locale. Only `agentPromptIntro` and all other surrounding dock doc strings are expected to be translated for high-confidence locales.

Learnt from: HamptonMakes
Repo: manaflow-ai/cmux PR: 4443
File: Resources/Localizable.xcstrings:59654-59745
Timestamp: 2026-05-21T21:34:34.427Z
Learning: For `settings.automation.*` integration-toggle keys in `Resources/Localizable.xcstrings` (e.g., `settings.automation.cursor`, `settings.automation.gemini`, `settings.automation.amp` and their `.note`, `.subtitleOff`, `.subtitleOn` sub-keys), the established repo pattern is to provide only `en`, `ja`, and `ko` locales with `extractionState: "manual"` and `state: "translated"`. Do NOT flag these as partial-localization violations — the en/ja/ko-only set is intentional for automation integration settings and matches the existing sibling-key precedent.

Learnt from: austinywang
Repo: manaflow-ai/cmux PR: 3971
File: Resources/Localizable.xcstrings:64948-64951
Timestamp: 2026-05-13T21:22:34.162Z
Learning: In `Resources/Localizable.xcstrings` for the `manaflow-ai/cmux` repo, `settings.betaFeatures.*` localization keys (e.g., `settings.betaFeatures.dock`, `settings.betaFeatures.feed`, and their subtitle/warning variants) intentionally include only English ("en") and Japanese ("ja") locales while the feature is in beta. Do not flag the absence of other locales for these beta feature keys as a localization gap — this is the established convention for beta-gated features in this project.

Learnt from: comp615
Repo: manaflow-ai/cmux PR: 5420
File: Sources/SessionIndexView.swift:1499-1500
Timestamp: 2026-06-05T13:30:21.464Z
Learning: In `Sources/SessionIndexView.swift` (manaflow-ai/cmux), the `.amp` case in `SessionTranscriptLoader`'s `parseLine`, `shouldParseRawLine`, and `inferredRole` switches intentionally returns `nil`/`false`. Amp sessions are indexed from the cmux plugin hook-store (`~/.cmuxterm/amp-hook-sessions.json`) which holds only session metadata and title — no per-message transcript file exists on disk. As a result, `SessionEntry.fileURL` is always `nil` for Amp entries, `load(entry:)` throws `.missingFile` before any parser branch is reached, and the UI correctly shows the "No transcript file" graceful state. The `.amp` switch branches are pure exhaustiveness guards. Do not flag them as dead code or suggest routing `.amp` through the generic file-based parser.

Learnt from: comp615
Repo: manaflow-ai/cmux PR: 5366
File: Sources/AmpSessionIndex.swift:0-0
Timestamp: 2026-06-05T02:13:27.941Z
Learning: In `Sources/AmpSessionIndex.swift` (manaflow-ai/cmux), the `ErrorBag` message for a failed Amp hook-store read is `"Amp: cannot read amp-hook-sessions.json"` — filename only, no absolute path, and no `error.localizedDescription` or raw decode detail. This is intentional: the Vault sidebar renders `SessionIndex` errors directly in-UI, so the message must comply with `user-facing-errors.md` (no implementation leaks). Other agent loaders (OpenCode, Codex) follow the same filename-only pattern.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2964
File: Sources/ContentView.swift:0-0
Timestamp: 2026-04-17T21:35:30.619Z
Learning: Repo: manaflow-ai/cmux — Session resume behavior: generate commands with a guaranteed cwd guard. In Sources/SessionIndexStore.swift, SessionEntry exposes a helper (e.g., resumeCommandWithCwd) that produces 'cd <shell-quoted cwd> && <resumeCommand>', and all call sites (clipboard, drag‑drop terminal, in‑app resume) should use this form so fresh shells and rc files cannot land outside the intended directory.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2525
File: Sources/GhosttyTerminalView.swift:481-513
Timestamp: 2026-04-02T10:13:39.235Z
Learning: Repo: manaflow-ai/cmux — In Sources/GhosttyTerminalView.swift, terminal file-link resolution trims trailing unmatched closing delimiters “) ] } >” only when they are dangling (more closers than openers), preserving wrapped tokens like “(file:///tmp/a.png)”. Implemented via terminalFileLinkTrailingClosingDelimiters and count comparison inside trimTrailingTerminalFileLinkPunctuation(_:) and exercised by a regression test (PR `#2525`, commit 3f5c5b6d).

Learnt from: austinywang
Repo: manaflow-ai/cmux PR: 5428
File: Sources/Panels/BrowserPanel.swift:4738-4744
Timestamp: 2026-06-05T04:14:05.292Z
Learning: Repo: manaflow-ai/cmux PR `#5428` / branch issue-5425-favicon-default-icon — In Sources/Panels/BrowserPanel.swift for this branch, `BrowserPanel` does not have a `pickerMessageHandler` symbol, and `ReactGrabMessageHandler` has no workspace-id update API. Do not suggest adding `pickerMessageHandler?.updateWorkspaceId(...)` calls here. Workspace transitions relevant to the favicon fix should invalidate/re-resolve the favicon cache partition; existing BrowserPanel closures read `workspaceId` dynamically.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2978
File: Sources/Workspace.swift:0-0
Timestamp: 2026-04-22T08:13:39.699Z
Learning: Repo: manaflow-ai/cmux — In Sources/RestorableAgentSession.swift, SessionRestorableAgentSnapshot.resumeCommand returns a cwd‑guarded shell string ("cd <shell-quoted cwd> && <resumeCommand>") when workingDirectory is present. Call sites like Workspace.createPanel(...) should pass .resumeCommand directly and must not prepend an additional cd guard.

Learnt from: apollow
Repo: manaflow-ai/cmux PR: 1089
File: CLI/cmux.swift:462-499
Timestamp: 2026-03-09T02:08:54.956Z
Learning: Repo: manaflow-ai/cmux
PR: `#1089`
File: CLI/cmux.swift
Component: ClaudeHookTagExtractor.extractTags(subtitle:body:)
Learning: For Claude Code session tag extraction, pre-redact sensitive spans (UUIDs, emails, access tokens, filesystem paths, ENV_VAR=..., long numerics) across the combined body+subtitle using unanchored sensitiveSpanPatterns before tokenization. Then tokenize and still filter each token with anchored sensitivePatterns. Rationale: prevents PII/path fragments from slipping into searchable tags after delimiter splitting.

Learnt from: mrosnerr
Repo: manaflow-ai/cmux PR: 2545
File: Sources/Workspace.swift:0-0
Timestamp: 2026-04-02T21:40:59.098Z
Learning: Repo: manaflow-ai/cmux — In Sources/Workspace.swift session snapshot logic, detected foreground command lines are only recorded if they pass SessionRestoreCommandSettings.isCommandAllowed(...). Commit f887189 moved gating to the SessionForegroundProcessCache so unallowed (potentially sensitive) commands are never written to the session JSON.

Learnt from: anthhub
Repo: manaflow-ai/cmux PR: 2239
File: CLI/cmux.swift:0-0
Timestamp: 2026-04-27T06:49:12.578Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift (CMUXCLI.runClaudeHook stop/idle), workspace resolution uses selective do/catch and early-returns "OK" only on teardown-ignored errors; surface resolution failure no longer aborts the handler; setClaudeStatus(..., "Idle", ...) is always attempted after resolution; notification and session upsert only run when completion and surfaceId are present; teardown errors are filtered by shouldIgnoreClaudeHookTeardownError(_:) for graceful shutdown.

Learnt from: HamptonMakes
Repo: manaflow-ai/cmux PR: 2007
File: Sources/cmuxApp.swift:3798-3799
Timestamp: 2026-03-23T16:36:55.259Z
Learning: Repo: manaflow-ai/cmux — In Sources/cmuxApp.swift, SettingsView.resetAllSettings() must reset newly added AppStorage toggles to defaults. Specifically, ensure ampHooksEnabled is set to AmpIntegrationSettings.defaultHooksEnabled so the Amp integration toggle resets correctly.
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cmuxTests/AmpSessionIndexTests.swift`:
- Around line 1-8: Replace XCTest usage in AmpSessionIndexTests.swift with the
project-standard Swift Testing primitives: change "import XCTest" to "import
SwiftTesting" (or the repo's Swift Testing module), convert the test container
from XCTestCase (AmpSessionIndexTests) to the Swift Testing form (use the
TestCase/struct pattern the codebase uses), and update all assertions and
helpers—replace XCTAssertEqual(...) with `#expect`(... == ...), XCTUnwrap(...)
with try `#require`(...), XCTAssertTrue(...) with `#expect`(...), and rename test
methods to drop the "test" prefix so they follow Swift Testing naming
conventions; update any references to XCTest-specific APIs accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ed4b9423-ec5e-4d74-ac6d-87db55f934ab

📥 Commits

Reviewing files that changed from the base of the PR and between 0575866 and 0157112.

⛔ Files ignored due to path filters (1)
  • Assets.xcassets/AgentIcons/Amp.imageset/Amp.svg is excluded by !**/*.svg
📒 Files selected for processing (13)
  • Assets.xcassets/AgentIcons/Amp.imageset/Contents.json
  • CLI/CMUXCLI+AmpExtension.swift
  • CLI/cmux.swift
  • Resources/Localizable.xcstrings
  • Sources/AmpSessionIndex.swift
  • Sources/SessionAgentPresentation.swift
  • Sources/SessionIndexModels.swift
  • Sources/SessionIndexStore.swift
  • Sources/SessionIndexView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/AmpSessionIndexTests.swift
  • cmuxTests/CLIGenericHookPersistenceTests.swift
  • cmuxTests/SessionIndexViewTests.swift

Comment thread cmuxTests/AmpSessionIndexTests.swift Outdated
New unit tests must use Swift Testing per AGENTS.md; XCTest is reserved
for UI tests and socket-harness suites. Migrate XCTestCase -> @suite
struct, XCTAssert* -> #expect, XCTUnwrap -> try #require.

Amp-Thread-ID: https://ampcode.com/threads/T-019e93a5-4b13-747c-9098-5f3117736ab0
Co-authored-by: Amp <amp@ampcode.com>
@comp615

comp615 commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

All review threads are resolved as of 106944ff6 (Swift Testing conversion + the earlier Greptile/i18n/privacy fixes). There are currently 0 open review comments. Could you re-evaluate and update your review status — the PR is showing CHANGES_REQUESTED only due to earlier review states whose comments are now all resolved.

🤖 (comment drafted by an AI assistant)

@coderabbitai

coderabbitai Bot commented Jun 5, 2026 •

Copy link
Copy Markdown

The PR description image shows the Vault sidebar in "By agent" mode with three sections: Claude Code (5 identical session entries, 4h ago), Codex (5 varied entries), and Amp (5 titled entries: "Successful test thread", "Debug AMP titles in Vault UI", "Can you set a test title for this?", "Amp session in cmux-fork", "Amp session in android-register" with recency timestamps from 2s–1h ago and the orange Amp icons). This confirms title resolution and the Vault UI rendering are working end-to-end.


@comp615 Understood — triggering a fresh full review against 106944ff6. All previously raised threads (Greptile P1s, i18n scope, privacy/error-message, Swift Testing conversion) are noted as resolved. The new review will evaluate the current state of the PR from scratch.


🧠 Learnings used
Learnt from: anthhub
Repo: manaflow-ai/cmux PR: 2239
File: CLI/cmux.swift:0-0
Timestamp: 2026-04-27T06:49:12.578Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift (CMUXCLI.runClaudeHook stop/idle), workspace resolution uses selective do/catch and early-returns "OK" only on teardown-ignored errors; surface resolution failure no longer aborts the handler; setClaudeStatus(..., "Idle", ...) is always attempted after resolution; notification and session upsert only run when completion and surfaceId are present; teardown errors are filtered by shouldIgnoreClaudeHookTeardownError(_:) for graceful shutdown.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3968
File: cmuxTests/SessionPersistenceTests.swift:1964-2003
Timestamp: 2026-05-19T21:21:31.876Z
Learning: In manaflow-ai/cmux tests validating Claude resume flows, ensure coverage asserts the preserved auth-selection sentinels are present in resumeCommand: 'CMUX_PRESERVE_CLAUDE_AUTH_SELECTION_ENV=1' and 'CMUX_PRESERVE_CLAUDE_AUTH_SELECTION_ENV_KEYS=…' before checking oversized/launcher-script behavior. File reference: cmuxTests/SessionPersistenceTests.swift.

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-05T06:21:41.655Z
Learning: Applies to **/*.{swift,ts,tsx,js,jsx,plist} : For production changes, fail when diffs violate `.github/review-bot-rules/full-internationalization.md`: user-facing Swift text must use `String(localized:defaultValue:)` or equivalent localized API with matching translated string-catalog entry, app string catalog or Info.plist additions and edits must include translated entries for every locale already supported, and web UI, metadata, API response, rendered markdown, changelog, or user-facing data changes must read from `next-intl` or locale-specific source and update every locale listed in `web/i18n/routing.ts` with matching `web/messages/` entries

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-02T22:33:31.386Z
Learning: Applies to **/{*.swift,*.plist,**/*.{ts,tsx,js,jsx},*.md,web/i18n/routing.ts,web/messages/**} : Fail when diffs to production changes violate `.github/review-bot-rules/full-internationalization.md`: user-facing Swift text must use `String(localized:defaultValue:)` or an equivalent localized API with a matching translated string-catalog entry, app string catalog or Info.plist additions and edits must include translated entries for every locale already supported by the touched catalog, and web UI, metadata, API response, rendered markdown, changelog, or user-facing data changes must read from `next-intl` or another locale-specific source and update every locale listed in `web/i18n/routing.ts` with matching `web/messages/` entries

Learnt from: mrosnerr
Repo: manaflow-ai/cmux PR: 2545
File: Sources/Workspace.swift:0-0
Timestamp: 2026-04-02T21:40:59.098Z
Learning: Repo: manaflow-ai/cmux — In Sources/Workspace.swift session snapshot logic, detected foreground command lines are only recorded if they pass SessionRestoreCommandSettings.isCommandAllowed(...). Commit f887189 moved gating to the SessionForegroundProcessCache so unallowed (potentially sensitive) commands are never written to the session JSON.

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-05T06:21:41.655Z
Learning: Applies to **/*.swift : For cmux-owned Swift code, fail when diffs introduce or materially expand legacy async patterns from `.github/review-bot-rules/swift-concurrency-modernization.md`: background Dispatch queues for ordinary async work, new Combine app state, completion-handler APIs where async throws is under our control, or fire-and-forget Tasks with real lifecycle

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3139
File: Sources/Panels/FilePreviewPanel.swift:534-537
Timestamp: 2026-04-28T05:45:34.719Z
Learning: Repo: manaflow-ai/cmux — Sources/Workspace.swift & Sources/Panels/FilePreviewPanel.swift (PR `#3139`): The shared close-confirmation gate in Workspace uses a generic `panel.isDirty` check (line ~8703) that applies to all panel types, including FilePreviewPanel. FilePreviewPanel exposes `Published private(set) var isDirty` and installFilePreviewPanelSubscription keeps the Bonsplit tab's isDirty flag in sync with it. All three teardown paths (tab close, pane collapse, workspace close) go through this gate, so no special-casing is needed for FilePreviewPanel's dirty state on teardown.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2662
File: Sources/TabManager.swift:1994-1995
Timestamp: 2026-04-07T05:27:49.028Z
Learning: Repo: manaflow-ai/cmux — Sources/TabManager.swift — In applyWorkspacePullRequestRefreshResults(...), resolution .unsupportedRepository must (1) clear any existing workspace.panelPullRequests[panelId] entry and (2) reset lastTerminalState timestamp. scheduleNextWorkspacePullRequestPoll(...) sets nextPollAt to a jittered background interval for .unsupportedRepository, avoiding hot-looping `git remote -v`. Intent: when a panel moves to a non-GitHub or otherwise unsupported repo, clear the sidebar PR badge and back off polling.

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-02T22:35:15.166Z
Learning: Applies to **/*.swift : Fail when diffs to cmux-owned Swift code introduce or materially expand legacy async patterns from `.github/review-bot-rules/swift-concurrency-modernization.md`: background Dispatch queues for ordinary async work, new Combine app state, completion-handler APIs where async throws is under our control, or fire-and-forget Tasks with real lifecycle

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-05T06:21:41.655Z
Learning: Applies to **/*.swift : For Swift changes that add or materially change standalone cmux-owned windows, fail when diffs violate `.github/review-bot-rules/swift-auxiliary-window-close-shortcuts.md`: user-visible NSWindow, NSPanel, NSWindowController, SwiftUI Window, or WindowGroup code without stable cmux.* identifier and shared close-shortcut ownership through cmuxAuxiliaryWindowIdentifiers

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-05T06:21:41.655Z
Learning: Applies to **/*.swift : For Swift changes, fail when diffs violate `.github/review-bot-rules/swift-concurrent-annotation.md`: missing `concurrent` on `nonisolated async` work that should leave the caller actor, invalid `concurrent` on synchronous or actor-isolated functions, or CPU/file/network-heavy async helpers called from UI isolation without an explicit hop

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-05T06:21:41.655Z
Learning: Applies to **/*.swift : For Swift architecture changes, fail when diffs violate `.github/review-bot-rules/swift-architectural-rethink.md`: symptom patches using sleeps, delayed dispatch, polling, locks, observers, side channels, duplicate entrypoint wiring, or split UI lifecycle ownership that leaves bad state representable

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-02T22:01:27.544Z
Learning: Applies to **/*.swift : Fail when diffs to Swift architecture changes violate `.github/review-bot-rules/swift-architectural-rethink.md`: symptom patches using sleeps, delayed dispatch, polling, locks, observers, side channels, duplicate entrypoint wiring, or split UI lifecycle ownership that leaves bad state representable

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-02T22:38:28.737Z
Learning: Applies to **/*.swift : Fail when diffs to Swift changes violate `.github/review-bot-rules/swift-concurrent-annotation.md`: missing `concurrent` on `nonisolated async` work that should leave the caller actor, invalid `concurrent` on synchronous or actor-isolated functions, or CPU/file/network-heavy async helpers called from UI isolation without an explicit hop

Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-06-05T06:21:41.655Z
Learning: Applies to **/*.swift : For production Swift changes, fail when diffs introduce or materially worsen Swift 6 actor isolation mistakes from `.github/review-bot-rules/swift-actor-isolation.md`: implicit MainActor value models or service protocols, shared mutable Sendable reference types without isolation, or UI-bound stores accessed from background contexts

Learnt from: austinywang
Repo: manaflow-ai/cmux PR: 3568
File: GhosttyTabs.xcodeproj/project.pbxproj:1588-1590
Timestamp: 2026-05-05T20:41:12.478Z
Learning: In the manaflow-ai/cmux repository, the SwiftPM package-boundary extraction of `JSONCValueEditor.swift` and `CmuxSettingsManagedValues.swift` into a dedicated Foundation-only package is intentionally deferred to a separate refactor PR. For the regression/fix PR (issue `#3551`, PR `#3568`), these files are scoped to the app target and covered by behavioral CI tests. Do not flag this as an unresolved issue within the context of that PR.

Learnt from: comp615
Repo: manaflow-ai/cmux PR: 5420
File: Sources/SessionIndexView.swift:1499-1500
Timestamp: 2026-06-05T13:30:21.464Z
Learning: In `Sources/SessionIndexView.swift` (manaflow-ai/cmux), the `.amp` case in `SessionTranscriptLoader`'s `parseLine`, `shouldParseRawLine`, and `inferredRole` switches intentionally returns `nil`/`false`. Amp sessions are indexed from the cmux plugin hook-store (`~/.cmuxterm/amp-hook-sessions.json`) which holds only session metadata and title — no per-message transcript file exists on disk. As a result, `SessionEntry.fileURL` is always `nil` for Amp entries, `load(entry:)` throws `.missingFile` before any parser branch is reached, and the UI correctly shows the "No transcript file" graceful state. The `.amp` switch branches are pure exhaustiveness guards. Do not flag them as dead code or suggest routing `.amp` through the generic file-based parser.

Learnt from: comp615
Repo: manaflow-ai/cmux PR: 5366
File: Sources/AmpSessionIndex.swift:0-0
Timestamp: 2026-06-05T02:13:27.941Z
Learning: In `Sources/AmpSessionIndex.swift` (manaflow-ai/cmux), the `ErrorBag` message for a failed Amp hook-store read is `"Amp: cannot read amp-hook-sessions.json"` — filename only, no absolute path, and no `error.localizedDescription` or raw decode detail. This is intentional: the Vault sidebar renders `SessionIndex` errors directly in-UI, so the message must comply with `user-facing-errors.md` (no implementation leaks). Other agent loaders (OpenCode, Codex) follow the same filename-only pattern.

Learnt from: where-is-atin
Repo: manaflow-ai/cmux PR: 3562
File: CLI/cmux.swift:15896-16092
Timestamp: 2026-05-06T00:48:16.440Z
Learning: In `CLI/cmux.swift`, the Pi session extension TypeScript bridge (`piSessionExtensionSource`) shares `printInstallPreview`, `CLIError`, `--yes`/`-y` flag handling, and structurally identical `normalizedLaunchArgv`/`hookEnvironment` shape with the codex, claude, and opencode bridges in the same file. Refactoring of this shared infrastructure is deferred to issue `#3578` with a two-phase plan: Phase 1 extracts shared infra, Phase 2 introduces per-agent packages (parser + bridge per agent).

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2964
File: Sources/ContentView.swift:0-0
Timestamp: 2026-04-17T21:35:30.619Z
Learning: Repo: manaflow-ai/cmux — Session resume behavior: generate commands with a guaranteed cwd guard. In Sources/SessionIndexStore.swift, SessionEntry exposes a helper (e.g., resumeCommandWithCwd) that produces 'cd <shell-quoted cwd> && <resumeCommand>', and all call sites (clipboard, drag‑drop terminal, in‑app resume) should use this form so fresh shells and rc files cannot land outside the intended directory.

Learnt from: mrosnerr
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-28T22:24:18.018Z
Learning: Repo: manaflow-ai/cmux — In Sources/GhosttyTerminalView.swift (PR `#3237`, commit 9dcb9c2), the explicit-vs-baseConfig.initialInput resolution logic was extracted from `TerminalSurface.createSurface(for:)` into a standalone `TerminalSurface.resolveInitialInput(...)` static/instance method for unit-testability. Behavior is unchanged. A companion `TerminalSurfaceResolveInitialInputTests` suite asserts the contract, including byte-for-byte preservation of Ghostty raw-bytes startup-input via `baseConfig.initialInput`.

Learnt from: mrosnerr
Repo: manaflow-ai/cmux PR: 3237
File: Sources/Workspace.swift:0-0
Timestamp: 2026-04-28T16:43:22.551Z
Learning: Repo: manaflow-ai/cmux — In Sources/Workspace.swift session-restore path (createPanel(from:inPane:)), treat both agent resume input and auto-detected foreground command as "initialInput" and gate them by the per-panel snapshot.terminal?.isRemoteBacked flag. Specifically: compute panelWasRemoteBacked first, set restoredAgentResumeInput = nil when true, and also skip commandToRestore when true. Precedence remains restoredAgentResumeInput ?? commandToRestore for local panels.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2525
File: Sources/GhosttyTerminalView.swift:481-513
Timestamp: 2026-04-02T10:13:39.235Z
Learning: Repo: manaflow-ai/cmux — In Sources/GhosttyTerminalView.swift, terminal file-link resolution trims trailing unmatched closing delimiters “) ] } >” only when they are dangling (more closers than openers), preserving wrapped tokens like “(file:///tmp/a.png)”. Implemented via terminalFileLinkTrailingClosingDelimiters and count comparison inside trimTrailingTerminalFileLinkPunctuation(_:) and exercised by a regression test (PR `#2525`, commit 3f5c5b6d).

Learnt from: mrosnerr
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-05T21:26:10.710Z
Learning: Repo: manaflow-ai/cmux — In Sources/Workspace.swift, applySessionPanelMetadata() must gate listeningPorts restoration on the per-panel snapshot.terminal?.isRemoteBacked flag (not workspace-wide remoteTerminalStartupCommand()), so that local panels are always eligible for port restore regardless of current SSH state. Fixed in commit 4d0fd871 (PR `#2545`).
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/AmpSessionIndex.swift`:
- Around line 10-12: The current decoding of the `sessions` dictionary is
brittle: replace the single-map decode of `[String: AmpHookSessionRecord]` with
a loss-tolerant, per-key decode that iterates the `sessions` keyed container and
attempts to decode each `AmpHookSessionRecord` individually (using
`decode`/`decodeIfPresent` inside a do/catch) so that decoding failures for a
single record are caught and skipped rather than failing the entire map; apply
the same per-entry lossy decoding approach wherever `sessions` is decoded (e.g.,
in the `loadAmpEntries`/decoding logic and the other occurrence around lines
31-37), preserving valid entries in the resulting `[String:
AmpHookSessionRecord]` and ignoring malformed ones.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2468b3c0-7f48-4524-9748-7f925dd707e1

📥 Commits

Reviewing files that changed from the base of the PR and between 0575866 and 106944f.

⛔ Files ignored due to path filters (1)
  • Assets.xcassets/AgentIcons/Amp.imageset/Amp.svg is excluded by !**/*.svg
📒 Files selected for processing (13)
  • Assets.xcassets/AgentIcons/Amp.imageset/Contents.json
  • CLI/CMUXCLI+AmpExtension.swift
  • CLI/cmux.swift
  • Resources/Localizable.xcstrings
  • Sources/AmpSessionIndex.swift
  • Sources/SessionAgentPresentation.swift
  • Sources/SessionIndexModels.swift
  • Sources/SessionIndexStore.swift
  • Sources/SessionIndexView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/AmpSessionIndexTests.swift
  • cmuxTests/CLIGenericHookPersistenceTests.swift
  • cmuxTests/SessionIndexViewTests.swift

Comment thread Sources/AmpSessionIndex.swift Outdated
Comment thread CLI/CMUXCLI+AmpExtension.swift
The store is persisted cross-version state; a single type-drifted record
previously failed the whole map decode and blanked the Amp listing.
Decode entry-by-entry and skip bad records, fulfilling the tolerance the
struct's doc comment already promises. Add a regression test.

Amp-Thread-ID: https://ampcode.com/threads/T-019e93a5-4b13-747c-9098-5f3117736ab0
Co-authored-by: Amp <amp@ampcode.com>
@comp615

comp615 commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

All review threads are resolved as of bb52d0fc6. The two items left unaddressed are deliberate, with rationale in their (resolved) threads: (1) en/ja localization is the documented standard per CLAUDE.md/AGENTS.md — you previously agreed and saved this as a repo learning; (2) the Greptile session.start guard suggestion would break session registration (turnActive is false at session.start) and relies on a session.end event Amp does not emit. Please re-evaluate — there should be no remaining actionable items.

🤖 (comment drafted by an AI assistant)

@coderabbitai

coderabbitai Bot commented Jun 5, 2026 •

Copy link
Copy Markdown

The PR description image shows the Vault sidebar in "By agent" view with Claude Code, Codex, and Amp sections — the Amp section displaying five titled entries ("Successful test thread", "Debug AMP titles in Vault UI", "Can you set a test title for this?", "Amp session in cmux-fork", "Amp session in android-register") with orange Amp icons and recency timestamps, confirming end-to-end title resolution and UI rendering are working.


@comp615 Understood on both counts:

  1. en/ja localization — already confirmed and saved as a repo learning. The four new Amp keys with en+ja entries satisfy the project standard per CLAUDE.md/AGENTS.md. ✅
  2. session.start / turnActive guard — turnActive is false at session.start by design (it's set to true on agent.start), so gating session-start hook payloads on turnActive would silently drop session registration. Additionally, Amp does not emit a session.end event, making the Greptile-suggested guard structurally incompatible with the plugin's lifecycle. The current implementation is correct. ✅

Triggering a full review against bb52d0fc6 with both items noted as non-actionable.


✏️ Learnings added
Learnt from: comp615
URL: https://github.com/manaflow-ai/cmux/pull/5420

Timestamp: 2026-06-05T17:43:24.382Z
Learning: In `CLI/CMUXCLI+AmpExtension.swift` (manaflow-ai/cmux), `turnActive` is `false` at `session.start` time — it is set to `true` only on `agent.start`. Therefore, gating the `session-start` hook payload emission on `turnActive` would prevent session registration and is incorrect. Additionally, Amp does not emit a `session.end` event, so any guard relying on that event is structurally unsound. Do NOT suggest adding a `turnActive` guard to the `session.start` handler branch or flag the absence of such a guard as a race condition. The current sequential lifecycle (session.start → agent.start sets turnActive=true → agent.end sets turnActive=false) is intentional.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3968
File: cmuxTests/SessionPersistenceTests.swift:1964-2003
Timestamp: 2026-05-19T21:21:31.876Z
Learning: In manaflow-ai/cmux tests validating Claude resume flows, ensure coverage asserts the preserved auth-selection sentinels are present in resumeCommand: 'CMUX_PRESERVE_CLAUDE_AUTH_SELECTION_ENV=1' and 'CMUX_PRESERVE_CLAUDE_AUTH_SELECTION_ENV_KEYS=…' before checking oversized/launcher-script behavior. File reference: cmuxTests/SessionPersistenceTests.swift.

Learnt from: anthhub
Repo: manaflow-ai/cmux PR: 2239
File: CLI/cmux.swift:0-0
Timestamp: 2026-04-27T06:49:12.578Z
Learning: Repo: manaflow-ai/cmux — In CLI/cmux.swift (CMUXCLI.runClaudeHook stop/idle), workspace resolution uses selective do/catch and early-returns "OK" only on teardown-ignored errors; surface resolution failure no longer aborts the handler; setClaudeStatus(..., "Idle", ...) is always attempted after resolution; notification and session upsert only run when completion and surfaceId are present; teardown errors are filtered by shouldIgnoreClaudeHookTeardownError(_:) for graceful shutdown.

Learnt from: mrosnerr
Repo: manaflow-ai/cmux PR: 2545
File: Sources/Workspace.swift:0-0
Timestamp: 2026-04-02T21:40:59.098Z
Learning: Repo: manaflow-ai/cmux — In Sources/Workspace.swift session snapshot logic, detected foreground command lines are only recorded if they pass SessionRestoreCommandSettings.isCommandAllowed(...). Commit f887189 moved gating to the SessionForegroundProcessCache so unallowed (potentially sensitive) commands are never written to the session JSON.

Learnt from: mrosnerr
Repo: manaflow-ai/cmux PR: 3237
File: Sources/Workspace.swift:0-0
Timestamp: 2026-04-28T16:43:22.551Z
Learning: Repo: manaflow-ai/cmux — In Sources/Workspace.swift session-restore path (createPanel(from:inPane:)), treat both agent resume input and auto-detected foreground command as "initialInput" and gate them by the per-panel snapshot.terminal?.isRemoteBacked flag. Specifically: compute panelWasRemoteBacked first, set restoredAgentResumeInput = nil when true, and also skip commandToRestore when true. Precedence remains restoredAgentResumeInput ?? commandToRestore for local panels.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2978
File: Sources/Workspace.swift:0-0
Timestamp: 2026-04-22T08:13:39.699Z
Learning: Repo: manaflow-ai/cmux — In Sources/RestorableAgentSession.swift, SessionRestorableAgentSnapshot.resumeCommand returns a cwd‑guarded shell string ("cd <shell-quoted cwd> && <resumeCommand>") when workingDirectory is present. Call sites like Workspace.createPanel(...) should pass .resumeCommand directly and must not prepend an additional cd guard.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 2964
File: Sources/ContentView.swift:0-0
Timestamp: 2026-04-17T21:35:30.619Z
Learning: Repo: manaflow-ai/cmux — Session resume behavior: generate commands with a guaranteed cwd guard. In Sources/SessionIndexStore.swift, SessionEntry exposes a helper (e.g., resumeCommandWithCwd) that produces 'cd <shell-quoted cwd> && <resumeCommand>', and all call sites (clipboard, drag‑drop terminal, in‑app resume) should use this form so fresh shells and rc files cannot land outside the intended directory.

Learnt from: lawrencecchen
Repo: manaflow-ai/cmux PR: 3122
File: Sources/RestorableAgentSession.swift:57-59
Timestamp: 2026-04-22T23:54:20.284Z
Learning: In manaflow-ai/cmux `Sources/RestorableAgentSession.swift`, `AgentLaunchCommandSnapshot.executablePath` (and its argv) are already normalized/canonical by the time `AgentResumeCommandBuilder.resumeArguments` processes them: wrapper launchers (claudeTeams, omo) export the real cmux binary path and persist argv canonically, and direct OpenCode hook capture strips/normalizes internal worker launch details before writing to the session JSON. Do NOT force-override `original.executable` with `invocation.fallbackExecutable` in the resume layer — doing so replaces valid captured absolute paths with generic names and regresses wrapper-launched session restores.

Learnt from: mrosnerr
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-28T22:24:18.018Z
Learning: Repo: manaflow-ai/cmux — In Sources/Workspace.swift (PR `#3237`, commit 9dcb9c2), the `newTerminalSurface(...)` method gained an `allowInitialInputWithRemoteStartupCommand: Bool` parameter (default `false`). The session-restore call site in `createPanel(from:inPane:)` passes `true` only when `!panelWasRemoteBacked && combinedInitialInput != nil`, making the per-panel snapshot flag the sole authority for restore-time `initialInput` injection. All 12 other call sites keep `false`, preserving the existing remote-drop defense.

Learnt from: austinywang
Repo: manaflow-ai/cmux PR: 5430
File: Packages/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizer.swift:0-0
Timestamp: 2026-06-05T04:42:27.510Z
Learning: In manaflow-ai/cmux PR `#5430`, the approach for re-applying cmux hook settings on Claude resume/fork was changed from directly re-injecting `--settings <hooks-json>` into the resume/fork argv (via a `containsClaudeHookSettingsOption` detection helper in `AgentLaunchSanitizer`) to instead routing claude resume and fork commands through the bare `claude` wrapper executable as the leading argv element. The wrapper (`Resources/bin/claude`) is already the canonical hook injection point and handles `--settings` injection unconditionally (modulo `CMUX_CLAUDE_HOOKS_DISABLED`), so routing through it is the preferred pattern. The `containsClaudeHookSettingsOption` helper and `ClaudeHookSettings` constant were removed as superseded. When reviewing future resume/fork command construction for Claude, verify that the argv leading executable is `"claude"` (the wrapper) rather than a captured real binary path, as this is what ensures hooks fire on resumed/forked sessions.

Learnt from: mrosnerr
Repo: manaflow-ai/cmux PR: 0
File: :0-0
Timestamp: 2026-04-05T21:26:10.710Z
Learning: Repo: manaflow-ai/cmux — In Sources/Workspace.swift, applySessionPanelMetadata() must gate listeningPorts restoration on the per-panel snapshot.terminal?.isRemoteBacked flag (not workspace-wide remoteTerminalStartupCommand()), so that local panels are always eligible for port restore regardless of current SSH state. Fixed in commit 4d0fd871 (PR `#2545`).

Learnt from: where-is-atin
Repo: manaflow-ai/cmux PR: 3562
File: CLI/cmux.swift:15896-16092
Timestamp: 2026-05-06T00:48:16.440Z
Learning: In `CLI/cmux.swift`, the Pi session extension TypeScript bridge (`piSessionExtensionSource`) shares `printInstallPreview`, `CLIError`, `--yes`/`-y` flag handling, and structurally identical `normalizedLaunchArgv`/`hookEnvironment` shape with the codex, claude, and opencode bridges in the same file. Refactoring of this shared infrastructure is deferred to issue `#3578` with a two-phase plan: Phase 1 extracts shared infra, Phase 2 introduces per-agent packages (parser + bridge per agent).

Learnt from: comp615
Repo: manaflow-ai/cmux PR: 5420
File: Sources/SessionIndexView.swift:1499-1500
Timestamp: 2026-06-05T13:30:21.464Z
Learning: In `Sources/SessionIndexView.swift` (manaflow-ai/cmux), the `.amp` case in `SessionTranscriptLoader`'s `parseLine`, `shouldParseRawLine`, and `inferredRole` switches intentionally returns `nil`/`false`. Amp sessions are indexed from the cmux plugin hook-store (`~/.cmuxterm/amp-hook-sessions.json`) which holds only session metadata and title — no per-message transcript file exists on disk. As a result, `SessionEntry.fileURL` is always `nil` for Amp entries, `load(entry:)` throws `.missingFile` before any parser branch is reached, and the UI correctly shows the "No transcript file" graceful state. The `.amp` switch branches are pure exhaustiveness guards. Do not flag them as dead code or suggest routing `.amp` through the generic file-based parser.

Learnt from: comp615
Repo: manaflow-ai/cmux PR: 5366
File: Sources/AmpSessionIndex.swift:0-0
Timestamp: 2026-06-05T02:13:27.941Z
Learning: In `Sources/AmpSessionIndex.swift` (manaflow-ai/cmux), the `ErrorBag` message for a failed Amp hook-store read is `"Amp: cannot read amp-hook-sessions.json"` — filename only, no absolute path, and no `error.localizedDescription` or raw decode detail. This is intentional: the Vault sidebar renders `SessionIndex` errors directly in-UI, so the message must comply with `user-facing-errors.md` (no implementation leaks). Other agent loaders (OpenCode, Codex) follow the same filename-only pattern.

Learnt from: atani
Repo: manaflow-ai/cmux PR: 819
File: Sources/AppDelegate.swift:3491-3493
Timestamp: 2026-03-04T14:06:16.241Z
Learning: For manaflow-ai/cmux PR `#819` (Japanese i18n), keep scope limited to localization changes; UX enhancements like preferring workspace.customTitle in workspaceDisplayName() or altering move-target labels should be handled in a separate follow-up issue.

Learnt from: HamptonMakes
Repo: manaflow-ai/cmux PR: 4443
File: Sources/cmuxApp.swift:6678-6695
Timestamp: 2026-05-22T15:04:55.554Z
Learning: In manaflow-ai/cmux, agent/automation settings strings (settings.automation.*) follow AGENTS.md, which scopes supported locales to English and Japanese; sibling toggles on main (Cursor/Gemini) also include Korean. For new entries like settings.automation.amp.*, matching en/ja/ko is acceptable and we should not require expansion to all app locales in the touched catalog unless maintainers request it.

Learnt from: HamptonMakes
Repo: manaflow-ai/cmux PR: 4443
File: CLI/CMUXCLI+AmpExtension.swift:361-366
Timestamp: 2026-05-22T15:03:53.311Z
Learning: In manaflow-ai/cmux (CLI/CMUXCLI+AmpExtension.swift), the `turnActive` flag and shared `inFlightTools` counter in the embedded Amp plugin are intentionally not keyed by a per-turn ID. The deployment model is one Amp session per terminal pane with sequential turns, so: `agent.start` always resets both before new turn events arrive; the `agent.end` → `agent.start` race is blocked by `turnActive = false`; a late `tool.result` after `agent.start` benignly shows "thinking", which is correct. Per-turn bookkeeping would only be needed for concurrent multi-thread sessions. Do not flag the single-flag approach as a race condition in this context.
✅ Action performed

Full review finished.

@greptile-apps

greptile-apps Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

@vercel

vercel Bot commented Jun 16, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jun 16, 2026 11:06pm

Comment thread Sources/AmpSessionIndex.swift Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants