@kraftapps-ai/kai 1.8.3 → 1.8.6

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 +67 -23
  2. package/package.json +1 -1
package/kai CHANGED
@@ -227,6 +227,9 @@ PRD_FILE=".kai/stories.json"
227
227
  PROGRESS_FILE=".kai/progress.txt"
228
228
  LOOP_MCP_ARGS="--mcp-config .kai/loop-mcp.json"
229
229
 
230
+ # Cap Node.js memory to prevent test runners from consuming all RAM
231
+ export NODE_OPTIONS="--max-old-space-size=2048"
232
+
230
233
  # Stream output live when running in a tmux pane
231
234
  KAI_STREAM=false
232
235
  if [ -n "${TMUX:-}" ]; then
@@ -265,11 +268,15 @@ You are an expert Shopify developer. You have access to the Shopify Dev MCP tool
265
268
  2. Read .kai/progress.txt for context on previous work.
266
269
  3. **PLAN before coding.** List files and changes before touching code.
267
270
  4. If the story involves Shopify APIs, call `learn_shopify_api` then use `introspect_graphql_schema` and `search_docs_chunks` to understand the right approach.
268
- 5. **WRITE FAILING TESTS FIRST.** For each acceptance criterion, write a test that verifies it. Run the tests — they MUST fail (red). If a test already passes, your test is not testing the right thing.
269
- 6. **Implement ONLY enough code to make the tests pass (green).** No more, no less.
271
+ 5. **WRITE FAILING TESTS FIRST.** For each acceptance criterion, write a test that verifies it. Run ONLY the relevant test file(s) — they MUST fail (red). If a test already passes, your test is not testing the right thing.
272
+ 6. **Implement ONLY enough code to make the tests pass (green).** No more, no less. Run only the relevant test file(s) to verify.
270
273
  7. **Refactor** if needed — clean up while keeping tests green.
271
- 8. Validate: run full test suite, validate GraphQL with `validate_graphql_codeblocks`, validate Liquid with `validate_theme_codeblocks`.
274
+ 8. **Final validation ONCE:** Run the full test suite ONE TIME at the end. Also validate GraphQL with `validate_graphql_codeblocks`, validate Liquid with `validate_theme_codeblocks`.
272
275
  9. **SELF-REVIEW.** For each acceptance criterion, cite the test that covers it AND evidence it passes (file, line, command output). No "should work" or "probably".
276
+
277
+ ## IMPORTANT: Resource management
278
+ - **NEVER run the full test suite repeatedly.** Run targeted tests during development (e.g., `npx vitest run path/to/test.ts`). Only run the full suite ONCE as a final check before committing.
279
+ - **Always use `npx vitest run`** (not `npx vitest` without `run`) — watch mode will hang forever.
273
280
  10. Commit with a descriptive message.
274
281
  11. Update .kai/stories.json: set `passes` to `true`.
275
282
  12. Append to .kai/progress.txt.
@@ -278,7 +285,7 @@ You are an expert Shopify developer. You have access to the Shopify Dev MCP tool
278
285
  - ONE STORY PER LOOP.
279
286
  - **TDD is mandatory.** Tests first, then implementation. No exceptions.
280
287
  - No placeholders. Fully implement or report BLOCKED.
281
- - Do not break existing functionality. Run the FULL test suite, not just your new tests.
288
+ - Do not break existing functionality. Run the full test suite ONCE at the end as a final check.
282
289
  - ALWAYS validate GraphQL and Liquid code using the MCP tools before marking complete.
283
290
  - If ALL stories have `passes: true`, output: <promise>COMPLETE</promise>
284
291
 
@@ -331,25 +338,51 @@ while :; do
331
338
 
332
339
  start_time=$(date +%s)
333
340
 
341
+ # Run worker in background with heartbeat monitor
334
342
  set +e
335
- if [ "$KAI_STREAM" = true ]; then
336
- claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS --system-prompt "$WORKER_PROMPT" $context_files 2>&1 | tee .kai/worker-output.tmp
337
- exit_code=${PIPESTATUS[0]}
338
- result=$(cat .kai/worker-output.tmp)
339
- else
340
- result=$(claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS --system-prompt "$WORKER_PROMPT" $context_files)
341
- exit_code=$?
342
- echo "$result" | tail -20
343
- fi
343
+ touch .kai/worker-heartbeat
344
+ claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS --system-prompt "$WORKER_PROMPT" $context_files > .kai/worker-output.tmp 2>&1 &
345
+ worker_pid=$!
346
+
347
+ echo " Worker started (PID $worker_pid)"
348
+ while kill -0 $worker_pid 2>/dev/null; do
349
+ sleep 30
350
+ elapsed_now=$(( $(date +%s) - start_time ))
351
+ mins=$((elapsed_now / 60))
352
+ secs=$((elapsed_now % 60))
353
+
354
+ # Detect what's running
355
+ activity=""
356
+ pgrep -f "vitest" > /dev/null 2>&1 && activity="running tests"
357
+ pgrep -f "esbuild" > /dev/null 2>&1 && activity="${activity:+$activity + }building"
358
+ pgrep -f "npm run build" > /dev/null 2>&1 && activity="${activity:+$activity + }building"
359
+ [ -z "$activity" ] && activity="thinking"
360
+
361
+ # Show recently changed files
362
+ changed=$(find . \( -name '*.ts' -o -name '*.tsx' -o -name '*.php' -o -name '*.less' -o -name '*.css' -o -name '*.json' \) \
363
+ -not -path './node_modules/*' -not -path './.kai/*' -not -path './vendor/*' \
364
+ -newer .kai/worker-heartbeat -printf '%f\n' 2>/dev/null | sort -u | head -5 | tr '\n' ', ')
365
+
366
+ echo " [${mins}m${secs}s] ${activity}${changed:+ | files: ${changed%,}}"
367
+ touch .kai/worker-heartbeat
368
+ done
369
+
370
+ wait $worker_pid
371
+ exit_code=$?
372
+ result=$(cat .kai/worker-output.tmp)
344
373
  set -e
345
374
 
346
375
  elapsed=$(( $(date +%s) - start_time ))
347
376
 
348
377
  if [ $exit_code -ne 0 ]; then
349
- echo "Failed (code ${exit_code}). Restarting..."
378
+ echo " Worker failed (code ${exit_code}). Last output:"
379
+ echo "$result" | tail -10
380
+ echo " Restarting..."
350
381
  continue
351
382
  fi
352
383
 
384
+ echo "$result" | tail -20
385
+
353
386
  if [[ "$result" == *"<promise>COMPLETE</promise>"* ]]; then
354
387
  echo "All stories complete after $iteration iterations!"
355
388
  exit 0
@@ -358,6 +391,7 @@ while :; do
358
391
  # Review
359
392
  STORY_PASSES=$(jq -r --arg id "$NEXT_ID" '.userStories[] | select(.id == $id) | .passes' "$PRD_FILE")
360
393
  if [ "$STORY_PASSES" = "true" ]; then
394
+ echo " Reviewing story #${NEXT_ID}..."
361
395
  last_commit=$(git log --oneline -1 2>/dev/null || echo "no git")
362
396
  ACCEPTANCE=$(jq -r --arg id "$NEXT_ID" '.userStories[] | select(.id == $id) | .acceptanceCriteria | join("\n- ")' "$PRD_FILE")
363
397
 
@@ -372,15 +406,21 @@ If ANY fails: REVIEW_FAIL: [reason]
372
406
  If all pass: REVIEW_PASS"
373
407
 
374
408
  set +e
375
- if [ "$KAI_STREAM" = true ]; then
376
- claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS "$REVIEW_PROMPT" 2>&1 | tee .kai/review-output.tmp
377
- review=$(cat .kai/review-output.tmp)
378
- else
379
- review=$(claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS "$REVIEW_PROMPT")
380
- echo "$review" | tail -5
381
- fi
409
+ claude -p --dangerously-skip-permissions $LOOP_MCP_ARGS "$REVIEW_PROMPT" > .kai/review-output.tmp 2>&1 &
410
+ review_pid=$!
411
+
412
+ while kill -0 $review_pid 2>/dev/null; do
413
+ sleep 15
414
+ elapsed_now=$(( $(date +%s) - start_time ))
415
+ echo " [${elapsed_now}s] reviewing..."
416
+ done
417
+
418
+ wait $review_pid
419
+ review=$(cat .kai/review-output.tmp)
382
420
  set -e
383
421
 
422
+ echo "$review" | tail -5
423
+
384
424
  if [[ "$review" == *"REVIEW_FAIL"* ]]; then
385
425
  jq --arg id "$NEXT_ID" '(.userStories[] | select(.id == $id)).passes = false' "$PRD_FILE" > "${PRD_FILE}.tmp" && mv "${PRD_FILE}.tmp" "$PRD_FILE"
386
426
  echo "REVIEW FEEDBACK: $review" >> "$PROGRESS_FILE"
@@ -452,12 +492,16 @@ The developer's name is: ${dev_name}"
452
492
 
453
493
  # ── Build loop run instructions for PM ────────────────
454
494
 
495
+ 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."
496
+
455
497
  if [ "$KAI_TMUX" = true ] || [ -n "${TMUX:-}" ]; then
456
498
  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\`
457
499
  The dev loop output streams live in the right tmux pane. You can also check \`tail -f .kai/loop.log\`.
458
- To stop the loop: \`tmux send-keys -t ${KAI_TMUX_SESSION}:0.1 C-c\`"
500
+ To stop the loop: \`tmux send-keys -t ${KAI_TMUX_SESSION}:0.1 C-c\`
501
+ ${LOOP_MONITOR}"
459
502
  else
460
- LOOP_INSTRUCTIONS="To run implementation, execute: \`nohup .kai/loop.sh > .kai/loop.log 2>&1 &\` then monitor with \`tail -f .kai/loop.log\`"
503
+ LOOP_INSTRUCTIONS="To run implementation, execute: \`nohup .kai/loop.sh > .kai/loop.log 2>&1 &\` then monitor with \`tail -f .kai/loop.log\`
504
+ ${LOOP_MONITOR}"
461
505
  fi
462
506
 
463
507
  # ── Build Claude args ─────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kraftapps-ai/kai",
3
- "version": "1.8.3",
3
+ "version": "1.8.6",
4
4
  "description": "Autonomous AI developer loop for Claude Code",
5
5
  "bin": {
6
6
  "kai": "kai"