@graypark/loophaus 3.8.0 → 3.9.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/README.md CHANGED
@@ -10,10 +10,10 @@
10
10
  <a href="https://github.com/vcz-Gray/loophaus/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="license" /></a>
11
11
  <img src="https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg?style=flat-square" alt="node version" />
12
12
  <img src="https://img.shields.io/badge/platform-Claude%20Code%20%7C%20Codex%20CLI%20%7C%20Kiro%20CLI-purple.svg?style=flat-square" alt="platform" />
13
- <img src="https://img.shields.io/badge/tests-296%20passing-brightgreen.svg?style=flat-square" alt="tests" />
13
+ <img src="https://img.shields.io/badge/tests-359%20passing-brightgreen.svg?style=flat-square" alt="tests" />
14
14
  </p>
15
15
 
16
- <h3 align="center">Control plane for coding agents iterative dev loops across Claude Code, Codex CLI, and Kiro CLI.</h3>
16
+ <h3 align="center">Run AI coding agents in autonomous loops fresh context each iteration, PRD-tracked progress, automatic quality gates.</h3>
17
17
 
18
18
  <p align="center">
19
19
  <sub>Based on <a href="https://ghuntley.com/ralph/">Geoffrey Huntley's Ralph Wiggum technique</a></sub>
@@ -21,26 +21,55 @@
21
21
 
22
22
  ---
23
23
 
24
- ## Why loophaus?
24
+ ## The Problem
25
25
 
26
- AI coding agents struggle with fundamental problems that get worse over long sessions:
26
+ AI coding agents struggle with long tasks:
27
27
 
28
- | Problem | What happens |
29
- |---------|-------------|
30
- | **Context rot** | Long conversations accumulate noise, the agent gets confused |
31
- | **No checkpoints** | All-or-nothing execution can't resume after interruption |
32
- | **Lost learnings** | Previous iterations' insights overwritten by new context |
33
- | **Completion ambiguity** | Agent says "done" but tests still fail |
34
- | **Platform lock-in** | Techniques that work in one agent don't transfer to others |
35
-
36
- loophaus solves this:
37
-
38
- - **Fresh context per iteration** — Each cycle reads PRD + progress from disk, zero degradation
39
- - **Git-enforced safety** — Atomic commits per story, rollback at any point
40
- - **Append-only learnings** — `progress.txt` accumulates knowledge across iterations
41
- - **Test-verified completion** — Agent can only exit when `<promise>COMPLETE</promise>` is genuinely true
28
+ - **Context rot** agent gets confused after 10+ iterations
29
+ - **Goal drift** — agent forgets the spec and solves the wrong problem
30
+ - **No quality signal** agent says "done" but tests still fail
31
+ - **Token waste** you re-explain the same context every time
32
+
33
+ ## The Solution
34
+
35
+ - **Fresh context per iteration** — Each cycle reads PRD + progress from disk, zero degradation even after 20+ iterations
36
+ - **PRD-linked progress tracking** — Stories are tracked in `prd.json` with pass/fail state, not "I think I'm done"
37
+ - **Quality scoring with keep/discard** — Autoresearch-inspired refinement loop measures quality (0-100) and reverts regressions
42
38
  - **Universal stop hook** — One Node.js hook works across Claude Code, Codex CLI, and Kiro CLI
43
39
 
40
+ ## Quick Start
41
+
42
+ ```bash
43
+ npm install -g @graypark/loophaus
44
+ loophaus install
45
+ ```
46
+
47
+ > **Note:** `npx @graypark/loophaus install` may fail on some npm versions due to a bin resolution cache bug. Use the global install above for reliable setup.
48
+
49
+ The installer auto-detects your host (Claude Code, Codex CLI, or Kiro CLI) and sets up everything — stop hook, commands, and skills.
50
+
51
+ Then in your AI coding session:
52
+
53
+ ```
54
+ /loop-plan Add user authentication with JWT, bcrypt, and login UI
55
+ ```
56
+
57
+ That's it. The interview generates a PRD, activates the loop, and starts implementing story by story.
58
+
59
+ ## Safety
60
+
61
+ - Every iteration creates a **git checkpoint** — atomic revert anytime
62
+ - **Max iterations limit** (default 20, configurable)
63
+ - **Quality threshold = circuit breaker** — score < 80 triggers refine or stop
64
+ - **Cost tracking** with policy enforcement (max $5, max 30 min)
65
+ - `loophaus clean` for data lifecycle management
66
+
67
+ ## Why not just script this?
68
+
69
+ 1. **Fresh context isolation** — no degradation after 20 iterations; each cycle starts from disk, not from a decaying conversation
70
+ 2. **PRD-linked progress tracking** — structured `prd.json` with pass/fail per story, not "I think I'm done"
71
+ 3. **Quality scoring with keep/discard** — autoresearch pattern: measure, keep improvements, revert regressions
72
+
44
73
  ## How it works
45
74
 
46
75
  An AI agent works on a task in a continuous loop. Each iteration starts with fresh context — reading the PRD and progress files to decide what to do next. The agent implements one story, commits, updates progress, and exits. The stop hook intercepts the exit and re-injects the prompt. Repeat until all stories pass.
@@ -80,33 +109,53 @@ An AI agent works on a task in a continuous loop. Each iteration starts with fre
80
109
  └─────────────────────────────────┘
81
110
  ```
82
111
 
83
- ## Quick Start
112
+ ## Commands
84
113
 
85
- ```bash
86
- npm install -g @graypark/loophaus
87
- loophaus install
88
- ```
114
+ | Command | Description |
115
+ |---------|-------------|
116
+ | `/loop-plan` | Interactive interview — asks targeted questions, generates PRD, activates loop |
117
+ | `/loop` | Start iterative dev loop directly (when you already have a PRD or custom prompt) |
118
+ | `/loop-stop` | Stop the active loop immediately |
119
+ | `/loop-pulse` | Check current loop status, iteration count, and progress |
89
120
 
90
- > **Note:** `npx @graypark/loophaus install` may fail on some npm versions due to a bin resolution cache bug. Use the global install above for reliable setup.
121
+ ## Quality Loop (v3.4.0+)
91
122
 
92
- The installer auto-detects your host (Claude Code, Codex CLI, or Kiro CLI) and sets up everything — stop hook, commands, and skills.
123
+ loophaus v3.4.0 introduces the **Quality Loop** inspired by [karpathy/autoresearch](https://github.com/karpathy/autoresearch)'s experiment-measure-keep/discard pattern.
93
124
 
94
- Then in your AI coding session:
125
+ Instead of simply marking a story as "done" when tests pass, `/loop-plan` now **measures quality** (0-100) and **iteratively refines** until the score meets the threshold.
95
126
 
96
127
  ```
97
- /loop-plan Add user authentication with JWT, bcrypt, and login UI
128
+ Phase 4: Implement
129
+
130
+ Phase 5: Evaluate (score 0-100)
131
+ ↓ ↑
132
+ Phase 6: Refine Loop
133
+ score improved? → keep (commit)
134
+ score declined? → discard (git reset)
135
+ max attempts reached? → move on
136
+
137
+ Phase 7: Report (with quality scores)
98
138
  ```
99
139
 
100
- That's it. The interview generates a PRD, activates the loop, and starts implementing story by story.
140
+ | autoresearch | loophaus |
141
+ |-------------|----------|
142
+ | `val_bpb` | quality score (weighted: tests, typecheck, lint, verify, diff, custom) |
143
+ | `results.tsv` | `.loophaus/results.tsv` |
144
+ | keep → advance | score improved → commit |
145
+ | discard → revert | score declined → `git reset --hard` |
146
+ | NEVER STOP | max 3 attempts per story (configurable) |
101
147
 
102
- ## Commands
148
+ ### Configuration
103
149
 
104
- | Command | Description |
105
- |---------|-------------|
106
- | `/loop-plan` | Interactive interview — asks targeted questions, generates PRD, activates loop |
107
- | `/loop` | Start iterative dev loop directly (when you already have a PRD or custom prompt) |
108
- | `/loop-stop` | Stop the active loop immediately |
109
- | `/loop-pulse` | Check current loop status, iteration count, and progress |
150
+ ```json
151
+ {
152
+ "qualityThreshold": 80,
153
+ "maxRefineAttempts": 3,
154
+ "qualityConfig": {
155
+ "weights": { "tests": 30, "typecheck": 25, "lint": 15, "verify": 15, "diff": 10, "custom": 5 }
156
+ }
157
+ }
158
+ ```
110
159
 
111
160
  ## Platform Support
112
161
 
@@ -165,55 +214,13 @@ loophaus install # Install to detected host
165
214
  loophaus status # Show current loop state and active host
166
215
  loophaus stats # Iteration history and completion metrics
167
216
  loophaus quality # Run quality scoring on current stories
217
+ loophaus demo # Run interactive demo
218
+ loophaus config # Show/edit configuration
219
+ loophaus update-check # Check for new versions
220
+ loophaus upgrade # Upgrade to latest version
168
221
  loophaus uninstall # Clean removal from all hosts
169
222
  ```
170
223
 
171
- ## Quality Loop (v3.4.0+)
172
-
173
- loophaus v3.4.0 introduces the **Quality Loop** — inspired by [karpathy/autoresearch](https://github.com/karpathy/autoresearch)'s experiment→measure→keep/discard pattern.
174
-
175
- Instead of simply marking a story as "done" when tests pass, `/loop-plan` now **measures quality** (0-100) and **iteratively refines** until the score meets the threshold.
176
-
177
- ```
178
- Phase 4: Implement
179
-
180
- Phase 5: Evaluate (score 0-100)
181
- ↓ ↑
182
- Phase 6: Refine Loop
183
- score improved? → keep (commit)
184
- score declined? → discard (git reset)
185
- max attempts reached? → move on
186
-
187
- Phase 7: Report (with quality scores)
188
- ```
189
-
190
- | autoresearch | loophaus |
191
- |-------------|----------|
192
- | `val_bpb` | quality score (weighted: tests, typecheck, lint, verify, diff, custom) |
193
- | `results.tsv` | `.loophaus/results.tsv` |
194
- | keep → advance | score improved → commit |
195
- | discard → revert | score declined → `git reset --hard` |
196
- | NEVER STOP | max 3 attempts per story (configurable) |
197
-
198
- ### Configuration
199
-
200
- ```json
201
- {
202
- "qualityThreshold": 80,
203
- "maxRefineAttempts": 3,
204
- "qualityConfig": {
205
- "weights": { "tests": 30, "typecheck": 25, "lint": 15, "verify": 15, "diff": 10, "custom": 5 }
206
- }
207
- }
208
- ```
209
-
210
- ### CLI
211
-
212
- ```bash
213
- loophaus quality # Score all stories
214
- loophaus quality --story US-001 # Score a specific story
215
- ```
216
-
217
224
  ## Architecture
218
225
 
219
226
  ```
@@ -253,7 +260,7 @@ loophaus/
253
260
  ├── .claude-plugin/
254
261
  │ └── plugin.json # Claude Code marketplace manifest
255
262
  ├── dist/ # Compiled output (tsc)
256
- └── tests/ # 296 test cases (vitest)
263
+ └── tests/ # 359 test cases (vitest)
257
264
  ```
258
265
 
259
266
  ## PRD Format
@@ -311,10 +318,10 @@ npm uninstall -g @graypark/loophaus
311
318
  git clone https://github.com/vcz-Gray/loophaus.git
312
319
  cd loophaus
313
320
  npm install
314
- npm test
315
- npm run typecheck # TypeScript strict mode
316
- npm run build # Compile to dist/
317
- npx vitest # watch mode
321
+ npm test # 359 tests
322
+ npm run typecheck # TypeScript strict mode
323
+ npm run build # Compile to dist/
324
+ npx vitest # watch mode
318
325
  ```
319
326
 
320
327
  ## License
@@ -24,7 +24,7 @@ const VALID_COMMANDS = [
24
24
  "install", "uninstall", "status", "stats", "loops", "watch",
25
25
  "replay", "compare", "worktree", "parallel", "quality",
26
26
  "sessions", "resume", "benchmark", "clean", "config",
27
- "update-check", "upgrade", "help",
27
+ "update-check", "upgrade", "demo", "help",
28
28
  ];
29
29
  function validateFlags() {
30
30
  for (const arg of args) {
@@ -122,6 +122,7 @@ Usage:
122
122
  npx @graypark/loophaus upgrade
123
123
  npx @graypark/loophaus sessions
124
124
  npx @graypark/loophaus resume <session-id>
125
+ npx @graypark/loophaus demo
125
126
  npx @graypark/loophaus --version
126
127
 
127
128
  Hosts:
@@ -878,6 +879,94 @@ function setNestedValue(obj, path, value) {
878
879
  }
879
880
  current[parts[parts.length - 1]] = value;
880
881
  }
882
+ async function runDemo() {
883
+ const { mkdtemp, writeFile, rm, mkdir } = await import("node:fs/promises");
884
+ const { tmpdir } = await import("node:os");
885
+ const { join: pathJoin } = await import("node:path");
886
+ const { execSync } = await import("node:child_process");
887
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
888
+ console.log(`loophaus demo`);
889
+ console.log(`\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550`);
890
+ console.log();
891
+ const demoDir = await mkdtemp(pathJoin(tmpdir(), "loophaus-demo-"));
892
+ try {
893
+ // Initialize git repo
894
+ execSync("git init -q", { cwd: demoDir, stdio: "ignore" });
895
+ execSync("git config user.email 'demo@loophaus.dev'", { cwd: demoDir, stdio: "ignore" });
896
+ execSync("git config user.name 'loophaus-demo'", { cwd: demoDir, stdio: "ignore" });
897
+ // Write broken index.mjs
898
+ const indexContent = `// index.mjs — broken sum function
899
+ export function sum(a, b) {
900
+ return a - b; // BUG: should be a + b
901
+ }
902
+ `;
903
+ await writeFile(pathJoin(demoDir, "index.mjs"), indexContent, "utf-8");
904
+ // Write prd.json with 2 stories
905
+ const prd = {
906
+ title: "Fix sum module",
907
+ userStories: [
908
+ { id: "US-001", title: "Fix sum function", acceptance: "sum(2, 3) returns 5", passes: false },
909
+ { id: "US-002", title: "Add tests", acceptance: "test file verifies sum works", passes: false },
910
+ ],
911
+ };
912
+ await writeFile(pathJoin(demoDir, "prd.json"), JSON.stringify(prd, null, 2), "utf-8");
913
+ // Write state.json
914
+ await mkdir(pathJoin(demoDir, ".loophaus"), { recursive: true });
915
+ const state = { active: true, currentIteration: 0, maxIterations: 4, completionPromise: "Fix sum module" };
916
+ await writeFile(pathJoin(demoDir, ".loophaus", "state.json"), JSON.stringify(state, null, 2), "utf-8");
917
+ // Initial commit
918
+ execSync("git add -A && git commit -q -m 'init: broken sum'", { cwd: demoDir, stdio: "ignore" });
919
+ // Show project tree
920
+ console.log(`Creating demo project...`);
921
+ console.log();
922
+ await sleep(400);
923
+ console.log(`\uD83D\uDCC1 ${demoDir}/`);
924
+ console.log(`\u251C\u2500\u2500 index.mjs (broken sum function)`);
925
+ console.log(`\u251C\u2500\u2500 prd.json (2 stories)`);
926
+ console.log(`\u2514\u2500\u2500 .loophaus/state.json`);
927
+ console.log();
928
+ await sleep(600);
929
+ // Simulate iteration 1
930
+ console.log(`Simulating loop iteration 1/4...`);
931
+ await sleep(300);
932
+ console.log(` \u2192 Reading prd.json: 2 stories, 0 done`);
933
+ await sleep(400);
934
+ console.log(` \u2192 Working on US-001: Fix sum function`);
935
+ await sleep(600);
936
+ console.log(` \u2192 Verified: sum(2, 3) = 5 \u2713`);
937
+ await sleep(300);
938
+ console.log(` \u2192 Committed: feat: US-001 Fix sum function`);
939
+ console.log();
940
+ await sleep(500);
941
+ // Simulate iteration 2
942
+ console.log(`Simulating loop iteration 2/4...`);
943
+ await sleep(300);
944
+ console.log(` \u2192 Reading prd.json: 2 stories, 1 done`);
945
+ await sleep(400);
946
+ console.log(` \u2192 Working on US-002: Add tests`);
947
+ await sleep(600);
948
+ console.log(` \u2192 Verified: 2 tests passing \u2713`);
949
+ await sleep(300);
950
+ console.log(` \u2192 Committed: feat: US-002 Add tests`);
951
+ console.log();
952
+ await sleep(500);
953
+ console.log(`Quality Score: 95/100 (A+)`);
954
+ console.log();
955
+ console.log(`All stories complete! \uD83C\uDF89`);
956
+ console.log();
957
+ console.log(`This is what /loop-plan does autonomously in your real projects.`);
958
+ console.log();
959
+ console.log(`Try it:`);
960
+ console.log(` cd your-project`);
961
+ console.log(` /loop-plan "describe your task here"`);
962
+ console.log();
963
+ console.log(`Cleaning up demo...`);
964
+ }
965
+ finally {
966
+ // Clean up temp directory
967
+ await rm(demoDir, { recursive: true, force: true });
968
+ }
969
+ }
881
970
  try {
882
971
  switch (command) {
883
972
  case "install":
@@ -934,6 +1023,9 @@ try {
934
1023
  case "resume":
935
1024
  await runResume();
936
1025
  break;
1026
+ case "demo":
1027
+ await runDemo();
1028
+ break;
937
1029
  default:
938
1030
  if (command.startsWith("-")) {
939
1031
  await runInstall();
package/dist/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@graypark/loophaus",
3
- "version": "3.8.0",
3
+ "version": "3.9.0",
4
4
  "type": "module",
5
- "description": "loophaus Control plane for coding agents. Iterative dev loops with multi-agent orchestration.",
5
+ "description": "Autonomous dev loops for AI coding agents fresh context each iteration, PRD-tracked progress, automatic quality gates.",
6
6
  "license": "MIT",
7
7
  "author": "graypark",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/vcz-Gray/loophaus"
10
+ "url": "git+https://github.com/vcz-Gray/loophaus.git"
11
11
  },
12
12
  "homepage": "https://github.com/vcz-Gray/loophaus#readme",
13
13
  "bugs": {
@@ -17,7 +17,7 @@
17
17
  "access": "public"
18
18
  },
19
19
  "bin": {
20
- "loophaus": "./dist/bin/loophaus.js"
20
+ "loophaus": "dist/bin/loophaus.js"
21
21
  },
22
22
  "files": [
23
23
  "dist/",
@@ -43,16 +43,23 @@
43
43
  "prepare": "npm run build"
44
44
  },
45
45
  "engines": {
46
- "node": ">=20.0.0"
46
+ "node": ">=20.0.0",
47
+ "npm": ">=9.0.0"
47
48
  },
48
49
  "keywords": [
49
50
  "loophaus",
50
- "loop",
51
+ "autonomous",
51
52
  "ai-agent",
52
- "iterative-development",
53
+ "coding-agents",
54
+ "fresh-context",
55
+ "prd",
56
+ "quality-scoring",
57
+ "autoresearch",
58
+ "claude-code",
59
+ "codex-cli",
60
+ "kiro-cli",
53
61
  "stop-hook",
54
- "control-plane",
55
- "coding-agents"
62
+ "iterative-development"
56
63
  ],
57
64
  "devDependencies": {
58
65
  "@types/node": "^25.5.0",
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@graypark/loophaus",
3
- "version": "3.8.0",
3
+ "version": "3.9.0",
4
4
  "type": "module",
5
- "description": "loophaus Control plane for coding agents. Iterative dev loops with multi-agent orchestration.",
5
+ "description": "Autonomous dev loops for AI coding agents fresh context each iteration, PRD-tracked progress, automatic quality gates.",
6
6
  "license": "MIT",
7
7
  "author": "graypark",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/vcz-Gray/loophaus"
10
+ "url": "git+https://github.com/vcz-Gray/loophaus.git"
11
11
  },
12
12
  "homepage": "https://github.com/vcz-Gray/loophaus#readme",
13
13
  "bugs": {
@@ -17,7 +17,7 @@
17
17
  "access": "public"
18
18
  },
19
19
  "bin": {
20
- "loophaus": "./dist/bin/loophaus.js"
20
+ "loophaus": "dist/bin/loophaus.js"
21
21
  },
22
22
  "files": [
23
23
  "dist/",
@@ -43,16 +43,23 @@
43
43
  "prepare": "npm run build"
44
44
  },
45
45
  "engines": {
46
- "node": ">=20.0.0"
46
+ "node": ">=20.0.0",
47
+ "npm": ">=9.0.0"
47
48
  },
48
49
  "keywords": [
49
50
  "loophaus",
50
- "loop",
51
+ "autonomous",
51
52
  "ai-agent",
52
- "iterative-development",
53
+ "coding-agents",
54
+ "fresh-context",
55
+ "prd",
56
+ "quality-scoring",
57
+ "autoresearch",
58
+ "claude-code",
59
+ "codex-cli",
60
+ "kiro-cli",
53
61
  "stop-hook",
54
- "control-plane",
55
- "coding-agents"
62
+ "iterative-development"
56
63
  ],
57
64
  "devDependencies": {
58
65
  "@types/node": "^25.5.0",