jumpstart-mode 1.1.11 → 1.1.13

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 (188) hide show
  1. package/.github/agents/jumpstart-adversary.agent.md +2 -1
  2. package/.github/agents/jumpstart-architect.agent.md +6 -7
  3. package/.github/agents/jumpstart-challenger.agent.md +2 -1
  4. package/.github/agents/jumpstart-developer.agent.md +1 -1
  5. package/.github/agents/jumpstart-devops.agent.md +2 -2
  6. package/.github/agents/jumpstart-diagram-verifier.agent.md +2 -1
  7. package/.github/agents/jumpstart-maintenance.agent.md +1 -0
  8. package/.github/agents/jumpstart-performance.agent.md +1 -0
  9. package/.github/agents/jumpstart-pm.agent.md +1 -1
  10. package/.github/agents/jumpstart-refactor.agent.md +1 -0
  11. package/.github/agents/jumpstart-requirements-extractor.agent.md +1 -0
  12. package/.github/agents/jumpstart-researcher.agent.md +1 -0
  13. package/.github/agents/jumpstart-retrospective.agent.md +1 -0
  14. package/.github/agents/jumpstart-reviewer.agent.md +2 -0
  15. package/.github/agents/jumpstart-scout.agent.md +1 -1
  16. package/.github/agents/jumpstart-scrum-master.agent.md +1 -0
  17. package/.github/agents/jumpstart-security.agent.md +2 -1
  18. package/.github/agents/jumpstart-tech-writer.agent.md +1 -0
  19. package/.github/agents/jumpstart-uiux-designer.agent.md +66 -0
  20. package/.github/workflows/quality.yml +19 -2
  21. package/.jumpstart/agents/analyst.md +38 -0
  22. package/.jumpstart/agents/architect.md +39 -1
  23. package/.jumpstart/agents/challenger.md +38 -0
  24. package/.jumpstart/agents/developer.md +41 -0
  25. package/.jumpstart/agents/pm.md +38 -0
  26. package/.jumpstart/agents/scout.md +33 -0
  27. package/.jumpstart/agents/ux-designer.md +29 -9
  28. package/.jumpstart/commands/commands.md +6 -5
  29. package/.jumpstart/config.yaml +25 -1
  30. package/.jumpstart/roadmap.md +1 -1
  31. package/.jumpstart/schemas/timeline.schema.json +1 -0
  32. package/.jumpstart/skills/README.md +1 -0
  33. package/.jumpstart/skills/quality-gates/SKILL.md +126 -0
  34. package/.jumpstart/skills/skill-creator/SKILL.md +485 -357
  35. package/.jumpstart/skills/skill-creator/agents/analyzer.md +274 -0
  36. package/.jumpstart/skills/skill-creator/agents/comparator.md +202 -0
  37. package/.jumpstart/skills/skill-creator/agents/grader.md +223 -0
  38. package/.jumpstart/skills/skill-creator/assets/eval_review.html +146 -0
  39. package/.jumpstart/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  40. package/.jumpstart/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  41. package/.jumpstart/skills/skill-creator/references/schemas.md +430 -0
  42. package/.jumpstart/skills/skill-creator/scripts/__init__.py +0 -0
  43. package/.jumpstart/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  44. package/.jumpstart/skills/skill-creator/scripts/generate_report.py +326 -0
  45. package/.jumpstart/skills/skill-creator/scripts/improve_description.py +247 -0
  46. package/.jumpstart/skills/skill-creator/scripts/package_skill.py +136 -110
  47. package/.jumpstart/skills/skill-creator/scripts/run_eval.py +310 -0
  48. package/.jumpstart/skills/skill-creator/scripts/run_loop.py +328 -0
  49. package/.jumpstart/skills/skill-creator/scripts/utils.py +47 -0
  50. package/.jumpstart/skills/ui-ux-pro-max/SKILL.md +266 -0
  51. package/.jumpstart/skills/ui-ux-pro-max/data/charts.csv +26 -0
  52. package/.jumpstart/skills/ui-ux-pro-max/data/colors.csv +97 -0
  53. package/.jumpstart/skills/ui-ux-pro-max/data/icons.csv +101 -0
  54. package/.jumpstart/skills/ui-ux-pro-max/data/landing.csv +31 -0
  55. package/.jumpstart/skills/ui-ux-pro-max/data/products.csv +97 -0
  56. package/.jumpstart/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  57. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  58. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  59. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  60. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  61. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  62. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  63. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  64. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  65. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  66. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  67. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  68. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  69. package/.jumpstart/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  70. package/.jumpstart/skills/ui-ux-pro-max/data/styles.csv +68 -0
  71. package/.jumpstart/skills/ui-ux-pro-max/data/typography.csv +58 -0
  72. package/.jumpstart/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  73. package/.jumpstart/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  74. package/.jumpstart/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  75. package/.jumpstart/skills/ui-ux-pro-max/scripts/core.py +253 -0
  76. package/.jumpstart/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  77. package/.jumpstart/skills/ui-ux-pro-max/scripts/search.py +114 -0
  78. package/.jumpstart/state/timeline.json +659 -0
  79. package/.jumpstart/templates/model-map.md +1 -1
  80. package/.jumpstart/templates/ux-design.md +3 -3
  81. package/.jumpstart/usage-log.json +74 -3
  82. package/AGENTS.md +1 -1
  83. package/README.md +64 -3
  84. package/bin/cli.js +3217 -1
  85. package/bin/headless-runner.js +62 -2
  86. package/bin/lib/agent-checkpoint.js +168 -0
  87. package/bin/lib/ai-evaluation.js +104 -0
  88. package/bin/lib/ai-intake.js +152 -0
  89. package/bin/lib/ambiguity-heatmap.js +152 -0
  90. package/bin/lib/artifact-comparison.js +104 -0
  91. package/bin/lib/ast-edit-engine.js +157 -0
  92. package/bin/lib/backlog-sync.js +338 -0
  93. package/bin/lib/bcdr-planning.js +158 -0
  94. package/bin/lib/bidirectional-trace.js +199 -0
  95. package/bin/lib/branch-workflow.js +266 -0
  96. package/bin/lib/cab-output.js +119 -0
  97. package/bin/lib/chat-integration.js +122 -0
  98. package/bin/lib/ci-cd-integration.js +208 -0
  99. package/bin/lib/codebase-retrieval.js +125 -0
  100. package/bin/lib/collaboration.js +168 -0
  101. package/bin/lib/compliance-packs.js +213 -0
  102. package/bin/lib/context-chunker.js +128 -0
  103. package/bin/lib/context-onboarding.js +122 -0
  104. package/bin/lib/contract-first.js +124 -0
  105. package/bin/lib/cost-router.js +148 -0
  106. package/bin/lib/credential-boundary.js +155 -0
  107. package/bin/lib/data-classification.js +180 -0
  108. package/bin/lib/data-contracts.js +129 -0
  109. package/bin/lib/db-evolution.js +158 -0
  110. package/bin/lib/decision-conflicts.js +299 -0
  111. package/bin/lib/delivery-confidence.js +361 -0
  112. package/bin/lib/dependency-upgrade.js +153 -0
  113. package/bin/lib/design-system.js +133 -0
  114. package/bin/lib/deterministic-artifacts.js +151 -0
  115. package/bin/lib/diagram-studio.js +115 -0
  116. package/bin/lib/domain-ontology.js +140 -0
  117. package/bin/lib/ea-review-packet.js +151 -0
  118. package/bin/lib/enterprise-search.js +123 -0
  119. package/bin/lib/enterprise-templates.js +140 -0
  120. package/bin/lib/environment-promotion.js +220 -0
  121. package/bin/lib/estimation-studio.js +130 -0
  122. package/bin/lib/event-modeling.js +133 -0
  123. package/bin/lib/evidence-collector.js +179 -0
  124. package/bin/lib/finops-planner.js +182 -0
  125. package/bin/lib/fitness-functions.js +279 -0
  126. package/bin/lib/focus.js +448 -0
  127. package/bin/lib/governance-dashboard.js +165 -0
  128. package/bin/lib/guided-handoff.js +120 -0
  129. package/bin/lib/impact-analysis.js +190 -0
  130. package/bin/lib/incident-feedback.js +157 -0
  131. package/bin/lib/integrate.js +1 -1
  132. package/bin/lib/knowledge-graph.js +122 -0
  133. package/bin/lib/legacy-modernizer.js +160 -0
  134. package/bin/lib/migration-planner.js +144 -0
  135. package/bin/lib/model-governance.js +185 -0
  136. package/bin/lib/model-router.js +144 -0
  137. package/bin/lib/multi-repo.js +272 -0
  138. package/bin/lib/next-phase.js +53 -8
  139. package/bin/lib/ops-ownership.js +152 -0
  140. package/bin/lib/parallel-agents.js +257 -0
  141. package/bin/lib/pattern-library.js +115 -0
  142. package/bin/lib/persona-packs.js +99 -0
  143. package/bin/lib/plan-executor.js +366 -0
  144. package/bin/lib/platform-engineering.js +119 -0
  145. package/bin/lib/playback-summaries.js +126 -0
  146. package/bin/lib/policy-engine.js +240 -0
  147. package/bin/lib/portfolio-reporting.js +357 -0
  148. package/bin/lib/pr-package.js +197 -0
  149. package/bin/lib/project-memory.js +235 -0
  150. package/bin/lib/prompt-governance.js +130 -0
  151. package/bin/lib/promptless-mode.js +128 -0
  152. package/bin/lib/quality-graph.js +193 -0
  153. package/bin/lib/raci-matrix.js +188 -0
  154. package/bin/lib/refactor-planner.js +167 -0
  155. package/bin/lib/reference-architectures.js +304 -0
  156. package/bin/lib/release-readiness.js +171 -0
  157. package/bin/lib/repo-graph.js +262 -0
  158. package/bin/lib/requirements-baseline.js +358 -0
  159. package/bin/lib/risk-register.js +211 -0
  160. package/bin/lib/role-approval.js +249 -0
  161. package/bin/lib/role-views.js +142 -0
  162. package/bin/lib/root-cause-analysis.js +132 -0
  163. package/bin/lib/runtime-debugger.js +154 -0
  164. package/bin/lib/safe-rename.js +135 -0
  165. package/bin/lib/secret-scanner.js +313 -0
  166. package/bin/lib/semantic-diff.js +335 -0
  167. package/bin/lib/sla-slo.js +210 -0
  168. package/bin/lib/smoke-tester.js +344 -0
  169. package/bin/lib/spec-comments.js +147 -0
  170. package/bin/lib/spec-maturity.js +287 -0
  171. package/bin/lib/sre-integration.js +154 -0
  172. package/bin/lib/structured-elicitation.js +174 -0
  173. package/bin/lib/telemetry-feedback.js +118 -0
  174. package/bin/lib/test-generator.js +146 -0
  175. package/bin/lib/timeline.js +2 -1
  176. package/bin/lib/tool-bridge.js +159 -0
  177. package/bin/lib/tool-guardrails.js +139 -0
  178. package/bin/lib/tool-schemas.js +281 -3
  179. package/bin/lib/transcript-ingestion.js +150 -0
  180. package/bin/lib/type-checker.js +261 -0
  181. package/bin/lib/uat-coverage.js +411 -0
  182. package/bin/lib/vendor-risk.js +173 -0
  183. package/bin/lib/waiver-workflow.js +174 -0
  184. package/bin/lib/web-dashboard.js +126 -0
  185. package/bin/lib/workshop-mode.js +165 -0
  186. package/bin/lib/workstream-ownership.js +104 -0
  187. package/package.json +1 -1
  188. package/.github/agents/jumpstart-ux-designer.agent.md +0 -45
@@ -0,0 +1,160 @@
1
+ /**
2
+ * legacy-modernizer.js — Legacy Code Modernization Mode (Item 48)
3
+ *
4
+ * COBOL, .NET Framework, Java monolith, SSIS, old Angular,
5
+ * old React, etc.
6
+ *
7
+ * Usage:
8
+ * node bin/lib/legacy-modernizer.js assess|plan|report [options]
9
+ *
10
+ * State file: .jumpstart/state/legacy-modernization.json
11
+ */
12
+
13
+ 'use strict';
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ const DEFAULT_STATE_FILE = path.join('.jumpstart', 'state', 'legacy-modernization.json');
19
+
20
+ const LEGACY_PLATFORMS = {
21
+ 'cobol': { risk: 'high', strategy: 'strangler-fig', estimated_effort: 'very-high' },
22
+ 'dotnet-framework': { risk: 'medium', strategy: 'phased-cutover', estimated_effort: 'high' },
23
+ 'java-monolith': { risk: 'medium', strategy: 'strangler-fig', estimated_effort: 'high' },
24
+ 'ssis': { risk: 'medium', strategy: 'phased-cutover', estimated_effort: 'medium' },
25
+ 'angular-legacy': { risk: 'low', strategy: 'phased-cutover', estimated_effort: 'medium' },
26
+ 'react-legacy': { risk: 'low', strategy: 'in-place', estimated_effort: 'low' },
27
+ 'jquery': { risk: 'low', strategy: 'phased-cutover', estimated_effort: 'medium' },
28
+ 'php-legacy': { risk: 'medium', strategy: 'strangler-fig', estimated_effort: 'high' }
29
+ };
30
+
31
+ const MODERNIZATION_PATTERNS = ['strangler-fig', 'phased-cutover', 'big-bang', 'in-place', 'rewrite'];
32
+
33
+ function defaultState() {
34
+ return {
35
+ version: '1.0.0',
36
+ created_at: new Date().toISOString(),
37
+ last_updated: null,
38
+ assessments: [],
39
+ modernization_plans: []
40
+ };
41
+ }
42
+
43
+ function loadState(stateFile) {
44
+ const filePath = stateFile || DEFAULT_STATE_FILE;
45
+ if (!fs.existsSync(filePath)) return defaultState();
46
+ try { return JSON.parse(fs.readFileSync(filePath, 'utf8')); }
47
+ catch { return defaultState(); }
48
+ }
49
+
50
+ function saveState(state, stateFile) {
51
+ const filePath = stateFile || DEFAULT_STATE_FILE;
52
+ const dir = path.dirname(filePath);
53
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
54
+ state.last_updated = new Date().toISOString();
55
+ fs.writeFileSync(filePath, JSON.stringify(state, null, 2) + '\n', 'utf8');
56
+ }
57
+
58
+ /**
59
+ * Assess a legacy system for modernization.
60
+ *
61
+ * @param {object} system - { name, platform, age_years?, loc?, dependencies? }
62
+ * @param {object} [options]
63
+ * @returns {object}
64
+ */
65
+ function assessSystem(system, options = {}) {
66
+ if (!system || !system.name || !system.platform) {
67
+ return { success: false, error: 'name and platform are required' };
68
+ }
69
+
70
+ const platform = system.platform.toLowerCase();
71
+ const platformInfo = LEGACY_PLATFORMS[platform] || { risk: 'medium', strategy: 'phased-cutover', estimated_effort: 'medium' };
72
+
73
+ const stateFile = options.stateFile || DEFAULT_STATE_FILE;
74
+ const state = loadState(stateFile);
75
+
76
+ const assessment = {
77
+ id: `LEG-${(state.assessments.length + 1).toString().padStart(3, '0')}`,
78
+ name: system.name,
79
+ platform,
80
+ age_years: system.age_years || null,
81
+ loc: system.loc || null,
82
+ risk_level: platformInfo.risk,
83
+ recommended_strategy: platformInfo.strategy,
84
+ estimated_effort: platformInfo.estimated_effort,
85
+ modernization_targets: system.modernization_targets || [],
86
+ assessed_at: new Date().toISOString()
87
+ };
88
+
89
+ state.assessments.push(assessment);
90
+ saveState(state, stateFile);
91
+
92
+ return { success: true, assessment };
93
+ }
94
+
95
+ /**
96
+ * Create a modernization plan.
97
+ *
98
+ * @param {string} assessmentId
99
+ * @param {object} plan - { target_platform, phases[], timeline? }
100
+ * @param {object} [options]
101
+ * @returns {object}
102
+ */
103
+ function createPlan(assessmentId, plan, options = {}) {
104
+ const stateFile = options.stateFile || DEFAULT_STATE_FILE;
105
+ const state = loadState(stateFile);
106
+
107
+ const assessment = state.assessments.find(a => a.id === assessmentId);
108
+ if (!assessment) return { success: false, error: `Assessment not found: ${assessmentId}` };
109
+
110
+ const modPlan = {
111
+ id: `MOD-${(state.modernization_plans.length + 1).toString().padStart(3, '0')}`,
112
+ assessment_id: assessmentId,
113
+ source_platform: assessment.platform,
114
+ target_platform: plan.target_platform || 'modern-stack',
115
+ strategy: assessment.recommended_strategy,
116
+ phases: (plan.phases || ['assess', 'plan', 'implement', 'validate', 'cutover']).map((p, i) => ({
117
+ order: i + 1,
118
+ name: typeof p === 'string' ? p : p.name,
119
+ status: 'pending'
120
+ })),
121
+ timeline: plan.timeline || null,
122
+ created_at: new Date().toISOString()
123
+ };
124
+
125
+ state.modernization_plans.push(modPlan);
126
+ saveState(state, stateFile);
127
+
128
+ return { success: true, plan: modPlan };
129
+ }
130
+
131
+ /**
132
+ * Generate modernization report.
133
+ *
134
+ * @param {object} [options]
135
+ * @returns {object}
136
+ */
137
+ function generateReport(options = {}) {
138
+ const stateFile = options.stateFile || DEFAULT_STATE_FILE;
139
+ const state = loadState(stateFile);
140
+
141
+ return {
142
+ success: true,
143
+ total_assessments: state.assessments.length,
144
+ total_plans: state.modernization_plans.length,
145
+ by_platform: state.assessments.reduce((acc, a) => { acc[a.platform] = (acc[a.platform] || 0) + 1; return acc; }, {}),
146
+ by_risk: state.assessments.reduce((acc, a) => { acc[a.risk_level] = (acc[a.risk_level] || 0) + 1; return acc; }, {}),
147
+ assessments: state.assessments
148
+ };
149
+ }
150
+
151
+ module.exports = {
152
+ defaultState,
153
+ loadState,
154
+ saveState,
155
+ assessSystem,
156
+ createPlan,
157
+ generateReport,
158
+ LEGACY_PLATFORMS,
159
+ MODERNIZATION_PATTERNS
160
+ };
@@ -0,0 +1,144 @@
1
+ /**
2
+ * migration-planner.js — Brownfield Migration Planner (Item 47)
3
+ *
4
+ * Special workflows for strangler patterns, phased cutovers,
5
+ * compatibility layers, and rollback.
6
+ *
7
+ * Usage:
8
+ * node bin/lib/migration-planner.js plan|status|report [options]
9
+ *
10
+ * State file: .jumpstart/state/migration-plan.json
11
+ */
12
+
13
+ 'use strict';
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ const DEFAULT_STATE_FILE = path.join('.jumpstart', 'state', 'migration-plan.json');
19
+
20
+ const MIGRATION_STRATEGIES = ['strangler-fig', 'big-bang', 'phased-cutover', 'parallel-run', 'feature-flag'];
21
+
22
+ const MIGRATION_PHASES = ['discovery', 'planning', 'compatibility-layer', 'migration', 'validation', 'cutover', 'cleanup'];
23
+
24
+ function defaultState() {
25
+ return {
26
+ version: '1.0.0',
27
+ created_at: new Date().toISOString(),
28
+ last_updated: null,
29
+ migrations: []
30
+ };
31
+ }
32
+
33
+ function loadState(stateFile) {
34
+ const filePath = stateFile || DEFAULT_STATE_FILE;
35
+ if (!fs.existsSync(filePath)) return defaultState();
36
+ try { return JSON.parse(fs.readFileSync(filePath, 'utf8')); }
37
+ catch { return defaultState(); }
38
+ }
39
+
40
+ function saveState(state, stateFile) {
41
+ const filePath = stateFile || DEFAULT_STATE_FILE;
42
+ const dir = path.dirname(filePath);
43
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
44
+ state.last_updated = new Date().toISOString();
45
+ fs.writeFileSync(filePath, JSON.stringify(state, null, 2) + '\n', 'utf8');
46
+ }
47
+
48
+ /**
49
+ * Create a migration plan.
50
+ *
51
+ * @param {object} migration - { name, strategy, source_system, target_system, components[] }
52
+ * @param {object} [options]
53
+ * @returns {object}
54
+ */
55
+ function createMigration(migration, options = {}) {
56
+ if (!migration || !migration.name || !migration.strategy) {
57
+ return { success: false, error: 'name and strategy are required' };
58
+ }
59
+
60
+ if (!MIGRATION_STRATEGIES.includes(migration.strategy)) {
61
+ return { success: false, error: `Invalid strategy. Must be one of: ${MIGRATION_STRATEGIES.join(', ')}` };
62
+ }
63
+
64
+ const stateFile = options.stateFile || DEFAULT_STATE_FILE;
65
+ const state = loadState(stateFile);
66
+
67
+ const plan = {
68
+ id: `MIG-${(state.migrations.length + 1).toString().padStart(3, '0')}`,
69
+ name: migration.name,
70
+ strategy: migration.strategy,
71
+ source_system: migration.source_system || null,
72
+ target_system: migration.target_system || null,
73
+ current_phase: 'discovery',
74
+ components: (migration.components || []).map(c => ({
75
+ name: c.name || c,
76
+ status: 'pending',
77
+ migrated_at: null
78
+ })),
79
+ rollback_plan: migration.rollback_plan || null,
80
+ compatibility_requirements: migration.compatibility_requirements || [],
81
+ created_at: new Date().toISOString()
82
+ };
83
+
84
+ state.migrations.push(plan);
85
+ saveState(state, stateFile);
86
+
87
+ return { success: true, migration: plan };
88
+ }
89
+
90
+ /**
91
+ * Advance migration phase.
92
+ *
93
+ * @param {string} migrationId
94
+ * @param {string} phase
95
+ * @param {object} [options]
96
+ * @returns {object}
97
+ */
98
+ function advancePhase(migrationId, phase, options = {}) {
99
+ if (!MIGRATION_PHASES.includes(phase)) {
100
+ return { success: false, error: `Invalid phase. Must be one of: ${MIGRATION_PHASES.join(', ')}` };
101
+ }
102
+
103
+ const stateFile = options.stateFile || DEFAULT_STATE_FILE;
104
+ const state = loadState(stateFile);
105
+
106
+ const migration = state.migrations.find(m => m.id === migrationId);
107
+ if (!migration) return { success: false, error: `Migration not found: ${migrationId}` };
108
+
109
+ migration.current_phase = phase;
110
+ migration.phase_updated_at = new Date().toISOString();
111
+ saveState(state, stateFile);
112
+
113
+ return { success: true, migration_id: migrationId, phase, previous_phase: migration.current_phase };
114
+ }
115
+
116
+ /**
117
+ * Generate migration report.
118
+ *
119
+ * @param {object} [options]
120
+ * @returns {object}
121
+ */
122
+ function generateReport(options = {}) {
123
+ const stateFile = options.stateFile || DEFAULT_STATE_FILE;
124
+ const state = loadState(stateFile);
125
+
126
+ return {
127
+ success: true,
128
+ total_migrations: state.migrations.length,
129
+ by_strategy: state.migrations.reduce((acc, m) => { acc[m.strategy] = (acc[m.strategy] || 0) + 1; return acc; }, {}),
130
+ by_phase: state.migrations.reduce((acc, m) => { acc[m.current_phase] = (acc[m.current_phase] || 0) + 1; return acc; }, {}),
131
+ migrations: state.migrations
132
+ };
133
+ }
134
+
135
+ module.exports = {
136
+ defaultState,
137
+ loadState,
138
+ saveState,
139
+ createMigration,
140
+ advancePhase,
141
+ generateReport,
142
+ MIGRATION_STRATEGIES,
143
+ MIGRATION_PHASES
144
+ };
@@ -0,0 +1,185 @@
1
+ /**
2
+ * model-governance.js — Model Governance Workflows (Item 33)
3
+ *
4
+ * Track model choice, prompting strategy, evals, risks,
5
+ * safety controls, and fallback models.
6
+ *
7
+ * Usage:
8
+ * node bin/lib/model-governance.js register|evaluate|report [options]
9
+ *
10
+ * State file: .jumpstart/state/model-governance.json
11
+ */
12
+
13
+ 'use strict';
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ const DEFAULT_STATE_FILE = path.join('.jumpstart', 'state', 'model-governance.json');
19
+
20
+ const MODEL_RISK_LEVELS = ['low', 'medium', 'high', 'critical'];
21
+ const MODEL_STATUSES = ['proposed', 'approved', 'deployed', 'deprecated', 'retired'];
22
+
23
+ function defaultState() {
24
+ return {
25
+ version: '1.0.0',
26
+ created_at: new Date().toISOString(),
27
+ last_updated: null,
28
+ models: [],
29
+ evaluations: [],
30
+ safety_controls: []
31
+ };
32
+ }
33
+
34
+ function loadState(stateFile) {
35
+ const filePath = stateFile || DEFAULT_STATE_FILE;
36
+ if (!fs.existsSync(filePath)) return defaultState();
37
+ try { return JSON.parse(fs.readFileSync(filePath, 'utf8')); }
38
+ catch { return defaultState(); }
39
+ }
40
+
41
+ function saveState(state, stateFile) {
42
+ const filePath = stateFile || DEFAULT_STATE_FILE;
43
+ const dir = path.dirname(filePath);
44
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
45
+ state.last_updated = new Date().toISOString();
46
+ fs.writeFileSync(filePath, JSON.stringify(state, null, 2) + '\n', 'utf8');
47
+ }
48
+
49
+ /**
50
+ * Register a model for governance tracking.
51
+ *
52
+ * @param {object} model - { name, provider, version, use_case, risk_level?, fallback? }
53
+ * @param {object} [options]
54
+ * @returns {object}
55
+ */
56
+ function registerModel(model, options = {}) {
57
+ if (!model || !model.name || !model.provider) {
58
+ return { success: false, error: 'name and provider are required' };
59
+ }
60
+
61
+ const stateFile = options.stateFile || DEFAULT_STATE_FILE;
62
+ const state = loadState(stateFile);
63
+
64
+ const riskLevel = (model.risk_level || 'medium').toLowerCase();
65
+ if (!MODEL_RISK_LEVELS.includes(riskLevel)) {
66
+ return { success: false, error: `Invalid risk level. Must be one of: ${MODEL_RISK_LEVELS.join(', ')}` };
67
+ }
68
+
69
+ const newModel = {
70
+ id: `MDL-${(state.models.length + 1).toString().padStart(3, '0')}`,
71
+ name: model.name,
72
+ provider: model.provider,
73
+ version: model.version || 'latest',
74
+ use_case: model.use_case || '',
75
+ risk_level: riskLevel,
76
+ status: 'proposed',
77
+ fallback: model.fallback || null,
78
+ prompting_strategy: model.prompting_strategy || null,
79
+ safety_controls: model.safety_controls || [],
80
+ data_handling: model.data_handling || null,
81
+ registered_at: new Date().toISOString()
82
+ };
83
+
84
+ state.models.push(newModel);
85
+ saveState(state, stateFile);
86
+
87
+ return { success: true, model: newModel };
88
+ }
89
+
90
+ /**
91
+ * Record a model evaluation.
92
+ *
93
+ * @param {string} modelId
94
+ * @param {object} evaluation - { metrics, notes?, evaluator? }
95
+ * @param {object} [options]
96
+ * @returns {object}
97
+ */
98
+ function recordEvaluation(modelId, evaluation, options = {}) {
99
+ const stateFile = options.stateFile || DEFAULT_STATE_FILE;
100
+ const state = loadState(stateFile);
101
+
102
+ const model = state.models.find(m => m.id === modelId);
103
+ if (!model) return { success: false, error: `Model not found: ${modelId}` };
104
+
105
+ const eval_ = {
106
+ id: `EVAL-${Date.now().toString(36).toUpperCase()}`,
107
+ model_id: modelId,
108
+ metrics: evaluation.metrics || {},
109
+ notes: evaluation.notes || '',
110
+ evaluator: evaluation.evaluator || null,
111
+ evaluated_at: new Date().toISOString()
112
+ };
113
+
114
+ state.evaluations.push(eval_);
115
+ saveState(state, stateFile);
116
+
117
+ return { success: true, evaluation: eval_ };
118
+ }
119
+
120
+ /**
121
+ * Update model status.
122
+ *
123
+ * @param {string} modelId
124
+ * @param {string} status
125
+ * @param {object} [options]
126
+ * @returns {object}
127
+ */
128
+ function updateStatus(modelId, status, options = {}) {
129
+ if (!MODEL_STATUSES.includes(status)) {
130
+ return { success: false, error: `Invalid status. Must be one of: ${MODEL_STATUSES.join(', ')}` };
131
+ }
132
+
133
+ const stateFile = options.stateFile || DEFAULT_STATE_FILE;
134
+ const state = loadState(stateFile);
135
+
136
+ const model = state.models.find(m => m.id === modelId);
137
+ if (!model) return { success: false, error: `Model not found: ${modelId}` };
138
+
139
+ model.status = status;
140
+ model.status_updated_at = new Date().toISOString();
141
+ saveState(state, stateFile);
142
+
143
+ return { success: true, model };
144
+ }
145
+
146
+ /**
147
+ * Generate model governance report.
148
+ *
149
+ * @param {object} [options]
150
+ * @returns {object}
151
+ */
152
+ function generateReport(options = {}) {
153
+ const stateFile = options.stateFile || DEFAULT_STATE_FILE;
154
+ const state = loadState(stateFile);
155
+
156
+ const byStatus = {};
157
+ const byRisk = {};
158
+ for (const m of state.models) {
159
+ byStatus[m.status] = (byStatus[m.status] || 0) + 1;
160
+ byRisk[m.risk_level] = (byRisk[m.risk_level] || 0) + 1;
161
+ }
162
+
163
+ return {
164
+ success: true,
165
+ total_models: state.models.length,
166
+ total_evaluations: state.evaluations.length,
167
+ by_status: byStatus,
168
+ by_risk: byRisk,
169
+ high_risk_models: state.models.filter(m => m.risk_level === 'high' || m.risk_level === 'critical'),
170
+ models_without_fallback: state.models.filter(m => !m.fallback),
171
+ models: state.models
172
+ };
173
+ }
174
+
175
+ module.exports = {
176
+ defaultState,
177
+ loadState,
178
+ saveState,
179
+ registerModel,
180
+ recordEvaluation,
181
+ updateStatus,
182
+ generateReport,
183
+ MODEL_RISK_LEVELS,
184
+ MODEL_STATUSES
185
+ };
@@ -0,0 +1,144 @@
1
+ /**
2
+ * model-router.js — Multi-Model Routing (Item 54)
3
+ *
4
+ * Use different models for planning, coding, review, diagramming,
5
+ * and summarization.
6
+ *
7
+ * Usage:
8
+ * node bin/lib/model-router.js route|config|report [options]
9
+ *
10
+ * Config: .jumpstart/model-routing.json
11
+ */
12
+
13
+ 'use strict';
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ const DEFAULT_CONFIG_FILE = path.join('.jumpstart', 'model-routing.json');
19
+
20
+ const TASK_TYPES = ['planning', 'coding', 'review', 'diagramming', 'summarization', 'testing', 'documentation', 'analysis'];
21
+
22
+ const DEFAULT_ROUTING = {
23
+ planning: { model: 'claude-3-opus', reason: 'Complex reasoning for architecture decisions' },
24
+ coding: { model: 'claude-3-sonnet', reason: 'Balanced quality and speed for code generation' },
25
+ review: { model: 'gpt-4o', reason: 'Thorough code review capabilities' },
26
+ diagramming: { model: 'claude-3-haiku', reason: 'Fast diagram generation' },
27
+ summarization: { model: 'claude-3-haiku', reason: 'Efficient summarization' },
28
+ testing: { model: 'claude-3-sonnet', reason: 'Good test generation quality' },
29
+ documentation: { model: 'claude-3-haiku', reason: 'Efficient doc generation' },
30
+ analysis: { model: 'claude-3-opus', reason: 'Deep analysis capabilities' }
31
+ };
32
+
33
+ /**
34
+ * Load routing configuration.
35
+ *
36
+ * @param {string} [configFile]
37
+ * @returns {object}
38
+ */
39
+ function loadConfig(configFile) {
40
+ const filePath = configFile || DEFAULT_CONFIG_FILE;
41
+ if (!fs.existsSync(filePath)) return { routing: { ...DEFAULT_ROUTING } };
42
+ try { return JSON.parse(fs.readFileSync(filePath, 'utf8')); }
43
+ catch { return { routing: { ...DEFAULT_ROUTING } }; }
44
+ }
45
+
46
+ /**
47
+ * Save routing configuration.
48
+ *
49
+ * @param {object} config
50
+ * @param {string} [configFile]
51
+ */
52
+ function saveConfig(config, configFile) {
53
+ const filePath = configFile || DEFAULT_CONFIG_FILE;
54
+ const dir = path.dirname(filePath);
55
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
56
+ fs.writeFileSync(filePath, JSON.stringify(config, null, 2) + '\n', 'utf8');
57
+ }
58
+
59
+ /**
60
+ * Route a task to the appropriate model.
61
+ *
62
+ * @param {string} taskType - Type of task to route.
63
+ * @param {object} [options]
64
+ * @returns {object}
65
+ */
66
+ function routeTask(taskType, options = {}) {
67
+ if (!TASK_TYPES.includes(taskType)) {
68
+ return { success: false, error: `Invalid task type. Must be one of: ${TASK_TYPES.join(', ')}` };
69
+ }
70
+
71
+ const configFile = options.configFile || DEFAULT_CONFIG_FILE;
72
+ const config = loadConfig(configFile);
73
+ const routing = config.routing || DEFAULT_ROUTING;
74
+ const route = routing[taskType] || DEFAULT_ROUTING[taskType];
75
+
76
+ return {
77
+ success: true,
78
+ task_type: taskType,
79
+ model: route.model,
80
+ reason: route.reason,
81
+ overridden: !!(config.routing && config.routing[taskType])
82
+ };
83
+ }
84
+
85
+ /**
86
+ * Configure routing for a task type.
87
+ *
88
+ * @param {string} taskType
89
+ * @param {string} model
90
+ * @param {object} [options]
91
+ * @returns {object}
92
+ */
93
+ function configureRoute(taskType, model, options = {}) {
94
+ if (!TASK_TYPES.includes(taskType)) {
95
+ return { success: false, error: `Invalid task type. Must be one of: ${TASK_TYPES.join(', ')}` };
96
+ }
97
+
98
+ const configFile = options.configFile || DEFAULT_CONFIG_FILE;
99
+ const config = loadConfig(configFile);
100
+ if (!config.routing) config.routing = { ...DEFAULT_ROUTING };
101
+
102
+ config.routing[taskType] = {
103
+ model,
104
+ reason: options.reason || `Custom routing to ${model}`,
105
+ configured_at: new Date().toISOString()
106
+ };
107
+
108
+ saveConfig(config, configFile);
109
+
110
+ return { success: true, task_type: taskType, model, routing: config.routing };
111
+ }
112
+
113
+ /**
114
+ * Get routing report.
115
+ *
116
+ * @param {object} [options]
117
+ * @returns {object}
118
+ */
119
+ function generateReport(options = {}) {
120
+ const configFile = options.configFile || DEFAULT_CONFIG_FILE;
121
+ const config = loadConfig(configFile);
122
+ const routing = config.routing || DEFAULT_ROUTING;
123
+
124
+ const models = [...new Set(Object.values(routing).map(r => r.model))];
125
+
126
+ return {
127
+ success: true,
128
+ task_types: TASK_TYPES.length,
129
+ configured_routes: Object.keys(routing).length,
130
+ unique_models: models.length,
131
+ models,
132
+ routing
133
+ };
134
+ }
135
+
136
+ module.exports = {
137
+ loadConfig,
138
+ saveConfig,
139
+ routeTask,
140
+ configureRoute,
141
+ generateReport,
142
+ TASK_TYPES,
143
+ DEFAULT_ROUTING
144
+ };