speclore 0.1.8 → 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 +29 -29
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +29 -29
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.js +8 -8
- package/dist/mcp/server.js.map +1 -1
- package/package.json +1 -1
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}
|
|
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}
|
|
954
|
+
logger.debug(`AI usage: ${model} - ${promptTokens}+${completionTokens} tokens, ~$${cost.toFixed(4)}`);
|
|
955
955
|
return cost;
|
|
956
956
|
}
|
|
957
957
|
/**
|
|
@@ -3766,7 +3766,7 @@ async function generateConstraints(projectRoot2, features, _context, config) {
|
|
|
3766
3766
|
try {
|
|
3767
3767
|
await writer.write(content);
|
|
3768
3768
|
writtenFiles.push(writer.configFile);
|
|
3769
|
-
logger.info(`Constraint written via plugin: ${writer.toolName}
|
|
3769
|
+
logger.info(`Constraint written via plugin: ${writer.toolName} -> ${writer.configFile}`);
|
|
3770
3770
|
} catch (err) {
|
|
3771
3771
|
logger.warn(`Writer plugin '${tool}' failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3772
3772
|
}
|
|
@@ -3991,7 +3991,7 @@ function resolveFromMappingFile(projectRoot2, _feature, scenario) {
|
|
|
3991
3991
|
if (mapping.scenarios && scenario.name in mapping.scenarios) {
|
|
3992
3992
|
const entry = mapping.scenarios[scenario.name];
|
|
3993
3993
|
if (entry) {
|
|
3994
|
-
logger.debug(`Mapping file hit: ${scenario.name}
|
|
3994
|
+
logger.debug(`Mapping file hit: ${scenario.name} -> ${entry.testMethod}`);
|
|
3995
3995
|
return {
|
|
3996
3996
|
name: scenario.name,
|
|
3997
3997
|
status: "passed",
|
|
@@ -4022,7 +4022,7 @@ function resolveFromTag(projectRoot2, _feature, scenario) {
|
|
|
4022
4022
|
while ((match = tagRegex.exec(content)) !== null) {
|
|
4023
4023
|
if (match[1].trim() === scenario.name) {
|
|
4024
4024
|
const methodMatch = findTestMethodNearby(content, match.index);
|
|
4025
|
-
logger.debug(`Tag hit: ${scenario.name}
|
|
4025
|
+
logger.debug(`Tag hit: ${scenario.name} -> ${methodMatch}`);
|
|
4026
4026
|
return {
|
|
4027
4027
|
name: scenario.name,
|
|
4028
4028
|
status: "passed",
|
|
@@ -4466,7 +4466,7 @@ function acquireLock(specLoreDir) {
|
|
|
4466
4466
|
try {
|
|
4467
4467
|
writeFileSync16(lockPath, JSON.stringify(lockInfo), { flag: "wx", encoding: "utf-8" });
|
|
4468
4468
|
} catch {
|
|
4469
|
-
logger.debug("Lock write failed
|
|
4469
|
+
logger.debug("Lock write failed - another process may have acquired it");
|
|
4470
4470
|
return false;
|
|
4471
4471
|
}
|
|
4472
4472
|
logger.debug(`Lock acquired by PID ${process.pid}`);
|
|
@@ -5030,10 +5030,10 @@ async function startMcpServer() {
|
|
|
5030
5030
|
mkdirSync16(specLoreDir, { recursive: true });
|
|
5031
5031
|
const locked = acquireLock(specLoreDir);
|
|
5032
5032
|
if (!locked) {
|
|
5033
|
-
logger.warn("Could not acquire lock
|
|
5033
|
+
logger.warn("Could not acquire lock - another SpecLore instance may be running.");
|
|
5034
5034
|
}
|
|
5035
5035
|
} catch {
|
|
5036
|
-
logger.warn("Could not acquire lock
|
|
5036
|
+
logger.warn("Could not acquire lock - .speclore/ directory may not exist.");
|
|
5037
5037
|
}
|
|
5038
5038
|
const transport = new StdioServerTransport();
|
|
5039
5039
|
await server.connect(transport);
|
|
@@ -5373,16 +5373,16 @@ function registerSetupCommand(program) {
|
|
|
5373
5373
|
if (opts.verbose) logger.setLevel("debug");
|
|
5374
5374
|
const projectRoot2 = process.cwd();
|
|
5375
5375
|
logger.info("SpecLore Setup");
|
|
5376
|
-
logger.info("
|
|
5376
|
+
logger.info("---------------");
|
|
5377
5377
|
const tools = detectAITools(projectRoot2);
|
|
5378
5378
|
if (tools.length === 0) {
|
|
5379
5379
|
logger.warn("No supported AI tools detected.");
|
|
5380
5380
|
logger.info("");
|
|
5381
5381
|
logger.info(" To enable MCP integration, open your AI client in this project first,");
|
|
5382
5382
|
logger.info(" then re-run setup. Or use manual configuration:");
|
|
5383
|
-
logger.info(" speclore mcp add cursor
|
|
5384
|
-
logger.info(" speclore mcp add claude
|
|
5385
|
-
logger.info(" speclore mcp add 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");
|
|
5386
5386
|
logger.info("");
|
|
5387
5387
|
} else {
|
|
5388
5388
|
logger.info(`Detected AI tools: ${tools.map((t) => t.tool).join(", ")}`);
|
|
@@ -5402,18 +5402,18 @@ function registerSetupCommand(program) {
|
|
|
5402
5402
|
logger.info("");
|
|
5403
5403
|
logger.info("Setup complete! Next steps:");
|
|
5404
5404
|
logger.info("");
|
|
5405
|
-
logger.info(" Option A
|
|
5406
|
-
logger.info(' speclore spec "your requirement"
|
|
5407
|
-
logger.info(" speclore code
|
|
5408
|
-
logger.info(" speclore verify
|
|
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");
|
|
5409
5409
|
logger.info("");
|
|
5410
|
-
logger.info(" Option B
|
|
5410
|
+
logger.info(" Option B - AI client workflow (recommended):");
|
|
5411
5411
|
logger.info(" Open Cursor / Qoder / Claude Code and start chatting.");
|
|
5412
|
-
logger.info(" MCP is already configured
|
|
5412
|
+
logger.info(" MCP is already configured - AI handles the full pipeline.");
|
|
5413
5413
|
logger.info("");
|
|
5414
|
-
logger.info(" Optional
|
|
5415
|
-
logger.info(" speclore init
|
|
5416
|
-
logger.info(" (Not required
|
|
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)");
|
|
5417
5417
|
});
|
|
5418
5418
|
}
|
|
5419
5419
|
|
|
@@ -5427,7 +5427,7 @@ function registerInitCommand(program) {
|
|
|
5427
5427
|
if (opts.verbose) logger.setLevel("debug");
|
|
5428
5428
|
const projectRoot2 = process.cwd();
|
|
5429
5429
|
logger.info("SpecLore Init");
|
|
5430
|
-
logger.info("
|
|
5430
|
+
logger.info("--------------");
|
|
5431
5431
|
const config = loadConfig(projectRoot2);
|
|
5432
5432
|
logger.info(`Project: ${config.project.name || "(unnamed)"}`);
|
|
5433
5433
|
const context = buildContext(projectRoot2, config);
|
|
@@ -5834,7 +5834,7 @@ function registerMcpConfigCommands(program) {
|
|
|
5834
5834
|
if (!client) return;
|
|
5835
5835
|
logger.info(`Configuring MCP for ${clientLabel(client)}...`);
|
|
5836
5836
|
writeMcpForClient(projectRoot2, client);
|
|
5837
|
-
logger.info(
|
|
5837
|
+
logger.info(`[OK] ${clientLabel(client)} MCP configured at ${getMcpPath(projectRoot2, client)}`);
|
|
5838
5838
|
});
|
|
5839
5839
|
mcpCmd.command("remove <client>").description("Remove SpecLore MCP config from a specific AI client (cursor | claude | qoder)").action((clientArg) => {
|
|
5840
5840
|
const projectRoot2 = process.cwd();
|
|
@@ -5847,7 +5847,7 @@ function registerMcpConfigCommands(program) {
|
|
|
5847
5847
|
}
|
|
5848
5848
|
const removed = removeMcpServerEntry(mcpPath, "speclore");
|
|
5849
5849
|
if (removed) {
|
|
5850
|
-
logger.info(
|
|
5850
|
+
logger.info(`[OK] Removed speclore from ${clientLabel(client)}: ${mcpPath}`);
|
|
5851
5851
|
} else {
|
|
5852
5852
|
logger.info(`${clientLabel(client)}: speclore entry not found in ${mcpPath}`);
|
|
5853
5853
|
}
|
|
@@ -5855,24 +5855,24 @@ function registerMcpConfigCommands(program) {
|
|
|
5855
5855
|
mcpCmd.command("list").description("Show current SpecLore MCP configuration status for all clients").action(() => {
|
|
5856
5856
|
const projectRoot2 = process.cwd();
|
|
5857
5857
|
logger.info("SpecLore MCP Configuration Status");
|
|
5858
|
-
logger.info("
|
|
5858
|
+
logger.info("------------------------------");
|
|
5859
5859
|
let anyFound = false;
|
|
5860
5860
|
for (const client of VALID_CLIENTS) {
|
|
5861
5861
|
const mcpPath = getMcpPath(projectRoot2, client);
|
|
5862
5862
|
if (!existsSync27(mcpPath)) {
|
|
5863
|
-
logger.info(`
|
|
5863
|
+
logger.info(` [-] ${clientLabel(client)}: no config file (${mcpPath})`);
|
|
5864
5864
|
continue;
|
|
5865
5865
|
}
|
|
5866
5866
|
try {
|
|
5867
5867
|
const config = JSON.parse(readFileSync20(mcpPath, "utf-8"));
|
|
5868
5868
|
if (config.mcpServers?.["speclore"]) {
|
|
5869
|
-
logger.info(`
|
|
5869
|
+
logger.info(` [OK] ${clientLabel(client)}: configured -> ${mcpPath}`);
|
|
5870
5870
|
anyFound = true;
|
|
5871
5871
|
} else {
|
|
5872
|
-
logger.info(`
|
|
5872
|
+
logger.info(` [-] ${clientLabel(client)}: config file exists but speclore not registered -> ${mcpPath}`);
|
|
5873
5873
|
}
|
|
5874
5874
|
} catch {
|
|
5875
|
-
logger.info(`
|
|
5875
|
+
logger.info(` [!] ${clientLabel(client)}: failed to parse ${mcpPath}`);
|
|
5876
5876
|
}
|
|
5877
5877
|
}
|
|
5878
5878
|
if (!anyFound) {
|