specweave 1.0.259 → 1.0.260

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 (63) hide show
  1. package/CLAUDE.md +39 -25
  2. package/bin/specweave.js +11 -0
  3. package/dist/dashboard/assets/index-DdtF4K1G.css +1 -0
  4. package/dist/dashboard/assets/index-cZA6rz8s.js +11 -0
  5. package/dist/dashboard/index.html +14 -0
  6. package/dist/src/cli/commands/dashboard.d.ts +18 -0
  7. package/dist/src/cli/commands/dashboard.d.ts.map +1 -0
  8. package/dist/src/cli/commands/dashboard.js +142 -0
  9. package/dist/src/cli/commands/dashboard.js.map +1 -0
  10. package/dist/src/core/lazy-loading/llm-plugin-detector.d.ts +9 -4
  11. package/dist/src/core/lazy-loading/llm-plugin-detector.d.ts.map +1 -1
  12. package/dist/src/core/lazy-loading/llm-plugin-detector.js +9 -4
  13. package/dist/src/core/lazy-loading/llm-plugin-detector.js.map +1 -1
  14. package/dist/src/dashboard/server/command-runner.d.ts +21 -0
  15. package/dist/src/dashboard/server/command-runner.d.ts.map +1 -0
  16. package/dist/src/dashboard/server/command-runner.js +92 -0
  17. package/dist/src/dashboard/server/command-runner.js.map +1 -0
  18. package/dist/src/dashboard/server/dashboard-server.d.ts +33 -0
  19. package/dist/src/dashboard/server/dashboard-server.d.ts.map +1 -0
  20. package/dist/src/dashboard/server/dashboard-server.js +812 -0
  21. package/dist/src/dashboard/server/dashboard-server.js.map +1 -0
  22. package/dist/src/dashboard/server/data/activity-stream.d.ts +27 -0
  23. package/dist/src/dashboard/server/data/activity-stream.d.ts.map +1 -0
  24. package/dist/src/dashboard/server/data/activity-stream.js +142 -0
  25. package/dist/src/dashboard/server/data/activity-stream.js.map +1 -0
  26. package/dist/src/dashboard/server/data/claude-log-parser.d.ts +34 -0
  27. package/dist/src/dashboard/server/data/claude-log-parser.d.ts.map +1 -0
  28. package/dist/src/dashboard/server/data/claude-log-parser.js +218 -0
  29. package/dist/src/dashboard/server/data/claude-log-parser.js.map +1 -0
  30. package/dist/src/dashboard/server/data/dashboard-data-aggregator.d.ts +35 -0
  31. package/dist/src/dashboard/server/data/dashboard-data-aggregator.d.ts.map +1 -0
  32. package/dist/src/dashboard/server/data/dashboard-data-aggregator.js +219 -0
  33. package/dist/src/dashboard/server/data/dashboard-data-aggregator.js.map +1 -0
  34. package/dist/src/dashboard/server/data/plugin-scanner.d.ts +35 -0
  35. package/dist/src/dashboard/server/data/plugin-scanner.d.ts.map +1 -0
  36. package/dist/src/dashboard/server/data/plugin-scanner.js +96 -0
  37. package/dist/src/dashboard/server/data/plugin-scanner.js.map +1 -0
  38. package/dist/src/dashboard/server/data/sync-audit-reader.d.ts +38 -0
  39. package/dist/src/dashboard/server/data/sync-audit-reader.d.ts.map +1 -0
  40. package/dist/src/dashboard/server/data/sync-audit-reader.js +94 -0
  41. package/dist/src/dashboard/server/data/sync-audit-reader.js.map +1 -0
  42. package/dist/src/dashboard/server/file-watcher.d.ts +19 -0
  43. package/dist/src/dashboard/server/file-watcher.d.ts.map +1 -0
  44. package/dist/src/dashboard/server/file-watcher.js +104 -0
  45. package/dist/src/dashboard/server/file-watcher.js.map +1 -0
  46. package/dist/src/dashboard/server/router.d.ts +16 -0
  47. package/dist/src/dashboard/server/router.d.ts.map +1 -0
  48. package/dist/src/dashboard/server/router.js +110 -0
  49. package/dist/src/dashboard/server/router.js.map +1 -0
  50. package/dist/src/dashboard/server/sse-manager.d.ts +25 -0
  51. package/dist/src/dashboard/server/sse-manager.d.ts.map +1 -0
  52. package/dist/src/dashboard/server/sse-manager.js +75 -0
  53. package/dist/src/dashboard/server/sse-manager.js.map +1 -0
  54. package/dist/src/dashboard/types.d.ts +183 -0
  55. package/dist/src/dashboard/types.d.ts.map +1 -0
  56. package/dist/src/dashboard/types.js +2 -0
  57. package/dist/src/dashboard/types.js.map +1 -0
  58. package/package.json +12 -2
  59. package/plugins/specweave/hooks/user-prompt-submit.sh +79 -154
  60. package/plugins/specweave/skills/do/SKILL.md +31 -1
  61. package/plugins/specweave/skills/increment/SKILL.md +1 -1
  62. package/plugins/specweave/skills/increment-planner/SKILL.md +26 -0
  63. package/plugins/specweave/skills/increment-work-router/SKILL.md +37 -9
@@ -372,9 +372,8 @@ escape_json_early() {
372
372
  }
373
373
 
374
374
  # v1.0.254: Prompt safety limits to prevent "Prompt is too long" errors
375
- # These must match the constants in src/core/lazy-loading/llm-plugin-detector.ts
375
+ # Must match MAX_ADDITIONAL_CONTEXT_LENGTH in src/core/lazy-loading/llm-plugin-detector.ts
376
376
  MAX_ADDITIONAL_CONTEXT_LENGTH=3000
377
- MAX_SKILL_FIRST_PROMPT_LENGTH=800
378
377
 
379
378
  # Helper: Output approve response with context (Claude Code hook format v1.0.166)
380
379
  # CRITICAL: systemMessage is NOT a valid field for UserPromptSubmit hooks!
@@ -386,7 +385,10 @@ MAX_SKILL_FIRST_PROMPT_LENGTH=800
386
385
  output_approve_with_context() {
387
386
  local context="$1"
388
387
  # v1.0.254: Safety truncation to prevent prompt overflow
388
+ # v1.0.260: Added overflow logging for debugging context budget issues
389
389
  if [[ ${#context} -gt $MAX_ADDITIONAL_CONTEXT_LENGTH ]]; then
390
+ local overflow_by=$(( ${#context} - MAX_ADDITIONAL_CONTEXT_LENGTH ))
391
+ echo "[$(date -Iseconds)] CONTEXT OVERFLOW | size=${#context} | max=$MAX_ADDITIONAL_CONTEXT_LENGTH | overflow_by=$overflow_by | truncating" >> "${LAZY_LOAD_LOG:-/dev/null}" 2>/dev/null
390
392
  context="${context:0:$MAX_ADDITIONAL_CONTEXT_LENGTH}... [context truncated for safety]"
391
393
  fi
392
394
  local escaped
@@ -394,16 +396,9 @@ output_approve_with_context() {
394
396
  printf '{"hookSpecificOutput":{"hookEventName":"UserPromptSubmit","additionalContext":"%s"}}\n' "$escaped"
395
397
  }
396
398
 
397
- # Helper: Truncate and escape a prompt for SKILL FIRST args (v1.0.254)
398
- # Truncates to MAX_SKILL_FIRST_PROMPT_LENGTH, escapes for JSON embedding.
399
- # Args: $1=raw prompt text
400
- # Returns: Escaped, truncated prompt on stdout
401
- truncate_and_escape_prompt() {
402
- local prompt="$1"
403
- local truncated="${prompt:0:$MAX_SKILL_FIRST_PROMPT_LENGTH}"
404
- [[ ${#prompt} -gt $MAX_SKILL_FIRST_PROMPT_LENGTH ]] && truncated="${truncated}... [truncated - see original prompt above]"
405
- printf '%s' "$truncated" | sed 's/\\/\\\\/g; s/"/\\"/g; s/ /\\t/g' | tr '\n' ' '
406
- }
399
+ # v1.0.260: truncate_and_escape_prompt() removed prompt embedding in SKILL FIRST
400
+ # was eliminated to save ~800 chars of context budget per turn. The skill reads
401
+ # the user's prompt from conversation context (it's already there).
407
402
 
408
403
  # Helper: Check if plugin is installed by reading installed_plugins.json (v1.0.175)
409
404
  # This is the SOURCE OF TRUTH - more reliable than `claude plugin list` which can have timing issues.
@@ -1169,48 +1164,28 @@ if [[ "${SPECWEAVE_DISABLE_AUTO_LOAD:-0}" != "1" ]] && [[ "${SPECWEAVE_DISABLE_H
1169
1164
 
1170
1165
  # Build feedback message
1171
1166
  if [[ -n "$PLUGINS_INSTALLED" ]]; then
1172
- # v1.0.171: STRICT BLOCKING restart warning with explicit tool blocklist
1173
- # Truncate prompt for display (max 500 chars to avoid bloat)
1174
- PROMPT_DISPLAY="${PROMPT:0:500}"
1175
- [[ ${#PROMPT} -gt 500 ]] && PROMPT_DISPLAY="${PROMPT_DISPLAY}..."
1176
- # Escape for JSON/markdown
1177
- PROMPT_DISPLAY=$(echo "$PROMPT_DISPLAY" | sed 's/\\/\\\\/g; s/"/\\"/g; s/`/\\`/g')
1178
-
1179
- AUTOLOAD_PLUGINS_MSG="\\n╔══════════════════════════════════════════════════════════════════════════════╗\\n"
1180
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}║ 🛑 FULL STOP - RESTART REQUIRED - DO NOT PROCEED ║\\n"
1181
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}╚══════════════════════════════════════════════════════════════════════════════╝\\n\\n"
1182
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}**Plugins installed**: ${PLUGINS_INSTALLED}\\n\\n"
1183
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}These plugins are NOT available in the current session. A restart is MANDATORY.\\n\\n"
1184
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}┌──────────────────────────────────────────────────────────────────────────────┐\\n"
1185
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}│ ⛔ YOU ARE BLOCKED FROM THE FOLLOWING ACTIONS: │\\n"
1186
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}├──────────────────────────────────────────────────────────────────────────────┤\\n"
1187
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}│ ❌ Write tool - BLOCKED (cannot create files) │\\n"
1188
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}│ ❌ Edit tool - BLOCKED (cannot modify files) │\\n"
1189
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}│ ❌ Bash tool - BLOCKED (except read-only commands) │\\n"
1190
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}│ ❌ Task tool - BLOCKED (agents need plugins) │\\n"
1191
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}│ ❌ Implementation - BLOCKED (no coding until restart) │\\n"
1192
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}└──────────────────────────────────────────────────────────────────────────────┘\\n\\n"
1193
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}┌──────────────────────────────────────────────────────────────────────────────┐\\n"
1194
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}│ ✅ YOUR ONLY ALLOWED ACTIONS: │\\n"
1195
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}├──────────────────────────────────────────────────────────────────────────────┤\\n"
1196
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}│ 1. Display this restart warning to user │\\n"
1197
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}│ 2. Provide the prompt below for user to copy │\\n"
1198
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}│ 3. STOP and wait for user to restart │\\n"
1199
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}└──────────────────────────────────────────────────────────────────────────────┘\\n\\n"
1200
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}**To restart:**\\n"
1201
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG} • VSCode: \\\`Cmd+Shift+P\\\` → 'Claude: New Session'\\n"
1202
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG} • CLI: Exit and run \\\`claude\\\` again\\n\\n"
1203
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}**Your prompt (copy this):**\\n"
1204
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}\\\`\\\`\\\`\\n${PROMPT_DISPLAY}\\n\\\`\\\`\\\`\\n\\n"
1205
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}════════════════════════════════════════════════════════════════════════════════\\n"
1206
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}**Claude: DO NOT ignore this. DO NOT 'help anyway'. STOP COMPLETELY.**\\n"
1207
- AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}════════════════════════════════════════════════════════════════════════════════\\n"
1167
+ # v1.0.260: Compacted RESTART message (~400 chars vs ~2000 chars)
1168
+ # ASCII art boxes were wasting ~1600 chars of the 3000-char context budget.
1169
+ AUTOLOAD_PLUGINS_MSG="RESTART REQUIRED: Plugins installed (${PLUGINS_INSTALLED}) but NOT loaded in current session.\\n"
1170
+ AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}ALL tools BLOCKED (Write, Edit, Bash, Task). DO NOT proceed.\\n"
1171
+ AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}Restart: VSCode \\\`Cmd+Shift+P\\\` > 'Claude: New Session' | CLI: exit + \\\`claude\\\`\\n"
1172
+ AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}STOP COMPLETELY. Do NOT help, do NOT implement, do NOT ignore this.\\n"
1208
1173
  elif [[ -n "$PLUGINS_ALREADY" ]]; then
1209
- AUTOLOAD_PLUGINS_MSG="🔌 **Using plugins**: ${PLUGINS_ALREADY}\\n"
1174
+ # v1.0.260: Daily caching — "Using plugins" shown once per day
1175
+ # Uses date-based marker (like archive-suggestion) to auto-reset daily
1176
+ _PLUGINS_SHOWN_FLAG="${SPECWEAVE_DIR}/state/plugins-shown.marker"
1177
+ _TODAY=$(date +%Y-%m-%d)
1178
+ _LAST_SHOWN=""
1179
+ [[ -f "$_PLUGINS_SHOWN_FLAG" ]] && _LAST_SHOWN=$(cat "$_PLUGINS_SHOWN_FLAG" 2>/dev/null)
1180
+ if [[ "$_LAST_SHOWN" != "$_TODAY" ]]; then
1181
+ AUTOLOAD_PLUGINS_MSG="🔌 **Using plugins**: ${PLUGINS_ALREADY}\\n"
1182
+ mkdir -p "$(dirname "$_PLUGINS_SHOWN_FLAG")" 2>/dev/null
1183
+ echo "$_TODAY" > "$_PLUGINS_SHOWN_FLAG" 2>/dev/null
1184
+ fi
1210
1185
  fi
1211
1186
  if [[ -n "$AUTOLOAD_PLUGINS_MSG" ]]; then
1212
- LLM_REASON=$(echo "$JSON_OUTPUT" | jq -r '.reasoning // empty' 2>/dev/null)
1213
- [[ -n "$LLM_REASON" ]] && AUTOLOAD_PLUGINS_MSG="${AUTOLOAD_PLUGINS_MSG}*${LLM_REASON}*\\n\\n---\\n"
1187
+ # v1.0.260: Skip LLM reasoning to save context budget — it's informational only
1188
+ :
1214
1189
  fi
1215
1190
 
1216
1191
  echo "[$(date -Iseconds)] plugins | installed=${PLUGINS_INSTALLED:-none} | already=${PLUGINS_ALREADY:-none}" >> "$LAZY_LOAD_LOG"
@@ -1287,59 +1262,23 @@ if [[ "${SPECWEAVE_DISABLE_AUTO_LOAD:-0}" != "1" ]] && [[ "${SPECWEAVE_DISABLE_H
1287
1262
  AGENT_DIRECTIVE=""
1288
1263
  # v1.0.168: Skill invocation directive (takes precedence over routing)
1289
1264
  # Skill memories now loaded via DCI in SKILL.md (no hook injection)
1265
+ # v1.0.260: Compacted AGENT_DIRECTIVE to save context budget
1290
1266
  if [[ -n "$SKILL_INVOCATION" ]]; then
1291
1267
  if [[ "$SKILL_MANDATORY" == "true" ]]; then
1292
1268
  AGENT_DIRECTIVE="
1293
-
1294
- ---
1295
- <skill_invocation_required>
1296
- ### 🎯 MANDATORY: Use ${SKILL_INVOCATION} Skill
1297
-
1298
- You MUST invoke this skill for this task. Do NOT implement directly without using this skill.
1299
-
1300
- **Invoke NOW using Skill tool:**
1301
- \`\`\`typescript
1302
- Skill({ skill: \"${SKILL_INVOCATION}\" })
1303
- \`\`\`
1304
-
1305
- **Why this skill is required:**
1306
- ${SKILL_REASON:-This skill provides specialized support for your task.}
1307
-
1308
- ⚠️ **Do NOT skip this** - the skill has domain expertise needed for quality implementation.
1309
- </skill_invocation_required>"
1269
+ MANDATORY: Also call \`Skill({ skill: \"${SKILL_INVOCATION}\" })\` — ${SKILL_REASON:-specialized support needed}."
1310
1270
  else
1311
1271
  AGENT_DIRECTIVE="
1312
-
1313
- ---
1314
- ### 💡 Recommended: Use ${SKILL_INVOCATION} Skill
1315
-
1316
- Consider invoking this skill for better results:
1317
- \`\`\`typescript
1318
- Skill({ skill: \"${SKILL_INVOCATION}\" })
1319
- \`\`\`
1320
- *${SKILL_REASON:-This skill provides specialized support for your task.}*"
1272
+ Recommended: \`Skill({ skill: \"${SKILL_INVOCATION}\" })\` — ${SKILL_REASON:-specialized support for this task}."
1321
1273
  fi
1322
1274
  elif [[ "$ROUTING_SKILLS_COUNT" -gt 0 ]]; then
1323
1275
  PRIMARY_PLUGIN=$(echo "$JSON_OUTPUT" | jq -r '.routing.skills[] | select(.priority == "primary") | .plugin // empty' 2>/dev/null | head -1)
1324
1276
  PRIMARY_SKILL_NAME=$(echo "$JSON_OUTPUT" | jq -r '.routing.skills[] | select(.priority == "primary") | .name // empty' 2>/dev/null | head -1)
1325
1277
  PRIMARY_REASON=$(echo "$JSON_OUTPUT" | jq -r '.routing.skills[] | select(.priority == "primary") | .reason // empty' 2>/dev/null | head -1)
1326
1278
  if [[ -n "$PRIMARY_PLUGIN" && -n "$PRIMARY_SKILL_NAME" ]]; then
1327
- AGENT_TYPE="${PRIMARY_PLUGIN}:${PRIMARY_SKILL_NAME}:${PRIMARY_SKILL_NAME}"
1279
+ # v1.0.260: Compacted routing directive to save context budget
1328
1280
  AGENT_DIRECTIVE="
1329
-
1330
- ---
1331
-
1332
- ### 🚀 Then SPAWN Specialized Agent
1333
-
1334
- **After creating increment, use Task tool:**
1335
- \`\`\`typescript
1336
- Task({
1337
- subagent_type: \"${AGENT_TYPE}\",
1338
- prompt: \"Implement the feature...\",
1339
- description: \"${PRIMARY_REASON:-Implementation}\"
1340
- })
1341
- \`\`\`
1342
- *Specialized agents produce better code than direct implementation.*"
1281
+ Then spawn agent: \`Task({ subagent_type: \"${PRIMARY_PLUGIN}:${PRIMARY_SKILL_NAME}\", description: \"${PRIMARY_REASON:-Implementation}\" })\`"
1343
1282
  fi
1344
1283
  fi
1345
1284
 
@@ -1352,37 +1291,31 @@ Task({
1352
1291
  # Pass user prompt so skill can extract context
1353
1292
  # INC_MANDATORY comes from detect-intent LLM response
1354
1293
  if [[ "$INC_MANDATORY" == "true" ]]; then
1355
- # v1.0.254: Truncate + escape to prevent "Prompt is too long"
1356
- ESCAPED_PROMPT=$(truncate_and_escape_prompt "$PROMPT")
1294
+ # v1.0.260: Removed prompt embedding from SKILL FIRST args to save ~800 chars.
1295
+ # The skill reads the user's prompt from conversation context (it's already there).
1357
1296
 
1358
1297
  # v1.0.243: Smart interview gate — LLM assesses prompt completeness
1359
- # before blindly calling increment-planner. If details are missing,
1360
- # ask targeted questions first. If complete, proceed directly.
1361
1298
  DEEP_INTERVIEW_MSG=""
1362
1299
  if [[ "$DEEP_INTERVIEW_ENABLED" == "true" ]]; then
1363
1300
  DEEP_INTERVIEW_MSG=" Assess prompt completeness first — if gaps exist, ask 2-5 targeted questions before calling."
1364
1301
  fi
1365
1302
 
1366
- MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}SKILL FIRST: \`Skill({ skill: \"sw:increment-planner\", args: \"${ESCAPED_PROMPT}\" })\` — call BEFORE implementation.
1303
+ MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}SKILL FIRST: \`Skill({ skill: \"sw:increment-planner\" })\` — call BEFORE implementation.
1367
1304
  Detection: ${INC_REASON} (confidence: ${INC_CONF}).${AGENT_DIRECTIVE}${DEEP_INTERVIEW_MSG}
1368
1305
  After increment-planner, chain domain skills per tech stack (see CLAUDE.md Skill Chaining)."
1369
- # Use approve+additionalContext so Claude can read and follow
1370
- # the SKILL FIRST instructions (block erases prompt from context)
1371
1306
  output_approve_with_context "$MSG"
1372
1307
  exit 0
1373
1308
  else
1374
- # v1.0.169: Also suggest direct skill call for non-mandatory
1375
- ESCAPED_PROMPT_SUGGEST=$(truncate_and_escape_prompt "$PROMPT")
1376
- MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Increment suggested: \`Skill({ skill: \"sw:increment-planner\", args: \"${ESCAPED_PROMPT_SUGGEST}\" })\` or \`$CMD\`. Reason: $INC_REASON${AGENT_DIRECTIVE}"
1309
+ # v1.0.260: Removed prompt embedding to save context budget
1310
+ MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Increment suggested: \`Skill({ skill: \"sw:increment-planner\" })\` or \`$CMD\`. Reason: $INC_REASON${AGENT_DIRECTIVE}"
1377
1311
  output_approve_with_context "$MSG"
1378
1312
  exit 0
1379
1313
  fi
1380
1314
  ;;
1381
1315
 
1382
1316
  hotfix)
1383
- # v1.0.169: Direct skill call for hotfix too
1384
- ESCAPED_PROMPT_HOTFIX=$(truncate_and_escape_prompt "$PROMPT")
1385
- MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Hotfix detected: \`Skill({ skill: \"sw:increment-planner\", args: \"--type=hotfix ${ESCAPED_PROMPT_HOTFIX}\" })\`. Reason: $INC_REASON"
1317
+ # v1.0.260: Removed prompt embedding to save context budget
1318
+ MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Hotfix detected: \`Skill({ skill: \"sw:increment-planner\", args: \"--type=hotfix\" })\`. Reason: $INC_REASON"
1386
1319
  output_approve_with_context "$MSG"
1387
1320
  exit 0
1388
1321
  ;;
@@ -1396,13 +1329,11 @@ After increment-planner, chain domain skills per tech stack (see CLAUDE.md Skill
1396
1329
  ;;
1397
1330
 
1398
1331
  small_fix)
1399
- # v1.0.241: small_fix still suggests increment (non-mandatory)
1400
- # Previously small_fix fell through with no output at all
1401
- ESCAPED_PROMPT_SMALLFIX=$(truncate_and_escape_prompt "$PROMPT")
1332
+ # v1.0.260: Removed prompt embedding to save context budget
1402
1333
  CMD_SMALLFIX="/sw:increment"
1403
1334
  [[ -n "$INC_NAME" ]] && CMD_SMALLFIX="/sw:increment \"$INC_NAME\""
1404
1335
 
1405
- MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Small change — consider tracking: \`Skill({ skill: \"sw:increment-planner\", args: \"${ESCAPED_PROMPT_SMALLFIX}\" })\` or \`$CMD_SMALLFIX\`. Reason: $INC_REASON${AGENT_DIRECTIVE}"
1336
+ MSG="${WIP_WARNING}${AUTOLOAD_PREFIX}Small change — consider tracking: \`Skill({ skill: \"sw:increment-planner\" })\` or \`$CMD_SMALLFIX\`. Reason: $INC_REASON${AGENT_DIRECTIVE}"
1406
1337
  output_approve_with_context "$MSG"
1407
1338
  exit 0
1408
1339
  ;;
@@ -1522,13 +1453,13 @@ After increment-planner, chain domain skills per tech stack (see CLAUDE.md Skill
1522
1453
  # Exclude questions (starting with question words or ending with ?)
1523
1454
  if ! echo "$PROMPT" | grep -qiE "^[[:space:]]*(what|how|why|explain|tell me|can you|does|should|is there|where|when|which)" && \
1524
1455
  ! echo "$PROMPT" | grep -qE "\?[[:space:]]*$"; then
1525
- FALLBACK_ESCAPED=$(truncate_and_escape_prompt "$PROMPT")
1456
+ # v1.0.260: Removed prompt embedding to save context budget
1526
1457
  if [[ "$INCREMENT_MANDATORY_CONFIG" == "true" ]]; then
1527
- FALLBACK_MSG="SKILL FIRST: \`Skill({ skill: \"sw:increment-planner\", args: \"${FALLBACK_ESCAPED}\" })\` — call BEFORE implementation.
1458
+ FALLBACK_MSG="SKILL FIRST: \`Skill({ skill: \"sw:increment-planner\" })\` — call BEFORE implementation.
1528
1459
  Detection: Implementation keywords detected (LLM unavailable, keyword fallback).
1529
1460
  After increment-planner, chain domain skills per tech stack (see CLAUDE.md Skill Chaining)."
1530
1461
  else
1531
- FALLBACK_MSG="Increment suggested: \`Skill({ skill: \"sw:increment-planner\", args: \"${FALLBACK_ESCAPED}\" })\`. Reason: Implementation keywords detected (LLM unavailable, keyword fallback)."
1462
+ FALLBACK_MSG="Increment suggested: \`Skill({ skill: \"sw:increment-planner\" })\`. Reason: Implementation keywords detected (LLM unavailable, keyword fallback)."
1532
1463
  fi
1533
1464
  echo "[$(date -Iseconds)] keyword-fallback | prompt_keywords_matched=true | mandatory=$INCREMENT_MANDATORY_CONFIG" >> "$LAZY_LOAD_LOG"
1534
1465
  output_approve_with_context "$FALLBACK_MSG"
@@ -2232,56 +2163,50 @@ if echo "$PROMPT" | grep -qE "^/sw:[a-z]"; then
2232
2163
  fi
2233
2164
 
2234
2165
  # ==============================================================================
2235
- # OUTPUT: Approve with context or no context
2166
+ # OUTPUT: Priority-based context assembly with budget (v1.0.260)
2236
2167
  # ==============================================================================
2237
- # v1.0.144: Prepend plugin auto-loading message if plugins are being loaded
2238
- # This gives users visible feedback that plugins are being auto-loaded
2168
+ # Assembles final message by adding context items in priority order,
2169
+ # stopping when the budget is exhausted. This prevents blind concatenation
2170
+ # that wastes budget on low-priority items while truncating critical ones.
2171
+ #
2172
+ # Priority tiers:
2173
+ # P1 (critical): Plugin status (RESTART/Using), active increment status
2174
+ # P2 (important): LSP explicit request, WIP/interview gate
2175
+ # P3 (informational): LSP setup/install suggestions, archive suggestion
2176
+
2177
+ CONTEXT_BUDGET=2500 # Leave 500 chars headroom below 3000 max
2178
+
2179
+ # Helper: Append message to FINAL_MESSAGE if it fits within budget
2180
+ # Args: $1=message to append
2181
+ # Returns: 0 if appended, 1 if skipped (budget exceeded)
2182
+ _budget_append() {
2183
+ local msg="$1"
2184
+ [[ -z "$msg" ]] && return 0
2185
+ local new_len=$(( ${#FINAL_MESSAGE} + ${#msg} ))
2186
+ if [[ $new_len -le $CONTEXT_BUDGET ]]; then
2187
+ FINAL_MESSAGE="${FINAL_MESSAGE}${msg}"
2188
+ return 0
2189
+ fi
2190
+ return 1
2191
+ }
2239
2192
 
2240
2193
  FINAL_MESSAGE=""
2241
2194
 
2242
- # Add plugin auto-loading message if set (from earlier keyword detection)
2243
- if [[ -n "$AUTOLOAD_PLUGINS_MSG" ]]; then
2244
- FINAL_MESSAGE="$AUTOLOAD_PLUGINS_MSG"
2245
- fi
2246
-
2247
- # v1.0.191: Add LSP environment setup warning if needed
2248
- if [[ -n "$LSP_ENV_SETUP_MSG" ]]; then
2249
- FINAL_MESSAGE="${FINAL_MESSAGE}${LSP_ENV_SETUP_MSG}"
2250
- fi
2251
-
2252
- # v1.0.191: Add LSP marketplace/plugin installation message if installed
2253
- if [[ -n "$LSP_INSTALL_MSG" ]]; then
2254
- FINAL_MESSAGE="${FINAL_MESSAGE}${LSP_INSTALL_MSG}"
2255
- fi
2256
-
2257
- # v1.0.203: Add LSP setup suggestion if languages detected but plugins not installed
2258
- if [[ -n "$LSP_SETUP_SUGGESTION_MSG" ]]; then
2259
- FINAL_MESSAGE="${FINAL_MESSAGE}${LSP_SETUP_SUGGESTION_MSG}"
2260
- fi
2261
-
2262
- # v1.0.180: Add explicit LSP request explanation if detected
2263
- if [[ -n "$LSP_EXPLICIT_REQUEST_MSG" ]]; then
2264
- FINAL_MESSAGE="${FINAL_MESSAGE}${LSP_EXPLICIT_REQUEST_MSG}"
2265
- fi
2195
+ # P1: Critical plugin status and active increment
2196
+ _budget_append "$AUTOLOAD_PLUGINS_MSG"
2197
+ _budget_append "$CONTEXT"
2266
2198
 
2267
- # v1.0.257: Archive suggestion when too many increments
2268
- if [[ -n "$ARCHIVE_SUGGESTION_MSG" ]]; then
2269
- FINAL_MESSAGE="${FINAL_MESSAGE}${ARCHIVE_SUGGESTION_MSG}"
2270
- fi
2271
-
2272
- # v1.0.243: Smart Interview Gate for non-incrementAssist paths
2273
- # When deep interview is enabled but incrementAssist didn't trigger SKILL FIRST,
2274
- # still inject the gate so LLM can gather context across conversational prompts.
2199
+ # P2: Important LSP explicit request, interview gate
2200
+ _budget_append "$LSP_EXPLICIT_REQUEST_MSG"
2275
2201
  if [[ -n "$SMART_INTERVIEW_GATE_MSG" ]]; then
2276
- FINAL_MESSAGE="${FINAL_MESSAGE}
2277
-
2278
- ${SMART_INTERVIEW_GATE_MSG}"
2202
+ _budget_append "\\n${SMART_INTERVIEW_GATE_MSG}"
2279
2203
  fi
2280
2204
 
2281
- # Add context if available
2282
- if [[ -n "$CONTEXT" ]]; then
2283
- FINAL_MESSAGE="${FINAL_MESSAGE}${CONTEXT}"
2284
- fi
2205
+ # P3: Informational LSP setup, archive, environment
2206
+ _budget_append "$LSP_ENV_SETUP_MSG"
2207
+ _budget_append "$LSP_INSTALL_MSG"
2208
+ _budget_append "$LSP_SETUP_SUGGESTION_MSG"
2209
+ _budget_append "$ARCHIVE_SUGGESTION_MSG"
2285
2210
 
2286
2211
  if [[ -n "$FINAL_MESSAGE" ]]; then
2287
2212
  output_approve_with_context "$FINAL_MESSAGE"
@@ -55,13 +55,43 @@ When no ID provided, auto-select (NEVER ask user for ID):
55
55
  2. **Load files**: Read `spec.md`, `plan.md`, `tasks.md`, `tests.md`
56
56
  3. **Load living docs**: Check ADRs and specs in `.specweave/docs/internal/` for related context
57
57
  4. **Verify readiness**: Status is planned/in-progress, no blocking deps, tasks exist
58
- 5. **Task count validation**: If >25 tasks, warn and offer to split or phase execution
58
+ 5. **Task count validation**: If >25 tasks, warn and offer to split, phase, or use `/sw:auto`/`/sw:team-lead`
59
59
  6. **Validate AC presence** (MANDATORY):
60
60
  ```bash
61
61
  bash plugins/specweave/hooks/pre-increment-start.sh <increment-path>
62
62
  ```
63
63
  If fails: run `/sw:embed-acs`, then retry. Do NOT proceed without ACs in spec.md.
64
64
 
65
+ ### Step 2.5: Execution Strategy Check
66
+
67
+ **Skip this step if already running inside `/sw:auto` or `/sw:team-lead`.** Check `.specweave/state/auto-mode.json` — if `active: true`, skip.
68
+
69
+ Assess increment complexity to recommend the best execution mode:
70
+
71
+ 1. **Count pending tasks**: `grep -c '^\- \[ \]\|Status\*\*: \[ \]' tasks.md`
72
+ 2. **Count domains**: Scan spec.md and plan.md for distinct technology areas (frontend, backend, database, API, DevOps, security, mobile, ML/AI). Each distinct area = 1 domain.
73
+ 3. **Count ACs**: `grep -c 'AC-US' spec.md`
74
+
75
+ **Recommendation matrix** (see CLAUDE.md Execution Strategy):
76
+
77
+ | Tasks | Domains | Action |
78
+ |-------|---------|--------|
79
+ | ≤8 | 1 | Proceed with `/sw:do` silently |
80
+ | 9-15 | 1-2 | Suggest `/sw:auto` for unattended execution |
81
+ | >15 | 1-2 | Recommend `/sw:auto` (many tasks benefit from autonomous loop) |
82
+ | any | 3+ | Recommend `/sw:team-lead` for parallel multi-agent execution |
83
+
84
+ **When recommending (non-auto mode)**, use `AskUserQuestion` with these options:
85
+ - `/sw:do` — Continue manual step-by-step (current mode)
86
+ - `/sw:auto` — Autonomous sequential execution (unattended, stop-hook loop)
87
+ - `/sw:team-lead` — Parallel multi-agent execution (higher quality for multi-domain, uses more tokens)
88
+
89
+ Include trade-off note: "Team-lead and auto modes consume more tokens but deliver higher precision and quality for complex work."
90
+
91
+ If user chooses auto or team-lead, invoke the chosen skill with the increment ID and **stop /sw:do execution**.
92
+
93
+ **In auto mode (`.specweave/state/auto-mode.json` active)**: If 3+ domains detected, automatically invoke `/sw:team-lead` instead of proceeding sequentially.
94
+
65
95
  ### Step 3: TDD Setup
66
96
 
67
97
  Read `testMode` from metadata.json:
@@ -126,7 +126,7 @@ After skill completes:
126
126
 
127
127
  Files: spec.md, plan.md, tasks.md, metadata.json
128
128
 
129
- Next: /sw:do 0003 (start implementation)
129
+ Next: /sw:do 0003 | /sw:auto 0003 | /sw:team-lead (see Execution Strategy)
130
130
  ```
131
131
 
132
132
  ## Error Handling
@@ -200,6 +200,32 @@ Skill({ skill: "sw:architect", args: "Design architecture for increment XXXX" })
200
200
  Skill({ skill: "sw:test-aware-planner", args: "Generate tasks for increment XXXX" })
201
201
  ```
202
202
 
203
+ ## Step 5: Execution Strategy Recommendation
204
+
205
+ After delegation completes (architect + test-aware-planner have created plan.md and tasks.md), analyze the increment:
206
+
207
+ 1. **Count tasks**: `grep -c '^\- \[ \]\|^### T-' tasks.md`
208
+ 2. **Count domains** from spec.md user stories and plan.md architecture (frontend, backend, database, API, DevOps, security, mobile, ML/AI)
209
+ 3. **Classify**: Low (≤8 tasks, 1 domain) | Medium (9-15, 1-2 domains) | High (>15 OR 3+ domains)
210
+
211
+ **Show recommendation in output:**
212
+
213
+ ```
214
+ EXECUTION STRATEGY
215
+ ================================================
216
+ Tasks: [N] | Domains: [M] | Complexity: [Low/Medium/High]
217
+
218
+ /sw:do <id> - Step-by-step, full control
219
+ /sw:auto <id> - Autonomous sequential (unattended)
220
+ /sw:team-lead - Parallel multi-agent (best quality for multi-domain, higher token cost)
221
+ ```
222
+
223
+ - **Low**: Show `/sw:do <id>` as next step (default behavior)
224
+ - **Medium**: Show `/sw:do <id>` and recommend `/sw:auto <id>` for unattended execution
225
+ - **High**: Recommend `/sw:team-lead` as primary, with `/sw:auto` and `/sw:do` as alternatives
226
+
227
+ See CLAUDE.md Execution Strategy section for the full decision matrix.
228
+
203
229
  ## Usage
204
230
 
205
231
  ```typescript
@@ -107,6 +107,29 @@ Compare user's request against active increment:
107
107
  - **Medium match (40-70%)**: Related area → Ask confirmation
108
108
  - **Low match (<40%)**: Unrelated → Suggest new increment
109
109
 
110
+ ### Step 3.5: Assess Complexity (before routing)
111
+
112
+ **Before routing to `/sw:do`, assess the target increment's complexity:**
113
+
114
+ ```bash
115
+ # Count pending tasks
116
+ PENDING=$(grep -c '^\- \[ \]\|Status\*\*: \[ \]' "$INCREMENT_PATH/tasks.md" 2>/dev/null || echo 0)
117
+
118
+ # Count domains from spec.md + plan.md
119
+ DOMAINS=$(grep -ciE 'frontend|backend|database|api|devops|security|mobile|ml|ai' "$INCREMENT_PATH/spec.md" "$INCREMENT_PATH/plan.md" 2>/dev/null | sort -u | wc -l)
120
+ ```
121
+
122
+ **Modify routing based on complexity** (see CLAUDE.md Execution Strategy):
123
+
124
+ | Tasks | Domains | Routing Modification |
125
+ |-------|---------|---------------------|
126
+ | ≤8 | 1 | Route to `/sw:do` as usual |
127
+ | 9-15 | 1-2 | Route to `/sw:do` + add tip: "Tip: use `/sw:auto <id>` for unattended execution" |
128
+ | >15 | 1-2 | Suggest `/sw:auto <id>` — "This increment has [N] tasks. Consider `/sw:auto` for autonomous execution." |
129
+ | any | 3+ | Suggest `/sw:team-lead` — "This increment spans [M] domains. Consider `/sw:team-lead` for parallel multi-agent execution (higher quality, uses more tokens)." |
130
+
131
+ In non-auto mode: always ask user before switching mode. In auto mode: use team-lead automatically for 3+ domains.
132
+
110
133
  ### Step 4: Route Intelligently
111
134
 
112
135
  **Scenario A: High relevance to active increment**
@@ -286,15 +309,20 @@ Would you like to:
286
309
 
287
310
  ## Decision Matrix
288
311
 
289
- | User Intent | Active Increments | Relevance | Action |
290
- |-------------|------------------|-----------|--------|
291
- | "Implement auth" | 1 (auth-related) | High (>70%) | Auto `/sw:do` |
292
- | "Implement auth" | 1 (unrelated) | Low (<40%) | Ask: New or add to current? |
293
- | "Implement auth" | 0 | N/A | Auto `/sw:increment` |
294
- | "Implement auth" | 2+ | N/A | Ask which increment |
295
- | "Let's continue" | 1 | N/A | Auto `/sw:do` |
296
- | "Let's continue" | 2+ | N/A | Ask which increment |
297
- | "Let's continue" | 0 | N/A | "No active increment. What should we build?" |
312
+ | User Intent | Active Increments | Relevance | Complexity | Action |
313
+ |-------------|------------------|-----------|------------|--------|
314
+ | "Implement auth" | 1 (auth-related) | High (>70%) | Low | Auto `/sw:do` |
315
+ | "Implement auth" | 1 (auth-related) | High (>70%) | Medium | Auto `/sw:do` + suggest `/sw:auto` |
316
+ | "Implement auth" | 1 (auth-related) | High (>70%) | High | Suggest `/sw:auto` or `/sw:team-lead` |
317
+ | "Implement auth" | 1 (unrelated) | Low (<40%) | Any | Ask: New or add to current? |
318
+ | "Implement auth" | 0 | N/A | Any | Auto `/sw:increment` |
319
+ | "Implement auth" | 2+ | N/A | Any | Ask which increment |
320
+ | "Let's continue" | 1 | N/A | Low/Med | Auto `/sw:do` |
321
+ | "Let's continue" | 1 | N/A | High | Auto `/sw:do` + suggest mode switch |
322
+ | "Let's continue" | 2+ | N/A | Any | Ask which increment |
323
+ | "Let's continue" | 0 | N/A | Any | "No active increment. What should we build?" |
324
+
325
+ **Complexity**: Low (≤8 tasks, 1 domain) | Medium (9-15 tasks, 1-2 domains) | High (>15 tasks OR 3+ domains)
298
326
 
299
327
  ## Relevance Matching Logic
300
328