docs(domain): CONTEXT.md 改名 GLOSSARY.md 并对齐引用

domain-modeling skill 升级后单上下文约定文件名为 GLOSSARY.md:
git mv 保历史、内容零改动;AGENTS.md、docs/agents/domain.md 及
NG2 源码注释中的活引用随之对齐。docs/design、docs/research、ADR
中的旧名引用属历史记录,不改写。
This commit is contained in:
Qiu Yuzhou
2026-10-04 15:06:41 +08:00
parent edaa492257
commit 7bb327ba1d
22 changed files with 34 additions and 34 deletions
+2 -2
View File
@@ -14,9 +14,9 @@ triage 标签使用五个默认角色名作为标签字符串(needs-triage / nee
### Domain docs
single-context:根目录一个 `CONTEXT.md` + `docs/adr/`,按需惰性创建。见 `docs/agents/domain.md`。
single-context:根目录一个 `GLOSSARY.md` + `docs/adr/`,按需惰性创建。见 `docs/agents/domain.md`。
现状与已定设计以当前代码、`CONTEXT.md` 和 `docs/adr/` 为准。仅 `CONTEXT.md` 和 `docs/adr/` 持续维护为最新状态;判断当前实现时,以当前代码为事实依据。将设计文档或研究报告作为实现依据前,应先在代码中核实相关描述。
现状与已定设计以当前代码、`GLOSSARY.md` 和 `docs/adr/` 为准。仅 `GLOSSARY.md` 和 `docs/adr/` 持续维护为最新状态;判断当前实现时,以当前代码为事实依据。将设计文档或研究报告作为实现依据前,应先在代码中核实相关描述。
`docs/design/` 记录对应任务执行时的需求、设计与规格,仅作为历史参考,不代表最新代码现状。
View File
@@ -7,14 +7,14 @@ extension CatalogWorkflow {
// MARK: - 删除确认事实
/// 删除资格(命令入口的统一 disable 判据,如分区工具栏删除钮):节点存在
/// 且来源为 manual。订阅节点结构只读(CONTEXT.md),其移除属订阅分区流程,
/// 且来源为 manual。订阅节点结构只读(GLOSSARY.md),其移除属订阅分区流程,
/// 不经此口径。
func canDelete(_ id: NodeID) -> Bool {
guard let node = tree.node(withID: id) else { return false }
return node.isManual
}
/// 删除确认档位(CONTEXT.md:空手动组/服务器单次;非空手动组二次并点名规模)。
/// 删除确认档位(GLOSSARY.md:空手动组/服务器单次;非空手动组二次并点名规模)。
/// 节点不存在时为 `nil`。
func deleteFacts(for id: NodeID) -> DeleteConfirmKind? {
guard let node = tree.node(withID: id) else { return nil }
@@ -25,7 +25,7 @@ extension CatalogWorkflow {
try dependencies.credentials.save(url.absoluteString, for: record.urlRef)
do {
try commitSubscriptionDocument { catalog, subscriptions in
// 固定分组挂在目录根(CONTEXT.md「Subscription group」);名称以 host
// 固定分组挂在目录根(GLOSSARY.md「Subscription group」);名称以 host
// 兜底,首次成功刷新后跟随远端。
try catalog.addGroup(url.host ?? "", source: .subscription, id: record.groupID)
subscriptions.append(record)
@@ -118,7 +118,7 @@ extension CatalogWorkflow {
if let optionsRef = fields.pluginOptionsRef { try? credentials.delete(optionsRef) }
}
/// 插件选择落盘(issue #38,D10/CONTEXT.md 不变量):「无」整体清除引用与
/// 插件选择落盘(issue #38,D10/GLOSSARY.md 不变量):「无」整体清除引用与
/// 参数秘密;受管程序写引用、参数按空/非空经 journal 写删钥匙串;集外引用
/// 原样保留(不因打开或保存表单而漂移,激活语义由状态机点名拒绝)。
/// 受管集校验已由 `updateServer` 的表单校验完成。
@@ -151,7 +151,7 @@ final class CatalogWorkflow: ObservableObject {
/// 表单新建手动服务器:校验与提交语义与编辑对称——表单校验在建 journal
/// 前失败保持裸 `ServerFormError`;密码与可选插件参数和目录作为一个逻辑
/// 变更提交,持久化失败经 journal 回滚并以 `CommitError` 报出。新身份恒
/// 全新 UUID,不按内容去重(CONTEXT.md 不变量);返回新节点身份供选中。
/// 全新 UUID,不按内容去重(GLOSSARY.md 不变量);返回新节点身份供选中。
@discardableResult
func createServer(_ draft: ServerEditDraft, into parent: NodeID?) async throws -> NodeID {
let draft = try Self.prepareServerDraft(draft)
@@ -184,7 +184,7 @@ extension CatalogTreeSnapshot {
// MARK: - 目录政策事实(UI 写句子;本 module 不产成句文案)
/// 删除确认档位(CONTEXT.md 删除不变量的结构化事实)。
/// 删除确认档位(GLOSSARY.md 删除不变量的结构化事实)。
enum DeleteConfirmKind: Equatable, Sendable {
/// 服务器叶子:单次确认。
case leaf
@@ -1,7 +1,7 @@
import Combine
import Foundation
/// 插件参数会话草稿(issue #81,见 CONTEXT.md「Plugin parameter draft」):
/// 插件参数会话草稿(issue #81,见 GLOSSARY.md「Plugin parameter draft」):
/// 带稳定行身份的有序参数行 + 原始文本双模式。解析与拼装遵循受管
/// v2ray-plugin v1.3.2 的 SIP003 转义语义(未转义 `;` 分隔项目、第一个
/// 未转义 `=` 分隔参数名与值、反斜杠转义后续字符);原始参数字符串仍是
@@ -3,7 +3,7 @@ import SystemConfiguration
// MARK: - 命令地址投影(issue #72)
/// 首页命令地址候选(CONTEXT.md「Terminal command address」)。身份 = BSD
/// 首页命令地址候选(GLOSSARY.md「Terminal command address」)。身份 = BSD
/// 接口身份 + 规范化 IP;显示名与类型注记仅用于呈现,不参与身份,由呈现层
/// 自行组合(菜单项主行 IP、副标题「注记 - 名称」与收起状态说明行)。
struct TerminalCommandAddress: Equatable, Sendable {
@@ -46,7 +46,7 @@ extension ProxyRuntimeController {
&& settings.agentEnabled
}
/// 派生文档对当前运行时是否无事可做(CONTEXT.md「有效值未变的提交不做
/// 派生文档对当前运行时是否无事可做(GLOSSARY.md「有效值未变的提交不做
/// 运行时收敛」):磁盘契约与派生字节逐位相同、agent 已注册且 wrapper
/// 存活、控制器处于健康运行态——计划层动作序列为空即幂等跳过。判定在
/// 置 `starting` 之前进行,跳过路径不闪状态、不重走健康门;磁盘漂移或
+2 -2
View File
@@ -267,7 +267,7 @@ extension ServersView {
}
// 删除:作用于当前选中的服务器叶子或手动分组,确认弹窗与右键菜单共用
// deleteTarget 流(档位见 deleteFacts);无选中或选中项不可删(订阅节点
// 结构只读,CONTEXT.md)即禁用,资格判定归政策 seam。
// 结构只读,GLOSSARY.md)即禁用,资格判定归政策 seam。
ToolbarItem(placement: .primaryAction) {
Button {
deleteTarget = selection
@@ -278,7 +278,7 @@ extension ServersView {
.help("删除")
.disabled(!canDeleteSelection)
}
// 分享(分享/导出术语见 CONTEXT.md):作用于选中的服务器叶子,弹窗内
// 分享(分享/导出术语见 GLOSSARY.md):作用于选中的服务器叶子,弹窗内
// 提供二维码与复制 ss:// 链接两条通路;无有效载荷即不可用。
ToolbarItem(placement: .primaryAction) {
Button {
+1 -1
View File
@@ -3,7 +3,7 @@ import SwiftUI
/// 侧栏树行(issue #41):来源标识、有效性提示、活动目标标记与右键菜单。
/// 数据来自目录工作流 module 的树 projection;激活经 seam 的 typed command,
/// 活动目标标记由父视图传入(运行时事实,不进目录 projection)。删除一律
/// 交父视图确认弹窗(空手动组单次、非空二次,CONTEXT.md)。
/// 交父视图确认弹窗(空手动组单次、非空二次,GLOSSARY.md)。
struct SidebarRow: View {
let node: CatalogTreeNode
let workflow: CatalogWorkflow
+2 -2
View File
@@ -1,4 +1,4 @@
/// 目录操作失败原因,逐项对应 CONTEXT.md 的结构不变量(单父、显子序、
/// 目录操作失败原因,逐项对应 GLOSSARY.md 的结构不变量(单父、显子序、
/// 无环、手动/订阅严格分离)。
enum CatalogError: Error, Equatable, Sendable {
/// 目标节点不存在。
@@ -18,7 +18,7 @@ enum CatalogError: Error, Equatable, Sendable {
/// 订阅子树由远端权威所有:本地结构操作(移动/删除/改连接字段/改名)一律拒绝;
/// 整棵订阅子树的移除属于订阅票(#35)。
case subscriptionNodeImmutable(NodeID)
/// 订阅服务器叶子必须位于其订阅固定分组内,不得直挂目录根(CONTEXT.md
/// 订阅服务器叶子必须位于其订阅固定分组内,不得直挂目录根(GLOSSARY.md
/// 「Subscription group」:根层只允许订阅固定分组本身)。
case subscriptionServerAtRoot(NodeID)
/// 把分组移动进它自己的子树会成环。
+1 -1
View File
@@ -42,7 +42,7 @@ struct ServerFields: Codable, Equatable, Sendable {
}
}
/// 分组:命名的有序容器,显式持有子节点顺序(CONTEXT.md「Configuration group」)。
/// 分组:命名的有序容器,显式持有子节点顺序(GLOSSARY.md「Configuration group」)。
struct GroupFields: Codable, Equatable, Sendable {
var name: String
var children: [NodeID]
@@ -1,4 +1,4 @@
/// 配置目录:不可见的配置树根(CONTEXT.md「Configuration catalog」)。有序顶层
/// 配置目录:不可见的配置树根(GLOSSARY.md「Configuration catalog」)。有序顶层
/// 子节点为服务器配置或配置组。存储形态:全量节点表 + 根序 + 各分组显子序;
/// 单父由「一个身份只出现在一条子序里」构造保证,无环与来源分离由操作校验。
///
@@ -252,7 +252,7 @@ extension ConfigurationCatalog {
return collected
}
/// 订阅快照原子应用(CONTEXT.md 刷新契约):以快照整体重建固定分组子树;
/// 订阅快照原子应用(GLOSSARY.md 刷新契约):以快照整体重建固定分组子树;
/// 名称、结构、顺序和连接字段全部跟随远端(扩展缺失时由调用方给 URL host
/// 兜底)。返回被移除的旧服务器叶子(供调用方清理凭据)。
@discardableResult
@@ -1,6 +1,6 @@
import Foundation
/// 受管插件提供缝(spec #21 D10,CONTEXT.md「Managed plugin」):给定服务器
/// 受管插件提供缝(spec #21 D10,GLOSSARY.md「Managed plugin」):给定服务器
/// 持有的插件程序引用,返回本版本提供的 bundle 内绝对路径;返回 nil 即
/// 「本版本未提供」,该引用使叶子成为无效激活候选(激活点名拒绝)。
protocol ManagedPluginProviding {
+2 -2
View File
@@ -1,6 +1,6 @@
import Foundation
/// 节点来源:手动子树与订阅子树严格分离(CONTEXT.md「Relationships and invariants」)。
/// 节点来源:手动子树与订阅子树严格分离(GLOSSARY.md「Relationships and invariants」)。
enum NodeSource: String, Codable, Equatable, Sendable {
case manual
case subscription
@@ -27,7 +27,7 @@ struct NodeID: Hashable, Codable, Sendable {
}
}
/// 凭据引用:指向 Keychain 权威副本的非秘密关联(CONTEXT.md「Credential
/// 凭据引用:指向 Keychain 权威副本的非秘密关联(GLOSSARY.md「Credential
/// reference」)。配置树只存引用,永不存秘密明文;秘密值按 D5 由
/// CredentialStoring 写读。
struct CredentialReference: Hashable, Codable, Sendable {
@@ -4,7 +4,7 @@ struct SkippedServer: Equatable, Sendable {
let reason: LeafInvalidationReason
}
/// 激活产出:活动目标身份 + 完整派生文档。组目标保持组 UUID(CONTEXT.md
/// 激活产出:活动目标身份 + 完整派生文档。组目标保持组 UUID(GLOSSARY.md
/// 「Active target」),不被 sslocal 实际选中的后代替换。
struct RuntimeConfiguration: Equatable, Sendable {
let targetID: NodeID
@@ -176,7 +176,7 @@ struct SslocalRuntimeDocument: Codable, Equatable, Sendable {
}
/// 上游 `servers[]` 条目。id 携带叶子身份,供上游稳定标识;显示名是目录
/// 元数据,不进契约(CONTEXT.md「Runtime configuration file」)。
/// 元数据,不进契约(GLOSSARY.md「Runtime configuration file」)。
/// 插件字段在无插件时整体省略(D10)。
struct SslocalServerDocument: Codable, Equatable, Sendable {
let id: String
@@ -4,7 +4,7 @@ import Foundation
/// 身份 + 订阅 URL 凭据引用 + 最近刷新状态。URL 是敏感信息,权威副本在凭据
/// 存储(D5),目录文档只持引用;编辑 URL 保留订阅与固定分组身份。
struct SubscriptionRecord: Codable, Equatable, Sendable, Identifiable {
/// 订阅源身份;删除后新建即新身份(CONTEXT.md「Subscription」)。
/// 订阅源身份;删除后新建即新身份(GLOSSARY.md「Subscription」)。
let id: NodeID
/// 固定订阅分组的稳定身份(客户端所有,跨刷新与 URL 编辑不变)。
let groupID: NodeID
@@ -2,7 +2,7 @@ import XCTest
@testable import ShadowsocksX_NG2
/// 目录提交 → 运行时收敛语义(D3/D5 与 CONTEXT.md「有效值未变的提交不做
/// 目录提交 → 运行时收敛语义(D3/D5 与 GLOSSARY.md「有效值未变的提交不做
/// 运行时收敛」):与主测试类同构扩展,按既有模式独立成文件。
final class ProxyRuntimeCatalogConvergenceTests: ProxyRuntimeControllerTests {
override func makeDefaultRuleSnapshots() -> BuiltinRuleSnapshots {
+8 -8
View File
@@ -4,8 +4,8 @@ How the engineering skills should consume this repo's domain documentation when
## Before exploring, read these
- **`CONTEXT.md`** at the repo root, or
- **`CONTEXT-MAP.md`** at the repo root if it exists — it points at one `CONTEXT.md` per context. Read each one relevant to the topic.
- **`GLOSSARY.md`** at the repo root, or
- **`GLOSSARY-MAP.md`** at the repo root if it exists — it points at one `GLOSSARY.md` per context. Read each one relevant to the topic.
- **`docs/adr/`** — read ADRs that touch the area you're about to work in. In multi-context repos, also check `src/<context>/docs/adr/` for context-scoped decisions.
If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved.
@@ -16,31 +16,31 @@ Single-context repo (this repo):
```
/
├── CONTEXT.md
├── GLOSSARY.md
├── docs/adr/
│ ├── 0001-event-sourced-orders.md
│ └── 0002-postgres-for-write-model.md
└── src/
```
Multi-context repo (presence of `CONTEXT-MAP.md` at the root):
Multi-context repo (presence of `GLOSSARY-MAP.md` at the root):
```
/
├── CONTEXT-MAP.md
├── GLOSSARY-MAP.md
├── docs/adr/ ← system-wide decisions
└── src/
├── ordering/
│ ├── CONTEXT.md
│ ├── GLOSSARY.md
│ └── docs/adr/ ← context-specific decisions
└── billing/
├── CONTEXT.md
├── GLOSSARY.md
└── docs/adr/
```
## Use the glossary's vocabulary
When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.
When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `GLOSSARY.md`. Don't drift to synonyms the glossary explicitly avoids.
If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`).