@hanzlaa/rcode 4.4.4 → 4.6.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 +11 -4
- package/CLAUDE.md +11 -4
- package/CONTRIBUTING.md +6 -1
- package/cli/doctor.js +122 -0
- package/cli/index.js +4 -0
- package/cli/install.js +8 -0
- package/cli/lib/namespace-migrate.cjs +216 -0
- package/cli/migrate-namespace.js +61 -0
- package/cli/update.js +19 -0
- package/dist/rcode.js +215 -208
- package/package.json +14 -12
- package/rcode/agents/rcode-mariam.md +6 -0
- package/rcode/agents/rcode-sadiq.md +6 -0
- package/rcode/agents/rcode-waleed.md +6 -0
- package/rcode/bin/lib/brain.cjs +353 -0
- package/rcode/bin/lib/gitignore.cjs +126 -0
- package/rcode/bin/lib/memory-drift.cjs +237 -0
- package/rcode/bin/lib/memory-select.cjs +263 -0
- package/rcode/bin/lib/progress.cjs +440 -0
- package/rcode/bin/lib/state-reader.cjs +127 -0
- package/rcode/bin/lib/summary.cjs +82 -0
- package/rcode/bin/rcode-hooks.cjs +230 -64
- package/rcode/bin/rcode-tools.cjs +106 -985
- package/rcode/data/intent-table.json +19 -19
- package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/templates/heartbeat.sh +0 -0
- package/rcode/skills/agents/mariam-marketing/SKILL.md +1 -0
- package/rcode/skills/agents/sadiq-analyst/SKILL.md +1 -0
- package/rcode/skills/agents/waleed-architect/SKILL.md +1 -0
- package/rcode/templates/memory/INDEX.md +6 -1
- package/rcode/templates/settings-hooks.json +12 -1
- package/rcode/workflows/council.md +29 -1
- package/rcode/workflows/do.md +2 -2
- package/rcode/workflows/enable-hooks.md +3 -2
- package/rcode/workflows/new-project-roadmap.md +2 -2
- package/server/dashboard.js +6 -3
- package/server/lib/html/client/components/App.js +1 -1
- package/server/lib/html/client/components/OrchPanel.js +2 -2
- package/server/lib/html/client/components/XtermPanel.js +98 -23
- package/server/lib/html/client/orchestrator.js +28 -15
- package/server/lib/html/client/views/OrchestrationView.js +247 -169
- package/server/lib/html/css.js +596 -227
- package/server/lib/html/shell.js +9 -3
- package/server/orchestrator.js +3 -4
|
@@ -1,87 +1,87 @@
|
|
|
1
1
|
[
|
|
2
2
|
{
|
|
3
3
|
"intent": "new-project",
|
|
4
|
-
"keywords": ["set up a new project", "initialize a new project", "start a new project", "create a new project"],
|
|
4
|
+
"keywords": ["set up a new project", "initialize a new project", "start a new project", "create a new project", "naya project shuru karo", "naya project banao", "مشروع جديد", "ابدأ مشروع جديد"],
|
|
5
5
|
"command": "/rcode-new-project"
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
8
|
"intent": "map-codebase",
|
|
9
|
-
"keywords": ["map the codebase", "map this codebase", "analyze the codebase", "analyse the codebase", "map existing codebase"],
|
|
9
|
+
"keywords": ["map the codebase", "map this codebase", "analyze the codebase", "analyse the codebase", "map existing codebase", "codebase samjhao", "code ka structure dikhao", "حلل الكود", "افهم هيكل المشروع"],
|
|
10
10
|
"command": "/rcode-map-codebase"
|
|
11
11
|
},
|
|
12
12
|
{
|
|
13
13
|
"intent": "debug",
|
|
14
|
-
"keywords": ["bug", "getting an error", "throwing an error", "error in the", "fix the error", "debug this", "crash", "failure", "broken", "not working", "fails", "exception", "traceback"],
|
|
14
|
+
"keywords": ["bug", "getting an error", "throwing an error", "error in the", "fix the error", "debug this", "crash", "failure", "broken", "not working", "fails", "exception", "traceback", "kharab", "masla", "ye kaam nahi kar raha", "yeh kaam nahi kar raha", "error a raha hai", "theek karo", "khud se crash", "خطأ", "مشكلة", "لا يعمل", "أصلح الخطأ", "تعطل البرنامج"],
|
|
15
15
|
"command": "/rcode-debug"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
|
-
"intent": "audit
|
|
19
|
-
"keywords": ["
|
|
20
|
-
"command": "/rcode-
|
|
18
|
+
"intent": "karpathy-audit",
|
|
19
|
+
"keywords": ["review changes", "check my diff", "karpathy", "too complex", "complexity", "diff check karo", "پیچیدہ کوڈ", "تحقق من التغييرات"],
|
|
20
|
+
"command": "/rcode-karpathy-audit"
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"intent": "lazy",
|
|
24
|
-
"keywords": ["be lazy", "lazy mode", "simplest solution", "yagni", "over-engineered", "over-engineering", "kam code likho"],
|
|
24
|
+
"keywords": ["be lazy", "lazy mode", "simplest solution", "yagni", "over-engineered", "over-engineering", "kam code likho", "asaan tareeqa", "سهل الحل", "أبسط طريقة"],
|
|
25
25
|
"command": "/rcode-lazy"
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"intent": "checkpoint",
|
|
29
|
-
"keywords": ["checkpoint", "explain this diff", "human review", "walk through the change", "walk through this change"],
|
|
29
|
+
"keywords": ["checkpoint", "explain this diff", "human review", "walk through the change", "walk through this change", "diff samjhao", "اشرح هذا التغيير"],
|
|
30
30
|
"command": "/rcode-checkpoint-preview"
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
"intent": "brainstorm",
|
|
34
|
-
"keywords": ["brainstorm", "generate ideas", "explore options", "what could we do", "ideate", "ideas for"],
|
|
34
|
+
"keywords": ["brainstorm", "generate ideas", "explore options", "what could we do", "ideate", "ideas for", "ideas do", "hum kya kar sakte hain", "أفكار", "ما الذي يمكننا فعله"],
|
|
35
35
|
"command": "/rcode-brainstorm"
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
"intent": "explore",
|
|
39
|
-
"keywords": ["explore", "research phase", "do some research", "comparing", "investigate", "look into", "understand how"],
|
|
39
|
+
"keywords": ["explore", "research phase", "do some research", "comparing", "investigate", "look into", "understand how", "research karo", "pata karo", "ابحث عن", "قارن بين"],
|
|
40
40
|
"command": "/rcode-research-phase"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"intent": "discuss",
|
|
44
|
-
"keywords": ["which one", "better ux", "how should", "still have confusion", "conflicting", "discuss the scope", "design this", "architect this"],
|
|
44
|
+
"keywords": ["which one", "better ux", "how should", "still have confusion", "conflicting", "discuss the scope", "design this", "architect this", "confusion hai", "kaunsa behtar hai", "أيهما أفضل", "لست متأكداً"],
|
|
45
45
|
"command": "/rcode-discuss-phase"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"intent": "add-phase",
|
|
49
|
-
"keywords": ["refactor", "migration", "multi-file", "system redesign", "multi file", "large refactor", "architectural", "integration", "integrate"],
|
|
49
|
+
"keywords": ["refactor", "migration", "multi-file", "system redesign", "multi file", "large refactor", "architectural", "integration", "integrate", "poora refactor karo", "migration karna hai", "إعادة هيكلة", "ترحيل النظام"],
|
|
50
50
|
"command": "/rcode-add-phase"
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"intent": "sprint-planning",
|
|
54
|
-
"keywords": ["sprint planning", "plan the sprint", "next sprint", "what's in this sprint"],
|
|
54
|
+
"keywords": ["sprint planning", "plan the sprint", "next sprint", "what's in this sprint", "sprint plan karo", "تخطيط السبرنت"],
|
|
55
55
|
"command": "/rcode-sprint-planning"
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"intent": "execute-sprint",
|
|
59
|
-
"keywords": ["run the sprint", "start sprint", "execute sprint", "work on sprint"],
|
|
59
|
+
"keywords": ["run the sprint", "start sprint", "execute sprint", "work on sprint", "sprint chalao", "sprint shuru karo", "نفذ السبرنت", "ابدأ السبرنت"],
|
|
60
60
|
"command": "/rcode-execute-sprint"
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
"intent": "plan",
|
|
64
|
-
"keywords": ["let's plan", "plan phase", "plan this", "let me plan", "planning phase", "create a plan", "please plan", "plan and think", "scope this", "scope the feature"],
|
|
64
|
+
"keywords": ["let's plan", "plan phase", "plan this", "let me plan", "planning phase", "create a plan", "please plan", "plan and think", "scope this", "scope the feature", "plan banao", "isko plan karo", "خطط لهذا", "أنشئ خطة"],
|
|
65
65
|
"command": "/rcode-plan"
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
"intent": "new-milestone",
|
|
69
|
-
"keywords": ["create milestones", "plan milestones", "create roadmap", "break project into milestones", "new milestone", "what milestones"],
|
|
69
|
+
"keywords": ["create milestones", "plan milestones", "create roadmap", "break project into milestones", "new milestone", "what milestones", "milestones banao", "خطة الطريق", "مراحل المشروع"],
|
|
70
70
|
"command": "/rcode-new-milestone"
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"intent": "epics-stories",
|
|
74
|
-
"keywords": ["create epics", "user stories", "create stories", "epics and stories", "break into epics"],
|
|
74
|
+
"keywords": ["create epics", "user stories", "create stories", "epics and stories", "break into epics", "stories banao", "قصص المستخدم", "أنشئ ملاحم"],
|
|
75
75
|
"command": "/rcode-create-epics-and-stories"
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
"intent": "feature-drift",
|
|
79
|
-
"keywords": ["out of date", "out-of-date", "verify docs", "audit feature docs", "fill out existing", "prd drift", "docs vs code"],
|
|
79
|
+
"keywords": ["out of date", "out-of-date", "verify docs", "audit feature docs", "fill out existing", "prd drift", "docs vs code", "docs purane hain", "الوثائق قديمة", "تحقق من التوثيق"],
|
|
80
80
|
"command": "/rcode-feature-drift"
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
"intent": "audit",
|
|
84
|
-
"keywords": ["re-audit", "extend the audit", "fill out the", "expand the", "re audit"],
|
|
84
|
+
"keywords": ["re-audit", "extend the audit", "fill out the", "expand the", "re audit", "audit", "code review", "dobara audit karo", "audit karo", "code review karo", "دقق الكود", "مراجعة الكود", "راجع التغييرات"],
|
|
85
85
|
"command": "/rcode-audit"
|
|
86
86
|
}
|
|
87
87
|
]
|
package/rcode/skills/actions/4-implementation/rcode-herdr-orchestration/templates/heartbeat.sh
CHANGED
|
File without changes
|
|
@@ -88,6 +88,7 @@ Five named heuristics. Cite by name when reasoning:
|
|
|
88
88
|
- **Never claim market readiness from < 4 disconfirmable signals.** Three customers is a focus group at best.
|
|
89
89
|
- **Never write a launch plan** without a 90-day proof point AND the kill criterion.
|
|
90
90
|
- **Never speculate on market data without WebSearch.** "unknown — would need 1 hour of research" is a valid answer.
|
|
91
|
+
- **Grounding rule (mandatory):** any pricing, fee, rate, market-size, or regulation claim MUST be verified with WebSearch/WebFetch in-session, or explicitly tagged `[unverified — training data]`.
|
|
91
92
|
- **Never write PRDs / user stories / architecture decisions.** Stay in the GTM lane.
|
|
92
93
|
- Brand consistency over clever campaigns
|
|
93
94
|
|
|
@@ -84,6 +84,7 @@ State the rule by name when refusing.
|
|
|
84
84
|
- **Never accept urgency manufactured by sales pressure** without independent market signal. Get the LOI in writing first.
|
|
85
85
|
- **Never make a strategic call under context-switch pressure.** If the user is tired or mid-fire, defer. Bad strategy at midnight is worse than no strategy.
|
|
86
86
|
- **Never write code, PRDs, or research reports.** Strategy directors set bets and kill switches; that's the deliverable.
|
|
87
|
+
- **Grounding rule (mandatory):** any pricing, fee, rate, market-size, or regulation claim MUST be verified with WebSearch/WebFetch in-session, or explicitly tagged `[unverified — training data]`.
|
|
87
88
|
|
|
88
89
|
## In Round 2 (council follow-ups)
|
|
89
90
|
|
|
@@ -86,6 +86,7 @@ State the rule by name when refusing.
|
|
|
86
86
|
- **Never propose "rewrite from scratch"** without a measurable pain point AND a parallel-run migration plan. Joel Spolsky test: if you can't write the migration plan in 200 words, the rewrite is wrong-shaped.
|
|
87
87
|
- **Never recommend bleeding-edge tech** for systems with multi-year lifetime expectations. Beta dependencies are a Reversibility-test fail.
|
|
88
88
|
- **Never write production code** in your responses. ADRs and decision matrices only. Code goes to Yousef / Hanzla / Omar / Haitham.
|
|
89
|
+
- **Grounding rule (mandatory):** any pricing, fee, rate, market-size, or regulation claim MUST be verified with WebSearch/WebFetch in-session, or explicitly tagged `[unverified — training data]`.
|
|
89
90
|
|
|
90
91
|
## Capabilities
|
|
91
92
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Memory Bank — `{{PROJECT_NAME}}`
|
|
2
2
|
|
|
3
|
-
> The Memory Bank is your project's persistent brain.
|
|
3
|
+
> The Memory Bank is your project's persistent brain. Full read/write access is on-demand: run `/rcode-memory-init` to scaffold it, `/rcode-memory-update` after work happens, `/rcode-memory-distill` to regenerate the compressed distillates, and `/rcode-memory-audit` to check it for staleness. Ambient injection also runs automatically (#958): the `session-start` hook emits its usual one-line phase-status primer from `.rcode/state.json`, then — when this directory exists and has content — a relevance-ranked selector (`rcode/bin/lib/memory-select.cjs`) scores every file here against the current phase, git branch, and recently touched files, and injects the top-scoring excerpts as `additionalContext` within a ~1500-token budget (override via `.rcode/config.yaml`'s `memory_inject_budget`). The `pre-compact` hook does the same with a smaller ~600-token budget as part of its survival context. This keeps agents grounded in relevant memory without a human having to run a `/rcode-memory-*` command first — full manual review is still the way to go deep.
|
|
4
|
+
>
|
|
5
|
+
> A `post-commit` hook runs a lightweight drift check after every commit (#958): it compares `project/stack.md` and `project/decisions.md` claims against the last 10 commits and the current working tree — removed/added dependencies, referenced files/dirs that no longer exist, and an `INDEX.md` older than 30 days. If it finds anything, it nudges you toward `/rcode-memory-update` once per session. Run `rcode-hooks drift` (or `node .rcode/bin/rcode-hooks.cjs drift` if the CLI isn't on your PATH) anytime for the full report.
|
|
4
6
|
|
|
5
7
|
**Last updated:** {{INIT_DATE}}
|
|
6
8
|
|
|
@@ -27,6 +29,8 @@
|
|
|
27
29
|
|
|
28
30
|
## Token budget guide
|
|
29
31
|
|
|
32
|
+
- **Ambient session-start injection** (~1.5K tokens, `memory_inject_budget`) — automatic, relevance-ranked, no command needed
|
|
33
|
+
- **Ambient pre-compact injection** (~600 tokens) — automatic survival context alongside `HANDOFF.json`
|
|
30
34
|
- **`INDEX.md` only** (~500 tokens) — quick orientation
|
|
31
35
|
- **`INDEX.md` + `distillates/project.distillate.md`** (~5K tokens) — standard session start
|
|
32
36
|
- **Full `project/` directory** (~10–15K tokens) — deep planning
|
|
@@ -39,6 +43,7 @@
|
|
|
39
43
|
- **`incidents/known-issues.md`** — add when a workaround ships, remove when a real fix lands
|
|
40
44
|
- **`distillates/`** — regenerate via `/rcode-memory-distill` when source files change
|
|
41
45
|
- **Whole bank** — audit via `/rcode-memory-audit` at every milestone close
|
|
46
|
+
- **Drift check** — runs automatically on every commit; run `rcode-hooks drift` manually anytime, or after a large dependency/refactor change
|
|
42
47
|
|
|
43
48
|
## Constraints
|
|
44
49
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"_comment": "pre-edit hook is currently advisory (logs warning, does not block). Full session-read tracking requires PostToolUse Read hook to write state file. Implemented in follow-up. prompt-router (UserPromptSubmit) is advisory — emits additionalContext to nudge toward the right rcode command; never blocks.",
|
|
2
|
+
"_comment": "pre-edit hook is currently advisory (logs warning, does not block). Full session-read tracking requires PostToolUse Read hook to write state file. Implemented in follow-up. prompt-router (UserPromptSubmit) is advisory — emits additionalContext to nudge toward the right rcode command; never blocks. session-start (SessionStart) emits a one-line project status primer at session open.",
|
|
3
3
|
"hooks": {
|
|
4
4
|
"PreToolUse": [
|
|
5
5
|
{
|
|
@@ -85,6 +85,17 @@
|
|
|
85
85
|
}
|
|
86
86
|
]
|
|
87
87
|
}
|
|
88
|
+
],
|
|
89
|
+
"SessionStart": [
|
|
90
|
+
{
|
|
91
|
+
"matcher": "",
|
|
92
|
+
"hooks": [
|
|
93
|
+
{
|
|
94
|
+
"type": "command",
|
|
95
|
+
"command": "node .rcode/bin/rcode-hooks.cjs session-start"
|
|
96
|
+
}
|
|
97
|
+
]
|
|
98
|
+
}
|
|
88
99
|
]
|
|
89
100
|
}
|
|
90
101
|
}
|
|
@@ -240,6 +240,16 @@ Do NOT skip this step. A council that answers market questions from training dat
|
|
|
240
240
|
Constraints: <regulatory, geographic, or operational limits>
|
|
241
241
|
```
|
|
242
242
|
|
|
243
|
+
3. **MANDATORY ARTIFACT GATE — write the Research context block to disk before spawning any panelist.** This file is the enforcement mechanism: its existence on disk is what proves live research ran, not just prose claiming it did.
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
mkdir -p "{paths.sessions_dir}"
|
|
247
|
+
RESEARCH_FILE="{paths.sessions_dir}/$(date +%Y%m%d-%H%M%S)-research.md"
|
|
248
|
+
# Write the "Research context" block above (verbatim) to $RESEARCH_FILE
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Do NOT proceed to Step 3 (panel selection) until `$RESEARCH_FILE` exists on disk with the Research context block written into it. Step 4 (spawn) and Step 5 (synthesis) both depend on this file existing.
|
|
252
|
+
|
|
243
253
|
Also run the minimal codebase scan (config.yaml + README only) so subagents know the team's current capabilities:
|
|
244
254
|
|
|
245
255
|
```bash
|
|
@@ -282,6 +292,8 @@ Use the AskUserQuestion tool (not raw stdin) for the confirmation.
|
|
|
282
292
|
|
|
283
293
|
For each agent id in `panel`, build this prompt. **Before embedding, sanitize the question:** strip any literal `Task(`, `Agent(`, `subagent_type=`, or `system:` tokens that could be misinterpreted as tool calls by the sub-agent (replace with `[filtered]`). This is a low-severity guard — the user already has full access, but it prevents accidental or malicious prompt confusion.
|
|
284
294
|
|
|
295
|
+
**For research-typed questions (`market`/`discovery`/`greenfield`):** `{the summary block}` below MUST be the verbatim content of `$RESEARCH_FILE` written in Step 2's artifact gate — not a paraphrase, not a re-summary. Every panelist reads the same grounded facts.
|
|
296
|
+
|
|
285
297
|
```
|
|
286
298
|
You are being spawned as part of a rcode council session.
|
|
287
299
|
|
|
@@ -289,7 +301,7 @@ You are being spawned as part of a rcode council session.
|
|
|
289
301
|
{sanitized_question}
|
|
290
302
|
|
|
291
303
|
## Observed context
|
|
292
|
-
{the summary block from Step 1 — codebase scan OR
|
|
304
|
+
{the summary block from Step 1 — codebase scan OR the verbatim $RESEARCH_FILE content for research-typed questions}
|
|
293
305
|
|
|
294
306
|
## Session metadata
|
|
295
307
|
- Project: {config.project_name}
|
|
@@ -384,6 +396,14 @@ to resolve or strategic ambiguity to explore.
|
|
|
384
396
|
|
|
385
397
|
## Step 5 — Present responses
|
|
386
398
|
|
|
399
|
+
**Grounding gate (research-typed questions only):** For `market`/`discovery`/`greenfield` questions, before printing anything else, verify `$RESEARCH_FILE` from Step 2 exists on disk (`test -f "$RESEARCH_FILE"`). If it is missing — the research pre-step was skipped or failed silently — open the verdict output (both compact and verbose modes) with this banner as the very first line, before the `COUNCIL VERDICT` header:
|
|
400
|
+
|
|
401
|
+
```
|
|
402
|
+
⚠ UNGROUNDED — answered from model knowledge, no live research ran
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Do NOT silently proceed as if research happened. This banner is mandatory whenever the file is missing for a research-typed question; it is never shown for `codebase`/`frontend`/`backend`/etc. questions where no research file is expected.
|
|
406
|
+
|
|
387
407
|
Before saving any artifact, print the panel output inline. Two modes:
|
|
388
408
|
|
|
389
409
|
### Default mode (compact summary)
|
|
@@ -417,6 +437,9 @@ Format:
|
|
|
417
437
|
**Orchestrator note**
|
|
418
438
|
{max 2 sentences — sharpest remaining disagreement OR clearest convergent action}
|
|
419
439
|
|
|
440
|
+
**Data freshness**
|
|
441
|
+
{N} claims live-verified (sources: {comma-separated source names/URLs}) / {M} claims from model knowledge
|
|
442
|
+
|
|
420
443
|
📄 Full transcripts: {artifact path}
|
|
421
444
|
```
|
|
422
445
|
|
|
@@ -425,6 +448,7 @@ Rules for compact mode:
|
|
|
425
448
|
- Convergence table: 2-5 rows, only axes where panelists take a stance. Cells ≤ 6 words.
|
|
426
449
|
- Round 2 deltas: ≤ 15 words each. "Held position" is a valid delta.
|
|
427
450
|
- No section headers beyond the four above. No numbered story breakdowns. No tables from panelists verbatim.
|
|
451
|
+
- **Data freshness footer is mandatory on every synthesis**, not just research-typed questions. Count claims across all panelist responses: a claim is "live-verified" if it cites a source found via WebSearch/WebFetch in this session (Step 2's research file, or a panelist's own in-session lookup); everything else — including anything tagged `[unverified — training data]` by a panelist — counts toward "from model knowledge". For non-research question types with no external claims, use `0 claims live-verified / 0 from model knowledge — no external claims made`.
|
|
428
452
|
|
|
429
453
|
### Verbose mode (`--verbose` flag or `output.verbose: true` in config)
|
|
430
454
|
|
|
@@ -449,6 +473,8 @@ Print Round 1 (and Round 2 if ran) verbatim in panel order. Do NOT summarize.
|
|
|
449
473
|
|
|
450
474
|
---
|
|
451
475
|
**Orchestrator Note:** {max 3 sentences}
|
|
476
|
+
|
|
477
|
+
**Data freshness:** {N} claims live-verified (sources) / {M} claims from model knowledge
|
|
452
478
|
```
|
|
453
479
|
|
|
454
480
|
Before presenting, load the commit format reference:
|
|
@@ -575,6 +601,8 @@ node .rcode/bin/rcode-tools.cjs state record-session
|
|
|
575
601
|
- [ ] Round 2 cross-talk executed (unless consensus or agent deferred)
|
|
576
602
|
- [ ] Session artifact written to `.planning/council-sessions/council-{date}-{slug}.md`
|
|
577
603
|
- [ ] State updated with session record and timestamp
|
|
604
|
+
- [ ] For research-typed questions (`market`/`discovery`/`greenfield`): `$RESEARCH_FILE` written before spawn, or ⚠ UNGROUNDED banner shown
|
|
605
|
+
- [ ] Data freshness footer included in synthesis output
|
|
578
606
|
|
|
579
607
|
## On Error
|
|
580
608
|
|
package/rcode/workflows/do.md
CHANGED
|
@@ -290,7 +290,7 @@ Evaluate `$QUESTION` against these routing rules. Apply the **first matching** r
|
|
|
290
290
|
| A bug, error, crash, failure, or something broken | `/rcode-debug` | Needs systematic investigation |
|
|
291
291
|
| Validate an idea, "working backwards", "press release", "PRFAQ", "is this worth building" | `/rcode-prfaq` | Stress-test concept before committing sprint capacity |
|
|
292
292
|
| Brainstorm, generate ideas, "explore options", "what could we do" | `/rcode-brainstorm` | Structured ideation before planning |
|
|
293
|
-
|
|
|
293
|
+
| "karpathy", "review changes", "check my diff", "too complex" — 4-principle code audit against a diff | `/rcode-karpathy-audit` | Runs the karpathy-audit workflow directly (review.md has no `--karpathy` flag) |
|
|
294
294
|
| Make it simpler, "be lazy", "lazy mode", "simplest solution", "yagni", "over-engineered", "kam code likho" | `/rcode-lazy` | Generative simplicity lens — YAGNI before code is written (rcode-trim removes bloat after the fact) |
|
|
295
295
|
| Walk through a change, "checkpoint", "explain this diff", "human review" | `/rcode-checkpoint-preview` | Human-in-the-loop diff walkthrough |
|
|
296
296
|
| Exploring, researching, comparing, or "how does X work" | `/rcode-research-phase` | Domain research before planning |
|
|
@@ -317,7 +317,7 @@ Evaluate `$QUESTION` against these routing rules. Apply the **first matching** r
|
|
|
317
317
|
| Adding tests, "write tests", "test coverage" | `/rcode-add-tests` | Test generation |
|
|
318
318
|
| Completing a milestone, shipping, releasing | `/rcode-complete-milestone` | Milestone lifecycle |
|
|
319
319
|
| Drift / out-of-date / "verify docs vs code" / "audit feature docs" / "fill out existing PRD/epics/stories" | `/rcode-feature-drift` | Detects PRD↔epics↔stories↔code drift; --fix patches trivial items |
|
|
320
|
-
|
|
|
320
|
+
| Bare "audit" / "code review" / re-audit / extend / fill out / expand an existing artifact | `/rcode-audit` | Unified audit entry — disambiguates plans/phase/milestone/UAT/code before dispatching |
|
|
321
321
|
> **SEO route guard:** Skills in this block assume a project context exists (`.planning/PROJECT.md`). If absent, the `HAS_PRD` check in `<step name="check_project">` redirects to `/rcode-new-project`.
|
|
322
322
|
|
|
323
323
|
| **— SEO / Content intent —** | | |
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Workflow: rcode-enable-hooks
|
|
2
2
|
|
|
3
3
|
<purpose>
|
|
4
|
-
Merge rcode opt-in hooks from settings-hooks.json into .claude/settings.json. Creates settings.json if missing. Enables all
|
|
4
|
+
Merge rcode opt-in hooks from settings-hooks.json into .claude/settings.json. Creates settings.json if missing. Enables all 10 guardrails: pre-edit (read-before-edit check), pre-workflow (command hint), post-commit (format validation), bash-guard (blocks dangerous commands), pre-compact (refreshes HANDOFF.json before context compaction), stop-verify (syntax-checks files changed during the response), cost-track (logs measured token usage to .rcode/telemetry/cost.jsonl), compact-nudge (advises /rcode-trim or /clear after many edits), prompt-router (proactive nudge toward the right rcode command for long-term memory consistency), and session-start (SessionStart — one-line project status primer at session open).
|
|
5
5
|
</purpose>
|
|
6
6
|
|
|
7
7
|
|
|
@@ -44,7 +44,7 @@ If `.claude/` directory does not exist, create it first.
|
|
|
44
44
|
|
|
45
45
|
## Step 3 — Merge hooks
|
|
46
46
|
|
|
47
|
-
For each hook type (`PreToolUse`, `PostToolUse`, `PreCompact`, `Stop`, `UserPromptSubmit`):
|
|
47
|
+
For each hook type (`PreToolUse`, `PostToolUse`, `PreCompact`, `Stop`, `UserPromptSubmit`, `SessionStart`):
|
|
48
48
|
|
|
49
49
|
- If the hook type does not exist in the current settings.json, add it.
|
|
50
50
|
- If it exists, append the new matchers and hook commands (avoid duplicates by checking for exact command matches).
|
|
@@ -87,6 +87,7 @@ Enabled guardrails:
|
|
|
87
87
|
• cost-track: Logs measured token usage to .rcode/telemetry/cost.jsonl
|
|
88
88
|
• compact-nudge: Advises /rcode-trim or /clear after many edits
|
|
89
89
|
• prompt-router: Nudges toward the matching /rcode-* command and /rcode-memory-update so work lands in .rcode/state.json (toggle via prompt_nudge in .rcode/config.yaml: every|once-per-intent|when-stale|off)
|
|
90
|
+
• session-start: Greets the session with one-line phase status and suggested next command
|
|
90
91
|
|
|
91
92
|
To disable, remove the hooks section from .claude/settings.json or edit .rcode/templates/settings-hooks.json and re-run.
|
|
92
93
|
```
|
|
@@ -302,12 +302,12 @@ Use AskUserQuestion:
|
|
|
302
302
|
node .rcode/bin/rcode-tools.cjs generate-claude-md
|
|
303
303
|
```
|
|
304
304
|
|
|
305
|
-
This ensures new projects get the default rcode workflow-enforcement guidance and current project context in `CLAUDE.md
|
|
305
|
+
This ensures new projects get the default rcode workflow-enforcement guidance and current project context in `CLAUDE.md` and `AGENTS.md` (the cross-tool standard read by Codex, Cursor, Windsurf, Antigravity, and Gemini). `AGENTS.md` is only written when absent — an install-managed roster section is preserved.
|
|
306
306
|
|
|
307
307
|
**Commit roadmap (after approval or auto mode):**
|
|
308
308
|
|
|
309
309
|
```bash
|
|
310
|
-
node .rcode/bin/rcode-tools.cjs commit "docs: create roadmap ([N] phases)" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md CLAUDE.md
|
|
310
|
+
node .rcode/bin/rcode-tools.cjs commit "docs: create roadmap ([N] phases)" --files .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md CLAUDE.md AGENTS.md
|
|
311
311
|
```
|
|
312
312
|
|
|
313
313
|
## 9. Done
|
package/server/dashboard.js
CHANGED
|
@@ -36,6 +36,9 @@ const { renderHtml } = require('./lib/html/shell');
|
|
|
36
36
|
|
|
37
37
|
// ---------- Configuration ----------
|
|
38
38
|
const PORT = parseInt(process.env.PORT || '7717', 10);
|
|
39
|
+
// #969 — the orchestrator's actual port, injected into the client so it never
|
|
40
|
+
// has to hardcode 7718. Defaults match orchestrator.js's own default.
|
|
41
|
+
const ORCH_PORT = parseInt(process.env.ORCH_PORT || '7718', 10);
|
|
39
42
|
const RCODE_DIR = process.env.RCODE_DIR || path.join(process.cwd(), '.rcode');
|
|
40
43
|
const PROJECT_ROOT = path.dirname(RCODE_DIR);
|
|
41
44
|
// Fallback root for agent prompts when rcode is installed as a package (not run
|
|
@@ -147,7 +150,7 @@ function handleRequest(req, res) {
|
|
|
147
150
|
return;
|
|
148
151
|
}
|
|
149
152
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
150
|
-
res.end(JSON.stringify({ token: ORCH_TOKEN }));
|
|
153
|
+
res.end(JSON.stringify({ token: ORCH_TOKEN, orchPort: ORCH_PORT }));
|
|
151
154
|
return;
|
|
152
155
|
}
|
|
153
156
|
|
|
@@ -178,7 +181,7 @@ function handleRequest(req, res) {
|
|
|
178
181
|
|
|
179
182
|
if (url === '/' || url === '/index.html') {
|
|
180
183
|
const state = scanState(RCODE_DIR);
|
|
181
|
-
const html = renderHtml(state, ORCH_TOKEN);
|
|
184
|
+
const html = renderHtml(state, ORCH_TOKEN, ORCH_PORT);
|
|
182
185
|
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-cache' });
|
|
183
186
|
res.end(html);
|
|
184
187
|
return;
|
|
@@ -257,7 +260,7 @@ function spawnOrchestrator() {
|
|
|
257
260
|
console.error('[orch] spawn error:', err.message);
|
|
258
261
|
_orchProc = null;
|
|
259
262
|
});
|
|
260
|
-
console.log(
|
|
263
|
+
console.log(`[orch] orchestrator started (port ${ORCH_PORT})`);
|
|
261
264
|
} catch (err) {
|
|
262
265
|
console.error('[orch] failed to start:', err.message);
|
|
263
266
|
}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
import { html, useState, useEffect, useRef, useCallback } from '../preact.js';
|
|
17
17
|
import { useStore, setState } from '../store.js';
|
|
18
|
-
import { orchToken, stopSession, cleanSessions,
|
|
18
|
+
import { orchToken, stopSession, cleanSessions, orchWs } from '../orchestrator.js';
|
|
19
19
|
import { showToast } from './shared.js';
|
|
20
20
|
import { Icon } from '../icons-client.js';
|
|
21
21
|
|
|
@@ -106,7 +106,7 @@ export function OrchPanel() {
|
|
|
106
106
|
return;
|
|
107
107
|
}
|
|
108
108
|
const ws = new WebSocket(
|
|
109
|
-
|
|
109
|
+
orchWs() + '/ws/' + encodeURIComponent(storyId) +
|
|
110
110
|
'?token=' + encodeURIComponent(tok)
|
|
111
111
|
);
|
|
112
112
|
_streams[storyId] = ws;
|
|
@@ -9,18 +9,34 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Store field: state.terminal = { open, storyId, title, minimized, fullscreen }
|
|
11
11
|
* Setting state.terminal via orchestrator.js triggers this component.
|
|
12
|
+
*
|
|
13
|
+
* Two mount points, one singleton terminal:
|
|
14
|
+
* - App.js mounts one instance as a floating overlay (backdrop + sliding
|
|
15
|
+
* panel + minimized pill) on every view.
|
|
16
|
+
* - OrchestrationView.js mounts a second instance with `docked=true` to
|
|
17
|
+
* embed the SAME xterm.js Terminal inline in its right column.
|
|
18
|
+
* Only one instance may touch the DOM at a time — App.js passes
|
|
19
|
+
* `suspend=${view === 'orchestration'}` so its overlay instance goes fully
|
|
20
|
+
* inert (renders null, effects no-op) while Orchestration's docked instance
|
|
21
|
+
* is mounted. `ensureTerm()` reparents the shared xterm DOM node into
|
|
22
|
+
* whichever container asks for it, so the buffer/connection survive the
|
|
23
|
+
* hand-off in both directions.
|
|
12
24
|
*/
|
|
13
25
|
|
|
14
26
|
import { html, useEffect, useRef, useCallback } from '../preact.js';
|
|
15
27
|
import { useStore, setState } from '../store.js';
|
|
16
|
-
import { orchToken, stopSession,
|
|
28
|
+
import { orchToken, stopSession, orchWs } from '../orchestrator.js';
|
|
17
29
|
|
|
18
30
|
// ── Internal state (module-scoped, one panel at a time) ──────────────────────
|
|
19
|
-
// These
|
|
20
|
-
// across panel open/close cycles
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
31
|
+
// These are NOT component state because the xterm instance (and the story it
|
|
32
|
+
// is currently connected to) must persist across panel open/close cycles,
|
|
33
|
+
// Preact re-renders, and — now — across the two XtermPanel mount points
|
|
34
|
+
// (floating overlay vs. docked). Component-local refs would not be shared
|
|
35
|
+
// between those two instances.
|
|
36
|
+
let _term = null;
|
|
37
|
+
let _termFit = null;
|
|
38
|
+
let _termWs = null;
|
|
39
|
+
let _currentStory = null;
|
|
24
40
|
|
|
25
41
|
function setStatus(dotStatus) {
|
|
26
42
|
// Propagate connection status via a store signal so the pill/header can react
|
|
@@ -34,9 +50,23 @@ function _resize() {
|
|
|
34
50
|
}
|
|
35
51
|
}
|
|
36
52
|
|
|
37
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Build the xterm instance exactly once; attach to `containerEl`.
|
|
55
|
+
* If the instance already exists but lives under a DIFFERENT container
|
|
56
|
+
* (e.g. the overlay panel had it, and the docked panel is now asking), move
|
|
57
|
+
* its root DOM node into `containerEl` instead of no-oping. xterm.js's root
|
|
58
|
+
* element is a plain DOM node — reparenting it is safe and preserves the
|
|
59
|
+
* scrollback buffer and any live WebSocket connection.
|
|
60
|
+
*/
|
|
38
61
|
function ensureTerm(containerEl) {
|
|
39
|
-
if (_term
|
|
62
|
+
if (_term) {
|
|
63
|
+
if (_term.element && _term.element.parentElement !== containerEl) {
|
|
64
|
+
containerEl.appendChild(_term.element);
|
|
65
|
+
if (_termFit) { try { _termFit.fit(); } catch (_e) {} }
|
|
66
|
+
}
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (typeof Terminal === 'undefined') return;
|
|
40
70
|
_term = new Terminal({
|
|
41
71
|
theme: {
|
|
42
72
|
background: '#0c0c0e', foreground: '#c9d1d9',
|
|
@@ -74,7 +104,7 @@ function connectWs(storyId) {
|
|
|
74
104
|
return;
|
|
75
105
|
}
|
|
76
106
|
setStatus('connecting');
|
|
77
|
-
const url =
|
|
107
|
+
const url = orchWs() + '/ws/' + encodeURIComponent(storyId) + '?token=' + encodeURIComponent(tok);
|
|
78
108
|
const ws = new WebSocket(url);
|
|
79
109
|
_termWs = ws;
|
|
80
110
|
|
|
@@ -98,10 +128,9 @@ function connectWs(storyId) {
|
|
|
98
128
|
|
|
99
129
|
// ── Component ─────────────────────────────────────────────────────────────────
|
|
100
130
|
|
|
101
|
-
export function XtermPanel() {
|
|
131
|
+
export function XtermPanel({ docked = false, suspend = false } = {}) {
|
|
102
132
|
const { terminal, termStatus } = useStore();
|
|
103
133
|
const containerRef = useRef(null);
|
|
104
|
-
const currentStoryRef = useRef(null);
|
|
105
134
|
|
|
106
135
|
const t = terminal || {};
|
|
107
136
|
const open = !!t.open;
|
|
@@ -110,28 +139,37 @@ export function XtermPanel() {
|
|
|
110
139
|
const storyId = t.storyId || '';
|
|
111
140
|
const title = t.title || 'Terminal';
|
|
112
141
|
|
|
113
|
-
// Build xterm instance on
|
|
114
|
-
//
|
|
115
|
-
//
|
|
142
|
+
// Build/attach the xterm instance on open; (re)connect only when the
|
|
143
|
+
// focused storyId actually changes. `_currentStory` is module-scoped (not
|
|
144
|
+
// a per-instance ref) so that handing the terminal off between the
|
|
145
|
+
// floating overlay and the docked panel — same storyId, different
|
|
146
|
+
// container — reparents via ensureTerm() without tearing down the
|
|
147
|
+
// connection or clearing the buffer. `suspend` is in the dep array so the
|
|
148
|
+
// OTHER (un-suspending) instance re-runs this effect and reclaims the
|
|
149
|
+
// terminal DOM node when the user navigates away from Orchestration.
|
|
116
150
|
useEffect(() => {
|
|
117
|
-
if (!open || !containerRef.current) return;
|
|
151
|
+
if (suspend || !open || !containerRef.current) return;
|
|
118
152
|
ensureTerm(containerRef.current);
|
|
119
|
-
|
|
120
|
-
if (
|
|
121
|
-
|
|
153
|
+
const isNewSession = storyId && storyId !== _currentStory;
|
|
154
|
+
if (isNewSession) {
|
|
155
|
+
_currentStory = storyId;
|
|
156
|
+
if (_term) _term.clear();
|
|
122
157
|
connectWs(storyId);
|
|
123
158
|
}
|
|
159
|
+
_resize();
|
|
124
160
|
window.addEventListener('resize', _resize);
|
|
125
161
|
return () => window.removeEventListener('resize', _resize);
|
|
126
|
-
}, [open, storyId]);
|
|
162
|
+
}, [open, storyId, suspend]);
|
|
127
163
|
|
|
128
164
|
// Resize when entering/leaving fullscreen or on open
|
|
129
165
|
useEffect(() => {
|
|
130
|
-
if (open) { setTimeout(_resize, 50); }
|
|
131
|
-
}, [open, fullscreen]);
|
|
166
|
+
if (!suspend && open) { setTimeout(_resize, 50); }
|
|
167
|
+
}, [open, fullscreen, suspend]);
|
|
132
168
|
|
|
133
|
-
// Escape key closes
|
|
169
|
+
// Escape key closes (docked panel has no "close" concept — it just shows
|
|
170
|
+
// the empty state when store.terminal is cleared elsewhere)
|
|
134
171
|
useEffect(() => {
|
|
172
|
+
if (suspend || docked) return;
|
|
135
173
|
function onKey(e) {
|
|
136
174
|
if (e.key === 'Escape' && open && !minimized) {
|
|
137
175
|
setState({ terminal: { ...t, open: false } });
|
|
@@ -139,9 +177,11 @@ export function XtermPanel() {
|
|
|
139
177
|
}
|
|
140
178
|
window.addEventListener('keydown', onKey);
|
|
141
179
|
return () => window.removeEventListener('keydown', onKey);
|
|
142
|
-
}, [open, minimized, t]);
|
|
180
|
+
}, [open, minimized, t, suspend, docked]);
|
|
143
181
|
|
|
144
182
|
const dotCls = 'term-status-dot ' + (termStatus || '');
|
|
183
|
+
// Statuses that mean "output is actively streaming" for the docked live pulse.
|
|
184
|
+
const isLive = open && ['running', 'connecting', 'blocked', 'waiting'].includes(termStatus);
|
|
145
185
|
|
|
146
186
|
// ── Actions ──
|
|
147
187
|
const handleMinimize = useCallback(() => {
|
|
@@ -167,6 +207,41 @@ export function XtermPanel() {
|
|
|
167
207
|
setTimeout(_resize, 50);
|
|
168
208
|
}, [t, fullscreen]);
|
|
169
209
|
|
|
210
|
+
// Fully inert while the sibling instance owns the terminal DOM — no
|
|
211
|
+
// backdrop, no panel, no pill, nothing rendered at all.
|
|
212
|
+
if (suspend) return null;
|
|
213
|
+
|
|
214
|
+
// ── Docked render (Orchestration view's right column) ──
|
|
215
|
+
if (docked) {
|
|
216
|
+
return html`
|
|
217
|
+
<div class="orch-term-dock">
|
|
218
|
+
<div class="orch-term-dock-header">
|
|
219
|
+
<span class="orch-term-dot red"></span>
|
|
220
|
+
<span class="orch-term-dot amber"></span>
|
|
221
|
+
<span class="orch-term-dot green"></span>
|
|
222
|
+
<span class="orch-term-dock-label">xterm${open ? ' · ' + title : ''}</span>
|
|
223
|
+
${isLive ? html`
|
|
224
|
+
<span class="orch-term-dock-live">
|
|
225
|
+
<span class="orch-term-dock-live-dot"></span>live
|
|
226
|
+
</span>
|
|
227
|
+
` : null}
|
|
228
|
+
${open ? html`
|
|
229
|
+
<button class="orch-term-dock-stop" onClick=${handleStop} title="End the agent session">Stop</button>
|
|
230
|
+
` : null}
|
|
231
|
+
</div>
|
|
232
|
+
<div class="orch-term-dock-body">
|
|
233
|
+
${open
|
|
234
|
+
? html`<div ref=${containerRef} class="orch-term-dock-container"></div>`
|
|
235
|
+
: html`
|
|
236
|
+
<div class="orch-term-dock-empty">
|
|
237
|
+
No active execution. Select a command from the Runner picker to begin.
|
|
238
|
+
</div>
|
|
239
|
+
`}
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
`;
|
|
243
|
+
}
|
|
244
|
+
|
|
170
245
|
// ── Pill (minimized state) ──
|
|
171
246
|
const pill = html`
|
|
172
247
|
<div
|