@hanzlaa/rcode 3.4.32 → 3.4.33

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/cli/agent.js CHANGED
@@ -39,8 +39,9 @@ module.exports = function agent(args, { packageRoot }) {
39
39
  process.exit(1);
40
40
  }
41
41
 
42
- // Check claude binary is on PATH
43
- const claudeCheck = spawnSync('which', ['claude'], { encoding: 'utf8' });
42
+ // Check claude binary is on PATH (cross-platform: 'where' on Windows, 'which' elsewhere)
43
+ const whichCmd = process.platform === 'win32' ? 'where' : 'which';
44
+ const claudeCheck = spawnSync(whichCmd, ['claude'], { encoding: 'utf8' });
44
45
  if (claudeCheck.status !== 0) {
45
46
  console.error('Error: claude binary not found. Install Claude Code: https://claude.ai/code');
46
47
  process.exit(1);
package/dist/rcode.js CHANGED
@@ -18904,7 +18904,8 @@ var require_agent = __commonJS({
18904
18904
  console.error(`Available: ${available}`);
18905
18905
  process.exit(1);
18906
18906
  }
18907
- const claudeCheck = spawnSync("which", ["claude"], { encoding: "utf8" });
18907
+ const whichCmd = process.platform === "win32" ? "where" : "which";
18908
+ const claudeCheck = spawnSync(whichCmd, ["claude"], { encoding: "utf8" });
18908
18909
  if (claudeCheck.status !== 0) {
18909
18910
  console.error("Error: claude binary not found. Install Claude Code: https://claude.ai/code");
18910
18911
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzlaa/rcode",
3
- "version": "3.4.32",
3
+ "version": "3.4.33",
4
4
  "description": "rcode — the memory bank for AI-driven SaaS teams. Persistent project context, distinctive engineering personas, and phase-based workflows. Built by Rihal. Works in Claude Code, Cursor, Gemini, VS Code, and Antigravity.",
5
5
  "main": "cli/index.js",
6
6
  "bin": {
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: rihal-cross-platform-auditor
3
+ description: |
4
+ Cross-platform portability auditor. Detects bash-isms, macOS-only flags
5
+ (BSD sed/awk), hardcoded absolute Unix paths in Node code, Windows path
6
+ separators, and CRLF line endings. Audit-only — never modifies scripts.
7
+ Activates: "cross-platform audit", "bash-isms", "macOS only",
8
+ "Windows compatibility", "portability check".
9
+ Do NOT use for: fixing scripts, frontend RTL, or translation.
10
+ tools: Read, Bash, Grep, Glob
11
+ color: yellow
12
+ ---
13
+
14
+ @.rihal/references/response-style.md
15
+ @.rihal/skills/agents/rihal-cross-platform-auditor/SKILL.md
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: rihal-dep-auditor
3
+ description: |
4
+ Dependency health auditor — scans for outdated packages, CVEs, unused
5
+ dependencies, loose version pins, and missing lock files. Audit-only:
6
+ never modifies package.json or runs installs.
7
+ Activates: "audit dependencies", "dep health", "CVE scan", "check packages",
8
+ "outdated deps", "loose pins", "lock file".
9
+ Do NOT use for: installing packages, updating deps, or security penetration testing.
10
+ tools: Read, Bash, Grep, Glob
11
+ color: yellow
12
+ ---
13
+
14
+ @.rihal/references/response-style.md
15
+ @.rihal/skills/agents/rihal-dep-auditor/SKILL.md
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: rihal-i18n-auditor
3
+ description: |
4
+ Internationalization and localization auditor. Detects hardcoded English
5
+ strings in workflow output, missing response_language pass-through to
6
+ subagents, AskUserQuestion with English-only prompts, and RTL/Arabic
7
+ layout gaps. Audit-only — never modifies string files.
8
+ Activates: "i18n audit", "translation check", "hardcoded strings",
9
+ "response_language missing", "RTL audit", "Arabic layout", "multilingual audit".
10
+ Do NOT use for: adding translations, RTL CSS (use rihal-haitham), content translation.
11
+ tools: Read, Bash, Grep, Glob
12
+ color: yellow
13
+ ---
14
+
15
+ @.rihal/references/response-style.md
16
+ @.rihal/skills/agents/rihal-i18n-auditor/SKILL.md
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: rihal-observability-auditor
3
+ description: |
4
+ Observability and silent-failure auditor. Detects unguarded rihal-tools
5
+ shell calls, Task() results that are never checked, bare 2>/dev/null
6
+ without fallback echo, INIT calls without .ok checks, and unstructured
7
+ console.log in production code. Audit-only — never adds instrumentation.
8
+ Activates: "observability audit", "silent failures", "unguarded calls",
9
+ "missing error handling", "tool call guard".
10
+ Do NOT use for: adding logging, instrumentation setup, or fixing error handlers.
11
+ tools: Read, Bash, Grep, Glob
12
+ color: yellow
13
+ ---
14
+
15
+ @.rihal/references/response-style.md
16
+ @.rihal/skills/agents/rihal-observability-auditor/SKILL.md
@@ -8,7 +8,7 @@ color: cyan
8
8
 
9
9
  @.rihal/references/response-style.md
10
10
  @.rihal/references/karpathy-guidelines.md
11
- @rihal/brain/best-practices/no-theoretical-suggestions.md
11
+ @.rihal/brain/best-practices/no-theoretical-suggestions.md
12
12
  @.rihal/references/researcher-shared.md
13
13
 
14
14
  <role>
@@ -8,7 +8,7 @@ color: green
8
8
  @.rihal/references/response-style.md
9
9
  @.rihal/references/karpathy-guidelines-full.md
10
10
  @.rihal/references/output-realism.md
11
- @rihal/brain/best-practices/no-theoretical-suggestions.md
11
+ @.rihal/brain/best-practices/no-theoretical-suggestions.md
12
12
  @.rihal/references/planner-playbook.md
13
13
 
14
14
  <role>
@@ -17,11 +17,15 @@ failed_layers: '' # set at runtime: comma-separated list of layers that failed o
17
17
 
18
18
  2. Launch parallel subagents without conversation context. If subagents are not available, generate prompt files in `{implementation_artifacts}` — one per reviewer role below — and HALT. Ask the user to run each in a separate session (ideally a different LLM) and paste back the findings. When findings are pasted, resume from this point and proceed to step 3.
19
19
 
20
- - **Blind Hunter** receives `{diff_output}` only. No spec, no context docs, no project access. Invoke via the `rihal-review-adversarial-general` skill.
20
+ **Subagent mapping** (issue #720): the three reviewer roles below map to actual agents shipped in `.claude/agents/`. The skill names that used to be referenced here (`rihal-review-adversarial-general`, `rihal-review-edge-case-hunter`) are skills, not subagents, and `Task(subagent_type=...)` cannot reach them. Use the agents listed.
21
21
 
22
- - **Edge Case Hunter** — receives `{diff_output}` and read access to the project. Invoke via the `rihal-review-edge-case-hunter` skill.
22
+ - **Blind Hunter** — receives `{diff_output}` only. No spec, no context docs, no project access. Dispatch:
23
+ `Task(subagent_type="rihal-security-adversary", model="sonnet", prompt="<adversarial review of diff>")`. The security-adversary persona's cynical mindset is the right fit for an isolated diff-only review.
23
24
 
24
- - **Acceptance Auditor** (only if `{review_mode}` = `"full"`) — receives `{diff_output}`, the content of the file at `{spec_file}`, and any loaded context docs. Its prompt:
25
+ - **Edge Case Hunter** — receives `{diff_output}` and read access to the project. Dispatch:
26
+ `Task(subagent_type="rihal-edge-case-hunter", model="sonnet", prompt="<enumerate edge cases for diff>")`.
27
+
28
+ - **Acceptance Auditor** (only if `{review_mode}` = `"full"`) — receives `{diff_output}`, the content of the file at `{spec_file}`, and any loaded context docs. Dispatch via `rihal-code-reviewer`. Its prompt:
25
29
  > You are an Acceptance Auditor. Review this diff against the spec and context docs. Check for: violations of acceptance criteria, deviations from spec intent, missing implementation of specified behavior, contradictions between spec constraints and actual code. Output findings as a Markdown list. Each finding: one-line title, which AC/constraint it violates, and evidence from the diff.
26
30
 
27
31
  3. **Subagent failure handling**: If any subagent fails, times out, or returns empty results, append the layer name to `{failed_layers}` (comma-separated) and proceed with findings from the remaining layers.
@@ -59,7 +59,7 @@ Majlis (مجلس) is the consulting council. Convenes specialists when a questio
59
59
  | DM | Decision matrix — walk through a specific choice with pros/cons per agent | `rihal-majlis-decision` |
60
60
  | CM | Crisis mode — rapid consultation during an incident | `rihal-majlis-crisis` |
61
61
 
62
- ## Consultation Protocol
62
+ ## Workflow
63
63
 
64
64
  1. **Frame the question** — restate clearly so every agent answers the same question.
65
65
  2. **Determine the council** — identify which agents' domains are relevant (3 minimum, 12 maximum, 3-8 ideal).
package/rihal/team.yaml CHANGED
@@ -520,3 +520,35 @@ tactical_agents:
520
520
  role: Verifier
521
521
  authority_level: quality
522
522
  description: Verifies phase goal achievement goal-backward
523
+
524
+ - id: rihal-i18n-auditor
525
+ name: i18n Auditor
526
+ file_path: rihal/agents/rihal-i18n-auditor.md
527
+ skill_path: rihal/skills/agents/rihal-i18n-auditor
528
+ role: i18n Auditor
529
+ authority_level: quality
530
+ description: Detects hardcoded English strings, missing response_language threading, and RTL layout gaps
531
+
532
+ - id: rihal-cross-platform-auditor
533
+ name: Cross-Platform Auditor
534
+ file_path: rihal/agents/rihal-cross-platform-auditor.md
535
+ skill_path: rihal/skills/agents/rihal-cross-platform-auditor
536
+ role: Cross-Platform Auditor
537
+ authority_level: quality
538
+ description: Detects bash-isms, macOS-only flags, hardcoded Unix paths, and CRLF line endings
539
+
540
+ - id: rihal-dep-auditor
541
+ name: Dep Auditor
542
+ file_path: rihal/agents/rihal-dep-auditor.md
543
+ skill_path: rihal/skills/agents/rihal-dep-auditor
544
+ role: Dependency Health Auditor
545
+ authority_level: quality
546
+ description: Scans for outdated packages, CVEs, unused dependencies, and loose version pins
547
+
548
+ - id: rihal-observability-auditor
549
+ name: Observability Auditor
550
+ file_path: rihal/agents/rihal-observability-auditor.md
551
+ skill_path: rihal/skills/agents/rihal-observability-auditor
552
+ role: Observability Auditor
553
+ authority_level: quality
554
+ description: Detects unguarded shell calls, unchecked Task() results, and missing INIT .ok checks
@@ -79,7 +79,7 @@ const server = http.createServer((req, res) => {
79
79
  res.end('Not found');
80
80
  });
81
81
 
82
- server.listen(PORT, () => {
82
+ server.listen(PORT, '127.0.0.1', () => {
83
83
  console.log(`\n🕌 Majlis (مجلس) — Rihal Code Dashboard`);
84
84
  console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
85
85
  console.log(` Mode: view-only`);
package/server/lib/api.js CHANGED
@@ -132,6 +132,13 @@ function handleApiFile(req, res, projectRoot) {
132
132
  if (!resolved.startsWith(projectRoot + path.sep) && resolved !== projectRoot) {
133
133
  res.writeHead(403); res.end('Forbidden'); return;
134
134
  }
135
+ // Dereference symlinks so a symlink outside projectRoot cannot bypass the guard
136
+ let realResolved;
137
+ try { realResolved = fs.realpathSync(resolved); }
138
+ catch { res.writeHead(404); res.end('File not found'); return; }
139
+ if (!realResolved.startsWith(projectRoot + path.sep) && realResolved !== projectRoot) {
140
+ res.writeHead(403); res.end('Forbidden'); return;
141
+ }
135
142
  if (!resolved.endsWith('.md')) {
136
143
  res.writeHead(403); res.end('Forbidden: only .md files'); return;
137
144
  }
@@ -29,9 +29,9 @@ function chip(s) {
29
29
  : s === 'blocked' ? 'blocked'
30
30
  : s === 'planned' ? 'planned'
31
31
  : s === 'todo' ? 'todo' : 'other';
32
- return '<span class="status-chip ' + c + '">● ' + s + '</span>';
32
+ return '<span class="status-chip ' + c + '">● ' + esc(s) + '</span>';
33
33
  }
34
- function tag(t) { return '<span class="tag">' + t + '</span>'; }
34
+ function tag(t) { return '<span class="tag">' + esc(t) + '</span>'; }
35
35
  function esc(s) { return String(s || '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#39;'); }
36
36
  function pct(d, t) { return t > 0 ? Math.round(d/t*100) + '%' : '—'; }
37
37
  function pctNum(d, t) { return t > 0 ? Math.round(d/t*100) : 0; }