@luizsantiago/spec-guardrails 4.1.1 → 4.2.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 +159 -124
- package/index.js +6 -0
- package/lib/cursor-hooks.js +115 -0
- package/lib/install.js +10 -2
- package/package.json +2 -2
- package/skills/agent-architecture.md +13 -2
- package/skills/references/elicitation.md +12 -0
- package/templates/GETTING_STARTED.md +5 -3
- package/templates/config.yaml.example +7 -1
package/README.md
CHANGED
|
@@ -5,27 +5,24 @@
|
|
|
5
5
|
|
|
6
6
|
**Governed spec-driven development for AI coding agents.**
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Spec Guardrails installs a working method into your repository: the agent writes down what it is going to build, gets your approval, implements in small waves, and proves the result before calling it done. Nothing about your stack changes — you get written requirements, a task plan, and verification evidence stored as files in the project.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## What this solves
|
|
13
|
-
|
|
14
|
-
AI agents are fast but forgetful. Ask for a feature and you usually get code with no written requirement, no record of the decisions, no proof it works, and nothing left behind when the chat window closes. The next session starts from zero.
|
|
10
|
+
npm: [`@luizsantiago/spec-guardrails`](https://www.npmjs.com/package/@luizsantiago/spec-guardrails) **4.2.x**
|
|
15
11
|
|
|
16
|
-
|
|
12
|
+
---
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
2. **Break it into jobs** — a checklist you can read and approve.
|
|
20
|
-
3. **Implement in small waves** — one job at a time, each committed.
|
|
21
|
-
4. **Prove it works** — a separate verification pass that did not write the code.
|
|
22
|
-
5. **Keep the record** — spec, decisions, and proof stay in your repo, in git.
|
|
14
|
+
## What changes in practice
|
|
23
15
|
|
|
24
|
-
|
|
16
|
+
| Without it | With Spec Guardrails |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| The agent jumps straight to code and says "done" | Requirements are written and approved first, and "done" needs evidence |
|
|
19
|
+
| Each new chat starts from zero | Specs, decisions, and state live in `.specs/` and survive the session |
|
|
20
|
+
| Small fixes and risky features get the same treatment | The agent measures complexity and applies only the depth the change needs |
|
|
21
|
+
| The whole playbook is pasted into every message | One phase guide is loaded per turn, which keeps cost and focus under control |
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
You stay in charge of scope: the agent proposes, you approve specs, task plans, and anything that touches git beyond local commits.
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
Read more: [Overview](docs/guide/Overview.md) · [How it works](docs/guide/How-it-works.md) · [Concepts](docs/guide/concepts.md)
|
|
29
26
|
|
|
30
27
|
---
|
|
31
28
|
|
|
@@ -38,184 +35,215 @@ npx @luizsantiago/spec-guardrails install
|
|
|
38
35
|
npx @luizsantiago/spec-guardrails doctor
|
|
39
36
|
```
|
|
40
37
|
|
|
41
|
-
`install` writes the agent
|
|
38
|
+
`install` writes the phase guides for your agent and creates the `.specs/` folder. Re-run it after upgrading the package — your existing `.specs/` notes are preserved. After that, you work in **agent chat**, not in the terminal; the agent calls the CLI and checks when needed.
|
|
42
39
|
|
|
43
40
|
| Requirement | Role |
|
|
44
41
|
| --- | --- |
|
|
45
|
-
| **Node.js 18+** | Required —
|
|
46
|
-
| **Python 3.10+** | Optional — turns on
|
|
42
|
+
| **Node.js 18+** | Required — the CLI and the install step |
|
|
43
|
+
| **Python 3.10+** | Optional — turns on automatic proof at each step |
|
|
44
|
+
|
|
45
|
+
### Do you need Python?
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
**Node alone is enough to use everything** — every phase, every document, every approval point. The full process runs the same way.
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
The difference is who decides whether a step is really finished:
|
|
50
|
+
|
|
51
|
+
- **Without Python** — the agent checks its own work by reading the phase checklist. It works, but you are trusting the agent to be honest when it is eager to move on.
|
|
52
|
+
- **With Python** — the same checks run automatically, and the agent **cannot advance** with half-done work: saying "done" without test evidence, writing a task that matches no requirement, or closing a step with an open question all stop the process until fixed.
|
|
53
|
+
|
|
54
|
+
In short: Python turns "trust the agent" into "the agent has to prove it."
|
|
55
|
+
|
|
56
|
+
Which checks exist and what each one requires: [Gates](docs/guide/gates.md) · [Guarantees matrix](docs/guide/Guarantees-matrix.md)
|
|
57
|
+
|
|
58
|
+
Read more: [Quick start](docs/guide/Quick-start.md) · [Platform parity](docs/guide/Platform-parity.md) · [CHANGELOG](docs/CHANGELOG.md)
|
|
51
59
|
|
|
52
60
|
---
|
|
53
61
|
|
|
54
|
-
## How
|
|
62
|
+
## How you use it day to day
|
|
55
63
|
|
|
56
|
-
You
|
|
64
|
+
You describe your project or the feature you want — in chat, or by pointing the agent at a file such as `prd.md` or `docs/brief.md`. With Spec Guardrails already installed, the agent reads that material plus what is already in the repo and picks up from there if work is in progress (`STATE.md` tells it where you left off).
|
|
57
65
|
|
|
58
66
|
```
|
|
59
|
-
YOU describe the
|
|
67
|
+
YOU describe the project or feature
|
|
68
|
+
(chat, prd.md, docs/brief.md, kickoff paste)
|
|
60
69
|
│
|
|
61
70
|
▼
|
|
62
71
|
┌──────────────────────┐
|
|
63
|
-
│
|
|
64
|
-
│ │
|
|
72
|
+
│ READ & CLASSIFY │ Agent reads your inputs and the repo,
|
|
73
|
+
│ │ then sizes the change (see table below).
|
|
65
74
|
└──────────┬───────────┘
|
|
75
|
+
│
|
|
76
|
+
Still vague? ──► Requirements analysis (optional)
|
|
77
|
+
│ Up to 5 questions per round, one topic at a time,
|
|
78
|
+
│ with suggested options — never repeats what your
|
|
79
|
+
│ document already answered.
|
|
66
80
|
▼
|
|
67
81
|
┌──────────────────────┐
|
|
68
|
-
│
|
|
69
|
-
│ │ what is out of scope.
|
|
82
|
+
│ REQUIREMENTS BRIEF │ Captured gaps and decisions in writing.
|
|
70
83
|
└──────────┬───────────┘
|
|
71
84
|
│
|
|
72
|
-
◆ YOU APPROVE ◆
|
|
85
|
+
◆ YOU APPROVE ◆ (1 of 3 — when elicitation ran)
|
|
73
86
|
│
|
|
74
87
|
▼
|
|
75
88
|
┌──────────────────────┐
|
|
76
|
-
│
|
|
77
|
-
│ │
|
|
89
|
+
│ SPECIFY │ What must happen, what "done" means,
|
|
90
|
+
│ │ what is out of scope → spec.md
|
|
78
91
|
└──────────┬───────────┘
|
|
79
92
|
│
|
|
80
|
-
◆ YOU APPROVE ◆
|
|
93
|
+
◆ YOU APPROVE ◆ (2 of 3)
|
|
81
94
|
│
|
|
82
95
|
▼
|
|
83
96
|
┌──────────────────────┐
|
|
84
|
-
│
|
|
85
|
-
│
|
|
97
|
+
│ TASKS │ Small checkable jobs → tasks.md
|
|
98
|
+
│ │ (+ task-graph.md when work can split)
|
|
99
|
+
└──────────┬───────────┘
|
|
100
|
+
│
|
|
101
|
+
◆ YOU APPROVE ◆ (3 of 3)
|
|
102
|
+
│
|
|
103
|
+
▼
|
|
104
|
+
┌──────────────────────┐
|
|
105
|
+
│ BUILD (loop) │ One wave at a time: test, implement,
|
|
106
|
+
│ ↺ │ check, commit — repeat until done.
|
|
86
107
|
└──────────┬───────────┘
|
|
87
108
|
▼
|
|
88
109
|
┌──────────────────────┐
|
|
89
|
-
│
|
|
90
|
-
│ │ code checks it against the spec.
|
|
110
|
+
│ VERIFY │ Independent review with proof → validation.md
|
|
91
111
|
└──────────┬───────────┘
|
|
92
112
|
▼
|
|
93
113
|
┌──────────────────────┐
|
|
94
|
-
│
|
|
95
|
-
│ │ project memory for future runs.
|
|
114
|
+
│ ARCHIVE │ Fold outcome into project memory.
|
|
96
115
|
└──────────────────────┘
|
|
116
|
+
|
|
117
|
+
Tiny fix (≤3 files, no new dependency)?
|
|
118
|
+
Express lane: build → verify → commit (no spec/tasks ceremony).
|
|
97
119
|
```
|
|
98
120
|
|
|
99
|
-
|
|
121
|
+
The agent never skips your approvals on the full path. Requirements analysis is **suggested**, not forced — if the request is already clear, it goes straight to Specify.
|
|
100
122
|
|
|
101
|
-
|
|
123
|
+
Read more: [How it works](docs/guide/How-it-works.md) · [Agent commands](docs/guide/agent-commands.md)
|
|
102
124
|
|
|
103
125
|
---
|
|
104
126
|
|
|
105
|
-
##
|
|
127
|
+
## How it sizes the work
|
|
106
128
|
|
|
107
|
-
|
|
129
|
+
Before starting, the agent classifies the change and loads only what that change needs. A typo does not get a task graph; a payments integration does not skip review.
|
|
108
130
|
|
|
109
|
-
|
|
|
110
|
-
| --- | --- |
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
|
|
|
114
|
-
| New
|
|
115
|
-
|
|
|
131
|
+
| Complexity | Typical scope | What gets created | Your approvals |
|
|
132
|
+
| --- | --- | --- | --- |
|
|
133
|
+
| **Quick** | ≤3 files, no new dependency, no auth/payments | Code + quick evidence | None (express lane) |
|
|
134
|
+
| **Simple** | Small localized change, 2–5 files | `spec.md` → code → `validation.md` | Spec |
|
|
135
|
+
| **Medium** | Real feature, under ~10 jobs | `spec.md`, `tasks.md` → code → `validation.md` → archive | Spec + tasks |
|
|
136
|
+
| **Complex** | New APIs, architecture, infrastructure | Above + `design.md`, option discussion | Spec + tasks (+ design when used) |
|
|
137
|
+
| **Parallel** | Work safely splittable across agents | Above + `task-graph.md` | Spec + tasks |
|
|
116
138
|
|
|
117
|
-
|
|
139
|
+
This is also why sessions stay affordable: the agent loads one short guide per step instead of the entire playbook.
|
|
118
140
|
|
|
119
|
-
|
|
120
|
-
- **Cost and accuracy** — the agent reads one short guide per step instead of the whole playbook. Less context per turn means lower token spend and fewer instructions competing for attention.
|
|
121
|
-
|
|
122
|
-
The agent proposes the depth and explains why; you can always ask for more or less.
|
|
123
|
-
|
|
124
|
-
Deeper: [Overview → Three ways to start](docs/guide/Overview.md#three-ways-to-start-pick-one) · [Loop patterns](docs/guide/loop-patterns.md)
|
|
141
|
+
Read more: [Complexity tiers](docs/guide/concepts.md#complexity-tiers--how-the-agent-chooses-depth) · [Token efficiency](docs/guide/Token-efficiency.md)
|
|
125
142
|
|
|
126
143
|
---
|
|
127
144
|
|
|
128
|
-
## What
|
|
145
|
+
## What is inside the kit
|
|
129
146
|
|
|
130
|
-
Each
|
|
147
|
+
Each block names what ships in the package, how many pieces there are, and what you get from it. Technical detail lives in the linked guides.
|
|
131
148
|
|
|
132
|
-
### Artifacts
|
|
149
|
+
### Artifacts (12)
|
|
133
150
|
|
|
134
|
-
|
|
151
|
+
Plain markdown in `.specs/` — the paper trail that survives the chat and reviews like code in git.
|
|
135
152
|
|
|
136
|
-
|
|
153
|
+
| File | What it holds |
|
|
154
|
+
| --- | --- |
|
|
155
|
+
| `STATE.md` | Active feature, current phase, next step |
|
|
156
|
+
| `requirements-brief.md` | Answers from requirements analysis, signed off by you |
|
|
157
|
+
| `spec.md` | Requirements, acceptance criteria, out of scope |
|
|
158
|
+
| `exploration.md` | Compared solution options (when used) |
|
|
159
|
+
| `design.md` | Technical approach and decisions (when used) |
|
|
160
|
+
| `tasks.md` | Checkable jobs with file ownership |
|
|
161
|
+
| `task-graph.md` | Which jobs can run in parallel (when used) |
|
|
162
|
+
| `validation.md` | Independent verify verdict and proof |
|
|
163
|
+
| `project/PROJECT.md` | Long-lived repo map |
|
|
164
|
+
| `project/ROADMAP.md` | Planned and delivered features |
|
|
165
|
+
| `domains/<slug>/spec.md` | Consolidated domain knowledge after archive |
|
|
166
|
+
| `lessons.json` | Rules learned from past failures |
|
|
137
167
|
|
|
138
|
-
|
|
168
|
+
→ [Architecture](docs/guide/Architecture.md)
|
|
139
169
|
|
|
140
|
-
|
|
170
|
+
### Skills (1 hub + 19 phase guides + 8 specialists)
|
|
171
|
+
|
|
172
|
+
Instructions the agent loads **one at a time** — hub `agent-architecture.md` (router + contract), phase guides such as `specify.md`, `tasks.md`, `implement.md`, `validate.md`, and specialists such as `appsec.md`, `qa-strategy.md`, `security-review.md` when the work needs them.
|
|
141
173
|
|
|
142
174
|
→ [Skills and hub](docs/guide/skills-and-hub.md)
|
|
143
175
|
|
|
144
|
-
### Gates
|
|
176
|
+
### Gates (9)
|
|
177
|
+
|
|
178
|
+
Automatic checks at step boundaries — each one blocks a specific kind of shortcut:
|
|
145
179
|
|
|
146
|
-
|
|
180
|
+
| Gate | Stops the agent when… |
|
|
181
|
+
| --- | --- |
|
|
182
|
+
| `validate-req-analysis` | Requirements brief has open questions or no owner approval |
|
|
183
|
+
| `validate-spec` | Spec has no testable acceptance criteria |
|
|
184
|
+
| `analyze-artifacts` | A requirement has no matching task |
|
|
185
|
+
| `validate-tasks` | Tasks are vague or file ownership conflicts |
|
|
186
|
+
| `validate-traceability` | REQ → task → proof chain is broken |
|
|
187
|
+
| `validate-state` | Feature is declared done without evidence |
|
|
188
|
+
| `validate-quick` | Quick-mode fix broke its size or shape rules |
|
|
189
|
+
| `check-commit` | Commit message does not follow the agreed format |
|
|
190
|
+
| `lessons` | A failed verify tries to skip the lesson step |
|
|
147
191
|
|
|
148
|
-
→ [Gates](docs/guide/gates.md) · [
|
|
192
|
+
→ [Gates](docs/guide/gates.md) · [Garantees matrix](docs/guide/Guarantees-matrix.md)
|
|
149
193
|
|
|
150
|
-
### Requirements analysis
|
|
194
|
+
### Requirements analysis
|
|
151
195
|
|
|
152
|
-
|
|
196
|
+
When the request is still fuzzy, the agent asks a **few targeted questions** — at most five per round, one topic at a time, always with suggested options — and never re-asks what your document already answered. You approve the brief before Specify starts.
|
|
153
197
|
|
|
154
|
-
→ [Requirements analysis](docs/guide/
|
|
198
|
+
→ [Requirements analysis](docs/guide/requirements-analysis.md)
|
|
155
199
|
|
|
156
|
-
### Loops
|
|
200
|
+
### Loops
|
|
157
201
|
|
|
158
|
-
|
|
202
|
+
Implementation happens in **small waves**: pick the next runnable jobs, test, implement, check, commit, repeat. Parallel work only when two jobs touch different files; if tests fail, the agent retries a bounded number of times before escalating to you.
|
|
159
203
|
|
|
160
204
|
→ [Loop patterns](docs/guide/loop-patterns.md)
|
|
161
205
|
|
|
162
|
-
### Memory
|
|
206
|
+
### Memory (6 commands)
|
|
163
207
|
|
|
164
|
-
|
|
208
|
+
`memory-index`, `memory-search`, `memory-query`, `memory-retrieve`, `episodes`, and `code-index` — so a new session or teammate can ask "what did we decide about session timeout?" without you re-explaining. Lessons from verify failures feed back into future runs.
|
|
165
209
|
|
|
166
210
|
→ [Memory](docs/guide/Memory.md) · [Brownfield context](docs/guide/brownfield-context.md)
|
|
167
211
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
## What lands in your repository
|
|
212
|
+
### Optional — off by default
|
|
171
213
|
|
|
172
|
-
|
|
|
214
|
+
| Capability | What it adds |
|
|
173
215
|
| --- | --- |
|
|
174
|
-
|
|
|
175
|
-
|
|
|
176
|
-
| `.specs/features/NNN-slug/` | Spec, job list, and verification per feature |
|
|
177
|
-
| `.specs/guardrails/scripts/` | The check scripts (Brakes mode) |
|
|
178
|
-
| `.specs/config.yaml` | Optional project rules and limits |
|
|
216
|
+
| **Cursor IDE hooks** | Scope check before file edits and shell-command policy on Cursor — disabled by default; requirements analysis can ask if you want them; you can also enable or disable anytime in chat |
|
|
217
|
+
| **Semantic memory search** | Find past specs and decisions by meaning, not just keywords |
|
|
179
218
|
|
|
180
|
-
|
|
219
|
+
→ [Cursor hooks and sandbox](docs/guide/Cursor-hooks-and-sandbox.md) · [Memory](docs/guide/Memory.md)
|
|
181
220
|
|
|
182
221
|
---
|
|
183
222
|
|
|
184
|
-
##
|
|
185
|
-
|
|
186
|
-
Start with the core flow. Turn these on when the work calls for them.
|
|
223
|
+
## What lands in your repository
|
|
187
224
|
|
|
188
|
-
|
|
|
225
|
+
| Path | Role |
|
|
189
226
|
| --- | --- |
|
|
190
|
-
|
|
|
191
|
-
|
|
|
192
|
-
|
|
|
193
|
-
|
|
|
194
|
-
|
|
|
195
|
-
| Semantic retrieval | Search memory by meaning instead of keyword — off by default |
|
|
196
|
-
|
|
197
|
-
### Cursor hooks — optional, and off by default in this repo
|
|
198
|
-
|
|
199
|
-
On **Cursor**, `install` can register IDE hooks that check scope before a file edit and screen shell commands before they run. They are a safety net, not part of the core flow — everything above works without them.
|
|
200
|
-
|
|
201
|
-
Be aware they spawn a short-lived **Node** process per action, which can make the IDE feel heavy on busy sessions, especially on Windows. To reduce or remove that cost, delete the `beforeShellExecution` entry from `.cursor/hooks.json` first, then `preToolUse` if needed.
|
|
202
|
-
|
|
203
|
-
→ [Cursor hooks and sandbox](docs/guide/Cursor-hooks-and-sandbox.md) — what they do, symptoms, tuning, full disable
|
|
227
|
+
| `.cursor/skills/` (+ Claude, Copilot, Codex trees) | Phase instructions for the agent |
|
|
228
|
+
| `.specs/STATE.md` | Active feature and next step |
|
|
229
|
+
| `.specs/features/NNN-slug/` | Spec, tasks, and validation per feature |
|
|
230
|
+
| `.specs/guardrails/scripts/` | Python checks (when Brakes mode is on) |
|
|
231
|
+
| `.specs/config.yaml` | Optional project rules and execution policy |
|
|
204
232
|
|
|
205
233
|
---
|
|
206
234
|
|
|
207
235
|
## Documentation
|
|
208
236
|
|
|
209
|
-
|
|
|
210
|
-
| --- | --- |
|
|
211
|
-
|
|
|
212
|
-
|
|
|
213
|
-
|
|
|
214
|
-
|
|
|
215
|
-
|
|
|
216
|
-
|
|
|
217
|
-
|
|
|
218
|
-
|
|
|
237
|
+
| Topic | Start here | Go deeper |
|
|
238
|
+
| --- | --- | --- |
|
|
239
|
+
| Orientation | [Overview](docs/guide/Overview.md) | [Concepts](docs/guide/concepts.md) |
|
|
240
|
+
| First session | [Quick start](docs/guide/Quick-start.md) | [Agent commands](docs/guide/agent-commands.md) |
|
|
241
|
+
| Process model | [How it works](docs/guide/How-it-works.md) | [Loop patterns](docs/guide/loop-patterns.md) |
|
|
242
|
+
| Enforcement | [Gates](docs/guide/gates.md) | [Gates and guarantees](docs/guide/Gates-and-guarantees.md) |
|
|
243
|
+
| Requirements | [Requirements analysis](docs/guide/requirements-analysis.md) | [Agent commands → /elicit](docs/guide/agent-commands.md) |
|
|
244
|
+
| Long-running projects | [Memory](docs/guide/Memory.md) | [Brownfield context](docs/guide/brownfield-context.md) |
|
|
245
|
+
| Cursor IDE (optional) | [Cursor hooks and sandbox](docs/guide/Cursor-hooks-and-sandbox.md) | [Guarantees matrix](docs/guide/Guarantees-matrix.md) |
|
|
246
|
+
| Questions | [FAQ](docs/guide/FAQ.md) | [Stability policy](docs/guide/Stability-policy.md) |
|
|
219
247
|
|
|
220
248
|
Full index: [docs/guide/README.md](docs/guide/README.md)
|
|
221
249
|
|
|
@@ -223,36 +251,43 @@ Full index: [docs/guide/README.md](docs/guide/README.md)
|
|
|
223
251
|
|
|
224
252
|
## Contributing
|
|
225
253
|
|
|
226
|
-
Focused improvements to skills, gates, CLI, docs, and tests are welcome.
|
|
254
|
+
Focused improvements to skills, gates, CLI, docs, and tests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for repository layout, gate stability rules, and local checks.
|
|
255
|
+
|
|
256
|
+
**Build your contribution with Spec Guardrails.** In your own project or fork, install the latest stable release and let the phases guide the change:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
npx @luizsantiago/spec-guardrails@latest install
|
|
260
|
+
npx @luizsantiago/spec-guardrails doctor
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Describe the change in chat, approve the spec and the task plan, implement, and verify before opening the pull request — the resulting `.specs/` folder is the evidence that supports your PR.
|
|
264
|
+
|
|
265
|
+
**In this source repository**, work against your branch instead of the published package:
|
|
227
266
|
|
|
228
267
|
```bash
|
|
229
268
|
git clone https://github.com/luizssantiago92/spec-guardrails.git
|
|
230
269
|
cd spec-guardrails
|
|
231
270
|
npm install
|
|
232
271
|
npm run guardrails -- install
|
|
233
|
-
npm
|
|
272
|
+
npm run guardrails -- doctor
|
|
234
273
|
```
|
|
235
274
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
We build Spec Guardrails using Spec Guardrails — the recommended contribution workflow, gate stability rules, and the adversarial test policy are in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
275
|
+
Edit sources under `skills/`, `lib/`, `scripts/`, and `rules/`; re-run `npm run guardrails -- install` after changing shipped assets, and run `npm test` before every PR.
|
|
239
276
|
|
|
240
277
|
---
|
|
241
278
|
|
|
242
279
|
## Credits
|
|
243
280
|
|
|
244
|
-
Spec Guardrails adapts patterns from
|
|
281
|
+
Spec Guardrails adapts patterns from open-source work. These are the projects whose ideas are actually shipped in the package:
|
|
245
282
|
|
|
246
|
-
| Project | License |
|
|
283
|
+
| Project | License | Used for |
|
|
247
284
|
| --- | --- | --- |
|
|
248
|
-
| [tlc-spec-driven](https://github.com/tech-leads-club/agent-skills) | CC-BY-4.0 |
|
|
249
|
-
| [addyosmani/agent-skills](https://github.com/addyosmani/agent-skills) | MIT |
|
|
250
|
-
| [graph-engineering](https://github.com/codejunkie99/graph-engineering) | MIT |
|
|
251
|
-
| [loop-engineering](https://github.com/cobusgreyling/loop-engineering) | MIT |
|
|
252
|
-
|
|
253
|
-
Everything else — the Node CLI, the Python gates, the platform adapters, and the requirements analysis phase — is original work in this repository.
|
|
285
|
+
| [tlc-spec-driven](https://github.com/tech-leads-club/agent-skills/tree/main/packages/skills-catalog/skills/(development)/tlc-spec-driven) | CC-BY-4.0 | Spec → tasks → execute → verify model, `.specs/` layout, gate philosophy |
|
|
286
|
+
| [addyosmani/agent-skills](https://github.com/addyosmani/agent-skills) | MIT | Design-discussion patterns and definition-of-done framing |
|
|
287
|
+
| [graph-engineering](https://github.com/codejunkie99/graph-engineering) | MIT | Task-graph rules behind safe parallel waves |
|
|
288
|
+
| [loop-engineering](https://github.com/cobusgreyling/loop-engineering) | MIT | Wave-based execution model |
|
|
254
289
|
|
|
255
|
-
Full lineage, including
|
|
290
|
+
Everything else — the CLI, the Python checks, the platform adapters, and the requirements-analysis phase — is original work in this repository. Full lineage, including references we cite but do not bundle: [Credits and lineage](docs/guide/credits.md).
|
|
256
291
|
|
|
257
292
|
---
|
|
258
293
|
|
package/index.js
CHANGED
|
@@ -67,6 +67,8 @@ Commands:
|
|
|
67
67
|
install Install skills, references, gates and .specs/ memory
|
|
68
68
|
[--preset <name>] Seed .specs/config.yaml from a built-in preset
|
|
69
69
|
[--force-config] Replace existing config.yaml when using --preset
|
|
70
|
+
[--with-cursor-hooks] Register Cursor IDE hooks (off by default)
|
|
71
|
+
[--without-cursor-hooks] Remove shipped Cursor hooks and set cursor.hooks: false
|
|
70
72
|
init-config [--preset <name>] Create .specs/config.yaml (default preset: default)
|
|
71
73
|
[--force] Replace existing config.yaml
|
|
72
74
|
preset list List built-in config presets
|
|
@@ -202,6 +204,10 @@ if (command === "--version" || command === "-v" || command === "version") {
|
|
|
202
204
|
}
|
|
203
205
|
} else if (arg === "--force-config") {
|
|
204
206
|
installOptions.forceConfig = true;
|
|
207
|
+
} else if (arg === "--with-cursor-hooks") {
|
|
208
|
+
installOptions.withCursorHooks = true;
|
|
209
|
+
} else if (arg === "--without-cursor-hooks") {
|
|
210
|
+
installOptions.withoutCursorHooks = true;
|
|
205
211
|
} else {
|
|
206
212
|
throw new Error(`Unknown install flag: ${arg}`);
|
|
207
213
|
}
|
package/lib/cursor-hooks.js
CHANGED
|
@@ -107,3 +107,118 @@ export async function installCursorHooks(cwd, options = {}) {
|
|
|
107
107
|
await fs.writeFile(hooksJsonPath, `${JSON.stringify(merged, null, 2)}\n`, "utf8");
|
|
108
108
|
log(`✅ Cursor hooks → ${CURSOR_HOOKS_JSON} (context-guard + sandbox shell checks)`);
|
|
109
109
|
}
|
|
110
|
+
|
|
111
|
+
/** @type {Set<string>} */
|
|
112
|
+
const SHIPPED_HOOK_COMMANDS = new Set(CURSOR_HOOK_SCRIPTS.map((script) => script.dest));
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Read `cursor.hooks` from `.specs/config.yaml` (default false).
|
|
116
|
+
*
|
|
117
|
+
* @param {string} text
|
|
118
|
+
* @returns {boolean}
|
|
119
|
+
*/
|
|
120
|
+
export function parseCursorHooksFromConfigText(text) {
|
|
121
|
+
const cursorBlock = text.match(/^cursor:\s*\n(?:[ \t#].*\n)*/m);
|
|
122
|
+
if (!cursorBlock) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
const hooksLine = cursorBlock[0].match(/^\s+hooks:\s*(true|false)\s*(?:#.*)?$/m);
|
|
126
|
+
return hooksLine?.[1] === "true";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @param {string} cwd
|
|
131
|
+
* @returns {Promise<boolean>}
|
|
132
|
+
*/
|
|
133
|
+
export async function readCursorHooksEnabled(cwd) {
|
|
134
|
+
try {
|
|
135
|
+
const text = await readFileSafe(path.join(cwd, ".specs/config.yaml"));
|
|
136
|
+
return parseCursorHooksFromConfigText(text);
|
|
137
|
+
} catch {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Persist `cursor.hooks` in `.specs/config.yaml` when the file exists.
|
|
144
|
+
*
|
|
145
|
+
* @param {string} cwd
|
|
146
|
+
* @param {boolean} enabled
|
|
147
|
+
* @returns {Promise<boolean>}
|
|
148
|
+
*/
|
|
149
|
+
export async function writeCursorHooksInConfig(cwd, enabled) {
|
|
150
|
+
const configPath = path.join(cwd, ".specs/config.yaml");
|
|
151
|
+
let text;
|
|
152
|
+
try {
|
|
153
|
+
text = await readFileSafe(configPath);
|
|
154
|
+
} catch {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const cursorBlock = `cursor:\n hooks: ${enabled ? "true" : "false"}\n`;
|
|
159
|
+
|
|
160
|
+
if (/^cursor:/m.test(text)) {
|
|
161
|
+
text = text.replace(/^cursor:\s*\n(?:[ \t#].*\n)*/m, cursorBlock);
|
|
162
|
+
} else {
|
|
163
|
+
text = `${text.replace(/\s+$/, "")}\n\n${cursorBlock}`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
await fs.writeFile(configPath, text, "utf8");
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Resolve whether install should register Cursor hooks.
|
|
172
|
+
*
|
|
173
|
+
* @param {string} cwd
|
|
174
|
+
* @param {{ withCursorHooks?: boolean, withoutCursorHooks?: boolean }} [options]
|
|
175
|
+
* @returns {Promise<boolean>}
|
|
176
|
+
*/
|
|
177
|
+
export async function resolveCursorHooksInstall(cwd, options = {}) {
|
|
178
|
+
if (options.withCursorHooks === true) {
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
if (options.withoutCursorHooks === true || options.withCursorHooks === false) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return readCursorHooksEnabled(cwd);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Remove shipped hook entries and scripts; persist `cursor.hooks: false`.
|
|
189
|
+
*
|
|
190
|
+
* @param {string} cwd
|
|
191
|
+
* @param {{ log?: (message: string) => void }} [options]
|
|
192
|
+
*/
|
|
193
|
+
export async function removeCursorHooks(cwd, options = {}) {
|
|
194
|
+
const log = options.log ?? (() => {});
|
|
195
|
+
const hooksJsonPath = path.join(cwd, CURSOR_HOOKS_JSON);
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
const existing = JSON.parse(await readFileSafe(hooksJsonPath));
|
|
199
|
+
if (existing.hooks && typeof existing.hooks === "object") {
|
|
200
|
+
for (const [event, entries] of Object.entries(existing.hooks)) {
|
|
201
|
+
if (!Array.isArray(entries)) {
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
existing.hooks[event] = entries.filter(
|
|
205
|
+
(entry) => !SHIPPED_HOOK_COMMANDS.has(/** @type {{ command?: string }} */ (entry).command),
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
await fs.writeFile(hooksJsonPath, `${JSON.stringify(existing, null, 2)}\n`, "utf8");
|
|
209
|
+
}
|
|
210
|
+
} catch {
|
|
211
|
+
// hooks.json missing or invalid — still remove scripts below
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
for (const script of CURSOR_HOOK_SCRIPTS) {
|
|
215
|
+
try {
|
|
216
|
+
await fs.unlink(path.join(cwd, script.dest));
|
|
217
|
+
} catch {
|
|
218
|
+
// already absent
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
await writeCursorHooksInConfig(cwd, false);
|
|
223
|
+
log(`✅ Cursor hooks disabled → removed shipped entries from ${CURSOR_HOOKS_JSON}`);
|
|
224
|
+
}
|
package/lib/install.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
resolveAssetOverride,
|
|
14
14
|
} from "./constants.js";
|
|
15
15
|
import { installPlatformAdapters } from "./adapters.js";
|
|
16
|
-
import { installCursorHooks } from "./cursor-hooks.js";
|
|
16
|
+
import { installCursorHooks, removeCursorHooks, resolveCursorHooksInstall, writeCursorHooksInConfig } from "./cursor-hooks.js";
|
|
17
17
|
import { ensureDir, readFileSafe, writeFileIfMissing } from "./fs-utils.js";
|
|
18
18
|
import { hasPython } from "./gates.js";
|
|
19
19
|
import { initGuardrailsMemory } from "./memory.js";
|
|
@@ -119,7 +119,15 @@ export async function install(options = {}) {
|
|
|
119
119
|
await installPlatformAdapters(cwd);
|
|
120
120
|
log("✅ Adapters → .cursorrules, CLAUDE.md, copilot-instructions.md, AGENTS.md, .codex/AGENTS.md");
|
|
121
121
|
|
|
122
|
-
await
|
|
122
|
+
const hooksEnabled = await resolveCursorHooksInstall(cwd, options);
|
|
123
|
+
if (hooksEnabled) {
|
|
124
|
+
await installCursorHooks(cwd, { log });
|
|
125
|
+
await writeCursorHooksInConfig(cwd, true);
|
|
126
|
+
} else if (options.withoutCursorHooks || options.withCursorHooks === false) {
|
|
127
|
+
await removeCursorHooks(cwd, { log });
|
|
128
|
+
} else {
|
|
129
|
+
log("ℹ️ Cursor hooks skipped (off by default). Enable: install --with-cursor-hooks or cursor.hooks: true in .specs/config.yaml");
|
|
130
|
+
}
|
|
123
131
|
|
|
124
132
|
const gettingStartedCreated = await writeFileIfMissing(
|
|
125
133
|
path.join(cwd, ".specs/GETTING_STARTED.md"),
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luizsantiago/spec-guardrails",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"description": "Governed spec-driven
|
|
3
|
+
"version": "4.2.1",
|
|
4
|
+
"description": "Governed spec-driven development for AI coding agents. Your agent writes the spec, gets your approval, builds in small waves, and proves the result — plans and project memory stored as files in your repo.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"spec-guardrails": "./index.js"
|
|
@@ -49,11 +49,11 @@ Structural gates run **before** owner review, so they cannot drift when the mode
|
|
|
49
49
|
| Before Execute waves (3+ tasks) | `npx @luizsantiago/spec-guardrails loop-plan [feature]` |
|
|
50
50
|
| Parallel wave (2+ tasks, disjoint Files) | `npx @luizsantiago/spec-guardrails workspace-prepare [feature] --tasks T1,T2` |
|
|
51
51
|
| After parallel wave merge | `npx @luizsantiago/spec-guardrails workspace-cleanup [feature] --force` |
|
|
52
|
-
| Before editing paths outside task Files | `npx @luizsantiago/spec-guardrails context-guard check-edit <path> [--op write]` — **Cursor:**
|
|
52
|
+
| Before editing paths outside task Files | `npx @luizsantiago/spec-guardrails context-guard check-edit <path> [--op write]` — **Cursor:** optional auto-run via hooks when `cursor.hooks: true` (see below) |
|
|
53
53
|
| Before claiming feature complete | `npx @luizsantiago/spec-guardrails context-guard check-complete [feature]` |
|
|
54
54
|
| Session episodic note | `npx @luizsantiago/spec-guardrails episodes record --summary "…"` |
|
|
55
55
|
| Brownfield code lookup | `npx @luizsantiago/spec-guardrails code-index rebuild` · `code-index search "…"` |
|
|
56
|
-
| Shell safety check | `npx @luizsantiago/spec-guardrails sandbox check-command "<cmd>"` |
|
|
56
|
+
| Shell safety check | `npx @luizsantiago/spec-guardrails sandbox check-command "<cmd>"` — **Cursor:** optional auto-run via hooks when enabled |
|
|
57
57
|
| Solution exploration (explicit) | `npx @luizsantiago/spec-guardrails solution-explore init <feature> --candidates A,B` |
|
|
58
58
|
| Before exploration decision | `npx @luizsantiago/spec-guardrails solution-explore validate [feature]` |
|
|
59
59
|
| Retrieve related context | `npx @luizsantiago/spec-guardrails memory-retrieve "<query>"` |
|
|
@@ -73,6 +73,17 @@ A **non-zero exit means STOP** — fix the artifact, then re-run the gate. Never
|
|
|
73
73
|
|
|
74
74
|
**Process mode (Brakes off).** If Python 3.10+ or shell execution is unavailable, say so once, then perform the same checks by reading the artifact against the reference checklist. Process mode never lowers the standard; it only changes who runs the check. Run `doctor` to see separate **Process** and **Brakes** scores.
|
|
75
75
|
|
|
76
|
+
## Cursor IDE hooks (optional — off by default)
|
|
77
|
+
|
|
78
|
+
Shipped hooks auto-run `context-guard check-edit` and `sandbox check-command` on Cursor. **They are not installed unless the owner opts in** — the core loop and CLI checks work the same without them.
|
|
79
|
+
|
|
80
|
+
| Owner says | Action |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| Enable Cursor hooks | `npx @luizsantiago/spec-guardrails install --with-cursor-hooks` |
|
|
83
|
+
| Disable Cursor hooks | `npx @luizsantiago/spec-guardrails install --without-cursor-hooks` |
|
|
84
|
+
|
|
85
|
+
`/elicit` may ask once on Cursor during the first requirements round. Recommend **off** on low-RAM machines (each edit/shell spawns Node). Details: repository doc [Cursor hooks and sandbox](https://github.com/luizssantiago92/spec-guardrails/blob/main/docs/guide/Cursor-hooks-and-sandbox.md).
|
|
86
|
+
|
|
76
87
|
## Phase Map
|
|
77
88
|
|
|
78
89
|
```
|
|
@@ -108,6 +108,18 @@ Mark covered items: `covered by kickoff.md §…` — **do not ask again**.
|
|
|
108
108
|
| One area per round | UI **or** API **or** data — not all at once |
|
|
109
109
|
| Stop when | Gaps closed, owner says "enough", or Open questions is `- none` |
|
|
110
110
|
|
|
111
|
+
**Cursor IDE hooks (optional, once per project — first elicitation round only):**
|
|
112
|
+
|
|
113
|
+
If the platform is **Cursor** and `.cursor/hooks.json` has no shipped Spec Guardrails entries yet, ask **once**:
|
|
114
|
+
|
|
115
|
+
> "Cursor can run automatic scope checks before file edits and screen shell commands. This is **off by default** (lighter on modest machines). Enable Cursor hooks for this project? A) Yes — run `install --with-cursor-hooks` B) No — keep off (recommended on low-RAM machines) C) Decide later"
|
|
116
|
+
|
|
117
|
+
- **Yes** → `npx @luizsantiago/spec-guardrails install --with-cursor-hooks` (sets `cursor.hooks: true` in config when present).
|
|
118
|
+
- **No** → note in brief or STATE; do not install hooks.
|
|
119
|
+
- **Later** → skip; owner can say "enable Cursor hooks" or "disable Cursor hooks" in chat anytime.
|
|
120
|
+
|
|
121
|
+
Never block Elicitation or Specify on this question.
|
|
122
|
+
|
|
111
123
|
Templates by detected type (ask only relevant dimensions):
|
|
112
124
|
|
|
113
125
|
- **UI** — layout, primary actions, navigation, states
|
|
@@ -16,17 +16,18 @@ You installed the **Spec Guardrails**. You do **not** need to memorize CLI comma
|
|
|
16
16
|
|
|
17
17
|
3. Review `.specs/features/…/spec.md` and **approve** before implementation.
|
|
18
18
|
|
|
19
|
-
**Plain-language guide:** [Overview](https://github.com/luizssantiago92/spec-guardrails/blob/main/docs/guide/Overview.md) · [Memory](https://github.com/luizssantiago92/spec-guardrails/blob/main/docs/guide/Memory.md)
|
|
19
|
+
**Plain-language guide:** [Overview](https://github.com/luizssantiago92/spec-guardrails/blob/main/docs/guide/Overview.md) · [Requirements analysis](https://github.com/luizssantiago92/spec-guardrails/blob/main/docs/guide/requirements-analysis.md) · [Memory](https://github.com/luizssantiago92/spec-guardrails/blob/main/docs/guide/Memory.md)
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
23
|
## Agent commands (chat — not terminal)
|
|
24
24
|
|
|
25
|
-
Type these in **chat** in your agent environment. They load phase procedures from the installed skills tree (e.g. `.cursor/skills/references/`, `.github/skills/references/`, `.codex/skills/references/` — use the tree your agent loads).
|
|
25
|
+
Type these in **chat** in your agent environment. They load phase procedures from the installed skills tree (e.g. `.cursor/skills/references/`, `.github/skills/references/`, `.codex/skills/references/` — use the tree your agent loads). With **Python 3.10+**, the agent runs automatic gates at each step; without Python, the same checks are done manually (Process mode).
|
|
26
26
|
|
|
27
27
|
| Command | When |
|
|
28
28
|
| --- | --- |
|
|
29
|
-
| `/
|
|
29
|
+
| `/elicit` | Request is vague — structured Q&A before Specify (optional) |
|
|
30
|
+
| `/specify` | **Start here** when the goal is clear — written requirements |
|
|
30
31
|
| `/tasks` | Break into jobs after spec approval |
|
|
31
32
|
| `/loop` | Implement — agent runs `loop-plan` each wave |
|
|
32
33
|
| `/verify` | Fresh-context proof after last task |
|
|
@@ -43,6 +44,7 @@ Type these in **chat** in your agent environment. They load phase procedures fro
|
|
|
43
44
|
| Command | When |
|
|
44
45
|
| --- | --- |
|
|
45
46
|
| `install` | First time or upgrade |
|
|
47
|
+
| `install --with-cursor-hooks` | Optional — enable Cursor IDE hooks (off by default on 4.2+) |
|
|
46
48
|
| `project-init` | Brownfield repo (optional) |
|
|
47
49
|
| `doctor` | Install looks broken |
|
|
48
50
|
| `classify-change` / `feature-status` | Pick a tier or see next step |
|
|
@@ -72,7 +72,13 @@ elicitation:
|
|
|
72
72
|
- docs/prd.md
|
|
73
73
|
- .specs/project/kickoff.md
|
|
74
74
|
|
|
75
|
-
#
|
|
75
|
+
# Cursor IDE hooks (optional — off by default; Cursor only)
|
|
76
|
+
# Enable: install --with-cursor-hooks or hooks: true then re-run install
|
|
77
|
+
# Disable: install --without-cursor-hooks
|
|
78
|
+
cursor:
|
|
79
|
+
hooks: false
|
|
80
|
+
|
|
81
|
+
# Soft OS sandbox (optional — policy, not containers; used when hooks are enabled)
|
|
76
82
|
sandbox:
|
|
77
83
|
mode: warn
|
|
78
84
|
deny_patterns:
|