@hanzlaa/rcode 3.4.32 → 3.5.0
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/AGENTS.md +6 -6
- package/CONTRIBUTING.md +2 -0
- package/LICENSE +21 -0
- package/README.md +66 -403
- package/cli/agent.js +3 -2
- package/cli/doctor.js +87 -1
- package/cli/install.js +122 -31
- package/cli/lib/schemas.cjs +318 -0
- package/cli/postinstall.js +19 -3
- package/dist/rcode.js +318 -24
- package/package.json +8 -4
- package/rihal/agents/rihal-cross-platform-auditor.md +15 -0
- package/rihal/agents/rihal-dep-auditor.md +15 -0
- package/rihal/agents/rihal-docs-auditor.md +3 -145
- package/rihal/agents/rihal-i18n-auditor.md +16 -0
- package/rihal/agents/rihal-nyquist-auditor.md +4 -156
- package/rihal/agents/rihal-observability-auditor.md +16 -0
- package/rihal/agents/rihal-phase-researcher.md +1 -1
- package/rihal/agents/rihal-planner.md +1 -1
- package/rihal/bin/rihal-hooks.cjs +394 -4
- package/rihal/bin/rihal-tools.cjs +891 -24
- package/rihal/commands/create-prd.md +18 -0
- package/rihal/commands/execute-milestone.md +18 -0
- package/rihal/commands/plan-milestone.md +18 -0
- package/rihal/commands/scaffold-milestone.md +18 -0
- package/rihal/commands/scaffold-skill.md +18 -0
- package/rihal/references/REFERENCES_INDEX.md +49 -7
- package/rihal/references/agent-contracts.md +10 -0
- package/rihal/references/design-tokens.md +98 -0
- package/rihal/references/docs-auditor-playbook.md +148 -0
- package/rihal/references/git-preflight.md +117 -0
- package/rihal/references/iterative-retrieval.md +85 -0
- package/rihal/references/nyquist-auditor-playbook.md +157 -0
- package/rihal/references/workstream-flag.md +2 -2
- package/rihal/skills/actions/1-analysis/rihal-prfaq/SKILL.md +9 -0
- package/rihal/skills/actions/4-implementation/rihal-checkpoint-preview/SKILL.md +9 -0
- package/rihal/skills/actions/4-implementation/rihal-ci/SKILL.md +4 -0
- package/rihal/skills/actions/4-implementation/rihal-code-review/steps/step-02-review.md +7 -3
- package/rihal/skills/actions/4-implementation/rihal-harden/SKILL.md +4 -0
- package/rihal/skills/actions/4-implementation/rihal-migrate/SKILL.md +4 -0
- package/rihal/skills/agents/haitham-frontend/SKILL.md +2 -0
- package/rihal/skills/agents/majlis-council/SKILL.md +1 -1
- package/rihal/team.yaml +32 -0
- package/rihal/templates/settings-hooks.json +39 -0
- package/rihal/workflows/check-todos.md +4 -0
- package/rihal/workflows/code-review-fix.md +4 -3
- package/rihal/workflows/code-review.md +1 -1
- package/rihal/workflows/debug.md +1 -1
- package/rihal/workflows/dev-story.md +4 -0
- package/rihal/workflows/diff.md +2 -2
- package/rihal/workflows/do.md +16 -8
- package/rihal/workflows/docs-update.md +2 -2
- package/rihal/workflows/enable-hooks.md +6 -1
- package/rihal/workflows/execute-milestone.md +139 -0
- package/rihal/workflows/execute-regression-gates.md +1 -1
- package/rihal/workflows/execute-sprint.md +54 -2
- package/rihal/workflows/execute-verify-phase-goal.md +31 -4
- package/rihal/workflows/execute-waves.md +33 -5
- package/rihal/workflows/execute.md +40 -6
- package/rihal/workflows/help.md +1 -1
- package/rihal/workflows/import.md +1 -1
- package/rihal/workflows/lens-audit.md +39 -23
- package/rihal/workflows/list-workspaces.md +1 -1
- package/rihal/workflows/map-codebase.md +4 -4
- package/rihal/workflows/new-milestone.md +18 -1
- package/rihal/workflows/new-project-research.md +53 -1
- package/rihal/workflows/new-workspace.md +1 -1
- package/rihal/workflows/plan-milestone.md +105 -0
- package/rihal/workflows/plan-research-validation.md +1 -1
- package/rihal/workflows/plan-spawn-planner.md +1 -1
- package/rihal/workflows/plan.md +31 -3
- package/rihal/workflows/plant-seed.md +6 -0
- package/rihal/workflows/quick.md +11 -5
- package/rihal/workflows/research-phase.md +24 -0
- package/rihal/workflows/scaffold-milestone.md +60 -0
- package/rihal/workflows/scaffold-skill.md +137 -0
- package/rihal/workflows/scan.md +1 -1
- package/rihal/workflows/session-report.md +43 -3
- package/rihal/workflows/verify-work.md +3 -3
- package/server/dashboard.js +53 -6
- package/server/lib/api.js +7 -0
- package/server/lib/html/client.js +725 -13
- package/server/lib/html/css.js +2046 -466
- package/server/lib/html/shell.js +227 -134
- package/server/lib/scanner.js +33 -0
- package/server/orchestrator.js +438 -0
|
@@ -75,7 +75,40 @@ Extract counts:
|
|
|
75
75
|
- **Chains:** count of `*-chain.md` files
|
|
76
76
|
- **Discusses:** count of `*-discuss.md` files
|
|
77
77
|
|
|
78
|
-
## Step 5 —
|
|
78
|
+
## Step 5 — Token usage (measured or estimated)
|
|
79
|
+
|
|
80
|
+
### Step 5a — Prefer measured totals from cost.jsonl
|
|
81
|
+
|
|
82
|
+
If the `cost-track` hook (#745) is enabled, it appends one usage record per
|
|
83
|
+
response to `.rihal/telemetry/cost.jsonl`. Check for it first:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
test -f .rihal/telemetry/cost.jsonl && echo "measured" || echo "estimated"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**If `.rihal/telemetry/cost.jsonl` exists:** sum the `input_tokens` and
|
|
90
|
+
`output_tokens` across every line and report the **measured** totals — label
|
|
91
|
+
them clearly as "measured":
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
node -e "
|
|
95
|
+
const fs=require('fs');
|
|
96
|
+
let i=0,o=0,n=0;
|
|
97
|
+
for(const l of fs.readFileSync('.rihal/telemetry/cost.jsonl','utf8').split('\n').filter(Boolean)){
|
|
98
|
+
try{const r=JSON.parse(l);i+=r.input_tokens||0;o+=r.output_tokens||0;n++;}catch{}
|
|
99
|
+
}
|
|
100
|
+
console.log('responses='+n,'input='+i,'output='+o,'total='+(i+o));
|
|
101
|
+
"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Report: `Total (measured): {input} input + {output} output = {total} tokens
|
|
105
|
+
across {responses} responses`. Skip the heuristic estimate below — measured
|
|
106
|
+
data supersedes it.
|
|
107
|
+
|
|
108
|
+
**If `.rihal/telemetry/cost.jsonl` does NOT exist:** fall back to the heuristic
|
|
109
|
+
estimate in Step 5b and label the result "estimated".
|
|
110
|
+
|
|
111
|
+
### Step 5b — Heuristic estimate (fallback only)
|
|
79
112
|
|
|
80
113
|
Calculate estimated tokens (note: these are rough approximations, not actual measurements).
|
|
81
114
|
|
|
@@ -135,9 +168,16 @@ Write `.planning/SESSION-REPORT-{YYYY-MM-DD-HHmmss}.md` with this structure:
|
|
|
135
168
|
- **Blockers Identified:** {count} ({open_count} open)
|
|
136
169
|
- **Commits:** {count}
|
|
137
170
|
|
|
138
|
-
##
|
|
171
|
+
## Token Usage ({measured|estimated})
|
|
172
|
+
|
|
173
|
+
**If cost.jsonl exists — measured:**
|
|
174
|
+
|
|
175
|
+
- Responses tracked: {count}
|
|
176
|
+
- Input tokens: {input}
|
|
177
|
+
- Output tokens: {output}
|
|
178
|
+
- **Total (measured): {grand_total} tokens**
|
|
139
179
|
|
|
140
|
-
**
|
|
180
|
+
**If cost.jsonl absent — estimated** (approximations based on artifact counts):
|
|
141
181
|
|
|
142
182
|
- Council Sessions: {count} × 50K = {total}K
|
|
143
183
|
- Chains: {count} × 30K = {total}K
|
|
@@ -523,7 +523,7 @@ Plans must be executable prompts.
|
|
|
523
523
|
</downstream_consumer>
|
|
524
524
|
""",
|
|
525
525
|
subagent_type="rihal-planner",
|
|
526
|
-
model="
|
|
526
|
+
model="{model}",
|
|
527
527
|
model="{planner_model}",
|
|
528
528
|
description="Plan gap fixes for Phase {phase}"
|
|
529
529
|
)
|
|
@@ -573,7 +573,7 @@ Return one of:
|
|
|
573
573
|
</expected_output>
|
|
574
574
|
""",
|
|
575
575
|
subagent_type="rihal-sprint-checker",
|
|
576
|
-
model="
|
|
576
|
+
model="{model}",
|
|
577
577
|
model="{checker_model}",
|
|
578
578
|
description="Verify Phase {phase} fix plans"
|
|
579
579
|
)
|
|
@@ -618,7 +618,7 @@ Do NOT replan from scratch unless issues are fundamental.
|
|
|
618
618
|
</instructions>
|
|
619
619
|
""",
|
|
620
620
|
subagent_type="rihal-planner",
|
|
621
|
-
model="
|
|
621
|
+
model="{model}",
|
|
622
622
|
model="{planner_model}",
|
|
623
623
|
description="Revise Phase {phase} plans"
|
|
624
624
|
)
|
package/server/dashboard.js
CHANGED
|
@@ -20,8 +20,10 @@
|
|
|
20
20
|
* Stop: kill $(lsof -t -i:7717)
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
-
const http
|
|
24
|
-
const path
|
|
23
|
+
const http = require('http');
|
|
24
|
+
const path = require('path');
|
|
25
|
+
const crypto = require('crypto');
|
|
26
|
+
const { spawn } = require('child_process');
|
|
25
27
|
|
|
26
28
|
const { scanState } = require('./lib/scanner');
|
|
27
29
|
const { handleApiState, handleApiFiles, handleApiFile, handleApiHierarchy, handleApiMemory } = require('./lib/api');
|
|
@@ -32,6 +34,9 @@ const PORT = parseInt(process.env.PORT || '7717', 10);
|
|
|
32
34
|
const RIHAL_DIR = process.env.RIHAL_DIR || path.join(process.cwd(), '.rihal');
|
|
33
35
|
const PROJECT_ROOT = path.dirname(RIHAL_DIR);
|
|
34
36
|
|
|
37
|
+
// Shared orchestrator token — generated once, passed to orchestrator via env and embedded in HTML
|
|
38
|
+
const ORCH_TOKEN = process.env.ORCH_TOKEN || crypto.randomBytes(24).toString('hex');
|
|
39
|
+
|
|
35
40
|
// ---------- HTTP Server ----------
|
|
36
41
|
const server = http.createServer((req, res) => {
|
|
37
42
|
const url = req.url || '/';
|
|
@@ -69,7 +74,7 @@ const server = http.createServer((req, res) => {
|
|
|
69
74
|
|
|
70
75
|
if (url === '/' || url === '/index.html') {
|
|
71
76
|
const state = scanState(RIHAL_DIR);
|
|
72
|
-
const html = renderHtml(state);
|
|
77
|
+
const html = renderHtml(state, ORCH_TOKEN);
|
|
73
78
|
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
74
79
|
res.end(html);
|
|
75
80
|
return;
|
|
@@ -79,7 +84,7 @@ const server = http.createServer((req, res) => {
|
|
|
79
84
|
res.end('Not found');
|
|
80
85
|
});
|
|
81
86
|
|
|
82
|
-
server.listen(PORT, () => {
|
|
87
|
+
server.listen(PORT, '127.0.0.1', () => {
|
|
83
88
|
console.log(`\n🕌 Majlis (مجلس) — Rihal Code Dashboard`);
|
|
84
89
|
console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
|
|
85
90
|
console.log(` Mode: view-only`);
|
|
@@ -91,6 +96,48 @@ server.listen(PORT, () => {
|
|
|
91
96
|
console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`);
|
|
92
97
|
});
|
|
93
98
|
|
|
99
|
+
// ── Auto-spawn orchestrator (port 7718) ──────────────────────────
|
|
100
|
+
const ORCH_BIN = path.join(__dirname, 'orchestrator.js');
|
|
101
|
+
let _orchProc = null;
|
|
102
|
+
|
|
103
|
+
function spawnOrchestrator() {
|
|
104
|
+
try {
|
|
105
|
+
_orchProc = spawn(process.execPath, [ORCH_BIN], {
|
|
106
|
+
cwd: path.join(__dirname, '..'),
|
|
107
|
+
env: { ...process.env, ORCH_TOKEN },
|
|
108
|
+
stdio: 'pipe',
|
|
109
|
+
});
|
|
110
|
+
_orchProc.stdout.on('data', chunk => {
|
|
111
|
+
const msg = chunk.toString().trim();
|
|
112
|
+
if (msg) console.log('[orch]', msg);
|
|
113
|
+
});
|
|
114
|
+
_orchProc.stderr.on('data', chunk => {
|
|
115
|
+
const msg = chunk.toString().trim();
|
|
116
|
+
if (msg && !msg.includes('no stdin')) console.error('[orch]', msg);
|
|
117
|
+
});
|
|
118
|
+
_orchProc.on('exit', (code, signal) => {
|
|
119
|
+
_orchProc = null;
|
|
120
|
+
if (signal !== 'SIGTERM' && signal !== 'SIGINT') {
|
|
121
|
+
console.log(`[orch] exited (${code}) — restarting in 3s…`);
|
|
122
|
+
setTimeout(spawnOrchestrator, 3000);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
_orchProc.on('error', err => {
|
|
126
|
+
console.error('[orch] spawn error:', err.message);
|
|
127
|
+
_orchProc = null;
|
|
128
|
+
});
|
|
129
|
+
console.log('[orch] orchestrator started (port 7718)');
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.error('[orch] failed to start:', err.message);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
spawnOrchestrator();
|
|
136
|
+
|
|
94
137
|
// Graceful shutdown
|
|
95
|
-
|
|
96
|
-
|
|
138
|
+
function shutdown() {
|
|
139
|
+
if (_orchProc) { try { _orchProc.kill('SIGTERM'); } catch {} }
|
|
140
|
+
server.close(() => process.exit(0));
|
|
141
|
+
}
|
|
142
|
+
process.on('SIGTERM', shutdown);
|
|
143
|
+
process.on('SIGINT', shutdown);
|
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
|
}
|