@hanzlaa/rcode 4.4.1 → 4.4.2
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/README.md +11 -11
- package/cli/install.js +7 -2
- package/dist/rcode.js +1 -1
- package/package.json +1 -1
- package/rcode/bin/rcode-tools.cjs +30 -8
- package/rcode/commands/lazy.md +7 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ pnpm dlx @hanzlaa/rcode install
|
|
|
23
23
|
[](https://github.com/hanzlahabib/rcode/actions/workflows/test.yml)
|
|
24
24
|
[](LICENSE)
|
|
25
25
|
|
|
26
|
-
Status: `@hanzlaa/rcode` v4.4.
|
|
26
|
+
Status: `@hanzlaa/rcode` v4.4.2 on npm. 45 agents · 116 commands · 129 workflows · **1 runtime dependency**. Test status tracked by CI badge above. Actively dogfooded on real projects every week.
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
@@ -127,18 +127,18 @@ The point isn't "I beat LangChain." The point is **you don't need LangChain for
|
|
|
127
127
|
> node benchmarks/facts.cjs
|
|
128
128
|
> ```
|
|
129
129
|
|
|
130
|
-
<p align="center"><img src="brand/hero-receipt.png" alt="benchmarks/facts.cjs output — 497 tests, 0 failing · 45 agents · 116 commands · 1 runtime dependency, computed from files on disk" width="720"></p>
|
|
131
|
-
|
|
132
130
|
| Metric | Value | Why it's not a vanity number |
|
|
133
131
|
|---|---|---|
|
|
134
|
-
| **Portable methodology corpus** |
|
|
135
|
-
| **Automated tests** | **
|
|
136
|
-
| **Tested CLI engine** |
|
|
137
|
-
| **Runtime dependencies** | **1** (`ws`, for the dashboard socket) | The
|
|
138
|
-
| **Specialist agents / commands / workflows / skills** | **45 /
|
|
139
|
-
| **Core-op latency** | **~
|
|
140
|
-
|
|
141
|
-
|
|
132
|
+
| **Portable methodology corpus** | **~105,000 lines** of markdown | A 10-person eng org's playbooks (agents + commands + workflows + skills + references) — as files you own and grep, not a SaaS you rent. |
|
|
133
|
+
| **Automated tests** | **495** across 62 files | The methodology is *guarded*, not vibes. Live pass/fail status is on the CI badge above; `node --test` (or `node benchmarks/facts.cjs`) reproduces locally in seconds. |
|
|
134
|
+
| **Tested CLI engine** | **~9,700 lines** (`rcode-tools.cjs` + `lib/`) | The deterministic brain — routing, state, planning math — is real code under test, not prompt soup. |
|
|
135
|
+
| **Runtime dependencies** | **1** (`ws`, for the dashboard socket) | The dashboard is otherwise pure Node stdlib. Almost nothing to audit, nothing to CVE-scan, nothing to break on `npm install`. |
|
|
136
|
+
| **Specialist agents / commands / workflows / skills** | **45 / 117 / 129 / 96** | An entire engineering org, phrase-activated, that travels with you across Claude Code, Cursor, Codex, VS Code, Antigravity, Windsurf. |
|
|
137
|
+
| **Core-op latency** | **~60 ms**, **0 LLM tokens** (best-of-7) | Intent routing, state reads, and milestone-health are deterministic *local* compute — a few ms over Node's own cold-start floor. The orchestration layer doesn't burn API tokens on bookkeeping the way pure-LLM agent frameworks do. |
|
|
138
|
+
|
|
139
|
+
> Counts above are produced by `node benchmarks/facts.cjs` and may drift slightly between releases — run it for the exact current figures.
|
|
140
|
+
|
|
141
|
+
**The headline:** an entire software-delivery methodology — ~105k lines of it — guarded by a real test suite, riding on a single runtime dependency, with an orchestration brain that costs **zero tokens** to think. Not a viral prompt. A system you can verify line by line.
|
|
142
142
|
|
|
143
143
|
---
|
|
144
144
|
|
package/cli/install.js
CHANGED
|
@@ -825,15 +825,20 @@ function seedStarterPlanning(target, projectName) {
|
|
|
825
825
|
|
|
826
826
|
const state = {
|
|
827
827
|
version: '1',
|
|
828
|
-
|
|
828
|
+
// #940 — match the canonical schema (cli/lib/schemas.cjs stateSchema):
|
|
829
|
+
// schema_version is required, milestones is a plural array. Without these
|
|
830
|
+
// a freshly-installed state.json failed `rcode-tools validate` until the
|
|
831
|
+
// first migrateState() read. Write conformant state up front.
|
|
832
|
+
schema_version: 2,
|
|
833
|
+
project: resolvedProject || path.basename(target),
|
|
829
834
|
...(isStubProject ? { _seeded_stub: true } : {}),
|
|
830
835
|
created: now,
|
|
831
836
|
updated: now,
|
|
832
837
|
current_phase: resolvedPhase,
|
|
833
838
|
current_plan: 0,
|
|
834
839
|
current_sprint: null,
|
|
835
|
-
milestone: null,
|
|
836
840
|
phases: [],
|
|
841
|
+
milestones: [],
|
|
837
842
|
executions: [],
|
|
838
843
|
decisions: [],
|
|
839
844
|
blockers: [],
|
package/dist/rcode.js
CHANGED
|
@@ -196,7 +196,7 @@ _None._
|
|
|
196
196
|
## Next Action
|
|
197
197
|
|
|
198
198
|
Run \`/rcode-new-project <description>\` to bootstrap, or \`/rcode-sprint-planning\` once a real phase exists.
|
|
199
|
-
`);let c=p.join(t,".rcode","state.json");function l(){let d=p.join(t,".planning","ROADMAP.md");if(!D.existsSync(d))return!0;try{return D.readFileSync(d,"utf8").includes("<!-- INSTALL STUB")}catch{return!0}}if(!D.existsSync(c)){let d=new Date().toISOString(),f=l(),g=null,m=p.join(t,".rcode","config.yaml");if(D.existsSync(m))try{let F=D.readFileSync(m,"utf8").match(/^project_name:\s*"?([^"\n]+)"?/m);F&&(g=F[1].trim())}catch{}let y=null,h=p.join(t,".planning","ROADMAP.md");if(!f&&D.existsSync(h))try{let b=D.readFileSync(h,"utf8"),F=b.match(/^\|\s*(\d+(?:\.\d+)?)\s*\|/m);if(F)y=String(parseInt(F[1],10));else{let T=b.match(/^#{2,4}\s*Phase\s+(\d+(?:\.\d+)?)/im);T&&(y=String(parseInt(T[1],10)))}}catch{}let w={version:"1",project:g,...f?{_seeded_stub:!0}:{},created:d,updated:d,current_phase:y,current_plan:0,current_sprint:null,
|
|
199
|
+
`);let c=p.join(t,".rcode","state.json");function l(){let d=p.join(t,".planning","ROADMAP.md");if(!D.existsSync(d))return!0;try{return D.readFileSync(d,"utf8").includes("<!-- INSTALL STUB")}catch{return!0}}if(!D.existsSync(c)){let d=new Date().toISOString(),f=l(),g=null,m=p.join(t,".rcode","config.yaml");if(D.existsSync(m))try{let F=D.readFileSync(m,"utf8").match(/^project_name:\s*"?([^"\n]+)"?/m);F&&(g=F[1].trim())}catch{}let y=null,h=p.join(t,".planning","ROADMAP.md");if(!f&&D.existsSync(h))try{let b=D.readFileSync(h,"utf8"),F=b.match(/^\|\s*(\d+(?:\.\d+)?)\s*\|/m);if(F)y=String(parseInt(F[1],10));else{let T=b.match(/^#{2,4}\s*Phase\s+(\d+(?:\.\d+)?)/im);T&&(y=String(parseInt(T[1],10)))}}catch{}let w={version:"1",schema_version:2,project:g||p.basename(t),...f?{_seeded_stub:!0}:{},created:d,updated:d,current_phase:y,current_plan:0,current_sprint:null,phases:[],milestones:[],executions:[],decisions:[],blockers:[],council_sessions:[],chains:[],workstreams:[],active_workstream:null,last_session:null,velocity_history:[]};D.mkdirSync(p.dirname(c),{recursive:!0}),Ft(c,JSON.stringify(w,null,2)+`
|
|
200
200
|
`)}return!0}function uk(t,e={}){let r=e.commitPlanning!==!1,n="# ===== rcode-managed gitignore block (npx @hanzlaa/rcode install) =====",s="# ===== end rcode-managed gitignore block =====",i=["",n,"# Added automatically on first rcode install. Idempotent \u2014 safe to re-run.","# Edit `commit_planning` in .rcode/config.yaml to flip planning-artifact tracking.","","# Installed methodology files (regenerate with: npx @hanzlaa/rcode install)",".claude/",".rcode/bin/",".rcode/workflows/",".rcode/references/",".rcode/commands/",".rcode/skills/","","# Pulled rcode brain content (refresh with: rcode brain pull)",".rcode/brain/rcode-github/",".rcode/brain/rcode-docs/",".rcode/brain/best-practices/","","# Runtime noise","node_modules/",".rcode/state.json.lock",".planning/debug/",".planning/_backup/"];r||i.push("","# Planning artifacts \u2014 kept local (commit_planning: false)",".planning/"),i.push("","# What you DO commit:","# .rcode/config.yaml - project mode/language/profile/commit_planning","# .rcode/state.json - decisions, roadmap pointer, blockers","# .rcode/brain/sources.yaml - brain source manifest",r?"# .planning/ - PRD, roadmap, sprints, SUMMARY.md files":"# (planning artifacts are NOT committed \u2014 see commit_planning in config)",s,"");let o=i.join(`
|
|
201
201
|
`),a=p.join(t,".gitignore");try{let l=function(d,f){let g=d.indexOf(n);if(g<0)return null;let m=d.indexOf(s,g);if(m<0){let w=g;return w>0&&d[w-1]===`
|
|
202
202
|
`&&(w-=1),d.slice(0,w)+f}let y=g;y>0&&d[y-1]===`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzlaa/rcode",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.2",
|
|
4
4
|
"description": "rcode — the AI team that never forgets. Persistent memory, specialist agents, and slash commands for AI IDEs. Works in Claude Code, Cursor, Gemini, VS Code, and Antigravity.",
|
|
5
5
|
"main": "cli/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -7596,21 +7596,43 @@ async function main() {
|
|
|
7596
7596
|
const validateErrors = [];
|
|
7597
7597
|
|
|
7598
7598
|
if (target === 'state' || target === 'all') {
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7599
|
+
// Read state.json directly — readState() is scoped inside cmdState()
|
|
7600
|
+
// and isn't reachable here (#940). Validate against the REAL schema:
|
|
7601
|
+
// phases[] + milestones[], current_phase nullable on fresh installs.
|
|
7602
|
+
const statePathV = path.join(RCODE_DIR, 'state.json');
|
|
7603
|
+
if (!fs.existsSync(statePathV)) {
|
|
7604
|
+
validateErrors.push('state: state.json not found — run rcode install');
|
|
7602
7605
|
} else {
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
|
|
7606
|
+
let state = null;
|
|
7607
|
+
try {
|
|
7608
|
+
state = JSON.parse(fs.readFileSync(statePathV, 'utf8'));
|
|
7609
|
+
} catch (e) {
|
|
7610
|
+
validateErrors.push(`state: invalid JSON — ${e.message}`);
|
|
7611
|
+
}
|
|
7612
|
+
if (state) {
|
|
7613
|
+
// current_phase is legitimately null on a fresh / stub project,
|
|
7614
|
+
// so do NOT require it. milestones is an array (no current_milestone field).
|
|
7615
|
+
// schema_version 1 is valid on disk — migrateState() upgrades it to 2
|
|
7616
|
+
// transparently on read, so accept either and only flag the unknown.
|
|
7617
|
+
if (state.schema_version != null && ![1, 2].includes(state.schema_version)) {
|
|
7618
|
+
validateErrors.push(`state: unknown schema_version ${state.schema_version} (expected 1 or 2)`);
|
|
7619
|
+
}
|
|
7620
|
+
if (state.phases != null && !Array.isArray(state.phases) && typeof state.phases !== 'object') {
|
|
7621
|
+
validateErrors.push('state: phases must be an array or object');
|
|
7622
|
+
}
|
|
7623
|
+
if (state.milestones != null && !Array.isArray(state.milestones)) {
|
|
7624
|
+
validateErrors.push('state: milestones must be an array');
|
|
7625
|
+
}
|
|
7626
|
+
}
|
|
7607
7627
|
}
|
|
7608
7628
|
}
|
|
7609
7629
|
|
|
7610
7630
|
if (target === 'config' || target === 'all') {
|
|
7631
|
+
// config.yaml holds project identity + workflow prefs only — it does
|
|
7632
|
+
// NOT track current_phase (that lives in state.json). Only require
|
|
7633
|
+
// the fields config actually owns (#940).
|
|
7611
7634
|
const config = readConfig();
|
|
7612
7635
|
if (!config.project_name) validateErrors.push('config: missing project_name');
|
|
7613
|
-
if (!config.current_phase && !config.phase) validateErrors.push('config: missing current_phase or phase');
|
|
7614
7636
|
}
|
|
7615
7637
|
|
|
7616
7638
|
if (validateErrors.length) {
|
package/rcode/commands/lazy.md
CHANGED
|
@@ -5,6 +5,12 @@ argument-hint: "[challenge or code to simplify] [--intensity=lite|full|ultra]"
|
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
7
7
|
- AskUserQuestion
|
|
8
|
+
- Skill
|
|
8
9
|
---
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
Invoke the `rcode-lazy` skill (via the Skill tool) and apply it to: $ARGUMENTS
|
|
12
|
+
|
|
13
|
+
`rcode-lazy` is the always-on "lazy senior dev" lens — it forces the simplest
|
|
14
|
+
solution that actually works (YAGNI, stdlib before custom code, native platform
|
|
15
|
+
features before dependencies, one line before fifty) before any code is written.
|
|
16
|
+
Pass `--intensity=lite|full|ultra` through if the user provided it; default is `full`.
|