sillyspec 3.26.9 → 3.26.11
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-archive/SKILL.md +85 -85
- package/.claude/skills/sillyspec-brainstorm/SKILL.md +114 -114
- package/.claude/skills/sillyspec-commit/SKILL.md +109 -109
- package/.claude/skills/sillyspec-continue/SKILL.md +45 -45
- package/.claude/skills/sillyspec-doctor/SKILL.md +76 -76
- package/.claude/skills/sillyspec-execute/SKILL.md +200 -200
- package/.claude/skills/sillyspec-explore/SKILL.md +95 -95
- package/.claude/skills/sillyspec-knowledge/SKILL.md +269 -269
- package/.claude/skills/sillyspec-plan/SKILL.md +148 -148
- package/.claude/skills/sillyspec-quick/SKILL.md +111 -111
- package/.claude/skills/sillyspec-resume/SKILL.md +68 -68
- package/.claude/skills/sillyspec-scan/SKILL.md +79 -79
- package/.claude/skills/sillyspec-state/SKILL.md +64 -64
- package/.claude/skills/sillyspec-status/SKILL.md +54 -54
- package/.claude/skills/sillyspec-verify/SKILL.md +83 -81
- package/.claude/skills/sillyspec-workspace/SKILL.md +169 -169
- package/.gitattributes +2 -0
- package/.husky/pre-push +20 -20
- package/.npmrc-publish +2 -0
- package/README.md +201 -201
- package/SKILL.md +90 -90
- package/package.json +39 -39
- package/packages/dashboard/dist/assets/index-Bq_Z2hne.js +7446 -7446
- package/packages/dashboard/dist/assets/index-O2W5RV4z.css +1 -1
- package/packages/dashboard/dist/index.html +16 -16
- package/packages/dashboard/package.json +25 -25
- package/packages/dashboard/server/executor.js +86 -86
- package/packages/dashboard/server/index.js +601 -601
- package/packages/dashboard/server/parser.js +526 -526
- package/src/change-risk-profile.js +254 -254
- package/src/classify-change.js +109 -109
- package/src/config-schema.js +310 -310
- package/src/contract-matrix.js +379 -379
- package/src/db.js +350 -350
- package/src/dispatch/backends/local-agent.js +155 -155
- package/src/dispatch/backends/sillyhub-mcp.js +245 -245
- package/src/dispatch/probe.js +210 -210
- package/src/dispatch/strategy.js +121 -121
- package/src/docs-check.js +131 -4
- package/src/doctor-diagnostics.js +711 -711
- package/src/endpoint-extractor.js +401 -401
- package/src/fs-atomic.js +69 -69
- package/src/git-helper.js +79 -79
- package/src/hooks/claude-pre-tool-use.cjs +125 -125
- package/src/hooks/worktree-guard.js +848 -848
- package/src/index.js +90 -8
- package/src/init.js +623 -623
- package/src/knowledge-match.js +130 -130
- package/src/local-detect.js +120 -120
- package/src/machine-interface.js +543 -543
- package/src/migrate.js +127 -127
- package/src/progress/change-registry.js +297 -260
- package/src/progress/consistency-doctor.js +355 -355
- package/src/progress/shared.js +36 -36
- package/src/progress/stage-machine.js +29 -1
- package/src/progress/step-store.js +261 -261
- package/src/progress.js +1131 -1127
- package/src/quicklog.js +693 -675
- package/src/review-tier.js +77 -77
- package/src/run/command.js +1385 -1364
- package/src/run/complete-handlers.js +198 -9
- package/src/run/complete.js +225 -24
- package/src/run/concurrent-detect.js +22 -0
- package/src/run/gates.js +755 -755
- package/src/run/prompt.js +761 -721
- package/src/run/quick-audit.js +155 -146
- package/src/run/shared.js +1268 -1197
- package/src/run/stage.js +487 -479
- package/src/scan-postcheck.js +371 -371
- package/src/setup.js +416 -416
- package/src/sillyhub-mcp/client.js +529 -529
- package/src/spec-sync.js +323 -0
- package/src/stage-contract.js +897 -897
- package/src/stage-review.js +549 -549
- package/src/stages/archive.js +155 -154
- package/src/stages/brainstorm-auto.js +236 -236
- package/src/stages/brainstorm.js +596 -597
- package/src/stages/cmd-existence.js +145 -145
- package/src/stages/doctor.js +371 -371
- package/src/stages/execute.js +1003 -991
- package/src/stages/explore.js +34 -34
- package/src/stages/index.js +29 -29
- package/src/stages/knowledge.js +498 -498
- package/src/stages/plan-postcheck.js +1302 -1281
- package/src/stages/plan.js +625 -604
- package/src/stages/quick.js +151 -143
- package/src/stages/scan.js +606 -605
- package/src/stages/status.js +64 -64
- package/src/stages/verify.js +264 -261
- package/src/sync.js +1223 -1125
- package/src/task-review.js +1019 -1019
- package/src/verify-postcheck.js +1186 -1186
- package/src/workflow.js +600 -600
- package/src/worktree-apply.js +1213 -1136
- package/src/worktree-deps.js +353 -353
- package/src/worktree.js +1481 -1437
- package/templates/workflows/archive-impact.yaml +79 -79
- package/templates/workflows/scan-docs.yaml +132 -132
package/src/migrate.js
CHANGED
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, renameSync, copyFileSync, statSync, cpSync } from 'fs';
|
|
2
|
-
import { basename, join, resolve } from 'path';
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Migrate old .sillyspec/ structure to unified .sillyspec/docs/<project>/ structure
|
|
7
|
-
* @param {string} projectDir - Path to the project directory
|
|
8
|
-
*/
|
|
9
|
-
export function migrateDocs(projectDir) {
|
|
10
|
-
const sillyspecDir = join(projectDir, '.sillyspec');
|
|
11
|
-
if (!existsSync(sillyspecDir)) {
|
|
12
|
-
console.error('❌ .sillyspec/ 目录不存在');
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Determine project name from projects/*.yaml or directory name
|
|
17
|
-
let projectName = basename(resolve(projectDir));
|
|
18
|
-
const projectsDir = join(sillyspecDir, 'projects');
|
|
19
|
-
if (existsSync(projectsDir)) {
|
|
20
|
-
const yamlFiles = readdirSync(projectsDir).filter(f => f.endsWith('.yaml'));
|
|
21
|
-
if (yamlFiles.length > 0) {
|
|
22
|
-
projectName = yamlFiles[0].replace('.yaml', '');
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
console.log(chalk.cyan(`📦 迁移项目: ${projectName}`));
|
|
27
|
-
console.log('');
|
|
28
|
-
|
|
29
|
-
const docsBase = join(sillyspecDir, 'docs', projectName);
|
|
30
|
-
let migrated = 0;
|
|
31
|
-
|
|
32
|
-
// 1. codebase/ → .sillyspec/docs/<project>/scan/
|
|
33
|
-
const codebaseDir = join(sillyspecDir, 'codebase');
|
|
34
|
-
if (existsSync(codebaseDir)) {
|
|
35
|
-
const targetDir = join(docsBase, 'scan');
|
|
36
|
-
mkdirSync(targetDir, { recursive: true });
|
|
37
|
-
const files = readdirSync(codebaseDir).filter(f => f.endsWith('.md'));
|
|
38
|
-
for (const file of files) {
|
|
39
|
-
const src = join(codebaseDir, file);
|
|
40
|
-
const dest = join(targetDir, file);
|
|
41
|
-
if (!existsSync(dest)) {
|
|
42
|
-
copyFileSync(src, dest);
|
|
43
|
-
console.log(chalk.green(' ✅') + ` scan/${file}`);
|
|
44
|
-
migrated++;
|
|
45
|
-
} else {
|
|
46
|
-
console.log(chalk.yellow(' ⏭️') + ` scan/${file} (已存在)`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// 2. specs/ is deprecated — designs live in changes/<变更名>/design.md
|
|
52
|
-
|
|
53
|
-
// 3. changes/archive/ → .sillyspec/docs/<project>/archive/
|
|
54
|
-
const archiveDir = join(sillyspecDir, 'changes', 'archive');
|
|
55
|
-
if (existsSync(archiveDir)) {
|
|
56
|
-
const targetDir = join(docsBase, 'archive');
|
|
57
|
-
mkdirSync(targetDir, { recursive: true });
|
|
58
|
-
const entries = readdirSync(archiveDir);
|
|
59
|
-
for (const entry of entries) {
|
|
60
|
-
const src = join(archiveDir, entry);
|
|
61
|
-
const dest = join(targetDir, entry);
|
|
62
|
-
if (!existsSync(dest)) {
|
|
63
|
-
// 归档变更本身是目录(含 design.md 等),copyFileSync 对目录源抛 EISDIR;
|
|
64
|
-
// 按类型分发:目录用 cpSync 递归、文件用 copyFileSync,单条失败 try/catch 不中断整体迁移
|
|
65
|
-
try {
|
|
66
|
-
if (statSync(src).isDirectory()) {
|
|
67
|
-
cpSync(src, dest, { recursive: true });
|
|
68
|
-
} else {
|
|
69
|
-
copyFileSync(src, dest);
|
|
70
|
-
}
|
|
71
|
-
console.log(chalk.green(' ✅') + ` archive/${entry}`);
|
|
72
|
-
migrated++;
|
|
73
|
-
} catch (err) {
|
|
74
|
-
console.log(chalk.yellow(' ⚠️') + ` archive/${entry} 迁移失败: ${err.message}`);
|
|
75
|
-
}
|
|
76
|
-
} else {
|
|
77
|
-
console.log(chalk.yellow(' ⏭️') + ` archive/${entry} (已存在)`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// 4. knowledge/ → .sillyspec/docs/<project>/archive/ (append knowledge files)
|
|
83
|
-
const knowledgeDir = join(sillyspecDir, 'knowledge');
|
|
84
|
-
if (existsSync(knowledgeDir)) {
|
|
85
|
-
const targetDir = join(docsBase, 'archive');
|
|
86
|
-
mkdirSync(targetDir, { recursive: true });
|
|
87
|
-
const files = readdirSync(knowledgeDir).filter(f => f.endsWith('.md'));
|
|
88
|
-
for (const file of files) {
|
|
89
|
-
const src = join(knowledgeDir, file);
|
|
90
|
-
const dest = join(targetDir, `knowledge-${file}`);
|
|
91
|
-
if (!existsSync(dest)) {
|
|
92
|
-
copyFileSync(src, dest);
|
|
93
|
-
console.log(chalk.green(' ✅') + ` archive/knowledge-${file}`);
|
|
94
|
-
migrated++;
|
|
95
|
-
} else {
|
|
96
|
-
console.log(chalk.yellow(' ⏭️') + ` archive/knowledge-${file} (已存在)`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// 5. quicklog/ → .sillyspec/docs/<project>/quicklog/
|
|
102
|
-
const quicklogDir = join(sillyspecDir, 'quicklog');
|
|
103
|
-
if (existsSync(quicklogDir)) {
|
|
104
|
-
const targetDir = join(docsBase, 'quicklog');
|
|
105
|
-
mkdirSync(targetDir, { recursive: true });
|
|
106
|
-
const files = readdirSync(quicklogDir).filter(f => f.endsWith('.md'));
|
|
107
|
-
for (const file of files) {
|
|
108
|
-
const src = join(quicklogDir, file);
|
|
109
|
-
const dest = join(targetDir, file);
|
|
110
|
-
if (!existsSync(dest)) {
|
|
111
|
-
copyFileSync(src, dest);
|
|
112
|
-
console.log(chalk.green(' ✅') + ` quicklog/${file}`);
|
|
113
|
-
migrated++;
|
|
114
|
-
} else {
|
|
115
|
-
console.log(chalk.yellow(' ⏭️') + ` quicklog/${file} (已存在)`);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
console.log('');
|
|
121
|
-
if (migrated > 0) {
|
|
122
|
-
console.log(chalk.green(` ✅ 迁移完成,共迁移 ${migrated} 个文件`));
|
|
123
|
-
console.log(chalk.dim(' 旧文件保留在原位,确认无误后可手动删除'));
|
|
124
|
-
} else {
|
|
125
|
-
console.log(chalk.yellow(' 没有需要迁移的文件'));
|
|
126
|
-
}
|
|
127
|
-
}
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync, renameSync, copyFileSync, statSync, cpSync } from 'fs';
|
|
2
|
+
import { basename, join, resolve } from 'path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Migrate old .sillyspec/ structure to unified .sillyspec/docs/<project>/ structure
|
|
7
|
+
* @param {string} projectDir - Path to the project directory
|
|
8
|
+
*/
|
|
9
|
+
export function migrateDocs(projectDir) {
|
|
10
|
+
const sillyspecDir = join(projectDir, '.sillyspec');
|
|
11
|
+
if (!existsSync(sillyspecDir)) {
|
|
12
|
+
console.error('❌ .sillyspec/ 目录不存在');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Determine project name from projects/*.yaml or directory name
|
|
17
|
+
let projectName = basename(resolve(projectDir));
|
|
18
|
+
const projectsDir = join(sillyspecDir, 'projects');
|
|
19
|
+
if (existsSync(projectsDir)) {
|
|
20
|
+
const yamlFiles = readdirSync(projectsDir).filter(f => f.endsWith('.yaml'));
|
|
21
|
+
if (yamlFiles.length > 0) {
|
|
22
|
+
projectName = yamlFiles[0].replace('.yaml', '');
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log(chalk.cyan(`📦 迁移项目: ${projectName}`));
|
|
27
|
+
console.log('');
|
|
28
|
+
|
|
29
|
+
const docsBase = join(sillyspecDir, 'docs', projectName);
|
|
30
|
+
let migrated = 0;
|
|
31
|
+
|
|
32
|
+
// 1. codebase/ → .sillyspec/docs/<project>/scan/
|
|
33
|
+
const codebaseDir = join(sillyspecDir, 'codebase');
|
|
34
|
+
if (existsSync(codebaseDir)) {
|
|
35
|
+
const targetDir = join(docsBase, 'scan');
|
|
36
|
+
mkdirSync(targetDir, { recursive: true });
|
|
37
|
+
const files = readdirSync(codebaseDir).filter(f => f.endsWith('.md'));
|
|
38
|
+
for (const file of files) {
|
|
39
|
+
const src = join(codebaseDir, file);
|
|
40
|
+
const dest = join(targetDir, file);
|
|
41
|
+
if (!existsSync(dest)) {
|
|
42
|
+
copyFileSync(src, dest);
|
|
43
|
+
console.log(chalk.green(' ✅') + ` scan/${file}`);
|
|
44
|
+
migrated++;
|
|
45
|
+
} else {
|
|
46
|
+
console.log(chalk.yellow(' ⏭️') + ` scan/${file} (已存在)`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 2. specs/ is deprecated — designs live in changes/<变更名>/design.md
|
|
52
|
+
|
|
53
|
+
// 3. changes/archive/ → .sillyspec/docs/<project>/archive/
|
|
54
|
+
const archiveDir = join(sillyspecDir, 'changes', 'archive');
|
|
55
|
+
if (existsSync(archiveDir)) {
|
|
56
|
+
const targetDir = join(docsBase, 'archive');
|
|
57
|
+
mkdirSync(targetDir, { recursive: true });
|
|
58
|
+
const entries = readdirSync(archiveDir);
|
|
59
|
+
for (const entry of entries) {
|
|
60
|
+
const src = join(archiveDir, entry);
|
|
61
|
+
const dest = join(targetDir, entry);
|
|
62
|
+
if (!existsSync(dest)) {
|
|
63
|
+
// 归档变更本身是目录(含 design.md 等),copyFileSync 对目录源抛 EISDIR;
|
|
64
|
+
// 按类型分发:目录用 cpSync 递归、文件用 copyFileSync,单条失败 try/catch 不中断整体迁移
|
|
65
|
+
try {
|
|
66
|
+
if (statSync(src).isDirectory()) {
|
|
67
|
+
cpSync(src, dest, { recursive: true });
|
|
68
|
+
} else {
|
|
69
|
+
copyFileSync(src, dest);
|
|
70
|
+
}
|
|
71
|
+
console.log(chalk.green(' ✅') + ` archive/${entry}`);
|
|
72
|
+
migrated++;
|
|
73
|
+
} catch (err) {
|
|
74
|
+
console.log(chalk.yellow(' ⚠️') + ` archive/${entry} 迁移失败: ${err.message}`);
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
console.log(chalk.yellow(' ⏭️') + ` archive/${entry} (已存在)`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 4. knowledge/ → .sillyspec/docs/<project>/archive/ (append knowledge files)
|
|
83
|
+
const knowledgeDir = join(sillyspecDir, 'knowledge');
|
|
84
|
+
if (existsSync(knowledgeDir)) {
|
|
85
|
+
const targetDir = join(docsBase, 'archive');
|
|
86
|
+
mkdirSync(targetDir, { recursive: true });
|
|
87
|
+
const files = readdirSync(knowledgeDir).filter(f => f.endsWith('.md'));
|
|
88
|
+
for (const file of files) {
|
|
89
|
+
const src = join(knowledgeDir, file);
|
|
90
|
+
const dest = join(targetDir, `knowledge-${file}`);
|
|
91
|
+
if (!existsSync(dest)) {
|
|
92
|
+
copyFileSync(src, dest);
|
|
93
|
+
console.log(chalk.green(' ✅') + ` archive/knowledge-${file}`);
|
|
94
|
+
migrated++;
|
|
95
|
+
} else {
|
|
96
|
+
console.log(chalk.yellow(' ⏭️') + ` archive/knowledge-${file} (已存在)`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 5. quicklog/ → .sillyspec/docs/<project>/quicklog/
|
|
102
|
+
const quicklogDir = join(sillyspecDir, 'quicklog');
|
|
103
|
+
if (existsSync(quicklogDir)) {
|
|
104
|
+
const targetDir = join(docsBase, 'quicklog');
|
|
105
|
+
mkdirSync(targetDir, { recursive: true });
|
|
106
|
+
const files = readdirSync(quicklogDir).filter(f => f.endsWith('.md'));
|
|
107
|
+
for (const file of files) {
|
|
108
|
+
const src = join(quicklogDir, file);
|
|
109
|
+
const dest = join(targetDir, file);
|
|
110
|
+
if (!existsSync(dest)) {
|
|
111
|
+
copyFileSync(src, dest);
|
|
112
|
+
console.log(chalk.green(' ✅') + ` quicklog/${file}`);
|
|
113
|
+
migrated++;
|
|
114
|
+
} else {
|
|
115
|
+
console.log(chalk.yellow(' ⏭️') + ` quicklog/${file} (已存在)`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log('');
|
|
121
|
+
if (migrated > 0) {
|
|
122
|
+
console.log(chalk.green(` ✅ 迁移完成,共迁移 ${migrated} 个文件`));
|
|
123
|
+
console.log(chalk.dim(' 旧文件保留在原位,确认无误后可手动删除'));
|
|
124
|
+
} else {
|
|
125
|
+
console.log(chalk.yellow(' 没有需要迁移的文件'));
|
|
126
|
+
}
|
|
127
|
+
}
|