Skip to content

Apps: place sidebar sections automatically and add apps place - #33016

Merged
teamleaderleo merged 6 commits into
feat-cmux-nextfrom
lane/app-slot/sidebar-placement
Nov 3, 2026
Merged

teamleaderleo merged 6 commits into
feat-cmux-nextfrom
lane/app-slot/sidebar-placement

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Local apps and new user installs place their sidebar sections at the end of the manifest's default region, including the band below the workspace list. Existing installs receive receipts on first run without any layout change; first-party deployment defaults never auto-place. Saving a newly appearing customize app uses the existing reload path. Placement and its receipt commit together in the sidebar document, so a person's move or removal survives later saves and restarts. cmux apps place APP#SECTION [--region top|middle|bottom] explicitly places or restores one section.

Leo (2026-11-02): "let’s do all these" — "A sidebar panel slot plus ’an agent writes the app, it hot-reloads’. This covers his PR view, makes Session Info extensible, and is mostly built."

The existing v1/v2 schemas already accept defaultRegion: "bottom"; this adds validator coverage. V2 contributions use APP#cmux.section/1, matching the scene provider. Titles remain with that provider for localization. No new watcher or grant policy is introduced.

Design: sidebar spec; daemon contract updated in plans/cmux-next/app-platform.md. Bottom-band rendering and drag forwarding are in #33130. Related prior art: #26713 implements web panes beside chat; this builds on base and does not modify it.

Risk: normal. Placement adds durable personal layout state. Section and receipt share one transaction; existing contributions are adopted in place. Upgrade receipts do not alter the layout. New-install eligibility persists across hidden installs and migration retries. Reconciliation with all receipts present avoids registry writes. Explicit placement is limited to installed, enabled, visible apps on the existing local-only apps door.

Changelog

  • Added: Local apps and new user installs place sidebar sections automatically, and agents can place a section with cmux apps place.

Observed / Not run

  • Formatting and static prepush checks pass.
  • Previous head: focused fleet run passed at a6ae7d3579c1ba1181b55fd2709d87e5bc56c238: cargo test --locked -p cmux-tui-core apps, cargo test --locked -p cmux-app-manifest, and cargo test --locked -p cmux-tui apps_place. The receipt verifies the exact head and source tree. This covers customize first appearance, personal move/removal through reload and restart, hidden/uninstalled apps, explicit restoration, manifest regions and CLI transport.
  • Policy revision d5703f722710f8ab008d38ca4482df9c941948c6: focused fleet validation passed all core app, manifest and CLI tests. Final head 8e948fd2886db402983d8d6b703679e07394f70f: core all-target clippy with -D warnings and focused tests passed, and the crash ratchet passed. Both receipts verify the tested head and source tree. New regression tests cover fresh/legacy defaults, legacy store/local installs without layout changes, hidden installs across restart, migration retries, and reconciliation without registry writes.
  • Not run: interactive sidebar rendering/dragging (separate bottom-band PR), complete app build or end-to-end agent authoring.

Review follow-ups: #33380 (explicit region/scroll), #33383 (temporarily missing local packages), #33382 (initialization retry), #33381 (non-user-origin coverage). Each links the independent review; the implementation owner owns their fix-forward.

Agent session: agent session

Add transactional sidebar placement receipts so local reload and daemon restart preserve personal moves and removals. Explicit CLI placement uses the existing private daemon transport.

Validation: formatting and static prepush checks passed; focused fleet tests follow on the pushed PR head.
Agent-Session: https://cmux.com/deeplink/agent?id=aid-6fb2d6c86da62ef0c651
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 8e948fd: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr33016 -f ref=lane/app-slot/sidebar-placement -f platform=macos -f backend_mode=local

web and size checks: green

Shipped in:

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 3, 2026
@blacksmith-sh

blacksmith-sh Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
build_only must be a conjunctive exclusion on the helper, signing, and publication jobs
, and must not gate the unsigned app build/
build_only must be a conjunctive exclusion on the helper, signing, and publication jobs
, and must not gate the unsigned app build
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

Fresh sidebar documents already contain the built-in recent chats app. Assert against each fixture app while continuing to reject duplicate sections and verify visibility, movement and persisted removal.

Agent-Session: https://cmux.com/deeplink/agent?id=aid-6fb2d6c86da62ef0c651
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (claude opus-5.5 medium, area owner): BLOCK at 1d279da

Visual verdict: no images; native sidebar effect described below.

[blocking] Automatic placement runs for every installed, enabled, visible app at daemon start and on every apps-changed (reconcile_sidebar in apps/sidebar.rs), and the receipt table starts empty. On the first launch after this lands, every existing user gets a new sidebar section for each such app that implements cmux.section/1, including the first-party default cmux/coderouter (Resources/AppPlatform/first-party/coderouter/cmux-app.v2.json, which the default layout already shows as the item itm_app_coderouter, not as a section), and any store app such as quick-links the person installed without adding its section. That is a sidebar change users notice on upgrade. Fix: place automatically only (a) local apps (Source::Local: the customize folder and <state>/apps/local), whose sections the person wrote, and (b) an app the person installs after this change (an install through apps-set installed: true with origin user). On the first run with this code, record a receipt for every section of the apps already installed without adding anything, so upgrades change no layout. Add a test for each: a first-party default is not placed at startup, an already installed store app is not placed on upgrade, and a new user install is placed once.

Follow-ups:

  • [follow-up] reconcile_sidebar commits a sidebar transaction on every apps-changed even when every section is already receipted. Skip the commit when no section lacks a receipt, which you can check with one read before calling commit_sidebar_ops.

@cursor

cursor Bot commented Nov 3, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (claude opus-5.5 medium subagent): BLOCK at a6ae7d3
Visual verdict: no images; the change is a native sidebar effect, described below.
I checked the diff since the previous BLOCK at 1d279da. The only new commit is a6ae7d3, a one-line change to a fixture's script runtime in cmux-app-manifest/tests/fixtures.rs. The placement filter is the same as before. The failing inventory / test_event_stream_drift_is_rejected check fails the same way on base (39ca8ed), so it is a base red and not this PR's.

[blocking] The earlier finding still stands. Supervisor::reconcile_sidebar (cmux-tui-core/src/apps/sidebar.rs:16-29) places a section automatically for every installed, enabled and visible package, both at daemon start and on every apps-changed. The apps.sidebar.placed:* receipts start out empty. So on upgrade, every existing user gets new sections from first-party defaults (cmux/coderouter, which has cmux.section/1) and from every app installed before this change. Fix:

  • Place automatically only when the package is Source::Local (local/customize or <state>/apps/local) or when the install happened after this change. Two ways to do that: record a placement receipt for every app already installed the first time the receipt table is created, or trigger placement from the user-origin install transition instead of from every apps-changed.
  • Add tests: a first-party default with cmux.section/1, and an app installed before the receipts existed, are both not placed when the daemon starts; a new user install is placed.
    Follow-ups: none beyond the fix above.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (claude opus-5.5 medium): BLOCK at d5703f7
Visual verdict: code only

I read the placement policy (apps/sidebar.rs, the startup snapshot in supervisor.rs, mirror.rs eligibility, the customize seeds in local_reload.rs) and the new integration tests against the policy. The policy logic itself is sound. Only Local apps, or apps a person installed after the upgrade (sidebar_auto_place), are placed, and Source::Default is always excluded. On upgrade, existing installs (hidden and disabled included) get receipts with no ops. A hidden new install stays eligible across restarts and migration retries because the startup snapshot leaves out sidebar_auto_place members. The all-receipted fast path is read-only. reconcile_sidebar runs from emit without holding inner. The eight policy tests map onto those cases: defaults on fresh and existing installs, legacy store installs, a new store install with removal across restart, a hidden install across restart, no registry writes, migration retry, customize on first start, and a legacy customize upgrade.

The blocks are reds this PR causes at this head, and both are trivial to fix:

  • [blocking] clippy (changed cmux-tui packages) fails -D warnings on three unnecessary qualification errors in crates/cmux-tui-core/src/apps/sidebar.rs at lines 247, 256 and 257 (the test module's super::super::mirror::Tier and rusqlite::Connection, which are already imported). The acpmux subagents.rs clippy error in the same job is not this PR's.
  • [blocking] cmux-next crash ratchet and fast gates say "rust cmux-tui-core: expect: head 191, base ok", so this PR turns them red. The new hit is receipt_key(section).expect("app section") in placement_ops. A let Some(key) = receipt_key(section) else { continue }; (or building the key from the contribution already matched) removes it.

Follow-ups:

  • [follow-up] When place_sidebar gets no --region and the section already exists, it uses the manifest's default region and moves the section there, which undoes a person's move. With no region it should probably leave an existing section alone. Also, SectionMove does not update scroll for the new region.
  • [follow-up] Only packages in the catalog at startup get receipts. A Local app that is installed in the mirror but whose directory is missing at the first upgraded start gets no receipt, and is auto-placed when its directory returns. A one-time layout change for an old install in a narrow case.
  • [follow-up] When initialization fails, every apps-changed logs "sidebar placement not initialized" until the next restart, and nothing retries inside the process.
  • [follow-up] No test covers a non-User origin (agent) install of a store app staying unplaced, which mirror::commit relies on.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (claude opus-5.5 medium): SHIP at 8e948fd
Visual verdict: code only
The BLOCK at d5703f7 (#33016 (comment)) is fixed. I read the whole diff since that head: it only removes the redundant Tier/Source/Connection qualifications in the test module and replaces receipt_key(section).expect(...) in placement_ops with let Some(key) = ... else { continue }. The placement policy is unchanged from the reviewed head. Land once clippy and the crash ratchet are green at this head.
Follow-ups: #33380, #33381, #33382, #33383

@teamleaderleo teamleaderleo left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Review (subagent Codex GPT-6): SHIP at 8e948fd

Review (subagent Codex GPT-6): SHIP at 8e948fd.

Reviewed the narrow d5703f7..8e948fd fix against the two blocking findings in the Opus review, which found the placement policy sound. The redundant test-module qualifications are removed, and receipt_key(...).expect(...) now uses a non-panicking branch. No behavior regression found in this patch. Test execution is recorded separately by the implementation owner.

Review follow-ups: #33380, #33383, #33382, #33381.

@teamleaderleo
teamleaderleo merged commit e17575a into feat-cmux-next Nov 3, 2026
190 of 193 checks passed
@teamleaderleo
teamleaderleo deleted the lane/app-slot/sidebar-placement branch November 3, 2026 09:04
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at 8e948fd

Reviewer: codex gpt-6-astra high, fast tier.

Follow-ups: 3. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at 8e948fd
Visual verdict: no images; Leo tries the build

  1. [P2] [follow-up] supervisor.rs:278: Upgrade receipts cover only packages currently in the catalog. If an existing local package is temporarily missing or invalid, initialization completes without its receipt; repairing it later automatically adds its section, including one previously removed. Preserve adoption state for unavailable legacy installs (Apps: preserve upgrade placement decisions for temporarily missing local packages #33383).

  2. [P2] [follow-up] supervisor.rs:289: Initialization errors are logged without retry. After a transient failure, every subsequent automatic placement rejects the missing initialization marker until restart. Retry initialization while preserving the original migration snapshot (Apps: retry sidebar placement initialization after a transient failure #33382).

  3. [P2] [follow-up] sidebar.rs:36: No images demonstrate the newly placed sections. Verify their rendered placement in the build.

Source review completed; tests could not run because Cargo is unavailable.

Follow-ups:

@lawrencecchen

Copy link
Copy Markdown
Contributor

Base red on feat-cmux-next from this PR: cmux-tui::terminal_host_recovery interrupted_public_creation_publishes_once_and_replays_stable_ids_after_two_restarts fails at terminal_host_recovery.rs:3637 (first_resolution["revision"] is "2", the test expects "1"). Bisected on the fleet (Linux, the test alone): green at 9168b56 (job of key brs-thr5-9168b56a), red at this PR's e17575a (key brs-thr4-e17575a9), red at the merge base b657cec and at the tip 78ee0e1.

Mechanism (read from the code): at start the apps supervisor calls initialize_sidebar_placements (apps/sidebar.rs initialize), which commits through commit_sidebar_ops -> commit_state -> commit_state_mutation. That always takes a new resource revision, even though this mutation writes only meta receipts and changes no resource (applied.changes is empty, no events). So every fresh daemon now spends revision 1 on the receipt, and the first public creation is revision 2. The test's comment says its exact revisions "count creation commits only".

Question for you (the fix depends on your intent):

  • Product: the receipt-only initialization should not take a public resource revision (write the receipts in a registry transaction that does not bump resource_revision, or skip the commit when there is nothing to change and no section exists). Clients that read cursor.revision then see no phantom change at start.
  • Test: a fresh daemon may take a revision at start, and the test should read the revision before the create and assert before + 1.

I left this group unfixed until you answer. (BASE RED SUITE for the cmux-next Performance Lead; owner of the revision path: PL-daemon.)

@lawrencecchen

Copy link
Copy Markdown
Contributor

No answer by 19:00Z, so per the Performance Lead I took the product side, which matches this PR's intent ("Only metadata is written"): #35842 writes the start-up receipts as registry metadata, with no resource revision.

(BASE RED SUITE for the cmux-next Performance Lead.)

cmux-bot Bot pushed a commit that referenced this pull request Nov 4, 2026
…ion (from #33016) (#35842)

* fix(cmux-tui-core): the apps sidebar's start-up receipts take no resource revision

#33016 seeds sidebar placement receipts at every daemon start "without changing the layout"
("Only metadata is written"). It wrote them through commit_sidebar_ops, a resource commit, so
each fresh daemon spent resource revision 1 on a mutation that changes no resource and
publishes nothing, and the first real change became revision 2.
terminal_host_recovery's interrupted_public_creation_publishes_once_and_replays_stable_ids_after_two_restarts
(red on feat since e17575a: revision "2" for "1") counts creation commits only. The
receipts and the initialized marker are now written as registry metadata in one transaction,
under the same migration check (no document, no marker, so the next start initializes again).

* fix(cmux-tui-core): write_registry_meta names Transaction as imported (clippy unused_qualifications)

This branch was previously deployed

3 inactive deployments
artifacts — 8e948fd2 Deployed Nov 3, 2026 by teamleaderleo via publish tree-addressed cmux-tui #104898
sentry-dsyms — 8e948fd2 Deployed Nov 3, 2026 by teamleaderleo via upload cmux-tui dSYMs to Sentry #104898
ci-routing-agent — 8e948fd2 Deployed Nov 3, 2026 by teamleaderleo via cmux-tui tree preflight #104898
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants