musubi-sdd 5.1.0 → 5.6.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 (232) hide show
  1. package/README.ja.md +106 -48
  2. package/README.md +110 -32
  3. package/bin/musubi-analyze.js +74 -67
  4. package/bin/musubi-browser.js +27 -26
  5. package/bin/musubi-change.js +48 -47
  6. package/bin/musubi-checkpoint.js +10 -7
  7. package/bin/musubi-convert.js +25 -25
  8. package/bin/musubi-costs.js +27 -10
  9. package/bin/musubi-gui.js +52 -46
  10. package/bin/musubi-init.js +1952 -10
  11. package/bin/musubi-orchestrate.js +327 -239
  12. package/bin/musubi-remember.js +69 -56
  13. package/bin/musubi-resolve.js +53 -45
  14. package/bin/musubi-trace.js +51 -22
  15. package/bin/musubi-validate.js +39 -30
  16. package/bin/musubi-workflow.js +33 -34
  17. package/bin/musubi.js +39 -2
  18. package/package.json +1 -1
  19. package/src/agents/agent-loop.js +94 -95
  20. package/src/agents/agentic/code-generator.js +119 -109
  21. package/src/agents/agentic/code-reviewer.js +105 -108
  22. package/src/agents/agentic/index.js +4 -4
  23. package/src/agents/browser/action-executor.js +13 -13
  24. package/src/agents/browser/ai-comparator.js +11 -10
  25. package/src/agents/browser/context-manager.js +6 -6
  26. package/src/agents/browser/index.js +5 -5
  27. package/src/agents/browser/nl-parser.js +31 -46
  28. package/src/agents/browser/screenshot.js +2 -2
  29. package/src/agents/browser/test-generator.js +6 -4
  30. package/src/agents/function-tool.js +71 -65
  31. package/src/agents/index.js +7 -7
  32. package/src/agents/schema-generator.js +98 -94
  33. package/src/analyzers/ast-extractor.js +158 -146
  34. package/src/analyzers/codegraph-auto-update.js +858 -0
  35. package/src/analyzers/complexity-analyzer.js +536 -0
  36. package/src/analyzers/context-optimizer.js +241 -126
  37. package/src/analyzers/impact-analyzer.js +1 -1
  38. package/src/analyzers/large-project-analyzer.js +766 -0
  39. package/src/analyzers/repository-map.js +77 -81
  40. package/src/analyzers/security-analyzer.js +19 -11
  41. package/src/analyzers/stuck-detector.js +19 -17
  42. package/src/converters/index.js +78 -57
  43. package/src/converters/ir/types.js +12 -12
  44. package/src/converters/parsers/musubi-parser.js +134 -126
  45. package/src/converters/parsers/openapi-parser.js +70 -53
  46. package/src/converters/parsers/speckit-parser.js +239 -175
  47. package/src/converters/writers/musubi-writer.js +123 -118
  48. package/src/converters/writers/speckit-writer.js +124 -113
  49. package/src/generators/rust-migration-generator.js +512 -0
  50. package/src/gui/public/index.html +1365 -1211
  51. package/src/gui/server.js +41 -40
  52. package/src/gui/services/file-watcher.js +23 -8
  53. package/src/gui/services/project-scanner.js +26 -20
  54. package/src/gui/services/replanning-service.js +27 -23
  55. package/src/gui/services/traceability-service.js +8 -8
  56. package/src/gui/services/workflow-service.js +14 -7
  57. package/src/index.js +151 -0
  58. package/src/integrations/cicd.js +90 -104
  59. package/src/integrations/codegraph-mcp.js +643 -0
  60. package/src/integrations/documentation.js +142 -103
  61. package/src/integrations/examples.js +95 -80
  62. package/src/integrations/github-client.js +17 -17
  63. package/src/integrations/index.js +5 -5
  64. package/src/integrations/mcp/index.js +21 -21
  65. package/src/integrations/mcp/mcp-context-provider.js +76 -78
  66. package/src/integrations/mcp/mcp-discovery.js +74 -72
  67. package/src/integrations/mcp/mcp-tool-registry.js +99 -94
  68. package/src/integrations/mcp-connector.js +70 -66
  69. package/src/integrations/platforms.js +50 -49
  70. package/src/integrations/tool-discovery.js +37 -31
  71. package/src/llm-providers/anthropic-provider.js +11 -11
  72. package/src/llm-providers/base-provider.js +16 -18
  73. package/src/llm-providers/copilot-provider.js +22 -19
  74. package/src/llm-providers/index.js +26 -25
  75. package/src/llm-providers/ollama-provider.js +11 -11
  76. package/src/llm-providers/openai-provider.js +12 -12
  77. package/src/managers/agent-memory.js +36 -24
  78. package/src/managers/checkpoint-manager.js +4 -8
  79. package/src/managers/delta-spec.js +19 -19
  80. package/src/managers/index.js +13 -4
  81. package/src/managers/memory-condenser.js +35 -45
  82. package/src/managers/repo-skill-manager.js +57 -31
  83. package/src/managers/skill-loader.js +25 -22
  84. package/src/managers/skill-tools.js +36 -72
  85. package/src/managers/workflow.js +30 -22
  86. package/src/monitoring/cost-tracker.js +48 -46
  87. package/src/monitoring/incident-manager.js +116 -106
  88. package/src/monitoring/index.js +144 -134
  89. package/src/monitoring/observability.js +75 -62
  90. package/src/monitoring/quality-dashboard.js +45 -41
  91. package/src/monitoring/release-manager.js +63 -53
  92. package/src/orchestration/agent-skill-binding.js +39 -47
  93. package/src/orchestration/error-handler.js +65 -107
  94. package/src/orchestration/guardrails/base-guardrail.js +26 -24
  95. package/src/orchestration/guardrails/guardrail-rules.js +50 -64
  96. package/src/orchestration/guardrails/index.js +5 -5
  97. package/src/orchestration/guardrails/input-guardrail.js +58 -45
  98. package/src/orchestration/guardrails/output-guardrail.js +104 -81
  99. package/src/orchestration/guardrails/safety-check.js +79 -79
  100. package/src/orchestration/index.js +38 -55
  101. package/src/orchestration/mcp-tool-adapters.js +96 -99
  102. package/src/orchestration/orchestration-engine.js +21 -21
  103. package/src/orchestration/pattern-registry.js +60 -45
  104. package/src/orchestration/patterns/auto.js +34 -47
  105. package/src/orchestration/patterns/group-chat.js +59 -65
  106. package/src/orchestration/patterns/handoff.js +67 -65
  107. package/src/orchestration/patterns/human-in-loop.js +51 -72
  108. package/src/orchestration/patterns/nested.js +25 -40
  109. package/src/orchestration/patterns/sequential.js +35 -34
  110. package/src/orchestration/patterns/swarm.js +63 -56
  111. package/src/orchestration/patterns/triage.js +150 -109
  112. package/src/orchestration/reasoning/index.js +9 -9
  113. package/src/orchestration/reasoning/planning-engine.js +143 -140
  114. package/src/orchestration/reasoning/reasoning-engine.js +206 -144
  115. package/src/orchestration/reasoning/self-correction.js +121 -128
  116. package/src/orchestration/replanning/adaptive-goal-modifier.js +107 -112
  117. package/src/orchestration/replanning/alternative-generator.js +37 -42
  118. package/src/orchestration/replanning/config.js +63 -59
  119. package/src/orchestration/replanning/goal-progress-tracker.js +98 -100
  120. package/src/orchestration/replanning/index.js +24 -20
  121. package/src/orchestration/replanning/plan-evaluator.js +49 -50
  122. package/src/orchestration/replanning/plan-monitor.js +32 -28
  123. package/src/orchestration/replanning/proactive-path-optimizer.js +175 -178
  124. package/src/orchestration/replanning/replan-history.js +33 -26
  125. package/src/orchestration/replanning/replanning-engine.js +106 -108
  126. package/src/orchestration/skill-executor.js +107 -109
  127. package/src/orchestration/skill-registry.js +85 -89
  128. package/src/orchestration/workflow-examples.js +228 -231
  129. package/src/orchestration/workflow-executor.js +65 -68
  130. package/src/orchestration/workflow-orchestrator.js +72 -73
  131. package/src/phase4-integration.js +47 -40
  132. package/src/phase5-integration.js +89 -30
  133. package/src/reporters/coverage-report.js +82 -30
  134. package/src/reporters/hierarchical-reporter.js +498 -0
  135. package/src/reporters/traceability-matrix-report.js +29 -20
  136. package/src/resolvers/issue-resolver.js +43 -31
  137. package/src/steering/advanced-validation.js +133 -124
  138. package/src/steering/auto-updater.js +60 -73
  139. package/src/steering/index.js +6 -6
  140. package/src/steering/quality-metrics.js +41 -35
  141. package/src/steering/steering-auto-update.js +83 -86
  142. package/src/steering/steering-validator.js +98 -106
  143. package/src/steering/template-constraints.js +53 -54
  144. package/src/templates/agents/claude-code/CLAUDE.md +32 -32
  145. package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +13 -5
  146. package/src/templates/agents/claude-code/skills/ai-ml-engineer/mlops-guide.md +23 -23
  147. package/src/templates/agents/claude-code/skills/ai-ml-engineer/model-card-template.md +60 -41
  148. package/src/templates/agents/claude-code/skills/api-designer/api-patterns.md +27 -19
  149. package/src/templates/agents/claude-code/skills/api-designer/openapi-template.md +11 -7
  150. package/src/templates/agents/claude-code/skills/bug-hunter/SKILL.md +4 -3
  151. package/src/templates/agents/claude-code/skills/bug-hunter/root-cause-analysis.md +37 -15
  152. package/src/templates/agents/claude-code/skills/change-impact-analyzer/dependency-graph-patterns.md +36 -42
  153. package/src/templates/agents/claude-code/skills/change-impact-analyzer/impact-analysis-template.md +69 -60
  154. package/src/templates/agents/claude-code/skills/cloud-architect/aws-patterns.md +31 -38
  155. package/src/templates/agents/claude-code/skills/cloud-architect/azure-patterns.md +28 -23
  156. package/src/templates/agents/claude-code/skills/code-reviewer/SKILL.md +61 -0
  157. package/src/templates/agents/claude-code/skills/code-reviewer/best-practices.md +27 -0
  158. package/src/templates/agents/claude-code/skills/code-reviewer/review-checklist.md +29 -10
  159. package/src/templates/agents/claude-code/skills/code-reviewer/review-standards.md +29 -24
  160. package/src/templates/agents/claude-code/skills/constitution-enforcer/SKILL.md +8 -6
  161. package/src/templates/agents/claude-code/skills/constitution-enforcer/constitutional-articles.md +62 -26
  162. package/src/templates/agents/claude-code/skills/constitution-enforcer/phase-minus-one-gates.md +35 -16
  163. package/src/templates/agents/claude-code/skills/database-administrator/backup-recovery.md +27 -17
  164. package/src/templates/agents/claude-code/skills/database-administrator/tuning-guide.md +25 -20
  165. package/src/templates/agents/claude-code/skills/database-schema-designer/schema-patterns.md +39 -22
  166. package/src/templates/agents/claude-code/skills/devops-engineer/ci-cd-templates.md +25 -22
  167. package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +24 -21
  168. package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +148 -63
  169. package/src/templates/agents/claude-code/skills/orchestrator/patterns.md +35 -16
  170. package/src/templates/agents/claude-code/skills/orchestrator/selection-matrix.md +69 -64
  171. package/src/templates/agents/claude-code/skills/performance-engineer/optimization-playbook.md +47 -47
  172. package/src/templates/agents/claude-code/skills/performance-optimizer/SKILL.md +69 -0
  173. package/src/templates/agents/claude-code/skills/performance-optimizer/benchmark-template.md +63 -45
  174. package/src/templates/agents/claude-code/skills/performance-optimizer/optimization-patterns.md +33 -35
  175. package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +7 -6
  176. package/src/templates/agents/claude-code/skills/project-manager/agile-ceremonies.md +47 -28
  177. package/src/templates/agents/claude-code/skills/project-manager/project-templates.md +94 -78
  178. package/src/templates/agents/claude-code/skills/quality-assurance/SKILL.md +20 -17
  179. package/src/templates/agents/claude-code/skills/quality-assurance/qa-plan-template.md +63 -49
  180. package/src/templates/agents/claude-code/skills/release-coordinator/SKILL.md +5 -5
  181. package/src/templates/agents/claude-code/skills/release-coordinator/feature-flag-guide.md +30 -26
  182. package/src/templates/agents/claude-code/skills/release-coordinator/release-plan-template.md +67 -35
  183. package/src/templates/agents/claude-code/skills/requirements-analyst/ears-format.md +54 -42
  184. package/src/templates/agents/claude-code/skills/requirements-analyst/validation-rules.md +36 -33
  185. package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +77 -19
  186. package/src/templates/agents/claude-code/skills/security-auditor/audit-checklists.md +24 -24
  187. package/src/templates/agents/claude-code/skills/security-auditor/owasp-top-10.md +61 -20
  188. package/src/templates/agents/claude-code/skills/security-auditor/vulnerability-patterns.md +43 -11
  189. package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +1 -0
  190. package/src/templates/agents/claude-code/skills/site-reliability-engineer/incident-response-template.md +55 -25
  191. package/src/templates/agents/claude-code/skills/site-reliability-engineer/observability-patterns.md +78 -68
  192. package/src/templates/agents/claude-code/skills/site-reliability-engineer/slo-sli-guide.md +73 -53
  193. package/src/templates/agents/claude-code/skills/software-developer/solid-principles.md +83 -37
  194. package/src/templates/agents/claude-code/skills/software-developer/test-first-workflow.md +38 -31
  195. package/src/templates/agents/claude-code/skills/steering/SKILL.md +1 -0
  196. package/src/templates/agents/claude-code/skills/steering/auto-update-rules.md +31 -0
  197. package/src/templates/agents/claude-code/skills/system-architect/adr-template.md +25 -7
  198. package/src/templates/agents/claude-code/skills/system-architect/c4-model-guide.md +74 -61
  199. package/src/templates/agents/claude-code/skills/technical-writer/doc-templates/documentation-templates.md +70 -52
  200. package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +2 -0
  201. package/src/templates/agents/claude-code/skills/test-engineer/ears-test-mapping.md +75 -71
  202. package/src/templates/agents/claude-code/skills/test-engineer/test-types.md +85 -63
  203. package/src/templates/agents/claude-code/skills/traceability-auditor/coverage-matrix-template.md +39 -36
  204. package/src/templates/agents/claude-code/skills/traceability-auditor/gap-detection-rules.md +22 -17
  205. package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +1 -0
  206. package/src/templates/agents/claude-code/skills/ui-ux-designer/accessibility-guidelines.md +49 -75
  207. package/src/templates/agents/claude-code/skills/ui-ux-designer/design-system-components.md +71 -59
  208. package/src/templates/agents/codex/AGENTS.md +74 -42
  209. package/src/templates/agents/cursor/AGENTS.md +74 -42
  210. package/src/templates/agents/gemini-cli/GEMINI.md +74 -42
  211. package/src/templates/agents/github-copilot/AGENTS.md +83 -51
  212. package/src/templates/agents/qwen-code/QWEN.md +74 -42
  213. package/src/templates/agents/windsurf/AGENTS.md +74 -42
  214. package/src/templates/architectures/README.md +41 -0
  215. package/src/templates/architectures/clean-architecture/README.md +113 -0
  216. package/src/templates/architectures/event-driven/README.md +162 -0
  217. package/src/templates/architectures/hexagonal/README.md +130 -0
  218. package/src/templates/index.js +6 -1
  219. package/src/templates/locale-manager.js +16 -16
  220. package/src/templates/shared/delta-spec-template.md +20 -13
  221. package/src/templates/shared/github-actions/musubi-issue-resolver.yml +5 -5
  222. package/src/templates/shared/github-actions/musubi-security-check.yml +3 -3
  223. package/src/templates/shared/github-actions/musubi-validate.yml +4 -4
  224. package/src/templates/shared/steering/structure.md +95 -0
  225. package/src/templates/skills/browser-agent.md +21 -16
  226. package/src/templates/skills/web-gui.md +8 -0
  227. package/src/templates/template-constraints.js +50 -53
  228. package/src/validators/advanced-validation.js +30 -36
  229. package/src/validators/constitutional-validator.js +77 -73
  230. package/src/validators/critic-system.js +49 -59
  231. package/src/validators/delta-format.js +59 -55
  232. package/src/validators/traceability-validator.js +7 -11
@@ -1,17 +1,17 @@
1
1
  /**
2
2
  * Incident Manager - Incident response and management
3
- *
3
+ *
4
4
  * Provides incident management capabilities:
5
5
  * - Incident lifecycle management
6
6
  * - Runbook execution
7
7
  * - Post-mortem generation
8
8
  * - On-call management
9
- *
9
+ *
10
10
  * Part of MUSUBI v5.0.0 - Production Readiness
11
- *
11
+ *
12
12
  * @module monitoring/incident-manager
13
13
  * @version 1.0.0
14
- *
14
+ *
15
15
  * @traceability
16
16
  * - Requirement: REQ-P5-002 (Incident Management)
17
17
  * - Design: docs/design/tdd-musubi-v5.0.0.md#3.2
@@ -28,7 +28,7 @@ const IncidentSeverity = {
28
28
  SEV2: 'sev2', // High - significant impact
29
29
  SEV3: 'sev3', // Medium - limited impact
30
30
  SEV4: 'sev4', // Low - minimal impact
31
- SEV5: 'sev5' // Informational
31
+ SEV5: 'sev5', // Informational
32
32
  };
33
33
 
34
34
  /**
@@ -42,7 +42,7 @@ const IncidentStatus = {
42
42
  MITIGATING: 'mitigating',
43
43
  MONITORING: 'monitoring',
44
44
  RESOLVED: 'resolved',
45
- CLOSED: 'closed'
45
+ CLOSED: 'closed',
46
46
  };
47
47
 
48
48
  /**
@@ -53,7 +53,7 @@ const StepStatus = {
53
53
  IN_PROGRESS: 'in-progress',
54
54
  COMPLETED: 'completed',
55
55
  FAILED: 'failed',
56
- SKIPPED: 'skipped'
56
+ SKIPPED: 'skipped',
57
57
  };
58
58
 
59
59
  /**
@@ -66,35 +66,37 @@ class Incident {
66
66
  this.description = options.description || '';
67
67
  this.severity = options.severity || IncidentSeverity.SEV3;
68
68
  this.status = options.status || IncidentStatus.DETECTED;
69
-
69
+
70
70
  this.detectedAt = options.detectedAt || new Date();
71
71
  this.acknowledgedAt = null;
72
72
  this.mitigatedAt = null;
73
73
  this.resolvedAt = null;
74
74
  this.closedAt = null;
75
-
75
+
76
76
  this.affectedServices = options.affectedServices || [];
77
77
  this.impactSummary = options.impactSummary || '';
78
78
  this.customerImpact = options.customerImpact || {
79
79
  affected: 0,
80
- percentage: 0
80
+ percentage: 0,
81
81
  };
82
-
82
+
83
83
  this.assignee = options.assignee || null;
84
84
  this.responders = options.responders || [];
85
85
  this.commander = options.commander || null;
86
-
87
- this.timeline = [{
88
- timestamp: this.detectedAt,
89
- action: 'detected',
90
- description: 'Incident detected',
91
- actor: 'system'
92
- }];
93
-
86
+
87
+ this.timeline = [
88
+ {
89
+ timestamp: this.detectedAt,
90
+ action: 'detected',
91
+ description: 'Incident detected',
92
+ actor: 'system',
93
+ },
94
+ ];
95
+
94
96
  this.rootCause = null;
95
97
  this.resolution = null;
96
98
  this.postMortem = null;
97
-
99
+
98
100
  this.relatedIncidents = options.relatedIncidents || [];
99
101
  this.tags = options.tags || [];
100
102
  this.metadata = options.metadata || {};
@@ -107,15 +109,15 @@ class Incident {
107
109
  if (this.acknowledgedAt) {
108
110
  throw new Error('Incident already acknowledged');
109
111
  }
110
-
112
+
111
113
  this.acknowledgedAt = new Date();
112
114
  this.status = IncidentStatus.TRIAGING;
113
115
  this.assignee = responder;
114
-
116
+
115
117
  if (!this.responders.includes(responder)) {
116
118
  this.responders.push(responder);
117
119
  }
118
-
120
+
119
121
  this._addTimelineEntry('acknowledged', `Acknowledged by ${responder}`, responder);
120
122
  return this;
121
123
  }
@@ -137,7 +139,11 @@ class Incident {
137
139
  setCommander(commander) {
138
140
  this.commander = commander;
139
141
  this.addResponder(commander, 'commander');
140
- this._addTimelineEntry('commander_assigned', `${commander} assigned as incident commander`, commander);
142
+ this._addTimelineEntry(
143
+ 'commander_assigned',
144
+ `${commander} assigned as incident commander`,
145
+ commander
146
+ );
141
147
  return this;
142
148
  }
143
149
 
@@ -147,9 +153,13 @@ class Incident {
147
153
  updateStatus(newStatus, note = '', actor = 'system') {
148
154
  const previousStatus = this.status;
149
155
  this.status = newStatus;
150
-
151
- this._addTimelineEntry('status_change', `Status changed from ${previousStatus} to ${newStatus}. ${note}`, actor);
152
-
156
+
157
+ this._addTimelineEntry(
158
+ 'status_change',
159
+ `Status changed from ${previousStatus} to ${newStatus}. ${note}`,
160
+ actor
161
+ );
162
+
153
163
  // Update timestamps
154
164
  if (newStatus === IncidentStatus.MITIGATING && !this.mitigatedAt) {
155
165
  // Record when mitigation started
@@ -160,7 +170,7 @@ class Incident {
160
170
  if (newStatus === IncidentStatus.CLOSED) {
161
171
  this.closedAt = new Date();
162
172
  }
163
-
173
+
164
174
  return this;
165
175
  }
166
176
 
@@ -170,7 +180,11 @@ class Incident {
170
180
  updateSeverity(newSeverity, reason = '', actor = 'system') {
171
181
  const previousSeverity = this.severity;
172
182
  this.severity = newSeverity;
173
- this._addTimelineEntry('severity_change', `Severity changed from ${previousSeverity} to ${newSeverity}. ${reason}`, actor);
183
+ this._addTimelineEntry(
184
+ 'severity_change',
185
+ `Severity changed from ${previousSeverity} to ${newSeverity}. ${reason}`,
186
+ actor
187
+ );
174
188
  return this;
175
189
  }
176
190
 
@@ -208,21 +222,17 @@ class Incident {
208
222
  */
209
223
  getMetrics() {
210
224
  const now = new Date();
211
-
225
+
212
226
  return {
213
- timeToAcknowledge: this.acknowledgedAt
214
- ? (this.acknowledgedAt - this.detectedAt) / 1000
215
- : null,
216
- timeToMitigate: this.mitigatedAt
217
- ? (this.mitigatedAt - this.detectedAt) / 1000
218
- : null,
219
- timeToResolve: this.resolvedAt
220
- ? (this.resolvedAt - this.detectedAt) / 1000
227
+ timeToAcknowledge: this.acknowledgedAt
228
+ ? (this.acknowledgedAt - this.detectedAt) / 1000
221
229
  : null,
222
- totalDuration: this.closedAt
223
- ? (this.closedAt - this.detectedAt) / 1000
230
+ timeToMitigate: this.mitigatedAt ? (this.mitigatedAt - this.detectedAt) / 1000 : null,
231
+ timeToResolve: this.resolvedAt ? (this.resolvedAt - this.detectedAt) / 1000 : null,
232
+ totalDuration: this.closedAt
233
+ ? (this.closedAt - this.detectedAt) / 1000
224
234
  : (now - this.detectedAt) / 1000,
225
- isOpen: !this.closedAt
235
+ isOpen: !this.closedAt,
226
236
  };
227
237
  }
228
238
 
@@ -235,7 +245,7 @@ class Incident {
235
245
  timestamp: new Date(),
236
246
  action,
237
247
  description,
238
- actor
248
+ actor,
239
249
  });
240
250
  }
241
251
 
@@ -270,7 +280,7 @@ class Incident {
270
280
  rootCause: this.rootCause,
271
281
  resolution: this.resolution,
272
282
  tags: this.tags,
273
- metrics: this.getMetrics()
283
+ metrics: this.getMetrics(),
274
284
  };
275
285
  }
276
286
  }
@@ -287,7 +297,7 @@ class Runbook {
287
297
  this.category = options.category || 'general';
288
298
  this.tags = options.tags || [];
289
299
  this.estimatedDuration = options.estimatedDuration || '15 minutes';
290
-
300
+
291
301
  this.steps = (options.steps || []).map((step, index) => ({
292
302
  id: step.id || `step-${index + 1}`,
293
303
  order: step.order || index + 1,
@@ -297,9 +307,9 @@ class Runbook {
297
307
  expectedOutput: step.expectedOutput || null,
298
308
  onFailure: step.onFailure || 'abort', // abort, continue, retry
299
309
  timeout: step.timeout || 300, // seconds
300
- requiresConfirmation: step.requiresConfirmation || false
310
+ requiresConfirmation: step.requiresConfirmation || false,
301
311
  }));
302
-
312
+
303
313
  this.metadata = options.metadata || {};
304
314
  }
305
315
 
@@ -313,7 +323,7 @@ class Runbook {
313
323
  tags: this.tags,
314
324
  estimatedDuration: this.estimatedDuration,
315
325
  steps: this.steps,
316
- metadata: this.metadata
326
+ metadata: this.metadata,
317
327
  };
318
328
  }
319
329
  }
@@ -329,16 +339,16 @@ class RunbookExecution {
329
339
  this.startedAt = new Date();
330
340
  this.completedAt = null;
331
341
  this.status = 'running';
332
-
342
+
333
343
  this.stepResults = runbook.steps.map(step => ({
334
344
  stepId: step.id,
335
345
  status: StepStatus.PENDING,
336
346
  startedAt: null,
337
347
  completedAt: null,
338
348
  output: null,
339
- error: null
349
+ error: null,
340
350
  }));
341
-
351
+
342
352
  this.currentStepIndex = 0;
343
353
  }
344
354
 
@@ -365,13 +375,13 @@ class RunbookExecution {
365
375
  result.output = output;
366
376
  this.currentStepIndex++;
367
377
  }
368
-
378
+
369
379
  // Check if all steps completed
370
380
  if (this.currentStepIndex >= this.runbook.steps.length) {
371
381
  this.status = 'completed';
372
382
  this.completedAt = new Date();
373
383
  }
374
-
384
+
375
385
  return this;
376
386
  }
377
387
 
@@ -385,7 +395,7 @@ class RunbookExecution {
385
395
  result.completedAt = new Date();
386
396
  result.error = error;
387
397
  }
388
-
398
+
389
399
  // Get step config to determine action
390
400
  const step = this.runbook.steps.find(s => s.id === stepId);
391
401
  if (step && step.onFailure === 'abort') {
@@ -394,7 +404,7 @@ class RunbookExecution {
394
404
  } else if (step && step.onFailure === 'continue') {
395
405
  this.currentStepIndex++;
396
406
  }
397
-
407
+
398
408
  return this;
399
409
  }
400
410
 
@@ -426,16 +436,15 @@ class RunbookExecution {
426
436
  * Get execution progress
427
437
  */
428
438
  getProgress() {
429
- const completed = this.stepResults.filter(r =>
430
- r.status === StepStatus.COMPLETED ||
431
- r.status === StepStatus.SKIPPED
439
+ const completed = this.stepResults.filter(
440
+ r => r.status === StepStatus.COMPLETED || r.status === StepStatus.SKIPPED
432
441
  ).length;
433
-
442
+
434
443
  return {
435
444
  total: this.runbook.steps.length,
436
445
  completed,
437
446
  percentage: Math.round((completed / this.runbook.steps.length) * 100),
438
- currentStep: this.getCurrentStep()
447
+ currentStep: this.getCurrentStep(),
439
448
  };
440
449
  }
441
450
 
@@ -449,7 +458,7 @@ class RunbookExecution {
449
458
  completedAt: this.completedAt,
450
459
  status: this.status,
451
460
  stepResults: this.stepResults,
452
- progress: this.getProgress()
461
+ progress: this.getProgress(),
453
462
  };
454
463
  }
455
464
  }
@@ -464,30 +473,30 @@ class PostMortem {
464
473
  this.title = `Post-Mortem: ${incident.title}`;
465
474
  this.createdAt = new Date();
466
475
  this.status = 'draft';
467
-
476
+
468
477
  // Auto-populate from incident
469
478
  this.summary = {
470
479
  severity: incident.severity,
471
480
  duration: incident.getMetrics().totalDuration,
472
481
  affectedServices: incident.affectedServices,
473
- customerImpact: incident.customerImpact
482
+ customerImpact: incident.customerImpact,
474
483
  };
475
-
484
+
476
485
  this.timeline = incident.timeline;
477
486
  this.rootCause = incident.rootCause || 'TBD';
478
487
  this.resolution = incident.resolution || 'TBD';
479
-
488
+
480
489
  this.detection = {
481
490
  method: 'TBD',
482
- timeToDetect: incident.getMetrics().timeToAcknowledge
491
+ timeToDetect: incident.getMetrics().timeToAcknowledge,
483
492
  };
484
-
493
+
485
494
  this.response = {
486
495
  responders: incident.responders,
487
496
  commander: incident.commander,
488
- timeToMitigate: incident.getMetrics().timeToMitigate
497
+ timeToMitigate: incident.getMetrics().timeToMitigate,
489
498
  };
490
-
499
+
491
500
  this.actionItems = [];
492
501
  this.lessonsLearned = [];
493
502
  this.whatWentWell = [];
@@ -506,7 +515,7 @@ class PostMortem {
506
515
  priority: item.priority || 'medium',
507
516
  dueDate: item.dueDate || null,
508
517
  status: 'open',
509
- createdAt: new Date()
518
+ createdAt: new Date(),
510
519
  });
511
520
  return this;
512
521
  }
@@ -621,7 +630,7 @@ class PostMortem {
621
630
  whatWentWell: this.whatWentWell,
622
631
  whatWentPoorly: this.whatWentPoorly,
623
632
  lessonsLearned: this.lessonsLearned,
624
- actionItems: this.actionItems
633
+ actionItems: this.actionItems,
625
634
  };
626
635
  }
627
636
  }
@@ -636,16 +645,16 @@ class IncidentManager extends EventEmitter {
636
645
  this.runbooks = new Map();
637
646
  this.executions = new Map();
638
647
  this.postMortems = new Map();
639
-
648
+
640
649
  this.oncall = {
641
650
  primary: options.primaryOncall || null,
642
651
  secondary: options.secondaryOncall || null,
643
- escalation: options.escalation || []
652
+ escalation: options.escalation || [],
644
653
  };
645
-
654
+
646
655
  this.options = {
647
656
  autoAcknowledgeTimeout: options.autoAcknowledgeTimeout || 300, // 5 minutes
648
- ...options
657
+ ...options,
649
658
  };
650
659
  }
651
660
 
@@ -656,16 +665,16 @@ class IncidentManager extends EventEmitter {
656
665
  const incident = options instanceof Incident ? options : new Incident(options);
657
666
  this.incidents.set(incident.id, incident);
658
667
  this.emit('incidentCreated', incident);
659
-
668
+
660
669
  // Auto-notify on-call
661
670
  if (this.oncall.primary) {
662
671
  this.emit('notify', {
663
672
  type: 'incident',
664
673
  incident,
665
- recipient: this.oncall.primary
674
+ recipient: this.oncall.primary,
666
675
  });
667
676
  }
668
-
677
+
669
678
  return incident;
670
679
  }
671
680
 
@@ -681,7 +690,7 @@ class IncidentManager extends EventEmitter {
681
690
  */
682
691
  listIncidents(filter = {}) {
683
692
  let incidents = [...this.incidents.values()];
684
-
693
+
685
694
  if (filter.status) {
686
695
  const statuses = Array.isArray(filter.status) ? filter.status : [filter.status];
687
696
  incidents = incidents.filter(i => statuses.includes(i.status));
@@ -691,12 +700,11 @@ class IncidentManager extends EventEmitter {
691
700
  incidents = incidents.filter(i => severities.includes(i.severity));
692
701
  }
693
702
  if (filter.open) {
694
- incidents = incidents.filter(i =>
695
- i.status !== IncidentStatus.RESOLVED &&
696
- i.status !== IncidentStatus.CLOSED
703
+ incidents = incidents.filter(
704
+ i => i.status !== IncidentStatus.RESOLVED && i.status !== IncidentStatus.CLOSED
697
705
  );
698
706
  }
699
-
707
+
700
708
  return incidents.map(i => i.toJSON());
701
709
  }
702
710
 
@@ -706,7 +714,7 @@ class IncidentManager extends EventEmitter {
706
714
  acknowledgeIncident(incidentId, responder) {
707
715
  const incident = this.incidents.get(incidentId);
708
716
  if (!incident) throw new Error(`Incident not found: ${incidentId}`);
709
-
717
+
710
718
  incident.acknowledge(responder);
711
719
  this.emit('incidentAcknowledged', incident);
712
720
  return incident;
@@ -718,7 +726,7 @@ class IncidentManager extends EventEmitter {
718
726
  updateIncidentStatus(incidentId, newStatus, note = '', actor = 'system') {
719
727
  const incident = this.incidents.get(incidentId);
720
728
  if (!incident) throw new Error(`Incident not found: ${incidentId}`);
721
-
729
+
722
730
  incident.updateStatus(newStatus, note, actor);
723
731
  this.emit('incidentStatusChanged', { incident, newStatus });
724
732
  return incident;
@@ -730,7 +738,7 @@ class IncidentManager extends EventEmitter {
730
738
  resolveIncident(incidentId, resolution, actor = 'system') {
731
739
  const incident = this.incidents.get(incidentId);
732
740
  if (!incident) throw new Error(`Incident not found: ${incidentId}`);
733
-
741
+
734
742
  incident.setResolution(resolution, actor);
735
743
  this.emit('incidentResolved', incident);
736
744
  return incident;
@@ -758,14 +766,14 @@ class IncidentManager extends EventEmitter {
758
766
  */
759
767
  listRunbooks(filter = {}) {
760
768
  let runbooks = [...this.runbooks.values()];
761
-
769
+
762
770
  if (filter.category) {
763
771
  runbooks = runbooks.filter(r => r.category === filter.category);
764
772
  }
765
773
  if (filter.tag) {
766
774
  runbooks = runbooks.filter(r => r.tags.includes(filter.tag));
767
775
  }
768
-
776
+
769
777
  return runbooks.map(r => r.toJSON());
770
778
  }
771
779
 
@@ -775,16 +783,16 @@ class IncidentManager extends EventEmitter {
775
783
  executeRunbook(runbookId, incident = null) {
776
784
  const runbook = this.runbooks.get(runbookId);
777
785
  if (!runbook) throw new Error(`Runbook not found: ${runbookId}`);
778
-
786
+
779
787
  const execution = new RunbookExecution(runbook, incident);
780
788
  this.executions.set(execution.id, execution);
781
789
  this.emit('runbookExecutionStarted', execution);
782
-
790
+
783
791
  // Link to incident if provided
784
792
  if (incident) {
785
793
  incident.addUpdate(`Runbook "${runbook.name}" execution started`, 'system');
786
794
  }
787
-
795
+
788
796
  return execution;
789
797
  }
790
798
 
@@ -801,11 +809,11 @@ class IncidentManager extends EventEmitter {
801
809
  createPostMortem(incidentId) {
802
810
  const incident = this.incidents.get(incidentId);
803
811
  if (!incident) throw new Error(`Incident not found: ${incidentId}`);
804
-
812
+
805
813
  const postMortem = new PostMortem(incident);
806
814
  this.postMortems.set(postMortem.id, postMortem);
807
815
  incident.postMortem = postMortem.id;
808
-
816
+
809
817
  this.emit('postMortemCreated', postMortem);
810
818
  return postMortem;
811
819
  }
@@ -840,10 +848,8 @@ class IncidentManager extends EventEmitter {
840
848
  getStatistics(options = {}) {
841
849
  const incidents = [...this.incidents.values()];
842
850
  const { since } = options;
843
-
844
- const filtered = since
845
- ? incidents.filter(i => i.detectedAt >= since)
846
- : incidents;
851
+
852
+ const filtered = since ? incidents.filter(i => i.detectedAt >= since) : incidents;
847
853
 
848
854
  const metrics = filtered.map(i => i.getMetrics());
849
855
  const acknowledged = metrics.filter(m => m.timeToAcknowledge !== null);
@@ -851,15 +857,19 @@ class IncidentManager extends EventEmitter {
851
857
 
852
858
  return {
853
859
  total: filtered.length,
854
- open: filtered.filter(i => i.status !== IncidentStatus.CLOSED && i.status !== IncidentStatus.RESOLVED).length,
860
+ open: filtered.filter(
861
+ i => i.status !== IncidentStatus.CLOSED && i.status !== IncidentStatus.RESOLVED
862
+ ).length,
855
863
  bySeverity: this._countBy(filtered, 'severity'),
856
864
  byStatus: this._countBy(filtered, 'status'),
857
- mttr: resolved.length > 0
858
- ? resolved.reduce((sum, m) => sum + m.timeToResolve, 0) / resolved.length
859
- : null,
860
- mtta: acknowledged.length > 0
861
- ? acknowledged.reduce((sum, m) => sum + m.timeToAcknowledge, 0) / acknowledged.length
862
- : null
865
+ mttr:
866
+ resolved.length > 0
867
+ ? resolved.reduce((sum, m) => sum + m.timeToResolve, 0) / resolved.length
868
+ : null,
869
+ mtta:
870
+ acknowledged.length > 0
871
+ ? acknowledged.reduce((sum, m) => sum + m.timeToAcknowledge, 0) / acknowledged.length
872
+ : null,
863
873
  };
864
874
  }
865
875
 
@@ -889,12 +899,12 @@ module.exports = {
889
899
  RunbookExecution,
890
900
  PostMortem,
891
901
  IncidentManager,
892
-
902
+
893
903
  // Constants
894
904
  IncidentSeverity,
895
905
  IncidentStatus,
896
906
  StepStatus,
897
-
907
+
898
908
  // Factory
899
- createIncidentManager
909
+ createIncidentManager,
900
910
  };