@ericrisco/rsc 0.1.25 → 0.1.27
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 +28 -2
- package/manifest.json +3 -3
- package/package.json +1 -1
- package/scripts/install-apply.js +33 -15
- package/skills/building-agents/SKILL.md +2 -0
- package/skills/design/SKILL.md +2 -0
- package/skills/fastapi/SKILL.md +2 -0
- package/skills/flutter/SKILL.md +2 -0
- package/skills/go/SKILL.md +2 -0
- package/skills/nextjs/SKILL.md +2 -0
- package/skills/postgresdb/SKILL.md +2 -0
- package/skills/react/SKILL.md +2 -0
- package/skills/sdd/SKILL.md +1 -1
- package/skills/specify/SKILL.md +1 -1
- package/skills/suggest/SKILL.md +38 -1
- package/targets/claude.js +18 -1
- package/targets/userprompt-gate.mjs +34 -0
package/README.md
CHANGED
|
@@ -32,6 +32,30 @@ npx @ericrisco/rsc # plain-language wizard — no jargon, installs wh
|
|
|
32
32
|
|
|
33
33
|
---
|
|
34
34
|
|
|
35
|
+
## 🤖 For agents: "install this harness"
|
|
36
|
+
|
|
37
|
+
If you're an AI coding agent (Claude Code, Cursor, Copilot, Codex, Gemini…) and your user
|
|
38
|
+
asked you to **install rsc / this harness / these skills**, run this in the **root of the
|
|
39
|
+
project they're equipping** — not inside a clone of this repo (see the note under *Install*):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx @ericrisco/rsc@latest
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
That launches a plain-language wizard: it asks **which assistants** to target and **what the
|
|
46
|
+
user wants**, reads the repo, then installs the floor (`orient` + `rsc-suggest` + `harness` +
|
|
47
|
+
`init`) plus only the skills that fit — one at a time. No global install and no API key needed.
|
|
48
|
+
|
|
49
|
+
- **Choose assistants non-interactively:** `npx @ericrisco/rsc@latest --target claude` (comma-separate for several).
|
|
50
|
+
- **Already installed, just refreshing skills + hooks:** `rsc sync` (or re-run the command above).
|
|
51
|
+
- **Add one skill by id:** `rsc add <id>` · **browse the catalog:** `rsc consult "<what you want>"` or `rsc list`.
|
|
52
|
+
|
|
53
|
+
From then on it's self-driving: `rsc-suggest` proposes the next skill as tasks appear, and in
|
|
54
|
+
Claude Code a hook re-asserts the spec-first **new-feature gate** on every turn — so a feature
|
|
55
|
+
request routes through `specify` before any skill writes code.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
35
59
|
## Why this exists
|
|
36
60
|
|
|
37
61
|
Most skill packs dump hundreds of files into your context and call it a day. This
|
|
@@ -86,8 +110,10 @@ The first run asks **which assistants** you want — Claude Code, Codex, Copilot
|
|
|
86
110
|
Cursor, Gemini, Windsurf, Cline and 11 more (pick any combination) — and installs
|
|
87
111
|
the **floor**:
|
|
88
112
|
`orient` + `rsc-suggest` (always-on) + `harness` + `init`. In Claude Code it
|
|
89
|
-
also wires a `SessionStart` hook so your assistant proposes new skills on its
|
|
90
|
-
own
|
|
113
|
+
also wires a `SessionStart` hook (so your assistant proposes new skills on its
|
|
114
|
+
own) and a `UserPromptSubmit` hook that re-asserts the **SDD new-feature gate**
|
|
115
|
+
on every turn — so a feature request, in any language, routes through `specify`
|
|
116
|
+
first, before any skill writes code. Opt out per project with `.rsc/.no-feature-gate`.
|
|
91
117
|
|
|
92
118
|
Everything stays **in the project**, and the real skill files are written
|
|
93
119
|
**once** to `.rsc/skills/<id>/`. Each assistant you pick gets a lightweight
|
package/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.27",
|
|
3
3
|
"counts": {
|
|
4
4
|
"skills": 231
|
|
5
5
|
},
|
|
@@ -3666,7 +3666,7 @@
|
|
|
3666
3666
|
},
|
|
3667
3667
|
{
|
|
3668
3668
|
"id": "sdd",
|
|
3669
|
-
"description": "Use when you want a disciplined, spec-driven path from a feature idea to shipped, verified software — the rsc-sdd dispatcher / front door. It states the SDD method, reads the accompaniment dial from 02-DOCS, and routes to the right phase skill: constitution -> specify -> clarify -> plan -> tasks -> analyze -> implement -> verify -> review -> ship, with debug / worktrees / parallel callable on demand. Use it to START a feature, when unsure which SDD phase you are in, or to govern the whole flow. Triggers: 'spec-driven development', 'sdd', 'build this feature properly', 'start a new feature', 'I have an idea, take it to production', 'which phase am I in', 'run the sdd flow', 'desarrollo dirigido por especificación', 'monta esta feature bien', 'de la idea a producción', 'per-phase model routing', 'use a cheaper model for implementation', 'qué modelo por fase'. NOT itself a single phase (it dispatches), NOT the workspace harness (harness), NOT a stack build skill.",
|
|
3669
|
+
"description": "Use when you want a disciplined, spec-driven path from a feature idea to shipped, verified software — the rsc-sdd dispatcher / front door. It states the SDD method, reads the accompaniment dial from 02-DOCS, and routes to the right phase skill: constitution -> specify -> clarify -> plan -> tasks -> analyze -> implement -> verify -> review -> ship, with debug / worktrees / parallel callable on demand. Use it to START a feature, when unsure which SDD phase you are in, or to govern the whole flow. Triggers: 'spec-driven development', 'sdd', 'build this feature properly', 'start a new feature', 'I have an idea, take it to production', 'which phase am I in', 'run the sdd flow', 'desarrollo dirigido por especificación', 'monta esta feature bien', 'munta aquesta feature bé', 'de la idea a producción', 'de la idea a producció', 'fem un SDD per X', 'quina fase soc', 'per-phase model routing', 'use a cheaper model for implementation', 'qué modelo por fase'. NOT itself a single phase (it dispatches), NOT the workspace harness (harness), NOT a stack build skill.",
|
|
3670
3670
|
"tags": [
|
|
3671
3671
|
"sdd",
|
|
3672
3672
|
"spec",
|
|
@@ -3971,7 +3971,7 @@
|
|
|
3971
3971
|
},
|
|
3972
3972
|
{
|
|
3973
3973
|
"id": "specify",
|
|
3974
|
-
"description": "Use when a feature, change, or product idea is still fuzzy and needs brainstorming into an APPROVED spec BEFORE any planning or code — the brainstorming front door of SDD. Turns a one-line intent into a WHAT/WHY spec (problem, goals, users, scope, behaviour, acceptance) with zero implementation detail, via one-question-at-a-time dialogue, 2-3 proposed approaches with a recommendation, and a design the user approves before anything gets built. Triggers: 'write a spec for…', 'spec this out', 'brainstorm this feature', 'especifica esta feature', 'I want to add X', 'tengo una idea', 'se me ha ocurrido', '¿y si…?', 'wouldn't it be nice if…', 'let's think this through', 'what should this feature do', 'draft a PRD', or any moment someone jumps to HOW before WHAT is agreed. NOT the technical plan (that's `plan`), NOT the de-risking ambiguity sweep (that's `clarify`), NOT project-wide principles (that's `constitution`).",
|
|
3974
|
+
"description": "Use when a feature, change, or product idea is still fuzzy and needs brainstorming into an APPROVED spec BEFORE any planning or code — the brainstorming front door of SDD. Turns a one-line intent into a WHAT/WHY spec (problem, goals, users, scope, behaviour, acceptance) with zero implementation detail, via one-question-at-a-time dialogue, 2-3 proposed approaches with a recommendation, and a design the user approves before anything gets built. Triggers: 'write a spec for…', 'spec this out', 'brainstorm this feature', 'especifica esta feature', 'm'agradaria afegir/posar X', 'voldria…', 'vull afegir/fer X', 'es podria afegir…', 'estaria bé que…', 'i si…?', 'I want to add X', 'tengo una idea', 'se me ha ocurrido', '¿y si…?', 'wouldn't it be nice if…', 'let's think this through', 'what should this feature do', 'draft a PRD', or any moment someone jumps to HOW before WHAT is agreed. NOT the technical plan (that's `plan`), NOT the de-risking ambiguity sweep (that's `clarify`), NOT project-wide principles (that's `constitution`).",
|
|
3975
3975
|
"tags": [
|
|
3976
3976
|
"sdd",
|
|
3977
3977
|
"spec",
|
package/package.json
CHANGED
package/scripts/install-apply.js
CHANGED
|
@@ -14,22 +14,37 @@ const CLI_VERSION = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8'))
|
|
|
14
14
|
// materialized at — the single, target-agnostic source of truth for "installed
|
|
15
15
|
// skills version" (read by the SessionStart update check too).
|
|
16
16
|
const versionFile = (cwd) => join(cwd, '.rsc', '.version');
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
|
|
18
|
+
// Per-skill base version. A single global `.rsc/.version` cannot represent a
|
|
19
|
+
// partially-refreshed base set, which broke multi-target sync: the first target's pass
|
|
20
|
+
// bumped `.rsc/.version`, so later targets saw "current" and skipped refreshing their
|
|
21
|
+
// exclusive skills' bases. Tracking the version each base was materialized at makes the
|
|
22
|
+
// refresh decision per skill, independent of target ordering. (Absent file → every base
|
|
23
|
+
// is treated as stale and refreshed once, which self-heals installs from before this.)
|
|
24
|
+
const baseVersionsFile = (cwd) => join(cwd, '.rsc', '.base-versions.json');
|
|
25
|
+
function readBaseVersions(cwd) {
|
|
26
|
+
try { return JSON.parse(readFileSync(baseVersionsFile(cwd), 'utf8')); } catch { return {}; }
|
|
27
|
+
}
|
|
28
|
+
function writeBaseVersions(cwd, versions) {
|
|
29
|
+
mkdirSync(dirname(baseVersionsFile(cwd)), { recursive: true });
|
|
30
|
+
writeFileSync(baseVersionsFile(cwd), JSON.stringify(versions, null, 2) + '\n');
|
|
19
31
|
}
|
|
20
32
|
|
|
21
|
-
// Materialize the real skill files into the project-local base.
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
|
|
33
|
+
// Materialize the real skill files into the project-local base. Copied once and reused;
|
|
34
|
+
// when the recorded base version for THIS skill differs from the CLI version, the base is
|
|
35
|
+
// re-copied so a reinstall/sync actually updates content. Tracked per skill (see
|
|
36
|
+
// baseVersionsFile) so a multi-target sync refreshes every target's bases, not just the
|
|
37
|
+
// first target's. Skills are read-only catalog (user customization lives in 02-DOCS), so
|
|
38
|
+
// overwriting on a version change is safe. Mutates `baseVersions` with the new mark.
|
|
39
|
+
function ensureBase(id, cwd, baseVersions) {
|
|
27
40
|
const dest = baseDir(id, cwd);
|
|
28
|
-
|
|
41
|
+
const stale = baseVersions[id] !== CLI_VERSION;
|
|
42
|
+
if (stale && existsSync(dest)) rmSync(dest, { recursive: true, force: true });
|
|
29
43
|
if (!existsSync(dest)) {
|
|
30
44
|
mkdirSync(dirname(dest), { recursive: true });
|
|
31
45
|
cpSync(join(ROOT, 'skills', id), dest, { recursive: true });
|
|
32
46
|
}
|
|
47
|
+
baseVersions[id] = CLI_VERSION;
|
|
33
48
|
return dest;
|
|
34
49
|
}
|
|
35
50
|
|
|
@@ -46,7 +61,7 @@ function generatedHookFiles({ target, cwd }) {
|
|
|
46
61
|
function managedPathsForInstall({ skillIds, target, home, cwd }) {
|
|
47
62
|
const paths = targetPaths(target, home, cwd);
|
|
48
63
|
const plan = planInstall({ skillIds, target, home, cwd });
|
|
49
|
-
const out = [paths.stateFile, versionFile(cwd)];
|
|
64
|
+
const out = [paths.stateFile, versionFile(cwd), baseVersionsFile(cwd)];
|
|
50
65
|
for (const step of plan) {
|
|
51
66
|
if (step.kind === 'skill') {
|
|
52
67
|
out.push(step.to, baseDir(step.id, cwd));
|
|
@@ -64,18 +79,21 @@ export async function applyInstall({ skillIds, target, home, cwd = process.cwd()
|
|
|
64
79
|
if (dryRun) return { dryRun: true, skills: skillIds, paths: managedPaths };
|
|
65
80
|
const state = readState(paths.stateFile);
|
|
66
81
|
const backup = createBackup({ cwd, operation, target, paths: managedPaths, cliVersion: CLI_VERSION });
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
|
|
82
|
+
// Decide base refresh per skill (see baseVersionsFile): a base is re-materialized when
|
|
83
|
+
// its recorded version differs from the CLI version. Robust to multi-target installs/
|
|
84
|
+
// syncs — a single global marker would be bumped by the first target and make later
|
|
85
|
+
// targets skip refreshing their exclusive skills' bases.
|
|
86
|
+
const baseVersions = readBaseVersions(cwd);
|
|
70
87
|
for (const step of plan) {
|
|
71
88
|
if (step.kind === 'skill') {
|
|
72
|
-
const base = ensureBase(step.id, cwd,
|
|
89
|
+
const base = ensureBase(step.id, cwd, baseVersions);
|
|
73
90
|
const files = await writeSkill(target, step.id, base, step.to);
|
|
74
91
|
state.skills[step.id] = { files, base };
|
|
75
92
|
} else if (step.kind === 'hook') {
|
|
76
|
-
await wireHook(target, paths, join(ensureBase('suggest', cwd,
|
|
93
|
+
await wireHook(target, paths, join(ensureBase('suggest', cwd, baseVersions), 'SKILL.md'));
|
|
77
94
|
}
|
|
78
95
|
}
|
|
96
|
+
writeBaseVersions(cwd, baseVersions);
|
|
79
97
|
state.version = CLI_VERSION;
|
|
80
98
|
writeState(paths.stateFile, state);
|
|
81
99
|
mkdirSync(dirname(versionFile(cwd)), { recursive: true });
|
|
@@ -18,6 +18,8 @@ Build production LLM agents that are model-agnostic by construction — a thin p
|
|
|
18
18
|
|
|
19
19
|
## When to use / When NOT to use
|
|
20
20
|
|
|
21
|
+
> **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
|
|
22
|
+
|
|
21
23
|
**Use when:** starting any production-bound LLM feature; code is hardwired to one SDK and you want to swap/route/fallback models; adding tools/function calling, structured output, or streaming; standing up RAG over Postgres/`pgvector` or an external store; building an eval harness / CI quality gate; adding tracing, cost tracking, caching, or routing/cascades; building or hardening an MCP server.
|
|
22
24
|
|
|
23
25
|
**Do NOT use when:**
|
package/skills/design/SKILL.md
CHANGED
|
@@ -12,6 +12,8 @@ origin: risco
|
|
|
12
12
|
|
|
13
13
|
## When to use / When NOT to use
|
|
14
14
|
|
|
15
|
+
> **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
|
|
16
|
+
|
|
15
17
|
Use when:
|
|
16
18
|
|
|
17
19
|
- Building a new landing or marketing page.
|
package/skills/fastapi/SKILL.md
CHANGED
|
@@ -22,6 +22,8 @@ pip-audit 2.7+, PostgreSQL 16. (All lower bounds; install the latest in each lin
|
|
|
22
22
|
|
|
23
23
|
## When to use
|
|
24
24
|
|
|
25
|
+
> **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
|
|
26
|
+
|
|
25
27
|
- Writing or reviewing any FastAPI route, router, dependency, schema, or app factory.
|
|
26
28
|
- Designing async DB access (SQLAlchemy 2.0), migrations (Alembic), or eager-loading.
|
|
27
29
|
- Adding auth (OAuth2 password flow + JWT), RBAC, password hashing.
|
package/skills/flutter/SKILL.md
CHANGED
|
@@ -22,6 +22,8 @@ subproject — never the FastAPI/Go/Next.js siblings.
|
|
|
22
22
|
|
|
23
23
|
## When to use / When NOT to use
|
|
24
24
|
|
|
25
|
+
> **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
|
|
26
|
+
|
|
25
27
|
**Use when:**
|
|
26
28
|
|
|
27
29
|
- Building a new Flutter feature or screen, or choosing/refactoring state management.
|
package/skills/go/SKILL.md
CHANGED
|
@@ -16,6 +16,8 @@ logging, and fixed loop-variable semantics (no more `tt := tt`).
|
|
|
16
16
|
|
|
17
17
|
## When to use / When NOT to use
|
|
18
18
|
|
|
19
|
+
> **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
|
|
20
|
+
|
|
19
21
|
**Use when:**
|
|
20
22
|
|
|
21
23
|
- Authoring, reviewing, or testing any `.go` file.
|
package/skills/nextjs/SKILL.md
CHANGED
|
@@ -13,6 +13,8 @@ origin: risco
|
|
|
13
13
|
|
|
14
14
|
## When to use / When NOT to use
|
|
15
15
|
|
|
16
|
+
> **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
|
|
17
|
+
|
|
16
18
|
**Use when:**
|
|
17
19
|
|
|
18
20
|
- Editing or creating files under `app/` (pages, layouts, `route.ts`, server actions).
|
|
@@ -14,6 +14,8 @@ example is runnable.
|
|
|
14
14
|
|
|
15
15
|
## When to use / When NOT to use
|
|
16
16
|
|
|
17
|
+
> **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
|
|
18
|
+
|
|
17
19
|
**When to use:**
|
|
18
20
|
|
|
19
21
|
- Schema/DDL decisions: types, keys, constraints, generated/identity columns, enum-vs-lookup, jsonb-vs-column.
|
package/skills/react/SKILL.md
CHANGED
|
@@ -12,6 +12,8 @@ origin: risco
|
|
|
12
12
|
|
|
13
13
|
## When to use
|
|
14
14
|
|
|
15
|
+
> **⚠️ SDD new-feature gate — read this first.** If this skill fired on a **new, non-trivial feature or behaviour change** and there is **no approved spec + plan** under `02-DOCS/wiki/sdd/`, STOP — do **not** write feature code yet. Hand off to `../specify/SKILL.md` first: it runs brainstorm → spec → plan → tasks before any code, then routes back here once the plan is approved. Build here directly only for a genuinely one-line / low-risk change. Method: `../sdd/SKILL.md`.
|
|
16
|
+
|
|
15
17
|
- A repo with `vite.config.{ts,js}` + `react` + `react-dom` and **no** `next` and **no** `@react-router/dev` framework mode — i.e. an SPA.
|
|
16
18
|
- Creating components and deciding **where state lives** (local / lifted / URL / context / store).
|
|
17
19
|
- Wiring **server data**: queries, mutations, caching, optimistic UI.
|
package/skills/sdd/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sdd
|
|
3
|
-
description: "Use when you want a disciplined, spec-driven path from a feature idea to shipped, verified software — the rsc-sdd dispatcher / front door. It states the SDD method, reads the accompaniment dial from 02-DOCS, and routes to the right phase skill: constitution -> specify -> clarify -> plan -> tasks -> analyze -> implement -> verify -> review -> ship, with debug / worktrees / parallel callable on demand. Use it to START a feature, when unsure which SDD phase you are in, or to govern the whole flow. Triggers: 'spec-driven development', 'sdd', 'build this feature properly', 'start a new feature', 'I have an idea, take it to production', 'which phase am I in', 'run the sdd flow', 'desarrollo dirigido por especificación', 'monta esta feature bien', 'de la idea a producción', 'per-phase model routing', 'use a cheaper model for implementation', 'qué modelo por fase'. NOT itself a single phase (it dispatches), NOT the workspace harness (harness), NOT a stack build skill."
|
|
3
|
+
description: "Use when you want a disciplined, spec-driven path from a feature idea to shipped, verified software — the rsc-sdd dispatcher / front door. It states the SDD method, reads the accompaniment dial from 02-DOCS, and routes to the right phase skill: constitution -> specify -> clarify -> plan -> tasks -> analyze -> implement -> verify -> review -> ship, with debug / worktrees / parallel callable on demand. Use it to START a feature, when unsure which SDD phase you are in, or to govern the whole flow. Triggers: 'spec-driven development', 'sdd', 'build this feature properly', 'start a new feature', 'I have an idea, take it to production', 'which phase am I in', 'run the sdd flow', 'desarrollo dirigido por especificación', 'monta esta feature bien', 'munta aquesta feature bé', 'de la idea a producción', 'de la idea a producció', 'fem un SDD per X', 'quina fase soc', 'per-phase model routing', 'use a cheaper model for implementation', 'qué modelo por fase'. NOT itself a single phase (it dispatches), NOT the workspace harness (harness), NOT a stack build skill."
|
|
4
4
|
tags: [sdd, spec, workflow, plan]
|
|
5
5
|
recommends: [sdd-init, constitution, specify]
|
|
6
6
|
profiles: [core, full]
|
package/skills/specify/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: specify
|
|
3
|
-
description: "Use when a feature, change, or product idea is still fuzzy and needs brainstorming into an APPROVED spec BEFORE any planning or code — the brainstorming front door of SDD. Turns a one-line intent into a WHAT/WHY spec (problem, goals, users, scope, behaviour, acceptance) with zero implementation detail, via one-question-at-a-time dialogue, 2-3 proposed approaches with a recommendation, and a design the user approves before anything gets built. Triggers: 'write a spec for…', 'spec this out', 'brainstorm this feature', 'especifica esta feature', 'I want to add X', 'tengo una idea', 'se me ha ocurrido', '¿y si…?', 'wouldn't it be nice if…', 'let's think this through', 'what should this feature do', 'draft a PRD', or any moment someone jumps to HOW before WHAT is agreed. NOT the technical plan (that's `plan`), NOT the de-risking ambiguity sweep (that's `clarify`), NOT project-wide principles (that's `constitution`)."
|
|
3
|
+
description: "Use when a feature, change, or product idea is still fuzzy and needs brainstorming into an APPROVED spec BEFORE any planning or code — the brainstorming front door of SDD. Turns a one-line intent into a WHAT/WHY spec (problem, goals, users, scope, behaviour, acceptance) with zero implementation detail, via one-question-at-a-time dialogue, 2-3 proposed approaches with a recommendation, and a design the user approves before anything gets built. Triggers: 'write a spec for…', 'spec this out', 'brainstorm this feature', 'especifica esta feature', 'm'agradaria afegir/posar X', 'voldria…', 'vull afegir/fer X', 'es podria afegir…', 'estaria bé que…', 'i si…?', 'I want to add X', 'tengo una idea', 'se me ha ocurrido', '¿y si…?', 'wouldn't it be nice if…', 'let's think this through', 'what should this feature do', 'draft a PRD', or any moment someone jumps to HOW before WHAT is agreed. NOT the technical plan (that's `plan`), NOT the de-risking ambiguity sweep (that's `clarify`), NOT project-wide principles (that's `constitution`)."
|
|
4
4
|
tags: [sdd, spec, requirements]
|
|
5
5
|
recommends: [clarify, plan]
|
|
6
6
|
profiles: [core, full]
|
package/skills/suggest/SKILL.md
CHANGED
|
@@ -8,7 +8,44 @@ profiles: [minimal, core, full]
|
|
|
8
8
|
|
|
9
9
|
# rsc-suggest — detect & install the skill the task needs
|
|
10
10
|
|
|
11
|
-
You are always loaded
|
|
11
|
+
You are always loaded — your body is injected into context at the start of **every** session, and again after every compaction, so you are the one piece guaranteed to be present *before any other skill is matched*. That makes you the **always-on layer**. You do two jobs, in this order:
|
|
12
|
+
|
|
13
|
+
1. **Route new-feature intent into SDD before any code is written** — the new-feature gate below. This is your first duty; it runs before everything else.
|
|
14
|
+
2. **Keep the session equipped** — detect when the task needs an rsc skill that is **not installed**, name it, and install it on confirm.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## The new-feature gate (always-on — runs before any other skill)
|
|
19
|
+
|
|
20
|
+
This is the **highest-precedence rule in the session.** It fires on **every** user turn, in **any language**, and runs **before you plan, answer, or invoke ANY other skill — no matter how many skills are installed or how strongly one of them matches the request.** That covers the stack skills (`nextjs`, `react`, `fastapi`, `flutter`, `go`, `postgresdb`, `building-agents`, `design`) **and any other skill that would build, create, scaffold, generate, or produce the feature** (e.g. `chatbot`, `course-builder`, `marketing`, automation/connector skills). A skill matching the request does **not** override this gate — it runs *inside* the SDD chain, after the plan is approved. There is no skill with priority over this check.
|
|
21
|
+
|
|
22
|
+
**The rule (non-negotiable).** The moment the user wants to **build, add, or change a feature**, you MUST route it into SDD via `specify` **first**. **No feature code is written — by ANY skill — until a spec AND a plan exist and the user has approved them.** A stack skill that matched the same request does **not** get to skip this: it builds only *after* the plan is approved.
|
|
23
|
+
|
|
24
|
+
**Where does this turn go? When unsure, choose `specify` — the safe default.**
|
|
25
|
+
|
|
26
|
+
| The turn is… | Route to |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| A new feature / capability / integration / UI, a behaviour change, a data-model or architecture change, "it should also…", anything non-trivial | **`specify`** → `clarify` → `plan` → `tasks` → `implement` (which fans work out to subagents via `parallel`) |
|
|
29
|
+
| A genuinely one-line / low-risk change: typo, copy tweak, config bump, rename, non-breaking dependency bump | Just do it inline, then verify — and **say out loud** you are skipping the chain |
|
|
30
|
+
| A bug fix that restores intended behaviour | **`debug`**, then resume |
|
|
31
|
+
| Ambiguous / in-between / you cannot tell | **`specify`** — a skipped spec is where drift hides |
|
|
32
|
+
|
|
33
|
+
**Triggers — detect the *intent*, never a fixed phrase, in ANY language.** What fires the gate is the **meaning**, not the words: the user wants something to exist or behave differently than it does now — build, add, create, change, replace, integrate, "it should also…", "wouldn't it be nice if…". This is judged **semantically**, so it holds in **any language** — Catalan, Spanish, English, Portuguese, French, Italian, German, Basque, Galician, or anything else, including a language with no example below. The lists that follow are **illustrative examples, NOT a checklist**: never wait for one of these phrases to appear before firing. If the meaning is feature-shaped, the gate fires — full stop.
|
|
34
|
+
- **CA:** "m'agradaria afegir/posar…", "vull fer/posar…", "es podria…", "i si…".
|
|
35
|
+
- **ES:** "quiero añadir/montar…", "me gustaría…", "se me ha ocurrido", "¿y si…?".
|
|
36
|
+
- **EN:** "I want to add…", "let's build…", "it should also…".
|
|
37
|
+
- A **URL plus a description of desired behaviour** ("on this page I'd like…") **is** a feature request — in any language.
|
|
38
|
+
|
|
39
|
+
**Stop rationalizing — every one of these is wrong:**
|
|
40
|
+
- *"I understand the feature, I'll just build it."* → That is the exact failure SDD prevents. Spec first; the artifact is the contract.
|
|
41
|
+
- *"A more specific skill matched (a stack skill, `chatbot`, `course-builder`, marketing…), so it takes precedence."* → **No skill outranks this gate.** Any builder skill **defers** to `specify` for new features and runs *inside* the chain, after the plan is approved. Route first.
|
|
42
|
+
- *"The user gave lots of detail / a URL, so they want code now."* → Detail feeds the spec, not the editor.
|
|
43
|
+
- *"The dial is L0, so I'll skip the gate to stay terse."* → L0 changes how many words and questions, **never** whether the gate fires.
|
|
44
|
+
- *"It's phrased in a language I have no example for, so maybe it isn't a feature request."* → The trigger lists are examples, not a closed set. Judge the **meaning**, not the keywords; any language with build/add/change intent fires the gate identically.
|
|
45
|
+
|
|
46
|
+
If `specify` / `sdd` are **not installed**, fall through to the install detector below and offer to add them *before* routing. The gate decides **where the turn goes**; the detector below only handles **missing** skills. Full method and phase map: `../sdd/SKILL.md`.
|
|
47
|
+
|
|
48
|
+
---
|
|
12
49
|
|
|
13
50
|
When the current task would clearly benefit from an rsc skill that is **not installed**:
|
|
14
51
|
|
package/targets/claude.js
CHANGED
|
@@ -107,7 +107,24 @@ export function wireHook(paths) {
|
|
|
107
107
|
);
|
|
108
108
|
settings.hooks.PreToolUse.push({ matcher: 'Bash', hooks: [{ type: 'command', command: dgCmd }] });
|
|
109
109
|
|
|
110
|
+
// New-feature gate: a UserPromptSubmit hook that re-injects the SDD new-feature gate as
|
|
111
|
+
// the most-recent instruction on every user turn. SessionStart injects the full gate (the
|
|
112
|
+
// `suggest` body) once; this keeps the precedence rule salient regardless of how many
|
|
113
|
+
// skills are installed or how long the session runs (otherwise a strongly-matched stack
|
|
114
|
+
// skill can pull the model to code despite the gate being in context). UserPromptSubmit
|
|
115
|
+
// stdout is added to context, so a plain print suffices. Materialized + node-run
|
|
116
|
+
// (Windows-safe), idempotent, fail-open, opt-out via .rsc/.no-feature-gate. Other
|
|
117
|
+
// (non-rsc) UserPromptSubmit hooks are preserved.
|
|
118
|
+
const fgDest = join(paths.projectRoot, '.rsc', 'userprompt-gate.mjs');
|
|
119
|
+
copyFileSync(join(HERE, 'userprompt-gate.mjs'), fgDest);
|
|
120
|
+
const fgCmd = `node "${fgDest}" "${paths.projectRoot}"`;
|
|
121
|
+
settings.hooks.UserPromptSubmit ||= [];
|
|
122
|
+
settings.hooks.UserPromptSubmit = settings.hooks.UserPromptSubmit.filter(
|
|
123
|
+
(e) => !JSON.stringify(e).includes('.rsc/userprompt-gate.'),
|
|
124
|
+
);
|
|
125
|
+
settings.hooks.UserPromptSubmit.push({ hooks: [{ type: 'command', command: fgCmd }] });
|
|
126
|
+
|
|
110
127
|
mkdirSync(dirname(file), { recursive: true });
|
|
111
128
|
writeFileSync(file, JSON.stringify(settings, null, 2) + '\n');
|
|
112
|
-
return [file, scriptDest, wlDest, sgDest, dgDest];
|
|
129
|
+
return [file, scriptDest, wlDest, sgDest, dgDest, fgDest];
|
|
113
130
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// rsc UserPromptSubmit payload (claude). Re-injects the SDD new-feature gate as the
|
|
3
|
+
// MOST-RECENT instruction on every user turn. The SessionStart hook already injects the
|
|
4
|
+
// full gate (the `suggest` body) once per session, but in a long session — or one with
|
|
5
|
+
// many installed skills whose descriptions crowd the context — that single injection can
|
|
6
|
+
// lose salience and a strongly-matched stack/builder skill can pull the model straight to
|
|
7
|
+
// code. This keeps the precedence rule in front of the model every turn, so the gate is
|
|
8
|
+
// independent of skill count and session length. Stdout is added to context for
|
|
9
|
+
// UserPromptSubmit, so a plain print is enough (no JSON needed).
|
|
10
|
+
//
|
|
11
|
+
// Invoked as `node userprompt-gate.mjs <projectRoot>` (not bash) so it runs on Windows too.
|
|
12
|
+
// argv[2] = absolute project root
|
|
13
|
+
// Fail-open (never blocks a turn). Opt out per project with .rsc/.no-feature-gate.
|
|
14
|
+
import { existsSync } from 'node:fs';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
|
|
17
|
+
const root = process.argv[2] || process.cwd();
|
|
18
|
+
|
|
19
|
+
// Opt-out: a project that does not want the always-on gate drops this marker file.
|
|
20
|
+
if (existsSync(join(root, '.rsc', '.no-feature-gate'))) process.exit(0);
|
|
21
|
+
|
|
22
|
+
process.stdout.write(`===== rsc SDD new-feature gate (highest precedence) =====
|
|
23
|
+
Before acting on this turn: if the user wants to BUILD, ADD, or CHANGE a feature — in
|
|
24
|
+
ANY language, judged by intent, not by keywords — you MUST route it through SDD via
|
|
25
|
+
\`specify\` FIRST. No feature code is written by ANY skill (stack skills included —
|
|
26
|
+
nextjs/react/fastapi/flutter/go/postgresdb/building-agents/design — and any builder skill
|
|
27
|
+
such as chatbot/course-builder/marketing) until a spec AND a plan exist and the user has
|
|
28
|
+
approved them. No skill outranks this gate.
|
|
29
|
+
- Unclear / in-between? -> \`specify\` (the safe default; a skipped spec is where drift hides).
|
|
30
|
+
- One-line / low-risk change, or a bug fix restoring intended behaviour? -> skip the chain,
|
|
31
|
+
do it, and say so out loud.
|
|
32
|
+
Full gate + decision table live in the always-on \`suggest\` body; method in \`sdd\`.
|
|
33
|
+
=========================================================
|
|
34
|
+
`);
|