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