@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.
@@ -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" ]] && [[ -f "$PRD_FILE" ]]; then
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 and current slug's prompts (will be regenerated below)
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" ]] && { rm "$f"; (( ++DELETED_COUNT )); }
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
- echo " LOOP_NAME=$SLUG \\"
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"