speclock 1.4.0 → 1.5.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
@@ -76,7 +76,7 @@ Or run it yourself:
76
76
  npx speclock setup --goal "Build my app"
77
77
  ```
78
78
 
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.
79
+ **That's it.** SpecLock creates `SPECLOCK.md`, injects a marker into `package.json`, and generates `.speclock/context/latest.md`. The AI reads these automatically and follows the rules. When the AI returns in a new session, it sees the SpecLock marker in `package.json` and knows to check the rules before making changes.
80
80
 
81
81
  ### Lovable (MCP Remote — No Install)
82
82
 
@@ -287,4 +287,4 @@ MIT License - see [LICENSE](LICENSE) file.
287
287
 
288
288
  ---
289
289
 
290
- *SpecLock v1.3.1 — Because remembering isn't enough. AI needs to respect boundaries.*
290
+ *SpecLock v1.5.0 — Because remembering isn't enough. AI needs to respect boundaries.*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "speclock",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
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",
package/src/cli/index.js CHANGED
@@ -13,6 +13,7 @@ import {
13
13
  createSpecLockMd,
14
14
  guardFile,
15
15
  unguardFile,
16
+ injectPackageJsonMarker,
16
17
  } from "../core/engine.js";
17
18
  import { generateContext } from "../core/context.js";
18
19
  import { readBrain } from "../core/storage.js";
@@ -71,7 +72,7 @@ function refreshContext(root) {
71
72
 
72
73
  function printHelp() {
73
74
  console.log(`
74
- SpecLock v1.4.0 — AI Constraint Engine
75
+ SpecLock v1.5.0 — AI Constraint Engine
75
76
  Developed by Sandeep Roy (github.com/sgroy10)
76
77
 
77
78
  Usage: speclock <command> [options]
@@ -181,18 +182,25 @@ async function main() {
181
182
  const mdPath = createSpecLockMd(root);
182
183
  console.log(`Created SPECLOCK.md (AI instructions file).`);
183
184
 
184
- // 4. Generate context
185
+ // 4. Inject marker into package.json (so AI tools auto-discover SpecLock)
186
+ const pkgResult = injectPackageJsonMarker(root);
187
+ if (pkgResult.success) {
188
+ console.log("Injected SpecLock marker into package.json.");
189
+ }
190
+
191
+ // 5. Generate context
185
192
  generateContext(root);
186
193
  console.log("Generated .speclock/context/latest.md");
187
194
 
188
- // 5. Print summary
195
+ // 6. Print summary
189
196
  console.log(`
190
197
  SpecLock is ready!
191
198
 
192
- Files created:
199
+ Files created/updated:
193
200
  .speclock/brain.json — Project memory
194
201
  .speclock/context/latest.md — Context for AI (read this)
195
202
  SPECLOCK.md — AI rules (read this)
203
+ package.json — SpecLock marker added (AI auto-discovery)
196
204
 
197
205
  Next steps:
198
206
  The AI should read SPECLOCK.md for rules and
@@ -210,8 +218,9 @@ Next steps:
210
218
  if (cmd === "init") {
211
219
  ensureInit(root);
212
220
  createSpecLockMd(root);
221
+ injectPackageJsonMarker(root);
213
222
  generateContext(root);
214
- console.log("SpecLock initialized. Created SPECLOCK.md and context file.");
223
+ console.log("SpecLock initialized. Created SPECLOCK.md, updated package.json, and generated context file.");
215
224
  return;
216
225
  }
217
226
 
@@ -702,54 +702,85 @@ export async function watchRepo(root) {
702
702
  export function createSpecLockMd(root) {
703
703
  const mdContent = `# SpecLock — AI Constraint Engine Active
704
704
 
705
- ## MANDATORY: Read this BEFORE doing anything.
705
+ ## STOP Read this before doing ANYTHING.
706
706
 
707
- This project uses **SpecLock** for AI constraint enforcement.
707
+ This project has SpecLock installed. It tracks project memory, goals, constraints (locks), and decisions.
708
708
 
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
709
+ **Step 1:** Read \`.speclock/context/latest.md\` this contains the full project memory.
710
+ **Step 2:** Follow ALL rules below on every message.
713
711
 
714
- **If a file starts with "SPECLOCK-GUARD DO NOT MODIFY" → DO NOT EDIT IT.**
712
+ **If a file contains "SPECLOCK-GUARD" at the top → DO NOT EDIT IT. Period.**
715
713
 
716
- ## Rules (MANDATORY every message, no exceptions)
714
+ ## Returning to This Project? (New Chat Session)
717
715
 
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\`.
716
+ If you are starting a new chat on this project:
717
+ 1. SpecLock is ALREADY installed — do NOT reinstall it
718
+ 2. The \`.speclock/\` directory contains all project memory
719
+ 3. Run \`npx speclock status\` to see the current state
720
+ 4. Read \`.speclock/context/latest.md\` for full context (goals, locks, decisions, history)
721
+ 5. Respect ALL existing locks and constraints before making any changes
719
722
 
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.
723
+ **DO NOT say "SpecLock is not installed" if you can read this file, it IS installed.**
721
724
 
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]"
725
+ ## Your Job (Do This Automatically The User Will NOT Ask)
723
726
 
724
- 4. **AFTER COMPLETING A FEATURE OR CHANGE**: Run \`npx speclock log-change "what was built" --files file1.tsx,file2.ts\`.
727
+ ### On EVERY message:
728
+ Read \`.speclock/context/latest.md\` first. Always. No exceptions.
725
729
 
726
- 5. **WHEN AN ARCHITECTURAL DECISION IS MADE**: Run \`npx speclock decide "the decision"\`
730
+ ### Before changing ANY code:
731
+ Run \`npx speclock check "what you plan to do"\` BEFORE writing code.
732
+ If conflict → STOP. Tell the user. Do NOT proceed.
727
733
 
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.
734
+ ### Detect constraints from natural language:
735
+ Users will NOT say "lock this." They speak naturally. YOU must detect it.
729
736
 
730
- ## Quick Reference
737
+ Examples of what users say → what you do:
738
+
739
+ | User says | You do |
740
+ |-----------|--------|
741
+ | "don't touch the auth" | \`npx speclock lock "Never modify auth files"\` + \`npx speclock guard src/components/Auth.tsx --lock "Never modify auth files"\` |
742
+ | "database is firebase, don't change it" | \`npx speclock lock "Database must always be Firebase"\` |
743
+ | "leave the payment system alone" | \`npx speclock lock "Never modify payment system"\` + guard the payment files |
744
+ | "always use Supabase" | \`npx speclock lock "Always use Supabase"\` |
745
+ | "the API is done, don't mess with it" | \`npx speclock lock "Never modify API endpoints"\` + guard the API files |
746
+
747
+ When you lock something, ALSO guard the specific files:
748
+ \`npx speclock guard <filepath> --lock "the constraint"\`
749
+ This injects a warning directly into the file so it cannot be missed.
750
+
751
+ ### When user wants to change something locked:
752
+ User might say "actually, let me change auth" or "ok modify the database."
753
+ 1. Warn: "This is currently locked: [constraint]. Want me to unlock?"
754
+ 2. If they confirm → \`npx speclock lock remove <lockId>\` + \`npx speclock unguard <file>\`
755
+ 3. Make the changes
756
+ 4. Ask if they want to re-lock: "Want me to lock this again?"
757
+
758
+ ### After building something:
759
+ \`npx speclock log-change "what you built" --files file1.tsx,file2.ts\`
760
+
761
+ ### When a tech decision is made:
762
+ \`npx speclock decide "the decision"\`
763
+
764
+ ## Commands
731
765
 
732
766
  \`\`\`bash
733
- npx speclock check "what you plan to do" # CHECK BEFORE CHANGES
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
737
- npx speclock lock remove <lockId> # Remove a constraint
738
- npx speclock log-change "what changed" # Log a change
739
- npx speclock decide "decision text" # Record a decision
740
- npx speclock context # Regenerate context file
741
- npx speclock status # See brain summary
767
+ npx speclock status # CHECK IF ALREADY SET UP
768
+ npx speclock check "what you plan to do" # ALWAYS RUN BEFORE CHANGES
769
+ npx speclock lock "constraint" # Lock a constraint
770
+ npx speclock guard <file> --lock "constraint" # Protect a specific file
771
+ npx speclock unguard <file> # Remove file protection
772
+ npx speclock lock remove <lockId> # Unlock a constraint
773
+ npx speclock log-change "what changed" # Log changes
774
+ npx speclock decide "decision" # Record a decision
775
+ npx speclock context # Refresh context file
742
776
  \`\`\`
743
777
 
744
- ## How It Works
745
-
746
- SpecLock maintains a \`.speclock/\` directory with structured project memory:
747
- - \`brain.json\` — goals, locks, decisions, session history
748
- - \`events.log\` — immutable audit trail
749
- - \`context/latest.md\` — human-readable context (read this!)
778
+ ## Key Rule
750
779
 
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.
780
+ **The user will NEVER tell you to run these commands. You run them automatically.**
781
+ **The user will NEVER say "lock this." You detect the intent and lock it yourself.**
782
+ **The user will NEVER say "check constraints." You check before EVERY code change.**
783
+ **If this file exists, SpecLock is installed. Do NOT reinstall. Just read the context and follow the rules.**
753
784
  `;
754
785
  const filePath = path.join(root, "SPECLOCK.md");
755
786
  fs.writeFileSync(filePath, mdContent);
@@ -810,6 +841,34 @@ export function guardFile(root, relativeFilePath, lockText) {
810
841
  return { success: true };
811
842
  }
812
843
 
844
+ // --- Package.json marker injection (makes Bolt.new auto-discover SpecLock) ---
845
+
846
+ export function injectPackageJsonMarker(root) {
847
+ const pkgPath = path.join(root, "package.json");
848
+ if (!fs.existsSync(pkgPath)) {
849
+ return { success: false, error: "No package.json found in project root." };
850
+ }
851
+
852
+ try {
853
+ const raw = fs.readFileSync(pkgPath, "utf-8");
854
+ const pkg = JSON.parse(raw);
855
+
856
+ // Add speclock marker
857
+ pkg.speclock = {
858
+ active: true,
859
+ rules: "IMPORTANT: Read SPECLOCK.md before making ANY changes to this project. Read .speclock/context/latest.md for project memory, goals, locks, and decisions. Run 'npx speclock check' before modifying locked files.",
860
+ };
861
+
862
+ // Write back with same formatting
863
+ const indent = raw.match(/^(\s+)/m)?.[1] || " ";
864
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, indent) + "\n");
865
+
866
+ return { success: true };
867
+ } catch (err) {
868
+ return { success: false, error: `Failed to modify package.json: ${err.message}` };
869
+ }
870
+ }
871
+
813
872
  export function unguardFile(root, relativeFilePath) {
814
873
  const fullPath = path.join(root, relativeFilePath);
815
874
  if (!fs.existsSync(fullPath)) {