@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.
Files changed (2) hide show
  1. package/kai +73 -22
  2. 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/ is git-ignored ───────────────────────
64
+ # ── Ensure .kai/ and Playwright artifacts are git-ignored
65
65
 
66
66
  mkdir -p .kai
67
- if [ ! -f ".kai/.gitignore" ]; then
68
- echo "*" > .kai/.gitignore
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
- if [ "$KAI_STREAM" = true ]; then
343
- claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS --system-prompt "$WORKER_PROMPT" $context_files 2>&1 | tee .kai/worker-output.tmp
344
- exit_code=${PIPESTATUS[0]}
345
- result=$(cat .kai/worker-output.tmp)
346
- else
347
- result=$(claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS --system-prompt "$WORKER_PROMPT" $context_files)
348
- exit_code=$?
349
- echo "$result" | tail -20
350
- fi
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 "Failed (code ${exit_code}). Restarting..."
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
- if [ "$KAI_STREAM" = true ]; then
383
- claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS "$REVIEW_PROMPT" 2>&1 | tee .kai/review-output.tmp
384
- review=$(cat .kai/review-output.tmp)
385
- else
386
- review=$(claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS "$REVIEW_PROMPT")
387
- echo "$review" | tail -5
388
- fi
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 ─────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kraftapps-ai/kai",
3
- "version": "1.8.4",
3
+ "version": "1.8.7",
4
4
  "description": "Autonomous AI developer loop for Claude Code",
5
5
  "bin": {
6
6
  "kai": "kai"