musubi-sdd 5.0.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 +164 -145
- package/src/analyzers/codegraph-auto-update.js +858 -0
- package/src/analyzers/complexity-analyzer.js +536 -0
- package/src/analyzers/context-optimizer.js +247 -125
- package/src/analyzers/impact-analyzer.js +1 -1
- package/src/analyzers/large-project-analyzer.js +766 -0
- package/src/analyzers/repository-map.js +83 -80
- 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 +53 -44
- package/src/monitoring/incident-manager.js +123 -103
- package/src/monitoring/index.js +144 -134
- package/src/monitoring/observability.js +82 -59
- package/src/monitoring/quality-dashboard.js +51 -39
- package/src/monitoring/release-manager.js +70 -50
- 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,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Skill Registry - Centralized skill registration and discovery
|
|
3
3
|
* Sprint 3.1: Skill System Architecture
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* Inspired by OpenAI Agents SDK skill management patterns
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -32,23 +32,23 @@ class SkillMetadata {
|
|
|
32
32
|
|
|
33
33
|
validate() {
|
|
34
34
|
const errors = [];
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
if (!this.id) {
|
|
37
37
|
errors.push('Skill ID is required');
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
if (!this.name) {
|
|
41
41
|
errors.push('Skill name is required');
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
if (!/^[a-z0-9-]+$/.test(this.id)) {
|
|
45
45
|
errors.push('Skill ID must be lowercase alphanumeric with hyphens');
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
if (!['P0', 'P1', 'P2', 'P3'].includes(this.priority)) {
|
|
49
49
|
errors.push('Priority must be P0, P1, P2, or P3');
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
// Validate inputs
|
|
53
53
|
for (const input of this.inputs) {
|
|
54
54
|
if (!input.name) {
|
|
@@ -58,17 +58,17 @@ class SkillMetadata {
|
|
|
58
58
|
errors.push(`Input ${input.name || 'unknown'} must have a type`);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
// Validate outputs
|
|
63
63
|
for (const output of this.outputs) {
|
|
64
64
|
if (!output.name) {
|
|
65
65
|
errors.push('Output name is required');
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
return {
|
|
70
70
|
valid: errors.length === 0,
|
|
71
|
-
errors
|
|
71
|
+
errors,
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -89,7 +89,7 @@ class SkillMetadata {
|
|
|
89
89
|
priority: this.priority,
|
|
90
90
|
permissions: this.permissions,
|
|
91
91
|
createdAt: this.createdAt,
|
|
92
|
-
updatedAt: this.updatedAt
|
|
92
|
+
updatedAt: this.updatedAt,
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -107,7 +107,7 @@ const SkillCategory = {
|
|
|
107
107
|
VALIDATION: 'validation',
|
|
108
108
|
INTEGRATION: 'integration',
|
|
109
109
|
MONITORING: 'monitoring',
|
|
110
|
-
GENERAL: 'general'
|
|
110
|
+
GENERAL: 'general',
|
|
111
111
|
};
|
|
112
112
|
|
|
113
113
|
/**
|
|
@@ -117,7 +117,7 @@ const SkillPriority = {
|
|
|
117
117
|
P0: 'P0', // Critical - blocks all other work
|
|
118
118
|
P1: 'P1', // High - should run soon
|
|
119
119
|
P2: 'P2', // Medium - normal priority
|
|
120
|
-
P3: 'P3'
|
|
120
|
+
P3: 'P3', // Low - background/optional
|
|
121
121
|
};
|
|
122
122
|
|
|
123
123
|
/**
|
|
@@ -127,7 +127,7 @@ const SkillHealth = {
|
|
|
127
127
|
HEALTHY: 'healthy',
|
|
128
128
|
DEGRADED: 'degraded',
|
|
129
129
|
UNHEALTHY: 'unhealthy',
|
|
130
|
-
UNKNOWN: 'unknown'
|
|
130
|
+
UNKNOWN: 'unknown',
|
|
131
131
|
};
|
|
132
132
|
|
|
133
133
|
/**
|
|
@@ -146,17 +146,17 @@ class SkillRegistry extends EventEmitter {
|
|
|
146
146
|
beforeRegister: [],
|
|
147
147
|
afterRegister: [],
|
|
148
148
|
beforeUnregister: [],
|
|
149
|
-
afterUnregister: []
|
|
149
|
+
afterUnregister: [],
|
|
150
150
|
};
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
// Options
|
|
153
153
|
this.options = {
|
|
154
154
|
enableHealthMonitoring: options.enableHealthMonitoring !== false,
|
|
155
155
|
healthCheckInterval: options.healthCheckInterval || 60000,
|
|
156
156
|
maxSkills: options.maxSkills || 1000,
|
|
157
|
-
enableStats: options.enableStats !== false
|
|
157
|
+
enableStats: options.enableStats !== false,
|
|
158
158
|
};
|
|
159
|
-
|
|
159
|
+
|
|
160
160
|
// Start health monitoring if enabled
|
|
161
161
|
if (this.options.enableHealthMonitoring) {
|
|
162
162
|
this._startHealthMonitoring();
|
|
@@ -167,21 +167,19 @@ class SkillRegistry extends EventEmitter {
|
|
|
167
167
|
* Register a new skill
|
|
168
168
|
*/
|
|
169
169
|
registerSkill(skillDef, handler = null) {
|
|
170
|
-
const metadata = skillDef instanceof SkillMetadata
|
|
171
|
-
|
|
172
|
-
: new SkillMetadata(skillDef);
|
|
173
|
-
|
|
170
|
+
const metadata = skillDef instanceof SkillMetadata ? skillDef : new SkillMetadata(skillDef);
|
|
171
|
+
|
|
174
172
|
// Validate metadata
|
|
175
173
|
const validation = metadata.validate();
|
|
176
174
|
if (!validation.valid) {
|
|
177
175
|
throw new Error(`Invalid skill metadata: ${validation.errors.join(', ')}`);
|
|
178
176
|
}
|
|
179
|
-
|
|
177
|
+
|
|
180
178
|
// Check max skills limit
|
|
181
179
|
if (this.skills.size >= this.options.maxSkills) {
|
|
182
180
|
throw new Error(`Maximum skill limit (${this.options.maxSkills}) reached`);
|
|
183
181
|
}
|
|
184
|
-
|
|
182
|
+
|
|
185
183
|
// Run custom validators
|
|
186
184
|
for (const validator of this.validators) {
|
|
187
185
|
const result = validator(metadata);
|
|
@@ -189,38 +187,38 @@ class SkillRegistry extends EventEmitter {
|
|
|
189
187
|
throw new Error(`Skill validation failed: ${result.error}`);
|
|
190
188
|
}
|
|
191
189
|
}
|
|
192
|
-
|
|
190
|
+
|
|
193
191
|
// Run beforeRegister hooks
|
|
194
192
|
for (const hook of this.hooks.beforeRegister) {
|
|
195
193
|
hook(metadata);
|
|
196
194
|
}
|
|
197
|
-
|
|
195
|
+
|
|
198
196
|
// Check for duplicate
|
|
199
197
|
if (this.skills.has(metadata.id)) {
|
|
200
198
|
throw new Error(`Skill with ID '${metadata.id}' already exists`);
|
|
201
199
|
}
|
|
202
|
-
|
|
200
|
+
|
|
203
201
|
// Validate dependencies exist
|
|
204
202
|
for (const dep of metadata.dependencies) {
|
|
205
203
|
if (!this.skills.has(dep)) {
|
|
206
204
|
throw new Error(`Dependency '${dep}' not found for skill '${metadata.id}'`);
|
|
207
205
|
}
|
|
208
206
|
}
|
|
209
|
-
|
|
207
|
+
|
|
210
208
|
// Store skill
|
|
211
209
|
const skillEntry = {
|
|
212
210
|
metadata,
|
|
213
211
|
handler,
|
|
214
|
-
registeredAt: new Date().toISOString()
|
|
212
|
+
registeredAt: new Date().toISOString(),
|
|
215
213
|
};
|
|
216
214
|
this.skills.set(metadata.id, skillEntry);
|
|
217
|
-
|
|
215
|
+
|
|
218
216
|
// Update indexes
|
|
219
217
|
this._addToIndex(this.categoryIndex, metadata.category, metadata.id);
|
|
220
218
|
for (const tag of metadata.tags) {
|
|
221
219
|
this._addToIndex(this.tagIndex, tag, metadata.id);
|
|
222
220
|
}
|
|
223
|
-
|
|
221
|
+
|
|
224
222
|
// Initialize health and stats
|
|
225
223
|
this.healthStatus.set(metadata.id, SkillHealth.HEALTHY);
|
|
226
224
|
if (this.options.enableStats) {
|
|
@@ -229,17 +227,17 @@ class SkillRegistry extends EventEmitter {
|
|
|
229
227
|
successCount: 0,
|
|
230
228
|
failureCount: 0,
|
|
231
229
|
averageExecutionTime: 0,
|
|
232
|
-
lastExecutedAt: null
|
|
230
|
+
lastExecutedAt: null,
|
|
233
231
|
});
|
|
234
232
|
}
|
|
235
|
-
|
|
233
|
+
|
|
236
234
|
// Run afterRegister hooks
|
|
237
235
|
for (const hook of this.hooks.afterRegister) {
|
|
238
236
|
hook(metadata);
|
|
239
237
|
}
|
|
240
|
-
|
|
238
|
+
|
|
241
239
|
this.emit('skill-registered', { skillId: metadata.id, metadata });
|
|
242
|
-
|
|
240
|
+
|
|
243
241
|
return metadata;
|
|
244
242
|
}
|
|
245
243
|
|
|
@@ -251,39 +249,37 @@ class SkillRegistry extends EventEmitter {
|
|
|
251
249
|
if (!skillEntry) {
|
|
252
250
|
return false;
|
|
253
251
|
}
|
|
254
|
-
|
|
252
|
+
|
|
255
253
|
// Check if other skills depend on this one
|
|
256
254
|
const dependents = this._findDependents(skillId);
|
|
257
255
|
if (dependents.length > 0) {
|
|
258
|
-
throw new Error(
|
|
259
|
-
`Cannot unregister skill '${skillId}': required by ${dependents.join(', ')}`
|
|
260
|
-
);
|
|
256
|
+
throw new Error(`Cannot unregister skill '${skillId}': required by ${dependents.join(', ')}`);
|
|
261
257
|
}
|
|
262
|
-
|
|
258
|
+
|
|
263
259
|
// Run beforeUnregister hooks
|
|
264
260
|
for (const hook of this.hooks.beforeUnregister) {
|
|
265
261
|
hook(skillEntry.metadata);
|
|
266
262
|
}
|
|
267
|
-
|
|
263
|
+
|
|
268
264
|
// Remove from indexes
|
|
269
265
|
const metadata = skillEntry.metadata;
|
|
270
266
|
this._removeFromIndex(this.categoryIndex, metadata.category, skillId);
|
|
271
267
|
for (const tag of metadata.tags) {
|
|
272
268
|
this._removeFromIndex(this.tagIndex, tag, skillId);
|
|
273
269
|
}
|
|
274
|
-
|
|
270
|
+
|
|
275
271
|
// Remove skill
|
|
276
272
|
this.skills.delete(skillId);
|
|
277
273
|
this.healthStatus.delete(skillId);
|
|
278
274
|
this.executionStats.delete(skillId);
|
|
279
|
-
|
|
275
|
+
|
|
280
276
|
// Run afterUnregister hooks
|
|
281
277
|
for (const hook of this.hooks.afterUnregister) {
|
|
282
278
|
hook(metadata);
|
|
283
279
|
}
|
|
284
|
-
|
|
280
|
+
|
|
285
281
|
this.emit('skill-unregistered', { skillId, metadata });
|
|
286
|
-
|
|
282
|
+
|
|
287
283
|
return true;
|
|
288
284
|
}
|
|
289
285
|
|
|
@@ -321,7 +317,9 @@ class SkillRegistry extends EventEmitter {
|
|
|
321
317
|
*/
|
|
322
318
|
findByCategory(category) {
|
|
323
319
|
const skillIds = this.categoryIndex.get(category) || new Set();
|
|
324
|
-
return Array.from(skillIds)
|
|
320
|
+
return Array.from(skillIds)
|
|
321
|
+
.map(id => this.getSkill(id))
|
|
322
|
+
.filter(Boolean);
|
|
325
323
|
}
|
|
326
324
|
|
|
327
325
|
/**
|
|
@@ -330,9 +328,7 @@ class SkillRegistry extends EventEmitter {
|
|
|
330
328
|
findByTags(tags, matchAll = false) {
|
|
331
329
|
if (matchAll) {
|
|
332
330
|
// AND matching - skill must have all tags
|
|
333
|
-
return this.getAllSkills().filter(skill =>
|
|
334
|
-
tags.every(tag => skill.tags.includes(tag))
|
|
335
|
-
);
|
|
331
|
+
return this.getAllSkills().filter(skill => tags.every(tag => skill.tags.includes(tag)));
|
|
336
332
|
} else {
|
|
337
333
|
// OR matching - skill must have at least one tag
|
|
338
334
|
const matchedIds = new Set();
|
|
@@ -342,7 +338,9 @@ class SkillRegistry extends EventEmitter {
|
|
|
342
338
|
matchedIds.add(id);
|
|
343
339
|
}
|
|
344
340
|
}
|
|
345
|
-
return Array.from(matchedIds)
|
|
341
|
+
return Array.from(matchedIds)
|
|
342
|
+
.map(id => this.getSkill(id))
|
|
343
|
+
.filter(Boolean);
|
|
346
344
|
}
|
|
347
345
|
}
|
|
348
346
|
|
|
@@ -351,11 +349,12 @@ class SkillRegistry extends EventEmitter {
|
|
|
351
349
|
*/
|
|
352
350
|
search(query) {
|
|
353
351
|
const lowerQuery = query.toLowerCase();
|
|
354
|
-
return this.getAllSkills().filter(
|
|
355
|
-
skill
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
352
|
+
return this.getAllSkills().filter(
|
|
353
|
+
skill =>
|
|
354
|
+
skill.id.toLowerCase().includes(lowerQuery) ||
|
|
355
|
+
skill.name.toLowerCase().includes(lowerQuery) ||
|
|
356
|
+
skill.description.toLowerCase().includes(lowerQuery) ||
|
|
357
|
+
skill.tags.some(tag => tag.toLowerCase().includes(lowerQuery))
|
|
359
358
|
);
|
|
360
359
|
}
|
|
361
360
|
|
|
@@ -374,13 +373,13 @@ class SkillRegistry extends EventEmitter {
|
|
|
374
373
|
if (!skill) {
|
|
375
374
|
throw new Error(`Skill '${skillId}' not found`);
|
|
376
375
|
}
|
|
377
|
-
|
|
376
|
+
|
|
378
377
|
// Circular dependency check
|
|
379
378
|
if (visited.has(skillId)) {
|
|
380
379
|
throw new Error(`Circular dependency detected: ${skillId}`);
|
|
381
380
|
}
|
|
382
381
|
visited.add(skillId);
|
|
383
|
-
|
|
382
|
+
|
|
384
383
|
const resolved = [];
|
|
385
384
|
for (const depId of skill.dependencies) {
|
|
386
385
|
const depResolved = this.resolveDependencies(depId, new Set(visited));
|
|
@@ -391,7 +390,7 @@ class SkillRegistry extends EventEmitter {
|
|
|
391
390
|
}
|
|
392
391
|
}
|
|
393
392
|
resolved.push(skillId);
|
|
394
|
-
|
|
393
|
+
|
|
395
394
|
return resolved;
|
|
396
395
|
}
|
|
397
396
|
|
|
@@ -402,19 +401,19 @@ class SkillRegistry extends EventEmitter {
|
|
|
402
401
|
if (!this.skills.has(skillId)) {
|
|
403
402
|
return false;
|
|
404
403
|
}
|
|
405
|
-
|
|
404
|
+
|
|
406
405
|
const previousStatus = this.healthStatus.get(skillId);
|
|
407
406
|
this.healthStatus.set(skillId, status);
|
|
408
|
-
|
|
407
|
+
|
|
409
408
|
if (previousStatus !== status) {
|
|
410
|
-
this.emit('health-changed', {
|
|
411
|
-
skillId,
|
|
412
|
-
previousStatus,
|
|
409
|
+
this.emit('health-changed', {
|
|
410
|
+
skillId,
|
|
411
|
+
previousStatus,
|
|
413
412
|
newStatus: status,
|
|
414
|
-
reason
|
|
413
|
+
reason,
|
|
415
414
|
});
|
|
416
415
|
}
|
|
417
|
-
|
|
416
|
+
|
|
418
417
|
return true;
|
|
419
418
|
}
|
|
420
419
|
|
|
@@ -429,9 +428,7 @@ class SkillRegistry extends EventEmitter {
|
|
|
429
428
|
* Get all healthy skills
|
|
430
429
|
*/
|
|
431
430
|
getHealthySkills() {
|
|
432
|
-
return this.getAllSkills().filter(
|
|
433
|
-
skill => this.getHealth(skill.id) === SkillHealth.HEALTHY
|
|
434
|
-
);
|
|
431
|
+
return this.getAllSkills().filter(skill => this.getHealth(skill.id) === SkillHealth.HEALTHY);
|
|
435
432
|
}
|
|
436
433
|
|
|
437
434
|
/**
|
|
@@ -439,25 +436,24 @@ class SkillRegistry extends EventEmitter {
|
|
|
439
436
|
*/
|
|
440
437
|
recordExecution(skillId, success, executionTime) {
|
|
441
438
|
if (!this.options.enableStats) return;
|
|
442
|
-
|
|
439
|
+
|
|
443
440
|
const stats = this.executionStats.get(skillId);
|
|
444
441
|
if (!stats) return;
|
|
445
|
-
|
|
442
|
+
|
|
446
443
|
stats.totalExecutions++;
|
|
447
444
|
if (success) {
|
|
448
445
|
stats.successCount++;
|
|
449
446
|
} else {
|
|
450
447
|
stats.failureCount++;
|
|
451
448
|
}
|
|
452
|
-
|
|
449
|
+
|
|
453
450
|
// Update average execution time
|
|
454
|
-
stats.averageExecutionTime =
|
|
455
|
-
(stats.averageExecutionTime * (stats.totalExecutions - 1) + executionTime) /
|
|
456
|
-
stats.totalExecutions
|
|
457
|
-
|
|
458
|
-
|
|
451
|
+
stats.averageExecutionTime =
|
|
452
|
+
(stats.averageExecutionTime * (stats.totalExecutions - 1) + executionTime) /
|
|
453
|
+
stats.totalExecutions;
|
|
454
|
+
|
|
459
455
|
stats.lastExecutedAt = new Date().toISOString();
|
|
460
|
-
|
|
456
|
+
|
|
461
457
|
this.emit('execution-recorded', { skillId, success, executionTime, stats });
|
|
462
458
|
}
|
|
463
459
|
|
|
@@ -499,22 +495,22 @@ class SkillRegistry extends EventEmitter {
|
|
|
499
495
|
for (const [category, ids] of this.categoryIndex) {
|
|
500
496
|
categories[category] = ids.size;
|
|
501
497
|
}
|
|
502
|
-
|
|
498
|
+
|
|
503
499
|
const healthCounts = {
|
|
504
500
|
[SkillHealth.HEALTHY]: 0,
|
|
505
501
|
[SkillHealth.DEGRADED]: 0,
|
|
506
502
|
[SkillHealth.UNHEALTHY]: 0,
|
|
507
|
-
[SkillHealth.UNKNOWN]: 0
|
|
503
|
+
[SkillHealth.UNKNOWN]: 0,
|
|
508
504
|
};
|
|
509
505
|
for (const status of this.healthStatus.values()) {
|
|
510
506
|
healthCounts[status]++;
|
|
511
507
|
}
|
|
512
|
-
|
|
508
|
+
|
|
513
509
|
return {
|
|
514
510
|
totalSkills: this.skills.size,
|
|
515
511
|
categories,
|
|
516
512
|
healthStatus: healthCounts,
|
|
517
|
-
tags: Array.from(this.tagIndex.keys())
|
|
513
|
+
tags: Array.from(this.tagIndex.keys()),
|
|
518
514
|
};
|
|
519
515
|
}
|
|
520
516
|
|
|
@@ -527,7 +523,7 @@ class SkillRegistry extends EventEmitter {
|
|
|
527
523
|
version: '1.0.0',
|
|
528
524
|
exportedAt: new Date().toISOString(),
|
|
529
525
|
skills,
|
|
530
|
-
summary: this.getSummary()
|
|
526
|
+
summary: this.getSummary(),
|
|
531
527
|
};
|
|
532
528
|
}
|
|
533
529
|
|
|
@@ -538,10 +534,10 @@ class SkillRegistry extends EventEmitter {
|
|
|
538
534
|
if (!data.skills || !Array.isArray(data.skills)) {
|
|
539
535
|
throw new Error('Invalid import data: skills array required');
|
|
540
536
|
}
|
|
541
|
-
|
|
537
|
+
|
|
542
538
|
const imported = [];
|
|
543
539
|
const errors = [];
|
|
544
|
-
|
|
540
|
+
|
|
545
541
|
for (const skillDef of data.skills) {
|
|
546
542
|
try {
|
|
547
543
|
const metadata = this.registerSkill(skillDef);
|
|
@@ -550,7 +546,7 @@ class SkillRegistry extends EventEmitter {
|
|
|
550
546
|
errors.push({ skillId: skillDef.id, error: error.message });
|
|
551
547
|
}
|
|
552
548
|
}
|
|
553
|
-
|
|
549
|
+
|
|
554
550
|
return { imported, errors };
|
|
555
551
|
}
|
|
556
552
|
|
|
@@ -602,21 +598,21 @@ class SkillRegistry extends EventEmitter {
|
|
|
602
598
|
}
|
|
603
599
|
|
|
604
600
|
_performHealthCheck() {
|
|
605
|
-
for (const [skillId,
|
|
601
|
+
for (const [skillId, _entry] of this.skills) {
|
|
606
602
|
const stats = this.executionStats.get(skillId);
|
|
607
603
|
if (!stats || stats.totalExecutions === 0) {
|
|
608
604
|
continue;
|
|
609
605
|
}
|
|
610
|
-
|
|
606
|
+
|
|
611
607
|
const failureRate = stats.failureCount / stats.totalExecutions;
|
|
612
|
-
|
|
608
|
+
|
|
613
609
|
let newStatus = SkillHealth.HEALTHY;
|
|
614
610
|
if (failureRate > 0.5) {
|
|
615
611
|
newStatus = SkillHealth.UNHEALTHY;
|
|
616
612
|
} else if (failureRate > 0.2) {
|
|
617
613
|
newStatus = SkillHealth.DEGRADED;
|
|
618
614
|
}
|
|
619
|
-
|
|
615
|
+
|
|
620
616
|
this.updateHealth(skillId, newStatus, `Failure rate: ${(failureRate * 100).toFixed(1)}%`);
|
|
621
617
|
}
|
|
622
618
|
}
|
|
@@ -646,5 +642,5 @@ module.exports = {
|
|
|
646
642
|
SkillMetadata,
|
|
647
643
|
SkillCategory,
|
|
648
644
|
SkillPriority,
|
|
649
|
-
SkillHealth
|
|
645
|
+
SkillHealth,
|
|
650
646
|
};
|