sillyspec 3.22.6 → 3.22.8
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.
- package/.claude/skills/sillyspec-brainstorm/SKILL.md +8 -2
- package/.claude/skills/sillyspec-quick/SKILL.md +1 -0
- package/package.json +1 -1
- package/src/run.js +21 -0
- package/src/stages/archive.js +3 -0
- package/src/stages/brainstorm.js +21 -14
- package/src/stages/execute.js +1 -1
- package/src/stages/plan.js +3 -2
- package/src/stages/scan.js +12 -3
- package/src/stages/verify.js +1 -1
- package/src/worktree.js +7 -2
|
@@ -64,10 +64,16 @@ sillyspec run brainstorm --done --answer "..." --output "..." # 一步完成
|
|
|
64
64
|
## 阶段流转
|
|
65
65
|
|
|
66
66
|
```
|
|
67
|
-
|
|
67
|
+
┌─ scale=large → plan(四件套齐)
|
|
68
|
+
scan → brainstorm ┤
|
|
69
|
+
└─ scale=small → quick --linked-changes(仅 design.md)
|
|
68
70
|
```
|
|
69
71
|
|
|
70
|
-
brainstorm
|
|
72
|
+
brainstorm 完成时按 design.md frontmatter 的 `scale` 分叉:
|
|
73
|
+
- **large**(多文件/跨模块/有状态机或 schema 变更):四件套齐 + 自审通过 → `sillyspec run plan --change <变更名>`
|
|
74
|
+
- **small**(≤2 文件、单模块、无跨模块依赖):仅生成 design.md → `sillyspec run quick --linked-changes <变更名>`
|
|
75
|
+
|
|
76
|
+
> 规模由 AI 在 brainstorm 最后一步评估并写入 design.md frontmatter。判错可手动改 `scale` 后再跑相应阶段。
|
|
71
77
|
|
|
72
78
|
## 铁律
|
|
73
79
|
|
|
@@ -7,6 +7,7 @@ description: 用于明确、低风险、范围很小的直接任务。适合用
|
|
|
7
7
|
|
|
8
8
|
- 明确、低风险、范围小的直接修改:改文案、修小 bug、更新单个文件
|
|
9
9
|
- 用户说"直接改、快速修、顺手调整、不要完整流程"
|
|
10
|
+
- brainstorm 判定 `scale=small` 的变更:带 design.md 进 quick(`sillyspec run quick --linked-changes <变更名>`),design 当背景
|
|
10
11
|
- 跳过 brainstorm/plan,但仍走 quick 的 3 步流程(理解任务 → 实现 → 自检提交)
|
|
11
12
|
|
|
12
13
|
## 多变更说明(quick 特殊,务必注意)
|
package/package.json
CHANGED
package/src/run.js
CHANGED
|
@@ -1571,6 +1571,25 @@ export async function runCommand(args, cwd, specDir = null) {
|
|
|
1571
1571
|
}
|
|
1572
1572
|
}
|
|
1573
1573
|
|
|
1574
|
+
// quick 启动(非 --done):reset steps + 生成 quickRunId,避免多会话共享 progress.default.quick
|
|
1575
|
+
// 继承并行会话的 step1(会话 B 复用会话 A 的 ql,本会话改动无 ql 记录)。C-实用方案:
|
|
1576
|
+
// 每次 quick 启动 reset steps(逻辑隔离,本会话从 step1 重跑建独立 ql)+ 写 current-quick-run-id。
|
|
1577
|
+
if (stageName === 'quick' && !isDone && !isStatus && !isSkip && !isReset && !isReopen) {
|
|
1578
|
+
const qStage = progress.stages?.quick
|
|
1579
|
+
if (qStage?.steps?.length) {
|
|
1580
|
+
qStage.steps = qStage.steps.map(s => ({ ...s, status: 'pending', completedAt: null }))
|
|
1581
|
+
qStage.status = 'in-progress'
|
|
1582
|
+
}
|
|
1583
|
+
try {
|
|
1584
|
+
const now = new Date()
|
|
1585
|
+
const pad = (n) => String(n).padStart(2, '0')
|
|
1586
|
+
const quickRunId = `quick-${now.getFullYear()}-${pad(now.getMonth()+1)}-${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`
|
|
1587
|
+
const runtimeRoot = platformOpts.runtimeRoot || join(specRoot, '.runtime')
|
|
1588
|
+
mkdirSync(runtimeRoot, { recursive: true })
|
|
1589
|
+
writeFileSync(join(runtimeRoot, 'current-quick-run-id'), quickRunId)
|
|
1590
|
+
} catch {}
|
|
1591
|
+
}
|
|
1592
|
+
|
|
1574
1593
|
// 确保步骤已初始化
|
|
1575
1594
|
const changed = await ensureStageSteps(progress, stageName, cwd, specRoot)
|
|
1576
1595
|
if (changed && effectiveChange) {
|
|
@@ -1832,6 +1851,7 @@ async function runStage(pm, progress, stageName, cwd, changeName, skipApproval =
|
|
|
1832
1851
|
try {
|
|
1833
1852
|
const gitResult = safeGit(cwd, ['rev-parse', 'HEAD'])
|
|
1834
1853
|
const scanGuard = {
|
|
1854
|
+
name_zh: '扫描守卫',
|
|
1835
1855
|
sourceCommit: gitResult.value,
|
|
1836
1856
|
sourceCommitError: gitResult.error,
|
|
1837
1857
|
startedAt: new Date().toISOString(),
|
|
@@ -1878,6 +1898,7 @@ async function runStage(pm, progress, stageName, cwd, changeName, skipApproval =
|
|
|
1878
1898
|
const allowNew = quickOpts?.isAllowNew || false
|
|
1879
1899
|
const forceBaseline = quickOpts?.isForceBaseline || false
|
|
1880
1900
|
progress.quickGuard = {
|
|
1901
|
+
name_zh: '快速任务守卫',
|
|
1881
1902
|
baselineCommit: safeGit(cwd, ['rev-parse', 'HEAD']).value,
|
|
1882
1903
|
baselineFiles,
|
|
1883
1904
|
allowedFiles,
|
package/src/stages/archive.js
CHANGED
|
@@ -23,6 +23,9 @@ export const definition = {
|
|
|
23
23
|
name: 'extract-module-impact',
|
|
24
24
|
prompt: `按照 \`.sillyspec/workflows/archive-impact.yaml\` 中定义的 \`impact-analyzer\` 角色规则,分析本次变更影响的模块。
|
|
25
25
|
|
|
26
|
+
### 文件标题规则(sillyhub 平台解析识别用)
|
|
27
|
+
module-impact.md 第一行标题必须用中文:# 模块影响分析(Module Impact)— <变更简述>
|
|
28
|
+
|
|
26
29
|
### 操作
|
|
27
30
|
1. 读取 \`.sillyspec/workflows/archive-impact.yaml\`,了解角色定义和检查规则
|
|
28
31
|
2. 读取变更目录下的 proposal.md、design.md、tasks.md
|
package/src/stages/brainstorm.js
CHANGED
|
@@ -329,6 +329,9 @@ HTML 原型文件路径(或"跳过"如果不适合)`,
|
|
|
329
329
|
name: '写设计文档并自审',
|
|
330
330
|
prompt: `撰写 design 文档并进行 AI 自审。
|
|
331
331
|
|
|
332
|
+
### 文件标题规则(sillyhub 平台解析识别用)
|
|
333
|
+
design.md 第一行标题必须用中文:# 设计文档(Design)— <变更简述>
|
|
334
|
+
|
|
332
335
|
### design.md 必须包含的章节
|
|
333
336
|
1. **背景**:为什么做、解决什么问题
|
|
334
337
|
2. **设计目标**:要达成什么
|
|
@@ -519,18 +522,21 @@ status: passed | needs-user-input | blocked | skipped
|
|
|
519
522
|
requiresWait: true,
|
|
520
523
|
waitReason: '等待用户最终确认设计方案',
|
|
521
524
|
waitOptions: ['确认', '需要修改', '推翻重来'],
|
|
522
|
-
prompt:
|
|
525
|
+
prompt: `用户确认设计方案,按变更规模生成规范文件并给出实现路径建议。
|
|
526
|
+
|
|
527
|
+
### 规模评估(展示前先做)
|
|
528
|
+
读取 design.md 的「文件变更清单」,判断本次变更规模:
|
|
529
|
+
- **small(小变更)**:改动 ≤ 2 个文件、单模块、无跨模块依赖、无状态机/schema/API 变更
|
|
530
|
+
- **large(大变更)**:不满足上述任意一条
|
|
531
|
+
在 design.md frontmatter 写入 \`scale: small\` 或 \`scale: large\`(frontmatter 不存在则补 \`author\`/\`created_at\`/\`scale\`)。规模决定下面的产物范围和实现路径。
|
|
523
532
|
|
|
524
533
|
### 操作
|
|
525
|
-
1. 展示 design.md
|
|
534
|
+
1. 展示 design.md 摘要 + **规模评估结果(small/large + 一句依据)** 给用户
|
|
526
535
|
2. 暂停等待用户选择:✅ 确认 / ✏️ 修改 / ❌ 推翻重来
|
|
527
|
-
3.
|
|
528
|
-
- **design.md
|
|
529
|
-
- **
|
|
530
|
-
-
|
|
531
|
-
- **requirements.md**:角色表 + FR 编号需求 + Given/When/Then 行为规格 + 非功能需求 + D-xxx@vN 覆盖关系
|
|
532
|
-
- **tasks.md**:任务列表(只列名称、对应文件路径、覆盖的 FR-xxx/D-xxx@vN,细节在 plan 阶段展开)
|
|
533
|
-
- \`git add .sillyspec/\` — 暂存规范文件(不要 commit)
|
|
536
|
+
3. 确认后,**按规模生成规范文件**:
|
|
537
|
+
- **scale=large**:在 \`.sillyspec/changes/<change-name>/\` 下生成完整四件套(design.md / decisions.md 可选 / proposal.md / requirements.md / tasks.md),实现路径 → \`sillyspec run plan --change <变更名>\`
|
|
538
|
+
- **scale=small**:只生成/补全 design.md(proposal/requirements/tasks 对 quick 无用,不生成),实现路径 → \`sillyspec run quick --linked-changes <变更名>\`
|
|
539
|
+
- 两种规模都执行 \`git add .sillyspec/\` — 暂存规范文件(不要 commit)
|
|
534
540
|
|
|
535
541
|
所有规范文件头部必须包含 YAML frontmatter:
|
|
536
542
|
\`\`\`\`yaml
|
|
@@ -542,7 +548,7 @@ created_at: <now-datetime>
|
|
|
542
548
|
|
|
543
549
|
### proposal.md 格式要求
|
|
544
550
|
\`\`\`markdown
|
|
545
|
-
# Proposal
|
|
551
|
+
# 提案书(Proposal)
|
|
546
552
|
|
|
547
553
|
## 动机
|
|
548
554
|
为什么做、解决什么核心问题
|
|
@@ -565,7 +571,7 @@ created_at: <now-datetime>
|
|
|
565
571
|
|
|
566
572
|
### requirements.md 格式要求
|
|
567
573
|
\`\`\`markdown
|
|
568
|
-
# Requirements
|
|
574
|
+
# 需求规格(Requirements)
|
|
569
575
|
|
|
570
576
|
## 角色
|
|
571
577
|
| 角色 | 说明 |
|
|
@@ -595,7 +601,7 @@ Then 期望结果
|
|
|
595
601
|
|
|
596
602
|
### decisions.md 格式要求(仅在有 Grill/重大决策时生成)
|
|
597
603
|
\`\`\`markdown
|
|
598
|
-
# Decisions
|
|
604
|
+
# 决策记录(Decisions)
|
|
599
605
|
|
|
600
606
|
## D-001@v1: 决策短标题
|
|
601
607
|
- type: definition | consistency | feasibility | term | boundary | premise | architecture | compatibility | risk
|
|
@@ -637,8 +643,9 @@ Then 期望结果
|
|
|
637
643
|
- 推翻重来回到 Step 6(对话式探索)
|
|
638
644
|
- 表名/字段名/类名必须来自真实代码或标注"新增"
|
|
639
645
|
- 如果存在 decisions.md,requirements.md 必须引用全部当前版本 D-xxx@vN;没有覆盖的 D-xxx@vN 必须标注为剩余风险
|
|
640
|
-
- 如果 Design Grill 产生 P0/P1 unresolved blocker,必须回到 design 修正,不能进入 plan
|
|
641
|
-
- tasks.md 只列任务名,细节在 plan
|
|
646
|
+
- 如果 Design Grill 产生 P0/P1 unresolved blocker,必须回到 design 修正,不能进入 plan/quick
|
|
647
|
+
- tasks.md 只列任务名,细节在 plan 阶段展开
|
|
648
|
+
- **规范 md 文件第一行标题用中文**(sillyhub 平台解析识别用):tasks.md 第一行用 # 任务清单(Tasks)(proposal/design/requirements/decisions 见各自模板,均已含中文标题)`,
|
|
642
649
|
|
|
643
650
|
}
|
|
644
651
|
]
|
package/src/stages/execute.js
CHANGED
|
@@ -627,7 +627,7 @@ task-XX 对应:.sillyspec/.runtime/execute-runs/{EXECUTE_RUN_ID}/tasks/task-XX
|
|
|
627
627
|
|
|
628
628
|
**review.json 必填字段:**
|
|
629
629
|
|
|
630
|
-
{ "schemaVersion": 1, "task": "task-XX", "base": "<git-base-commit>", "head": "<git-head-commit>",
|
|
630
|
+
{ "name_zh": "任务评审", "schemaVersion": 1, "task": "task-XX", "base": "<git-base-commit>", "head": "<git-head-commit>",
|
|
631
631
|
"changedFiles": ["src/foo.js"], "specVerdict": "pass|fail|cannot_verify",
|
|
632
632
|
"qualityVerdict": "pass|fail|cannot_verify", "reviewerNotes": "评审说明",
|
|
633
633
|
"requiredEvidence": [] }
|
package/src/stages/plan.js
CHANGED
|
@@ -200,7 +200,7 @@ plan_level: none
|
|
|
200
200
|
plan_level: light
|
|
201
201
|
---
|
|
202
202
|
|
|
203
|
-
#
|
|
203
|
+
# 轻量计划(Light Plan):<需求简述>
|
|
204
204
|
|
|
205
205
|
## 来源
|
|
206
206
|
直接引用 brainstorm 结论或用户原始需求,不重新扩写。
|
|
@@ -243,7 +243,7 @@ light 计划的约束:
|
|
|
243
243
|
plan_level: full
|
|
244
244
|
---
|
|
245
245
|
|
|
246
|
-
#
|
|
246
|
+
# 实现计划(Plan)
|
|
247
247
|
|
|
248
248
|
## Spike 前置验证(如需要)
|
|
249
249
|
| Spike | 验证内容 | 不通过后果 |
|
|
@@ -400,6 +400,7 @@ export function buildCoordinatorStep(changeDir, taskNames) {
|
|
|
400
400
|
---
|
|
401
401
|
id: task-${num}
|
|
402
402
|
title: ${name}
|
|
403
|
+
title_zh: <任务中文标题>
|
|
403
404
|
author: <git-user>
|
|
404
405
|
created_at: <now-datetime>
|
|
405
406
|
priority: P0
|
package/src/stages/scan.js
CHANGED
|
@@ -159,6 +159,14 @@ export const definition = {
|
|
|
159
159
|
- 断点续扫步骤列出的缺失文档列表
|
|
160
160
|
- 环境探测结果摘要(如有 _env-detect.md,直接贴入)
|
|
161
161
|
- **⚠️ 必须强调:子代理必须用 write 工具将文件写入磁盘**
|
|
162
|
+
- **文件标题用中文**(sillyhub 平台解析识别用):每份 scan 文档第一行用 # 中文名(English)格式:
|
|
163
|
+
- STRUCTURE.md = # 目录结构(Structure)
|
|
164
|
+
- CONVENTIONS.md = # 代码约定(Conventions)
|
|
165
|
+
- ARCHITECTURE.md = # 架构(Architecture)
|
|
166
|
+
- TESTING.md = # 测试(Testing)
|
|
167
|
+
- CONCERNS.md = # 关注点(Concerns)
|
|
168
|
+
- INTEGRATIONS.md = # 集成(Integrations)
|
|
169
|
+
- PROJECT.md = # 项目(Project)
|
|
162
170
|
|
|
163
171
|
### 完成后
|
|
164
172
|
列出每个项目的 7 份文档状态:
|
|
@@ -451,7 +459,7 @@ step1 → step2 → step3
|
|
|
451
459
|
|
|
452
460
|
文件格式:
|
|
453
461
|
\`\`\`markdown
|
|
454
|
-
# Glossary
|
|
462
|
+
# 术语表(Glossary)
|
|
455
463
|
|
|
456
464
|
## Session
|
|
457
465
|
在本项目中,session 指...(项目内特殊含义)
|
|
@@ -486,9 +494,9 @@ step1 → step2 → step3
|
|
|
486
494
|
|
|
487
495
|
INDEX.md 维护索引,格式(每行:关键词1|关键词2 → [条目名](文件#锚点);关键词用于 execute 阶段命中匹配,必须给出能区分该知识的词):
|
|
488
496
|
\`\`\`markdown
|
|
489
|
-
# Knowledge Index
|
|
497
|
+
# 知识索引(Knowledge Index)
|
|
490
498
|
|
|
491
|
-
## Conventions
|
|
499
|
+
## 约定(Conventions)
|
|
492
500
|
- ESM|module|import → [ESM Only](conventions.md#esm-only)
|
|
493
501
|
\`\`\`
|
|
494
502
|
|
|
@@ -498,6 +506,7 @@ INDEX.md 维护索引,格式(每行:关键词1|关键词2 → [条目名](
|
|
|
498
506
|
3. **不确定分类或不确定长期有效 → uncategorized.md** — 宁可不确定也不要放错
|
|
499
507
|
4. **每个正式分类条目必须更新 INDEX.md** — 添加对应分类下的链接
|
|
500
508
|
5. **每个条目用 markdown 锚点格式** — 文件内用 \`## 标题\`,INDEX 用 \`[#标题]\` 或 \`(文件名#标题)\`
|
|
509
|
+
6. **knowledge 文件标题用中文**(sillyhub 平台解析识别用):conventions.md 第一行 # 项目约定(Conventions)、patterns.md = # 复用模式(Patterns)、known-issues.md = # 已知问题(Known Issues)、uncategorized.md = # 未分类知识(Uncategorized)、INDEX.md 见模板(知识索引)
|
|
501
510
|
|
|
502
511
|
### 操作
|
|
503
512
|
1. 读取现有 knowledge 文件:\`{KNOWLEDGE_ROOT}/INDEX.md\`、\`{KNOWLEDGE_ROOT}/conventions.md\` 等
|
package/src/stages/verify.js
CHANGED
package/src/worktree.js
CHANGED
|
@@ -315,7 +315,8 @@ export class WorktreeManager {
|
|
|
315
315
|
// worktree 内任何已写入的内容,不触发幽灵清理)。最终完整 meta 在 step 6 覆盖。
|
|
316
316
|
try {
|
|
317
317
|
const placeholderMeta = {
|
|
318
|
-
|
|
318
|
+
name_zh: 'worktree 元数据',
|
|
319
|
+
changeName: name,
|
|
319
320
|
branch,
|
|
320
321
|
baseBranch,
|
|
321
322
|
baseHash,
|
|
@@ -381,6 +382,7 @@ export class WorktreeManager {
|
|
|
381
382
|
|
|
382
383
|
// 6. 写入 meta.json
|
|
383
384
|
const meta = {
|
|
385
|
+
name_zh: 'worktree 元数据',
|
|
384
386
|
changeName: name,
|
|
385
387
|
branch,
|
|
386
388
|
baseBranch,
|
|
@@ -416,6 +418,7 @@ export class WorktreeManager {
|
|
|
416
418
|
_recoverNativeWorktreeMeta(name, { worktreePath, branch }) {
|
|
417
419
|
const baseHash = gitQuiet(worktreePath, 'rev-parse HEAD') || null
|
|
418
420
|
const meta = {
|
|
421
|
+
name_zh: 'worktree 元数据',
|
|
419
422
|
changeName: name,
|
|
420
423
|
branch: branch || BRANCH_PREFIX + name,
|
|
421
424
|
baseBranch: branch,
|
|
@@ -459,7 +462,8 @@ export class WorktreeManager {
|
|
|
459
462
|
baseBranch = baseBranch || gitQuiet(this.cwd, 'symbolic-ref --short HEAD') || gitQuiet(this.cwd, 'rev-parse HEAD')
|
|
460
463
|
baseHash = baseHash || git(this.cwd, 'rev-parse HEAD')
|
|
461
464
|
const meta = {
|
|
462
|
-
|
|
465
|
+
name_zh: 'worktree 元数据',
|
|
466
|
+
changeName: name,
|
|
463
467
|
branch: branch || BRANCH_PREFIX + name,
|
|
464
468
|
baseBranch,
|
|
465
469
|
baseHash,
|
|
@@ -494,6 +498,7 @@ export class WorktreeManager {
|
|
|
494
498
|
}
|
|
495
499
|
|
|
496
500
|
const meta = {
|
|
501
|
+
name_zh: 'worktree 元数据',
|
|
497
502
|
changeName: name,
|
|
498
503
|
branch: branch || BRANCH_PREFIX + name,
|
|
499
504
|
baseBranch,
|