sela-core 1.0.6 → 1.0.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.
Files changed (124) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/ErrorHandler.d.ts +1 -1
  3. package/dist/cli/ErrorHandler.js +14 -14
  4. package/dist/cli/commands/bulk.d.ts +1 -1
  5. package/dist/cli/commands/bulk.d.ts.map +1 -1
  6. package/dist/cli/commands/bulk.js +51 -33
  7. package/dist/cli/commands/init.d.ts +1 -1
  8. package/dist/cli/commands/init.d.ts.map +1 -1
  9. package/dist/cli/commands/init.js +26 -18
  10. package/dist/cli/commands/showReport.d.ts +1 -1
  11. package/dist/cli/commands/showReport.d.ts.map +1 -1
  12. package/dist/cli/commands/showReport.js +12 -10
  13. package/dist/cli/commands/status.d.ts +1 -1
  14. package/dist/cli/commands/status.d.ts.map +1 -1
  15. package/dist/cli/commands/status.js +8 -8
  16. package/dist/cli/commands/sync.d.ts +1 -1
  17. package/dist/cli/commands/sync.d.ts.map +1 -1
  18. package/dist/cli/commands/sync.js +38 -30
  19. package/dist/cli/index.js +9 -9
  20. package/dist/cli/ui/DnaTable.d.ts +1 -1
  21. package/dist/cli/ui/DnaTable.d.ts.map +1 -1
  22. package/dist/cli/ui/DnaTable.js +23 -16
  23. package/dist/cli/ui/RefactorWizard.d.ts +3 -3
  24. package/dist/cli/ui/RefactorWizard.d.ts.map +1 -1
  25. package/dist/cli/ui/RefactorWizard.js +108 -82
  26. package/dist/config/ConfigLoader.d.ts +3 -2
  27. package/dist/config/ConfigLoader.d.ts.map +1 -1
  28. package/dist/config/ConfigLoader.js +23 -13
  29. package/dist/config/DryRunGuard.d.ts +14 -0
  30. package/dist/config/DryRunGuard.d.ts.map +1 -0
  31. package/dist/config/DryRunGuard.js +79 -0
  32. package/dist/config/SelaConfig.d.ts +26 -16
  33. package/dist/config/SelaConfig.d.ts.map +1 -1
  34. package/dist/config/SelaConfig.js +54 -22
  35. package/dist/engine/HealingRegistry.d.ts +1 -1
  36. package/dist/engine/HealingRegistry.js +3 -3
  37. package/dist/engine/SelaEngine.d.ts +13 -10
  38. package/dist/engine/SelaEngine.d.ts.map +1 -1
  39. package/dist/engine/SelaEngine.js +292 -101
  40. package/dist/errors/SelaError.d.ts +132 -0
  41. package/dist/errors/SelaError.d.ts.map +1 -0
  42. package/dist/errors/SelaError.js +154 -0
  43. package/dist/fixtures/expectProxy.d.ts +1 -1
  44. package/dist/fixtures/expectProxy.d.ts.map +1 -1
  45. package/dist/fixtures/expectProxy.js +17 -10
  46. package/dist/fixtures/index.d.ts +7 -1
  47. package/dist/fixtures/index.d.ts.map +1 -1
  48. package/dist/fixtures/index.js +26 -11
  49. package/dist/fixtures/proxyTag.d.ts +12 -0
  50. package/dist/fixtures/proxyTag.d.ts.map +1 -0
  51. package/dist/fixtures/proxyTag.js +45 -0
  52. package/dist/index.d.ts +8 -6
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +9 -4
  55. package/dist/reporter/SelaReporter.d.ts +143 -0
  56. package/dist/reporter/SelaReporter.d.ts.map +1 -0
  57. package/dist/reporter/SelaReporter.js +428 -0
  58. package/dist/services/ASTSourceUpdater.d.ts +20 -1
  59. package/dist/services/ASTSourceUpdater.d.ts.map +1 -1
  60. package/dist/services/ASTSourceUpdater.js +257 -89
  61. package/dist/services/ArgumentTypeAnalyzer.js +7 -7
  62. package/dist/services/BlastRadiusAnalyzer.d.ts.map +1 -1
  63. package/dist/services/BlastRadiusAnalyzer.js +5 -2
  64. package/dist/services/ChainValidator.js +22 -22
  65. package/dist/services/CrossFileHealer.js +7 -7
  66. package/dist/services/DefinitionTracer.d.ts +1 -1
  67. package/dist/services/DefinitionTracer.d.ts.map +1 -1
  68. package/dist/services/DefinitionTracer.js +28 -13
  69. package/dist/services/DnaEditorService.d.ts +2 -2
  70. package/dist/services/DnaEditorService.d.ts.map +1 -1
  71. package/dist/services/DnaEditorService.js +81 -62
  72. package/dist/services/DnaIndexService.d.ts +1 -1
  73. package/dist/services/DnaIndexService.d.ts.map +1 -1
  74. package/dist/services/DnaIndexService.js +14 -14
  75. package/dist/services/HealReportService.d.ts +43 -1
  76. package/dist/services/HealReportService.d.ts.map +1 -1
  77. package/dist/services/HealReportService.js +108 -25
  78. package/dist/services/HealingAdvisory.js +1 -1
  79. package/dist/services/HealingCacheService.d.ts +135 -0
  80. package/dist/services/HealingCacheService.d.ts.map +1 -0
  81. package/dist/services/HealingCacheService.js +460 -0
  82. package/dist/services/HealthReportService.d.ts +1 -1
  83. package/dist/services/HealthReportService.d.ts.map +1 -1
  84. package/dist/services/HealthReportService.js +25 -25
  85. package/dist/services/InitializerUpdater.d.ts.map +1 -1
  86. package/dist/services/InitializerUpdater.js +20 -1
  87. package/dist/services/IntentAuditor.d.ts +18 -1
  88. package/dist/services/IntentAuditor.d.ts.map +1 -1
  89. package/dist/services/IntentAuditor.js +50 -26
  90. package/dist/services/InteractiveReview.d.ts +15 -0
  91. package/dist/services/InteractiveReview.d.ts.map +1 -0
  92. package/dist/services/InteractiveReview.js +125 -0
  93. package/dist/services/LLMService.d.ts +18 -2
  94. package/dist/services/LLMService.d.ts.map +1 -1
  95. package/dist/services/LLMService.js +33 -23
  96. package/dist/services/PRAutomationService.d.ts +14 -1
  97. package/dist/services/PRAutomationService.d.ts.map +1 -1
  98. package/dist/services/PRAutomationService.js +287 -92
  99. package/dist/services/PendingPromptLedger.d.ts +44 -0
  100. package/dist/services/PendingPromptLedger.d.ts.map +1 -0
  101. package/dist/services/PendingPromptLedger.js +180 -0
  102. package/dist/services/ReportGenerator.d.ts +70 -0
  103. package/dist/services/ReportGenerator.d.ts.map +1 -0
  104. package/dist/services/ReportGenerator.js +191 -0
  105. package/dist/services/SafetyGuard.d.ts +30 -7
  106. package/dist/services/SafetyGuard.d.ts.map +1 -1
  107. package/dist/services/SafetyGuard.js +85 -116
  108. package/dist/services/SnapshotService.js +5 -5
  109. package/dist/services/SourceLinkService.d.ts +2 -2
  110. package/dist/services/SourceLinkService.d.ts.map +1 -1
  111. package/dist/services/SourceLinkService.js +31 -22
  112. package/dist/services/SourceUpdater.d.ts +1 -1
  113. package/dist/services/SourceUpdater.d.ts.map +1 -1
  114. package/dist/services/SourceUpdater.js +66 -34
  115. package/dist/services/TemplateDiffService.d.ts.map +1 -1
  116. package/dist/services/TemplateDiffService.js +18 -15
  117. package/dist/services/WorkspaceSnapshotService.d.ts +71 -0
  118. package/dist/services/WorkspaceSnapshotService.d.ts.map +1 -0
  119. package/dist/services/WorkspaceSnapshotService.js +200 -0
  120. package/dist/types/index.d.ts +1 -1
  121. package/dist/utils/IsolatedDiff.d.ts +45 -0
  122. package/dist/utils/IsolatedDiff.d.ts.map +1 -0
  123. package/dist/utils/IsolatedDiff.js +382 -0
  124. package/package.json +71 -67
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Fixwright
1
+ # Sela
2
2
 
3
3
 
4
4
 
@@ -1,4 +1,4 @@
1
- export type CliErrorCode = 'CONFIG_NOT_FOUND' | 'SNAPSHOT_DIR_MISSING' | 'DNA_NOT_FOUND' | 'SOURCE_FILE_MISSING' | 'VALIDATION_FAILED' | 'AST_ERROR' | 'UNKNOWN';
1
+ export type CliErrorCode = "CONFIG_NOT_FOUND" | "SNAPSHOT_DIR_MISSING" | "DNA_NOT_FOUND" | "SOURCE_FILE_MISSING" | "VALIDATION_FAILED" | "AST_ERROR" | "UNKNOWN";
2
2
  export interface CliError {
3
3
  code: CliErrorCode;
4
4
  message: string;
@@ -17,28 +17,28 @@ const EXIT_CODES = {
17
17
  UNKNOWN: 1,
18
18
  };
19
19
  const KNOWN_CODES = new Set([
20
- 'CONFIG_NOT_FOUND',
21
- 'SNAPSHOT_DIR_MISSING',
22
- 'DNA_NOT_FOUND',
23
- 'SOURCE_FILE_MISSING',
24
- 'VALIDATION_FAILED',
25
- 'AST_ERROR',
26
- 'UNKNOWN',
20
+ "CONFIG_NOT_FOUND",
21
+ "SNAPSHOT_DIR_MISSING",
22
+ "DNA_NOT_FOUND",
23
+ "SOURCE_FILE_MISSING",
24
+ "VALIDATION_FAILED",
25
+ "AST_ERROR",
26
+ "UNKNOWN",
27
27
  ]);
28
28
  function isKnownCode(val) {
29
- return typeof val === 'string' && KNOWN_CODES.has(val);
29
+ return typeof val === "string" && KNOWN_CODES.has(val);
30
30
  }
31
31
  function classify(err) {
32
32
  if (err instanceof commander_1.CommanderError) {
33
33
  return {
34
- code: 'UNKNOWN',
34
+ code: "UNKNOWN",
35
35
  message: err.message,
36
36
  exitCode: err.exitCode ?? EXIT_CODES.UNKNOWN,
37
37
  };
38
38
  }
39
39
  if (err instanceof Error) {
40
40
  const typed = err;
41
- const code = isKnownCode(typed.code) ? typed.code : 'UNKNOWN';
41
+ const code = isKnownCode(typed.code) ? typed.code : "UNKNOWN";
42
42
  return {
43
43
  code,
44
44
  message: err.message,
@@ -47,13 +47,13 @@ function classify(err) {
47
47
  };
48
48
  }
49
49
  return {
50
- code: 'UNKNOWN',
50
+ code: "UNKNOWN",
51
51
  message: String(err),
52
52
  exitCode: EXIT_CODES.UNKNOWN,
53
53
  };
54
54
  }
55
55
  function handleError(err) {
56
- // Commander uses exitCode 0 for --help/--version not real errors
56
+ // Commander uses exitCode 0 for --help/--version - not real errors
57
57
  if (err instanceof commander_1.CommanderError && err.exitCode === 0) {
58
58
  process.exit(0);
59
59
  }
@@ -65,6 +65,6 @@ function handleError(err) {
65
65
  process.exit(cliErr.exitCode);
66
66
  }
67
67
  function registerGlobalHandlers() {
68
- process.on('uncaughtException', handleError);
69
- process.on('unhandledRejection', handleError);
68
+ process.on("uncaughtException", handleError);
69
+ process.on("unhandledRejection", handleError);
70
70
  }
@@ -1,3 +1,3 @@
1
- import type { Command } from 'commander';
1
+ import type { Command } from "commander";
2
2
  export declare function registerBulkUpdate(dna: Command): void;
3
3
  //# sourceMappingURL=bulk.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bulk.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/bulk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4DzC,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CA4GrD"}
1
+ {"version":3,"file":"bulk.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/bulk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA0EzC,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CA0IrD"}
@@ -14,51 +14,61 @@ const SourceLinkService_js_1 = require("../../services/SourceLinkService.js");
14
14
  const ProgressReporter_js_1 = require("../ui/ProgressReporter.js");
15
15
  function renderTargets(targets) {
16
16
  const table = new cli_table3_1.default({
17
- head: [chalk_1.default.bold('Key'), chalk_1.default.bold('Source File'), chalk_1.default.bold('Selector')],
17
+ head: [
18
+ chalk_1.default.bold("Key"),
19
+ chalk_1.default.bold("Source File"),
20
+ chalk_1.default.bold("Selector"),
21
+ ],
18
22
  colWidths: [12, 48, 44],
19
- style: { head: [], border: ['dim'] },
23
+ style: { head: [], border: ["dim"] },
20
24
  });
21
25
  for (const r of targets) {
22
- table.push([chalk_1.default.dim(r.key.slice(0, 9)), r.sourceFile || chalk_1.default.dim('—'), chalk_1.default.yellow(r.selector)]);
26
+ table.push([
27
+ chalk_1.default.dim(r.key.slice(0, 9)),
28
+ r.sourceFile || chalk_1.default.dim("-"),
29
+ chalk_1.default.yellow(r.selector),
30
+ ]);
23
31
  }
24
- process.stdout.write(table.toString() + '\n');
32
+ process.stdout.write(table.toString() + "\n");
25
33
  }
26
34
  function renderResults(results) {
27
- process.stdout.write('\n');
35
+ process.stdout.write("\n");
28
36
  const passed = results.filter((r) => r.success);
29
37
  const failed = results.filter((r) => !r.success);
30
38
  for (const r of passed) {
31
- const src = r.sourceUpdated ? chalk_1.default.dim(' + source') : '';
32
- process.stdout.write(` ${chalk_1.default.green('')} ${chalk_1.default.dim(r.key.slice(0, 9))}${src}\n`);
39
+ const src = r.sourceUpdated ? chalk_1.default.dim(" + source") : "";
40
+ process.stdout.write(` ${chalk_1.default.green("")} ${chalk_1.default.dim(r.key.slice(0, 9))}${src}\n`);
33
41
  }
34
42
  for (const r of failed) {
35
- process.stdout.write(` ${chalk_1.default.red('')} ${chalk_1.default.dim(r.key.slice(0, 9))} ${chalk_1.default.red(r.reason)}\n`);
43
+ process.stdout.write(` ${chalk_1.default.red("")} ${chalk_1.default.dim(r.key.slice(0, 9))} ${chalk_1.default.red(r.reason)}\n`);
36
44
  }
37
45
  process.stdout.write(`\n ${chalk_1.default.bold(String(passed.length))} updated` +
38
- (failed.length ? ` ${chalk_1.default.red(String(failed.length) + ' failed')}` : '') +
39
- '\n\n');
46
+ (failed.length
47
+ ? ` ${chalk_1.default.red(String(failed.length) + " failed")}`
48
+ : "") +
49
+ "\n\n");
40
50
  }
41
51
  function registerBulkUpdate(dna) {
42
52
  dna
43
- .command('bulk-update')
44
- .description('Replace a selector across all matching DNAs')
45
- .requiredOption('--old <selector>', 'Selector to replace')
46
- .requiredOption('--new <selector>', 'Replacement selector')
47
- .option('--dry-run', 'Show affected DNAs without writing')
48
- .option('--no-source', 'Skip .spec.ts updates')
49
- .option('--confirm', 'Auto-confirm without interactive prompt')
50
- .option('--json', 'Emit JSON result instead of formatted output')
51
- .option('--dir <path>', 'Override snapshot directory')
53
+ .command("bulk-update")
54
+ .description("Replace a selector across all matching DNAs")
55
+ .requiredOption("--old <selector>", "Selector to replace")
56
+ .requiredOption("--new <selector>", "Replacement selector")
57
+ .option("--dry-run", "Show affected DNAs without writing")
58
+ .option("--no-source", "Skip .spec.ts updates")
59
+ .option("--confirm", "Auto-confirm without interactive prompt")
60
+ .option("--json", "Emit JSON result instead of formatted output")
61
+ .option("--dir <path>", "Override snapshot directory")
52
62
  .action(async (opts) => {
53
63
  const config = ConfigLoader_js_1.ConfigLoader.getInstance();
54
64
  const snapshotDir = opts.dir ?? config.dnaStoragePath;
55
65
  const progress = new ProgressReporter_js_1.ProgressReporter(opts.json);
56
66
  const dnaIndex = new DnaIndexService_js_1.DnaIndexService();
57
- await progress.run('Scanning DNA snapshots…', () => dnaIndex.buildIndex(snapshotDir));
67
+ await progress.run("Scanning DNA snapshots…", () => dnaIndex.buildIndex(snapshotDir));
58
68
  const targets = dnaIndex.findBySelector(opts.old);
59
69
  if (targets.length === 0) {
60
70
  if (opts.json) {
61
- process.stdout.write(JSON.stringify({ matched: 0, results: [] }, null, 2) + '\n');
71
+ process.stdout.write(JSON.stringify({ matched: 0, results: [] }, null, 2) + "\n");
62
72
  }
63
73
  else {
64
74
  process.stdout.write(`No DNA records match selector: ${chalk_1.default.yellow(opts.old)}\n`);
@@ -66,51 +76,59 @@ function registerBulkUpdate(dna) {
66
76
  return;
67
77
  }
68
78
  if (!opts.json) {
69
- process.stdout.write(`\n ${chalk_1.default.bold(String(targets.length))} DNA${targets.length > 1 ? 's' : ''} match ` +
79
+ process.stdout.write(`\n ${chalk_1.default.bold(String(targets.length))} DNA${targets.length > 1 ? "s" : ""} match ` +
70
80
  `${chalk_1.default.yellow(opts.old)} → ${chalk_1.default.green(opts.new)}\n\n`);
71
81
  renderTargets(targets);
72
82
  }
73
83
  // ── dry-run: stop here ────────────────────────────────────────────────
74
84
  if (opts.dryRun) {
75
85
  if (opts.json) {
76
- process.stdout.write(JSON.stringify({ dryRun: true, matched: targets.length, targets: targets.map((t) => t.key) }, null, 2) + '\n');
86
+ process.stdout.write(JSON.stringify({
87
+ dryRun: true,
88
+ matched: targets.length,
89
+ targets: targets.map((t) => t.key),
90
+ }, null, 2) + "\n");
77
91
  }
78
92
  else {
79
- process.stdout.write(chalk_1.default.dim('\n [dry-run] No files written.\n\n'));
93
+ process.stdout.write(chalk_1.default.dim("\n [dry-run] No files written.\n\n"));
80
94
  }
81
95
  return;
82
96
  }
83
- // ── confirm (skip in --json mode requires --confirm flag) ──────────
97
+ // ── confirm (skip in --json mode - requires --confirm flag) ──────────
84
98
  if (!opts.confirm && !opts.json) {
85
99
  const prompt = new enquirer_js_1.Confirm({
86
- name: 'ok',
87
- message: `Update ${targets.length} DNA file${targets.length > 1 ? 's' : ''}?`,
100
+ name: "ok",
101
+ message: `Update ${targets.length} DNA file${targets.length > 1 ? "s" : ""}?`,
88
102
  });
89
103
  const yes = (await prompt.run());
90
104
  if (!yes) {
91
- process.stdout.write(chalk_1.default.dim('Aborted.\n'));
105
+ process.stdout.write(chalk_1.default.dim("Aborted.\n"));
92
106
  return;
93
107
  }
94
108
  }
95
109
  else if (!opts.confirm && opts.json) {
96
110
  // In JSON/CI mode without --confirm, abort safely rather than hanging on a prompt.
97
- process.stderr.write('bulk-update: pass --confirm to skip interactive prompt in --json mode\n');
111
+ process.stderr.write("bulk-update: pass --confirm to skip interactive prompt in --json mode\n");
98
112
  process.exit(1);
99
113
  }
100
114
  // ── write sequentially (backup safety) ───────────────────────────────
101
115
  const editor = new DnaEditorService_js_1.DnaEditorService(snapshotDir);
102
116
  const sourceLink = opts.source ? new SourceLinkService_js_1.SourceLinkService() : null;
103
117
  const results = [];
104
- await progress.run(`Updating ${targets.length} DNA file${targets.length > 1 ? 's' : ''}…`, async () => {
118
+ await progress.run(`Updating ${targets.length} DNA file${targets.length > 1 ? "s" : ""}…`, async () => {
105
119
  for (const record of targets) {
106
- const result = { key: record.key, success: false, reason: '' };
120
+ const result = {
121
+ key: record.key,
122
+ success: false,
123
+ reason: "",
124
+ };
107
125
  try {
108
126
  await editor.write(record.key, { selector: opts.new });
109
127
  result.success = true;
110
128
  if (sourceLink && record.sourceFile && record.sourceLine > 0) {
111
129
  const patch = {
112
130
  key: record.key,
113
- field: 'selector',
131
+ field: "selector",
114
132
  oldValue: opts.old,
115
133
  newValue: opts.new,
116
134
  applySourceUpdate: true,
@@ -131,7 +149,7 @@ function registerBulkUpdate(dna) {
131
149
  }
132
150
  });
133
151
  if (opts.json) {
134
- process.stdout.write(JSON.stringify({ matched: targets.length, results }, null, 2) + '\n');
152
+ process.stdout.write(JSON.stringify({ matched: targets.length, results }, null, 2) + "\n");
135
153
  }
136
154
  else {
137
155
  renderResults(results);
@@ -1,3 +1,3 @@
1
- import { Command } from 'commander';
1
+ import { Command } from "commander";
2
2
  export declare function registerInit(program: Command): void;
3
3
  //# sourceMappingURL=init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAQnD"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAWnD"}
@@ -36,7 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.registerInit = registerInit;
37
37
  const fs = __importStar(require("fs"));
38
38
  const path = __importStar(require("path"));
39
- const PACKAGE_NAME = 'sela-core';
39
+ const PACKAGE_NAME = "sela-core";
40
40
  const CONFIG_TEMPLATE_TS = `import { defineConfig } from '${PACKAGE_NAME}';
41
41
 
42
42
  export default defineConfig({
@@ -55,30 +55,30 @@ module.exports = defineConfig({
55
55
  dnaStoragePath: 'sela-snapshots',
56
56
  });
57
57
  `;
58
- const REQUIRED_ENV_VARS = ['ANTHROPIC_API_KEY'];
58
+ const REQUIRED_ENV_VARS = ["ANTHROPIC_API_KEY"];
59
59
  function registerInit(program) {
60
60
  program
61
- .command('init')
62
- .description('Initialize Sela in the current project')
63
- .option('--no-update-imports', 'Skip swapping @playwright/test imports to sela-core')
61
+ .command("init")
62
+ .description("Initialize Sela in the current project")
63
+ .option("--no-update-imports", "Skip swapping @playwright/test imports to sela-core")
64
64
  .action(async (opts) => {
65
65
  await runInit(opts);
66
66
  });
67
67
  }
68
68
  async function runInit(opts) {
69
69
  const cwd = process.cwd();
70
- const isTs = fs.existsSync(path.join(cwd, 'tsconfig.json'));
71
- const configFile = isTs ? 'sela.config.ts' : 'sela.config.js';
70
+ const isTs = fs.existsSync(path.join(cwd, "tsconfig.json"));
71
+ const configFile = isTs ? "sela.config.ts" : "sela.config.js";
72
72
  const configPath = path.join(cwd, configFile);
73
73
  console.error(`\n🚀 Initializing Sela`);
74
- console.error(` Project type : ${isTs ? 'TypeScript' : 'JavaScript'}`);
74
+ console.error(` Project type : ${isTs ? "TypeScript" : "JavaScript"}`);
75
75
  console.error(` Directory : ${cwd}\n`);
76
76
  // ── Config file ──────────────────────────────────────────────────
77
77
  if (fs.existsSync(configPath)) {
78
- console.error(`✅ ${configFile} already exists skipping`);
78
+ console.error(`✅ ${configFile} already exists - skipping`);
79
79
  }
80
80
  else {
81
- fs.writeFileSync(configPath, isTs ? CONFIG_TEMPLATE_TS : CONFIG_TEMPLATE_JS, 'utf8');
81
+ fs.writeFileSync(configPath, isTs ? CONFIG_TEMPLATE_TS : CONFIG_TEMPLATE_JS, "utf8");
82
82
  console.error(`✅ Created ${configFile}`);
83
83
  }
84
84
  // ── Environment variables ────────────────────────────────────────
@@ -107,21 +107,29 @@ async function runInit(opts) {
107
107
  console.error(` import { test, expect } from '${PACKAGE_NAME}'\n`);
108
108
  }
109
109
  function loadDotEnv(cwd) {
110
- const envPath = path.join(cwd, '.env');
110
+ const envPath = path.join(cwd, ".env");
111
111
  if (!fs.existsSync(envPath))
112
112
  return;
113
113
  try {
114
114
  // eslint-disable-next-line @typescript-eslint/no-var-requires
115
- const dotenv = require('dotenv');
115
+ const dotenv = require("dotenv");
116
116
  dotenv.config({ path: envPath });
117
117
  }
118
118
  catch {
119
- // dotenv missing skip silently
119
+ // dotenv missing - skip silently
120
120
  }
121
121
  }
122
122
  function walkDir(dir, exts) {
123
123
  const results = [];
124
- const ignore = new Set(['node_modules', 'dist', '.git', 'sela-snapshots', 'fixwright-snapshots', 'test-results', 'playwright-report']);
124
+ const ignore = new Set([
125
+ "node_modules",
126
+ "dist",
127
+ ".git",
128
+ "sela-snapshots",
129
+ "fixwright-snapshots",
130
+ "test-results",
131
+ "playwright-report",
132
+ ]);
125
133
  function walk(current) {
126
134
  if (!fs.existsSync(current))
127
135
  return;
@@ -140,16 +148,16 @@ function walkDir(dir, exts) {
140
148
  }
141
149
  function swapImports(cwd, isTs) {
142
150
  const exts = isTs
143
- ? ['.spec.ts', '.test.ts', '.spec.js', '.test.js']
144
- : ['.spec.js', '.test.js'];
151
+ ? [".spec.ts", ".test.ts", ".spec.js", ".test.js"]
152
+ : [".spec.js", ".test.js"];
145
153
  const files = walkDir(cwd, exts);
146
154
  let swapped = 0;
147
155
  const importRegex = /(from\s+|require\s*\(\s*)(['"])@playwright\/test\2/g;
148
156
  for (const filePath of files) {
149
- const content = fs.readFileSync(filePath, 'utf8');
157
+ const content = fs.readFileSync(filePath, "utf8");
150
158
  const updated = content.replace(importRegex, (_m, prefix, quote) => `${prefix}${quote}${PACKAGE_NAME}${quote}`);
151
159
  if (updated !== content) {
152
- fs.writeFileSync(filePath, updated, 'utf8');
160
+ fs.writeFileSync(filePath, updated, "utf8");
153
161
  swapped++;
154
162
  }
155
163
  }
@@ -1,3 +1,3 @@
1
- import type { Command } from 'commander';
1
+ import type { Command } from "commander";
2
2
  export declare function registerShowReport(program: Command): void;
3
3
  //# sourceMappingURL=showReport.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"showReport.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/showReport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBzC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiCzD"}
1
+ {"version":3,"file":"showReport.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/showReport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuBzC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAyCzD"}
@@ -40,9 +40,9 @@ const child_process_1 = require("child_process");
40
40
  function openInBrowser(absPath) {
41
41
  return new Promise((resolve, reject) => {
42
42
  const platform = process.platform;
43
- const cmd = platform === 'win32'
43
+ const cmd = platform === "win32"
44
44
  ? `start "" "${absPath}"`
45
- : platform === 'darwin'
45
+ : platform === "darwin"
46
46
  ? `open "${absPath}"`
47
47
  : `xdg-open "${absPath}"`;
48
48
  (0, child_process_1.exec)(cmd, (err) => (err ? reject(err) : resolve()));
@@ -50,21 +50,23 @@ function openInBrowser(absPath) {
50
50
  }
51
51
  function registerShowReport(program) {
52
52
  program
53
- .command('show-report')
54
- .description('Open the latest Sela Insights healing report (sela-report.html) in the default browser')
55
- .option('--file <path>', 'Override path to the report file', 'sela-report.html')
56
- .option('--print', 'Print the resolved path instead of opening the browser')
53
+ .command("show-report")
54
+ .description("Open the latest Sela Insights healing report (sela-report.html) in the default browser")
55
+ .option("--file <path>", "Override path to the report file", "sela-report.html")
56
+ .option("--print", "Print the resolved path instead of opening the browser")
57
57
  .action(async (opts) => {
58
- const requested = opts.file ?? 'sela-report.html';
59
- const abs = path.isAbsolute(requested) ? requested : path.resolve(process.cwd(), requested);
58
+ const requested = opts.file ?? "sela-report.html";
59
+ const abs = path.isAbsolute(requested)
60
+ ? requested
61
+ : path.resolve(process.cwd(), requested);
60
62
  if (!fs.existsSync(abs)) {
61
63
  process.stderr.write(`[sela] No report found at ${abs}\n` +
62
- ` Run your test suite first the report is generated automatically when Sela performs at least one heal attempt.\n`);
64
+ ` Run your test suite first - the report is generated automatically when Sela performs at least one heal attempt.\n`);
63
65
  process.exit(1);
64
66
  return;
65
67
  }
66
68
  if (opts.print) {
67
- process.stdout.write(abs + '\n');
69
+ process.stdout.write(abs + "\n");
68
70
  return;
69
71
  }
70
72
  try {
@@ -1,3 +1,3 @@
1
- import type { Command } from 'commander';
1
+ import type { Command } from "commander";
2
2
  export declare function registerStatus(program: Command): void;
3
3
  //# sourceMappingURL=status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkCzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6BrD"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoCzC,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA6BrD"}
@@ -5,7 +5,7 @@ const ConfigLoader_js_1 = require("../../config/ConfigLoader.js");
5
5
  const DnaIndexService_js_1 = require("../../services/DnaIndexService.js");
6
6
  const HealthReportService_js_1 = require("../../services/HealthReportService.js");
7
7
  const ProgressReporter_js_1 = require("../ui/ProgressReporter.js");
8
- // Compact JSON shape for CI/CD consumers avoids serialising full DnaRecord arrays.
8
+ // Compact JSON shape for CI/CD consumers - avoids serialising full DnaRecord arrays.
9
9
  function toJsonOutput(report) {
10
10
  const { total, orphaned, recentlyHealed, neverHealed, topHealedFiles } = report;
11
11
  const brokenTotal = orphaned.length + report.unverifiedHeals.length;
@@ -29,20 +29,20 @@ function toJsonOutput(report) {
29
29
  }
30
30
  function registerStatus(program) {
31
31
  program
32
- .command('status')
33
- .description('Show ecosystem health report')
34
- .option('--json', 'Emit raw JSON instead of formatted output')
35
- .option('--dir <path>', 'Override snapshot directory')
32
+ .command("status")
33
+ .description("Show ecosystem health report")
34
+ .option("--json", "Emit raw JSON instead of formatted output")
35
+ .option("--dir <path>", "Override snapshot directory")
36
36
  .action(async (opts) => {
37
37
  const config = ConfigLoader_js_1.ConfigLoader.getInstance();
38
38
  const snapshotDir = opts.dir ?? config.dnaStoragePath;
39
39
  const progress = new ProgressReporter_js_1.ProgressReporter(opts.json);
40
40
  const dnaIndex = new DnaIndexService_js_1.DnaIndexService();
41
- const index = await progress.run('Scanning DNA snapshots…', () => dnaIndex.buildIndex(snapshotDir));
41
+ const index = await progress.run("Scanning DNA snapshots…", () => dnaIndex.buildIndex(snapshotDir));
42
42
  const healthSvc = new HealthReportService_js_1.HealthReportService();
43
- const report = await progress.run('Generating health report…', async () => healthSvc.generate(index));
43
+ const report = await progress.run("Generating health report…", async () => healthSvc.generate(index));
44
44
  if (opts.json) {
45
- process.stdout.write(JSON.stringify(toJsonOutput(report), null, 2) + '\n');
45
+ process.stdout.write(JSON.stringify(toJsonOutput(report), null, 2) + "\n");
46
46
  }
47
47
  else {
48
48
  process.stdout.write(healthSvc.format(report));
@@ -1,3 +1,3 @@
1
- import type { Command } from 'commander';
1
+ import type { Command } from "commander";
2
2
  export declare function registerSyncSource(dna: Command): void;
3
3
  //# sourceMappingURL=sync.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CA+HrD"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBzC,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CA+LrD"}