@atlashub/smartstack-cli 1.2.0 → 1.4.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/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/commands/business-analyse/0-orchestrate.md +640 -0
- package/templates/commands/business-analyse.md +84 -3
- package/templates/commands/ralph-loop/cancel-ralph.md +18 -0
- package/templates/commands/ralph-loop/help.md +126 -0
- package/templates/commands/ralph-loop/ralph-loop.md +18 -0
- package/templates/hooks/hooks.json +10 -0
- package/templates/hooks/stop-hook.sh +177 -0
|
@@ -1,11 +1,46 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Business Analysis - Complete business analysis workflow (BABOK/IEEE 830)
|
|
3
|
+
argument-hint: "<description du besoin>"
|
|
3
4
|
---
|
|
4
5
|
|
|
5
6
|
# Business Analysis - Expert Workflow
|
|
6
7
|
|
|
7
8
|
Senior Business Analyst expert. Complete business analysis without writing code.
|
|
8
9
|
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## MODE AUTOMATIQUE (RECOMMANDE)
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
+==============================================================================+
|
|
16
|
+
| /business-analyse "<description du besoin>" |
|
|
17
|
+
| |
|
|
18
|
+
| ORCHESTRE AUTOMATIQUEMENT TOUT LE WORKFLOW: |
|
|
19
|
+
| ├── 1. Verification MCP SmartStack (alerte si absent) |
|
|
20
|
+
| ├── 2. Analyse du contexte (Application/Module/Granularite) |
|
|
21
|
+
| ├── 3. Definition des integrations (Workflows/Notifs/IA) |
|
|
22
|
+
| ├── 4. Creation prd.json + progress.txt (Ralph Loop ready) |
|
|
23
|
+
| ├── 5. Execution phases 1-7 avec Ralph Loop |
|
|
24
|
+
| ├── 6. Validation utilisateur (gate obligatoire) |
|
|
25
|
+
| ├── 7. Implementation avec Ralph Loop |
|
|
26
|
+
| └── 8. Documentation HTML auto-generee |
|
|
27
|
+
| |
|
|
28
|
+
| RESULTAT: Feature complete en ~30 minutes avec validation |
|
|
29
|
+
+==============================================================================+
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Usage:**
|
|
33
|
+
```bash
|
|
34
|
+
# Mode automatique complet (RECOMMANDE)
|
|
35
|
+
/business-analyse "Je veux gerer les contacts clients avec import/export"
|
|
36
|
+
|
|
37
|
+
# Mode manuel (phases individuelles)
|
|
38
|
+
/business-analyse:1-init
|
|
39
|
+
/business-analyse:2-discover ...
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
9
44
|
## Philosophy
|
|
10
45
|
|
|
11
46
|
```
|
|
@@ -91,7 +126,9 @@ Examples:
|
|
|
91
126
|
|
|
92
127
|
| Phase | Command | Model | Description | Output |
|
|
93
128
|
|-------|----------|-------|-------------|--------|
|
|
94
|
-
|
|
|
129
|
+
| **AUTO** | **`/business-analyse`** | **opus** | **Orchestration complete automatique** | **Feature complete** |
|
|
130
|
+
| 0 | `/business-analyse:0-orchestrate` | opus | Orchestration manuelle avec questions | context.json, prd.json |
|
|
131
|
+
| 0.5 | *Validation* | - | Context business check (automatic) | Block if not business |
|
|
95
132
|
| 1 | `/business-analyse:1-init` | haiku | Initialize project structure + code scan | `config.json`, structure |
|
|
96
133
|
| 2 | `/business-analyse:2-discover` | **opus** | Requirements elicitation (ultrathink) | `1-discovery.md` |
|
|
97
134
|
| 3 | `/business-analyse:3-analyse` | sonnet | Business analysis BRD + doc scan (ultrathink) | `2-business-requirements.md` |
|
|
@@ -552,8 +589,52 @@ The skill is triggered automatically when user asks about:
|
|
|
552
589
|
|
|
553
590
|
## Next
|
|
554
591
|
|
|
555
|
-
|
|
556
|
-
|
|
592
|
+
**Mode automatique (RECOMMANDE):**
|
|
593
|
+
```bash
|
|
594
|
+
/business-analyse "Description de votre besoin"
|
|
557
595
|
```
|
|
596
|
+
|
|
597
|
+
**Mode manuel:**
|
|
598
|
+
```bash
|
|
558
599
|
/business-analyse:1-init
|
|
559
600
|
```
|
|
601
|
+
|
|
602
|
+
---
|
|
603
|
+
|
|
604
|
+
## EXECUTION AUTOMATIQUE
|
|
605
|
+
|
|
606
|
+
Si cette commande est appelee avec un argument (description du besoin):
|
|
607
|
+
|
|
608
|
+
```
|
|
609
|
+
ARGUMENTS = "$ARGUMENTS"
|
|
610
|
+
|
|
611
|
+
SI ARGUMENTS non vide:
|
|
612
|
+
→ Executer /business-analyse:0-orchestrate $ARGUMENTS
|
|
613
|
+
→ Le workflow complet est lance automatiquement
|
|
614
|
+
|
|
615
|
+
SINON:
|
|
616
|
+
→ Afficher ce fichier d'aide
|
|
617
|
+
→ Proposer les options
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
**Lancer le mode automatique maintenant:**
|
|
621
|
+
|
|
622
|
+
```javascript
|
|
623
|
+
if (ARGUMENTS && ARGUMENTS.trim().length > 0) {
|
|
624
|
+
// Mode automatique - lancer l'orchestration
|
|
625
|
+
execute("/business-analyse:0-orchestrate " + ARGUMENTS);
|
|
626
|
+
} else {
|
|
627
|
+
// Mode manuel - afficher l'aide et proposer les options
|
|
628
|
+
AskUserQuestion({
|
|
629
|
+
questions: [{
|
|
630
|
+
question: "Comment souhaitez-vous proceder?",
|
|
631
|
+
header: "Mode",
|
|
632
|
+
options: [
|
|
633
|
+
{ label: "Mode automatique (Recommande)", description: "Orchestration complete avec Ralph Loop" },
|
|
634
|
+
{ label: "Mode manuel", description: "Executer les phases une par une" }
|
|
635
|
+
],
|
|
636
|
+
multiSelect: false
|
|
637
|
+
}]
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Cancel active Ralph Loop"
|
|
3
|
+
allowed-tools: ["Bash(test -f .claude/ralph-loop.local.md:*)", "Bash(rm .claude/ralph-loop.local.md)", "Read(.claude/ralph-loop.local.md)"]
|
|
4
|
+
hide-from-slash-command-tool: "true"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Cancel Ralph
|
|
8
|
+
|
|
9
|
+
To cancel the Ralph loop:
|
|
10
|
+
|
|
11
|
+
1. Check if `.claude/ralph-loop.local.md` exists using Bash: `test -f .claude/ralph-loop.local.md && echo "EXISTS" || echo "NOT_FOUND"`
|
|
12
|
+
|
|
13
|
+
2. **If NOT_FOUND**: Say "No active Ralph loop found."
|
|
14
|
+
|
|
15
|
+
3. **If EXISTS**:
|
|
16
|
+
- Read `.claude/ralph-loop.local.md` to get the current iteration number from the `iteration:` field
|
|
17
|
+
- Remove the file using Bash: `rm .claude/ralph-loop.local.md`
|
|
18
|
+
- Report: "Cancelled Ralph loop (was at iteration N)" where N is the iteration value
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Explain Ralph Loop plugin and available commands"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Ralph Loop Plugin Help
|
|
6
|
+
|
|
7
|
+
Please explain the following to the user:
|
|
8
|
+
|
|
9
|
+
## What is Ralph Loop?
|
|
10
|
+
|
|
11
|
+
Ralph Loop implements the Ralph Wiggum technique - an iterative development methodology based on continuous AI loops, pioneered by Geoffrey Huntley.
|
|
12
|
+
|
|
13
|
+
**Core concept:**
|
|
14
|
+
```bash
|
|
15
|
+
while :; do
|
|
16
|
+
cat PROMPT.md | claude-code --continue
|
|
17
|
+
done
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The same prompt is fed to Claude repeatedly. The "self-referential" aspect comes from Claude seeing its own previous work in the files and git history, not from feeding output back as input.
|
|
21
|
+
|
|
22
|
+
**Each iteration:**
|
|
23
|
+
1. Claude receives the SAME prompt
|
|
24
|
+
2. Works on the task, modifying files
|
|
25
|
+
3. Tries to exit
|
|
26
|
+
4. Stop hook intercepts and feeds the same prompt again
|
|
27
|
+
5. Claude sees its previous work in the files
|
|
28
|
+
6. Iteratively improves until completion
|
|
29
|
+
|
|
30
|
+
The technique is described as "deterministically bad in an undeterministic world" - failures are predictable, enabling systematic improvement through prompt tuning.
|
|
31
|
+
|
|
32
|
+
## Available Commands
|
|
33
|
+
|
|
34
|
+
### /ralph-loop <PROMPT> [OPTIONS]
|
|
35
|
+
|
|
36
|
+
Start a Ralph loop in your current session.
|
|
37
|
+
|
|
38
|
+
**Usage:**
|
|
39
|
+
```
|
|
40
|
+
/ralph-loop "Refactor the cache layer" --max-iterations 20
|
|
41
|
+
/ralph-loop "Add tests" --completion-promise "TESTS COMPLETE"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Options:**
|
|
45
|
+
- `--max-iterations <n>` - Max iterations before auto-stop
|
|
46
|
+
- `--completion-promise <text>` - Promise phrase to signal completion
|
|
47
|
+
|
|
48
|
+
**How it works:**
|
|
49
|
+
1. Creates `.claude/.ralph-loop.local.md` state file
|
|
50
|
+
2. You work on the task
|
|
51
|
+
3. When you try to exit, stop hook intercepts
|
|
52
|
+
4. Same prompt fed back
|
|
53
|
+
5. You see your previous work
|
|
54
|
+
6. Continues until promise detected or max iterations
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### /cancel-ralph
|
|
59
|
+
|
|
60
|
+
Cancel an active Ralph loop (removes the loop state file).
|
|
61
|
+
|
|
62
|
+
**Usage:**
|
|
63
|
+
```
|
|
64
|
+
/cancel-ralph
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**How it works:**
|
|
68
|
+
- Checks for active loop state file
|
|
69
|
+
- Removes `.claude/.ralph-loop.local.md`
|
|
70
|
+
- Reports cancellation with iteration count
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Key Concepts
|
|
75
|
+
|
|
76
|
+
### Completion Promises
|
|
77
|
+
|
|
78
|
+
To signal completion, Claude must output a `<promise>` tag:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
<promise>TASK COMPLETE</promise>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The stop hook looks for this specific tag. Without it (or `--max-iterations`), Ralph runs infinitely.
|
|
85
|
+
|
|
86
|
+
### Self-Reference Mechanism
|
|
87
|
+
|
|
88
|
+
The "loop" doesn't mean Claude talks to itself. It means:
|
|
89
|
+
- Same prompt repeated
|
|
90
|
+
- Claude's work persists in files
|
|
91
|
+
- Each iteration sees previous attempts
|
|
92
|
+
- Builds incrementally toward goal
|
|
93
|
+
|
|
94
|
+
## Example
|
|
95
|
+
|
|
96
|
+
### Interactive Bug Fix
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
/ralph-loop "Fix the token refresh logic in auth.ts. Output <promise>FIXED</promise> when all tests pass." --completion-promise "FIXED" --max-iterations 10
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
You'll see Ralph:
|
|
103
|
+
- Attempt fixes
|
|
104
|
+
- Run tests
|
|
105
|
+
- See failures
|
|
106
|
+
- Iterate on solution
|
|
107
|
+
- In your current session
|
|
108
|
+
|
|
109
|
+
## When to Use Ralph
|
|
110
|
+
|
|
111
|
+
**Good for:**
|
|
112
|
+
- Well-defined tasks with clear success criteria
|
|
113
|
+
- Tasks requiring iteration and refinement
|
|
114
|
+
- Iterative development with self-correction
|
|
115
|
+
- Greenfield projects
|
|
116
|
+
|
|
117
|
+
**Not good for:**
|
|
118
|
+
- Tasks requiring human judgment or design decisions
|
|
119
|
+
- One-shot operations
|
|
120
|
+
- Tasks with unclear success criteria
|
|
121
|
+
- Debugging production issues (use targeted debugging instead)
|
|
122
|
+
|
|
123
|
+
## Learn More
|
|
124
|
+
|
|
125
|
+
- Original technique: https://ghuntley.com/ralph/
|
|
126
|
+
- Ralph Orchestrator: https://github.com/mikeyobrien/ralph-orchestrator
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Start Ralph Loop in current session"
|
|
3
|
+
argument-hint: "PROMPT [--max-iterations N] [--completion-promise TEXT]"
|
|
4
|
+
allowed-tools: ["Bash(${CLAUDE_PLUGIN_ROOT}/scripts/setup-ralph-loop.sh:*)"]
|
|
5
|
+
hide-from-slash-command-tool: "true"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Ralph Loop Command
|
|
9
|
+
|
|
10
|
+
Execute the setup script to initialize the Ralph loop:
|
|
11
|
+
|
|
12
|
+
```!
|
|
13
|
+
"${CLAUDE_PLUGIN_ROOT}/scripts/setup-ralph-loop.sh" $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Please work on the task. When you try to exit, the Ralph loop will feed the SAME PROMPT back to you for the next iteration. You'll see your previous work in files and git history, allowing you to iterate and improve.
|
|
17
|
+
|
|
18
|
+
CRITICAL RULE: If a completion promise is set, you may ONLY output it when the statement is completely and unequivocally TRUE. Do not output false promises to escape the loop, even if you think you're stuck or should exit for other reasons. The loop is designed to continue until genuine completion.
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Ralph Loop Stop Hook
|
|
4
|
+
# Prevents session exit when a ralph-loop is active
|
|
5
|
+
# Feeds Claude's output back as input to continue the loop
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
# Read hook input from stdin (advanced stop hook API)
|
|
10
|
+
HOOK_INPUT=$(cat)
|
|
11
|
+
|
|
12
|
+
# Check if ralph-loop is active
|
|
13
|
+
RALPH_STATE_FILE=".claude/ralph-loop.local.md"
|
|
14
|
+
|
|
15
|
+
if [[ ! -f "$RALPH_STATE_FILE" ]]; then
|
|
16
|
+
# No active loop - allow exit
|
|
17
|
+
exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Parse markdown frontmatter (YAML between ---) and extract values
|
|
21
|
+
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$RALPH_STATE_FILE")
|
|
22
|
+
ITERATION=$(echo "$FRONTMATTER" | grep '^iteration:' | sed 's/iteration: *//')
|
|
23
|
+
MAX_ITERATIONS=$(echo "$FRONTMATTER" | grep '^max_iterations:' | sed 's/max_iterations: *//')
|
|
24
|
+
# Extract completion_promise and strip surrounding quotes if present
|
|
25
|
+
COMPLETION_PROMISE=$(echo "$FRONTMATTER" | grep '^completion_promise:' | sed 's/completion_promise: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
26
|
+
|
|
27
|
+
# Validate numeric fields before arithmetic operations
|
|
28
|
+
if [[ ! "$ITERATION" =~ ^[0-9]+$ ]]; then
|
|
29
|
+
echo "⚠️ Ralph loop: State file corrupted" >&2
|
|
30
|
+
echo " File: $RALPH_STATE_FILE" >&2
|
|
31
|
+
echo " Problem: 'iteration' field is not a valid number (got: '$ITERATION')" >&2
|
|
32
|
+
echo "" >&2
|
|
33
|
+
echo " This usually means the state file was manually edited or corrupted." >&2
|
|
34
|
+
echo " Ralph loop is stopping. Run /ralph-loop again to start fresh." >&2
|
|
35
|
+
rm "$RALPH_STATE_FILE"
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
if [[ ! "$MAX_ITERATIONS" =~ ^[0-9]+$ ]]; then
|
|
40
|
+
echo "⚠️ Ralph loop: State file corrupted" >&2
|
|
41
|
+
echo " File: $RALPH_STATE_FILE" >&2
|
|
42
|
+
echo " Problem: 'max_iterations' field is not a valid number (got: '$MAX_ITERATIONS')" >&2
|
|
43
|
+
echo "" >&2
|
|
44
|
+
echo " This usually means the state file was manually edited or corrupted." >&2
|
|
45
|
+
echo " Ralph loop is stopping. Run /ralph-loop again to start fresh." >&2
|
|
46
|
+
rm "$RALPH_STATE_FILE"
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Check if max iterations reached
|
|
51
|
+
if [[ $MAX_ITERATIONS -gt 0 ]] && [[ $ITERATION -ge $MAX_ITERATIONS ]]; then
|
|
52
|
+
echo "🛑 Ralph loop: Max iterations ($MAX_ITERATIONS) reached."
|
|
53
|
+
rm "$RALPH_STATE_FILE"
|
|
54
|
+
exit 0
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Get transcript path from hook input
|
|
58
|
+
TRANSCRIPT_PATH=$(echo "$HOOK_INPUT" | jq -r '.transcript_path')
|
|
59
|
+
|
|
60
|
+
if [[ ! -f "$TRANSCRIPT_PATH" ]]; then
|
|
61
|
+
echo "⚠️ Ralph loop: Transcript file not found" >&2
|
|
62
|
+
echo " Expected: $TRANSCRIPT_PATH" >&2
|
|
63
|
+
echo " This is unusual and may indicate a Claude Code internal issue." >&2
|
|
64
|
+
echo " Ralph loop is stopping." >&2
|
|
65
|
+
rm "$RALPH_STATE_FILE"
|
|
66
|
+
exit 0
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# Read last assistant message from transcript (JSONL format - one JSON per line)
|
|
70
|
+
# First check if there are any assistant messages
|
|
71
|
+
if ! grep -q '"role":"assistant"' "$TRANSCRIPT_PATH"; then
|
|
72
|
+
echo "⚠️ Ralph loop: No assistant messages found in transcript" >&2
|
|
73
|
+
echo " Transcript: $TRANSCRIPT_PATH" >&2
|
|
74
|
+
echo " This is unusual and may indicate a transcript format issue" >&2
|
|
75
|
+
echo " Ralph loop is stopping." >&2
|
|
76
|
+
rm "$RALPH_STATE_FILE"
|
|
77
|
+
exit 0
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# Extract last assistant message with explicit error handling
|
|
81
|
+
LAST_LINE=$(grep '"role":"assistant"' "$TRANSCRIPT_PATH" | tail -1)
|
|
82
|
+
if [[ -z "$LAST_LINE" ]]; then
|
|
83
|
+
echo "⚠️ Ralph loop: Failed to extract last assistant message" >&2
|
|
84
|
+
echo " Ralph loop is stopping." >&2
|
|
85
|
+
rm "$RALPH_STATE_FILE"
|
|
86
|
+
exit 0
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Parse JSON with error handling
|
|
90
|
+
LAST_OUTPUT=$(echo "$LAST_LINE" | jq -r '
|
|
91
|
+
.message.content |
|
|
92
|
+
map(select(.type == "text")) |
|
|
93
|
+
map(.text) |
|
|
94
|
+
join("\n")
|
|
95
|
+
' 2>&1)
|
|
96
|
+
|
|
97
|
+
# Check if jq succeeded
|
|
98
|
+
if [[ $? -ne 0 ]]; then
|
|
99
|
+
echo "⚠️ Ralph loop: Failed to parse assistant message JSON" >&2
|
|
100
|
+
echo " Error: $LAST_OUTPUT" >&2
|
|
101
|
+
echo " This may indicate a transcript format issue" >&2
|
|
102
|
+
echo " Ralph loop is stopping." >&2
|
|
103
|
+
rm "$RALPH_STATE_FILE"
|
|
104
|
+
exit 0
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
if [[ -z "$LAST_OUTPUT" ]]; then
|
|
108
|
+
echo "⚠️ Ralph loop: Assistant message contained no text content" >&2
|
|
109
|
+
echo " Ralph loop is stopping." >&2
|
|
110
|
+
rm "$RALPH_STATE_FILE"
|
|
111
|
+
exit 0
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Check for completion promise (only if set)
|
|
115
|
+
if [[ "$COMPLETION_PROMISE" != "null" ]] && [[ -n "$COMPLETION_PROMISE" ]]; then
|
|
116
|
+
# Extract text from <promise> tags using Perl for multiline support
|
|
117
|
+
# -0777 slurps entire input, s flag makes . match newlines
|
|
118
|
+
# .*? is non-greedy (takes FIRST tag), whitespace normalized
|
|
119
|
+
PROMISE_TEXT=$(echo "$LAST_OUTPUT" | perl -0777 -pe 's/.*?<promise>(.*?)<\/promise>.*/$1/s; s/^\s+|\s+$//g; s/\s+/ /g' 2>/dev/null || echo "")
|
|
120
|
+
|
|
121
|
+
# Use = for literal string comparison (not pattern matching)
|
|
122
|
+
# == in [[ ]] does glob pattern matching which breaks with *, ?, [ characters
|
|
123
|
+
if [[ -n "$PROMISE_TEXT" ]] && [[ "$PROMISE_TEXT" = "$COMPLETION_PROMISE" ]]; then
|
|
124
|
+
echo "✅ Ralph loop: Detected <promise>$COMPLETION_PROMISE</promise>"
|
|
125
|
+
rm "$RALPH_STATE_FILE"
|
|
126
|
+
exit 0
|
|
127
|
+
fi
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# Not complete - continue loop with SAME PROMPT
|
|
131
|
+
NEXT_ITERATION=$((ITERATION + 1))
|
|
132
|
+
|
|
133
|
+
# Extract prompt (everything after the closing ---)
|
|
134
|
+
# Skip first --- line, skip until second --- line, then print everything after
|
|
135
|
+
# Use i>=2 instead of i==2 to handle --- in prompt content
|
|
136
|
+
PROMPT_TEXT=$(awk '/^---$/{i++; next} i>=2' "$RALPH_STATE_FILE")
|
|
137
|
+
|
|
138
|
+
if [[ -z "$PROMPT_TEXT" ]]; then
|
|
139
|
+
echo "⚠️ Ralph loop: State file corrupted or incomplete" >&2
|
|
140
|
+
echo " File: $RALPH_STATE_FILE" >&2
|
|
141
|
+
echo " Problem: No prompt text found" >&2
|
|
142
|
+
echo "" >&2
|
|
143
|
+
echo " This usually means:" >&2
|
|
144
|
+
echo " • State file was manually edited" >&2
|
|
145
|
+
echo " • File was corrupted during writing" >&2
|
|
146
|
+
echo "" >&2
|
|
147
|
+
echo " Ralph loop is stopping. Run /ralph-loop again to start fresh." >&2
|
|
148
|
+
rm "$RALPH_STATE_FILE"
|
|
149
|
+
exit 0
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
# Update iteration in frontmatter (portable across macOS and Linux)
|
|
153
|
+
# Create temp file, then atomically replace
|
|
154
|
+
TEMP_FILE="${RALPH_STATE_FILE}.tmp.$$"
|
|
155
|
+
sed "s/^iteration: .*/iteration: $NEXT_ITERATION/" "$RALPH_STATE_FILE" > "$TEMP_FILE"
|
|
156
|
+
mv "$TEMP_FILE" "$RALPH_STATE_FILE"
|
|
157
|
+
|
|
158
|
+
# Build system message with iteration count and completion promise info
|
|
159
|
+
if [[ "$COMPLETION_PROMISE" != "null" ]] && [[ -n "$COMPLETION_PROMISE" ]]; then
|
|
160
|
+
SYSTEM_MSG="🔄 Ralph iteration $NEXT_ITERATION | To stop: output <promise>$COMPLETION_PROMISE</promise> (ONLY when statement is TRUE - do not lie to exit!)"
|
|
161
|
+
else
|
|
162
|
+
SYSTEM_MSG="🔄 Ralph iteration $NEXT_ITERATION | No completion promise set - loop runs infinitely"
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# Output JSON to block the stop and feed prompt back
|
|
166
|
+
# The "reason" field contains the prompt that will be sent back to Claude
|
|
167
|
+
jq -n \
|
|
168
|
+
--arg prompt "$PROMPT_TEXT" \
|
|
169
|
+
--arg msg "$SYSTEM_MSG" \
|
|
170
|
+
'{
|
|
171
|
+
"decision": "block",
|
|
172
|
+
"reason": $prompt,
|
|
173
|
+
"systemMessage": $msg
|
|
174
|
+
}'
|
|
175
|
+
|
|
176
|
+
# Exit 0 for successful hook execution
|
|
177
|
+
exit 0
|