@lifeaitools/rdc-skills 0.24.24 → 0.24.26
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/.claude-plugin/plugin.json +1 -1
- package/README.md +28 -18
- package/commands/help.md +1 -0
- package/git-sha.json +1 -1
- package/lib/catalog.mjs +31 -2
- package/package.json +1 -1
- package/skills/help/SKILL.md +1 -0
- package/tests/curl-surface.test.mjs +10 -0
- package/tests/help-surface.test.mjs +15 -1
- package/tests/mcp.test.mjs +17 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rdc",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.26",
|
|
4
4
|
"description": "RDC typed-agent dispatch skill suite for Claude Code — plan, build, review, overnight unattended builds with work-item tracking and TDD enforcement.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "LIFEAI",
|
package/README.md
CHANGED
|
@@ -124,6 +124,12 @@ curl -s -X POST https://rdc-skills.regendevcorp.com/mcp \
|
|
|
124
124
|
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"rdc_skill_list","arguments":{}}}'
|
|
125
125
|
```
|
|
126
126
|
|
|
127
|
+
`rdc_skill_list` returns the full caller-facing catalog for each skill:
|
|
128
|
+
`name`, `slash`, accepted `aliases`, `category`, `summary`, `when_to_use`,
|
|
129
|
+
`usage`, `args`, `requires`, `produces`, `follows`, `leads_to`,
|
|
130
|
+
`default_model`, `sandbox_aware`, `output_contract`, `enabled_default`,
|
|
131
|
+
`codeflow_required`, and supported `variants` (`cli`, `cloud`).
|
|
132
|
+
|
|
127
133
|
Search by natural-language intent:
|
|
128
134
|
|
|
129
135
|
```bash
|
|
@@ -286,31 +292,35 @@ Boundaries:
|
|
|
286
292
|
|
|
287
293
|
```
|
|
288
294
|
skills/
|
|
295
|
+
brochure/SKILL.md (print-quality PDF rendering)
|
|
289
296
|
build/SKILL.md (dispatch agents in waves — mandatory validator gate)
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
review/SKILL.md (quality gate: tests, types, docs)
|
|
293
|
-
overnight/SKILL.md (unattended multi-epic supervisor)
|
|
294
|
-
fixit/SKILL.md (quick-fix bypass)
|
|
295
|
-
status/SKILL.md (project dashboard)
|
|
296
|
-
report/SKILL.md (nightly report)
|
|
297
|
+
channel-formatter/SKILL.md (channel-native formatting and content packs)
|
|
298
|
+
co-develop/SKILL.md (peer-aware Claude/Codex co-development)
|
|
297
299
|
collab/SKILL.md (bidirectional claude.ai ↔ Claude Code relay)
|
|
300
|
+
convert/SKILL.md (Office/Markdown conversion)
|
|
301
|
+
deploy/SKILL.md (Coolify ops: deploy, new, diagnose, audit)
|
|
302
|
+
design/SKILL.md (RDC/Studio design, Palette Library, Rampa CLI)
|
|
303
|
+
fixit/SKILL.md (quick-fix bypass)
|
|
304
|
+
fs-mcp/SKILL.md (File System MCP bridge guidance)
|
|
298
305
|
handoff/SKILL.md (planning → work items)
|
|
306
|
+
help/SKILL.md (manifest-driven skill index)
|
|
307
|
+
housekeeping/SKILL.md (weekly maintenance audit)
|
|
308
|
+
lifeai-brochure-author/SKILL.md (brochure JSX authoring)
|
|
309
|
+
overnight/SKILL.md (unattended multi-epic supervisor)
|
|
310
|
+
plan/SKILL.md (create architecture + tasks)
|
|
311
|
+
preplan/SKILL.md (research before planning)
|
|
299
312
|
prototype/SKILL.md (build JSX prototype)
|
|
300
|
-
workitems/SKILL.md (work item management)
|
|
301
|
-
design/SKILL.md (RDC/Studio design, Palette Library, Rampa CLI)
|
|
302
|
-
help/SKILL.md (skill index — shows current version)
|
|
303
|
-
deploy/SKILL.md (Coolify ops: deploy, new, diagnose, audit)
|
|
304
|
-
release/SKILL.md (atomic package/app release)
|
|
305
|
-
self-test/SKILL.md (skill suite health check)
|
|
306
|
-
watch/SKILL.md (session log watcher)
|
|
307
|
-
channel-formatter/SKILL.md (channel-native formatting and content packs)
|
|
308
|
-
convert/SKILL.md (Office/Markdown conversion)
|
|
309
|
-
brochure/SKILL.md (print-quality PDF rendering)
|
|
310
313
|
rdc-brochurify/SKILL.md (Brochurify orchestration)
|
|
311
|
-
lifeai-brochure-author/SKILL.md (brochure JSX authoring)
|
|
312
314
|
rdc-extract-verifier-rules/SKILL.md (verifier rule extraction)
|
|
315
|
+
release/SKILL.md (atomic package/app release)
|
|
316
|
+
report/SKILL.md (nightly report)
|
|
317
|
+
review/SKILL.md (quality gate: tests, types, docs)
|
|
313
318
|
rpms-filemap/SKILL.md (canonical RPMS file map)
|
|
319
|
+
self-test/SKILL.md (skill suite health check)
|
|
320
|
+
status/SKILL.md (project dashboard)
|
|
321
|
+
terminal-config/SKILL.md (Windows Terminal and hidden-launch policy)
|
|
322
|
+
watch/SKILL.md (session log watcher)
|
|
323
|
+
workitems/SKILL.md (work item management)
|
|
314
324
|
|
|
315
325
|
guides/agents/ (agent-only playbooks — dispatched by rdc:build, not user-invocable)
|
|
316
326
|
frontend.md (React, UI, Tailwind)
|
package/commands/help.md
CHANGED
|
@@ -47,6 +47,7 @@ Header: Accept: application/json, text/event-stream
|
|
|
47
47
|
Tools: rdc_skill_list, rdc_skill_search, rdc_skill_get
|
|
48
48
|
Variants: cli for Claude Code/Codex/local terminal; cloud for claude.ai
|
|
49
49
|
Response: SSE `data:` line contains the JSON-RPC envelope; tool text is result.content[0].text
|
|
50
|
+
Catalog: rdc_skill_list returns aliases, args, requires, produces, follows, leads_to, output_contract, codeflow_required, and variants
|
|
50
51
|
```
|
|
51
52
|
|
|
52
53
|
Minimal curl examples:
|
package/git-sha.json
CHANGED
package/lib/catalog.mjs
CHANGED
|
@@ -51,9 +51,12 @@ function toCatalogEntry(name, meta, frontmatter) {
|
|
|
51
51
|
const metaTriggers = Array.isArray(meta.triggers) && meta.triggers.length ? meta.triggers : null;
|
|
52
52
|
const fmTriggers = Array.isArray(fm.triggers) ? fm.triggers : [];
|
|
53
53
|
const slash = meta.slash || fm.slash || `rdc:${name}`;
|
|
54
|
+
const aliases = [name, slash];
|
|
55
|
+
if (slash.startsWith('rdc:')) aliases.push(`/${slash}`);
|
|
54
56
|
return {
|
|
55
57
|
name,
|
|
56
58
|
slash,
|
|
59
|
+
aliases,
|
|
57
60
|
category: meta.category || fm.category || 'tooling',
|
|
58
61
|
summary: description,
|
|
59
62
|
when_to_use: metaTriggers || fmTriggers,
|
|
@@ -62,6 +65,18 @@ function toCatalogEntry(name, meta, frontmatter) {
|
|
|
62
65
|
args: meta.args || fm.args || { positional: [], flags: [] },
|
|
63
66
|
requires: Array.isArray(meta.requires) ? meta.requires
|
|
64
67
|
: Array.isArray(fm.requires) ? fm.requires : [],
|
|
68
|
+
produces: Array.isArray(meta.produces) ? meta.produces
|
|
69
|
+
: Array.isArray(fm.produces) ? fm.produces : [],
|
|
70
|
+
follows: Array.isArray(meta.follows) ? meta.follows
|
|
71
|
+
: Array.isArray(fm.follows) ? fm.follows : [],
|
|
72
|
+
leads_to: Array.isArray(meta.leads_to) ? meta.leads_to
|
|
73
|
+
: Array.isArray(fm.leads_to) ? fm.leads_to : [],
|
|
74
|
+
default_model: meta.default_model || fm.default_model || 'inherit',
|
|
75
|
+
sandbox_aware: Boolean(meta.sandbox_aware ?? fm.sandbox_aware ?? false),
|
|
76
|
+
output_contract: meta.output_contract || fm.output_contract || null,
|
|
77
|
+
enabled_default: Boolean(meta.enabled_default ?? fm.enabled_default ?? true),
|
|
78
|
+
codeflow_required: Boolean(meta.codeflow_required ?? fm.codeflow_required ?? false),
|
|
79
|
+
variants: ['cli', 'cloud'],
|
|
65
80
|
};
|
|
66
81
|
}
|
|
67
82
|
|
|
@@ -179,7 +194,8 @@ export function getCloudOverride(name) {
|
|
|
179
194
|
|
|
180
195
|
/**
|
|
181
196
|
* Fuzzy/substring search over name + slash + summary + triggers.
|
|
182
|
-
* Returns ranked
|
|
197
|
+
* Returns ranked rows with enough metadata for raw MCP/curl callers to choose
|
|
198
|
+
* and fetch a skill without a second catalog lookup. score: higher = better.
|
|
183
199
|
*/
|
|
184
200
|
export function searchSkills(query) {
|
|
185
201
|
const q = String(query || '').trim().toLowerCase();
|
|
@@ -201,7 +217,20 @@ export function searchSkills(query) {
|
|
|
201
217
|
if (hay.triggers.includes(term)) score += 12;
|
|
202
218
|
if (hay.summary.includes(term)) score += 6;
|
|
203
219
|
}
|
|
204
|
-
if (score > 0)
|
|
220
|
+
if (score > 0) {
|
|
221
|
+
results.push({
|
|
222
|
+
name: s.name,
|
|
223
|
+
slash: s.slash,
|
|
224
|
+
aliases: s.aliases,
|
|
225
|
+
category: s.category,
|
|
226
|
+
summary: s.summary,
|
|
227
|
+
usage: s.usage,
|
|
228
|
+
requires: s.requires,
|
|
229
|
+
codeflow_required: s.codeflow_required,
|
|
230
|
+
variants: s.variants,
|
|
231
|
+
score,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
205
234
|
}
|
|
206
235
|
return results.sort((a, b) => b.score - a.score);
|
|
207
236
|
}
|
package/package.json
CHANGED
package/skills/help/SKILL.md
CHANGED
|
@@ -95,6 +95,7 @@ RDC SKILLS — manifest: .claude-plugin/plugin.json @ v{version}
|
|
|
95
95
|
Tools: rdc_skill_list, rdc_skill_search, rdc_skill_get
|
|
96
96
|
Variants: cli for Claude Code/Codex/local terminal; cloud for claude.ai
|
|
97
97
|
Response: SSE `data:` line contains the JSON-RPC envelope; tool text is result.content[0].text
|
|
98
|
+
Catalog: rdc_skill_list returns aliases, args, requires, produces, follows, leads_to, output_contract, codeflow_required, and variants
|
|
98
99
|
|
|
99
100
|
Extract the JSON-RPC envelope:
|
|
100
101
|
curl -s -X POST https://rdc-skills.regendevcorp.com/mcp \
|
|
@@ -170,6 +170,12 @@ async function main() {
|
|
|
170
170
|
const listed = JSON.parse(resultText(latestEnvelope(list.stdout)));
|
|
171
171
|
check('rdc_skill_list exposes 29 skills', listed.count === 29, `count ${listed.count}`);
|
|
172
172
|
check('rdc_skill_list includes visible slash name', listed.skills.some((s) => s.slash === 'rdc:build'));
|
|
173
|
+
const buildRow = listed.skills.find((s) => s.name === 'build');
|
|
174
|
+
check('rdc_skill_list exposes aliases for slash callers', buildRow?.aliases?.includes('/rdc:build'));
|
|
175
|
+
check('rdc_skill_list exposes supported variants', JSON.stringify(buildRow?.variants) === JSON.stringify(['cli', 'cloud']));
|
|
176
|
+
check('rdc_skill_list exposes output contract metadata', typeof buildRow?.output_contract === 'string');
|
|
177
|
+
check('rdc_skill_list exposes CodeFlow requirement metadata', buildRow?.codeflow_required === true);
|
|
178
|
+
check('rdc_skill_list exposes side-effect metadata', Array.isArray(buildRow?.produces));
|
|
173
179
|
|
|
174
180
|
const search = postMcp({
|
|
175
181
|
jsonrpc: '2.0',
|
|
@@ -186,6 +192,10 @@ async function main() {
|
|
|
186
192
|
'natural language search finds channel formatter',
|
|
187
193
|
searchBody.results?.some((s) => s.name === 'channel-formatter' || s.slash === 'rdc:channel-formatter'),
|
|
188
194
|
);
|
|
195
|
+
const formatterHit = searchBody.results?.find((s) => s.name === 'channel-formatter');
|
|
196
|
+
check('rdc_skill_search exposes usage metadata', /rdc:channel-formatter/.test(formatterHit?.usage || ''));
|
|
197
|
+
check('rdc_skill_search exposes category metadata', formatterHit?.category === 'tooling');
|
|
198
|
+
check('rdc_skill_search exposes variant metadata', formatterHit?.variants?.includes('cloud'));
|
|
189
199
|
|
|
190
200
|
const get = postMcp({
|
|
191
201
|
jsonrpc: '2.0',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
|
-
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
4
4
|
import { dirname, join, resolve } from 'node:path';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
6
|
|
|
@@ -26,6 +26,9 @@ for (const [name, text] of Object.entries(docs)) {
|
|
|
26
26
|
assert.match(text, /rdc_skill_list/, `${name} must mention rdc_skill_list`);
|
|
27
27
|
assert.match(text, /rdc_skill_search/, `${name} must mention rdc_skill_search`);
|
|
28
28
|
assert.match(text, /rdc_skill_get/, `${name} must mention rdc_skill_get`);
|
|
29
|
+
assert.match(text, /output_contract/, `${name} must describe rdc_skill_list metadata fields`);
|
|
30
|
+
assert.match(text, /codeflow_required/, `${name} must describe CodeFlow metadata`);
|
|
31
|
+
assert.match(text, /variants/, `${name} must describe supported skill variants`);
|
|
29
32
|
assert.match(text, /turn this article into social posts/, `${name} must include a natural-language search example`);
|
|
30
33
|
assert.match(text, /"name":"rdc:build"/, `${name} must show rdc_skill_get accepts visible slash names`);
|
|
31
34
|
assert.doesNotMatch(text, /https:\/\/rdc-skills\.dev\.regendevcorp\.com\/mcp/, `${name} must not point callers at dev MCP`);
|
|
@@ -43,4 +46,15 @@ assert.match(docs.commandHelp, /manifest-driven/i, 'command help should be manif
|
|
|
43
46
|
assert.doesNotMatch(docs.commandHelp, /Print the full usage menu below verbatim/, 'command help must not use stale static menu wording');
|
|
44
47
|
assert.doesNotMatch(docs.commandHelp, /get\/<service>/, 'command help must use current clauth /v/<service> wording');
|
|
45
48
|
|
|
49
|
+
const skillDirs = readdirSync(join(root, 'skills'))
|
|
50
|
+
.filter((name) => {
|
|
51
|
+
const dir = join(root, 'skills', name);
|
|
52
|
+
return statSync(dir).isDirectory() && existsSync(join(dir, 'SKILL.md'));
|
|
53
|
+
})
|
|
54
|
+
.sort();
|
|
55
|
+
const readmeSkillDirs = [...docs.readme.matchAll(/^\s{2}([A-Za-z0-9_-]+)\/SKILL\.md/gm)]
|
|
56
|
+
.map((match) => match[1])
|
|
57
|
+
.sort();
|
|
58
|
+
assert.deepEqual(readmeSkillDirs, skillDirs, 'README File Structure must list every skill directory exactly once');
|
|
59
|
+
|
|
46
60
|
console.log('help surface tests — PASS');
|
package/tests/mcp.test.mjs
CHANGED
|
@@ -89,6 +89,21 @@ function unitTests() {
|
|
|
89
89
|
check('unit: catalog non-empty', cat.length >= 20, `got ${cat.length}`);
|
|
90
90
|
check('unit: every entry has name+slash+category+summary field',
|
|
91
91
|
cat.every((s) => s.name && s.slash && s.category && 'summary' in s));
|
|
92
|
+
check('unit: every entry exposes caller metadata fields',
|
|
93
|
+
cat.every((s) => Array.isArray(s.aliases)
|
|
94
|
+
&& Array.isArray(s.produces)
|
|
95
|
+
&& Array.isArray(s.follows)
|
|
96
|
+
&& Array.isArray(s.leads_to)
|
|
97
|
+
&& Array.isArray(s.variants)
|
|
98
|
+
&& 'default_model' in s
|
|
99
|
+
&& 'sandbox_aware' in s
|
|
100
|
+
&& 'output_contract' in s
|
|
101
|
+
&& 'enabled_default' in s
|
|
102
|
+
&& 'codeflow_required' in s));
|
|
103
|
+
check('unit: every entry exposes cli/cloud variants',
|
|
104
|
+
cat.every((s) => JSON.stringify(s.variants) === JSON.stringify(['cli', 'cloud'])));
|
|
105
|
+
check('unit: every rdc slash entry includes leading slash alias',
|
|
106
|
+
cat.every((s) => !s.slash.startsWith('rdc:') || s.aliases.includes(`/${s.slash}`)));
|
|
92
107
|
check('unit: every slash is explicit caller-facing shape',
|
|
93
108
|
cat.every((s) => /^rdc:/.test(s.slash) || s.slash === s.name));
|
|
94
109
|
check('unit: no synthesized duplicate rdc prefixes',
|
|
@@ -190,6 +205,8 @@ async function sweep(url, label, { compareSource }) {
|
|
|
190
205
|
const se = await mcp(url, { jsonrpc: '2.0', id: 21, method: 'tools/call', params: { name: 'rdc_skill_search', arguments: { query: 'deploy' } } });
|
|
191
206
|
let sr; try { sr = JSON.parse(callText(se.json)); } catch { sr = { results: [] }; }
|
|
192
207
|
check(`${label}: search returns ranked results`, (sr.results || []).length > 0 && sr.results[0].name);
|
|
208
|
+
check(`${label}: search result includes caller metadata`,
|
|
209
|
+
Boolean(sr.results?.[0]?.usage && sr.results?.[0]?.category && Array.isArray(sr.results?.[0]?.variants)));
|
|
193
210
|
|
|
194
211
|
return names.length;
|
|
195
212
|
}
|