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.
- package/README.ja.md +106 -48
- package/README.md +110 -32
- package/bin/musubi-analyze.js +74 -67
- package/bin/musubi-browser.js +27 -26
- package/bin/musubi-change.js +48 -47
- package/bin/musubi-checkpoint.js +10 -7
- package/bin/musubi-convert.js +25 -25
- package/bin/musubi-costs.js +27 -10
- package/bin/musubi-gui.js +52 -46
- package/bin/musubi-init.js +1952 -10
- package/bin/musubi-orchestrate.js +327 -239
- package/bin/musubi-remember.js +69 -56
- package/bin/musubi-resolve.js +53 -45
- package/bin/musubi-trace.js +51 -22
- package/bin/musubi-validate.js +39 -30
- package/bin/musubi-workflow.js +33 -34
- package/bin/musubi.js +39 -2
- package/package.json +1 -1
- package/src/agents/agent-loop.js +94 -95
- package/src/agents/agentic/code-generator.js +119 -109
- package/src/agents/agentic/code-reviewer.js +105 -108
- package/src/agents/agentic/index.js +4 -4
- package/src/agents/browser/action-executor.js +13 -13
- package/src/agents/browser/ai-comparator.js +11 -10
- package/src/agents/browser/context-manager.js +6 -6
- package/src/agents/browser/index.js +5 -5
- package/src/agents/browser/nl-parser.js +31 -46
- package/src/agents/browser/screenshot.js +2 -2
- package/src/agents/browser/test-generator.js +6 -4
- package/src/agents/function-tool.js +71 -65
- package/src/agents/index.js +7 -7
- package/src/agents/schema-generator.js +98 -94
- package/src/analyzers/ast-extractor.js +158 -146
- package/src/analyzers/codegraph-auto-update.js +858 -0
- package/src/analyzers/complexity-analyzer.js +536 -0
- package/src/analyzers/context-optimizer.js +241 -126
- package/src/analyzers/impact-analyzer.js +1 -1
- package/src/analyzers/large-project-analyzer.js +766 -0
- package/src/analyzers/repository-map.js +77 -81
- package/src/analyzers/security-analyzer.js +19 -11
- package/src/analyzers/stuck-detector.js +19 -17
- package/src/converters/index.js +78 -57
- package/src/converters/ir/types.js +12 -12
- package/src/converters/parsers/musubi-parser.js +134 -126
- package/src/converters/parsers/openapi-parser.js +70 -53
- package/src/converters/parsers/speckit-parser.js +239 -175
- package/src/converters/writers/musubi-writer.js +123 -118
- package/src/converters/writers/speckit-writer.js +124 -113
- package/src/generators/rust-migration-generator.js +512 -0
- package/src/gui/public/index.html +1365 -1211
- package/src/gui/server.js +41 -40
- package/src/gui/services/file-watcher.js +23 -8
- package/src/gui/services/project-scanner.js +26 -20
- package/src/gui/services/replanning-service.js +27 -23
- package/src/gui/services/traceability-service.js +8 -8
- package/src/gui/services/workflow-service.js +14 -7
- package/src/index.js +151 -0
- package/src/integrations/cicd.js +90 -104
- package/src/integrations/codegraph-mcp.js +643 -0
- package/src/integrations/documentation.js +142 -103
- package/src/integrations/examples.js +95 -80
- package/src/integrations/github-client.js +17 -17
- package/src/integrations/index.js +5 -5
- package/src/integrations/mcp/index.js +21 -21
- package/src/integrations/mcp/mcp-context-provider.js +76 -78
- package/src/integrations/mcp/mcp-discovery.js +74 -72
- package/src/integrations/mcp/mcp-tool-registry.js +99 -94
- package/src/integrations/mcp-connector.js +70 -66
- package/src/integrations/platforms.js +50 -49
- package/src/integrations/tool-discovery.js +37 -31
- package/src/llm-providers/anthropic-provider.js +11 -11
- package/src/llm-providers/base-provider.js +16 -18
- package/src/llm-providers/copilot-provider.js +22 -19
- package/src/llm-providers/index.js +26 -25
- package/src/llm-providers/ollama-provider.js +11 -11
- package/src/llm-providers/openai-provider.js +12 -12
- package/src/managers/agent-memory.js +36 -24
- package/src/managers/checkpoint-manager.js +4 -8
- package/src/managers/delta-spec.js +19 -19
- package/src/managers/index.js +13 -4
- package/src/managers/memory-condenser.js +35 -45
- package/src/managers/repo-skill-manager.js +57 -31
- package/src/managers/skill-loader.js +25 -22
- package/src/managers/skill-tools.js +36 -72
- package/src/managers/workflow.js +30 -22
- package/src/monitoring/cost-tracker.js +48 -46
- package/src/monitoring/incident-manager.js +116 -106
- package/src/monitoring/index.js +144 -134
- package/src/monitoring/observability.js +75 -62
- package/src/monitoring/quality-dashboard.js +45 -41
- package/src/monitoring/release-manager.js +63 -53
- package/src/orchestration/agent-skill-binding.js +39 -47
- package/src/orchestration/error-handler.js +65 -107
- package/src/orchestration/guardrails/base-guardrail.js +26 -24
- package/src/orchestration/guardrails/guardrail-rules.js +50 -64
- package/src/orchestration/guardrails/index.js +5 -5
- package/src/orchestration/guardrails/input-guardrail.js +58 -45
- package/src/orchestration/guardrails/output-guardrail.js +104 -81
- package/src/orchestration/guardrails/safety-check.js +79 -79
- package/src/orchestration/index.js +38 -55
- package/src/orchestration/mcp-tool-adapters.js +96 -99
- package/src/orchestration/orchestration-engine.js +21 -21
- package/src/orchestration/pattern-registry.js +60 -45
- package/src/orchestration/patterns/auto.js +34 -47
- package/src/orchestration/patterns/group-chat.js +59 -65
- package/src/orchestration/patterns/handoff.js +67 -65
- package/src/orchestration/patterns/human-in-loop.js +51 -72
- package/src/orchestration/patterns/nested.js +25 -40
- package/src/orchestration/patterns/sequential.js +35 -34
- package/src/orchestration/patterns/swarm.js +63 -56
- package/src/orchestration/patterns/triage.js +150 -109
- package/src/orchestration/reasoning/index.js +9 -9
- package/src/orchestration/reasoning/planning-engine.js +143 -140
- package/src/orchestration/reasoning/reasoning-engine.js +206 -144
- package/src/orchestration/reasoning/self-correction.js +121 -128
- package/src/orchestration/replanning/adaptive-goal-modifier.js +107 -112
- package/src/orchestration/replanning/alternative-generator.js +37 -42
- package/src/orchestration/replanning/config.js +63 -59
- package/src/orchestration/replanning/goal-progress-tracker.js +98 -100
- package/src/orchestration/replanning/index.js +24 -20
- package/src/orchestration/replanning/plan-evaluator.js +49 -50
- package/src/orchestration/replanning/plan-monitor.js +32 -28
- package/src/orchestration/replanning/proactive-path-optimizer.js +175 -178
- package/src/orchestration/replanning/replan-history.js +33 -26
- package/src/orchestration/replanning/replanning-engine.js +106 -108
- package/src/orchestration/skill-executor.js +107 -109
- package/src/orchestration/skill-registry.js +85 -89
- package/src/orchestration/workflow-examples.js +228 -231
- package/src/orchestration/workflow-executor.js +65 -68
- package/src/orchestration/workflow-orchestrator.js +72 -73
- package/src/phase4-integration.js +47 -40
- package/src/phase5-integration.js +89 -30
- package/src/reporters/coverage-report.js +82 -30
- package/src/reporters/hierarchical-reporter.js +498 -0
- package/src/reporters/traceability-matrix-report.js +29 -20
- package/src/resolvers/issue-resolver.js +43 -31
- package/src/steering/advanced-validation.js +133 -124
- package/src/steering/auto-updater.js +60 -73
- package/src/steering/index.js +6 -6
- package/src/steering/quality-metrics.js +41 -35
- package/src/steering/steering-auto-update.js +83 -86
- package/src/steering/steering-validator.js +98 -106
- package/src/steering/template-constraints.js +53 -54
- package/src/templates/agents/claude-code/CLAUDE.md +32 -32
- package/src/templates/agents/claude-code/skills/agent-assistant/SKILL.md +13 -5
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/mlops-guide.md +23 -23
- package/src/templates/agents/claude-code/skills/ai-ml-engineer/model-card-template.md +60 -41
- package/src/templates/agents/claude-code/skills/api-designer/api-patterns.md +27 -19
- package/src/templates/agents/claude-code/skills/api-designer/openapi-template.md +11 -7
- package/src/templates/agents/claude-code/skills/bug-hunter/SKILL.md +4 -3
- package/src/templates/agents/claude-code/skills/bug-hunter/root-cause-analysis.md +37 -15
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/dependency-graph-patterns.md +36 -42
- package/src/templates/agents/claude-code/skills/change-impact-analyzer/impact-analysis-template.md +69 -60
- package/src/templates/agents/claude-code/skills/cloud-architect/aws-patterns.md +31 -38
- package/src/templates/agents/claude-code/skills/cloud-architect/azure-patterns.md +28 -23
- package/src/templates/agents/claude-code/skills/code-reviewer/SKILL.md +61 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/best-practices.md +27 -0
- package/src/templates/agents/claude-code/skills/code-reviewer/review-checklist.md +29 -10
- package/src/templates/agents/claude-code/skills/code-reviewer/review-standards.md +29 -24
- package/src/templates/agents/claude-code/skills/constitution-enforcer/SKILL.md +8 -6
- package/src/templates/agents/claude-code/skills/constitution-enforcer/constitutional-articles.md +62 -26
- package/src/templates/agents/claude-code/skills/constitution-enforcer/phase-minus-one-gates.md +35 -16
- package/src/templates/agents/claude-code/skills/database-administrator/backup-recovery.md +27 -17
- package/src/templates/agents/claude-code/skills/database-administrator/tuning-guide.md +25 -20
- package/src/templates/agents/claude-code/skills/database-schema-designer/schema-patterns.md +39 -22
- package/src/templates/agents/claude-code/skills/devops-engineer/ci-cd-templates.md +25 -22
- package/src/templates/agents/claude-code/skills/issue-resolver/SKILL.md +24 -21
- package/src/templates/agents/claude-code/skills/orchestrator/SKILL.md +148 -63
- package/src/templates/agents/claude-code/skills/orchestrator/patterns.md +35 -16
- package/src/templates/agents/claude-code/skills/orchestrator/selection-matrix.md +69 -64
- package/src/templates/agents/claude-code/skills/performance-engineer/optimization-playbook.md +47 -47
- package/src/templates/agents/claude-code/skills/performance-optimizer/SKILL.md +69 -0
- package/src/templates/agents/claude-code/skills/performance-optimizer/benchmark-template.md +63 -45
- package/src/templates/agents/claude-code/skills/performance-optimizer/optimization-patterns.md +33 -35
- package/src/templates/agents/claude-code/skills/project-manager/SKILL.md +7 -6
- package/src/templates/agents/claude-code/skills/project-manager/agile-ceremonies.md +47 -28
- package/src/templates/agents/claude-code/skills/project-manager/project-templates.md +94 -78
- package/src/templates/agents/claude-code/skills/quality-assurance/SKILL.md +20 -17
- package/src/templates/agents/claude-code/skills/quality-assurance/qa-plan-template.md +63 -49
- package/src/templates/agents/claude-code/skills/release-coordinator/SKILL.md +5 -5
- package/src/templates/agents/claude-code/skills/release-coordinator/feature-flag-guide.md +30 -26
- package/src/templates/agents/claude-code/skills/release-coordinator/release-plan-template.md +67 -35
- package/src/templates/agents/claude-code/skills/requirements-analyst/ears-format.md +54 -42
- package/src/templates/agents/claude-code/skills/requirements-analyst/validation-rules.md +36 -33
- package/src/templates/agents/claude-code/skills/security-auditor/SKILL.md +77 -19
- package/src/templates/agents/claude-code/skills/security-auditor/audit-checklists.md +24 -24
- package/src/templates/agents/claude-code/skills/security-auditor/owasp-top-10.md +61 -20
- package/src/templates/agents/claude-code/skills/security-auditor/vulnerability-patterns.md +43 -11
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/incident-response-template.md +55 -25
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/observability-patterns.md +78 -68
- package/src/templates/agents/claude-code/skills/site-reliability-engineer/slo-sli-guide.md +73 -53
- package/src/templates/agents/claude-code/skills/software-developer/solid-principles.md +83 -37
- package/src/templates/agents/claude-code/skills/software-developer/test-first-workflow.md +38 -31
- package/src/templates/agents/claude-code/skills/steering/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/steering/auto-update-rules.md +31 -0
- package/src/templates/agents/claude-code/skills/system-architect/adr-template.md +25 -7
- package/src/templates/agents/claude-code/skills/system-architect/c4-model-guide.md +74 -61
- package/src/templates/agents/claude-code/skills/technical-writer/doc-templates/documentation-templates.md +70 -52
- package/src/templates/agents/claude-code/skills/test-engineer/SKILL.md +2 -0
- package/src/templates/agents/claude-code/skills/test-engineer/ears-test-mapping.md +75 -71
- package/src/templates/agents/claude-code/skills/test-engineer/test-types.md +85 -63
- package/src/templates/agents/claude-code/skills/traceability-auditor/coverage-matrix-template.md +39 -36
- package/src/templates/agents/claude-code/skills/traceability-auditor/gap-detection-rules.md +22 -17
- package/src/templates/agents/claude-code/skills/ui-ux-designer/SKILL.md +1 -0
- package/src/templates/agents/claude-code/skills/ui-ux-designer/accessibility-guidelines.md +49 -75
- package/src/templates/agents/claude-code/skills/ui-ux-designer/design-system-components.md +71 -59
- package/src/templates/agents/codex/AGENTS.md +74 -42
- package/src/templates/agents/cursor/AGENTS.md +74 -42
- package/src/templates/agents/gemini-cli/GEMINI.md +74 -42
- package/src/templates/agents/github-copilot/AGENTS.md +83 -51
- package/src/templates/agents/qwen-code/QWEN.md +74 -42
- package/src/templates/agents/windsurf/AGENTS.md +74 -42
- package/src/templates/architectures/README.md +41 -0
- package/src/templates/architectures/clean-architecture/README.md +113 -0
- package/src/templates/architectures/event-driven/README.md +162 -0
- package/src/templates/architectures/hexagonal/README.md +130 -0
- package/src/templates/index.js +6 -1
- package/src/templates/locale-manager.js +16 -16
- package/src/templates/shared/delta-spec-template.md +20 -13
- package/src/templates/shared/github-actions/musubi-issue-resolver.yml +5 -5
- package/src/templates/shared/github-actions/musubi-security-check.yml +3 -3
- package/src/templates/shared/github-actions/musubi-validate.yml +4 -4
- package/src/templates/shared/steering/structure.md +95 -0
- package/src/templates/skills/browser-agent.md +21 -16
- package/src/templates/skills/web-gui.md +8 -0
- package/src/templates/template-constraints.js +50 -53
- package/src/validators/advanced-validation.js +30 -36
- package/src/validators/constitutional-validator.js +77 -73
- package/src/validators/critic-system.js +49 -59
- package/src/validators/delta-format.js +59 -55
- package/src/validators/traceability-validator.js +7 -11
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Observability Module - Logs, Metrics, and Traces
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Provides unified observability capabilities:
|
|
5
5
|
* - Structured logging
|
|
6
6
|
* - Metrics collection
|
|
7
7
|
* - Distributed tracing
|
|
8
8
|
* - Correlation IDs
|
|
9
|
-
*
|
|
9
|
+
*
|
|
10
10
|
* Part of MUSUBI v5.0.0 - Production Readiness
|
|
11
|
-
*
|
|
11
|
+
*
|
|
12
12
|
* @module monitoring/observability
|
|
13
13
|
* @version 1.0.0
|
|
14
|
-
*
|
|
14
|
+
*
|
|
15
15
|
* @traceability
|
|
16
16
|
* - Requirement: REQ-P5-004 (Observability Integration)
|
|
17
17
|
* - Design: docs/design/tdd-musubi-v5.0.0.md#3.4
|
|
@@ -29,7 +29,7 @@ const LogLevel = {
|
|
|
29
29
|
INFO: 'info',
|
|
30
30
|
WARN: 'warn',
|
|
31
31
|
ERROR: 'error',
|
|
32
|
-
FATAL: 'fatal'
|
|
32
|
+
FATAL: 'fatal',
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
/**
|
|
@@ -41,7 +41,7 @@ const LOG_PRIORITY = {
|
|
|
41
41
|
[LogLevel.INFO]: 2,
|
|
42
42
|
[LogLevel.WARN]: 3,
|
|
43
43
|
[LogLevel.ERROR]: 4,
|
|
44
|
-
[LogLevel.FATAL]: 5
|
|
44
|
+
[LogLevel.FATAL]: 5,
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -50,7 +50,7 @@ const LOG_PRIORITY = {
|
|
|
50
50
|
const TraceStatus = {
|
|
51
51
|
OK: 'ok',
|
|
52
52
|
ERROR: 'error',
|
|
53
|
-
UNSET: 'unset'
|
|
53
|
+
UNSET: 'unset',
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
/**
|
|
@@ -61,7 +61,7 @@ const SpanKind = {
|
|
|
61
61
|
SERVER: 'server',
|
|
62
62
|
CLIENT: 'client',
|
|
63
63
|
PRODUCER: 'producer',
|
|
64
|
-
CONSUMER: 'consumer'
|
|
64
|
+
CONSUMER: 'consumer',
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
/**
|
|
@@ -98,7 +98,7 @@ class Logger extends EventEmitter {
|
|
|
98
98
|
level: this.level,
|
|
99
99
|
context: { ...this.context, ...context },
|
|
100
100
|
outputs: this.outputs,
|
|
101
|
-
parent: this
|
|
101
|
+
parent: this,
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
|
|
@@ -121,7 +121,7 @@ class Logger extends EventEmitter {
|
|
|
121
121
|
logger: this.name,
|
|
122
122
|
message,
|
|
123
123
|
...this.context,
|
|
124
|
-
...meta
|
|
124
|
+
...meta,
|
|
125
125
|
};
|
|
126
126
|
|
|
127
127
|
for (const output of this.outputs) {
|
|
@@ -131,12 +131,24 @@ class Logger extends EventEmitter {
|
|
|
131
131
|
this.emit('log', entry);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
trace(message, meta) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
134
|
+
trace(message, meta) {
|
|
135
|
+
this.log(LogLevel.TRACE, message, meta);
|
|
136
|
+
}
|
|
137
|
+
debug(message, meta) {
|
|
138
|
+
this.log(LogLevel.DEBUG, message, meta);
|
|
139
|
+
}
|
|
140
|
+
info(message, meta) {
|
|
141
|
+
this.log(LogLevel.INFO, message, meta);
|
|
142
|
+
}
|
|
143
|
+
warn(message, meta) {
|
|
144
|
+
this.log(LogLevel.WARN, message, meta);
|
|
145
|
+
}
|
|
146
|
+
error(message, meta) {
|
|
147
|
+
this.log(LogLevel.ERROR, message, meta);
|
|
148
|
+
}
|
|
149
|
+
fatal(message, meta) {
|
|
150
|
+
this.log(LogLevel.FATAL, message, meta);
|
|
151
|
+
}
|
|
140
152
|
|
|
141
153
|
/**
|
|
142
154
|
* Add an output
|
|
@@ -166,10 +178,8 @@ class ConsoleOutput {
|
|
|
166
178
|
|
|
167
179
|
write(entry) {
|
|
168
180
|
if (this.format === 'json') {
|
|
169
|
-
const output = this.pretty
|
|
170
|
-
|
|
171
|
-
: JSON.stringify(entry);
|
|
172
|
-
|
|
181
|
+
const output = this.pretty ? JSON.stringify(entry, null, 2) : JSON.stringify(entry);
|
|
182
|
+
|
|
173
183
|
if (entry.level === LogLevel.ERROR || entry.level === LogLevel.FATAL) {
|
|
174
184
|
console.error(output);
|
|
175
185
|
} else if (entry.level === LogLevel.WARN) {
|
|
@@ -197,7 +207,7 @@ class FileOutput {
|
|
|
197
207
|
|
|
198
208
|
write(entry) {
|
|
199
209
|
this.buffer.push(JSON.stringify(entry) + '\n');
|
|
200
|
-
|
|
210
|
+
|
|
201
211
|
if (this.buffer.length >= this.bufferSize) {
|
|
202
212
|
this.flush();
|
|
203
213
|
}
|
|
@@ -242,7 +252,7 @@ class MetricsCollector extends EventEmitter {
|
|
|
242
252
|
type: 'counter',
|
|
243
253
|
name: fullName,
|
|
244
254
|
help,
|
|
245
|
-
values: new Map()
|
|
255
|
+
values: new Map(),
|
|
246
256
|
});
|
|
247
257
|
}
|
|
248
258
|
return new CounterMetric(this.metrics.get(fullName), this.labels);
|
|
@@ -258,7 +268,7 @@ class MetricsCollector extends EventEmitter {
|
|
|
258
268
|
type: 'gauge',
|
|
259
269
|
name: fullName,
|
|
260
270
|
help,
|
|
261
|
-
values: new Map()
|
|
271
|
+
values: new Map(),
|
|
262
272
|
});
|
|
263
273
|
}
|
|
264
274
|
return new GaugeMetric(this.metrics.get(fullName), this.labels);
|
|
@@ -275,7 +285,7 @@ class MetricsCollector extends EventEmitter {
|
|
|
275
285
|
name: fullName,
|
|
276
286
|
help,
|
|
277
287
|
buckets,
|
|
278
|
-
values: new Map()
|
|
288
|
+
values: new Map(),
|
|
279
289
|
});
|
|
280
290
|
}
|
|
281
291
|
return new HistogramMetric(this.metrics.get(fullName), this.labels);
|
|
@@ -323,13 +333,13 @@ class MetricsCollector extends EventEmitter {
|
|
|
323
333
|
name: metric.name,
|
|
324
334
|
type: metric.type,
|
|
325
335
|
help: metric.help,
|
|
326
|
-
values: []
|
|
336
|
+
values: [],
|
|
327
337
|
};
|
|
328
338
|
|
|
329
339
|
for (const [labelsKey, value] of metric.values) {
|
|
330
340
|
metricData.values.push({
|
|
331
341
|
labels: labelsKey,
|
|
332
|
-
value: metric.type === 'histogram' ? { ...value } : value
|
|
342
|
+
value: metric.type === 'histogram' ? { ...value } : value,
|
|
333
343
|
});
|
|
334
344
|
}
|
|
335
345
|
|
|
@@ -430,12 +440,12 @@ class HistogramMetric {
|
|
|
430
440
|
observe(value, labels = {}) {
|
|
431
441
|
const key = this._labelKey(labels);
|
|
432
442
|
let data = this.metric.values.get(key);
|
|
433
|
-
|
|
443
|
+
|
|
434
444
|
if (!data) {
|
|
435
445
|
data = {
|
|
436
446
|
buckets: this.metric.buckets.map(() => 0),
|
|
437
447
|
sum: 0,
|
|
438
|
-
count: 0
|
|
448
|
+
count: 0,
|
|
439
449
|
};
|
|
440
450
|
this.metric.values.set(key, data);
|
|
441
451
|
}
|
|
@@ -500,7 +510,7 @@ class Span {
|
|
|
500
510
|
this.events.push({
|
|
501
511
|
name,
|
|
502
512
|
timestamp: Date.now(),
|
|
503
|
-
attributes
|
|
513
|
+
attributes,
|
|
504
514
|
});
|
|
505
515
|
return this;
|
|
506
516
|
}
|
|
@@ -536,7 +546,7 @@ class Span {
|
|
|
536
546
|
getContext() {
|
|
537
547
|
return {
|
|
538
548
|
traceId: this.traceId,
|
|
539
|
-
spanId: this.spanId
|
|
549
|
+
spanId: this.spanId,
|
|
540
550
|
};
|
|
541
551
|
}
|
|
542
552
|
|
|
@@ -554,7 +564,7 @@ class Span {
|
|
|
554
564
|
statusMessage: this.statusMessage,
|
|
555
565
|
attributes: this.attributes,
|
|
556
566
|
events: this.events,
|
|
557
|
-
links: this.links
|
|
567
|
+
links: this.links,
|
|
558
568
|
};
|
|
559
569
|
}
|
|
560
570
|
}
|
|
@@ -583,9 +593,9 @@ class Tracer extends EventEmitter {
|
|
|
583
593
|
attributes: {
|
|
584
594
|
'service.name': this.serviceName,
|
|
585
595
|
'service.version': this.version,
|
|
586
|
-
...options.attributes
|
|
596
|
+
...options.attributes,
|
|
587
597
|
},
|
|
588
|
-
links: options.links
|
|
598
|
+
links: options.links,
|
|
589
599
|
});
|
|
590
600
|
|
|
591
601
|
this.spans.push(span);
|
|
@@ -600,7 +610,7 @@ class Tracer extends EventEmitter {
|
|
|
600
610
|
return this.startSpan(name, {
|
|
601
611
|
traceId: parent.traceId,
|
|
602
612
|
parentSpanId: parent.spanId,
|
|
603
|
-
...options
|
|
613
|
+
...options,
|
|
604
614
|
});
|
|
605
615
|
}
|
|
606
616
|
|
|
@@ -610,11 +620,11 @@ class Tracer extends EventEmitter {
|
|
|
610
620
|
endSpan(span) {
|
|
611
621
|
span.end();
|
|
612
622
|
this.emit('spanEnded', span);
|
|
613
|
-
|
|
623
|
+
|
|
614
624
|
for (const exporter of this.exporters) {
|
|
615
625
|
exporter.export(span);
|
|
616
626
|
}
|
|
617
|
-
|
|
627
|
+
|
|
618
628
|
return span;
|
|
619
629
|
}
|
|
620
630
|
|
|
@@ -722,7 +732,7 @@ class CorrelationContext {
|
|
|
722
732
|
*/
|
|
723
733
|
toHeaders() {
|
|
724
734
|
const headers = {};
|
|
725
|
-
|
|
735
|
+
|
|
726
736
|
if (this.has('traceId')) {
|
|
727
737
|
headers['x-trace-id'] = this.get('traceId');
|
|
728
738
|
}
|
|
@@ -732,7 +742,7 @@ class CorrelationContext {
|
|
|
732
742
|
if (this.has('correlationId')) {
|
|
733
743
|
headers['x-correlation-id'] = this.get('correlationId');
|
|
734
744
|
}
|
|
735
|
-
|
|
745
|
+
|
|
736
746
|
return headers;
|
|
737
747
|
}
|
|
738
748
|
|
|
@@ -741,7 +751,7 @@ class CorrelationContext {
|
|
|
741
751
|
*/
|
|
742
752
|
static fromHeaders(headers) {
|
|
743
753
|
const ctx = new CorrelationContext();
|
|
744
|
-
|
|
754
|
+
|
|
745
755
|
if (headers['x-trace-id']) {
|
|
746
756
|
ctx.set('traceId', headers['x-trace-id']);
|
|
747
757
|
}
|
|
@@ -751,7 +761,7 @@ class CorrelationContext {
|
|
|
751
761
|
if (headers['x-correlation-id']) {
|
|
752
762
|
ctx.set('correlationId', headers['x-correlation-id']);
|
|
753
763
|
}
|
|
754
|
-
|
|
764
|
+
|
|
755
765
|
return ctx;
|
|
756
766
|
}
|
|
757
767
|
}
|
|
@@ -764,22 +774,22 @@ class ObservabilityProvider extends EventEmitter {
|
|
|
764
774
|
super();
|
|
765
775
|
this.serviceName = options.serviceName || 'musubi-service';
|
|
766
776
|
this.version = options.version || '1.0.0';
|
|
767
|
-
|
|
777
|
+
|
|
768
778
|
this.logger = new Logger({
|
|
769
779
|
name: this.serviceName,
|
|
770
|
-
level: options.logLevel || LogLevel.INFO
|
|
780
|
+
level: options.logLevel || LogLevel.INFO,
|
|
771
781
|
});
|
|
772
|
-
|
|
782
|
+
|
|
773
783
|
this.metrics = new MetricsCollector({
|
|
774
784
|
name: this.serviceName,
|
|
775
|
-
prefix: options.metricsPrefix || ''
|
|
785
|
+
prefix: options.metricsPrefix || '',
|
|
776
786
|
});
|
|
777
|
-
|
|
787
|
+
|
|
778
788
|
this.tracer = new Tracer({
|
|
779
789
|
serviceName: this.serviceName,
|
|
780
|
-
version: this.version
|
|
790
|
+
version: this.version,
|
|
781
791
|
});
|
|
782
|
-
|
|
792
|
+
|
|
783
793
|
// Standard metrics
|
|
784
794
|
this._setupStandardMetrics();
|
|
785
795
|
}
|
|
@@ -790,9 +800,12 @@ class ObservabilityProvider extends EventEmitter {
|
|
|
790
800
|
_setupStandardMetrics() {
|
|
791
801
|
// Request metrics
|
|
792
802
|
this.requestCounter = this.metrics.counter('http_requests_total', 'Total HTTP requests');
|
|
793
|
-
this.requestDuration = this.metrics.histogram(
|
|
803
|
+
this.requestDuration = this.metrics.histogram(
|
|
804
|
+
'http_request_duration_seconds',
|
|
805
|
+
'HTTP request duration'
|
|
806
|
+
);
|
|
794
807
|
this.requestErrors = this.metrics.counter('http_request_errors_total', 'Total HTTP errors');
|
|
795
|
-
|
|
808
|
+
|
|
796
809
|
// Resource metrics
|
|
797
810
|
this.activeConnections = this.metrics.gauge('active_connections', 'Active connections');
|
|
798
811
|
}
|
|
@@ -823,10 +836,10 @@ class ObservabilityProvider extends EventEmitter {
|
|
|
823
836
|
*/
|
|
824
837
|
trace(name, fn, options = {}) {
|
|
825
838
|
const span = this.tracer.startSpan(name, options);
|
|
826
|
-
|
|
839
|
+
|
|
827
840
|
try {
|
|
828
841
|
const result = fn(span);
|
|
829
|
-
|
|
842
|
+
|
|
830
843
|
if (result && typeof result.then === 'function') {
|
|
831
844
|
return result
|
|
832
845
|
.then(r => {
|
|
@@ -838,13 +851,13 @@ class ObservabilityProvider extends EventEmitter {
|
|
|
838
851
|
span.setStatus(TraceStatus.ERROR, err.message);
|
|
839
852
|
span.addEvent('exception', {
|
|
840
853
|
'exception.type': err.name,
|
|
841
|
-
'exception.message': err.message
|
|
854
|
+
'exception.message': err.message,
|
|
842
855
|
});
|
|
843
856
|
this.tracer.endSpan(span);
|
|
844
857
|
throw err;
|
|
845
858
|
});
|
|
846
859
|
}
|
|
847
|
-
|
|
860
|
+
|
|
848
861
|
span.setStatus(TraceStatus.OK);
|
|
849
862
|
this.tracer.endSpan(span);
|
|
850
863
|
return result;
|
|
@@ -852,7 +865,7 @@ class ObservabilityProvider extends EventEmitter {
|
|
|
852
865
|
span.setStatus(TraceStatus.ERROR, err.message);
|
|
853
866
|
span.addEvent('exception', {
|
|
854
867
|
'exception.type': err.name,
|
|
855
|
-
'exception.message': err.message
|
|
868
|
+
'exception.message': err.message,
|
|
856
869
|
});
|
|
857
870
|
this.tracer.endSpan(span);
|
|
858
871
|
throw err;
|
|
@@ -864,10 +877,10 @@ class ObservabilityProvider extends EventEmitter {
|
|
|
864
877
|
*/
|
|
865
878
|
recordRequest(method, path, statusCode, duration) {
|
|
866
879
|
const labels = { method, path, status_code: statusCode.toString() };
|
|
867
|
-
|
|
880
|
+
|
|
868
881
|
this.requestCounter.inc(labels);
|
|
869
882
|
this.requestDuration.observe(duration / 1000, { method, path }); // Convert to seconds
|
|
870
|
-
|
|
883
|
+
|
|
871
884
|
if (statusCode >= 400) {
|
|
872
885
|
this.requestErrors.inc(labels);
|
|
873
886
|
}
|
|
@@ -880,10 +893,10 @@ class ObservabilityProvider extends EventEmitter {
|
|
|
880
893
|
return {
|
|
881
894
|
service: {
|
|
882
895
|
name: this.serviceName,
|
|
883
|
-
version: this.version
|
|
896
|
+
version: this.version,
|
|
884
897
|
},
|
|
885
898
|
metrics: this.metrics.toJSON(),
|
|
886
|
-
traces: this.tracer.getAllSpans()
|
|
899
|
+
traces: this.tracer.getAllSpans(),
|
|
887
900
|
};
|
|
888
901
|
}
|
|
889
902
|
}
|
|
@@ -931,18 +944,18 @@ module.exports = {
|
|
|
931
944
|
MemoryExporter,
|
|
932
945
|
CorrelationContext,
|
|
933
946
|
ObservabilityProvider,
|
|
934
|
-
|
|
947
|
+
|
|
935
948
|
// Constants
|
|
936
949
|
LogLevel,
|
|
937
950
|
TraceStatus,
|
|
938
951
|
SpanKind,
|
|
939
|
-
|
|
952
|
+
|
|
940
953
|
// Factories
|
|
941
954
|
createLogger,
|
|
942
955
|
createMetricsCollector,
|
|
943
956
|
createTracer,
|
|
944
957
|
createObservability,
|
|
945
|
-
|
|
958
|
+
|
|
946
959
|
// Utilities
|
|
947
|
-
generateId
|
|
960
|
+
generateId,
|
|
948
961
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Quality Metrics Dashboard
|
|
3
3
|
* カバレッジメトリクス、Constitutional準拠メトリクス、プロジェクトヘルス指標
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* Part of MUSUBI v5.0.0 - Production Readiness
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* @module monitoring/quality-dashboard
|
|
8
8
|
* @version 1.0.0
|
|
9
|
-
*
|
|
9
|
+
*
|
|
10
10
|
* @traceability
|
|
11
11
|
* - Requirement: REQ-P5-001 (Quality Dashboard)
|
|
12
12
|
* - Design: docs/design/tdd-musubi-v5.0.0.md#3.1
|
|
@@ -24,17 +24,17 @@ const METRIC_CATEGORY = {
|
|
|
24
24
|
QUALITY: 'quality',
|
|
25
25
|
HEALTH: 'health',
|
|
26
26
|
PERFORMANCE: 'performance',
|
|
27
|
-
CUSTOM: 'custom'
|
|
27
|
+
CUSTOM: 'custom',
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Health status levels
|
|
32
32
|
*/
|
|
33
33
|
const HEALTH_STATUS = {
|
|
34
|
-
HEALTHY: 'healthy',
|
|
35
|
-
WARNING: 'warning',
|
|
36
|
-
CRITICAL: 'critical',
|
|
37
|
-
FAILING: 'failing'
|
|
34
|
+
HEALTHY: 'healthy', // 80-100%
|
|
35
|
+
WARNING: 'warning', // 50-79%
|
|
36
|
+
CRITICAL: 'critical', // 20-49%
|
|
37
|
+
FAILING: 'failing', // <20%
|
|
38
38
|
};
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -49,7 +49,7 @@ const CONSTITUTIONAL_ARTICLES = {
|
|
|
49
49
|
INCREMENTAL_ADOPTION: 'article-6',
|
|
50
50
|
SEPARATION_OF_CONCERNS: 'article-7',
|
|
51
51
|
FEEDBACK_LOOPS: 'article-8',
|
|
52
|
-
GOVERNANCE: 'article-9'
|
|
52
|
+
GOVERNANCE: 'article-9',
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
/**
|
|
@@ -64,17 +64,17 @@ class QualityDashboard extends EventEmitter {
|
|
|
64
64
|
*/
|
|
65
65
|
constructor(options = {}) {
|
|
66
66
|
super();
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
this.thresholds = {
|
|
69
69
|
coverage: { healthy: 80, warning: 50, critical: 20 },
|
|
70
70
|
constitutional: { healthy: 90, warning: 70, critical: 50 },
|
|
71
71
|
quality: { healthy: 80, warning: 60, critical: 40 },
|
|
72
|
-
...options.thresholds
|
|
72
|
+
...options.thresholds,
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
this.autoCollect = options.autoCollect ?? false;
|
|
76
76
|
this.collectInterval = options.collectInterval ?? 60000;
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
this.metrics = new Map();
|
|
79
79
|
this.history = [];
|
|
80
80
|
this.collectors = new Map();
|
|
@@ -93,25 +93,27 @@ class QualityDashboard extends EventEmitter {
|
|
|
93
93
|
*/
|
|
94
94
|
initializeDefaultCollectors() {
|
|
95
95
|
// Coverage metrics collector
|
|
96
|
-
this.registerCollector('coverage', async
|
|
96
|
+
this.registerCollector('coverage', async context => ({
|
|
97
97
|
lines: context?.coverage?.lines ?? 0,
|
|
98
98
|
branches: context?.coverage?.branches ?? 0,
|
|
99
99
|
functions: context?.coverage?.functions ?? 0,
|
|
100
100
|
statements: context?.coverage?.statements ?? 0,
|
|
101
|
-
overall:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
overall:
|
|
102
|
+
context?.coverage?.overall ??
|
|
103
|
+
((context?.coverage?.lines ?? 0) +
|
|
104
|
+
(context?.coverage?.branches ?? 0) +
|
|
105
|
+
(context?.coverage?.functions ?? 0) +
|
|
106
|
+
(context?.coverage?.statements ?? 0)) /
|
|
107
|
+
4,
|
|
106
108
|
}));
|
|
107
109
|
|
|
108
110
|
// Constitutional compliance collector
|
|
109
|
-
this.registerCollector('constitutional', async
|
|
111
|
+
this.registerCollector('constitutional', async context => {
|
|
110
112
|
const articles = context?.constitutional ?? {};
|
|
111
113
|
const scores = Object.values(CONSTITUTIONAL_ARTICLES).map(id => ({
|
|
112
114
|
id,
|
|
113
115
|
score: articles[id]?.score ?? 0,
|
|
114
|
-
compliant: articles[id]?.compliant ?? false
|
|
116
|
+
compliant: articles[id]?.compliant ?? false,
|
|
115
117
|
}));
|
|
116
118
|
|
|
117
119
|
const totalScore = scores.reduce((sum, s) => sum + s.score, 0) / scores.length;
|
|
@@ -122,25 +124,27 @@ class QualityDashboard extends EventEmitter {
|
|
|
122
124
|
totalScore,
|
|
123
125
|
compliantCount,
|
|
124
126
|
totalArticles: scores.length,
|
|
125
|
-
complianceRate: (compliantCount / scores.length) * 100
|
|
127
|
+
complianceRate: (compliantCount / scores.length) * 100,
|
|
126
128
|
};
|
|
127
129
|
});
|
|
128
130
|
|
|
129
131
|
// Quality metrics collector
|
|
130
|
-
this.registerCollector('quality', async
|
|
132
|
+
this.registerCollector('quality', async context => ({
|
|
131
133
|
codeComplexity: context?.quality?.complexity ?? 0,
|
|
132
134
|
maintainability: context?.quality?.maintainability ?? 0,
|
|
133
135
|
documentation: context?.quality?.documentation ?? 0,
|
|
134
136
|
testQuality: context?.quality?.testQuality ?? 0,
|
|
135
|
-
overall:
|
|
137
|
+
overall:
|
|
138
|
+
context?.quality?.overall ??
|
|
136
139
|
((context?.quality?.complexity ?? 0) +
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
(context?.quality?.maintainability ?? 0) +
|
|
141
|
+
(context?.quality?.documentation ?? 0) +
|
|
142
|
+
(context?.quality?.testQuality ?? 0)) /
|
|
143
|
+
4,
|
|
140
144
|
}));
|
|
141
145
|
|
|
142
146
|
// Health metrics collector
|
|
143
|
-
this.registerCollector('health', async
|
|
147
|
+
this.registerCollector('health', async _context => {
|
|
144
148
|
const coverage = await this.getMetric('coverage');
|
|
145
149
|
const constitutional = await this.getMetric('constitutional');
|
|
146
150
|
const quality = await this.getMetric('quality');
|
|
@@ -157,7 +161,7 @@ class QualityDashboard extends EventEmitter {
|
|
|
157
161
|
qualityScore,
|
|
158
162
|
overall,
|
|
159
163
|
status: this.calculateStatus(overall, 'quality'),
|
|
160
|
-
timestamp: new Date().toISOString()
|
|
164
|
+
timestamp: new Date().toISOString(),
|
|
161
165
|
};
|
|
162
166
|
});
|
|
163
167
|
}
|
|
@@ -197,20 +201,20 @@ class QualityDashboard extends EventEmitter {
|
|
|
197
201
|
const data = await collector(context);
|
|
198
202
|
results[name] = {
|
|
199
203
|
...data,
|
|
200
|
-
collectedAt: timestamp
|
|
204
|
+
collectedAt: timestamp,
|
|
201
205
|
};
|
|
202
206
|
this.metrics.set(name, results[name]);
|
|
203
207
|
} catch (error) {
|
|
204
208
|
results[name] = {
|
|
205
209
|
error: error.message,
|
|
206
|
-
collectedAt: timestamp
|
|
210
|
+
collectedAt: timestamp,
|
|
207
211
|
};
|
|
208
212
|
}
|
|
209
213
|
}
|
|
210
214
|
|
|
211
215
|
const snapshot = {
|
|
212
216
|
timestamp,
|
|
213
|
-
metrics: { ...results }
|
|
217
|
+
metrics: { ...results },
|
|
214
218
|
};
|
|
215
219
|
|
|
216
220
|
this.history.push(snapshot);
|
|
@@ -271,20 +275,20 @@ class QualityDashboard extends EventEmitter {
|
|
|
271
275
|
breakdown: {
|
|
272
276
|
coverage: {
|
|
273
277
|
score: coverage?.overall ?? 0,
|
|
274
|
-
status: this.calculateStatus(coverage?.overall ?? 0, 'coverage')
|
|
278
|
+
status: this.calculateStatus(coverage?.overall ?? 0, 'coverage'),
|
|
275
279
|
},
|
|
276
280
|
constitutional: {
|
|
277
281
|
score: constitutional?.totalScore ?? 0,
|
|
278
282
|
status: this.calculateStatus(constitutional?.totalScore ?? 0, 'constitutional'),
|
|
279
283
|
compliantArticles: constitutional?.compliantCount ?? 0,
|
|
280
|
-
totalArticles: constitutional?.totalArticles ?? 9
|
|
284
|
+
totalArticles: constitutional?.totalArticles ?? 9,
|
|
281
285
|
},
|
|
282
286
|
quality: {
|
|
283
287
|
score: quality?.overall ?? 0,
|
|
284
|
-
status: this.calculateStatus(quality?.overall ?? 0, 'quality')
|
|
285
|
-
}
|
|
288
|
+
status: this.calculateStatus(quality?.overall ?? 0, 'quality'),
|
|
289
|
+
},
|
|
286
290
|
},
|
|
287
|
-
lastUpdated: health?.timestamp ?? null
|
|
291
|
+
lastUpdated: health?.timestamp ?? null,
|
|
288
292
|
};
|
|
289
293
|
}
|
|
290
294
|
|
|
@@ -300,7 +304,7 @@ class QualityDashboard extends EventEmitter {
|
|
|
300
304
|
.slice(-limit)
|
|
301
305
|
.map(h => ({
|
|
302
306
|
timestamp: h.timestamp,
|
|
303
|
-
value: h.metrics[metricName]
|
|
307
|
+
value: h.metrics[metricName],
|
|
304
308
|
}));
|
|
305
309
|
|
|
306
310
|
if (data.length < 2) {
|
|
@@ -414,7 +418,7 @@ class QualityDashboard extends EventEmitter {
|
|
|
414
418
|
[HEALTH_STATUS.HEALTHY]: '🟢',
|
|
415
419
|
[HEALTH_STATUS.WARNING]: '🟡',
|
|
416
420
|
[HEALTH_STATUS.CRITICAL]: '🟠',
|
|
417
|
-
[HEALTH_STATUS.FAILING]: '🔴'
|
|
421
|
+
[HEALTH_STATUS.FAILING]: '🔴',
|
|
418
422
|
};
|
|
419
423
|
return emojis[status] || '⚪';
|
|
420
424
|
}
|
|
@@ -456,7 +460,7 @@ class QualityDashboard extends EventEmitter {
|
|
|
456
460
|
setThresholds(category, thresholds) {
|
|
457
461
|
this.thresholds[category] = {
|
|
458
462
|
...this.thresholds[category],
|
|
459
|
-
...thresholds
|
|
463
|
+
...thresholds,
|
|
460
464
|
};
|
|
461
465
|
}
|
|
462
466
|
|
|
@@ -470,7 +474,7 @@ class QualityDashboard extends EventEmitter {
|
|
|
470
474
|
collectorsCount: this.collectors.size,
|
|
471
475
|
historyCount: this.history.length,
|
|
472
476
|
autoCollecting: this.intervalId !== null,
|
|
473
|
-
thresholds: { ...this.thresholds }
|
|
477
|
+
thresholds: { ...this.thresholds },
|
|
474
478
|
};
|
|
475
479
|
}
|
|
476
480
|
}
|
|
@@ -487,5 +491,5 @@ module.exports = {
|
|
|
487
491
|
createQualityDashboard,
|
|
488
492
|
METRIC_CATEGORY,
|
|
489
493
|
HEALTH_STATUS,
|
|
490
|
-
CONSTITUTIONAL_ARTICLES
|
|
494
|
+
CONSTITUTIONAL_ARTICLES,
|
|
491
495
|
};
|