@oevery/rsp 2.0.0 → 2.0.3
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 +15 -2
- package/README.zh-CN.md +15 -2
- package/dist/cli.mjs +111 -39
- package/package.json +1 -1
- package/rules/rsp-rules.md +7 -0
- package/skills/rsp/SKILL.md +40 -1
package/README.md
CHANGED
|
@@ -55,11 +55,12 @@ npx -y @oevery/rsp doctor
|
|
|
55
55
|
## File ownership
|
|
56
56
|
|
|
57
57
|
- `AGENTS.md`: only the `<!-- rsp:begin --> ... <!-- rsp:end -->` block is managed by RSP.
|
|
58
|
-
- `.rsp/specs/INDEX.md`: auto-generated. Rebuild with `rsp update`.
|
|
58
|
+
- `.rsp/specs/INDEX.md`: auto-generated index of additional spec files beyond `design.md`. Rebuild with `rsp update`.
|
|
59
59
|
- `.rsp/archives/INDEX.md`: auto-generated. Rebuild with `rsp update`.
|
|
60
60
|
- `.rsp/specs/design.md`: created by `rsp init`, then owned by the project.
|
|
61
61
|
- `.rsp/rules/project-rules.md`: optional; create only when the project has durable local rules.
|
|
62
62
|
- Keep durable architecture, boundaries, and cross-cutting technical constraints in `.rsp/specs/design.md`.
|
|
63
|
+
- Treat `.rsp/specs/INDEX.md` as a directory for additional spec files; it does not list `design.md`.
|
|
63
64
|
- Keep stable workflow rules, validation expectations, and local operating constraints in `.rsp/rules/project-rules.md`.
|
|
64
65
|
|
|
65
66
|
## AGENTS integration
|
|
@@ -70,6 +71,9 @@ Managed block example:
|
|
|
70
71
|
<!-- rsp:begin -->
|
|
71
72
|
## RSP Entry
|
|
72
73
|
|
|
74
|
+
RSP keeps durable rules, specs, and current work under `.rsp/`.
|
|
75
|
+
Treat AGENTS.md as navigation only; keep durable rules and design in `.rsp/`.
|
|
76
|
+
|
|
73
77
|
Read in order:
|
|
74
78
|
1. .rsp/rules/rsp-rules.md
|
|
75
79
|
2. .rsp/focus.d/
|
|
@@ -77,6 +81,9 @@ Read in order:
|
|
|
77
81
|
4. .rsp/specs/design.md
|
|
78
82
|
5. .rsp/specs/INDEX.md
|
|
79
83
|
6. only the relevant additional .rsp/rules/*.md and .rsp/specs/*.md files
|
|
84
|
+
|
|
85
|
+
If `.rsp/focus.d/` is empty, ask what to work on or suggest `npx -y @oevery/rsp create <name>`.
|
|
86
|
+
If your agent supports Agent Skills, load `rsp` for setup, repair, and durable-decision tasks.
|
|
80
87
|
<!-- rsp:end -->
|
|
81
88
|
```
|
|
82
89
|
|
|
@@ -111,11 +118,17 @@ When this README shows `rsp <command>`, it assumes the command is already availa
|
|
|
111
118
|
Example optional installation flow:
|
|
112
119
|
|
|
113
120
|
```bash
|
|
114
|
-
npx skills add oevery/rsp
|
|
121
|
+
npx skills add oevery/rsp
|
|
115
122
|
```
|
|
116
123
|
|
|
117
124
|
This repository publishes a skill named `rsp` under `skills/rsp/`.
|
|
118
125
|
|
|
126
|
+
`rsp update` refreshes project-local RSP files only. If you use the published RSP skill, refresh it separately after upgrading:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
npx skills add oevery/rsp
|
|
130
|
+
```
|
|
131
|
+
|
|
119
132
|
## Work Model
|
|
120
133
|
|
|
121
134
|
```text
|
package/README.zh-CN.md
CHANGED
|
@@ -55,11 +55,12 @@ npx -y @oevery/rsp doctor
|
|
|
55
55
|
## 文件所有权
|
|
56
56
|
|
|
57
57
|
- `AGENTS.md`:只有 `<!-- rsp:begin --> ... <!-- rsp:end -->` 受管块由 RSP 维护。
|
|
58
|
-
- `.rsp/specs/INDEX.md
|
|
58
|
+
- `.rsp/specs/INDEX.md`:自动生成,用于索引 `design.md` 之外的附加 spec 文件;使用 `rsp update` 重建。
|
|
59
59
|
- `.rsp/archives/INDEX.md`:自动生成,使用 `rsp update` 重建。
|
|
60
60
|
- `.rsp/specs/design.md`:由 `rsp init` 创建,之后由项目维护。
|
|
61
61
|
- `.rsp/rules/project-rules.md`:可选,仅在项目确有长期本地规则时创建。
|
|
62
62
|
- 将长期架构、边界和跨模块技术约束放在 `.rsp/specs/design.md`。
|
|
63
|
+
- 将 `.rsp/specs/INDEX.md` 视为附加 spec 的目录;它不列出 `design.md`。
|
|
63
64
|
- 将稳定的工作流规则、验证要求和本地运行约束放在 `.rsp/rules/project-rules.md`。
|
|
64
65
|
|
|
65
66
|
## AGENTS 接入
|
|
@@ -70,6 +71,9 @@ npx -y @oevery/rsp doctor
|
|
|
70
71
|
<!-- rsp:begin -->
|
|
71
72
|
## RSP Entry
|
|
72
73
|
|
|
74
|
+
RSP keeps durable rules, specs, and current work under `.rsp/`.
|
|
75
|
+
Treat AGENTS.md as navigation only; keep durable rules and design in `.rsp/`.
|
|
76
|
+
|
|
73
77
|
Read in order:
|
|
74
78
|
1. .rsp/rules/rsp-rules.md
|
|
75
79
|
2. .rsp/focus.d/
|
|
@@ -77,6 +81,9 @@ Read in order:
|
|
|
77
81
|
4. .rsp/specs/design.md
|
|
78
82
|
5. .rsp/specs/INDEX.md
|
|
79
83
|
6. only the relevant additional .rsp/rules/*.md and .rsp/specs/*.md files
|
|
84
|
+
|
|
85
|
+
If `.rsp/focus.d/` is empty, ask what to work on or suggest `npx -y @oevery/rsp create <name>`.
|
|
86
|
+
If your agent supports Agent Skills, load `rsp` for setup, repair, and durable-decision tasks.
|
|
80
87
|
<!-- rsp:end -->
|
|
81
88
|
```
|
|
82
89
|
|
|
@@ -105,11 +112,17 @@ Read in order:
|
|
|
105
112
|
可选安装示例:
|
|
106
113
|
|
|
107
114
|
```bash
|
|
108
|
-
npx skills add oevery/rsp
|
|
115
|
+
npx skills add oevery/rsp
|
|
109
116
|
```
|
|
110
117
|
|
|
111
118
|
本仓库发布了一个名为 `rsp` 的 skill,位于 `skills/rsp/`。
|
|
112
119
|
|
|
120
|
+
`rsp update` 只会刷新项目内的 RSP 文件。如果你在使用发布出来的 RSP skill,升级后还需要单独刷新一次:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npx skills add oevery/rsp
|
|
124
|
+
```
|
|
125
|
+
|
|
113
126
|
## 工作模型
|
|
114
127
|
|
|
115
128
|
```text
|
package/dist/cli.mjs
CHANGED
|
@@ -19,7 +19,7 @@ import pc from "picocolors";
|
|
|
19
19
|
|
|
20
20
|
// src/core/helpers.ts
|
|
21
21
|
import { existsSync } from "fs";
|
|
22
|
-
import { readdir, readFile, rmdir
|
|
22
|
+
import { readdir, readFile, rmdir } from "fs/promises";
|
|
23
23
|
import { basename, dirname, join, relative, sep } from "path";
|
|
24
24
|
import { parse } from "yaml";
|
|
25
25
|
|
|
@@ -166,6 +166,7 @@ kind: ops
|
|
|
166
166
|
|
|
167
167
|
## Tasks
|
|
168
168
|
- [ ] Review the repository structure, entrypoints, and primary outputs
|
|
169
|
+
- [ ] Review AGENTS.md and confirm the RSP entry points to the right project files
|
|
169
170
|
- [ ] Fill .rsp/specs/design.md with durable architecture facts
|
|
170
171
|
- [ ] Add .rsp/rules/project-rules.md if stable local rules or validation steps exist
|
|
171
172
|
|
|
@@ -209,12 +210,15 @@ ${template.acceptanceSection}
|
|
|
209
210
|
- Approach:
|
|
210
211
|
- ${template.approach}
|
|
211
212
|
- Affected areas:
|
|
212
|
-
- ${template.
|
|
213
|
+
- ${template.affectedArea1}
|
|
214
|
+
- ${template.affectedArea2}
|
|
213
215
|
- Constraints:
|
|
214
216
|
- ${template.constraints}
|
|
215
217
|
|
|
216
218
|
## Tasks
|
|
219
|
+
- [ ] Finalize the proposal, spec, and design details for this change
|
|
217
220
|
- [ ] ${template.task}
|
|
221
|
+
- [ ] Verify the result and update any required durable docs or rules
|
|
218
222
|
|
|
219
223
|
## Verify
|
|
220
224
|
- Automated:
|
|
@@ -231,6 +235,51 @@ ${template.acceptanceSection}
|
|
|
231
235
|
}
|
|
232
236
|
function getChangeTemplateByKind(kind) {
|
|
233
237
|
switch (kind) {
|
|
238
|
+
case "feature":
|
|
239
|
+
return {
|
|
240
|
+
why: "<what user need or capability gap this addresses>",
|
|
241
|
+
scope: "<what new behavior or capability will be delivered>",
|
|
242
|
+
nonGoals: "<what related capabilities are explicitly out of scope>",
|
|
243
|
+
specSection: "### ADDED\n- Requirement: <new user-facing behavior>\n - <verifiable requirement for the new capability>",
|
|
244
|
+
acceptanceSection: "#### Scenario: user exercises the new capability\n- GIVEN <context>\n- WHEN <user action>\n- THEN <expected new behavior>",
|
|
245
|
+
approach: "<how the new capability will be implemented>",
|
|
246
|
+
affectedArea1: "<concrete file path, directory, module, or subsystem 1>",
|
|
247
|
+
affectedArea2: "<concrete file path, directory, module, or subsystem 2 if needed>",
|
|
248
|
+
constraints: "<behavior, compatibility, performance, safety, or scope constraint that must hold>",
|
|
249
|
+
task: "<implement the new behavior and its acceptance scenario in the affected areas>",
|
|
250
|
+
automatedVerify: "<exact test, lint, build, or check command for the new behavior>",
|
|
251
|
+
manualVerify: "<exact end-to-end user scenario to validate the new capability>"
|
|
252
|
+
};
|
|
253
|
+
case "fix":
|
|
254
|
+
return {
|
|
255
|
+
why: "<what current behavior is wrong or broken>",
|
|
256
|
+
scope: "<what specific defect is being corrected>",
|
|
257
|
+
nonGoals: "<what related but separate issues are out of scope>",
|
|
258
|
+
specSection: "### MODIFIED\n- Requirement: correct behavior\n - <expected correct behavior after the fix>",
|
|
259
|
+
acceptanceSection: "#### Scenario: defect is resolved\n- GIVEN <conditions that trigger the defect>\n- WHEN <action that previously failed>\n- THEN <expected correct outcome>\n- AND the original broken outcome no longer occurs",
|
|
260
|
+
approach: "<root cause analysis and fix strategy>",
|
|
261
|
+
affectedArea1: "<concrete file path, directory, module, or subsystem containing the defect>",
|
|
262
|
+
affectedArea2: "<secondary path, dependency, or test file if needed>",
|
|
263
|
+
constraints: "<regression, backward-compatibility, safety, or scope constraint that must hold>",
|
|
264
|
+
task: "<identify the root cause and apply the minimal fix>",
|
|
265
|
+
automatedVerify: "<exact regression test, lint, build, or check command that proves the fix>",
|
|
266
|
+
manualVerify: "<exact steps to reproduce the original issue and confirm it no longer occurs>"
|
|
267
|
+
};
|
|
268
|
+
case "refactor":
|
|
269
|
+
return {
|
|
270
|
+
why: "<what maintainability, readability, or structural issue motivates this>",
|
|
271
|
+
scope: "<what code areas are being restructured>",
|
|
272
|
+
nonGoals: "<no behavior change is expected or intended>",
|
|
273
|
+
specSection: "### MODIFIED\n- Requirement: internal structure improvement\n - <desired structural outcome without observable behavior change>",
|
|
274
|
+
acceptanceSection: "#### Scenario: behavior is preserved after restructuring\n- GIVEN the existing codebase before the refactor\n- WHEN the refactored code runs against existing tests\n- THEN all existing tests pass unchanged",
|
|
275
|
+
approach: "<how the code will be restructured (rename, extract, move, etc.)>",
|
|
276
|
+
affectedArea1: "<concrete file path, directory, module, or subsystem being refactored>",
|
|
277
|
+
affectedArea2: "<secondary path, dependency, or test file if needed>",
|
|
278
|
+
constraints: "<observable behavior must remain unchanged; compatibility, performance, and safety constraints must still hold>",
|
|
279
|
+
task: "<restructure the code while keeping behavior identical>",
|
|
280
|
+
automatedVerify: "<exact existing test, lint, build, or check command that must continue to pass>",
|
|
281
|
+
manualVerify: "<exact scenario to spot-check that behavior is unchanged after the refactor>"
|
|
282
|
+
};
|
|
234
283
|
case "docs":
|
|
235
284
|
return {
|
|
236
285
|
why: "<why the documentation change matters>",
|
|
@@ -239,11 +288,12 @@ function getChangeTemplateByKind(kind) {
|
|
|
239
288
|
specSection: "### MODIFIED\n- Requirement: documentation accuracy\n - <what durable reader-facing behavior or explanation changes>",
|
|
240
289
|
acceptanceSection: "#### Scenario: reader follows the updated guidance\n- GIVEN the updated documentation\n- WHEN a reader follows the documented workflow\n- THEN the steps are accurate and sufficient",
|
|
241
290
|
approach: "<how the documentation will be updated and organized>",
|
|
242
|
-
|
|
243
|
-
|
|
291
|
+
affectedArea1: "<concrete doc path, directory, module doc, or documentation surface 1>",
|
|
292
|
+
affectedArea2: "<secondary doc path or reference file if needed>",
|
|
293
|
+
constraints: "<durable wording, consistency, scope, or audience constraint that must hold>",
|
|
244
294
|
task: "<update the target documentation and supporting references>",
|
|
245
|
-
automatedVerify: "<
|
|
246
|
-
manualVerify: "<
|
|
295
|
+
automatedVerify: "<exact markdown, docs, link, lint, build, or check command if applicable>",
|
|
296
|
+
manualVerify: "<exact reader or operator scenario to confirm the updated guidance is accurate>"
|
|
247
297
|
};
|
|
248
298
|
case "research":
|
|
249
299
|
return {
|
|
@@ -253,11 +303,12 @@ function getChangeTemplateByKind(kind) {
|
|
|
253
303
|
specSection: "### ADDED\n- Requirement: research outcome recording\n - <what finding, option, or decision must be captured clearly>",
|
|
254
304
|
acceptanceSection: "#### Scenario: research question is resolved\n- GIVEN the current uncertainty or open question\n- WHEN the investigation is completed\n- THEN the result is recorded clearly enough to guide follow-up work",
|
|
255
305
|
approach: "<how the investigation will be performed and what evidence will be gathered>",
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
306
|
+
affectedArea1: "<concrete file path, directory, module, subsystem, or source under investigation>",
|
|
307
|
+
affectedArea2: "<secondary path, dependency, environment, or evidence source if needed>",
|
|
308
|
+
constraints: "<time, evidence, safety, or scope constraint for the investigation>",
|
|
309
|
+
task: "<gather evidence, record the recommendation or finding, and note any follow-up implementation work if needed>",
|
|
310
|
+
automatedVerify: "<exact command, script, query, or check used to confirm the observed behavior>",
|
|
311
|
+
manualVerify: "<exact review of the findings to confirm they answer the original question and identify follow-up work if needed>"
|
|
261
312
|
};
|
|
262
313
|
case "ops":
|
|
263
314
|
return {
|
|
@@ -267,11 +318,12 @@ function getChangeTemplateByKind(kind) {
|
|
|
267
318
|
specSection: "### MODIFIED\n- Requirement: operational behavior\n - <what reliable operational outcome should change or stay true>",
|
|
268
319
|
acceptanceSection: "#### Scenario: operational path succeeds\n- GIVEN the target environment or workflow\n- WHEN the operational change is applied\n- THEN the expected operational outcome is reliable",
|
|
269
320
|
approach: "<how the operational change will be applied safely>",
|
|
270
|
-
|
|
271
|
-
|
|
321
|
+
affectedArea1: "<concrete script, config path, workflow, environment path, or operational surface 1>",
|
|
322
|
+
affectedArea2: "<secondary script, config path, dependency, or environment surface if needed>",
|
|
323
|
+
constraints: "<rollback, safety, reliability, environment, or scope constraint that must hold>",
|
|
272
324
|
task: "<apply and verify the operational change>",
|
|
273
|
-
automatedVerify: "<
|
|
274
|
-
manualVerify: "<
|
|
325
|
+
automatedVerify: "<exact operational validation, lint, build, deploy, or check command>",
|
|
326
|
+
manualVerify: "<exact operator workflow or environment scenario to confirm the operational result>"
|
|
275
327
|
};
|
|
276
328
|
default:
|
|
277
329
|
return {
|
|
@@ -281,11 +333,12 @@ function getChangeTemplateByKind(kind) {
|
|
|
281
333
|
specSection: "### ADDED\n- Requirement: <new or updated behavior>\n - <verifiable requirement>",
|
|
282
334
|
acceptanceSection: "#### Scenario: <name>\n- GIVEN <context>\n- WHEN <action>\n- THEN <expected outcome>",
|
|
283
335
|
approach: "<how the change will be implemented>",
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
336
|
+
affectedArea1: "<concrete file path, directory, module, or subsystem 1>",
|
|
337
|
+
affectedArea2: "<concrete file path, directory, module, or subsystem 2 if needed>",
|
|
338
|
+
constraints: "<behavior, compatibility, performance, safety, or scope constraint that must hold>",
|
|
339
|
+
task: "<implement the core change in the affected areas>",
|
|
340
|
+
automatedVerify: "<exact test, lint, build, or check command>",
|
|
341
|
+
manualVerify: "<exact end-to-end scenario to validate>"
|
|
289
342
|
};
|
|
290
343
|
}
|
|
291
344
|
}
|
|
@@ -293,6 +346,9 @@ function renderRspAgentsBlock() {
|
|
|
293
346
|
return `${RSP_AGENTS_BEGIN}
|
|
294
347
|
## RSP Entry
|
|
295
348
|
|
|
349
|
+
RSP keeps durable rules, specs, and current work under \`.rsp/\`.
|
|
350
|
+
Treat AGENTS.md as navigation only; keep durable rules and design in \`.rsp/\`.
|
|
351
|
+
|
|
296
352
|
Read in order:
|
|
297
353
|
1. .rsp/rules/rsp-rules.md
|
|
298
354
|
2. .rsp/focus.d/
|
|
@@ -300,6 +356,9 @@ Read in order:
|
|
|
300
356
|
4. .rsp/specs/design.md
|
|
301
357
|
5. .rsp/specs/INDEX.md
|
|
302
358
|
6. only the relevant additional .rsp/rules/*.md and .rsp/specs/*.md files
|
|
359
|
+
|
|
360
|
+
If \`.rsp/focus.d/\` is empty, ask what to work on or suggest \`npx -y @oevery/rsp create <name>\`.
|
|
361
|
+
If your agent supports Agent Skills, load \`rsp\` for setup, repair, and durable-decision tasks.
|
|
303
362
|
${RSP_AGENTS_END}`;
|
|
304
363
|
}
|
|
305
364
|
function upsertRspAgentsBlock(content) {
|
|
@@ -332,6 +391,16 @@ function guardRspInitialized() {
|
|
|
332
391
|
process.exit(1);
|
|
333
392
|
}
|
|
334
393
|
}
|
|
394
|
+
async function getFocusedChangeNames(options = {}) {
|
|
395
|
+
const names = /* @__PURE__ */ new Set();
|
|
396
|
+
const focusDir = join(RSP_DIR, "focus.d");
|
|
397
|
+
if (!existsSync(focusDir))
|
|
398
|
+
return names;
|
|
399
|
+
const entries = await walkFiles(focusDir, options);
|
|
400
|
+
for (const entryPath of entries)
|
|
401
|
+
names.add(normalizeLogicalPath(relative(focusDir, entryPath)));
|
|
402
|
+
return names;
|
|
403
|
+
}
|
|
335
404
|
function getOpenCheckboxes(sectionText) {
|
|
336
405
|
return sectionText.split("\n").map((line) => line.trim()).filter((line) => /^- \[[ /]\]/.test(line));
|
|
337
406
|
}
|
|
@@ -632,14 +701,17 @@ async function buildSpecsIndex({ acquireLock = true } = {}) {
|
|
|
632
701
|
`);
|
|
633
702
|
return;
|
|
634
703
|
}
|
|
635
|
-
const specFiles = (await walkMarkdownFiles(specsDir)).filter((fp) =>
|
|
704
|
+
const specFiles = (await walkMarkdownFiles(specsDir)).filter((fp) => {
|
|
705
|
+
const name = basename2(fp);
|
|
706
|
+
return name !== "INDEX.md" && name !== "design.md";
|
|
707
|
+
}).sort();
|
|
636
708
|
const lines = [];
|
|
637
709
|
lines.push("# Specs Index");
|
|
638
710
|
lines.push("");
|
|
639
|
-
lines.push("
|
|
711
|
+
lines.push("_Additional project-level specs beyond `design.md`._");
|
|
640
712
|
lines.push("");
|
|
641
713
|
if (specFiles.length === 0) {
|
|
642
|
-
lines.push("_No project-level specs yet._");
|
|
714
|
+
lines.push("_No additional project-level specs yet._");
|
|
643
715
|
} else {
|
|
644
716
|
lines.push("| File | Title | Summary |");
|
|
645
717
|
lines.push("|------|-------|---------|");
|
|
@@ -782,6 +854,7 @@ async function archiveChange(name) {
|
|
|
782
854
|
console.error(` ${pc.red("Error:")} change name must be kebab-case with optional subdirectory (lowercase, digits, hyphens, slashes)`);
|
|
783
855
|
process.exit(1);
|
|
784
856
|
}
|
|
857
|
+
guardRspInitialized();
|
|
785
858
|
const srcPath = join7(CHANGES_DIR, `${name}.md`);
|
|
786
859
|
if (!existsSync7(srcPath)) {
|
|
787
860
|
console.error(` ${pc.red("Change not found:")} .rsp/changes/${name}.md`);
|
|
@@ -1185,7 +1258,7 @@ async function createChange(name, summary = "", kind) {
|
|
|
1185
1258
|
console.log(` ${pc.dim("Unchanged focus.")} Run: rsp focus ${name}`);
|
|
1186
1259
|
else
|
|
1187
1260
|
console.log(` ${pc.dim("focused via focus.d")} \u2192 ${name}`);
|
|
1188
|
-
console.log(` ${pc.cyan("Next:")}
|
|
1261
|
+
console.log(` ${pc.cyan("Next:")} fill proposal/spec/design first, then implement and complete the tasks
|
|
1189
1262
|
`);
|
|
1190
1263
|
});
|
|
1191
1264
|
}
|
|
@@ -1387,8 +1460,7 @@ function reportConfigListField(checks, parsed, key) {
|
|
|
1387
1460
|
async function checkActiveChangeConsistency(checks, reportRuntime) {
|
|
1388
1461
|
const changeFiles = existsSync10(CHANGES_DIR) ? await walkMarkdownFiles(CHANGES_DIR, { onError: reportRuntime }) : [];
|
|
1389
1462
|
const changeNames = new Set(changeFiles.map((fp) => changeNameFromPath(CHANGES_DIR, fp)));
|
|
1390
|
-
const
|
|
1391
|
-
const focusNames = new Set(focusEntries.map((fp) => normalizeLogicalPath(relative5(FOCUS_DIR, fp))));
|
|
1463
|
+
const focusNames = await getFocusedChangeNames({ onError: reportRuntime });
|
|
1392
1464
|
const missingChangeFiles = [...focusNames].filter((name) => !changeNames.has(name));
|
|
1393
1465
|
const unfocusedChangeFiles = [...changeNames].filter((name) => !focusNames.has(name));
|
|
1394
1466
|
if (missingChangeFiles.length === 0) {
|
|
@@ -1515,7 +1587,7 @@ async function initProject(args = {}) {
|
|
|
1515
1587
|
const bundledRules = await readFile9(join12(PKG_ROOT, "rules", "rsp-rules.md"), "utf-8");
|
|
1516
1588
|
created = await ensureFile(join12(RSP_DIR, "rules", "rsp-rules.md"), bundledRules) || created;
|
|
1517
1589
|
created = await ensureFile(join12(RSP_DIR, "config.yaml"), generateConfigTemplate()) || created;
|
|
1518
|
-
const createdSpecsIndex = await ensureFile(join12(RSP_DIR, "specs", "INDEX.md"), "# Specs Index\n\
|
|
1590
|
+
const createdSpecsIndex = await ensureFile(join12(RSP_DIR, "specs", "INDEX.md"), "# Specs Index\n\n_Additional project-level specs beyond `design.md`._\n");
|
|
1519
1591
|
created = createdSpecsIndex || created;
|
|
1520
1592
|
const createdDesign = await ensureFile(join12(RSP_DIR, "specs", "design.md"), generateDesignContent(projectName));
|
|
1521
1593
|
created = createdDesign || created;
|
|
@@ -1595,21 +1667,16 @@ ${managed}
|
|
|
1595
1667
|
|
|
1596
1668
|
// src/commands/status.ts
|
|
1597
1669
|
import { existsSync as existsSync13 } from "fs";
|
|
1598
|
-
import { readFile as readFile10, stat
|
|
1599
|
-
import { join as join13
|
|
1670
|
+
import { readFile as readFile10, stat } from "fs/promises";
|
|
1671
|
+
import { join as join13 } from "path";
|
|
1600
1672
|
var COL_CHANGE = 32;
|
|
1601
1673
|
var COL_KIND = 10;
|
|
1602
1674
|
var COL_AGE = 7;
|
|
1603
1675
|
var COL_PROGRESS = 10;
|
|
1604
1676
|
async function showStatus(options = {}, runOptions = {}) {
|
|
1605
|
-
const focusedSet = /* @__PURE__ */ new Set();
|
|
1606
1677
|
const runtime = [];
|
|
1607
1678
|
const reportRuntime = (diagnostic) => recordRuntimeDiagnostic(runtime, diagnostic, Boolean(runOptions.verbose) && !runOptions.json);
|
|
1608
|
-
|
|
1609
|
-
const entries = await walkFiles(FOCUS_DIR, { onError: reportRuntime });
|
|
1610
|
-
for (const entryPath of entries)
|
|
1611
|
-
focusedSet.add(normalizeLogicalPath(relative6(FOCUS_DIR, entryPath)));
|
|
1612
|
-
}
|
|
1679
|
+
const focusedSet = await getFocusedChangeNames({ onError: reportRuntime });
|
|
1613
1680
|
const changeFiles = existsSync13(CHANGES_DIR) ? await walkMarkdownFiles(CHANGES_DIR, { onError: reportRuntime }) : [];
|
|
1614
1681
|
const changeMap = {};
|
|
1615
1682
|
for (const fp of changeFiles)
|
|
@@ -1655,7 +1722,7 @@ async function showStatus(options = {}, runOptions = {}) {
|
|
|
1655
1722
|
});
|
|
1656
1723
|
}
|
|
1657
1724
|
try {
|
|
1658
|
-
const s = await
|
|
1725
|
+
const s = await stat(fp);
|
|
1659
1726
|
ageDays = Math.floor((Date.now() - s.mtime.getTime()) / (1e3 * 60 * 60 * 24));
|
|
1660
1727
|
} catch (error) {
|
|
1661
1728
|
reportRuntime({
|
|
@@ -1816,9 +1883,11 @@ function printArchiveTrend(trend) {
|
|
|
1816
1883
|
import { existsSync as existsSync14 } from "fs";
|
|
1817
1884
|
import { mkdir as mkdir8, readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
|
|
1818
1885
|
import { join as join14 } from "path";
|
|
1886
|
+
var SKILL_REFRESH_HINT = " Note: if you use the published RSP skill, refresh it too:\n npx skills add oevery/rsp\n";
|
|
1819
1887
|
async function updateProject() {
|
|
1820
1888
|
if (!existsSync14(RSP_DIR)) {
|
|
1821
|
-
console.
|
|
1889
|
+
console.error(` ${pc.red("Error:")} RSP is not initialized in this project`);
|
|
1890
|
+
console.error(` ${pc.dim("Run: rsp init")}`);
|
|
1822
1891
|
process.exit(1);
|
|
1823
1892
|
}
|
|
1824
1893
|
return withRspLock("update", async () => {
|
|
@@ -1845,12 +1914,15 @@ async function updateProject() {
|
|
|
1845
1914
|
}
|
|
1846
1915
|
await buildSpecsIndex({ acquireLock: false });
|
|
1847
1916
|
await buildArchiveIndex({ acquireLock: false });
|
|
1848
|
-
if (!updated)
|
|
1917
|
+
if (!updated) {
|
|
1849
1918
|
console.log(` ${pc.dim("Already up to date.")}
|
|
1850
1919
|
`);
|
|
1851
|
-
|
|
1920
|
+
console.log(SKILL_REFRESH_HINT);
|
|
1921
|
+
} else {
|
|
1852
1922
|
console.log(` ${pc.green("Update complete.")}
|
|
1853
1923
|
`);
|
|
1924
|
+
console.log(SKILL_REFRESH_HINT);
|
|
1925
|
+
}
|
|
1854
1926
|
});
|
|
1855
1927
|
}
|
|
1856
1928
|
|
package/package.json
CHANGED
package/rules/rsp-rules.md
CHANGED
|
@@ -7,6 +7,12 @@ description: Core RSP rules for Rules, Specs, and Plans driven development.
|
|
|
7
7
|
|
|
8
8
|
This file is the canonical RSP rules source.
|
|
9
9
|
|
|
10
|
+
## Scope
|
|
11
|
+
|
|
12
|
+
- Paths in this file are relative to the project root unless stated otherwise.
|
|
13
|
+
- These rules are tool-agnostic and apply even when the agent does not support skills.
|
|
14
|
+
- If the agent supports Agent Skills, load the `rsp` skill for initialization, audit or repair, and durable-decision tasks.
|
|
15
|
+
|
|
10
16
|
## Read order
|
|
11
17
|
|
|
12
18
|
1. Read `AGENTS.md`.
|
|
@@ -15,6 +21,7 @@ This file is the canonical RSP rules source.
|
|
|
15
21
|
4. If `focus.d/` is empty, ask the user what to work on or suggest `npx -y @oevery/rsp create <name>`.
|
|
16
22
|
5. Read each `changes/<name>.md` file marked in `focus.d/`.
|
|
17
23
|
6. Read `specs/design.md` and `specs/INDEX.md`.
|
|
24
|
+
`specs/INDEX.md` lists only additional spec files beyond `specs/design.md`.
|
|
18
25
|
7. Read only the relevant additional `rules/` and `specs/` files.
|
|
19
26
|
|
|
20
27
|
## Core rules
|
package/skills/rsp/SKILL.md
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rsp
|
|
3
|
-
description: Use this skill when
|
|
3
|
+
description: Use this skill when initializing RSP in a repository, operating an existing .rsp project, auditing or repairing .rsp state, or deciding whether a change needs durable updates before archive.
|
|
4
|
+
compatibility:
|
|
5
|
+
agents:
|
|
6
|
+
- any agent that supports the Agent Skills format
|
|
7
|
+
requirements:
|
|
8
|
+
- Node.js 18+
|
|
9
|
+
- local filesystem read/write access
|
|
10
|
+
- shell access for `rsp` or `npx -y @oevery/rsp`
|
|
11
|
+
optional_requirements:
|
|
12
|
+
- network access for first-run `npx` installation or skill refresh
|
|
13
|
+
metadata:
|
|
14
|
+
author: oevery
|
|
15
|
+
version: 2.0.3
|
|
4
16
|
---
|
|
5
17
|
|
|
6
18
|
# RSP Skill
|
|
@@ -11,6 +23,19 @@ This skill operationalizes the rules in `.rsp/rules/rsp-rules.md`. Always load a
|
|
|
11
23
|
|
|
12
24
|
Prefer exact file paths, exact commands, and exact durable facts over vague summaries.
|
|
13
25
|
|
|
26
|
+
## When to use
|
|
27
|
+
|
|
28
|
+
- Use this skill when a repository already contains `.rsp/` and the task is to operate within that workflow.
|
|
29
|
+
- Use this skill when adopting RSP in a repository that does not yet have `.rsp/`.
|
|
30
|
+
- Use this skill when the task is to audit or repair `.rsp/`, `AGENTS.md`, generated indices, or focus markers.
|
|
31
|
+
- Use this skill when deciding whether a completed change needs durable updates before archive.
|
|
32
|
+
|
|
33
|
+
## When not to use
|
|
34
|
+
|
|
35
|
+
- Do not load this skill for general coding tasks unrelated to `.rsp/`.
|
|
36
|
+
- Do not use this skill as a substitute for reading `.rsp/rules/rsp-rules.md` during a focused RSP task.
|
|
37
|
+
- Do not use this skill when the repository does not use RSP and the user did not ask to adopt it.
|
|
38
|
+
|
|
14
39
|
## Workflow
|
|
15
40
|
|
|
16
41
|
### Adopt or initialize
|
|
@@ -40,9 +65,23 @@ Prefer exact file paths, exact commands, and exact durable facts over vague summ
|
|
|
40
65
|
2. Check that `AGENTS.md` contains the managed RSP block.
|
|
41
66
|
3. Check that `specs/design.md` exists.
|
|
42
67
|
4. Check that `specs/INDEX.md` and `archives/INDEX.md` are still generated files.
|
|
68
|
+
`specs/INDEX.md` should list only additional spec files beyond `specs/design.md`.
|
|
43
69
|
5. Check that `focus.d/` markers and `changes/` files are in sync.
|
|
44
70
|
6. If generated indices or the managed AGENTS block drift, run `npx -y @oevery/rsp update`.
|
|
45
71
|
|
|
72
|
+
## Expected outputs
|
|
73
|
+
|
|
74
|
+
- exact file paths to read or update
|
|
75
|
+
- exact RSP commands to run
|
|
76
|
+
- a single durable-decision result in the required template when evaluating archive readiness
|
|
77
|
+
|
|
78
|
+
## Trigger examples
|
|
79
|
+
|
|
80
|
+
- "Set up RSP in this repository."
|
|
81
|
+
- "Repair the broken .rsp state in this project."
|
|
82
|
+
- "Check whether this change needs spec or rule writeback before archive."
|
|
83
|
+
- "Audit the RSP setup and tell me what is missing."
|
|
84
|
+
|
|
46
85
|
## Durable decision
|
|
47
86
|
|
|
48
87
|
Before `npx -y @oevery/rsp archive <name>`:
|