specweave 0.22.14 → 0.23.1

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 (211) hide show
  1. package/CLAUDE.md +178 -1
  2. package/dist/src/cli/commands/import-external.d.ts +22 -0
  3. package/dist/src/cli/commands/import-external.d.ts.map +1 -0
  4. package/dist/src/cli/commands/import-external.js +282 -0
  5. package/dist/src/cli/commands/import-external.js.map +1 -0
  6. package/dist/src/cli/commands/init.d.ts.map +1 -1
  7. package/dist/src/cli/commands/init.js +46 -0
  8. package/dist/src/cli/commands/init.js.map +1 -1
  9. package/dist/src/cli/helpers/github-repo-selector.d.ts +59 -0
  10. package/dist/src/cli/helpers/github-repo-selector.d.ts.map +1 -0
  11. package/dist/src/cli/helpers/github-repo-selector.js +265 -0
  12. package/dist/src/cli/helpers/github-repo-selector.js.map +1 -0
  13. package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
  14. package/dist/src/cli/helpers/issue-tracker/index.js +5 -17
  15. package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
  16. package/dist/src/config/types.d.ts +16 -16
  17. package/dist/src/core/increment/ac-status-manager.d.ts.map +1 -1
  18. package/dist/src/core/increment/ac-status-manager.js +4 -2
  19. package/dist/src/core/increment/ac-status-manager.js.map +1 -1
  20. package/dist/src/core/increment/completion-validator.d.ts +30 -1
  21. package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
  22. package/dist/src/core/increment/completion-validator.js +151 -3
  23. package/dist/src/core/increment/completion-validator.js.map +1 -1
  24. package/dist/src/core/increment/increment-archiver.d.ts +25 -0
  25. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
  26. package/dist/src/core/increment/increment-archiver.js +130 -3
  27. package/dist/src/core/increment/increment-archiver.js.map +1 -1
  28. package/dist/src/core/living-docs/feature-archiver.d.ts +37 -0
  29. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
  30. package/dist/src/core/living-docs/feature-archiver.js +262 -18
  31. package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
  32. package/dist/src/core/living-docs/feature-id-manager.d.ts +17 -0
  33. package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -1
  34. package/dist/src/core/living-docs/feature-id-manager.js +25 -0
  35. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
  36. package/dist/src/core/living-docs/living-docs-sync.d.ts +14 -0
  37. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  38. package/dist/src/core/living-docs/living-docs-sync.js +46 -0
  39. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  40. package/dist/src/core/repo-structure/repo-id-generator.d.ts +20 -0
  41. package/dist/src/core/repo-structure/repo-id-generator.d.ts.map +1 -1
  42. package/dist/src/core/repo-structure/repo-id-generator.js +44 -0
  43. package/dist/src/core/repo-structure/repo-id-generator.js.map +1 -1
  44. package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
  45. package/dist/src/core/repo-structure/repo-structure-manager.js +5 -2
  46. package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
  47. package/dist/src/core/sync/sync-event-logger.d.ts +15 -1
  48. package/dist/src/core/sync/sync-event-logger.d.ts.map +1 -1
  49. package/dist/src/core/sync/sync-event-logger.js +39 -1
  50. package/dist/src/core/sync/sync-event-logger.js.map +1 -1
  51. package/dist/src/core/types/sync-config-validator.d.ts +57 -0
  52. package/dist/src/core/types/sync-config-validator.d.ts.map +1 -0
  53. package/dist/src/core/types/sync-config-validator.js +116 -0
  54. package/dist/src/core/types/sync-config-validator.js.map +1 -0
  55. package/dist/src/importers/duplicate-detector.d.ts +107 -0
  56. package/dist/src/importers/duplicate-detector.d.ts.map +1 -0
  57. package/dist/src/importers/duplicate-detector.js +189 -0
  58. package/dist/src/importers/duplicate-detector.js.map +1 -0
  59. package/dist/src/importers/import-coordinator.d.ts +15 -0
  60. package/dist/src/importers/import-coordinator.d.ts.map +1 -1
  61. package/dist/src/importers/import-coordinator.js +43 -1
  62. package/dist/src/importers/import-coordinator.js.map +1 -1
  63. package/dist/src/importers/item-converter.d.ts +5 -0
  64. package/dist/src/importers/item-converter.d.ts.map +1 -1
  65. package/dist/src/importers/item-converter.js +27 -2
  66. package/dist/src/importers/item-converter.js.map +1 -1
  67. package/dist/src/importers/rate-limiter.d.ts +128 -0
  68. package/dist/src/importers/rate-limiter.d.ts.map +1 -0
  69. package/dist/src/importers/rate-limiter.js +200 -0
  70. package/dist/src/importers/rate-limiter.js.map +1 -0
  71. package/dist/src/init/compliance/types.d.ts +2 -2
  72. package/dist/src/integrations/ado/ado-client.d.ts +6 -0
  73. package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
  74. package/dist/src/integrations/ado/ado-client.js +23 -0
  75. package/dist/src/integrations/ado/ado-client.js.map +1 -1
  76. package/dist/src/integrations/jira/jira-client.d.ts +6 -0
  77. package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
  78. package/dist/src/integrations/jira/jira-client.js +38 -0
  79. package/dist/src/integrations/jira/jira-client.js.map +1 -1
  80. package/dist/src/sync/external-item-sync-service.d.ts +150 -0
  81. package/dist/src/sync/external-item-sync-service.d.ts.map +1 -0
  82. package/dist/src/sync/external-item-sync-service.js +241 -0
  83. package/dist/src/sync/external-item-sync-service.js.map +1 -0
  84. package/dist/src/sync/format-preservation-sync.d.ts +90 -0
  85. package/dist/src/sync/format-preservation-sync.d.ts.map +1 -0
  86. package/dist/src/sync/format-preservation-sync.js +173 -0
  87. package/dist/src/sync/format-preservation-sync.js.map +1 -0
  88. package/dist/src/sync/index.d.ts +8 -0
  89. package/dist/src/sync/index.d.ts.map +1 -0
  90. package/dist/src/sync/index.js +6 -0
  91. package/dist/src/sync/index.js.map +1 -0
  92. package/dist/src/sync/sync-coordinator.d.ts +49 -0
  93. package/dist/src/sync/sync-coordinator.d.ts.map +1 -0
  94. package/dist/src/sync/sync-coordinator.js +248 -0
  95. package/dist/src/sync/sync-coordinator.js.map +1 -0
  96. package/dist/src/sync/sync-metadata.d.ts +75 -0
  97. package/dist/src/sync/sync-metadata.d.ts.map +1 -0
  98. package/dist/src/sync/sync-metadata.js +100 -0
  99. package/dist/src/sync/sync-metadata.js.map +1 -0
  100. package/dist/src/types/living-docs-us-file.d.ts +63 -0
  101. package/dist/src/types/living-docs-us-file.d.ts.map +1 -0
  102. package/dist/src/types/living-docs-us-file.js +27 -0
  103. package/dist/src/types/living-docs-us-file.js.map +1 -0
  104. package/dist/src/validators/format-preservation-validator.d.ts +127 -0
  105. package/dist/src/validators/format-preservation-validator.d.ts.map +1 -0
  106. package/dist/src/validators/format-preservation-validator.js +187 -0
  107. package/dist/src/validators/format-preservation-validator.js.map +1 -0
  108. package/package.json +3 -2
  109. package/plugins/specweave/.claude-plugin/plugin.json +20 -0
  110. package/plugins/specweave/commands/specweave-archive-features.md +11 -1
  111. package/plugins/specweave/commands/specweave-archive.md +51 -15
  112. package/plugins/specweave/commands/specweave-import-docs.md +88 -278
  113. package/plugins/specweave/commands/specweave-import-external.md +407 -0
  114. package/plugins/specweave/hooks/post-edit-spec.sh +94 -0
  115. package/plugins/specweave/hooks/post-increment-completion.sh +0 -0
  116. package/plugins/specweave/hooks/post-spec-update.sh +0 -0
  117. package/plugins/specweave/hooks/post-task-completion.sh +13 -3
  118. package/plugins/specweave/hooks/post-write-spec.sh +91 -0
  119. package/plugins/specweave/lib/hooks/auto-transition.js +1 -1
  120. package/plugins/specweave/lib/hooks/auto-transition.js.bak +50 -0
  121. package/plugins/specweave/lib/hooks/auto-transition.ts +1 -1
  122. package/plugins/specweave/lib/hooks/auto-transition.ts.bak +84 -0
  123. package/plugins/specweave/lib/hooks/git-diff-analyzer.d.js.bak +0 -0
  124. package/plugins/specweave/lib/hooks/git-diff-analyzer.d.ts.bak +89 -0
  125. package/plugins/specweave/lib/hooks/git-diff-analyzer.js.bak +142 -0
  126. package/plugins/specweave/lib/hooks/git-diff-analyzer.ts.bak +269 -0
  127. package/plugins/specweave/lib/hooks/invoke-translator-skill.d.js.bak +0 -0
  128. package/plugins/specweave/lib/hooks/invoke-translator-skill.d.ts.bak +60 -0
  129. package/plugins/specweave/lib/hooks/invoke-translator-skill.js +1 -1
  130. package/plugins/specweave/lib/hooks/invoke-translator-skill.js.bak +155 -0
  131. package/plugins/specweave/lib/hooks/invoke-translator-skill.ts +1 -1
  132. package/plugins/specweave/lib/hooks/invoke-translator-skill.ts.bak +264 -0
  133. package/plugins/specweave/lib/hooks/prepare-reflection-context.d.js.bak +0 -0
  134. package/plugins/specweave/lib/hooks/prepare-reflection-context.d.ts.bak +42 -0
  135. package/plugins/specweave/lib/hooks/prepare-reflection-context.js.bak +110 -0
  136. package/plugins/specweave/lib/hooks/prepare-reflection-context.ts.bak +178 -0
  137. package/plugins/specweave/lib/hooks/reflection-config-loader.d.js.bak +0 -0
  138. package/plugins/specweave/lib/hooks/reflection-config-loader.d.ts.bak +45 -0
  139. package/plugins/specweave/lib/hooks/reflection-config-loader.js.bak +92 -0
  140. package/plugins/specweave/lib/hooks/reflection-config-loader.ts.bak +156 -0
  141. package/plugins/specweave/lib/hooks/reflection-parser.d.js.bak +0 -0
  142. package/plugins/specweave/lib/hooks/reflection-parser.d.ts.bak +33 -0
  143. package/plugins/specweave/lib/hooks/reflection-parser.js.bak +301 -0
  144. package/plugins/specweave/lib/hooks/reflection-parser.ts.bak +484 -0
  145. package/plugins/specweave/lib/hooks/reflection-prompt-builder.d.js.bak +0 -0
  146. package/plugins/specweave/lib/hooks/reflection-prompt-builder.d.ts.bak +56 -0
  147. package/plugins/specweave/lib/hooks/reflection-prompt-builder.js.bak +182 -0
  148. package/plugins/specweave/lib/hooks/reflection-prompt-builder.ts.bak +306 -0
  149. package/plugins/specweave/lib/hooks/reflection-storage.d.js.bak +0 -0
  150. package/plugins/specweave/lib/hooks/reflection-storage.d.ts.bak +64 -0
  151. package/plugins/specweave/lib/hooks/reflection-storage.js.bak +231 -0
  152. package/plugins/specweave/lib/hooks/reflection-storage.ts.bak +369 -0
  153. package/plugins/specweave/lib/hooks/run-self-reflection.d.js.bak +0 -0
  154. package/plugins/specweave/lib/hooks/run-self-reflection.d.ts.bak +43 -0
  155. package/plugins/specweave/lib/hooks/run-self-reflection.js.bak +132 -0
  156. package/plugins/specweave/lib/hooks/run-self-reflection.ts.bak +258 -0
  157. package/plugins/specweave/lib/hooks/sync-cache.js.bak +294 -0
  158. package/plugins/specweave/lib/hooks/sync-living-docs.d.js.bak +1 -0
  159. package/plugins/specweave/lib/hooks/sync-living-docs.d.ts.bak +27 -0
  160. package/plugins/specweave/lib/hooks/sync-living-docs.js +35 -1
  161. package/plugins/specweave/lib/hooks/sync-living-docs.js.bak +339 -0
  162. package/plugins/specweave/lib/hooks/sync-us-tasks.js +179 -3
  163. package/plugins/specweave/lib/hooks/sync-us-tasks.js.bak +476 -0
  164. package/plugins/specweave/lib/hooks/translate-file.d.js.bak +0 -0
  165. package/plugins/specweave/lib/hooks/translate-file.d.ts.bak +59 -0
  166. package/plugins/specweave/lib/hooks/translate-file.js +1 -1
  167. package/plugins/specweave/lib/hooks/translate-file.js.bak +289 -0
  168. package/plugins/specweave/lib/hooks/translate-file.ts +1 -1
  169. package/plugins/specweave/lib/hooks/translate-file.ts.bak +428 -0
  170. package/plugins/specweave/lib/hooks/translate-living-docs.d.js.bak +0 -0
  171. package/plugins/specweave/lib/hooks/translate-living-docs.d.ts.bak +13 -0
  172. package/plugins/specweave/lib/hooks/translate-living-docs.js.bak +119 -0
  173. package/plugins/specweave/lib/hooks/translate-living-docs.ts.bak +224 -0
  174. package/plugins/specweave/lib/hooks/update-ac-status.js +1 -1
  175. package/plugins/specweave/lib/hooks/update-ac-status.js.bak +51 -0
  176. package/plugins/specweave/lib/hooks/update-ac-status.ts +1 -1
  177. package/plugins/specweave/lib/hooks/update-ac-status.ts.bak +103 -0
  178. package/plugins/specweave/lib/hooks/update-tasks-md.d.js.bak +1 -0
  179. package/plugins/specweave/lib/hooks/update-tasks-md.d.ts.bak +29 -0
  180. package/plugins/specweave/lib/hooks/update-tasks-md.js.bak +296 -0
  181. package/plugins/specweave/lib/hooks/update-tasks-md.ts.bak +489 -0
  182. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.d.ts +115 -0
  183. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +345 -0
  184. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -0
  185. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.d.ts +106 -0
  186. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +220 -0
  187. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -0
  188. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +60 -0
  189. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +192 -0
  190. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -0
  191. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.d.ts +52 -0
  192. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +276 -0
  193. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -0
  194. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +163 -0
  195. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +541 -0
  196. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -0
  197. package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +157 -0
  198. package/plugins/specweave/lib/vendor/core/types/increment-metadata.js +191 -0
  199. package/plugins/specweave/lib/vendor/core/types/increment-metadata.js.map +1 -0
  200. package/plugins/specweave/lib/vendor/generators/spec/task-parser.d.ts +95 -0
  201. package/plugins/specweave/lib/vendor/generators/spec/task-parser.js +301 -0
  202. package/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -0
  203. package/plugins/specweave/lib/vendor/utils/logger.d.ts +48 -0
  204. package/plugins/specweave/lib/vendor/utils/logger.js +53 -0
  205. package/plugins/specweave/lib/vendor/utils/logger.js.map +1 -0
  206. package/plugins/specweave/lib/vendor/utils/translation.d.ts +187 -0
  207. package/plugins/specweave/lib/vendor/utils/translation.js +414 -0
  208. package/plugins/specweave/lib/vendor/utils/translation.js.map +1 -0
  209. package/plugins/specweave-github/commands/specweave-github-update-user-story.md +1 -1
  210. package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +1 -1
  211. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +531 -0
@@ -0,0 +1,414 @@
1
+ /**
2
+ * Translation Utilities
3
+ *
4
+ * LLM-native translation system for SpecWeave multilingual support.
5
+ * Provides zero-cost language detection and cost-efficient translation
6
+ * using Claude Haiku via current LLM session.
7
+ *
8
+ * Strategy:
9
+ * - Language Detection: Simple heuristic (no API calls, <1ms)
10
+ * - Translation: Claude Haiku via current session (~$0.0025 per file)
11
+ * - Preservation: Markdown, code blocks, technical terms stay intact
12
+ *
13
+ * @see .specweave/increments/0006-llm-native-i18n/reports/DESIGN-POST-GENERATION-TRANSLATION.md
14
+ */
15
+ /**
16
+ * Language detection patterns (Unicode ranges for major scripts)
17
+ */
18
+ const LANGUAGE_PATTERNS = {
19
+ ru: /[а-яА-ЯёЁ]/, // Cyrillic (Russian)
20
+ zh: /[\u4e00-\u9fff]/, // Chinese characters (CJK Unified Ideographs)
21
+ ja: /[\u3040-\u309f\u30a0-\u30ff]/, // Hiragana + Katakana (Japanese)
22
+ ko: /[\uac00-\ud7af]/, // Hangul (Korean)
23
+ ar: /[\u0600-\u06ff]/, // Arabic
24
+ he: /[\u0590-\u05ff]/, // Hebrew
25
+ // Latin-based languages need context (Spanish, German, French, Portuguese)
26
+ // We'll use heuristics for these
27
+ };
28
+ /**
29
+ * Spanish-specific words/patterns
30
+ */
31
+ const SPANISH_INDICATORS = [
32
+ 'ción', 'sión', 'qué', 'cuál', 'español', 'también', 'año', 'señor'
33
+ ];
34
+ /**
35
+ * German-specific words/patterns
36
+ */
37
+ const GERMAN_INDICATORS = [
38
+ 'ß', 'ä', 'ö', 'ü', 'dass', 'ich', 'und', 'der', 'die', 'das'
39
+ ];
40
+ /**
41
+ * French-specific words/patterns
42
+ */
43
+ const FRENCH_INDICATORS = [
44
+ 'ç', 'où', 'être', 'français', 'avec', 'dans', 'pour', 'qui', 'que'
45
+ ];
46
+ /**
47
+ * Portuguese-specific words/patterns
48
+ */
49
+ const PORTUGUESE_INDICATORS = [
50
+ 'ção', 'português', 'também', 'não', 'com', 'para', 'seu', 'sua', 'documentação'
51
+ ];
52
+ /**
53
+ * Detects the language of the given content using simple heuristics
54
+ *
55
+ * @param content - The text content to analyze
56
+ * @returns Language detection result with confidence score
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const result = detectLanguage('Это тестовый документ');
61
+ * console.log(result.language); // 'ru'
62
+ * console.log(result.confidence); // 0.95
63
+ * ```
64
+ */
65
+ export function detectLanguage(content) {
66
+ // Calculate non-ASCII ratio
67
+ const nonAsciiChars = content.match(/[^\x00-\x7F]/g) || [];
68
+ const totalChars = content.length;
69
+ const nonAsciiRatio = totalChars > 0 ? nonAsciiChars.length / totalChars : 0;
70
+ // If <5% non-ASCII, likely English
71
+ if (nonAsciiRatio < 0.05) {
72
+ return {
73
+ language: 'en',
74
+ confidence: 0.95,
75
+ nonAsciiRatio,
76
+ detectionMethod: 'heuristic'
77
+ };
78
+ }
79
+ // Try to detect specific language
80
+ const detected = detectSpecificLanguage(content);
81
+ if (detected !== 'unknown') {
82
+ return {
83
+ language: detected,
84
+ confidence: 0.90,
85
+ nonAsciiRatio,
86
+ detectionMethod: 'heuristic'
87
+ };
88
+ }
89
+ // Fallback: unknown language
90
+ return {
91
+ language: 'unknown',
92
+ confidence: 0.5,
93
+ nonAsciiRatio,
94
+ detectionMethod: 'heuristic'
95
+ };
96
+ }
97
+ /**
98
+ * Detects specific language from content
99
+ *
100
+ * @param content - The text content to analyze
101
+ * @returns Detected language code or 'unknown'
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * detectSpecificLanguage('Это текст'); // 'ru'
106
+ * detectSpecificLanguage('这是文本'); // 'zh'
107
+ * ```
108
+ */
109
+ export function detectSpecificLanguage(content) {
110
+ // Test against Unicode ranges first (most reliable)
111
+ for (const [lang, pattern] of Object.entries(LANGUAGE_PATTERNS)) {
112
+ if (pattern.test(content)) {
113
+ return lang;
114
+ }
115
+ }
116
+ // For Latin-based languages, use indicator words
117
+ const lowerContent = content.toLowerCase();
118
+ // Spanish
119
+ if (SPANISH_INDICATORS.some(indicator => lowerContent.includes(indicator))) {
120
+ return 'es';
121
+ }
122
+ // Portuguese (check before French due to overlap in 'ção' and 'em')
123
+ if (PORTUGUESE_INDICATORS.some(indicator => lowerContent.includes(indicator))) {
124
+ return 'pt';
125
+ }
126
+ // German
127
+ if (GERMAN_INDICATORS.some(indicator => lowerContent.includes(indicator))) {
128
+ return 'de';
129
+ }
130
+ // French
131
+ if (FRENCH_INDICATORS.some(indicator => lowerContent.includes(indicator))) {
132
+ return 'fr';
133
+ }
134
+ return 'unknown';
135
+ }
136
+ /**
137
+ * Preserves code blocks, inline code, and links before translation
138
+ *
139
+ * @param content - Markdown content to preserve
140
+ * @returns Preserved content with placeholders
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const content = 'Text\n```js\ncode\n```\nMore text';
145
+ * const preserved = preserveCodeBlocks(content);
146
+ * // preserved.blocks = ['```js\ncode\n```']
147
+ * // preserved.preserved = 'Text\n__CODE_BLOCK_0__\nMore text'
148
+ * ```
149
+ */
150
+ export function preserveCodeBlocks(content) {
151
+ const blocks = [];
152
+ const inlineCode = [];
153
+ const links = [];
154
+ // 1. Preserve fenced code blocks (```...```)
155
+ let preserved = content.replace(/```[\s\S]*?```/g, (match) => {
156
+ blocks.push(match);
157
+ return `__CODE_BLOCK_${blocks.length - 1}__`;
158
+ });
159
+ // 2. Preserve inline code (`...`)
160
+ preserved = preserved.replace(/`[^`]+`/g, (match) => {
161
+ inlineCode.push(match);
162
+ return `__INLINE_CODE_${inlineCode.length - 1}__`;
163
+ });
164
+ // 3. Preserve markdown links ([text](url))
165
+ preserved = preserved.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, text, url) => {
166
+ links.push(match);
167
+ return `__LINK_${links.length - 1}__`;
168
+ });
169
+ return {
170
+ preserved,
171
+ blocks,
172
+ inlineCode,
173
+ links
174
+ };
175
+ }
176
+ /**
177
+ * Restores preserved code blocks, inline code, and links after translation
178
+ *
179
+ * @param translated - Translated text with placeholders
180
+ * @param preserved - Preserved content structure
181
+ * @returns Restored text with original code blocks and links
182
+ *
183
+ * @example
184
+ * ```typescript
185
+ * const translated = 'Текст\n__CODE_BLOCK_0__\nБольше текста';
186
+ * const preserved = { blocks: ['```js\ncode\n```'], inlineCode: [], links: [] };
187
+ * const restored = restoreCodeBlocks(translated, preserved);
188
+ * // Result: 'Текст\n```js\ncode\n```\nБольше текста'
189
+ * ```
190
+ */
191
+ export function restoreCodeBlocks(translated, preserved) {
192
+ let restored = translated;
193
+ // Restore in reverse order of preservation (links → inline code → blocks)
194
+ // 1. Restore links
195
+ preserved.links.forEach((link, i) => {
196
+ restored = restored.replace(`__LINK_${i}__`, link);
197
+ });
198
+ // 2. Restore inline code
199
+ preserved.inlineCode.forEach((code, i) => {
200
+ restored = restored.replace(`__INLINE_CODE_${i}__`, code);
201
+ });
202
+ // 3. Restore code blocks
203
+ preserved.blocks.forEach((block, i) => {
204
+ restored = restored.replace(`__CODE_BLOCK_${i}__`, block);
205
+ });
206
+ return restored;
207
+ }
208
+ /**
209
+ * Estimates the number of tokens in a text
210
+ * Rule of thumb: ~4 characters per token for English, ~2-3 for other languages
211
+ *
212
+ * @param text - Text to estimate
213
+ * @param language - Language code for estimation
214
+ * @returns Estimated token count
215
+ */
216
+ export function estimateTokens(text, language = 'en') {
217
+ const charsPerToken = language === 'en' ? 4 : 3;
218
+ return Math.ceil(text.length / charsPerToken);
219
+ }
220
+ /**
221
+ * Estimates translation cost using Claude Haiku pricing
222
+ * Haiku pricing (as of 2025): $0.25 per 1M input tokens, $1.25 per 1M output tokens
223
+ *
224
+ * @param inputTokens - Input token count
225
+ * @param outputTokens - Output token count (defaults to input for balanced estimate)
226
+ * @returns Estimated cost in USD
227
+ */
228
+ export function estimateTranslationCost(inputTokens, outputTokens) {
229
+ const HAIKU_INPUT_COST_PER_1M = 0.25;
230
+ const HAIKU_OUTPUT_COST_PER_1M = 1.25;
231
+ const actualOutputTokens = outputTokens || inputTokens; // Assume similar length
232
+ const inputCost = (inputTokens / 1000000) * HAIKU_INPUT_COST_PER_1M;
233
+ const outputCost = (actualOutputTokens / 1000000) * HAIKU_OUTPUT_COST_PER_1M;
234
+ return inputCost + outputCost;
235
+ }
236
+ /**
237
+ * Generates translation prompt for LLM
238
+ *
239
+ * @param content - Content to translate
240
+ * @param sourceLanguage - Source language code
241
+ * @param targetLanguage - Target language code (default: 'en')
242
+ * @returns Translation prompt for LLM
243
+ */
244
+ export function generateTranslationPrompt(content, sourceLanguage, targetLanguage = 'en') {
245
+ const languageNames = {
246
+ en: 'English',
247
+ ru: 'Russian',
248
+ es: 'Spanish',
249
+ zh: 'Chinese',
250
+ de: 'German',
251
+ fr: 'French',
252
+ ja: 'Japanese',
253
+ ko: 'Korean',
254
+ pt: 'Portuguese',
255
+ ar: 'Arabic',
256
+ he: 'Hebrew',
257
+ unknown: 'Unknown'
258
+ };
259
+ const sourceName = languageNames[sourceLanguage] || sourceLanguage;
260
+ const targetName = languageNames[targetLanguage] || targetLanguage;
261
+ return `You are a technical translator specializing in software documentation.
262
+
263
+ Translate the following ${sourceName} document to ${targetName}.
264
+
265
+ PRESERVATION RULES (CRITICAL):
266
+ 1. **Markdown Formatting**: Preserve ALL markdown syntax exactly (headers, lists, links, code blocks, tables)
267
+ 2. **YAML Frontmatter**: Keep structure intact, translate values only
268
+ 3. **Code Blocks**: NEVER translate code (keep as-is, including comments if in English)
269
+ 4. **Inline Code**: NEVER translate \`code spans\` (keep as-is)
270
+ 5. **Technical Terms**: Keep in English (Git, Docker, Kubernetes, TypeScript, React, etc.)
271
+ 6. **Framework Terms**: Keep in English (Increment, Living Docs, SpecWeave, ADR, RFC, HLD, PRD)
272
+ 7. **Document Structure**: Maintain exact heading hierarchy and nesting
273
+ 8. **Links**: Preserve link structure, translate link text only if needed
274
+ 9. **Formatting**: Preserve bold (**text**), italic (*text*), code spans (\`code\`)
275
+ 10. **Placeholders**: Do NOT translate placeholders like __CODE_BLOCK_0__, __INLINE_CODE_1__, __LINK_2__
276
+ 11. **IDs and References**: Keep task IDs (T-001), test IDs (TC-001), user story IDs (US-001) unchanged
277
+
278
+ TRANSLATION STYLE:
279
+ - Professional technical ${targetName}
280
+ - Clear, concise, unambiguous language
281
+ - Industry-standard terminology
282
+ - Consistent term usage throughout
283
+ - Natural phrasing (not word-for-word literal)
284
+
285
+ SOURCE DOCUMENT (${sourceName}):
286
+ ---
287
+ ${content}
288
+ ---
289
+
290
+ TRANSLATED ${targetName.toUpperCase()} VERSION (preserve all formatting):`;
291
+ }
292
+ /**
293
+ * Translates content to English using LLM (Claude Haiku)
294
+ * This function generates the prompt but delegates actual LLM invocation
295
+ * to the caller (via Task tool, skill, or direct API)
296
+ *
297
+ * @param content - Content to translate
298
+ * @param sourceLanguage - Source language code
299
+ * @returns Translation prompt and metadata (caller must invoke LLM)
300
+ *
301
+ * @example
302
+ * ```typescript
303
+ * const content = 'Это тестовый документ';
304
+ * const result = prepareTranslation(content, 'ru');
305
+ * // Caller then invokes LLM with result.prompt
306
+ * ```
307
+ */
308
+ export function prepareTranslation(content, sourceLanguage, targetLanguage = 'en') {
309
+ // 1. Preserve code blocks and links
310
+ const preserved = preserveCodeBlocks(content);
311
+ // 2. Generate translation prompt
312
+ const prompt = generateTranslationPrompt(preserved.preserved, sourceLanguage, targetLanguage);
313
+ // 3. Estimate cost
314
+ const inputTokens = estimateTokens(prompt, sourceLanguage);
315
+ const outputTokens = estimateTokens(preserved.preserved, targetLanguage);
316
+ const estimatedCost = estimateTranslationCost(inputTokens, outputTokens);
317
+ return {
318
+ prompt,
319
+ preserved,
320
+ estimatedTokens: inputTokens + outputTokens,
321
+ estimatedCost
322
+ };
323
+ }
324
+ /**
325
+ * Post-processes translated content
326
+ * Restores code blocks, validates markdown, cleans up extra whitespace
327
+ *
328
+ * @param translated - Translated text from LLM
329
+ * @param preserved - Preserved content structure
330
+ * @returns Cleaned and restored translated content
331
+ */
332
+ export function postProcessTranslation(translated, preserved) {
333
+ // 1. Restore preserved blocks
334
+ let restored = restoreCodeBlocks(translated, preserved);
335
+ // 2. Clean up extra whitespace (LLM sometimes adds extra newlines)
336
+ restored = restored
337
+ .replace(/\n{4,}/g, '\n\n\n') // Max 3 consecutive newlines
338
+ .replace(/[ \t]+$/gm, ''); // Remove trailing spaces
339
+ // 3. Ensure file ends with single newline
340
+ restored = restored.trim() + '\n';
341
+ return restored;
342
+ }
343
+ /**
344
+ * Validates that translated content preserves markdown structure
345
+ * Returns warnings if structure doesn't match
346
+ *
347
+ * @param original - Original content
348
+ * @param translated - Translated content
349
+ * @returns Array of validation warnings (empty if valid)
350
+ */
351
+ export function validateTranslation(original, translated) {
352
+ const warnings = [];
353
+ // 1. Check heading count matches
354
+ const originalHeadings = (original.match(/^#{1,6}\s/gm) || []).length;
355
+ const translatedHeadings = (translated.match(/^#{1,6}\s/gm) || []).length;
356
+ if (originalHeadings !== translatedHeadings) {
357
+ warnings.push(`Heading count mismatch: original has ${originalHeadings}, translated has ${translatedHeadings}`);
358
+ }
359
+ // 2. Check code block count matches
360
+ const originalCodeBlocks = (original.match(/```/g) || []).length;
361
+ const translatedCodeBlocks = (translated.match(/```/g) || []).length;
362
+ if (originalCodeBlocks !== translatedCodeBlocks) {
363
+ warnings.push(`Code block count mismatch: original has ${originalCodeBlocks}, translated has ${translatedCodeBlocks}`);
364
+ }
365
+ // 3. Check link count matches
366
+ const originalLinks = (original.match(/\[([^\]]+)\]\(([^)]+)\)/g) || []).length;
367
+ const translatedLinks = (translated.match(/\[([^\]]+)\]\(([^)]+)\)/g) || []).length;
368
+ if (originalLinks !== translatedLinks) {
369
+ warnings.push(`Link count mismatch: original has ${originalLinks}, translated has ${translatedLinks}`);
370
+ }
371
+ // 4. Check YAML frontmatter present in both (if exists in original)
372
+ const hasOriginalYAML = /^---\n[\s\S]*?\n---/m.test(original);
373
+ const hasTranslatedYAML = /^---\n[\s\S]*?\n---/m.test(translated);
374
+ if (hasOriginalYAML && !hasTranslatedYAML) {
375
+ warnings.push('YAML frontmatter missing in translation');
376
+ }
377
+ return warnings;
378
+ }
379
+ /**
380
+ * Gets human-readable language name
381
+ *
382
+ * @param code - Language code
383
+ * @returns Human-readable name
384
+ */
385
+ export function getLanguageName(code) {
386
+ const names = {
387
+ en: 'English',
388
+ ru: 'Russian',
389
+ es: 'Spanish',
390
+ zh: 'Chinese',
391
+ de: 'German',
392
+ fr: 'French',
393
+ ja: 'Japanese',
394
+ ko: 'Korean',
395
+ pt: 'Portuguese',
396
+ ar: 'Arabic',
397
+ he: 'Hebrew',
398
+ unknown: 'Unknown'
399
+ };
400
+ return names[code] || code;
401
+ }
402
+ /**
403
+ * Formats cost for display
404
+ *
405
+ * @param cost - Cost in USD
406
+ * @returns Formatted string (e.g., "$0.0025" or "<$0.001")
407
+ */
408
+ export function formatCost(cost) {
409
+ if (cost < 0.001) {
410
+ return '<$0.001';
411
+ }
412
+ return `$${cost.toFixed(4)}`;
413
+ }
414
+ //# sourceMappingURL=translation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translation.js","sourceRoot":"","sources":["../../../src/utils/translation.ts"],"names":[],"mappings":"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"}
@@ -53,7 +53,7 @@ description: Update GitHub issue for user story with proper ACs and tasks
53
53
  **What Gets Updated**:
54
54
 
55
55
  ```markdown
56
- **Feature**: [FS-031](../../_features/FS-031/FEATURE.md)
56
+ **Feature**: [FS-031](../../_features/_archive/FS-031/FEATURE.md)
57
57
  **Status**: complete
58
58
  **Priority**: P1
59
59
  **Project**: default
@@ -94,7 +94,7 @@ if (repo && taskLink.startsWith('../../')) {
94
94
  **I want** feature
95
95
  **So that** benefit
96
96
 
97
- 📄 View full story: [`us-004-name.md`](https://github.com/owner/repo/tree/develop/.specweave/docs/internal/specs/default/FS-031/us-004-name.md)
97
+ 📄 View full story: [`us-004-name.md`](https://github.com/owner/repo/tree/develop/.specweave/docs/internal/specs/default/_archive/FS-031/us-004-name.md)
98
98
 
99
99
  ---
100
100