orchestrix 16.1.7 → 16.1.9

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.
@@ -254,12 +254,20 @@ AGENT_LOAD_WAIT=15
254
254
  # Auto-start workflow command (sent to SM window)
255
255
  AUTO_START_COMMAND="1"
256
256
 
257
+ # Language flag: read from $ORCHESTRIX_LANG (e.g., "zh") or empty for English.
258
+ # Yuri sets this before calling start-orchestrix.sh to propagate frontend locale.
259
+ LANG_FLAG=""
260
+ if [ -n "$ORCHESTRIX_LANG" ] && [ "$ORCHESTRIX_LANG" != "en" ]; then
261
+ LANG_FLAG="--lang=$ORCHESTRIX_LANG"
262
+ echo "🌐 Language: $ORCHESTRIX_LANG"
263
+ fi
264
+
257
265
  # Agent activation commands (MCP version uses /o command)
258
266
  declare -a AGENT_COMMANDS=(
259
- "/o architect" # Window 0 - Architect
260
- "/o sm" # Window 1 - SM
261
- "/o dev" # Window 2 - Dev
262
- "/o qa" # Window 3 - QA
267
+ "/o architect $LANG_FLAG" # Window 0 - Architect
268
+ "/o sm $LANG_FLAG" # Window 1 - SM
269
+ "/o dev $LANG_FLAG" # Window 2 - Dev
270
+ "/o qa $LANG_FLAG" # Window 3 - QA
263
271
  )
264
272
 
265
273
  declare -a AGENT_NAMES=(
@@ -254,27 +254,168 @@ tmux kill-session -t "$OP_SESSION"
254
254
  # Launch dev session with same op-{name}
255
255
  # start-orchestrix.sh reads ORCHESTRIX_SESSION and uses it as the session name
256
256
  # instead of its default "orchestrix-{repo-id}" naming.
257
- ORCHESTRIX_SESSION="$OP_SESSION" bash "$WORK_DIR/.orchestrix-core/scripts/start-orchestrix.sh"
257
+ ORCHESTRIX_SESSION="$OP_SESSION" ORCHESTRIX_LANG="$LANG" bash "$WORK_DIR/.orchestrix-core/scripts/start-orchestrix.sh"
258
258
  ```
259
259
 
260
- **Important**: Pass `ORCHESTRIX_SESSION` inline (not `export`) to avoid polluting Yuri's own shell environment. The script creates a new `op-{name}` session with 4 dev agent windows.
260
+ **Important**: Pass `ORCHESTRIX_SESSION` and `ORCHESTRIX_LANG` inline (not `export`) to avoid polluting Yuri's own shell environment. `$LANG` is `zh` or `en` based on your `--lang` activation parameter. The script creates a new `op-{name}` session with 4 dev agent windows, all using the same language.
261
261
 
262
- ### Phase B: Remote Development Monitoring
262
+ ### Agent Autonomy Model (Phase B CRITICAL)
263
263
 
264
- After `start-orchestrix.sh` launches, HANDOFF automation runs autonomously. Yuri monitors:
264
+ Phase B (Development) operates in two distinct modes. Violating this boundary
265
+ causes handoff chain breakage, agent window resets, and lost progress.
265
266
 
267
+ #### Mode 1: Kickoff (Yuri sends ONE command)
268
+
269
+ Yuri's job is to **kick the SM once** to start the development loop. After that,
270
+ Yuri transitions to Mode 2 immediately.
271
+
272
+ ```bash
273
+ # Send exactly ONE command to SM window to start the loop
274
+ tmux send-keys -t "$OP_SESSION:1" "*draft {first_story_id}"
275
+ sleep 1
276
+ tmux send-keys -t "$OP_SESSION:1" Enter
277
+ ```
278
+
279
+ This is the ONLY direct command Yuri sends to any agent window during Phase B.
280
+
281
+ #### Mode 2: Monitor Only (Yuri observes, does NOT send commands)
282
+
283
+ After kickoff, the **handoff-detector.sh** (Stop Hook) drives the entire agent loop:
284
+
285
+ ```
286
+ SM *draft → HANDOFF → Architect *review → HANDOFF → Dev *develop
287
+ → HANDOFF → QA *test → HANDOFF → SM *create-next-story → loop
288
+ ```
289
+
290
+ Each agent completes its task, emits a `🎯 HANDOFF TO {agent}: *{command}` message,
291
+ then calls `/clear`. The Stop Hook:
292
+ 1. Parses the HANDOFF message from the tmux pane output
293
+ 2. Routes the command to the target agent's window
294
+ 3. `/clear`s the source window and reloads the agent (`/o {agent}`)
295
+
296
+ **WHY Yuri must NOT send commands after kickoff:**
297
+ - The handoff-detector `/clear`s agent windows after each task completion
298
+ - If Yuri sends a command to a window that is about to be `/clear`ed, the command is lost
299
+ - If Yuri `/clear`s a window manually, it triggers a Stop event that confuses the handoff-detector
300
+ - Two orchestrators fighting over the same tmux windows creates race conditions
301
+
302
+ #### When Yuri CAN re-intervene (Stuck Recovery)
303
+
304
+ Yuri re-enters command-sending mode ONLY when stuck detection triggers (see Monitoring Loop below).
305
+ After recovery, Yuri returns to Monitor Only mode immediately.
306
+
307
+ ### Phase B: Remote Development Monitoring (5-Minute Polling Loop)
308
+
309
+ After kickoff, Yuri enters a **polling loop** that runs every 5 minutes until all stories are done.
310
+
311
+ ```
312
+ WHILE stories_done < total_stories:
313
+ → 2.1 Scan story statuses
314
+ → 2.2 Report to user
315
+ → 2.3 Stuck detection & recovery
316
+ → 2.4 Save state
317
+ → Sleep 5 minutes
318
+ ```
319
+
320
+ #### 2.1 Scan Story Statuses (Multi-Source)
321
+
322
+ **Primary source** — story docs:
323
+ ```bash
324
+ # Count stories by status
325
+ DONE=$(grep -rl 'status: done' "$WORK_DIR/docs/stories/" 2>/dev/null | wc -l)
326
+ TOTAL=$(ls "$WORK_DIR/docs/stories/"*.md 2>/dev/null | wc -l)
327
+ ```
328
+
329
+ **Secondary source** — git log (cross-validation):
330
+ ```bash
331
+ COMMITTED=$(git -C "$WORK_DIR" log --oneline --since="$ITERATION_START" | grep -cE "feat\(story-|feat\(solo-")
332
+ ```
333
+
334
+ **Tertiary source** — handoff-detector log:
335
+ ```bash
336
+ HANDOFF_LOG="/tmp/${OP_SESSION}-handoff.log"
337
+ [ -f "$HANDOFF_LOG" ] && tail -20 "$HANDOFF_LOG"
338
+ ```
339
+
340
+ If story doc count and git commit count diverge by > 1, trust git commits
341
+ (story docs may not be updated if SM was bypassed during stuck recovery).
342
+
343
+ #### 2.2 Report to User
344
+
345
+ ```
346
+ 📊 Progress: {done}/{total} stories
347
+ ✅ Done: {list of done story IDs}
348
+ 🔄 In Progress: {list}
349
+ ⏳ Remaining: {count}
350
+ 🔗 Handoff chain: {last 3 handoff events from log}
351
+ ```
352
+
353
+ #### 2.3 Stuck Detection & Recovery
354
+
355
+ **Step A: Process health check (every poll, not just when stuck):**
356
+ ```bash
357
+ for W in 0 1 2 3; do
358
+ PANE_PID=$(tmux display-message -t "$OP_SESSION:$W" -p '#{pane_pid}' 2>/dev/null)
359
+ CLAUDE_ALIVE=$(pgrep -P "$PANE_PID" -f "claude" 2>/dev/null | head -1)
360
+ if [ -z "$CLAUDE_ALIVE" ]; then
361
+ # Claude process died in window $W — restart
362
+ AGENT=$(echo "architect sm dev qa" | cut -d' ' -f$((W+1)))
363
+ tmux send-keys -t "$OP_SESSION:$W" "claude"
364
+ sleep 1
365
+ tmux send-keys -t "$OP_SESSION:$W" Enter
366
+ sleep 12
367
+ tmux send-keys -t "$OP_SESSION:$W" "/o $AGENT"
368
+ sleep 1
369
+ tmux send-keys -t "$OP_SESSION:$W" Enter
370
+ fi
371
+ done
372
+ ```
373
+
374
+ **Step B: Handoff chain health (every poll):**
266
375
  ```bash
267
- # Watch HANDOFF log
268
- tail -f /tmp/${OP_SESSION}-handoff.log
376
+ HANDOFF_LOG="/tmp/${OP_SESSION}-handoff.log"
377
+ if [ -f "$HANDOFF_LOG" ]; then
378
+ LAST_HANDOFF_TIME=$(tail -1 "$HANDOFF_LOG" | grep -oE '[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:]+')
379
+ # If last handoff was > 10 min ago but stories are still in progress, chain may be broken
380
+ fi
381
+ ```
269
382
 
270
- # Check specific agent output
271
- tmux capture-pane -t "$OP_SESSION:1" -p | tail -20 # SM
272
- tmux capture-pane -t "$OP_SESSION:2" -p | tail -20 # Dev
383
+ **Step C: Stuck escalation (3 consecutive polls with same done count = 15 min no progress):**
273
384
 
274
- # Check story completion
275
- ls "$WORK_DIR/docs/stories/"
276
- git -C "$WORK_DIR" log --oneline -5
385
+ IF no progress for 15 minutes:
386
+ 1. Capture all 4 tmux window contents:
387
+ ```bash
388
+ for W in 0 1 2 3; do
389
+ tmux capture-pane -t "$OP_SESSION:$W" -p -S -50
390
+ done
277
391
  ```
392
+ 2. Check handoff log for routing errors.
393
+ 3. Analyze for error patterns (exceptions, stuck loops, missing handoffs).
394
+ 4. Attempt recovery:
395
+ - IF handoff was emitted but not routed → manually `tmux send-keys` the command to target window
396
+ - IF agent window shows error → `/clear` → `/o {agent}` → resend last command
397
+ - IF agent process dead → restart (Step A above)
398
+ 5. Increment `stuck_count`.
399
+
400
+ **Stuck escalation thresholds:**
401
+
402
+ | stuck_count | Action |
403
+ |-------------|--------|
404
+ | 1 | Auto-recovery: resend handoff / restart agent |
405
+ | 2 | Capture full diagnostics, attempt deeper recovery |
406
+ | 3 | Escalate to user with full diagnostics report |
407
+ | > 3 | Pause monitoring loop, wait for user intervention |
408
+
409
+ #### 2.4 Completion Detection
410
+
411
+ When monitoring an agent in a tmux window:
412
+
413
+ | Priority | Signal | Pattern | Reliability |
414
+ |----------|--------|---------|-------------|
415
+ | **P1** | Claude Code completion | `/[A-Z][a-z]*ed for [0-9]/` (e.g., "Baked for 31s") | Highest |
416
+ | **P2** | TUI idle indicator | `○` in last lines of pane | High |
417
+ | **P3** | Approval prompt | `◐` → auto-send `y` + Enter | High |
418
+ | **P4** | Content hash stability (3×30s) | Fallback | Medium |
278
419
 
279
420
  ### Session Lifecycle
280
421
 
@@ -286,6 +427,31 @@ git -C "$WORK_DIR" log --oneline -5
286
427
  | User says "stop" / "cancel" | `tmux kill-session -t "$OP_SESSION"` |
287
428
  | Reconnect / resume | Check `tmux has-session -t "$OP_SESSION"` to detect existing session |
288
429
 
430
+ ### `/clear` Usage Rules
431
+
432
+ **`/clear` is ONLY for error recovery or cross-phase re-activation.** Never use it
433
+ during normal within-phase workflow.
434
+
435
+ | Scenario | Action |
436
+ |----------|--------|
437
+ | **Same phase, same window** (e.g., asking agent to modify its output) | Just send the new instruction + Enter. Do NOT `/clear`. |
438
+ | **Same phase, agent drifted** (e.g., noise corrupted context) | `/clear` Enter → wait 1s → `/o {agent}` Enter → wait 15s → send command Enter |
439
+ | **Cross-phase re-activation** (e.g., Phase B needs to modify a Phase A agent) | `/clear` Enter → wait 1s → `/o {agent}` Enter → wait 15s → send command Enter |
440
+ | **Agent load failure** | `/clear` Enter → retry `/o {agent}` Enter |
441
+ | **Stuck agent** (no change 5min) | `/clear` Enter → restart |
442
+
443
+ ### Iteration Scope
444
+
445
+ When starting a new iteration on an existing project, Yuri must ensure the SM
446
+ knows which epics/stories are in scope. Two approaches:
447
+
448
+ 1. **Via command context**: Include scope in the kickoff command:
449
+ `*draft 6.1` + context about epic order (6→7→8)
450
+ 2. **Via scope file**: Create `docs/prd/iteration-{N}-scope.yaml` listing epic order
451
+ and story IDs. SM reads this file to determine what to draft next.
452
+
453
+ The scope file approach is more robust because SM loses context on `/clear`.
454
+
289
455
  ---
290
456
 
291
457
  ## Full Workflow Overview
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchestrix",
3
- "version": "16.1.7",
3
+ "version": "16.1.9",
4
4
  "description": "Install Orchestrix multi-agent infrastructure into any project. One command: npx orchestrix install",
5
5
  "bin": {
6
6
  "orchestrix": "bin/o8x.js"