speclock 1.2.1 → 1.3.1

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,6 +1,6 @@
1
1
  # SpecLock
2
2
 
3
- **AI Continuity Engine** — The MCP server that kills AI amnesia.
3
+ **AI Continuity Engine** — MCP server + npm package that kills AI amnesia. Works with Lovable, Claude Code, Cursor, Bolt.new, and more.
4
4
 
5
5
  > Developed by **Sandeep Roy** ([github.com/sgroy10](https://github.com/sgroy10))
6
6
 
@@ -94,7 +94,28 @@ The MCP server gives the AI tools for memory and constraint checking. The projec
94
94
 
95
95
  **Windsurf / Cline / Any MCP tool** — Same pattern as above.
96
96
 
97
- ### 2. Add Project Instructions (Required)
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)
98
119
 
99
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.
100
121
 
@@ -202,7 +223,7 @@ AI: 🔓 Unlocked. Proceeding with auth file changes.
202
223
  | `speclock_checkpoint` | Create named git tag for rollback |
203
224
  | `speclock_repo_status` | Branch, commit, changed files, diff |
204
225
 
205
- ### Intelligence (NEW in v1.1)
226
+ ### Intelligence
206
227
  | Tool | Purpose |
207
228
  |------|---------|
208
229
  | `speclock_suggest_locks` | AI-powered lock suggestions from patterns |
@@ -262,50 +283,67 @@ Multi-Agent Timeline:
262
283
 
263
284
  ## CLI Commands
264
285
 
265
- ```
286
+ ```bash
287
+ # Setup (NEW in v1.3.0)
288
+ speclock setup --goal "Build my app" Full one-shot setup (init + SPECLOCK.md + context)
289
+
290
+ # Memory Management
266
291
  speclock init Initialize SpecLock
267
292
  speclock goal <text> Set project goal
268
293
  speclock lock <text> [--tags a,b] Add a SpecLock constraint
269
294
  speclock lock remove <id> Remove a lock
270
295
  speclock decide <text> Record a decision
271
296
  speclock note <text> Add a note
272
- speclock facts deploy --provider X Set deploy facts
297
+
298
+ # Change Tracking
299
+ speclock log-change <text> --files x Log a significant change (NEW in v1.3.0)
273
300
  speclock context Generate and print context pack
301
+
302
+ # Protection
303
+ speclock check <text> Check for lock conflicts (NEW in v1.3.0)
304
+
305
+ # Other
306
+ speclock facts deploy --provider X Set deploy facts
274
307
  speclock watch Start file watcher
275
308
  speclock serve [--project <path>] Start MCP server
276
309
  speclock status Show brain summary
277
310
  ```
278
311
 
279
- ## Why MCP?
312
+ ## Three Integration Modes
280
313
 
281
- MCP (Model Context Protocol) is the universal integration standard for AI tools. One SpecLock MCP server works with:
314
+ SpecLock works everywhere because it adapts to your platform:
282
315
 
283
- - Claude Code
284
- - Cursor
285
- - Windsurf
286
- - Cline
287
- - Codex
288
- - Any MCP-compatible tool
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 |
289
321
 
290
322
  SpecLock is infrastructure, not a competitor. It makes **every** AI coding tool better.
291
323
 
292
324
  ## Architecture
293
325
 
294
326
  ```
295
- ┌─────────────────────────────────────────────────────────┐
296
- AI Tool (Claude Code, Cursor, etc.)
297
- └────────────────────┬────────────────────────────────────┘
298
- MCP Protocol (stdio)
299
- ┌────────────────────▼────────────────────────────────────┐
300
- │ SpecLock MCP Server (19 tools) │
301
- │ Memory | Tracking | Protection | Git | Intelligence │
302
- └────────────────────┬────────────────────────────────────┘
303
-
304
- .speclock/
305
- ├── brain.json (structured memory)
306
- ├── events.log (immutable audit trail)
307
- ├── patches/ (git diffs per event)
308
- └── context/ (generated context packs)
327
+ ┌─────────────────────────────────────────────────────┐
328
+ AI Tool (Bolt.new, Lovable, Claude Code)
329
+ └──────────────┬──────────────────┬────────────────────┘
330
+
331
+ MCP Protocol File-Based (npm)
332
+ (19 tool calls) (reads SPECLOCK.md +
333
+ .speclock/context/latest.md,
334
+ runs CLI commands)
335
+
336
+ ┌──────────────▼──────────────────▼────────────────────┐
337
+ SpecLock Core Engine │
338
+ │ Memory | Tracking | Protection | Git | Intelligence │
339
+ └──────────────────────┬───────────────────────────────┘
340
+
341
+ .speclock/
342
+ ├── brain.json (structured memory)
343
+ ├── events.log (immutable audit trail)
344
+ ├── patches/ (git diffs per event)
345
+ └── context/
346
+ └── latest.md (human-readable context)
309
347
  ```
310
348
 
311
349
  ## Contributing
@@ -326,4 +364,4 @@ MIT License - see [LICENSE](LICENSE) file.
326
364
 
327
365
  ---
328
366
 
329
- *SpecLock — Because no AI session should ever forget.*
367
+ *SpecLock v1.3.0 — Because no AI session should ever forget.*
@@ -0,0 +1,146 @@
1
+ # SpecLock Project Instructions — Copy-Paste Templates
2
+
3
+ These are **project-level instructions** that you paste into your AI coding platform's settings. They force the AI to use SpecLock on every action — turning it from a passive notepad into an active guardrail.
4
+
5
+ ---
6
+
7
+ ## For Lovable
8
+
9
+ Go to **Project Settings → Knowledge** and paste this:
10
+
11
+ ```
12
+ ## SpecLock Rules (MANDATORY — follow on every message)
13
+
14
+ 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."
15
+
16
+ 2. BEFORE WRITING OR MODIFYING ANY CODE: Call speclock_check_conflict with a description of what you're about to change (e.g., "Adding payment page, creating new route and components" or "Modifying the auth login flow"). 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.
17
+
18
+ 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]"
19
+
20
+ 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.
21
+
22
+ 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.
23
+
24
+ 6. END OF CONVERSATION: Call speclock_session_summary with what was accomplished.
25
+ ```
26
+
27
+ ---
28
+
29
+ ## For Cursor
30
+
31
+ Create or add to `.cursorrules` in your project root:
32
+
33
+ ```
34
+ ## SpecLock Rules (MANDATORY — follow on every message)
35
+
36
+ 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."
37
+
38
+ 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.
39
+
40
+ 3. WHEN I SAY "lock this", "never touch this", "don't change this": Call speclock_add_lock immediately. Confirm: "🔒 Locked: [constraint]"
41
+
42
+ 4. AFTER COMPLETING ANY FEATURE: Call speclock_log_change with a summary and files affected. Call speclock_add_decision if an architectural choice was made.
43
+
44
+ 5. WHEN I ASK TO CHANGE SOMETHING LOCKED: Warn me: "⚠️ This is locked: [constraint]. Unlock and proceed?" Only continue if I confirm.
45
+
46
+ 6. END OF SESSION: Call speclock_session_summary.
47
+ ```
48
+
49
+ ---
50
+
51
+ ## For Claude Code
52
+
53
+ Add to `CLAUDE.md` in your project root:
54
+
55
+ ```
56
+ ## SpecLock Rules (MANDATORY — follow on every message)
57
+
58
+ 1. START OF EVERY CONVERSATION: Call speclock_session_briefing FIRST. Read all locks, decisions, and goals before doing anything else. Show: "🔒 Memory loaded — X locks, Y decisions."
59
+
60
+ 2. BEFORE WRITING OR MODIFYING ANY CODE: Call speclock_check_conflict with what you're about to change. If conflict found (HIGH), STOP and warn me. Do NOT proceed unless I override.
61
+
62
+ 3. WHEN I SAY "lock this", "never touch", "don't change": Call speclock_add_lock. Confirm: "🔒 Locked: [constraint]"
63
+
64
+ 4. AFTER COMPLETING FEATURES: Call speclock_log_change + speclock_add_decision for architectural choices.
65
+
66
+ 5. LOCKED ITEMS: Warn before changing. Only proceed if I confirm unlock.
67
+
68
+ 6. END OF SESSION: Call speclock_session_summary.
69
+ ```
70
+
71
+ ---
72
+
73
+ ## For Windsurf
74
+
75
+ Add to `.windsurfrules` in your project root:
76
+
77
+ ```
78
+ ## SpecLock Rules (MANDATORY — follow on every message)
79
+
80
+ 1. START OF EVERY CONVERSATION: Call speclock_session_briefing FIRST. Show: "🔒 Memory loaded — X locks, Y decisions."
81
+
82
+ 2. BEFORE MODIFYING CODE: Call speclock_check_conflict. If HIGH conflict, STOP and warn me.
83
+
84
+ 3. WHEN I SAY "lock this" / "never touch" / "don't change": Call speclock_add_lock. Confirm: "🔒 Locked: [constraint]"
85
+
86
+ 4. AFTER FEATURES: Call speclock_log_change + speclock_add_decision.
87
+
88
+ 5. LOCKED ITEMS: Warn before changing. Only unlock if I confirm.
89
+
90
+ 6. END: Call speclock_session_summary.
91
+ ```
92
+
93
+ ---
94
+
95
+ ## How It Works In Practice
96
+
97
+ ### Example 1: User locks something
98
+ ```
99
+ User: "Don't ever touch the auth files"
100
+ AI: 🔒 Locked: "Never modify auth files"
101
+ ```
102
+
103
+ ### Example 2: AI checks before changing
104
+ ```
105
+ User: "Add social login to the login page"
106
+ AI: *calls speclock_check_conflict("Modifying auth login page to add social login")*
107
+ ⚠️ This conflicts with your lock: "Never modify auth files"
108
+ Should I proceed anyway, or find another approach?
109
+ ```
110
+
111
+ ### Example 3: New session, full memory
112
+ ```
113
+ User: "Let's keep working on the dashboard"
114
+ AI: *calls speclock_session_briefing*
115
+ 🔒 Memory loaded — 5 locks, 3 decisions, 2 sessions tracked.
116
+ Last session you added the payment page and locked the auth files.
117
+ Ready to work on the dashboard.
118
+ ```
119
+
120
+ ### Example 4: User changes their mind
121
+ ```
122
+ User: "Actually, unlock the auth files, I need to change them"
123
+ AI: You locked: "Never modify auth files". Want me to unlock this?
124
+ User: "Yes"
125
+ AI: 🔓 Unlocked. Proceeding with auth file changes.
126
+ ```
127
+
128
+ ---
129
+
130
+ ## The Complete Setup (2 minutes)
131
+
132
+ ### Lovable:
133
+ 1. Connect SpecLock: Settings → Connectors → Custom → URL: `https://speclock-mcp-production.up.railway.app/mcp` → No auth
134
+ 2. Paste the instruction above into: Project Settings → Knowledge
135
+ 3. Say "initialize speclock" in your first chat
136
+ 4. Done. Every session after: AI auto-checks memory and constraints.
137
+
138
+ ### Cursor:
139
+ 1. Add to `.cursor/mcp.json`: `{"mcpServers":{"speclock":{"command":"npx","args":["-y","speclock","serve","--project","."]}}}`
140
+ 2. Create `.cursorrules` with the instruction above
141
+ 3. Done.
142
+
143
+ ### Claude Code:
144
+ 1. Add to `~/.claude.json` or `.mcp.json`: `{"mcpServers":{"speclock":{"command":"npx","args":["-y","speclock","serve","--project","."]}}}`
145
+ 2. Add the instruction above to `CLAUDE.md`
146
+ 3. Done.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "speclock",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "description": "AI continuity engine — MCP server + CLI that kills AI amnesia. Maintains project memory, enforces constraints, and detects drift across AI coding sessions.",
5
5
  "type": "module",
6
6
  "main": "src/mcp/server.js",
@@ -54,6 +54,7 @@
54
54
  "bin/",
55
55
  "src/",
56
56
  "README.md",
57
+ "SPECLOCK-INSTRUCTIONS.md",
57
58
  "LICENSE"
58
59
  ],
59
60
  "devDependencies": {
package/src/cli/index.js CHANGED
@@ -7,7 +7,10 @@ import {
7
7
  addDecision,
8
8
  addNote,
9
9
  updateDeployFacts,
10
+ logChange,
11
+ checkConflict,
10
12
  watchRepo,
13
+ createSpecLockMd,
11
14
  } from "../core/engine.js";
12
15
  import { generateContext } from "../core/context.js";
13
16
  import { readBrain } from "../core/storage.js";
@@ -52,50 +55,56 @@ function rootDir() {
52
55
  return process.cwd();
53
56
  }
54
57
 
58
+ // --- Auto-regenerate context after write operations ---
59
+
60
+ function refreshContext(root) {
61
+ try {
62
+ generateContext(root);
63
+ } catch (_) {
64
+ // Silently skip if context generation fails
65
+ }
66
+ }
67
+
55
68
  // --- Help text ---
56
69
 
57
70
  function printHelp() {
58
71
  console.log(`
59
- SpecLock v1.1.0 — AI Continuity Engine
72
+ SpecLock v1.3.0 — AI Continuity Engine
60
73
  Developed by Sandeep Roy (github.com/sgroy10)
61
74
 
62
75
  Usage: speclock <command> [options]
63
76
 
64
77
  Commands:
65
- init Initialize SpecLock in current directory
66
- goal <text> Set or update the project goal
67
- lock <text> [--tags a,b] Add a non-negotiable constraint (SpecLock)
68
- lock remove <id> Remove a lock by ID
69
- decide <text> [--tags a,b] Record a decision
70
- note <text> [--pinned] Add a pinned note
71
- facts deploy [--provider X] Set deployment facts
72
- context Generate and print context pack
73
- watch Start file watcher (auto-track changes)
74
- serve [--project <path>] Start MCP stdio server
75
- status Show project brain summary
78
+ setup [--goal <text>] Full setup: init + SPECLOCK.md + context
79
+ init Initialize SpecLock in current directory
80
+ goal <text> Set or update the project goal
81
+ lock <text> [--tags a,b] Add a non-negotiable constraint
82
+ lock remove <id> Remove a lock by ID
83
+ decide <text> [--tags a,b] Record a decision
84
+ note <text> [--pinned] Add a pinned note
85
+ log-change <text> [--files x,y] Log a significant change
86
+ check <text> Check if action conflicts with locks
87
+ context Generate and print context pack
88
+ facts deploy [--provider X] Set deployment facts
89
+ watch Start file watcher (auto-track changes)
90
+ serve [--project <path>] Start MCP stdio server
91
+ status Show project brain summary
76
92
 
77
93
  Options:
78
- --tags <a,b,c> Comma-separated tags
79
- --source <user|agent> Who created this (default: user)
80
- --provider <name> Deploy provider
81
- --branch <name> Deploy branch
82
- --autoDeploy <true|false> Auto-deploy setting
83
- --url <url> Deployment URL
84
- --notes <text> Additional notes
85
- --project <path> Project root (for serve)
94
+ --tags <a,b,c> Comma-separated tags
95
+ --source <user|agent> Who created this (default: user)
96
+ --files <a.ts,b.ts> Comma-separated file paths
97
+ --goal <text> Goal text (for setup command)
98
+ --project <path> Project root (for serve)
86
99
 
87
100
  Examples:
88
- speclock init
89
- speclock goal "Ship v1 of the continuity engine"
90
- speclock lock "No external database in v1" --tags scope
91
- speclock decide "Use MCP as primary integration" --tags architecture
92
- speclock context
93
- speclock serve --project /path/to/repo
94
-
95
- MCP Tools (19): init, get_context, set_goal, add_lock, remove_lock,
96
- add_decision, add_note, set_deploy_facts, log_change, get_changes,
97
- get_events, check_conflict, session_briefing, session_summary,
98
- checkpoint, repo_status, suggest_locks, detect_drift, health
101
+ npx speclock setup --goal "Build PawPalace pet shop"
102
+ npx speclock lock "Never modify auth files"
103
+ npx speclock check "Adding social login to auth page"
104
+ npx speclock log-change "Built payment system" --files src/pay.tsx
105
+ npx speclock decide "Use Supabase for auth"
106
+ npx speclock context
107
+ npx speclock status
99
108
  `);
100
109
  }
101
110
 
@@ -104,7 +113,7 @@ MCP Tools (19): init, get_context, set_goal, add_lock, remove_lock,
104
113
  function showStatus(root) {
105
114
  const brain = readBrain(root);
106
115
  if (!brain) {
107
- console.log("SpecLock not initialized. Run: speclock init");
116
+ console.log("SpecLock not initialized. Run: npx speclock setup");
108
117
  return;
109
118
  }
110
119
 
@@ -113,11 +122,11 @@ function showStatus(root) {
113
122
  console.log(`\nSpecLock Status — ${brain.project.name}`);
114
123
  console.log("=".repeat(50));
115
124
  console.log(`Goal: ${brain.goal.text || "(not set)"}`);
116
- console.log(`SpecLocks: ${activeLocks.length} active`);
125
+ console.log(`Locks: ${activeLocks.length} active`);
117
126
  console.log(`Decisions: ${brain.decisions.length}`);
118
127
  console.log(`Notes: ${brain.notes.length}`);
119
128
  console.log(`Events: ${brain.events.count}`);
120
- console.log(`Deploy: ${brain.facts.deploy.provider}`);
129
+ console.log(`Deploy: ${brain.facts.deploy.provider || "(not set)"}`);
121
130
 
122
131
  if (brain.sessions.current) {
123
132
  console.log(`Session: active (${brain.sessions.current.toolUsed})`);
@@ -133,7 +142,6 @@ function showStatus(root) {
133
142
  }
134
143
 
135
144
  console.log(`Recent changes: ${brain.state.recentChanges.length}`);
136
- console.log(`Reverts: ${brain.state.reverts.length}`);
137
145
  console.log("");
138
146
  }
139
147
 
@@ -148,12 +156,60 @@ async function main() {
148
156
  process.exit(0);
149
157
  }
150
158
 
159
+ // --- SETUP (new: one-shot full setup) ---
160
+ if (cmd === "setup") {
161
+ const flags = parseFlags(args);
162
+ const goalText = flags.goal || flags._.join(" ").trim();
163
+
164
+ // 1. Initialize
165
+ ensureInit(root);
166
+ console.log("Initialized .speclock/ directory.");
167
+
168
+ // 2. Set goal if provided
169
+ if (goalText) {
170
+ setGoal(root, goalText);
171
+ console.log(`Goal set: "${goalText}"`);
172
+ }
173
+
174
+ // 3. Create SPECLOCK.md in project root
175
+ const mdPath = createSpecLockMd(root);
176
+ console.log(`Created SPECLOCK.md (AI instructions file).`);
177
+
178
+ // 4. Generate context
179
+ generateContext(root);
180
+ console.log("Generated .speclock/context/latest.md");
181
+
182
+ // 5. Print summary
183
+ console.log(`
184
+ SpecLock is ready!
185
+
186
+ Files created:
187
+ .speclock/brain.json — Project memory
188
+ .speclock/context/latest.md — Context for AI (read this)
189
+ SPECLOCK.md — AI rules (read this)
190
+
191
+ Next steps:
192
+ The AI should read SPECLOCK.md for rules and
193
+ .speclock/context/latest.md for project context.
194
+
195
+ To add constraints: npx speclock lock "Never touch auth files"
196
+ To check conflicts: npx speclock check "Modifying auth page"
197
+ To log changes: npx speclock log-change "Built landing page"
198
+ To see status: npx speclock status
199
+ `);
200
+ return;
201
+ }
202
+
203
+ // --- INIT ---
151
204
  if (cmd === "init") {
152
205
  ensureInit(root);
153
- console.log("SpecLock initialized.");
206
+ createSpecLockMd(root);
207
+ generateContext(root);
208
+ console.log("SpecLock initialized. Created SPECLOCK.md and context file.");
154
209
  return;
155
210
  }
156
211
 
212
+ // --- GOAL ---
157
213
  if (cmd === "goal") {
158
214
  const text = args.join(" ").trim();
159
215
  if (!text) {
@@ -162,10 +218,12 @@ async function main() {
162
218
  process.exit(1);
163
219
  }
164
220
  setGoal(root, text);
221
+ refreshContext(root);
165
222
  console.log(`Goal set: "${text}"`);
166
223
  return;
167
224
  }
168
225
 
226
+ // --- LOCK ---
169
227
  if (cmd === "lock") {
170
228
  // Check for "lock remove <id>"
171
229
  if (args[0] === "remove") {
@@ -177,6 +235,7 @@ async function main() {
177
235
  }
178
236
  const result = removeLock(root, lockId);
179
237
  if (result.removed) {
238
+ refreshContext(root);
180
239
  console.log(`Lock removed: "${result.lockText}"`);
181
240
  } else {
182
241
  console.error(result.error);
@@ -193,10 +252,12 @@ async function main() {
193
252
  process.exit(1);
194
253
  }
195
254
  const { lockId } = addLock(root, text, parseTags(flags.tags), flags.source || "user");
196
- console.log(`SpecLock added (${lockId}): "${text}"`);
255
+ refreshContext(root);
256
+ console.log(`Locked (${lockId}): "${text}"`);
197
257
  return;
198
258
  }
199
259
 
260
+ // --- DECIDE ---
200
261
  if (cmd === "decide") {
201
262
  const flags = parseFlags(args);
202
263
  const text = flags._.join(" ").trim();
@@ -206,10 +267,12 @@ async function main() {
206
267
  process.exit(1);
207
268
  }
208
269
  const { decId } = addDecision(root, text, parseTags(flags.tags), flags.source || "user");
270
+ refreshContext(root);
209
271
  console.log(`Decision recorded (${decId}): "${text}"`);
210
272
  return;
211
273
  }
212
274
 
275
+ // --- NOTE ---
213
276
  if (cmd === "note") {
214
277
  const flags = parseFlags(args);
215
278
  const text = flags._.join(" ").trim();
@@ -220,10 +283,60 @@ async function main() {
220
283
  }
221
284
  const pinned = flags.pinned !== false;
222
285
  const { noteId } = addNote(root, text, pinned);
286
+ refreshContext(root);
223
287
  console.log(`Note added (${noteId}): "${text}"`);
224
288
  return;
225
289
  }
226
290
 
291
+ // --- LOG-CHANGE (new) ---
292
+ if (cmd === "log-change") {
293
+ const flags = parseFlags(args);
294
+ const text = flags._.join(" ").trim();
295
+ if (!text) {
296
+ console.error("Error: Change summary is required.");
297
+ console.error('Usage: speclock log-change "what changed" --files a.ts,b.ts');
298
+ process.exit(1);
299
+ }
300
+ const files = flags.files ? flags.files.split(",").map((f) => f.trim()).filter(Boolean) : [];
301
+ logChange(root, text, files);
302
+ refreshContext(root);
303
+ console.log(`Change logged: "${text}"`);
304
+ if (files.length > 0) {
305
+ console.log(`Files: ${files.join(", ")}`);
306
+ }
307
+ return;
308
+ }
309
+
310
+ // --- CHECK (new: conflict check) ---
311
+ if (cmd === "check") {
312
+ const text = args.join(" ").trim();
313
+ if (!text) {
314
+ console.error("Error: Action description is required.");
315
+ console.error('Usage: speclock check "what you plan to do"');
316
+ process.exit(1);
317
+ }
318
+ const result = checkConflict(root, text);
319
+ if (result.hasConflict) {
320
+ console.log(`\nCONFLICT DETECTED`);
321
+ console.log("=".repeat(50));
322
+ for (const lock of result.conflictingLocks) {
323
+ console.log(` [${lock.confidence}] "${lock.text}"`);
324
+ console.log(` Confidence: ${lock.score}%`);
325
+ if (lock.reasons && lock.reasons.length > 0) {
326
+ for (const reason of lock.reasons) {
327
+ console.log(` - ${reason}`);
328
+ }
329
+ }
330
+ console.log("");
331
+ }
332
+ console.log(result.analysis);
333
+ } else {
334
+ console.log(`No conflicts found. Safe to proceed with: "${text}"`);
335
+ }
336
+ return;
337
+ }
338
+
339
+ // --- FACTS ---
227
340
  if (cmd === "facts") {
228
341
  const sub = args.shift();
229
342
  if (sub !== "deploy") {
@@ -245,21 +358,25 @@ async function main() {
245
358
  String(flags.autoDeploy).toLowerCase() === "true";
246
359
  }
247
360
  updateDeployFacts(root, payload);
361
+ refreshContext(root);
248
362
  console.log("Deploy facts updated.");
249
363
  return;
250
364
  }
251
365
 
366
+ // --- CONTEXT ---
252
367
  if (cmd === "context") {
253
368
  const md = generateContext(root);
254
369
  console.log(md);
255
370
  return;
256
371
  }
257
372
 
373
+ // --- WATCH ---
258
374
  if (cmd === "watch") {
259
375
  await watchRepo(root);
260
376
  return;
261
377
  }
262
378
 
379
+ // --- SERVE ---
263
380
  if (cmd === "serve") {
264
381
  // Start MCP server — pass through --project if provided
265
382
  const flags = parseFlags(args);
@@ -269,6 +386,7 @@ async function main() {
269
386
  return;
270
387
  }
271
388
 
389
+ // --- STATUS ---
272
390
  if (cmd === "status") {
273
391
  showStatus(root);
274
392
  return;
@@ -696,3 +696,53 @@ export async function watchRepo(root) {
696
696
  console.log("SpecLock watching for changes...");
697
697
  return watcher;
698
698
  }
699
+
700
+ // --- SPECLOCK.md generator (for npm dependency / file-based mode) ---
701
+
702
+ export function createSpecLockMd(root) {
703
+ const mdContent = `# SpecLock — Project Memory Active
704
+
705
+ This project uses **SpecLock** for AI continuity across sessions.
706
+ Read \`.speclock/context/latest.md\` for full project context before making changes.
707
+
708
+ ## Rules (follow on every message)
709
+
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.
711
+
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.
713
+
714
+ 3. **WHEN USER SAYS "lock this", "never touch", "don't change", "always", "critical"**: Run \`npx speclock lock "the exact constraint"\`. Confirm: "Locked: [constraint]"
715
+
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.
717
+
718
+ 5. **WHEN AN ARCHITECTURAL DECISION IS MADE**: Run \`npx speclock decide "the decision"\`
719
+
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>\`
721
+
722
+ ## Quick Reference
723
+
724
+ \`\`\`bash
725
+ npx speclock status # See brain summary
726
+ npx speclock context # Regenerate context file
727
+ npx speclock lock "constraint text" # Add a constraint
728
+ npx speclock lock remove <lockId> # Remove a constraint
729
+ npx speclock decide "decision text" # Record a decision
730
+ 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
734
+ \`\`\`
735
+
736
+ ## How It Works
737
+
738
+ SpecLock maintains a \`.speclock/\` directory with structured project memory:
739
+ - \`brain.json\` — goals, locks, decisions, session history
740
+ - \`events.log\` — immutable audit trail
741
+ - \`context/latest.md\` — human-readable context (read this!)
742
+
743
+ Every command automatically refreshes the context file so it's always up to date.
744
+ `;
745
+ const filePath = path.join(root, "SPECLOCK.md");
746
+ fs.writeFileSync(filePath, mdContent);
747
+ return filePath;
748
+ }