@el-j/magic-agent-helix 4.0.0-beta.6 โ†’ 4.0.0-beta.8

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/dist/cli.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import * as p from "node:fs";
3
3
  import { realpathSync as te, readFileSync as oe } from "node:fs";
4
- import * as d from "node:path";
4
+ import * as f from "node:path";
5
5
  import { resolve as ne, dirname as se, join as ie } from "node:path";
6
6
  import { fileURLToPath as U } from "node:url";
7
7
  import { Command as re } from "commander";
8
8
  import t from "picocolors";
9
- import { loadUserConfig as O, mergeConfigs as L, PluginRegistry as C, getFormatter as Y, validateInstructions as ae } from "@el-j/magic-helix-core";
9
+ import { loadUserConfig as O, mergeConfigs as M, PluginRegistry as C, getFormatter as K, validateInstructions as ae } from "@el-j/magic-helix-core";
10
10
  import W from "inquirer";
11
11
  import j from "ora";
12
12
  import q from "gradient-string";
@@ -14,13 +14,13 @@ import { glob as ce } from "glob";
14
14
  async function le() {
15
15
  console.log(t.cyan(`๐Ÿงน Cleaning generated instruction files...
16
16
  `));
17
- const e = j("Loading configuration...").start(), n = O(), s = L(n);
17
+ const e = j("Loading configuration...").start(), n = O(), s = M(n);
18
18
  e.succeed("Configuration loaded.");
19
- const r = d.resolve(
19
+ const a = f.resolve(
20
20
  process.cwd(),
21
21
  s.outputDirectory
22
22
  );
23
- if (!p.existsSync(r)) {
23
+ if (!p.existsSync(a)) {
24
24
  console.log(
25
25
  t.yellow(
26
26
  `โš ๏ธ Output directory ${s.outputDirectory} does not exist. Nothing to clean.`
@@ -28,16 +28,16 @@ async function le() {
28
28
  );
29
29
  return;
30
30
  }
31
- const a = p.readdirSync(r).filter((g) => g.endsWith(".md"));
32
- if (a.length === 0) {
31
+ const i = p.readdirSync(a).filter((g) => g.endsWith(".md"));
32
+ if (i.length === 0) {
33
33
  console.log(t.gray("No instruction files found. Nothing to clean."));
34
34
  return;
35
35
  }
36
36
  console.log(
37
- t.yellow(`Found ${a.length} instruction file(s) to delete:
37
+ t.yellow(`Found ${i.length} instruction file(s) to delete:
38
38
  `)
39
39
  );
40
- for (const g of a)
40
+ for (const g of i)
41
41
  console.log(t.gray(` - ${g}`));
42
42
  console.log();
43
43
  const { confirm: o } = await W.prompt([
@@ -45,7 +45,7 @@ async function le() {
45
45
  type: "confirm",
46
46
  name: "confirm",
47
47
  message: t.red(
48
- `Are you sure you want to delete all ${a.length} file(s)?`
48
+ `Are you sure you want to delete all ${i.length} file(s)?`
49
49
  ),
50
50
  default: !1
51
51
  }
@@ -54,21 +54,21 @@ async function le() {
54
54
  console.log(t.yellow("Clean cancelled."));
55
55
  return;
56
56
  }
57
- const c = j("Deleting files...").start();
58
- let i = 0, l = 0;
59
- for (const g of a)
57
+ const r = j("Deleting files...").start();
58
+ let c = 0, l = 0;
59
+ for (const g of i)
60
60
  try {
61
- p.unlinkSync(d.join(r, g)), i++;
61
+ p.unlinkSync(f.join(a, g)), c++;
62
62
  } catch (u) {
63
63
  console.error(
64
64
  t.red(` โŒ Error deleting ${g}: ${u.message}`)
65
65
  ), l++;
66
66
  }
67
- l === 0 ? c.succeed(
68
- t.green(`โœ… Successfully deleted ${i} file(s).`)
69
- ) : c.warn(
67
+ l === 0 ? r.succeed(
68
+ t.green(`โœ… Successfully deleted ${c} file(s).`)
69
+ ) : r.warn(
70
70
  t.yellow(
71
- `โš ๏ธ Deleted ${i} file(s), ${l} error(s) occurred.`
71
+ `โš ๏ธ Deleted ${c} file(s), ${l} error(s) occurred.`
72
72
  )
73
73
  );
74
74
  }
@@ -94,10 +94,10 @@ const _ = "magic-helix.config.json", I = "ai_templates", ge = {
94
94
  async function ue() {
95
95
  const e = j(
96
96
  t.bold("Initializing Magic Helix for custom rules...")
97
- ).start(), n = d.resolve(process.cwd(), _), s = d.resolve(process.cwd(), I);
97
+ ).start(), n = f.resolve(process.cwd(), _), s = f.resolve(process.cwd(), I);
98
98
  if (p.existsSync(n)) {
99
99
  e.stop();
100
- const { overwrite: a } = await W.prompt([
100
+ const { overwrite: i } = await W.prompt([
101
101
  {
102
102
  type: "confirm",
103
103
  name: "overwrite",
@@ -105,7 +105,7 @@ async function ue() {
105
105
  default: !1
106
106
  }
107
107
  ]);
108
- if (!a) {
108
+ if (!i) {
109
109
  e.warn(t.yellow("Operation cancelled."));
110
110
  return;
111
111
  }
@@ -119,18 +119,18 @@ async function ue() {
119
119
  ), e.succeed(
120
120
  t.green(`Created minimal config file: ${t.bold(_)}`)
121
121
  );
122
- } catch (a) {
123
- e.fail(t.red(`Error writing config file: ${a.message}`));
122
+ } catch (i) {
123
+ e.fail(t.red(`Error writing config file: ${i.message}`));
124
124
  return;
125
125
  }
126
126
  e.start("Creating templates directory..."), p.existsSync(s) || p.mkdirSync(s, { recursive: !0 });
127
- const r = d.resolve(s, "my-custom-rule.md");
128
- p.existsSync(r) ? e.succeed(
127
+ const a = f.resolve(s, "my-custom-rule.md");
128
+ p.existsSync(a) ? e.succeed(
129
129
  t.green(
130
130
  `Templates directory ${t.bold(I)} already exists.`
131
131
  )
132
132
  ) : (p.writeFileSync(
133
- r,
133
+ a,
134
134
  `# My Team's Custom Rule
135
135
  - This rule is specific to our "domain-my-rules" tag.
136
136
  - ALWAYS follow this important pattern.
@@ -157,20 +157,20 @@ Next steps:`)), console.log(
157
157
  async function de() {
158
158
  console.log(t.cyan(`๐Ÿ“‹ Listing project information...
159
159
  `));
160
- const e = j("Loading configuration...").start(), n = O(), s = L(n);
160
+ const e = j("Loading configuration...").start(), n = O(), s = M(n);
161
161
  e.succeed("Configuration loaded.");
162
- const { dependencyTagMap: r, configFileTagMap: a, fileGlobTagMap: o, tagTemplateMap: c } = s, i = j("Scanning for projects...").start(), l = await fe();
162
+ const { dependencyTagMap: a, configFileTagMap: i, fileGlobTagMap: o, tagTemplateMap: r } = s, c = j("Scanning for projects...").start(), l = await fe();
163
163
  if (l.length === 0) {
164
- i.warn(t.yellow("No projects found."));
164
+ c.warn(t.yellow("No projects found."));
165
165
  return;
166
166
  }
167
- i.succeed(`Found ${l.length} projects.`);
167
+ c.succeed(`Found ${l.length} projects.`);
168
168
  const g = j("Analyzing projects...").start();
169
169
  for (const u of l)
170
170
  await pe(
171
171
  u,
172
- r,
173
172
  a,
173
+ i,
174
174
  o
175
175
  );
176
176
  g.succeed(`Analysis complete.
@@ -183,7 +183,7 @@ async function de() {
183
183
  console.log(t.green(` Tags: ${[...u.tags].join(", ")}`));
184
184
  const h = [];
185
185
  for (const w of u.tags) {
186
- const m = c[w];
186
+ const m = r[w];
187
187
  if (m)
188
188
  for (const v of m)
189
189
  h.push(`${u.name}.${v.suffix}`);
@@ -198,25 +198,25 @@ async function de() {
198
198
  async function fe() {
199
199
  const e = [], n = process.cwd(), s = C.getInstance();
200
200
  await s.initialize();
201
- const a = (await s.detectAllProjects(n)).map((o) => o.metadata);
202
- if (a.length === 0)
201
+ const i = (await s.detectAllProjects(n)).map((o) => o.metadata);
202
+ if (i.length === 0)
203
203
  return [];
204
- for (const o of a) {
205
- const c = d.relative(n, o.projectPath);
204
+ for (const o of i) {
205
+ const r = f.relative(n, o.projectPath);
206
206
  e.push({
207
- name: o.name || d.basename(o.projectPath),
208
- path: c || ".",
207
+ name: o.name || f.basename(o.projectPath),
208
+ path: r || ".",
209
209
  tags: /* @__PURE__ */ new Set()
210
210
  });
211
211
  }
212
212
  return e;
213
213
  }
214
- async function pe(e, n, s, r) {
215
- const a = d.resolve(process.cwd(), e.path);
214
+ async function pe(e, n, s, a) {
215
+ const i = f.resolve(process.cwd(), e.path);
216
216
  try {
217
- const i = (await C.getInstance().detectAllProjects(a)).map((l) => l.metadata);
218
- if (i.length > 0) {
219
- const l = i[0];
217
+ const c = (await C.getInstance().detectAllProjects(i)).map((l) => l.metadata);
218
+ if (c.length > 0) {
219
+ const l = c[0];
220
220
  if (l.tags?.length)
221
221
  for (const g of l.tags)
222
222
  e.tags.add(g);
@@ -230,20 +230,20 @@ async function pe(e, n, s, r) {
230
230
  }
231
231
  try {
232
232
  for (const o in s) {
233
- const c = s[o], i = d.join(a, o);
234
- p.existsSync(i) && e.tags.add(c);
233
+ const r = s[o], c = f.join(i, o);
234
+ p.existsSync(c) && e.tags.add(r);
235
235
  }
236
236
  } catch {
237
237
  }
238
238
  try {
239
239
  const { glob: o } = await import("glob");
240
- for (const c in r) {
241
- const i = r[c];
242
- (await o(c, {
243
- cwd: a,
240
+ for (const r in a) {
241
+ const c = a[r];
242
+ (await o(r, {
243
+ cwd: i,
244
244
  nodir: !0,
245
245
  dot: !0
246
- })).length > 0 && e.tags.add(i);
246
+ })).length > 0 && e.tags.add(c);
247
247
  }
248
248
  } catch {
249
249
  }
@@ -253,22 +253,22 @@ async function me(e = {}) {
253
253
  try {
254
254
  const n = C.getInstance();
255
255
  await n.initialize({ verbose: e.verbose });
256
- const s = await n.getAllPlugins(), r = n.getStatistics();
256
+ const s = await n.getAllPlugins(), a = n.getStatistics();
257
257
  if (s.length === 0) {
258
258
  console.log(t.yellow("โš ๏ธ No plugins loaded"));
259
259
  return;
260
260
  }
261
261
  console.log(t.green(`โœ… ${s.length} plugin(s) loaded successfully`)), console.log();
262
- const a = s.sort((o, c) => c.priority - o.priority);
262
+ const i = s.sort((o, r) => r.priority - o.priority);
263
263
  console.log(t.bold("Available Language Plugins:")), console.log("โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€");
264
- for (const o of a) {
265
- const c = o.priority >= 90 ? "green" : o.priority >= 70 ? "yellow" : "cyan";
264
+ for (const o of i) {
265
+ const r = o.priority >= 90 ? "green" : o.priority >= 70 ? "yellow" : "cyan";
266
266
  if (console.log(
267
- `${t.bold(o.displayName)} (${t[c](`priority: ${o.priority}`)}) v${o.version}`
267
+ `${t.bold(o.displayName)} (${t[r](`priority: ${o.priority}`)}) v${o.version}`
268
268
  ), e.verbose) {
269
- const i = o.getTemplates();
270
- i.length > 0 && console.log(
271
- ` ๐Ÿ“ Templates: ${i.map((g) => g.name).join(", ")}`
269
+ const c = o.getTemplates();
270
+ c.length > 0 && console.log(
271
+ ` ๐Ÿ“ Templates: ${c.map((g) => g.name).join(", ")}`
272
272
  );
273
273
  const l = o.getDependencyTagMap?.();
274
274
  l && Object.keys(l).length > 0 && console.log(
@@ -276,11 +276,11 @@ async function me(e = {}) {
276
276
  ), console.log();
277
277
  }
278
278
  }
279
- if (e.verbose || (console.log(), console.log(t.dim("๐Ÿ’ก Use --verbose for detailed plugin information"))), console.log(), console.log(t.bold("System Statistics:")), console.log("โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€"), console.log(`๐Ÿ“Š Total plugins: ${r.totalLoaded}`), console.log(`โšก Average load time: ${r.averageLoadTime.toFixed(1)}ms`), console.log(`โŒ Load errors: ${r.totalErrors}`), r.totalErrors > 0 && e.verbose) {
279
+ if (e.verbose || (console.log(), console.log(t.dim("๐Ÿ’ก Use --verbose for detailed plugin information"))), console.log(), console.log(t.bold("System Statistics:")), console.log("โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€"), console.log(`๐Ÿ“Š Total plugins: ${a.totalLoaded}`), console.log(`โšก Average load time: ${a.averageLoadTime.toFixed(1)}ms`), console.log(`โŒ Load errors: ${a.totalErrors}`), a.totalErrors > 0 && e.verbose) {
280
280
  const o = n.getLoadErrors();
281
281
  console.log(), console.log(t.red("Load Errors:")), console.log("โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€");
282
- for (const c of o)
283
- console.log(`โŒ ${c.source.identifier}: ${c.error.message}`);
282
+ for (const r of o)
283
+ console.log(`โŒ ${r.source.identifier}: ${r.error.message}`);
284
284
  }
285
285
  } catch (n) {
286
286
  console.error(
@@ -432,21 +432,21 @@ const ye = {
432
432
  function he(e) {
433
433
  return ye[e]?.extensions || [];
434
434
  }
435
- function K(e, n, s) {
436
- const r = /* @__PURE__ */ new Set();
437
- for (const c of n) {
438
- const i = he(c);
439
- for (const l of i)
440
- r.add(l);
435
+ function Y(e, n, s) {
436
+ const a = /* @__PURE__ */ new Set();
437
+ for (const r of n) {
438
+ const c = he(r);
439
+ for (const l of c)
440
+ a.add(l);
441
441
  }
442
- if (r.size === 0)
442
+ if (a.size === 0)
443
443
  return `${e}/src/**/*.{ts,js,vue,tsx,jsx}`;
444
- const a = Array.from(r).join(",");
445
- let o = `${e}/src/**/*.{${a}}`;
444
+ const i = Array.from(a).join(",");
445
+ let o = `${e}/src/**/*.{${i}}`;
446
446
  if (s) {
447
- const c = s.split(",").map((i) => i.trim());
448
- for (const i of c)
449
- i.endsWith("/**") ? o += ` !(${e}/src/${i})` : i.includes("*") ? o += ` !(${e}/src/${i})` : o += ` !(${e}/src/${i})`;
447
+ const r = s.split(",").map((c) => c.trim());
448
+ for (const c of r)
449
+ c.endsWith("/**") ? o += ` !(${e}/src/${c})` : c.includes("*") ? o += ` !(${e}/src/${c})` : o += ` !(${e}/src/${c})`;
450
450
  }
451
451
  return o;
452
452
  }
@@ -458,19 +458,19 @@ function $(e, n) {
458
458
  }
459
459
  async function we(e = {}) {
460
460
  Q(e);
461
- const n = j("Loading configurations...").start(), s = O(e.config), r = L(s);
462
- e.target && (r.target = e.target), n.succeed("Configuration loaded.");
463
- const { dependencyTagMap: a, configFileTagMap: o, fileGlobTagMap: c, tagTemplateMap: i } = r, l = d.resolve(
461
+ const n = j("Loading configurations...").start(), s = O(e.config), a = M(s);
462
+ e.target && (a.target = e.target), n.succeed("Configuration loaded.");
463
+ const { dependencyTagMap: i, configFileTagMap: o, fileGlobTagMap: r, tagTemplateMap: c } = a, l = f.resolve(
464
464
  process.cwd(),
465
- r.templateDirectory
466
- ), g = d.resolve(
465
+ a.templateDirectory
466
+ ), g = f.resolve(
467
467
  process.cwd(),
468
- r.outputDirectory
469
- ), u = Y(r.target);
468
+ a.outputDirectory
469
+ ), u = K(a.target);
470
470
  if (!p.existsSync(g)) {
471
471
  console.log(
472
472
  t.yellow(
473
- `โš ๏ธ Output directory ${r.outputDirectory} does not exist.`
473
+ `โš ๏ธ Output directory ${a.outputDirectory} does not exist.`
474
474
  )
475
475
  ), console.log(
476
476
  t.gray(" Run 'magic-helix run' first to generate instruction files.")
@@ -492,13 +492,13 @@ async function we(e = {}) {
492
492
  for (const y of w)
493
493
  await je(
494
494
  y,
495
- a,
495
+ i,
496
496
  o,
497
- c
497
+ r
498
498
  ), v += y.tags.size;
499
499
  m.succeed(`Project analysis complete. Found ${v} tags.`), console.log(
500
500
  t.cyan(`
501
- Refreshing instruction files in ${r.outputDirectory}...`)
501
+ Refreshing instruction files in ${a.outputDirectory}...`)
502
502
  );
503
503
  let D = 0, N = 0;
504
504
  for (const y of w) {
@@ -507,25 +507,25 @@ Refreshing instruction files in ${r.outputDirectory}...`)
507
507
  continue;
508
508
  }
509
509
  console.log(t.bold(` Processing: ${y.name}`)), console.log(t.gray(` Tags: ${[...y.tags].join(", ")}`));
510
- const z = K(y.path, y.tags);
510
+ const z = Y(y.path, y.tags);
511
511
  for (const S of y.tags) {
512
- const M = i[S];
513
- if (M)
514
- for (const P of M) {
515
- const T = `${y.name}.${P.suffix}`, F = d.join(g, T);
512
+ const L = c[S];
513
+ if (L)
514
+ for (const P of L) {
515
+ const T = `${y.name}.${P.suffix}`, F = f.join(g, T);
516
516
  if (!p.existsSync(F)) {
517
517
  console.log(
518
518
  t.yellow(` โš ๏ธ File not found, skipping: ${T}`)
519
519
  );
520
520
  continue;
521
521
  }
522
- const f = xe(l, P.template), x = "Custom";
523
- if (!f) {
522
+ const d = xe(l, P.template), x = "Custom";
523
+ if (!d) {
524
524
  console.warn(t.yellow(` โš ๏ธ Template not found: ${P.template}`));
525
525
  continue;
526
526
  }
527
527
  const R = u.getFrontmatter(z, y.name), k = u.format(
528
- f,
528
+ d,
529
529
  z,
530
530
  y.name
531
531
  ), b = `${R}
@@ -544,25 +544,25 @@ ${k}`;
544
544
  async function $e() {
545
545
  const e = [], n = process.cwd(), s = C.getInstance();
546
546
  await s.initialize();
547
- const a = (await s.detectAllProjects(n)).map((o) => o.metadata);
548
- if (a.length === 0)
547
+ const i = (await s.detectAllProjects(n)).map((o) => o.metadata);
548
+ if (i.length === 0)
549
549
  return [];
550
- for (const o of a) {
551
- const c = d.relative(n, o.projectPath);
550
+ for (const o of i) {
551
+ const r = f.relative(n, o.projectPath);
552
552
  e.push({
553
- name: o.name || d.basename(o.projectPath),
554
- path: c || ".",
553
+ name: o.name || f.basename(o.projectPath),
554
+ path: r || ".",
555
555
  tags: /* @__PURE__ */ new Set()
556
556
  });
557
557
  }
558
558
  return e;
559
559
  }
560
- async function je(e, n, s, r) {
561
- const a = d.resolve(process.cwd(), e.path);
560
+ async function je(e, n, s, a) {
561
+ const i = f.resolve(process.cwd(), e.path);
562
562
  try {
563
- const i = (await C.getInstance().detectAllProjects(a)).map((l) => l.metadata);
564
- if (i.length > 0) {
565
- const l = i[0];
563
+ const c = (await C.getInstance().detectAllProjects(i)).map((l) => l.metadata);
564
+ if (c.length > 0) {
565
+ const l = c[0];
566
566
  if (l.tags?.length)
567
567
  for (const g of l.tags)
568
568
  e.tags.add(g);
@@ -581,8 +581,8 @@ async function je(e, n, s, r) {
581
581
  }
582
582
  try {
583
583
  for (const o in s) {
584
- const c = s[o], i = d.join(a, o);
585
- p.existsSync(i) && e.tags.add(c);
584
+ const r = s[o], c = f.join(i, o);
585
+ p.existsSync(c) && e.tags.add(r);
586
586
  }
587
587
  } catch (o) {
588
588
  console.warn(
@@ -593,13 +593,13 @@ async function je(e, n, s, r) {
593
593
  }
594
594
  try {
595
595
  const { glob: o } = await import("glob");
596
- for (const c in r) {
597
- const i = r[c];
598
- (await o(c, {
599
- cwd: a,
596
+ for (const r in a) {
597
+ const c = a[r];
598
+ (await o(r, {
599
+ cwd: i,
600
600
  nodir: !0,
601
601
  dot: !0
602
- })).length > 0 && e.tags.add(i);
602
+ })).length > 0 && e.tags.add(c);
603
603
  }
604
604
  } catch (o) {
605
605
  console.warn(
@@ -610,7 +610,7 @@ async function je(e, n, s, r) {
610
610
  }
611
611
  }
612
612
  function xe(e, n) {
613
- const s = d.join(e, n);
613
+ const s = f.join(e, n);
614
614
  try {
615
615
  return p.readFileSync(s, "utf-8");
616
616
  } catch {
@@ -682,15 +682,15 @@ async function J(e = {}) {
682
682
  q.pastel.multiline("๐Ÿค– Running AI Convention Aligner...")
683
683
  ), n.dryRun && $("normal", s) && console.log(t.yellow(`๐Ÿ” DRY RUN MODE - No files will be written
684
684
  `));
685
- const r = j("Loading configurations...").start(), a = O(n.config), o = L(a);
686
- n.outputDir && (o.outputDirectory = n.outputDir), n.target && (o.target = n.target), r.succeed("Configuration loaded.");
687
- const { dependencyTagMap: c, configFileTagMap: i, fileGlobTagMap: l, tagTemplateMap: g } = o, u = d.resolve(
685
+ const a = j("Loading configurations...").start(), i = O(n.config), o = M(i);
686
+ n.outputDir && (o.outputDirectory = n.outputDir), n.target && (o.target = n.target), a.succeed("Configuration loaded.");
687
+ const { dependencyTagMap: r, configFileTagMap: c, fileGlobTagMap: l, tagTemplateMap: g } = o, u = f.resolve(
688
688
  process.cwd(),
689
689
  o.templateDirectory
690
- ), h = d.resolve(
690
+ ), h = f.resolve(
691
691
  process.cwd(),
692
692
  o.outputDirectory
693
- ), w = Y(o.target), m = j("Scanning for projects...").start(), v = await Pe();
693
+ ), w = K(o.target), m = j("Scanning for projects...").start(), v = await Pe();
694
694
  if (v.length === 0) {
695
695
  m.warn(
696
696
  t.yellow(
@@ -715,25 +715,25 @@ Supported project types: Node.js, Python, Go, Rust, Java, Ruby, PHP, C#, Swift,
715
715
  m.succeed(`Found ${v.length} projects.`);
716
716
  const D = j("Analyzing project tags...").start();
717
717
  let N = 0;
718
- for (const f of v) {
719
- if (n.project && f.name !== n.project) {
720
- $("verbose", s) && console.log(t.gray(`Skipping ${f.name} (not target project)`));
718
+ for (const d of v) {
719
+ if (n.project && d.name !== n.project) {
720
+ $("verbose", s) && console.log(t.gray(`Skipping ${d.name} (not target project)`));
721
721
  continue;
722
722
  }
723
723
  await Te(
724
- f,
724
+ d,
725
+ r,
725
726
  c,
726
- i,
727
727
  l
728
- ), N += f.tags.size;
728
+ ), N += d.tags.size;
729
729
  }
730
730
  D.succeed(`Project analysis complete. Found ${N} tags.`), n.dryRun ? $("verbose", s) && console.log(t.gray(`Would ensure directory: ${h}`)) : be(h);
731
731
  let y = g;
732
732
  if (n.template) {
733
- const f = n.template.split(",").map((x) => x.trim());
733
+ const d = n.template.split(",").map((x) => x.trim());
734
734
  y = {};
735
735
  for (const [x, R] of Object.entries(g)) {
736
- const k = R.filter((b) => f.some((A) => {
736
+ const k = R.filter((b) => d.some((A) => {
737
737
  if (A.includes("*")) {
738
738
  const E = new RegExp(A.replace(/\*/g, ".*"));
739
739
  return E.test(b.template) || E.test(x);
@@ -747,13 +747,13 @@ Supported project types: Node.js, Python, Go, Rust, Java, Ruby, PHP, C#, Swift,
747
747
  );
748
748
  }
749
749
  const z = await Se(), S = {};
750
- for (const [f, x] of Object.entries(y))
751
- S[f] = x.map((R) => ({
750
+ for (const [d, x] of Object.entries(y))
751
+ S[d] = x.map((R) => ({
752
752
  template: R.template,
753
753
  suffix: R.suffix
754
754
  }));
755
- for (const [f, x] of Object.entries(z))
756
- S[f] || (S[f] = []), S[f].push(...x);
755
+ for (const [d, x] of Object.entries(z))
756
+ S[d] || (S[d] = []), S[d].push(...x);
757
757
  $("verbose", s) && (console.log(t.gray(`
758
758
  --- Template Map Debug ---`)), console.log(
759
759
  t.gray(
@@ -777,22 +777,22 @@ Supported project types: Node.js, Python, Go, Rust, Java, Ruby, PHP, C#, Swift,
777
777
  t.cyan(`
778
778
  Generating instruction files in ${o.outputDirectory}...`)
779
779
  );
780
- const M = j("Generating instruction files...").start(), P = [];
780
+ const L = j("Generating instruction files...").start(), P = [];
781
781
  let T = 0, F = 0;
782
- for (const f of v) {
783
- if (n.project && f.name !== n.project)
782
+ for (const d of v) {
783
+ if (n.project && d.name !== n.project)
784
784
  continue;
785
- if (f.tags.size === 0) {
786
- $("normal", s) && console.log(t.gray(` Skipping: ${f.name} (No matching tags)`));
785
+ if (d.tags.size === 0) {
786
+ $("normal", s) && console.log(t.gray(` Skipping: ${d.name} (No matching tags)`));
787
787
  continue;
788
788
  }
789
- T++, $("normal", s) && console.log(t.bold(` Processing: ${f.name}`)), $("verbose", s) && console.log(t.gray(` Tags: ${[...f.tags].join(", ")}`));
790
- const x = K(
791
- f.path,
792
- f.tags,
789
+ T++, $("normal", s) && console.log(t.bold(` Processing: ${d.name}`)), $("verbose", s) && console.log(t.gray(` Tags: ${[...d.tags].join(", ")}`));
790
+ const x = Y(
791
+ d.path,
792
+ d.tags,
793
793
  n.exclude
794
794
  );
795
- for (const R of f.tags) {
795
+ for (const R of d.tags) {
796
796
  const k = S[R];
797
797
  if (k)
798
798
  for (const b of k) {
@@ -802,12 +802,12 @@ Generating instruction files in ${o.outputDirectory}...`)
802
802
  console.warn(t.yellow(` โš ๏ธ Template not found: ${b.template}`));
803
803
  continue;
804
804
  }
805
- const B = w.getFrontmatter(x, f.name), X = w.format(
805
+ const B = w.getFrontmatter(x, d.name), X = w.format(
806
806
  A,
807
807
  x,
808
- f.name
808
+ d.name
809
809
  ), Z = `${B}
810
- ${X}`, G = b.suffix, ee = d.join(h, G);
810
+ ${X}`, G = `${v.length > 1 ? `${d.name.replace(/[@/]/g, "-")}.` : ""}${b.suffix}`, ee = f.join(h, G);
811
811
  P.push(G), n.dryRun ? $("normal", s) && console.log(
812
812
  t.cyan(
813
813
  ` ๐Ÿ“ Would generate: ${t.bold(G)} (from ${E})`
@@ -820,7 +820,7 @@ ${X}`, G = b.suffix, ee = d.join(h, G);
820
820
  }
821
821
  }
822
822
  }
823
- M.succeed(
823
+ L.succeed(
824
824
  `Generated ${P.length} files from ${F} templates across ${T} projects`
825
825
  ), !n.dryRun && !n.skipPruning ? await Fe(h, P, n.force) : n.dryRun && $("verbose", s) && console.log(t.gray(`
826
826
  Would check for old files to prune...`)), $("normal", s) && (console.log(`
@@ -877,9 +877,9 @@ async function Se() {
877
877
  let n = [];
878
878
  try {
879
879
  n = await e.getAllPlugins();
880
- } catch (r) {
880
+ } catch (a) {
881
881
  console.warn(
882
- t.yellow(`โš ๏ธ Failed to get plugins: ${r.message}`)
882
+ t.yellow(`โš ๏ธ Failed to get plugins: ${a.message}`)
883
883
  ), console.warn(
884
884
  t.yellow(
885
885
  `โš ๏ธ Registry type: ${typeof e}, has getAllPlugins: ${typeof e?.getAllPlugins}`
@@ -888,35 +888,35 @@ async function Se() {
888
888
  }
889
889
  n.length === 0 && console.warn(t.yellow("โš ๏ธ No plugins loaded from registry!"));
890
890
  const s = {};
891
- for (const r of n) {
892
- let a = [];
891
+ for (const a of n) {
892
+ let i = [];
893
893
  try {
894
- const o = await r.getTemplates();
895
- a = Array.isArray(o) ? o : [];
894
+ const o = await a.getTemplates();
895
+ i = Array.isArray(o) ? o : [];
896
896
  } catch (o) {
897
897
  console.warn(
898
898
  t.yellow(
899
- `โš ๏ธ Plugin ${r.name} getTemplates failed: ${o.message}`
899
+ `โš ๏ธ Plugin ${a.name} getTemplates failed: ${o.message}`
900
900
  )
901
901
  );
902
902
  continue;
903
903
  }
904
- for (const o of a) {
905
- const i = `${o.name.replace(/^lang-/, "").replace(/-core$/, "")}.instructions.md`;
904
+ for (const o of i) {
905
+ const c = `${o.name.replace(/^lang-/, "").replace(/-core$/, "")}.instructions.md`;
906
906
  let l = null;
907
907
  try {
908
908
  l = typeof o.content == "function" ? await o.content() : o.content;
909
909
  } catch (g) {
910
910
  console.warn(
911
911
  t.yellow(
912
- `โš ๏ธ Plugin ${r.name} template ${o.name} failed to load: ${g.message}`
912
+ `โš ๏ธ Plugin ${a.name} template ${o.name} failed to load: ${g.message}`
913
913
  )
914
914
  );
915
915
  }
916
916
  for (const g of o.tags)
917
917
  s[g] || (s[g] = []), s[g].push({
918
- template: `plugin:${r.name}/${o.name}`,
919
- suffix: i,
918
+ template: `plugin:${a.name}/${o.name}`,
919
+ suffix: c,
920
920
  inlineContent: l ?? void 0
921
921
  });
922
922
  }
@@ -925,39 +925,51 @@ async function Se() {
925
925
  }
926
926
  async function Pe() {
927
927
  await H();
928
- const e = [], n = process.cwd(), r = await C.getInstance().detectAllProjects(n);
929
- if (r.length === 0)
928
+ const e = process.cwd(), s = await C.getInstance().detectAllProjects(e);
929
+ if (s.length === 0)
930
930
  return [];
931
- for (const a of r) {
932
- const o = d.relative(n, a.metadata.projectPath);
933
- e.push({
931
+ const a = /* @__PURE__ */ new Map();
932
+ for (const i of s) {
933
+ const r = f.relative(e, i.metadata.projectPath) || ".";
934
+ a.has(r) || a.set(r, {
934
935
  name: Ce(
935
- a.metadata.name || d.basename(a.metadata.projectPath)
936
+ i.metadata.name || f.basename(i.metadata.projectPath)
936
937
  ),
937
- path: o || ".",
938
- tags: /* @__PURE__ */ new Set()
938
+ path: r,
939
+ tags: /* @__PURE__ */ new Set(),
940
+ allMetadata: []
939
941
  });
942
+ const c = a.get(r);
943
+ if (c.allMetadata.push(i.metadata), i.metadata.tags?.length)
944
+ for (const l of i.metadata.tags)
945
+ c.tags.add(l);
940
946
  }
941
- return e;
947
+ return Array.from(a.values()).map(
948
+ ({ name: i, path: o, tags: r }) => ({
949
+ name: i,
950
+ path: o,
951
+ tags: r
952
+ })
953
+ );
942
954
  }
943
955
  function Ce(e) {
944
956
  let s = e.trim().replace(/^@/, "").replace(/[\\/\s]+/g, "-");
945
957
  return s = s.replace(/-+/g, "-"), s;
946
958
  }
947
- async function Te(e, n, s, r) {
959
+ async function Te(e, n, s, a) {
948
960
  await H();
949
- const a = d.resolve(process.cwd(), e.path);
961
+ const i = f.resolve(process.cwd(), e.path);
950
962
  try {
951
- const c = await C.getInstance().detectAllProjects(a);
952
- if (c.length > 0) {
953
- const i = c[0].metadata;
954
- if (i.tags?.length)
955
- for (const l of i.tags)
956
- e.tags.add(l);
957
- for (const l in i.dependencies) {
958
- n[l] && e.tags.add(n[l]);
959
- const g = l.split(/[@/:]/g).pop();
960
- g && n[g] && e.tags.add(n[g]);
963
+ const r = await C.getInstance().detectAllProjects(i);
964
+ for (const c of r) {
965
+ const l = c.metadata;
966
+ if (l.tags?.length)
967
+ for (const g of l.tags)
968
+ e.tags.add(g);
969
+ for (const g in l.dependencies) {
970
+ n[g] && e.tags.add(n[g]);
971
+ const u = g.split(/[@/:]/g).pop();
972
+ u && n[u] && e.tags.add(n[u]);
961
973
  }
962
974
  }
963
975
  } catch (o) {
@@ -969,8 +981,8 @@ async function Te(e, n, s, r) {
969
981
  }
970
982
  try {
971
983
  for (const o in s) {
972
- const c = s[o], i = d.join(a, o);
973
- p.existsSync(i) && e.tags.add(c);
984
+ const r = s[o], c = f.join(i, o);
985
+ p.existsSync(c) && e.tags.add(r);
974
986
  }
975
987
  } catch (o) {
976
988
  console.warn(
@@ -980,14 +992,14 @@ async function Te(e, n, s, r) {
980
992
  );
981
993
  }
982
994
  try {
983
- for (const o in r) {
984
- const c = r[o];
995
+ for (const o in a) {
996
+ const r = a[o];
985
997
  (await ce(o, {
986
- cwd: a,
998
+ cwd: i,
987
999
  nodir: !0,
988
1000
  dot: !0
989
1001
  // Include dotfiles if needed, though 'src' patterns usually don't
990
- })).length > 0 && e.tags.add(c);
1002
+ })).length > 0 && e.tags.add(r);
991
1003
  }
992
1004
  } catch (o) {
993
1005
  console.warn(
@@ -998,7 +1010,7 @@ async function Te(e, n, s, r) {
998
1010
  }
999
1011
  }
1000
1012
  function Re(e, n) {
1001
- const s = d.join(e, n);
1013
+ const s = f.join(e, n);
1002
1014
  try {
1003
1015
  return p.readFileSync(s, "utf-8");
1004
1016
  } catch {
@@ -1006,35 +1018,35 @@ function Re(e, n) {
1006
1018
  }
1007
1019
  }
1008
1020
  async function Fe(e, n, s = !1) {
1009
- const a = p.readdirSync(e).filter((o) => o.endsWith(".md")).filter((o) => !n.includes(o));
1010
- if (a.length > 0) {
1021
+ const i = p.readdirSync(e).filter((o) => o.endsWith(".md")).filter((o) => !n.includes(o));
1022
+ if (i.length > 0) {
1011
1023
  console.warn(
1012
1024
  t.yellow(
1013
1025
  `
1014
- โš ๏ธ Found ${a.length} instruction files that are no longer generated:`
1026
+ โš ๏ธ Found ${i.length} instruction files that are no longer generated:`
1015
1027
  )
1016
1028
  );
1017
- for (const c of a)
1018
- console.warn(t.yellow(` - ${c}`));
1029
+ for (const r of i)
1030
+ console.warn(t.yellow(` - ${r}`));
1019
1031
  let o = s;
1020
1032
  if (s || (o = (await W.prompt([
1021
1033
  {
1022
1034
  type: "confirm",
1023
1035
  name: "prune",
1024
- message: `Do you want to delete these ${a.length} old files?`,
1036
+ message: `Do you want to delete these ${i.length} old files?`,
1025
1037
  default: !1
1026
1038
  }
1027
1039
  ])).prune), o) {
1028
- let c = 0;
1029
- for (const i of a)
1040
+ let r = 0;
1041
+ for (const c of i)
1030
1042
  try {
1031
- p.unlinkSync(d.join(e, i)), c++;
1043
+ p.unlinkSync(f.join(e, c)), r++;
1032
1044
  } catch (l) {
1033
1045
  console.error(
1034
- t.red(` โŒ Error deleting ${i}: ${l.message}`)
1046
+ t.red(` โŒ Error deleting ${c}: ${l.message}`)
1035
1047
  );
1036
1048
  }
1037
- console.log(`โœ… Pruned ${c} old files.`);
1049
+ console.log(`โœ… Pruned ${r} old files.`);
1038
1050
  }
1039
1051
  }
1040
1052
  }
@@ -1043,13 +1055,13 @@ async function ke() {
1043
1055
  t.cyan(`๐Ÿ” Validating instruction files with quality scoring...
1044
1056
  `)
1045
1057
  );
1046
- const e = j("Loading configuration...").start(), n = O(), s = L(n);
1058
+ const e = j("Loading configuration...").start(), n = O(), s = M(n);
1047
1059
  e.succeed("Configuration loaded.");
1048
- const r = d.resolve(
1060
+ const a = f.resolve(
1049
1061
  process.cwd(),
1050
1062
  s.outputDirectory
1051
1063
  );
1052
- if (!p.existsSync(r)) {
1064
+ if (!p.existsSync(a)) {
1053
1065
  e.fail(
1054
1066
  t.red(
1055
1067
  `โŒ Output directory ${s.outputDirectory} does not exist. Run 'magic-helix run' first.`
@@ -1057,14 +1069,14 @@ async function ke() {
1057
1069
  );
1058
1070
  return;
1059
1071
  }
1060
- const a = p.readdirSync(r).filter((u) => u.endsWith(".md"));
1061
- if (a.length === 0) {
1072
+ const i = p.readdirSync(a).filter((u) => u.endsWith(".md"));
1073
+ if (i.length === 0) {
1062
1074
  console.log(
1063
1075
  t.yellow("No instruction files found. Run 'magic-helix run' first.")
1064
1076
  );
1065
1077
  return;
1066
1078
  }
1067
- console.log(t.gray(`Checking ${a.length} instruction file(s)...
1079
+ console.log(t.gray(`Checking ${i.length} instruction file(s)...
1068
1080
  `));
1069
1081
  let o = { track: () => {
1070
1082
  } };
@@ -1076,13 +1088,13 @@ async function ke() {
1076
1088
  }
1077
1089
  } catch {
1078
1090
  }
1079
- let c = 0, i = 0;
1091
+ let r = 0, c = 0;
1080
1092
  const l = [];
1081
- for (const u of a) {
1082
- const h = d.join(r, u);
1093
+ for (const u of i) {
1094
+ const h = f.join(a, u);
1083
1095
  try {
1084
1096
  const w = p.readFileSync(h, "utf-8"), m = ae(w), v = Ae(m.overallScore);
1085
- l.push({ file: u, score: m.overallScore, grade: v }), m.overallScore >= 70 ? c++ : i++;
1097
+ l.push({ file: u, score: m.overallScore, grade: v }), m.overallScore >= 70 ? r++ : c++;
1086
1098
  const D = m.overallScore >= 90 ? t.green : m.overallScore >= 70 ? t.blue : t.yellow;
1087
1099
  console.log(
1088
1100
  D(`${v} ${m.overallScore}/100`) + t.gray(` - ${u}`)
@@ -1098,24 +1110,24 @@ async function ke() {
1098
1110
  missingCount: m.missingElements.length
1099
1111
  });
1100
1112
  } catch (w) {
1101
- i++, console.log(t.red(`ERROR - ${u}: ${w.message}`));
1113
+ c++, console.log(t.red(`ERROR - ${u}: ${w.message}`));
1102
1114
  }
1103
1115
  }
1104
1116
  console.log(t.bold(`
1105
1117
  === Validation Summary ===
1106
- `)), console.log(t.green(`โœ… Passed (โ‰ฅ70): ${c}`)), console.log(t.red(`โŒ Failed (<70): ${i}`));
1118
+ `)), console.log(t.green(`โœ… Passed (โ‰ฅ70): ${r}`)), console.log(t.red(`โŒ Failed (<70): ${c}`));
1107
1119
  const g = l.reduce((u, h) => u + h.score, 0) / l.length;
1108
1120
  console.log(t.cyan(`๐Ÿ“Š Average Score: ${Math.round(g)}/100`)), o.track({
1109
1121
  type: "summary",
1110
1122
  files: l.length,
1111
- pass: c,
1112
- fail: i,
1123
+ pass: r,
1124
+ fail: c,
1113
1125
  averageScore: Math.round(g)
1114
- }), i === 0 && g >= 80 ? console.log(t.green(`
1115
- โœจ All instruction files meet quality standards!`)) : i > 0 && console.log(
1126
+ }), c === 0 && g >= 80 ? console.log(t.green(`
1127
+ โœจ All instruction files meet quality standards!`)) : c > 0 && console.log(
1116
1128
  t.yellow(
1117
1129
  `
1118
- โš ๏ธ ${i} file(s) need improvement. Run with --verbose for details.`
1130
+ โš ๏ธ ${c} file(s) need improvement. Run with --verbose for details.`
1119
1131
  )
1120
1132
  );
1121
1133
  }