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