@oevery/rsp 3.3.0 → 4.0.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 +24 -17
- package/README.zh-CN.md +25 -18
- package/dist/{chunk-TSUDEX5Y.mjs → chunk-HFSTLCCK.mjs} +1261 -319
- package/dist/cli.mjs +1129 -2350
- package/dist/{entry-GIDNR7CJ.mjs → entry-RIJQ2X46.mjs} +122 -36
- package/package.json +32 -24
- package/skills/rsp/SKILL.md +43 -38
- package/skills/rsp/references/closeout.md +38 -0
- package/skills/rsp/references/context-migration.md +22 -0
- package/skills/rsp/references/control-outcome.md +3 -29
- package/skills/rsp/references/coordination-recovery.md +25 -0
- package/skills/rsp/references/coordination-review.md +15 -0
- package/skills/rsp/references/coordination.md +59 -0
- package/skills/rsp/references/durable-review.md +60 -12
- package/skills/rsp/references/focus-continuation.md +8 -4
- package/skills/rsp/references/groups-dependencies.md +6 -4
- package/skills/rsp/references/response-language.md +2 -0
- package/skills/rsp/references/setup-repair.md +37 -7
- package/skills/rsp/references/work-model.md +27 -0
- package/skills/rsp-commit/SKILL.md +76 -31
- package/skills/rsp-commit/references/message.md +34 -0
- package/skills/rsp-doc/SKILL.md +65 -0
- package/skills/rsp-doc/agents/openai.yaml +3 -0
- package/skills/rsp-doc/references/artifact-lenses.md +43 -0
- package/skills/rsp-doc/references/release-communication.md +39 -0
- package/skills/rsp-doc/references/skill-authoring.md +36 -0
- package/skills/rsp-implement/SKILL.md +56 -25
- package/skills/rsp-implement/references/diagnosis.md +10 -0
- package/skills/rsp-implement/references/finding-resolution.md +21 -0
- package/skills/rsp-implement/references/test-first.md +7 -0
- package/skills/rsp-review/SKILL.md +46 -45
- package/skills/rsp-review/references/code-review.md +23 -8
- package/skills/rsp-review/references/document-review.md +25 -8
- package/skills/rsp-review/references/release-communication.md +21 -0
- package/skills/{rsp-structural-audit/references/structural-lenses.md → rsp-review/references/structural-review.md} +5 -5
- package/skills/rsp-shape/SKILL.md +24 -45
- package/skills/rsp-shape/references/complex-shaping.md +3 -1
- package/skills/rsp-shape/references/deep-clarification.md +4 -4
- package/skills/rsp-shape/references/domain-modeling.md +13 -0
- package/skills/rsp-shape/references/module-seams.md +13 -0
- package/skills/rsp-shape/references/planning.md +42 -0
- package/skills/{rsp-design → rsp-shape}/references/reversible-exploration.md +2 -2
- package/skills/rsp-verify/SKILL.md +44 -12
- package/dist/chunk-7HXQNBIG.mjs +0 -871
- package/dist/chunk-JOMFFQRG.mjs +0 -99
- package/dist/chunk-QM2UVPQK.mjs +0 -375
- package/dist/entry-YAW3PYFA.mjs +0 -174
- package/rules/rsp-rules.md +0 -48
- package/skills/rsp/references/implementation-evidence.md +0 -12
- package/skills/rsp/references/managed-routing.md +0 -45
- package/skills/rsp-design/SKILL.md +0 -53
- package/skills/rsp-design/references/domain-modeling.md +0 -11
- package/skills/rsp-design/references/module-seams.md +0 -11
- package/skills/rsp-diagnose/SKILL.md +0 -48
- package/skills/rsp-manage/SKILL.md +0 -101
- package/skills/rsp-manage/references/closeout.md +0 -13
- package/skills/rsp-manage/references/delegation.md +0 -47
- package/skills/rsp-manage/references/interruption-recovery.md +0 -19
- package/skills/rsp-manage/references/review-convergence.md +0 -9
- package/skills/rsp-release-docs/SKILL.md +0 -77
- package/skills/rsp-release-docs/references/convention-discovery.md +0 -65
- package/skills/rsp-release-docs/references/evidence-and-surfaces.md +0 -21
- package/skills/rsp-release-docs/references/output-contracts.md +0 -97
- package/skills/rsp-release-docs/references/publication-lifecycle.md +0 -28
- package/skills/rsp-resolve-findings/SKILL.md +0 -61
- package/skills/rsp-structural-audit/SKILL.md +0 -71
- package/skills/rsp-tdd/SKILL.md +0 -56
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ArchiveHistoryError,
|
|
4
|
+
CHANGES_DIR,
|
|
4
5
|
SPECS_DEFAULT_RESULT_LIMIT,
|
|
5
6
|
SPECS_SEARCH_EXCERPT_CODE_POINTS,
|
|
6
7
|
WorkRefError,
|
|
@@ -8,7 +9,10 @@ import {
|
|
|
8
9
|
inspectArchiveHistory,
|
|
9
10
|
inspectProjectStatus,
|
|
10
11
|
inspectSpecs,
|
|
12
|
+
isMarkdownComment,
|
|
13
|
+
markdownText,
|
|
11
14
|
normalizeLogicalPath,
|
|
15
|
+
parseMarkdown,
|
|
12
16
|
projectDependencyForest,
|
|
13
17
|
projectSpecsDetail,
|
|
14
18
|
projectSpecsSearch,
|
|
@@ -17,16 +21,7 @@ import {
|
|
|
17
21
|
readArchiveHistoryDetail,
|
|
18
22
|
readArchiveHistoryDocument,
|
|
19
23
|
resolveWorkRefPath
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import {
|
|
22
|
-
displayWidth,
|
|
23
|
-
openTerminalSession,
|
|
24
|
-
truncateDisplay,
|
|
25
|
-
wrapDisplay
|
|
26
|
-
} from "./chunk-JOMFFQRG.mjs";
|
|
27
|
-
import {
|
|
28
|
-
CHANGES_DIR
|
|
29
|
-
} from "./chunk-7HXQNBIG.mjs";
|
|
24
|
+
} from "./chunk-HFSTLCCK.mjs";
|
|
30
25
|
|
|
31
26
|
// src/tui/entry.tsx
|
|
32
27
|
import process from "process";
|
|
@@ -37,6 +32,81 @@ import React from "react";
|
|
|
37
32
|
import { Box as Box3, Text as Text3, useApp, useInput, useStdout } from "ink";
|
|
38
33
|
import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "react";
|
|
39
34
|
|
|
35
|
+
// src/tui/display.ts
|
|
36
|
+
var segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
37
|
+
function isWide(codePoint) {
|
|
38
|
+
return codePoint >= 4352 && (codePoint <= 4447 || codePoint === 9001 || codePoint === 9002 || codePoint >= 11904 && codePoint <= 42191 && codePoint !== 12351 || codePoint >= 44032 && codePoint <= 55203 || codePoint >= 63744 && codePoint <= 64255 || codePoint >= 65040 && codePoint <= 65049 || codePoint >= 65072 && codePoint <= 65135 || codePoint >= 65280 && codePoint <= 65376 || codePoint >= 65504 && codePoint <= 65510 || codePoint >= 127744 && codePoint <= 129791 || codePoint >= 131072 && codePoint <= 262141);
|
|
39
|
+
}
|
|
40
|
+
function displayWidth(value) {
|
|
41
|
+
let width = 0;
|
|
42
|
+
for (const { segment } of segmenter.segment(value)) {
|
|
43
|
+
const codePoint = segment.codePointAt(0) ?? 0;
|
|
44
|
+
if (/^\p{Mark}$/u.test(segment) || codePoint === 8205)
|
|
45
|
+
continue;
|
|
46
|
+
width += isWide(codePoint) ? 2 : 1;
|
|
47
|
+
}
|
|
48
|
+
return width;
|
|
49
|
+
}
|
|
50
|
+
function truncateDisplay(value, maxWidth) {
|
|
51
|
+
if (displayWidth(value) <= maxWidth)
|
|
52
|
+
return value;
|
|
53
|
+
if (maxWidth <= 1)
|
|
54
|
+
return "\u2026".slice(0, maxWidth);
|
|
55
|
+
let result = "";
|
|
56
|
+
for (const { segment } of segmenter.segment(value)) {
|
|
57
|
+
if (displayWidth(result + segment) > maxWidth - 1)
|
|
58
|
+
break;
|
|
59
|
+
result += segment;
|
|
60
|
+
}
|
|
61
|
+
return `${result}\u2026`;
|
|
62
|
+
}
|
|
63
|
+
function wrapDisplay(value, maxWidth, firstPrefix = "", continuationPrefix = firstPrefix) {
|
|
64
|
+
const width = Math.max(1, maxWidth);
|
|
65
|
+
if (displayWidth(firstPrefix) >= width)
|
|
66
|
+
return [truncateDisplay(`${firstPrefix}${value}`, width)];
|
|
67
|
+
const lines = [];
|
|
68
|
+
let prefix = firstPrefix;
|
|
69
|
+
let line = prefix;
|
|
70
|
+
const pushLine = () => {
|
|
71
|
+
lines.push(line);
|
|
72
|
+
prefix = continuationPrefix;
|
|
73
|
+
line = prefix;
|
|
74
|
+
};
|
|
75
|
+
const appendUnbroken = (token) => {
|
|
76
|
+
for (const { segment } of segmenter.segment(token)) {
|
|
77
|
+
if (displayWidth(line + segment) > width && line !== prefix)
|
|
78
|
+
pushLine();
|
|
79
|
+
if (displayWidth(line + segment) > width) {
|
|
80
|
+
lines.push(truncateDisplay(line + segment, width));
|
|
81
|
+
prefix = continuationPrefix;
|
|
82
|
+
line = prefix;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
line += segment;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
let pendingWhitespace = "";
|
|
89
|
+
for (const token of value.split(/(\s+)/u).filter(Boolean)) {
|
|
90
|
+
if (token.trim().length === 0) {
|
|
91
|
+
if (line !== prefix)
|
|
92
|
+
pendingWhitespace += token;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const separator = line === prefix ? "" : pendingWhitespace;
|
|
96
|
+
if (displayWidth(line + separator + token) <= width) {
|
|
97
|
+
line += `${separator}${token}`;
|
|
98
|
+
} else {
|
|
99
|
+
if (line !== prefix && separator)
|
|
100
|
+
pushLine();
|
|
101
|
+
appendUnbroken(token);
|
|
102
|
+
}
|
|
103
|
+
pendingWhitespace = "";
|
|
104
|
+
}
|
|
105
|
+
if (line !== prefix || lines.length === 0)
|
|
106
|
+
lines.push(line);
|
|
107
|
+
return lines;
|
|
108
|
+
}
|
|
109
|
+
|
|
40
110
|
// src/tui/history-display.ts
|
|
41
111
|
function formatHistoryRow(record, width) {
|
|
42
112
|
const boundedWidth = Math.max(1, width);
|
|
@@ -138,18 +208,17 @@ function projectHistoryEvidence(evidence, options) {
|
|
|
138
208
|
}
|
|
139
209
|
|
|
140
210
|
// src/tui/markdown-presentation.ts
|
|
141
|
-
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
142
|
-
import { gfmFromMarkdown } from "mdast-util-gfm";
|
|
143
|
-
import { gfm } from "micromark-extension-gfm";
|
|
144
211
|
var EMPTY_LINE = { spans: [{ text: "" }] };
|
|
145
212
|
var graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
146
213
|
function markdownLineText(line) {
|
|
147
214
|
return line.spans.map((span) => span.text).join("");
|
|
148
215
|
}
|
|
149
216
|
function projectMarkdownLines(content, width) {
|
|
150
|
-
const root =
|
|
217
|
+
const root = parseMarkdown(sanitizeMarkdown(content)).root;
|
|
151
218
|
const logical = [];
|
|
152
219
|
root.children.forEach((node, index) => {
|
|
220
|
+
if (node.type === "yaml" || isMarkdownComment(node))
|
|
221
|
+
return;
|
|
153
222
|
if (index > 0 && logical.length > 0 && markdownLineText(logical.at(-1)) !== "")
|
|
154
223
|
logical.push(EMPTY_LINE);
|
|
155
224
|
logical.push(...projectBlock(node, 0, Math.max(1, width)));
|
|
@@ -173,9 +242,6 @@ function projectMarkdownLineViewport(lines, options) {
|
|
|
173
242
|
hasNext: end < lines.length
|
|
174
243
|
};
|
|
175
244
|
}
|
|
176
|
-
function stripFrontmatter(content) {
|
|
177
|
-
return content.replace(/^---\r?\n[\s\S]*?\r?\n(?:---|\.\.\.)\r?\n/u, "");
|
|
178
|
-
}
|
|
179
245
|
function sanitizeMarkdown(value) {
|
|
180
246
|
let result = "";
|
|
181
247
|
for (let index = 0; index < value.length; index++) {
|
|
@@ -222,7 +288,7 @@ function projectBlock(node, depth, width) {
|
|
|
222
288
|
case "table":
|
|
223
289
|
return projectTable(node, width);
|
|
224
290
|
case "html":
|
|
225
|
-
return [metavariableLine(node.value) ?? { spans: [{ text: node.
|
|
291
|
+
return [metavariableLine(node.value) ?? { spans: [{ text: markdownText(node).trim(), dim: true }] }];
|
|
226
292
|
default:
|
|
227
293
|
return "children" in node ? inlineLines(node.children.filter((child) => isPhrasing(child))) : [];
|
|
228
294
|
}
|
|
@@ -263,11 +329,13 @@ function inlineLines(children, style = {}, prefix = "") {
|
|
|
263
329
|
return lines;
|
|
264
330
|
}
|
|
265
331
|
function projectInline(node, inherited) {
|
|
332
|
+
if (isMarkdownComment(node))
|
|
333
|
+
return [];
|
|
266
334
|
switch (node.type) {
|
|
267
335
|
case "text":
|
|
268
336
|
return [{ text: node.value, ...inherited }];
|
|
269
337
|
case "html":
|
|
270
|
-
return metavariableSpan(node.value, inherited) ?? [{ text: node
|
|
338
|
+
return metavariableSpan(node.value, inherited) ?? [{ text: markdownText(node), ...inherited, dim: true }];
|
|
271
339
|
case "inlineCode":
|
|
272
340
|
return [{ text: node.value, ...inherited, code: true, color: "cyan" }];
|
|
273
341
|
case "break":
|
|
@@ -751,16 +819,8 @@ function projectItemDependencyForest(item, snapshot) {
|
|
|
751
819
|
const forest = projectDependencyForest(snapshot.plan, roots);
|
|
752
820
|
return item.type === "change" ? forest[0]?.children ?? [] : forest;
|
|
753
821
|
}
|
|
754
|
-
function projectExternalBlockers(item
|
|
755
|
-
|
|
756
|
-
return [];
|
|
757
|
-
const edges = snapshot.plan.edges.filter((edge) => edge.change === item.workRef);
|
|
758
|
-
return item.record.blockerEntries.filter((entry) => {
|
|
759
|
-
const dependency = entry.match(/^requires\s+`([^`]+)`:\s*(\S.*)$/i);
|
|
760
|
-
if (!dependency)
|
|
761
|
-
return true;
|
|
762
|
-
return !edges.some((edge) => edge.requires === dependency[1] && edge.reason === dependency[2]);
|
|
763
|
-
});
|
|
822
|
+
function projectExternalBlockers(item) {
|
|
823
|
+
return item.type === "change" ? item.record.externalBlockers : [];
|
|
764
824
|
}
|
|
765
825
|
function projectNextAction(item, snapshot) {
|
|
766
826
|
if (item.type === "history")
|
|
@@ -808,9 +868,7 @@ function projectWorkDetailLines(item, snapshot, messages, width) {
|
|
|
808
868
|
add(messages.none);
|
|
809
869
|
if (item.type === "group")
|
|
810
870
|
add(`${messages.changes}: ${item.group.slices.length ? item.group.slices.map((slice) => `${slice.name} (${slice.state})`).join(", ") : messages.none}`);
|
|
811
|
-
|
|
812
|
-
const blockers = external.length ? external.join("; ") : item.type === "group" && item.group.blockers || snapshot.plan.blocked.some((blocked) => blocked.change === item.workRef && blocked.external) ? messages.yes : messages.none;
|
|
813
|
-
add(`${messages.blockers}: ${blockers}`);
|
|
871
|
+
add(`${messages.blockers}: ${blockersLabel(item, snapshot, messages)}`);
|
|
814
872
|
const next = projectNextAction(item, snapshot);
|
|
815
873
|
add(`${next.kind === "command" ? messages.nextCommand : next.kind === "blocked" ? messages.nextAction : messages.reviewGroupBrief}: ${next.kind === "blocked" ? messages.awaitingOwnerDecision : next.value}`);
|
|
816
874
|
return lines;
|
|
@@ -821,6 +879,13 @@ function workStateLabel(item, snapshot, messages) {
|
|
|
821
879
|
const state = projectItemState(item, snapshot);
|
|
822
880
|
return (state.focused ? [messages.focused, messages[state.execution]] : [messages[state.execution]]).join(" \xB7 ");
|
|
823
881
|
}
|
|
882
|
+
function blockersLabel(item, snapshot, messages) {
|
|
883
|
+
const external = projectExternalBlockers(item);
|
|
884
|
+
if (external.length)
|
|
885
|
+
return external.join("; ");
|
|
886
|
+
const inherited = item.type === "group" && item.group.blockers || snapshot.plan.blocked.some((blocked) => blocked.change === item.workRef && blocked.external);
|
|
887
|
+
return inherited ? messages.yes : messages.none;
|
|
888
|
+
}
|
|
824
889
|
function dependencySymbol(node, snapshot) {
|
|
825
890
|
if (snapshot.focused.includes(node.name))
|
|
826
891
|
return "\u25CE";
|
|
@@ -861,9 +926,8 @@ function WorkDetail({ expanded, item, messages, snapshot, width }) {
|
|
|
861
926
|
if (!item || item.type === "history")
|
|
862
927
|
return /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: messages.noWork });
|
|
863
928
|
const forest = projectItemDependencyForest(item, snapshot);
|
|
864
|
-
const externalBlockers = projectExternalBlockers(item, snapshot);
|
|
865
929
|
const nextAction = projectNextAction(item, snapshot);
|
|
866
|
-
const blockers =
|
|
930
|
+
const blockers = blockersLabel(item, snapshot, messages);
|
|
867
931
|
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingLeft: 1, width, children: [
|
|
868
932
|
/* @__PURE__ */ jsxs2(Text2, { bold: true, children: [
|
|
869
933
|
messages.detail,
|
|
@@ -982,10 +1046,16 @@ function scopeNavigation(scope, messages, width) {
|
|
|
982
1046
|
const navigation = labels.map(([candidate, label]) => candidate === scope ? `[${label}]` : label).join(" ");
|
|
983
1047
|
return truncateDisplay(`${messages.title} ${navigation}`, width);
|
|
984
1048
|
}
|
|
1049
|
+
function terminalDimensions(stdout) {
|
|
1050
|
+
return {
|
|
1051
|
+
width: "columns" in stdout && typeof stdout.columns === "number" ? stdout.columns : 80,
|
|
1052
|
+
height: "rows" in stdout && typeof stdout.rows === "number" ? stdout.rows : 24
|
|
1053
|
+
};
|
|
1054
|
+
}
|
|
985
1055
|
function DashboardApp({ initialDimensions, initialSnapshot, inspectHistory, inspectHistoryDetail, inspectHistoryDocument, inspectStatus, messages, specsSource, workSource }) {
|
|
986
1056
|
const { exit } = useApp();
|
|
987
1057
|
const { stdout } = useStdout();
|
|
988
|
-
const dimensions = initialDimensions ??
|
|
1058
|
+
const dimensions = initialDimensions ?? terminalDimensions(stdout);
|
|
989
1059
|
const [state, dispatch] = useReducer(reduceDashboard, initialDashboardState(initialSnapshot, dimensions));
|
|
990
1060
|
const filterRefs = useRef({ work: "", specs: "", history: "" });
|
|
991
1061
|
const refreshing = useRef(false);
|
|
@@ -1182,7 +1252,7 @@ function DashboardApp({ initialDimensions, initialSnapshot, inspectHistory, insp
|
|
|
1182
1252
|
}
|
|
1183
1253
|
}, [detailDocumentState, inspectHistoryDocument, selected, state.scope, workSource]);
|
|
1184
1254
|
useEffect(() => {
|
|
1185
|
-
const resize = () => dispatch({ type: "resize",
|
|
1255
|
+
const resize = () => dispatch({ type: "resize", ...terminalDimensions(stdout) });
|
|
1186
1256
|
stdout.on("resize", resize);
|
|
1187
1257
|
return () => {
|
|
1188
1258
|
stdout.off("resize", resize);
|
|
@@ -1655,6 +1725,22 @@ function createTuiSpecsSource(dependencies = defaultDependencies2) {
|
|
|
1655
1725
|
};
|
|
1656
1726
|
}
|
|
1657
1727
|
|
|
1728
|
+
// src/tui/terminal.ts
|
|
1729
|
+
function openTerminalSession(stdout, options) {
|
|
1730
|
+
let cleaned = false;
|
|
1731
|
+
if (!options.screenReader)
|
|
1732
|
+
stdout.write("\x1B[?1049h\x1B[?25l");
|
|
1733
|
+
return {
|
|
1734
|
+
cleanup() {
|
|
1735
|
+
if (cleaned)
|
|
1736
|
+
return;
|
|
1737
|
+
cleaned = true;
|
|
1738
|
+
if (!options.screenReader)
|
|
1739
|
+
stdout.write("\x1B[?25h\x1B[?1049l");
|
|
1740
|
+
}
|
|
1741
|
+
};
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1658
1744
|
// src/tui/work-source.ts
|
|
1659
1745
|
import { Buffer } from "buffer";
|
|
1660
1746
|
import { constants } from "fs";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oevery/rsp",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.0",
|
|
5
5
|
"description": "RSP (Reliable Software Practice), a repository-native engineering workflow for humans and AI agents",
|
|
6
6
|
"author": "oevery",
|
|
7
7
|
"license": "MIT",
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
"files": [
|
|
30
30
|
"bin/",
|
|
31
31
|
"dist/",
|
|
32
|
-
"rules/",
|
|
33
32
|
"skills/"
|
|
34
33
|
],
|
|
35
34
|
"engines": {
|
|
@@ -37,12 +36,10 @@
|
|
|
37
36
|
},
|
|
38
37
|
"scripts": {
|
|
39
38
|
"prepare": "pnpm run build",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"release
|
|
44
|
-
"skills:security-check": "node scripts/skill-security-preflight.mjs --suppressions skill-security-suppressions.json",
|
|
45
|
-
"prepublishOnly": "pnpm run release:candidate-check",
|
|
39
|
+
"skills:security-check": "node scripts/skill-security-preflight.mjs",
|
|
40
|
+
"skills:package-check": "node scripts/skill-package-check.mjs",
|
|
41
|
+
"prepublishOnly": "pnpm run release:check",
|
|
42
|
+
"release": "release-it",
|
|
46
43
|
"build": "tsup",
|
|
47
44
|
"dev": "tsup --watch",
|
|
48
45
|
"docs:build": "vitepress build docs",
|
|
@@ -53,30 +50,41 @@
|
|
|
53
50
|
"lint": "eslint .",
|
|
54
51
|
"lint:fix": "eslint --fix .",
|
|
55
52
|
"typecheck": "tsc --noEmit",
|
|
56
|
-
"test": "pnpm run build &&
|
|
57
|
-
"test:
|
|
53
|
+
"test": "pnpm run build && pnpm run test:code",
|
|
54
|
+
"test:code": "vitest run --no-file-parallelism",
|
|
55
|
+
"test:diagnostics": "vitest run --config tests/diagnostics/vitest.config.ts",
|
|
56
|
+
"test:pack": "node tests/code/package/package-check.mjs",
|
|
57
|
+
"test:skills": "uv run --frozen --project tests/skills python tests/skills/evaluate.py",
|
|
58
|
+
"release:check": "pnpm run build && pnpm run typecheck && pnpm run lint && pnpm run test:code && pnpm run test:skills check && pnpm run skills:security-check && pnpm run docs:check"
|
|
58
59
|
},
|
|
59
60
|
"dependencies": {
|
|
60
61
|
"citty": "^0.2.2",
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"mdast-util-
|
|
64
|
-
"
|
|
62
|
+
"hast-util-from-html": "^2.0.3",
|
|
63
|
+
"ink": "~8.0.0",
|
|
64
|
+
"mdast-util-from-markdown": "^2.1.0",
|
|
65
|
+
"mdast-util-frontmatter": "^2.0.1",
|
|
66
|
+
"mdast-util-gfm": "^3.1.0",
|
|
67
|
+
"micromark-extension-frontmatter": "^2.0.0",
|
|
68
|
+
"micromark-extension-gfm": "^3.0.0",
|
|
65
69
|
"picocolors": "^1.1.1",
|
|
66
|
-
"react": "~19.
|
|
67
|
-
"yaml": "^2.9.
|
|
70
|
+
"react": "~19.3.1",
|
|
71
|
+
"yaml": "^2.9.1"
|
|
68
72
|
},
|
|
69
73
|
"devDependencies": {
|
|
70
|
-
"@antfu/eslint-config": "^9.
|
|
71
|
-
"@
|
|
74
|
+
"@antfu/eslint-config": "^9.5.1",
|
|
75
|
+
"@release-it/conventional-changelog": "12.0.2",
|
|
76
|
+
"@types/hast": "^3.0.5",
|
|
77
|
+
"@types/mdast": "^4.0.4",
|
|
72
78
|
"@types/node": "^22.20.1",
|
|
73
|
-
"@types/react": "19.
|
|
74
|
-
"eslint": "^10.
|
|
75
|
-
"ink-testing-library": "4.0.0",
|
|
76
|
-
"
|
|
79
|
+
"@types/react": "^19.3.0",
|
|
80
|
+
"eslint": "^10.13.0",
|
|
81
|
+
"ink-testing-library": "^4.0.0",
|
|
82
|
+
"release-it": "21.1.1",
|
|
83
|
+
"smol-toml": "^1.9.1",
|
|
84
|
+
"tsup": "^9.0.0",
|
|
77
85
|
"typescript": "^5.9.3",
|
|
78
86
|
"vitepress": "^1.6.4",
|
|
79
|
-
"vitest": "^
|
|
80
|
-
"wrangler": "^4.
|
|
87
|
+
"vitest": "^5.0.5",
|
|
88
|
+
"wrangler": "^4.151.3"
|
|
81
89
|
}
|
|
82
90
|
}
|
package/skills/rsp/SKILL.md
CHANGED
|
@@ -1,73 +1,78 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rsp
|
|
3
|
-
description:
|
|
3
|
+
description: Coordinate authorized direct, Change or Group work; select capabilities and accept results while executors load their methods. Retain recovery and evidence and prepare delivery without treating completion as closure.
|
|
4
4
|
license: MIT
|
|
5
5
|
metadata:
|
|
6
6
|
author: oevery
|
|
7
|
-
version: "2026.
|
|
7
|
+
version: "2026.10.22.4"
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
# RSP
|
|
10
|
+
# RSP Core
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Carry the authorized request through execution, applicable evidence and needed knowledge updates. Core owns the goal, boundary, capability selection, cross-capability decisions and result acceptance. Capabilities own their methods and may be invoked directly. Skills are the only workflow. A missing or unusable required Skill stops dependent work; report the incomplete installation without reading retired Rules or installing implicitly.
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Select the work and responsibility
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Before mutation, read nearest instructions and relevant CONTEXT; establish intent, authority and the existing owner from evidence. Use known paths and discover missing context as needed. An explicit WorkRef wins; multiple focus markers alone do not block work. Preserve dirty work and its owner. Before switching owners, check overlapping product and knowledge paths; overlap transfers no authority.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
- **Direct:** a clear bounded request needing no durable continuity. Create no Change and run no tracking preflight merely to execute it.
|
|
19
|
+
- **Change:** one delivery/acceptance boundary needing sustained work or cross-session recovery. Read its six sections and relevant Specs; Focus is only a sparse recovery pointer.
|
|
20
|
+
- **Group:** independently acceptable/deliverable child Changes with dependencies or integration obligations. Read the Brief then select a child; the Brief is not executable work. File count, complexity and agent count alone do not create a Group.
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
Load the [work model](references/work-model.md) when tracked identities are missing from context; required tracking cannot be bypassed by relabelling work Direct. Use rsp status for needed owner, dependency or recovery facts, and JSON for exact dependency data. Required dependency checks and fresh archive readiness still apply.
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
Use the CLI invocation selected by the project AGENTS entry: consumer projects pin an exact package in `.rsp/version`; an explicit `.rsp/source` selects the RSP development checkout's own built CLI. `rsp` in these Skills denotes that selection, never `@latest`, a version range, or an unverified global binary. Do not substitute a published package for source mode because version strings match. Only an authorized upgrade selects another exact package target and runs its `update` command for the complete environment; source-mode update retains the local source selection. Upgrade notices grant no migration authority. Resolve needed settings through the selected CLI's successful rsp config --json summary. Reuse it until relevant drift or recovery; raw YAML is diagnostic only. Projection failure blocks choices depending on unknown settings, while independent authorized work continues.
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
Select capabilities from their descriptions and the task contract. Executors load applicable methods and inspect sources; Core consults method details when needed for its own work or a concrete coordination question. Select the responsibility needed now:
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
- rsp-shape: bounded read-only design or authorized planning; reopen planning only for material unresolved choices.
|
|
29
|
+
- rsp-implement: diagnosis, authorized implementation or accepted-finding correction, including ordinary own checks.
|
|
30
|
+
- rsp-doc: substantive document/Skill writing, needed knowledge writeback and final Change reconciliation.
|
|
31
|
+
- rsp-verify: a requested declared-evidence result or a separately required verification obligation; ordinary implementation checks stay with Implement.
|
|
32
|
+
- rsp-review: fixed-scope read-only judgment or explicitly bounded structural discovery. Supporting checks remain within that review.
|
|
33
|
+
- rsp-commit: separately authorized exact local delivery; required for Git execution, with no Core substitute if unavailable.
|
|
27
34
|
|
|
28
|
-
|
|
35
|
+
Continue authorized same-scope work without another continuation request. A phase, role or method change alone requires no tool call, worker, review or test run. Required review, independent execution and protected operations still apply. For ownerless release checks, establish the exact candidate, check contract, baseline and effects authority; invent no Change or Verify owner.
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
2. Return `RouteDisposition: direct` only for one ready owner, one writer, one execution phase, one integrated decisive check, no recovery, no independent acceptance obligation, no managed lifecycle coordination, and no ready successor. Multiple changed files or documentation surfaces do not by themselves alter that route. Perform no Manage handoff or managed Assignment. After the direct result and fresh verification exist, explicit local commit authority may route exactly once to `rsp-commit` with a `direct` owner summary, exact allowed paths, decisive evidence, and current authority; do not invent a Change, WorkRef, lifecycle state, or RSP trailer. An available Commit refusal returns its real missing condition to Core and never becomes a manual fallback. Rederive before further mutation if any condition changes.
|
|
32
|
-
3. Core resolves whether one unambiguous shape-ready Change or shallow Group is the `WorkOwner` before Manage qualification. Missing or non-ready ownership reports `RouteDisposition: shape`; Core invokes Shape only with independently granted planning-artifact authority. Material product or authority questions stop for their `DecisionOwner`; ask one highest-impact owner question that resumes through fresh Core derivation after the answer. Invalid ownership, topology, dirty paths, scope, route, or authority stops for rerouting.
|
|
33
|
-
4. Read [managed routing](references/managed-routing.md) for initial qualification and handoff. On `selected`, pass the WorkRef, authority, evidence, closeout ceiling, and return boundaries to `rsp-manage`. Once selected, Manage solely owns same-goal revalidation, interruption and resume, selected-goal execution, and lifecycle orchestration; `rsp-commit` retains the exact local delivery procedure. Automatic selection grants routing only.
|
|
34
|
-
5. If Manage is declined, continue ordinary routing when the owner and authority are clear; otherwise return the one required input. For incomplete or failed evidence use [Implementation evidence](#implementation-evidence). When required Tasks and verification pass, load [durable writeback decision](references/durable-review.md); do not infer release, archive, Git, publication, approval, or human acceptance.
|
|
37
|
+
## Execute and reconcile evidence
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
Implement owns ordinary self-checks. Main-agent inspection can assess results, but an implementation participant cannot certify required independent review. Select extra Verify/Review only when requested, required or supported by concrete risk, not per task or per worker automatically.
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
Reuse traceable observations, checks and reviews while their target, acceptance boundary and relevant inputs still apply. Changed code, dependencies, configuration, tools or environment invalidate affected evidence; role changes and delivery-scope confirmation alone do not. Include excluded worktree inputs when assessing a staged slice, and recognize behavior changes in normative Specs or executable Skills even when stored as Markdown.
|
|
39
42
|
|
|
40
|
-
|
|
43
|
+
Check paths, diff, outcomes, omissions and evidence applicability. Reuse executor checks when applicable. Independent semantic review may use implementer test evidence; required independent execution must run. Keep commands, results, tested boundaries and decisive sources with their existing owner, including failures, unavailable checks and superseded results. Add no evidence ledger.
|
|
41
44
|
|
|
42
|
-
For
|
|
45
|
+
For required correction/re-review, load [review convergence](references/coordination-review.md). Batch compatible findings into one correction, run covering checks, then review finding resolution and new risks in the correction. Stop for changed scope/authority, unsafe replay, missing required capability, non-convergence or no new discriminating evidence. Required failures remain incomplete.
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
Dependent writes require successful prerequisites; observe each required result rather than relying on a batch's final exit status. Recover tool failures within unchanged authority, inspecting uncertain effects before safe replay. Named checks and Commit's one-attempt rule remain binding.
|
|
45
48
|
|
|
46
|
-
|
|
49
|
+
## Coordinate only when needed and allowed
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
Work shape does not choose agent topology. Automatic delegation defaults off. An explicit worker request or binding independent-worker requirement permits that bounded dispatch; otherwise resolve workflow.delegation before automatic delegation. When auto is enabled, the user or main agent chooses zero, one or multiple execution workers. RSP has no worker-count tiers or maximum; host constraints still apply.
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
Load [worker coordination](references/coordination.md) for actual dispatch, dependencies/shared-resource arbitration or required independent workers. Keep tightly coupled work local; never simulate missing worker identity or independence. Workers do not delegate further by default. Main retains integration and result acceptance; child passes do not establish integration coverage.
|
|
51
54
|
|
|
52
|
-
|
|
55
|
+
Load [interruption recovery](references/coordination-recovery.md) for pause/resume or unsettled host effects, and [focus continuation](references/focus-continuation.md) for a recovery snapshot. Cross-session continuation refreshes current authority, owner, applicable status, Git index, dirty paths, evidence applicability and replay safety. Cancelling a wait does not stop workers or release resources.
|
|
53
56
|
|
|
54
|
-
|
|
57
|
+
## Maintain records and prepare delivery
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
During execution update Tasks/Verify directly for actual outcomes when scope, contract, design and knowledge remain accurate. Consolidate repeated conclusions for the same scope and candidate; retain distinct inputs, outcomes, material failures and evidence references. When changing Blockers, use the [shared work-model syntax](references/work-model.md). Passing checks or recovery alone adds no whole-document rewrite. Routine narration stays in the conversation; retained execution evidence stays with its existing owner. Focus is replaceable recovery guidance, never acceptance or authority.
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
- [groups and dependencies](references/groups-dependencies.md) for grouped or dependent work.
|
|
60
|
-
- [conflict handling](references/conflict-handling.md) for an intersecting Git operation.
|
|
61
|
-
- [durable writeback decision](references/durable-review.md) after required Tasks and implementation verification pass.
|
|
61
|
+
Ordinary completion and checkpoint commits leave Change open; a generic commit request does not establish final delivery. At established final delivery or an explicit close request, load [delivery closeout](references/closeout.md). workflow.closeout is ask (default), auto or manual; no setting grants Git, push, publication, deployment, approval or human acceptance authority.
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
For necessary stable-knowledge updates, load [durable writeback](references/durable-review.md) to establish facts, update their owners and reconcile affected records. Final delivery or closure additionally requires whole-Change convergence and consistency checks. Reuse applicable evidence and fill missing or invalidated coverage and separately required review. Already-accurate records need no edit; current readiness is a lifecycle observation, not semantic acceptance.
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
Operate command-owned state through RSP commands. Persist only open and archived; derive readiness and routing. A complete Task list never closes work. Reopen is exceptional recovery requiring explicit authority: load [reopen recovery](references/reopen-recovery.md) only when actually needed.
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
Other conditional procedures:
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
- [Setup and repair](references/setup-repair.md) for initialization, audit or repair.
|
|
70
|
+
- [Groups and dependencies](references/groups-dependencies.md) for grouped work.
|
|
71
|
+
- [Context migration](references/context-migration.md) when a root/relevant legacy CONTEXT-MAP.md is found or migration requested; preserve context, discovery alone grants no migration.
|
|
72
|
+
- [Conflict handling](references/conflict-handling.md) for an intersecting Git operation.
|
|
70
73
|
|
|
71
|
-
##
|
|
74
|
+
## Return the result
|
|
72
75
|
|
|
73
|
-
|
|
76
|
+
Follow explicit response language, personal instructions, then conversation language. Existing artifacts retain their language; new artifacts follow explicit instruction, effective project settings, scoped instructions, then conversation language. Keep identifiers and machine values exact; load [language details](references/response-language.md) only for contested choices.
|
|
77
|
+
|
|
78
|
+
Report the outcome, decisive evidence, material limits and needed next action. Distinguish observed effects, checks, review and acceptance; unverified claims stay unverified. Missing Required evidence blocks only dependent completion. No mandatory phase receipts or repeated logs. Load [control outcome](references/control-outcome.md) only for a consumer needing its technical rendering. For unfinished work retain only the owner, authority, evidence, blocker and safe continuation needed by the next actor.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Final delivery and lifecycle closeout
|
|
2
|
+
|
|
3
|
+
Load for an established final-delivery boundary, an explicit close request, or a delivery question requiring checkpoint classification. Ordinary completion never activates closeout. A generic commit request defaults to a checkpoint unless final delivery is already established; checkpoints keep Change open and require only the authorized slice and applicable evidence.
|
|
4
|
+
|
|
5
|
+
## Decide closure independently of Git
|
|
6
|
+
|
|
7
|
+
Use the validated workflow.closeout setting from rsp config --json:
|
|
8
|
+
|
|
9
|
+
- ask (default): prepare a concrete final boundary, applicable evidence and required knowledge/Change updates, then ask whether to close before terminal staging. Reuse explicit closure authority already granted; do not ask twice.
|
|
10
|
+
- auto: close eligible work at established final delivery without another closure request, subject to nearer denial.
|
|
11
|
+
- manual: close only on an explicit close request. Authorized final commits may leave work open and must report that fact.
|
|
12
|
+
|
|
13
|
+
Explicit refusal keeps work open. A decision to leave it open does not block an otherwise authorized commit. Neither policy, readiness nor archive grants Git authority. An explicit standalone close request can close eligible work without a commit. Do not interpret finishing implementation, a pass, a successor task or elapsed time as final delivery.
|
|
14
|
+
|
|
15
|
+
## Reconcile the final boundary
|
|
16
|
+
|
|
17
|
+
1. Confirm exact delivery scope and inspect existing evidence for that boundary.
|
|
18
|
+
2. Apply [durable writeback](durable-review.md): necessary stable knowledge first, final Change reconciliation second. These can be one operation with no edits when already current.
|
|
19
|
+
3. Fill missing or invalidated checks and separately required review. Reuse applicable results; ordinary record cleanup does not invalidate code tests. Changed normative contracts and executable Skills need affected checks/judgment. Fresh independent review is not a universal closeout prerequisite.
|
|
20
|
+
4. For each Change to close, obtain current rsp ready <work-ref> --json with completionGate: pass and archiveReady: yes. Also require accurate final records, completed or unnecessary knowledge updates, applicable Required evidence and every separately required review. Readiness alone does not establish semantic acceptance.
|
|
21
|
+
|
|
22
|
+
Missing Required evidence, active blockers or contradictory contracts prevent closure. Optional omissions remain visible. Fresh authority, owner and exact Git/lifecycle observations remain necessary even when tests are reused.
|
|
23
|
+
|
|
24
|
+
## Close only when authorized
|
|
25
|
+
|
|
26
|
+
Run rsp archive <work-ref>. Inspect the resulting archive and entire lifecycle diff, including Focus removal and cleanup warnings. Use the returned filename in the selected WorkRef's archive directory: .rsp/archives/ for an ungrouped Change, .rsp/archives/<group>/ for a child. Do not guess dates, suffixes or directories. Expand read-only discovery only for incomplete or contradictory output/effects; do not replay the mutation.
|
|
27
|
+
|
|
28
|
+
For a Group, archive eligible authorized children independently, reconcile the Brief and integrated evidence, then run rsp group close <group> after every child and Group gate passes. Request-only integration conditions must first be recorded in the Brief; child passes alone do not prove integration.
|
|
29
|
+
|
|
30
|
+
Never delete or copy lifecycle files to bypass commands. If archive succeeds but commit fails, report the archived, uncommitted state. Do not automatically reopen, rewrite history or repeat uncertain mutations.
|
|
31
|
+
|
|
32
|
+
## Route exact delivery separately
|
|
33
|
+
|
|
34
|
+
With explicit local commit authority, route to rsp-commit with the delivery kind (direct, change, integration, group or release), purpose (checkpoint or terminal), real owner/WorkRefs, exact paths, applicable verification and lifecycle evidence only when applicable. No transport schema or duplicate receipt is required.
|
|
35
|
+
|
|
36
|
+
Integration requires at least two real WorkRefs and one shared delivery boundary but creates no Group. Ambiguous, mixed, stale or denied boundaries stop before staging. Missing Commit capability has no Core fallback. Commit audits the exact index and owns Git execution.
|
|
37
|
+
|
|
38
|
+
Push requires explicit authority and an unambiguous remote, branch and milestone. Never infer it from commit or closure; no force push or automatic publication. Remote failure preserves local commits and stops at that boundary.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Context migration
|
|
2
|
+
|
|
3
|
+
Load when a legacy CONTEXT-MAP.md is found, CLI reports it, or the user requests context migration. This is a conditional Core method, not a separate Skill or a mandatory project phase. CONTEXT.md remains the target model for vocabulary, domain relationships, and navigation.
|
|
4
|
+
|
|
5
|
+
## Inspect without migrating
|
|
6
|
+
|
|
7
|
+
Read the relevant legacy map, existing root/local CONTEXT files, scoped instructions, and incoming references. File presence is a migration signal, not proof that its content is obsolete or that an existing CONTEXT already contains it. Resolve overlapping or contradictory definitions with their owner; do not choose a winner from the filename.
|
|
8
|
+
|
|
9
|
+
Without migration authority, preserve files and use the legacy content relevant to the current task alongside current context. Report the pending migration without repeatedly demanding it or blocking unrelated work. Stop only work that depends on an unresolved meaning or authority conflict. Do not follow unsafe or out-of-scope paths merely because a legacy map points to them.
|
|
10
|
+
|
|
11
|
+
## Migrate within explicit scope
|
|
12
|
+
|
|
13
|
+
Establish authorized source files, target owners, reference updates, and whether retiring the old file is included. Reuse the selected WorkRef when tracked; bounded direct migration needs no new work record.
|
|
14
|
+
|
|
15
|
+
1. Map useful terms, relationships, and navigation to their root/local CONTEXT owners. Keep contracts and operating rules with their existing Spec/AGENTS owners, using links instead of parallel definitions. Resolve material conflicts before changing their meaning.
|
|
16
|
+
2. Merge into existing context without overwriting unrelated content or renaming concepts for consistency alone. For substantial writing use Doc when available; otherwise preserve meaning and verify the reader's navigation directly. Doc supplies the writing method, not migration or deletion authority.
|
|
17
|
+
3. Update active references and entry instructions. Check both lost meaning and broken paths; historical snapshots need not be rewritten.
|
|
18
|
+
4. Retire the old map only after checking preserved meaning, active references, and explicit retirement authority. If any gate is missing, keep it and report the remaining work.
|
|
19
|
+
|
|
20
|
+
`rsp update` and `rsp doctor` only detect the root legacy path and provide guidance; they do not compare semantics, merge context, or retire project files. A successful command is not migration acceptance.
|
|
21
|
+
|
|
22
|
+
Return the source-to-owner result, changed files, checks, and unresolved conflicts or permissions. Migration completion derives from inspected documents and references, not a new marker or stored lifecycle state.
|