@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.
Files changed (54) hide show
  1. package/.claude-plugin/plugin.json +2 -1
  2. package/.github/workflows/self-test.yml +34 -34
  3. package/CHANGELOG.md +10 -0
  4. package/README.md +1 -1
  5. package/commands/build.md +181 -181
  6. package/commands/collab.md +180 -180
  7. package/commands/deploy.md +152 -152
  8. package/commands/fixit.md +105 -105
  9. package/commands/handoff.md +173 -173
  10. package/commands/overnight.md +220 -220
  11. package/commands/plan.md +158 -158
  12. package/commands/preplan.md +131 -131
  13. package/commands/prototype.md +145 -145
  14. package/commands/report.md +99 -99
  15. package/commands/review.md +120 -120
  16. package/commands/status.md +86 -86
  17. package/commands/workitems.md +127 -127
  18. package/guides/agent-bootstrap.md +206 -202
  19. package/guides/agents/backend.md +102 -102
  20. package/guides/agents/content.md +94 -94
  21. package/guides/agents/cs2.md +56 -56
  22. package/guides/agents/data.md +86 -86
  23. package/guides/agents/design.md +77 -77
  24. package/guides/agents/frontend.md +91 -91
  25. package/guides/agents/infrastructure.md +81 -81
  26. package/guides/agents/setup.md +280 -278
  27. package/guides/agents/verify.md +119 -119
  28. package/guides/agents/viz.md +106 -106
  29. package/guides/engineering-behavior.md +43 -0
  30. package/hooks/rdc-invocation-marker.js +143 -0
  31. package/hooks/rdc-output-contract-gate.js +85 -0
  32. package/package.json +2 -2
  33. package/scripts/install-rdc-skills.js +29 -0
  34. package/scripts/install.ps1 +15 -0
  35. package/scripts/self-test.mjs +1414 -1323
  36. package/skills/build/SKILL.md +359 -355
  37. package/skills/collab/SKILL.md +217 -217
  38. package/skills/deploy/SKILL.md +198 -198
  39. package/skills/design/SKILL.md +211 -211
  40. package/skills/fixit/SKILL.md +136 -132
  41. package/skills/fs-mcp/SKILL.md +131 -0
  42. package/skills/handoff/SKILL.md +200 -200
  43. package/skills/help/SKILL.md +104 -104
  44. package/skills/overnight/SKILL.md +224 -224
  45. package/skills/plan/SKILL.md +252 -252
  46. package/skills/preplan/SKILL.md +86 -86
  47. package/skills/prototype/SKILL.md +150 -150
  48. package/skills/release/SKILL.md +342 -342
  49. package/skills/report/SKILL.md +100 -100
  50. package/skills/review/SKILL.md +122 -121
  51. package/skills/self-test/SKILL.md +126 -126
  52. package/skills/status/SKILL.md +99 -99
  53. package/skills/watch/SKILL.md +91 -91
  54. 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.33",
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.33",
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
  }
@@ -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
  )