orchestrix 16.1.8 → 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.
- package/lib/embedded/yuri.md +176 -10
- package/package.json +1 -1
package/lib/embedded/yuri.md
CHANGED
|
@@ -259,22 +259,163 @@ ORCHESTRIX_SESSION="$OP_SESSION" ORCHESTRIX_LANG="$LANG" bash "$WORK_DIR/.orches
|
|
|
259
259
|
|
|
260
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
|
|
262
|
+
### Agent Autonomy Model (Phase B — CRITICAL)
|
|
263
263
|
|
|
264
|
-
|
|
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
|
-
|
|
268
|
-
|
|
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
|
-
|
|
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
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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
|