adspecs 0.1.19 → 0.1.21

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 (74) hide show
  1. package/.adspecs/feature.json +16 -16
  2. package/.adspecs/feature.yml +28 -28
  3. package/.adspecs/paths.json +17 -17
  4. package/.adspecs/templates/04-/345/211/215/347/253/257/345/212/237/350/203/275/350/256/276/350/256/241/346/250/241/346/235/277.md +1 -1
  5. package/.adspecs/templates/05-/345/220/216/347/253/257/344/273/273/345/212/241/346/270/205/345/215/225/346/250/241/346/235/277.md +613 -724
  6. package/.adspecs/templates/05b-/345/211/215/347/253/257/344/273/273/345/212/241/346/270/205/345/215/225/346/250/241/346/235/277.md +51 -51
  7. package/.claude-plugin/marketplace.json +23 -23
  8. package/.claude-plugin/plugin.json +18 -18
  9. package/.qoder-plugin/plugin.json +31 -31
  10. package/CLAUDE.md +1 -5
  11. package/INSTALL.md +3 -3
  12. package/README.md +395 -395
  13. package/bin/adspecs.js +129 -129
  14. package/hooks/commit-queue.js +245 -245
  15. package/hooks/hooks.json +63 -63
  16. package/hooks/session-start.js +44 -44
  17. package/hooks/wiki-queue.js +127 -127
  18. package/package.json +61 -61
  19. package/references/ant6-front-standard/index.md +99 -99
  20. package/references/antd-front-demo/public/mockServiceWorker.js +361 -361
  21. package/references/ecp-end-standard/index.md +63 -63
  22. package/references/python-end-standard/01-Python/345/220/216/347/253/257/347/274/226/347/240/201/350/247/204/350/214/203.md +372 -372
  23. package/references/python-end-standard/02-/346/225/260/346/215/256/345/272/223/350/256/276/350/256/241/344/270/216/344/275/277/347/224/250/350/247/204/350/214/203.md +226 -226
  24. package/references/python-end-standard/03-Celery/345/274/202/346/255/245/344/273/273/345/212/241/350/247/204/350/214/203.md +237 -237
  25. package/references/python-end-standard/04-Redis/344/275/277/347/224/250/350/247/204/350/214/203.md +231 -231
  26. package/scripts/postinstall.js +107 -107
  27. package/scripts/sync-version.js +105 -105
  28. package/skills/.claude/.wiki-update-queue +26 -26
  29. package/skills/adspecs-constitution/SKILL.md +157 -0
  30. package/skills/adspecs-export-word/SKILL.md +498 -498
  31. package/skills/adspecs-export-word/references/md-to-docx.js +862 -862
  32. package/skills/adspecs-export-word/references/package-lock.json +220 -220
  33. package/skills/adspecs-export-word/references/package.json +10 -10
  34. package/skills/adspecs-front-prototype/SKILL.md +405 -405
  35. package/skills/adspecs-front-spec/SKILL.md +4 -4
  36. package/skills/adspecs-front-tasks/SKILL.md +213 -173
  37. package/skills/adspecs-plan/SKILL.md +59 -69
  38. package/skills/adspecs-prd/SKILL.md +13 -5
  39. package/skills/adspecs-prd-to-demo/SKILL.md +532 -0
  40. package/skills/adspecs-tasks/SKILL.md +175 -204
  41. package/skills/adspecs-update-status/SKILL.md +382 -382
  42. package/skills/adspecs-utest/SKILL.md +107 -116
  43. package/skills/grill-me/SKILL.md +7 -0
  44. package/skills/grill-me/agents/openai.yaml +5 -0
  45. package/skills/playwright-cli/SKILL.md +420 -0
  46. package/skills/playwright-cli/references/element-attributes.md +23 -0
  47. package/skills/playwright-cli/references/playwright-tests.md +39 -0
  48. package/skills/playwright-cli/references/request-mocking.md +87 -0
  49. package/skills/playwright-cli/references/running-code.md +241 -0
  50. package/skills/playwright-cli/references/session-management.md +225 -0
  51. package/skills/playwright-cli/references/storage-state.md +275 -0
  52. package/skills/playwright-cli/references/test-generation.md +433 -0
  53. package/skills/playwright-cli/references/tracing.md +139 -0
  54. package/skills/playwright-cli/references/video-recording.md +143 -0
  55. package/skills/playwright-trace/SKILL.md +171 -0
  56. package/skills/project-init/SKILL.md +93 -22
  57. package/skills/project-init/references/front-demo/.claude/settings.local.json +9 -0
  58. package/skills/wiki-update/SKILL.md +232 -232
  59. package/src/commands/doctor.js +197 -197
  60. package/src/commands/init.js +83 -83
  61. package/src/commands/plugin.js +165 -165
  62. package/src/commands/update.js +87 -87
  63. package/src/lib/area-scanner.js +129 -129
  64. package/src/lib/copier.js +104 -104
  65. package/src/lib/dir-utils.js +161 -133
  66. package/src/lib/json-merge.js +114 -114
  67. package/src/lib/paths-defaults.js +37 -37
  68. package/src/lib/prompts.js +428 -347
  69. package/src/lib/readme-gen.js +143 -143
  70. package/src/lib/report.js +338 -327
  71. package/src/lib/scaffolder.js +551 -518
  72. package/src/lib/short-name.js +36 -36
  73. package/src/utils.js +80 -80
  74. package/references/antd-front-demo/.env +0 -15
@@ -1,237 +1,237 @@
1
- # Celery 异步任务规范
2
-
3
- > **版本**: v1.0 | **修订日期**: 2026-07-15
4
- > **技术栈**: Celery 5.4+ / Redis (Broker + Backend)
5
-
6
- ---
7
-
8
- ## 一、Celery 实例配置
9
-
10
- ```python
11
- # app/tasks/celery_app.py
12
- from celery import Celery
13
- from app.core.config import settings
14
-
15
- celery_app = Celery(
16
- "worker",
17
- broker=settings.CELERY_BROKER_URL,
18
- backend=settings.CELERY_RESULT_BACKEND,
19
- )
20
-
21
- celery_app.conf.update(
22
- # 序列化
23
- task_serializer="json",
24
- accept_content=["json"],
25
- result_serializer="json",
26
-
27
- # 时区
28
- timezone="Asia/Shanghai",
29
- enable_utc=True,
30
-
31
- # 任务执行
32
- task_track_started=True,
33
- task_time_limit=300, # 硬超时 5 分钟
34
- task_soft_time_limit=240, # 软超时 4 分钟
35
-
36
- # Worker(SQLite 场景)
37
- worker_concurrency=1, # SQLite 不支持并发写
38
- worker_prefetch_multiplier=1,
39
- worker_pool="solo", # 单进程池
40
-
41
- # 结果过期
42
- result_expires=3600,
43
-
44
- # Beat 定时任务
45
- beat_schedule={},
46
- )
47
- ```
48
-
49
- ---
50
-
51
- ## 二、任务定义规范
52
-
53
- ### 2.1 命名规则
54
-
55
- ```
56
- {action}_{entity}_task
57
- ```
58
-
59
- 示例: `sync_inventory_task`, `generate_report_task`, `send_notification_task`
60
-
61
- ### 2.2 任务定义
62
-
63
- ```python
64
- # app/tasks/inventory_tasks.py
65
- from app.tasks.celery_app import celery_app
66
-
67
- @celery_app.task(
68
- name="inventory.sync_inventory",
69
- bind=True,
70
- autoretry_for=(ConnectionError, TimeoutError),
71
- max_retries=3,
72
- retry_backoff=True,
73
- retry_backoff_max=600,
74
- )
75
- def sync_inventory_task(self, warehouse_id: int, material_type: str | None = None):
76
- """同步库存数据"""
77
- try:
78
- # 任务逻辑(Celery 任务内使用同步数据库会话)
79
- from app.core.database import SessionLocal
80
- with SessionLocal() as db:
81
- # ... 业务逻辑
82
- db.commit()
83
- except Exception as exc:
84
- self.retry(exc=exc)
85
- ```
86
-
87
- ### 2.3 参数规范
88
-
89
- | 规则 | 说明 |
90
- |----------------|------------------------------------------------|
91
- | 可序列化 | 参数必须是 JSON 可序列化的(str/int/float/dict/list) |
92
- | 禁止传对象 | 禁止传递 SQLAlchemy Model 实例 |
93
- | 传递 ID | 通过 ID 在任务内部重新查询数据库 |
94
- | 参数校验 | 任务开头进行参数校验,失败直接 raise |
95
-
96
- ---
97
-
98
- ## 三、任务调用
99
-
100
- ```python
101
- from app.tasks.inventory_tasks import sync_inventory_task
102
-
103
- # 异步调用
104
- result = sync_inventory_task.delay(warehouse_id=123, material_type="aluminum")
105
-
106
- # 指定 ETA
107
- from datetime import datetime, timedelta
108
- result = sync_inventory_task.apply_async(
109
- kwargs={"warehouse_id": 123},
110
- eta=datetime.utcnow() + timedelta(minutes=10),
111
- )
112
-
113
- # 获取结果(同步等待)
114
- result.get(timeout=60)
115
-
116
- # 检查状态
117
- result.status # PENDING / STARTED / SUCCESS / FAILURE / RETRY
118
- result.ready() # bool
119
- ```
120
-
121
- ---
122
-
123
- ## 四、错误处理与重试
124
-
125
- ```python
126
- @celery_app.task(
127
- bind=True,
128
- autoretry_for=(ConnectionError,),
129
- max_retries=3,
130
- retry_backoff=True,
131
- retry_backoff_max=600,
132
- retry_jitter=True,
133
- )
134
- def process_order_task(self, order_id: int):
135
- """处理订单"""
136
- try:
137
- # 业务逻辑
138
- ...
139
- except BusinessLogicError as exc:
140
- # 业务错误不重试,直接记录
141
- logger.error(f"Order {order_id} failed: {exc}")
142
- raise
143
- except ExternalServiceError as exc:
144
- # 外部服务错误,手动重试
145
- raise self.retry(exc=exc, countdown=60)
146
- ```
147
-
148
- | 场景 | 策略 |
149
- |----------------|----------------------|
150
- | 网络超时 | autoretry + backoff |
151
- | 业务逻辑错误 | 不重试,记录日志 |
152
- | 数据不一致 | 不重试,告警通知 |
153
- | 外部服务故障 | 手动 retry + 固定间隔|
154
-
155
- ---
156
-
157
- ## 五、定时任务(Celery Beat)
158
-
159
- ```python
160
- celery_app.conf.beat_schedule = {
161
- "daily-inventory-sync": {
162
- "task": "inventory.sync_inventory",
163
- "schedule": crontab(hour=2, minute=0), # 每天凌晨 2 点
164
- "kwargs": {"warehouse_id": 0},
165
- },
166
- "weekly-report": {
167
- "task": "report.generate_weekly_report",
168
- "schedule": crontab(day_of_week="monday", hour=8, minute=0),
169
- },
170
- }
171
- ```
172
-
173
- ---
174
-
175
- ## 六、Worker 配置
176
-
177
- ### 6.1 启动命令
178
-
179
- ```bash
180
- # 开发环境
181
- celery -A app.tasks.celery_app worker --loglevel=debug --pool=solo
182
-
183
- # 生产环境(SQLite)
184
- celery -A app.tasks.celery_app worker --loglevel=info --pool=solo --concurrency=1
185
-
186
- # Beat 定时任务调度
187
- celery -A app.tasks.celery_app beat --loglevel=info
188
- ```
189
-
190
- ### 6.2 SQLite 注意事项
191
-
192
- | 事项 | 说明 |
193
- |--------------|------------------------------------------------|
194
- | 并发 | 必须 `--concurrency=1`,SQLite 不支持并发写 |
195
- | 连接池 | 每个任务创建新的数据库连接,任务结束关闭 |
196
- | 事务 | 任务内部手动 commit,不依赖外部事务 |
197
- | 长时间任务 | 拆分为多个短任务,避免长时间持有数据库锁 |
198
-
199
- ---
200
-
201
- ## 七、监控(Flower)
202
-
203
- ```bash
204
- celery -A app.tasks.celery_app flower --port=5555
205
- # 访问 http://localhost:5555
206
- ```
207
-
208
- ---
209
-
210
- ## 八、任务测试
211
-
212
- ```python
213
- # tests/conftest.py
214
- @pytest.fixture(autouse=True)
215
- def celery_eager_mode(monkeypatch):
216
- """测试时任务同步执行"""
217
- from app.tasks.celery_app import celery_app
218
- celery_app.conf.update(
219
- task_always_eager=True,
220
- task_eager_propagates=True,
221
- )
222
-
223
- # tests/test_tasks/test_inventory.py
224
- def test_sync_inventory_task_success(db_session):
225
- """测试库存同步任务成功"""
226
- warehouse = WarehouseFactory()
227
- db_session.add(warehouse)
228
- db_session.commit()
229
-
230
- result = sync_inventory_task.delay(warehouse_id=warehouse.id)
231
- assert result.successful()
232
-
233
- def test_sync_inventory_task_invalid_id():
234
- """测试无效仓库 ID"""
235
- result = sync_inventory_task.delay(warehouse_id=99999)
236
- assert result.failed()
237
- ```
1
+ # Celery 异步任务规范
2
+
3
+ > **版本**: v1.0 | **修订日期**: 2026-07-15
4
+ > **技术栈**: Celery 5.4+ / Redis (Broker + Backend)
5
+
6
+ ---
7
+
8
+ ## 一、Celery 实例配置
9
+
10
+ ```python
11
+ # app/tasks/celery_app.py
12
+ from celery import Celery
13
+ from app.core.config import settings
14
+
15
+ celery_app = Celery(
16
+ "worker",
17
+ broker=settings.CELERY_BROKER_URL,
18
+ backend=settings.CELERY_RESULT_BACKEND,
19
+ )
20
+
21
+ celery_app.conf.update(
22
+ # 序列化
23
+ task_serializer="json",
24
+ accept_content=["json"],
25
+ result_serializer="json",
26
+
27
+ # 时区
28
+ timezone="Asia/Shanghai",
29
+ enable_utc=True,
30
+
31
+ # 任务执行
32
+ task_track_started=True,
33
+ task_time_limit=300, # 硬超时 5 分钟
34
+ task_soft_time_limit=240, # 软超时 4 分钟
35
+
36
+ # Worker(SQLite 场景)
37
+ worker_concurrency=1, # SQLite 不支持并发写
38
+ worker_prefetch_multiplier=1,
39
+ worker_pool="solo", # 单进程池
40
+
41
+ # 结果过期
42
+ result_expires=3600,
43
+
44
+ # Beat 定时任务
45
+ beat_schedule={},
46
+ )
47
+ ```
48
+
49
+ ---
50
+
51
+ ## 二、任务定义规范
52
+
53
+ ### 2.1 命名规则
54
+
55
+ ```
56
+ {action}_{entity}_task
57
+ ```
58
+
59
+ 示例: `sync_inventory_task`, `generate_report_task`, `send_notification_task`
60
+
61
+ ### 2.2 任务定义
62
+
63
+ ```python
64
+ # app/tasks/inventory_tasks.py
65
+ from app.tasks.celery_app import celery_app
66
+
67
+ @celery_app.task(
68
+ name="inventory.sync_inventory",
69
+ bind=True,
70
+ autoretry_for=(ConnectionError, TimeoutError),
71
+ max_retries=3,
72
+ retry_backoff=True,
73
+ retry_backoff_max=600,
74
+ )
75
+ def sync_inventory_task(self, warehouse_id: int, material_type: str | None = None):
76
+ """同步库存数据"""
77
+ try:
78
+ # 任务逻辑(Celery 任务内使用同步数据库会话)
79
+ from app.core.database import SessionLocal
80
+ with SessionLocal() as db:
81
+ # ... 业务逻辑
82
+ db.commit()
83
+ except Exception as exc:
84
+ self.retry(exc=exc)
85
+ ```
86
+
87
+ ### 2.3 参数规范
88
+
89
+ | 规则 | 说明 |
90
+ |----------------|------------------------------------------------|
91
+ | 可序列化 | 参数必须是 JSON 可序列化的(str/int/float/dict/list) |
92
+ | 禁止传对象 | 禁止传递 SQLAlchemy Model 实例 |
93
+ | 传递 ID | 通过 ID 在任务内部重新查询数据库 |
94
+ | 参数校验 | 任务开头进行参数校验,失败直接 raise |
95
+
96
+ ---
97
+
98
+ ## 三、任务调用
99
+
100
+ ```python
101
+ from app.tasks.inventory_tasks import sync_inventory_task
102
+
103
+ # 异步调用
104
+ result = sync_inventory_task.delay(warehouse_id=123, material_type="aluminum")
105
+
106
+ # 指定 ETA
107
+ from datetime import datetime, timedelta
108
+ result = sync_inventory_task.apply_async(
109
+ kwargs={"warehouse_id": 123},
110
+ eta=datetime.utcnow() + timedelta(minutes=10),
111
+ )
112
+
113
+ # 获取结果(同步等待)
114
+ result.get(timeout=60)
115
+
116
+ # 检查状态
117
+ result.status # PENDING / STARTED / SUCCESS / FAILURE / RETRY
118
+ result.ready() # bool
119
+ ```
120
+
121
+ ---
122
+
123
+ ## 四、错误处理与重试
124
+
125
+ ```python
126
+ @celery_app.task(
127
+ bind=True,
128
+ autoretry_for=(ConnectionError,),
129
+ max_retries=3,
130
+ retry_backoff=True,
131
+ retry_backoff_max=600,
132
+ retry_jitter=True,
133
+ )
134
+ def process_order_task(self, order_id: int):
135
+ """处理订单"""
136
+ try:
137
+ # 业务逻辑
138
+ ...
139
+ except BusinessLogicError as exc:
140
+ # 业务错误不重试,直接记录
141
+ logger.error(f"Order {order_id} failed: {exc}")
142
+ raise
143
+ except ExternalServiceError as exc:
144
+ # 外部服务错误,手动重试
145
+ raise self.retry(exc=exc, countdown=60)
146
+ ```
147
+
148
+ | 场景 | 策略 |
149
+ |----------------|----------------------|
150
+ | 网络超时 | autoretry + backoff |
151
+ | 业务逻辑错误 | 不重试,记录日志 |
152
+ | 数据不一致 | 不重试,告警通知 |
153
+ | 外部服务故障 | 手动 retry + 固定间隔|
154
+
155
+ ---
156
+
157
+ ## 五、定时任务(Celery Beat)
158
+
159
+ ```python
160
+ celery_app.conf.beat_schedule = {
161
+ "daily-inventory-sync": {
162
+ "task": "inventory.sync_inventory",
163
+ "schedule": crontab(hour=2, minute=0), # 每天凌晨 2 点
164
+ "kwargs": {"warehouse_id": 0},
165
+ },
166
+ "weekly-report": {
167
+ "task": "report.generate_weekly_report",
168
+ "schedule": crontab(day_of_week="monday", hour=8, minute=0),
169
+ },
170
+ }
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 六、Worker 配置
176
+
177
+ ### 6.1 启动命令
178
+
179
+ ```bash
180
+ # 开发环境
181
+ celery -A app.tasks.celery_app worker --loglevel=debug --pool=solo
182
+
183
+ # 生产环境(SQLite)
184
+ celery -A app.tasks.celery_app worker --loglevel=info --pool=solo --concurrency=1
185
+
186
+ # Beat 定时任务调度
187
+ celery -A app.tasks.celery_app beat --loglevel=info
188
+ ```
189
+
190
+ ### 6.2 SQLite 注意事项
191
+
192
+ | 事项 | 说明 |
193
+ |--------------|------------------------------------------------|
194
+ | 并发 | 必须 `--concurrency=1`,SQLite 不支持并发写 |
195
+ | 连接池 | 每个任务创建新的数据库连接,任务结束关闭 |
196
+ | 事务 | 任务内部手动 commit,不依赖外部事务 |
197
+ | 长时间任务 | 拆分为多个短任务,避免长时间持有数据库锁 |
198
+
199
+ ---
200
+
201
+ ## 七、监控(Flower)
202
+
203
+ ```bash
204
+ celery -A app.tasks.celery_app flower --port=5555
205
+ # 访问 http://localhost:5555
206
+ ```
207
+
208
+ ---
209
+
210
+ ## 八、任务测试
211
+
212
+ ```python
213
+ # tests/conftest.py
214
+ @pytest.fixture(autouse=True)
215
+ def celery_eager_mode(monkeypatch):
216
+ """测试时任务同步执行"""
217
+ from app.tasks.celery_app import celery_app
218
+ celery_app.conf.update(
219
+ task_always_eager=True,
220
+ task_eager_propagates=True,
221
+ )
222
+
223
+ # tests/test_tasks/test_inventory.py
224
+ def test_sync_inventory_task_success(db_session):
225
+ """测试库存同步任务成功"""
226
+ warehouse = WarehouseFactory()
227
+ db_session.add(warehouse)
228
+ db_session.commit()
229
+
230
+ result = sync_inventory_task.delay(warehouse_id=warehouse.id)
231
+ assert result.successful()
232
+
233
+ def test_sync_inventory_task_invalid_id():
234
+ """测试无效仓库 ID"""
235
+ result = sync_inventory_task.delay(warehouse_id=99999)
236
+ assert result.failed()
237
+ ```