@hanzlaa/rcode 4.14.0 → 4.15.1

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 (35) hide show
  1. package/cli/install.js +93 -6
  2. package/cli/uninstall.js +13 -0
  3. package/dist/rcode.js +195 -195
  4. package/package.json +1 -1
  5. package/rcode/agents/rcode-orchestrator.md +3 -0
  6. package/rcode/agents/rules/orchestrator/contract.md +18 -0
  7. package/rcode/agents/rules/roadmapper/detailed-guide.md +4 -2
  8. package/rcode/agents/rules/sprint-checker/dimensions.md +45 -0
  9. package/rcode/agents/rules/sprint-checker/plan-quality-rubric.md +110 -0
  10. package/rcode/bin/lib/customize.cjs +115 -0
  11. package/rcode/bin/lib/memlog.cjs +124 -0
  12. package/rcode/bin/rcode-tools.cjs +13 -0
  13. package/rcode/references/agent-shared-rules.md +40 -0
  14. package/rcode/references/roadmapper-playbook.md +8 -0
  15. package/rcode/references/sprint-checker-playbook.md +11 -0
  16. package/rcode/references/universal-anti-patterns.md +26 -0
  17. package/rcode/skills/actions/4-implementation/rcode-code-review/SKILL.md +12 -5
  18. package/rcode/skills/actions/4-implementation/rcode-code-review/steps/step-02-review.md +61 -10
  19. package/rcode/skills/actions/4-implementation/rcode-code-review/steps/step-03-triage.md +28 -3
  20. package/rcode/skills/actions/4-implementation/rcode-code-review/workflow.md +8 -1
  21. package/rcode/skills/agents/haitham-frontend/SKILL.md +1 -1
  22. package/rcode/skills/agents/hanzla-engineer/SKILL.md +1 -1
  23. package/rcode/skills/agents/hussain-pm/SKILL.md +1 -1
  24. package/rcode/skills/agents/noor-writer/SKILL.md +2 -2
  25. package/rcode/skills/agents/orchestrator/SKILL.md +35 -5
  26. package/rcode/skills/agents/yousef-backend/SKILL.md +2 -2
  27. package/rcode/skills/agents/zayd-ml/SKILL.md +1 -1
  28. package/rcode/skills/core/rcode-help/SKILL.md +2 -1
  29. package/rcode/workflows/execute-sprint.md +1 -1
  30. package/rcode/workflows/execute.md +5 -0
  31. package/rcode/workflows/new-project-research-decision.md +2 -0
  32. package/rcode/workflows/new-project.md +5 -0
  33. package/rcode/workflows/plan.md +9 -0
  34. package/rcode/workflows/secure-phase.md +3 -1
  35. package/rcode/skills/rcode-init/SKILL.md +0 -134
package/cli/install.js CHANGED
@@ -723,9 +723,17 @@ function getPathsForIde(ide, target) {
723
723
  // claude/vscode install paths). We install agent + command files to .claude/
724
724
  // so multi-IDE installs share files, and the rcode workflow bridge gives
725
725
  // Codex access to lifecycle workflows via `rcode workflow show <name>` (#883).
726
- // NOTE: Codex surfaces native /slash commands ONLY from ~/.codex/prompts/*.md
727
- // (home, startup-loaded)installed separately by installNativeHomeSlashCommands()
728
- // under the opt-in --global flag, since .claude/commands is invisible to Codex.
726
+ //
727
+ // What Codex actually reads verified live against Codex CLI 0.150.1:
728
+ // AGENTS.md → project instructions ✅ written here
729
+ // ~/.codex/prompts/*.md → /slash commands (--global only)
730
+ // ~/.codex/skills/<n>/ → skills (--global only)
731
+ // (no agents surface) → Codex has NO subagent concept at all
732
+ //
733
+ // The agentsDir below is therefore written for MULTI-IDE SHARING ONLY.
734
+ // Codex itself never reads it, and rcode's agents cannot appear in Codex
735
+ // in any form — not a bug to fix, an absent surface. Skills are the only
736
+ // place rcode's capabilities can surface there.
729
737
  return {
730
738
  agentsDir: path.join(target, '.claude', 'agents'),
731
739
  commandsDir: path.join(target, '.claude', 'commands'),
@@ -994,6 +1002,10 @@ function ensureRcodeGitignore(target, options = {}) {
994
1002
  '.rcode/brain/rcode-docs/',
995
1003
  '.rcode/brain/best-practices/',
996
1004
  '',
1005
+ '# Personal customization layer — team overrides (.rcode/custom/<name>.md)',
1006
+ '# ARE committed; the .user.md layer is per-developer and is not.',
1007
+ '.rcode/custom/*.user.md',
1008
+ '',
997
1009
  '# Runtime noise',
998
1010
  'node_modules/',
999
1011
  '.rcode/state.json.lock',
@@ -1361,12 +1373,29 @@ function installSkills(packageRoot, target, options = {}) {
1361
1373
  let skippedGlobal = 0;
1362
1374
 
1363
1375
  const _internalSkillCache = new Map();
1376
+ // `user-invocable: true` WINS over `internal: true`.
1377
+ //
1378
+ // These two flags contradict each other and 36 of the 38 internal skills
1379
+ // declared both. The installer read only `internal`, so every one of those
1380
+ // skills went to .rcode/skills/ instead of .claude/skills/ — which means the
1381
+ // model never saw their descriptions and they could never auto-activate. They
1382
+ // worked only if the user typed the exact slash command.
1383
+ //
1384
+ // That is how "review this PR <url>" reached the built-in code-review skill
1385
+ // instead of rcode's: rcode's reviewer was invisible, not out-competed.
1386
+ //
1387
+ // A skill that declares user-invocable, writes its description for activation
1388
+ // ("Activates when the user says..."), and lists trigger phrases is user-facing
1389
+ // by every signal it gives. `internal` is for genuine utility libraries that
1390
+ // other skills call — and those do not claim to be user-invocable.
1364
1391
  function isInternalSkill(skillDir) {
1365
1392
  if (_internalSkillCache.has(skillDir)) return _internalSkillCache.get(skillDir);
1366
1393
  const skillMd = path.join(skillDir, 'SKILL.md');
1367
1394
  if (!fs.existsSync(skillMd)) { _internalSkillCache.set(skillDir, false); return false; }
1368
1395
  const text = fs.readFileSync(skillMd, 'utf8');
1369
- const result = /^internal:\s*true\s*$/m.test(text);
1396
+ const internal = /^internal:\s*true\s*$/m.test(text);
1397
+ const userInvocable = /^user-invocable:\s*true\s*$/m.test(text);
1398
+ const result = internal && !userInvocable;
1370
1399
  _internalSkillCache.set(skillDir, result);
1371
1400
  return result;
1372
1401
  }
@@ -1558,6 +1587,20 @@ function buildInstallPlan(ide = 'claude', target = process.cwd()) {
1558
1587
  plan.push({ src: f, rel: path.join('.rcode', 'data', rel) });
1559
1588
  }
1560
1589
 
1590
+ // .rcode/templates/ — every template, not just the starter projects.
1591
+ //
1592
+ // Only `templates/projects/` was ever copied, so a fresh install had NO
1593
+ // .md templates at all while workflows went on reading them:
1594
+ // plan-research-validation.md and validate-phase.md both read
1595
+ // `.rcode/templates/VALIDATION.md`, which never existed. Any templates found
1596
+ // in an older project were leftovers from a version that did copy them, which
1597
+ // is why this stayed invisible — it only broke on FRESH installs.
1598
+ for (const f of walkFiles(path.join(SOURCE_ROOT, 'templates'))) {
1599
+ const rel = path.relative(path.join(SOURCE_ROOT, 'templates'), f);
1600
+ if (rel.startsWith('projects' + path.sep) || rel === 'projects') continue; // handled below
1601
+ plan.push({ src: f, rel: path.join('.rcode', 'templates', rel) });
1602
+ }
1603
+
1561
1604
  // .rcode/templates/projects/ — starter templates consumed by /rcode-from-template
1562
1605
  const projectTemplatesSrc = path.join(SOURCE_ROOT, 'templates', 'projects');
1563
1606
  const relProjectTemplates = path.relative(target, path.join(target, '.rcode', 'templates', 'projects'));
@@ -2272,6 +2315,50 @@ function mergeSlashRouterHook(jsonPath, eventKey, command, label) {
2272
2315
  return true;
2273
2316
  }
2274
2317
 
2318
+ // Codex reads SKILLS from ~/.codex/skills/<name>/SKILL.md — verified live against
2319
+ // Codex CLI 0.150.1, which prints the paths it loads on boot and lists them under
2320
+ // `/skills`. Entries there are commonly symlinks into a shared ~/.agents/skills.
2321
+ //
2322
+ // This is a DIFFERENT surface from ~/.codex/prompts (slash commands) and from
2323
+ // AGENTS.md (instructions), and rcode targeted neither of the first two for
2324
+ // skills — so none of rcode's skills appeared in Codex at all. Codex has no
2325
+ // subagent concept, so rcode's agents cannot surface there in any form; skills
2326
+ // are the only place its capabilities can show up.
2327
+ function installCodexSkills(opts) {
2328
+ const home = homedir();
2329
+ const destRoot = path.join(home, '.codex', 'skills');
2330
+ ensureDir(destRoot);
2331
+
2332
+ // Source: every SKILL.md under rcode/skills/, installed as rcode-<name>/ to
2333
+ // stay inside rcode's namespace and never collide with a user's own skills.
2334
+ const srcRoot = path.join(SOURCE_ROOT, 'skills');
2335
+ if (!fs.existsSync(srcRoot)) return 0;
2336
+
2337
+ let written = 0;
2338
+ for (const skillFile of walkFiles(srcRoot)) {
2339
+ if (path.basename(skillFile) !== 'SKILL.md') continue;
2340
+ const skillDir = path.dirname(skillFile);
2341
+ const bare = path.basename(skillDir);
2342
+ const name = bare.startsWith('rcode-') ? bare : `rcode-${bare}`;
2343
+ const destDir = path.join(destRoot, name);
2344
+ ensureDir(destDir);
2345
+ // Copy the whole skill folder — references/, steps/, templates/ and the
2346
+ // like are part of the contract, not decoration.
2347
+ for (const f of walkFiles(skillDir)) {
2348
+ const rel = path.relative(skillDir, f);
2349
+ const out = path.join(destDir, rel);
2350
+ ensureDir(path.dirname(out));
2351
+ fs.copyFileSync(f, out);
2352
+ }
2353
+ written++;
2354
+ }
2355
+
2356
+ if (opts && opts.global !== 'silent') {
2357
+ console.log(' ' + ok(`Codex skills: ${written} → ~/.codex/skills/rcode-*/`));
2358
+ }
2359
+ return written;
2360
+ }
2361
+
2275
2362
  // Codex: ~/.codex/hooks.json, event UserPromptSubmit.
2276
2363
  function installCodexSlashRouterHook(opts) {
2277
2364
  installSlashRouterCommands(opts);
@@ -2291,7 +2378,7 @@ function installNativeHomeSlashCommands(opts) {
2291
2378
  const ides = Array.isArray(opts.ides) ? opts.ides : [opts.ide].filter(Boolean);
2292
2379
  for (const ide of ides) {
2293
2380
  switch (ide) {
2294
- case 'codex': installCodexSlashRouterHook(opts); break;
2381
+ case 'codex': installCodexSlashRouterHook(opts); installCodexSkills(opts); break;
2295
2382
  case 'antigravity': installAntigravitySlashRouterHook(opts); break;
2296
2383
  default:
2297
2384
  break;
@@ -2378,7 +2465,7 @@ async function installInner(opts) {
2378
2465
  // writes on a GLOBAL install. A project-local install silently leaves Codex
2379
2466
  // with no working slash commands — warn instead of implying success.
2380
2467
  if (!opts.global) {
2381
- console.log(' ' + warn('Codex /rcode-* slash commands need a GLOBAL install — re-run with `--global` to wire the ~/.codex/hooks.json router. This project-local install does NOT enable them.'));
2468
+ console.log(' ' + warn('Codex needs a GLOBAL install — re-run with `--global` to wire the ~/.codex/hooks.json router AND copy rcode skills to ~/.codex/skills/. This project-local install enables NEITHER: Codex reads slash commands and skills only from its home dir, and has no agents surface at all.'));
2382
2469
  }
2383
2470
  }
2384
2471
 
package/cli/uninstall.js CHANGED
@@ -791,6 +791,19 @@ async function runUninstall(args) {
791
791
  if (editors.includes('codex')) {
792
792
  const r = removeSlashRouterHook(path.join(os.homedir(), '.codex', 'hooks.json'), 'UserPromptSubmit');
793
793
  if (r === 'removed') console.log(` ✓ removed rcode slash-router hook from ~/.codex/hooks.json`);
794
+ // Skills installed to ~/.codex/skills/rcode-*/ by installCodexSkills().
795
+ // Only rcode-prefixed entries — the user's own skills and their symlinks
796
+ // into ~/.agents/skills live in the same directory and are not ours.
797
+ const codexSkills = path.join(os.homedir(), '.codex', 'skills');
798
+ let removedSkills = 0;
799
+ try {
800
+ for (const entry of fs.readdirSync(codexSkills)) {
801
+ if (!entry.startsWith('rcode-')) continue;
802
+ fs.rmSync(path.join(codexSkills, entry), { recursive: true, force: true });
803
+ removedSkills++;
804
+ }
805
+ } catch { /* directory absent — nothing installed */ }
806
+ if (removedSkills > 0) console.log(` ✓ removed ${removedSkills} rcode skill(s) from ~/.codex/skills/`);
794
807
  }
795
808
  if (editors.includes('antigravity')) {
796
809
  const r = removeSlashRouterHook(path.join(os.homedir(), '.gemini', 'antigravity', 'settings.json'), 'UserPrompt');