speccrew 0.1.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 (153) hide show
  1. package/.speccrew/agents/speccrew-feature-designer.md +142 -0
  2. package/.speccrew/agents/speccrew-product-manager.md +61 -0
  3. package/.speccrew/agents/speccrew-system-designer.md +200 -0
  4. package/.speccrew/agents/speccrew-system-developer.md +238 -0
  5. package/.speccrew/agents/speccrew-task-worker.md +80 -0
  6. package/.speccrew/agents/speccrew-team-leader.md +92 -0
  7. package/.speccrew/agents/speccrew-test-manager.md +313 -0
  8. package/.speccrew/skills/speccrew-create-agents/SKILL.md +98 -0
  9. package/.speccrew/skills/speccrew-create-agents/templates/agents/designer-agent.md +54 -0
  10. package/.speccrew/skills/speccrew-create-agents/templates/agents/dev-agent.md +79 -0
  11. package/.speccrew/skills/speccrew-create-agents/templates/agents/test-agent.md +80 -0
  12. package/.speccrew/skills/speccrew-dev-backend/SKILL.md +205 -0
  13. package/.speccrew/skills/speccrew-dev-backend/templates/TASK-RECORD-TEMPLATE.md +118 -0
  14. package/.speccrew/skills/speccrew-dev-desktop/SKILL.md +258 -0
  15. package/.speccrew/skills/speccrew-dev-desktop/templates/TASK-RECORD-TEMPLATE.md +161 -0
  16. package/.speccrew/skills/speccrew-dev-frontend/SKILL.md +202 -0
  17. package/.speccrew/skills/speccrew-dev-frontend/templates/TASK-RECORD-TEMPLATE.md +115 -0
  18. package/.speccrew/skills/speccrew-dev-mobile/SKILL.md +200 -0
  19. package/.speccrew/skills/speccrew-dev-mobile/templates/TASK-RECORD-TEMPLATE.md +125 -0
  20. package/.speccrew/skills/speccrew-fd-api-contract/SKILL.md +73 -0
  21. package/.speccrew/skills/speccrew-fd-api-contract/templates/API-CONTRACT-TEMPLATE.md +96 -0
  22. package/.speccrew/skills/speccrew-fd-feature-design/SKILL.md +395 -0
  23. package/.speccrew/skills/speccrew-fd-feature-design/templates/FEATURE-SPEC-TEMPLATE.md +387 -0
  24. package/.speccrew/skills/speccrew-get-timestamp/SKILL.md +80 -0
  25. package/.speccrew/skills/speccrew-get-timestamp/scripts/get-timestamp.js +35 -0
  26. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/SKILL.md +1116 -0
  27. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-FASTAPI.md +462 -0
  28. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-JAVA.md +480 -0
  29. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-NET.md +464 -0
  30. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE.md +480 -0
  31. package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/MODULE-OVERVIEW-TEMPLATE.md +367 -0
  32. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/SKILL.md +667 -0
  33. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/STATUS-FORMATS.md +74 -0
  34. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/batch-orchestrator.js +176 -0
  35. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/get-next-batch.js +150 -0
  36. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/get-pending-features.js +106 -0
  37. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/mark-stale.js +249 -0
  38. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/process-batch-results.js +848 -0
  39. package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/update-feature-status.js +226 -0
  40. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/SKILL.md +264 -0
  41. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/examples/features.json +34 -0
  42. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/generate-inventory.js +867 -0
  43. package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/test-inventory.js +26 -0
  44. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/SKILL.md +165 -0
  45. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/apply-module-mapping.js +208 -0
  46. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/extract-module-summary.js +180 -0
  47. package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/reindex-modules.js +358 -0
  48. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/SKILL.md +1055 -0
  49. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-DESKTOP.md +303 -0
  50. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-ELECTRON.md +327 -0
  51. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-MINIAPP.md +292 -0
  52. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-MOBILE.md +281 -0
  53. package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI.md +324 -0
  54. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/SKILL.md +270 -0
  55. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/COMPONENT-PATTERN-TEMPLATE.md +33 -0
  56. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/LAYOUT-PATTERN-TEMPLATE.md +33 -0
  57. package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/PAGE-TYPE-TEMPLATE.md +33 -0
  58. package/.speccrew/skills/speccrew-knowledge-graph-query/SKILL.md +229 -0
  59. package/.speccrew/skills/speccrew-knowledge-graph-query/scripts/graph-query.js +549 -0
  60. package/.speccrew/skills/speccrew-knowledge-graph-write/SKILL.md +181 -0
  61. package/.speccrew/skills/speccrew-knowledge-graph-write/scripts/graph-write.js +651 -0
  62. package/.speccrew/skills/speccrew-knowledge-module-summarize/SKILL.md +305 -0
  63. package/.speccrew/skills/speccrew-knowledge-module-summarize/templates/MODULE-OVERVIEW-TEMPLATE.md +400 -0
  64. package/.speccrew/skills/speccrew-knowledge-system-summarize/SKILL.md +351 -0
  65. package/.speccrew/skills/speccrew-knowledge-system-summarize/templates/SYSTEM-OVERVIEW-TEMPLATE.md +294 -0
  66. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/SKILL.md +683 -0
  67. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/STATUS-FORMATS.md +550 -0
  68. package/.speccrew/skills/speccrew-knowledge-techs-dispatch/templates/techs-manifest-EXAMPLE.json +35 -0
  69. package/.speccrew/skills/speccrew-knowledge-techs-generate/SKILL.md +1087 -0
  70. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/ARCHITECTURE-TEMPLATE.md +240 -0
  71. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/COLOR-SYSTEM-TEMPLATE.md +68 -0
  72. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/COMPONENT-LIBRARY-TEMPLATE.md +86 -0
  73. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-BUILD-TEMPLATE.md +466 -0
  74. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DATA-TEMPLATE.md +432 -0
  75. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DESIGN-TEMPLATE.md +1209 -0
  76. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DEV-TEMPLATE.md +1433 -0
  77. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-SYSTEM-TEST-TEMPLATE.md +1052 -0
  78. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-UNIT-TEST-TEMPLATE.md +946 -0
  79. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/INDEX-TEMPLATE.md +29 -0
  80. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/PAGE-LAYOUTS-TEMPLATE.md +69 -0
  81. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/PAGE-TYPE-SUMMARY-TEMPLATE.md +74 -0
  82. package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/TECH-STACK-TEMPLATE.md +232 -0
  83. package/.speccrew/skills/speccrew-knowledge-techs-generate-conventions/SKILL.md +628 -0
  84. package/.speccrew/skills/speccrew-knowledge-techs-generate-ui-style/SKILL.md +392 -0
  85. package/.speccrew/skills/speccrew-knowledge-techs-index/SKILL.md +489 -0
  86. package/.speccrew/skills/speccrew-knowledge-techs-index/templates/INDEX-TEMPLATE.md +243 -0
  87. package/.speccrew/skills/speccrew-knowledge-techs-init/SKILL.md +269 -0
  88. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/SKILL.md +562 -0
  89. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/BUSINESS-COMPONENTS-TEMPLATE.md +171 -0
  90. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMMON-COMPONENTS-TEMPLATE.md +177 -0
  91. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMPONENT-INDIVIDUAL-TEMPLATE.md +80 -0
  92. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMPONENT-LIBRARY-TEMPLATE.md +118 -0
  93. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/LAYOUT-INDIVIDUAL-TEMPLATE.md +97 -0
  94. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/LAYOUT-PATTERNS-TEMPLATE.md +208 -0
  95. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/NAVIGATION-PATTERNS-TEMPLATE.md +157 -0
  96. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/PAGE-TYPE-INDIVIDUAL-TEMPLATE.md +123 -0
  97. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/PAGE-TYPE-SUMMARY-TEMPLATE.md +58 -0
  98. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/SPACING-TEMPLATE.md +119 -0
  99. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/STYLE-SYSTEM-TEMPLATE.md +117 -0
  100. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/TYPOGRAPHY-TEMPLATE.md +107 -0
  101. package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/UI-STYLE-GUIDE-TEMPLATE.md +171 -0
  102. package/.speccrew/skills/speccrew-pm-requirement-analysis/SKILL.md +434 -0
  103. package/.speccrew/skills/speccrew-pm-requirement-analysis/templates/BIZS-MODELING-TEMPLATE.md +332 -0
  104. package/.speccrew/skills/speccrew-pm-requirement-analysis/templates/PRD-TEMPLATE.md +200 -0
  105. package/.speccrew/skills/speccrew-pm-requirement-assess/SKILL.md +195 -0
  106. package/.speccrew/skills/speccrew-project-diagnosis/SKILL.md +208 -0
  107. package/.speccrew/skills/speccrew-project-diagnosis/templates/DIAGNOSIS-REPORT-TEMPLATE.md +202 -0
  108. package/.speccrew/skills/speccrew-sd-backend/SKILL.md +188 -0
  109. package/.speccrew/skills/speccrew-sd-backend/templates/INDEX-TEMPLATE.md +85 -0
  110. package/.speccrew/skills/speccrew-sd-backend/templates/SD-BACKEND-TEMPLATE.md +269 -0
  111. package/.speccrew/skills/speccrew-sd-desktop/SKILL.md +192 -0
  112. package/.speccrew/skills/speccrew-sd-desktop/templates/INDEX-TEMPLATE.md +271 -0
  113. package/.speccrew/skills/speccrew-sd-desktop/templates/SD-DESKTOP-TEMPLATE.md +673 -0
  114. package/.speccrew/skills/speccrew-sd-frontend/SKILL.md +176 -0
  115. package/.speccrew/skills/speccrew-sd-frontend/templates/INDEX-TEMPLATE.md +184 -0
  116. package/.speccrew/skills/speccrew-sd-frontend/templates/SD-FRONTEND-TEMPLATE.md +382 -0
  117. package/.speccrew/skills/speccrew-sd-mobile/SKILL.md +189 -0
  118. package/.speccrew/skills/speccrew-sd-mobile/templates/INDEX-TEMPLATE.md +219 -0
  119. package/.speccrew/skills/speccrew-sd-mobile/templates/SD-MOBILE-TEMPLATE.md +534 -0
  120. package/.speccrew/skills/speccrew-test-case-design/SKILL.md +284 -0
  121. package/.speccrew/skills/speccrew-test-case-design/templates/TEST-CASE-DESIGN-TEMPLATE.md +263 -0
  122. package/.speccrew/skills/speccrew-test-code-gen/SKILL.md +313 -0
  123. package/.speccrew/skills/speccrew-test-code-gen/templates/TEST-CODE-PLAN-TEMPLATE.md +180 -0
  124. package/.speccrew/skills/speccrew-test-execute/SKILL.md +283 -0
  125. package/.speccrew/skills/speccrew-test-execute/templates/BUG-REPORT-TEMPLATE.md +50 -0
  126. package/.speccrew/skills/speccrew-test-execute/templates/TEST-REPORT-TEMPLATE.md +57 -0
  127. package/.speccrew/skills/speccrew-workflow-diagnose/SKILL.md +155 -0
  128. package/LICENSE +21 -0
  129. package/README.ar.md +318 -0
  130. package/README.en.md +318 -0
  131. package/README.es.md +318 -0
  132. package/README.md +340 -0
  133. package/bin/cli.js +62 -0
  134. package/lib/commands/doctor.js +138 -0
  135. package/lib/commands/init.js +231 -0
  136. package/lib/commands/list.js +114 -0
  137. package/lib/commands/uninstall.js +117 -0
  138. package/lib/commands/update.js +351 -0
  139. package/lib/ide-adapters.js +73 -0
  140. package/lib/utils.js +104 -0
  141. package/package.json +28 -0
  142. package/workspace-template/docs/configs/document-templates.json +667 -0
  143. package/workspace-template/docs/configs/platform-mapping.json +194 -0
  144. package/workspace-template/docs/configs/tech-stack-mappings.json +313 -0
  145. package/workspace-template/docs/configs/validation-rules.json +87 -0
  146. package/workspace-template/docs/rules/mermaid-rule.md +114 -0
  147. package/workspace-template/docs/solutions/Agent/346/212/200/350/203/275/345/256/232/344/271/211+/351/234/200/346/261/202/346/226/207/346/241/243+UML/344/275/277/347/224/250/346/250/241/346/235/277/357/274/210ISA-95/345/205/255/346/256/265/345/274/217/350/236/215/345/220/210/347/211/210/357/274/211.md +586 -0
  148. package/workspace-template/docs/solutions/agent-knowledge-map.md +238 -0
  149. package/workspace-template/docs/solutions/bizs-knowledge-pipeline.md +678 -0
  150. package/workspace-template/docs/solutions/harness.md +410 -0
  151. package/workspace-template/docs/solutions/knowledge-incremental-sync-spec.md +943 -0
  152. package/workspace-template/docs/solutions/techs-knowledge-pipeline.md +803 -0
  153. package/workspace-template/docs/solutions/workspace-structure.md +318 -0
package/bin/cli.js ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require('path');
4
+ const command = process.argv[2];
5
+ const args = process.argv.slice(3);
6
+ const projectRoot = process.cwd();
7
+
8
+ function printUsage() {
9
+ console.log(`
10
+ SpecCrew - Spec-Driven Development toolkit for AI-powered IDEs
11
+
12
+ Usage: speccrew <command> [options]
13
+
14
+ Commands:
15
+ init Initialize SpecCrew in the current project
16
+ update Update SpecCrew agents and skills
17
+ doctor Check environment and installation health
18
+ uninstall Remove SpecCrew from the current project
19
+ list List installed agents and skills
20
+
21
+ Options:
22
+ --help Show help
23
+ --version Show version
24
+
25
+ Examples:
26
+ speccrew init --ide qoder
27
+ speccrew update
28
+ speccrew doctor
29
+ `);
30
+ }
31
+
32
+ switch (command) {
33
+ case 'init':
34
+ require('../lib/commands/init').run();
35
+ break;
36
+ case 'update':
37
+ require('../lib/commands/update').run();
38
+ break;
39
+ case 'doctor':
40
+ require('../lib/commands/doctor').run(projectRoot, args);
41
+ break;
42
+ case 'uninstall':
43
+ require('../lib/commands/uninstall').run(projectRoot, args);
44
+ break;
45
+ case 'list':
46
+ require('../lib/commands/list').run(projectRoot, args);
47
+ break;
48
+ case '--version':
49
+ case '-v':
50
+ const pkg = require('../package.json');
51
+ console.log(pkg.version);
52
+ break;
53
+ case '--help':
54
+ case '-h':
55
+ case undefined:
56
+ printUsage();
57
+ break;
58
+ default:
59
+ console.error(`Unknown command: ${command}`);
60
+ printUsage();
61
+ process.exit(1);
62
+ }
@@ -0,0 +1,138 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { readSpeccrewRC, getPackageVersion, getSourceRoot, isSpeccrewFile } = require('../utils');
4
+ const { detectIDE, IDE_CONFIGS } = require('../ide-adapters');
5
+
6
+ function run(projectRoot, args) {
7
+ console.log('SpecCrew Doctor\n');
8
+
9
+ const results = [];
10
+
11
+ // 1. Node.js 版本检查
12
+ const nodeVersion = process.version;
13
+ const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0], 10);
14
+ if (majorVersion >= 16) {
15
+ results.push({ status: 'PASS', message: `Node.js ${nodeVersion} (>= 16.0.0)` });
16
+ } else {
17
+ results.push({ status: 'FAIL', message: `Node.js ${nodeVersion} (< 16.0.0)` });
18
+ }
19
+
20
+ // 2. SpecCrew 安装状态
21
+ const rc = readSpeccrewRC(projectRoot);
22
+ const version = getPackageVersion();
23
+ if (rc) {
24
+ results.push({ status: 'PASS', message: `SpecCrew v${version} installed` });
25
+ } else {
26
+ results.push({ status: 'WARN', message: 'Not initialized, run speccrew init' });
27
+ }
28
+
29
+ // 3. IDE 目录检查
30
+ const detectedIDEs = detectIDE(projectRoot);
31
+ if (detectedIDEs.length > 0) {
32
+ const ideNames = detectedIDEs.map(ide => `${ide.name} (${ide.baseDir}/)`).join(', ');
33
+ results.push({ status: 'PASS', message: `IDE: ${ideNames}` });
34
+ } else {
35
+ results.push({ status: 'WARN', message: 'No supported IDE detected' });
36
+ }
37
+
38
+ // 4. Agents 完整性检查
39
+ const sourceRoot = getSourceRoot();
40
+ const sourceAgentsDir = path.join(sourceRoot, 'agents');
41
+ let sourceAgentCount = 0;
42
+ let installedAgentCount = 0;
43
+ let missingAgents = [];
44
+
45
+ if (fs.existsSync(sourceAgentsDir)) {
46
+ const sourceAgents = fs.readdirSync(sourceAgentsDir).filter(isSpeccrewFile);
47
+ sourceAgentCount = sourceAgents.length;
48
+
49
+ for (const ide of detectedIDEs) {
50
+ const agentsDir = path.join(projectRoot, ide.agentsDir);
51
+ if (fs.existsSync(agentsDir)) {
52
+ const installed = fs.readdirSync(agentsDir).filter(isSpeccrewFile);
53
+ installedAgentCount = installed.length;
54
+
55
+ for (const agent of sourceAgents) {
56
+ const agentName = agent.replace(/\.md$/, '');
57
+ if (!installed.includes(agent)) {
58
+ missingAgents.push(agentName);
59
+ }
60
+ }
61
+ }
62
+ }
63
+ }
64
+
65
+ if (missingAgents.length === 0 && sourceAgentCount > 0) {
66
+ results.push({ status: 'PASS', message: `Agents: ${installedAgentCount}/${sourceAgentCount} installed` });
67
+ } else if (sourceAgentCount > 0) {
68
+ results.push({ status: 'WARN', message: `Agents: ${installedAgentCount}/${sourceAgentCount} installed (missing: ${missingAgents.join(', ')})` });
69
+ } else {
70
+ results.push({ status: 'WARN', message: 'Agents: source not found' });
71
+ }
72
+
73
+ // 5. Skills 完整性检查
74
+ const sourceSkillsDir = path.join(sourceRoot, 'skills');
75
+ let sourceSkillCount = 0;
76
+ let installedSkillCount = 0;
77
+ let missingSkills = [];
78
+
79
+ if (fs.existsSync(sourceSkillsDir)) {
80
+ const sourceSkills = fs.readdirSync(sourceSkillsDir).filter(isSpeccrewFile);
81
+ sourceSkillCount = sourceSkills.length;
82
+
83
+ for (const ide of detectedIDEs) {
84
+ const skillsDir = path.join(projectRoot, ide.skillsDir);
85
+ if (fs.existsSync(skillsDir)) {
86
+ const installed = fs.readdirSync(skillsDir).filter(isSpeccrewFile);
87
+ installedSkillCount = Math.max(installedSkillCount, installed.length);
88
+
89
+ for (const skill of sourceSkills) {
90
+ if (!installed.includes(skill)) {
91
+ missingSkills.push(skill);
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+
98
+ if (missingSkills.length === 0 && sourceSkillCount > 0) {
99
+ results.push({ status: 'PASS', message: `Skills: ${installedSkillCount}/${sourceSkillCount} installed` });
100
+ } else if (sourceSkillCount > 0) {
101
+ results.push({ status: 'WARN', message: `Skills: ${installedSkillCount}/${sourceSkillCount} installed (missing: ${missingSkills.join(', ')})` });
102
+ } else {
103
+ results.push({ status: 'WARN', message: 'Skills: source not found' });
104
+ }
105
+
106
+ // 6. Workspace 目录检查
107
+ const workspaceDir = path.join(projectRoot, 'speccrew-workspace');
108
+ const docsDir = path.join(workspaceDir, 'docs');
109
+ if (fs.existsSync(workspaceDir) && fs.existsSync(docsDir)) {
110
+ results.push({ status: 'PASS', message: 'Workspace: speccrew-workspace/ OK' });
111
+ } else if (fs.existsSync(workspaceDir)) {
112
+ results.push({ status: 'WARN', message: 'Workspace: speccrew-workspace/ exists but docs/ missing' });
113
+ } else {
114
+ results.push({ status: 'WARN', message: 'Workspace: speccrew-workspace/ not found' });
115
+ }
116
+
117
+ // 输出结果
118
+ let passCount = 0;
119
+ let warnCount = 0;
120
+ let failCount = 0;
121
+
122
+ for (const result of results) {
123
+ const icon = result.status === 'PASS' ? 'PASS' : result.status === 'WARN' ? 'WARN' : 'FAIL';
124
+ const padding = ' ';
125
+ console.log(`${padding}${icon} ${result.message}`);
126
+
127
+ if (result.status === 'PASS') passCount++;
128
+ else if (result.status === 'WARN') warnCount++;
129
+ else failCount++;
130
+ }
131
+
132
+ console.log('');
133
+ console.log(`${passCount} passed, ${warnCount} warning${warnCount !== 1 ? 's' : ''}, ${failCount} error${failCount !== 1 ? 's' : ''}`);
134
+
135
+ return failCount === 0;
136
+ }
137
+
138
+ module.exports = { run };
@@ -0,0 +1,231 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const {
4
+ copyDirRecursive,
5
+ isSpeccrewFile,
6
+ writeSpeccrewRC,
7
+ getPackageVersion,
8
+ getSourceRoot,
9
+ getWorkspaceTemplatePath,
10
+ ensureDirectories,
11
+ } = require('../utils');
12
+ const { resolveIDE } = require('../ide-adapters');
13
+
14
+ // 解析命令行参数
15
+ function parseArgs() {
16
+ const args = process.argv.slice(2);
17
+ let ide = null;
18
+
19
+ for (let i = 0; i < args.length; i++) {
20
+ if (args[i] === '--ide' && i + 1 < args.length) {
21
+ ide = args[i + 1];
22
+ break;
23
+ }
24
+ }
25
+
26
+ return { ide };
27
+ }
28
+
29
+ // 检查 Node.js 版本 >= 16
30
+ function checkNodeVersion() {
31
+ const version = process.version;
32
+ const major = parseInt(version.slice(1).split('.')[0], 10);
33
+ if (major < 16) {
34
+ throw new Error(`Node.js version ${version} is not supported. Please upgrade to Node.js 16 or higher.`);
35
+ }
36
+ }
37
+
38
+ // 复制 agents(speccrew-* 前缀文件,总是覆盖)
39
+ function copyAgents(sourceDir, destDir) {
40
+ if (!fs.existsSync(sourceDir)) return { copied: 0, skipped: 0 };
41
+
42
+ fs.mkdirSync(destDir, { recursive: true });
43
+ let copied = 0, skipped = 0;
44
+
45
+ const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
46
+ for (const entry of entries) {
47
+ if (!isSpeccrewFile(entry.name)) {
48
+ skipped++;
49
+ continue;
50
+ }
51
+
52
+ const srcPath = path.join(sourceDir, entry.name);
53
+ const destPath = path.join(destDir, entry.name);
54
+
55
+ fs.copyFileSync(srcPath, destPath);
56
+ copied++;
57
+ }
58
+
59
+ return { copied, skipped };
60
+ }
61
+
62
+ // 复制 skills(speccrew-* 前缀目录,递归复制,总是覆盖)
63
+ function copySkills(sourceDir, destDir) {
64
+ if (!fs.existsSync(sourceDir)) return { copied: 0, skipped: 0 };
65
+
66
+ let copied = 0, skipped = 0;
67
+
68
+ const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
69
+ for (const entry of entries) {
70
+ if (!isSpeccrewFile(entry.name)) {
71
+ skipped++;
72
+ continue;
73
+ }
74
+
75
+ const srcPath = path.join(sourceDir, entry.name);
76
+ const destPath = path.join(destDir, entry.name);
77
+
78
+ if (entry.isDirectory()) {
79
+ const result = copyDirRecursive(srcPath, destPath);
80
+ copied += result.copied;
81
+ skipped += result.skipped;
82
+ } else {
83
+ fs.copyFileSync(srcPath, destPath);
84
+ copied++;
85
+ }
86
+ }
87
+
88
+ return { copied, skipped };
89
+ }
90
+
91
+ // 创建 workspace 目录结构
92
+ function createWorkspaceStructure(workspaceDir) {
93
+ const dirs = [
94
+ 'iterations',
95
+ 'iteration-archives',
96
+ 'knowledges/base/diagnosis-reports',
97
+ 'knowledges/base/sync-state',
98
+ 'knowledges/base/tech-debts',
99
+ 'knowledges/bizs',
100
+ 'knowledges/techs',
101
+ 'docs/configs',
102
+ 'docs/rules',
103
+ 'docs/solutions',
104
+ 'docs/templates',
105
+ ];
106
+
107
+ ensureDirectories(workspaceDir, dirs);
108
+ }
109
+
110
+ // 复制 workspace 模板(仅复制不存在的文件)
111
+ function copyWorkspaceTemplate(templateDir, workspaceDir) {
112
+ if (!fs.existsSync(templateDir)) return { copied: 0, skipped: 0 };
113
+
114
+ const docsSourceDir = path.join(templateDir, 'docs');
115
+ const docsDestDir = path.join(workspaceDir, 'docs');
116
+
117
+ if (!fs.existsSync(docsSourceDir)) return { copied: 0, skipped: 0 };
118
+
119
+ fs.mkdirSync(docsDestDir, { recursive: true });
120
+ let copied = 0, skipped = 0;
121
+
122
+ function copyIfNotExists(src, dest) {
123
+ const entries = fs.readdirSync(src, { withFileTypes: true });
124
+ for (const entry of entries) {
125
+ const srcPath = path.join(src, entry.name);
126
+ const destPath = path.join(dest, entry.name);
127
+
128
+ if (entry.isDirectory()) {
129
+ fs.mkdirSync(destPath, { recursive: true });
130
+ copyIfNotExists(srcPath, destPath);
131
+ } else {
132
+ if (!fs.existsSync(destPath)) {
133
+ fs.copyFileSync(srcPath, destPath);
134
+ copied++;
135
+ } else {
136
+ skipped++;
137
+ }
138
+ }
139
+ }
140
+ }
141
+
142
+ copyIfNotExists(docsSourceDir, docsDestDir);
143
+ return { copied, skipped };
144
+ }
145
+
146
+ // 主函数
147
+ function run() {
148
+ try {
149
+ // 1. 解析参数
150
+ const { ide: cliIdeArg } = parseArgs();
151
+
152
+ // 2. 确定项目根目录
153
+ const projectRoot = process.cwd();
154
+
155
+ // 3. 检查 Node.js 版本
156
+ checkNodeVersion();
157
+
158
+ // 4. 解析 IDE
159
+ const ideConfigs = resolveIDE(projectRoot, cliIdeArg);
160
+
161
+ // 5. 确定源文件路径
162
+ const sourceRoot = getSourceRoot();
163
+
164
+ // 统计信息
165
+ const stats = {
166
+ ides: [],
167
+ totalAgents: 0,
168
+ totalSkills: 0,
169
+ workspaceCreated: false,
170
+ };
171
+
172
+ // 6. 对每个检测到的 IDE 复制 agents 和 skills
173
+ for (const ideConfig of ideConfigs) {
174
+ const agentsSourceDir = path.join(sourceRoot, 'agents');
175
+ const skillsSourceDir = path.join(sourceRoot, 'skills');
176
+ const agentsDestDir = path.join(projectRoot, ideConfig.agentsDir);
177
+ const skillsDestDir = path.join(projectRoot, ideConfig.skillsDir);
178
+
179
+ const agentsResult = copyAgents(agentsSourceDir, agentsDestDir);
180
+ const skillsResult = copySkills(skillsSourceDir, skillsDestDir);
181
+
182
+ stats.ides.push({
183
+ name: ideConfig.name,
184
+ baseDir: ideConfig.baseDir,
185
+ agents: agentsResult.copied,
186
+ skills: skillsResult.copied,
187
+ });
188
+ stats.totalAgents += agentsResult.copied;
189
+ stats.totalSkills += skillsResult.copied;
190
+ }
191
+
192
+ // 7. 创建 speccrew-workspace 目录结构
193
+ const workspaceDir = path.join(projectRoot, 'speccrew-workspace');
194
+ createWorkspaceStructure(workspaceDir);
195
+ stats.workspaceCreated = true;
196
+
197
+ // 8. 复制 workspace 模板
198
+ const templateDir = getWorkspaceTemplatePath();
199
+ copyWorkspaceTemplate(templateDir, workspaceDir);
200
+
201
+ // 9. 写入 .speccrewrc
202
+ const version = getPackageVersion();
203
+ const rcConfig = {
204
+ ide: ideConfigs.length === 1 ? ideConfigs[0].id : ideConfigs.map(c => c.id),
205
+ version: version,
206
+ installedAt: new Date().toISOString(),
207
+ };
208
+ writeSpeccrewRC(projectRoot, rcConfig);
209
+
210
+ // 10. 输出安装摘要
211
+ console.log(`SpecCrew v${version} installed successfully!\n`);
212
+
213
+ for (const ide of stats.ides) {
214
+ console.log(`IDE: ${ide.name} (${ide.baseDir}/)`);
215
+ console.log(`Agents: ${ide.agents} installed`);
216
+ console.log(`Skills: ${ide.skills} installed`);
217
+ }
218
+
219
+ if (stats.workspaceCreated) {
220
+ console.log('Workspace: speccrew-workspace/ created');
221
+ }
222
+
223
+ console.log('\nGet started: Ask your AI agent to help with your project!');
224
+
225
+ } catch (error) {
226
+ console.error(`Error: ${error.message}`);
227
+ process.exit(1);
228
+ }
229
+ }
230
+
231
+ module.exports = { run };
@@ -0,0 +1,114 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { readSpeccrewRC, getPackageVersion, isSpeccrewFile } = require('../utils');
4
+
5
+ function run(projectRoot, args) {
6
+ // 检查是否已初始化
7
+ const rc = readSpeccrewRC(projectRoot);
8
+ if (!rc) {
9
+ console.log('SpecCrew is not initialized in this project.');
10
+ console.log('Run "speccrew init" to initialize.');
11
+ return false;
12
+ }
13
+
14
+ const version = getPackageVersion();
15
+ const ides = rc.ide ? (Array.isArray(rc.ide) ? rc.ide : [rc.ide]) : [];
16
+ const ideNames = ides.map(id => {
17
+ const names = { qoder: 'Qoder', cursor: 'Cursor' };
18
+ return names[id] || id;
19
+ });
20
+ const ideDisplay = ideNames.length > 0 ? ideNames.join(', ') : 'Unknown';
21
+ const ideDirs = ides.map(id => {
22
+ const dirs = { qoder: '.qoder/', cursor: '.cursor/' };
23
+ return dirs[id] || `.${id}/`;
24
+ });
25
+
26
+ console.log(`SpecCrew v${version} | IDE: ${ideDisplay} (${ideDirs.join(', ')})\n`);
27
+
28
+ // 收集所有 agents 和 skills
29
+ const speccrewAgents = new Set();
30
+ const speccrewSkills = new Set();
31
+ const userAgents = new Set();
32
+ const userSkills = new Set();
33
+
34
+ for (const ideId of ides) {
35
+ const ideConfig = getIDEConfig(ideId);
36
+ if (!ideConfig) continue;
37
+
38
+ // 扫描 agents
39
+ const agentsDir = path.join(projectRoot, ideConfig.agentsDir);
40
+ if (fs.existsSync(agentsDir)) {
41
+ const entries = fs.readdirSync(agentsDir, { withFileTypes: true });
42
+ for (const entry of entries) {
43
+ const name = entry.name;
44
+ if (isSpeccrewFile(name)) {
45
+ speccrewAgents.add(name.replace(/\.md$/, ''));
46
+ } else if (!name.startsWith('.') && entry.isDirectory()) {
47
+ userAgents.add(`${ideConfig.agentsDir}/${name}`);
48
+ }
49
+ }
50
+ }
51
+
52
+ // 扫描 skills
53
+ const skillsDir = path.join(projectRoot, ideConfig.skillsDir);
54
+ if (fs.existsSync(skillsDir)) {
55
+ const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
56
+ for (const entry of entries) {
57
+ const name = entry.name;
58
+ if (isSpeccrewFile(name)) {
59
+ speccrewSkills.add(name);
60
+ } else if (!name.startsWith('.') && entry.isDirectory()) {
61
+ userSkills.add(`${ideConfig.skillsDir}/${name}`);
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ // 输出 Agents
68
+ const sortedAgents = Array.from(speccrewAgents).sort();
69
+ console.log(`Agents (${sortedAgents.length}):`);
70
+ for (const agent of sortedAgents) {
71
+ console.log(` ${agent}`);
72
+ }
73
+ console.log('');
74
+
75
+ // 输出 Skills
76
+ const sortedSkills = Array.from(speccrewSkills).sort();
77
+ console.log(`Skills (${sortedSkills.length}):`);
78
+ for (const skill of sortedSkills) {
79
+ console.log(` ${skill}`);
80
+ }
81
+ console.log('');
82
+
83
+ // 输出用户自定义内容
84
+ const allUserDefined = [...Array.from(userAgents), ...Array.from(userSkills)].sort();
85
+ if (allUserDefined.length > 0) {
86
+ console.log('User-defined:');
87
+ for (const item of allUserDefined) {
88
+ console.log(` ${item}`);
89
+ }
90
+ }
91
+
92
+ return true;
93
+ }
94
+
95
+ // 获取 IDE 配置(简化版,避免循环依赖)
96
+ function getIDEConfig(ideId) {
97
+ const configs = {
98
+ qoder: {
99
+ name: 'Qoder',
100
+ baseDir: '.qoder',
101
+ skillsDir: '.qoder/skills',
102
+ agentsDir: '.qoder/agents',
103
+ },
104
+ cursor: {
105
+ name: 'Cursor',
106
+ baseDir: '.cursor',
107
+ skillsDir: '.cursor/skills',
108
+ agentsDir: '.cursor/agents',
109
+ },
110
+ };
111
+ return configs[ideId] || null;
112
+ }
113
+
114
+ module.exports = { run };
@@ -0,0 +1,117 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { readSpeccrewRC, isSpeccrewFile, removeDirRecursive } = require('../utils');
4
+
5
+ function run(projectRoot, args) {
6
+ // 检查是否已初始化
7
+ const rc = readSpeccrewRC(projectRoot);
8
+ if (!rc) {
9
+ console.log('SpecCrew is not initialized in this project.');
10
+ console.log('Run "speccrew init" to initialize.');
11
+ return false;
12
+ }
13
+
14
+ console.log('SpecCrew Uninstall\n');
15
+
16
+ const isAll = args.includes('--all');
17
+ let removedAgents = 0;
18
+ let removedSkills = 0;
19
+ const removedItems = [];
20
+
21
+ // 获取 IDE 配置
22
+ const ides = rc.ide ? (Array.isArray(rc.ide) ? rc.ide : [rc.ide]) : [];
23
+
24
+ // 删除每个 IDE 目录下的 speccrew-* agents 和 skills
25
+ for (const ideId of ides) {
26
+ const ideConfig = getIDEConfig(ideId);
27
+ if (!ideConfig) continue;
28
+
29
+ // 删除 agents
30
+ const agentsDir = path.join(projectRoot, ideConfig.agentsDir);
31
+ if (fs.existsSync(agentsDir)) {
32
+ const entries = fs.readdirSync(agentsDir, { withFileTypes: true });
33
+ for (const entry of entries) {
34
+ if (isSpeccrewFile(entry.name)) {
35
+ const fullPath = path.join(agentsDir, entry.name);
36
+ if (entry.isDirectory()) {
37
+ removeDirRecursive(fullPath);
38
+ } else {
39
+ fs.unlinkSync(fullPath);
40
+ }
41
+ removedAgents++;
42
+ removedItems.push(`${ideConfig.baseDir}/agents/${entry.name}`);
43
+ }
44
+ }
45
+ }
46
+
47
+ // 删除 skills
48
+ const skillsDir = path.join(projectRoot, ideConfig.skillsDir);
49
+ if (fs.existsSync(skillsDir)) {
50
+ const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
51
+ for (const entry of entries) {
52
+ if (isSpeccrewFile(entry.name)) {
53
+ const fullPath = path.join(skillsDir, entry.name);
54
+ if (entry.isDirectory()) {
55
+ removeDirRecursive(fullPath);
56
+ } else {
57
+ fs.unlinkSync(fullPath);
58
+ }
59
+ removedSkills++;
60
+ removedItems.push(`${ideConfig.baseDir}/skills/${entry.name}`);
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ // 如果 --all,删除 workspace
67
+ let workspaceRemoved = false;
68
+ if (isAll) {
69
+ const workspaceDir = path.join(projectRoot, 'speccrew-workspace');
70
+ if (fs.existsSync(workspaceDir)) {
71
+ removeDirRecursive(workspaceDir);
72
+ workspaceRemoved = true;
73
+ removedItems.push('speccrew-workspace/');
74
+ }
75
+ }
76
+
77
+ // 删除 .speccrewrc
78
+ const rcPath = path.join(projectRoot, '.speccrewrc');
79
+ if (fs.existsSync(rcPath)) {
80
+ fs.unlinkSync(rcPath);
81
+ removedItems.push('.speccrewrc');
82
+ }
83
+
84
+ // 输出摘要
85
+ console.log(`Removed ${removedAgents} agent(s) and ${removedSkills} skill(s)`);
86
+ if (workspaceRemoved) {
87
+ console.log('Removed speccrew-workspace/');
88
+ }
89
+ console.log('Removed .speccrewrc');
90
+ console.log('\nSpecCrew has been uninstalled.');
91
+ if (!isAll) {
92
+ console.log('Workspace data preserved. Use --all to remove everything.');
93
+ }
94
+
95
+ return true;
96
+ }
97
+
98
+ // 获取 IDE 配置(简化版,避免循环依赖)
99
+ function getIDEConfig(ideId) {
100
+ const configs = {
101
+ qoder: {
102
+ name: 'Qoder',
103
+ baseDir: '.qoder',
104
+ skillsDir: '.qoder/skills',
105
+ agentsDir: '.qoder/agents',
106
+ },
107
+ cursor: {
108
+ name: 'Cursor',
109
+ baseDir: '.cursor',
110
+ skillsDir: '.cursor/skills',
111
+ agentsDir: '.cursor/agents',
112
+ },
113
+ };
114
+ return configs[ideId] || null;
115
+ }
116
+
117
+ module.exports = { run };