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.
- package/.speccrew/agents/speccrew-feature-designer.md +142 -0
- package/.speccrew/agents/speccrew-product-manager.md +61 -0
- package/.speccrew/agents/speccrew-system-designer.md +200 -0
- package/.speccrew/agents/speccrew-system-developer.md +238 -0
- package/.speccrew/agents/speccrew-task-worker.md +80 -0
- package/.speccrew/agents/speccrew-team-leader.md +92 -0
- package/.speccrew/agents/speccrew-test-manager.md +313 -0
- package/.speccrew/skills/speccrew-create-agents/SKILL.md +98 -0
- package/.speccrew/skills/speccrew-create-agents/templates/agents/designer-agent.md +54 -0
- package/.speccrew/skills/speccrew-create-agents/templates/agents/dev-agent.md +79 -0
- package/.speccrew/skills/speccrew-create-agents/templates/agents/test-agent.md +80 -0
- package/.speccrew/skills/speccrew-dev-backend/SKILL.md +205 -0
- package/.speccrew/skills/speccrew-dev-backend/templates/TASK-RECORD-TEMPLATE.md +118 -0
- package/.speccrew/skills/speccrew-dev-desktop/SKILL.md +258 -0
- package/.speccrew/skills/speccrew-dev-desktop/templates/TASK-RECORD-TEMPLATE.md +161 -0
- package/.speccrew/skills/speccrew-dev-frontend/SKILL.md +202 -0
- package/.speccrew/skills/speccrew-dev-frontend/templates/TASK-RECORD-TEMPLATE.md +115 -0
- package/.speccrew/skills/speccrew-dev-mobile/SKILL.md +200 -0
- package/.speccrew/skills/speccrew-dev-mobile/templates/TASK-RECORD-TEMPLATE.md +125 -0
- package/.speccrew/skills/speccrew-fd-api-contract/SKILL.md +73 -0
- package/.speccrew/skills/speccrew-fd-api-contract/templates/API-CONTRACT-TEMPLATE.md +96 -0
- package/.speccrew/skills/speccrew-fd-feature-design/SKILL.md +395 -0
- package/.speccrew/skills/speccrew-fd-feature-design/templates/FEATURE-SPEC-TEMPLATE.md +387 -0
- package/.speccrew/skills/speccrew-get-timestamp/SKILL.md +80 -0
- package/.speccrew/skills/speccrew-get-timestamp/scripts/get-timestamp.js +35 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/SKILL.md +1116 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-FASTAPI.md +462 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-JAVA.md +480 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE-NET.md +464 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/FEATURE-DETAIL-TEMPLATE.md +480 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-api-analyze/templates/MODULE-OVERVIEW-TEMPLATE.md +367 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/SKILL.md +667 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/STATUS-FORMATS.md +74 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/batch-orchestrator.js +176 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/get-next-batch.js +150 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/get-pending-features.js +106 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/mark-stale.js +249 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/process-batch-results.js +848 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-dispatch/scripts/update-feature-status.js +226 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-init-features/SKILL.md +264 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-init-features/examples/features.json +34 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/generate-inventory.js +867 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-init-features/scripts/test-inventory.js +26 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/SKILL.md +165 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/apply-module-mapping.js +208 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/extract-module-summary.js +180 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-module-classify/scripts/reindex-modules.js +358 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/SKILL.md +1055 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-DESKTOP.md +303 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-ELECTRON.md +327 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-MINIAPP.md +292 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI-MOBILE.md +281 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-ui-analyze/templates/FEATURE-DETAIL-TEMPLATE-UI.md +324 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/SKILL.md +270 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/COMPONENT-PATTERN-TEMPLATE.md +33 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/LAYOUT-PATTERN-TEMPLATE.md +33 -0
- package/.speccrew/skills/speccrew-knowledge-bizs-ui-style-extract/templates/PAGE-TYPE-TEMPLATE.md +33 -0
- package/.speccrew/skills/speccrew-knowledge-graph-query/SKILL.md +229 -0
- package/.speccrew/skills/speccrew-knowledge-graph-query/scripts/graph-query.js +549 -0
- package/.speccrew/skills/speccrew-knowledge-graph-write/SKILL.md +181 -0
- package/.speccrew/skills/speccrew-knowledge-graph-write/scripts/graph-write.js +651 -0
- package/.speccrew/skills/speccrew-knowledge-module-summarize/SKILL.md +305 -0
- package/.speccrew/skills/speccrew-knowledge-module-summarize/templates/MODULE-OVERVIEW-TEMPLATE.md +400 -0
- package/.speccrew/skills/speccrew-knowledge-system-summarize/SKILL.md +351 -0
- package/.speccrew/skills/speccrew-knowledge-system-summarize/templates/SYSTEM-OVERVIEW-TEMPLATE.md +294 -0
- package/.speccrew/skills/speccrew-knowledge-techs-dispatch/SKILL.md +683 -0
- package/.speccrew/skills/speccrew-knowledge-techs-dispatch/STATUS-FORMATS.md +550 -0
- package/.speccrew/skills/speccrew-knowledge-techs-dispatch/templates/techs-manifest-EXAMPLE.json +35 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/SKILL.md +1087 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/ARCHITECTURE-TEMPLATE.md +240 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/COLOR-SYSTEM-TEMPLATE.md +68 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/COMPONENT-LIBRARY-TEMPLATE.md +86 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-BUILD-TEMPLATE.md +466 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DATA-TEMPLATE.md +432 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DESIGN-TEMPLATE.md +1209 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-DEV-TEMPLATE.md +1433 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-SYSTEM-TEST-TEMPLATE.md +1052 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/CONVENTIONS-UNIT-TEST-TEMPLATE.md +946 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/INDEX-TEMPLATE.md +29 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/PAGE-LAYOUTS-TEMPLATE.md +69 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/PAGE-TYPE-SUMMARY-TEMPLATE.md +74 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate/templates/TECH-STACK-TEMPLATE.md +232 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate-conventions/SKILL.md +628 -0
- package/.speccrew/skills/speccrew-knowledge-techs-generate-ui-style/SKILL.md +392 -0
- package/.speccrew/skills/speccrew-knowledge-techs-index/SKILL.md +489 -0
- package/.speccrew/skills/speccrew-knowledge-techs-index/templates/INDEX-TEMPLATE.md +243 -0
- package/.speccrew/skills/speccrew-knowledge-techs-init/SKILL.md +269 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/SKILL.md +562 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/BUSINESS-COMPONENTS-TEMPLATE.md +171 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMMON-COMPONENTS-TEMPLATE.md +177 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMPONENT-INDIVIDUAL-TEMPLATE.md +80 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/COMPONENT-LIBRARY-TEMPLATE.md +118 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/LAYOUT-INDIVIDUAL-TEMPLATE.md +97 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/LAYOUT-PATTERNS-TEMPLATE.md +208 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/NAVIGATION-PATTERNS-TEMPLATE.md +157 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/PAGE-TYPE-INDIVIDUAL-TEMPLATE.md +123 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/PAGE-TYPE-SUMMARY-TEMPLATE.md +58 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/SPACING-TEMPLATE.md +119 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/STYLE-SYSTEM-TEMPLATE.md +117 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/TYPOGRAPHY-TEMPLATE.md +107 -0
- package/.speccrew/skills/speccrew-knowledge-techs-ui-analyze/templates/UI-STYLE-GUIDE-TEMPLATE.md +171 -0
- package/.speccrew/skills/speccrew-pm-requirement-analysis/SKILL.md +434 -0
- package/.speccrew/skills/speccrew-pm-requirement-analysis/templates/BIZS-MODELING-TEMPLATE.md +332 -0
- package/.speccrew/skills/speccrew-pm-requirement-analysis/templates/PRD-TEMPLATE.md +200 -0
- package/.speccrew/skills/speccrew-pm-requirement-assess/SKILL.md +195 -0
- package/.speccrew/skills/speccrew-project-diagnosis/SKILL.md +208 -0
- package/.speccrew/skills/speccrew-project-diagnosis/templates/DIAGNOSIS-REPORT-TEMPLATE.md +202 -0
- package/.speccrew/skills/speccrew-sd-backend/SKILL.md +188 -0
- package/.speccrew/skills/speccrew-sd-backend/templates/INDEX-TEMPLATE.md +85 -0
- package/.speccrew/skills/speccrew-sd-backend/templates/SD-BACKEND-TEMPLATE.md +269 -0
- package/.speccrew/skills/speccrew-sd-desktop/SKILL.md +192 -0
- package/.speccrew/skills/speccrew-sd-desktop/templates/INDEX-TEMPLATE.md +271 -0
- package/.speccrew/skills/speccrew-sd-desktop/templates/SD-DESKTOP-TEMPLATE.md +673 -0
- package/.speccrew/skills/speccrew-sd-frontend/SKILL.md +176 -0
- package/.speccrew/skills/speccrew-sd-frontend/templates/INDEX-TEMPLATE.md +184 -0
- package/.speccrew/skills/speccrew-sd-frontend/templates/SD-FRONTEND-TEMPLATE.md +382 -0
- package/.speccrew/skills/speccrew-sd-mobile/SKILL.md +189 -0
- package/.speccrew/skills/speccrew-sd-mobile/templates/INDEX-TEMPLATE.md +219 -0
- package/.speccrew/skills/speccrew-sd-mobile/templates/SD-MOBILE-TEMPLATE.md +534 -0
- package/.speccrew/skills/speccrew-test-case-design/SKILL.md +284 -0
- package/.speccrew/skills/speccrew-test-case-design/templates/TEST-CASE-DESIGN-TEMPLATE.md +263 -0
- package/.speccrew/skills/speccrew-test-code-gen/SKILL.md +313 -0
- package/.speccrew/skills/speccrew-test-code-gen/templates/TEST-CODE-PLAN-TEMPLATE.md +180 -0
- package/.speccrew/skills/speccrew-test-execute/SKILL.md +283 -0
- package/.speccrew/skills/speccrew-test-execute/templates/BUG-REPORT-TEMPLATE.md +50 -0
- package/.speccrew/skills/speccrew-test-execute/templates/TEST-REPORT-TEMPLATE.md +57 -0
- package/.speccrew/skills/speccrew-workflow-diagnose/SKILL.md +155 -0
- package/LICENSE +21 -0
- package/README.ar.md +318 -0
- package/README.en.md +318 -0
- package/README.es.md +318 -0
- package/README.md +340 -0
- package/bin/cli.js +62 -0
- package/lib/commands/doctor.js +138 -0
- package/lib/commands/init.js +231 -0
- package/lib/commands/list.js +114 -0
- package/lib/commands/uninstall.js +117 -0
- package/lib/commands/update.js +351 -0
- package/lib/ide-adapters.js +73 -0
- package/lib/utils.js +104 -0
- package/package.json +28 -0
- package/workspace-template/docs/configs/document-templates.json +667 -0
- package/workspace-template/docs/configs/platform-mapping.json +194 -0
- package/workspace-template/docs/configs/tech-stack-mappings.json +313 -0
- package/workspace-template/docs/configs/validation-rules.json +87 -0
- package/workspace-template/docs/rules/mermaid-rule.md +114 -0
- 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
- package/workspace-template/docs/solutions/agent-knowledge-map.md +238 -0
- package/workspace-template/docs/solutions/bizs-knowledge-pipeline.md +678 -0
- package/workspace-template/docs/solutions/harness.md +410 -0
- package/workspace-template/docs/solutions/knowledge-incremental-sync-spec.md +943 -0
- package/workspace-template/docs/solutions/techs-knowledge-pipeline.md +803 -0
- package/workspace-template/docs/solutions/workspace-structure.md +318 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Status File Formats (Bizs Pipeline)
|
|
2
|
+
|
|
3
|
+
This document defines the status tracking formats for the bizs pipeline.
|
|
4
|
+
|
|
5
|
+
> **Note**: Stage 2 and Stage 3 status tracking is now handled directly within `features-{platform}.json` files and Worker return values. The legacy `stage2-status.json` and `stage3-status.json` files have been removed.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Feature Status Tracking (Stage 2)
|
|
10
|
+
|
|
11
|
+
Feature analysis status is tracked directly in `features-{platform}.json` files located at:
|
|
12
|
+
- `speccrew-workspace/knowledges/base/sync-state/knowledge-bizs/features-{platform}.json`
|
|
13
|
+
|
|
14
|
+
**Feature Object Schema**:
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"id": "string (unique feature identifier)",
|
|
18
|
+
"fileName": "string",
|
|
19
|
+
"sourcePath": "string",
|
|
20
|
+
"documentPath": "string",
|
|
21
|
+
"module": "string",
|
|
22
|
+
"analyzed": "boolean",
|
|
23
|
+
"status": "pending | in_progress | completed | failed",
|
|
24
|
+
"startedAt": "ISO timestamp (optional)",
|
|
25
|
+
"completedAt": "ISO timestamp (optional)",
|
|
26
|
+
"error": "string (optional, when status=failed)",
|
|
27
|
+
"analysisNotes": "string (optional, notes from analysis; may contain [WARN: document missing] if document was not generated)"
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Example Feature Entry**:
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"id": "user-index-vue",
|
|
35
|
+
"fileName": "index",
|
|
36
|
+
"sourcePath": "frontend-web/src/views/system/user/index.vue",
|
|
37
|
+
"documentPath": "speccrew-workspace/knowledges/bizs/web/system/user/index.md",
|
|
38
|
+
"module": "system",
|
|
39
|
+
"analyzed": true,
|
|
40
|
+
"status": "completed",
|
|
41
|
+
"startedAt": "2024-01-15T10:30:00Z",
|
|
42
|
+
"completedAt": "2024-01-15T10:35:00Z"
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Module Status Tracking (Stage 3)
|
|
49
|
+
|
|
50
|
+
Module summarization status is determined by aggregating feature statuses from `features-{platform}.json`:
|
|
51
|
+
|
|
52
|
+
| Module Status | Condition |
|
|
53
|
+
|---------------|-----------|
|
|
54
|
+
| `pending` | Module has features but no overview document exists |
|
|
55
|
+
| `completed` | Overview document exists at `{module}/{module}-overview.md` |
|
|
56
|
+
| `failed` | Worker explicitly reported failure |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Field Reference
|
|
61
|
+
|
|
62
|
+
| Field | Type | Description |
|
|
63
|
+
|-------|------|-------------|
|
|
64
|
+
| `features[].id` | string | Unique feature identifier (used for marker file naming) |
|
|
65
|
+
| `features[].fileName` | string | Feature file name |
|
|
66
|
+
| `features[].sourcePath` | string | Source code file path |
|
|
67
|
+
| `features[].documentPath` | string | Generated documentation path |
|
|
68
|
+
| `features[].module` | string | Module code_name |
|
|
69
|
+
| `features[].analyzed` | boolean | Whether feature has been analyzed |
|
|
70
|
+
| `features[].status` | string | `pending`, `in_progress`, `completed`, `failed` |
|
|
71
|
+
| `features[].startedAt` | string | ISO timestamp when analysis started |
|
|
72
|
+
| `features[].completedAt` | string | ISO timestamp when analysis completed |
|
|
73
|
+
| `features[].error` | string | Error message when status is `failed` |
|
|
74
|
+
| `features[].analysisNotes` | string | Analysis notes from Worker; contains `[WARN: document missing at {path}]` if document was expected but not found |
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Batch Orchestrator - Main control script for Stage 2 loop.
|
|
5
|
+
*
|
|
6
|
+
* This script simplifies the Stage 2 loop in SKILL.md by merging
|
|
7
|
+
* "get batch" and "process previous batch results" steps into a single call.
|
|
8
|
+
*
|
|
9
|
+
* Modes:
|
|
10
|
+
* 1. get-batch: Get the next batch of features to process
|
|
11
|
+
* 2. process-results: Process the previous batch results
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { execFileSync } = require('child_process');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
|
|
17
|
+
// Parse command line arguments
|
|
18
|
+
function parseArgs() {
|
|
19
|
+
const args = process.argv.slice(2);
|
|
20
|
+
const result = {
|
|
21
|
+
mode: null,
|
|
22
|
+
syncStatePath: null,
|
|
23
|
+
batchSize: 5,
|
|
24
|
+
graphRoot: null,
|
|
25
|
+
graphWriteScript: null,
|
|
26
|
+
platformId: null
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// First non-option argument is the mode
|
|
30
|
+
let modeFound = false;
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < args.length; i++) {
|
|
33
|
+
const arg = args[i];
|
|
34
|
+
|
|
35
|
+
// Skip if it's a flag
|
|
36
|
+
if (arg.startsWith('--')) {
|
|
37
|
+
switch (arg) {
|
|
38
|
+
case '--syncStatePath':
|
|
39
|
+
case '-SyncStatePath':
|
|
40
|
+
result.syncStatePath = args[++i];
|
|
41
|
+
break;
|
|
42
|
+
case '--batchSize':
|
|
43
|
+
case '-BatchSize':
|
|
44
|
+
result.batchSize = parseInt(args[++i], 10) || 5;
|
|
45
|
+
break;
|
|
46
|
+
case '--graphRoot':
|
|
47
|
+
case '-GraphRoot':
|
|
48
|
+
result.graphRoot = args[++i];
|
|
49
|
+
break;
|
|
50
|
+
case '--graphWriteScript':
|
|
51
|
+
case '-GraphWriteScript':
|
|
52
|
+
result.graphWriteScript = args[++i];
|
|
53
|
+
break;
|
|
54
|
+
case '--platformId':
|
|
55
|
+
case '-PlatformId':
|
|
56
|
+
result.platformId = args[++i];
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
} else if (!modeFound) {
|
|
60
|
+
// First non-flag argument is the mode
|
|
61
|
+
result.mode = arg;
|
|
62
|
+
modeFound = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Get the path to a script in the same directory
|
|
70
|
+
function getScriptPath(scriptName) {
|
|
71
|
+
return path.join(__dirname, scriptName);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Mode 1: Get the next batch of features
|
|
75
|
+
function getBatch(args) {
|
|
76
|
+
if (!args.syncStatePath) {
|
|
77
|
+
throw new Error('--syncStatePath is required for get-batch mode');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const getNextBatchScript = getScriptPath('get-next-batch.js');
|
|
81
|
+
|
|
82
|
+
const commandArgs = [
|
|
83
|
+
getNextBatchScript,
|
|
84
|
+
'--syncStatePath', args.syncStatePath,
|
|
85
|
+
'--batchSize', String(args.batchSize)
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
// Execute get-next-batch.js and capture output
|
|
89
|
+
const output = execFileSync('node', commandArgs, { encoding: 'utf8' });
|
|
90
|
+
|
|
91
|
+
// Parse the output (JSON array of features)
|
|
92
|
+
const batch = JSON.parse(output);
|
|
93
|
+
|
|
94
|
+
// Determine the response based on whether there are features
|
|
95
|
+
if (batch.length === 0) {
|
|
96
|
+
return {
|
|
97
|
+
action: 'done',
|
|
98
|
+
message: 'All features have been processed'
|
|
99
|
+
};
|
|
100
|
+
} else {
|
|
101
|
+
return {
|
|
102
|
+
action: 'process',
|
|
103
|
+
batch: batch,
|
|
104
|
+
batchSize: batch.length,
|
|
105
|
+
iteration: null // Could be enhanced with state tracking
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Mode 2: Process the previous batch results
|
|
111
|
+
function processResults(args) {
|
|
112
|
+
if (!args.syncStatePath) {
|
|
113
|
+
throw new Error('--syncStatePath is required for process-results mode');
|
|
114
|
+
}
|
|
115
|
+
if (!args.graphRoot) {
|
|
116
|
+
throw new Error('--graphRoot is required for process-results mode');
|
|
117
|
+
}
|
|
118
|
+
if (!args.graphWriteScript) {
|
|
119
|
+
throw new Error('--graphWriteScript is required for process-results mode');
|
|
120
|
+
}
|
|
121
|
+
if (!args.platformId) {
|
|
122
|
+
throw new Error('--platformId is required for process-results mode');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const processBatchResultsScript = getScriptPath('process-batch-results.js');
|
|
126
|
+
|
|
127
|
+
const commandArgs = [
|
|
128
|
+
processBatchResultsScript,
|
|
129
|
+
'--syncStatePath', args.syncStatePath,
|
|
130
|
+
'--graphRoot', args.graphRoot,
|
|
131
|
+
'--graphWriteScript', args.graphWriteScript,
|
|
132
|
+
'--platformId', args.platformId
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
// Execute process-batch-results.js and capture output
|
|
136
|
+
const output = execFileSync('node', commandArgs, { encoding: 'utf8' });
|
|
137
|
+
|
|
138
|
+
// Parse and return the output (JSON result)
|
|
139
|
+
return JSON.parse(output);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function main() {
|
|
143
|
+
try {
|
|
144
|
+
const args = parseArgs();
|
|
145
|
+
|
|
146
|
+
if (!args.mode) {
|
|
147
|
+
console.error('Error: Mode is required. Use "get-batch" or "process-results"');
|
|
148
|
+
console.error('Usage:');
|
|
149
|
+
console.error(' node batch-orchestrator.js get-batch --syncStatePath <path> [--batchSize 5]');
|
|
150
|
+
console.error(' node batch-orchestrator.js process-results --syncStatePath <path> --graphRoot <path> --graphWriteScript <path> --platformId <id>');
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let result;
|
|
155
|
+
|
|
156
|
+
switch (args.mode) {
|
|
157
|
+
case 'get-batch':
|
|
158
|
+
result = getBatch(args);
|
|
159
|
+
break;
|
|
160
|
+
case 'process-results':
|
|
161
|
+
result = processResults(args);
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
throw new Error(`Unknown mode: ${args.mode}. Use "get-batch" or "process-results"`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Output result as JSON
|
|
168
|
+
console.log(JSON.stringify(result, null, 2));
|
|
169
|
+
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.error(`Error: ${error.message}`);
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
main();
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get the next batch of features to process from features-*.json files.
|
|
5
|
+
*
|
|
6
|
+
* Scans the sync-state directory for all features-*.json files and extracts
|
|
7
|
+
* features where analyzed=false or analyzed field is missing.
|
|
8
|
+
* Additionally excludes features that have a corresponding .done.json file in the
|
|
9
|
+
* completed/ directory (indicating Worker has finished but results not yet processed).
|
|
10
|
+
* Returns a JSON array limited to BatchSize items.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
|
|
16
|
+
// Parse command line arguments
|
|
17
|
+
function parseArgs() {
|
|
18
|
+
const args = process.argv.slice(2);
|
|
19
|
+
const result = {
|
|
20
|
+
syncStatePath: null,
|
|
21
|
+
batchSize: 5
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
for (let i = 0; i < args.length; i++) {
|
|
25
|
+
const arg = args[i];
|
|
26
|
+
switch (arg) {
|
|
27
|
+
case '--syncStatePath':
|
|
28
|
+
case '-SyncStatePath':
|
|
29
|
+
result.syncStatePath = args[++i];
|
|
30
|
+
break;
|
|
31
|
+
case '--batchSize':
|
|
32
|
+
case '-BatchSize':
|
|
33
|
+
result.batchSize = parseInt(args[++i], 10) || 5;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function main() {
|
|
42
|
+
try {
|
|
43
|
+
const args = parseArgs();
|
|
44
|
+
|
|
45
|
+
if (!args.syncStatePath) {
|
|
46
|
+
console.error('Error: --syncStatePath is required');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Resolve full path
|
|
51
|
+
const fullPath = path.resolve(args.syncStatePath);
|
|
52
|
+
if (!fs.existsSync(fullPath)) {
|
|
53
|
+
console.error(`SyncStatePath not found: ${args.syncStatePath}`);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Path to completed directory
|
|
58
|
+
const completedDir = path.join(fullPath, 'completed');
|
|
59
|
+
|
|
60
|
+
// Build set of completed feature fileNames (for fast lookup)
|
|
61
|
+
const completedFeatureFileNames = new Set();
|
|
62
|
+
const completedFeatureIds = new Set();
|
|
63
|
+
if (fs.existsSync(completedDir) && fs.statSync(completedDir).isDirectory()) {
|
|
64
|
+
const doneFiles = fs.readdirSync(completedDir).filter(f => f.endsWith('.done.json'));
|
|
65
|
+
for (const doneFile of doneFiles) {
|
|
66
|
+
// Read .done.json file content to extract fileName or featureId
|
|
67
|
+
const doneFilePath = path.join(completedDir, doneFile);
|
|
68
|
+
try {
|
|
69
|
+
const doneRawContent = fs.readFileSync(doneFilePath, 'utf8');
|
|
70
|
+
const doneContent = JSON.parse(doneRawContent);
|
|
71
|
+
// Use fileName field if available, fallback to featureId
|
|
72
|
+
if (doneContent.fileName) {
|
|
73
|
+
completedFeatureFileNames.add(doneContent.fileName);
|
|
74
|
+
}
|
|
75
|
+
if (doneContent.featureId) {
|
|
76
|
+
completedFeatureIds.add(doneContent.featureId);
|
|
77
|
+
}
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.warn(`Warning: Failed to read .done.json file ${doneFile}: ${error.message}`);
|
|
80
|
+
// Fallback: use filename without extension (legacy behavior)
|
|
81
|
+
const baseName = path.basename(doneFile, '.done.json');
|
|
82
|
+
completedFeatureIds.add(baseName);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Find all features-*.json files
|
|
88
|
+
const featureFiles = fs.readdirSync(fullPath).filter(f => {
|
|
89
|
+
return f.startsWith('features-') && f.endsWith('.json') && fs.statSync(path.join(fullPath, f)).isFile();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const candidateFeatures = [];
|
|
93
|
+
|
|
94
|
+
for (const fileName of featureFiles) {
|
|
95
|
+
const filePath = path.join(fullPath, fileName);
|
|
96
|
+
const rawContent = fs.readFileSync(filePath, 'utf8');
|
|
97
|
+
const content = JSON.parse(rawContent);
|
|
98
|
+
|
|
99
|
+
const platformType = content.platformType;
|
|
100
|
+
const platformSubtype = content.platformSubtype || null;
|
|
101
|
+
const sourcePath = content.sourcePath;
|
|
102
|
+
const techStack = content.techStack;
|
|
103
|
+
const platformName = content.platformName;
|
|
104
|
+
|
|
105
|
+
if (!content.features || !Array.isArray(content.features)) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (const feature of content.features) {
|
|
110
|
+
// Check if feature needs analysis: analyzed=false or analyzed field missing
|
|
111
|
+
const needsAnalysis = !('analyzed' in feature) || feature.analyzed === false;
|
|
112
|
+
|
|
113
|
+
if (!needsAnalysis) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Use feature's id and fileName fields
|
|
118
|
+
const featureId = feature.id;
|
|
119
|
+
const featureFileName = feature.fileName;
|
|
120
|
+
|
|
121
|
+
// Skip if already completed (has .done.json file)
|
|
122
|
+
// Check both fileName (new format) and featureId (legacy format)
|
|
123
|
+
if (completedFeatureFileNames.has(featureFileName) || completedFeatureIds.has(featureId)) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
candidateFeatures.push({
|
|
128
|
+
sourceFile: fileName,
|
|
129
|
+
platformName: platformName,
|
|
130
|
+
platformType: platformType,
|
|
131
|
+
platformSubtype: platformSubtype,
|
|
132
|
+
sourcePath: sourcePath,
|
|
133
|
+
techStack: techStack,
|
|
134
|
+
feature: feature
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Take only the first BatchSize items
|
|
140
|
+
const batchFeatures = candidateFeatures.slice(0, args.batchSize);
|
|
141
|
+
|
|
142
|
+
// Output as JSON
|
|
143
|
+
console.log(JSON.stringify(batchFeatures, null, 2));
|
|
144
|
+
} catch (error) {
|
|
145
|
+
console.error(`Error: ${error.message}`);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
main();
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get all pending features from features-*.json files.
|
|
5
|
+
*
|
|
6
|
+
* Scans the sync-state directory for all features-*.json files and extracts
|
|
7
|
+
* features where status='pending' or status field is missing (backward compatibility).
|
|
8
|
+
* Returns a flat JSON array with platform metadata attached to each feature for easy dispatch.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
// Parse command line arguments
|
|
15
|
+
function parseArgs() {
|
|
16
|
+
const args = process.argv.slice(2);
|
|
17
|
+
const result = {
|
|
18
|
+
syncStatePath: null,
|
|
19
|
+
platformId: null
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
for (let i = 0; i < args.length; i++) {
|
|
23
|
+
const arg = args[i];
|
|
24
|
+
switch (arg) {
|
|
25
|
+
case '--syncStatePath':
|
|
26
|
+
case '-SyncStatePath':
|
|
27
|
+
result.syncStatePath = args[++i];
|
|
28
|
+
break;
|
|
29
|
+
case '--platformId':
|
|
30
|
+
case '-platformId':
|
|
31
|
+
result.platformId = args[++i];
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function main() {
|
|
40
|
+
try {
|
|
41
|
+
const args = parseArgs();
|
|
42
|
+
|
|
43
|
+
if (!args.syncStatePath) {
|
|
44
|
+
console.error('Error: --syncStatePath is required');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Resolve full path
|
|
49
|
+
const fullPath = path.resolve(args.syncStatePath);
|
|
50
|
+
if (!fs.existsSync(fullPath)) {
|
|
51
|
+
console.error(`SyncStatePath not found: ${args.syncStatePath}`);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Find features-*.json files, filtered by platformId if specified
|
|
56
|
+
let featureFiles = fs.readdirSync(fullPath).filter(f => {
|
|
57
|
+
return f.startsWith('features-') && f.endsWith('.json') && fs.statSync(path.join(fullPath, f)).isFile();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// If platformId is specified, filter to only the matching file
|
|
61
|
+
if (args.platformId) {
|
|
62
|
+
const targetFile = `features-${args.platformId}.json`;
|
|
63
|
+
featureFiles = featureFiles.filter(f => f === targetFile);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const pendingFeatures = [];
|
|
67
|
+
|
|
68
|
+
for (const fileName of featureFiles) {
|
|
69
|
+
const filePath = path.join(fullPath, fileName);
|
|
70
|
+
const rawContent = fs.readFileSync(filePath, 'utf8');
|
|
71
|
+
const content = JSON.parse(rawContent);
|
|
72
|
+
|
|
73
|
+
const platformType = content.platformType;
|
|
74
|
+
const platformSubtype = content.platformSubtype || null;
|
|
75
|
+
const sourcePath = content.sourcePath;
|
|
76
|
+
const techStack = content.techStack;
|
|
77
|
+
const platformName = content.platformName;
|
|
78
|
+
|
|
79
|
+
if (!content.features || !Array.isArray(content.features)) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for (const feature of content.features) {
|
|
84
|
+
if (!('status' in feature) || feature.status === 'pending') {
|
|
85
|
+
pendingFeatures.push({
|
|
86
|
+
sourceFile: fileName,
|
|
87
|
+
platformName: platformName,
|
|
88
|
+
platformType: platformType,
|
|
89
|
+
platformSubtype: platformSubtype,
|
|
90
|
+
sourcePath: sourcePath,
|
|
91
|
+
techStack: techStack,
|
|
92
|
+
feature: feature
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Output as JSON
|
|
99
|
+
console.log(JSON.stringify(pendingFeatures, null, 2));
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error(`Error: ${error.message}`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
main();
|