@liriraid/agentflow-ai 1.0.25 → 1.0.27

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/bin/agentflow.mjs CHANGED
File without changes
package/orchestrator.js CHANGED
@@ -9,12 +9,17 @@
9
9
  const blessed = require("blessed");
10
10
  const { spawn } = require("child_process");
11
11
  const fs = require("fs");
12
+ const os = require("os");
12
13
  const path = require("path");
13
14
 
14
15
  const WORKSPACE = process.env.ORCHESTRATOR_WORKSPACE
15
16
  ? path.resolve(process.env.ORCHESTRATOR_WORKSPACE)
16
17
  : path.resolve(process.cwd());
17
18
 
19
+ // Global supply chain — the user's ~/.claude dir (rules, skills, CLAUDE.md, etc.)
20
+ // Worker agents are given access to this dir so they follow the same standards as Claude.
21
+ const GLOBAL_CLAUDE_DIR = path.join(os.homedir(), ".claude");
22
+
18
23
  // ============================================================================
19
24
  // CONFIGURATION — loaded from orchestrator.config.json
20
25
  // ============================================================================
@@ -1008,35 +1013,6 @@ function parseCompletedFromFile() {
1008
1013
  }
1009
1014
 
1010
1015
  const loggedUnknownAgents = new Set();
1011
- let queueWatcher = null;
1012
-
1013
- function setupQueueWatcher() {
1014
- if (!fs.existsSync(QUEUE_FILE)) return;
1015
-
1016
- if (queueWatcher) {
1017
- try { queueWatcher.close(); } catch {}
1018
- queueWatcher = null;
1019
- }
1020
-
1021
- try {
1022
- queueWatcher = fs.watch(QUEUE_FILE, { persistent: false }, (eventType, filename) => {
1023
- if (eventType === 'change' && filename === path.basename(QUEUE_FILE)) {
1024
- log('DEBUG', `QUEUE.md changed, reloading queue immediately`);
1025
- reloadQueue();
1026
- scheduleNext();
1027
- renderDashboard();
1028
- }
1029
- });
1030
- queueWatcher.on('error', (err) => {
1031
- log('WARN', `fs.watch failed for QUEUE.md: ${err.message}, falling back to polling`);
1032
- queueWatcher = null;
1033
- });
1034
- log('INFO', 'Realtime QUEUE.md watcher enabled');
1035
- } catch (err) {
1036
- log('WARN', `Failed to setup QUEUE.md watcher: ${err.message}, using polling`);
1037
- queueWatcher = null;
1038
- }
1039
- }
1040
1016
 
1041
1017
  function reloadQueue() {
1042
1018
  state.queue = parseQueue();
@@ -1178,6 +1154,14 @@ function generateBrief(task) {
1178
1154
  if (taskMatch) taskEntry = taskMatch[0];
1179
1155
  }
1180
1156
 
1157
+ // Global developer standards — read the user's ~/.claude/CLAUDE.md verbatim.
1158
+ // Each developer has their own standards there; we don't parse specific sections.
1159
+ let globalStandards = "";
1160
+ const globalClaude = path.join(GLOBAL_CLAUDE_DIR, "CLAUDE.md");
1161
+ if (fs.existsSync(globalClaude)) {
1162
+ globalStandards = fs.readFileSync(globalClaude, "utf-8").trim();
1163
+ }
1164
+
1181
1165
  // Project plan — if `<projectName>-plan.md` or `PLAN.md` exists in the workspace,
1182
1166
  // inject it as shared context so every agent sees the big-picture plan.
1183
1167
  let projectPlan = "";
@@ -1217,7 +1201,9 @@ function generateBrief(task) {
1217
1201
  # Priority: ${task.priority}
1218
1202
  # Workspace: ${WORKSPACE}
1219
1203
  # Progress file: ${progressFile}
1204
+ # Global supply chain: ${GLOBAL_CLAUDE_DIR}
1220
1205
 
1206
+ ${globalStandards ? `## Global Developer Standards\n> Extracted from ${globalClaude} — apply these rules to ALL code in this task.\n\n${globalStandards}\n` : ""}
1221
1207
  ${projectPlan ? `## Project Plan (big picture — use as context, don't try to do everything)\n${projectPlan}\n` : ""}
1222
1208
  ${agentInstructions ? `## Agent Instructions\n${agentInstructions}` : ""}
1223
1209
  ${protocolRules ? `## Protocol Rules\n${protocolRules}` : ""}
@@ -1274,6 +1260,7 @@ function buildCliCommand(agentCfg, task, prompt) {
1274
1260
  ...(agentCfg.model ? ["--model", agentCfg.model] : []),
1275
1261
  "--add-dir",
1276
1262
  WORKSPACE,
1263
+ ...(fs.existsSync(GLOBAL_CLAUDE_DIR) ? ["--add-dir", GLOBAL_CLAUDE_DIR] : []),
1277
1264
  "--name",
1278
1265
  `${task.agent}-${task.id}`,
1279
1266
  ],
@@ -1281,7 +1268,14 @@ function buildCliCommand(agentCfg, task, prompt) {
1281
1268
  case "codex":
1282
1269
  return {
1283
1270
  cmd: "codex",
1284
- args: ["exec", "--yolo", "--add-dir", WORKSPACE, "-"],
1271
+ args: [
1272
+ "exec",
1273
+ "--yolo",
1274
+ "--add-dir",
1275
+ WORKSPACE,
1276
+ ...(fs.existsSync(GLOBAL_CLAUDE_DIR) ? ["--add-dir", GLOBAL_CLAUDE_DIR] : []),
1277
+ "-",
1278
+ ],
1285
1279
  };
1286
1280
  case "opencode":
1287
1281
  return {
@@ -1421,7 +1415,7 @@ function launchAgent(task) {
1421
1415
  if (txt) {
1422
1416
  for (const l of txt.split("\n").slice(-3))
1423
1417
  appendToAgent(agentName, l.slice(0, 120));
1424
- ag.lastLine = txt.split("\n").pop().slice(0, 80);
1418
+ ag.lastLine = (txt.split("\n").pop() || "").slice(0, 80);
1425
1419
  }
1426
1420
  }
1427
1421
  if (block.type === "tool_use") {
@@ -1685,6 +1679,7 @@ function failTask(task, agentName, code) {
1685
1679
  task.status = "failed";
1686
1680
  ag.lastLine = L.lastFailed(task.id);
1687
1681
  log("ERROR", L.logPermanentFail(task.id, retries));
1682
+ updateQueueFile(task);
1688
1683
  writeNotifyFile(L.notifyPermanentFail(timestamp(), task.id, agentName));
1689
1684
  } else {
1690
1685
  task.status = "pending";
@@ -1870,6 +1865,7 @@ function getClaudeFallbackAgent(task) {
1870
1865
 
1871
1866
  function getAlternativeSupportAgent(failedAgentName) {
1872
1867
  if (failedAgentName === "OpenCode") return "Codex";
1868
+ if (failedAgentName === "Codex") return "OpenCode";
1873
1869
  return null;
1874
1870
  }
1875
1871
 
@@ -1907,45 +1903,9 @@ function tryFallbackToAlternative(task, failedAgentName, reason) {
1907
1903
  log("WARN", L.logReassignWarn(task.id, targetAgent));
1908
1904
  }
1909
1905
 
1910
- // Notificar a Claude (sesión principal) cuando hay fallback
1911
- notifyClaudeOfFallback(task, failedAgentName, targetAgent, reason);
1912
1906
  return true;
1913
1907
  }
1914
1908
 
1915
- // ============================================================================
1916
- // CLAUDE FALLBACK NOTIFIER — avisa a Claude principal cuando hay reasignación
1917
- // ============================================================================
1918
- function notifyClaudeOfFallback(task, fromAgent, toAgent, reason) {
1919
- const lang = WORKSPACE_LANGUAGE;
1920
- const prompt = lang === 'es'
1921
- ? `⚠️ FALLBACK: La tarea "${task.id}: ${task.title}" falló en ${fromAgent} (${reason}) y fue reasignada a ${toAgent}.
1922
-
1923
- Estado actual:
1924
- - QUEUE.md tiene ahora la tarea asignada a ${toAgent}
1925
- - El agente ${toAgent} está procediendo automáticamente
1926
-
1927
- Acción: No necesitas hacer nada — solo toma nota del cambio. El orquestador将继续 automáticamente.
1928
- Si quieres revisar el progreso, lee INBOX.md o STATUS.md.`
1929
- : `⚠️ FALLBACK: Task "${task.id}: ${task.title}" failed on ${fromAgent} (${reason}) and was reassigned to ${toAgent}.
1930
-
1931
- Current state:
1932
- - QUEUE.md now has the task assigned to ${toAgent}
1933
- - Agent ${toAgent} is proceeding automatically
1934
-
1935
- Action: You don't need to do anything — just take note of the change. The orchestrator will continue automatically.
1936
- If you want to check progress, read INBOX.md or STATUS.md.`;
1937
-
1938
- const logPath = path.join(LOG_DIR, `fallback-notify-${Date.now()}.log`);
1939
- try {
1940
- const logFd = fs.openSync(logPath, 'a');
1941
- const child = spawn('claude', ['-p', prompt, '--add-dir', WORKSPACE, '--dangerously-skip-permissions'], {
1942
- cwd: WORKSPACE, stdio: ['ignore', logFd, logFd], shell: true, windowsHide: true, detached: true
1943
- });
1944
- fs.closeSync(logFd);
1945
- child.unref();
1946
- } catch {}
1947
- }
1948
-
1949
1909
  // ============================================================================
1950
1910
  // KEYBOARD
1951
1911
  // ============================================================================
@@ -2050,7 +2010,6 @@ function setupFallbackQueueWatcher() {
2050
2010
  }
2051
2011
 
2052
2012
  startQueueWatcher();
2053
- setupQueueWatcher();
2054
2013
 
2055
2014
  // Slow fallback (5 min) — only runs if there is actually pending work or busy agents
2056
2015
  // fs.watch handles real-time; this is just a safety net
@@ -2062,92 +2021,12 @@ setInterval(() => {
2062
2021
  renderDashboard();
2063
2022
  }, 5 * 60 * 1000);
2064
2023
 
2065
- // ============================================================================
2066
- // INBOX WATCHER reacts immediately when a task completion is written to INBOX.md
2067
- // Spawns headless Claude to check if a new implementation task needs to be created
2068
- // ============================================================================
2069
- let _inboxDebounce = null;
2070
- let _lastInboxContent = '';
2071
- let _inboxDispatching = false;
2072
-
2073
- function dispatchInboxClaude() {
2074
- if (_inboxDispatching) return;
2075
- let content = '';
2076
- try { content = fs.existsSync(INBOX_FILE) ? fs.readFileSync(INBOX_FILE, 'utf-8') : ''; } catch {}
2077
- if (!content.trim() || content === _lastInboxContent) return;
2078
-
2079
- _lastInboxContent = content;
2080
- _inboxDispatching = true;
2081
-
2082
- const lang = WORKSPACE_LANGUAGE;
2083
- const prompt = lang === 'es'
2084
- ? `Eres el orquestador de este workspace. Tu única misión ahora es procesar el INBOX.
2085
-
2086
- Pasos:
2087
- 1. Lee INBOX.md en ${WORKSPACE}
2088
- 2. Lee QUEUE.md en ${WORKSPACE} para ver las tareas existentes (secciones Pendientes, En progreso, Completadas)
2089
-
2090
- Si en INBOX.md hay análisis completados de un agente (especialmente OpenCode) que aún NO tienen su tarea de implementación en la sección ## Pendientes de QUEUE.md:
2091
- - Determina el siguiente TASK ID disponible leyendo QUEUE.md
2092
- - Crea la nueva TASK en QUEUE.md con el formato exacto:
2093
- TASK-NNN | título corto | Codex | P1 | repo | descripción basada en el análisis
2094
-
2095
- Si ya existe la tarea correspondiente, o el análisis no está completo, responde solo: "Sin acción necesaria."
2096
-
2097
- Reglas: No hagas commit ni push. No analices código del proyecto. Solo lee INBOX.md y QUEUE.md, y edita QUEUE.md si hace falta.`
2098
- : `You are the orchestrator for this workspace. Your only mission now is to process the INBOX.
2099
-
2100
- Steps:
2101
- 1. Read INBOX.md in ${WORKSPACE}
2102
- 2. Read QUEUE.md in ${WORKSPACE} to see existing tasks (sections Pending, In Progress, Completed)
2103
-
2104
- If INBOX.md contains completed analyses from an agent (especially OpenCode) that do NOT yet have a corresponding implementation task in the ## Pending section of QUEUE.md:
2105
- - Determine the next available TASK ID by reading QUEUE.md
2106
- - Create the new TASK in QUEUE.md with the exact format:
2107
- TASK-NNN | short title | Codex | P1 | repo | description based on the analysis
2108
-
2109
- If the corresponding task already exists, or the analysis is not complete, reply only: "No action needed."
2110
-
2111
- Rules: Do not commit or push. Do not analyze project code. Only read INBOX.md and QUEUE.md, and edit QUEUE.md if necessary.`;
2112
-
2113
- const logPath = path.join(LOG_DIR, `inbox-trigger-${Date.now()}.log`);
2114
- try {
2115
- const logFd = fs.openSync(logPath, 'a');
2116
- const child = spawn('claude', [
2117
- '-p', prompt,
2118
- '--add-dir', WORKSPACE,
2119
- '--dangerously-skip-permissions'
2120
- ], {
2121
- cwd: WORKSPACE,
2122
- stdio: ['ignore', logFd, logFd],
2123
- shell: true,
2124
- windowsHide: true,
2125
- detached: true
2126
- });
2127
- fs.closeSync(logFd);
2128
- child.unref();
2129
- log('INFO', lang === 'es'
2130
- ? 'INBOX: Claude despachado para procesar notificación'
2131
- : 'INBOX: Claude dispatched to process notification');
2132
- } catch {}
2133
- setTimeout(() => { _inboxDispatching = false; }, 3 * 60 * 1000);
2134
- }
2135
-
2136
- function startInboxWatcher() {
2137
- if (!fs.existsSync(INBOX_FILE)) {
2138
- try { fs.writeFileSync(INBOX_FILE, '', 'utf-8'); } catch {}
2139
- }
2140
- try {
2141
- const watchName = path.basename(INBOX_FILE);
2142
- const watcher = fs.watch(WORKSPACE, {persistent: false}, (eventType, filename) => {
2143
- if (filename !== watchName) return;
2144
- if (_inboxDebounce) clearTimeout(_inboxDebounce);
2145
- _inboxDebounce = setTimeout(dispatchInboxClaude, 100);
2146
- });
2147
- watcher.on('error', () => {});
2148
- } catch {}
2024
+ // INBOX.md initialization — create empty file if it doesn't exist so the
2025
+ // Claude session can watch it. Notifications are delivered via NOTIFY.md +
2026
+ // the asyncRewake hook in .claude/settings.json (watch-notify.js).
2027
+ if (!fs.existsSync(INBOX_FILE)) {
2028
+ try { fs.writeFileSync(INBOX_FILE, '', 'utf-8'); } catch {}
2149
2029
  }
2150
- startInboxWatcher();
2151
2030
 
2152
2031
  // ============================================================================
2153
2032
  // AWAY MODE WATCHER — monitors .away-mode file; when active runs periodic
@@ -2169,7 +2048,7 @@ function runAwayModeCheck() {
2169
2048
  const completedCount = (state.completed || []).length;
2170
2049
  const hasWork = pendingTasks.length > 0 || inProgressTasks.length > 0 || busy;
2171
2050
 
2172
- if (!hasWork && completedCount > 0) {
2051
+ if (!hasWork) {
2173
2052
  try { fs.unlinkSync(AWAY_MODE_FILE); } catch {}
2174
2053
  deactivateAwayMode();
2175
2054
 
package/package.json CHANGED
@@ -1,65 +1,64 @@
1
- {
2
- "name": "@liriraid/agentflow-ai",
3
- "version": "1.0.25",
4
- "description": "Multi-agent workspace orchestrator with TUI. Coordinates AI coding agents over your real frontend and backend projects.",
5
- "author": "LiriRaid",
6
- "homepage": "https://github.com/LiriRaid/agentflow-ai#readme",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/LiriRaid/agentflow-ai.git"
10
- },
11
- "bugs": {
12
- "url": "https://github.com/LiriRaid/agentflow-ai/issues"
13
- },
14
- "publishConfig": {
15
- "access": "public"
16
- },
17
- "main": "orchestrator.js",
18
- "bin": {
19
- "agentflow": "bin/agentflow.mjs"
20
- },
21
- "files": [
22
- "bin",
23
- "src",
24
- "templates",
25
- "orchestrator.js",
26
- "LICENSE",
27
- "README.md"
28
- ],
29
- "packageManager": "pnpm@11.6.0",
30
- "engines": {
31
- "node": ">=18.0.0"
32
- },
33
- "scripts": {
34
- "start": "node orchestrator.js",
35
- "start:paused": "node orchestrator.js --paused",
36
- "start:ink": "node src/ink/index.mjs",
37
- "start:ink:paused": "node src/ink/index.mjs --paused",
38
- "cli:help": "node bin/agentflow.mjs --help"
39
- },
40
- "keywords": [
41
- "ai",
42
- "agents",
43
- "orchestrator",
44
- "agentflow-ai",
45
- "claude",
46
- "codex",
47
- "gemini",
48
- "cursor",
49
- "opencode",
50
- "abacus",
51
- "tui",
52
- "multi-agent",
53
- "coding-assistant",
54
- "openspec",
55
- "engram",
56
- "skills",
57
- "agent-config"
58
- ],
59
- "license": "MIT",
60
- "dependencies": {
61
- "blessed": "^0.1.81",
62
- "ink": "^5.2.1",
63
- "react": "^18.3.1"
64
- }
65
- }
1
+ {
2
+ "name": "@liriraid/agentflow-ai",
3
+ "version": "1.0.27",
4
+ "description": "Multi-agent workspace orchestrator with TUI. Coordinates AI coding agents over your real frontend and backend projects.",
5
+ "author": "LiriRaid",
6
+ "homepage": "https://github.com/LiriRaid/agentflow-ai#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/LiriRaid/agentflow-ai.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/LiriRaid/agentflow-ai/issues"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "main": "orchestrator.js",
18
+ "bin": {
19
+ "agentflow": "bin/agentflow.mjs"
20
+ },
21
+ "files": [
22
+ "bin",
23
+ "src",
24
+ "templates",
25
+ "orchestrator.js",
26
+ "LICENSE",
27
+ "README.md"
28
+ ],
29
+ "engines": {
30
+ "node": ">=18.0.0"
31
+ },
32
+ "keywords": [
33
+ "ai",
34
+ "agents",
35
+ "orchestrator",
36
+ "agentflow-ai",
37
+ "claude",
38
+ "codex",
39
+ "gemini",
40
+ "cursor",
41
+ "opencode",
42
+ "abacus",
43
+ "tui",
44
+ "multi-agent",
45
+ "coding-assistant",
46
+ "openspec",
47
+ "engram",
48
+ "skills",
49
+ "agent-config"
50
+ ],
51
+ "license": "MIT",
52
+ "dependencies": {
53
+ "blessed": "^0.1.81",
54
+ "ink": "^5.2.1",
55
+ "react": "^18.3.1"
56
+ },
57
+ "scripts": {
58
+ "start": "node orchestrator.js",
59
+ "start:paused": "node orchestrator.js --paused",
60
+ "start:ink": "node src/ink/index.mjs",
61
+ "start:ink:paused": "node src/ink/index.mjs --paused",
62
+ "cli:help": "node bin/agentflow.mjs --help"
63
+ }
64
+ }
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ // Background watcher for NOTIFY.md (asyncRewake hook).
4
+ // Launched on every Stop event. Polls until NOTIFY.md appears, then
5
+ // exits with code 2 to wake the Claude session with the notification.
6
+ // If .away-mode exists, exits immediately — Away Mode handles monitoring.
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ const cwd = process.cwd();
11
+ const notifyFile = path.join(cwd, 'NOTIFY.md');
12
+ const awayFile = path.join(cwd, '.away-mode');
13
+
14
+ if (fs.existsSync(awayFile)) process.exit(0);
15
+ if (fs.existsSync(notifyFile)) deliver();
16
+
17
+ const POLL_MS = 10_000;
18
+ const MAX_MS = 30 * 60_000;
19
+ const start = Date.now();
20
+
21
+ const timer = setInterval(() => {
22
+ if (fs.existsSync(awayFile)) { clearInterval(timer); process.exit(0); }
23
+ if (Date.now() - start > MAX_MS) { clearInterval(timer); process.exit(0); }
24
+ if (fs.existsSync(notifyFile)) { clearInterval(timer); deliver(); }
25
+ }, POLL_MS);
26
+
27
+ function deliver() {
28
+ const content = fs.readFileSync(notifyFile, 'utf8').trim();
29
+ try { fs.unlinkSync(notifyFile); } catch {}
30
+ if (!content) process.exit(0);
31
+ process.stdout.write('\n' + content + '\n');
32
+ process.exit(2);
33
+ }
@@ -6,6 +6,11 @@
6
6
  {
7
7
  "type": "command",
8
8
  "command": "node .claude/hooks/notify-check.js"
9
+ },
10
+ {
11
+ "type": "command",
12
+ "command": "node .claude/hooks/watch-notify.js",
13
+ "asyncRewake": true
9
14
  }
10
15
  ]
11
16
  }
@@ -16,7 +16,7 @@ Gather useful context before creating TASKs or OpenSpec artifacts.
16
16
 
17
17
  ## Critical Rules
18
18
 
19
- - Understand the user's exact scope first.
19
+ - Understand the user's exact scope first — clarify by asking the user directly, **NOT by reading project files yourself**.
20
20
  - Prefer exploration before implementation when context is unclear.
21
21
  - Use **ONLY OpenCode** as the exploration agent when deep codebase analysis is needed — its role is **EXCLUSIVELY analysis**, **NEVER implementation**.
22
22
  - When delegating exploration to OpenCode, include in the brief exactly what it must report: flows, dependencies, architecture findings, inconsistencies, etc.
@@ -47,6 +47,23 @@ The TUI handles automatic fallback: Codex fails → Claude-Worker directly. You
47
47
 
48
48
  The `repo` field determines the working directory: `frontend` for UI/client work, `backend` for API/server work. Codex and OpenCode can work in either repo depending on the task.
49
49
 
50
+ ### Parallel Execution Rule
51
+
52
+ **Never queue all tasks behind one OpenCode analysis if context already exists.**
53
+
54
+ When multiple tasks arrive:
55
+
56
+ - **Check context first**: Are there existing OpenCode reports in `progress/PROGRESS-OpenCode.md` or `INBOX.md` for the area being touched? Is this a long session where the codebase is already well understood?
57
+ - **If context is sufficient** → assign all implementation tasks directly to Codex (and Claude-Worker for overflow) in parallel. Do NOT send them to OpenCode first.
58
+ - **If context is missing for a specific area** → send ONE task to OpenCode for that area. Assign all other independent tasks to Codex in parallel — do not make them wait.
59
+ - **Never serialize work that can run in parallel.** If 5 tasks are independent and context is clear, all 5 go out at once to available agents.
60
+
61
+ **When is context "sufficient"?**
62
+ - OpenCode already reported on this area in the current session.
63
+ - The task is a direct follow-up to a completed task (same files, same pattern).
64
+ - The user explicitly defined what to change (specific files, keys, values) — no exploration needed.
65
+ - Similar tasks were already completed successfully in this session.
66
+
50
67
  ## This Workspace Is NOT the Real Project
51
68
 
52
69
  This directory (`orchestrator-<name>`) exists **only** for work management:
@@ -57,7 +74,7 @@ This directory (`orchestrator-<name>`) exists **only** for work management:
57
74
  - `logs/` — agent output
58
75
 
59
76
  The real project code lives at the paths defined in `orchestrator.config.json → repos`.
60
- When you need to understand the project in order to plan tasks, **read files from those paths**.
77
+ **Do NOT read real project code files to understand the project.** If codebase analysis is needed to plan tasks, delegate it to OpenCode via a TASK in `QUEUE.md` — that is what OpenCode is for.
61
78
  **Never modify real project files directly** — that is exclusively the workers' job.
62
79
 
63
80
  ## Startup Checklist
@@ -119,14 +136,16 @@ del .away-mode
119
136
 
120
137
  ## Fallback Policy
121
138
 
122
- The TUI handles fallback automatically following this chain:
139
+ The TUI handles fallback automatically following these chains:
123
140
 
141
+ **By failure:**
124
142
  ```
125
- Codex fails → OpenCodeFrontend (frontend repo) or Backend (backend repo)
126
- ```
127
- Codex fails → Frontend (frontend repo) or Backend (backend repo) directly
143
+ OpenCode fails → CodexClaude-Worker (Frontend/Backend)
144
+ Codex fails → OpenCode → Claude-Worker (Frontend/Backend)
128
145
  ```
129
146
 
147
+ **By availability (when assigning new tasks):** Claude-Orchestrator should check `STATUS.md` before writing to `QUEUE.md`. If the primary agent for a task is already busy or rate-limited, assign directly to the next available idle agent in the chain rather than queuing behind a busy one.
148
+
130
149
  As Orchestrator you do **not** need to manually reassign on failure — the TUI does it. Your role is:
131
150
 
132
151
  1. Check `INBOX.md` or `QUEUE.md` to confirm the fallback ran correctly.
@@ -160,11 +179,12 @@ Default agent summary:
160
179
  ## How To Assign Work
161
180
 
162
181
  1. **When the user asks for a change or new task** → **NEVER analyze directly yourself**
163
- - **If prior analysis is needed**: Create a TASK in `QUEUE.md` assigned **EXCLUSIVELY** to **OpenCode** to explore the context
164
- - **Wait for the report**: OpenCode writes findings to `progress/PROGRESS-OpenCode.md` and notifies in `INBOX.md`
165
- - **Then implement**: **READ OPENCODE'S REPORT** in `progress/PROGRESS-OpenCode.md` or `INBOX.md` and create new TASK assigned to **Codex** (or Claude-Worker if Codex is unavailable)
182
+ - **If context already exists** (OpenCode reports from this session, completed similar tasks, user-specified exact changes): **skip OpenCode** and create implementation TASKs directly assigned to **Codex** or **Claude-Worker**. Assign all independent tasks in parallel.
183
+ - **If prior analysis is needed** (new area, unknown structure, no prior report): Create ONE TASK in `QUEUE.md` assigned to **OpenCode** for that area. Assign all other independent tasks to Codex in parallel — do not make them wait for OpenCode.
184
+ - **Wait for the OpenCode report only for the tasks that depend on it**: OpenCode writes findings to `progress/PROGRESS-OpenCode.md` and notifies in `INBOX.md`
185
+ - **Then implement the dependent task**: **READ OPENCODE'S REPORT** and create the implementation TASK assigned to **Codex**
166
186
  - **OpenCode DOES NOT implement** — its TASKs are **ONLY for analysis**; implementation **ALWAYS** goes to Codex or Claude-Worker
167
- - **NEVER, under any circumstances, analyze the project code yourself (Claude-Orchestrator)** — **THIS IS OPENCODE'S EXCLUSIVE JOB**. If a report from OpenCode already exists, **USE THAT CONTEXT** to create implementation tasks.
187
+ - **NEVER analyze the project code yourself (Claude-Orchestrator)** — use OpenCode for that. If a report already exists, **USE THAT CONTEXT** directly.
168
188
 
169
189
  2. Write TASKs in `QUEUE.md` with this format:
170
190
 
@@ -202,10 +222,11 @@ Routing preferences:
202
222
  8. Use Engram for durable decisions, bugs, discoveries, and session summaries.
203
223
  9. Use `openspec/changes/<change-name>/` for large changes.
204
224
  10. Claude remains the final reviewer before work is considered accepted.
205
- 11. **MANDATORY VERIFICATION:** Before creating any implementation TASK, **READ AND CONFIRM THAT:**
206
- - There is an OpenCode report in `INBOX.md` or `progress/PROGRESS-OpenCode.md` for the requested analysis.
207
- - The implementation TASK is based **EXCLUSIVELY** on OpenCode's report.
208
- - **YOU (Claude-Orchestrator) HAVE NOT** analyzed the code yourself.
225
+ 11. **MANDATORY VERIFICATION:** Before creating implementation TASKs, confirm one of:
226
+ - There is an OpenCode report in `INBOX.md` or `progress/PROGRESS-OpenCode.md` covering the area, OR
227
+ - The user provided explicit enough detail (exact files, values, changes) that no exploration is needed, OR
228
+ - Similar work was already completed this session (context is already established).
229
+ - **YOU (Claude-Orchestrator) HAVE NOT** analyzed the code yourself in any case.
209
230
 
210
231
  ## TUI Controls
211
232
 
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ // Watcher en background para NOTIFY.md (hook asyncRewake).
4
+ // Se lanza en cada evento Stop. Espera hasta que aparezca NOTIFY.md y
5
+ // sale con código 2 para despertar la sesión de Claude con la notificación.
6
+ // Si existe .away-mode, sale inmediatamente — el Away Mode maneja el monitoreo.
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+
10
+ const cwd = process.cwd();
11
+ const notifyFile = path.join(cwd, 'NOTIFY.md');
12
+ const awayFile = path.join(cwd, '.away-mode');
13
+
14
+ if (fs.existsSync(awayFile)) process.exit(0);
15
+ if (fs.existsSync(notifyFile)) deliver();
16
+
17
+ const POLL_MS = 10_000;
18
+ const MAX_MS = 30 * 60_000;
19
+ const start = Date.now();
20
+
21
+ const timer = setInterval(() => {
22
+ if (fs.existsSync(awayFile)) { clearInterval(timer); process.exit(0); }
23
+ if (Date.now() - start > MAX_MS) { clearInterval(timer); process.exit(0); }
24
+ if (fs.existsSync(notifyFile)) { clearInterval(timer); deliver(); }
25
+ }, POLL_MS);
26
+
27
+ function deliver() {
28
+ const content = fs.readFileSync(notifyFile, 'utf8').trim();
29
+ try { fs.unlinkSync(notifyFile); } catch {}
30
+ if (!content) process.exit(0);
31
+ process.stdout.write('\n' + content + '\n');
32
+ process.exit(2);
33
+ }
@@ -6,6 +6,11 @@
6
6
  {
7
7
  "type": "command",
8
8
  "command": "node .claude/hooks/notify-check.js"
9
+ },
10
+ {
11
+ "type": "command",
12
+ "command": "node .claude/hooks/watch-notify.js",
13
+ "asyncRewake": true
9
14
  }
10
15
  ]
11
16
  }
@@ -17,7 +17,7 @@ Guiar la fase de exploración del orquestador para reunir contexto útil antes d
17
17
 
18
18
  ## Reglas críticas
19
19
 
20
- - Empieza por entender el alcance exacto del pedido del usuario.
20
+ - Empieza por entender el alcance exacto del pedido del usuario — acláralo preguntándole directamente, **NO leyendo archivos del proyecto tú mismo**.
21
21
  - Si hace falta lectura amplia, prioriza exploración y análisis antes de planear implementación.
22
22
  - Usa **SOLO OpenCode** como agente de exploración cuando necesites análisis profundo del codebase — su rol es **EXCLUSIVAMENTE análisis**, **NUNCA implementación**.
23
23
  - Al delegar exploración a OpenCode, incluye en el brief exactamente qué debe reportar: flujos, dependencias, hallazgos de arquitectura, inconsistencias, etc.
@@ -38,7 +38,7 @@ Este directorio (`orchestrator-<nombre>`) existe **únicamente** para gestión d
38
38
  - `logs/` — salida de los agentes
39
39
 
40
40
  El código real del proyecto vive en las rutas definidas en `orchestrator.config.json → repos`.
41
- Cuando necesites entender el proyecto para planificar tareas, **lee archivos desde esas rutas**.
41
+ **NO leas archivos de código del proyecto real para planificar tareas.** Si necesitas análisis del codebase para crear TASKs, delégalo a OpenCode mediante una TASK en `QUEUE.md` — para eso existe OpenCode.
42
42
  **Nunca modifiques archivos del proyecto real directamente** — eso es trabajo exclusivo de los agentes workers.
43
43
 
44
44
  ## Al iniciar la sesión — OBLIGATORIO
@@ -132,14 +132,16 @@ del .away-mode
132
132
 
133
133
  ### Fallback por cuota o indisponibilidad
134
134
 
135
- La TUI gestiona el fallback automáticamente siguiendo esta cadena:
135
+ La TUI gestiona el fallback automáticamente siguiendo estas cadenas:
136
136
 
137
+ **Por fallo:**
137
138
  ```
138
- Codex falla → OpenCodeFrontend (repo FE) o Backend (repo BE)
139
- ```
140
- Codex falla → Frontend (repo FE) o Backend (repo BE) directamente
139
+ OpenCode falla → CodexClaude-Worker (Frontend/Backend)
140
+ Codex falla → OpenCode → Claude-Worker (Frontend/Backend)
141
141
  ```
142
142
 
143
+ **Por disponibilidad (al asignar tareas nuevas):** Claude-Orquestador debe revisar `STATUS.md` antes de escribir en `QUEUE.md`. Si el agente primario para una tarea ya está ocupado o tiene rate limit, asigna directamente al siguiente agente idle en la cadena en lugar de dejar la tarea esperando detrás de uno ocupado.
144
+
143
145
  Como Orquestador, **no necesitas reasignar manualmente** cuando hay un fallo — la TUI lo hace sola. Tu rol en este caso es:
144
146
 
145
147
  1. Verificar en `INBOX.md` o `QUEUE.md` que el fallback se ejecutó correctamente.
@@ -180,11 +182,12 @@ Revisa `orchestrator.config.json` → `agents`. Cada entrada tiene:
180
182
  ## Cómo asignar trabajo
181
183
 
182
184
  1. **Cuando el usuario pide un cambio o nueva tarea** → **NUNCA analices directamente**
183
- - **Si necesita análisis previo**: Crea una TASK en `QUEUE.md` asignada **EXCLUSIVAMENTE** a **OpenCode** para que explore el contexto
184
- - **Espera el reporte**: OpenCode escribe hallazgos en `progress/PROGRESS-OpenCode.md` y notifica en `INBOX.md`
185
- - **Luego implementa**: **LEE EL REPORTE DE OPENCODE** en `progress/PROGRESS-OpenCode.md` o `INBOX.md` y crea nueva TASK asignada a **Codex** (o Claude-Worker si Codex no está disponible)
185
+ - **Si ya existe contexto suficiente** (reportes de OpenCode de esta sesión, tareas similares ya completadas, cambios que el usuario especificó exactamente): **omite OpenCode** y crea TASKs de implementación directamente asignadas a **Codex** o **Claude-Worker**. Asigna todas las tareas independientes en paralelo.
186
+ - **Si se necesita análisis previo** (área nueva, estructura desconocida, sin reporte previo): Crea UNA TASK asignada a **OpenCode** para esa área. Asigna todas las demás tareas independientes a Codex en paralelo — no las hagas esperar a OpenCode.
187
+ - **Espera el reporte de OpenCode solo para las tareas que dependen de él**: OpenCode escribe hallazgos en `progress/PROGRESS-OpenCode.md` y notifica en `INBOX.md`
188
+ - **Luego implementa la tarea dependiente**: **LEE EL REPORTE DE OPENCODE** y crea la TASK de implementación asignada a **Codex**
186
189
  - **OpenCode NO implementa** — sus TASKs son **SOLO de análisis**; la implementación **SIEMPRE** va a Codex o Claude-Worker
187
- - **NUNCA, bajo ninguna circunstancia, analices el código del proyecto directamente tú mismo (Claude-Orquestador)** — **ESO ES TRABAJO EXCLUSIVO DE OPENCODE**. Si ya existe un reporte de OpenCode, **USA ESE CONTEXTO** para crear tareas de implementación.
190
+ - **NUNCA analices el código del proyecto tú mismo (Claude-Orquestador)** — usa OpenCode para eso. Si ya existe un reporte, **USA ESE CONTEXTO** directamente.
188
191
 
189
192
  2. Escribe TASKs en `QUEUE.md` (formato pipe; la TUI lo lee):
190
193
  ```
@@ -198,12 +201,16 @@ Revisa `orchestrator.config.json` → `agents`. Cada entrada tiene:
198
201
  6. **La TUI inicia automáticamente** - NO necesitas presionar R ni S. La TUI detecta nuevas tasks y las lanza.
199
202
  7. **Codex es la primera opción para implementación; OpenCode es la segunda opción.** Claude-Worker es el fallback automático de Codex/OpenCode y también toma trabajo cuando hay más tareas que agentes disponibles.
200
203
  8. **REGLA CRÍTICA SOBRE ANÁLISIS:** Si OpenCode ya analizó algo y escribió su reporte en `INBOX.md` o `progress/PROGRESS-OpenCode.md`, **TÚ (Claude-Orquestador) NO DEBES VOLVER A ANALIZAR EL MISMO CÓDIGO**. Usa el reporte existente para crear tareas de implementación. Si necesitas más detalles, pide a OpenCode que haga un análisis adicional con una nueva TASK, pero **NUNCA lo hagas tú directamente**.
201
- 9. Distribución según cantidad de TASKs independientes:
202
- - **1 tarea de análisis**: OpenCode.
203
- - **1 tarea de implementación**: Codex. Nunca Claude-Worker en primera instancia.
204
- - **2 tareas paralelas**: OpenCode (análisis) + Codex (implementación si la spec está clara).
205
- - **3+ tareas** y Codex ocupado: el excedente va a `Frontend` (repo FE) o `Backend` (repo BE) según corresponda.
206
- 8. Si hay más TASKs que agentes disponibles, deja el resto en cola con dependencias claras o prioridad menor; no uses Gemini, Cursor ni Abacus salvo permiso explícito.
204
+ 9. **Regla de ejecución en paralelo — nunca serialices lo que puede correr en paralelo:**
205
+ - **Si el contexto ya existe**: asigna todas las tareas independientes en paralelo a Codex y Claude-Worker a la vez. No las pongas en cola una por una.
206
+ - **Si falta contexto para un área**: manda UNA TASK a OpenCode para esa área. Las demás tareas independientes van a Codex en paralelo — no esperan a OpenCode.
207
+ - **Distribución por volumen:**
208
+ - 1 tarea de análisis OpenCode
209
+ - 1 tarea de implementación Codex
210
+ - 2 tareas paralelas → OpenCode (análisis) + Codex (implementación con spec clara)
211
+ - 3+ tareas independientes con contexto claro → Codex + Frontend/Backend en paralelo
212
+ - **¿Cuándo el contexto es suficiente?** OpenCode ya reportó sobre esa área en esta sesión / el usuario especificó exactamente qué cambiar / tareas similares ya se completaron esta sesión.
213
+ 10. Si hay más TASKs que agentes disponibles, deja el resto en cola con dependencias claras o prioridad menor; no uses Gemini, Cursor ni Abacus salvo permiso explícito.
207
214
  9. El campo `repo` determina en qué directorio trabaja el agente. Usa siempre el valor correcto: `frontend` para trabajo de UI/cliente, `backend` para trabajo de API/servidor. Codex y OpenCode pueden trabajar en ambos repos según lo que indique la task.
208
215
 
209
216
  ## Reglas
@@ -216,12 +223,13 @@ Revisa `orchestrator.config.json` → `agents`. Cada entrada tiene:
216
223
  6. Al terminar la sesión, escribe un `handoffs/HANDOFF-<fecha>.md` resumiendo qué se hizo y qué sigue.
217
224
  7. **Por defecto solo usa Claude, Codex y OpenCode**. No uses Gemini, Cursor ni Abacus salvo instrucción explícita del usuario.
218
225
  8. Si el usuario activa **Modo Ausencia**, revisa progreso cada 5 minutos y reasigna nuevas TASKs razonables dentro del alcance actual sin esperar confirmación intermedia.
219
- 9. La TUI gestiona el fallback automáticamente: Codex falla → OpenCode → Claude-Worker (Frontend/Backend según repo). Solo intervén manualmente si la tarea queda marcada `failed`.
226
+ 9. La TUI gestiona el fallback automáticamente: OpenCode falla → Codex → Claude-Worker; Codex falla → OpenCode → Claude-Worker. Solo intervén manualmente si la tarea queda marcada `failed`.
220
227
  10. Usa Engram para guardar decisiones, hallazgos, bugs y resúmenes de sesión; no dependas solo del contexto corto de la conversación.
221
- 11. **VERIFICACIÓN OBLIGATORIA:** Antes de crear cualquier TASK de implementación, **LEE Y CONFIRMA QUE:**
222
- - Existe un reporte de OpenCode en `INBOX.md` o `progress/PROGRESS-OpenCode.md` para el análisis solicitado.
223
- - La TASK de implementación se basa **EXCLUSIVAMENTE** en el reporte de OpenCode.
224
- - **NO** has analizado el código mismo (Claude-Orquestador).
228
+ 11. **VERIFICACIÓN OBLIGATORIA:** Antes de crear TASKs de implementación, confirma una de estas condiciones:
229
+ - Existe un reporte de OpenCode en `INBOX.md` o `progress/PROGRESS-OpenCode.md` que cubre el área, O
230
+ - El usuario especificó con suficiente detalle qué cambiar (archivos exactos, valores, cambios concretos), O
231
+ - Trabajo similar ya se completó esta sesión (el contexto ya está establecido).
232
+ - **NO** has analizado el código tú mismo (Claude-Orquestador) en ningún caso.
225
233
  11. Para cambios grandes, usa `openspec/changes/<change-name>/` para proposal, spec, design, tasks y verify; no dejes todo solo en la conversación.
226
234
  12. No asumas bypass total o autoaceptación de cambios en los agentes. Claude debe seguir siendo la autoridad final para validar el resultado esperado antes de que el usuario dé la aprobación definitiva.
227
235