Skip to content

feat(settings): sync case options and selection across devices - #732

Draft
opticon454 wants to merge 1 commit into
Ark0N:masterfrom
opticon454:feature/sync-case-state
Draft

opticon454 wants to merge 1 commit into
Ark0N:masterfrom
opticon454:feature/sync-case-state

Conversation

@opticon454

@opticon454 opticon454 commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Adds an opt-in Sync cases across devices setting, off by default. The feature stores each case's Agent Teams and Opus 1M options on the server and follows the last selected case when another device returns to its tab. It uses the existing settings endpoint and adds a minor changeset and settings documentation.

Draft: four confirmed review findings must be fixed before this is ready to merge. Existing tests pass but do not cover these defects. The branch has been rebased onto upstream/master at f1f7eec4; this draft contains one feature commit and seven changed files. The settings payload conflict was resolved by retaining both the sync field and upstream backup and agent settings.

Open findings

  • CASE-SYNC-001, high: administrator case names and options reach non-admins. settingsForNonAdmin omits caseOrder and lastUsedCase but retains the new caseSettings map. The settings load path then imports that map into local case options without a role check. Reproduced by applying a filtered administrator map while _settingsReadOnly() returns true. Redact the map server-side and gate client application on a confirmed writable role.
  • CASE-SYNC-002, high: concurrent saves lose case options. Two devices can GET the same map, add different case entries, then PUT replacement maps; the second write discards the first. Reproduced with concurrent alpha and beta updates. Send only the changed case and merge it inside upstream's existing serialised settings writer. Preserve input order for rapid saves from one device.
  • CASE-SYNC-003, high: failed sync requests are silently accepted. A GET returning HTTP 500 still leads to a replacement PUT, and a PUT returning HTTP 403 resolves without reporting rejection or marking settings read-only. Check both HTTP status and the response envelope, preserve local choices, report that they were not synced and reuse existing forbidden-write handling.
  • CASE-SYNC-004, medium: disabling sync elsewhere does not stop case following. With cached sync enabled, a response containing syncCaseState: false and a different valid lastUsedCase still changes selection. Refresh the cached preference and obey server authority before applying options or selection, including enable and disable transitions.

These findings were reproduced with assertions against the real client methods and server redaction function. They concern this unmerged feature branch.

Completion plan

  1. The rebase onto current upstream is complete. Reuse mutateSettingsFile for serialised, atomic per-case merging. Preserve validation, the merged 500-case limit and existing access checks; do not introduce another persistence layer.
  2. Implement the four fixes above. Await this device's pending saves before importing a snapshot; discard stale refresh results. Keep local fallback when a save fails. Give the new switch an accessible name.
  3. Carry shared options through the existing administrator case-rename transaction and rollback, and remove stale entries when a case is deleted or unlinked. Keep non-admin case operations independent of the shared map.
  4. Add regressions for privacy, concurrent and rapid saves, failed requests, read-only identity changes, stale responses and enable/disable transitions. Extend existing rename/delete tests and add a two-context browser test using an isolated test home and port 0.
  5. Update the documentation and changeset, then rerun the full CI suite, package tests, static checks and focused browser test before marking this ready. Preserve the default-off behaviour and existing local options while sync is off.

Validation after rebasing

  • Full CI unit/integration suite: 13,508 passed, 12 skipped, across 666 passing files and one skipped file; no failures.
  • xterm-zerolag-input: 282 passed across 10 files.
  • Lockfile, typecheck, lint, frontend syntax, browser exclusions, formatting, installer syntax, CLI catalogue and public asset checks passed, including the Bash 3.2 installer checks.
  • Pre-push static checks passed. The branch was force-pushed with an explicit lease on the previous head.
  • The four previously reproduced findings remain open. Browser, mobile and performance suites were not run. Passing existing tests does not clear the findings.

Rebased implementation commit: aaf3ccd29523bd5c70f6dc52edd2e8f88482fdf1. Upstream base: f1f7eec4d6a54c73822d118262712535eea5fd28. No deployment or release is included.

Release 1.47.0 rebase

Rebased onto f1f7eec4d6a54c73822d118262712535eea5fd28 in an isolated /tmp worktree, preserving the feature patch unchanged. Neither this PR nor the other rebased PR carries a change to src/web/public/whats-new.json, so regeneration was not needed. Full CI suite: 13,508 passed, 12 skipped, across 666 passing files and one skipped file. All 282 package tests and static/installer checks passed. The four open findings remain unresolved and this PR remains a draft.

@opticon454
opticon454 force-pushed the feature/sync-case-state branch from 6700fcb to 63234bb Compare October 28, 2026 08:14
@opticon454

Copy link
Copy Markdown
Contributor Author

Rebased this branch onto upstream/master at ecf28fa3bedaa7faaa8eaaa7fba265aca27f6d1d in an isolated /tmp worktree. The only conflict was in src/web/public/settings-ui.js; the resolution retains the sync setting and upstream's config-backup, inbox-persistence and agent-coordination settings. The feature remains one commit across seven files.

Force-pushed with an explicit lease on the previous PR head, 6700fcb46c4ce49bb8a433e55f1e95c598fdf926. New head: 63234bba69d8da0e600a04bb5d92898f2c8ec672.

Validation after resolving the conflict:

  • Full CI unit/integration suite: 13,433 passed, 12 skipped, across 660 passing files and one skipped file.
  • xterm-zerolag-input: 282 passed across 10 files.
  • All static, public asset, CLI catalogue and installer checks passed, including Bash 3.2.
  • Pre-push static checks passed.

This resolves the merge conflict only. The four findings in the PR description remain open, and this PR remains a draft. Browser, mobile and performance suites were not run. Fresh upstream CI will report against the rebased head.

@opticon454
opticon454 force-pushed the feature/sync-case-state branch from 63234bb to aaf3ccd Compare October 28, 2026 13:34
@opticon454

Copy link
Copy Markdown
Contributor Author

Rebased onto release 1.47.0's upstream/master (f1f7eec4d6a54c73822d118262712535eea5fd28) in an isolated /tmp worktree. Git range-diff confirms that the feature patch is unchanged. Force-pushed with an explicit lease on the previous head, 63234bba69d8da0e600a04bb5d92898f2c8ec672; the new head is aaf3ccd29523bd5c70f6dc52edd2e8f88482fdf1.

Validation:

  • Full CI unit/integration suite: 13,508 passed, 12 skipped, across 666 passing files and one skipped file.
  • xterm package: 282 passed.
  • Static checks, public asset checks and installer checks, including Bash 3.2, passed.
  • No PR-owned whats-new.json change was present, so no regeneration was needed.

The four known findings remain open; this PR remains a draft. Browser, mobile and performance suites were not run on this branch. Fresh upstream CI will validate the rebased head.

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