@lifeaitools/rdc-skills 0.9.33 → 0.9.35
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 +2 -1
- package/.github/workflows/self-test.yml +34 -34
- package/CHANGELOG.md +10 -0
- package/README.md +1 -1
- package/commands/build.md +181 -181
- package/commands/collab.md +180 -180
- package/commands/deploy.md +152 -152
- package/commands/fixit.md +105 -105
- package/commands/handoff.md +173 -173
- package/commands/overnight.md +220 -220
- package/commands/plan.md +158 -158
- package/commands/preplan.md +131 -131
- package/commands/prototype.md +145 -145
- package/commands/report.md +99 -99
- package/commands/review.md +120 -120
- package/commands/status.md +86 -86
- package/commands/workitems.md +127 -127
- package/guides/agent-bootstrap.md +206 -202
- package/guides/agents/backend.md +102 -102
- package/guides/agents/content.md +94 -94
- package/guides/agents/cs2.md +56 -56
- package/guides/agents/data.md +86 -86
- package/guides/agents/design.md +77 -77
- package/guides/agents/frontend.md +91 -91
- package/guides/agents/infrastructure.md +81 -81
- package/guides/agents/setup.md +280 -278
- package/guides/agents/verify.md +119 -119
- package/guides/agents/viz.md +106 -106
- package/guides/engineering-behavior.md +43 -0
- package/hooks/rdc-invocation-marker.js +143 -0
- package/hooks/rdc-output-contract-gate.js +85 -0
- package/package.json +2 -2
- package/scripts/install-rdc-skills.js +29 -0
- package/scripts/install.ps1 +15 -0
- package/scripts/self-test.mjs +1414 -1323
- package/skills/build/SKILL.md +359 -355
- package/skills/collab/SKILL.md +217 -217
- package/skills/deploy/SKILL.md +198 -198
- package/skills/design/SKILL.md +211 -211
- package/skills/fixit/SKILL.md +136 -132
- package/skills/fs-mcp/SKILL.md +131 -0
- package/skills/handoff/SKILL.md +200 -200
- package/skills/help/SKILL.md +104 -104
- package/skills/overnight/SKILL.md +224 -224
- package/skills/plan/SKILL.md +252 -252
- package/skills/preplan/SKILL.md +86 -86
- package/skills/prototype/SKILL.md +150 -150
- package/skills/release/SKILL.md +342 -342
- package/skills/report/SKILL.md +100 -100
- package/skills/review/SKILL.md +122 -121
- package/skills/self-test/SKILL.md +126 -126
- package/skills/status/SKILL.md +99 -99
- package/skills/watch/SKILL.md +91 -91
- package/skills/workitems/SKILL.md +151 -151
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Stop hook — enforce visible RDC output contract artifacts.
|
|
4
|
+
*
|
|
5
|
+
* Triggered only when rdc-invocation-marker.js has marked the session. It checks
|
|
6
|
+
* positive output patterns only: at least one checklist row and one verdict
|
|
7
|
+
* line. It intentionally does not police forbidden phrases.
|
|
8
|
+
*/
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const os = require('os');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const hookLog = require('./hook-logger');
|
|
15
|
+
|
|
16
|
+
function readStdin() {
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
let input = '';
|
|
19
|
+
process.stdin.setEncoding('utf8');
|
|
20
|
+
process.stdin.on('data', (chunk) => { input += chunk; });
|
|
21
|
+
process.stdin.on('end', () => resolve(input));
|
|
22
|
+
process.stdin.resume();
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function markerPath(sessionId) {
|
|
27
|
+
const safe = String(sessionId || 'unknown').replace(/[^a-zA-Z0-9_.-]/g, '_');
|
|
28
|
+
return path.join(os.homedir(), '.claude', 'rdc-active', `${safe}.json`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function readMarker(sessionId) {
|
|
32
|
+
const p = markerPath(sessionId);
|
|
33
|
+
if (!fs.existsSync(p)) return null;
|
|
34
|
+
try {
|
|
35
|
+
return { path: p, data: JSON.parse(fs.readFileSync(p, 'utf8')) };
|
|
36
|
+
} catch {
|
|
37
|
+
return { path: p, data: { command: 'unknown' } };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function hasChecklist(text) {
|
|
42
|
+
return /(?:^|\n)\s*(?:[-*]\s*)?\[(?: |x|X|~|!|-)\]\s+\S/m.test(text || '');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function hasVerdict(text) {
|
|
46
|
+
return /(?:^|\n)\s*(?:✅|⚠️|❌)\s+\S/m.test(text || '');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function block(reason, details = {}) {
|
|
50
|
+
hookLog('rdc-output-contract-gate', 'Stop', 'block', details);
|
|
51
|
+
process.stdout.write(JSON.stringify({ decision: 'block', reason }));
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function pass(marker) {
|
|
56
|
+
try { fs.unlinkSync(marker.path); } catch {}
|
|
57
|
+
hookLog('rdc-output-contract-gate', 'Stop', 'pass', {
|
|
58
|
+
command: marker.data.command || null,
|
|
59
|
+
});
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function main() {
|
|
64
|
+
let raw;
|
|
65
|
+
try { raw = JSON.parse(await readStdin()); } catch { process.exit(0); }
|
|
66
|
+
const marker = readMarker(raw.session_id);
|
|
67
|
+
if (!marker) process.exit(0);
|
|
68
|
+
|
|
69
|
+
const message = String(raw.last_assistant_message || '');
|
|
70
|
+
const checklist = hasChecklist(message);
|
|
71
|
+
const verdict = hasVerdict(message);
|
|
72
|
+
if (checklist && verdict) pass(marker);
|
|
73
|
+
|
|
74
|
+
const command = marker.data.command || 'rdc';
|
|
75
|
+
const missing = [];
|
|
76
|
+
if (!checklist) missing.push('a visible checklist row like `[ ] Step` or `[x] Step`');
|
|
77
|
+
if (!verdict) missing.push('a final verdict line beginning with ✅, ⚠️, or ❌');
|
|
78
|
+
|
|
79
|
+
block(
|
|
80
|
+
`RDC output contract incomplete for /${command}: missing ${missing.join(' and ')}. Continue the response by rendering the RDC checklist and verdict required by .rdc/guides/output-contract.md. Do not restart the task; correct the visible output contract.`,
|
|
81
|
+
{ command, checklist, verdict, stop_hook_active: raw.stop_hook_active === true },
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
main().catch((e) => block(`RDC output contract gate crashed: ${e.message}`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifeaitools/rdc-skills",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.35",
|
|
4
4
|
"description": "RDC typed-agent dispatch skill suite for Claude Code - plan, build, review, overnight builds",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"type": "plugin",
|
|
20
20
|
"skills": "skills/",
|
|
21
21
|
"guides": "guides/",
|
|
22
|
-
"version": "0.9.
|
|
22
|
+
"version": "0.9.35",
|
|
23
23
|
"commands": "commands/"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
@@ -100,6 +100,22 @@ function copyDirRecursive(src, dst) {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
function copyMissingProjectGuides(projectRoot) {
|
|
104
|
+
if (!projectRoot) return 0;
|
|
105
|
+
const src = path.join(repoRoot, 'guides');
|
|
106
|
+
const dst = path.join(projectRoot, '.rdc', 'guides');
|
|
107
|
+
if (!fs.existsSync(src) || !fs.existsSync(dst)) return 0;
|
|
108
|
+
let copied = 0;
|
|
109
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
110
|
+
if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
|
|
111
|
+
const target = path.join(dst, entry.name);
|
|
112
|
+
if (fs.existsSync(target)) continue;
|
|
113
|
+
fs.copyFileSync(path.join(src, entry.name), target);
|
|
114
|
+
copied++;
|
|
115
|
+
}
|
|
116
|
+
return copied;
|
|
117
|
+
}
|
|
118
|
+
|
|
103
119
|
function readJson(p, fallback = {}) {
|
|
104
120
|
if (!fs.existsSync(p)) return fallback;
|
|
105
121
|
try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return fallback; }
|
|
@@ -541,6 +557,12 @@ function buildHooksConfig(hooksDir) {
|
|
|
541
557
|
return entry;
|
|
542
558
|
};
|
|
543
559
|
return {
|
|
560
|
+
UserPromptExpansion: [{ hooks: [
|
|
561
|
+
cmd('rdc-invocation-marker.js', 'Marking RDC slash command...'),
|
|
562
|
+
]}],
|
|
563
|
+
UserPromptSubmit: [{ hooks: [
|
|
564
|
+
cmd('rdc-invocation-marker.js', 'Marking RDC prompt...'),
|
|
565
|
+
]}],
|
|
544
566
|
SessionStart: [{ hooks: [
|
|
545
567
|
cmd('check-cwd.js'),
|
|
546
568
|
cmd('check-stale-work-items.js', 'Checking for stale work items...'),
|
|
@@ -566,6 +588,7 @@ function buildHooksConfig(hooksDir) {
|
|
|
566
588
|
]}],
|
|
567
589
|
Stop: [{ hooks: [
|
|
568
590
|
cmd('rate-limit-retry.js', 'Checking for rate limits...'),
|
|
591
|
+
cmd('rdc-output-contract-gate.js', 'Checking RDC output contract...'),
|
|
569
592
|
cmd('post-work-check.js', 'Checking for undocumented work...'),
|
|
570
593
|
cmd('no-stop-open-epics.js', 'Checking for open epics...'),
|
|
571
594
|
]}],
|
|
@@ -780,6 +803,12 @@ async function main() {
|
|
|
780
803
|
} else {
|
|
781
804
|
info('[2.7] Symlinks — no rdc skill links created (skills may already be linked)');
|
|
782
805
|
}
|
|
806
|
+
const projectGuideCount = copyMissingProjectGuides(codexRoot);
|
|
807
|
+
if (projectGuideCount > 0) {
|
|
808
|
+
ok(`[2.8] Guides — ${projectGuideCount} missing guide(s) copied to ${path.join(codexRoot, '.rdc', 'guides')}`);
|
|
809
|
+
} else {
|
|
810
|
+
info('[2.8] Guides — project .rdc/guides already has base guide files or is absent');
|
|
811
|
+
}
|
|
783
812
|
} else {
|
|
784
813
|
info('[2.7] Symlinks — skipped (no codex root found)');
|
|
785
814
|
}
|
package/scripts/install.ps1
CHANGED
|
@@ -82,6 +82,20 @@ if ($SkipHooks) {
|
|
|
82
82
|
$hooksBase = $hooksDir.Replace("\", "/")
|
|
83
83
|
|
|
84
84
|
$hooksConfig = [PSCustomObject]@{
|
|
85
|
+
UserPromptExpansion = @(
|
|
86
|
+
[PSCustomObject]@{
|
|
87
|
+
hooks = @(
|
|
88
|
+
[PSCustomObject]@{ type = "command"; command = "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$hooksBase/run-hidden-hook.ps1`" `"$hooksBase/rdc-invocation-marker.js`""; statusMessage = "Marking RDC slash command..." }
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
UserPromptSubmit = @(
|
|
93
|
+
[PSCustomObject]@{
|
|
94
|
+
hooks = @(
|
|
95
|
+
[PSCustomObject]@{ type = "command"; command = "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$hooksBase/run-hidden-hook.ps1`" `"$hooksBase/rdc-invocation-marker.js`""; statusMessage = "Marking RDC prompt..." }
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
)
|
|
85
99
|
SessionStart = @(
|
|
86
100
|
[PSCustomObject]@{
|
|
87
101
|
hooks = @(
|
|
@@ -130,6 +144,7 @@ if ($SkipHooks) {
|
|
|
130
144
|
[PSCustomObject]@{
|
|
131
145
|
hooks = @(
|
|
132
146
|
[PSCustomObject]@{ type = "command"; command = "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$hooksBase/run-hidden-hook.ps1`" `"$hooksBase/rate-limit-retry.js`""; statusMessage = "Checking for rate limits..." },
|
|
147
|
+
[PSCustomObject]@{ type = "command"; command = "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$hooksBase/run-hidden-hook.ps1`" `"$hooksBase/rdc-output-contract-gate.js`""; statusMessage = "Checking RDC output contract..." },
|
|
133
148
|
[PSCustomObject]@{ type = "command"; command = "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$hooksBase/run-hidden-hook.ps1`" `"$hooksBase/post-work-check.js`""; statusMessage = "Checking for undocumented work..." },
|
|
134
149
|
[PSCustomObject]@{ type = "command"; command = "powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$hooksBase/run-hidden-hook.ps1`" `"$hooksBase/no-stop-open-epics.js`""; statusMessage = "Checking for open epics..." }
|
|
135
150
|
)
|