docs: streamline agent guidance in English

This commit is contained in:
Qiu Yuzhou
2026-10-24 02:56:36 +08:00
parent 2365befbfe
commit 2e5c159d51
4 changed files with 67 additions and 32 deletions
+11 -11
View File
@@ -1,37 +1,37 @@
# ShadowsocksX-NG
macOS Shadowsocks 客户端。旧版实现已从本仓库移除,归档在 [shadowsocks/ShadowsocksX-NG](https://github.com/shadowsocks/ShadowsocksX-NG) 的 [`legacy-v1`](https://github.com/shadowsocks/ShadowsocksX-NG/tree/legacy-v1) 分支,仅作只读参考;新实现位于 `ShadowsocksX-NG2/`。文档与注释中引用旧版源码的链接都指向该分支。
A macOS Shadowsocks client. The legacy implementation has been removed from this repository and archived on the [`legacy-v1`](https://github.com/shadowsocks/ShadowsocksX-NG/tree/legacy-v1) branch of [shadowsocks/ShadowsocksX-NG](https://github.com/shadowsocks/ShadowsocksX-NG) for read-only reference. The new implementation lives in `ShadowsocksX-NG2/`. Links to legacy source code in documentation and comments must point to that branch.
## Agent skills
### Local validation
验证 ShadowsocksX-NG2 变更或诊断本地验证产物时,读取 [本地验证技能](.agents/skills/shadowsocksx-ng2-local-validation/SKILL.md)。仓库内版本为维护入口;memory 中的同名技能仅为历史快照。
When validating ShadowsocksX-NG2 changes or diagnosing local validation artifacts, read the [local validation skill](.agents/skills/shadowsocksx-ng2-local-validation/SKILL.md). The repository copy is maintained; copies with the same name in memory are historical snapshots.
### Git commits
Git 提交消息使用英文 Conventional Commits 格式。
Write commit messages in English using Conventional Commits.
### Issue tracker
Issue 跟踪在本仓库的 GitHub Issues,统一用 `gh` CLI 操作,并在每条命令上显式指定本仓库。见 `docs/agents/issue-tracker.md`。
Track issues in this repository's GitHub Issues. Use the `gh` CLI and explicitly specify this repository in every command. See `docs/agents/issue-tracker.md`.
### Code comments
编写或修改代码注释时,禁止引用 fork 仓库的 Issue 编号(包括 `#123`、`owner/repo#123` 或 Issue 链接),因为合并到上游后无法依靠上游 Issue 跟踪这些引用。注释应直接说明行为、约束或设计原因,使其无需查阅 fork Issue 也能理解。
When writing or modifying code comments, do not reference fork repository issues through numbers such as `#123`, qualified references such as `owner/repo#123`, or issue links. These references cannot be tracked through upstream issues after merging. State the behavior, constraint, or design rationale directly so the comment is understandable without consulting a fork issue.
### Triage labels
triage 标签使用五个默认角色名作为标签字符串(needs-triage / needs-info / ready-for-agent / ready-for-human / wontfix)。见 `docs/agents/triage-labels.md`。
Use the five default role names as triage label strings: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, and `wontfix`. See `docs/agents/triage-labels.md`.
### Domain docs
single-context:根目录一个 `GLOSSARY.md` + `docs/adr/`,按需惰性创建。见 `docs/agents/domain.md`。
Use a single context: one root `GLOSSARY.md` plus `docs/adr/`, created on demand. See `docs/agents/domain.md`.
`GLOSSARY.md` 和新建 ADR 的正文使用简体中文,代码标识符与必要的英文术语保留原文。已有 ADR 保留原文,不作语言迁移。
Write the body of `GLOSSARY.md` and new ADRs in Simplified Chinese, retaining code identifiers and necessary English terms. Existing ADRs retain their original language.
现状与已定设计以当前代码、`GLOSSARY.md` 和 `docs/adr/` 为准。仅 `GLOSSARY.md` 和 `docs/adr/` 持续维护为最新状态;判断当前实现时,以当前代码为事实依据。将设计文档或研究报告作为实现依据前,应先在代码中核实相关描述。
Current code, `GLOSSARY.md`, and `docs/adr/` define the current state and accepted designs. Only `GLOSSARY.md` and `docs/adr/` are continuously maintained as current documentation; use current code as the source of truth for implementation behavior. Before using a design document or research report as an implementation basis, verify the relevant descriptions against the code.
`docs/design/` 记录对应任务执行时的需求、设计与规格,仅作为历史参考,不代表最新代码现状。
`docs/design/` records requirements, designs, and specifications at the time of each task. It is historical reference and does not represent the latest implementation.
`docs/research/` 收录研究报告。各文档记录写作时点对上游能力、候选方案与结论的调研,不描述项目当前状态,也不代表相关设计已经被采纳。
`docs/research/` contains research reports. Each report records upstream capabilities, candidate solutions, and conclusions at the time of writing. It does not describe the project's current state or establish that a design has been adopted.
+6 -21
View File
@@ -1,26 +1,11 @@
# ShadowsocksX-NG2
新实现(2.0)所在目录。仓库级约定见根目录 [`AGENTS.md`](../AGENTS.md);工程结构、外部二进制供应链、签名基线、构建测试命令、代码风格工具安装与基线版本见 [`README.md`](README.md),本文件不重复。
See the root [`AGENTS.md`](../AGENTS.md) for repository conventions and [`README.md`](README.md) for project and development documentation.
## Unit tests(hostless)
## Testing principles
单测不以 app 为宿主(ADR-0021)。两条约定:
- Keep unit tests hostless and access packaged resources through explicit dependency injection.
- Isolate test resources to support parallel execution across multiple runners.
- Choose the smallest deterministic inputs that serve the assertions. When optimizing duration, preserve the tested workflow, scenario relationships, and timing semantics.
- 测试需要 app 产物(嵌入二进制、打包面 Info.plist 断言)时,一律经 `Tests/AppArtifact.swift` 定位。
- 生产代码读取 app bundle 内打包资源(规则快照、LaunchDaemon 清单等)时,走注入缝——控制器的 `appBundle` 参数(生产默认 `Bundle.main`),测试夹具注入 `AppArtifact.bundle`。
背景与三处资源缝的由来见 [ADR-0021](../docs/adr/0021-hostless-unit-tests.md)。
## Test framework
- 新增测试默认用 Swift Testing(`import Testing`);UI 测试与性能测试依赖 XCTest 专属 API(`XCUIApplication`、`measure` 计时),继续用 XCTest;存量 XCTest 用例不回迁。
- 单测多 runner 并行执行:新夹具只占用进程私有资源——运行时分配端口、临时目录、UUID 后缀命名空间,不写共享路径与固定名。
## Test fixtures and execution cost
- 输入规模由断言目标决定。启停、保存、部署、回滚、状态投影等行为集成测试使用小型确定性输入,保留真实的被测工作流与编译路径;规则行为夹具优先复用 `ProxyRuntimeFixture.controlFlowRuleSnapshot`。
- 验证打包资源、完整规则语义、大数据边界或性能的专用用例,显式注入完整数据。行为测试通过规则数据注入缝缩小输入;仍需清单等打包资源时保留 `AppArtifact.bundle`。
- 小夹具保留场景依赖:覆盖、遮蔽、禁用、孤立记录等关系按用例构造;公共夹具中无关的域名避开用例自身的规则,避免意外吸收或重复使预期部署变成无操作。替身实现被测流程依赖的注册、退出、回执等生命周期语义。
- 异步穿插优先用 expectation、gate 或可控时钟观测阶段;与断言无关的生产延迟通过注入缩短。保留用例刻意验证的超时、健康窗、进程监督等待与数据边界。
- 存量 XCTest 按行为拆为可独立调度的具体测试类;共享夹具基类只放状态和工厂,不含 `test*` 方法,避免子类重复执行继承用例。拆类或调整夹具后核对用例清单,确认无遗漏、重复或新增跳过。
- 优化耗时先记录同一配置下的全量墙钟、最慢类和用例,再分段测量定位计算与等待。优先消除测试目标之外的重复计算,再评估拆类并行或独立的生产性能优化;用例耗时合计除以墙钟表示执行重叠,不能当作 CPU 使用率。
Before adding or modifying tests or optimizing test duration, read [Writing and optimizing tests](../docs/development.md#writing-and-optimizing-tests) for framework selection, resource lookup, fixture design, and measurement methods.
+25
View File
@@ -66,6 +66,31 @@ You can build and run unit tests without a certificate: the Debug baseline uses
`Tests/Smoke/` contains real-process smoke tests. A wrapper launches real `sslocal` to verify startup, handshake, ACL routing, and plugin supervision. These tests are not part of the default `task test`; run them locally with their separate scheme. CI runs them as an independent job. Pending reload-signal accumulation is tested without child processes in `RuntimeReloadStateTests`; real signal delivery and combined server/ACL routing remain covered by `RuntimePublicationSmokeTests`.
## Writing and optimizing tests
### Hostless tests and packaged resources
Unit tests run without the app as a host ([ADR-0021](adr/0021-hostless-unit-tests.md)):
- Tests that need the app product, such as embedded binaries or packaged `Info.plist` assertions, locate it through `Tests/Support/AppArtifact.swift`.
- Production code reads packaged resources, such as rule snapshots and LaunchDaemon manifests, through explicit dependency injection. Controllers use an `appBundle` parameter with `Bundle.main` as the production default; test fixtures inject `AppArtifact.bundle`.
See ADR-0021 for the background and the three resource seams.
### Test framework and isolation
- Use Swift Testing (`import Testing`) for new tests by default. UI and performance tests continue to use XCTest for its exclusive APIs (`XCUIApplication` and `measure`). Existing XCTest cases stay in XCTest.
- Unit tests run in parallel across multiple runners. New fixtures use process-private resources: dynamically allocated ports, temporary directories, and UUID-suffixed namespaces instead of shared paths or fixed names.
### Fixtures and execution cost
- Choose input size from the assertion's purpose. Behavior integration tests for starting, stopping, saving, deploying, rolling back, and state projection use small deterministic inputs while retaining the real workflow and compilation path. Prefer `ProxyRuntimeFixture.controlFlowRuleSnapshot` for rule behavior fixtures.
- Dedicated tests for packaged resources, complete rule semantics, large-data boundaries, or performance explicitly inject complete data. Behavior tests reduce inputs through rule-data injection; retain `AppArtifact.bundle` when packaged resources such as manifests are still needed.
- Small fixtures preserve scenario relationships, including overrides, shadowing, disabled entries, and orphaned records. Keep unrelated domains in shared fixtures outside the test's own rules, so accidental absorption or duplication does not turn an expected deployment into a no-op. Test doubles implement lifecycle behavior required by the tested workflow, including registration, exit, and receipts.
- Observe asynchronous interleaving with expectations, gates, or controllable clocks. Shorten production delays unrelated to assertions through injection. Preserve timeouts, health windows, process-supervision waits, and data boundaries that a case deliberately tests.
- Split existing XCTest cases by behavior into concrete classes that can be scheduled independently. Shared fixture base classes contain only state and factories; keep `test*` methods in concrete classes to avoid inherited cases running more than once. After splitting classes or changing fixtures, compare test inventories for omissions, duplicates, and newly skipped cases.
- Before optimizing duration, record the full-suite wall time and the slowest classes and cases under the same configuration. Then measure individual segments to distinguish computation from waiting. First remove repeated computation outside the test's purpose; then assess parallel scheduling through class splits or separate production performance changes. Summed case durations divided by wall time measure execution overlap, not CPU utilization.
## Code style tools
- `swift format` is included with the Xcode/Swift toolchain and does not need a separate installation (baseline: Apple Swift 6.4). Install SwiftLint with `brew install swiftlint` (baseline: 0.65.0), and install the hook manager with `brew install pre-commit`. If a required tool is missing, pre-commit rejects a commit that contains NG2 Swift files.
+25
View File
@@ -61,6 +61,31 @@ Swift Package Manager 从 `project.yml` 固定的正式版本解析 AgeSwift,
`Tests/Smoke/` 是真实进程冒烟(经 wrapper 拉起真实 sslocal 验证启动、握手、
ACL 路由与插件监管),不在默认 `task test` 内,由独立 scheme 按需运行。
## 编写与优化测试
### Hostless 与打包资源
单测不以 app 为宿主(ADR-0021)。两条约定:
- 测试需要 app 产物(嵌入二进制、打包面 Info.plist 断言)时,一律经 `Tests/Support/AppArtifact.swift` 定位。
- 生产代码读取 app bundle 内打包资源(规则快照、LaunchDaemon 清单等)时,走注入缝——控制器的 `appBundle` 参数(生产默认 `Bundle.main`),测试夹具注入 `AppArtifact.bundle`。
背景与三处资源缝的由来见 [ADR-0021](../docs/adr/0021-hostless-unit-tests.md)。
### 测试框架与隔离
- 新增测试默认用 Swift Testing(`import Testing`);UI 测试与性能测试依赖 XCTest 专属 API(`XCUIApplication`、`measure` 计时),继续用 XCTest;存量 XCTest 用例不回迁。
- 单测多 runner 并行执行:新夹具只占用进程私有资源——运行时分配端口、临时目录、UUID 后缀命名空间,不写共享路径与固定名。
### 夹具与执行成本
- 输入规模由断言目标决定。启停、保存、部署、回滚、状态投影等行为集成测试使用小型确定性输入,保留真实的被测工作流与编译路径;规则行为夹具优先复用 `ProxyRuntimeFixture.controlFlowRuleSnapshot`。
- 验证打包资源、完整规则语义、大数据边界或性能的专用用例,显式注入完整数据。行为测试通过规则数据注入缝缩小输入;仍需清单等打包资源时保留 `AppArtifact.bundle`。
- 小夹具保留场景依赖:覆盖、遮蔽、禁用、孤立记录等关系按用例构造;公共夹具中无关的域名避开用例自身的规则,避免意外吸收或重复使预期部署变成无操作。替身实现被测流程依赖的注册、退出、回执等生命周期语义。
- 异步穿插优先用 expectation、gate 或可控时钟观测阶段;与断言无关的生产延迟通过注入缩短。保留用例刻意验证的超时、健康窗、进程监督等待与数据边界。
- 存量 XCTest 按行为拆为可独立调度的具体测试类;共享夹具基类只放状态和工厂,不含 `test*` 方法,避免子类重复执行继承用例。拆类或调整夹具后核对用例清单,确认无遗漏、重复或新增跳过。
- 优化耗时先记录同一配置下的全量墙钟、最慢类和用例,再分段测量定位计算与等待。优先消除测试目标之外的重复计算,再评估拆类并行或独立的生产性能优化;用例耗时合计除以墙钟表示执行重叠,不能当作 CPU 使用率。
## 代码风格工具
- `swift format` 随 Xcode/Swift 工具链提供,无需单独安装(基线:Apple Swift 6.4);SwiftLint 需 `brew install swiftlint`(基线 0.65.0),钩子管理器需 `brew install pre-commit`。缺少必需工具时,暂存了 NG2 Swift 文件的提交会被拒绝。