22 Commits
Author SHA1 Message Date
Qiu Yuzhou 3e64743237 fix(runtime): allow initial balancer startup
Initial multi-server checks can consume the entire five-second listener
budget before sslocal binds its inbound ports. Allow 15 seconds for
listeners and 30 seconds for GUI startup health confirmation.

Include endpoint readiness diagnostics and a delayed-start regression.
2026-10-30 08:52:36 +08:00
Qiu Yuzhou 59ce386bad test(rules): strengthen isolation and remove redundant checks 2026-10-25 14:32:12 +08:00
Qiu Yuzhou f6abd4343e feat(rules)!: add isolated routing presets
Add Mainland China proxy routing with independent rule workspaces.
Preserve existing routing choices through equivalent preset mappings.

BREAKING CHANGE: existing custom rules and enablement settings are
not migrated. Recreate them in the appropriate preset.
2026-10-25 14:32:12 +08:00
Qiu Yuzhou 5d6b8f433f test: move process lifecycle checks to smoke 2026-10-24 03:27:28 +08:00
Qiu Yuzhou b7648ceecd test(smoke): stop on missing deployment receipt 2026-10-24 02:51:39 +08:00
Qiu Yuzhou ca9215099b fix(tests): restore strict test compilation 2026-10-24 02:51:27 +08:00
Qiu Yuzhou b6b9349d64 style: resolve SwiftLint violations 2026-10-23 01:10:40 +08:00
Qiu Yuzhou f847c01e70 chore(deps): update v2ray-plugin to v1.4.0 2026-10-22 00:49:56 +08:00
Qiu Yuzhou 2c75ee67ec feat(runtime): hot reload ACL rules with signals 2026-10-20 23:54:05 +08:00
Qiu Yuzhou 6f33260b3b chore(sslocal): pin fork v1.26.0 2026-10-20 17:21:44 +08:00
Qiu Yuzhou 1541e97fb3 test(runtime): silence unified-log writes during test runs
Add the SSXNG_SYSTEM_LOG=0 test seam: RuntimeLog.emit and the sslocal
unified-log destination skip their os.Logger writes when it is set,
while stderr lines and the event sink are unaffected. Test execution
no longer floods the unified log store (a full validate run previously
recorded 795 entries under the shared subsystem, 743 from xctest and
52 from test-spawned agents).

The switch is injected by the schemes' test actions only (Run/Profile
keep system logging so debugging from Xcode still shows it), and set
explicitly in the fixtures that spawn the agent/sslocal processes,
including the fixture that strips inherited SSXNG_* path seams. The
main scheme is now declared explicitly to keep the variable out of the
Launch/Profile actions. Document the seam in ADR-0045.
2026-10-20 12:38:21 +08:00
Qiu Yuzhou 0f3454602f refactor: separate proxy preferences from listening configuration 2026-10-19 12:10:48 +08:00
Qiu Yuzhou e0db8b1e13 refactor(runtime): publish isolated supervision generations
Separate Agent supervision from sslocal input and preserve the latest intent after deployment failure. Persist failure barriers, serialize publication and retirement, and verify reload and single-instance behavior with real processes.

Refs #83
2026-10-19 03:00:33 +08:00
Qiu Yuzhou 297fc30c41 feat(connectivity): measure warmed HTTP latency phases 2026-10-15 17:39:13 +08:00
Qiu Yuzhou c49d605a5b chore(ng2): remove fork issue references from comments 2026-10-13 00:38:06 +08:00
Qiu Yuzhou f80018a260 test: 并发执行冒烟测试并隔离本地网络夹具 2026-10-04 01:46:21 +08:00
Qiu Yuzhou 14fdd493a3 fix(rules-smoke): adapt smoke fixtures to sourceless ProxyRule
fcd5645「slim built-in snapshots」移除了 ProxyRule 的 source 字段后 Smoke
target 未同步,构造器多传 source: 导致冒烟编译失败(先于收敛脊柱重构就
存在的破损)。移除冒烟夹具中的 source 实参与不再使用的 RuleSourceIdentity
局部值;来源身份属于浏览集合层,运行时文档与 ACL 只消费 action+match,
夹具语义不变。
2026-10-03 11:21:37 +08:00
Qiu Yuzhou 280a3fe6fe fix(rules): make validation and ACL order independent (#75)
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.
2026-10-02 16:34:52 +08:00
Qiu Yuzhou ac60d14099 refactor(tests): locate app product via bundle ancestor walk, not Bundle.main
测试需要 app 产物(嵌入二进制、打包面断言)时改经 AppArtifact 沿测试包
落盘位置向上查找 ShadowsocksX-NG2.app,覆盖两种布局:TEST_HOST 过渡期
.xctest 嵌于 Contents/PlugIns/,去宿主化后与 .app 平级。接触点:
AgentLifecycleTests wrapper、BundleManagedPluginProviderTests 组合根事实
断言、smoke 三处 sslocal/wrapper/plugin 定位、SkeletonTests 改读产物
Info.plist。行为等价(665 单测 + 11 冒烟全绿),为去 TEST_HOST 铺路。
2026-09-30 20:05:37 +08:00
Qiu Yuzhou b8e5919bcd fix(runtime): converge proxy runtime only when contract bytes change
Every catalog commit re-expanded the active target and ran the full
deploy cycle unconditionally: the status face flashed back to starting,
the launch health gate re-probed both local inbounds, and system proxy
converged again — even when the derived contract was byte-identical to
what was already deployed. Remark edits went further: remarks were part
of SslocalServerDocument, so renaming the active server rewrote the
contract and signalled sslocal for a change with no runtime effect.

The reload predicate is now contract byte equality, shared by both
layers (CONTEXT.md: a committed edit that leaves the runtime
configuration file's bytes unchanged triggers no runtime convergence
work). remarks leave the contract — upstream treats them as optional
metadata and the GUI resolves display names from the catalog — so
remark-only edits and no-op re-saves derive byte-identical documents.
The catalogDidCommit deploy path skips write, signal, health gate and
system proxy converge when ProxyRuntimePlan.actions returns empty
(registered agent, live wrapper, on-disk contract equals the derived
document); disk drift or a dead wrapper keeps the self-healing deploy.
Catalog revalidation (candidate skips, target invalidation) still runs
on every commit, and explicit intents (activation, switches, settings,
launch resync) are untouched.

The remark-edit runtime test — which encoded the old behavior as the
example of a value change — is replaced by four catalog-convergence
cases: remark-only edit and outside-subtree edit stay untouched, group
member and active server value edits rewrite and signal.

Also repairs the smoke suite, which failed on HEAD before this change:
its ACL documents used a sslocal-active.acl path while
RuntimeFileStore.write validates against acl-active.ini, so every
ACL-bearing case threw before spawning the wrapper. Smoke ACL paths now
bind to the store-validated location, and the suite passes 11/11 against
real sslocal, confirming upstream accepts the contract without remarks.
2026-09-29 11:57:37 +08:00
Qiu Yuzhou 5abb6c6033 build: migrate NG2 to Swift 6 and clear warnings 2026-09-28 08:44:53 +08:00
Qiu Yuzhou 851660f1c6 test: split real-process smoke into opt-in target
Real sslocal smoke (11 tests, ~27s) sat on every task test as the
slow tail. Tests/Smoke now builds as a separate target behind the
ShadowsocksX-NG2Smoke scheme; task test:smoke runs it on demand and
the README release gate requires it green next to packaging-gate.

SignalRecorder also gains kill(_, 0) semantics (stale pids report
ESRCH): the GUI-restart test burned the 5s waitForWrapperExit
ceiling on pid 99999, now 0.18s. Default lane: 617 tests ~40s.
2026-09-27 01:11:48 +08:00