orchestrix 16.1.2 → 16.1.4

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.
@@ -45,11 +45,18 @@ if [ -z "$REPO_ID" ]; then
45
45
  fi
46
46
 
47
47
  # Generate dynamic session name and log file
48
- SESSION_NAME="orchestrix-${REPO_ID}"
48
+ # If ORCHESTRIX_SESSION is pre-set (e.g., by Yuri remote orchestration), use it.
49
+ # Otherwise, default to orchestrix-{REPO_ID}.
50
+ if [ -n "$ORCHESTRIX_SESSION" ]; then
51
+ SESSION_NAME="$ORCHESTRIX_SESSION"
52
+ echo "🏷️ Using pre-set session name: $SESSION_NAME"
53
+ else
54
+ SESSION_NAME="orchestrix-${REPO_ID}"
55
+ echo "🏷️ Repository ID: $REPO_ID"
56
+ fi
49
57
  # IMPORTANT: Must match handoff-detector.sh pattern: /tmp/${SESSION_NAME}-handoff.log
50
58
  LOG_FILE="/tmp/${SESSION_NAME}-handoff.log"
51
59
 
52
- echo "🏷️ Repository ID: $REPO_ID"
53
60
  echo "📺 tmux Session: $SESSION_NAME"
54
61
  echo "📝 Log file: $LOG_FILE"
55
62
 
@@ -37,6 +37,52 @@ HANDOFF → Auto-routing between agents
37
37
 
38
38
  ---
39
39
 
40
+ ## Environment Detection (Blueprint vs Standalone)
41
+
42
+ > On startup, detect which mode you're running in. This determines how project creation and session management work.
43
+
44
+ ### Detection
45
+
46
+ ```bash
47
+ # Check if running inside a youlidao.ai blueprint workspace
48
+ test -f .youlidao/blueprint.json
49
+ ```
50
+
51
+ | Condition | Mode | Workspace Path | Session Naming |
52
+ |-----------|------|----------------|----------------|
53
+ | `.youlidao/blueprint.json` exists | **Blueprint** | Current directory (already set up) | `op-{blueprint-name}` |
54
+ | `.youlidao/blueprint.json` missing | **Standalone** | Create `~/Codes/{name}/` | `op-{project-name}` |
55
+
56
+ ### Blueprint Mode Behavior
57
+
58
+ When running inside a blueprint workspace (e.g., activated by Gateway in a blueprint tmux session):
59
+
60
+ 1. **Skip project creation steps** — directory, git init, Orchestrix install all done by Gateway
61
+ 2. **Read project context from `.youlidao/blueprint.json`**:
62
+ ```bash
63
+ cat .youlidao/blueprint.json
64
+ # → { "blueprintId": "...", "blueprintName": "...", "createdAt": "..." }
65
+ ```
66
+ 3. **Initialize `.yuri/` memory** in the existing workspace (if not already present):
67
+ - Create `.yuri/identity.yaml` from blueprint metadata
68
+ - Create `.yuri/focus.yaml`, `.yuri/state/`, `.yuri/timeline/`
69
+ - Register in `~/.yuri/portfolio/registry.yaml`
70
+ 4. **Use current directory as `WORK_DIR`** for all op-session operations
71
+ 5. **Derive `OP_SESSION` name** from `blueprintName`:
72
+ ```bash
73
+ OP_SESSION="op-$(cat .youlidao/blueprint.json | jq -r '.blueprintName')"
74
+ ```
75
+
76
+ ### Standalone Mode Behavior
77
+
78
+ When NOT in a blueprint workspace (standard Orchestrix usage):
79
+
80
+ 1. Follow the full `*create` flow (collect name, create `~/Codes/{name}/`, install Orchestrix)
81
+ 2. Use `~/Codes/{name}/` as `WORK_DIR`
82
+ 3. Session name: `op-{project-dir-name}`
83
+
84
+ ---
85
+
40
86
  ## tmux Protocol (Mandatory 3-Step Pattern)
41
87
 
42
88
  > **When sending any content to Claude Code via tmux, strictly follow three steps. Violating this causes content to get stuck in the input box.**
@@ -76,6 +122,153 @@ tmux send-keys -t $WIN Enter
76
122
 
77
123
  ---
78
124
 
125
+ ## Remote Orchestration Mode (op-session)
126
+
127
+ > When Yuri runs as a **resident coordinator** (e.g., in a blueprint session), agents work in a **separate tmux session** named `op-{project-name}`. Yuri manages the full lifecycle of this session remotely.
128
+
129
+ ### Architecture
130
+
131
+ ```
132
+ Yuri's window (resident, never cleared)
133
+
134
+ │ tmux send-keys / capture-pane
135
+
136
+ op-{project-name} ← separate tmux session
137
+ ├── Phase A: 1 window "planning", sequential agent switching
138
+ └── Phase B: 4 windows (start-orchestrix.sh), HANDOFF automation
139
+ ```
140
+
141
+ **Key principle**: Yuri **never leaves its own window**. All agent operations happen in the `op-{name}` session via tmux commands.
142
+
143
+ ### Phase A: Remote Planning Pipeline
144
+
145
+ #### Step 1: Create op-session
146
+
147
+ ```bash
148
+ # Determine session name and workspace path
149
+ # Blueprint mode: read from .youlidao/blueprint.json
150
+ # Standalone mode: use project directory name
151
+ if [ -f .youlidao/blueprint.json ]; then
152
+ BP_NAME=$(cat .youlidao/blueprint.json | jq -r '.blueprintName')
153
+ OP_SESSION="op-${BP_NAME}"
154
+ WORK_DIR="$(pwd)"
155
+ else
156
+ OP_SESSION="op-{project-name}"
157
+ WORK_DIR="$HOME/Codes/{project-name}"
158
+ fi
159
+
160
+ # Create session with planning window
161
+ tmux new-session -d -s "$OP_SESSION" -n "planning" -c "$WORK_DIR"
162
+
163
+ # Start Claude Code in planning window
164
+ tmux send-keys -t "$OP_SESSION:planning" "cc"
165
+ sleep 1
166
+ tmux send-keys -t "$OP_SESSION:planning" Enter
167
+
168
+ # Wait for CC ready
169
+ sleep 12
170
+ ```
171
+
172
+ #### Step 2: Run planning agents sequentially
173
+
174
+ ```bash
175
+ # Activate first agent
176
+ tmux send-keys -t "$OP_SESSION:planning" "/o analyst"
177
+ sleep 1
178
+ tmux send-keys -t "$OP_SESSION:planning" Enter
179
+ sleep 12 # Wait for agent load via MCP
180
+
181
+ # Send command
182
+ tmux send-keys -t "$OP_SESSION:planning" "*create-doc project-brief"
183
+ sleep 1
184
+ tmux send-keys -t "$OP_SESSION:planning" Enter
185
+
186
+ # Monitor completion (use detection methods from table above)
187
+ # Poll output until completion detected:
188
+ tmux capture-pane -t "$OP_SESSION:planning" -p | tail -20
189
+ ```
190
+
191
+ #### Step 3: Switch to next agent (repeat for each)
192
+
193
+ ```bash
194
+ # Clear previous agent
195
+ tmux send-keys -t "$OP_SESSION:planning" "/clear"
196
+ sleep 1
197
+ tmux send-keys -t "$OP_SESSION:planning" Enter
198
+ sleep 2
199
+
200
+ # Activate next agent
201
+ tmux send-keys -t "$OP_SESSION:planning" "/o pm"
202
+ sleep 1
203
+ tmux send-keys -t "$OP_SESSION:planning" Enter
204
+ sleep 12
205
+
206
+ # Send command
207
+ tmux send-keys -t "$OP_SESSION:planning" "*create-doc prd"
208
+ sleep 1
209
+ tmux send-keys -t "$OP_SESSION:planning" Enter
210
+ ```
211
+
212
+ **Planning agent sequence**: `analyst` → `pm` → `ux-expert` (optional) → `architect` → `po`
213
+
214
+ #### Step 4: Report progress
215
+
216
+ After each agent completes, output structured progress to your own window (visible to the user):
217
+
218
+ ```
219
+ 📋 Planning Progress [2/5]
220
+ ✅ Analyst — project-brief.md generated
221
+ ▶️ PM — generating PRD...
222
+ ⏳ UX Expert
223
+ ⏳ Architect
224
+ ⏳ PO
225
+ ```
226
+
227
+ ### Phase A → B Transition
228
+
229
+ When PO completes (step 5):
230
+
231
+ ```bash
232
+ # Kill planning session
233
+ tmux kill-session -t "$OP_SESSION"
234
+
235
+ # Launch dev session with same op-{name}
236
+ # start-orchestrix.sh reads ORCHESTRIX_SESSION and uses it as the session name
237
+ # instead of its default "orchestrix-{repo-id}" naming.
238
+ ORCHESTRIX_SESSION="$OP_SESSION" bash "$WORK_DIR/.orchestrix-core/scripts/start-orchestrix.sh"
239
+ ```
240
+
241
+ **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.
242
+
243
+ ### Phase B: Remote Development Monitoring
244
+
245
+ After `start-orchestrix.sh` launches, HANDOFF automation runs autonomously. Yuri monitors:
246
+
247
+ ```bash
248
+ # Watch HANDOFF log
249
+ tail -f /tmp/${OP_SESSION}-handoff.log
250
+
251
+ # Check specific agent output
252
+ tmux capture-pane -t "$OP_SESSION:1" -p | tail -20 # SM
253
+ tmux capture-pane -t "$OP_SESSION:2" -p | tail -20 # Dev
254
+
255
+ # Check story completion
256
+ ls "$WORK_DIR/docs/stories/"
257
+ git -C "$WORK_DIR" log --oneline -5
258
+ ```
259
+
260
+ ### Session Lifecycle
261
+
262
+ | Event | Action |
263
+ |-------|--------|
264
+ | User says "start planning" | Create `op-{name}`, begin agent sequence |
265
+ | Planning complete | Kill `op-{name}`, launch `start-orchestrix.sh` |
266
+ | Development complete | Report to user, ready for Phase C |
267
+ | User says "stop" / "cancel" | `tmux kill-session -t "$OP_SESSION"` |
268
+ | Reconnect / resume | Check `tmux has-session -t "$OP_SESSION"` to detect existing session |
269
+
270
+ ---
271
+
79
272
  ## Full Workflow Overview
80
273
 
81
274
  ```
package/lib/license.js CHANGED
@@ -2,14 +2,24 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
+ const os = require('os');
5
6
  const ui = require('./ui');
6
7
 
8
+ // License key format: orch_{tier}_{identifier}
9
+ // Examples: orch_live_xxx, orch_trial_xxx, ORCH-TEAM-xxx
10
+ const KEY_PATTERN = /^(orch_[a-z]+_[\w]+|ORCH-[A-Z]+-[\w-]+)$/;
11
+
12
+ function isValidKeyFormat(key) {
13
+ return KEY_PATTERN.test(key);
14
+ }
15
+
7
16
  /**
8
17
  * Resolve license key from multiple sources (priority order):
9
18
  * 1. --key CLI flag
10
19
  * 2. ORCHESTRIX_LICENSE_KEY env var
11
- * 3. .env.local file in cwd
12
- * 4. Interactive prompt
20
+ * 3. .orchestrix-key hidden file (project dir → home dir)
21
+ * 4. .env.local file in cwd
22
+ * 5. Interactive prompt (saves to .orchestrix-key for next time)
13
23
  */
14
24
  async function resolveKey(flags) {
15
25
  // 1. CLI flag
@@ -23,7 +33,23 @@ async function resolveKey(flags) {
23
33
  return process.env.ORCHESTRIX_LICENSE_KEY;
24
34
  }
25
35
 
26
- // 3. .env.local file
36
+ // 3. .orchestrix-key hidden file (project dir first, then home dir)
37
+ const keyLocations = [
38
+ path.join(process.cwd(), '.orchestrix-key'),
39
+ path.join(os.homedir(), '.orchestrix-key'),
40
+ ];
41
+ for (const keyPath of keyLocations) {
42
+ if (fs.existsSync(keyPath)) {
43
+ const raw = fs.readFileSync(keyPath, 'utf-8').trim();
44
+ if (raw && isValidKeyFormat(raw)) {
45
+ const rel = keyPath.startsWith(process.cwd()) ? '.orchestrix-key' : '~/.orchestrix-key';
46
+ ui.info(`Using license key from ${rel}`);
47
+ return raw;
48
+ }
49
+ }
50
+ }
51
+
52
+ // 4. .env.local file
27
53
  const envLocalPath = path.join(process.cwd(), '.env.local');
28
54
  if (fs.existsSync(envLocalPath)) {
29
55
  const content = fs.readFileSync(envLocalPath, 'utf-8');
@@ -34,11 +60,17 @@ async function resolveKey(flags) {
34
60
  }
35
61
  }
36
62
 
37
- // 4. Interactive prompt
63
+ // 5. Interactive prompt
38
64
  const key = await ui.prompt('Enter your Orchestrix license key');
39
65
  if (!key) {
40
66
  throw new Error('License key is required. Use --key <KEY> or set ORCHESTRIX_LICENSE_KEY env var.');
41
67
  }
68
+
69
+ // Save to ~/.orchestrix-key for future use
70
+ const globalKeyPath = path.join(os.homedir(), '.orchestrix-key');
71
+ fs.writeFileSync(globalKeyPath, key + '\n', { mode: 0o600 });
72
+ ui.success(`License key saved to ~/.orchestrix-key`);
73
+
42
74
  return key;
43
75
  }
44
76
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchestrix",
3
- "version": "16.1.2",
3
+ "version": "16.1.4",
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"