speclock 5.2.2 → 5.2.4

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  "name": "speclock",
4
4
 
5
- "version": "5.2.2",
5
+ "version": "5.2.4",
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.2 — AI Constraint Engine (Spec Compiler + Code Graph + Typed Constraints + Python SDK + ROS2 + REST API v2 + Gemini LLM + Policy-as-Code + Auth + RBAC + Encryption)
120
+ SpecLock v5.2.4 — 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]
@@ -9,7 +9,7 @@
9
9
  import { readBrain, readEvents } from "./storage.js";
10
10
  import { verifyAuditChain } from "./audit.js";
11
11
 
12
- const VERSION = "5.2.2";
12
+ const VERSION = "5.2.4";
13
13
 
14
14
  // PHI-related keywords for HIPAA filtering
15
15
  const PHI_KEYWORDS = [
@@ -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", "portfolio"],
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", "sensor", "actuator", "controller",
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,7 +236,7 @@ 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"],
240
242
  "revamp": ["replace", "rewrite", "change"],
@@ -446,6 +448,9 @@ export const CONCEPT_MAP = {
446
448
  "accounting", "payment"],
447
449
  "wages": ["salary", "payroll", "compensation", "financial records"],
448
450
  "compensation": ["salary", "payroll", "wages", "financial records"],
451
+ "earnings": ["salary", "payroll", "compensation", "income", "wages",
452
+ "financial records"],
453
+ "ytd": ["year to date", "payroll", "earnings", "salary"],
449
454
 
450
455
  // Payment providers (brand names → payment gateway concept + cross-references)
451
456
  "razorpay": ["payment gateway", "payment processing", "payment",
@@ -737,18 +742,81 @@ export const CONCEPT_MAP = {
737
742
  "inspection timestamps": ["safety records", "maintenance dates", "compliance dates"],
738
743
 
739
744
  // Gaming / virtual economy
740
- "virtual currency": ["in-game currency", "game tokens", "game economy"],
745
+ "virtual currency": ["in-game currency", "game tokens", "game economy",
746
+ "currency distribution"],
747
+ "currency distribution": ["virtual currency", "game economy", "in-game currency",
748
+ "game tokens"],
749
+ "game economy": ["virtual currency", "in-game currency", "currency",
750
+ "currency distribution", "virtual economy"],
751
+ "virtual economy": ["virtual currency", "in-game currency", "game economy",
752
+ "currency distribution", "game tokens"],
741
753
  "player data": ["user data", "gamer data", "player records", "pii"],
742
754
  "player ips": ["ip addresses", "pii", "player data", "network data"],
743
- "cheat detection": ["anti-cheat", "cheat prevention", "security", "game integrity"],
755
+ "cheat detection": ["anti-cheat", "cheat prevention", "security",
756
+ "game integrity", "anti-cheat system"],
757
+ "anti-cheat": ["cheat detection", "cheat prevention", "game integrity",
758
+ "anti-cheat system"],
744
759
 
745
760
  // Real estate / tenant screening
746
- "background check": ["tenant screening", "verification", "due diligence"],
761
+ "background check": ["tenant screening", "verification", "due diligence",
762
+ "screening"],
747
763
  "tenant screening": ["background check", "credit check", "verification"],
748
764
 
765
+ // Insurance / claims
766
+ "denied claims": ["claim decisions", "claims processing", "claim status"],
767
+ "claim decisions": ["denied claims", "claims processing", "claim approvals"],
768
+ "claims processing": ["denied claims", "claim decisions", "claims pipeline"],
769
+
770
+ // Government / benefits
771
+ "denied applications": ["application decisions", "application processing",
772
+ "benefits decisions"],
773
+
749
774
  // Telecom / billing
750
775
  "call records": ["cdr", "call data", "telecom records", "billing records"],
751
776
  "subscriber data": ["customer data", "user data", "telecom records"],
777
+ "roaming": ["telecom", "billing", "subscriber", "mobile charges",
778
+ "roaming charges"],
779
+ "roaming charges": ["billing", "telecom billing", "subscriber charges",
780
+ "mobile charges"],
781
+ "location data": ["subscriber data", "tracking data", "geolocation",
782
+ "user location", "pii"],
783
+
784
+ // Frontend frameworks (alternatives = change framework conflict)
785
+ "react": ["frontend framework", "ui framework", "vue", "angular",
786
+ "svelte", "sveltekit", "next.js", "nextjs"],
787
+ "vue": ["frontend framework", "ui framework", "react", "angular",
788
+ "svelte", "sveltekit", "nuxt"],
789
+ "vue 3": ["frontend framework", "ui framework", "react", "angular",
790
+ "svelte", "sveltekit", "nuxt", "vue"],
791
+ "vue.js": ["frontend framework", "ui framework", "react", "angular",
792
+ "svelte", "sveltekit", "nuxt", "vue"],
793
+ "svelte": ["frontend framework", "ui framework", "react", "vue",
794
+ "angular", "sveltekit"],
795
+ "sveltekit": ["frontend framework", "ui framework", "react", "vue",
796
+ "angular", "svelte", "next.js", "nuxt"],
797
+ "angular": ["frontend framework", "ui framework", "react", "vue",
798
+ "svelte", "sveltekit"],
799
+ "next.js": ["frontend framework", "ui framework", "react", "nuxt",
800
+ "sveltekit", "nextjs"],
801
+ "nextjs": ["frontend framework", "ui framework", "react", "nuxt",
802
+ "sveltekit", "next.js"],
803
+ "nuxt": ["frontend framework", "ui framework", "vue", "next.js",
804
+ "nextjs", "sveltekit"],
805
+ "frontend framework":["react", "vue", "angular", "svelte", "sveltekit",
806
+ "ui framework", "next.js", "nuxt"],
807
+ "ui framework": ["frontend framework", "react", "vue", "angular",
808
+ "svelte", "sveltekit"],
809
+
810
+ // Backend frameworks (alternatives = change backend conflict)
811
+ "express": ["backend framework", "fastify", "koa", "hapi", "nestjs"],
812
+ "fastify": ["backend framework", "express", "koa", "hapi", "nestjs"],
813
+ "django": ["backend framework", "flask", "fastapi", "rails"],
814
+ "flask": ["backend framework", "django", "fastapi"],
815
+ "fastapi": ["backend framework", "django", "flask"],
816
+ "rails": ["backend framework", "django", "laravel", "ruby on rails"],
817
+ "laravel": ["backend framework", "rails", "django", "symfony"],
818
+ "spring": ["backend framework", "spring boot", "java framework"],
819
+ "nestjs": ["backend framework", "express", "fastify"],
752
820
  };
753
821
 
754
822
  // ===================================================================
@@ -1773,6 +1841,12 @@ export function scoreConflict({ actionText, lockText }) {
1773
1841
  [/\bmake\s+\w+\s+visible\b/i, "expose", "make ... visible"],
1774
1842
  [/\bmake\s+\w+\s+accessible\b/i, "expose", "make ... accessible"],
1775
1843
  [/\bmake\s+\w+\s+(?:data\s+)?public\b/i, "expose", "make ... public"],
1844
+ // "streamline X detection/verification/authentication/checks" patterns
1845
+ [/\bstreamline\s+\w+\s+detection\b/i, "weaken", "streamline ... detection"],
1846
+ [/\bstreamline\s+\w+\s+detection\b/i, "disable", "streamline ... detection"],
1847
+ [/\bstreamline\s+\w+\s+verification\b/i, "bypass", "streamline ... verification"],
1848
+ [/\bstreamline\s+\w+\s+authentication\b/i, "weaken", "streamline ... authentication"],
1849
+ [/\bstreamline\s+\w+\s+(?:check|checks)\b/i, "bypass", "streamline ... checks"],
1776
1850
  ];
1777
1851
  for (const [pattern, meaning, label] of SPLIT_PHRASE_PATTERNS) {
1778
1852
  if (pattern.test(actionText) && lockExpanded.expanded.includes(meaning)) {
@@ -2160,6 +2234,51 @@ export function scoreConflict({ actionText, lockText }) {
2160
2234
  }
2161
2235
  }
2162
2236
 
2237
+ // Check 3d: Non-destructive sub-activities against ANY prohibitive lock
2238
+ // These patterns are inherently safe regardless of subject overlap:
2239
+ // "Write tests for X" → testing never modifies the system
2240
+ // "Update X library version" → version bumps are maintenance
2241
+ // "Add validation to X" → adding safety checks is constructive
2242
+ // "Optimize X queries/performance" → performance tuning ≠ schema change
2243
+ //
2244
+ // GUARD: compound sentences may hide destructive ops behind safe prefixes.
2245
+ // "Optimize DB performance by moving data to unencrypted replica" is NOT safe.
2246
+ // Skip safe-intent if text also contains clearly destructive/insecure content.
2247
+ if (!intentAligned && lockIsProhibitive) {
2248
+ const _actionLowerSafe = actionText.toLowerCase();
2249
+ const _compoundDestructive = /\b(?:unencrypted|plaintext|without\s+encryption|without\s+auth|unsigned|untrusted|insecure|delet(?:e|ing)|remov(?:e|ing)|drop(?:ping)?|destroy|purg(?:e|ing)|wip(?:e|ing)|eras(?:e|ing)|bypass|disabl(?:e|ing)|expos(?:e|ing)|leak|truncat(?:e|ing)|nuk(?:e|ing))\b/i.test(_actionLowerSafe);
2250
+
2251
+ // Pattern 1: Writing/creating/running tests
2252
+ if (!_compoundDestructive && /\b(?:write|create|add|run)\s+(?:unit\s+|integration\s+|e2e\s+|end-to-end\s+)?tests?\b/i.test(_actionLowerSafe)) {
2253
+ intentAligned = true;
2254
+ reasons.push("intent alignment: writing/running tests is non-destructive — does not modify locked system");
2255
+ }
2256
+
2257
+ // Pattern 2: Updating library/client/package version
2258
+ if (!intentAligned && !_compoundDestructive && /\b(?:update|upgrade|bump)\s+\S+\s+(?:library|client|package|dependency|sdk|version)\b/i.test(_actionLowerSafe)) {
2259
+ intentAligned = true;
2260
+ reasons.push("intent alignment: updating library/client version is maintenance — does not modify locked system");
2261
+ }
2262
+
2263
+ // Pattern 3: Adding validation/sanitization (safety improvement)
2264
+ if (!intentAligned && !_compoundDestructive && /\b(?:add|implement|create)\s+(?:input\s+)?(?:validation|sanitization|sanitizing|input\s+checks?)\b/i.test(_actionLowerSafe)) {
2265
+ intentAligned = true;
2266
+ reasons.push("intent alignment: adding validation/sanitization is a safety improvement — does not modify locked system");
2267
+ }
2268
+
2269
+ // Pattern 4: Optimizing queries/performance (non-structural)
2270
+ if (!intentAligned && !_compoundDestructive && /\boptimize\s+\S+\s+(?:query|queries|performance|speed|latency|throughput)\b/i.test(_actionLowerSafe)) {
2271
+ intentAligned = true;
2272
+ reasons.push("intent alignment: optimizing queries/performance is non-destructive — does not modify locked schema/system");
2273
+ }
2274
+
2275
+ // Pattern 5: Adding database indexes (performance optimization, not schema modification)
2276
+ if (!intentAligned && !_compoundDestructive && /\b(?:add|create)\s+(?:an?\s+)?index\b/i.test(_actionLowerSafe)) {
2277
+ intentAligned = true;
2278
+ reasons.push("intent alignment: adding a database index is a performance optimization — does not modify locked schema");
2279
+ }
2280
+ }
2281
+
2163
2282
  // Check 3c: Working WITH locked technology (not replacing it)
2164
2283
  // "Update the Stripe UI components" vs "must always use Stripe" → working WITH Stripe → safe
2165
2284
  // "Update the Stripe payment UI" vs "Stripe API keys must never be exposed" → different subject → safe
@@ -2315,7 +2434,12 @@ export function scoreConflict({ actionText, lockText }) {
2315
2434
  "placeholder", "logo", "banner", "hero", "avatar",
2316
2435
  "sidebar", "navigation", "menu", "breadcrumb", "footer",
2317
2436
  ]);
2318
- if (!intentAligned && !hasStrongVocabMatch) {
2437
+ // Guard: structural verbs (redesign, overhaul, rewrite) targeting a locked component
2438
+ // are NOT cosmetic — "Redesign the checkout page with a new layout" is a real change
2439
+ // to the checkout flow, even though "layout" is a cosmetic word.
2440
+ const _structuralVerbs = /\b(?:redesign|overhaul|restructure|rebuild|rewrite|rearchitect|revamp)\b/i;
2441
+ const _hasStructuralVerbWithOverlap = _structuralVerbs.test(actionText) && directOverlap.length >= 1;
2442
+ if (!intentAligned && !hasStrongVocabMatch && !_hasStructuralVerbWithOverlap) {
2319
2443
  const actionLower = actionText.toLowerCase();
2320
2444
  const actionWords = actionLower.split(/\s+/).map(w => w.replace(/[^a-z]/g, ""));
2321
2445
  const hasUISubject = actionWords.some(w => UI_COSMETIC_WORDS.has(w));
@@ -2407,6 +2531,7 @@ const QUESTION_PREFIXES = [
2407
2531
  /^is\s+(?:it\s+)?(?:a\s+)?(?:good\s+idea\s+)?(?:to\s+)?/i,
2408
2532
  /^let\s+me\s+/i,
2409
2533
  /^we\s+should\s+(?:probably\s+)?(?:consider\s+)?(?:look\s+at\s+)?/i,
2534
+ /^how\s+hard\s+(?:would|will|could)\s+it\s+be\s+to\s+/i,
2410
2535
  /^explore\s+(?:using\s+)?/i,
2411
2536
  ];
2412
2537
 
@@ -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.2 &mdash; AI Constraint Engine</div>
92
+ <div class="meta">v5.2.4 &mdash; 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.2 &mdash; Developed by Sandeep Roy &mdash; <a href="https://github.com/sgroy10/speclock" style="color:var(--accent)">GitHub</a>
185
+ SpecLock v5.2.4 &mdash; Developed by Sandeep Roy &mdash; <a href="https://github.com/sgroy10/speclock" style="color:var(--accent)">GitHub</a>
186
186
  </div>
187
187
 
188
188
  <script>
@@ -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.2";
116
+ const VERSION = "5.2.4";
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.2";
123
+ const VERSION = "5.2.4";
124
124
  const AUTHOR = "Sandeep Roy";
125
125
 
126
126
  const server = new McpServer(