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 +2 -2
- package/package.json +1 -1
- package/src/cli/index.js +14 -5
- package/src/core/engine.js +91 -32
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.**
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
//
|
|
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
|
|
package/src/core/engine.js
CHANGED
|
@@ -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
|
-
##
|
|
705
|
+
## STOP — Read this before doing ANYTHING.
|
|
706
706
|
|
|
707
|
-
This project
|
|
707
|
+
This project has SpecLock installed. It tracks project memory, goals, constraints (locks), and decisions.
|
|
708
708
|
|
|
709
|
-
**
|
|
710
|
-
|
|
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
|
|
712
|
+
**If a file contains "SPECLOCK-GUARD" at the top → DO NOT EDIT IT. Period.**
|
|
715
713
|
|
|
716
|
-
##
|
|
714
|
+
## Returning to This Project? (New Chat Session)
|
|
717
715
|
|
|
718
|
-
|
|
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
|
-
|
|
723
|
+
**DO NOT say "SpecLock is not installed" — if you can read this file, it IS installed.**
|
|
721
724
|
|
|
722
|
-
|
|
725
|
+
## Your Job (Do This Automatically — The User Will NOT Ask)
|
|
723
726
|
|
|
724
|
-
|
|
727
|
+
### On EVERY message:
|
|
728
|
+
Read \`.speclock/context/latest.md\` first. Always. No exceptions.
|
|
725
729
|
|
|
726
|
-
|
|
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
|
-
|
|
734
|
+
### Detect constraints from natural language:
|
|
735
|
+
Users will NOT say "lock this." They speak naturally. YOU must detect it.
|
|
729
736
|
|
|
730
|
-
|
|
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
|
|
734
|
-
npx speclock
|
|
735
|
-
npx speclock
|
|
736
|
-
npx speclock
|
|
737
|
-
npx speclock
|
|
738
|
-
npx speclock
|
|
739
|
-
npx speclock
|
|
740
|
-
npx speclock
|
|
741
|
-
npx speclock
|
|
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
|
-
##
|
|
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
|
-
**
|
|
752
|
-
|
|
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)) {
|