@luizsantiago/spec-guardrails 3.9.0 → 4.1.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
@@ -3,156 +3,177 @@
3
3
  [![npm version](https://img.shields.io/npm/v/@luizsantiago/spec-guardrails.svg)](https://www.npmjs.com/package/@luizsantiago/spec-guardrails)
4
4
  [![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
5
5
 
6
- **Keep AI coding agents honest — specify the work, prove each step, verify independently.**
6
+ **Governed spec-driven development for AI coding agents.**
7
7
 
8
- npm: [`@luizsantiago/spec-guardrails`](https://www.npmjs.com/package/@luizsantiago/spec-guardrails) **3.9.x**
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.
9
9
 
10
- ---
10
+ npm: [`@luizsantiago/spec-guardrails`](https://www.npmjs.com/package/@luizsantiago/spec-guardrails) **4.1.x**
11
11
 
12
- ## What is Spec Guardrails?
12
+ ---
13
13
 
14
- **Spec Guardrails** is a **process kit** for AI-assisted software development. It does not replace your app, framework, or tests. It gives your agent a repeatable way to work:
14
+ ## What it is
15
15
 
16
- 1. **Write down the goal** before coding (`spec.md`)
17
- 2. **Break work into small jobs** (`tasks.md`)
18
- 3. **Implement in waves** with real checks
19
- 4. **Verify with fresh eyes** — proof, not “trust me”
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:
20
17
 
21
- Everything important lives in **`.specs/`** in your repo so the project remembers decisions across chats and teammates.
18
+ | Layer | Role |
19
+ | --- | --- |
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 |
22
23
 
23
- **You** approve specs and tasks. **The agent** follows phase guides and runs checks. **Gates** (optional Python scripts) can **stop** the workflow when paperwork or evidence is missing.
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.
24
25
 
25
- > **Plain-language guide:** [Overview](docs/guide/Overview.md) · [How it works](docs/guide/How-it-works.md) · [Quick start](docs/guide/Quick-start.md)
26
+ Full narrative: [Overview](docs/guide/Overview.md) · [How it works](docs/guide/How-it-works.md)
26
27
 
27
28
  ---
28
29
 
29
- ## What it is not
30
+ ## Why teams use it
31
+
32
+ | Benefit | Outcome |
33
+ | --- | --- |
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) |
30
40
 
31
- - Not a code generator or a new framework
32
- - Not a vector database or “AI memory” that reads your whole codebase
33
- - Not automatic push/merge/deploy — you stay in control of git tiers
34
- - Not a replacement for code review or product judgment
41
+ Process vs Brakes: [FAQ](docs/guide/FAQ.md#process-vs-brakes) · Guarantees: [Guarantees matrix](docs/guide/Guarantees-matrix.md)
35
42
 
36
43
  ---
37
44
 
38
- ## Install (once per project)
45
+ ## Install
46
+
47
+ In your project root:
39
48
 
40
49
  ```bash
41
50
  npx @luizsantiago/spec-guardrails install
42
51
  ```
43
52
 
44
- | Requirement | Purpose |
53
+ Re-run after upgrading the package; existing `.specs/` notes are preserved. Check readiness with `doctor`.
54
+
55
+ | Requirement | Role |
45
56
  | --- | --- |
46
57
  | **Node.js 18+** | Required — CLI and install |
47
- | **Python 3.10+** | Optional — enables **Brakes mode** (automatic gates). Without Python you still get the full workflow in **Process mode** |
48
-
49
- Re-run `install` after upgrading the package. Your `.specs/` notes and `STATE.md` are kept.
58
+ | **Python 3.10+** | Optional — enables Brakes mode (automatic gates) |
50
59
 
51
- Check readiness: `npx @luizsantiago/spec-guardrails doctor`
52
-
53
- Works with **Cursor, Claude Code, GitHub Copilot, OpenAI Codex**, and other agents via root `AGENTS.md`. See [Platform parity](docs/guide/Platform-parity.md).
60
+ Platform setup: [Platform parity](docs/guide/Platform-parity.md) · Release notes: [CHANGELOG](docs/CHANGELOG.md)
54
61
 
55
62
  ---
56
63
 
57
- ## How you use it day to day
64
+ ## How you work day to day
65
+
66
+ Interaction happens in **agent chat**, not the terminal. The agent runs CLI helpers and gates when needed.
58
67
 
59
- You talk to the agent in **chat**, not the terminal. These are **agent commands** (phrases the agent understands):
68
+ ### Core commands
60
69
 
61
- | Command | When to use |
70
+ | Command | Use when |
62
71
  | --- | --- |
63
- | `/specify` | Start a real feature — written requirements first |
64
- | `/tasks` | Shopping list of jobs after you approve the spec |
65
- | `/loop` | Implement — one wave at a time |
66
- | `/verify` | Proof after the last job — use a **fresh** chat when possible |
67
- | `/quick` | Tiny fix only (≤3 files, no big design decisions) |
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) |
68
79
 
69
80
  **Typical path:** `/specify` → approve → `/tasks` → approve → `/loop` → `/verify` → `/archive`
70
81
 
71
- You do **not** need to memorize CLI commands. The agent runs gates and helpers for you when **Brakes mode** is available.
82
+ When input is still exploratory, `/explore` or `/elicit` may come first. The agent suggests depth; it does not block Specify without approval.
72
83
 
73
- **Full command reference:** [Agent commands](docs/guide/agent-commands.md)
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)
74
85
 
75
- ---
86
+ ### Optional capabilities
76
87
 
77
- ## Two modes (same product)
88
+ Enable when the work warrants them — most teams start with the core loop only.
78
89
 
79
- | Mode | You need | What changes |
80
- | --- | --- | --- |
81
- | **Process** | Node only | Full workflow + `.specs/` memory + phase skills |
82
- | **Brakes** | Node + Python | Same + scripts that **exit non-zero** when specs, tasks, or evidence are incomplete |
83
-
84
- Both are intentional. Add Python when you want automatic stop signs, not just checklists.
90
+ | Capability | Purpose |
91
+ | --- | --- |
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 |
85
100
 
86
- Details: [FAQ → Process vs Brakes](docs/guide/FAQ.md#process-vs-brakes)
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)
87
102
 
88
103
  ---
89
104
 
90
- ## What lands in your repo
105
+ ## What lands in your repository
91
106
 
92
107
  | Path | Role |
93
108
  | --- | --- |
94
- | `.cursor/skills/` (and Claude, Copilot, Codex trees) | Instructions the agent reads per phase |
95
- | `.specs/STATE.md` | Where you are — active feature, next step |
96
- | `.specs/features/NNN-slug/` | Spec, tasks, validation for each feature |
109
+ | `.cursor/skills/` (+ Claude, Copilot, Codex trees) | Phase instructions for the agent |
110
+ | `.specs/STATE.md` | Active feature and next step |
111
+ | `.specs/features/NNN-slug/` | Spec, tasks, and validation per feature |
97
112
  | `.specs/guardrails/scripts/` | Python gates (Brakes mode) |
98
- | `.specs/config.yaml` | Optional project rules and policy |
113
+ | `.specs/config.yaml` | Optional project rules and execution policy |
114
+
115
+ Architecture: [Skills and hub](docs/guide/skills-and-hub.md) · [Architecture](docs/guide/Architecture.md)
99
116
 
100
117
  ---
101
118
 
102
- ## Optional capabilities (use when you need them)
119
+ ## Documentation
103
120
 
104
- Most projects start with Specify → Tasks → Loop → Verify only. Turn these on when the work warrants it:
121
+ Start with the guide that matches your question; each page links deeper where needed.
105
122
 
106
- | Capability | Plain purpose | Learn more |
123
+ | Topic | Start here | Go deeper |
107
124
  | --- | --- | --- |
108
- | **Memory search** | Find text in past specs and validations | [Memory guide](docs/guide/Memory.md) |
109
- | **Context guards** | Check scope before edit or “done” | [Agent commands](docs/guide/agent-commands.md) · **Cursor:** auto via hooks |
110
- | **Episodic memory** | Session notes → episodic → lessons | [Memory → Episodes](docs/guide/Memory.md#episodic-memory-lifecycle) |
111
- | **Code index** | Lightweight brownfield file/symbol map | [Brownfield context](docs/guide/brownfield-context.md) |
112
- | **Sandbox policy** | Block/warn destructive shell commands | [Overview → Safety](docs/guide/Overview.md#safety-and-limits) |
113
- | **Execution policy** | Limit paths, retries, dangerous ops | [Overview → Safety](docs/guide/Overview.md#safety-and-limits) |
114
- | **Solution exploration** | Compare two+ implementations before committing | [Overview → Exploration](docs/guide/Overview.md#optional-exploration-mode) |
115
- | **Semantic retrieval** | Search by meaning (needs OpenAI or Ollama) | [Memory → Semantic](docs/guide/Memory.md#semantic-search-optional) |
125
+ | Orientation | [Overview](docs/guide/Overview.md) | [Concepts](docs/guide/concepts.md) |
126
+ | 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
+ | Process model | [How it works](docs/guide/How-it-works.md) | [Loop patterns](docs/guide/loop-patterns.md) |
129
+ | Enforcement | [Gates](docs/guide/gates.md) | [Gates and guarantees](docs/guide/Gates-and-guarantees.md) |
130
+ | Long-running projects | [Memory](docs/guide/Memory.md) | [Brownfield context](docs/guide/brownfield-context.md) |
131
+ | Questions | [FAQ](docs/guide/FAQ.md) | [Stability policy](docs/guide/Stability-policy.md) |
116
132
 
117
- **Default:** semantic search is **off**. FTS + graph search work without any API.
133
+ Full index: [docs/guide/README.md](docs/guide/README.md)
118
134
 
119
135
  ---
120
136
 
121
- ## Documentation
137
+ ## Contributing
122
138
 
123
- | Start here | Best for |
124
- | --- | --- |
125
- | **[Overview](docs/guide/Overview.md)** | Complete simple picture — workflow, layers, team use |
126
- | [Quick start](docs/guide/Quick-start.md) | First ten minutes |
127
- | [How it works](docs/guide/How-it-works.md) | Story from idea to archive |
128
- | [Memory](docs/guide/Memory.md) | `.specs/` memory and search — when and how much |
129
- | [FAQ](docs/guide/FAQ.md) | Common questions |
139
+ We welcome focused improvements — skills, gates, CLI, docs, and tests. See [CONTRIBUTING.md](CONTRIBUTING.md) for layout, gate stability rules, and local checks.
130
140
 
131
- | Go deeper | Best for |
132
- | --- | --- |
133
- | [Agent commands](docs/guide/agent-commands.md) | Every `/specify`, `/loop`, CLI helper |
134
- | [Guarantees matrix](docs/guide/Guarantees-matrix.md) | Product promises → mechanisms |
135
- | [Gates](docs/guide/gates.md) | What each gate checks |
136
- | [Architecture](docs/guide/Architecture.md) | Core vs platform adapters |
137
- | [Concepts](docs/guide/concepts.md) | Spec-driven, loop, graph, tiers |
138
- | [Changelog](docs/CHANGELOG.md) | Version history |
141
+ ### Use Spec Guardrails to build your contribution
139
142
 
140
- Doc index: [docs/guide/README.md](docs/guide/README.md)
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.
141
144
 
142
- ---
145
+ **In your own project or fork** — use the latest stable release from npm:
146
+
147
+ ```bash
148
+ npx @luizsantiago/spec-guardrails@latest install
149
+ npx @luizsantiago/spec-guardrails doctor
150
+ ```
151
+
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.
143
153
 
144
- ## Upgrading
154
+ **In this source repository** — work against the branch you are developing, not the published tarball:
145
155
 
146
156
  ```bash
147
- npx @luizsantiago/spec-guardrails install
157
+ git clone https://github.com/luizssantiago92/spec-guardrails.git
158
+ cd spec-guardrails
159
+ npm install
160
+ npm run guardrails -- install
161
+ npm run guardrails -- doctor
148
162
  ```
149
163
 
150
- See [CHANGELOG](docs/CHANGELOG.md) for release notes.
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.
165
+
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 |
172
+
173
+ Gate changes follow the adversarial test policy in [CONTRIBUTING.md](CONTRIBUTING.md). Credits: [docs/guide/credits.md](docs/guide/credits.md)
151
174
 
152
175
  ---
153
176
 
154
- ## Contributing · Credits · License
177
+ ## License
155
178
 
156
- - [CONTRIBUTING.md](CONTRIBUTING.md)
157
- - [Credits](docs/guide/credits.md)
158
- - MIT — see [LICENSE](LICENSE)
179
+ MIT — see [LICENSE](LICENSE).
package/index.js CHANGED
@@ -35,6 +35,11 @@ import {
35
35
  listWorkspaces,
36
36
  prepareWorkspaces,
37
37
  } from "./lib/workspace-isolation.js";
38
+ import {
39
+ formatDiscoverReport,
40
+ formatPromoteMessage,
41
+ reqAnalysisInit,
42
+ } from "./lib/req-analysis.js";
38
43
  import {
39
44
  formatExplorationInit,
40
45
  formatExplorationStatus,
@@ -76,6 +81,17 @@ Commands:
76
81
  feature-init "<description>" Allocate NNN-slug feature, STATE, local branch (Tier 0)
77
82
  [--no-branch] Skip git checkout -b
78
83
  [--no-spec] Skip spec.md stub
84
+ req-analysis init "<description>" Scaffold requirements brief (/elicit phase)
85
+ [--scope project|feature] project = macro brief; feature = one delivery (default: feature)
86
+ [--force] Replace existing brief scaffold
87
+ req-analysis discover List local kickoff sources (prd.md, kickoff.md, …)
88
+ req-analysis promote Print next steps after brief approval
89
+ [--scope project|feature] Match the brief scope
90
+ req-analysis validate [brief.md] Gate: approved requirements brief before /specify
91
+ req-analysis context Assemble kickoff + brief context for Specify
92
+ [--scope project|feature] Scope (default: project)
93
+ [--slug <feature-slug>] Feature slug when scope=feature
94
+ [--json] Machine-readable output
79
95
  archive-feature [feature] Fold verified feature into ROADMAP + domain spec; reset STATE
80
96
  [--domain <slug>] Domain folder under .specs/domains/ (default: feature slug)
81
97
  [--skip-verify] Skip validate-state (tests / recovery only)
@@ -157,6 +173,7 @@ Commands:
157
173
  [--json] Machine-readable plan for agents
158
174
  validate-traceability [feature] REQ → tasks → validation coverage chain
159
175
  validate-quick [quick-folder] Quick-mode TASK.md / SUMMARY.md structural gate
176
+ validate-req-analysis [brief.md] Requirements brief gate before /specify (/elicit)
160
177
  validate-state [feature] Completion gate before declaring a feature done
161
178
  check-commit --message "<msg>" Conventional Commits gate
162
179
  lessons <add|list|penalize|prune|promote|graduate|status> Lessons engine
@@ -890,6 +907,98 @@ if (command === "--version" || command === "-v" || command === "version") {
890
907
  console.error(`❌ ${err.message}`);
891
908
  process.exit(1);
892
909
  }
910
+ } else if (command === "req-analysis") {
911
+ try {
912
+ const sub = args[0];
913
+ const rest = args.slice(1);
914
+
915
+ if (sub === "init") {
916
+ let scope = "feature";
917
+ let force = false;
918
+ const positional = [];
919
+ for (let i = 0; i < rest.length; i += 1) {
920
+ const arg = rest[i];
921
+ if (arg === "--force") {
922
+ force = true;
923
+ } else if (arg === "--scope" && rest[i + 1]) {
924
+ scope = rest[i + 1];
925
+ i += 1;
926
+ } else if (arg.startsWith("--scope=")) {
927
+ scope = arg.slice("--scope=".length);
928
+ } else if (!arg.startsWith("--")) {
929
+ positional.push(arg);
930
+ }
931
+ }
932
+ const description = positional.join(" ").trim();
933
+ if (scope === "feature" && !description) {
934
+ throw new Error(
935
+ 'Usage: req-analysis init "<description>" [--scope project|feature] [--force]',
936
+ );
937
+ }
938
+ const result = await reqAnalysisInit(description, { scope, force });
939
+ console.log(`✅ Elicitation scaffold (${result.scope})`);
940
+ for (const briefPath of result.paths) {
941
+ console.log(` ${briefPath}`);
942
+ }
943
+ console.log("");
944
+ console.log(await formatDiscoverReport(process.cwd()));
945
+ } else if (sub === "discover") {
946
+ console.log(await formatDiscoverReport(process.cwd()));
947
+ } else if (sub === "promote") {
948
+ let scope = "feature";
949
+ let description = "";
950
+ for (let i = 0; i < rest.length; i += 1) {
951
+ const arg = rest[i];
952
+ if (arg.startsWith("--scope=")) {
953
+ scope = arg.slice("--scope=".length);
954
+ } else if (arg === "--scope" && rest[i + 1]) {
955
+ scope = rest[i + 1];
956
+ i += 1;
957
+ } else if (!arg.startsWith("--")) {
958
+ description = `${description} ${arg}`.trim();
959
+ }
960
+ }
961
+ console.log(formatPromoteMessage({ scope, description }));
962
+ } else if (sub === "validate") {
963
+ const briefPath = rest.find((arg) => !arg.startsWith("--"));
964
+ const code = await runGate("validate-req-analysis", briefPath ? [briefPath] : []);
965
+ process.exit(code);
966
+ } else if (sub === "context") {
967
+ let scope = "project";
968
+ let slug = "";
969
+ let json = false;
970
+ for (let i = 0; i < rest.length; i += 1) {
971
+ const arg = rest[i];
972
+ if (arg === "--json") {
973
+ json = true;
974
+ } else if (arg === "--scope" && rest[i + 1]) {
975
+ scope = rest[i + 1];
976
+ i += 1;
977
+ } else if (arg.startsWith("--scope=")) {
978
+ scope = arg.slice("--scope=".length);
979
+ } else if (arg === "--slug" && rest[i + 1]) {
980
+ slug = rest[i + 1];
981
+ i += 1;
982
+ } else if (arg.startsWith("--slug=")) {
983
+ slug = arg.slice("--slug=".length);
984
+ }
985
+ }
986
+ const scriptArgs = ["--scope", scope];
987
+ if (slug) {
988
+ scriptArgs.push("--slug", slug);
989
+ }
990
+ if (json) {
991
+ scriptArgs.push("--json");
992
+ }
993
+ const code = await runGuardrailsScript("req-context", scriptArgs);
994
+ process.exit(code);
995
+ } else {
996
+ throw new Error("Usage: req-analysis init | discover | promote | validate | context");
997
+ }
998
+ } catch (err) {
999
+ console.error(`❌ ${err.message}`);
1000
+ process.exit(1);
1001
+ }
893
1002
  } else if (command === "classify-change") {
894
1003
  try {
895
1004
  let json = false;
@@ -26,12 +26,21 @@ const DEPENDENCY_SIGNALS = [
26
26
  /\badd\s+package\b/i,
27
27
  ];
28
28
 
29
+ const VAGUE_SIGNALS = [
30
+ /\bimprove\b/i,
31
+ /\bmake\s+(?:it|this|things?)\s+better\b/i,
32
+ /\badd\s+(?:a\s+)?(?:interface|page|screen|ui|dashboard)\b/i,
33
+ /\b(?:somehow|something|stuff)\b/i,
34
+ /\bwithout\s+(?:criteria|details|spec)\b/i,
35
+ ];
36
+
29
37
  /**
30
38
  * @param {{ description?: string, files?: string[] }} input
31
39
  * @returns {{
32
40
  * tier: "quick" | "simple" | "medium" | "complex",
33
41
  * reasons: string[],
34
42
  * next: string,
43
+ * suggestElicit: boolean,
35
44
  * fileCount: number,
36
45
  * }}
37
46
  */
@@ -45,6 +54,7 @@ export function classifyChange(input = {}) {
45
54
  const hasComplex = COMPLEX_SIGNALS.some((re) => re.test(haystack));
46
55
  const hasMedium = MEDIUM_SIGNALS.some((re) => re.test(haystack));
47
56
  const hasNewDep = DEPENDENCY_SIGNALS.some((re) => re.test(haystack));
57
+ const hasVague = VAGUE_SIGNALS.some((re) => re.test(haystack));
48
58
 
49
59
  if (hasComplex) {
50
60
  reasons.push("sensitive surface or architecture signal in description/paths");
@@ -103,10 +113,15 @@ export function classifyChange(input = {}) {
103
113
  'feature-init → full pipeline (+ /discuss, /plan; optional AppSec/QA on verify)',
104
114
  };
105
115
 
116
+ if (hasVague) {
117
+ reasons.push("vague delivery language — consider /elicit before /specify");
118
+ }
119
+
106
120
  return {
107
121
  tier,
108
122
  reasons,
109
123
  next: nextByTier[tier],
124
+ suggestElicit: hasVague && !hasComplex,
110
125
  fileCount,
111
126
  };
112
127
  }
@@ -123,5 +138,8 @@ export function formatClassifyChange(result) {
123
138
  ...result.reasons.map((r) => ` - ${r}`),
124
139
  `Next: ${result.next}`,
125
140
  ];
141
+ if (result.suggestElicit) {
142
+ lines.push("Suggest: /elicit (structured Q&A) or /specify if scope is already clear");
143
+ }
126
144
  return `${lines.join("\n")}\n`;
127
145
  }
package/lib/constants.js CHANGED
@@ -77,6 +77,7 @@ export const SKILL_ASSETS = [
77
77
  /** @type {{ file: string, remotePath: string }[]} */
78
78
  export const REFERENCE_ASSETS = [
79
79
  { file: "explore.md", remotePath: "skills/references/explore.md" },
80
+ { file: "elicitation.md", remotePath: "skills/references/elicitation.md" },
80
81
  { file: "solution-exploration.md", remotePath: "skills/references/solution-exploration.md" },
81
82
  { file: "project-init.md", remotePath: "skills/references/project-init.md" },
82
83
  { file: "constitution.md", remotePath: "skills/references/constitution.md" },
@@ -117,6 +118,8 @@ export const SCRIPT_ASSETS = [
117
118
  { file: "_memory_embed.py", remotePath: "scripts/_memory_embed.py" },
118
119
  { file: "episodes.py", remotePath: "scripts/episodes.py" },
119
120
  { file: "code_index.py", remotePath: "scripts/code_index.py" },
121
+ { file: "validate_req_analysis.py", remotePath: "scripts/validate_req_analysis.py" },
122
+ { file: "req_context.py", remotePath: "scripts/req_context.py" },
120
123
  ];
121
124
 
122
125
  /** @type {{ file: string, remotePath: string }[]} */
package/lib/gates.js CHANGED
@@ -34,6 +34,7 @@ const GATE_SCRIPTS = {
34
34
  "validate-state": "validate_state.py",
35
35
  "validate-traceability": "validate_traceability.py",
36
36
  "validate-quick": "validate_quick.py",
37
+ "validate-req-analysis": "validate_req_analysis.py",
37
38
  "analyze-artifacts": "analyze_artifacts.py",
38
39
  "check-commit": "check_commit.py",
39
40
  lessons: "lessons.py",
@@ -47,6 +48,7 @@ const AUX_SCRIPTS = {
47
48
  "memory-retrieve": "memory_retrieve.py",
48
49
  episodes: "episodes.py",
49
50
  "code-index": "code_index.py",
51
+ "req-context": "req_context.py",
50
52
  };
51
53
 
52
54
  const GUARDRAILS_SCRIPTS = { ...GATE_SCRIPTS, ...AUX_SCRIPTS };