svharness 0.8.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +290 -61
  2. package/dist/adapters/claude-code.js +1 -0
  3. package/dist/adapters/codechat.js +1 -0
  4. package/dist/adapters/cursor.js +1 -0
  5. package/dist/adapters/generic.js +1 -0
  6. package/dist/adapters/index.js +2 -0
  7. package/dist/adapters/opencode.js +17 -0
  8. package/dist/adapters/qoder.js +1 -0
  9. package/dist/commands/apply.js +456 -71
  10. package/dist/commands/convert.js +371 -0
  11. package/dist/commands/init.js +156 -11
  12. package/dist/commands/references-apply-skills.js +47 -0
  13. package/dist/commands/wizard.js +442 -0
  14. package/dist/config/constants.js +7 -0
  15. package/dist/config/index.js +18 -0
  16. package/dist/config/load-config.js +54 -0
  17. package/dist/config/merge-options.js +115 -0
  18. package/dist/config/normalize.js +165 -0
  19. package/dist/config/save-config.js +40 -0
  20. package/dist/config/types.js +2 -0
  21. package/dist/core/agent-injector.js +58 -9
  22. package/dist/core/apply-project-entry.js +66 -0
  23. package/dist/core/build-project-entry.js +98 -0
  24. package/dist/core/doc-intake-paths.js +155 -0
  25. package/dist/core/extra-assets-intake.js +254 -0
  26. package/dist/core/markitdown-client.js +156 -0
  27. package/dist/core/next-steps.js +33 -22
  28. package/dist/core/project-ignore.js +53 -0
  29. package/dist/core/reference-apply-skills.js +35 -0
  30. package/dist/core/render-meta.js +2 -1
  31. package/dist/core/repomix-pack.js +3 -3
  32. package/dist/core/state.js +44 -24
  33. package/dist/index.js +211 -140
  34. package/dist/utils/harness-name.js +41 -0
  35. package/dist/utils/validate-args.js +147 -6
  36. package/dist/wiki/wikiTasksWriter.js +5 -6
  37. package/package.json +2 -1
  38. package/templates/_shared/apply-skills/harness-apply-skills-main.md +19 -78
  39. package/templates/_shared/build-rules/harness-build-rule-agent-agnostic.md +5 -5
  40. package/templates/_shared/build-rules/harness-build-rule-chinese-only.md +5 -5
  41. package/templates/_shared/build-rules/harness-build-rule-convert-check.md +46 -0
  42. package/templates/_shared/build-rules/harness-build-rule-memory-write.md +1 -1
  43. package/templates/_shared/build-rules/harness-build-rule-orchestrator-flow.md +36 -10
  44. package/templates/_shared/build-rules/harness-build-rule-skills-tasks-output.md +3 -2
  45. package/templates/_shared/build-rules/harness-build-rule-specs-schema.md +3 -3
  46. package/templates/_shared/build-rules/harness-build-rule-user-interaction.md +36 -16
  47. package/templates/_shared/build-skills/harness-build-skill-agent-env-merge.md +75 -0
  48. package/templates/_shared/build-skills/harness-build-skill-knowledge-builder.md +49 -85
  49. package/templates/_shared/build-skills/harness-build-skill-orchestrator.md +35 -18
  50. package/templates/_shared/build-skills/harness-build-skill-references-intake.md +91 -0
  51. package/templates/_shared/build-skills/harness-build-skill-spec-builder.md +19 -9
  52. package/templates/_shared/build-skills/harness-build-skill-wiki-writer.md +24 -24
  53. package/templates/_shared/build-skills/harness-build-skills-main.md +83 -0
  54. package/templates/_shared/meta/AGENTS_APPLY.md.ejs +139 -0
  55. package/templates/_shared/meta/{AGENTS.md.ejs → AGENTS_BUILD.md.ejs} +7 -5
  56. package/templates/_shared/meta/CHANGELOG.md.ejs +3 -3
  57. package/templates/_shared/meta/README.md.ejs +11 -9
  58. package/templates/_shared/meta/harness.yaml.ejs +28 -7
  59. package/templates/_shared/skeleton/baseline/code/.gitkeep +1 -0
  60. package/templates/_shared/skeleton/baseline/wiki/.gitkeep +1 -0
  61. package/templates/_shared/skeleton/references/apply-skills-registry.example.yaml +11 -0
  62. package/templates/_shared/skeleton/references/md/.gitkeep +1 -0
  63. package/templates/_shared/skeleton/references/raw/.gitkeep +1 -0
  64. package/templates/_shared/skeleton/references/yaml/.gitkeep +1 -0
  65. package/templates/_shared/skeleton/requirements/md/.gitkeep +1 -0
  66. package/templates/_shared/skeleton/requirements/raw/.gitkeep +1 -0
  67. package/templates/_shared/skeleton/requirements/yaml/.gitkeep +1 -0
  68. package/templates/android-xml/skeleton/agent-env/skills/harness-android-cli/SKILL.md +88 -0
  69. package/templates/android-xml/skeleton/agent-env/skills/harness-android-service-patterns/SKILL.md +205 -0
  70. package/templates/android-xml/skeleton/agent-env/skills/harness-android-xml-architecture/SKILL.md +138 -0
  71. package/templates/android-xml/skeleton/agent-env/skills/harness-lifecycle-management/SKILL.md +158 -0
  72. package/templates/android-xml/skeleton/agent-env/skills/harness-xml-ui/SKILL.md +112 -0
  73. package/templates/cpp/skeleton/agent-env/skills/harness-cmake-build/SKILL.md +163 -0
  74. package/templates/cpp/skeleton/agent-env/skills/harness-cpp-architecture/SKILL.md +157 -0
  75. package/templates/cpp/skeleton/agent-env/skills/harness-cpp-concurrency/SKILL.md +180 -0
  76. package/templates/cpp/skeleton/agent-env/skills/harness-memory-safety/SKILL.md +163 -0
  77. package/templates/cpp/skeleton/agent-env/skills/harness-modern-cpp/SKILL.md +149 -0
  78. package/templates/python/skeleton/agent-env/skills/harness-async-patterns/SKILL.md +162 -0
  79. package/templates/python/skeleton/agent-env/skills/harness-python-architecture/SKILL.md +160 -0
  80. package/templates/python/skeleton/agent-env/skills/harness-python-package-structure/SKILL.md +210 -0
  81. package/templates/python/skeleton/agent-env/skills/harness-python-performance/SKILL.md +207 -0
  82. package/templates/python/skeleton/agent-env/skills/harness-python-testing/SKILL.md +198 -0
  83. package/templates/svharness.config.example.yaml +40 -0
  84. package/templates/web-react/skeleton/agent-env/skills/harness-react-architecture/SKILL.md +177 -0
  85. package/templates/web-react/skeleton/agent-env/skills/harness-react-performance/SKILL.md +177 -0
  86. package/templates/web-react/skeleton/agent-env/skills/harness-react-testing/SKILL.md +193 -0
  87. package/templates/web-react/skeleton/agent-env/skills/harness-react-ui-patterns/SKILL.md +257 -0
  88. package/templates/web-react/skeleton/agent-env/skills/harness-state-management/SKILL.md +189 -0
  89. package/templates/_shared/skeleton/assets/baseline/code/.gitkeep +0 -1
  90. package/templates/_shared/skeleton/assets/baseline/wiki/.gitkeep +0 -1
  91. package/templates/_shared/skeleton/assets/raw/.gitkeep +0 -1
  92. package/templates/_shared/skeleton/assets/requirements/.gitkeep +0 -1
  93. /package/templates/_shared/skeleton/{assets/baseline/repomix → agent-env/_incoming/skills}/.gitkeep +0 -0
@@ -0,0 +1,149 @@
1
+ ---
2
+ name: harness-modern-cpp
3
+ description: Modern C++ (C++17/20) 最佳实践。覆盖智能指针、std::optional/span/variant、结构化绑定、constexpr 与范围算法。
4
+ ---
5
+
6
+ # Modern C++ 最佳实践
7
+
8
+ ## 概述
9
+
10
+ 优先使用 C++17/20 特性替代旧式 C 风格代码,提升代码安全性与可读性。
11
+
12
+ > **刚性约束已由 rules 加载:**
13
+ > - `seed-raii` — 禁止裸 new/delete,必须使用 RAII
14
+
15
+ ---
16
+
17
+ ## 智能指针
18
+
19
+ ```cpp
20
+ // 唯一所有权 — std::unique_ptr
21
+ auto sensor = std::make_unique<TemperatureSensor>(args...);
22
+
23
+ // 共享所有权 — std::shared_ptr(谨慎使用,只在真正需要时)
24
+ auto config = std::make_shared<Configuration>(path);
25
+
26
+ // 观察者 — 裸指针/引用(非拥有)
27
+ void process(const ISensor* sensor) {
28
+ if (sensor != nullptr) {
29
+ auto data = sensor->read();
30
+ }
31
+ }
32
+ ```
33
+
34
+ ## std::optional
35
+
36
+ ```cpp
37
+ // 可能无返回值的函数
38
+ std::optional<double> parseValue(const std::string& input) {
39
+ try {
40
+ return std::stod(input);
41
+ } catch (...) {
42
+ return std::nullopt; // 失败时不抛异常
43
+ }
44
+ }
45
+
46
+ // 使用
47
+ auto result = parseValue("3.14");
48
+ if (result.has_value()) {
49
+ use(result.value());
50
+ }
51
+
52
+ // 或使用 value_or 提供默认值
53
+ double v = parseValue(text).value_or(0.0);
54
+ ```
55
+
56
+ ## std::span — 连续内存视图
57
+
58
+ ```cpp
59
+ // 替代 (T* data, size_t len) 参数对
60
+ double computeAverage(std::span<const double> values) {
61
+ double sum = 0.0;
62
+ for (double v : values) {
63
+ sum += v;
64
+ }
65
+ return sum / static_cast<double>(values.size());
66
+ }
67
+
68
+ // 可传入 vector 或数组
69
+ std::vector<double> vec = {1.0, 2.0, 3.0};
70
+ double avg = computeAverage(vec);
71
+
72
+ double arr[] = {4.0, 5.0, 6.0};
73
+ avg = computeAverage(arr);
74
+ ```
75
+
76
+ ## std::variant — 类型安全联合体
77
+
78
+ ```cpp
79
+ // 替代裸 union
80
+ using Command = std::variant<StartCmd, StopCmd, ConfigCmd, ErrorCmd>;
81
+
82
+ void handleCommand(const Command& cmd) {
83
+ std::visit([](const auto& c) {
84
+ // 编译器确保所有类型都被处理
85
+ c.execute();
86
+ }, cmd);
87
+ }
88
+ ```
89
+
90
+ ## 结构化绑定
91
+
92
+ ```cpp
93
+ // 从 pair 解包
94
+ std::map<std::string, int> counts;
95
+ for (const auto& [key, value] : counts) {
96
+ // ...
97
+ }
98
+
99
+ // 从自定义类型解包
100
+ struct Point { double x, y, z; };
101
+ Point p{1.0, 2.0, 3.0};
102
+ auto [x, y, z] = p;
103
+ ```
104
+
105
+ ## constexpr
106
+
107
+ ```cpp
108
+ // 编译期计算
109
+ constexpr uint32_t crc32TableEntry(uint8_t index) {
110
+ uint32_t crc = index;
111
+ for (int i = 0; i < 8; ++i) {
112
+ crc = (crc & 1) ? (crc >> 1) ^ 0xEDB88320 : (crc >> 1);
113
+ }
114
+ return crc;
115
+ }
116
+
117
+ constexpr auto CRC_TABLE = []() {
118
+ std::array<uint32_t, 256> table{};
119
+ for (size_t i = 0; i < 256; ++i) {
120
+ table[i] = crc32TableEntry(static_cast<uint8_t>(i));
121
+ }
122
+ return table;
123
+ }();
124
+ ```
125
+
126
+ ## 范围算法 (C++20)
127
+
128
+ ```cpp
129
+ #include <ranges>
130
+ #include <algorithm>
131
+
132
+ std::vector<int> data = {4, 2, 3, 1, 5, 2, 6};
133
+
134
+ // 链式操作
135
+ auto result = data
136
+ | std::views::filter([](int n) { return n > 2; })
137
+ | std::views::transform([](int n) { return n * n; })
138
+ | std::views::take(3);
139
+
140
+ // 输出: 16, 9, 25
141
+ for (int v : result) { /* ... */ }
142
+ ```
143
+
144
+ ---
145
+
146
+ ## 相关规则
147
+
148
+ - `seed-raii` — RAII 与智能指针
149
+ - `seed-header-guards` — 头文件保护符
@@ -0,0 +1,162 @@
1
+ ---
2
+ name: harness-async-patterns
3
+ description: Python 异步编程模式。覆盖 asyncio 核心用法、协程管理、并发限流与错误处理。
4
+ ---
5
+
6
+ # 异步编程模式
7
+
8
+ ## 概述
9
+
10
+ 使用 `asyncio` 实现高并发 I/O 操作。遵循结构化并发原则,避免回调地狱。
11
+
12
+ ---
13
+
14
+ ## 基础模式
15
+
16
+ ### 协程定义与调用
17
+
18
+ ```python
19
+ import asyncio
20
+
21
+ async def fetch_data(url: str) -> dict:
22
+ async with httpx.AsyncClient() as client:
23
+ resp = await client.get(url)
24
+ resp.raise_for_status()
25
+ return resp.json()
26
+
27
+ # 入口点
28
+ async def main() -> None:
29
+ data = await fetch_data("https://api.example.com/data")
30
+ print(data)
31
+
32
+ asyncio.run(main())
33
+ ```
34
+
35
+ ### 并发执行
36
+
37
+ ```python
38
+ async def main() -> None:
39
+ # 并发运行多个协程
40
+ async with asyncio.TaskGroup() as tg:
41
+ task1 = tg.create_task(fetch_data("/api/users"))
42
+ task2 = tg.create_task(fetch_data("/api/posts"))
43
+ task3 = tg.create_task(fetch_data("/api/comments"))
44
+
45
+ results = [task1.result(), task2.result(), task3.result()]
46
+ ```
47
+
48
+ ## 并发限流
49
+
50
+ ```python
51
+ import asyncio
52
+ from asyncio import Semaphore
53
+
54
+ class RateLimiter:
55
+ """并发限流器。"""
56
+
57
+ def __init__(self, max_concurrent: int) -> None:
58
+ self._semaphore = Semaphore(max_concurrent)
59
+
60
+ async def execute[T](self, coro: asyncio.Task[T]) -> T:
61
+ async with self._semaphore:
62
+ return await coro
63
+
64
+ # 使用
65
+ async def batch_process(items: list[str]) -> list[dict]:
66
+ limiter = RateLimiter(max_concurrent=10)
67
+
68
+ async with asyncio.TaskGroup() as tg:
69
+ tasks = [
70
+ tg.create_task(limiter.execute(process_item(item)))
71
+ for item in items
72
+ ]
73
+
74
+ return [t.result() for t in tasks]
75
+ ```
76
+
77
+ ## 超时处理
78
+
79
+ ```python
80
+ async def fetch_with_timeout(url: str, timeout: float = 5.0) -> dict | None:
81
+ try:
82
+ async with asyncio.timeout(timeout):
83
+ return await fetch_data(url)
84
+ except asyncio.TimeoutError:
85
+ logger.warning("Request to %s timed out after %ss", url, timeout)
86
+ return None
87
+ ```
88
+
89
+ ## 生产者-消费者模式
90
+
91
+ ```python
92
+ import asyncio
93
+ from asyncio import Queue
94
+
95
+ async def producer(queue: Queue[int]) -> None:
96
+ for i in range(100):
97
+ await queue.put(i)
98
+ await asyncio.sleep(0.01)
99
+
100
+ async def consumer(name: str, queue: Queue[int]) -> None:
101
+ while True:
102
+ item = await queue.get()
103
+ try:
104
+ print(f"{name} processing {item}")
105
+ await asyncio.sleep(0.1) # 模拟处理
106
+ finally:
107
+ queue.task_done()
108
+
109
+ async def main() -> None:
110
+ queue: Queue[int] = asyncio.Queue(maxsize=20)
111
+
112
+ async with asyncio.TaskGroup() as tg:
113
+ tg.create_task(producer(queue))
114
+ for i in range(3):
115
+ tg.create_task(consumer(f"worker-{i}", queue))
116
+
117
+ await queue.join() # 等待所有任务完成
118
+ ```
119
+
120
+ ## 异步上下文管理器
121
+
122
+ ```python
123
+ import asyncio
124
+ from typing import Self
125
+
126
+ class AsyncDBConnection:
127
+ async def __aenter__(self) -> Self:
128
+ self.conn = await create_connection()
129
+ return self
130
+
131
+ async def __aexit__(
132
+ self,
133
+ exc_type: type[BaseException] | None,
134
+ exc_val: BaseException | None,
135
+ exc_tb: object,
136
+ ) -> None:
137
+ await self.conn.close()
138
+
139
+ async def query(self, sql: str) -> list[dict]:
140
+ return await self.conn.execute(sql)
141
+
142
+ # 使用
143
+ async with AsyncDBConnection() as db:
144
+ results = await db.query("SELECT * FROM users")
145
+ ```
146
+
147
+ ## 常见陷阱
148
+
149
+ | 陷阱 | 说明 | 解决方案 |
150
+ |------|------|---------|
151
+ | **阻塞调用阻塞事件循环** | 在协程中调用 `time.sleep()` 等同步阻塞 | 使用 `asyncio.to_thread()` 或 `loop.run_in_executor()` |
152
+ | **忘记 await** | 协程不会自动执行 | 始终 `await` 或 `create_task` |
153
+ | **没有超时** | 协程可能永远挂起 | 始终设置 `asyncio.timeout` |
154
+ | **TaskGroup 优于 gather** | `gather(return_exceptions=True)` 容易遗漏异常 | 优先使用 `TaskGroup` |
155
+ | **共享可变状态** | 协程间数据竞争 | 使用 `Queue` 或不可变数据结构 |
156
+
157
+ ---
158
+
159
+ ## 相关规则
160
+
161
+ - `seed-type-annotations` — 类型注解
162
+ - `seed-context-managers` — 上下文管理器
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: harness-python-architecture
3
+ description: Python 项目架构与模块化设计。覆盖分层职责、依赖管理、配置分离与项目结构。
4
+ ---
5
+
6
+ # Python 架构设计指引
7
+
8
+ ## 概述
9
+
10
+ 采用分层模块化架构,保持低耦合高内聚。明确接口边界,避免循环依赖。
11
+
12
+ > **刚性约束已由 rules 加载:**
13
+ > - `seed-import-order` — 导入顺序规范
14
+ > - `seed-pep8-naming` — PEP 8 命名规范
15
+ > - `seed-type-annotations` — 类型注解
16
+
17
+ ---
18
+
19
+ ## 项目结构
20
+
21
+ ```
22
+ project/
23
+ ├── src/
24
+ │ ├── core/ # 核心抽象与接口
25
+ │ │ ├── interfaces/ # 抽象基类 / Protocol
26
+ │ │ ├── models/ # 数据模型
27
+ │ │ └── errors/ # 自定义异常
28
+ │ ├── services/ # 业务服务层
29
+ │ │ ├── service_a/
30
+ │ │ └── service_b/
31
+ │ ├── repositories/ # 数据访问层
32
+ │ ├── api/ # HTTP API 层
33
+ │ │ ├── routes/
34
+ │ │ ├── middleware/
35
+ │ │ └── dependencies/
36
+ │ ├── config/ # 配置管理
37
+ │ ├── utils/ # 工具函数
38
+ │ └── main.py # 应用入口
39
+ ├── tests/
40
+ │ ├── unit/
41
+ │ ├── integration/
42
+ │ └── conftest.py
43
+ ├── scripts/ # 脚本工具
44
+ ├── pyproject.toml # 项目元数据与依赖
45
+ ├── requirements.txt
46
+ └── README.md
47
+ ```
48
+
49
+ ## 分层依赖规则
50
+
51
+ ```
52
+ API Layer(路由入口)
53
+ │ 依赖 Service 层
54
+
55
+ Service Layer(业务逻辑)
56
+ │ 依赖 Repository 层、Core 接口
57
+
58
+ Repository Layer(数据访问)
59
+ │ 依赖 Core 模型
60
+
61
+ Core Layer(核心抽象)
62
+ │ 零依赖或仅依赖标准库
63
+ ```
64
+
65
+ | 层级 | 职责 | 可依赖 |
66
+ |------|------|--------|
67
+ | **API** | 请求处理、参数校验、响应序列化 | Service |
68
+ | **Service** | 业务编排、事务管理、事件发布 | Repository、Core |
69
+ | **Repository** | 数据存取(DB/API/文件) | Core |
70
+ | **Core** | 纯数据模型、接口协议、异常定义 | 标准库 |
71
+
72
+ ## 依赖注入
73
+
74
+ ```python
75
+ from abc import ABC, abstractmethod
76
+ from dataclasses import dataclass
77
+
78
+ # Core 接口
79
+ class UserRepository(ABC):
80
+ @abstractmethod
81
+ async def find_by_id(self, user_id: str) -> User | None:
82
+ ...
83
+
84
+ # Service 通过构造器注入依赖
85
+ class UserService:
86
+ def __init__(self, repo: UserRepository) -> None:
87
+ self._repo = repo
88
+
89
+ async def get_user(self, user_id: str) -> UserDTO | None:
90
+ user = await self._repo.find_by_id(user_id)
91
+ if user is None:
92
+ return None
93
+ return UserDTO.from_domain(user)
94
+
95
+ # 组装(依赖注入入口)
96
+ def wire_dependencies() -> UserService:
97
+ repo = PostgresUserRepository(dsn=settings.DATABASE_URL)
98
+ return UserService(repo=repo)
99
+ ```
100
+
101
+ ## 配置管理
102
+
103
+ ```python
104
+ from pydantic_settings import BaseSettings
105
+
106
+ class Settings(BaseSettings):
107
+ # 应用配置
108
+ APP_NAME: str = "my-service"
109
+ DEBUG: bool = False
110
+
111
+ # 数据库
112
+ DATABASE_URL: str
113
+ DB_POOL_SIZE: int = 10
114
+
115
+ # 外部服务
116
+ REDIS_URL: str = "redis://localhost:6379"
117
+ API_TIMEOUT_SECONDS: float = 30.0
118
+
119
+ model_config = {"env_file": ".env", "env_file_encoding": "utf-8"}
120
+
121
+ # 全局单例(线程安全,不可变)
122
+ settings = Settings()
123
+ ```
124
+
125
+ ## 错误处理
126
+
127
+ ```python
128
+ class AppError(Exception):
129
+ """应用基础异常。"""
130
+ def __init__(self, message: str, code: str) -> None:
131
+ self.message = message
132
+ self.code = code
133
+ super().__init__(message)
134
+
135
+ class NotFoundError(AppError):
136
+ def __init__(self, entity: str, entity_id: str) -> None:
137
+ super().__init__(
138
+ message=f"{entity} not found: {entity_id}",
139
+ code="NOT_FOUND",
140
+ )
141
+
142
+ class ValidationError(AppError):
143
+ def __init__(self, field: str, reason: str) -> None:
144
+ super().__init__(
145
+ message=f"Validation failed for {field}: {reason}",
146
+ code="VALIDATION_ERROR",
147
+ )
148
+
149
+ # 统一错误处理
150
+ def handle_error(error: AppError) -> dict[str, str]:
151
+ return {"error": error.code, "message": error.message}
152
+ ```
153
+
154
+ ---
155
+
156
+ ## 相关规则
157
+
158
+ - `seed-import-order` — 导入顺序规范
159
+ - `seed-pep8-naming` — PEP 8 命名规范
160
+ - `seed-type-annotations` — 类型注解
@@ -0,0 +1,210 @@
1
+ ---
2
+ name: harness-python-package-structure
3
+ description: Python 包与模块组织管理。覆盖包结构、__init__.py 规范、依赖管理与发布配置。
4
+ ---
5
+
6
+ # 包与模块组织
7
+
8
+ ## 概述
9
+
10
+ 规范的包结构是 Python 项目的基石。遵循标准约定,确保可导入性、可测试性与可分发性。
11
+
12
+ > **相关规则:**
13
+ > - `seed-import-order` — 导入顺序规范
14
+ > - `seed-pep8-naming` — PEP 8 命名规范
15
+
16
+ ---
17
+
18
+ ## 包结构
19
+
20
+ ```
21
+ my_package/
22
+ ├── __init__.py # 包入口,导出公共 API
23
+ ├── _internal/ # 内部实现,不导出
24
+ │ ├── __init__.py
25
+ │ ├── _helpers.py
26
+ │ └── _constants.py
27
+ ├── models/ # 数据模型
28
+ │ ├── __init__.py
29
+ │ ├── user.py
30
+ │ └── order.py
31
+ ├── services/ # 业务服务
32
+ │ ├── __init__.py
33
+ │ ├── user_service.py
34
+ │ └── payment_service.py
35
+ ├── cli.py # 命令行入口(可选)
36
+ └── __version__.py # 版本信息
37
+ ```
38
+
39
+ ## __init__.py 规范
40
+
41
+ ```python
42
+ # my_package/__init__.py
43
+ """My Package - 简短描述包的目的。
44
+
45
+ 这个包提供了用户管理与支付处理功能。
46
+ """
47
+
48
+ from my_package.models.user import User, UserRole
49
+ from my_package.models.order import Order, OrderStatus
50
+ from my_package.services.user_service import UserService
51
+ from my_package.services.payment_service import PaymentService
52
+
53
+ __all__ = [
54
+ "User",
55
+ "UserRole",
56
+ "Order",
57
+ "OrderStatus",
58
+ "UserService",
59
+ "PaymentService",
60
+ ]
61
+ ```
62
+
63
+ ## pyproject.toml 配置
64
+
65
+ ```toml
66
+ [build-system]
67
+ requires = ["setuptools>=68.0", "wheel"]
68
+ build-backend = "setuptools.backends._legacy:_Backend"
69
+
70
+ [project]
71
+ name = "my-package"
72
+ version = "0.1.0"
73
+ description = "A short description"
74
+ readme = "README.md"
75
+ requires-python = ">=3.11"
76
+ license = { text = "MIT" }
77
+ authors = [
78
+ { name = "Developer", email = "dev@example.com" },
79
+ ]
80
+
81
+ dependencies = [
82
+ "httpx>=0.27",
83
+ "pydantic>=2.0",
84
+ "python-dotenv>=1.0",
85
+ ]
86
+
87
+ [project.optional-dependencies]
88
+ dev = [
89
+ "pytest>=8.0",
90
+ "pytest-asyncio>=0.23",
91
+ "pytest-cov>=5.0",
92
+ "ruff>=0.3",
93
+ "mypy>=1.8",
94
+ ]
95
+ test = [
96
+ "pytest>=8.0",
97
+ "pytest-asyncio>=0.23",
98
+ "pytest-cov>=5.0",
99
+ ]
100
+
101
+ [project.urls]
102
+ Homepage = "https://github.com/example/my-package"
103
+
104
+ [project.scripts]
105
+ my-cli = "my_package.cli:main"
106
+ ```
107
+
108
+ ## 模块组织原则
109
+
110
+ ### 1. 单一职责
111
+
112
+ ```python
113
+ # 正确:职责分离
114
+ # services/user_service.py
115
+ class UserService:
116
+ """仅处理用户相关的业务逻辑。"""
117
+
118
+ async def create_user(self, data: CreateUserDTO) -> User:
119
+ ...
120
+
121
+ async def deactivate_user(self, user_id: str) -> None:
122
+ ...
123
+
124
+ # services/notification_service.py
125
+ class NotificationService:
126
+ """仅处理通知发送。"""
127
+ ...
128
+ ```
129
+
130
+ ### 2. 显式 re-export
131
+
132
+ ```python
133
+ # services/__init__.py
134
+ from my_package.services.user_service import UserService
135
+ from my_package.services.payment_service import PaymentService
136
+
137
+ __all__ = ["UserService", "PaymentService"]
138
+ ```
139
+
140
+ ### 3. 内部实现隐藏
141
+
142
+ ```python
143
+ # _internal/_helpers.py
144
+ # 单下划线前缀表示内部实现,不视为公共 API
145
+ def _format_currency(amount: float, currency: str) -> str:
146
+ ...
147
+ ```
148
+
149
+ ## 依赖管理
150
+
151
+ ```txt
152
+ # requirements.txt — 锁定版本部署
153
+ httpx==0.27.0
154
+ pydantic==2.5.0
155
+ python-dotenv==1.0.1
156
+ uvicorn[standard]==0.27.0
157
+
158
+ # requirements-dev.txt — 开发依赖
159
+ -r requirements.txt
160
+ pytest==8.0.0
161
+ pytest-cov==5.0.0
162
+ ruff==0.3.0
163
+ mypy==1.8.0
164
+ pre-commit==3.6.0
165
+ ```
166
+
167
+ 或使用 Poetry:
168
+
169
+ ```toml
170
+ [tool.poetry]
171
+ name = "my-package"
172
+ version = "0.1.0"
173
+
174
+ [tool.poetry.dependencies]
175
+ python = "^3.11"
176
+ httpx = "^0.27"
177
+ pydantic = "^2.5"
178
+
179
+ [tool.poetry.group.dev.dependencies]
180
+ pytest = "^8.0"
181
+ ruff = "^0.3"
182
+ mypy = "^1.8"
183
+ ```
184
+
185
+ ## 命令行入口
186
+
187
+ ```python
188
+ # cli.py
189
+ import argparse
190
+
191
+ def main(argv: list[str] | None = None) -> None:
192
+ parser = argparse.ArgumentParser(description="My CLI Tool")
193
+ parser.add_argument("--verbose", "-v", action="store_true")
194
+ args = parser.parse_args(argv)
195
+
196
+ if args.verbose:
197
+ print("Verbose mode enabled")
198
+ print("Running my CLI...")
199
+
200
+ if __name__ == "__main__":
201
+ main()
202
+ ```
203
+
204
+ ---
205
+
206
+ ## 相关规则
207
+
208
+ - `seed-import-order` — 导入顺序规范
209
+ - `seed-pep8-naming` — PEP 8 命名规范
210
+ - `seed-type-annotations` — 类型注解