speclock 5.2.3 → 5.2.5
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/cli/index.js +1 -1
- package/src/core/compliance.js +1 -1
- package/src/core/semantics.js +87 -16
- package/src/dashboard/index.html +2 -2
- package/src/mcp/http-server.js +1 -1
- package/src/mcp/server.js +1 -1
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
"name": "speclock",
|
|
4
4
|
|
|
5
|
-
"version": "5.2.
|
|
5
|
+
"version": "5.2.5",
|
|
6
6
|
|
|
7
7
|
"description": "AI Constraint Engine — AI Patch Firewall. Diff-native review (interface breaks, protected symbols, dependency drift, schema changes, API impact), Patch Gateway (ALLOW/WARN/BLOCK verdicts), Spec Compiler (NL→constraints), Code Graph (blast radius, lock-to-file mapping), Typed constraints, REST API v2, Python SDK, ROS2 integration. 42 MCP tools, Gemini LLM hybrid, HMAC audit chain, RBAC, encryption, SOC 2/HIPAA compliance.",
|
|
8
8
|
|
package/src/cli/index.js
CHANGED
|
@@ -117,7 +117,7 @@ function refreshContext(root) {
|
|
|
117
117
|
|
|
118
118
|
function printHelp() {
|
|
119
119
|
console.log(`
|
|
120
|
-
SpecLock v5.2.
|
|
120
|
+
SpecLock v5.2.5 — AI Constraint Engine (Spec Compiler + Code Graph + Typed Constraints + Python SDK + ROS2 + REST API v2 + Gemini LLM + Policy-as-Code + Auth + RBAC + Encryption)
|
|
121
121
|
Developed by Sandeep Roy (github.com/sgroy10)
|
|
122
122
|
|
|
123
123
|
Usage: speclock <command> [options]
|
package/src/core/compliance.js
CHANGED
package/src/core/semantics.js
CHANGED
|
@@ -91,7 +91,7 @@ export const SYNONYM_GROUPS = [
|
|
|
91
91
|
"private key", "access key", "api secret", "api token",
|
|
92
92
|
"credentials", "credential"],
|
|
93
93
|
["frontend", "frontend code", "client-side", "client side",
|
|
94
|
-
"browser", "react state", "ui component"],
|
|
94
|
+
"browser", "react state", "ui component", "ui"],
|
|
95
95
|
|
|
96
96
|
// --- Dependencies ---
|
|
97
97
|
["dependency", "package", "library", "module", "import", "require",
|
|
@@ -118,9 +118,10 @@ export const SYNONYM_GROUPS = [
|
|
|
118
118
|
["financial records", "financial data", "accounting records",
|
|
119
119
|
"ledger", "general ledger", "accounts"],
|
|
120
120
|
["trade", "trades", "executed trade", "trade record", "order",
|
|
121
|
-
"position"
|
|
121
|
+
"position"],
|
|
122
|
+
["portfolio", "holdings", "investment portfolio"],
|
|
122
123
|
["salary", "salaries", "payroll", "wages", "compensation",
|
|
123
|
-
"remuneration", "stipend"],
|
|
124
|
+
"remuneration", "stipend", "earnings", "ytd"],
|
|
124
125
|
["payment gateway", "payment provider", "payment processor",
|
|
125
126
|
"payment service", "payment platform"],
|
|
126
127
|
["razorpay", "stripe", "paypal", "phonepe", "paytm", "ccavenue",
|
|
@@ -130,8 +131,9 @@ export const SYNONYM_GROUPS = [
|
|
|
130
131
|
// --- IoT / firmware ---
|
|
131
132
|
["firmware", "firmware update", "ota", "over the air",
|
|
132
133
|
"flash", "rom", "bios", "bootloader", "embedded software"],
|
|
133
|
-
["device", "iot", "
|
|
134
|
+
["device", "iot", "controller",
|
|
134
135
|
"microcontroller", "mcu", "plc", "edge device"],
|
|
136
|
+
["sensor", "actuator", "probe", "detector"],
|
|
135
137
|
["signed", "unsigned", "verified", "unverified",
|
|
136
138
|
"trusted", "untrusted", "certified", "uncertified"],
|
|
137
139
|
|
|
@@ -234,9 +236,10 @@ export const EUPHEMISM_MAP = {
|
|
|
234
236
|
"thin out": ["delete", "remove", "reduce"],
|
|
235
237
|
|
|
236
238
|
// Modification euphemisms
|
|
237
|
-
"streamline": ["remove", "simplify", "modify", "reduce"],
|
|
239
|
+
"streamline": ["remove", "simplify", "modify", "reduce", "weaken", "bypass", "disable"],
|
|
238
240
|
"optimize": ["modify", "change", "remove", "reduce"],
|
|
239
241
|
"modernize": ["replace", "rewrite", "change"],
|
|
242
|
+
"reorganize": ["modify", "change", "tamper", "alter"],
|
|
240
243
|
"revamp": ["replace", "rewrite", "change"],
|
|
241
244
|
"overhaul": ["replace", "rewrite", "change", "modify"],
|
|
242
245
|
"refresh": ["replace", "update", "change"],
|
|
@@ -446,6 +449,9 @@ export const CONCEPT_MAP = {
|
|
|
446
449
|
"accounting", "payment"],
|
|
447
450
|
"wages": ["salary", "payroll", "compensation", "financial records"],
|
|
448
451
|
"compensation": ["salary", "payroll", "wages", "financial records"],
|
|
452
|
+
"earnings": ["salary", "payroll", "compensation", "income", "wages",
|
|
453
|
+
"financial records"],
|
|
454
|
+
"ytd": ["year to date", "payroll", "earnings", "salary"],
|
|
449
455
|
|
|
450
456
|
// Payment providers (brand names → payment gateway concept + cross-references)
|
|
451
457
|
"razorpay": ["payment gateway", "payment processing", "payment",
|
|
@@ -737,26 +743,57 @@ export const CONCEPT_MAP = {
|
|
|
737
743
|
"inspection timestamps": ["safety records", "maintenance dates", "compliance dates"],
|
|
738
744
|
|
|
739
745
|
// Gaming / virtual economy
|
|
740
|
-
"virtual currency": ["in-game currency", "game tokens", "game economy"
|
|
746
|
+
"virtual currency": ["in-game currency", "game tokens", "game economy",
|
|
747
|
+
"currency distribution"],
|
|
748
|
+
"currency distribution": ["virtual currency", "game economy", "in-game currency",
|
|
749
|
+
"game tokens"],
|
|
750
|
+
"game economy": ["virtual currency", "in-game currency", "currency",
|
|
751
|
+
"currency distribution", "virtual economy"],
|
|
752
|
+
"virtual economy": ["virtual currency", "in-game currency", "game economy",
|
|
753
|
+
"currency distribution", "game tokens"],
|
|
741
754
|
"player data": ["user data", "gamer data", "player records", "pii"],
|
|
742
755
|
"player ips": ["ip addresses", "pii", "player data", "network data"],
|
|
743
|
-
"cheat detection": ["anti-cheat", "cheat prevention", "security",
|
|
756
|
+
"cheat detection": ["anti-cheat", "cheat prevention", "security",
|
|
757
|
+
"game integrity", "anti-cheat system"],
|
|
758
|
+
"anti-cheat": ["cheat detection", "cheat prevention", "game integrity",
|
|
759
|
+
"anti-cheat system"],
|
|
744
760
|
|
|
745
761
|
// Real estate / tenant screening
|
|
746
|
-
"background check": ["tenant screening", "verification", "due diligence"
|
|
762
|
+
"background check": ["tenant screening", "verification", "due diligence",
|
|
763
|
+
"screening"],
|
|
747
764
|
"tenant screening": ["background check", "credit check", "verification"],
|
|
748
765
|
|
|
766
|
+
// Insurance / claims
|
|
767
|
+
"denied claims": ["claim decisions", "claims processing", "claim status"],
|
|
768
|
+
"claim decisions": ["denied claims", "claims processing", "claim approvals"],
|
|
769
|
+
"claims processing": ["denied claims", "claim decisions", "claims pipeline"],
|
|
770
|
+
|
|
771
|
+
// Government / benefits
|
|
772
|
+
"denied applications": ["application decisions", "application processing",
|
|
773
|
+
"benefits decisions"],
|
|
774
|
+
|
|
775
|
+
// Privacy / data protection
|
|
776
|
+
"privacy": ["confidential", "pii", "personal data", "data protection",
|
|
777
|
+
"restricted access"],
|
|
778
|
+
"confidential": ["privacy", "private", "restricted", "pii", "data protection"],
|
|
779
|
+
|
|
749
780
|
// Telecom / billing
|
|
750
781
|
"call records": ["cdr", "call data", "telecom records", "billing records"],
|
|
751
782
|
"subscriber data": ["customer data", "user data", "telecom records"],
|
|
783
|
+
"roaming": ["telecom", "billing", "subscriber", "mobile charges",
|
|
784
|
+
"roaming charges"],
|
|
785
|
+
"roaming charges": ["billing", "telecom billing", "subscriber charges",
|
|
786
|
+
"mobile charges"],
|
|
787
|
+
"location data": ["subscriber data", "tracking data", "geolocation",
|
|
788
|
+
"user location", "pii"],
|
|
752
789
|
|
|
753
790
|
// Frontend frameworks (alternatives = change framework conflict)
|
|
754
|
-
"react": ["frontend framework", "ui framework", "
|
|
755
|
-
"svelte", "sveltekit", "next.js", "nextjs"],
|
|
756
|
-
"vue": ["frontend framework", "ui framework", "
|
|
757
|
-
"svelte", "sveltekit", "nuxt"],
|
|
758
|
-
"vue 3": ["frontend framework", "ui framework", "
|
|
759
|
-
"svelte", "sveltekit", "nuxt", "vue"],
|
|
791
|
+
"react": ["frontend framework", "ui framework", "frontend", "ui",
|
|
792
|
+
"vue", "angular", "svelte", "sveltekit", "next.js", "nextjs"],
|
|
793
|
+
"vue": ["frontend framework", "ui framework", "frontend", "ui",
|
|
794
|
+
"react", "angular", "svelte", "sveltekit", "nuxt"],
|
|
795
|
+
"vue 3": ["frontend framework", "ui framework", "frontend", "ui",
|
|
796
|
+
"react", "angular", "svelte", "sveltekit", "nuxt", "vue"],
|
|
760
797
|
"vue.js": ["frontend framework", "ui framework", "react", "angular",
|
|
761
798
|
"svelte", "sveltekit", "nuxt", "vue"],
|
|
762
799
|
"svelte": ["frontend framework", "ui framework", "react", "vue",
|
|
@@ -775,6 +812,11 @@ export const CONCEPT_MAP = {
|
|
|
775
812
|
"ui framework", "next.js", "nuxt"],
|
|
776
813
|
"ui framework": ["frontend framework", "react", "vue", "angular",
|
|
777
814
|
"svelte", "sveltekit"],
|
|
815
|
+
"tech stack": ["frontend framework", "backend framework", "react", "vue",
|
|
816
|
+
"angular", "svelte", "express", "django", "technology stack"],
|
|
817
|
+
"technology stack": ["tech stack", "frontend framework", "backend framework"],
|
|
818
|
+
"application framework": ["frontend framework", "backend framework", "react",
|
|
819
|
+
"vue", "angular", "express", "django"],
|
|
778
820
|
|
|
779
821
|
// Backend frameworks (alternatives = change backend conflict)
|
|
780
822
|
"express": ["backend framework", "fastify", "koa", "hapi", "nestjs"],
|
|
@@ -1018,6 +1060,15 @@ export function tokenize(text) {
|
|
|
1018
1060
|
}
|
|
1019
1061
|
}
|
|
1020
1062
|
|
|
1063
|
+
// Split hyphenated tokens — "react-based" also adds "react", "based"
|
|
1064
|
+
for (const w of [...rawWords]) {
|
|
1065
|
+
if (w.includes('-')) {
|
|
1066
|
+
for (const part of w.split('-')) {
|
|
1067
|
+
if (part.length >= 2 && !rawWords.includes(part)) rawWords.push(part);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1021
1072
|
// Basic plural normalization — add both singular and plural forms
|
|
1022
1073
|
// so "databases" matches "database" and vice versa
|
|
1023
1074
|
const words = [...rawWords];
|
|
@@ -1810,6 +1861,12 @@ export function scoreConflict({ actionText, lockText }) {
|
|
|
1810
1861
|
[/\bmake\s+\w+\s+visible\b/i, "expose", "make ... visible"],
|
|
1811
1862
|
[/\bmake\s+\w+\s+accessible\b/i, "expose", "make ... accessible"],
|
|
1812
1863
|
[/\bmake\s+\w+\s+(?:data\s+)?public\b/i, "expose", "make ... public"],
|
|
1864
|
+
// "streamline X detection/verification/authentication/checks" patterns
|
|
1865
|
+
[/\bstreamline\s+\w+\s+detection\b/i, "weaken", "streamline ... detection"],
|
|
1866
|
+
[/\bstreamline\s+\w+\s+detection\b/i, "disable", "streamline ... detection"],
|
|
1867
|
+
[/\bstreamline\s+\w+\s+verification\b/i, "bypass", "streamline ... verification"],
|
|
1868
|
+
[/\bstreamline\s+\w+\s+authentication\b/i, "weaken", "streamline ... authentication"],
|
|
1869
|
+
[/\bstreamline\s+\w+\s+(?:check|checks)\b/i, "bypass", "streamline ... checks"],
|
|
1813
1870
|
];
|
|
1814
1871
|
for (const [pattern, meaning, label] of SPLIT_PHRASE_PATTERNS) {
|
|
1815
1872
|
if (pattern.test(actionText) && lockExpanded.expanded.includes(meaning)) {
|
|
@@ -2234,6 +2291,12 @@ export function scoreConflict({ actionText, lockText }) {
|
|
|
2234
2291
|
intentAligned = true;
|
|
2235
2292
|
reasons.push("intent alignment: optimizing queries/performance is non-destructive — does not modify locked schema/system");
|
|
2236
2293
|
}
|
|
2294
|
+
|
|
2295
|
+
// Pattern 5: Adding database indexes (performance optimization, not schema modification)
|
|
2296
|
+
if (!intentAligned && !_compoundDestructive && /\b(?:add|create)\s+(?:an?\s+)?index\b/i.test(_actionLowerSafe)) {
|
|
2297
|
+
intentAligned = true;
|
|
2298
|
+
reasons.push("intent alignment: adding a database index is a performance optimization — does not modify locked schema");
|
|
2299
|
+
}
|
|
2237
2300
|
}
|
|
2238
2301
|
|
|
2239
2302
|
// Check 3c: Working WITH locked technology (not replacing it)
|
|
@@ -2391,10 +2454,18 @@ export function scoreConflict({ actionText, lockText }) {
|
|
|
2391
2454
|
"placeholder", "logo", "banner", "hero", "avatar",
|
|
2392
2455
|
"sidebar", "navigation", "menu", "breadcrumb", "footer",
|
|
2393
2456
|
]);
|
|
2394
|
-
|
|
2457
|
+
// Guard: structural verbs (redesign, overhaul, rewrite) targeting a locked component
|
|
2458
|
+
// are NOT cosmetic — "Redesign the checkout page with a new layout" is a real change
|
|
2459
|
+
// to the checkout flow, even though "layout" is a cosmetic word.
|
|
2460
|
+
const _structuralVerbs = /\b(?:redesign|overhaul|restructure|rebuild|rewrite|rearchitect|revamp)\b/i;
|
|
2461
|
+
const _hasStructuralVerbWithOverlap = _structuralVerbs.test(actionText) && directOverlap.length >= 1;
|
|
2462
|
+
if (!intentAligned && !hasStrongVocabMatch && !_hasStructuralVerbWithOverlap) {
|
|
2395
2463
|
const actionLower = actionText.toLowerCase();
|
|
2396
2464
|
const actionWords = actionLower.split(/\s+/).map(w => w.replace(/[^a-z]/g, ""));
|
|
2397
|
-
|
|
2465
|
+
// Guard: "background" in "background check/screening/process" is NOT cosmetic CSS
|
|
2466
|
+
const _hasNonCosmeticBackground = /\bbackground\s+(?:check|screening|investigation|process|task|job|worker|service)\b/i.test(actionLower);
|
|
2467
|
+
const hasUISubject = actionWords.some(w =>
|
|
2468
|
+
UI_COSMETIC_WORDS.has(w) && !(w === "background" && _hasNonCosmeticBackground));
|
|
2398
2469
|
if (hasUISubject) {
|
|
2399
2470
|
intentAligned = true;
|
|
2400
2471
|
reasons.push(
|
package/src/dashboard/index.html
CHANGED
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
<div class="header">
|
|
90
90
|
<div>
|
|
91
91
|
<h1><span>SpecLock</span> Dashboard</h1>
|
|
92
|
-
<div class="meta">v5.2.
|
|
92
|
+
<div class="meta">v5.2.5 — AI Constraint Engine</div>
|
|
93
93
|
</div>
|
|
94
94
|
<div style="display:flex;align-items:center;gap:12px;">
|
|
95
95
|
<span id="health-badge" class="status-badge healthy">Loading...</span>
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
</div>
|
|
183
183
|
|
|
184
184
|
<div style="text-align:center;padding:24px;color:var(--muted);font-size:12px;">
|
|
185
|
-
SpecLock v5.2.
|
|
185
|
+
SpecLock v5.2.5 — Developed by Sandeep Roy — <a href="https://github.com/sgroy10/speclock" style="color:var(--accent)">GitHub</a>
|
|
186
186
|
</div>
|
|
187
187
|
|
|
188
188
|
<script>
|
package/src/mcp/http-server.js
CHANGED
|
@@ -113,7 +113,7 @@ import { fileURLToPath } from "url";
|
|
|
113
113
|
import _path from "path";
|
|
114
114
|
|
|
115
115
|
const PROJECT_ROOT = process.env.SPECLOCK_PROJECT_ROOT || process.cwd();
|
|
116
|
-
const VERSION = "5.2.
|
|
116
|
+
const VERSION = "5.2.5";
|
|
117
117
|
const AUTHOR = "Sandeep Roy";
|
|
118
118
|
const START_TIME = Date.now();
|
|
119
119
|
|
package/src/mcp/server.js
CHANGED
|
@@ -120,7 +120,7 @@ const PROJECT_ROOT =
|
|
|
120
120
|
args.project || process.env.SPECLOCK_PROJECT_ROOT || process.cwd();
|
|
121
121
|
|
|
122
122
|
// --- MCP Server ---
|
|
123
|
-
const VERSION = "5.2.
|
|
123
|
+
const VERSION = "5.2.5";
|
|
124
124
|
const AUTHOR = "Sandeep Roy";
|
|
125
125
|
|
|
126
126
|
const server = new McpServer(
|