speccrew 0.5.7 → 0.5.9
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.
|
@@ -266,6 +266,9 @@ After completing all steps, output a structured completion report for the System
|
|
|
266
266
|
| **Explicit Transaction Boundaries** | Transaction boundaries must be explicitly marked |
|
|
267
267
|
| **Exception Code Mapping** | Exception handling must map to API Contract error codes |
|
|
268
268
|
| **Follow Techs Conventions** | Naming, directory structure, patterns from techs knowledge |
|
|
269
|
+
| **FORBIDDEN: TODO/FIXME Placeholders** | Design documents MUST contain complete implementation logic. Do NOT use TODO, FIXME, HACK, or any placeholder comments. Every method, validation rule, and business logic MUST be fully specified with actual pseudocode. |
|
|
270
|
+
| **API Route Consistency** | All API routes in the design document MUST exactly match the routes defined in the API Contract document. Before writing any route, READ the API Contract and copy routes verbatim. Do NOT invent or modify routes. |
|
|
271
|
+
| **Cross-Feature Dependency Marking** | When referencing functionality from another Feature (e.g., conflict detection from F-APPT-002), MUST explicitly mark it as `[DEPENDENCY: F-XXX-NNN]` and define a degradation strategy for when that Feature is not yet implemented. |
|
|
269
272
|
|
|
270
273
|
# Mermaid Diagram Requirements
|
|
271
274
|
|
|
@@ -296,3 +299,6 @@ When generating Mermaid diagrams, follow compatibility guidelines:
|
|
|
296
299
|
- [ ] INDEX.md generated with complete module list
|
|
297
300
|
- [ ] All files written to correct paths under 03.system-design/{platform_id}/
|
|
298
301
|
- [ ] All Mermaid diagrams follow compatibility guidelines
|
|
302
|
+
- [ ] **No TODO/FIXME placeholders** — all methods have complete pseudocode implementation
|
|
303
|
+
- [ ] **API routes match API Contract exactly** — verified route-by-route
|
|
304
|
+
- [ ] **Cross-Feature dependencies explicitly marked** — all `[DEPENDENCY: F-XXX-NNN]` tags present with degradation strategy
|
|
@@ -263,6 +263,10 @@ After completing all steps, output a structured completion report for the System
|
|
|
263
263
|
| **One Module Per Function Group** | Each module design document maps to one or more related Feature Spec functions |
|
|
264
264
|
| **Status Markers Required** | Use [EXISTING], [MODIFIED], [NEW] markers for all components and store modules |
|
|
265
265
|
| **Follow Techs Conventions** | Naming, directory structure, patterns must follow techs knowledge |
|
|
266
|
+
| **FORBIDDEN: TODO/FIXME Placeholders** | Design documents MUST contain complete implementation logic. Do NOT use TODO, FIXME, HACK, or any placeholder comments. Every component, method, and interaction MUST be fully specified with actual pseudocode. |
|
|
267
|
+
| **API Route Consistency** | All API routes in the design document MUST exactly match the routes defined in the API Contract document. Before writing any route, READ the API Contract and copy routes verbatim. Do NOT invent or modify routes. |
|
|
268
|
+
| **Cross-Feature Dependency Marking** | When referencing functionality from another Feature (e.g., conflict detection from F-APPT-002), MUST explicitly mark it as `[DEPENDENCY: F-XXX-NNN]` and define a degradation strategy (e.g., hide button, show placeholder) for when that Feature is not yet implemented. |
|
|
269
|
+
| **Mermaid for All Diagrams** | ALL component trees, interaction flows, and state management diagrams MUST use Mermaid syntax (`graph TB`, `sequenceDiagram`, `flowchart`). Plain text ASCII diagrams are FORBIDDEN for these sections. |
|
|
266
270
|
|
|
267
271
|
# Checklist
|
|
268
272
|
|
|
@@ -277,3 +281,7 @@ After completing all steps, output a structured completion report for the System
|
|
|
277
281
|
- [ ] INDEX.md generated with complete module list
|
|
278
282
|
- [ ] All files written to correct paths under 03.system-design/{platform_id}/
|
|
279
283
|
- [ ] Checkpoint A passed: function extraction confirmed with user
|
|
284
|
+
- [ ] **No TODO/FIXME placeholders** — all components and methods have complete pseudocode
|
|
285
|
+
- [ ] **API routes match API Contract exactly** — verified route-by-route
|
|
286
|
+
- [ ] **Cross-Feature dependencies explicitly marked** — all `[DEPENDENCY: F-XXX-NNN]` tags present with degradation strategy
|
|
287
|
+
- [ ] **Mermaid diagrams used** — no ASCII text diagrams for flows or component trees
|
|
@@ -253,6 +253,10 @@ After completing all steps, output a structured completion report for the System
|
|
|
253
253
|
| **Follow Techs Conventions** | Naming, directory structure, patterns must follow techs knowledge |
|
|
254
254
|
| **Platform-Specific Handling** | Properly handle iOS/Android differences, permissions, and native integrations |
|
|
255
255
|
| **Offline Support** | Consider offline-first patterns where applicable |
|
|
256
|
+
| **FORBIDDEN: TODO/FIXME Placeholders** | Design documents MUST contain complete implementation logic. Do NOT use TODO, FIXME, HACK, or any placeholder comments. Every screen, component, and method MUST be fully specified with actual pseudocode. |
|
|
257
|
+
| **API Route Consistency** | All API routes in the design document MUST exactly match the routes defined in the API Contract document. Before writing any route, READ the API Contract and copy routes verbatim. Do NOT invent or modify routes. |
|
|
258
|
+
| **Cross-Feature Dependency Marking** | When referencing functionality from another Feature (e.g., conflict detection from F-APPT-002), MUST explicitly mark it as `[DEPENDENCY: F-XXX-NNN]` and define a degradation strategy (e.g., hide button, show placeholder) for when that Feature is not yet implemented. |
|
|
259
|
+
| **Mermaid for All Diagrams** | ALL screen trees, navigation flows, interaction sequences, and state diagrams MUST use Mermaid syntax (`graph TB`, `sequenceDiagram`, `flowchart`). Plain text ASCII diagrams are FORBIDDEN for these sections. |
|
|
256
260
|
|
|
257
261
|
# Checklist
|
|
258
262
|
|
|
@@ -269,4 +273,8 @@ After completing all steps, output a structured completion report for the System
|
|
|
269
273
|
- [ ] App lifecycle handling documented
|
|
270
274
|
- [ ] INDEX.md generated with complete module list
|
|
271
275
|
- [ ] All files written to correct paths under 03.system-design/{platform_id}/
|
|
272
|
-
- [ ] Checkpoint A passed
|
|
276
|
+
- [ ] **Checkpoint A passed**: function extraction confirmed with user
|
|
277
|
+
- [ ] **No TODO/FIXME placeholders** — all screens and methods have complete pseudocode
|
|
278
|
+
- [ ] **API routes match API Contract exactly** — verified route-by-route
|
|
279
|
+
- [ ] **Cross-Feature dependencies explicitly marked** — all `[DEPENDENCY: F-XXX-NNN]` tags present with degradation strategy
|
|
280
|
+
- [ ] **Mermaid diagrams used** — no ASCII text diagrams for flows or screen trees
|
package/package.json
CHANGED
|
@@ -225,7 +225,10 @@ function parseArgs() {
|
|
|
225
225
|
description: null,
|
|
226
226
|
startedAt: null,
|
|
227
227
|
completedAt: null,
|
|
228
|
-
confirmedAt: null
|
|
228
|
+
confirmedAt: null,
|
|
229
|
+
featuresDir: null,
|
|
230
|
+
platforms: null,
|
|
231
|
+
force: false
|
|
229
232
|
};
|
|
230
233
|
|
|
231
234
|
// 第一个参数是命令
|
|
@@ -314,6 +317,18 @@ function parseArgs() {
|
|
|
314
317
|
case '-Overview':
|
|
315
318
|
result.overview = true;
|
|
316
319
|
break;
|
|
320
|
+
case '--features-dir':
|
|
321
|
+
case '-Features-Dir':
|
|
322
|
+
result.featuresDir = args[++i];
|
|
323
|
+
break;
|
|
324
|
+
case '--platforms':
|
|
325
|
+
case '-Platforms':
|
|
326
|
+
result.platforms = args[++i];
|
|
327
|
+
break;
|
|
328
|
+
case '--force':
|
|
329
|
+
case '-Force':
|
|
330
|
+
result.force = true;
|
|
331
|
+
break;
|
|
317
332
|
}
|
|
318
333
|
}
|
|
319
334
|
|
|
@@ -785,6 +800,154 @@ function cmdUpdateWorkflow(args) {
|
|
|
785
800
|
}
|
|
786
801
|
}
|
|
787
802
|
|
|
803
|
+
/**
|
|
804
|
+
* 命令:init-tasks - 扫描 feature-design 目录生成任务列表
|
|
805
|
+
*/
|
|
806
|
+
function cmdInitTasks(args) {
|
|
807
|
+
// 参数验证
|
|
808
|
+
if (!args.file || !args.stage || !args.featuresDir || !args.platforms) {
|
|
809
|
+
outputError('Usage: init-tasks --file <path> --stage <stage_name> --features-dir <dir> --platforms <comma-separated> [--force]');
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
const filePath = path.resolve(args.file);
|
|
813
|
+
const featuresDir = path.resolve(args.featuresDir);
|
|
814
|
+
const platforms = args.platforms.split(',').map(p => p.trim()).filter(p => p);
|
|
815
|
+
|
|
816
|
+
// 验证 platforms 非空
|
|
817
|
+
if (platforms.length === 0) {
|
|
818
|
+
outputError('Platforms list cannot be empty');
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// 验证 features-dir 存在
|
|
822
|
+
if (!fs.existsSync(featuresDir)) {
|
|
823
|
+
outputError(`Features directory not found: ${featuresDir}`);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// 扫描 .feature-spec.md 文件
|
|
827
|
+
const featureFiles = [];
|
|
828
|
+
const files = fs.readdirSync(featuresDir);
|
|
829
|
+
for (const file of files) {
|
|
830
|
+
if (file.endsWith('.feature-spec.md')) {
|
|
831
|
+
featureFiles.push(file);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
if (featureFiles.length === 0) {
|
|
836
|
+
outputError(`No .feature-spec.md files found in: ${featuresDir}`);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// 从文件名提取 feature 信息
|
|
840
|
+
// 格式: F-{MODULE}-{NNN}-{feature-name}.feature-spec.md
|
|
841
|
+
const featurePattern = /^(F-([A-Z]+)-\d+)-(.+)\.feature-spec\.md$/;
|
|
842
|
+
const features = [];
|
|
843
|
+
|
|
844
|
+
for (const file of featureFiles) {
|
|
845
|
+
const match = file.match(featurePattern);
|
|
846
|
+
if (match) {
|
|
847
|
+
features.push({
|
|
848
|
+
feature_id: match[1], // F-APPT-001
|
|
849
|
+
module: match[2], // APPT
|
|
850
|
+
name: match[3], // 预约信息CRUD
|
|
851
|
+
file: file
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
if (features.length === 0) {
|
|
857
|
+
outputError('No valid feature files found. Expected format: F-{MODULE}-{NNN}-{feature-name}.feature-spec.md');
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
// 按 feature ID 排序
|
|
861
|
+
features.sort((a, b) => a.feature_id.localeCompare(b.feature_id));
|
|
862
|
+
|
|
863
|
+
// 检查目标文件是否已有 tasks
|
|
864
|
+
if (fs.existsSync(filePath)) {
|
|
865
|
+
const existingData = readJsonFile(filePath);
|
|
866
|
+
if (existingData.tasks && existingData.tasks.length > 0 && !args.force) {
|
|
867
|
+
outputError(`Progress file already has ${existingData.tasks.length} tasks. Use --force to overwrite.`);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// 生成任务列表
|
|
872
|
+
const tasks = [];
|
|
873
|
+
const now = getTimestamp();
|
|
874
|
+
|
|
875
|
+
// Module 排序顺序
|
|
876
|
+
const moduleOrder = ['APPT', 'BASE', 'CUST', 'EMP', 'ITEM', 'KNW', 'REPORT', 'REV', 'SERV'];
|
|
877
|
+
const getModuleIndex = (module) => {
|
|
878
|
+
const idx = moduleOrder.indexOf(module);
|
|
879
|
+
return idx === -1 ? 999 : idx;
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
// 按 module 分组
|
|
883
|
+
const featuresByModule = {};
|
|
884
|
+
for (const feature of features) {
|
|
885
|
+
if (!featuresByModule[feature.module]) {
|
|
886
|
+
featuresByModule[feature.module] = [];
|
|
887
|
+
}
|
|
888
|
+
featuresByModule[feature.module].push(feature);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// 每个 module 内按 feature ID 排序
|
|
892
|
+
for (const module of Object.keys(featuresByModule)) {
|
|
893
|
+
featuresByModule[module].sort((a, b) => a.feature_id.localeCompare(b.feature_id));
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// 按 module 顺序生成任务
|
|
897
|
+
const sortedModules = Object.keys(featuresByModule).sort((a, b) => getModuleIndex(a) - getModuleIndex(b));
|
|
898
|
+
|
|
899
|
+
for (const module of sortedModules) {
|
|
900
|
+
for (const feature of featuresByModule[module]) {
|
|
901
|
+
for (const platform of platforms) {
|
|
902
|
+
tasks.push({
|
|
903
|
+
id: `sd-${platform}-${feature.feature_id}`,
|
|
904
|
+
name: `System Design - ${platform} - ${feature.feature_id} ${feature.name}`,
|
|
905
|
+
status: 'pending',
|
|
906
|
+
platform: platform,
|
|
907
|
+
feature_id: feature.feature_id,
|
|
908
|
+
module: feature.module,
|
|
909
|
+
created_at: now
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// 创建进度文件结构
|
|
916
|
+
const progressData = {
|
|
917
|
+
stage: args.stage,
|
|
918
|
+
created_at: now,
|
|
919
|
+
updated_at: now,
|
|
920
|
+
counts: calculateCounts(tasks),
|
|
921
|
+
tasks: tasks,
|
|
922
|
+
checkpoints: {}
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
// 确保目录存在
|
|
926
|
+
const dir = path.dirname(filePath);
|
|
927
|
+
if (!fs.existsSync(dir)) {
|
|
928
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// 获取锁并写入
|
|
932
|
+
let lockPath = null;
|
|
933
|
+
try {
|
|
934
|
+
lockPath = acquireLock(filePath);
|
|
935
|
+
atomicWriteJson(filePath, progressData);
|
|
936
|
+
outputSuccess(
|
|
937
|
+
`Generated ${tasks.length} tasks from ${features.length} features × ${platforms.length} platforms`,
|
|
938
|
+
{
|
|
939
|
+
file: filePath,
|
|
940
|
+
stage: args.stage,
|
|
941
|
+
features_count: features.length,
|
|
942
|
+
platforms: platforms,
|
|
943
|
+
counts: progressData.counts
|
|
944
|
+
}
|
|
945
|
+
);
|
|
946
|
+
} finally {
|
|
947
|
+
if (lockPath) releaseLock(lockPath);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
788
951
|
// ============================================================================
|
|
789
952
|
// 主入口
|
|
790
953
|
// ============================================================================
|
|
@@ -803,6 +966,7 @@ function main() {
|
|
|
803
966
|
console.error(' update-counts Recalculate task counts');
|
|
804
967
|
console.error(' write-checkpoint Write or update a checkpoint');
|
|
805
968
|
console.error(' update-workflow Update a workflow stage status');
|
|
969
|
+
console.error(' init-tasks Generate tasks from feature-spec files');
|
|
806
970
|
console.error('');
|
|
807
971
|
console.error('Run "node update-progress.js <command> --help" for more information.');
|
|
808
972
|
process.exit(1);
|
|
@@ -829,6 +993,9 @@ function main() {
|
|
|
829
993
|
case 'update-workflow':
|
|
830
994
|
cmdUpdateWorkflow(args);
|
|
831
995
|
break;
|
|
996
|
+
case 'init-tasks':
|
|
997
|
+
cmdInitTasks(args);
|
|
998
|
+
break;
|
|
832
999
|
default:
|
|
833
1000
|
outputError(`Unknown command: ${args.command}`);
|
|
834
1001
|
}
|