speclock 1.3.1 → 1.4.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/README.md CHANGED
@@ -1,9 +1,11 @@
1
1
  # SpecLock
2
2
 
3
- **AI Continuity Engine** — MCP server + npm package that kills AI amnesia. Works with Lovable, Claude Code, Cursor, Bolt.new, and more.
3
+ **AI Constraint Engine** — Memory + enforcement for AI coding tools. The only solution that makes your AI **respect boundaries**, not just remember things.
4
4
 
5
5
  > Developed by **Sandeep Roy** ([github.com/sgroy10](https://github.com/sgroy10))
6
6
 
7
+ **Website**: [sgroy10.github.io/speclock](https://sgroy10.github.io/speclock/) | **npm**: [npmjs.com/package/speclock](https://www.npmjs.com/package/speclock) | **Smithery**: [smithery.ai/servers/sgroy10/speclock](https://smithery.ai/servers/sgroy10/speclock)
8
+
7
9
  [![npm version](https://img.shields.io/npm/v/speclock.svg)](https://www.npmjs.com/package/speclock)
8
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
9
11
  [![MCP Compatible](https://img.shields.io/badge/MCP-Compatible-green.svg)](https://modelcontextprotocol.io)
@@ -13,73 +15,78 @@
13
15
 
14
16
  ## The Problem
15
17
 
16
- Every AI coding tool forgets. Every. Single. Session.
18
+ AI tools now have memory. Claude Code has auto-memory. Cursor has Memory Bank. Mem0 exists.
19
+
20
+ **But memory without enforcement is dangerous.**
17
21
 
18
- - Claude Code forgets the decisions you made yesterday
19
- - Cursor forgets the constraints you set last week
20
- - Codex rebuilds what another agent already built
21
- - Your AI agent violates rules it agreed to 3 sessions ago
22
+ - Your AI remembers you use PostgreSQL then switches to MongoDB because it "seemed better"
23
+ - Your AI remembers your auth setup then rewrites it while "fixing" a bug
24
+ - Your AI remembers your constraints then ignores them when they're inconvenient
25
+ - You said "never touch auth files" 3 sessions ago — the AI doesn't care
22
26
 
23
- **AI amnesia is the #1 productivity killer in AI-assisted development.**
27
+ **Remembering is not the same as respecting.** AI tools need guardrails, not just memory.
24
28
 
25
29
  ## The Solution
26
30
 
27
- SpecLock maintains a `.speclock/` directory inside your repo that gives every AI agent perfect memory across sessions, across tools, across time.
31
+ SpecLock adds **active constraint enforcement** on top of persistent memory. When your AI tries to break something you locked, SpecLock **stops it before the damage is done**.
28
32
 
29
33
  ```
30
- .speclock/
31
- ├── brain.json # Structured project memory
32
- ├── events.log # Append-only event ledger (JSONL)
33
- ├── patches/ # Git diffs captured per event
34
- └── context/
35
- └── latest.md # Always-fresh context pack for any AI agent
36
- ```
34
+ You: "Don't ever touch the auth files"
35
+ AI: 🔒 Locked: "Never modify auth files"
37
36
 
38
- **SpecLock = MCP Server + Project Instructions.**
37
+ ... 5 sessions later ...
39
38
 
40
- The MCP server gives the AI tools for memory and constraint checking. The project instructions force the AI to use them on every action — automatically. Together, they create an active guardrail that prevents AI coding tools from breaking your work.
39
+ You: "Add social login to the login page"
40
+ AI: ⚠️ CONFLICT: This violates your lock "Never modify auth files"
41
+ Should I proceed or find another approach?
42
+ ```
41
43
 
42
- **No context is ever lost. No constraints ever violated.**
44
+ No other tool does this. Not Claude's native memory. Not Mem0. Not CLAUDE.md files.
43
45
 
44
- ## Why SpecLock Wins
46
+ ## How SpecLock Is Different
45
47
 
46
- | Feature | CLAUDE.md / .cursorrules | Chat History | Memory Plugins | **SpecLock** |
47
- |---------|--------------------------|--------------|----------------|--------------|
48
- | Structured memory | Static files | Noise-heavy | Generic | **Structured brain.json** |
49
- | Constraint enforcement | None | None | None | **Active lock checking** |
50
- | Conflict detection | None | None | None | **Semantic + synonym matching** |
51
- | Drift detection | None | None | None | **Auto-scan against locks** |
52
- | Git-aware | No | No | No | **Checkpoints, diffs, reverts** |
53
- | Multi-agent | No | No | Partial | **Full session timeline** |
54
- | Auto-suggestions | No | No | No | **AI-powered lock suggestions** |
55
- | Cross-tool | Tool-specific | Tool-specific | Tool-specific | **Universal MCP** |
48
+ | Feature | Claude Native Memory | Mem0 | CLAUDE.md / .cursorrules | **SpecLock** |
49
+ |---------|---------------------|------|--------------------------|--------------|
50
+ | Remembers context | Yes | Yes | Manual | **Yes** |
51
+ | **Stops the AI from breaking things** | No | No | No | **Yes active enforcement** |
52
+ | **Semantic conflict detection** | No | No | No | **Yes synonym + negation analysis** |
53
+ | Works on Bolt.new | No | No | No | **Yes — npm file-based mode** |
54
+ | Works on Lovable | No | No | No | **Yes MCP remote** |
55
+ | Structured decisions/locks | No | Tags only | Flat text | **Goals, locks, decisions, changes** |
56
+ | Git-aware (checkpoints, rollback) | No | No | No | **Yes** |
57
+ | Drift detection | No | No | No | **Yes — scans changes against locks** |
58
+ | Multi-agent timeline | No | No | No | **Yes** |
59
+ | Cross-platform | Claude only | MCP only | Tool-specific | **Universal (MCP + npm)** |
56
60
 
57
61
  **Other tools remember. SpecLock enforces.**
58
62
 
59
63
  ## Quick Start
60
64
 
61
- ### 1. Connect SpecLock to Your AI Tool
65
+ ### Bolt.new / Aider / Any npm Platform (No MCP Needed)
62
66
 
63
- **Lovable** (no install needed):
67
+ Just tell the AI:
64
68
 
65
- 1. Go to **Settings → Connectors → Personal connectors → New MCP server**
66
- 2. Enter URL: `https://speclock-mcp-production.up.railway.app/mcp` No auth
67
- 3. Enable it in your project's prompt box
69
+ ```
70
+ "Install speclock and set up project memory"
71
+ ```
68
72
 
69
- **Claude Code** Add to `.claude/settings.json` or `.mcp.json`:
73
+ Or run it yourself:
70
74
 
71
- ```json
72
- {
73
- "mcpServers": {
74
- "speclock": {
75
- "command": "npx",
76
- "args": ["-y", "speclock", "serve", "--project", "."]
77
- }
78
- }
79
- }
75
+ ```bash
76
+ npx speclock setup --goal "Build my app"
80
77
  ```
81
78
 
82
- **Cursor**Add to `.cursor/mcp.json`:
79
+ **That's it.** The AI reads `SPECLOCK.md`, follows the rules, and uses CLI commands. Tested on Bolt.new the AI ran 17 commands automatically on first install, setting up goals, locks, and decisions without any configuration.
80
+
81
+ ### Lovable (MCP Remote — No Install)
82
+
83
+ 1. Go to **Settings → Connectors → Personal connectors → New MCP server**
84
+ 2. Enter URL: `https://speclock-mcp-production.up.railway.app/mcp` — No auth
85
+ 3. Paste [Project Instructions](#project-instructions) into Knowledge
86
+
87
+ ### Claude Code (MCP Local)
88
+
89
+ Add to `.claude/settings.json` or `.mcp.json`:
83
90
 
84
91
  ```json
85
92
  {
@@ -92,104 +99,85 @@ The MCP server gives the AI tools for memory and constraint checking. The projec
92
99
  }
93
100
  ```
94
101
 
95
- **Windsurf / Cline / Any MCP tool** — Same pattern as above.
96
-
97
- **Bolt.new / Aider / Any platform with npm** (NEW in v1.3.0):
98
-
99
- No MCP needed. Just tell the AI:
100
-
101
- ```
102
- "Install speclock and set up project memory"
103
- ```
104
-
105
- Or run it yourself:
106
-
107
- ```bash
108
- npx speclock setup --goal "Build my app"
109
- ```
110
-
111
- This creates:
112
- - `SPECLOCK.md` — AI rules file (the AI reads this automatically)
113
- - `.speclock/brain.json` — Project memory
114
- - `.speclock/context/latest.md` — Context file for the AI
115
-
116
- **That's it.** The AI reads `SPECLOCK.md`, follows the rules, and uses CLI commands (`npx speclock lock "..."`, `npx speclock check "..."`, etc.) instead of MCP tools. Tested and working on Bolt.new — the AI ran 17 commands automatically on first install.
117
-
118
- ### 2. Add Project Instructions (Required for MCP platforms)
119
-
120
- > **This is the critical step.** Without project instructions, the AI has the tools but won't use them automatically. With them, SpecLock becomes an active guardrail.
102
+ ### Cursor / Windsurf / Cline
121
103
 
122
- Copy-paste the rules below into your platform's project instruction settings:
104
+ Same MCP config as Claude Code. Add to `.cursor/mcp.json` or equivalent.
123
105
 
124
- | Platform | Where to paste |
125
- |----------|----------------|
126
- | **Lovable** | Project Settings → Knowledge |
127
- | **Cursor** | `.cursorrules` file in project root |
128
- | **Claude Code** | `CLAUDE.md` file in project root |
129
- | **Windsurf** | `.windsurfrules` file in project root |
106
+ ### Project Instructions
130
107
 
131
- **The rules to paste:**
108
+ For MCP platforms, paste these rules into your platform's instruction settings (Lovable Knowledge, .cursorrules, CLAUDE.md, etc.):
132
109
 
133
110
  ```
134
111
  ## SpecLock Rules (MANDATORY — follow on every message)
135
112
 
136
- 1. START OF EVERY CONVERSATION: Call speclock_session_briefing FIRST. Read all locks, decisions, and goals before doing anything else. Show a brief summary: "🔒 Memory loaded — X locks, Y decisions."
137
-
138
- 2. BEFORE WRITING OR MODIFYING ANY CODE: Call speclock_check_conflict with a description of what you're about to change. If a conflict is found with HIGH confidence, STOP and tell me which lock would be violated. Do NOT proceed unless I explicitly say to override it.
113
+ 1. START: Call speclock_session_briefing FIRST. Show: "🔒 Memory loaded — X locks, Y decisions."
114
+ 2. BEFORE CHANGES: Call speclock_check_conflict. If HIGH conflict, STOP and warn.
115
+ 3. LOCK: When user says "never/always/don't touch" call speclock_add_lock immediately.
116
+ 4. AFTER FEATURES: Call speclock_log_change with summary + files affected.
117
+ 5. UNLOCK: When user wants to change something locked → warn first, only proceed on confirm.
118
+ 6. END: Call speclock_session_summary with what was accomplished.
119
+ ```
139
120
 
140
- 3. WHEN I SAY "lock this", "never touch this", "don't ever change this", "this is critical", or similar: Immediately call speclock_add_lock with my exact constraint. Confirm with: "🔒 Locked: [constraint]"
121
+ See [SPECLOCK-INSTRUCTIONS.md](SPECLOCK-INSTRUCTIONS.md) for platform-specific versions.
141
122
 
142
- 4. AFTER COMPLETING ANY FEATURE OR SIGNIFICANT CHANGE: Call speclock_log_change with a summary of what was built/changed and which files were affected. Also call speclock_add_decision if an architectural choice was made.
123
+ ## What It Looks Like In Practice
143
124
 
144
- 5. WHEN I ASK TO REMOVE OR CHANGE SOMETHING THAT WAS LOCKED: Warn me first: "⚠️ You locked this: [constraint]. Want me to unlock it and proceed?" Only proceed if I confirm.
125
+ ### Bolt.new Session 1 (Setup)
126
+ ```
127
+ User: "Install speclock and set up memory for my SaaS"
145
128
 
146
- 6. END OF CONVERSATION: Call speclock_session_summary with what was accomplished.
129
+ Bolt: Ran npx speclock setup
130
+ ✓ Set goal: "Build B2B SaaS API"
131
+ ✓ Added 6 locks (auth, security, rate limiting...)
132
+ ✓ Recorded 7 decisions (Supabase, Stripe, Gemini...)
133
+ ✓ Context file generated — project memory active
147
134
  ```
148
135
 
149
- See [SPECLOCK-INSTRUCTIONS.md](SPECLOCK-INSTRUCTIONS.md) for platform-specific versions and detailed examples.
136
+ ### Bolt.new Session 2 (Full Memory)
137
+ ```
138
+ User: "Create a plan for the API endpoints"
150
139
 
151
- ### 3. Start Building
140
+ Bolt: Read project context (6 locks, 7 decisions)
141
+ ✓ Created 10-phase plan respecting ALL constraints
142
+ ✓ All plans use Supabase (locked), Bearer auth (locked)
143
+ ✓ Logged planning phase back to SpecLock
144
+ ```
152
145
 
153
- That's it. Now when you chat with your AI tool:
146
+ ### Any Platform Constraint Enforcement
147
+ ```
148
+ You: "Add social login to the login page"
149
+ AI: ⚠️ CONFLICT (HIGH — 100%): Violates lock "Never modify auth files"
150
+ Reasons:
151
+ - Direct keyword match: auth
152
+ - Synonym match: security, authentication
153
+ - Lock prohibits this action (negation detected)
154
+
155
+ Should I proceed or find another approach?
156
+ ```
154
157
 
155
- 1. **Every session starts**: AI auto-loads your project memory — goals, constraints, decisions, history
156
- 2. **During work**: AI auto-captures decisions, logs changes, checks constraints before modifying code
157
- 3. **Constraint protection**: If the AI tries to break something you locked, it stops and warns you
158
- 4. **Every session ends**: AI records what was accomplished
159
- 5. **Next session**: Full continuity — the AI remembers everything from all previous sessions
158
+ ## Killer Feature: Semantic Conflict Detection
160
159
 
161
- ## How It Works In Practice
160
+ Not just keyword matching. SpecLock uses **synonym expansion** (15 groups), **negation detection**, and **destructive action flagging**:
162
161
 
163
- ### You lock something important:
164
- ```
165
- You: "Don't ever touch the auth files"
166
- AI: 🔒 Locked: "Never modify auth files"
167
162
  ```
163
+ Lock: "No breaking changes to public API"
164
+ Action: "Remove the external endpoints"
168
165
 
169
- ### AI checks before every change:
170
- ```
171
- You: "Add social login to the login page"
172
- AI: ⚠️ This conflicts with your lock: "Never modify auth files"
173
- Should I proceed anyway, or find another approach?
166
+ Result: [HIGH] Conflict detected (confidence: 85%)
167
+ - synonym match: remove/delete, external/public, endpoints/api
168
+ - lock prohibits this action (negation detected)
169
+ - destructive action against locked constraint
174
170
  ```
175
171
 
176
- ### New session, full memory:
177
- ```
178
- You: "Let's keep working on the dashboard"
179
- AI: 🔒 Memory loaded — 5 locks, 3 decisions, 2 sessions tracked.
180
- Last session you added the payment page and locked the auth files.
181
- Ready to work on the dashboard.
182
- ```
172
+ ## Three Integration Modes
183
173
 
184
- ### You change your mind:
185
- ```
186
- You: "Actually, unlock the auth files, I need to change them"
187
- AI: You locked: "Never modify auth files". Want me to unlock this?
188
- You: "Yes"
189
- AI: 🔓 Unlocked. Proceeding with auth file changes.
190
- ```
174
+ | Mode | Platforms | How It Works |
175
+ |------|-----------|--------------|
176
+ | **MCP Remote** | Lovable, bolt.diy, Base44 | Connect via URL — no install needed |
177
+ | **MCP Local** | Claude Code, Cursor, Windsurf, Cline | `npx speclock serve` — 19 tools via MCP |
178
+ | **npm File-Based** | Bolt.new, Aider, Rocket.new | `npx speclock setup` — AI reads SPECLOCK.md + uses CLI |
191
179
 
192
- ## MCP Tools (19)
180
+ ## 19 MCP Tools
193
181
 
194
182
  ### Memory Management
195
183
  | Tool | Purpose |
@@ -206,11 +194,11 @@ AI: 🔓 Unlocked. Proceeding with auth file changes.
206
194
  ### Change Tracking
207
195
  | Tool | Purpose |
208
196
  |------|---------|
209
- | `speclock_log_change` | Manually log a significant change |
197
+ | `speclock_log_change` | Log a significant change |
210
198
  | `speclock_get_changes` | Get recent tracked changes |
211
- | `speclock_get_events` | Get event log (filterable by type/time) |
199
+ | `speclock_get_events` | Get event log (filterable) |
212
200
 
213
- ### Continuity Protection
201
+ ### Enforcement & Protection
214
202
  | Tool | Purpose |
215
203
  |------|---------|
216
204
  | `speclock_check_conflict` | Check action against locks (semantic matching) |
@@ -230,97 +218,32 @@ AI: 🔓 Unlocked. Proceeding with auth file changes.
230
218
  | `speclock_detect_drift` | Scan changes for constraint violations |
231
219
  | `speclock_health` | Health score + multi-agent timeline |
232
220
 
233
- ## Killer Features
234
-
235
- ### Semantic Conflict Detection
236
-
237
- Not just keyword matching — SpecLock understands synonyms, negation, and destructive intent:
238
-
239
- ```
240
- Lock: "No breaking changes to public API"
241
-
242
- Action: "remove the external endpoints"
243
- Result: [HIGH] Conflict detected (confidence: 85%)
244
- - synonym match: remove/delete, external/public, endpoints/api
245
- - lock prohibits this action (negation detected)
246
- - destructive action against locked constraint
247
- ```
248
-
249
- ### Auto-Lock Suggestions
250
-
251
- SpecLock analyzes your decisions and notes for commitment language and suggests constraints:
252
-
253
- ```
254
- Decision: "Always use REST for public endpoints"
255
- → Suggestion: Promote to lock (contains "always" — strong commitment language)
256
-
257
- Project mentions "security" but has no security lock
258
- → Suggestion: "No secrets or credentials in source code"
259
- ```
260
-
261
- ### Drift Detection
262
-
263
- Proactively scans recent changes against your locks:
264
-
265
- ```
266
- Lock: "No database schema changes without migration"
267
- Change: "Modified users table schema directly"
268
- → [HIGH] Drift detected — review immediately
269
- ```
270
-
271
- ### Multi-Agent Timeline
272
-
273
- Track which AI tools touched your project and what they did:
274
-
275
- ```
276
- Health Check — Score: 85/100 (Grade: A)
277
-
278
- Multi-Agent Timeline:
279
- - claude-code: 12 sessions, last active 2026-02-24
280
- - cursor: 5 sessions, last active 2026-02-23
281
- - codex: 2 sessions, last active 2026-02-20
282
- ```
283
-
284
221
  ## CLI Commands
285
222
 
286
223
  ```bash
287
- # Setup (NEW in v1.3.0)
288
- speclock setup --goal "Build my app" Full one-shot setup (init + SPECLOCK.md + context)
224
+ # Setup
225
+ speclock setup --goal "Build my app" # One-shot: init + rules + context
289
226
 
290
- # Memory Management
291
- speclock init Initialize SpecLock
292
- speclock goal <text> Set project goal
293
- speclock lock <text> [--tags a,b] Add a SpecLock constraint
294
- speclock lock remove <id> Remove a lock
295
- speclock decide <text> Record a decision
296
- speclock note <text> Add a note
227
+ # Memory
228
+ speclock goal <text> # Set project goal
229
+ speclock lock <text> [--tags a,b] # Add a constraint
230
+ speclock lock remove <id> # Remove a lock
231
+ speclock decide <text> # Record a decision
232
+ speclock note <text> # Add a note
297
233
 
298
- # Change Tracking
299
- speclock log-change <text> --files x Log a significant change (NEW in v1.3.0)
300
- speclock context Generate and print context pack
234
+ # Tracking
235
+ speclock log-change <text> --files x # Log a change
236
+ speclock context # Regenerate context file
301
237
 
302
- # Protection
303
- speclock check <text> Check for lock conflicts (NEW in v1.3.0)
238
+ # Enforcement
239
+ speclock check <text> # Check for lock conflicts
304
240
 
305
241
  # Other
306
- speclock facts deploy --provider X Set deploy facts
307
- speclock watch Start file watcher
308
- speclock serve [--project <path>] Start MCP server
309
- speclock status Show brain summary
242
+ speclock status # Show brain summary
243
+ speclock serve [--project <path>] # Start MCP server
244
+ speclock watch # Start file watcher
310
245
  ```
311
246
 
312
- ## Three Integration Modes
313
-
314
- SpecLock works everywhere because it adapts to your platform:
315
-
316
- | Mode | Platforms | How It Works |
317
- |------|-----------|--------------|
318
- | **MCP Remote** | Lovable, bolt.diy, Base44 | Connect via URL — no install needed |
319
- | **MCP Local** | Claude Code, Cursor, Windsurf, Cline | `npx speclock serve` — 19 tools via MCP |
320
- | **npm File-Based** | Bolt.new, Aider, Rocket.new | `npx speclock setup` — AI reads SPECLOCK.md + uses CLI |
321
-
322
- SpecLock is infrastructure, not a competitor. It makes **every** AI coding tool better.
323
-
324
247
  ## Architecture
325
248
 
326
249
  ```
@@ -335,7 +258,7 @@ SpecLock is infrastructure, not a competitor. It makes **every** AI coding tool
335
258
  │ │
336
259
  ┌──────────────▼──────────────────▼────────────────────┐
337
260
  │ SpecLock Core Engine │
338
- │ Memory | Tracking | Protection | Git | Intelligence
261
+ │ Memory | Tracking | Enforcement | Git | Intelligence│
339
262
  └──────────────────────┬───────────────────────────────┘
340
263
 
341
264
  .speclock/
@@ -364,4 +287,4 @@ MIT License - see [LICENSE](LICENSE) file.
364
287
 
365
288
  ---
366
289
 
367
- *SpecLock v1.3.0 — Because no AI session should ever forget.*
290
+ *SpecLock v1.3.1 — Because remembering isn't enough. AI needs to respect boundaries.*
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "speclock",
3
- "version": "1.3.1",
4
- "description": "AI continuity engine — MCP server + CLI that kills AI amnesia. Maintains project memory, enforces constraints, and detects drift across AI coding sessions.",
3
+ "version": "1.4.0",
4
+ "description": "AI constraint engine — MCP server + CLI with active enforcement. Memory + guardrails for AI coding tools. Works with Bolt.new, Claude Code, Cursor, Lovable.",
5
5
  "type": "module",
6
6
  "main": "src/mcp/server.js",
7
7
  "bin": {
package/src/cli/index.js CHANGED
@@ -11,6 +11,8 @@ import {
11
11
  checkConflict,
12
12
  watchRepo,
13
13
  createSpecLockMd,
14
+ guardFile,
15
+ unguardFile,
14
16
  } from "../core/engine.js";
15
17
  import { generateContext } from "../core/context.js";
16
18
  import { readBrain } from "../core/storage.js";
@@ -69,7 +71,7 @@ function refreshContext(root) {
69
71
 
70
72
  function printHelp() {
71
73
  console.log(`
72
- SpecLock v1.3.0 — AI Continuity Engine
74
+ SpecLock v1.4.0 — AI Constraint Engine
73
75
  Developed by Sandeep Roy (github.com/sgroy10)
74
76
 
75
77
  Usage: speclock <command> [options]
@@ -80,6 +82,8 @@ Commands:
80
82
  goal <text> Set or update the project goal
81
83
  lock <text> [--tags a,b] Add a non-negotiable constraint
82
84
  lock remove <id> Remove a lock by ID
85
+ guard <file> [--lock "text"] Inject lock warning into a file (NEW)
86
+ unguard <file> Remove lock warning from a file (NEW)
83
87
  decide <text> [--tags a,b] Record a decision
84
88
  note <text> [--pinned] Add a pinned note
85
89
  log-change <text> [--files x,y] Log a significant change
@@ -95,11 +99,13 @@ Options:
95
99
  --source <user|agent> Who created this (default: user)
96
100
  --files <a.ts,b.ts> Comma-separated file paths
97
101
  --goal <text> Goal text (for setup command)
102
+ --lock <text> Lock text (for guard command)
98
103
  --project <path> Project root (for serve)
99
104
 
100
105
  Examples:
101
106
  npx speclock setup --goal "Build PawPalace pet shop"
102
107
  npx speclock lock "Never modify auth files"
108
+ npx speclock guard src/Auth.tsx --lock "Never modify auth files"
103
109
  npx speclock check "Adding social login to auth page"
104
110
  npx speclock log-change "Built payment system" --files src/pay.tsx
105
111
  npx speclock decide "Use Supabase for auth"
@@ -336,6 +342,45 @@ Next steps:
336
342
  return;
337
343
  }
338
344
 
345
+ // --- GUARD (new: file-level lock) ---
346
+ if (cmd === "guard") {
347
+ const flags = parseFlags(args);
348
+ const filePath = flags._[0];
349
+ if (!filePath) {
350
+ console.error("Error: File path is required.");
351
+ console.error('Usage: speclock guard <file> --lock "constraint text"');
352
+ process.exit(1);
353
+ }
354
+ const lockText = flags.lock || "This file is locked by SpecLock. Do not modify.";
355
+ const result = guardFile(root, filePath, lockText);
356
+ if (result.success) {
357
+ console.log(`Guarded: ${filePath}`);
358
+ console.log(`Lock warning injected: "${lockText}"`);
359
+ } else {
360
+ console.error(result.error);
361
+ process.exit(1);
362
+ }
363
+ return;
364
+ }
365
+
366
+ // --- UNGUARD ---
367
+ if (cmd === "unguard") {
368
+ const filePath = args[0];
369
+ if (!filePath) {
370
+ console.error("Error: File path is required.");
371
+ console.error("Usage: speclock unguard <file>");
372
+ process.exit(1);
373
+ }
374
+ const result = unguardFile(root, filePath);
375
+ if (result.success) {
376
+ console.log(`Unguarded: ${filePath}`);
377
+ } else {
378
+ console.error(result.error);
379
+ process.exit(1);
380
+ }
381
+ return;
382
+ }
383
+
339
384
  // --- FACTS ---
340
385
  if (cmd === "facts") {
341
386
  const sub = args.shift();
@@ -700,37 +700,45 @@ export async function watchRepo(root) {
700
700
  // --- SPECLOCK.md generator (for npm dependency / file-based mode) ---
701
701
 
702
702
  export function createSpecLockMd(root) {
703
- const mdContent = `# SpecLock — Project Memory Active
703
+ const mdContent = `# SpecLock — AI Constraint Engine Active
704
704
 
705
- This project uses **SpecLock** for AI continuity across sessions.
706
- Read \`.speclock/context/latest.md\` for full project context before making changes.
705
+ ## MANDATORY: Read this BEFORE doing anything.
707
706
 
708
- ## Rules (follow on every message)
707
+ This project uses **SpecLock** for AI constraint enforcement.
709
708
 
710
- 1. **START OF EVERY MESSAGE**: Read \`.speclock/context/latest.md\` for project memory goals, constraints (locks), decisions, and recent changes. If the file doesn't exist, run \`npx speclock context\` to generate it.
709
+ **STOP. Before writing or modifying ANY code, you MUST:**
710
+ 1. Read \`.speclock/context/latest.md\` for project memory
711
+ 2. Run \`npx speclock check "what you plan to change"\`
712
+ 3. If conflict found → STOP and warn the user
711
713
 
712
- 2. **BEFORE MODIFYING CODE**: Run \`npx speclock check "description of what you plan to change"\`. If a conflict is found (HIGH confidence), STOP and warn the user which constraint would be violated. Do NOT proceed unless the user explicitly says to override.
714
+ **If a file starts with "SPECLOCK-GUARD DO NOT MODIFY" DO NOT EDIT IT.**
713
715
 
714
- 3. **WHEN USER SAYS "lock this", "never touch", "don't change", "always", "critical"**: Run \`npx speclock lock "the exact constraint"\`. Confirm: "Locked: [constraint]"
716
+ ## Rules (MANDATORY every message, no exceptions)
715
717
 
716
- 4. **AFTER COMPLETING A FEATURE OR SIGNIFICANT CHANGE**: Run \`npx speclock log-change "what was built/changed" --files file1.tsx,file2.ts\`. Then run \`npx speclock context\` to refresh the context file.
718
+ 1. **FIRST ACTION OF EVERY MESSAGE**: Read \`.speclock/context/latest.md\`. This contains all project constraints (locks), decisions, and goals. Show: "Memory loaded — X locks, Y decisions." If the file doesn't exist, run \`npx speclock context\`.
719
+
720
+ 2. **BEFORE MODIFYING ANY CODE — EVERY TIME**: Run \`npx speclock check "description of what you plan to change"\`. If a conflict is found (HIGH confidence), STOP IMMEDIATELY. Tell the user which constraint would be violated. Do NOT proceed unless the user explicitly overrides. THIS IS THE MOST IMPORTANT RULE.
721
+
722
+ 3. **WHEN USER SAYS "lock this", "never touch", "don't change", "always", "critical"**: Run \`npx speclock lock "the exact constraint"\`. Then run \`npx speclock guard <file> --lock "constraint"\` on the specific files to inject a lock warning directly into the file. Confirm: "Locked: [constraint]"
723
+
724
+ 4. **AFTER COMPLETING A FEATURE OR CHANGE**: Run \`npx speclock log-change "what was built" --files file1.tsx,file2.ts\`.
717
725
 
718
726
  5. **WHEN AN ARCHITECTURAL DECISION IS MADE**: Run \`npx speclock decide "the decision"\`
719
727
 
720
- 6. **WHEN USER WANTS TO CHANGE SOMETHING LOCKED**: Warn first: "This is locked: [constraint]. Want me to unlock and proceed?" If confirmed, run \`npx speclock lock remove <lockId>\`
728
+ 6. **WHEN USER WANTS TO CHANGE SOMETHING LOCKED**: Warn first. If confirmed, run \`npx speclock lock remove <lockId>\` and \`npx speclock unguard <file>\` to remove the file guard.
721
729
 
722
730
  ## Quick Reference
723
731
 
724
732
  \`\`\`bash
725
- npx speclock status # See brain summary
726
- npx speclock context # Regenerate context file
733
+ npx speclock check "what you plan to do" # CHECK BEFORE CHANGES
727
734
  npx speclock lock "constraint text" # Add a constraint
735
+ npx speclock guard src/Auth.tsx --lock "text" # Inject lock into file
736
+ npx speclock unguard src/Auth.tsx # Remove file lock
728
737
  npx speclock lock remove <lockId> # Remove a constraint
729
- npx speclock decide "decision text" # Record a decision
730
738
  npx speclock log-change "what changed" # Log a change
731
- npx speclock check "what you plan to do" # Check for conflicts
732
- npx speclock goal "project goal" # Set/update goal
733
- npx speclock note "important note" # Add a note
739
+ npx speclock decide "decision text" # Record a decision
740
+ npx speclock context # Regenerate context file
741
+ npx speclock status # See brain summary
734
742
  \`\`\`
735
743
 
736
744
  ## How It Works
@@ -740,9 +748,94 @@ SpecLock maintains a \`.speclock/\` directory with structured project memory:
740
748
  - \`events.log\` — immutable audit trail
741
749
  - \`context/latest.md\` — human-readable context (read this!)
742
750
 
743
- Every command automatically refreshes the context file so it's always up to date.
751
+ **Guarded files** have a lock warning header injected directly into the source code.
752
+ When you see "SPECLOCK-GUARD" at the top of a file, that file is LOCKED.
744
753
  `;
745
754
  const filePath = path.join(root, "SPECLOCK.md");
746
755
  fs.writeFileSync(filePath, mdContent);
747
756
  return filePath;
748
757
  }
758
+
759
+ // --- File-level lock guard ---
760
+
761
+ const GUARD_MARKERS = {
762
+ js: { start: "// ", block: false },
763
+ ts: { start: "// ", block: false },
764
+ jsx: { start: "// ", block: false },
765
+ tsx: { start: "// ", block: false },
766
+ py: { start: "# ", block: false },
767
+ rb: { start: "# ", block: false },
768
+ sh: { start: "# ", block: false },
769
+ css: { start: "/* ", end: " */", block: true },
770
+ html: { start: "<!-- ", end: " -->", block: true },
771
+ vue: { start: "<!-- ", end: " -->", block: true },
772
+ svelte: { start: "<!-- ", end: " -->", block: true },
773
+ sql: { start: "-- ", block: false },
774
+ };
775
+
776
+ const GUARD_TAG = "SPECLOCK-GUARD";
777
+
778
+ function getCommentStyle(filePath) {
779
+ const ext = path.extname(filePath).slice(1).toLowerCase();
780
+ return GUARD_MARKERS[ext] || { start: "// ", block: false };
781
+ }
782
+
783
+ export function guardFile(root, relativeFilePath, lockText) {
784
+ const fullPath = path.join(root, relativeFilePath);
785
+ if (!fs.existsSync(fullPath)) {
786
+ return { success: false, error: `File not found: ${relativeFilePath}` };
787
+ }
788
+
789
+ const content = fs.readFileSync(fullPath, "utf-8");
790
+ const style = getCommentStyle(fullPath);
791
+
792
+ // Check if already guarded
793
+ if (content.includes(GUARD_TAG)) {
794
+ return { success: false, error: `File already guarded: ${relativeFilePath}` };
795
+ }
796
+
797
+ const warningLines = [
798
+ `${style.start}${"=".repeat(60)}${style.end || ""}`,
799
+ `${style.start}${GUARD_TAG} — DO NOT MODIFY THIS FILE${style.end || ""}`,
800
+ `${style.start}LOCKED BY SPECLOCK: ${lockText}${style.end || ""}`,
801
+ `${style.start}Run "npx speclock check" before ANY changes to this file.${style.end || ""}`,
802
+ `${style.start}If you modify this file, you are VIOLATING a project constraint.${style.end || ""}`,
803
+ `${style.start}${"=".repeat(60)}${style.end || ""}`,
804
+ "",
805
+ ];
806
+
807
+ const guarded = warningLines.join("\n") + content;
808
+ fs.writeFileSync(fullPath, guarded);
809
+
810
+ return { success: true };
811
+ }
812
+
813
+ export function unguardFile(root, relativeFilePath) {
814
+ const fullPath = path.join(root, relativeFilePath);
815
+ if (!fs.existsSync(fullPath)) {
816
+ return { success: false, error: `File not found: ${relativeFilePath}` };
817
+ }
818
+
819
+ const content = fs.readFileSync(fullPath, "utf-8");
820
+ if (!content.includes(GUARD_TAG)) {
821
+ return { success: false, error: `File is not guarded: ${relativeFilePath}` };
822
+ }
823
+
824
+ // Remove everything from first marker line to the blank line after last marker
825
+ const lines = content.split("\n");
826
+ let guardEnd = 0;
827
+ let inGuard = false;
828
+ for (let i = 0; i < lines.length; i++) {
829
+ if (lines[i].includes(GUARD_TAG)) inGuard = true;
830
+ if (inGuard && lines[i].includes("=".repeat(60)) && i > 0) {
831
+ guardEnd = i + 1; // Skip the blank line after
832
+ if (lines[guardEnd] === "") guardEnd++;
833
+ break;
834
+ }
835
+ }
836
+
837
+ const unguarded = lines.slice(guardEnd).join("\n");
838
+ fs.writeFileSync(fullPath, unguarded);
839
+
840
+ return { success: true };
841
+ }