@ai-dev-methodologies/rlp-desk 0.0.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/LICENSE +21 -0
- package/README.md +182 -0
- package/docs/architecture.md +129 -0
- package/docs/getting-started.md +153 -0
- package/docs/protocol-reference.md +220 -0
- package/examples/calculator/.claude/ralph-desk/plans/prd-loop-test.md +37 -0
- package/examples/calculator/.claude/ralph-desk/plans/test-spec-loop-test.md +29 -0
- package/examples/calculator/.claude/ralph-desk/prompts/loop-test.verifier.prompt.md +29 -0
- package/examples/calculator/.claude/ralph-desk/prompts/loop-test.worker.prompt.md +32 -0
- package/install.sh +53 -0
- package/package.json +40 -0
- package/scripts/postinstall.js +48 -0
- package/scripts/uninstall.js +45 -0
- package/src/commands/rlp-desk.md +164 -0
- package/src/governance.md +170 -0
- package/src/scripts/init_ralph_desk.zsh +245 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# PRD: loop-test
|
|
2
|
+
|
|
3
|
+
## Objective
|
|
4
|
+
Implement a Python calculator module: calc.py + test_calc.py
|
|
5
|
+
|
|
6
|
+
## User Stories
|
|
7
|
+
|
|
8
|
+
### US-001: calc.py — Basic Operations
|
|
9
|
+
- **Priority**: P0
|
|
10
|
+
- **Acceptance Criteria**:
|
|
11
|
+
- [ ] calc.py exists at the project root
|
|
12
|
+
- [ ] Implements add(a, b), subtract(a, b), multiply(a, b), divide(a, b)
|
|
13
|
+
- [ ] divide(a, 0) raises ValueError
|
|
14
|
+
- [ ] All functions have type hints: (a: float, b: float) -> float
|
|
15
|
+
- **Status**: not started
|
|
16
|
+
|
|
17
|
+
### US-002: test_calc.py — Tests
|
|
18
|
+
- **Priority**: P0
|
|
19
|
+
- **Acceptance Criteria**:
|
|
20
|
+
- [ ] test_calc.py exists at the project root
|
|
21
|
+
- [ ] Uses pytest (import pytest)
|
|
22
|
+
- [ ] At least 2 test cases per function (8+ total)
|
|
23
|
+
- [ ] Includes divide-by-zero test (pytest.raises)
|
|
24
|
+
- [ ] python3 -m pytest test_calc.py -v → ALL PASSED
|
|
25
|
+
- **Status**: not started
|
|
26
|
+
|
|
27
|
+
## Non-Goals
|
|
28
|
+
- CLI interface, complex math operations
|
|
29
|
+
|
|
30
|
+
## Technical Constraints
|
|
31
|
+
- Python 3 standard library + pytest only
|
|
32
|
+
- Work on only one story per iteration
|
|
33
|
+
|
|
34
|
+
## Done When
|
|
35
|
+
- US-001 and US-002 acceptance criteria all pass
|
|
36
|
+
- python3 -m pytest test_calc.py -v → ALL PASSED
|
|
37
|
+
- Independent verifier confirms
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Test Specification: loop-test
|
|
2
|
+
|
|
3
|
+
## Verification Commands
|
|
4
|
+
### Test
|
|
5
|
+
```bash
|
|
6
|
+
python3 -m pytest test_calc.py -v
|
|
7
|
+
```
|
|
8
|
+
### Type hint check
|
|
9
|
+
```bash
|
|
10
|
+
grep -c "def.*float.*float.*float" calc.py
|
|
11
|
+
```
|
|
12
|
+
### Divide by zero
|
|
13
|
+
```bash
|
|
14
|
+
python3 -c "from calc import divide; divide(1, 0)"
|
|
15
|
+
# must raise ValueError
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Criteria → Verification Mapping
|
|
19
|
+
| Criterion | Method | Command |
|
|
20
|
+
|-----------|--------|---------|
|
|
21
|
+
| US-001 AC1: calc.py exists | automated | `test -f calc.py` |
|
|
22
|
+
| US-001 AC2: 4 functions | automated | `python3 -c "from calc import add, subtract, multiply, divide"` |
|
|
23
|
+
| US-001 AC3: divide by zero | automated | `python3 -c "from calc import divide; divide(1, 0)"` → ValueError |
|
|
24
|
+
| US-001 AC4: type hints | automated | `grep "def add" calc.py` must show float annotations |
|
|
25
|
+
| US-002 AC1: test_calc.py exists | automated | `test -f test_calc.py` |
|
|
26
|
+
| US-002 AC2: uses pytest | automated | `grep "import pytest" test_calc.py` |
|
|
27
|
+
| US-002 AC3: 8+ tests | automated | `python3 -m pytest test_calc.py -v` → count PASSED >= 8 |
|
|
28
|
+
| US-002 AC4: divide zero test | automated | `grep "pytest.raises" test_calc.py` |
|
|
29
|
+
| US-002 AC5: ALL PASSED | automated | `python3 -m pytest test_calc.py -v` exit code 0 |
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Independent verifier for RLP Desk: loop-test
|
|
2
|
+
|
|
3
|
+
STRICT VERIFICATION RULES:
|
|
4
|
+
- Run EVERY command in the test spec. Do not skip any.
|
|
5
|
+
- A single failing criterion = verdict FAIL.
|
|
6
|
+
- Do NOT modify any code files.
|
|
7
|
+
|
|
8
|
+
Required reads:
|
|
9
|
+
- PRD: .claude/ralph-desk/plans/prd-loop-test.md
|
|
10
|
+
- Test Spec: .claude/ralph-desk/plans/test-spec-loop-test.md
|
|
11
|
+
- Campaign Memory: .claude/ralph-desk/memos/loop-test-memory.md
|
|
12
|
+
- Done Claim: .claude/ralph-desk/memos/loop-test-done-claim.json
|
|
13
|
+
|
|
14
|
+
Verification process:
|
|
15
|
+
1. Read PRD - get all acceptance criteria
|
|
16
|
+
2. Read done claim
|
|
17
|
+
3. Run EVERY verification command from test spec:
|
|
18
|
+
- test -f calc.py
|
|
19
|
+
- python3 -c "from calc import add, subtract, multiply, divide"
|
|
20
|
+
- python3 -c "from calc import divide; divide(1, 0)" → must raise ValueError
|
|
21
|
+
- grep for type hints in calc.py (all 4 functions must have float annotations)
|
|
22
|
+
- test -f test_calc.py
|
|
23
|
+
- grep "import pytest" test_calc.py
|
|
24
|
+
- grep "pytest.raises" test_calc.py
|
|
25
|
+
- python3 -m pytest test_calc.py -v → must show 8+ PASSED, 0 FAILED, exit code 0
|
|
26
|
+
4. Write verdict JSON to: .claude/ralph-desk/memos/loop-test-verify-verdict.json
|
|
27
|
+
|
|
28
|
+
CRITICAL: If even ONE criterion fails, verdict must be "fail" with recommended_state_transition "continue".
|
|
29
|
+
Include the specific failure in next_iteration_contract so the next worker knows what to fix.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Execute the plan for loop-test.
|
|
2
|
+
|
|
3
|
+
Required reads every iteration:
|
|
4
|
+
- PRD: .claude/ralph-desk/plans/prd-loop-test.md
|
|
5
|
+
- Test Spec: .claude/ralph-desk/plans/test-spec-loop-test.md
|
|
6
|
+
- Campaign Memory: .claude/ralph-desk/memos/loop-test-memory.md
|
|
7
|
+
- Latest Context: .claude/ralph-desk/context/loop-test-latest.md
|
|
8
|
+
|
|
9
|
+
CRITICAL RULE: Work on only ONE User Story per iteration.
|
|
10
|
+
- Check campaign memory's "Next Iteration Contract" first and do that.
|
|
11
|
+
- Do not touch already-completed stories.
|
|
12
|
+
|
|
13
|
+
Iteration rules:
|
|
14
|
+
- Use fresh context only; do NOT depend on prior chat history.
|
|
15
|
+
- Execute exactly ONE bounded next action (ONE user story).
|
|
16
|
+
- Refresh context file with the current frontier.
|
|
17
|
+
- Rewrite campaign memory in full.
|
|
18
|
+
|
|
19
|
+
MANDATORY: When done, write the following signal file:
|
|
20
|
+
- Path: .claude/ralph-desk/memos/loop-test-iter-signal.json
|
|
21
|
+
- Format: {"iteration": N, "status": "continue|verify|blocked", "timestamp": "ISO"}
|
|
22
|
+
- Status values:
|
|
23
|
+
- "continue" = current story done but other stories remain
|
|
24
|
+
- "verify" = all stories complete + done-claim written
|
|
25
|
+
- "blocked" = autonomous blocker
|
|
26
|
+
|
|
27
|
+
Stop behavior:
|
|
28
|
+
- Current story done but other stories remain → memory stop=continue, signal status=continue
|
|
29
|
+
- All stories complete + all tests pass → write done-claim JSON (.claude/ralph-desk/memos/loop-test-done-claim.json) + signal status=verify
|
|
30
|
+
- Autonomous blocker → write blocked.md + signal status=blocked
|
|
31
|
+
|
|
32
|
+
Objective: Implement a Python calculator module: calc.py (4 functions + type hints + ValueError) + test_calc.py (pytest, 8+ tests, all passed)
|
package/install.sh
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# =============================================================================
|
|
5
|
+
# RLP Desk Installer
|
|
6
|
+
#
|
|
7
|
+
# Installs the RLP Desk slash command and support files into ~/.claude/
|
|
8
|
+
#
|
|
9
|
+
# Usage:
|
|
10
|
+
# curl -sSL https://raw.githubusercontent.com/ai-dev-methodologies/rlp-desk/main/install.sh | bash
|
|
11
|
+
#
|
|
12
|
+
# Safe to run multiple times (idempotent).
|
|
13
|
+
# =============================================================================
|
|
14
|
+
|
|
15
|
+
REPO_URL="https://raw.githubusercontent.com/ai-dev-methodologies/rlp-desk/main"
|
|
16
|
+
CLAUDE_DIR="$HOME/.claude"
|
|
17
|
+
COMMANDS_DIR="$CLAUDE_DIR/commands"
|
|
18
|
+
DESK_DIR="$CLAUDE_DIR/ralph-desk"
|
|
19
|
+
|
|
20
|
+
echo ""
|
|
21
|
+
echo " RLP Desk Installer"
|
|
22
|
+
echo " ==================="
|
|
23
|
+
echo ""
|
|
24
|
+
|
|
25
|
+
# Create directories
|
|
26
|
+
mkdir -p "$COMMANDS_DIR"
|
|
27
|
+
mkdir -p "$DESK_DIR"
|
|
28
|
+
|
|
29
|
+
# Download slash command
|
|
30
|
+
echo " Downloading slash command..."
|
|
31
|
+
curl -sSL "$REPO_URL/src/commands/rlp-desk.md" -o "$COMMANDS_DIR/rlp-desk.md"
|
|
32
|
+
|
|
33
|
+
# Download init script
|
|
34
|
+
echo " Downloading init script..."
|
|
35
|
+
curl -sSL "$REPO_URL/src/scripts/init_ralph_desk.zsh" -o "$DESK_DIR/init_ralph_desk.zsh"
|
|
36
|
+
chmod +x "$DESK_DIR/init_ralph_desk.zsh"
|
|
37
|
+
|
|
38
|
+
# Download governance protocol
|
|
39
|
+
echo " Downloading governance protocol..."
|
|
40
|
+
curl -sSL "$REPO_URL/src/governance.md" -o "$DESK_DIR/governance.md"
|
|
41
|
+
|
|
42
|
+
echo ""
|
|
43
|
+
echo " Done! Installed to:"
|
|
44
|
+
echo ""
|
|
45
|
+
echo " Slash command: $COMMANDS_DIR/rlp-desk.md"
|
|
46
|
+
echo " Init script: $DESK_DIR/init_ralph_desk.zsh"
|
|
47
|
+
echo " Governance: $DESK_DIR/governance.md"
|
|
48
|
+
echo ""
|
|
49
|
+
echo " Usage:"
|
|
50
|
+
echo " 1. Open Claude Code in your project directory"
|
|
51
|
+
echo " 2. Run: /rlp-desk brainstorm \"your task description\""
|
|
52
|
+
echo " 3. Run: /rlp-desk run <slug>"
|
|
53
|
+
echo ""
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ai-dev-methodologies/rlp-desk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Fresh-context iterative loops for Claude Code — autonomous task completion with independent verification",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"postinstall": "node scripts/postinstall.js",
|
|
7
|
+
"uninstall": "node scripts/uninstall.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"src/",
|
|
11
|
+
"scripts/",
|
|
12
|
+
"docs/",
|
|
13
|
+
"examples/",
|
|
14
|
+
"install.sh",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"claude-code",
|
|
20
|
+
"ralph-loop",
|
|
21
|
+
"ai-coding",
|
|
22
|
+
"fresh-context",
|
|
23
|
+
"agent-loop",
|
|
24
|
+
"autonomous",
|
|
25
|
+
"verification"
|
|
26
|
+
],
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "https://github.com/ai-dev-methodologies/rlp-desk.git"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/ai-dev-methodologies/rlp-desk",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/ai-dev-methodologies/rlp-desk/issues"
|
|
34
|
+
},
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"author": "ai-dev-methodologies",
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=16"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const os = require("os");
|
|
7
|
+
|
|
8
|
+
const home = os.homedir();
|
|
9
|
+
const claudeDir = path.join(home, ".claude");
|
|
10
|
+
const commandsDir = path.join(claudeDir, "commands");
|
|
11
|
+
const deskDir = path.join(claudeDir, "ralph-desk");
|
|
12
|
+
const pkgDir = path.join(__dirname, "..");
|
|
13
|
+
|
|
14
|
+
console.log("");
|
|
15
|
+
console.log(" RLP Desk v0.0.1");
|
|
16
|
+
console.log(" ================");
|
|
17
|
+
console.log("");
|
|
18
|
+
|
|
19
|
+
// Create directories
|
|
20
|
+
fs.mkdirSync(commandsDir, { recursive: true });
|
|
21
|
+
fs.mkdirSync(deskDir, { recursive: true });
|
|
22
|
+
|
|
23
|
+
// Copy files
|
|
24
|
+
const copies = [
|
|
25
|
+
["src/commands/rlp-desk.md", path.join(commandsDir, "rlp-desk.md")],
|
|
26
|
+
[
|
|
27
|
+
"src/scripts/init_ralph_desk.zsh",
|
|
28
|
+
path.join(deskDir, "init_ralph_desk.zsh"),
|
|
29
|
+
],
|
|
30
|
+
["src/governance.md", path.join(deskDir, "governance.md")],
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
for (const [src, dest] of copies) {
|
|
34
|
+
fs.copyFileSync(path.join(pkgDir, src), dest);
|
|
35
|
+
console.log(" + " + dest);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Make scripts executable
|
|
39
|
+
try {
|
|
40
|
+
fs.chmodSync(path.join(deskDir, "init_ralph_desk.zsh"), 0o755);
|
|
41
|
+
} catch (_) {
|
|
42
|
+
// chmod may fail on Windows — not critical
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log("");
|
|
46
|
+
console.log(" Done! Open Claude Code and run:");
|
|
47
|
+
console.log(" /rlp-desk brainstorm \"your task description\"");
|
|
48
|
+
console.log("");
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const os = require("os");
|
|
7
|
+
|
|
8
|
+
const home = os.homedir();
|
|
9
|
+
const claudeDir = path.join(home, ".claude");
|
|
10
|
+
const commandsDir = path.join(claudeDir, "commands");
|
|
11
|
+
const deskDir = path.join(claudeDir, "ralph-desk");
|
|
12
|
+
|
|
13
|
+
console.log("");
|
|
14
|
+
console.log(" Uninstalling RLP Desk...");
|
|
15
|
+
console.log("");
|
|
16
|
+
|
|
17
|
+
const files = [
|
|
18
|
+
path.join(commandsDir, "rlp-desk.md"),
|
|
19
|
+
path.join(deskDir, "init_ralph_desk.zsh"),
|
|
20
|
+
path.join(deskDir, "governance.md"),
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
for (const f of files) {
|
|
24
|
+
try {
|
|
25
|
+
fs.unlinkSync(f);
|
|
26
|
+
console.log(" - " + f);
|
|
27
|
+
} catch (_) {
|
|
28
|
+
// File may not exist
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Remove ralph-desk dir if empty
|
|
33
|
+
try {
|
|
34
|
+
const remaining = fs.readdirSync(deskDir);
|
|
35
|
+
if (remaining.length === 0) {
|
|
36
|
+
fs.rmdirSync(deskDir);
|
|
37
|
+
console.log(" - " + deskDir);
|
|
38
|
+
}
|
|
39
|
+
} catch (_) {
|
|
40
|
+
// Directory may not exist
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log("");
|
|
44
|
+
console.log(" RLP Desk uninstalled.");
|
|
45
|
+
console.log("");
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Fresh-context RLP Desk — brainstorm, init, run, status, logs, clean"
|
|
3
|
+
argument-hint: "<brainstorm|init|run|status|logs|clean> <slug> [options]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# RLP Desk for Claude Code
|
|
7
|
+
|
|
8
|
+
**YOU are the leader.** You orchestrate fresh-context workers/verifiers via Agent().
|
|
9
|
+
|
|
10
|
+
The user invoked: `/rlp-desk $ARGUMENTS`
|
|
11
|
+
|
|
12
|
+
Parse the first word of `$ARGUMENTS` as the subcommand.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## `brainstorm <description>`
|
|
17
|
+
|
|
18
|
+
Planning phase BEFORE init. Interactively define the contract with the user.
|
|
19
|
+
|
|
20
|
+
Determine all of the following:
|
|
21
|
+
1. **Slug** — short identifier (e.g., `auth-refactor`)
|
|
22
|
+
2. **Objective** — what the loop achieves
|
|
23
|
+
3. **User Stories** — discrete units with testable acceptance criteria
|
|
24
|
+
4. **Iteration Unit** — one worker does per iteration (default: one user story)
|
|
25
|
+
5. **Verification Commands** — build, test, lint commands
|
|
26
|
+
6. **Completion / Blocked Criteria**
|
|
27
|
+
7. **Worker / Verifier Model** — haiku, sonnet, opus
|
|
28
|
+
8. **Max Iterations**
|
|
29
|
+
|
|
30
|
+
Present the contract summary. On approval, offer to run `init`.
|
|
31
|
+
Do NOT create files during brainstorm.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## `init <slug> [objective]`
|
|
36
|
+
|
|
37
|
+
Run: `~/.claude/ralph-desk/init_ralph_desk.zsh <slug> "<objective>"`
|
|
38
|
+
If brainstorm was done, auto-fill PRD and test-spec with the results.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## `run <slug> [options]`
|
|
43
|
+
|
|
44
|
+
**YOU are the leader. Do NOT delegate leadership.**
|
|
45
|
+
|
|
46
|
+
Options (parse from `$ARGUMENTS`):
|
|
47
|
+
- `--max-iter N` (default: 100)
|
|
48
|
+
- `--worker-model MODEL` (default: sonnet)
|
|
49
|
+
- `--verifier-model MODEL` (default: sonnet)
|
|
50
|
+
|
|
51
|
+
### Preparation
|
|
52
|
+
1. Validate scaffold: `.claude/ralph-desk/prompts/<slug>.worker.prompt.md` etc.
|
|
53
|
+
2. Check sentinels (complete/blocked). Found → tell user `/rlp-desk clean <slug>`.
|
|
54
|
+
3. Clean previous `done-claim.json`, `verify-verdict.json`.
|
|
55
|
+
|
|
56
|
+
### Leader Loop
|
|
57
|
+
|
|
58
|
+
For each iteration (1 to max_iter):
|
|
59
|
+
|
|
60
|
+
**① Check sentinels**
|
|
61
|
+
```bash
|
|
62
|
+
test -f .claude/ralph-desk/memos/<slug>-complete.md # → done
|
|
63
|
+
test -f .claude/ralph-desk/memos/<slug>-blocked.md # → stop
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**② Read memory.md** → Stop Status, Next Iteration Contract
|
|
67
|
+
|
|
68
|
+
**③ Decide model** (§4 of governance.md)
|
|
69
|
+
- Previous iteration failed → upgrade model
|
|
70
|
+
- Simple task → downgrade
|
|
71
|
+
- User specified → use that
|
|
72
|
+
|
|
73
|
+
**④ Build worker prompt**
|
|
74
|
+
- Read `.claude/ralph-desk/prompts/<slug>.worker.prompt.md`
|
|
75
|
+
- Combine with iteration number + memory contract
|
|
76
|
+
- Write to `.claude/ralph-desk/logs/<slug>/iter-NNN.worker-prompt.md` (audit trail)
|
|
77
|
+
|
|
78
|
+
**⑤ Execute Worker via Agent()**
|
|
79
|
+
```
|
|
80
|
+
Agent(
|
|
81
|
+
description="rlp-desk worker iter-NNN",
|
|
82
|
+
subagent_type="executor",
|
|
83
|
+
model=<worker_model>,
|
|
84
|
+
mode="bypassPermissions",
|
|
85
|
+
prompt=<full worker prompt text>
|
|
86
|
+
)
|
|
87
|
+
```
|
|
88
|
+
- Agent returns synchronously. No polling needed.
|
|
89
|
+
- Each Agent() = fresh context. Guaranteed.
|
|
90
|
+
|
|
91
|
+
**⑥ Read memory.md again** (Worker updated it)
|
|
92
|
+
- `stop=continue` → go to ⑧
|
|
93
|
+
- `stop=verify` → go to ⑦
|
|
94
|
+
- `stop=blocked` → write BLOCKED sentinel, stop
|
|
95
|
+
|
|
96
|
+
**⑦ Execute Verifier via Agent()**
|
|
97
|
+
- Build verifier prompt, write to `iter-NNN.verifier-prompt.md`
|
|
98
|
+
```
|
|
99
|
+
Agent(
|
|
100
|
+
description="rlp-desk verifier iter-NNN",
|
|
101
|
+
subagent_type="executor",
|
|
102
|
+
model=<verifier_model>,
|
|
103
|
+
mode="bypassPermissions",
|
|
104
|
+
prompt=<full verifier prompt text>
|
|
105
|
+
)
|
|
106
|
+
```
|
|
107
|
+
- Read `verify-verdict.json`:
|
|
108
|
+
- `pass` + `complete` → write COMPLETE sentinel, report done!
|
|
109
|
+
- `fail` + `continue` → go to ⑧
|
|
110
|
+
- `blocked` → write BLOCKED sentinel, stop
|
|
111
|
+
|
|
112
|
+
**⑧ Report iteration result to user, continue loop**
|
|
113
|
+
- Write `status.json`
|
|
114
|
+
- Report: iteration N, phase, model used, result
|
|
115
|
+
- Clean `done-claim.json`, `verify-verdict.json` for next iteration
|
|
116
|
+
|
|
117
|
+
### Circuit Breaker
|
|
118
|
+
- context-latest.md unchanged 3 iterations → BLOCKED
|
|
119
|
+
- Same error 2x → upgrade model, retry once, then BLOCKED
|
|
120
|
+
- max_iter reached → TIMEOUT, report to user
|
|
121
|
+
|
|
122
|
+
### Important Rules
|
|
123
|
+
- Each Agent() = new process = fresh context
|
|
124
|
+
- YOU track iteration count
|
|
125
|
+
- Write `status.json` after each iteration
|
|
126
|
+
- Worker claim ≠ complete. Only YOU write COMPLETE sentinel after verifier pass.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## `status <slug>`
|
|
131
|
+
Read `.claude/ralph-desk/logs/<slug>/status.json` and display.
|
|
132
|
+
|
|
133
|
+
## `logs <slug> [N]`
|
|
134
|
+
- No N: show latest `iter-*.worker-prompt.md` summary
|
|
135
|
+
- With N: read `iter-N.worker-prompt.md` and `iter-N.verifier-prompt.md`
|
|
136
|
+
|
|
137
|
+
## `clean <slug>`
|
|
138
|
+
Remove:
|
|
139
|
+
- `.claude/ralph-desk/memos/<slug>-complete.md`
|
|
140
|
+
- `.claude/ralph-desk/memos/<slug>-blocked.md`
|
|
141
|
+
- `.claude/ralph-desk/memos/<slug>-done-claim.json`
|
|
142
|
+
- `.claude/ralph-desk/memos/<slug>-verify-verdict.json`
|
|
143
|
+
- `.claude/ralph-desk/logs/<slug>/circuit-breaker.json`
|
|
144
|
+
|
|
145
|
+
## No args or `help`
|
|
146
|
+
```
|
|
147
|
+
/rlp-desk brainstorm <description> Plan before init (interactive)
|
|
148
|
+
/rlp-desk init <slug> [objective] Create project scaffold
|
|
149
|
+
/rlp-desk run <slug> [--opts] Run loop (this session = leader)
|
|
150
|
+
/rlp-desk status <slug> Show loop status
|
|
151
|
+
/rlp-desk logs <slug> [N] Show iteration log
|
|
152
|
+
/rlp-desk clean <slug> Reset for re-run
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Architecture
|
|
156
|
+
```
|
|
157
|
+
[This session = LEADER]
|
|
158
|
+
│
|
|
159
|
+
Agent()├──▶ [Worker: executor (fresh context)]
|
|
160
|
+
│ └── reads desk files, implements, updates memory
|
|
161
|
+
│
|
|
162
|
+
Agent()└──▶ [Verifier: executor (fresh context)]
|
|
163
|
+
└── reads done-claim, runs checks, writes verdict
|
|
164
|
+
```
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Ralph Desk Governance v2
|
|
2
|
+
|
|
3
|
+
Fresh-context independent verification protocol.
|
|
4
|
+
The Leader orchestrates, while Worker/Verifier run in isolated fresh contexts every iteration.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Core Principles
|
|
9
|
+
|
|
10
|
+
- **Fresh context per iteration**: Worker/Verifier start fresh every time. No prior conversation.
|
|
11
|
+
- **Filesystem = memory**: State exists only on the filesystem (PRD, memory, context, memos).
|
|
12
|
+
- **Worker claim ≠ complete**: A Worker's DONE is merely a claim. The Verifier must independently verify before it's confirmed.
|
|
13
|
+
- **Verifier is independent**: The Verifier judges based on evidence alone, without knowledge of the Worker's reasoning process.
|
|
14
|
+
- **Sentinels are Leader-owned**: Only the Leader writes COMPLETE/BLOCKED sentinels.
|
|
15
|
+
- **Claude models only**: haiku, sonnet, opus.
|
|
16
|
+
|
|
17
|
+
## 2. Roles
|
|
18
|
+
|
|
19
|
+
### Leader (current session)
|
|
20
|
+
- Operates the loop, selects models, controls flow
|
|
21
|
+
- Dispatches Worker/Verifier via Agent()
|
|
22
|
+
- Reads memory to assess state, writes sentinels
|
|
23
|
+
- **Does NOT write or execute code**
|
|
24
|
+
|
|
25
|
+
### Worker (fresh context)
|
|
26
|
+
- Performs one bounded action per iteration
|
|
27
|
+
- Updates context and memory (so the next fresh worker can continue)
|
|
28
|
+
- Writes done-claim.json when claiming completion
|
|
29
|
+
|
|
30
|
+
### Verifier (fresh context)
|
|
31
|
+
- Independently verifies Worker's done claim
|
|
32
|
+
- Runs commands directly to collect fresh evidence
|
|
33
|
+
- Writes verdict (pass/fail/blocked)
|
|
34
|
+
- **Must NEVER modify code**
|
|
35
|
+
|
|
36
|
+
## 3. State Flow
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
RUNNING → DONE_CLAIMED → VERIFYING → COMPLETE | CONTINUE | BLOCKED
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## 4. Model Routing (Claude only)
|
|
43
|
+
|
|
44
|
+
| Role | Default Model | Override Criteria |
|
|
45
|
+
|------|---------------|-------------------|
|
|
46
|
+
| Worker (simple) | haiku | Single file, clear change |
|
|
47
|
+
| Worker (standard) | sonnet | Most tasks (default) |
|
|
48
|
+
| Worker (complex) | opus | Architecture changes, multi-file, prior iteration failure |
|
|
49
|
+
| Verifier | sonnet | Sufficient for most cases |
|
|
50
|
+
| Verifier (strict) | opus | Security/critical logic verification |
|
|
51
|
+
|
|
52
|
+
The Leader decides each iteration. Decision criteria:
|
|
53
|
+
- Previous iteration failed → upgrade model
|
|
54
|
+
- Simple repetitive task → downgrade model
|
|
55
|
+
- User explicitly specified → use as given
|
|
56
|
+
|
|
57
|
+
## 5. Execution: Unified Agent() Approach
|
|
58
|
+
|
|
59
|
+
All environments (Claude Code, OpenCode) use the same Agent tool.
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
# Worker
|
|
63
|
+
Agent(
|
|
64
|
+
subagent_type="executor",
|
|
65
|
+
model="sonnet",
|
|
66
|
+
prompt=worker_prompt,
|
|
67
|
+
mode="bypassPermissions"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Verifier
|
|
71
|
+
Agent(
|
|
72
|
+
subagent_type="executor",
|
|
73
|
+
model="sonnet",
|
|
74
|
+
prompt=verifier_prompt,
|
|
75
|
+
mode="bypassPermissions"
|
|
76
|
+
)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Characteristics:
|
|
80
|
+
- Each call = fresh context (new subprocess)
|
|
81
|
+
- Synchronous return. No polling or signal files needed.
|
|
82
|
+
- After Agent completes, read memory.md to assess state.
|
|
83
|
+
- No tmux required.
|
|
84
|
+
- Monitor in real-time via ctrl+o (Claude Code UI).
|
|
85
|
+
- Prompts are still logged to logs/ for audit trail.
|
|
86
|
+
|
|
87
|
+
## 6. File Structure
|
|
88
|
+
|
|
89
|
+
### User-level (central)
|
|
90
|
+
```
|
|
91
|
+
~/.claude/ralph-desk/
|
|
92
|
+
├── init_ralph_desk.zsh # Scaffold generator (automation)
|
|
93
|
+
├── governance.md # This document
|
|
94
|
+
└── templates/ # Prompt templates
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Project-local
|
|
98
|
+
```
|
|
99
|
+
.claude/ralph-desk/
|
|
100
|
+
├── prompts/
|
|
101
|
+
│ ├── <slug>.worker.prompt.md # Worker base prompt
|
|
102
|
+
│ └── <slug>.verifier.prompt.md # Verifier base prompt
|
|
103
|
+
├── context/
|
|
104
|
+
│ └── <slug>-latest.md # Current frontier (Worker updates)
|
|
105
|
+
├── memos/
|
|
106
|
+
│ ├── <slug>-memory.md # Campaign memory (Worker updates)
|
|
107
|
+
│ ├── <slug>-done-claim.json # Worker's completion claim (runtime)
|
|
108
|
+
│ ├── <slug>-verify-verdict.json # Verifier's verdict (runtime)
|
|
109
|
+
│ ├── <slug>-complete.md # SENTINEL (Leader only)
|
|
110
|
+
│ └── <slug>-blocked.md # SENTINEL (Leader only)
|
|
111
|
+
├── plans/
|
|
112
|
+
│ ├── prd-<slug>.md # PRD (shared contract)
|
|
113
|
+
│ └── test-spec-<slug>.md # Verification criteria
|
|
114
|
+
└── logs/<slug>/
|
|
115
|
+
├── iter-NNN.worker-prompt.md # Audit trail prompt copy
|
|
116
|
+
├── iter-NNN.verifier-prompt.md # Audit trail prompt copy
|
|
117
|
+
└── status.json # Leader's loop state
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## 7. Leader Loop Protocol
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
for iteration in 1..max_iter:
|
|
124
|
+
|
|
125
|
+
① Check sentinels
|
|
126
|
+
- complete.md exists → stop
|
|
127
|
+
- blocked.md exists → stop
|
|
128
|
+
|
|
129
|
+
② Read memory.md → check Stop Status, Next Iteration Contract
|
|
130
|
+
|
|
131
|
+
③ Select model
|
|
132
|
+
- Default or situational decision (see §4)
|
|
133
|
+
- Context unchanged for 3 consecutive iterations → BLOCKED
|
|
134
|
+
|
|
135
|
+
④ Build Worker prompt
|
|
136
|
+
- Base prompt + iteration number + contract from memory
|
|
137
|
+
- Log to logs/<slug>/iter-NNN.worker-prompt.md
|
|
138
|
+
|
|
139
|
+
⑤ Execute Worker: Agent(subagent_type="executor", model=selected, prompt=prompt)
|
|
140
|
+
- Synchronous return, wait for completion
|
|
141
|
+
|
|
142
|
+
⑥ Read memory.md again → check Worker's updated state
|
|
143
|
+
- "continue" → go to ⑧
|
|
144
|
+
- "verify" → go to ⑦
|
|
145
|
+
- "blocked" → write BLOCKED sentinel, stop
|
|
146
|
+
|
|
147
|
+
⑦ Execute Verifier
|
|
148
|
+
- Build prompt → log to logs/<slug>/iter-NNN.verifier-prompt.md
|
|
149
|
+
- Agent(subagent_type="executor", model=selected, prompt=prompt)
|
|
150
|
+
- Read verify-verdict.json:
|
|
151
|
+
• pass + complete → write COMPLETE sentinel, stop
|
|
152
|
+
• fail + continue → go to ⑧
|
|
153
|
+
• blocked → write BLOCKED sentinel, stop
|
|
154
|
+
|
|
155
|
+
⑧ Update status.json, report to user, continue to next iteration
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## 8. Circuit Breaker
|
|
159
|
+
|
|
160
|
+
| Condition | Verdict |
|
|
161
|
+
|-----------|---------|
|
|
162
|
+
| context-latest.md unchanged for 3 consecutive iterations | BLOCKED |
|
|
163
|
+
| Worker repeats the same error twice | Upgrade model, retry once; if still failing → BLOCKED |
|
|
164
|
+
| max_iter reached | TIMEOUT (report to user) |
|
|
165
|
+
|
|
166
|
+
## 9. Change Policy
|
|
167
|
+
|
|
168
|
+
- Changes to the shared workflow → modify this document
|
|
169
|
+
- Project-specific objectives/criteria → modify project-local files
|
|
170
|
+
- Init script changes → modify init_ralph_desk.zsh
|