@ai-dev-methodologies/rlp-desk 0.4.0 → 0.5.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.
- package/README.md +145 -69
- package/docs/plans/cozy-gliding-trinket.md +53 -0
- package/docs/plans/keen-sauteeing-snowflake.md +245 -0
- package/docs/plans/toasty-whistling-diffie-agent-a6814625642e956da.md +201 -0
- package/docs/plans/toasty-whistling-diffie.md +117 -0
- package/docs/prompts/ralplan-codex-review.md +1 -1
- package/install.sh +5 -0
- package/package.json +1 -1
- package/scripts/postinstall.js +5 -0
- package/scripts/uninstall.js +1 -0
- package/src/commands/rlp-desk.md +193 -51
- package/src/governance.md +28 -10
- package/src/model-upgrade-table.md +50 -0
- package/src/scripts/init_ralph_desk.zsh +200 -19
- package/src/scripts/lib_ralph_desk.zsh +838 -0
- package/src/scripts/run_ralph_desk.zsh +821 -608
|
@@ -78,6 +78,138 @@ version_file() {
|
|
|
78
78
|
# Non-existent files silently skipped (no error)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
# --- PRD/test-spec per-US splitting helpers ---
|
|
82
|
+
|
|
83
|
+
split_prd_by_us() {
|
|
84
|
+
local prd_file="$1"
|
|
85
|
+
local slug="$2"
|
|
86
|
+
local plans_dir
|
|
87
|
+
plans_dir="$(dirname "$prd_file")"
|
|
88
|
+
|
|
89
|
+
[[ -f "$prd_file" ]] || return 0
|
|
90
|
+
|
|
91
|
+
local us_count
|
|
92
|
+
us_count=$(grep -c "^### US-" "$prd_file" 2>/dev/null) || us_count=0
|
|
93
|
+
if [[ "$us_count" -eq 0 ]]; then
|
|
94
|
+
echo " WARNING: No US markers (### US-NNN:) found in PRD — falling back to full PRD injection" >&2
|
|
95
|
+
# Clean up any stale per-US split files from previous runs to prevent stale artifacts
|
|
96
|
+
local stale_count=0
|
|
97
|
+
for stale in "$plans_dir"/prd-"$slug"-US-*.md(N); do
|
|
98
|
+
rm "$stale"; stale_count=$(( stale_count + 1 ))
|
|
99
|
+
done
|
|
100
|
+
[[ $stale_count -gt 0 ]] && echo " Cleaned $stale_count stale prd per-US file(s)"
|
|
101
|
+
return 0
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
awk -v dir="$plans_dir" -v slug="$slug" '
|
|
105
|
+
/^### US-[0-9]+:/ {
|
|
106
|
+
if (out != "") close(out)
|
|
107
|
+
match($0, /US-[0-9]+/)
|
|
108
|
+
us_id = substr($0, RSTART, RLENGTH)
|
|
109
|
+
out = dir "/prd-" slug "-" us_id ".md"
|
|
110
|
+
}
|
|
111
|
+
out != "" { print > out }
|
|
112
|
+
' "$prd_file"
|
|
113
|
+
|
|
114
|
+
local count
|
|
115
|
+
count=$(ls "$plans_dir"/prd-"$slug"-US-*.md 2>/dev/null | wc -l | tr -d ' ')
|
|
116
|
+
echo " Split PRD: $count per-US files"
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
split_test_spec_by_us() {
|
|
120
|
+
local ts_file="$1"
|
|
121
|
+
local slug="$2"
|
|
122
|
+
local plans_dir
|
|
123
|
+
plans_dir="$(dirname "$ts_file")"
|
|
124
|
+
|
|
125
|
+
[[ -f "$ts_file" ]] || return 0
|
|
126
|
+
|
|
127
|
+
local us_count
|
|
128
|
+
us_count=$(grep -c "^## US-" "$ts_file" 2>/dev/null) || us_count=0
|
|
129
|
+
if [[ "$us_count" -eq 0 ]]; then
|
|
130
|
+
echo " WARNING: No US section markers (## US-NNN:) in test-spec — skipping split" >&2
|
|
131
|
+
# Clean up any stale per-US test-spec files from previous runs
|
|
132
|
+
for stale in "$plans_dir"/test-spec-"$slug"-US-*.md(N); do
|
|
133
|
+
rm "$stale"
|
|
134
|
+
done
|
|
135
|
+
return 0
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
# Extract global header (everything before first ## US- section, e.g. Verification Commands)
|
|
139
|
+
local header_tmp="${plans_dir}/test-spec-${slug}-header.tmp.$$"
|
|
140
|
+
awk '/^## US-[0-9]+:/{exit} {print}' "$ts_file" > "$header_tmp"
|
|
141
|
+
|
|
142
|
+
awk -v dir="$plans_dir" -v slug="$slug" '
|
|
143
|
+
/^## US-[0-9]+:/ {
|
|
144
|
+
if (out != "") close(out)
|
|
145
|
+
match($0, /US-[0-9]+/)
|
|
146
|
+
us_id = substr($0, RSTART, RLENGTH)
|
|
147
|
+
out = dir "/test-spec-" slug "-" us_id ".md"
|
|
148
|
+
}
|
|
149
|
+
out != "" { print > out }
|
|
150
|
+
' "$ts_file"
|
|
151
|
+
|
|
152
|
+
# Prepend global header (Verification Commands etc.) to each split file
|
|
153
|
+
for split_file in "$plans_dir"/test-spec-"$slug"-US-*.md; do
|
|
154
|
+
[[ -f "$split_file" ]] || continue
|
|
155
|
+
local tmp="${split_file}.tmp.$$"
|
|
156
|
+
cat "$header_tmp" "$split_file" > "$tmp" && mv "$tmp" "$split_file"
|
|
157
|
+
done
|
|
158
|
+
rm -f "$header_tmp"
|
|
159
|
+
|
|
160
|
+
local count
|
|
161
|
+
count=$(ls "$plans_dir"/test-spec-"$slug"-US-*.md 2>/dev/null | wc -l | tr -d ' ')
|
|
162
|
+
echo " Split test-spec: $count per-US files (with global header)"
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
# --- Run command presets ---
|
|
166
|
+
# Detects codex CLI availability and shows appropriate run command presets.
|
|
167
|
+
# AC1: codex installed → cross-engine preset first, spark Pro, claude-only, basic
|
|
168
|
+
# AC2: codex not installed → tmux + claude-only first, install recommendation
|
|
169
|
+
# AC3: full options reference with defaults always shown
|
|
170
|
+
print_run_presets() {
|
|
171
|
+
local slug="$1"
|
|
172
|
+
local codex_available=0
|
|
173
|
+
command -v codex &>/dev/null && codex_available=1
|
|
174
|
+
|
|
175
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
176
|
+
echo "Available run commands (copy the one you want):"
|
|
177
|
+
echo ""
|
|
178
|
+
if [[ $codex_available -eq 1 ]]; then
|
|
179
|
+
echo "# Recommended: cross-engine + final-consensus (cost savings + blind-spot coverage):"
|
|
180
|
+
echo "/rlp-desk run $slug --worker-model gpt-5.4:high --final-consensus --debug"
|
|
181
|
+
echo ""
|
|
182
|
+
echo "# Spark Pro preset (fast codex worker, lower cost):"
|
|
183
|
+
echo "/rlp-desk run $slug --worker-model gpt-5.3-codex-spark:high --debug"
|
|
184
|
+
echo ""
|
|
185
|
+
echo "# Claude-only:"
|
|
186
|
+
echo "/rlp-desk run $slug --debug"
|
|
187
|
+
echo ""
|
|
188
|
+
echo "# Basic agent:"
|
|
189
|
+
echo "/rlp-desk run $slug"
|
|
190
|
+
else
|
|
191
|
+
echo "# Recommended: tmux mode + claude-only (real-time visibility):"
|
|
192
|
+
echo "/rlp-desk run $slug --mode tmux --debug"
|
|
193
|
+
echo ""
|
|
194
|
+
echo "# Agent mode:"
|
|
195
|
+
echo "/rlp-desk run $slug --debug"
|
|
196
|
+
echo ""
|
|
197
|
+
echo "# Install codex for cost savings + cross-engine blind-spot coverage:"
|
|
198
|
+
echo "npm install -g @openai/codex"
|
|
199
|
+
fi
|
|
200
|
+
echo ""
|
|
201
|
+
echo "# Full options reference:"
|
|
202
|
+
echo "# --mode agent|tmux (default: agent)"
|
|
203
|
+
echo "# --worker-model MODEL haiku|sonnet|opus or gpt-5.4:low|medium|high (default: sonnet)"
|
|
204
|
+
echo "# --verifier-model MODEL haiku|sonnet|opus (default: opus)"
|
|
205
|
+
echo "# --verify-consensus both claude+codex must pass"
|
|
206
|
+
echo "# --verify-mode per-us|batch (default: per-us)"
|
|
207
|
+
echo "# --max-iter N (default: 100)"
|
|
208
|
+
echo "# --debug enable debug logging"
|
|
209
|
+
echo "# --with-self-verification post-campaign analysis report"
|
|
210
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
211
|
+
}
|
|
212
|
+
|
|
81
213
|
echo "Initializing Ralph Desk: $SLUG"
|
|
82
214
|
echo " Root: $ROOT"
|
|
83
215
|
echo " Desk: $DESK"
|
|
@@ -90,7 +222,7 @@ mkdir -p "$DESK/prompts" "$DESK/context" "$DESK/memos" "$DESK/plans" "$DESK/logs
|
|
|
90
222
|
PRD_FILE="$DESK/plans/prd-$SLUG.md"
|
|
91
223
|
LOGS_DIR="$DESK/logs/$SLUG"
|
|
92
224
|
|
|
93
|
-
if [[ -n "$MODE" ]]
|
|
225
|
+
if [[ -n "$MODE" ]]; then
|
|
94
226
|
echo "Re-execution mode: --mode $MODE"
|
|
95
227
|
echo ""
|
|
96
228
|
|
|
@@ -116,16 +248,20 @@ if [[ -n "$MODE" ]] && [[ -f "$PRD_FILE" ]]; then
|
|
|
116
248
|
done
|
|
117
249
|
|
|
118
250
|
# Delete status.json, baseline.log, cost-log.jsonl
|
|
119
|
-
for f in "$LOGS_DIR/status.json" "$LOGS_DIR/baseline.log" "$LOGS_DIR/cost-log.jsonl"; do
|
|
251
|
+
for f in "$LOGS_DIR/runtime/status.json" "$LOGS_DIR/status.json" "$LOGS_DIR/baseline.log" "$LOGS_DIR/cost-log.jsonl"; do
|
|
120
252
|
[[ -f "$f" ]] && { rm "$f"; (( ++DELETED_COUNT )); }
|
|
121
253
|
done
|
|
122
254
|
|
|
123
|
-
# Delete test-spec
|
|
255
|
+
# Delete test-spec only for fresh re-execution mode; improve preserves custom edits
|
|
256
|
+
# and reruns split logic on the existing file.
|
|
124
257
|
for f in \
|
|
125
258
|
"$DESK/plans/test-spec-$SLUG.md" \
|
|
126
259
|
"$DESK/prompts/$SLUG.worker.prompt.md" \
|
|
127
260
|
"$DESK/prompts/$SLUG.verifier.prompt.md"; do
|
|
128
|
-
[[ -f "$f" ]] &&
|
|
261
|
+
[[ -f "$f" ]] &&
|
|
262
|
+
if [[ "$MODE" == "fresh" ]] || [[ "$f" != "$DESK/plans/test-spec-$SLUG.md" ]]; then
|
|
263
|
+
rm "$f"; (( ++DELETED_COUNT ));
|
|
264
|
+
fi
|
|
129
265
|
done
|
|
130
266
|
|
|
131
267
|
# Reset memory and context to fresh templates (rm here; scaffold below regenerates them)
|
|
@@ -144,12 +280,6 @@ if [[ -n "$MODE" ]] && [[ -f "$PRD_FILE" ]]; then
|
|
|
144
280
|
echo " Deleted: $DELETED_COUNT runtime artifacts"
|
|
145
281
|
echo " Reset: memory.md + context.md (regenerating from templates)"
|
|
146
282
|
echo ""
|
|
147
|
-
|
|
148
|
-
elif [[ -n "$MODE" ]] && [[ ! -f "$PRD_FILE" ]]; then
|
|
149
|
-
# Note: --mode provided but no PRD found for this slug — treating as first run
|
|
150
|
-
echo " Note: --mode $MODE provided but no PRD found for '$SLUG' — treating as first run."
|
|
151
|
-
echo ""
|
|
152
|
-
MODE=""
|
|
153
283
|
fi
|
|
154
284
|
|
|
155
285
|
# --- Worker Prompt ---
|
|
@@ -193,6 +323,7 @@ Read these files in order:
|
|
|
193
323
|
- Do not say "existing code has no tests" — you are improving it, add tests.
|
|
194
324
|
- Do not write code before tests — if you did, delete it and start with tests.
|
|
195
325
|
- **NEVER modify rlp-desk infrastructure files** (~/.claude/ralph-desk/*, ~/.claude/commands/rlp-desk.md). If you discover a bug in rlp-desk itself, report it in done-claim.json with {"status": "blocked", "reason": "rlp-desk bug: <description>"} and signal blocked. Do NOT attempt to fix rlp-desk — it is the orchestration tool, not your project code.
|
|
326
|
+
- **NEVER modify Claude Code settings** (~/.claude/settings.json, .claude/settings.local.json, or any settings files). Do NOT add permissions, change models, or alter configuration. If a permission prompt blocks you, report it as blocked — do NOT try to edit settings to bypass it.
|
|
196
327
|
|
|
197
328
|
## Iteration rules
|
|
198
329
|
- Use fresh context only; do NOT depend on prior chat history.
|
|
@@ -298,6 +429,10 @@ Check the iter-signal.json "us_id" field:
|
|
|
298
429
|
- Test-specific logic: no environment-detection patterns
|
|
299
430
|
- "Code inspection" claims: Worker must run actual commands
|
|
300
431
|
- Tautological tests: expected values that mirror implementation logic
|
|
432
|
+
10¼. **Anti-Rubber-Stamp Self-Check**:
|
|
433
|
+
- If your verdict history shows a 100% pass rate, re-examine your last verdict with increased scrutiny — a 100% pass rate is a red flag for insufficient rigor
|
|
434
|
+
- When issuing PASS with explicit warning: note any concerning patterns (e.g., low test diversity, marginal coverage) even if technically passing
|
|
435
|
+
- Never issue a silent PASS — every pass verdict must cite specific evidence for each AC checked
|
|
301
436
|
10½. **Worker Process Audit**:
|
|
302
437
|
- Test-first compliance: done-claim execution_steps must show write_test step before implement step for each AC
|
|
303
438
|
- RED phase evidence: at least one verify_red step with exit_code=1 per AC (proves tests were written before passing)
|
|
@@ -433,6 +568,9 @@ EOF
|
|
|
433
568
|
echo " + $F"
|
|
434
569
|
else echo " · $F"; fi
|
|
435
570
|
|
|
571
|
+
# Split PRD into per-US files (no-op with warning if no US markers)
|
|
572
|
+
split_prd_by_us "$DESK/plans/prd-$SLUG.md" "$SLUG"
|
|
573
|
+
|
|
436
574
|
# --- Test Spec ---
|
|
437
575
|
F="$DESK/plans/test-spec-$SLUG.md"
|
|
438
576
|
if [[ ! -f "$F" ]]; then
|
|
@@ -586,6 +724,9 @@ EOF
|
|
|
586
724
|
echo " + $F"
|
|
587
725
|
else echo " · $F"; fi
|
|
588
726
|
|
|
727
|
+
# Split test-spec into per-US files (no-op with warning if no US section markers)
|
|
728
|
+
split_test_spec_by_us "$DESK/plans/test-spec-$SLUG.md" "$SLUG"
|
|
729
|
+
|
|
589
730
|
# --- .gitignore for runtime artifacts ---
|
|
590
731
|
GITIGNORE="$ROOT/.gitignore"
|
|
591
732
|
MARKER="# RLP Desk runtime artifacts"
|
|
@@ -608,6 +749,53 @@ GIEOF
|
|
|
608
749
|
echo " + .gitignore (created with rlp-desk rules)"
|
|
609
750
|
fi
|
|
610
751
|
|
|
752
|
+
# --- Claude Code sensitive-file permissions for .claude/ralph-desk/ ---
|
|
753
|
+
# Worker/Verifier need Read/Edit/Write access to .claude/ralph-desk/ files.
|
|
754
|
+
# --dangerously-skip-permissions does NOT cover "sensitive file" access for .claude/ paths.
|
|
755
|
+
# Without these, every file operation triggers an interactive permission prompt that blocks automation.
|
|
756
|
+
SETTINGS_FILE="$ROOT/.claude/settings.local.json"
|
|
757
|
+
PERM_MARKER="Read(.claude/ralph-desk/**)"
|
|
758
|
+
|
|
759
|
+
if [[ -f "$SETTINGS_FILE" ]] && grep -qF "$PERM_MARKER" "$SETTINGS_FILE" 2>/dev/null; then
|
|
760
|
+
echo " · .claude/settings.local.json (rlp-desk permissions already present)"
|
|
761
|
+
else
|
|
762
|
+
PERMS='["Read(.claude/ralph-desk/**)", "Edit(.claude/ralph-desk/**)", "Write(.claude/ralph-desk/**)"]'
|
|
763
|
+
|
|
764
|
+
if [[ -f "$SETTINGS_FILE" ]]; then
|
|
765
|
+
if command -v jq &>/dev/null; then
|
|
766
|
+
jq --argjson perms "$PERMS" '
|
|
767
|
+
.permissions //= {} |
|
|
768
|
+
.permissions.allow //= [] |
|
|
769
|
+
.permissions.allow += ($perms - .permissions.allow)
|
|
770
|
+
' "$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" && mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE"
|
|
771
|
+
echo " + .claude/settings.local.json (rlp-desk permissions merged)"
|
|
772
|
+
else
|
|
773
|
+
echo " ⚠ jq not found. Add to .claude/settings.local.json manually:"
|
|
774
|
+
echo " permissions.allow: Read/Edit/Write(.claude/ralph-desk/**)"
|
|
775
|
+
fi
|
|
776
|
+
else
|
|
777
|
+
mkdir -p "$(dirname "$SETTINGS_FILE")"
|
|
778
|
+
cat > "$SETTINGS_FILE" <<'SETEOF'
|
|
779
|
+
{
|
|
780
|
+
"permissions": {
|
|
781
|
+
"allow": [
|
|
782
|
+
"Read(.claude/ralph-desk/**)",
|
|
783
|
+
"Edit(.claude/ralph-desk/**)",
|
|
784
|
+
"Write(.claude/ralph-desk/**)"
|
|
785
|
+
]
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
SETEOF
|
|
789
|
+
echo " + .claude/settings.local.json (created with rlp-desk permissions)"
|
|
790
|
+
fi
|
|
791
|
+
echo ""
|
|
792
|
+
echo " NOTE: Added Read/Edit/Write permissions for .claude/ralph-desk/ to"
|
|
793
|
+
echo " .claude/settings.local.json (local, not committed to git)."
|
|
794
|
+
echo " This prevents Worker/Verifier from being blocked by Claude Code's"
|
|
795
|
+
echo " sensitive-file prompts during automated loop execution."
|
|
796
|
+
echo " See: https://github.com/ai-dev-methodologies/rlp-desk#project-structure"
|
|
797
|
+
fi
|
|
798
|
+
|
|
611
799
|
# --- Post-init validation gate ---
|
|
612
800
|
INIT_FAIL=0
|
|
613
801
|
for REQUIRED_FILE in \
|
|
@@ -636,13 +824,6 @@ echo ""
|
|
|
636
824
|
echo "Next:"
|
|
637
825
|
echo " 1. Edit PRD: $DESK/plans/prd-$SLUG.md"
|
|
638
826
|
echo " 2. Edit test spec: $DESK/plans/test-spec-$SLUG.md"
|
|
639
|
-
echo " 3. Run:"
|
|
827
|
+
echo " 3. Run (copy a command below):"
|
|
640
828
|
echo ""
|
|
641
|
-
|
|
642
|
-
echo " PROMPT_FILE=$DESK/prompts/$SLUG.worker.prompt.md \\"
|
|
643
|
-
echo " VERIFIER_PROMPT_FILE=$DESK/prompts/$SLUG.verifier.prompt.md \\"
|
|
644
|
-
echo " CONTEXT_FILE=$DESK/context/$SLUG-latest.md \\"
|
|
645
|
-
echo " EXTRA_REQUIRED_FILES=$DESK/plans/prd-$SLUG.md:$DESK/plans/test-spec-$SLUG.md:$DESK/memos/$SLUG-memory.md \\"
|
|
646
|
-
echo " MAX_ITER=20 \\"
|
|
647
|
-
echo " $RUNNER_DIR/run_ralph_desk.zsh"
|
|
648
|
-
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
829
|
+
print_run_presets "$SLUG"
|