speclock 3.5.4 → 4.1.0
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/package.json +1 -1
- package/src/core/conflict.js +74 -3
- package/src/core/engine.js +10 -0
- package/src/core/llm-checker.js +60 -6
- package/src/core/lock-author.js +478 -0
- package/src/core/memory.js +12 -3
- package/src/core/semantics.js +562 -33
- package/src/mcp/server.js +26 -16
package/src/mcp/server.js
CHANGED
|
@@ -220,10 +220,15 @@ server.tool(
|
|
|
220
220
|
.describe("Who created this lock"),
|
|
221
221
|
},
|
|
222
222
|
async ({ text, tags, source }) => {
|
|
223
|
-
const { lockId } = addLock(PROJECT_ROOT, text, tags, source);
|
|
223
|
+
const { lockId, rewritten, rewriteReason } = addLock(PROJECT_ROOT, text, tags, source);
|
|
224
|
+
|
|
225
|
+
// Read the stored lock to get the normalized text
|
|
226
|
+
const brain = readBrain(PROJECT_ROOT);
|
|
227
|
+
const storedLock = brain?.specLock?.items?.find(l => l.id === lockId);
|
|
228
|
+
const storedText = storedLock?.text || text;
|
|
224
229
|
|
|
225
230
|
// Auto-guard related files
|
|
226
|
-
const guardResult = autoGuardRelatedFiles(PROJECT_ROOT,
|
|
231
|
+
const guardResult = autoGuardRelatedFiles(PROJECT_ROOT, storedText);
|
|
227
232
|
const guardMsg = guardResult.guarded.length > 0
|
|
228
233
|
? `\nAuto-guarded ${guardResult.guarded.length} file(s): ${guardResult.guarded.join(", ")}`
|
|
229
234
|
: "";
|
|
@@ -231,9 +236,14 @@ server.tool(
|
|
|
231
236
|
// Sync active locks to package.json
|
|
232
237
|
syncLocksToPackageJson(PROJECT_ROOT);
|
|
233
238
|
|
|
239
|
+
// Report rewrite if it happened
|
|
240
|
+
const rewriteMsg = rewritten
|
|
241
|
+
? `\n\nSmart Lock Authoring: Rewritten for accuracy.\n Original: "${text}"\n Stored as: "${storedText}"\n Reason: ${rewriteReason}`
|
|
242
|
+
: "";
|
|
243
|
+
|
|
234
244
|
return {
|
|
235
245
|
content: [
|
|
236
|
-
{ type: "text", text: `Lock added (${lockId}): "${
|
|
246
|
+
{ type: "text", text: `Lock added (${lockId}): "${storedText}"${guardMsg}${rewriteMsg}` },
|
|
237
247
|
],
|
|
238
248
|
};
|
|
239
249
|
}
|
|
@@ -460,10 +470,10 @@ server.tool(
|
|
|
460
470
|
// CONTINUITY PROTECTION TOOLS
|
|
461
471
|
// ========================================
|
|
462
472
|
|
|
463
|
-
// Tool 12: speclock_check_conflict (
|
|
473
|
+
// Tool 12: speclock_check_conflict (v4.1: hybrid heuristic + Gemini LLM)
|
|
464
474
|
server.tool(
|
|
465
475
|
"speclock_check_conflict",
|
|
466
|
-
"Check if a proposed action conflicts with any active SpecLock.
|
|
476
|
+
"Check if a proposed action conflicts with any active SpecLock. Uses fast heuristic + Gemini LLM for universal domain coverage. In hard enforcement mode, conflicts above the threshold will BLOCK the action (isError: true).",
|
|
467
477
|
{
|
|
468
478
|
proposedAction: z
|
|
469
479
|
.string()
|
|
@@ -471,18 +481,18 @@ server.tool(
|
|
|
471
481
|
.describe("Description of the action you plan to take"),
|
|
472
482
|
},
|
|
473
483
|
async ({ proposedAction }) => {
|
|
474
|
-
//
|
|
475
|
-
let result;
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
484
|
+
// Hybrid check: heuristic first, LLM for grey-zone (1-70%)
|
|
485
|
+
let result = await checkConflictAsync(PROJECT_ROOT, proposedAction);
|
|
486
|
+
|
|
487
|
+
// If async hybrid returned no conflict, also check enforcer for hard mode
|
|
488
|
+
if (!result.hasConflict) {
|
|
489
|
+
const enforced = enforceConflictCheck(PROJECT_ROOT, proposedAction);
|
|
490
|
+
if (enforced.blocked) {
|
|
491
|
+
return {
|
|
492
|
+
content: [{ type: "text", text: enforced.analysis }],
|
|
493
|
+
isError: true,
|
|
494
|
+
};
|
|
481
495
|
}
|
|
482
|
-
} catch (_) {}
|
|
483
|
-
|
|
484
|
-
if (!result) {
|
|
485
|
-
result = enforceConflictCheck(PROJECT_ROOT, proposedAction);
|
|
486
496
|
}
|
|
487
497
|
|
|
488
498
|
// In hard mode with blocking conflict, return isError: true
|