@luizsantiago/spec-guardrails 4.1.0 → 4.2.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
@@ -5,100 +5,218 @@
5
5
 
6
6
  **Governed spec-driven development for AI coding agents.**
7
7
 
8
- Spec Guardrails is a process kit that installs phase guides, persistent project memory, and optional structural checks into your repository. Teams keep ownership of requirements and approval gates; agents follow a repeatable path from written intent to verified delivery.
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
- npm: [`@luizsantiago/spec-guardrails`](https://www.npmjs.com/package/@luizsantiago/spec-guardrails) **4.1.x**
10
+ npm: [`@luizsantiago/spec-guardrails`](https://www.npmjs.com/package/@luizsantiago/spec-guardrails) **4.2.x**
11
11
 
12
12
  ---
13
13
 
14
- ## What it is
14
+ ## What changes in practice
15
15
 
16
- Spec Guardrails is **not** an application framework, a vector database, or a replacement for your stack. It is an **operating model** for AI-assisted engineering:
17
-
18
- | Layer | Role |
16
+ | Without it | With Spec Guardrails |
19
17
  | --- | --- |
20
- | **Phase guides** | Instructions the agent loads one step at a time |
21
- | **Project memory** | `.specs/` specs, tasks, validation, and state that survive chat sessions |
22
- | **Structural checks** | Optional Python gates that enforce document shape and evidence hooks |
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 |
23
22
 
24
- The default loop is **Specify Tasks Execute Verify → Archive**. You approve specs and task plans; the agent implements in waves and produces proof before work is considered done.
23
+ You stay in charge of scope: the agent proposes, you approve specs, task plans, and anything that touches git beyond local commits.
25
24
 
26
- Full narrative: [Overview](docs/guide/Overview.md) · [How it works](docs/guide/How-it-works.md)
25
+ Read more: [Overview](docs/guide/Overview.md) · [How it works](docs/guide/How-it-works.md) · [Concepts](docs/guide/concepts.md)
27
26
 
28
27
  ---
29
28
 
30
- ## Why teams use it
29
+ ## Install
30
+
31
+ Run once in your project root:
32
+
33
+ ```bash
34
+ npx @luizsantiago/spec-guardrails install
35
+ npx @luizsantiago/spec-guardrails doctor
36
+ ```
37
+
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.
31
39
 
32
- | Benefit | Outcome |
40
+ | Requirement | Role |
33
41
  | --- | --- |
34
- | **Traceability** | Requirements, jobs, and verification live in version-controlled artifacts |
35
- | **Controlled autonomy** | Agents propose and execute; humans approve scope, design forks, and git tiers |
36
- | **Progressive depth** | Quick fixes skip ceremony; complex work gets discuss, design, and task graphs |
37
- | **Platform-agnostic** | Cursor, Claude Code, GitHub Copilot, Codex, and other agents via root `AGENTS.md` |
38
- | **Token efficiency** | One phase guide per turn instead of dumping the entire playbook |
39
- | **Optional enforcement** | Process mode (Node only) or Brakes mode (Node + Python gates) |
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?
46
+
47
+ **Node alone is enough to use everything** every phase, every document, every approval point. The full process runs the same way.
48
+
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.
40
53
 
41
- Process vs Brakes: [FAQ](docs/guide/FAQ.md#process-vs-brakes) · Guarantees: [Guarantees matrix](docs/guide/Guarantees-matrix.md)
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)
42
59
 
43
60
  ---
44
61
 
45
- ## Install
62
+ ## How you use it day to day
46
63
 
47
- In your project root:
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).
48
65
 
49
- ```bash
50
- npx @luizsantiago/spec-guardrails install
66
+ ```
67
+ YOU describe the project or feature
68
+ (chat, prd.md, docs/brief.md, kickoff paste)
69
+
70
+
71
+ ┌──────────────────────┐
72
+ │ READ & CLASSIFY │ Agent reads your inputs and the repo,
73
+ │ │ then sizes the change (see table below).
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.
80
+
81
+ ┌──────────────────────┐
82
+ │ REQUIREMENTS BRIEF │ Captured gaps and decisions in writing.
83
+ └──────────┬───────────┘
84
+
85
+ ◆ YOU APPROVE ◆ (1 of 3 — when elicitation ran)
86
+
87
+
88
+ ┌──────────────────────┐
89
+ │ SPECIFY │ What must happen, what "done" means,
90
+ │ │ what is out of scope → spec.md
91
+ └──────────┬───────────┘
92
+
93
+ ◆ YOU APPROVE ◆ (2 of 3)
94
+
95
+
96
+ ┌──────────────────────┐
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.
107
+ └──────────┬───────────┘
108
+
109
+ ┌──────────────────────┐
110
+ │ VERIFY │ Independent review with proof → validation.md
111
+ └──────────┬───────────┘
112
+
113
+ ┌──────────────────────┐
114
+ │ ARCHIVE │ Fold outcome into project memory.
115
+ └──────────────────────┘
116
+
117
+ Tiny fix (≤3 files, no new dependency)?
118
+ Express lane: build → verify → commit (no spec/tasks ceremony).
51
119
  ```
52
120
 
53
- Re-run after upgrading the package; existing `.specs/` notes are preserved. Check readiness with `doctor`.
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.
54
122
 
55
- | Requirement | Role |
56
- | --- | --- |
57
- | **Node.js 18+** | Required — CLI and install |
58
- | **Python 3.10+** | Optional — enables Brakes mode (automatic gates) |
123
+ Read more: [How it works](docs/guide/How-it-works.md) · [Agent commands](docs/guide/agent-commands.md)
124
+
125
+ ---
126
+
127
+ ## How it sizes the work
128
+
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.
130
+
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 |
59
138
 
60
- Platform setup: [Platform parity](docs/guide/Platform-parity.md) · Release notes: [CHANGELOG](docs/CHANGELOG.md)
139
+ This is also why sessions stay affordable: the agent loads one short guide per step instead of the entire playbook.
140
+
141
+ Read more: [Complexity tiers](docs/guide/concepts.md#complexity-tiers--how-the-agent-chooses-depth) · [Token efficiency](docs/guide/Token-efficiency.md)
61
142
 
62
143
  ---
63
144
 
64
- ## How you work day to day
145
+ ## What is inside the kit
146
+
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.
65
148
 
66
- Interaction happens in **agent chat**, not the terminal. The agent runs CLI helpers and gates when needed.
149
+ ### Artifacts (12)
67
150
 
68
- ### Core commands
151
+ Plain markdown in `.specs/` — the paper trail that survives the chat and reviews like code in git.
69
152
 
70
- | Command | Use when |
153
+ | File | What it holds |
71
154
  | --- | --- |
72
- | `/specify` | Starting any non-trivial feature requirements in writing first |
73
- | `/elicit` | Kickoff or request is vague structured Q&A before Specify *(optional)* |
74
- | `/tasks` | Spec approved break work into a job list |
75
- | `/loop` | Implementation one wave at a time |
76
- | `/verify` | All jobs done independent proof *(prefer a fresh chat)* |
77
- | `/archive` | Feature validated fold into project memory |
78
- | `/quick` | Tiny fix only (≤3 files, no design fork) |
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 |
79
167
 
80
- **Typical path:** `/specify` approve → `/tasks` → approve → `/loop` → `/verify` → `/archive`
168
+ [Architecture](docs/guide/Architecture.md)
81
169
 
82
- When input is still exploratory, `/explore` or `/elicit` may come first. The agent suggests depth; it does not block Specify without approval.
170
+ ### Skills (1 hub + 19 phase guides + 8 specialists)
83
171
 
84
- Command reference: [Agent commands](docs/guide/agent-commands.md) · Entry paths: [Overview Three ways to start](docs/guide/Overview.md#three-ways-to-start-pick-one)
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.
85
173
 
86
- ### Optional capabilities
174
+ [Skills and hub](docs/guide/skills-and-hub.md)
87
175
 
88
- Enable when the work warrants them — most teams start with the core loop only.
176
+ ### Gates (9)
89
177
 
90
- | Capability | Purpose |
178
+ Automatic checks at step boundaries — each one blocks a specific kind of shortcut:
179
+
180
+ | Gate | Stops the agent when… |
91
181
  | --- | --- |
92
- | Memory search | Retrieve past specs, validations, and kickoff briefs |
93
- | Context guards | Scope check before edit or “done” (Cursor: hooks) |
94
- | Episodic memory | Session notes lessons for future runs |
95
- | Code index | Lightweight brownfield file and symbol map |
96
- | Solution exploration | Compare implementation options before committing |
97
- | Sandbox policy | Warn or block destructive shell commands (Cursor hook) |
98
- | Execution policy | Path allowlists, budgets, read/write/delete effects |
99
- | Semantic retrieval | Search by meaning off by default |
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 |
191
+
192
+ → [Gates](docs/guide/gates.md) · [Garantees matrix](docs/guide/Guarantees-matrix.md)
193
+
194
+ ### Requirements analysis
195
+
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.
197
+
198
+ → [Requirements analysis](docs/guide/requirements-analysis.md)
100
199
 
101
- Guides: [Memory](docs/guide/Memory.md) · [Cursor hooks and sandbox](docs/guide/Cursor-hooks-and-sandbox.md) · [Brownfield context](docs/guide/brownfield-context.md)
200
+ ### Loops
201
+
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.
203
+
204
+ → [Loop patterns](docs/guide/loop-patterns.md)
205
+
206
+ ### Memory (6 commands)
207
+
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.
209
+
210
+ → [Memory](docs/guide/Memory.md) · [Brownfield context](docs/guide/brownfield-context.md)
211
+
212
+ ### Optional — off by default
213
+
214
+ | Capability | What it adds |
215
+ | --- | --- |
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 |
218
+
219
+ → [Cursor hooks and sandbox](docs/guide/Cursor-hooks-and-sandbox.md) · [Memory](docs/guide/Memory.md)
102
220
 
103
221
  ---
104
222
 
@@ -109,25 +227,22 @@ Guides: [Memory](docs/guide/Memory.md) · [Cursor hooks and sandbox](docs/guide/
109
227
  | `.cursor/skills/` (+ Claude, Copilot, Codex trees) | Phase instructions for the agent |
110
228
  | `.specs/STATE.md` | Active feature and next step |
111
229
  | `.specs/features/NNN-slug/` | Spec, tasks, and validation per feature |
112
- | `.specs/guardrails/scripts/` | Python gates (Brakes mode) |
230
+ | `.specs/guardrails/scripts/` | Python checks (when Brakes mode is on) |
113
231
  | `.specs/config.yaml` | Optional project rules and execution policy |
114
232
 
115
- Architecture: [Skills and hub](docs/guide/skills-and-hub.md) · [Architecture](docs/guide/Architecture.md)
116
-
117
233
  ---
118
234
 
119
235
  ## Documentation
120
236
 
121
- Start with the guide that matches your question; each page links deeper where needed.
122
-
123
237
  | Topic | Start here | Go deeper |
124
238
  | --- | --- | --- |
125
239
  | Orientation | [Overview](docs/guide/Overview.md) | [Concepts](docs/guide/concepts.md) |
126
240
  | First session | [Quick start](docs/guide/Quick-start.md) | [Agent commands](docs/guide/agent-commands.md) |
127
- | Cursor IDE protection | [Cursor hooks and sandbox](docs/guide/Cursor-hooks-and-sandbox.md) | [Guarantees matrix](docs/guide/Guarantees-matrix.md) |
128
241
  | Process model | [How it works](docs/guide/How-it-works.md) | [Loop patterns](docs/guide/loop-patterns.md) |
129
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) |
130
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) |
131
246
  | Questions | [FAQ](docs/guide/FAQ.md) | [Stability policy](docs/guide/Stability-policy.md) |
132
247
 
133
248
  Full index: [docs/guide/README.md](docs/guide/README.md)
@@ -136,22 +251,18 @@ Full index: [docs/guide/README.md](docs/guide/README.md)
136
251
 
137
252
  ## Contributing
138
253
 
139
- We welcome focused improvements skills, gates, CLI, docs, and tests. See [CONTRIBUTING.md](CONTRIBUTING.md) for layout, gate stability rules, and local checks.
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.
140
255
 
141
- ### Use Spec Guardrails to build your contribution
142
-
143
- The recommended workflow is to **dogfood the product**: install Spec Guardrails, describe your change through the agent phases, implement against approved artifacts, and verify before opening a PR.
144
-
145
- **In your own project or fork** — use the latest stable release from npm:
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:
146
257
 
147
258
  ```bash
148
259
  npx @luizsantiago/spec-guardrails@latest install
149
260
  npx @luizsantiago/spec-guardrails doctor
150
261
  ```
151
262
 
152
- Then in chat: `/specify` (or `/elicit` if scope is unclear) `/tasks` `/loop` `/verify`. Your `.specs/` folder holds the spec and proof that guided the change.
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.
153
264
 
154
- **In this source repository** work against the branch you are developing, not the published tarball:
265
+ **In this source repository**, work against your branch instead of the published package:
155
266
 
156
267
  ```bash
157
268
  git clone https://github.com/luizssantiago92/spec-guardrails.git
@@ -161,16 +272,22 @@ npm run guardrails -- install
161
272
  npm run guardrails -- doctor
162
273
  ```
163
274
 
164
- Edit source under `skills/`, `lib/`, `scripts/`, and `rules/`; re-run `npm run guardrails -- install` after skill or gate changes. Run `npm test` before every PR.
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.
165
276
 
166
- | Path | Role |
167
- | --- | --- |
168
- | `skills/` | Hub and sister skills shipped to consumers |
169
- | `skills/references/` | Phase procedures (`specify.md`, `elicit.md`, …) |
170
- | `scripts/` | Deterministic Python gates |
171
- | `test/` | Node install tests and Python gate suites |
277
+ ---
278
+
279
+ ## Credits
280
+
281
+ Spec Guardrails adapts patterns from open-source work. These are the projects whose ideas are actually shipped in the package:
282
+
283
+ | Project | License | Used for |
284
+ | --- | --- | --- |
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 |
172
289
 
173
- Gate changes follow the adversarial test policy in [CONTRIBUTING.md](CONTRIBUTING.md). Credits: [docs/guide/credits.md](docs/guide/credits.md)
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).
174
291
 
175
292
  ---
176
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
  }
@@ -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 installCursorHooks(cwd, { log });
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.1.0",
4
- "description": "Spec-driven process kit for AI coding agents: write goals in .specs/, break into tasks, implement in waves, verify with proof. Process mode (Node) or Brakes mode (Node + Python gates). Works with Cursor, Claude, Copilot, and Codex.",
3
+ "version": "4.2.0",
4
+ "description": "Governed spec-driven process kit for AI agents: phase guides, .specs/ memory, optional Python gates. Loop: specify, tasks, execute, verify. Cursor hooks opt-in (off by default). Node 18+; Python 3.10+ for Brakes. Cursor, Claude, Copilot, Codex.",
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:** also auto-runs via `.cursor/hooks/` on write/edit tools |
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). In **Brakes mode**, the agent runs Python gates for you.
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
- | `/specify` | **Start here**written requirements |
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
- # Soft OS sandbox (optional — policy, not containers)
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: