specweave 0.23.0 → 0.23.2
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-plugin/marketplace.json +0 -88
- package/CLAUDE.md +100 -0
- package/bin/fix-marketplace-errors.sh +8 -8
- package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js +5 -17
- package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
- package/dist/src/core/repo-structure/repo-id-generator.d.ts +20 -0
- package/dist/src/core/repo-structure/repo-id-generator.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-id-generator.js +44 -0
- package/dist/src/core/repo-structure/repo-id-generator.js.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.js +5 -2
- package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/.claude-plugin/plugin.json +10 -0
- package/plugins/specweave/commands/specweave-archive.md +51 -15
- package/plugins/specweave/hooks/post-edit-spec.sh +62 -9
- package/plugins/specweave/hooks/post-metadata-change.sh +160 -0
- package/plugins/specweave/hooks/post-write-spec.sh +62 -8
- package/plugins/specweave/lib/hooks/auto-transition.js.bak +50 -0
- package/plugins/specweave/lib/hooks/auto-transition.ts.bak +84 -0
- package/plugins/specweave/lib/hooks/git-diff-analyzer.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/git-diff-analyzer.d.ts.bak +89 -0
- package/plugins/specweave/lib/hooks/git-diff-analyzer.js.bak +142 -0
- package/plugins/specweave/lib/hooks/git-diff-analyzer.ts.bak +269 -0
- package/plugins/specweave/lib/hooks/invoke-translator-skill.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/invoke-translator-skill.d.ts.bak +60 -0
- package/plugins/specweave/lib/hooks/invoke-translator-skill.js.bak +155 -0
- package/plugins/specweave/lib/hooks/invoke-translator-skill.ts.bak +264 -0
- package/plugins/specweave/lib/hooks/prepare-reflection-context.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/prepare-reflection-context.d.ts.bak +42 -0
- package/plugins/specweave/lib/hooks/prepare-reflection-context.js.bak +110 -0
- package/plugins/specweave/lib/hooks/prepare-reflection-context.ts.bak +178 -0
- package/plugins/specweave/lib/hooks/reflection-config-loader.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/reflection-config-loader.d.ts.bak +45 -0
- package/plugins/specweave/lib/hooks/reflection-config-loader.js.bak +92 -0
- package/plugins/specweave/lib/hooks/reflection-config-loader.ts.bak +156 -0
- package/plugins/specweave/lib/hooks/reflection-parser.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/reflection-parser.d.ts.bak +33 -0
- package/plugins/specweave/lib/hooks/reflection-parser.js.bak +301 -0
- package/plugins/specweave/lib/hooks/reflection-parser.ts.bak +484 -0
- package/plugins/specweave/lib/hooks/reflection-prompt-builder.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/reflection-prompt-builder.d.ts.bak +56 -0
- package/plugins/specweave/lib/hooks/reflection-prompt-builder.js.bak +182 -0
- package/plugins/specweave/lib/hooks/reflection-prompt-builder.ts.bak +306 -0
- package/plugins/specweave/lib/hooks/reflection-storage.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/reflection-storage.d.ts.bak +64 -0
- package/plugins/specweave/lib/hooks/reflection-storage.js.bak +231 -0
- package/plugins/specweave/lib/hooks/reflection-storage.ts.bak +369 -0
- package/plugins/specweave/lib/hooks/run-self-reflection.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/run-self-reflection.d.ts.bak +43 -0
- package/plugins/specweave/lib/hooks/run-self-reflection.js.bak +132 -0
- package/plugins/specweave/lib/hooks/run-self-reflection.ts.bak +258 -0
- package/plugins/specweave/lib/hooks/sync-cache.js.bak +294 -0
- package/plugins/specweave/lib/hooks/sync-living-docs.d.js.bak +1 -0
- package/plugins/specweave/lib/hooks/sync-living-docs.d.ts.bak +27 -0
- package/plugins/specweave/lib/hooks/sync-living-docs.js.bak +339 -0
- package/plugins/specweave/lib/hooks/sync-us-tasks.js.bak +476 -0
- package/plugins/specweave/lib/hooks/translate-file.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/translate-file.d.ts.bak +59 -0
- package/plugins/specweave/lib/hooks/translate-file.js.bak +289 -0
- package/plugins/specweave/lib/hooks/translate-file.ts.bak +428 -0
- package/plugins/specweave/lib/hooks/translate-living-docs.d.js.bak +0 -0
- package/plugins/specweave/lib/hooks/translate-living-docs.d.ts.bak +13 -0
- package/plugins/specweave/lib/hooks/translate-living-docs.js.bak +119 -0
- package/plugins/specweave/lib/hooks/translate-living-docs.ts.bak +224 -0
- package/plugins/specweave/lib/hooks/update-ac-status.js.bak +51 -0
- package/plugins/specweave/lib/hooks/update-ac-status.ts.bak +103 -0
- package/plugins/specweave/lib/hooks/update-tasks-md.d.js.bak +1 -0
- package/plugins/specweave/lib/hooks/update-tasks-md.d.ts.bak +29 -0
- package/plugins/specweave/lib/hooks/update-tasks-md.js.bak +296 -0
- package/plugins/specweave/lib/hooks/update-tasks-md.ts.bak +489 -0
- package/plugins/specweave-ado/lib/ado-multi-project-sync.js +1 -0
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +6225 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Living Docs Auto-Translation
|
|
3
|
+
*
|
|
4
|
+
* Automatically translates changed documentation files when language != 'en'
|
|
5
|
+
* and auto-translation is enabled in config.
|
|
6
|
+
*
|
|
7
|
+
* This runs as part of the post-task-completion hook.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Main function: Translate changed living docs
|
|
11
|
+
*/
|
|
12
|
+
export declare function translateLivingDocs(incrementId: string): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=translate-living-docs.d.ts.map
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
async function translateLivingDocs(incrementId) {
|
|
4
|
+
try {
|
|
5
|
+
const configPath = ".specweave/config.json";
|
|
6
|
+
if (!fs.existsSync(configPath)) {
|
|
7
|
+
console.log("[translate-living-docs] No config found, skipping translation");
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const config = await fs.readJson(configPath);
|
|
11
|
+
if (!config.language || config.language === "en") {
|
|
12
|
+
console.log("[translate-living-docs] Project language is English, skipping translation");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (!config.translation?.autoTranslateLivingDocs) {
|
|
16
|
+
console.log("[translate-living-docs] Auto-translation disabled in config");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
console.log(`[translate-living-docs] Auto-translating docs from ${config.language} to English...`);
|
|
20
|
+
const changedFiles = await detectChangedDocs();
|
|
21
|
+
if (changedFiles.length === 0) {
|
|
22
|
+
console.log("[translate-living-docs] No documentation changes detected");
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
console.log(`[translate-living-docs] Found ${changedFiles.length} changed file(s)`);
|
|
26
|
+
for (const file of changedFiles) {
|
|
27
|
+
try {
|
|
28
|
+
await translateFile(file, "en", config.translation);
|
|
29
|
+
console.log(`[translate-living-docs] \u2713 Translated: ${file} (${config.language} \u2192 en)`);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.warn(`[translate-living-docs] \u26A0\uFE0F Failed to translate ${file}: ${error.message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
console.log(`[translate-living-docs] \u2705 Translation complete (${changedFiles.length} files)`);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error(`[translate-living-docs] Error: ${error.message}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function detectChangedDocs() {
|
|
40
|
+
try {
|
|
41
|
+
const output = execSync(
|
|
42
|
+
"git diff --name-only .specweave/docs/",
|
|
43
|
+
{ encoding: "utf-8", stdio: ["pipe", "pipe", "ignore"] }
|
|
44
|
+
);
|
|
45
|
+
const files = output.split("\n").filter((f) => f.trim() && f.endsWith(".md")).map((f) => f.trim());
|
|
46
|
+
return files;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function translateFile(filePath, targetLanguage, translationConfig) {
|
|
52
|
+
const originalContent = await fs.readFile(filePath, "utf-8");
|
|
53
|
+
if (originalContent.includes(`<!-- Translated to ${targetLanguage} -->`)) {
|
|
54
|
+
console.log(`[translate-living-docs] File already translated, skipping: ${filePath}`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const translationPrompt = generateTranslationPrompt(
|
|
58
|
+
originalContent,
|
|
59
|
+
targetLanguage,
|
|
60
|
+
translationConfig
|
|
61
|
+
);
|
|
62
|
+
const markedContent = `<!-- Translation needed to ${targetLanguage} -->
|
|
63
|
+
<!-- Original content below -->
|
|
64
|
+
|
|
65
|
+
${originalContent}`;
|
|
66
|
+
console.log(`[translate-living-docs] Translation prompt generated for: ${filePath}`);
|
|
67
|
+
}
|
|
68
|
+
function generateTranslationPrompt(content, targetLanguage, translationConfig) {
|
|
69
|
+
const keepFrameworkTerms = translationConfig?.keepFrameworkTerms !== false;
|
|
70
|
+
const keepTechnicalTerms = translationConfig?.keepTechnicalTerms !== false;
|
|
71
|
+
return `
|
|
72
|
+
Translate the following markdown documentation to ${getLanguageName(targetLanguage)}.
|
|
73
|
+
|
|
74
|
+
CRITICAL RULES:
|
|
75
|
+
${keepFrameworkTerms ? "- Keep framework terms in English: increment, spec.md, plan.md, tasks.md, COMPLETION-SUMMARY.md, living docs, PM gate, RFC, ADR, PRD, HLD, LLD" : ""}
|
|
76
|
+
${keepTechnicalTerms ? "- Keep technical terms in English: TypeScript, npm, git, Docker, Kubernetes, API, CLI, REST, JSON, HTTP" : ""}
|
|
77
|
+
- Preserve ALL markdown formatting (headers, lists, code blocks, links)
|
|
78
|
+
- Do NOT translate code blocks
|
|
79
|
+
- Do NOT translate YAML frontmatter keys (only values if applicable)
|
|
80
|
+
- Preserve all emojis
|
|
81
|
+
- Preserve all file paths and URLs
|
|
82
|
+
|
|
83
|
+
Content to translate:
|
|
84
|
+
---
|
|
85
|
+
${content}
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
Translated version:
|
|
89
|
+
`.trim();
|
|
90
|
+
}
|
|
91
|
+
function getLanguageName(code) {
|
|
92
|
+
const names = {
|
|
93
|
+
en: "English",
|
|
94
|
+
ru: "Russian (\u0420\u0443\u0441\u0441\u043A\u0438\u0439)",
|
|
95
|
+
es: "Spanish (Espa\xF1ol)",
|
|
96
|
+
zh: "Chinese (\u4E2D\u6587)",
|
|
97
|
+
de: "German (Deutsch)",
|
|
98
|
+
fr: "French (Fran\xE7ais)",
|
|
99
|
+
ja: "Japanese (\u65E5\u672C\u8A9E)",
|
|
100
|
+
ko: "Korean (\uD55C\uAD6D\uC5B4)",
|
|
101
|
+
pt: "Portuguese (Portugu\xEAs)"
|
|
102
|
+
};
|
|
103
|
+
return names[code] || code;
|
|
104
|
+
}
|
|
105
|
+
async function main() {
|
|
106
|
+
const args = process.argv.slice(2);
|
|
107
|
+
const incrementId = args[0] || "current";
|
|
108
|
+
await translateLivingDocs(incrementId);
|
|
109
|
+
}
|
|
110
|
+
const isMainModule = import.meta.url === `file://${process.argv[1]}`;
|
|
111
|
+
if (isMainModule) {
|
|
112
|
+
main().catch((error) => {
|
|
113
|
+
console.error("[translate-living-docs] Fatal error:", error);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
export {
|
|
118
|
+
translateLivingDocs
|
|
119
|
+
};
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Living Docs Auto-Translation
|
|
3
|
+
*
|
|
4
|
+
* Automatically translates changed documentation files when language != 'en'
|
|
5
|
+
* and auto-translation is enabled in config.
|
|
6
|
+
*
|
|
7
|
+
* This runs as part of the post-task-completion hook.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { execSync } from 'child_process';
|
|
11
|
+
import fs from 'fs-extra';
|
|
12
|
+
import path from 'path';
|
|
13
|
+
|
|
14
|
+
interface Config {
|
|
15
|
+
language?: string;
|
|
16
|
+
translation?: {
|
|
17
|
+
autoTranslateLivingDocs?: boolean;
|
|
18
|
+
keepFrameworkTerms?: boolean;
|
|
19
|
+
keepTechnicalTerms?: boolean;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Main function: Translate changed living docs
|
|
25
|
+
*/
|
|
26
|
+
export async function translateLivingDocs(incrementId: string): Promise<void> {
|
|
27
|
+
try {
|
|
28
|
+
// 1. Load config
|
|
29
|
+
const configPath = '.specweave/config.json';
|
|
30
|
+
if (!fs.existsSync(configPath)) {
|
|
31
|
+
console.log('[translate-living-docs] No config found, skipping translation');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const config: Config = await fs.readJson(configPath);
|
|
36
|
+
|
|
37
|
+
// 2. Check if translation is enabled
|
|
38
|
+
if (!config.language || config.language === 'en') {
|
|
39
|
+
// Already English or no language set - skip translation
|
|
40
|
+
console.log('[translate-living-docs] Project language is English, skipping translation');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (!config.translation?.autoTranslateLivingDocs) {
|
|
45
|
+
// Auto-translation disabled
|
|
46
|
+
console.log('[translate-living-docs] Auto-translation disabled in config');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Always translate TO English for maintainability (not to user's language!)
|
|
51
|
+
console.log(`[translate-living-docs] Auto-translating docs from ${config.language} to English...`);
|
|
52
|
+
|
|
53
|
+
// 3. Detect changed documentation files
|
|
54
|
+
const changedFiles = await detectChangedDocs();
|
|
55
|
+
|
|
56
|
+
if (changedFiles.length === 0) {
|
|
57
|
+
console.log('[translate-living-docs] No documentation changes detected');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(`[translate-living-docs] Found ${changedFiles.length} changed file(s)`);
|
|
62
|
+
|
|
63
|
+
// 4. Translate each file TO English (always 'en', not config.language!)
|
|
64
|
+
for (const file of changedFiles) {
|
|
65
|
+
try {
|
|
66
|
+
// Always translate TO English for maintainability
|
|
67
|
+
await translateFile(file, 'en', config.translation);
|
|
68
|
+
console.log(`[translate-living-docs] ✓ Translated: ${file} (${config.language} → en)`);
|
|
69
|
+
} catch (error: any) {
|
|
70
|
+
console.warn(`[translate-living-docs] ⚠️ Failed to translate ${file}: ${error.message}`);
|
|
71
|
+
// Continue with other files
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
console.log(`[translate-living-docs] ✅ Translation complete (${changedFiles.length} files)`);
|
|
76
|
+
} catch (error: any) {
|
|
77
|
+
console.error(`[translate-living-docs] Error: ${error.message}`);
|
|
78
|
+
// Don't throw - translation errors shouldn't break the workflow
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Detect changed documentation files using git diff
|
|
84
|
+
*/
|
|
85
|
+
async function detectChangedDocs(): Promise<string[]> {
|
|
86
|
+
try {
|
|
87
|
+
// Get list of changed files in .specweave/docs/
|
|
88
|
+
const output = execSync(
|
|
89
|
+
'git diff --name-only .specweave/docs/',
|
|
90
|
+
{ encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// Filter for markdown files only
|
|
94
|
+
const files = output
|
|
95
|
+
.split('\n')
|
|
96
|
+
.filter(f => f.trim() && f.endsWith('.md'))
|
|
97
|
+
.map(f => f.trim());
|
|
98
|
+
|
|
99
|
+
return files;
|
|
100
|
+
} catch (error) {
|
|
101
|
+
// git diff might fail if not a git repo or no changes
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Translate a single file FROM user's language TO English
|
|
108
|
+
*
|
|
109
|
+
* NOTE: This is a simplified implementation that creates a translation prompt.
|
|
110
|
+
* In a real implementation with Claude Code, the translator skill would auto-activate
|
|
111
|
+
* and handle the translation. For now, we'll add a marker comment to indicate
|
|
112
|
+
* the file needs translation.
|
|
113
|
+
*
|
|
114
|
+
* @param filePath - File to translate
|
|
115
|
+
* @param targetLanguage - Target language (should always be 'en' for living docs)
|
|
116
|
+
* @param translationConfig - Translation settings
|
|
117
|
+
*/
|
|
118
|
+
async function translateFile(
|
|
119
|
+
filePath: string,
|
|
120
|
+
targetLanguage: string, // Should always be 'en' for living docs
|
|
121
|
+
translationConfig?: Config['translation']
|
|
122
|
+
): Promise<void> {
|
|
123
|
+
// Read original content
|
|
124
|
+
const originalContent = await fs.readFile(filePath, 'utf-8');
|
|
125
|
+
|
|
126
|
+
// Check if file already has translation marker (avoid re-translating)
|
|
127
|
+
if (originalContent.includes(`<!-- Translated to ${targetLanguage} -->`)) {
|
|
128
|
+
console.log(`[translate-living-docs] File already translated, skipping: ${filePath}`);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// For now, we'll create a translation request that the LLM can act on
|
|
133
|
+
// In a production system with Claude Code integration, this would invoke
|
|
134
|
+
// the translator skill directly
|
|
135
|
+
|
|
136
|
+
const translationPrompt = generateTranslationPrompt(
|
|
137
|
+
originalContent,
|
|
138
|
+
targetLanguage,
|
|
139
|
+
translationConfig
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
// TODO: In full implementation, this would:
|
|
143
|
+
// 1. Invoke translator skill via Claude Code API
|
|
144
|
+
// 2. Get translated content back
|
|
145
|
+
// 3. Write to file
|
|
146
|
+
|
|
147
|
+
// For MVP, we'll add a comment indicating translation is needed
|
|
148
|
+
const markedContent = `<!-- Translation needed to ${targetLanguage} -->\n<!-- Original content below -->\n\n${originalContent}`;
|
|
149
|
+
|
|
150
|
+
// Write back (commented out to avoid breaking existing docs)
|
|
151
|
+
// await fs.writeFile(filePath, markedContent, 'utf-8');
|
|
152
|
+
|
|
153
|
+
console.log(`[translate-living-docs] Translation prompt generated for: ${filePath}`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Generate translation prompt for LLM
|
|
158
|
+
*/
|
|
159
|
+
function generateTranslationPrompt(
|
|
160
|
+
content: string,
|
|
161
|
+
targetLanguage: string,
|
|
162
|
+
translationConfig?: Config['translation']
|
|
163
|
+
): string {
|
|
164
|
+
const keepFrameworkTerms = translationConfig?.keepFrameworkTerms !== false;
|
|
165
|
+
const keepTechnicalTerms = translationConfig?.keepTechnicalTerms !== false;
|
|
166
|
+
|
|
167
|
+
return `
|
|
168
|
+
Translate the following markdown documentation to ${getLanguageName(targetLanguage)}.
|
|
169
|
+
|
|
170
|
+
CRITICAL RULES:
|
|
171
|
+
${keepFrameworkTerms ? '- Keep framework terms in English: increment, spec.md, plan.md, tasks.md, COMPLETION-SUMMARY.md, living docs, PM gate, RFC, ADR, PRD, HLD, LLD' : ''}
|
|
172
|
+
${keepTechnicalTerms ? '- Keep technical terms in English: TypeScript, npm, git, Docker, Kubernetes, API, CLI, REST, JSON, HTTP' : ''}
|
|
173
|
+
- Preserve ALL markdown formatting (headers, lists, code blocks, links)
|
|
174
|
+
- Do NOT translate code blocks
|
|
175
|
+
- Do NOT translate YAML frontmatter keys (only values if applicable)
|
|
176
|
+
- Preserve all emojis
|
|
177
|
+
- Preserve all file paths and URLs
|
|
178
|
+
|
|
179
|
+
Content to translate:
|
|
180
|
+
---
|
|
181
|
+
${content}
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
Translated version:
|
|
185
|
+
`.trim();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Get human-readable language name
|
|
190
|
+
*/
|
|
191
|
+
function getLanguageName(code: string): string {
|
|
192
|
+
const names: Record<string, string> = {
|
|
193
|
+
en: 'English',
|
|
194
|
+
ru: 'Russian (Русский)',
|
|
195
|
+
es: 'Spanish (Español)',
|
|
196
|
+
zh: 'Chinese (中文)',
|
|
197
|
+
de: 'German (Deutsch)',
|
|
198
|
+
fr: 'French (Français)',
|
|
199
|
+
ja: 'Japanese (日本語)',
|
|
200
|
+
ko: 'Korean (한국어)',
|
|
201
|
+
pt: 'Portuguese (Português)',
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
return names[code] || code;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* CLI entry point (for standalone execution)
|
|
209
|
+
*/
|
|
210
|
+
async function main(): Promise<void> {
|
|
211
|
+
const args = process.argv.slice(2);
|
|
212
|
+
const incrementId = args[0] || 'current';
|
|
213
|
+
|
|
214
|
+
await translateLivingDocs(incrementId);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Check if running as main module
|
|
218
|
+
const isMainModule = import.meta.url === `file://${process.argv[1]}`;
|
|
219
|
+
if (isMainModule) {
|
|
220
|
+
main().catch(error => {
|
|
221
|
+
console.error('[translate-living-docs] Fatal error:', error);
|
|
222
|
+
process.exit(1);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { ACStatusManager } from "../../../../dist/src/core/increment/ac-status-manager.js";
|
|
3
|
+
async function updateACStatus(incrementId) {
|
|
4
|
+
try {
|
|
5
|
+
const projectRoot = process.cwd();
|
|
6
|
+
if (process.env.SKIP_AC_SYNC === "true") {
|
|
7
|
+
console.log("\u2139\uFE0F AC sync skipped (SKIP_AC_SYNC=true)");
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
console.log(`\u{1F504} Syncing AC status for increment ${incrementId}...`);
|
|
11
|
+
const manager = new ACStatusManager(projectRoot);
|
|
12
|
+
const result = await manager.syncACStatus(incrementId);
|
|
13
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
14
|
+
console.log("\n\u26A0\uFE0F Warnings:");
|
|
15
|
+
result.warnings.forEach((warning) => console.log(` ${warning}`));
|
|
16
|
+
}
|
|
17
|
+
if (result.conflicts && result.conflicts.length > 0) {
|
|
18
|
+
console.log("\n\u26A0\uFE0F Conflicts detected:");
|
|
19
|
+
result.conflicts.forEach((conflict) => console.log(` ${conflict}`));
|
|
20
|
+
}
|
|
21
|
+
if (result.updated && result.updated.length > 0) {
|
|
22
|
+
console.log("\n\u2705 Updated AC checkboxes:");
|
|
23
|
+
result.updated.forEach((acId) => console.log(` ${acId} \u2192 [x]`));
|
|
24
|
+
if (result.changes && result.changes.length > 0) {
|
|
25
|
+
console.log("\n\u{1F4DD} Changes:");
|
|
26
|
+
result.changes.forEach((change) => console.log(` ${change}`));
|
|
27
|
+
}
|
|
28
|
+
} else if (result.synced) {
|
|
29
|
+
console.log("\u2705 All ACs already in sync (no changes needed)");
|
|
30
|
+
} else {
|
|
31
|
+
console.log("\u2139\uFE0F No AC updates needed");
|
|
32
|
+
}
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error("\u274C Error updating AC status:", error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const isMainModule = import.meta.url === `file://${process.argv[1]}`;
|
|
38
|
+
if (isMainModule) {
|
|
39
|
+
const incrementId = process.argv[2];
|
|
40
|
+
if (!incrementId) {
|
|
41
|
+
console.error("Usage: node update-ac-status.js <increment-id>");
|
|
42
|
+
console.error("Example: node update-ac-status.js 0039-ultra-smart-next-command");
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
updateACStatus(incrementId).then(() => {
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}).catch((error) => {
|
|
48
|
+
console.error("Fatal error:", error);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AC Status Update Hook (ACStatusManager Integration)
|
|
5
|
+
*
|
|
6
|
+
* Uses ACStatusManager for sophisticated AC status synchronization:
|
|
7
|
+
* - Tracks completion percentage per AC (only updates at 100%)
|
|
8
|
+
* - Detects conflicts (AC checked but tasks incomplete)
|
|
9
|
+
* - Warns about orphaned ACs (no implementing tasks)
|
|
10
|
+
* - Provides detailed sync result with diff
|
|
11
|
+
* - Atomic file writes to prevent corruption
|
|
12
|
+
*
|
|
13
|
+
* Flow:
|
|
14
|
+
* 1. Parse tasks.md → Map AC-IDs to completion status
|
|
15
|
+
* 2. Parse spec.md → Extract current AC definitions
|
|
16
|
+
* 3. Compare task completion vs spec checkboxes
|
|
17
|
+
* 4. Update spec.md only for 100% complete ACs
|
|
18
|
+
* 5. Log conflicts, warnings, and changes
|
|
19
|
+
*
|
|
20
|
+
* Called by: plugins/specweave/hooks/post-task-completion.sh
|
|
21
|
+
*
|
|
22
|
+
* Example:
|
|
23
|
+
* - Tasks: T-001 [x], T-002 [x] (both have AC-US1-01) → AC-US1-01 100% complete
|
|
24
|
+
* - spec.md: - [ ] AC-US1-01 → - [x] AC-US1-01 ✅
|
|
25
|
+
* - Tasks: T-003 [x], T-004 [ ] (both have AC-US1-02) → AC-US1-02 50% complete
|
|
26
|
+
* - spec.md: - [ ] AC-US1-02 → NO CHANGE (partial completion)
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { ACStatusManager } from '../../../../dist/src/core/increment/ac-status-manager.js';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Main entry point - uses ACStatusManager for sophisticated sync
|
|
33
|
+
*/
|
|
34
|
+
async function updateACStatus(incrementId: string): Promise<void> {
|
|
35
|
+
try {
|
|
36
|
+
const projectRoot = process.cwd();
|
|
37
|
+
|
|
38
|
+
// Check if --skip-ac-sync flag is set (allows disabling hook temporarily)
|
|
39
|
+
if (process.env.SKIP_AC_SYNC === 'true') {
|
|
40
|
+
console.log('ℹ️ AC sync skipped (SKIP_AC_SYNC=true)');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.log(`🔄 Syncing AC status for increment ${incrementId}...`);
|
|
45
|
+
|
|
46
|
+
// Initialize ACStatusManager with project root
|
|
47
|
+
const manager = new ACStatusManager(projectRoot);
|
|
48
|
+
|
|
49
|
+
// Perform sophisticated sync
|
|
50
|
+
const result = await manager.syncACStatus(incrementId);
|
|
51
|
+
|
|
52
|
+
// Display results
|
|
53
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
54
|
+
console.log('\n⚠️ Warnings:');
|
|
55
|
+
result.warnings.forEach((warning: string) => console.log(` ${warning}`));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (result.conflicts && result.conflicts.length > 0) {
|
|
59
|
+
console.log('\n⚠️ Conflicts detected:');
|
|
60
|
+
result.conflicts.forEach((conflict: string) => console.log(` ${conflict}`));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (result.updated && result.updated.length > 0) {
|
|
64
|
+
console.log('\n✅ Updated AC checkboxes:');
|
|
65
|
+
result.updated.forEach((acId: string) => console.log(` ${acId} → [x]`));
|
|
66
|
+
|
|
67
|
+
if (result.changes && result.changes.length > 0) {
|
|
68
|
+
console.log('\n📝 Changes:');
|
|
69
|
+
result.changes.forEach((change: string) => console.log(` ${change}`));
|
|
70
|
+
}
|
|
71
|
+
} else if (result.synced) {
|
|
72
|
+
console.log('✅ All ACs already in sync (no changes needed)');
|
|
73
|
+
} else {
|
|
74
|
+
console.log('ℹ️ No AC updates needed');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error('❌ Error updating AC status:', error);
|
|
79
|
+
// Non-blocking: Don't throw, just log
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// CLI Entry Point (ES Module)
|
|
84
|
+
const isMainModule = import.meta.url === `file://${process.argv[1]}`;
|
|
85
|
+
|
|
86
|
+
if (isMainModule) {
|
|
87
|
+
const incrementId = process.argv[2];
|
|
88
|
+
|
|
89
|
+
if (!incrementId) {
|
|
90
|
+
console.error('Usage: node update-ac-status.js <increment-id>');
|
|
91
|
+
console.error('Example: node update-ac-status.js 0039-ultra-smart-next-command');
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
updateACStatus(incrementId)
|
|
96
|
+
.then(() => {
|
|
97
|
+
process.exit(0);
|
|
98
|
+
})
|
|
99
|
+
.catch((error) => {
|
|
100
|
+
console.error('Fatal error:', error);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* SpecWeave Tasks.md Auto-Updater
|
|
4
|
+
*
|
|
5
|
+
* Automatically updates tasks.md completion status after TodoWrite completes tasks.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node dist/hooks/lib/update-tasks-md.js <incrementId>
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
* node dist/hooks/lib/update-tasks-md.js 0006-llm-native-i18n
|
|
12
|
+
*
|
|
13
|
+
* What it does:
|
|
14
|
+
* 1. Reads tasks.md for the given increment
|
|
15
|
+
* 2. Finds recently completed tasks from TodoWrite
|
|
16
|
+
* 3. Updates "[ ]" to "[x]" for completed tasks
|
|
17
|
+
* 4. Updates "Status: ⏳ Pending" to "Status: [x] Completed"
|
|
18
|
+
* 5. Recalculates progress percentage
|
|
19
|
+
* 6. Writes back to tasks.md
|
|
20
|
+
*
|
|
21
|
+
* @author SpecWeave Team
|
|
22
|
+
* @version 1.0.0
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Main function - update tasks.md for given increment
|
|
26
|
+
*/
|
|
27
|
+
declare function updateTasksMd(incrementId: string): Promise<void>;
|
|
28
|
+
export { updateTasksMd };
|
|
29
|
+
//# sourceMappingURL=update-tasks-md.d.ts.map
|