@rbinar/dev-kit 1.0.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/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # @blinkbrosai/dev-kit
2
+
3
+ VS Code Copilot Agent Mode için blink.dev ajan sistemini projelerinize kuran CLI aracı.
4
+
5
+ ## Kurulum
6
+
7
+ ```bash
8
+ npm install -g @blinkbrosai/dev-kit
9
+ ```
10
+
11
+ > Node.js ≥18 gerektirir.
12
+
13
+ ## Kullanım
14
+
15
+ ### İlk kurulum
16
+
17
+ ```bash
18
+ blink-dev init --key=SIFRE
19
+ ```
20
+
21
+ Bu komut:
22
+ - `.github/agents/` altına 14 uzmanlaşmış ajan dosyasını kurar
23
+ - `.github/prompts/` altına prompt dosyalarını kurar
24
+ - `.github/copilot-instructions.md` dosyasını oluşturur (mevcut içeriği korur)
25
+ - `.blink/` scaffold dizinini oluşturur
26
+
27
+ ### Güncelleme
28
+
29
+ ```bash
30
+ blink-dev update --key=SIFRE
31
+ ```
32
+
33
+ Mevcut kurulumu en son sürüme günceller. Güncelleme öncesi otomatik backup alır.
34
+
35
+ ### Durum kontrolü
36
+
37
+ ```bash
38
+ blink-dev status
39
+ ```
40
+
41
+ Kurulu versiyon, ajan sayısı ve kurulum tarihini gösterir.
42
+
43
+ ### Sağlık kontrolü
44
+
45
+ ```bash
46
+ blink-dev doctor
47
+ ```
48
+
49
+ Kurulumun bütünlüğünü doğrular: eksik dosyalar, bozuk frontmatter, kırık handoff'lar.
50
+
51
+ ## Seçenekler
52
+
53
+ | Seçenek | Komutlar | Açıklama |
54
+ |---|---|---|
55
+ | `--key <şifre>` | init, update | Şifreleme anahtarı |
56
+ | `--force` | init | Mevcut kurulumu ez |
57
+ | `--dry-run` | init, update | Değişiklikleri göster, uygulamadan |
58
+
59
+ ## Ortam Değişkenleri
60
+
61
+ | Değişken | Açıklama |
62
+ |---|---|
63
+ | `BLINK_DEV_KEY` | `--key` yerine kullanılabilir |
64
+
65
+ ## Proje Yapısı (kurulum sonrası)
66
+
67
+ ```
68
+ projeniz/
69
+ ├── .github/
70
+ │ ├── agents/ ← 14 ajan dosyası
71
+ │ ├── prompts/ ← prompt dosyaları
72
+ │ └── copilot-instructions.md
73
+ ├── .blink/ ← proje konvansiyonları (scaffold)
74
+ │ ├── architecture.md
75
+ │ ├── conventions.md
76
+ │ ├── stack.md
77
+ │ ├── testing.md
78
+ │ └── todo.md
79
+ └── .blink-dev-version ← versiyon takip dosyası
80
+ ```
81
+
82
+ ## Ajanlar
83
+
84
+ | Ajan | Rol |
85
+ |---|---|
86
+ | blink.dev.Triage | Görev seçimi ve önceliklendirme |
87
+ | blink.dev.Planner | Araştırma ve plan üretimi |
88
+ | blink.dev.Coordinator | Paralel yürütme |
89
+ | blink.dev.Reviewer | Kalite kapısı |
90
+ | blink.dev.Shipper | Build, PR, merge, tag |
91
+ | blink.dev.Debugger | Hata ayıklama |
92
+ | blink.dev.Security | Güvenlik denetimi |
93
+ | blink.dev.Analyst | Kod sağlığı analizi |
94
+ | blink.dev.Scribe | Dokümantasyon |
95
+ | blink.dev.Critic | Özellik eleştirisi |
96
+ | blink.dev.Brainstorm | Fikir üretimi |
97
+ | blink.dev.Ops | Sunucu teşhisi |
98
+ | blink.dev.Initializer | Proje scaffold |
99
+ | blink.dev.Guardian | Risk değerlendirme |
100
+
101
+ ## Lisans
102
+
103
+ Tüm hakları saklıdır. Yeniden dağıtım yasaktır.
package/bin/cli.js ADDED
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const { Command } = require('commander');
5
+ const { version } = require('../package.json');
6
+ const readline = require('readline');
7
+
8
+ /**
9
+ * Anahtar çözümleme: option → env → interaktif prompt
10
+ */
11
+ async function resolveKey(options) {
12
+ if (options.key) return options.key;
13
+ if (process.env.BLINK_DEV_KEY) return process.env.BLINK_DEV_KEY;
14
+
15
+ const rl = readline.createInterface({
16
+ input: process.stdin,
17
+ output: process.stdout,
18
+ });
19
+
20
+ return new Promise((resolve) => {
21
+ rl.question('Anahtar: ', (answer) => {
22
+ rl.close();
23
+ if (!answer || !answer.trim()) {
24
+ console.error('Hata: Anahtar belirtilmedi.');
25
+ process.exit(1);
26
+ }
27
+ resolve(answer.trim());
28
+ });
29
+ });
30
+ }
31
+
32
+ const program = new Command();
33
+
34
+ program
35
+ .name('blink-dev')
36
+ .description('blink.dev agent dosyalarını yönetme CLI aracı')
37
+ .version(version);
38
+
39
+ // init
40
+ program
41
+ .command('init')
42
+ .description('Agent dosyalarını projeye kur')
43
+ .option('--key <password>', 'Şifre')
44
+ .option('--force', 'Mevcut kurulumu ez', false)
45
+ .option('--dry-run', 'Sadece göster, değişiklik yapma', false)
46
+ .action(async (options) => {
47
+ try {
48
+ const key = await resolveKey(options);
49
+ await require('../lib/commands/init')({ key, force: options.force, dryRun: options.dryRun });
50
+ } catch (err) {
51
+ console.error('init hatası:', err.message);
52
+ process.exit(1);
53
+ }
54
+ });
55
+
56
+ // update
57
+ program
58
+ .command('update')
59
+ .description('Mevcut kurulumu güncelle')
60
+ .option('--key <password>', 'Şifre')
61
+ .option('--dry-run', 'Sadece göster, değişiklik yapma', false)
62
+ .action(async (options) => {
63
+ try {
64
+ const key = await resolveKey(options);
65
+ await require('../lib/commands/update')({ key, dryRun: options.dryRun });
66
+ } catch (err) {
67
+ console.error('update hatası:', err.message);
68
+ process.exit(1);
69
+ }
70
+ });
71
+
72
+ // status
73
+ program
74
+ .command('status')
75
+ .description('Kurulum durumunu göster')
76
+ .action(async () => {
77
+ try {
78
+ await require('../lib/commands/status')();
79
+ } catch (err) {
80
+ console.error('status hatası:', err.message);
81
+ process.exit(1);
82
+ }
83
+ });
84
+
85
+ // doctor
86
+ program
87
+ .command('doctor')
88
+ .description('Kurulumu doğrula ve sorunları raporla')
89
+ .action(async () => {
90
+ try {
91
+ await require('../lib/commands/doctor')();
92
+ } catch (err) {
93
+ console.error('doctor hatası:', err.message);
94
+ process.exit(1);
95
+ }
96
+ });
97
+
98
+ program.parse();
Binary file
@@ -0,0 +1,23 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "createdAt": "2026-04-05T15:05:51.237Z",
4
+ "files": [
5
+ "agents/Analyst.agent.md",
6
+ "agents/Brainstorm.agent.md",
7
+ "agents/Coordinator.agent.md",
8
+ "agents/Critic.agent.md",
9
+ "agents/Debugger.agent.md",
10
+ "agents/Guardian.agent.md",
11
+ "agents/Initializer.agent.md",
12
+ "agents/Ops.agent.md",
13
+ "agents/Planner.agent.md",
14
+ "agents/Reviewer.agent.md",
15
+ "agents/Scribe.agent.md",
16
+ "agents/Security.agent.md",
17
+ "agents/Shipper.agent.md",
18
+ "agents/Triage.agent.md",
19
+ "prompts/blink-dev-close-issue.prompt.md",
20
+ "copilot-instructions.md"
21
+ ],
22
+ "checksum": "ee5f3bdae4c8f6689997769770b28d0c42b5523b902cbe7d6bf3407958a627bc"
23
+ }
@@ -0,0 +1,251 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+ const { isInitialized } = require('../installer');
6
+ const {
7
+ TARGET_AGENTS_DIR,
8
+ TARGET_BLINK_DIR,
9
+ TARGET_INSTRUCTIONS,
10
+ EXPECTED_AGENTS,
11
+ MARKER_START,
12
+ MARKER_END,
13
+ SCAFFOLD_FILES,
14
+ } = require('../constants');
15
+
16
+ /**
17
+ * Basit frontmatter kontrolü — `name:` ve `description:` satırlarını arar.
18
+ * Tam YAML parser kullanmaz.
19
+ */
20
+ function checkFrontmatter(content) {
21
+ const lines = content.split('\n');
22
+ if (lines[0] !== '---') return false;
23
+
24
+ const endIdx = lines.indexOf('---', 1);
25
+ if (endIdx === -1) return false;
26
+
27
+ const block = lines.slice(1, endIdx).join('\n');
28
+ const hasName = /^name\s*:/m.test(block);
29
+ const hasDescription = /^description\s*:/m.test(block);
30
+
31
+ return hasName && hasDescription;
32
+ }
33
+
34
+ /**
35
+ * Agent dosyasındaki handoff referanslarını çıkarır.
36
+ * `agent: blink.dev.XYZ` → 'XYZ'
37
+ */
38
+ function extractHandoffTargets(content) {
39
+ const targets = [];
40
+ const re = /^\s*agent\s*:\s*blink\.dev\.(\w+)/gm;
41
+ let match;
42
+ while ((match = re.exec(content)) !== null) {
43
+ targets.push(match[1]);
44
+ }
45
+ return targets;
46
+ }
47
+
48
+ async function doctor() {
49
+ const cwd = process.cwd();
50
+ const checks = [];
51
+
52
+ // ── Kontrol 1: Kurulum dosyası mevcut mu ──
53
+ const initialized = isInitialized(cwd);
54
+ checks.push({
55
+ name: 'Kurulum dosyası',
56
+ status: initialized ? 'ok' : 'error',
57
+ detail: initialized ? 'Kurulum dosyası mevcut' : 'Kurulum dosyası bulunamadı',
58
+ });
59
+
60
+ // ── Kontrol 2: Agent dizini mevcut mu ──
61
+ const agentsDir = path.join(cwd, TARGET_AGENTS_DIR);
62
+ const agentsDirExists = fs.existsSync(agentsDir);
63
+ checks.push({
64
+ name: 'Agent dizini',
65
+ status: agentsDirExists ? 'ok' : 'error',
66
+ detail: agentsDirExists ? 'Agent dizini mevcut' : 'Agent dizini bulunamadı',
67
+ });
68
+
69
+ // ── Kontrol 3: Beklenen agent dosyaları ──
70
+ const missingAgents = [];
71
+ for (const agent of EXPECTED_AGENTS) {
72
+ if (!fs.existsSync(path.join(agentsDir, agent))) {
73
+ missingAgents.push(agent.replace('.agent.md', ''));
74
+ }
75
+ }
76
+ const foundCount = EXPECTED_AGENTS.length - missingAgents.length;
77
+ const totalCount = EXPECTED_AGENTS.length;
78
+ if (missingAgents.length === 0) {
79
+ checks.push({
80
+ name: 'Agent dosyaları',
81
+ status: 'ok',
82
+ detail: `${totalCount}/${totalCount} agent dosyası mevcut`,
83
+ });
84
+ } else {
85
+ checks.push({
86
+ name: 'Agent dosyaları',
87
+ status: 'warn',
88
+ detail: `${foundCount}/${totalCount} agent dosyası mevcut (eksik: ${missingAgents.join(', ')})`,
89
+ });
90
+ }
91
+
92
+ // ── Kontrol 4: Agent YAML frontmatter geçerli mi ──
93
+ const brokenFrontmatter = [];
94
+ if (agentsDirExists) {
95
+ for (const agent of EXPECTED_AGENTS) {
96
+ const filePath = path.join(agentsDir, agent);
97
+ try {
98
+ const content = fs.readFileSync(filePath, 'utf8');
99
+ if (!checkFrontmatter(content)) {
100
+ brokenFrontmatter.push(agent.replace('.agent.md', ''));
101
+ }
102
+ } catch {
103
+ // Dosya okunamadıysa frontmatter kontrolü atla (eksik dosya zaten Kontrol 3'te raporlandı)
104
+ }
105
+ }
106
+ }
107
+ if (brokenFrontmatter.length === 0) {
108
+ checks.push({
109
+ name: 'Agent frontmatter',
110
+ status: 'ok',
111
+ detail: 'Tüm agent dosyalarının frontmatter\'ı geçerli',
112
+ });
113
+ } else {
114
+ checks.push({
115
+ name: 'Agent frontmatter',
116
+ status: 'error',
117
+ detail: `${brokenFrontmatter.length} dosyada frontmatter bozuk: ${brokenFrontmatter.join(', ')}`,
118
+ });
119
+ }
120
+
121
+ // ── Kontrol 5: copilot-instructions.md mevcut ve marker'lar sağlam mı ──
122
+ const instructionsPath = path.join(cwd, TARGET_INSTRUCTIONS);
123
+ if (!fs.existsSync(instructionsPath)) {
124
+ checks.push({
125
+ name: 'copilot-instructions.md',
126
+ status: 'error',
127
+ detail: 'Dosya bulunamadı',
128
+ });
129
+ } else {
130
+ try {
131
+ const content = fs.readFileSync(instructionsPath, 'utf8');
132
+ const startIdx = content.indexOf(MARKER_START);
133
+ const endIdx = content.indexOf(MARKER_END);
134
+
135
+ if (startIdx === -1 || endIdx === -1) {
136
+ checks.push({
137
+ name: 'copilot-instructions.md',
138
+ status: 'warn',
139
+ detail: 'Marker\'lar eksik',
140
+ });
141
+ } else if (startIdx >= endIdx) {
142
+ checks.push({
143
+ name: 'copilot-instructions.md',
144
+ status: 'warn',
145
+ detail: 'Marker sırası bozuk',
146
+ });
147
+ } else {
148
+ checks.push({
149
+ name: 'copilot-instructions.md',
150
+ status: 'ok',
151
+ detail: 'copilot-instructions.md sağlam',
152
+ });
153
+ }
154
+ } catch {
155
+ checks.push({
156
+ name: 'copilot-instructions.md',
157
+ status: 'error',
158
+ detail: 'Dosya okunamadı',
159
+ });
160
+ }
161
+ }
162
+
163
+ // ── Kontrol 6: .blink/ scaffold mevcut mi ──
164
+ const blinkDir = path.join(cwd, TARGET_BLINK_DIR);
165
+ const scaffoldKeys = Object.keys(SCAFFOLD_FILES);
166
+ const missingScaffold = [];
167
+ if (!fs.existsSync(blinkDir)) {
168
+ missingScaffold.push(...scaffoldKeys);
169
+ } else {
170
+ for (const file of scaffoldKeys) {
171
+ if (!fs.existsSync(path.join(blinkDir, file))) {
172
+ missingScaffold.push(file);
173
+ }
174
+ }
175
+ }
176
+ const scaffoldFound = scaffoldKeys.length - missingScaffold.length;
177
+ const scaffoldTotal = scaffoldKeys.length;
178
+ if (missingScaffold.length === 0) {
179
+ checks.push({
180
+ name: '.blink/ scaffold',
181
+ status: 'ok',
182
+ detail: `.blink/ scaffold tam (${scaffoldTotal}/${scaffoldTotal})`,
183
+ });
184
+ } else {
185
+ checks.push({
186
+ name: '.blink/ scaffold',
187
+ status: 'warn',
188
+ detail: `${missingScaffold.length}/${scaffoldTotal} dosya eksik`,
189
+ });
190
+ }
191
+
192
+ // ── Kontrol 7: Handoff hedefleri tutarlı mı ──
193
+ const brokenHandoffs = [];
194
+ if (agentsDirExists) {
195
+ for (const agent of EXPECTED_AGENTS) {
196
+ const filePath = path.join(agentsDir, agent);
197
+ try {
198
+ const content = fs.readFileSync(filePath, 'utf8');
199
+ const targets = extractHandoffTargets(content);
200
+ for (const target of targets) {
201
+ const targetFile = `${target}.agent.md`;
202
+ if (!fs.existsSync(path.join(agentsDir, targetFile))) {
203
+ const source = agent.replace('.agent.md', '');
204
+ const entry = `blink.dev.${source} → ${targetFile} bulunamadı`;
205
+ if (!brokenHandoffs.includes(entry)) {
206
+ brokenHandoffs.push(entry);
207
+ }
208
+ }
209
+ }
210
+ } catch {
211
+ // Dosya okunamadıysa handoff kontrolü atla
212
+ }
213
+ }
214
+ }
215
+ if (brokenHandoffs.length === 0) {
216
+ checks.push({
217
+ name: 'Handoff hedefleri',
218
+ status: 'ok',
219
+ detail: 'Tüm handoff hedefleri mevcut',
220
+ });
221
+ } else {
222
+ checks.push({
223
+ name: 'Handoff hedefleri',
224
+ status: 'error',
225
+ detail: `${brokenHandoffs.length} kırık handoff: ${brokenHandoffs.join(', ')}`,
226
+ });
227
+ }
228
+
229
+ // ── Çıktı ──
230
+ const icons = { ok: '✅', warn: '⚠️ ', error: '❌' };
231
+ const lines = ['blink-dev sağlık raporu', '═══════════════════════', ''];
232
+
233
+ for (const check of checks) {
234
+ lines.push(`${icons[check.status]} ${check.detail}`);
235
+ }
236
+
237
+ const okCount = checks.filter((c) => c.status === 'ok').length;
238
+ const warnCount = checks.filter((c) => c.status === 'warn').length;
239
+ const errorCount = checks.filter((c) => c.status === 'error').length;
240
+
241
+ lines.push('');
242
+ lines.push(`Sonuç: ${okCount} başarılı, ${warnCount} uyarı, ${errorCount} hata`);
243
+
244
+ console.log(lines.join('\n'));
245
+
246
+ if (errorCount > 0) {
247
+ process.exit(1);
248
+ }
249
+ }
250
+
251
+ module.exports = doctor;
@@ -0,0 +1,184 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const os = require('node:os');
5
+ const path = require('node:path');
6
+ const zlib = require('node:zlib');
7
+ const { Readable } = require('node:stream');
8
+ const { pipeline } = require('node:stream/promises');
9
+ const tar = require('tar');
10
+
11
+ const { decrypt } = require('../crypto');
12
+ const {
13
+ installFiles,
14
+ mergeCopilotInstructions,
15
+ createScaffold,
16
+ isInitialized,
17
+ writeVersion,
18
+ } = require('../installer');
19
+ const {
20
+ BUNDLE_PATH,
21
+ TARGET_AGENTS_DIR,
22
+ TARGET_PROMPTS_DIR,
23
+ } = require('../constants');
24
+
25
+ /**
26
+ * Tarball buffer'ından dosya haritası çıkarır.
27
+ * @param {Buffer} tarBuffer - Gunzip edilmiş .tar.gz buffer
28
+ * @returns {Promise<{ fileMap: Map<string, Buffer>, copilotInstructions: string | null }>}
29
+ */
30
+ async function extractFileMap(tarBuffer) {
31
+ const fileMap = new Map();
32
+ let copilotInstructions = null;
33
+
34
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'blink-dev-'));
35
+ const tmpTarGz = path.join(tmpDir, 'bundle.tar.gz');
36
+
37
+ try {
38
+ // 1. Buffer'ı geçici dosyaya yaz
39
+ fs.writeFileSync(tmpTarGz, tarBuffer);
40
+
41
+ // 2. Geçici dizine extract et
42
+ const extractDir = path.join(tmpDir, 'extracted');
43
+ fs.mkdirSync(extractDir, { recursive: true });
44
+
45
+ await tar.x({
46
+ file: tmpTarGz,
47
+ cwd: extractDir,
48
+ });
49
+
50
+ // 3. Extract edilen dosyaları oku ve fileMap'e ekle
51
+ function walkDir(dir, prefix) {
52
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
53
+ for (const entry of entries) {
54
+ const fullPath = path.join(dir, entry.name);
55
+ const relPath = prefix ? path.join(prefix, entry.name) : entry.name;
56
+
57
+ if (entry.isDirectory()) {
58
+ walkDir(fullPath, relPath);
59
+ } else if (entry.isFile()) {
60
+ const content = fs.readFileSync(fullPath);
61
+ const mapped = mapFilePath(relPath);
62
+
63
+ if (mapped === null) {
64
+ // copilot-instructions.md — ayrı tut
65
+ copilotInstructions = content.toString('utf8');
66
+ } else if (mapped) {
67
+ fileMap.set(mapped, content);
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ walkDir(extractDir, '');
74
+ } finally {
75
+ // Geçici dosyaları temizle
76
+ fs.rmSync(tmpDir, { recursive: true, force: true });
77
+ }
78
+
79
+ return { fileMap, copilotInstructions };
80
+ }
81
+
82
+ /**
83
+ * Tarball içi yolu hedef yola dönüştürür.
84
+ * @param {string} entryPath - Tarball içi dosya yolu
85
+ * @returns {string | null} - null = copilot-instructions.md (ayrı merge)
86
+ */
87
+ function mapFilePath(entryPath) {
88
+ // Normalize separators
89
+ const normalized = entryPath.split(path.sep).join('/');
90
+
91
+ if (normalized === 'copilot-instructions.md') {
92
+ return null;
93
+ }
94
+
95
+ if (normalized.startsWith('agents/')) {
96
+ return path.join(TARGET_AGENTS_DIR, normalized.slice('agents/'.length));
97
+ }
98
+
99
+ if (normalized.startsWith('prompts/')) {
100
+ return path.join(TARGET_PROMPTS_DIR, normalized.slice('prompts/'.length));
101
+ }
102
+
103
+ // Diğer dosyalar olduğu gibi kalsın
104
+ return normalized;
105
+ }
106
+
107
+ /**
108
+ * blink-dev init --key=SIFRE komutu handler'ı.
109
+ * @param {{ key: string, force?: boolean, dryRun?: boolean }} options
110
+ */
111
+ async function init({ key, force = false, dryRun = false }) {
112
+ const cwd = process.cwd();
113
+
114
+ // 1. Kurulum kontrolü
115
+ if (isInitialized(cwd) && !force) {
116
+ console.error('Bu proje zaten blink-dev ile kurulmuş. --force ile yeniden kurabilirsiniz.');
117
+ process.exit(1);
118
+ }
119
+
120
+ // 2. Bundle oku
121
+ let encBuffer;
122
+ try {
123
+ encBuffer = fs.readFileSync(BUNDLE_PATH);
124
+ } catch (_) {
125
+ console.error('Bundle dosyası bulunamadı: ' + BUNDLE_PATH);
126
+ process.exit(1);
127
+ }
128
+
129
+ // 3. Decrypt
130
+ let tarBuffer;
131
+ try {
132
+ tarBuffer = decrypt(encBuffer, key);
133
+ } catch (_) {
134
+ console.error('Hata: Geçersiz anahtar.');
135
+ process.exit(1);
136
+ }
137
+
138
+ // 4. Extract
139
+ const { fileMap, copilotInstructions } = await extractFileMap(tarBuffer);
140
+
141
+ // 5. Dry-run kontrolü
142
+ if (dryRun) {
143
+ const result = installFiles(fileMap, cwd, { dryRun: true });
144
+ if (result.installed.length > 0) {
145
+ console.log('Kurulacak dosyalar:');
146
+ for (const f of result.installed) {
147
+ console.log(' ' + f);
148
+ }
149
+ }
150
+ if (result.skipped.length > 0) {
151
+ console.log('Atlanacak dosyalar:');
152
+ for (const f of result.skipped) {
153
+ console.log(' ' + f);
154
+ }
155
+ }
156
+ return;
157
+ }
158
+
159
+ // 6. Dosyaları yaz
160
+ const { installed, skipped } = installFiles(fileMap, cwd, { force });
161
+
162
+ // 7. Copilot instructions merge
163
+ if (copilotInstructions) {
164
+ mergeCopilotInstructions(copilotInstructions, cwd);
165
+ }
166
+
167
+ // 8. Scaffold oluştur
168
+ const scaffold = createScaffold(cwd);
169
+
170
+ // 9. Versiyon yaz
171
+ writeVersion(cwd, require('../../package.json').version);
172
+
173
+ // 10. Başarı mesajı
174
+ console.log('');
175
+ console.log('✅ blink-dev başarıyla kuruldu!');
176
+ console.log('');
177
+ console.log('📁 Kurulan dosyalar: ' + installed.length);
178
+ console.log('⏩ Atlanan dosyalar: ' + skipped.length);
179
+ console.log('📝 .blink/ scaffold: ' + scaffold.created.length + ' dosya oluşturuldu');
180
+ console.log('');
181
+ console.log('Sonraki adım: VS Code Agent Mode\'u açın ve ajanları kullanmaya başlayın.');
182
+ }
183
+
184
+ module.exports = init;