@lifeaitools/rdc-skills 0.24.25 → 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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rdc",
3
- "version": "0.24.25",
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
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
@@ -1,3 +1,3 @@
1
1
  {
2
- "sha": "3adce37239675bd6c9d69b585053ff8bf3ee8137"
2
+ "sha": "5884908869da0ae91e3c004d9af344da71ae0079"
3
3
  }
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 [{ name, slash, summary, score }] (score: higher = better).
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) results.push({ name: s.name, slash: s.slash, summary: s.summary, score });
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifeaitools/rdc-skills",
3
- "version": "0.24.25",
3
+ "version": "0.24.26",
4
4
  "description": "RDC typed-agent dispatch skill suite for Claude Code - plan, build, review, overnight builds",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -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',
@@ -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`);
@@ -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
  }