@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.
Files changed (231) hide show
  1. package/.agent/CheatSheet.md +350 -0
  2. package/.agent/README.md +76 -0
  3. package/.agent/agents/README.md +155 -0
  4. package/.agent/agents/architect.md +185 -0
  5. package/.agent/agents/backend-specialist.md +276 -0
  6. package/.agent/agents/build-error-resolver.md +207 -0
  7. package/.agent/agents/code-reviewer.md +162 -0
  8. package/.agent/agents/database-architect.md +138 -0
  9. package/.agent/agents/devops-engineer.md +144 -0
  10. package/.agent/agents/doc-updater.md +229 -0
  11. package/.agent/agents/e2e-runner.md +145 -0
  12. package/.agent/agents/explorer-agent.md +143 -0
  13. package/.agent/agents/frontend-specialist.md +144 -0
  14. package/.agent/agents/go-reviewer.md +128 -0
  15. package/.agent/agents/knowledge-agent.md +197 -0
  16. package/.agent/agents/mobile-developer.md +150 -0
  17. package/.agent/agents/performance-optimizer.md +175 -0
  18. package/.agent/agents/planner.md +133 -0
  19. package/.agent/agents/pr-reviewer.md +148 -0
  20. package/.agent/agents/python-reviewer.md +123 -0
  21. package/.agent/agents/refactor-cleaner.md +201 -0
  22. package/.agent/agents/reliability-engineer.md +156 -0
  23. package/.agent/agents/security-reviewer.md +141 -0
  24. package/.agent/agents/sprint-orchestrator.md +124 -0
  25. package/.agent/agents/tdd-guide.md +179 -0
  26. package/.agent/agents/typescript-reviewer.md +110 -0
  27. package/.agent/checklists/README.md +102 -0
  28. package/.agent/checklists/pre-commit.md +93 -0
  29. package/.agent/checklists/session-end.md +99 -0
  30. package/.agent/checklists/session-start.md +102 -0
  31. package/.agent/checklists/task-complete.md +81 -0
  32. package/.agent/commands/README.md +130 -0
  33. package/.agent/commands/adr.md +29 -0
  34. package/.agent/commands/ask.md +28 -0
  35. package/.agent/commands/build.md +30 -0
  36. package/.agent/commands/changelog.md +40 -0
  37. package/.agent/commands/checkpoint.md +28 -0
  38. package/.agent/commands/code-review.md +65 -0
  39. package/.agent/commands/compact.md +28 -0
  40. package/.agent/commands/cook.md +30 -0
  41. package/.agent/commands/db.md +30 -0
  42. package/.agent/commands/debug.md +31 -0
  43. package/.agent/commands/deploy.md +37 -0
  44. package/.agent/commands/design.md +29 -0
  45. package/.agent/commands/doc.md +30 -0
  46. package/.agent/commands/eval.md +30 -0
  47. package/.agent/commands/fix.md +32 -0
  48. package/.agent/commands/git.md +32 -0
  49. package/.agent/commands/help.md +273 -0
  50. package/.agent/commands/implement.md +30 -0
  51. package/.agent/commands/integrate.md +32 -0
  52. package/.agent/commands/learn.md +29 -0
  53. package/.agent/commands/perf.md +31 -0
  54. package/.agent/commands/plan.md +56 -0
  55. package/.agent/commands/pr-describe.md +65 -0
  56. package/.agent/commands/pr-fix.md +45 -0
  57. package/.agent/commands/pr-merge.md +45 -0
  58. package/.agent/commands/pr-review.md +50 -0
  59. package/.agent/commands/pr-split.md +54 -0
  60. package/.agent/commands/pr-status.md +56 -0
  61. package/.agent/commands/pr.md +58 -0
  62. package/.agent/commands/refactor.md +32 -0
  63. package/.agent/commands/research.md +28 -0
  64. package/.agent/commands/scout.md +30 -0
  65. package/.agent/commands/security-scan.md +33 -0
  66. package/.agent/commands/setup.md +31 -0
  67. package/.agent/commands/status.md +59 -0
  68. package/.agent/commands/tdd.md +73 -0
  69. package/.agent/commands/verify.md +58 -0
  70. package/.agent/contexts/brainstorm.md +26 -0
  71. package/.agent/contexts/debug.md +28 -0
  72. package/.agent/contexts/implement.md +29 -0
  73. package/.agent/contexts/plan-quality-log.md +30 -0
  74. package/.agent/contexts/review.md +27 -0
  75. package/.agent/contexts/ship.md +28 -0
  76. package/.agent/decisions/001-trust-grade-governance.md +46 -0
  77. package/.agent/decisions/002-cross-ide-generation.md +15 -0
  78. package/.agent/engine/identity.json +4 -0
  79. package/.agent/engine/loading-rules.json +193 -0
  80. package/.agent/engine/marketplace-index.json +29 -0
  81. package/.agent/engine/mcp-servers/filesystem.json +9 -0
  82. package/.agent/engine/mcp-servers/github.json +11 -0
  83. package/.agent/engine/mcp-servers/postgres.json +11 -0
  84. package/.agent/engine/mcp-servers/supabase.json +11 -0
  85. package/.agent/engine/mcp-servers/vercel.json +11 -0
  86. package/.agent/engine/reliability-config.json +14 -0
  87. package/.agent/engine/sdlc-map.json +50 -0
  88. package/.agent/engine/workflow-state.json +167 -0
  89. package/.agent/hooks/README.md +101 -0
  90. package/.agent/hooks/hooks.json +104 -0
  91. package/.agent/hooks/templates/session-end.md +110 -0
  92. package/.agent/hooks/templates/session-start.md +95 -0
  93. package/.agent/manifest.json +466 -0
  94. package/.agent/rules/agent-upgrade-policy.md +56 -0
  95. package/.agent/rules/architecture.md +111 -0
  96. package/.agent/rules/coding-style.md +75 -0
  97. package/.agent/rules/documentation.md +74 -0
  98. package/.agent/rules/git-workflow.md +140 -0
  99. package/.agent/rules/quality-gate.md +117 -0
  100. package/.agent/rules/security.md +67 -0
  101. package/.agent/rules/sprint-tracking.md +103 -0
  102. package/.agent/rules/testing.md +80 -0
  103. package/.agent/rules/workflow-standards.md +30 -0
  104. package/.agent/rules.md +293 -0
  105. package/.agent/session-context.md +69 -0
  106. package/.agent/session-state.json +27 -0
  107. package/.agent/skills/README.md +135 -0
  108. package/.agent/skills/api-patterns/SKILL.md +117 -0
  109. package/.agent/skills/app-builder/SKILL.md +202 -0
  110. package/.agent/skills/architecture/SKILL.md +101 -0
  111. package/.agent/skills/behavioral-modes/SKILL.md +295 -0
  112. package/.agent/skills/brainstorming/SKILL.md +156 -0
  113. package/.agent/skills/clean-code/SKILL.md +142 -0
  114. package/.agent/skills/context-budget/SKILL.md +78 -0
  115. package/.agent/skills/continuous-learning/SKILL.md +145 -0
  116. package/.agent/skills/database-design/SKILL.md +303 -0
  117. package/.agent/skills/debugging-strategies/SKILL.md +158 -0
  118. package/.agent/skills/deployment-procedures/SKILL.md +191 -0
  119. package/.agent/skills/docker-patterns/SKILL.md +161 -0
  120. package/.agent/skills/eval-harness/SKILL.md +89 -0
  121. package/.agent/skills/frontend-patterns/SKILL.md +141 -0
  122. package/.agent/skills/git-workflow/SKILL.md +159 -0
  123. package/.agent/skills/i18n-localization/SKILL.md +191 -0
  124. package/.agent/skills/intelligent-routing/SKILL.md +180 -0
  125. package/.agent/skills/mcp-integration/SKILL.md +240 -0
  126. package/.agent/skills/mobile-design/SKILL.md +191 -0
  127. package/.agent/skills/nodejs-patterns/SKILL.md +164 -0
  128. package/.agent/skills/parallel-agents/SKILL.md +200 -0
  129. package/.agent/skills/performance-profiling/SKILL.md +134 -0
  130. package/.agent/skills/plan-validation/SKILL.md +192 -0
  131. package/.agent/skills/plan-writing/SKILL.md +183 -0
  132. package/.agent/skills/plan-writing/domain-enhancers.md +184 -0
  133. package/.agent/skills/plan-writing/plan-retrospective.md +116 -0
  134. package/.agent/skills/plan-writing/plan-schema.md +119 -0
  135. package/.agent/skills/pr-toolkit/SKILL.md +174 -0
  136. package/.agent/skills/production-readiness/SKILL.md +126 -0
  137. package/.agent/skills/security-practices/SKILL.md +109 -0
  138. package/.agent/skills/shell-conventions/SKILL.md +92 -0
  139. package/.agent/skills/strategic-compact/SKILL.md +62 -0
  140. package/.agent/skills/testing-patterns/SKILL.md +141 -0
  141. package/.agent/skills/typescript-expert/SKILL.md +160 -0
  142. package/.agent/skills/ui-ux-pro-max/SKILL.md +137 -0
  143. package/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -0
  144. package/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -0
  145. package/.agent/skills/ui-ux-pro-max/data/icons.csv +101 -0
  146. package/.agent/skills/ui-ux-pro-max/data/landing.csv +31 -0
  147. package/.agent/skills/ui-ux-pro-max/data/products.csv +97 -0
  148. package/.agent/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  149. package/.agent/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  150. package/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  151. package/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  152. package/.agent/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  153. package/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  154. package/.agent/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  155. package/.agent/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  156. package/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  157. package/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  158. package/.agent/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  159. package/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  160. package/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  161. package/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  162. package/.agent/skills/ui-ux-pro-max/data/styles.csv +68 -0
  163. package/.agent/skills/ui-ux-pro-max/data/typography.csv +58 -0
  164. package/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  165. package/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  166. package/.agent/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  167. package/.agent/skills/ui-ux-pro-max/scripts/core.py +253 -0
  168. package/.agent/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  169. package/.agent/skills/ui-ux-pro-max/scripts/search.py +114 -0
  170. package/.agent/skills/verification-loop/SKILL.md +89 -0
  171. package/.agent/skills/webapp-testing/SKILL.md +175 -0
  172. package/.agent/templates/adr-template.md +32 -0
  173. package/.agent/templates/bug-report.md +37 -0
  174. package/.agent/templates/feature-request.md +32 -0
  175. package/.agent/workflows/README.md +101 -0
  176. package/.agent/workflows/brainstorm.md +86 -0
  177. package/.agent/workflows/create.md +85 -0
  178. package/.agent/workflows/debug.md +83 -0
  179. package/.agent/workflows/deploy.md +114 -0
  180. package/.agent/workflows/enhance.md +85 -0
  181. package/.agent/workflows/orchestrate.md +106 -0
  182. package/.agent/workflows/plan.md +105 -0
  183. package/.agent/workflows/pr-fix.md +163 -0
  184. package/.agent/workflows/pr-merge.md +117 -0
  185. package/.agent/workflows/pr-review.md +178 -0
  186. package/.agent/workflows/pr-split.md +118 -0
  187. package/.agent/workflows/pr.md +184 -0
  188. package/.agent/workflows/preflight.md +107 -0
  189. package/.agent/workflows/preview.md +95 -0
  190. package/.agent/workflows/quality-gate.md +103 -0
  191. package/.agent/workflows/retrospective.md +100 -0
  192. package/.agent/workflows/review.md +104 -0
  193. package/.agent/workflows/status.md +89 -0
  194. package/.agent/workflows/test.md +98 -0
  195. package/.agent/workflows/ui-ux-pro-max.md +93 -0
  196. package/.agent/workflows/upgrade.md +97 -0
  197. package/LICENSE +21 -0
  198. package/README.md +218 -0
  199. package/bin/kit.js +773 -0
  200. package/lib/agent-registry.js +228 -0
  201. package/lib/agent-reputation.js +343 -0
  202. package/lib/circuit-breaker.js +195 -0
  203. package/lib/cli-commands.js +322 -0
  204. package/lib/config-validator.js +274 -0
  205. package/lib/conflict-detector.js +252 -0
  206. package/lib/constants.js +47 -0
  207. package/lib/engineering-manager.js +336 -0
  208. package/lib/error-budget.js +370 -0
  209. package/lib/hook-system.js +256 -0
  210. package/lib/ide-generator.js +434 -0
  211. package/lib/identity.js +240 -0
  212. package/lib/io.js +146 -0
  213. package/lib/learning-engine.js +163 -0
  214. package/lib/loading-engine.js +421 -0
  215. package/lib/logger.js +118 -0
  216. package/lib/marketplace.js +321 -0
  217. package/lib/plugin-system.js +604 -0
  218. package/lib/plugin-verifier.js +197 -0
  219. package/lib/rate-limiter.js +113 -0
  220. package/lib/security-scanner.js +312 -0
  221. package/lib/self-healing.js +468 -0
  222. package/lib/session-manager.js +264 -0
  223. package/lib/skill-sandbox.js +244 -0
  224. package/lib/task-governance.js +522 -0
  225. package/lib/task-model.js +332 -0
  226. package/lib/updater.js +240 -0
  227. package/lib/verify.js +279 -0
  228. package/lib/workflow-engine.js +373 -0
  229. package/lib/workflow-events.js +166 -0
  230. package/lib/workflow-persistence.js +160 -0
  231. package/package.json +57 -0
package/bin/kit.js ADDED
@@ -0,0 +1,773 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Devran AI Kit CLI
5
+ *
6
+ * Usage:
7
+ * npx @devran-ai/kit init
8
+ * kit init [options]
9
+ *
10
+ * @author Emre Dursun
11
+ * @license MIT
12
+ */
13
+
14
+ const fs = require('fs');
15
+ const path = require('path');
16
+
17
+ const VERSION = require('../package.json').version;
18
+ const AGENT_FOLDER = '.agent';
19
+ const { safeCopyDirSync, readJsonSafe } = require('../lib/io');
20
+ const { USER_DATA_FILES, USER_DATA_DIRS } = require('../lib/updater');
21
+
22
+ // ANSI colors
23
+ const colors = {
24
+ reset: '\x1b[0m',
25
+ bright: '\x1b[1m',
26
+ green: '\x1b[32m',
27
+ blue: '\x1b[34m',
28
+ yellow: '\x1b[33m',
29
+ red: '\x1b[31m',
30
+ cyan: '\x1b[36m',
31
+ };
32
+
33
+ function log(message, color = 'reset') {
34
+ console.log(`${colors[color]}${message}${colors.reset}`);
35
+ }
36
+
37
+ function logStep(step, message) {
38
+ console.log(`${colors.cyan}[${step}]${colors.reset} ${message}`);
39
+ }
40
+
41
+ function loadBannerCounts() {
42
+ try {
43
+ const manifestPath = path.join(__dirname, '..', AGENT_FOLDER, 'manifest.json');
44
+ const manifest = readJsonSafe(manifestPath, null);
45
+ if (manifest?.capabilities) {
46
+ return {
47
+ agents: manifest.capabilities.agents?.count || 19,
48
+ skills: manifest.capabilities.skills?.count || 32,
49
+ commands: manifest.capabilities.commands?.count || 31,
50
+ workflows: manifest.capabilities.workflows?.count || 14,
51
+ };
52
+ }
53
+ } catch { /* fallback to defaults */ }
54
+ return { agents: 19, skills: 32, commands: 31, workflows: 14 };
55
+ }
56
+
57
+ function showBanner() {
58
+ const counts = loadBannerCounts();
59
+ console.log(`
60
+ ${colors.bright}${colors.blue}Devran AI Kit${colors.reset} ${colors.green}v${VERSION}${colors.reset}
61
+ Trust-grade AI development framework
62
+
63
+ ${counts.agents} Agents | ${counts.skills} Skills | ${counts.commands} Commands | ${counts.workflows} Workflows
64
+ `);
65
+ }
66
+
67
+ function showHelp() {
68
+ showBanner();
69
+ console.log(`
70
+ ${colors.bright}Usage:${colors.reset}
71
+ kit init [options] Install .agent folder to your project
72
+ kit update Update to latest version
73
+ kit status Check installation status (alias: dashboard)
74
+ kit verify Run manifest integrity checks
75
+ kit scan Run security scan
76
+ kit plugin list List installed plugins
77
+ kit plugin install <p> Install plugin from directory
78
+ kit plugin remove <n> Remove installed plugin
79
+ kit market search <q> Search marketplace plugins
80
+ kit market info <name> Get marketplace plugin details
81
+ kit market install <n> Install from marketplace
82
+ kit heal [--file <f>] Detect and diagnose CI failures
83
+ kit health Run aggregated health check
84
+ kit --help Show this help message
85
+ kit --version Show version
86
+
87
+ ${colors.bright}Options:${colors.reset}
88
+ --force Overwrite existing .agent folder
89
+ --path <dir> Install to specific directory
90
+ --quiet Suppress output (for CI/CD)
91
+ --dry-run Preview actions without executing
92
+ --apply Apply self-healing patches (default: dry-run)
93
+ --file <path> CI log file for heal command
94
+ --ide <name> Generate config for single IDE (cursor|opencode|codex)
95
+ --skip-ide Skip IDE config generation
96
+
97
+ ${colors.bright}Examples:${colors.reset}
98
+ npx @devran-ai/kit init
99
+ kit init --force
100
+ kit scan
101
+ kit plugin list
102
+
103
+ ${colors.bright}IDE Reference:${colors.reset}
104
+ Type ${colors.cyan}/help${colors.reset} in your AI-powered IDE for the full reference:
105
+ commands, workflows, agents, skills, rules, and checklists.
106
+ `);
107
+ }
108
+
109
+ /**
110
+ * Creates a timestamped backup of a directory.
111
+ * @param {string} dirPath - Directory to back up
112
+ * @returns {string} Path to the backup directory
113
+ */
114
+ function backupDirectory(dirPath) {
115
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
116
+ const backupPath = `${dirPath}.backup-${timestamp}`;
117
+ safeCopyDirSync(dirPath, backupPath);
118
+ return backupPath;
119
+ }
120
+
121
+ /**
122
+ * Checks if there is an active session with in-progress work.
123
+ * @param {string} agentPath - Path to existing .agent directory
124
+ * @returns {boolean} True if session-state indicates active work
125
+ */
126
+ function hasActiveSession(agentPath) {
127
+ const statePath = path.join(agentPath, 'session-state.json');
128
+ const state = readJsonSafe(statePath, null);
129
+ if (!state) return false;
130
+ return state.currentTask || state.inProgress || state.activeWorkflow;
131
+ }
132
+
133
+ function countItems(dir, type = 'dir') {
134
+ try {
135
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
136
+ if (type === 'dir') {
137
+ return entries.filter(e => e.isDirectory()).length;
138
+ }
139
+ return entries.filter(e => e.isFile() && e.name !== 'README.md' && e.name.endsWith('.md')).length;
140
+ } catch {
141
+ return 0;
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Generates IDE-specific config files during init.
147
+ * Extracted from initCommand for readability (gemini-code-assist M-2).
148
+ */
149
+ function generateIdeConfigsForInit(agentPath, targetDir, options) {
150
+ try {
151
+ const { generateAllIdeConfigs, writeIdeConfigs, generateCursorConfig, generateOpenCodeConfig, generateCodexConfig } = require('../lib/ide-generator');
152
+ const manifest = JSON.parse(fs.readFileSync(path.join(agentPath, 'manifest.json'), 'utf-8'));
153
+ const rulesContent = fs.readFileSync(path.join(agentPath, 'rules.md'), 'utf-8');
154
+
155
+ const generatorMap = {
156
+ cursor: () => generateCursorConfig(manifest, rulesContent),
157
+ opencode: () => generateOpenCodeConfig(manifest),
158
+ codex: () => generateCodexConfig(manifest),
159
+ };
160
+
161
+ let configs;
162
+ if (options.ide && generatorMap[options.ide]) {
163
+ configs = [generatorMap[options.ide]()];
164
+ } else if (options.ide) {
165
+ const supported = Object.keys(generatorMap).join(', ');
166
+ log(` ⚠️ Unknown IDE: "${options.ide}". Supported: ${supported}`, 'yellow');
167
+ log(' Skipping IDE config generation.', 'yellow');
168
+ return;
169
+ } else {
170
+ configs = generateAllIdeConfigs(manifest, rulesContent);
171
+ }
172
+
173
+ const result = writeIdeConfigs(targetDir, configs, { force: options.force, skipExisting: !options.force });
174
+ for (const f of result.written) log(` ✓ ${f}`, 'green');
175
+ for (const f of result.skipped) log(` ⏭ ${f} (already exists)`, 'yellow');
176
+ } catch (err) {
177
+ log(` ⚠️ IDE config generation failed: ${err.message}`, 'yellow');
178
+ log(' .agent/ installed successfully — IDE configs can be generated later', 'yellow');
179
+ }
180
+ }
181
+
182
+ function initCommand(options) {
183
+ const targetDir = options.path || process.cwd();
184
+ const agentPath = path.join(targetDir, AGENT_FOLDER);
185
+ const sourcePath = path.join(__dirname, '..', AGENT_FOLDER);
186
+
187
+ // Verify source .agent folder exists
188
+ if (!fs.existsSync(sourcePath)) {
189
+ log(`\n❌ Source .agent folder not found at: ${sourcePath}`, 'red');
190
+ log(' The package may be corrupted. Try reinstalling:', 'yellow');
191
+ log(' npm install -g @devran-ai/kit\n', 'yellow');
192
+ process.exit(1);
193
+ }
194
+
195
+ if (!options.quiet) {
196
+ showBanner();
197
+ }
198
+
199
+ // Check if already exists
200
+ if (fs.existsSync(agentPath) && !options.force) {
201
+ log(`\n⚠️ ${AGENT_FOLDER} folder already exists!`, 'yellow');
202
+ log(' Use --force to overwrite', 'yellow');
203
+ log(' Use kit update for non-destructive updates\n', 'yellow');
204
+ process.exit(1);
205
+ }
206
+
207
+ // M-3: Active session warning for --force
208
+ if (options.force && fs.existsSync(agentPath) && hasActiveSession(agentPath)) {
209
+ log('\n⚠️ Active session detected! Force-overwrite will destroy in-progress work.', 'yellow');
210
+ log(' Consider using kit update instead.\n', 'yellow');
211
+ }
212
+
213
+ if (options.dryRun) {
214
+ log('\n🔍 Dry run mode - no changes will be made\n', 'cyan');
215
+ log(` Would copy: ${sourcePath}`, 'cyan');
216
+ log(` To: ${agentPath}\n`, 'cyan');
217
+ // M-2: Show force damage preview
218
+ if (options.force && fs.existsSync(agentPath)) {
219
+ log(' ⚠️ --force would overwrite these user files (restored from backup):', 'yellow');
220
+ for (const f of USER_DATA_FILES) {
221
+ if (fs.existsSync(path.join(agentPath, f))) {
222
+ log(` • ${f}`, 'yellow');
223
+ }
224
+ }
225
+ for (const d of USER_DATA_DIRS) {
226
+ if (fs.existsSync(path.join(agentPath, d))) {
227
+ log(` • ${d}/ (directory)`, 'yellow');
228
+ }
229
+ }
230
+ log('', 'reset');
231
+ }
232
+ return;
233
+ }
234
+
235
+ // C-2: Auto-backup before force-overwrite
236
+ let backupPath = null;
237
+ if (options.force && fs.existsSync(agentPath)) {
238
+ logStep('1/5', 'Backing up existing .agent folder...');
239
+ try {
240
+ backupPath = backupDirectory(agentPath);
241
+ log(` ✓ Backup created: ${path.basename(backupPath)}`, 'green');
242
+ } catch (err) {
243
+ log(` ⚠️ Backup failed: ${err.message}`, 'yellow');
244
+ log(' Proceeding without backup...', 'yellow');
245
+ }
246
+ }
247
+
248
+ // Dynamic step counter — avoids hardcoded step strings
249
+ const isForceWithBackup = backupPath !== null;
250
+ const totalSteps = isForceWithBackup ? 6 : 4;
251
+ let currentStep = isForceWithBackup ? 2 : 1;
252
+
253
+ // C-3: Atomic copy via temp directory
254
+ logStep(`${currentStep}/${totalSteps}`, 'Copying .agent folder...');
255
+
256
+ const tempPath = `${agentPath}.tmp-${Date.now()}`;
257
+ try {
258
+ safeCopyDirSync(sourcePath, tempPath);
259
+ // Remove old directory if force-overwriting
260
+ if (fs.existsSync(agentPath)) {
261
+ fs.rmSync(agentPath, { recursive: true, force: true });
262
+ }
263
+ // Atomic rename: move temp to final
264
+ fs.renameSync(tempPath, agentPath);
265
+ log(' ✓ Copied successfully', 'green');
266
+ } catch (err) {
267
+ // Cleanup temp directory on failure
268
+ try {
269
+ if (fs.existsSync(tempPath)) {
270
+ fs.rmSync(tempPath, { recursive: true, force: true });
271
+ }
272
+ } catch {
273
+ // Cleanup failure is non-critical
274
+ }
275
+ log(` ✗ Failed to copy: ${err.message}`, 'red');
276
+ process.exit(1);
277
+ }
278
+ currentStep++;
279
+
280
+ // E3: Restore user data files from backup after force-overwrite
281
+ if (isForceWithBackup) {
282
+ logStep(`${currentStep}/${totalSteps}`, 'Restoring user session data from backup...');
283
+ let restoredCount = 0;
284
+
285
+ for (const file of USER_DATA_FILES) {
286
+ const backupFile = path.join(backupPath, file);
287
+ const targetFile = path.join(agentPath, file);
288
+ if (fs.existsSync(backupFile)) {
289
+ const targetDirPath = path.dirname(targetFile);
290
+ if (!fs.existsSync(targetDirPath)) {
291
+ fs.mkdirSync(targetDirPath, { recursive: true });
292
+ }
293
+ fs.copyFileSync(backupFile, targetFile);
294
+ log(` ✓ Restored ${file}`, 'green');
295
+ restoredCount++;
296
+ }
297
+ }
298
+
299
+ for (const dir of USER_DATA_DIRS) {
300
+ const backupDir = path.join(backupPath, dir);
301
+ const targetDirPath = path.join(agentPath, dir);
302
+ if (fs.existsSync(backupDir)) {
303
+ safeCopyDirSync(backupDir, targetDirPath);
304
+ log(` ✓ Restored ${dir}/`, 'green');
305
+ restoredCount++;
306
+ }
307
+ }
308
+
309
+ if (restoredCount === 0) {
310
+ log(' ○ No user data to restore', 'yellow');
311
+ }
312
+ currentStep++;
313
+ }
314
+
315
+ // Verify installation
316
+ logStep(`${currentStep}/${totalSteps}`, 'Verifying installation...');
317
+ const skills = countItems(path.join(agentPath, 'skills'), 'dir');
318
+ const commands = countItems(path.join(agentPath, 'commands'), 'file');
319
+ const workflows = countItems(path.join(agentPath, 'workflows'), 'file');
320
+ log(` ✓ Skills: ${skills}, Commands: ${commands}, Workflows: ${workflows}`, 'green');
321
+ currentStep++;
322
+
323
+ // Generate IDE configurations (Cursor, OpenCode, Codex)
324
+ if (!options.skipIde) {
325
+ logStep(`${currentStep}/${totalSteps}`, 'Generating IDE configurations...');
326
+ generateIdeConfigsForInit(agentPath, targetDir, options);
327
+ }
328
+ currentStep++;
329
+
330
+ // Final message
331
+ logStep(`${currentStep}/${totalSteps}`, 'Setup complete!');
332
+
333
+ if (!options.quiet) {
334
+ console.log(`
335
+ ${colors.green}Devran AI Kit installed successfully.${colors.reset}
336
+
337
+ ${colors.bright}Next steps:${colors.reset}
338
+ 1. Open your project in an AI-powered IDE
339
+ 2. Run ${colors.cyan}/status${colors.reset} to verify
340
+ 3. Use ${colors.cyan}/help${colors.reset} to see available commands
341
+
342
+ ${colors.bright}Validate your installation:${colors.reset}
343
+ ${colors.cyan}kit verify${colors.reset} Manifest integrity check
344
+ ${colors.cyan}kit scan${colors.reset} Security scan
345
+
346
+ ${colors.bright}Quick start:${colors.reset}
347
+ ${colors.cyan}/plan${colors.reset} Create implementation plan
348
+ ${colors.cyan}/implement${colors.reset} Execute the plan
349
+ ${colors.cyan}/verify${colors.reset} Run quality gates
350
+
351
+ ${colors.yellow}📚 Documentation: https://github.com/devran-ai/kit${colors.reset}
352
+ `);
353
+ }
354
+ }
355
+
356
+ function statusCommand() {
357
+ showBanner();
358
+
359
+ const agentPath = path.join(process.cwd(), AGENT_FOLDER);
360
+
361
+ if (!fs.existsSync(agentPath)) {
362
+ log('❌ Not installed in current directory', 'red');
363
+ log(' Run: kit init\n', 'yellow');
364
+ return;
365
+ }
366
+
367
+ log('Devran AI Kit is installed\n', 'green');
368
+
369
+ const skills = countItems(path.join(agentPath, 'skills'), 'dir');
370
+ const commands = countItems(path.join(agentPath, 'commands'), 'file');
371
+ const workflows = countItems(path.join(agentPath, 'workflows'), 'file');
372
+
373
+ log(' ═══ Capabilities ═══', 'cyan');
374
+ console.log(` 📦 Skills: ${skills}`);
375
+ console.log(` ⌨️ Commands: ${commands}`);
376
+ console.log(` 🔄 Workflows: ${workflows}`);
377
+
378
+ // Workflow phase + available transitions
379
+ try {
380
+ const workflowEngine = require('../lib/workflow-engine');
381
+ const phase = workflowEngine.getCurrentPhase(process.cwd());
382
+ const available = workflowEngine.getAvailableTransitions(process.cwd());
383
+ console.log(` 🔁 Phase: ${phase}`);
384
+ if (available.length > 0) {
385
+ const nextPhases = available.map((t) => t.to).join(', ');
386
+ console.log(` ➡️ Next: ${nextPhases}`);
387
+ }
388
+ } catch {
389
+ // Engine not available, skip silently
390
+ }
391
+
392
+ // Error budget
393
+ try {
394
+ const errorBudget = require('../lib/error-budget');
395
+ const report = errorBudget.getBudgetReport(process.cwd());
396
+ const statusIcon = report.status === 'HEALTHY' ? '🟢' : report.status === 'WARNING' ? '🟡' : '🔴';
397
+ console.log(` ${statusIcon} Budget: ${report.status}`);
398
+ if (report.violations.length > 0) {
399
+ log(` ⚠️ Violations: ${report.violations.join(', ')}`, 'yellow');
400
+ }
401
+ } catch {
402
+ // Budget not available, skip silently
403
+ }
404
+
405
+ // Task metrics
406
+ try {
407
+ const taskModel = require('../lib/task-model');
408
+ const metrics = taskModel.getTaskMetrics(process.cwd());
409
+ if (metrics.total > 0) {
410
+ console.log('');
411
+ log(' ═══ Tasks ═══', 'cyan');
412
+ console.log(` 📋 Open: ${metrics.counts.open || 0}`);
413
+ console.log(` 🔨 In Progress: ${metrics.counts['in-progress'] || 0}`);
414
+ console.log(` 👁️ In Review: ${metrics.counts.review || 0}`);
415
+ console.log(` ✅ Done: ${metrics.counts.done || 0}`);
416
+ console.log(` 🚫 Blocked: ${metrics.counts.blocked || 0}`);
417
+ if (metrics.completionRate > 0) {
418
+ console.log(` 📊 Completion: ${metrics.completionRate}%`);
419
+ }
420
+ }
421
+ } catch {
422
+ // Task model not available, skip silently
423
+ }
424
+
425
+ // Hook readiness
426
+ try {
427
+ const hookSystem = require('../lib/hook-system');
428
+ const hookReport = hookSystem.getHookReport(process.cwd());
429
+ console.log('');
430
+ log(' ═══ Hooks ═══', 'cyan');
431
+ console.log(` 🪝 Events: ${hookReport.events.length}`);
432
+ console.log(` ✅ Ready: ${hookReport.readyCount}/${hookReport.events.length}`);
433
+ } catch {
434
+ // Hook system not available, skip silently
435
+ }
436
+
437
+ // Developer identity
438
+ try {
439
+ const identity = require('../lib/identity');
440
+ const current = identity.getCurrentIdentity(process.cwd());
441
+ if (current) {
442
+ console.log('');
443
+ log(' ═══ Identity ═══', 'cyan');
444
+ console.log(` 👤 Developer: ${current.name}`);
445
+ console.log(` 🔑 Role: ${current.role}`);
446
+ }
447
+ } catch {
448
+ // Identity not available, skip silently
449
+ }
450
+
451
+ // Plugins
452
+ try {
453
+ const pluginSystem = require('../lib/plugin-system');
454
+ const plugins = pluginSystem.listPlugins(process.cwd());
455
+ if (plugins.length > 0) {
456
+ console.log('');
457
+ log(' ═══ Plugins ═══', 'cyan');
458
+ console.log(` 🔌 Installed: ${plugins.length}`);
459
+ for (const plugin of plugins) {
460
+ console.log(` • ${plugin.name} v${plugin.version}`);
461
+ }
462
+ }
463
+ } catch {
464
+ // Plugin system not available, skip silently
465
+ }
466
+
467
+ // Phase 4 dashboard sections (D-5, E-5)
468
+ try {
469
+ const cliCommands = require('../lib/cli-commands');
470
+ cliCommands.renderDashboardSections(process.cwd());
471
+ } catch {
472
+ // Phase 4 modules not available, skip silently
473
+ }
474
+
475
+ console.log('');
476
+ }
477
+
478
+ function verifyCommand() {
479
+ showBanner();
480
+ logStep('1/1', 'Running manifest integrity checks...\n');
481
+
482
+ try {
483
+ const verify = require('../lib/verify');
484
+ const report = verify.runAllChecks(process.cwd());
485
+
486
+ for (const result of report.results) {
487
+ const icon = result.status === 'pass' ? '✓' : result.status === 'fail' ? '✗' : '⚠';
488
+ const color = result.status === 'pass' ? 'green' : result.status === 'fail' ? 'red' : 'yellow';
489
+ log(` ${icon} ${result.message}`, color);
490
+ }
491
+
492
+ console.log('');
493
+ log(` Passed: ${report.passed} Failed: ${report.failed} Warnings: ${report.warnings}`, report.failed > 0 ? 'red' : 'green');
494
+ console.log('');
495
+
496
+ if (report.failed > 0) {
497
+ process.exit(1);
498
+ }
499
+ } catch (/** @type {any} */ error) {
500
+ log(` ✗ Verification failed: ${error.message}`, 'red');
501
+ process.exit(1);
502
+ }
503
+ }
504
+
505
+ function updateCommand(updateOptions) {
506
+ showBanner();
507
+
508
+ const agentPath = path.join(updateOptions.path || process.cwd(), '.agent');
509
+ if (!fs.existsSync(agentPath)) {
510
+ log('\n❌ No .agent/ folder found. Run: kit init\n', 'red');
511
+ process.exit(1);
512
+ }
513
+
514
+ const sourceRoot = path.join(__dirname, '..');
515
+ const targetRoot = updateOptions.path || process.cwd();
516
+
517
+ try {
518
+ const updater = require('../lib/updater');
519
+ const isDryRun = updateOptions.dryRun;
520
+
521
+ // M-1: Show version transition (use source kit version, not CLI version)
522
+ const sourcePackage = readJsonSafe(path.join(sourceRoot, 'package.json'), {});
523
+ const kitVersion = sourcePackage.version || VERSION;
524
+ const currentManifest = readJsonSafe(path.join(agentPath, 'manifest.json'), {});
525
+ const currentVersion = currentManifest.kitVersion || 'unknown';
526
+ if (currentVersion !== kitVersion) {
527
+ log(`\n 📦 Upgrading: v${currentVersion} → v${kitVersion}`, 'cyan');
528
+ }
529
+
530
+ if (isDryRun) {
531
+ log('\n🔍 Dry run mode — no changes will be made\n', 'cyan');
532
+ }
533
+
534
+ logStep('1/2', isDryRun ? 'Analyzing differences...' : 'Applying updates...');
535
+
536
+ const report = updater.applyUpdate(sourceRoot, targetRoot, isDryRun);
537
+
538
+ if (report.added.length > 0) {
539
+ log(`\n 📁 New files (${report.added.length}):`, 'green');
540
+ for (const file of report.added) {
541
+ log(` + ${file}`, 'green');
542
+ }
543
+ }
544
+
545
+ if (report.updated.length > 0) {
546
+ log(`\n 📝 Updated files (${report.updated.length}):`, 'cyan');
547
+ for (const file of report.updated) {
548
+ log(` ~ ${file}`, 'cyan');
549
+ }
550
+ }
551
+
552
+ if (report.skipped.length > 0) {
553
+ log(`\n 🔒 Preserved files (${report.skipped.length}):`, 'yellow');
554
+ for (const file of report.skipped) {
555
+ log(` ○ ${file}`, 'yellow');
556
+ }
557
+ }
558
+
559
+ logStep('2/2', 'Summary');
560
+ console.log(`\n Added: ${report.added.length} Updated: ${report.updated.length} Skipped: ${report.skipped.length} Unchanged: ${report.unchanged.length}\n`);
561
+
562
+ if (report.added.length === 0 && report.updated.length === 0) {
563
+ log(' ✅ Already up to date!\n', 'green');
564
+ } else if (!isDryRun) {
565
+ log(' ✅ Update complete!\n', 'green');
566
+ }
567
+ } catch (/** @type {any} */ error) {
568
+ log(` ✗ Update failed: ${error.message}`, 'red');
569
+ process.exit(1);
570
+ }
571
+ }
572
+
573
+ function scanCommand() {
574
+ showBanner();
575
+ logStep('1/1', 'Running enhanced security scan...\n');
576
+
577
+ try {
578
+ const scanner = require('../lib/security-scanner');
579
+ const report = scanner.getSecurityReport(process.cwd());
580
+
581
+ log(` 📂 Files scanned: ${report.filesScanned}`, 'cyan');
582
+ console.log('');
583
+
584
+ if (report.findings.length === 0) {
585
+ log(' ✅ No security findings — all clear!\n', 'green');
586
+ } else {
587
+ for (const finding of report.findings) {
588
+ const icon = finding.severity === 'critical' ? '🔴' : finding.severity === 'high' ? '🟠' : finding.severity === 'medium' ? '🟡' : '⚪';
589
+ log(` ${icon} [${finding.severity.toUpperCase()}] ${finding.detail}`, finding.severity === 'critical' ? 'red' : finding.severity === 'high' ? 'yellow' : 'reset');
590
+ console.log(` File: ${finding.file}${finding.line ? `:${finding.line}` : ''}`);
591
+ }
592
+ console.log('');
593
+ }
594
+
595
+ log(` 🔴 Critical: ${report.criticalCount} 🟠 High: ${report.highCount} 🟡 Medium: ${report.mediumCount} ⚪ Low: ${report.lowCount}`, report.clean ? 'green' : 'red');
596
+ console.log('');
597
+
598
+ if (!report.clean) {
599
+ process.exit(1);
600
+ }
601
+ } catch (/** @type {any} */ error) {
602
+ log(` ✗ Security scan failed: ${error.message}`, 'red');
603
+ process.exit(1);
604
+ }
605
+ }
606
+
607
+ function pluginCommand(subCommand, pluginArg) {
608
+ showBanner();
609
+
610
+ try {
611
+ const pluginSystem = require('../lib/plugin-system');
612
+
613
+ switch (subCommand) {
614
+ case 'list': {
615
+ const plugins = pluginSystem.listPlugins(process.cwd());
616
+ if (plugins.length === 0) {
617
+ log(' No plugins installed\n', 'yellow');
618
+ } else {
619
+ log(` ═══ Installed Plugins (${plugins.length}) ═══\n`, 'cyan');
620
+ for (const plugin of plugins) {
621
+ console.log(` 🔌 ${plugin.name} v${plugin.version}`);
622
+ console.log(` Author: ${plugin.author}`);
623
+ console.log(` Installed: ${plugin.installedAt}`);
624
+ console.log('');
625
+ }
626
+ }
627
+ break;
628
+ }
629
+ case 'install': {
630
+ if (!pluginArg) {
631
+ log(' ✗ Usage: kit plugin install <path>\n', 'red');
632
+ process.exit(1);
633
+ }
634
+ const pluginPath = path.resolve(pluginArg);
635
+ logStep('1/1', `Installing plugin from ${pluginPath}...`);
636
+ const result = pluginSystem.installPlugin(pluginPath, process.cwd());
637
+ if (result.success) {
638
+ log('\n ✅ Plugin installed successfully!', 'green');
639
+ console.log(` Agents: ${result.installed.agents} Skills: ${result.installed.skills} Workflows: ${result.installed.workflows} Hooks: ${result.installed.hooks}\n`);
640
+ } else {
641
+ log('\n ✗ Plugin installation failed:', 'red');
642
+ for (const error of result.errors) {
643
+ log(` • ${error}`, 'red');
644
+ }
645
+ console.log('');
646
+ process.exit(1);
647
+ }
648
+ break;
649
+ }
650
+ case 'remove': {
651
+ if (!pluginArg) {
652
+ log(' ✗ Usage: kit plugin remove <name>\n', 'red');
653
+ process.exit(1);
654
+ }
655
+ logStep('1/1', `Removing plugin: ${pluginArg}...`);
656
+ const result = pluginSystem.removePlugin(pluginArg, process.cwd());
657
+ if (result.success) {
658
+ log('\n ✅ Plugin removed successfully!\n', 'green');
659
+ } else {
660
+ log(`\n ✗ ${result.error}\n`, 'red');
661
+ process.exit(1);
662
+ }
663
+ break;
664
+ }
665
+ default:
666
+ log(' Usage: kit plugin <list|install|remove>', 'yellow');
667
+ console.log('');
668
+ break;
669
+ }
670
+ } catch (/** @type {any} */ error) {
671
+ log(` ✗ Plugin command failed: ${error.message}`, 'red');
672
+ process.exit(1);
673
+ }
674
+ }
675
+
676
+ // Parse arguments
677
+ const args = process.argv.slice(2);
678
+ const command = args[0];
679
+
680
+ const options = {
681
+ force: args.includes('--force'),
682
+ quiet: args.includes('--quiet'),
683
+ dryRun: args.includes('--dry-run'),
684
+ apply: args.includes('--apply'),
685
+ skipIde: args.includes('--skip-ide'),
686
+ ide: null,
687
+ path: null,
688
+ file: null,
689
+ };
690
+
691
+ // Parse --ide option
692
+ const ideIndex = args.indexOf('--ide');
693
+ if (ideIndex !== -1 && args[ideIndex + 1]) {
694
+ options.ide = args[ideIndex + 1].toLowerCase();
695
+ }
696
+
697
+ // Parse --path option with traversal protection (H-7: use path.resolve boundary check)
698
+ const pathIndex = args.indexOf('--path');
699
+ if (pathIndex !== -1 && args[pathIndex + 1]) {
700
+ const resolvedPath = path.resolve(args[pathIndex + 1]);
701
+ const cwd = process.cwd();
702
+ if (!resolvedPath.startsWith(cwd + path.sep) && resolvedPath !== cwd) {
703
+ log('Error: --path must resolve within current working directory', 'red');
704
+ process.exit(1);
705
+ }
706
+ options.path = resolvedPath;
707
+ }
708
+
709
+ // Parse --file option with traversal protection (H-7: use path.resolve boundary check)
710
+ const fileIndex = args.indexOf('--file');
711
+ if (fileIndex !== -1 && args[fileIndex + 1]) {
712
+ const resolvedFile = path.resolve(args[fileIndex + 1]);
713
+ const cwdForFile = process.cwd();
714
+ if (!resolvedFile.startsWith(cwdForFile + path.sep) && resolvedFile !== cwdForFile) {
715
+ log('Error: --file must resolve within current working directory', 'red');
716
+ process.exit(1);
717
+ }
718
+ options.file = resolvedFile;
719
+ }
720
+
721
+ // Execute command
722
+ switch (command) {
723
+ case 'init':
724
+ initCommand(options);
725
+ break;
726
+ case 'status':
727
+ case 'dashboard':
728
+ statusCommand();
729
+ break;
730
+ case 'update':
731
+ updateCommand(options);
732
+ break;
733
+ case 'verify':
734
+ verifyCommand();
735
+ break;
736
+ case 'scan':
737
+ scanCommand();
738
+ break;
739
+ case 'plugin':
740
+ pluginCommand(args[1], args[2]);
741
+ break;
742
+ case 'market': {
743
+ const cliCommands = require('../lib/cli-commands');
744
+ cliCommands.marketCommand(process.cwd(), args[1], args[2], options);
745
+ break;
746
+ }
747
+ case 'heal': {
748
+ const cliCmd = require('../lib/cli-commands');
749
+ cliCmd.healCommand(process.cwd(), { file: options.file, apply: options.apply });
750
+ break;
751
+ }
752
+ case 'health': {
753
+ const cliHealth = require('../lib/cli-commands');
754
+ const result = cliHealth.healthCommand(process.cwd());
755
+ if (!result.healthy) {
756
+ process.exit(1);
757
+ }
758
+ break;
759
+ }
760
+ case '--version':
761
+ case '-v':
762
+ console.log(VERSION);
763
+ break;
764
+ case '--help':
765
+ case '-h':
766
+ case undefined:
767
+ showHelp();
768
+ break;
769
+ default:
770
+ log(`Unknown command: ${command}`, 'red');
771
+ log('Run kit --help for usage\n', 'yellow');
772
+ process.exit(1);
773
+ }