specweave 0.6.8 → 0.7.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/.claude-plugin/README.md +1 -1
- package/CLAUDE.md +903 -99
- package/README.md +143 -207
- package/bin/specweave.js +67 -0
- package/dist/cli/commands/abandon.d.ts +13 -0
- package/dist/cli/commands/abandon.d.ts.map +1 -0
- package/dist/cli/commands/abandon.js +15 -0
- package/dist/cli/commands/abandon.js.map +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +90 -18
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/pause.d.ts +13 -0
- package/dist/cli/commands/pause.d.ts.map +1 -0
- package/dist/cli/commands/pause.js +15 -0
- package/dist/cli/commands/pause.js.map +1 -0
- package/dist/cli/commands/qa.d.ts +54 -0
- package/dist/cli/commands/qa.d.ts.map +1 -0
- package/dist/cli/commands/qa.js +98 -0
- package/dist/cli/commands/qa.js.map +1 -0
- package/dist/cli/commands/resume.d.ts +12 -0
- package/dist/cli/commands/resume.d.ts.map +1 -0
- package/dist/cli/commands/resume.js +14 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/status.d.ts +12 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +23 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/helpers/issue-tracker/ado.d.ts +57 -0
- package/dist/cli/helpers/issue-tracker/ado.d.ts.map +1 -0
- package/dist/cli/helpers/issue-tracker/ado.js +223 -0
- package/dist/cli/helpers/issue-tracker/ado.js.map +1 -0
- package/dist/cli/helpers/issue-tracker/github.d.ts +65 -0
- package/dist/cli/helpers/issue-tracker/github.d.ts.map +1 -0
- package/dist/cli/helpers/issue-tracker/github.js +284 -0
- package/dist/cli/helpers/issue-tracker/github.js.map +1 -0
- package/dist/cli/helpers/issue-tracker/index.d.ts +22 -0
- package/dist/cli/helpers/issue-tracker/index.d.ts.map +1 -0
- package/dist/cli/helpers/issue-tracker/index.js +270 -0
- package/dist/cli/helpers/issue-tracker/index.js.map +1 -0
- package/dist/cli/helpers/issue-tracker/jira.d.ts +61 -0
- package/dist/cli/helpers/issue-tracker/jira.d.ts.map +1 -0
- package/dist/cli/helpers/issue-tracker/jira.js +265 -0
- package/dist/cli/helpers/issue-tracker/jira.js.map +1 -0
- package/dist/cli/helpers/issue-tracker/types.d.ts +86 -0
- package/dist/cli/helpers/issue-tracker/types.d.ts.map +1 -0
- package/dist/cli/helpers/issue-tracker/types.js +16 -0
- package/dist/cli/helpers/issue-tracker/types.js.map +1 -0
- package/dist/cli/helpers/issue-tracker/utils.d.ts +103 -0
- package/dist/cli/helpers/issue-tracker/utils.d.ts.map +1 -0
- package/dist/cli/helpers/issue-tracker/utils.js +240 -0
- package/dist/cli/helpers/issue-tracker/utils.js.map +1 -0
- package/dist/core/increment/limits.d.ts +68 -0
- package/dist/core/increment/limits.d.ts.map +1 -0
- package/dist/core/increment/limits.js +224 -0
- package/dist/core/increment/limits.js.map +1 -0
- package/dist/core/increment/metadata-manager.d.ts +114 -0
- package/dist/core/increment/metadata-manager.d.ts.map +1 -0
- package/dist/core/increment/metadata-manager.js +320 -0
- package/dist/core/increment/metadata-manager.js.map +1 -0
- package/dist/core/increment/status-commands.d.ts +43 -0
- package/dist/core/increment/status-commands.d.ts.map +1 -0
- package/dist/core/increment/status-commands.js +277 -0
- package/dist/core/increment/status-commands.js.map +1 -0
- package/dist/core/plugin-detector.d.ts +1 -0
- package/dist/core/plugin-detector.d.ts.map +1 -1
- package/dist/core/plugin-detector.js +25 -0
- package/dist/core/plugin-detector.js.map +1 -1
- package/dist/core/qa/qa-runner.d.ts +16 -0
- package/dist/core/qa/qa-runner.d.ts.map +1 -0
- package/dist/core/qa/qa-runner.js +404 -0
- package/dist/core/qa/qa-runner.js.map +1 -0
- package/dist/core/qa/quality-gate-decider.d.ts +53 -0
- package/dist/core/qa/quality-gate-decider.d.ts.map +1 -0
- package/dist/core/qa/quality-gate-decider.js +268 -0
- package/dist/core/qa/quality-gate-decider.js.map +1 -0
- package/dist/core/qa/risk-calculator.d.ts +126 -0
- package/dist/core/qa/risk-calculator.d.ts.map +1 -0
- package/dist/core/qa/risk-calculator.js +247 -0
- package/dist/core/qa/risk-calculator.js.map +1 -0
- package/dist/core/qa/types.d.ts +315 -0
- package/dist/core/qa/types.d.ts.map +1 -0
- package/dist/core/qa/types.js +8 -0
- package/dist/core/qa/types.js.map +1 -0
- package/dist/core/types/config.d.ts +35 -0
- package/dist/core/types/config.d.ts.map +1 -1
- package/dist/core/types/config.js +16 -0
- package/dist/core/types/config.js.map +1 -1
- package/dist/core/types/increment-metadata.d.ts +120 -0
- package/dist/core/types/increment-metadata.d.ts.map +1 -0
- package/dist/core/types/increment-metadata.js +138 -0
- package/dist/core/types/increment-metadata.js.map +1 -0
- package/dist/hooks/lib/invoke-translator-skill.d.ts +60 -0
- package/dist/hooks/lib/invoke-translator-skill.d.ts.map +1 -0
- package/dist/hooks/lib/invoke-translator-skill.js +201 -0
- package/dist/hooks/lib/invoke-translator-skill.js.map +1 -0
- package/dist/hooks/lib/translate-file.d.ts +59 -0
- package/dist/hooks/lib/translate-file.d.ts.map +1 -0
- package/dist/hooks/lib/translate-file.js +350 -0
- package/dist/hooks/lib/translate-file.js.map +1 -0
- package/dist/locales/en/cli.json +3 -1
- package/dist/metrics/calculators/change-failure-rate.d.ts +22 -0
- package/dist/metrics/calculators/change-failure-rate.d.ts.map +1 -0
- package/dist/metrics/calculators/change-failure-rate.js +70 -0
- package/dist/metrics/calculators/change-failure-rate.js.map +1 -0
- package/dist/metrics/calculators/deployment-frequency.d.ts +20 -0
- package/dist/metrics/calculators/deployment-frequency.d.ts.map +1 -0
- package/dist/metrics/calculators/deployment-frequency.js +61 -0
- package/dist/metrics/calculators/deployment-frequency.js.map +1 -0
- package/dist/metrics/calculators/lead-time.d.ts +22 -0
- package/dist/metrics/calculators/lead-time.d.ts.map +1 -0
- package/dist/metrics/calculators/lead-time.js +82 -0
- package/dist/metrics/calculators/lead-time.js.map +1 -0
- package/dist/metrics/calculators/mttr.d.ts +21 -0
- package/dist/metrics/calculators/mttr.d.ts.map +1 -0
- package/dist/metrics/calculators/mttr.js +60 -0
- package/dist/metrics/calculators/mttr.js.map +1 -0
- package/dist/metrics/dora-calculator.d.ts +24 -0
- package/dist/metrics/dora-calculator.d.ts.map +1 -0
- package/dist/metrics/dora-calculator.js +104 -0
- package/dist/metrics/dora-calculator.js.map +1 -0
- package/dist/metrics/github-client.d.ts +51 -0
- package/dist/metrics/github-client.d.ts.map +1 -0
- package/dist/metrics/github-client.js +133 -0
- package/dist/metrics/github-client.js.map +1 -0
- package/dist/metrics/types.d.ts +112 -0
- package/dist/metrics/types.d.ts.map +1 -0
- package/dist/metrics/types.js +10 -0
- package/dist/metrics/types.js.map +1 -0
- package/dist/metrics/utils/percentile.d.ts +25 -0
- package/dist/metrics/utils/percentile.d.ts.map +1 -0
- package/dist/metrics/utils/percentile.js +46 -0
- package/dist/metrics/utils/percentile.js.map +1 -0
- package/dist/metrics/utils/tier-classifier.d.ts +61 -0
- package/dist/metrics/utils/tier-classifier.d.ts.map +1 -0
- package/dist/metrics/utils/tier-classifier.js +100 -0
- package/dist/metrics/utils/tier-classifier.js.map +1 -0
- package/dist/utils/auth-helpers.d.ts +58 -0
- package/dist/utils/auth-helpers.d.ts.map +1 -0
- package/dist/utils/auth-helpers.js +108 -0
- package/dist/utils/auth-helpers.js.map +1 -0
- package/dist/utils/env-file.d.ts +88 -0
- package/dist/utils/env-file.d.ts.map +1 -0
- package/dist/utils/env-file.js +180 -0
- package/dist/utils/env-file.js.map +1 -0
- package/dist/utils/plugin-detection.d.ts +50 -0
- package/dist/utils/plugin-detection.d.ts.map +1 -0
- package/dist/utils/plugin-detection.js +229 -0
- package/dist/utils/plugin-detection.js.map +1 -0
- package/dist/utils/secrets-loader.d.ts +88 -0
- package/dist/utils/secrets-loader.d.ts.map +1 -0
- package/dist/utils/secrets-loader.js +271 -0
- package/dist/utils/secrets-loader.js.map +1 -0
- package/dist/utils/translation.d.ts +187 -0
- package/dist/utils/translation.d.ts.map +1 -0
- package/dist/utils/translation.js +414 -0
- package/dist/utils/translation.js.map +1 -0
- package/package.json +28 -44
- package/plugins/specweave/.claude-plugin/plugin.json +3 -3
- package/plugins/specweave/agents/pm/AGENT.md +330 -54
- package/plugins/specweave/agents/test-aware-planner/AGENT.md +1035 -0
- package/plugins/specweave/agents/test-aware-planner/templates/README.md +118 -0
- package/plugins/specweave/agents/test-aware-planner/templates/task-non-testable.md.template +24 -0
- package/plugins/specweave/agents/test-aware-planner/templates/task-testable.md.template +53 -0
- package/plugins/specweave/agents/test-aware-planner/templates/tasks-frontmatter.md.template +11 -0
- package/plugins/specweave/commands/README.md +88 -163
- package/plugins/specweave/commands/specweave-abandon.md +314 -0
- package/plugins/specweave/commands/specweave-check-tests.md +546 -0
- package/plugins/specweave/commands/{do.md → specweave-do.md} +5 -7
- package/plugins/specweave/commands/{increment.md → specweave-increment.md} +231 -4
- package/plugins/specweave/commands/specweave-pause.md +189 -0
- package/plugins/specweave/commands/specweave-qa.md +245 -0
- package/plugins/specweave/commands/specweave-resume.md +216 -0
- package/plugins/specweave/commands/specweave-status.md +397 -0
- package/plugins/specweave/commands/specweave-sync-tasks.md +256 -0
- package/plugins/specweave/commands/{translate.md → specweave-translate.md} +3 -3
- package/plugins/specweave/commands/specweave-update-scope.md +351 -0
- package/plugins/specweave/commands/specweave.md +21 -21
- package/plugins/specweave/hooks/post-increment-planning.sh +335 -0
- package/plugins/specweave/hooks/post-task-completion.sh +141 -0
- package/plugins/specweave/skills/SKILLS-INDEX.md +1 -1
- package/plugins/specweave/skills/brownfield-analyzer/SKILL.md +9 -9
- package/plugins/specweave/skills/increment-planner/SKILL.md +400 -212
- package/plugins/specweave/skills/increment-quality-judge-v2/SKILL.md +499 -0
- package/plugins/specweave/skills/plugin-detector/SKILL.md +114 -1
- package/plugins/specweave/skills/project-kickstarter/SKILL.md +74 -1
- package/plugins/specweave/skills/{rfc-generator → spec-generator}/SKILL.md +22 -29
- package/plugins/specweave/skills/specweave-detector/SKILL.md +3 -3
- package/plugins/specweave/skills/specweave-framework/SKILL.md +2 -2
- package/plugins/specweave-ado/.claude-plugin/plugin.json +18 -4
- package/plugins/specweave-ado/agents/ado-manager/AGENT.md +426 -0
- package/plugins/specweave-ado/commands/close-workitem.md +52 -0
- package/plugins/specweave-ado/commands/create-workitem.md +53 -0
- package/plugins/specweave-ado/commands/status.md +53 -0
- package/plugins/specweave-ado/commands/sync.md +55 -0
- package/plugins/specweave-ado/lib/ado-client.ts +361 -0
- package/plugins/specweave-ado/reference/ado-specweave-mapping.md +552 -0
- package/plugins/specweave-ado/skills/ado-sync/SKILL.md +344 -193
- package/plugins/specweave-docs/skills/docusaurus/SKILL.md +73 -0
- package/plugins/specweave-github/agents/github-manager/AGENT.md +49 -0
- package/plugins/specweave-github/commands/{github-close-issue.md → close-issue.md} +1 -1
- package/plugins/specweave-github/commands/{github-create-issue.md → create-issue.md} +1 -1
- package/plugins/specweave-github/commands/{github-status.md → status.md} +1 -1
- package/plugins/specweave-github/commands/{github-sync-tasks.md → sync-tasks.md} +1 -1
- package/plugins/specweave-github/commands/{github-sync.md → sync.md} +1 -1
- package/plugins/specweave-github/reference/github-specweave-mapping.md +377 -0
- package/plugins/specweave-github/skills/github-sync/SKILL.md +11 -3
- package/plugins/specweave-infrastructure/commands/{specweave.monitor-setup.md → monitor-setup.md} +5 -0
- package/plugins/specweave-infrastructure/commands/{specweave.slo-implement.md → slo-implement.md} +5 -0
- package/plugins/specweave-jira/agents/jira-manager/AGENT.md +380 -0
- package/plugins/specweave-jira/commands/{specweave.sync-jira.md → sync.md} +1 -1
- package/plugins/specweave-jira/reference/jira-specweave-mapping.md +508 -0
- package/plugins/specweave-ml/commands/ml-deploy.md +1 -1
- package/plugins/specweave-ml/commands/ml-evaluate.md +1 -1
- package/plugins/specweave-ml/commands/ml-explain.md +1 -1
- package/plugins/specweave-ml/commands/{specweave.ml-pipeline.md → ml-pipeline.md} +5 -0
- package/src/templates/AGENTS.md.template +331 -31
- package/src/templates/CLAUDE.md.template +36 -21
- package/src/templates/COMPLETION-REPORT.template.md +128 -0
- package/src/templates/README.md.template +17 -16
- package/src/templates/docs/README.md +11 -9
- package/src/templates/docs/spec-template.md +229 -0
- package/plugins/specweave/commands/inc.md +0 -85
- package/plugins/specweave/commands/list-increments.md +0 -180
- package/src/adapters/README.md +0 -275
- package/src/adapters/adapter-base.ts +0 -182
- package/src/adapters/adapter-interface.ts +0 -166
- package/src/adapters/adapter-loader.ts +0 -256
- package/src/adapters/agents-md-generator.ts +0 -228
- package/src/adapters/claude/README.md +0 -233
- package/src/adapters/claude/adapter.ts +0 -468
- package/src/adapters/claude-md-generator.ts +0 -377
- package/src/adapters/codex/README.md +0 -105
- package/src/adapters/codex/adapter.ts +0 -333
- package/src/adapters/cursor/.cursor/context/docs-context.md +0 -62
- package/src/adapters/cursor/.cursor/context/increments-context.md +0 -71
- package/src/adapters/cursor/.cursor/context/strategy-context.md +0 -73
- package/src/adapters/cursor/.cursor/context/tests-context.md +0 -89
- package/src/adapters/cursor/README.md +0 -283
- package/src/adapters/cursor/adapter.ts +0 -451
- package/src/adapters/doc-generator.ts +0 -331
- package/src/adapters/gemini/README.md +0 -97
- package/src/adapters/gemini/adapter.ts +0 -298
- package/src/adapters/generic/README.md +0 -277
- package/src/adapters/generic/adapter.ts +0 -378
- package/src/adapters/registry.yaml +0 -187
- /package/plugins/specweave/commands/{costs.md → specweave-costs.md} +0 -0
- /package/plugins/specweave/commands/{done.md → specweave-done.md} +0 -0
- /package/plugins/specweave/commands/{next.md → specweave-next.md} +0 -0
- /package/plugins/specweave/commands/{progress.md → specweave-progress.md} +0 -0
- /package/plugins/specweave/commands/{sync-docs.md → specweave-sync-docs.md} +0 -0
- /package/plugins/specweave/commands/{tdd-cycle.md → specweave-tdd-cycle.md} +0 -0
- /package/plugins/specweave/commands/{tdd-green.md → specweave-tdd-green.md} +0 -0
- /package/plugins/specweave/commands/{tdd-red.md → specweave-tdd-red.md} +0 -0
- /package/plugins/specweave/commands/{tdd-refactor.md → specweave-tdd-refactor.md} +0 -0
- /package/plugins/specweave/commands/{validate.md → specweave-validate.md} +0 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Translation CLI Utility
|
|
3
|
+
*
|
|
4
|
+
* Translates a single file from detected source language to target language
|
|
5
|
+
* using the translation utilities and LLM invocation.
|
|
6
|
+
*
|
|
7
|
+
* This script is called from:
|
|
8
|
+
* - Post-increment-planning hook (auto-translate spec.md, plan.md, tasks.md)
|
|
9
|
+
* - Post-task-completion hook (auto-translate living docs)
|
|
10
|
+
* - Manual /specweave:translate command
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* node translate-file.js <file-path> [--target-lang en] [--preview]
|
|
14
|
+
*
|
|
15
|
+
* @see src/utils/translation.ts
|
|
16
|
+
* @see .specweave/increments/0006-llm-native-i18n/reports/DESIGN-POST-GENERATION-TRANSLATION.md
|
|
17
|
+
*/
|
|
18
|
+
import fs from 'fs-extra';
|
|
19
|
+
import { detectLanguage, prepareTranslation, postProcessTranslation, validateTranslation, getLanguageName, formatCost, } from '../../utils/translation.js';
|
|
20
|
+
/**
|
|
21
|
+
* Main translation function
|
|
22
|
+
*
|
|
23
|
+
* @param options - CLI options
|
|
24
|
+
* @returns Translation result
|
|
25
|
+
*/
|
|
26
|
+
export async function translateFile(options) {
|
|
27
|
+
const { filePath, targetLang, preview, verbose } = options;
|
|
28
|
+
// 1. Validate file exists
|
|
29
|
+
if (!await fs.pathExists(filePath)) {
|
|
30
|
+
throw new Error(`File not found: ${filePath}`);
|
|
31
|
+
}
|
|
32
|
+
if (verbose) {
|
|
33
|
+
console.log(`📄 Reading file: ${filePath}`);
|
|
34
|
+
}
|
|
35
|
+
// 2. Read original content
|
|
36
|
+
const originalContent = await fs.readFile(filePath, 'utf-8');
|
|
37
|
+
// 3. Detect source language
|
|
38
|
+
const detectionResult = detectLanguage(originalContent);
|
|
39
|
+
const sourceLanguage = detectionResult.language;
|
|
40
|
+
if (verbose) {
|
|
41
|
+
console.log(`🔍 Detected language: ${getLanguageName(sourceLanguage)} (confidence: ${(detectionResult.confidence * 100).toFixed(0)}%)`);
|
|
42
|
+
}
|
|
43
|
+
// 4. Check if already in target language
|
|
44
|
+
if (sourceLanguage === targetLang) {
|
|
45
|
+
if (verbose) {
|
|
46
|
+
console.log(`✅ File already in ${getLanguageName(targetLang)}, skipping translation`);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
success: true,
|
|
50
|
+
filePath,
|
|
51
|
+
sourceLanguage,
|
|
52
|
+
targetLanguage: targetLang,
|
|
53
|
+
warnings: [`Already in ${getLanguageName(targetLang)}`],
|
|
54
|
+
cost: 0,
|
|
55
|
+
tokensUsed: 0,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// 5. Check if source language is unknown
|
|
59
|
+
if (sourceLanguage === 'unknown') {
|
|
60
|
+
if (verbose) {
|
|
61
|
+
console.warn(`⚠️ Could not detect language, assuming English`);
|
|
62
|
+
}
|
|
63
|
+
// Assume English if detection fails
|
|
64
|
+
return {
|
|
65
|
+
success: false,
|
|
66
|
+
filePath,
|
|
67
|
+
sourceLanguage: 'unknown',
|
|
68
|
+
targetLanguage: targetLang,
|
|
69
|
+
warnings: ['Language detection failed - file may already be in English or mixed language'],
|
|
70
|
+
cost: 0,
|
|
71
|
+
tokensUsed: 0,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// 6. Prepare translation
|
|
75
|
+
if (verbose) {
|
|
76
|
+
console.log(`🌐 Translating from ${getLanguageName(sourceLanguage)} to ${getLanguageName(targetLang)}...`);
|
|
77
|
+
console.log(`💰 Estimated cost: ${formatCost(0.003)} (using Haiku)`);
|
|
78
|
+
}
|
|
79
|
+
const prepared = prepareTranslation(originalContent, sourceLanguage, targetLang);
|
|
80
|
+
// 7. Invoke LLM for translation
|
|
81
|
+
// NOTE: This is where we call the actual LLM
|
|
82
|
+
// For now, we'll create a simple prompt that can be used with Claude Code's Task tool
|
|
83
|
+
const translatedContent = await invokeLLMTranslation(prepared.prompt, verbose);
|
|
84
|
+
// 8. Post-process translation
|
|
85
|
+
const finalContent = postProcessTranslation(translatedContent, prepared.preserved);
|
|
86
|
+
// 9. Validate translation
|
|
87
|
+
const warnings = validateTranslation(originalContent, finalContent);
|
|
88
|
+
if (warnings.length > 0 && verbose) {
|
|
89
|
+
console.warn(`⚠️ Translation warnings:`);
|
|
90
|
+
warnings.forEach(w => console.warn(` - ${w}`));
|
|
91
|
+
}
|
|
92
|
+
// 10. Preview or write
|
|
93
|
+
if (preview) {
|
|
94
|
+
if (verbose) {
|
|
95
|
+
console.log(`\n📋 PREVIEW (first 500 chars):\n`);
|
|
96
|
+
console.log(finalContent.substring(0, 500));
|
|
97
|
+
console.log(`\n... (${finalContent.length} total characters)\n`);
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
success: true,
|
|
101
|
+
filePath,
|
|
102
|
+
sourceLanguage,
|
|
103
|
+
targetLanguage: targetLang,
|
|
104
|
+
warnings,
|
|
105
|
+
cost: prepared.estimatedCost,
|
|
106
|
+
tokensUsed: prepared.estimatedTokens,
|
|
107
|
+
preview: finalContent,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// Write translated content back to file
|
|
112
|
+
await fs.writeFile(filePath, finalContent, 'utf-8');
|
|
113
|
+
if (verbose) {
|
|
114
|
+
console.log(`✅ Translation complete: ${filePath}`);
|
|
115
|
+
console.log(` Tokens used: ${prepared.estimatedTokens.toLocaleString()}`);
|
|
116
|
+
console.log(` Cost: ${formatCost(prepared.estimatedCost)}`);
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
success: true,
|
|
120
|
+
filePath,
|
|
121
|
+
sourceLanguage,
|
|
122
|
+
targetLanguage: targetLang,
|
|
123
|
+
warnings,
|
|
124
|
+
cost: prepared.estimatedCost,
|
|
125
|
+
tokensUsed: prepared.estimatedTokens,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Invokes LLM for translation using Anthropic API
|
|
131
|
+
*
|
|
132
|
+
* PRODUCTION IMPLEMENTATION:
|
|
133
|
+
* 1. Checks for ANTHROPIC_API_KEY in environment
|
|
134
|
+
* 2. If available: Uses Anthropic API directly (fully automatic)
|
|
135
|
+
* 3. If not available: Provides clear instructions for manual translation
|
|
136
|
+
*
|
|
137
|
+
* @param prompt - Translation prompt
|
|
138
|
+
* @param verbose - Show detailed output
|
|
139
|
+
* @returns Translated content
|
|
140
|
+
*/
|
|
141
|
+
async function invokeLLMTranslation(prompt, verbose) {
|
|
142
|
+
// Extract the content to translate (between --- markers)
|
|
143
|
+
const contentMatch = prompt.match(/SOURCE DOCUMENT[^\n]*:\n---\n([\s\S]*?)\n---/);
|
|
144
|
+
const contentToTranslate = contentMatch ? contentMatch[1] : '';
|
|
145
|
+
// Check if ANTHROPIC_API_KEY is available
|
|
146
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
147
|
+
if (apiKey) {
|
|
148
|
+
// Fully automatic translation using Anthropic API
|
|
149
|
+
if (verbose) {
|
|
150
|
+
console.log(`\n🤖 Translating via Anthropic API (Haiku model)...`);
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
// Dynamic import of Anthropic SDK (allows graceful fallback if not installed)
|
|
154
|
+
const Anthropic = await import('@anthropic-ai/sdk').then(m => m.default);
|
|
155
|
+
const anthropic = new Anthropic({
|
|
156
|
+
apiKey,
|
|
157
|
+
});
|
|
158
|
+
const message = await anthropic.messages.create({
|
|
159
|
+
model: 'claude-3-haiku-20240307',
|
|
160
|
+
max_tokens: 8000,
|
|
161
|
+
messages: [
|
|
162
|
+
{
|
|
163
|
+
role: 'user',
|
|
164
|
+
content: prompt,
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
});
|
|
168
|
+
// Extract translated content from response
|
|
169
|
+
const translatedContent = message.content[0].type === 'text'
|
|
170
|
+
? message.content[0].text
|
|
171
|
+
: contentToTranslate;
|
|
172
|
+
if (verbose) {
|
|
173
|
+
console.log(`✅ Translation complete via API`);
|
|
174
|
+
console.log(` Model: claude-3-haiku-20240307`);
|
|
175
|
+
console.log(` Input tokens: ${message.usage.input_tokens}`);
|
|
176
|
+
console.log(` Output tokens: ${message.usage.output_tokens}`);
|
|
177
|
+
console.log(` Cost: ~$${((message.usage.input_tokens * 0.25 + message.usage.output_tokens * 1.25) / 1000000).toFixed(4)}`);
|
|
178
|
+
}
|
|
179
|
+
return translatedContent;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
console.error(`\n❌ API translation failed: ${error.message}`);
|
|
183
|
+
console.error(` Falling back to manual translation instructions\n`);
|
|
184
|
+
// Fall through to manual instructions
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Fallback: Manual translation instructions
|
|
188
|
+
const isInteractive = process.stdout.isTTY && process.env.CLAUDE_CODE_SESSION;
|
|
189
|
+
if (isInteractive) {
|
|
190
|
+
// Interactive mode: Output prompt for Claude to process
|
|
191
|
+
if (verbose) {
|
|
192
|
+
console.log(`\n🤖 Invoking Claude Code translator skill...`);
|
|
193
|
+
console.log(` (Tip: Set ANTHROPIC_API_KEY for fully automatic translation)\n`);
|
|
194
|
+
}
|
|
195
|
+
// Output the translation prompt
|
|
196
|
+
// The translator skill should auto-activate on this prompt
|
|
197
|
+
console.log('\n' + '='.repeat(80));
|
|
198
|
+
console.log('TRANSLATION REQUEST (translator skill will auto-activate):');
|
|
199
|
+
console.log('='.repeat(80));
|
|
200
|
+
console.log(prompt);
|
|
201
|
+
console.log('='.repeat(80) + '\n');
|
|
202
|
+
// In interactive mode, we expect the user/Claude to provide translation
|
|
203
|
+
// For now, return a marker indicating manual intervention needed
|
|
204
|
+
return `<!-- ⚠️ TRANSLATION IN PROGRESS - Manual translation required via translator skill -->\n\n${contentToTranslate}`;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
// Non-interactive/automated mode: Provide clear instructions
|
|
208
|
+
if (verbose) {
|
|
209
|
+
console.log(`\n🤖 Generating translation (automated mode)...`);
|
|
210
|
+
}
|
|
211
|
+
console.error('\n⚠️ AUTO-TRANSLATION REQUIRES MANUAL STEP:');
|
|
212
|
+
console.error(' Option A (Recommended): Set ANTHROPIC_API_KEY environment variable');
|
|
213
|
+
console.error(' Option B: Run /specweave:translate <file-path>');
|
|
214
|
+
console.error(' Option C: Manually translate the content\n');
|
|
215
|
+
// Return original content with clear marker
|
|
216
|
+
return `<!-- ⚠️ AUTO-TRANSLATION PENDING -->\n<!-- Set ANTHROPIC_API_KEY for automatic translation -->\n<!-- Or run: /specweave:translate to complete -->\n<!-- Original content below -->\n\n${contentToTranslate}`;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Batch translate multiple files
|
|
221
|
+
*
|
|
222
|
+
* @param filePaths - Array of file paths to translate
|
|
223
|
+
* @param targetLang - Target language
|
|
224
|
+
* @param preview - Preview mode
|
|
225
|
+
* @param verbose - Verbose output
|
|
226
|
+
* @returns Array of translation results
|
|
227
|
+
*/
|
|
228
|
+
export async function batchTranslateFiles(filePaths, targetLang = 'en', preview = false, verbose = false) {
|
|
229
|
+
const results = [];
|
|
230
|
+
if (verbose) {
|
|
231
|
+
console.log(`\n🔄 Batch translating ${filePaths.length} file(s) to ${getLanguageName(targetLang)}...\n`);
|
|
232
|
+
}
|
|
233
|
+
for (const filePath of filePaths) {
|
|
234
|
+
try {
|
|
235
|
+
const result = await translateFile({
|
|
236
|
+
filePath,
|
|
237
|
+
targetLang,
|
|
238
|
+
preview,
|
|
239
|
+
verbose,
|
|
240
|
+
});
|
|
241
|
+
results.push(result);
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
if (verbose) {
|
|
245
|
+
console.error(`❌ Error translating ${filePath}: ${error.message}`);
|
|
246
|
+
}
|
|
247
|
+
results.push({
|
|
248
|
+
success: false,
|
|
249
|
+
filePath,
|
|
250
|
+
sourceLanguage: 'unknown',
|
|
251
|
+
targetLanguage: targetLang,
|
|
252
|
+
warnings: [error.message],
|
|
253
|
+
cost: 0,
|
|
254
|
+
tokensUsed: 0,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Summary
|
|
259
|
+
if (verbose) {
|
|
260
|
+
const successful = results.filter(r => r.success).length;
|
|
261
|
+
const totalCost = results.reduce((sum, r) => sum + r.cost, 0);
|
|
262
|
+
const totalTokens = results.reduce((sum, r) => sum + r.tokensUsed, 0);
|
|
263
|
+
console.log(`\n📊 Batch Translation Summary:`);
|
|
264
|
+
console.log(` Successful: ${successful}/${filePaths.length}`);
|
|
265
|
+
console.log(` Total tokens: ${totalTokens.toLocaleString()}`);
|
|
266
|
+
console.log(` Total cost: ${formatCost(totalCost)}`);
|
|
267
|
+
}
|
|
268
|
+
return results;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Parse CLI arguments
|
|
272
|
+
*/
|
|
273
|
+
function parseArgs() {
|
|
274
|
+
const args = process.argv.slice(2);
|
|
275
|
+
if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
|
|
276
|
+
console.log(`
|
|
277
|
+
Translation CLI Utility
|
|
278
|
+
|
|
279
|
+
Usage:
|
|
280
|
+
node translate-file.js <file-path> [options]
|
|
281
|
+
|
|
282
|
+
Options:
|
|
283
|
+
--target-lang <code> Target language (default: en)
|
|
284
|
+
--preview Preview translation without writing to file
|
|
285
|
+
--verbose, -v Show detailed output
|
|
286
|
+
--help, -h Show this help message
|
|
287
|
+
|
|
288
|
+
Supported Languages:
|
|
289
|
+
en (English), ru (Russian), es (Spanish), zh (Chinese),
|
|
290
|
+
de (German), fr (French), ja (Japanese), ko (Korean),
|
|
291
|
+
pt (Portuguese), ar (Arabic), he (Hebrew)
|
|
292
|
+
|
|
293
|
+
Examples:
|
|
294
|
+
# Translate Russian file to English
|
|
295
|
+
node translate-file.js .specweave/increments/0001/spec.md
|
|
296
|
+
|
|
297
|
+
# Preview translation
|
|
298
|
+
node translate-file.js spec.md --preview --verbose
|
|
299
|
+
|
|
300
|
+
# Translate to Spanish
|
|
301
|
+
node translate-file.js plan.md --target-lang es
|
|
302
|
+
`.trim());
|
|
303
|
+
process.exit(0);
|
|
304
|
+
}
|
|
305
|
+
const filePath = args[0];
|
|
306
|
+
let targetLang = 'en';
|
|
307
|
+
let preview = false;
|
|
308
|
+
let verbose = false;
|
|
309
|
+
// Parse options
|
|
310
|
+
for (let i = 1; i < args.length; i++) {
|
|
311
|
+
const arg = args[i];
|
|
312
|
+
if (arg === '--target-lang' && args[i + 1]) {
|
|
313
|
+
targetLang = args[i + 1];
|
|
314
|
+
i++;
|
|
315
|
+
}
|
|
316
|
+
else if (arg === '--preview') {
|
|
317
|
+
preview = true;
|
|
318
|
+
}
|
|
319
|
+
else if (arg === '--verbose' || arg === '-v') {
|
|
320
|
+
verbose = true;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return {
|
|
324
|
+
filePath,
|
|
325
|
+
targetLang,
|
|
326
|
+
preview,
|
|
327
|
+
verbose,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* CLI entry point
|
|
332
|
+
*/
|
|
333
|
+
async function main() {
|
|
334
|
+
try {
|
|
335
|
+
const options = parseArgs();
|
|
336
|
+
const result = await translateFile(options);
|
|
337
|
+
// Exit with appropriate code
|
|
338
|
+
process.exit(result.success ? 0 : 1);
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
console.error(`❌ Translation failed: ${error.message}`);
|
|
342
|
+
process.exit(1);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// Check if running as main module (ESM)
|
|
346
|
+
const isMainModule = import.meta.url === `file://${process.argv[1]}`;
|
|
347
|
+
if (isMainModule) {
|
|
348
|
+
main();
|
|
349
|
+
}
|
|
350
|
+
//# sourceMappingURL=translate-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate-file.js","sourceRoot":"","sources":["../../../src/hooks/lib/translate-file.ts"],"names":[],"mappings":"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"}
|
package/dist/locales/en/cli.json
CHANGED
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"header": "AI Tool Detection",
|
|
67
67
|
"detected": "Detected: {{tool}}",
|
|
68
68
|
"confirmPrompt": "Use {{tool}} for this project?",
|
|
69
|
+
"ciAutoConfirm": "CI environment detected - auto-confirming {{tool}}",
|
|
69
70
|
"selectPrompt": "Which AI tool will you use?",
|
|
70
71
|
"recommended": "Recommended - Full automation",
|
|
71
72
|
"tools": {
|
|
@@ -87,7 +88,8 @@
|
|
|
87
88
|
"copiedSkills": "✓ Copied {{count}} skill directories",
|
|
88
89
|
"copiedHooks": "✓ Copied {{count}} hook files",
|
|
89
90
|
"pluginAutoSetupDetails": "Claude Code will auto-load SpecWeave marketplace when you trust this folder",
|
|
90
|
-
"manualInstallInstructions": "Run manually: /plugin install specweave-core@specweave"
|
|
91
|
+
"manualInstallInstructions": "Run manually: /plugin install specweave-core@specweave",
|
|
92
|
+
"ciSkipPlugins": "CI environment detected - skipping plugin enablement (can configure manually later)"
|
|
91
93
|
},
|
|
92
94
|
"success": {
|
|
93
95
|
"pluginAutoSetup": "Plugin marketplace configured for automatic loading",
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change Failure Rate Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates percentage of deployments that cause failures (DORA metric #3)
|
|
5
|
+
* Data source: GitHub Issues with labels "incident" or "production-bug"
|
|
6
|
+
*/
|
|
7
|
+
import { Release, Issue, ChangeFailureRateMetric } from '../types';
|
|
8
|
+
/**
|
|
9
|
+
* Calculate Change Failure Rate
|
|
10
|
+
*
|
|
11
|
+
* Methodology:
|
|
12
|
+
* 1. Find issues labeled "incident" or "production-bug"
|
|
13
|
+
* 2. Link each incident to the most recent release before it
|
|
14
|
+
* 3. Calculate percentage of releases with incidents
|
|
15
|
+
* 4. Classify into DORA tier
|
|
16
|
+
*
|
|
17
|
+
* @param releases - Array of GitHub releases
|
|
18
|
+
* @param issues - Array of GitHub issues
|
|
19
|
+
* @returns Change failure rate metric
|
|
20
|
+
*/
|
|
21
|
+
export declare function calculateChangeFailureRate(releases: Release[], issues: Issue[]): ChangeFailureRateMetric;
|
|
22
|
+
//# sourceMappingURL=change-failure-rate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-failure-rate.d.ts","sourceRoot":"","sources":["../../../src/metrics/calculators/change-failure-rate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAGnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,EAAE,KAAK,EAAE,GACd,uBAAuB,CAkEzB"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Change Failure Rate Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates percentage of deployments that cause failures (DORA metric #3)
|
|
5
|
+
* Data source: GitHub Issues with labels "incident" or "production-bug"
|
|
6
|
+
*/
|
|
7
|
+
import { classifyChangeFailureRate } from '../utils/tier-classifier';
|
|
8
|
+
/**
|
|
9
|
+
* Calculate Change Failure Rate
|
|
10
|
+
*
|
|
11
|
+
* Methodology:
|
|
12
|
+
* 1. Find issues labeled "incident" or "production-bug"
|
|
13
|
+
* 2. Link each incident to the most recent release before it
|
|
14
|
+
* 3. Calculate percentage of releases with incidents
|
|
15
|
+
* 4. Classify into DORA tier
|
|
16
|
+
*
|
|
17
|
+
* @param releases - Array of GitHub releases
|
|
18
|
+
* @param issues - Array of GitHub issues
|
|
19
|
+
* @returns Change failure rate metric
|
|
20
|
+
*/
|
|
21
|
+
export function calculateChangeFailureRate(releases, issues) {
|
|
22
|
+
// Handle zero releases
|
|
23
|
+
if (releases.length === 0) {
|
|
24
|
+
return {
|
|
25
|
+
value: 0,
|
|
26
|
+
unit: 'percentage',
|
|
27
|
+
tier: 'N/A',
|
|
28
|
+
failedReleases: 0,
|
|
29
|
+
totalReleases: 0,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// Filter incidents (issues with incident or production-bug labels)
|
|
33
|
+
const incidents = issues.filter(issue => issue.labels.some(label => label.name === 'incident' || label.name === 'production-bug'));
|
|
34
|
+
// Handle zero incidents (perfect!)
|
|
35
|
+
if (incidents.length === 0) {
|
|
36
|
+
return {
|
|
37
|
+
value: 0,
|
|
38
|
+
unit: 'percentage',
|
|
39
|
+
tier: 'Elite',
|
|
40
|
+
failedReleases: 0,
|
|
41
|
+
totalReleases: releases.length,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// Sort releases by date (newest first)
|
|
45
|
+
const sortedReleases = [...releases].sort((a, b) => new Date(b.published_at).getTime() - new Date(a.published_at).getTime());
|
|
46
|
+
// Track which releases had incidents
|
|
47
|
+
const failedReleaseIds = new Set();
|
|
48
|
+
incidents.forEach(incident => {
|
|
49
|
+
const incidentDate = new Date(incident.created_at);
|
|
50
|
+
// Find most recent release before this incident
|
|
51
|
+
const applicableRelease = sortedReleases.find(release => new Date(release.published_at) <= incidentDate);
|
|
52
|
+
if (applicableRelease) {
|
|
53
|
+
failedReleaseIds.add(applicableRelease.id);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
// Calculate failure rate
|
|
57
|
+
const failedReleases = failedReleaseIds.size;
|
|
58
|
+
const totalReleases = releases.length;
|
|
59
|
+
const failureRate = (failedReleases / totalReleases) * 100;
|
|
60
|
+
// Classify tier
|
|
61
|
+
const tier = classifyChangeFailureRate(failureRate);
|
|
62
|
+
return {
|
|
63
|
+
value: Math.round(failureRate * 10) / 10, // Round to 1 decimal
|
|
64
|
+
unit: 'percentage',
|
|
65
|
+
tier,
|
|
66
|
+
failedReleases,
|
|
67
|
+
totalReleases,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=change-failure-rate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-failure-rate.js","sourceRoot":"","sources":["../../../src/metrics/calculators/change-failure-rate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAErE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,0BAA0B,CACxC,QAAmB,EACnB,MAAe;IAEf,uBAAuB;IACvB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,KAAK,EAAE,CAAC;YACR,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,KAAK;YACX,cAAc,EAAE,CAAC;YACjB,aAAa,EAAE,CAAC;SACjB,CAAC;IACJ,CAAC;IAED,mEAAmE;IACnE,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACtC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CACxB,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,CAC7D,CACF,CAAC;IAEF,mCAAmC;IACnC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,KAAK,EAAE,CAAC;YACR,IAAI,EAAE,YAAY;YAClB,IAAI,EAAE,OAAO;YACb,cAAc,EAAE,CAAC;YACjB,aAAa,EAAE,QAAQ,CAAC,MAAM;SAC/B,CAAC;IACJ,CAAC;IAED,uCAAuC;IACvC,MAAM,cAAc,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CACvC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAClF,CAAC;IAEF,qCAAqC;IACrC,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;IAE3C,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;QAC3B,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAEnD,gDAAgD;QAChD,MAAM,iBAAiB,GAAG,cAAc,CAAC,IAAI,CAC3C,OAAO,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,YAAY,CAC1D,CAAC;QAEF,IAAI,iBAAiB,EAAE,CAAC;YACtB,gBAAgB,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,yBAAyB;IACzB,MAAM,cAAc,GAAG,gBAAgB,CAAC,IAAI,CAAC;IAC7C,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC;IACtC,MAAM,WAAW,GAAG,CAAC,cAAc,GAAG,aAAa,CAAC,GAAG,GAAG,CAAC;IAE3D,gBAAgB;IAChB,MAAM,IAAI,GAAG,yBAAyB,CAAC,WAAW,CAAC,CAAC;IAEpD,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC,GAAG,EAAE,EAAG,qBAAqB;QAChE,IAAI,EAAE,YAAY;QAClB,IAAI;QACJ,cAAc;QACd,aAAa;KACd,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment Frequency Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates how often deployments occur (DORA metric #1)
|
|
5
|
+
* Data source: GitHub Releases API
|
|
6
|
+
*/
|
|
7
|
+
import { Release, DeploymentFrequencyMetric } from '../types';
|
|
8
|
+
/**
|
|
9
|
+
* Calculate Deployment Frequency from releases
|
|
10
|
+
*
|
|
11
|
+
* Methodology:
|
|
12
|
+
* 1. Count releases in last 30 days
|
|
13
|
+
* 2. Calculate deploys per month
|
|
14
|
+
* 3. Classify into DORA tier
|
|
15
|
+
*
|
|
16
|
+
* @param releases - Array of GitHub releases
|
|
17
|
+
* @returns Deployment frequency metric
|
|
18
|
+
*/
|
|
19
|
+
export declare function calculateDeploymentFrequency(releases: Release[]): DeploymentFrequencyMetric;
|
|
20
|
+
//# sourceMappingURL=deployment-frequency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-frequency.d.ts","sourceRoot":"","sources":["../../../src/metrics/calculators/deployment-frequency.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAG9D;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,OAAO,EAAE,GAClB,yBAAyB,CA8C3B"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deployment Frequency Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates how often deployments occur (DORA metric #1)
|
|
5
|
+
* Data source: GitHub Releases API
|
|
6
|
+
*/
|
|
7
|
+
import { classifyDeploymentFrequency } from '../utils/tier-classifier';
|
|
8
|
+
/**
|
|
9
|
+
* Calculate Deployment Frequency from releases
|
|
10
|
+
*
|
|
11
|
+
* Methodology:
|
|
12
|
+
* 1. Count releases in last 30 days
|
|
13
|
+
* 2. Calculate deploys per month
|
|
14
|
+
* 3. Classify into DORA tier
|
|
15
|
+
*
|
|
16
|
+
* @param releases - Array of GitHub releases
|
|
17
|
+
* @returns Deployment frequency metric
|
|
18
|
+
*/
|
|
19
|
+
export function calculateDeploymentFrequency(releases) {
|
|
20
|
+
// Handle zero releases
|
|
21
|
+
if (releases.length === 0) {
|
|
22
|
+
return {
|
|
23
|
+
value: 0,
|
|
24
|
+
unit: 'deploys/month',
|
|
25
|
+
tier: 'N/A',
|
|
26
|
+
description: 'No releases yet',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// Count releases
|
|
30
|
+
const deployCount = releases.length;
|
|
31
|
+
// Calculate deploys per year (for tier classification)
|
|
32
|
+
// Assumes 30-day window, so multiply by 12 to get annual rate
|
|
33
|
+
const deploysPerYear = (deployCount / 30) * 365;
|
|
34
|
+
// Classify tier
|
|
35
|
+
const tier = classifyDeploymentFrequency(deploysPerYear);
|
|
36
|
+
// Generate description
|
|
37
|
+
let description = '';
|
|
38
|
+
switch (tier) {
|
|
39
|
+
case 'Elite':
|
|
40
|
+
description = 'On-demand deployment capability (multiple deploys per day)';
|
|
41
|
+
break;
|
|
42
|
+
case 'High':
|
|
43
|
+
description = 'High deployment frequency (weekly to daily)';
|
|
44
|
+
break;
|
|
45
|
+
case 'Medium':
|
|
46
|
+
description = 'Moderate deployment frequency (monthly to weekly)';
|
|
47
|
+
break;
|
|
48
|
+
case 'Low':
|
|
49
|
+
description = 'Low deployment frequency (less than monthly)';
|
|
50
|
+
break;
|
|
51
|
+
default:
|
|
52
|
+
description = 'No data available';
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
value: deployCount,
|
|
56
|
+
unit: 'deploys/month',
|
|
57
|
+
tier,
|
|
58
|
+
description,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=deployment-frequency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment-frequency.js","sourceRoot":"","sources":["../../../src/metrics/calculators/deployment-frequency.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAEvE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,4BAA4B,CAC1C,QAAmB;IAEnB,uBAAuB;IACvB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,KAAK,EAAE,CAAC;YACR,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,KAAK;YACX,WAAW,EAAE,iBAAiB;SAC/B,CAAC;IACJ,CAAC;IAED,iBAAiB;IACjB,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC;IAEpC,uDAAuD;IACvD,8DAA8D;IAC9D,MAAM,cAAc,GAAG,CAAC,WAAW,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC;IAEhD,gBAAgB;IAChB,MAAM,IAAI,GAAG,2BAA2B,CAAC,cAAc,CAAC,CAAC;IAEzD,uBAAuB;IACvB,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,OAAO;YACV,WAAW,GAAG,4DAA4D,CAAC;YAC3E,MAAM;QACR,KAAK,MAAM;YACT,WAAW,GAAG,6CAA6C,CAAC;YAC5D,MAAM;QACR,KAAK,QAAQ;YACX,WAAW,GAAG,mDAAmD,CAAC;YAClE,MAAM;QACR,KAAK,KAAK;YACR,WAAW,GAAG,8CAA8C,CAAC;YAC7D,MAAM;QACR;YACE,WAAW,GAAG,mBAAmB,CAAC;IACtC,CAAC;IAED,OAAO;QACL,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE,eAAe;QACrB,IAAI;QACJ,WAAW;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lead Time for Changes Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates time from commit to deployment (DORA metric #2)
|
|
5
|
+
* Data source: Git commits + GitHub Releases API
|
|
6
|
+
*/
|
|
7
|
+
import { Release, Commit, LeadTimeMetric } from '../types';
|
|
8
|
+
/**
|
|
9
|
+
* Calculate Lead Time for Changes
|
|
10
|
+
*
|
|
11
|
+
* Methodology:
|
|
12
|
+
* 1. For each release, find all commits since previous release
|
|
13
|
+
* 2. Calculate time delta (commit date → release date) for each commit
|
|
14
|
+
* 3. Compute average, P50, P90
|
|
15
|
+
* 4. Classify into DORA tier
|
|
16
|
+
*
|
|
17
|
+
* @param releases - Array of GitHub releases (sorted by date desc)
|
|
18
|
+
* @param commits - Array of Git commits
|
|
19
|
+
* @returns Lead time metric
|
|
20
|
+
*/
|
|
21
|
+
export declare function calculateLeadTime(releases: Release[], commits: Commit[]): LeadTimeMetric;
|
|
22
|
+
//# sourceMappingURL=lead-time.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lead-time.d.ts","sourceRoot":"","sources":["../../../src/metrics/calculators/lead-time.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAI3D;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,EAAE,MAAM,EAAE,GAChB,cAAc,CAwEhB"}
|