@devran-ai/kit 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/CheatSheet.md +350 -0
- package/.agent/README.md +76 -0
- package/.agent/agents/README.md +155 -0
- package/.agent/agents/architect.md +185 -0
- package/.agent/agents/backend-specialist.md +276 -0
- package/.agent/agents/build-error-resolver.md +207 -0
- package/.agent/agents/code-reviewer.md +162 -0
- package/.agent/agents/database-architect.md +138 -0
- package/.agent/agents/devops-engineer.md +144 -0
- package/.agent/agents/doc-updater.md +229 -0
- package/.agent/agents/e2e-runner.md +145 -0
- package/.agent/agents/explorer-agent.md +143 -0
- package/.agent/agents/frontend-specialist.md +144 -0
- package/.agent/agents/go-reviewer.md +128 -0
- package/.agent/agents/knowledge-agent.md +197 -0
- package/.agent/agents/mobile-developer.md +150 -0
- package/.agent/agents/performance-optimizer.md +175 -0
- package/.agent/agents/planner.md +133 -0
- package/.agent/agents/pr-reviewer.md +148 -0
- package/.agent/agents/python-reviewer.md +123 -0
- package/.agent/agents/refactor-cleaner.md +201 -0
- package/.agent/agents/reliability-engineer.md +156 -0
- package/.agent/agents/security-reviewer.md +141 -0
- package/.agent/agents/sprint-orchestrator.md +124 -0
- package/.agent/agents/tdd-guide.md +179 -0
- package/.agent/agents/typescript-reviewer.md +110 -0
- package/.agent/checklists/README.md +102 -0
- package/.agent/checklists/pre-commit.md +93 -0
- package/.agent/checklists/session-end.md +99 -0
- package/.agent/checklists/session-start.md +102 -0
- package/.agent/checklists/task-complete.md +81 -0
- package/.agent/commands/README.md +130 -0
- package/.agent/commands/adr.md +29 -0
- package/.agent/commands/ask.md +28 -0
- package/.agent/commands/build.md +30 -0
- package/.agent/commands/changelog.md +40 -0
- package/.agent/commands/checkpoint.md +28 -0
- package/.agent/commands/code-review.md +65 -0
- package/.agent/commands/compact.md +28 -0
- package/.agent/commands/cook.md +30 -0
- package/.agent/commands/db.md +30 -0
- package/.agent/commands/debug.md +31 -0
- package/.agent/commands/deploy.md +37 -0
- package/.agent/commands/design.md +29 -0
- package/.agent/commands/doc.md +30 -0
- package/.agent/commands/eval.md +30 -0
- package/.agent/commands/fix.md +32 -0
- package/.agent/commands/git.md +32 -0
- package/.agent/commands/help.md +273 -0
- package/.agent/commands/implement.md +30 -0
- package/.agent/commands/integrate.md +32 -0
- package/.agent/commands/learn.md +29 -0
- package/.agent/commands/perf.md +31 -0
- package/.agent/commands/plan.md +56 -0
- package/.agent/commands/pr-describe.md +65 -0
- package/.agent/commands/pr-fix.md +45 -0
- package/.agent/commands/pr-merge.md +45 -0
- package/.agent/commands/pr-review.md +50 -0
- package/.agent/commands/pr-split.md +54 -0
- package/.agent/commands/pr-status.md +56 -0
- package/.agent/commands/pr.md +58 -0
- package/.agent/commands/refactor.md +32 -0
- package/.agent/commands/research.md +28 -0
- package/.agent/commands/scout.md +30 -0
- package/.agent/commands/security-scan.md +33 -0
- package/.agent/commands/setup.md +31 -0
- package/.agent/commands/status.md +59 -0
- package/.agent/commands/tdd.md +73 -0
- package/.agent/commands/verify.md +58 -0
- package/.agent/contexts/brainstorm.md +26 -0
- package/.agent/contexts/debug.md +28 -0
- package/.agent/contexts/implement.md +29 -0
- package/.agent/contexts/plan-quality-log.md +30 -0
- package/.agent/contexts/review.md +27 -0
- package/.agent/contexts/ship.md +28 -0
- package/.agent/decisions/001-trust-grade-governance.md +46 -0
- package/.agent/decisions/002-cross-ide-generation.md +15 -0
- package/.agent/engine/identity.json +4 -0
- package/.agent/engine/loading-rules.json +193 -0
- package/.agent/engine/marketplace-index.json +29 -0
- package/.agent/engine/mcp-servers/filesystem.json +9 -0
- package/.agent/engine/mcp-servers/github.json +11 -0
- package/.agent/engine/mcp-servers/postgres.json +11 -0
- package/.agent/engine/mcp-servers/supabase.json +11 -0
- package/.agent/engine/mcp-servers/vercel.json +11 -0
- package/.agent/engine/reliability-config.json +14 -0
- package/.agent/engine/sdlc-map.json +50 -0
- package/.agent/engine/workflow-state.json +167 -0
- package/.agent/hooks/README.md +101 -0
- package/.agent/hooks/hooks.json +104 -0
- package/.agent/hooks/templates/session-end.md +110 -0
- package/.agent/hooks/templates/session-start.md +95 -0
- package/.agent/manifest.json +466 -0
- package/.agent/rules/agent-upgrade-policy.md +56 -0
- package/.agent/rules/architecture.md +111 -0
- package/.agent/rules/coding-style.md +75 -0
- package/.agent/rules/documentation.md +74 -0
- package/.agent/rules/git-workflow.md +140 -0
- package/.agent/rules/quality-gate.md +117 -0
- package/.agent/rules/security.md +67 -0
- package/.agent/rules/sprint-tracking.md +103 -0
- package/.agent/rules/testing.md +80 -0
- package/.agent/rules/workflow-standards.md +30 -0
- package/.agent/rules.md +293 -0
- package/.agent/session-context.md +69 -0
- package/.agent/session-state.json +27 -0
- package/.agent/skills/README.md +135 -0
- package/.agent/skills/api-patterns/SKILL.md +117 -0
- package/.agent/skills/app-builder/SKILL.md +202 -0
- package/.agent/skills/architecture/SKILL.md +101 -0
- package/.agent/skills/behavioral-modes/SKILL.md +295 -0
- package/.agent/skills/brainstorming/SKILL.md +156 -0
- package/.agent/skills/clean-code/SKILL.md +142 -0
- package/.agent/skills/context-budget/SKILL.md +78 -0
- package/.agent/skills/continuous-learning/SKILL.md +145 -0
- package/.agent/skills/database-design/SKILL.md +303 -0
- package/.agent/skills/debugging-strategies/SKILL.md +158 -0
- package/.agent/skills/deployment-procedures/SKILL.md +191 -0
- package/.agent/skills/docker-patterns/SKILL.md +161 -0
- package/.agent/skills/eval-harness/SKILL.md +89 -0
- package/.agent/skills/frontend-patterns/SKILL.md +141 -0
- package/.agent/skills/git-workflow/SKILL.md +159 -0
- package/.agent/skills/i18n-localization/SKILL.md +191 -0
- package/.agent/skills/intelligent-routing/SKILL.md +180 -0
- package/.agent/skills/mcp-integration/SKILL.md +240 -0
- package/.agent/skills/mobile-design/SKILL.md +191 -0
- package/.agent/skills/nodejs-patterns/SKILL.md +164 -0
- package/.agent/skills/parallel-agents/SKILL.md +200 -0
- package/.agent/skills/performance-profiling/SKILL.md +134 -0
- package/.agent/skills/plan-validation/SKILL.md +192 -0
- package/.agent/skills/plan-writing/SKILL.md +183 -0
- package/.agent/skills/plan-writing/domain-enhancers.md +184 -0
- package/.agent/skills/plan-writing/plan-retrospective.md +116 -0
- package/.agent/skills/plan-writing/plan-schema.md +119 -0
- package/.agent/skills/pr-toolkit/SKILL.md +174 -0
- package/.agent/skills/production-readiness/SKILL.md +126 -0
- package/.agent/skills/security-practices/SKILL.md +109 -0
- package/.agent/skills/shell-conventions/SKILL.md +92 -0
- package/.agent/skills/strategic-compact/SKILL.md +62 -0
- package/.agent/skills/testing-patterns/SKILL.md +141 -0
- package/.agent/skills/typescript-expert/SKILL.md +160 -0
- package/.agent/skills/ui-ux-pro-max/SKILL.md +137 -0
- package/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/skills/ui-ux-pro-max/data/styles.csv +68 -0
- package/.agent/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/scripts/core.py +253 -0
- package/.agent/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/.agent/skills/ui-ux-pro-max/scripts/search.py +114 -0
- package/.agent/skills/verification-loop/SKILL.md +89 -0
- package/.agent/skills/webapp-testing/SKILL.md +175 -0
- package/.agent/templates/adr-template.md +32 -0
- package/.agent/templates/bug-report.md +37 -0
- package/.agent/templates/feature-request.md +32 -0
- package/.agent/workflows/README.md +101 -0
- package/.agent/workflows/brainstorm.md +86 -0
- package/.agent/workflows/create.md +85 -0
- package/.agent/workflows/debug.md +83 -0
- package/.agent/workflows/deploy.md +114 -0
- package/.agent/workflows/enhance.md +85 -0
- package/.agent/workflows/orchestrate.md +106 -0
- package/.agent/workflows/plan.md +105 -0
- package/.agent/workflows/pr-fix.md +163 -0
- package/.agent/workflows/pr-merge.md +117 -0
- package/.agent/workflows/pr-review.md +178 -0
- package/.agent/workflows/pr-split.md +118 -0
- package/.agent/workflows/pr.md +184 -0
- package/.agent/workflows/preflight.md +107 -0
- package/.agent/workflows/preview.md +95 -0
- package/.agent/workflows/quality-gate.md +103 -0
- package/.agent/workflows/retrospective.md +100 -0
- package/.agent/workflows/review.md +104 -0
- package/.agent/workflows/status.md +89 -0
- package/.agent/workflows/test.md +98 -0
- package/.agent/workflows/ui-ux-pro-max.md +93 -0
- package/.agent/workflows/upgrade.md +97 -0
- package/LICENSE +21 -0
- package/README.md +218 -0
- package/bin/kit.js +773 -0
- package/lib/agent-registry.js +228 -0
- package/lib/agent-reputation.js +343 -0
- package/lib/circuit-breaker.js +195 -0
- package/lib/cli-commands.js +322 -0
- package/lib/config-validator.js +274 -0
- package/lib/conflict-detector.js +252 -0
- package/lib/constants.js +47 -0
- package/lib/engineering-manager.js +336 -0
- package/lib/error-budget.js +370 -0
- package/lib/hook-system.js +256 -0
- package/lib/ide-generator.js +434 -0
- package/lib/identity.js +240 -0
- package/lib/io.js +146 -0
- package/lib/learning-engine.js +163 -0
- package/lib/loading-engine.js +421 -0
- package/lib/logger.js +118 -0
- package/lib/marketplace.js +321 -0
- package/lib/plugin-system.js +604 -0
- package/lib/plugin-verifier.js +197 -0
- package/lib/rate-limiter.js +113 -0
- package/lib/security-scanner.js +312 -0
- package/lib/self-healing.js +468 -0
- package/lib/session-manager.js +264 -0
- package/lib/skill-sandbox.js +244 -0
- package/lib/task-governance.js +522 -0
- package/lib/task-model.js +332 -0
- package/lib/updater.js +240 -0
- package/lib/verify.js +279 -0
- package/lib/workflow-engine.js +373 -0
- package/lib/workflow-events.js +166 -0
- package/lib/workflow-persistence.js +160 -0
- package/package.json +57 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Devran AI Kit — Circuit Breaker
|
|
3
|
+
*
|
|
4
|
+
* Implements the circuit breaker pattern for protecting external
|
|
5
|
+
* operations (git clones, network requests) from cascading failures.
|
|
6
|
+
*
|
|
7
|
+
* States: CLOSED (normal) → OPEN (failing) → HALF_OPEN (testing recovery)
|
|
8
|
+
*
|
|
9
|
+
* @module lib/circuit-breaker
|
|
10
|
+
* @author Emre Dursun
|
|
11
|
+
* @since v3.2.0
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict';
|
|
15
|
+
|
|
16
|
+
/** @typedef {'CLOSED' | 'OPEN' | 'HALF_OPEN'} CircuitState */
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {object} CircuitBreakerOptions
|
|
20
|
+
* @property {number} [failureThreshold=3] - Failures before opening circuit
|
|
21
|
+
* @property {number} [resetTimeoutMs=60000] - Time before attempting recovery (ms)
|
|
22
|
+
* @property {number} [halfOpenMaxAttempts=1] - Max attempts in half-open state
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {object} CircuitBreakerState
|
|
27
|
+
* @property {CircuitState} state - Current circuit state
|
|
28
|
+
* @property {number} failureCount - Consecutive failure count
|
|
29
|
+
* @property {number} successCount - Consecutive success count in half-open
|
|
30
|
+
* @property {number | null} lastFailureTime - Timestamp of last failure
|
|
31
|
+
* @property {number} totalFailures - Lifetime failure count
|
|
32
|
+
* @property {number} totalSuccesses - Lifetime success count
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Creates a new circuit breaker instance.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} name - Circuit breaker name for identification
|
|
39
|
+
* @param {CircuitBreakerOptions} [options] - Configuration options
|
|
40
|
+
* @returns {{ execute: Function, getState: Function, reset: Function }}
|
|
41
|
+
*/
|
|
42
|
+
function createCircuitBreaker(name, options = {}) {
|
|
43
|
+
const failureThreshold = options.failureThreshold || 3;
|
|
44
|
+
const resetTimeoutMs = options.resetTimeoutMs || 60000;
|
|
45
|
+
const halfOpenMaxAttempts = options.halfOpenMaxAttempts || 1;
|
|
46
|
+
|
|
47
|
+
/** @type {CircuitBreakerState} */
|
|
48
|
+
const state = {
|
|
49
|
+
state: 'CLOSED',
|
|
50
|
+
failureCount: 0,
|
|
51
|
+
successCount: 0,
|
|
52
|
+
lastFailureTime: null,
|
|
53
|
+
totalFailures: 0,
|
|
54
|
+
totalSuccesses: 0,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Checks if the circuit should transition from OPEN to HALF_OPEN.
|
|
59
|
+
*
|
|
60
|
+
* @returns {boolean}
|
|
61
|
+
*/
|
|
62
|
+
function shouldAttemptReset() {
|
|
63
|
+
if (state.state !== 'OPEN' || state.lastFailureTime === null) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return (Date.now() - state.lastFailureTime) >= resetTimeoutMs;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Records a successful operation.
|
|
71
|
+
*
|
|
72
|
+
* @returns {void}
|
|
73
|
+
*/
|
|
74
|
+
function onSuccess() {
|
|
75
|
+
state.totalSuccesses += 1;
|
|
76
|
+
|
|
77
|
+
if (state.state === 'HALF_OPEN') {
|
|
78
|
+
state.successCount += 1;
|
|
79
|
+
if (state.successCount >= halfOpenMaxAttempts) {
|
|
80
|
+
state.state = 'CLOSED';
|
|
81
|
+
state.failureCount = 0;
|
|
82
|
+
state.successCount = 0;
|
|
83
|
+
state.lastFailureTime = null;
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
state.failureCount = 0;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Records a failed operation.
|
|
92
|
+
*
|
|
93
|
+
* @returns {void}
|
|
94
|
+
*/
|
|
95
|
+
function onFailure() {
|
|
96
|
+
state.totalFailures += 1;
|
|
97
|
+
state.failureCount += 1;
|
|
98
|
+
state.lastFailureTime = Date.now();
|
|
99
|
+
|
|
100
|
+
if (state.state === 'HALF_OPEN') {
|
|
101
|
+
state.state = 'OPEN';
|
|
102
|
+
state.successCount = 0;
|
|
103
|
+
} else if (state.failureCount >= failureThreshold) {
|
|
104
|
+
state.state = 'OPEN';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Executes an operation through the circuit breaker.
|
|
110
|
+
*
|
|
111
|
+
* @param {Function} operation - Async or sync operation to execute
|
|
112
|
+
* @returns {*} Result of the operation
|
|
113
|
+
* @throws {Error} If circuit is open or operation fails
|
|
114
|
+
*/
|
|
115
|
+
function execute(operation) {
|
|
116
|
+
if (state.state === 'OPEN') {
|
|
117
|
+
if (shouldAttemptReset()) {
|
|
118
|
+
state.state = 'HALF_OPEN';
|
|
119
|
+
state.successCount = 0;
|
|
120
|
+
} else {
|
|
121
|
+
throw new Error(
|
|
122
|
+
`Circuit breaker "${name}" is OPEN — operation rejected. ` +
|
|
123
|
+
`${state.failureCount} consecutive failures. ` +
|
|
124
|
+
`Will retry after ${Math.ceil((resetTimeoutMs - (Date.now() - state.lastFailureTime)) / 1000)}s.`
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
const result = operation();
|
|
131
|
+
onSuccess();
|
|
132
|
+
return result;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
onFailure();
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Executes an asynchronous operation through the circuit breaker.
|
|
141
|
+
* Properly tracks Promise resolution/rejection for state management.
|
|
142
|
+
*
|
|
143
|
+
* @param {Function} operation - Async operation to execute (must return a Promise)
|
|
144
|
+
* @returns {Promise<*>} Result of the operation
|
|
145
|
+
* @throws {Error} If circuit is open or operation fails
|
|
146
|
+
*/
|
|
147
|
+
async function executeAsync(operation) {
|
|
148
|
+
if (state.state === 'OPEN') {
|
|
149
|
+
if (shouldAttemptReset()) {
|
|
150
|
+
state.state = 'HALF_OPEN';
|
|
151
|
+
state.successCount = 0;
|
|
152
|
+
} else {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`Circuit breaker "${name}" is OPEN — operation rejected. ` +
|
|
155
|
+
`${state.failureCount} consecutive failures. ` +
|
|
156
|
+
`Will retry after ${Math.ceil((resetTimeoutMs - (Date.now() - state.lastFailureTime)) / 1000)}s.`
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const result = await operation();
|
|
163
|
+
onSuccess();
|
|
164
|
+
return result;
|
|
165
|
+
} catch (error) {
|
|
166
|
+
onFailure();
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Returns a snapshot of the circuit breaker state.
|
|
173
|
+
*
|
|
174
|
+
* @returns {CircuitBreakerState & { name: string }}
|
|
175
|
+
*/
|
|
176
|
+
function getState() {
|
|
177
|
+
return { name, ...state };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Resets the circuit breaker to CLOSED state.
|
|
182
|
+
*
|
|
183
|
+
* @returns {void}
|
|
184
|
+
*/
|
|
185
|
+
function reset() {
|
|
186
|
+
state.state = 'CLOSED';
|
|
187
|
+
state.failureCount = 0;
|
|
188
|
+
state.successCount = 0;
|
|
189
|
+
state.lastFailureTime = null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return { execute, executeAsync, getState, reset };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
module.exports = { createCircuitBreaker };
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Devran AI Kit — CLI Command Handlers (Phase 4)
|
|
3
|
+
*
|
|
4
|
+
* Extracted command handlers to keep bin/kit.js under 800 lines.
|
|
5
|
+
* Handles: `market`, `heal`, and dashboard sections.
|
|
6
|
+
*
|
|
7
|
+
* @module lib/cli-commands
|
|
8
|
+
* @author Emre Dursun
|
|
9
|
+
* @since v3.0.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const { AGENT_DIR, ENGINE_DIR } = require('./constants');
|
|
17
|
+
|
|
18
|
+
// ANSI colors (shared with kit.js)
|
|
19
|
+
const colors = {
|
|
20
|
+
reset: '\x1b[0m',
|
|
21
|
+
bright: '\x1b[1m',
|
|
22
|
+
green: '\x1b[32m',
|
|
23
|
+
blue: '\x1b[34m',
|
|
24
|
+
yellow: '\x1b[33m',
|
|
25
|
+
red: '\x1b[31m',
|
|
26
|
+
cyan: '\x1b[36m',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Marketplace CLI handler.
|
|
31
|
+
*
|
|
32
|
+
* @param {string} projectRoot - Root directory
|
|
33
|
+
* @param {string} subCommand - Sub-command: search, info, install, update
|
|
34
|
+
* @param {string} [argument] - Argument for the sub-command
|
|
35
|
+
* @param {object} [options] - CLI options
|
|
36
|
+
* @returns {void}
|
|
37
|
+
*/
|
|
38
|
+
function marketCommand(projectRoot, subCommand, argument, options = {}) {
|
|
39
|
+
const marketplace = require('./marketplace');
|
|
40
|
+
|
|
41
|
+
switch (subCommand) {
|
|
42
|
+
case 'search': {
|
|
43
|
+
if (!argument) {
|
|
44
|
+
console.log(`${colors.yellow}Usage: kit market search <query>${colors.reset}`);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const results = marketplace.searchMarket(projectRoot, argument);
|
|
48
|
+
console.log(`\n${colors.bright}${colors.blue}═══ Marketplace Search: "${argument}" ═══${colors.reset}\n`);
|
|
49
|
+
if (results.length === 0) {
|
|
50
|
+
console.log(` No plugins found matching "${argument}"`);
|
|
51
|
+
} else {
|
|
52
|
+
for (const entry of results) {
|
|
53
|
+
console.log(` ${colors.green}${entry.name}${colors.reset} v${entry.version}`);
|
|
54
|
+
console.log(` ${entry.description}`);
|
|
55
|
+
console.log(` Tags: ${(entry.tags || []).join(', ')}`);
|
|
56
|
+
console.log('');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
console.log(` ${results.length} result(s)\n`);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
case 'info': {
|
|
64
|
+
if (!argument) {
|
|
65
|
+
console.log(`${colors.yellow}Usage: kit market info <plugin-name>${colors.reset}`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const info = marketplace.getMarketInfo(projectRoot, argument);
|
|
69
|
+
if (!info) {
|
|
70
|
+
console.log(`${colors.red}Plugin not found: ${argument}${colors.reset}`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
console.log(`\n${colors.bright}${colors.blue}═══ Plugin: ${info.name} ═══${colors.reset}\n`);
|
|
74
|
+
console.log(` Version: ${info.version}`);
|
|
75
|
+
console.log(` Author: ${info.author}`);
|
|
76
|
+
console.log(` Description: ${info.description}`);
|
|
77
|
+
console.log(` Repository: ${info.repository}`);
|
|
78
|
+
console.log(` Tags: ${(info.tags || []).join(', ')}\n`);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
case 'install': {
|
|
83
|
+
if (!argument) {
|
|
84
|
+
console.log(`${colors.yellow}Usage: kit market install <plugin-name>${colors.reset}`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log(`${colors.cyan}Installing ${argument}...${colors.reset}`);
|
|
88
|
+
const result = marketplace.installFromMarket(projectRoot, argument);
|
|
89
|
+
if (result.success) {
|
|
90
|
+
console.log(`${colors.green}✓ ${result.message}${colors.reset}`);
|
|
91
|
+
} else {
|
|
92
|
+
console.log(`${colors.red}✗ ${result.message}${colors.reset}`);
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
case 'update': {
|
|
98
|
+
const force = options.force || false;
|
|
99
|
+
const result = marketplace.updateRegistryIndex(projectRoot, { force });
|
|
100
|
+
if (result.updated) {
|
|
101
|
+
console.log(`${colors.green}✓ Registry updated (${result.entryCount} entries)${colors.reset}`);
|
|
102
|
+
} else {
|
|
103
|
+
console.log(`${colors.yellow}Registry is fresh (${result.entryCount} entries). Use --force to update.${colors.reset}`);
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
default:
|
|
109
|
+
console.log(`${colors.yellow}Usage: kit market <search|info|install|update> [arg]${colors.reset}`);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Self-healing CLI handler.
|
|
116
|
+
*
|
|
117
|
+
* @param {string} projectRoot - Root directory
|
|
118
|
+
* @param {object} [options] - CLI options
|
|
119
|
+
* @param {string} [options.file] - Path to CI log file
|
|
120
|
+
* @param {boolean} [options.apply] - Apply patches (default: dry-run)
|
|
121
|
+
* @returns {void}
|
|
122
|
+
*/
|
|
123
|
+
function healCommand(projectRoot, options = {}) {
|
|
124
|
+
const selfHealing = require('./self-healing');
|
|
125
|
+
let ciOutput = '';
|
|
126
|
+
|
|
127
|
+
// Input source (E-3): file > stdin > last-saved
|
|
128
|
+
if (options.file) {
|
|
129
|
+
const filePath = path.resolve(options.file);
|
|
130
|
+
if (!fs.existsSync(filePath)) {
|
|
131
|
+
console.log(`${colors.red}✗ CI log file not found: ${filePath}${colors.reset}`);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
ciOutput = fs.readFileSync(filePath, 'utf-8');
|
|
135
|
+
} else {
|
|
136
|
+
// Try last-saved CI output
|
|
137
|
+
const lastCiPath = path.join(projectRoot, AGENT_DIR, ENGINE_DIR, 'last-ci-output.txt');
|
|
138
|
+
if (fs.existsSync(lastCiPath)) {
|
|
139
|
+
ciOutput = fs.readFileSync(lastCiPath, 'utf-8');
|
|
140
|
+
} else {
|
|
141
|
+
console.log(`${colors.yellow}No CI output found. Use: kit heal --file <path>${colors.reset}`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
console.log(`\n${colors.bright}${colors.blue}═══ Self-Healing Pipeline ═══${colors.reset}\n`);
|
|
147
|
+
|
|
148
|
+
// Detect failures
|
|
149
|
+
const failures = selfHealing.detectFailure(ciOutput);
|
|
150
|
+
|
|
151
|
+
if (failures.length === 0) {
|
|
152
|
+
console.log(` ${colors.green}✓ No failures detected — pipeline is healthy${colors.reset}\n`);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
console.log(` ${colors.red}${failures.length} failure(s) detected${colors.reset}\n`);
|
|
157
|
+
|
|
158
|
+
// Diagnose and generate patches
|
|
159
|
+
for (const failure of failures) {
|
|
160
|
+
const diagnosis = selfHealing.diagnoseFailure(failure);
|
|
161
|
+
console.log(` ${colors.yellow}[${failure.type.toUpperCase()}]${colors.reset} ${failure.message}`);
|
|
162
|
+
console.log(` Diagnosis: ${diagnosis.category} — ${diagnosis.explanation}`);
|
|
163
|
+
|
|
164
|
+
if (diagnosis.autoFixable) {
|
|
165
|
+
const patch = selfHealing.generateFixPatch(failure, diagnosis);
|
|
166
|
+
if (patch) {
|
|
167
|
+
const dryRun = !options.apply;
|
|
168
|
+
const result = selfHealing.applyFixWithConfirmation(projectRoot, patch, { dryRun });
|
|
169
|
+
console.log(` Patch ${patch.patchId}: ${dryRun ? 'DRY RUN' : result.applied ? 'APPLIED' : 'FAILED'}`);
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
console.log(` ${colors.cyan}→ Manual review required${colors.reset}`);
|
|
173
|
+
}
|
|
174
|
+
console.log('');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Dashboard sections for Phase 4 features.
|
|
180
|
+
* Called by statusCommand() in kit.js.
|
|
181
|
+
*
|
|
182
|
+
* @param {string} projectRoot - Root directory
|
|
183
|
+
* @returns {void}
|
|
184
|
+
*/
|
|
185
|
+
function renderDashboardSections(projectRoot) {
|
|
186
|
+
// ═══ Reputation ═══
|
|
187
|
+
try {
|
|
188
|
+
const reputation = require('./agent-reputation');
|
|
189
|
+
const rankings = reputation.getRankings(projectRoot);
|
|
190
|
+
|
|
191
|
+
console.log(`\n${colors.bright}${colors.cyan}═══ Reputation ═══${colors.reset}`);
|
|
192
|
+
|
|
193
|
+
if (rankings.length === 0) {
|
|
194
|
+
console.log(' No reputation data yet');
|
|
195
|
+
} else {
|
|
196
|
+
for (const agent of rankings.slice(0, 5)) {
|
|
197
|
+
const trend = agent.trend;
|
|
198
|
+
console.log(` ${colors.green}${agent.agent}${colors.reset} — Score: ${agent.score} ${trend} | Reliability: ${agent.reliability}%`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
// Reputation module not available — silently skip
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ═══ Sprint ═══
|
|
206
|
+
try {
|
|
207
|
+
const engMgr = require('./engineering-manager');
|
|
208
|
+
const metrics = engMgr.getSprintMetrics(projectRoot);
|
|
209
|
+
|
|
210
|
+
console.log(`\n${colors.bright}${colors.cyan}═══ Sprint ═══${colors.reset}`);
|
|
211
|
+
console.log(` Total Sprints: ${metrics.totalSprints}`);
|
|
212
|
+
console.log(` Active Sprint: ${metrics.activeSprint ? metrics.activeSprint.name : 'none'}`);
|
|
213
|
+
console.log(` Velocity: ${metrics.velocity} tasks/sprint`);
|
|
214
|
+
} catch {
|
|
215
|
+
// Module not available — silently skip
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ═══ Health ═══
|
|
219
|
+
try {
|
|
220
|
+
const selfHealing = require('./self-healing');
|
|
221
|
+
const report = selfHealing.getHealingReport(projectRoot);
|
|
222
|
+
|
|
223
|
+
console.log(`\n${colors.bright}${colors.cyan}═══ Health ═══${colors.reset}`);
|
|
224
|
+
console.log(` Total Heals: ${report.totalHeals}`);
|
|
225
|
+
console.log(` Success Rate: ${report.successRate}%`);
|
|
226
|
+
console.log(` Pending Patches: ${report.pendingPatches}`);
|
|
227
|
+
} catch {
|
|
228
|
+
// Module not available — silently skip
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Health check CLI handler.
|
|
234
|
+
* Aggregates error budget, plugin integrity, config validation, and healing status.
|
|
235
|
+
*
|
|
236
|
+
* @param {string} projectRoot - Root directory
|
|
237
|
+
* @returns {{ healthy: boolean, checks: object[] }}
|
|
238
|
+
*/
|
|
239
|
+
function healthCommand(projectRoot) {
|
|
240
|
+
const checks = [];
|
|
241
|
+
|
|
242
|
+
// Error budget health
|
|
243
|
+
try {
|
|
244
|
+
const errorBudget = require('./error-budget');
|
|
245
|
+
const report = errorBudget.getBudgetReport(projectRoot);
|
|
246
|
+
checks.push({
|
|
247
|
+
name: 'Error Budget',
|
|
248
|
+
status: report.status,
|
|
249
|
+
healthy: report.status !== 'EXHAUSTED',
|
|
250
|
+
detail: report.violations.length > 0 ? `Violations: ${report.violations.join(', ')}` : 'All rates within thresholds',
|
|
251
|
+
});
|
|
252
|
+
} catch {
|
|
253
|
+
checks.push({ name: 'Error Budget', status: 'SKIPPED', healthy: true, detail: 'No reliability config found' });
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Plugin integrity
|
|
257
|
+
try {
|
|
258
|
+
const pluginVerifier = require('./plugin-verifier');
|
|
259
|
+
const result = pluginVerifier.verifyAllPlugins(projectRoot);
|
|
260
|
+
const pluginHealthy = result.invalid.length === 0;
|
|
261
|
+
checks.push({
|
|
262
|
+
name: 'Plugin Integrity',
|
|
263
|
+
status: pluginHealthy ? 'PASS' : 'FAIL',
|
|
264
|
+
healthy: pluginHealthy,
|
|
265
|
+
detail: `${result.valid} valid, ${result.invalid.length} invalid, ${result.unverified.length} unverified`,
|
|
266
|
+
});
|
|
267
|
+
} catch {
|
|
268
|
+
checks.push({ name: 'Plugin Integrity', status: 'SKIPPED', healthy: true, detail: 'Verifier not available' });
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Config validation
|
|
272
|
+
try {
|
|
273
|
+
const configValidator = require('./config-validator');
|
|
274
|
+
const result = configValidator.validateAllConfigs(projectRoot);
|
|
275
|
+
const invalidCount = result.totalConfigs - result.validConfigs;
|
|
276
|
+
const configHealthy = invalidCount === 0;
|
|
277
|
+
checks.push({
|
|
278
|
+
name: 'Config Validation',
|
|
279
|
+
status: configHealthy ? 'PASS' : 'FAIL',
|
|
280
|
+
healthy: configHealthy,
|
|
281
|
+
detail: `${result.validConfigs} valid, ${invalidCount} invalid of ${result.totalConfigs} configs`,
|
|
282
|
+
});
|
|
283
|
+
} catch {
|
|
284
|
+
checks.push({ name: 'Config Validation', status: 'SKIPPED', healthy: true, detail: 'Validator not available' });
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Self-healing status
|
|
288
|
+
try {
|
|
289
|
+
const selfHealing = require('./self-healing');
|
|
290
|
+
const report = selfHealing.getHealingReport(projectRoot);
|
|
291
|
+
checks.push({
|
|
292
|
+
name: 'Self-Healing',
|
|
293
|
+
status: report.pendingPatches > 0 ? 'WARNING' : 'PASS',
|
|
294
|
+
healthy: true,
|
|
295
|
+
detail: `${report.totalHeals} heals, ${report.successRate}% success, ${report.pendingPatches} pending`,
|
|
296
|
+
});
|
|
297
|
+
} catch {
|
|
298
|
+
checks.push({ name: 'Self-Healing', status: 'SKIPPED', healthy: true, detail: 'Healer not available' });
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const healthy = checks.every((c) => c.healthy);
|
|
302
|
+
|
|
303
|
+
// Render output
|
|
304
|
+
console.log(`\n${colors.bright}${colors.blue}═══ Health Check ═══${colors.reset}\n`);
|
|
305
|
+
for (const check of checks) {
|
|
306
|
+
const icon = check.status === 'PASS' || check.status === 'HEALTHY' ? '✓' : check.status === 'FAIL' || check.status === 'EXHAUSTED' ? '✗' : '⚠';
|
|
307
|
+
const color = check.healthy ? 'green' : 'red';
|
|
308
|
+
console.log(` ${colors[color]}${icon} ${check.name}: ${check.status}${colors.reset}`);
|
|
309
|
+
console.log(` ${check.detail}`);
|
|
310
|
+
}
|
|
311
|
+
console.log('');
|
|
312
|
+
console.log(` ${healthy ? `${colors.green}✅ All health checks passed` : `${colors.red}❌ Some health checks failed`}${colors.reset}\n`);
|
|
313
|
+
|
|
314
|
+
return { healthy, checks };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
module.exports = {
|
|
318
|
+
marketCommand,
|
|
319
|
+
healCommand,
|
|
320
|
+
healthCommand,
|
|
321
|
+
renderDashboardSections,
|
|
322
|
+
};
|