speclore 0.1.7 → 0.1.9

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/index.js CHANGED
@@ -371,7 +371,7 @@ var init_version = __esm({
371
371
  function readModuleConfig(config) {
372
372
  const boundaries = [];
373
373
  for (const [name, mod] of Object.entries(config.project.modules)) {
374
- logger.debug(`Reading module config: ${name} \u2192 ${mod.path}`);
374
+ logger.debug(`Reading module config: ${name} -> ${mod.path}`);
375
375
  boundaries.push({
376
376
  name,
377
377
  responsibility: mod.responsibility,
@@ -951,7 +951,7 @@ var init_cost_tracker = __esm({
951
951
  totalTokens: promptTokens + completionTokens,
952
952
  estimatedCostUsd: cost
953
953
  });
954
- logger.debug(`AI usage: ${model} \u2014 ${promptTokens}+${completionTokens} tokens, ~$${cost.toFixed(4)}`);
954
+ logger.debug(`AI usage: ${model} - ${promptTokens}+${completionTokens} tokens, ~$${cost.toFixed(4)}`);
955
955
  return cost;
956
956
  }
957
957
  /**
@@ -1503,8 +1503,7 @@ var init_pdf_reader = __esm({
1503
1503
  const uint8 = new Uint8Array(buffer);
1504
1504
  const doc = await pdfjsLib.getDocument({
1505
1505
  data: uint8,
1506
- useWorkerFetch: false,
1507
- isEvalSupported: false
1506
+ useWorkerFetch: false
1508
1507
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
1509
1508
  }).promise;
1510
1509
  const textParts = [];
@@ -1514,7 +1513,6 @@ var init_pdf_reader = __esm({
1514
1513
  const pageText = textContent.items.map((item) => item.str).join("");
1515
1514
  if (pageText) textParts.push(pageText);
1516
1515
  }
1517
- doc.destroy();
1518
1516
  const text = textParts.join("\n");
1519
1517
  return [{
1520
1518
  id: source.replace(/\\/g, "/").replace(/\.pdf$/i, ""),
@@ -2871,8 +2869,7 @@ async function extractPdfText(dataBuffer) {
2871
2869
  const uint8 = new Uint8Array(dataBuffer);
2872
2870
  const doc = await pdfjsLib.getDocument({
2873
2871
  data: uint8,
2874
- useWorkerFetch: false,
2875
- isEvalSupported: false
2872
+ useWorkerFetch: false
2876
2873
  }).promise;
2877
2874
  const textParts = [];
2878
2875
  for (let i = 1; i <= doc.numPages; i++) {
@@ -2881,7 +2878,6 @@ async function extractPdfText(dataBuffer) {
2881
2878
  const pageText = textContent.items.map((item) => item.str).join("");
2882
2879
  if (pageText) textParts.push(pageText);
2883
2880
  }
2884
- doc.destroy();
2885
2881
  return textParts.join("\n");
2886
2882
  }
2887
2883
  async function parsePdfBuffer(dataBuffer, idHint = "document") {
@@ -3770,7 +3766,7 @@ async function generateConstraints(projectRoot2, features, _context, config) {
3770
3766
  try {
3771
3767
  await writer.write(content);
3772
3768
  writtenFiles.push(writer.configFile);
3773
- logger.info(`Constraint written via plugin: ${writer.toolName} \u2192 ${writer.configFile}`);
3769
+ logger.info(`Constraint written via plugin: ${writer.toolName} -> ${writer.configFile}`);
3774
3770
  } catch (err) {
3775
3771
  logger.warn(`Writer plugin '${tool}' failed: ${err instanceof Error ? err.message : String(err)}`);
3776
3772
  }
@@ -3995,7 +3991,7 @@ function resolveFromMappingFile(projectRoot2, _feature, scenario) {
3995
3991
  if (mapping.scenarios && scenario.name in mapping.scenarios) {
3996
3992
  const entry = mapping.scenarios[scenario.name];
3997
3993
  if (entry) {
3998
- logger.debug(`Mapping file hit: ${scenario.name} \u2192 ${entry.testMethod}`);
3994
+ logger.debug(`Mapping file hit: ${scenario.name} -> ${entry.testMethod}`);
3999
3995
  return {
4000
3996
  name: scenario.name,
4001
3997
  status: "passed",
@@ -4026,7 +4022,7 @@ function resolveFromTag(projectRoot2, _feature, scenario) {
4026
4022
  while ((match = tagRegex.exec(content)) !== null) {
4027
4023
  if (match[1].trim() === scenario.name) {
4028
4024
  const methodMatch = findTestMethodNearby(content, match.index);
4029
- logger.debug(`Tag hit: ${scenario.name} \u2192 ${methodMatch}`);
4025
+ logger.debug(`Tag hit: ${scenario.name} -> ${methodMatch}`);
4030
4026
  return {
4031
4027
  name: scenario.name,
4032
4028
  status: "passed",
@@ -4470,7 +4466,7 @@ function acquireLock(specLoreDir) {
4470
4466
  try {
4471
4467
  writeFileSync16(lockPath, JSON.stringify(lockInfo), { flag: "wx", encoding: "utf-8" });
4472
4468
  } catch {
4473
- logger.debug("Lock write failed \u2014 another process may have acquired it");
4469
+ logger.debug("Lock write failed - another process may have acquired it");
4474
4470
  return false;
4475
4471
  }
4476
4472
  logger.debug(`Lock acquired by PID ${process.pid}`);
@@ -5034,10 +5030,10 @@ async function startMcpServer() {
5034
5030
  mkdirSync16(specLoreDir, { recursive: true });
5035
5031
  const locked = acquireLock(specLoreDir);
5036
5032
  if (!locked) {
5037
- logger.warn("Could not acquire lock \u2014 another SpecLore instance may be running.");
5033
+ logger.warn("Could not acquire lock - another SpecLore instance may be running.");
5038
5034
  }
5039
5035
  } catch {
5040
- logger.warn("Could not acquire lock \u2014 .speclore/ directory may not exist.");
5036
+ logger.warn("Could not acquire lock - .speclore/ directory may not exist.");
5041
5037
  }
5042
5038
  const transport = new StdioServerTransport();
5043
5039
  await server.connect(transport);
@@ -5377,16 +5373,16 @@ function registerSetupCommand(program) {
5377
5373
  if (opts.verbose) logger.setLevel("debug");
5378
5374
  const projectRoot2 = process.cwd();
5379
5375
  logger.info("SpecLore Setup");
5380
- logger.info("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
5376
+ logger.info("---------------");
5381
5377
  const tools = detectAITools(projectRoot2);
5382
5378
  if (tools.length === 0) {
5383
5379
  logger.warn("No supported AI tools detected.");
5384
5380
  logger.info("");
5385
5381
  logger.info(" To enable MCP integration, open your AI client in this project first,");
5386
5382
  logger.info(" then re-run setup. Or use manual configuration:");
5387
- logger.info(" speclore mcp add cursor \u2014 configure for Cursor");
5388
- logger.info(" speclore mcp add claude \u2014 configure for Claude Code");
5389
- logger.info(" speclore mcp add qoder \u2014 configure for Qoder");
5383
+ logger.info(" speclore mcp add cursor - configure for Cursor");
5384
+ logger.info(" speclore mcp add claude - configure for Claude Code");
5385
+ logger.info(" speclore mcp add qoder - configure for Qoder");
5390
5386
  logger.info("");
5391
5387
  } else {
5392
5388
  logger.info(`Detected AI tools: ${tools.map((t) => t.tool).join(", ")}`);
@@ -5406,18 +5402,18 @@ function registerSetupCommand(program) {
5406
5402
  logger.info("");
5407
5403
  logger.info("Setup complete! Next steps:");
5408
5404
  logger.info("");
5409
- logger.info(" Option A \u2014 CLI workflow (terminal users):");
5410
- logger.info(' speclore spec "your requirement" \u2192 generate .feature');
5411
- logger.info(" speclore code \u2192 generate constraints + tests");
5412
- logger.info(" speclore verify \u2192 run acceptance");
5405
+ logger.info(" Option A - CLI workflow (terminal users):");
5406
+ logger.info(' speclore spec "your requirement" -> generate .feature');
5407
+ logger.info(" speclore code -> generate constraints + tests");
5408
+ logger.info(" speclore verify -> run acceptance");
5413
5409
  logger.info("");
5414
- logger.info(" Option B \u2014 AI client workflow (recommended):");
5410
+ logger.info(" Option B - AI client workflow (recommended):");
5415
5411
  logger.info(" Open Cursor / Qoder / Claude Code and start chatting.");
5416
- logger.info(" MCP is already configured \u2014 AI handles the full pipeline.");
5412
+ logger.info(" MCP is already configured - AI handles the full pipeline.");
5417
5413
  logger.info("");
5418
- logger.info(" Optional \u2014 Pre-scan project context:");
5419
- logger.info(" speclore init \u2192 scan modules/entities/APIs for better AI context");
5420
- logger.info(" (Not required \u2014 context is auto-built on first spec/code call)");
5414
+ logger.info(" Optional - Pre-scan project context:");
5415
+ logger.info(" speclore init -> scan modules/entities/APIs for better AI context");
5416
+ logger.info(" (Not required - context is auto-built on first spec/code call)");
5421
5417
  });
5422
5418
  }
5423
5419
 
@@ -5431,7 +5427,7 @@ function registerInitCommand(program) {
5431
5427
  if (opts.verbose) logger.setLevel("debug");
5432
5428
  const projectRoot2 = process.cwd();
5433
5429
  logger.info("SpecLore Init");
5434
- logger.info("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
5430
+ logger.info("--------------");
5435
5431
  const config = loadConfig(projectRoot2);
5436
5432
  logger.info(`Project: ${config.project.name || "(unnamed)"}`);
5437
5433
  const context = buildContext(projectRoot2, config);
@@ -5838,7 +5834,7 @@ function registerMcpConfigCommands(program) {
5838
5834
  if (!client) return;
5839
5835
  logger.info(`Configuring MCP for ${clientLabel(client)}...`);
5840
5836
  writeMcpForClient(projectRoot2, client);
5841
- logger.info(`\u2713 ${clientLabel(client)} MCP configured at ${getMcpPath(projectRoot2, client)}`);
5837
+ logger.info(`[OK] ${clientLabel(client)} MCP configured at ${getMcpPath(projectRoot2, client)}`);
5842
5838
  });
5843
5839
  mcpCmd.command("remove <client>").description("Remove SpecLore MCP config from a specific AI client (cursor | claude | qoder)").action((clientArg) => {
5844
5840
  const projectRoot2 = process.cwd();
@@ -5851,7 +5847,7 @@ function registerMcpConfigCommands(program) {
5851
5847
  }
5852
5848
  const removed = removeMcpServerEntry(mcpPath, "speclore");
5853
5849
  if (removed) {
5854
- logger.info(`\u2713 Removed speclore from ${clientLabel(client)}: ${mcpPath}`);
5850
+ logger.info(`[OK] Removed speclore from ${clientLabel(client)}: ${mcpPath}`);
5855
5851
  } else {
5856
5852
  logger.info(`${clientLabel(client)}: speclore entry not found in ${mcpPath}`);
5857
5853
  }
@@ -5859,24 +5855,24 @@ function registerMcpConfigCommands(program) {
5859
5855
  mcpCmd.command("list").description("Show current SpecLore MCP configuration status for all clients").action(() => {
5860
5856
  const projectRoot2 = process.cwd();
5861
5857
  logger.info("SpecLore MCP Configuration Status");
5862
- logger.info("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
5858
+ logger.info("------------------------------");
5863
5859
  let anyFound = false;
5864
5860
  for (const client of VALID_CLIENTS) {
5865
5861
  const mcpPath = getMcpPath(projectRoot2, client);
5866
5862
  if (!existsSync27(mcpPath)) {
5867
- logger.info(` \u25CB ${clientLabel(client)}: no config file (${mcpPath})`);
5863
+ logger.info(` [-] ${clientLabel(client)}: no config file (${mcpPath})`);
5868
5864
  continue;
5869
5865
  }
5870
5866
  try {
5871
5867
  const config = JSON.parse(readFileSync20(mcpPath, "utf-8"));
5872
5868
  if (config.mcpServers?.["speclore"]) {
5873
- logger.info(` \u2713 ${clientLabel(client)}: configured \u2192 ${mcpPath}`);
5869
+ logger.info(` [OK] ${clientLabel(client)}: configured -> ${mcpPath}`);
5874
5870
  anyFound = true;
5875
5871
  } else {
5876
- logger.info(` \u25CB ${clientLabel(client)}: config file exists but speclore not registered \u2192 ${mcpPath}`);
5872
+ logger.info(` [-] ${clientLabel(client)}: config file exists but speclore not registered -> ${mcpPath}`);
5877
5873
  }
5878
5874
  } catch {
5879
- logger.info(` \u2717 ${clientLabel(client)}: failed to parse ${mcpPath}`);
5875
+ logger.info(` [!] ${clientLabel(client)}: failed to parse ${mcpPath}`);
5880
5876
  }
5881
5877
  }
5882
5878
  if (!anyFound) {