@kraftapps-ai/kai 1.8.4 → 1.8.7
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/kai +73 -22
- package/package.json +1 -1
package/kai
CHANGED
|
@@ -61,11 +61,25 @@ MEMORY_FILE=".kai/memory.md"
|
|
|
61
61
|
LOOP_SCRIPT=".kai/loop.sh"
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
# ── Ensure .kai/
|
|
64
|
+
# ── Ensure .kai/ and Playwright artifacts are git-ignored ─
|
|
65
65
|
|
|
66
66
|
mkdir -p .kai
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
|
|
68
|
+
# Add to project .gitignore (not just .kai/.gitignore) to prevent tracking
|
|
69
|
+
if [ -f ".gitignore" ]; then
|
|
70
|
+
for pattern in ".kai/" ".playwright-mcp/"; do
|
|
71
|
+
grep -qxF "$pattern" .gitignore 2>/dev/null || echo "$pattern" >> .gitignore
|
|
72
|
+
done
|
|
73
|
+
else
|
|
74
|
+
printf '%s\n' ".kai/" ".playwright-mcp/" > .gitignore
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Untrack .kai/ files if they were committed before the gitignore existed
|
|
78
|
+
if git ls-files --cached .kai/ 2>/dev/null | grep -q .; then
|
|
79
|
+
git rm -r --cached .kai/ > /dev/null 2>&1 || true
|
|
80
|
+
fi
|
|
81
|
+
if git ls-files --cached .playwright-mcp/ 2>/dev/null | grep -q .; then
|
|
82
|
+
git rm -r --cached .playwright-mcp/ > /dev/null 2>&1 || true
|
|
69
83
|
fi
|
|
70
84
|
|
|
71
85
|
# ── Auto-init if needed ───────────────────────────────
|
|
@@ -338,25 +352,51 @@ while :; do
|
|
|
338
352
|
|
|
339
353
|
start_time=$(date +%s)
|
|
340
354
|
|
|
355
|
+
# Run worker in background with heartbeat monitor
|
|
341
356
|
set +e
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
357
|
+
touch .kai/worker-heartbeat
|
|
358
|
+
claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS --system-prompt "$WORKER_PROMPT" $context_files > .kai/worker-output.tmp 2>&1 &
|
|
359
|
+
worker_pid=$!
|
|
360
|
+
|
|
361
|
+
echo " Worker started (PID $worker_pid)"
|
|
362
|
+
while kill -0 $worker_pid 2>/dev/null; do
|
|
363
|
+
sleep 30
|
|
364
|
+
elapsed_now=$(( $(date +%s) - start_time ))
|
|
365
|
+
mins=$((elapsed_now / 60))
|
|
366
|
+
secs=$((elapsed_now % 60))
|
|
367
|
+
|
|
368
|
+
# Detect what's running
|
|
369
|
+
activity=""
|
|
370
|
+
pgrep -f "vitest" > /dev/null 2>&1 && activity="running tests"
|
|
371
|
+
pgrep -f "esbuild" > /dev/null 2>&1 && activity="${activity:+$activity + }building"
|
|
372
|
+
pgrep -f "npm run build" > /dev/null 2>&1 && activity="${activity:+$activity + }building"
|
|
373
|
+
[ -z "$activity" ] && activity="thinking"
|
|
374
|
+
|
|
375
|
+
# Show recently changed files
|
|
376
|
+
changed=$(find . \( -name '*.ts' -o -name '*.tsx' -o -name '*.php' -o -name '*.less' -o -name '*.css' -o -name '*.json' \) \
|
|
377
|
+
-not -path './node_modules/*' -not -path './.kai/*' -not -path './vendor/*' \
|
|
378
|
+
-newer .kai/worker-heartbeat -printf '%f\n' 2>/dev/null | sort -u | head -5 | tr '\n' ', ')
|
|
379
|
+
|
|
380
|
+
echo " [${mins}m${secs}s] ${activity}${changed:+ | files: ${changed%,}}"
|
|
381
|
+
touch .kai/worker-heartbeat
|
|
382
|
+
done
|
|
383
|
+
|
|
384
|
+
wait $worker_pid
|
|
385
|
+
exit_code=$?
|
|
386
|
+
result=$(cat .kai/worker-output.tmp)
|
|
351
387
|
set -e
|
|
352
388
|
|
|
353
389
|
elapsed=$(( $(date +%s) - start_time ))
|
|
354
390
|
|
|
355
391
|
if [ $exit_code -ne 0 ]; then
|
|
356
|
-
echo "
|
|
392
|
+
echo " Worker failed (code ${exit_code}). Last output:"
|
|
393
|
+
echo "$result" | tail -10
|
|
394
|
+
echo " Restarting..."
|
|
357
395
|
continue
|
|
358
396
|
fi
|
|
359
397
|
|
|
398
|
+
echo "$result" | tail -20
|
|
399
|
+
|
|
360
400
|
if [[ "$result" == *"<promise>COMPLETE</promise>"* ]]; then
|
|
361
401
|
echo "All stories complete after $iteration iterations!"
|
|
362
402
|
exit 0
|
|
@@ -365,6 +405,7 @@ while :; do
|
|
|
365
405
|
# Review
|
|
366
406
|
STORY_PASSES=$(jq -r --arg id "$NEXT_ID" '.userStories[] | select(.id == $id) | .passes' "$PRD_FILE")
|
|
367
407
|
if [ "$STORY_PASSES" = "true" ]; then
|
|
408
|
+
echo " Reviewing story #${NEXT_ID}..."
|
|
368
409
|
last_commit=$(git log --oneline -1 2>/dev/null || echo "no git")
|
|
369
410
|
ACCEPTANCE=$(jq -r --arg id "$NEXT_ID" '.userStories[] | select(.id == $id) | .acceptanceCriteria | join("\n- ")' "$PRD_FILE")
|
|
370
411
|
|
|
@@ -379,15 +420,21 @@ If ANY fails: REVIEW_FAIL: [reason]
|
|
|
379
420
|
If all pass: REVIEW_PASS"
|
|
380
421
|
|
|
381
422
|
set +e
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
423
|
+
claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS "$REVIEW_PROMPT" > .kai/review-output.tmp 2>&1 &
|
|
424
|
+
review_pid=$!
|
|
425
|
+
|
|
426
|
+
while kill -0 $review_pid 2>/dev/null; do
|
|
427
|
+
sleep 15
|
|
428
|
+
elapsed_now=$(( $(date +%s) - start_time ))
|
|
429
|
+
echo " [${elapsed_now}s] reviewing..."
|
|
430
|
+
done
|
|
431
|
+
|
|
432
|
+
wait $review_pid
|
|
433
|
+
review=$(cat .kai/review-output.tmp)
|
|
389
434
|
set -e
|
|
390
435
|
|
|
436
|
+
echo "$review" | tail -5
|
|
437
|
+
|
|
391
438
|
if [[ "$review" == *"REVIEW_FAIL"* ]]; then
|
|
392
439
|
jq --arg id "$NEXT_ID" '(.userStories[] | select(.id == $id)).passes = false' "$PRD_FILE" > "${PRD_FILE}.tmp" && mv "${PRD_FILE}.tmp" "$PRD_FILE"
|
|
393
440
|
echo "REVIEW FEEDBACK: $review" >> "$PROGRESS_FILE"
|
|
@@ -459,12 +506,16 @@ The developer's name is: ${dev_name}"
|
|
|
459
506
|
|
|
460
507
|
# ── Build loop run instructions for PM ────────────────
|
|
461
508
|
|
|
509
|
+
LOOP_MONITOR="After starting the loop, IMMEDIATELY run \`/loop 5m\` with a prompt that reads .kai/stories.json and .kai/progress.txt to check progress, then report a brief status update to the developer (e.g., \"Story #X complete, working on #Y, 3 remaining\"). Stop the /loop when all stories are done or the loop has stopped."
|
|
510
|
+
|
|
462
511
|
if [ "$KAI_TMUX" = true ] || [ -n "${TMUX:-}" ]; then
|
|
463
512
|
LOOP_INSTRUCTIONS="To run implementation, execute: \`tmux send-keys -t ${KAI_TMUX_SESSION}:0.1 '.kai/loop.sh 2>&1 | tee .kai/loop.log' Enter\`
|
|
464
513
|
The dev loop output streams live in the right tmux pane. You can also check \`tail -f .kai/loop.log\`.
|
|
465
|
-
To stop the loop: \`tmux send-keys -t ${KAI_TMUX_SESSION}:0.1 C-c\`
|
|
514
|
+
To stop the loop: \`tmux send-keys -t ${KAI_TMUX_SESSION}:0.1 C-c\`
|
|
515
|
+
${LOOP_MONITOR}"
|
|
466
516
|
else
|
|
467
|
-
LOOP_INSTRUCTIONS="To run implementation, execute: \`nohup .kai/loop.sh > .kai/loop.log 2>&1 &\` then monitor with \`tail -f .kai/loop.log\`
|
|
517
|
+
LOOP_INSTRUCTIONS="To run implementation, execute: \`nohup .kai/loop.sh > .kai/loop.log 2>&1 &\` then monitor with \`tail -f .kai/loop.log\`
|
|
518
|
+
${LOOP_MONITOR}"
|
|
468
519
|
fi
|
|
469
520
|
|
|
470
521
|
# ── Build Claude args ─────────────────────────────────
|