orchestrix-yuri 4.2.3 → 4.2.5

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.
@@ -69,6 +69,48 @@ class Router {
69
69
  if (projectRoot) {
70
70
  this.orchestrator.tryRecover(projectRoot);
71
71
  }
72
+
73
+ // Independent progress reporter: sends periodic status card
74
+ // when dev phase is active (detected from focus.yaml + tmux),
75
+ // regardless of whether orchestrator is tracking it.
76
+ this._reportTimer = null;
77
+ this._startAutoReporter(config);
78
+ }
79
+
80
+ /**
81
+ * Start an independent timer that checks if dev phase is running
82
+ * and sends a progress card periodically.
83
+ */
84
+ _startAutoReporter(config) {
85
+ const interval = (config.engine && config.engine.report_interval) || 1800000; // 30 min
86
+ this._reportTimer = setInterval(() => {
87
+ // Skip if orchestrator is already reporting (avoid duplicates)
88
+ if (this.orchestrator.isRunning()) return;
89
+
90
+ // Check if dev phase is active
91
+ const projectRoot = engine.resolveProjectRoot();
92
+ if (!projectRoot) return;
93
+
94
+ const focusPath = path.join(projectRoot, '.yuri', 'focus.yaml');
95
+ if (!fs.existsSync(focusPath)) return;
96
+
97
+ try {
98
+ const focus = yaml.load(fs.readFileSync(focusPath, 'utf8')) || {};
99
+ if (parseInt(focus.phase, 10) !== 3) return;
100
+
101
+ // Check tmux session is alive
102
+ const { execSync } = require('child_process');
103
+ const sessions = execSync('tmux list-sessions -F "#{session_name}" 2>/dev/null', { encoding: 'utf8' }).trim();
104
+ if (!sessions.split('\n').some((s) => s.startsWith('orchestrix-'))) return;
105
+
106
+ // Generate and send progress card
107
+ const card = this._buildStatusCard(projectRoot, focus);
108
+ if (card) {
109
+ log.router('Auto-reporting dev progress');
110
+ this._sendProactive(card);
111
+ }
112
+ } catch { /* silent */ }
113
+ }, interval);
72
114
  }
73
115
 
74
116
  /**
@@ -725,6 +767,7 @@ class Router {
725
767
  * Graceful shutdown.
726
768
  */
727
769
  async shutdown() {
770
+ if (this._reportTimer) clearInterval(this._reportTimer);
728
771
  this.orchestrator.shutdown();
729
772
  if (engine.destroySession) engine.destroySession();
730
773
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchestrix-yuri",
3
- "version": "4.2.3",
3
+ "version": "4.2.5",
4
4
  "description": "Yuri — Meta-Orchestrator for Orchestrix. Drive your entire project lifecycle with natural language.",
5
5
  "main": "lib/installer.js",
6
6
  "bin": {
@@ -105,27 +105,63 @@ Read `{project}/.yuri/state/phase2.yaml`.
105
105
 
106
106
  ### IF Phase 3 (Develop) is in progress or complete:
107
107
 
108
- Read `{project}/.yuri/state/phase3.yaml`.
108
+ **Generate a progress card** using these data sources:
109
109
 
110
- Scan current story statuses:
110
+ **1. Scan story statuses:**
111
111
  ```bash
112
112
  SCRIPT_DIR="${CLAUDE_SKILL_DIR}/scripts"
113
113
  bash "$SCRIPT_DIR/scan-stories.sh" "$PROJECT_DIR"
114
114
  ```
115
115
 
116
- ```
117
- ### Development Progress
118
-
119
- | Metric | Value |
120
- |--------|-------|
121
- | Total Stories | {total} |
122
- | Done | {done count} |
123
- | In Progress | {in_progress count} |
124
- | Blocked | {blocked count} |
125
- | Remaining | {remaining count} |
116
+ The script outputs:
117
+ - `Total:{N}` — total planned stories from all `docs/prd/epic-*.yaml` definitions
118
+ - `Created:{N}` — story files in `docs/stories/`
119
+ - `StatusDone:{filename}` / `StatusInProgress:{filename}` / etc. — per-file status
120
+ - `Epics:{N}` — total epics (max N from `docs/prd/epic-N-*`)
121
+ - `CurrentEpic:{N}` epic of current story
122
+ - `CurrentStory:{filename}` InProgress or last non-Done story
126
123
 
127
- Progress: [{done}/{total}] {'█' * pct}{'░' * (100-pct)} {pct}%
128
- ```
124
+ **2. Detect active tmux agent:**
125
+ ```bash
126
+ # Check which orchestrix-* session exists
127
+ tmux list-sessions -F "#{session_name}" 2>/dev/null | grep "^orchestrix-"
128
+
129
+ # For each window (0=Architect, 1=SM, 2=Dev, 3=QA):
130
+ # - Window showing "Command | Description" table = IDLE
131
+ # - Window WITHOUT that table = actively executing
132
+ for w in 0 1 2 3; do
133
+ OUTPUT=$(tmux capture-pane -t "$DEV_SESSION:$w" -p -S -15)
134
+ if ! echo "$OUTPUT" | grep -q "Command.*Description"; then
135
+ echo "Window $w is ACTIVE"
136
+ fi
137
+ done
138
+ ```
139
+
140
+ **3. Format the progress card:**
141
+
142
+ ```
143
+ 📊 Dev Progress Report
144
+ ━━━━━━━━━━━━━━━━━━━━━
145
+ Epic: {CurrentEpic}/{Epics}
146
+ Story: {done}/{total} done ({pct}%) | {created} created
147
+ ▓▓▓▓▓▓░░░░░░░░░░░░░░ {pct}%
148
+ ━━━━━━━━━━━━━━━━━━━━━
149
+ ✅ Done: {N}
150
+ 🔄 InProgress: {N}
151
+ 📋 Approved: {N}
152
+ 📝 Draft: {N}
153
+ ━━━━━━━━━━━━━━━━━━━━━
154
+ 📝 Current: {CurrentStory}
155
+ 🤖 Agent: {active_agent} (window {N})
156
+ ⏱ Running for {elapsed}
157
+ ```
158
+
159
+ Where:
160
+ - `{pct}` = round(done / total * 100)
161
+ - Progress bar: `▓` for filled, `░` for empty (20 chars total)
162
+ - Only show status categories with count > 0
163
+ - `{elapsed}` = time since `focus.updated_at` or `phase3.started_at`
164
+ - If no agent is active (all windows show Command table), show "All agents idle (waiting for handoff)"
129
165
 
130
166
  ### IF Phase 4 (Test) is in progress or complete:
131
167