The sidebar List selection binding can be written back during view
updates (macOS List/NavigationSplitView selection re-sync on row
content changes); publishing from the setter then triggered the
"Publishing changes from within view updates" runtime warning. Guard
navigate(to:) against same-value writes and pin the no-publish
invariant with a regression test.
Add versioned sheet-local drafts, normalized previews, custom identity validation,
and explicit saves through the existing rule-document transaction. Preserve UUIDs,
builtin memberships, disabled identities, and deployment recovery outcomes.
Include approved Chinese and English editor copy. Verify public Workflow commands,
the production Controller adapter with hostless tests, and compiled bilingual
resources. Visual acceptance remains manual.
Reserve one toolbar status area through saving, deployment, and collection
refresh. Show counted transient success and persistent actionable failures,
with distinct applied, unchanged-runtime, and deferred-save results.
Keep cached rows when collection reload fails. Require explicit refresh
and fresh selection after a version conflict.
Validation: 774 hostless tests passed with local ad-hoc signing. Format,
lint, two-axis review, and isolated Chinese/English view rendering checked.
Implement #77 using the complete saved versioned rule collection. Normalize domain, IP, and URL hosts; preserve three outcomes and all deciding identities, source memberships, and other target-specific matches without DNS or runtime dependencies.
Invalidate results when the target changes or refresh starts, and reject late asynchronous publication. Add the native address test panel and approved Chinese/English copy.
Validation: 760 hostless tests and 2 fixed-sslocal semantics smoke tests passed; ad-hoc Debug build passed. Changed-file format/lint clean; existing repository warnings remain. Standards and Spec reviews found no issues. Visual acceptance remains manual.
Bound source metadata and conversion reports to a scrolling region so expansion does not compete with the native table for window constraints. Replace the nested split with a fixed source list and flexible table to keep the rules page inside the main window.
Defer native binding writes until after the current view update, merge filter edits into the latest query, and suppress unchanged query and selection publications.
Validated with 744 hostless tests, an unsigned Debug build, and isolated native window checks at 920x738 and 920x580, including real source selection and disclosure clicks.
Normalize source-independent match/action identities while preserving custom UUIDs. Analyze complete valid candidates for same-action coverage and full or partial opposite-action shadowing without dropping saved intent. Keep duplicate and fixed-local conflicts blocking, including mapped IPv6.
Canonicalize ACL entries without changing runtime source selection or proxy-default skeleton. Verify persistence and no-restart reordering through the Controller, collection permutations, and pinned sslocal loopback comparisons.
Validation: 728 hostless tests and 2 pinned-binary smoke tests passed with ad-hoc arm64 signing; format, lint (3 existing warnings, 0 errors), and diff checks passed. No real system-proxy writes or automatic visual checks.
The home server list card redesign in 1c706aa dropped the trailing
manage-servers button; restore it in the HomeCard trailing slot wired
to the existing onManageServers callback.
Preserve catalog hierarchy and order, separate selection from activation, and mark active targets and ancestors. Persist independent home expansion preferences and support explicit locate and keyboard navigation.
Show server names only and surface activation eligibility, skipped members, and failures. Refine row status visibility and use semantic selection colors for outlined activation buttons, including hover, pressed, disabled, contrast, and inactive-window states.
Validation: 695 hostless macOS arm64 tests passed for the tree implementation; 7 focused tests and ad-hoc app compilation passed after the semantic button refinement. Format and lint checks passed. Native UI interactions and theme changes remain unverified.
Group and server rows in the home target tree carried redundant
subtitles (source labels and a per-group server count) duplicating
what the tree structure already shows. Remove them so each item is
a single-line title, bumped callout to body for a stronger title
presence. TargetGroupInfo loses the now-unused sourceLabel field.
Both server trees held collapse state inside the destination
subtree — ServersView relied on OutlineGroup's built-in expansion
state and the home target tree kept a local @State set — so every
destination switch destroyed it. Hoist a shared
CatalogExpansionState to the composition root; the servers sidebar
and the home target tree now read and write one collapse set.
ServersView replaces OutlineGroup with a manual collapse tree
(flattened visible rows, .tag keeps List selection), trading away
OutlineGroup's arrow-key expand/collapse. MainApp extracts
makeRuntimeController to stay within the function-body lint budget.
Hoist "open main window" into its own section at the top; drop
the in-menu "update all subscriptions" and "copy HTTP export
line" entries, which stay available in the main workspace. The
removed copy path retires the menu's clipboard seam and its
error-alert plumbing.
Implements issue #71 with ADR-0020 (supersedes ADR-0019's endpoint-signature
cleanup, startup cleanup, and health-gate cleanup).
- New ShadowsocksX-NG2SystemProxyHelper target: app-bundled root LaunchDaemon
(SMAppService.daemon, on-demand via MachServices) that mechanically applies
a closed typed configuration or executes an unconditional clear. Clients are
accepted by code-signing bundle identifier only; requests run serially on a
shared queue (last-writer-wins).
- SystemProxyConfiguration is now the closed typed apply payload (Codable over
JSON XPC): explicit SOCKS/HTTP/HTTPS enable + endpoints, PAC and
auto-discovery disabled with URL/JS removed, explicit simple-hostname
exclusion, complete ExceptionsList. Unmodeled Proxies keys are preserved and
equivalent values skip the commit.
- Cleanup is a side effect of a persisted system-proxy intent on-to-off
transition only: the switch itself, or the agent-off cascade (persist both
intents off, clear, then stop listeners; failed cascade persistence records
no transition and clears nothing). Launch with the switch off, health-gate
closure, invalid targets, and passive events never clear. Failed clears are
surfaced without deferred retry.
- Endpoint-signature store, ownership migration, and direct Authorization
Services writes are removed; old signature files stay inert. Helper
unavailability or pending approval keeps an enabled intent pending and
surfaces the Login Items approval path (HomeView button + menu label).