Skip to content

fix(sidebar): keep a pinned agent in its workspace card - #852

Merged
devswha merged 1 commit into
mainfrom
fix/pinned-agents-stay-in-cards
Oct 11, 2026
Merged

devswha merged 1 commit into
mainfrom
fix/pinned-agents-stay-in-cards

Conversation

@devswha

@devswha devswha commented Oct 11, 2026

Copy link
Copy Markdown
Owner

Problem

From 0.4.7 mobile testing: with Settings → Appearance → Workspace cards (#673/#820) and Pin agents (#778/#820) both on, starring an agent pulled it out of its workspace card and put it above all cards. The user read that as the agent "escaping" its card and chose a different layout.

Change

  • AgentSidebar: in cards mode the groups are built from [...pinned, ...rest] instead of rest alone, and the separate pinned rows above the cards are gone. groupRows keeps first-appearance order, so:
    • a pinned agent stays in its own card, first in it (in pin order);
    • cards holding pins come first, in the order of their first pin; the rest keep herdr's order.
  • Flat mode (cards off, or Activity order) is unchanged: pinned rows lead the list.
  • Comments in AgentSidebar/sidebarPins updated to the new rule.

Tests

  • sidebarPins.test.ts: the grouping case now expects C1 pinned then A2 → cards C [C1], A [A2, A1], B [B1].
  • sidebar-activity-demo-regression: pinning infra keeps it inside the infra card, which becomes the first card; the star keeps keyboard focus; reload keeps it; unpinning returns checkout-api as the first card.
  • bun run check fast passes.

🤖 Generated with Claude Code

With Workspace cards on, a pin pulled the agent out of its card to the
top of the list, which read as the agent escaping its workspace. The
pinned rows are now grouped with the rest: each stays in its own card,
first there, and the cards holding pins lead in the order of their
first pin. Without cards the pinned rows still lead the flat list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 11, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 24 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: devswha/herdr-web-ui/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: fb6dc2b3-fb26-4ca5-8e0f-e3d245f06771

📥 Commits

Reviewing files that changed from the base of the PR and between 1bb5e49 and 30a1df6.


📒 Files selected for processing (5)
  • CHANGELOG.md
  • scripts/sidebar-activity-demo-regression.ts
  • src/components/AgentSidebar.tsx
  • src/lib/sidebarPins.test.ts
  • src/lib/sidebarPins.ts

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@devswha
devswha merged commit cf52fe4 into main Oct 11, 2026
9 checks passed
@devswha
devswha deleted the fix/pinned-agents-stay-in-cards branch October 11, 2026 23:49
devswha added a commit that referenced this pull request Oct 12, 2026
## Change

Release 0.4.8, from main at ca6db6e (20 PRs since v0.4.7: the 0.4.7
mobile walk-through fixes, two contributor PRs and the revived #793).

- `package.json` and `herdr-plugin.toml`: 0.4.8.
- CHANGELOG: `[Unreleased]` becomes `[0.4.8] - 2026-10-12`, with the
compare links. Twelve entries that had no PR link get theirs (#835 #837
#838 #840 #842 #843 #844+#848 #845 #847 #849 #851 #852). A Maintenance
line says the remote-PC runtime is now version 27.
- `release-summaries.json`: 0.4.8 in en/ko/ja/zh/tr (3 new, 6 improved,
8 fixed). The Turkish lines are not checked by a native speaker.
- `REMOTE_BUNDLE_VERSION` 26 -> 27: #836 adds the `pending-hold` server
feature and #787 serves precompressed assets, so `remote-v27` is
published before the app release.

Every PR merged since v0.4.7 is linked in the section: #787 #788 #793
#835 #836 #837 #838 #839 #840 #841 #842 #843 #844 #845 #846 #847 #848
#849 #851 #852.

## Validation

- `bun scripts/release-notes.ts 0.4.8` renders the summaries and the
full changelog (116 lines).
- `bun run check fast`: generated types, typecheck, build and 2800+ unit
tests pass.

## Release

After this merges and its CI on `main` passes: push `remote-v27`, wait
for its release, then run the Release workflow with `0.4.8`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
devswha added a commit that referenced this pull request Oct 12, 2026
…wsers (#854)

## Why
From 0.4.7 mobile testing: a star pinned on the PC did not show on the phone, and settings changed on one device did not reach the other — both lived only in each browser's `localStorage`. The user chose to sync **pins + settings that do not depend on the device**, keeping per-device ones local.

## Design
- **Scope, build-checked.** `SETTING_SCOPE` in `src/lib/settings.ts` marks every setting `shared` or `device` (`satisfies Record<keyof Settings, …>`, so a new setting must be classified). `shared/preferences.ts` lists the shared names; a unit test keeps the two equal.
  - shared: theme, palette, language, sidebarRows, agentOrder, agentCards, agentPins, autoSendQueued, showThinking, quickReplies, showQuickReplies, showSuggestionChip, showUsage, usageCount, usagePace, usageGlance, usageOrder, usageHidden, highlightCode
  - device: terminal*, keyBar*, shortcutOverrides, density, chat font/width, enterSends, keepScreenOn, alert*, voice*, paneClipboard, releasePaneAway, narrowPaneFont, quietOpenedDone, **defaultView** (phone chat vs desktop terminal)
  - Judgment calls for review: `language` (shared; `system` still resolves per browser), `defaultView` (device).
- **Server** (`server/preferences.ts`): one document in `stateDir/preferences.json` (0600, written whole via temp+rename) `{ revision, settings, pins }`. `GET/PUT /api/preferences` (not under `/api/machines`, never forwarded to a bridge). A PUT carries only the changed shared settings, laid over what is held (last write wins per setting), and `pins` only when they changed; unknown names are dropped, ≤500 pins, ≤64 KB. Watch-role devices are refused by the existing read-only gate. Each write is pushed as `{ type: "preferences" }` on `/api/machines/events`.
- **Client** (`src/lib/preferencesSync.ts`, used by `App` after the access gate):
  - load: a server with a document is applied (only the keys it holds); an empty server is never written on load;
  - change: debounced 600 ms, sends only what changed since the last match;
  - event: ignored at or below the last seen revision (own echo), or while a local change is unsent (it goes out next and wins);
  - 403 (watch device) → stop sending, keep receiving; 404 (older server) → sync off.
  - Pins moved to a small store in `sidebarPins.ts` (`useSyncExternalStore`), localStorage kept as cache.
- The `?read=` file reader (#849) does not run any of this.

## Tests
- Unit: `server/preferences.test.ts` (empty start, key stripping, merge, pins kept when omitted, revision, persistence, damaged file, 400/405/413), `preferencesSync.test.ts` (diff, apply), `settings.test.ts` (scope ↔ shared list).
- Contract: `device-access.contract.test.ts` — a watch device GETs 200, PUTs 403.
- Browser: new `preferences-sync-regression.ts` (two browsers, one server): no PUT on load; A's theme change reaches open B live and the PUT holds only `theme`; A's terminal font is never sent and B keeps its own; pins written elsewhere reach an open page; a later page takes the shared theme while keeping its own terminal font and an unchanged shared setting. Registered in `ci-browser.sh` (39 rows).
- `bun run check fast`, integration lane (447 pass), full browser lane — all pass except `narrow-pane-demo-regression`, which fails on `main` on this machine too (scripts after it were run individually and pass).

## Notes
- Interacts with #852 (pins stay in cards) in `AgentSidebar.tsx` — small textual conflict expected; whichever lands second needs a rebase.
- Feature + new route: per the repo's review practice this one should get the adversarial review before merge.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Maintainer commit 08e6c8b: one reconcile path for every document, held documents during an in-flight save, the document sent when the event stream opens, pins absent until first shared (first-share union, then last write wins), prune at pin time, server commits after the disk write, merged document under 64 KB.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.

1 participant