@huajiwuyan/hello 3.0.0

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 (117) hide show
  1. package/README.md +68 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +448 -0
  4. package/package.json +38 -0
  5. package/templates/claude/commands/hello.md +760 -0
  6. package/templates/claude/skills/SKILL.md +90 -0
  7. package/templates/claude/skills/SKILL.toml +7 -0
  8. package/templates/claude/skills/assets/icon-large.svg +12 -0
  9. package/templates/claude/skills/assets/icon-small-400px.svg +12 -0
  10. package/templates/claude/skills/assets/templates/CHANGELOG.md +24 -0
  11. package/templates/claude/skills/assets/templates/CHANGELOG_{YYYY}.md +25 -0
  12. package/templates/claude/skills/assets/templates/INDEX.md +36 -0
  13. package/templates/claude/skills/assets/templates/archive/_index.md +22 -0
  14. package/templates/claude/skills/assets/templates/context.md +82 -0
  15. package/templates/claude/skills/assets/templates/modules/_index.md +22 -0
  16. package/templates/claude/skills/assets/templates/modules/module.md +35 -0
  17. package/templates/claude/skills/assets/templates/plan/proposal.md +104 -0
  18. package/templates/claude/skills/assets/templates/plan/tasks.md +49 -0
  19. package/templates/claude/skills/references/functions/auto.md +217 -0
  20. package/templates/claude/skills/references/functions/clean.md +167 -0
  21. package/templates/claude/skills/references/functions/commit.md +374 -0
  22. package/templates/claude/skills/references/functions/exec.md +178 -0
  23. package/templates/claude/skills/references/functions/help.md +105 -0
  24. package/templates/claude/skills/references/functions/init.md +228 -0
  25. package/templates/claude/skills/references/functions/plan.md +219 -0
  26. package/templates/claude/skills/references/functions/review.md +146 -0
  27. package/templates/claude/skills/references/functions/rollback.md +208 -0
  28. package/templates/claude/skills/references/functions/test.md +153 -0
  29. package/templates/claude/skills/references/functions/upgrade.md +371 -0
  30. package/templates/claude/skills/references/functions/validate.md +147 -0
  31. package/templates/claude/skills/references/rules/package.md +212 -0
  32. package/templates/claude/skills/references/rules/scaling.md +150 -0
  33. package/templates/claude/skills/references/rules/state.md +318 -0
  34. package/templates/claude/skills/references/rules/tools.md +371 -0
  35. package/templates/claude/skills/references/services/knowledge.md +408 -0
  36. package/templates/claude/skills/references/services/templates.md +344 -0
  37. package/templates/claude/skills/references/stages/analyze.md +201 -0
  38. package/templates/claude/skills/references/stages/design.md +379 -0
  39. package/templates/claude/skills/references/stages/develop.md +497 -0
  40. package/templates/claude/skills/references/stages/evaluate.md +286 -0
  41. package/templates/claude/skills/references/stages/tweak.md +244 -0
  42. package/templates/claude/skills/scripts/create_package.py +260 -0
  43. package/templates/claude/skills/scripts/list_packages.py +145 -0
  44. package/templates/claude/skills/scripts/migrate_package.py +399 -0
  45. package/templates/claude/skills/scripts/project_stats.py +438 -0
  46. package/templates/claude/skills/scripts/upgradewiki.py +321 -0
  47. package/templates/claude/skills/scripts/utils.py +596 -0
  48. package/templates/claude/skills/scripts/validate_package.py +309 -0
  49. package/templates/codex/prompts/hello.md +757 -0
  50. package/templates/codex/skills/SKILL.md +74 -0
  51. package/templates/codex/skills/SKILL.toml +7 -0
  52. package/templates/codex/skills/assets/icon-large.svg +12 -0
  53. package/templates/codex/skills/assets/icon-small-400px.svg +12 -0
  54. package/templates/codex/skills/assets/templates/CHANGELOG.md +24 -0
  55. package/templates/codex/skills/assets/templates/CHANGELOG_{YYYY}.md +25 -0
  56. package/templates/codex/skills/assets/templates/INDEX.md +36 -0
  57. package/templates/codex/skills/assets/templates/archive/_index.md +22 -0
  58. package/templates/codex/skills/assets/templates/context.md +82 -0
  59. package/templates/codex/skills/assets/templates/modules/_index.md +22 -0
  60. package/templates/codex/skills/assets/templates/modules/module.md +35 -0
  61. package/templates/codex/skills/assets/templates/plan/proposal.md +104 -0
  62. package/templates/codex/skills/assets/templates/plan/tasks.md +29 -0
  63. package/templates/codex/skills/references/functions/auto.md +181 -0
  64. package/templates/codex/skills/references/functions/brain.md +275 -0
  65. package/templates/codex/skills/references/functions/clean.md +154 -0
  66. package/templates/codex/skills/references/functions/commit.md +265 -0
  67. package/templates/codex/skills/references/functions/debug/condition-based-waiting.md +151 -0
  68. package/templates/codex/skills/references/functions/debug/defense-in-depth.md +147 -0
  69. package/templates/codex/skills/references/functions/debug/root-cause-tracing.md +168 -0
  70. package/templates/codex/skills/references/functions/debug.md +389 -0
  71. package/templates/codex/skills/references/functions/exec.md +153 -0
  72. package/templates/codex/skills/references/functions/help.md +101 -0
  73. package/templates/codex/skills/references/functions/init.md +221 -0
  74. package/templates/codex/skills/references/functions/plan.md +178 -0
  75. package/templates/codex/skills/references/functions/review.md +135 -0
  76. package/templates/codex/skills/references/functions/rlm.md +864 -0
  77. package/templates/codex/skills/references/functions/rollback.md +190 -0
  78. package/templates/codex/skills/references/functions/test.md +140 -0
  79. package/templates/codex/skills/references/functions/upgrade.md +363 -0
  80. package/templates/codex/skills/references/functions/validate.md +135 -0
  81. package/templates/codex/skills/references/rules/cache.md +136 -0
  82. package/templates/codex/skills/references/rules/scaling.md +124 -0
  83. package/templates/codex/skills/references/rules/state.md +201 -0
  84. package/templates/codex/skills/references/rules/tools.md +301 -0
  85. package/templates/codex/skills/references/services/attention.md +53 -0
  86. package/templates/codex/skills/references/services/knowledge.md +559 -0
  87. package/templates/codex/skills/references/services/package.md +383 -0
  88. package/templates/codex/skills/references/services/templates.md +390 -0
  89. package/templates/codex/skills/references/stages/analyze.md +191 -0
  90. package/templates/codex/skills/references/stages/design.md +355 -0
  91. package/templates/codex/skills/references/stages/develop.md +520 -0
  92. package/templates/codex/skills/references/stages/tweak.md +239 -0
  93. package/templates/codex/skills/rlm/__init__.py +39 -0
  94. package/templates/codex/skills/rlm/agent_orchestrator.py +422 -0
  95. package/templates/codex/skills/rlm/context_manager.py +366 -0
  96. package/templates/codex/skills/rlm/engine.py +915 -0
  97. package/templates/codex/skills/rlm/folding.py +391 -0
  98. package/templates/codex/skills/rlm/repl.py +452 -0
  99. package/templates/codex/skills/rlm/roles/analyzer.md +66 -0
  100. package/templates/codex/skills/rlm/roles/designer.md +94 -0
  101. package/templates/codex/skills/rlm/roles/explorer.md +43 -0
  102. package/templates/codex/skills/rlm/roles/implementer.md +62 -0
  103. package/templates/codex/skills/rlm/roles/kb_keeper.md +138 -0
  104. package/templates/codex/skills/rlm/roles/pkg_keeper.md +163 -0
  105. package/templates/codex/skills/rlm/roles/reviewer.md +74 -0
  106. package/templates/codex/skills/rlm/roles/synthesizer.md +90 -0
  107. package/templates/codex/skills/rlm/roles/tester.md +83 -0
  108. package/templates/codex/skills/rlm/schemas/agent_result.json +174 -0
  109. package/templates/codex/skills/rlm/session.py +376 -0
  110. package/templates/codex/skills/rlm/shared_tasks.py +370 -0
  111. package/templates/codex/skills/scripts/create_package.py +260 -0
  112. package/templates/codex/skills/scripts/list_packages.py +145 -0
  113. package/templates/codex/skills/scripts/migrate_package.py +399 -0
  114. package/templates/codex/skills/scripts/project_stats.py +438 -0
  115. package/templates/codex/skills/scripts/upgradewiki.py +321 -0
  116. package/templates/codex/skills/scripts/utils.py +596 -0
  117. package/templates/codex/skills/scripts/validate_package.py +309 -0
@@ -0,0 +1,370 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ HelloAGENTS-RLM Shared Tasks Manager
5
+ 多终端协作任务管理器
6
+
7
+ 核心设计:
8
+ - 默认隔离模式: 每个终端独立任务列表
9
+ - 协作模式: 通过环境变量指定共享任务列表 ID
10
+ - 支持任务依赖: blocks/blocked_by 自动管理
11
+ - 文件锁保护并发写入
12
+ """
13
+
14
+ import fcntl
15
+ import json
16
+ import os
17
+ import platform
18
+ import sys
19
+ from datetime import datetime
20
+ from pathlib import Path
21
+ from typing import Any, Dict, List, Optional
22
+
23
+
24
+ class SharedTasksManager:
25
+ """
26
+ 多终端协作任务管理器
27
+
28
+ 使用方式:
29
+ 隔离模式(默认): 直接运行 AI CLI
30
+ 协作模式: hellotasks=<任务列表ID> <AI CLI 命令>
31
+
32
+ 支持的 AI CLI:
33
+ - Codex CLI: hellotasks=auth-migration codex
34
+ - Claude Code: hellotasks=auth-migration claude
35
+
36
+ 任务存储位置:
37
+ 协作模式: {项目目录}/helloagents/tasks/{list_id}.json
38
+ 隔离模式: 由 session.py 管理
39
+ """
40
+
41
+ def __init__(self, project_root: Optional[Path] = None):
42
+ """
43
+ 初始化任务管理器
44
+
45
+ Args:
46
+ project_root: 项目根目录,默认为当前工作目录
47
+ """
48
+ self.project_root = project_root or Path.cwd()
49
+ self.tasks_dir = self.project_root / "helloagents" / "tasks"
50
+
51
+ # 从环境变量获取任务列表 ID
52
+ self.list_id = os.environ.get("hellotasks")
53
+ self.is_collaborative = bool(self.list_id)
54
+
55
+ if self.is_collaborative:
56
+ self.tasks_dir.mkdir(parents=True, exist_ok=True)
57
+ self.tasks_file = self.tasks_dir / f"{self.list_id}.json"
58
+ self._init_task_list()
59
+
60
+ def _init_task_list(self):
61
+ """初始化任务列表文件"""
62
+ if not self.tasks_file.exists():
63
+ initial_data = {
64
+ "list_id": self.list_id,
65
+ "created_at": datetime.now().isoformat(),
66
+ "last_updated": datetime.now().isoformat(),
67
+ "tasks": [],
68
+ }
69
+ self._write_tasks(initial_data)
70
+
71
+ # ==================== 文件锁操作 ====================
72
+
73
+ def _read_tasks(self) -> Dict[str, Any]:
74
+ """读取任务列表(带共享锁)"""
75
+ if not self.is_collaborative:
76
+ return {"tasks": []}
77
+
78
+ if not self.tasks_file.exists():
79
+ return {"list_id": self.list_id, "tasks": []}
80
+
81
+ try:
82
+ with open(self.tasks_file, 'r', encoding='utf-8') as f:
83
+ # Windows 不支持 fcntl,使用替代方案
84
+ if platform.system() != 'Windows':
85
+ fcntl.flock(f.fileno(), fcntl.LOCK_SH)
86
+ try:
87
+ return json.load(f)
88
+ finally:
89
+ if platform.system() != 'Windows':
90
+ fcntl.flock(f.fileno(), fcntl.LOCK_UN)
91
+ except Exception:
92
+ return {"list_id": self.list_id, "tasks": []}
93
+
94
+ def _write_tasks(self, data: Dict[str, Any]) -> bool:
95
+ """写入任务列表(带排他锁)"""
96
+ if not self.is_collaborative:
97
+ return False
98
+
99
+ data["last_updated"] = datetime.now().isoformat()
100
+
101
+ try:
102
+ with open(self.tasks_file, 'w', encoding='utf-8') as f:
103
+ # Windows 使用简单的文件写入
104
+ if platform.system() != 'Windows':
105
+ fcntl.flock(f.fileno(), fcntl.LOCK_EX)
106
+ try:
107
+ json.dump(data, f, ensure_ascii=False, indent=2)
108
+ return True
109
+ finally:
110
+ if platform.system() != 'Windows':
111
+ fcntl.flock(f.fileno(), fcntl.LOCK_UN)
112
+ except Exception:
113
+ return False
114
+
115
+ # ==================== 任务 CRUD ====================
116
+
117
+ def add_task(
118
+ self,
119
+ subject: str,
120
+ description: str = "",
121
+ blocks: Optional[List[str]] = None,
122
+ blocked_by: Optional[List[str]] = None,
123
+ ) -> Optional[str]:
124
+ """
125
+ 添加任务
126
+
127
+ Args:
128
+ subject: 任务标题
129
+ description: 任务描述
130
+ blocks: 此任务完成后解锁的任务 ID 列表
131
+ blocked_by: 阻塞此任务的任务 ID 列表
132
+
133
+ Returns:
134
+ 任务 ID,失败返回 None
135
+ """
136
+ if not self.is_collaborative:
137
+ return None
138
+
139
+ data = self._read_tasks()
140
+ task_id = f"t{len(data['tasks']) + 1}_{datetime.now().strftime('%H%M%S')}"
141
+
142
+ task = {
143
+ "id": task_id,
144
+ "subject": subject,
145
+ "description": description,
146
+ "status": "pending",
147
+ "owner": None,
148
+ "blocks": blocks or [],
149
+ "blocked_by": blocked_by or [],
150
+ "created_at": datetime.now().isoformat(),
151
+ "updated_at": datetime.now().isoformat(),
152
+ }
153
+
154
+ data["tasks"].append(task)
155
+ if self._write_tasks(data):
156
+ return task_id
157
+ return None
158
+
159
+ def update_task(
160
+ self,
161
+ task_id: str,
162
+ status: Optional[str] = None,
163
+ owner: Optional[str] = None,
164
+ ) -> bool:
165
+ """
166
+ 更新任务状态
167
+
168
+ Args:
169
+ task_id: 任务 ID
170
+ status: 新状态 (pending/in_progress/completed)
171
+ owner: 任务负责人(终端标识)
172
+
173
+ Returns:
174
+ 是否成功
175
+ """
176
+ if not self.is_collaborative:
177
+ return False
178
+
179
+ data = self._read_tasks()
180
+
181
+ for task in data["tasks"]:
182
+ if task["id"] == task_id:
183
+ if status:
184
+ task["status"] = status
185
+ if owner is not None:
186
+ task["owner"] = owner
187
+ task["updated_at"] = datetime.now().isoformat()
188
+
189
+ # 如果任务完成,自动更新依赖关系
190
+ if status == "completed":
191
+ self._resolve_dependencies(data, task_id)
192
+
193
+ return self._write_tasks(data)
194
+
195
+ return False
196
+
197
+ def _resolve_dependencies(self, data: Dict[str, Any], completed_task_id: str):
198
+ """解除依赖:将 completed_task_id 从其他任务的 blocked_by 中移除"""
199
+ for task in data["tasks"]:
200
+ if completed_task_id in task.get("blocked_by", []):
201
+ task["blocked_by"].remove(completed_task_id)
202
+ task["updated_at"] = datetime.now().isoformat()
203
+
204
+ def claim_task(self, task_id: str, owner: str) -> bool:
205
+ """
206
+ 认领任务
207
+
208
+ Args:
209
+ task_id: 任务 ID
210
+ owner: 认领者标识
211
+
212
+ Returns:
213
+ 是否成功(已被他人认领则失败)
214
+ """
215
+ if not self.is_collaborative:
216
+ return False
217
+
218
+ data = self._read_tasks()
219
+
220
+ for task in data["tasks"]:
221
+ if task["id"] == task_id:
222
+ # 检查是否已被认领
223
+ if task["owner"] and task["owner"] != owner:
224
+ return False # 已被他人认领
225
+
226
+ # 检查是否被阻塞
227
+ if task.get("blocked_by"):
228
+ return False # 还有未完成的依赖
229
+
230
+ task["owner"] = owner
231
+ task["status"] = "in_progress"
232
+ task["updated_at"] = datetime.now().isoformat()
233
+ return self._write_tasks(data)
234
+
235
+ return False
236
+
237
+ def get_available_tasks(self) -> List[Dict[str, Any]]:
238
+ """获取可认领的任务(无阻塞、未被认领)"""
239
+ if not self.is_collaborative:
240
+ return []
241
+
242
+ data = self._read_tasks()
243
+ available = []
244
+
245
+ for task in data["tasks"]:
246
+ if (task["status"] == "pending" and
247
+ not task.get("owner") and
248
+ not task.get("blocked_by")):
249
+ available.append(task)
250
+
251
+ return available
252
+
253
+ def get_task_list(self) -> List[Dict[str, Any]]:
254
+ """获取完整任务列表"""
255
+ if not self.is_collaborative:
256
+ return []
257
+
258
+ data = self._read_tasks()
259
+ return data.get("tasks", [])
260
+
261
+ def get_task(self, task_id: str) -> Optional[Dict[str, Any]]:
262
+ """获取单个任务详情"""
263
+ if not self.is_collaborative:
264
+ return None
265
+
266
+ data = self._read_tasks()
267
+ for task in data["tasks"]:
268
+ if task["id"] == task_id:
269
+ return task
270
+ return None
271
+
272
+ # ==================== 状态查询 ====================
273
+
274
+ def get_status(self) -> Dict[str, Any]:
275
+ """获取任务列表状态"""
276
+ if not self.is_collaborative:
277
+ return {
278
+ "mode": "isolated",
279
+ "message": "未指定共享任务列表,使用隔离模式",
280
+ }
281
+
282
+ data = self._read_tasks()
283
+ tasks = data.get("tasks", [])
284
+
285
+ pending = sum(1 for t in tasks if t["status"] == "pending")
286
+ in_progress = sum(1 for t in tasks if t["status"] == "in_progress")
287
+ completed = sum(1 for t in tasks if t["status"] == "completed")
288
+ blocked = sum(1 for t in tasks if t.get("blocked_by"))
289
+
290
+ return {
291
+ "mode": "collaborative",
292
+ "list_id": self.list_id,
293
+ "tasks_file": str(self.tasks_file),
294
+ "total": len(tasks),
295
+ "pending": pending,
296
+ "in_progress": in_progress,
297
+ "completed": completed,
298
+ "blocked": blocked,
299
+ "last_updated": data.get("last_updated"),
300
+ }
301
+
302
+ def refresh(self) -> List[Dict[str, Any]]:
303
+ """
304
+ 强制刷新任务列表(从文件重新读取)
305
+
306
+ 用于检查其他终端的更新
307
+ """
308
+ return self.get_task_list()
309
+
310
+
311
+ # ==================== 便捷函数 ====================
312
+
313
+ def get_task_manager(project_root: Optional[str] = None) -> SharedTasksManager:
314
+ """获取任务管理器实例"""
315
+ return SharedTasksManager(
316
+ project_root=Path(project_root) if project_root else None
317
+ )
318
+
319
+
320
+ def is_collaborative_mode() -> bool:
321
+ """检查是否为协作模式"""
322
+ return bool(os.environ.get("hellotasks"))
323
+
324
+
325
+ # ==================== CLI 入口 ====================
326
+
327
+ if __name__ == "__main__":
328
+ import argparse
329
+
330
+ parser = argparse.ArgumentParser(description="HelloAGENTS Shared Tasks Manager")
331
+ parser.add_argument("--status", action="store_true", help="显示任务列表状态")
332
+ parser.add_argument("--list", action="store_true", help="列出所有任务")
333
+ parser.add_argument("--available", action="store_true", help="列出可认领的任务")
334
+ parser.add_argument("--add", type=str, help="添加任务 (subject)")
335
+ parser.add_argument("--complete", type=str, help="标记任务完成 (task_id)")
336
+ parser.add_argument("--claim", type=str, help="认领任务 (task_id)")
337
+ parser.add_argument("--owner", type=str, default="cli", help="认领者标识")
338
+
339
+ args = parser.parse_args()
340
+ manager = SharedTasksManager()
341
+
342
+ if args.status:
343
+ print(json.dumps(manager.get_status(), ensure_ascii=False, indent=2))
344
+
345
+ elif args.list:
346
+ tasks = manager.get_task_list()
347
+ print(json.dumps(tasks, ensure_ascii=False, indent=2))
348
+
349
+ elif args.available:
350
+ tasks = manager.get_available_tasks()
351
+ print(json.dumps(tasks, ensure_ascii=False, indent=2))
352
+
353
+ elif args.add:
354
+ task_id = manager.add_task(subject=args.add)
355
+ if task_id:
356
+ print(json.dumps({"success": True, "task_id": task_id}, ensure_ascii=False))
357
+ else:
358
+ print(json.dumps({"success": False, "error": "添加失败或非协作模式"}, ensure_ascii=False))
359
+
360
+ elif args.complete:
361
+ success = manager.update_task(args.complete, status="completed")
362
+ print(json.dumps({"success": success}, ensure_ascii=False))
363
+
364
+ elif args.claim:
365
+ success = manager.claim_task(args.claim, owner=args.owner)
366
+ print(json.dumps({"success": success}, ensure_ascii=False))
367
+
368
+ else:
369
+ # 默认显示状态
370
+ print(json.dumps(manager.get_status(), ensure_ascii=False, indent=2))
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ 创建 HelloAGENTS 方案包
5
+
6
+ Usage:
7
+ python create_package.py <feature-name> [--path <base-path>] [--type <implementation|overview>]
8
+
9
+ Examples:
10
+ python create_package.py user-login
11
+ python create_package.py api-refactor --type overview
12
+ python create_package.py auth-system --path /path/to/project
13
+ """
14
+
15
+ import argparse
16
+ import re
17
+ import sys
18
+ from pathlib import Path
19
+ from datetime import datetime
20
+
21
+ # 确保能找到同目录下的 utils 模块
22
+ sys.path.insert(0, str(Path(__file__).parent))
23
+ from utils import (
24
+ setup_encoding,
25
+ get_plan_path,
26
+ generate_package_name,
27
+ print_error,
28
+ print_success,
29
+ validate_base_path,
30
+ get_template_loader,
31
+ ExecutionReport
32
+ )
33
+
34
+
35
+ # 模板路径常量
36
+ TEMPLATE_PROPOSAL = "plan/proposal.md"
37
+ TEMPLATE_TASKS = "plan/tasks.md"
38
+
39
+
40
+ def create_package(feature: str, base_path: str = None, pkg_type: str = "implementation") -> ExecutionReport:
41
+ """
42
+ 创建方案包(并发安全,支持 AI 降级接手)
43
+
44
+ Args:
45
+ feature: 功能名称
46
+ base_path: 项目根目录
47
+ pkg_type: 方案包类型 (implementation/overview)
48
+
49
+ Returns:
50
+ ExecutionReport: 执行报告,包含完成状态和上下文
51
+ """
52
+ report = ExecutionReport("create_package")
53
+ report.set_context(feature=feature, pkg_type=pkg_type, base_path=base_path or "cwd")
54
+
55
+ plan_path = get_plan_path(base_path)
56
+ original_name = generate_package_name(feature)
57
+
58
+ # 步骤1: 确保父目录存在
59
+ try:
60
+ plan_path.mkdir(parents=True, exist_ok=True)
61
+ report.mark_completed(
62
+ "创建 plan/ 目录",
63
+ str(plan_path),
64
+ "检查目录是否存在: ls 或 Read 工具"
65
+ )
66
+ except PermissionError as e:
67
+ report.mark_failed(
68
+ "创建 plan/ 目录",
69
+ ["创建 plan/ 目录", "创建方案包目录", "创建 proposal.md", "创建 tasks.md"],
70
+ f"权限不足: {e}"
71
+ )
72
+ return report
73
+
74
+ # 步骤2: 并发安全的目录创建(原子操作 + 重试)
75
+ max_retries = 100
76
+ package_path = None
77
+ package_name = None
78
+
79
+ for version in range(1, max_retries + 1):
80
+ package_name = original_name if version == 1 else f"{original_name}_v{version}"
81
+ package_path = plan_path / package_name
82
+
83
+ try:
84
+ package_path.mkdir(exist_ok=False)
85
+ report.mark_completed(
86
+ "创建方案包目录",
87
+ str(package_path),
88
+ "检查目录是否存在且为空目录"
89
+ )
90
+ report.set_context(package_path=str(package_path), package_name=package_name)
91
+ break
92
+ except FileExistsError:
93
+ continue
94
+ except PermissionError as e:
95
+ report.mark_failed(
96
+ "创建方案包目录",
97
+ ["创建方案包目录", "创建 proposal.md", "创建 tasks.md"],
98
+ f"权限不足: {package_path}"
99
+ )
100
+ return report
101
+ else:
102
+ report.mark_failed(
103
+ "创建方案包目录",
104
+ ["创建方案包目录", "创建 proposal.md", "创建 tasks.md"],
105
+ f"超过最大重试次数 ({max_retries}),存在大量同名方案包"
106
+ )
107
+ return report
108
+
109
+ # 步骤3: 加载并填充模板
110
+ current_date = datetime.now().strftime("%Y-%m-%d")
111
+ loader = get_template_loader()
112
+
113
+ # 定义占位符替换映射
114
+ replacements = {
115
+ "{feature}": feature,
116
+ "{YYYY-MM-DD}": current_date,
117
+ "{pkg_type}": pkg_type,
118
+ "{package_name}": package_name,
119
+ "{YYYYMMDDHHMM}_{feature}": package_name
120
+ }
121
+
122
+ # 步骤4: proposal.md - 检查模板存在性
123
+ proposal_content = loader.fill(TEMPLATE_PROPOSAL, replacements)
124
+ if proposal_content is None:
125
+ report.mark_failed(
126
+ f"加载模板 {TEMPLATE_PROPOSAL}",
127
+ ["创建 proposal.md(需包含:元信息、需求、方案章节)", "创建 tasks.md"],
128
+ f"模板文件不存在: {TEMPLATE_PROPOSAL}"
129
+ )
130
+ return report
131
+
132
+ # 步骤5: tasks.md - 检查模板存在性
133
+ tasks_content = loader.fill(TEMPLATE_TASKS, replacements)
134
+ if tasks_content is None:
135
+ report.mark_failed(
136
+ f"加载模板 {TEMPLATE_TASKS}",
137
+ ["创建 tasks.md(需包含:执行状态、任务列表、执行备注章节)"],
138
+ f"模板文件不存在: {TEMPLATE_TASKS}"
139
+ )
140
+ # 仍需标记 proposal 模板加载成功
141
+ report.mark_completed(
142
+ "加载 proposal.md 模板",
143
+ "模板内容已加载",
144
+ "N/A - 模板加载成功但未写入文件"
145
+ )
146
+ return report
147
+
148
+ # overview 类型:替换任务列表为"无执行任务"
149
+ if pkg_type == "overview":
150
+ # 替换执行状态中的完成率
151
+ tasks_content = re.sub(r'完成率:\s*\d+%', '完成率: N/A', tasks_content)
152
+ tasks_content = re.sub(r'总任务:\s*\w+', '总任务: 0', tasks_content)
153
+ # 替换任务列表部分
154
+ tasks_content = re.sub(
155
+ r'## 任务列表\s*\n.*?(?=\n---)',
156
+ '## 任务列表\n\n> 无执行任务(概述文档)\n',
157
+ tasks_content,
158
+ flags=re.DOTALL
159
+ )
160
+
161
+ # 步骤6: 写入 proposal.md
162
+ proposal_path = package_path / "proposal.md"
163
+ try:
164
+ proposal_path.write_text(proposal_content, encoding='utf-8')
165
+ report.mark_completed(
166
+ "创建 proposal.md",
167
+ str(proposal_path),
168
+ "检查文件存在且包含必需章节(元信息、需求、方案)"
169
+ )
170
+ except Exception as e:
171
+ report.mark_failed(
172
+ "写入 proposal.md",
173
+ ["创建 proposal.md", "创建 tasks.md"],
174
+ str(e)
175
+ )
176
+ return report
177
+
178
+ # 步骤7: 写入 tasks.md
179
+ tasks_path = package_path / "tasks.md"
180
+ try:
181
+ tasks_path.write_text(tasks_content, encoding='utf-8')
182
+ report.mark_completed(
183
+ "创建 tasks.md",
184
+ str(tasks_path),
185
+ "检查文件存在且包含必需章节(执行状态、任务列表)"
186
+ )
187
+ except Exception as e:
188
+ report.mark_failed(
189
+ "写入 tasks.md",
190
+ ["创建 tasks.md"],
191
+ str(e)
192
+ )
193
+ return report
194
+
195
+ # 全部完成
196
+ report.mark_success(str(package_path))
197
+ return report
198
+
199
+
200
+ def main():
201
+ setup_encoding()
202
+ parser = argparse.ArgumentParser(
203
+ description="创建 HelloAGENTS 方案包"
204
+ )
205
+ parser.add_argument(
206
+ "feature",
207
+ help="功能名称 (如: user-login, api-refactor)"
208
+ )
209
+ parser.add_argument(
210
+ "--path",
211
+ default=None,
212
+ help="项目根目录 (默认: 当前目录)"
213
+ )
214
+ parser.add_argument(
215
+ "--type",
216
+ choices=["implementation", "overview"],
217
+ default="implementation",
218
+ help="方案包类型: implementation(实施计划) 或 overview(概述文档)"
219
+ )
220
+
221
+ args = parser.parse_args()
222
+
223
+ # 验证基础路径
224
+ try:
225
+ validate_base_path(args.path)
226
+ except ValueError as e:
227
+ report = ExecutionReport("create_package")
228
+ report.mark_failed("验证基础路径", ["验证路径", "创建方案包"], str(e))
229
+ report.print_report()
230
+ sys.exit(1)
231
+
232
+ # 验证 feature 名称
233
+ feature = args.feature.strip()
234
+ if not feature:
235
+ report = ExecutionReport("create_package")
236
+ report.mark_failed("验证功能名称", ["创建方案包"], "功能名称不能为空")
237
+ report.print_report()
238
+ sys.exit(1)
239
+
240
+ # 预验证 feature 名称有效性(检查规范化后是否为空)
241
+ try:
242
+ generate_package_name(feature)
243
+ except ValueError as e:
244
+ report = ExecutionReport("create_package")
245
+ report.mark_failed("验证功能名称", ["创建方案包"], str(e))
246
+ report.print_report()
247
+ sys.exit(1)
248
+
249
+ # 执行创建
250
+ report = create_package(feature, args.path, args.type)
251
+
252
+ # 输出执行报告(JSON格式,供 AI 解析)
253
+ report.print_report()
254
+
255
+ # 返回状态码
256
+ sys.exit(0 if report.success else 1)
257
+
258
+
259
+ if __name__ == "__main__":
260
+ main()