ralph-lisa-loop 0.3.12 → 0.3.13
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/cli.js +10 -0
- package/dist/commands.d.ts +10 -0
- package/dist/commands.js +119 -0
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -98,6 +98,12 @@ switch (cmd) {
|
|
|
98
98
|
case "notify":
|
|
99
99
|
(0, commands_js_1.cmdNotify)(rest);
|
|
100
100
|
break;
|
|
101
|
+
case "smoke-test":
|
|
102
|
+
(0, commands_js_1.cmdSmokeTest)(rest);
|
|
103
|
+
break;
|
|
104
|
+
case "smoke-check":
|
|
105
|
+
(0, commands_js_1.cmdSmokeCheck)(rest);
|
|
106
|
+
break;
|
|
101
107
|
case "help":
|
|
102
108
|
case "--help":
|
|
103
109
|
case "-h":
|
|
@@ -183,6 +189,10 @@ function showHelp() {
|
|
|
183
189
|
console.log(' ralph-lisa emergency-msg <agent> "msg" Send emergency message to agent pane');
|
|
184
190
|
console.log(' ralph-lisa notify "message" Send notification via RL_NOTIFY_CMD');
|
|
185
191
|
console.log("");
|
|
192
|
+
console.log("Smoke Testing:");
|
|
193
|
+
console.log(" ralph-lisa smoke-test Run smoke test (uses RL_SMOKE_CMD)");
|
|
194
|
+
console.log(" ralph-lisa smoke-check Check smoke test environment");
|
|
195
|
+
console.log("");
|
|
186
196
|
console.log("Diagnostics:");
|
|
187
197
|
console.log(" ralph-lisa state-dir Show state directory resolution");
|
|
188
198
|
console.log(" ralph-lisa state-dir /path Set state directory (tmux env)");
|
package/dist/commands.d.ts
CHANGED
|
@@ -58,4 +58,14 @@ export declare function cmdAddContext(args: string[]): void;
|
|
|
58
58
|
export declare function cmdDoctor(args: string[]): void;
|
|
59
59
|
export declare function cmdEmergencyMsg(args: string[]): void;
|
|
60
60
|
export declare function cmdNotify(args: string[]): void;
|
|
61
|
+
/**
|
|
62
|
+
* Run smoke test command and persist results.
|
|
63
|
+
* Called automatically during step transition or manually via `ralph-lisa smoke-test`.
|
|
64
|
+
*/
|
|
65
|
+
export declare function runSmokeTest(dir: string): {
|
|
66
|
+
passed: boolean;
|
|
67
|
+
output: string;
|
|
68
|
+
};
|
|
69
|
+
export declare function cmdSmokeTest(_args: string[]): void;
|
|
70
|
+
export declare function cmdSmokeCheck(_args: string[]): void;
|
|
61
71
|
export {};
|
package/dist/commands.js
CHANGED
|
@@ -69,6 +69,9 @@ exports.cmdAddContext = cmdAddContext;
|
|
|
69
69
|
exports.cmdDoctor = cmdDoctor;
|
|
70
70
|
exports.cmdEmergencyMsg = cmdEmergencyMsg;
|
|
71
71
|
exports.cmdNotify = cmdNotify;
|
|
72
|
+
exports.runSmokeTest = runSmokeTest;
|
|
73
|
+
exports.cmdSmokeTest = cmdSmokeTest;
|
|
74
|
+
exports.cmdSmokeCheck = cmdSmokeCheck;
|
|
72
75
|
const fs = __importStar(require("node:fs"));
|
|
73
76
|
const path = __importStar(require("node:path"));
|
|
74
77
|
const crypto = __importStar(require("node:crypto"));
|
|
@@ -236,6 +239,7 @@ function cmdInit(args) {
|
|
|
236
239
|
(0, state_js_1.writeFile)(path.join(dir, "round.txt"), "1");
|
|
237
240
|
(0, state_js_1.writeFile)(path.join(dir, "step.txt"), "planning");
|
|
238
241
|
(0, state_js_1.writeFile)(path.join(dir, "turn.txt"), "ralph");
|
|
242
|
+
(0, state_js_1.writeFile)(path.join(dir, ".project_root"), process.cwd()); // persist project root for smoke-test cwd
|
|
239
243
|
(0, state_js_1.writeFile)(path.join(dir, "last_action.txt"), "(No action yet)");
|
|
240
244
|
(0, state_js_1.writeFile)(path.join(dir, "plan.md"), "# Plan\n\n(To be drafted by Ralph and reviewed by Lisa)\n");
|
|
241
245
|
(0, state_js_1.writeFile)(path.join(dir, "work.md"), "# Ralph Work\n\n(Waiting for Ralph to submit)\n");
|
|
@@ -775,6 +779,26 @@ function cmdStep(args) {
|
|
|
775
779
|
process.exit(1);
|
|
776
780
|
}
|
|
777
781
|
}
|
|
782
|
+
// Auto smoke test: run if current step had CODE/FIX submissions (step50)
|
|
783
|
+
if (process.env.RL_SMOKE_AUTO !== "false") {
|
|
784
|
+
const history = (0, state_js_1.readFile)(path.join(dir, "history.md"));
|
|
785
|
+
const currentStep = (0, state_js_1.getStep)();
|
|
786
|
+
const escaped = currentStep.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
787
|
+
const stepBlockRe = new RegExp(`^# Step: ${escaped}\\n\\nStarted:`, "gm");
|
|
788
|
+
let lastMatch = null;
|
|
789
|
+
let m;
|
|
790
|
+
while ((m = stepBlockRe.exec(history)) !== null) {
|
|
791
|
+
lastMatch = m;
|
|
792
|
+
}
|
|
793
|
+
const stepSection = lastMatch ? history.slice(lastMatch.index) : "";
|
|
794
|
+
if (/\[CODE\]|\[FIX\]/.test(stepSection)) {
|
|
795
|
+
console.log(`[Smoke] Development step detected (CODE/FIX found). Running smoke test...`);
|
|
796
|
+
runSmokeTest(dir);
|
|
797
|
+
}
|
|
798
|
+
else {
|
|
799
|
+
console.log(`[Smoke] Planning step (no CODE/FIX). Skipping smoke test.`);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
778
802
|
(0, state_js_1.setStep)(stepName);
|
|
779
803
|
(0, state_js_1.setRound)(1);
|
|
780
804
|
(0, state_js_1.setTurn)("ralph");
|
|
@@ -3344,3 +3368,98 @@ function cmdNotify(args) {
|
|
|
3344
3368
|
notifyUser(message);
|
|
3345
3369
|
console.log(`Notification sent: ${message}`);
|
|
3346
3370
|
}
|
|
3371
|
+
// ─── smoke test ───────────────────────────────────
|
|
3372
|
+
/**
|
|
3373
|
+
* Run smoke test command and persist results.
|
|
3374
|
+
* Called automatically during step transition or manually via `ralph-lisa smoke-test`.
|
|
3375
|
+
*/
|
|
3376
|
+
function runSmokeTest(dir) {
|
|
3377
|
+
const cmd = process.env.RL_SMOKE_CMD;
|
|
3378
|
+
if (!cmd) {
|
|
3379
|
+
console.log("[Smoke] No RL_SMOKE_CMD configured. Skipping smoke test.");
|
|
3380
|
+
return { passed: true, output: "Skipped: RL_SMOKE_CMD not configured" };
|
|
3381
|
+
}
|
|
3382
|
+
const debug = process.env.RL_SMOKE_DEBUG === "true";
|
|
3383
|
+
console.log(`[Smoke] Running: ${cmd}`);
|
|
3384
|
+
const ts = new Date().toISOString();
|
|
3385
|
+
const startTime = Date.now();
|
|
3386
|
+
let exitCode = 0;
|
|
3387
|
+
let output = "";
|
|
3388
|
+
try {
|
|
3389
|
+
output = (0, node_child_process_1.execSync)(cmd, {
|
|
3390
|
+
cwd: (0, state_js_1.readFile)(path.join(dir, ".project_root")).trim() || (0, state_js_1.findProjectRoot)() || process.cwd(), // persisted root > upward search > cwd
|
|
3391
|
+
encoding: "utf-8",
|
|
3392
|
+
timeout: 300000, // 5 min
|
|
3393
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
3394
|
+
});
|
|
3395
|
+
}
|
|
3396
|
+
catch (e) {
|
|
3397
|
+
exitCode = e.status || 1;
|
|
3398
|
+
output = (e.stdout || "") + "\n" + (e.stderr || "");
|
|
3399
|
+
}
|
|
3400
|
+
const duration = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
3401
|
+
const passed = exitCode === 0;
|
|
3402
|
+
// Persist results (append)
|
|
3403
|
+
const resultsFile = path.join(dir, "smoke-results.md");
|
|
3404
|
+
const last50 = output.split("\n").slice(-50).join("\n");
|
|
3405
|
+
const entry = `\n## Run: ${ts}\n- Command: ${cmd}\n- Exit code: ${exitCode}\n- Duration: ${duration}s\n- Result: ${passed ? "PASSED" : "FAILED"}\n\n### Output (last 50 lines)\n\`\`\`\n${last50}\n\`\`\`\n`;
|
|
3406
|
+
// Create header if file doesn't exist
|
|
3407
|
+
if (!fs.existsSync(resultsFile)) {
|
|
3408
|
+
fs.writeFileSync(resultsFile, "# Smoke Test Results\n");
|
|
3409
|
+
}
|
|
3410
|
+
fs.appendFileSync(resultsFile, entry);
|
|
3411
|
+
// Debug log (full output, overwrite)
|
|
3412
|
+
if (debug) {
|
|
3413
|
+
const debugFile = path.join(dir, "smoke-debug.log");
|
|
3414
|
+
fs.writeFileSync(debugFile, `# Smoke Debug Log\n# ${ts}\n# Command: ${cmd}\n# Exit code: ${exitCode}\n\n${output}`);
|
|
3415
|
+
console.log(`[Smoke] Debug log: ${debugFile}`);
|
|
3416
|
+
}
|
|
3417
|
+
if (passed) {
|
|
3418
|
+
console.log(`[Smoke] PASSED (${duration}s)`);
|
|
3419
|
+
}
|
|
3420
|
+
else {
|
|
3421
|
+
console.log(`[Smoke] FAILED (exit code ${exitCode}, ${duration}s)`);
|
|
3422
|
+
console.log("[Smoke] Results saved to .dual-agent/smoke-results.md");
|
|
3423
|
+
}
|
|
3424
|
+
return { passed, output: last50 };
|
|
3425
|
+
}
|
|
3426
|
+
function cmdSmokeTest(_args) {
|
|
3427
|
+
const dir = (0, state_js_1.stateDir)();
|
|
3428
|
+
const result = runSmokeTest(dir);
|
|
3429
|
+
process.exit(result.passed ? 0 : 1);
|
|
3430
|
+
}
|
|
3431
|
+
function cmdSmokeCheck(_args) {
|
|
3432
|
+
const cmd = process.env.RL_SMOKE_CMD;
|
|
3433
|
+
console.log(line());
|
|
3434
|
+
console.log("Smoke Test Environment Check");
|
|
3435
|
+
console.log(line());
|
|
3436
|
+
if (!cmd) {
|
|
3437
|
+
console.log(" RL_SMOKE_CMD: (not set)");
|
|
3438
|
+
console.log("");
|
|
3439
|
+
console.log(" Configure your project's smoke test command:");
|
|
3440
|
+
console.log(' export RL_SMOKE_CMD="npm run test:e2e"');
|
|
3441
|
+
console.log(' export RL_SMOKE_CMD="pytest tests/smoke/"');
|
|
3442
|
+
console.log(' export RL_SMOKE_CMD="flutter test integration_test/"');
|
|
3443
|
+
console.log("");
|
|
3444
|
+
console.log(" Then run: ralph-lisa smoke-check");
|
|
3445
|
+
process.exit(1);
|
|
3446
|
+
}
|
|
3447
|
+
console.log(` RL_SMOKE_CMD: ${cmd}`);
|
|
3448
|
+
// Check base command exists
|
|
3449
|
+
const baseCmd = cmd.split(/\s+/)[0];
|
|
3450
|
+
try {
|
|
3451
|
+
(0, node_child_process_1.execSync)(`command -v "${baseCmd}" 2>/dev/null`, { stdio: "pipe" });
|
|
3452
|
+
console.log(` Base command '${baseCmd}': OK`);
|
|
3453
|
+
}
|
|
3454
|
+
catch {
|
|
3455
|
+
console.log(` Base command '${baseCmd}': NOT FOUND`);
|
|
3456
|
+
console.log("");
|
|
3457
|
+
console.log(` Install '${baseCmd}' or adjust RL_SMOKE_CMD.`);
|
|
3458
|
+
process.exit(1);
|
|
3459
|
+
}
|
|
3460
|
+
console.log(` RL_SMOKE_AUTO: ${process.env.RL_SMOKE_AUTO || "true"} (auto-trigger on step transition)`);
|
|
3461
|
+
console.log(` RL_SMOKE_DEBUG: ${process.env.RL_SMOKE_DEBUG || "false"} (full output capture)`);
|
|
3462
|
+
console.log("");
|
|
3463
|
+
console.log(` Tip: run the full command manually to verify: ${cmd}`);
|
|
3464
|
+
console.log(line());
|
|
3465
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ralph-lisa-loop",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.13",
|
|
4
4
|
"description": "Turn-based dual-agent collaboration: Ralph codes, Lisa reviews, consensus required.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ralph-lisa": "dist/cli.js"
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "tsc",
|
|
11
11
|
"test": "node --test dist/test/*.js",
|
|
12
|
+
"test:smoke": "node --test dist/test/smoke.test.js",
|
|
12
13
|
"prepack": "npm run build"
|
|
13
14
|
},
|
|
14
15
|
"files": [
|