@liriraid/agentflow-ai 1.0.11 → 1.0.13
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/orchestrator.js
CHANGED
|
@@ -701,15 +701,15 @@ function parseQueue() {
|
|
|
701
701
|
let section = "";
|
|
702
702
|
for (const rawLine of content.split("\n")) {
|
|
703
703
|
const line = rawLine.trim();
|
|
704
|
-
if (line.startsWith("## Pending")) {
|
|
704
|
+
if (line.startsWith("## Pending") || line.startsWith("## Pendientes")) {
|
|
705
705
|
section = "pending";
|
|
706
706
|
continue;
|
|
707
707
|
}
|
|
708
|
-
if (line.startsWith("## In Progress")) {
|
|
708
|
+
if (line.startsWith("## In Progress") || line.startsWith("## En progreso")) {
|
|
709
709
|
section = "inprogress";
|
|
710
710
|
continue;
|
|
711
711
|
}
|
|
712
|
-
if (line.startsWith("## Completed")) {
|
|
712
|
+
if (line.startsWith("## Completed") || line.startsWith("## Completadas")) {
|
|
713
713
|
section = "completed";
|
|
714
714
|
continue;
|
|
715
715
|
}
|
|
@@ -743,15 +743,15 @@ function parseCompletedFromFile() {
|
|
|
743
743
|
let section = "";
|
|
744
744
|
for (const rawLine of content.split("\n")) {
|
|
745
745
|
const line = rawLine.trim();
|
|
746
|
-
if (line.startsWith("## Pending")) {
|
|
746
|
+
if (line.startsWith("## Pending") || line.startsWith("## Pendientes")) {
|
|
747
747
|
section = "pending";
|
|
748
748
|
continue;
|
|
749
749
|
}
|
|
750
|
-
if (line.startsWith("## In Progress")) {
|
|
750
|
+
if (line.startsWith("## In Progress") || line.startsWith("## En progreso")) {
|
|
751
751
|
section = "inprogress";
|
|
752
752
|
continue;
|
|
753
753
|
}
|
|
754
|
-
if (line.startsWith("## Completed")) {
|
|
754
|
+
if (line.startsWith("## Completed") || line.startsWith("## Completadas")) {
|
|
755
755
|
section = "completed";
|
|
756
756
|
continue;
|
|
757
757
|
}
|
|
@@ -798,6 +798,45 @@ function reloadQueue() {
|
|
|
798
798
|
});
|
|
799
799
|
}
|
|
800
800
|
|
|
801
|
+
// ============================================================================
|
|
802
|
+
// INBOX NOTIFICATIONS — written when a task completes so the Orchestrator
|
|
803
|
+
// session can detect it on next interaction without Modo Ausencia active.
|
|
804
|
+
// ============================================================================
|
|
805
|
+
function writeInboxNotification(task, agentName, elapsed) {
|
|
806
|
+
const inboxFile = path.join(WORKSPACE, "INBOX.md");
|
|
807
|
+
const progressFile = `progress/PROGRESS-${agentName}.md`;
|
|
808
|
+
const entry = [
|
|
809
|
+
``,
|
|
810
|
+
`## [${timestamp()}] ${task.id} completada — ${agentName}`,
|
|
811
|
+
``,
|
|
812
|
+
`- **Tarea:** ${task.title}`,
|
|
813
|
+
`- **Duración:** ${formatDuration(elapsed)}`,
|
|
814
|
+
`- **Reporte:** ${progressFile}`,
|
|
815
|
+
`- **Acción:** Lee \`${progressFile}\` y crea las siguientes TASKs si corresponde.`,
|
|
816
|
+
``,
|
|
817
|
+
].join("\n");
|
|
818
|
+
try {
|
|
819
|
+
fs.appendFileSync(inboxFile, entry, "utf-8");
|
|
820
|
+
} catch {}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
function writeInboxFailureNotification(task, failedAgent, newAgent, reason) {
|
|
824
|
+
const inboxFile = path.join(WORKSPACE, "INBOX.md");
|
|
825
|
+
const entry = [
|
|
826
|
+
``,
|
|
827
|
+
`## [${timestamp()}] ${task.id} falló — ${failedAgent} → reasignada a ${newAgent}`,
|
|
828
|
+
``,
|
|
829
|
+
`- **Tarea:** ${task.title}`,
|
|
830
|
+
`- **Motivo:** ${reason}`,
|
|
831
|
+
`- **Nuevo agente:** ${newAgent}`,
|
|
832
|
+
`- **Acción:** La TUI reasignó automáticamente. Verifica en QUEUE.md o espera la siguiente notificación de completada.`,
|
|
833
|
+
``,
|
|
834
|
+
].join("\n");
|
|
835
|
+
try {
|
|
836
|
+
fs.appendFileSync(inboxFile, entry, "utf-8");
|
|
837
|
+
} catch {}
|
|
838
|
+
}
|
|
839
|
+
|
|
801
840
|
// ============================================================================
|
|
802
841
|
// BRIEF GENERATOR
|
|
803
842
|
// ============================================================================
|
|
@@ -1217,6 +1256,7 @@ function completeTask(task, agentName) {
|
|
|
1217
1256
|
ag.startTime = null;
|
|
1218
1257
|
ag.lastLine = `Última: ${task.id} completada`;
|
|
1219
1258
|
updateQueueFile(task);
|
|
1259
|
+
writeInboxNotification(task, agentName, elapsed);
|
|
1220
1260
|
scheduleNext();
|
|
1221
1261
|
renderDashboard();
|
|
1222
1262
|
}
|
|
@@ -1302,19 +1342,20 @@ function failTask(task, agentName, code) {
|
|
|
1302
1342
|
ag.process = null;
|
|
1303
1343
|
ag.startTime = null;
|
|
1304
1344
|
|
|
1305
|
-
const
|
|
1345
|
+
const shouldFallback =
|
|
1306
1346
|
["Codex", "OpenCode"].includes(agentName) &&
|
|
1307
1347
|
(failureFlags.exhaustedQuota ||
|
|
1308
1348
|
failureFlags.providerUnavailable ||
|
|
1309
1349
|
retries >= maxRetries);
|
|
1310
1350
|
|
|
1311
|
-
if (
|
|
1351
|
+
if (shouldFallback) {
|
|
1312
1352
|
const reason = failureFlags.exhaustedQuota
|
|
1313
1353
|
? "cuota o límite agotado"
|
|
1314
1354
|
: failureFlags.providerUnavailable
|
|
1315
1355
|
? "proveedor o sesión no disponibles"
|
|
1316
1356
|
: "fallo persistente";
|
|
1317
|
-
if (
|
|
1357
|
+
if (tryFallbackToAlternative(task, agentName, reason)) {
|
|
1358
|
+
writeInboxFailureNotification(task, agentName, task.agent, reason);
|
|
1318
1359
|
setTimeout(() => {
|
|
1319
1360
|
scheduleNext();
|
|
1320
1361
|
renderDashboard();
|
|
@@ -1406,7 +1447,7 @@ function updateQueueFile(completedTask) {
|
|
|
1406
1447
|
`^${completedTask.id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(\\s|$|\\|)`,
|
|
1407
1448
|
);
|
|
1408
1449
|
const filtered = lines.filter((l) => !idMatcher.test(l.trim()));
|
|
1409
|
-
const idx = filtered.findIndex((l) => l.trim().startsWith("## Completed"));
|
|
1450
|
+
const idx = filtered.findIndex((l) => l.trim().startsWith("## Completed") || l.trim().startsWith("## Completadas"));
|
|
1410
1451
|
if (idx >= 0)
|
|
1411
1452
|
filtered.splice(
|
|
1412
1453
|
idx + 1,
|
|
@@ -1474,39 +1515,55 @@ function detectSupportAgentFailure(agentName) {
|
|
|
1474
1515
|
}
|
|
1475
1516
|
|
|
1476
1517
|
function getClaudeFallbackAgent(task) {
|
|
1518
|
+
// If both repos point to the same resolved path (frontend-only project), always prefer Frontend
|
|
1519
|
+
if (
|
|
1520
|
+
REPOS.backend &&
|
|
1521
|
+
REPOS.frontend &&
|
|
1522
|
+
path.resolve(REPOS.backend) === path.resolve(REPOS.frontend)
|
|
1523
|
+
) {
|
|
1524
|
+
if (AGENTS["Frontend"]?.cli === "claude") return "Frontend";
|
|
1525
|
+
}
|
|
1477
1526
|
const preferred = task.repo === "frontend" ? "Frontend" : "Backend";
|
|
1478
1527
|
if (AGENTS[preferred]?.cli === "claude") return preferred;
|
|
1479
|
-
return (
|
|
1480
|
-
Object.keys(AGENTS).find((name) => AGENTS[name]?.cli === "claude") || null
|
|
1481
|
-
);
|
|
1528
|
+
return Object.keys(AGENTS).find((name) => AGENTS[name]?.cli === "claude") || null;
|
|
1482
1529
|
}
|
|
1483
1530
|
|
|
1484
|
-
function
|
|
1531
|
+
function getAlternativeSupportAgent(failedAgentName) {
|
|
1532
|
+
if (failedAgentName === "Codex") return "OpenCode";
|
|
1533
|
+
if (failedAgentName === "OpenCode") return "Codex";
|
|
1534
|
+
return null;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
function tryFallbackToAlternative(task, failedAgentName, reason) {
|
|
1485
1538
|
if (!["Codex", "OpenCode"].includes(failedAgentName)) return false;
|
|
1486
|
-
const fallbackAgent = getClaudeFallbackAgent(task);
|
|
1487
|
-
if (!fallbackAgent || fallbackAgent === failedAgentName) return false;
|
|
1488
1539
|
|
|
1489
|
-
|
|
1490
|
-
|
|
1540
|
+
// Step 1: try sibling support agent (Codex → OpenCode, OpenCode → Codex)
|
|
1541
|
+
const siblingAgent = getAlternativeSupportAgent(failedAgentName);
|
|
1542
|
+
const siblingAvailable =
|
|
1543
|
+
siblingAgent &&
|
|
1544
|
+
AGENTS[siblingAgent] &&
|
|
1545
|
+
state.agents[siblingAgent]?.status === "idle" &&
|
|
1546
|
+
!rateLimitedAgents.has(siblingAgent);
|
|
1547
|
+
|
|
1548
|
+
// Step 2: if sibling is also unavailable, fall back to Claude worker (prefer Frontend)
|
|
1549
|
+
const targetAgent = siblingAvailable ? siblingAgent : getClaudeFallbackAgent(task);
|
|
1550
|
+
if (!targetAgent || targetAgent === failedAgentName) return false;
|
|
1551
|
+
|
|
1552
|
+
const queueUpdated = updateQueueTaskAgent(task.id, targetAgent);
|
|
1553
|
+
task.agent = targetAgent;
|
|
1491
1554
|
task.status = "pending";
|
|
1492
1555
|
task._retryAfter = Date.now() + 3000;
|
|
1493
1556
|
failedTasks.set(task.id, 0);
|
|
1494
1557
|
state.queue.push(task);
|
|
1495
1558
|
|
|
1496
|
-
log(
|
|
1497
|
-
"FALLBACK",
|
|
1498
|
-
`${task.id} fue reasignada de ${failedAgentName} a ${fallbackAgent} (${reason})`,
|
|
1499
|
-
);
|
|
1559
|
+
log("FALLBACK", `${task.id} reasignada de ${failedAgentName} a ${targetAgent} (${reason})`);
|
|
1500
1560
|
appendToAgent(
|
|
1501
1561
|
failedAgentName,
|
|
1502
|
-
`{yellow-fg}=== REASIGNADA A ${escBl(
|
|
1562
|
+
`{yellow-fg}=== REASIGNADA A ${escBl(targetAgent)} (${escBl(reason)}) ==={/yellow-fg}`,
|
|
1503
1563
|
true,
|
|
1504
1564
|
);
|
|
1505
1565
|
if (!queueUpdated) {
|
|
1506
|
-
log(
|
|
1507
|
-
"WARN",
|
|
1508
|
-
`${task.id} fue reasignada a ${fallbackAgent}, pero QUEUE.md no pudo actualizarse automáticamente`,
|
|
1509
|
-
);
|
|
1566
|
+
log("WARN", `${task.id} reasignada a ${targetAgent}, pero QUEUE.md no pudo actualizarse`);
|
|
1510
1567
|
}
|
|
1511
1568
|
return true;
|
|
1512
1569
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liriraid/agentflow-ai",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "Multi-agent workspace orchestrator with TUI. Coordinates AI coding agents over your real frontend and backend projects.",
|
|
5
5
|
"author": "LiriRaid",
|
|
6
6
|
"homepage": "https://github.com/LiriRaid/agentflow-ai#readme",
|
package/src/ink/app.mjs
CHANGED
|
@@ -89,18 +89,18 @@ const AgentCard = ({agent, text}) => {
|
|
|
89
89
|
borderStyle: 'round',
|
|
90
90
|
borderColor: statusColor,
|
|
91
91
|
width: '24%',
|
|
92
|
-
minHeight:
|
|
92
|
+
minHeight: 9,
|
|
93
93
|
paddingX: 1,
|
|
94
94
|
flexDirection: 'column'
|
|
95
95
|
},
|
|
96
|
-
h(Text, {bold: true}, agent.name),
|
|
96
|
+
h(Text, {bold: true, wrap: 'wrap'}, agent.name),
|
|
97
97
|
h(Text, {color: statusColor}, agent.status === 'busy' ? text.busy : text.idle),
|
|
98
98
|
h(
|
|
99
99
|
Text,
|
|
100
|
-
{color: COLORS.muted},
|
|
101
|
-
agent.task
|
|
100
|
+
{color: COLORS.muted, wrap: 'wrap'},
|
|
101
|
+
agent.task || text.noTask
|
|
102
102
|
),
|
|
103
|
-
h(Text, {color: COLORS.muted}, agent.detail || text.ready)
|
|
103
|
+
h(Text, {color: COLORS.muted, wrap: 'wrap'}, agent.detail || text.ready)
|
|
104
104
|
);
|
|
105
105
|
};
|
|
106
106
|
|
|
@@ -229,9 +229,7 @@ export function App({snapshot, paused = false, onAction}) {
|
|
|
229
229
|
key: agent.name,
|
|
230
230
|
agent: {
|
|
231
231
|
...agent,
|
|
232
|
-
|
|
233
|
-
task: agent.task ? truncate(agent.task, agentWidth) : null,
|
|
234
|
-
detail: truncate(agent.detail || text.ready, agentWidth)
|
|
232
|
+
detail: agent.detail || text.ready
|
|
235
233
|
}
|
|
236
234
|
})
|
|
237
235
|
)
|
|
@@ -36,28 +36,44 @@ When the user requests work after startup:
|
|
|
36
36
|
|
|
37
37
|
1. Do not implement the work in the interactive Claude session.
|
|
38
38
|
2. Convert the request into one or more TASKs in `QUEUE.md`.
|
|
39
|
-
3.
|
|
40
|
-
4. Assign a Claude-Worker only when:
|
|
41
|
-
- Codex
|
|
42
|
-
-
|
|
43
|
-
- the task is highly sensitive and needs Claude as the worker,
|
|
44
|
-
- the user explicitly asks Claude to take the worker task.
|
|
39
|
+
3. Always assign first to `OpenCode` (exploration) and `Codex` (implementation).
|
|
40
|
+
4. Assign a Claude-Worker (`Frontend` or `Backend`) **only** when:
|
|
41
|
+
- **Multiple independent tasks exist** AND Codex + OpenCode are both already occupied, OR
|
|
42
|
+
- A task has **permanently failed** in Codex AND OpenCode — then Claude-Worker takes it as last resort.
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
The TUI handles automatic fallback: Codex fails → tries OpenCode → tries Claude-Worker. You only need to manually assign Claude-Workers for load balancing (case a) or when the TUI marks a task as permanently `failed` (case b).
|
|
45
|
+
|
|
46
|
+
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.
|
|
47
|
+
|
|
48
|
+
## This Workspace Is NOT the Real Project
|
|
49
|
+
|
|
50
|
+
This directory (`orchestrator-<name>`) exists **only** for work management:
|
|
51
|
+
- `QUEUE.md` — task queue for agents
|
|
52
|
+
- `TASKS.md` — detailed task specs
|
|
53
|
+
- `handoffs/` — session continuity
|
|
54
|
+
- `progress/` — current state per agent
|
|
55
|
+
- `logs/` — agent output
|
|
56
|
+
|
|
57
|
+
The real project code lives at the paths defined in `orchestrator.config.json → repos`.
|
|
58
|
+
When you need to understand the project in order to plan tasks, **read files from those paths**.
|
|
59
|
+
**Never modify real project files directly** — that is exclusively the workers' job.
|
|
47
60
|
|
|
48
61
|
## Startup Checklist
|
|
49
62
|
|
|
50
63
|
When the user says something like `Read ORCHESTRATOR.md and start`, do this:
|
|
51
64
|
|
|
52
65
|
1. Read this file completely.
|
|
53
|
-
2. Read
|
|
54
|
-
3. Read
|
|
55
|
-
4. Read `
|
|
56
|
-
5. Read `
|
|
57
|
-
6. Read
|
|
58
|
-
7. Read `
|
|
59
|
-
8.
|
|
60
|
-
9.
|
|
66
|
+
2. Read `orchestrator.config.json` — identify the real project paths in `repos` (frontend, backend). Those are the paths where the worker agents operate.
|
|
67
|
+
3. Read `<projectName>-plan.md`, `PLAN.md`, or `plan.md` if present.
|
|
68
|
+
4. Read the newest `handoffs/HANDOFF-*.md` if the folder exists.
|
|
69
|
+
5. **Read `INBOX.md` if it exists** — it contains automatic TUI notifications of completed tasks that require your attention (creating next TASKs, reading agent reports, etc.).
|
|
70
|
+
6. Read `QUEUE.md` to understand pending, active, and completed work.
|
|
71
|
+
7. Read all `progress/PROGRESS-*.md` files if present.
|
|
72
|
+
8. Read `ENGRAM.md` and follow the memory rules.
|
|
73
|
+
9. Use `openspec/` for large or multi-phase changes.
|
|
74
|
+
10. Tell the user the orchestrator is ready and ask what to prioritize.
|
|
75
|
+
|
|
76
|
+
**INBOX rule:** At the start of EACH response, if `INBOX.md` has new entries since your last read, check it first. This is how you know when an agent finished and what to create next — without Away Mode active.
|
|
61
77
|
|
|
62
78
|
Startup is context loading only. Do not create project code changes during startup.
|
|
63
79
|
|
|
@@ -89,14 +105,19 @@ Away Mode limits:
|
|
|
89
105
|
|
|
90
106
|
## Fallback Policy
|
|
91
107
|
|
|
92
|
-
|
|
108
|
+
The TUI handles fallback automatically following this chain:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
Codex fails → tries OpenCode (if idle and not rate-limited)
|
|
112
|
+
↓ (if OpenCode also fails or is blocked)
|
|
113
|
+
→ Frontend (frontend repo) or Backend (backend repo) as last resort
|
|
114
|
+
```
|
|
93
115
|
|
|
94
|
-
|
|
95
|
-
2. Add a clear note in `QUEUE.md`, `TASKS.md`, or a handoff.
|
|
96
|
-
3. Reassign the TASK to a Claude-Worker (`Backend` or `Frontend`, based on the repo).
|
|
97
|
-
4. Include the available context so the Claude-Worker can continue instead of restarting from zero.
|
|
116
|
+
As Orchestrator you do **not** need to manually reassign on failure — the TUI does it. Your role is:
|
|
98
117
|
|
|
99
|
-
|
|
118
|
+
1. Check `INBOX.md` or `QUEUE.md` to confirm the fallback ran correctly.
|
|
119
|
+
2. If the TUI could not resolve it (task marked `failed`), then manually assign to `Frontend` or `Backend` based on the repo.
|
|
120
|
+
3. Leave a note in `QUEUE.md` or `TASKS.md` if the reason is relevant for the session.
|
|
100
121
|
|
|
101
122
|
## Agents
|
|
102
123
|
|
|
@@ -63,21 +63,21 @@
|
|
|
63
63
|
"Codex": {
|
|
64
64
|
"cli": "codex",
|
|
65
65
|
"profile": "codex",
|
|
66
|
-
"defaultRepo": "
|
|
66
|
+
"defaultRepo": "frontend",
|
|
67
67
|
"model": "gpt-5.5",
|
|
68
68
|
"instructionsFile": "agents/CODEX.md"
|
|
69
69
|
},
|
|
70
70
|
"Gemini": {
|
|
71
71
|
"cli": "gemini",
|
|
72
72
|
"profile": "gemini",
|
|
73
|
-
"defaultRepo": "
|
|
73
|
+
"defaultRepo": "frontend",
|
|
74
74
|
"model": "gemini-3-pro-preview",
|
|
75
75
|
"instructionsFile": "agents/GEMINI.md"
|
|
76
76
|
},
|
|
77
77
|
"OpenCode": {
|
|
78
78
|
"cli": "opencode",
|
|
79
79
|
"profile": "opencode",
|
|
80
|
-
"defaultRepo": "
|
|
80
|
+
"defaultRepo": "frontend",
|
|
81
81
|
"model": "opencode/glm-5-free",
|
|
82
82
|
"instructionsFile": "agents/OPENCODE.md"
|
|
83
83
|
},
|
|
@@ -16,19 +16,44 @@ Hay dos roles distintos que no deben confundirse:
|
|
|
16
16
|
1. **Claude-Orquestador**: la sesión interactiva que lee este archivo, divide el trabajo, edita `QUEUE.md`, revisa resultados y decide siguientes pasos. Este rol no modifica código del proyecto directamente.
|
|
17
17
|
2. **Claude-Worker**: agentes lanzados por la TUI con CLI `claude`, por ejemplo `Backend` y `Frontend`. Estos agentes sí pueden implementar código cuando una TASK se les asigna explícitamente.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
**Prioridad de asignación de trabajo:**
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
OpenCode / Codex → primera opción siempre (exploración e implementación)
|
|
23
|
+
Claude-Worker → último recurso, solo en estos dos casos:
|
|
24
|
+
a) Múltiples TASKs independientes Y Codex + OpenCode ambos ocupados → Claude-Worker toma 1
|
|
25
|
+
b) Codex falló persistentemente Y OpenCode también falló → Claude-Worker toma la tarea
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
El Orquestador NO asigna a Claude-Worker en la primera tanda si solo hay 1 tarea o si Codex/OpenCode están disponibles. La TUI gestiona el fallback automático al fallar un agente.
|
|
29
|
+
|
|
30
|
+
## El workspace NO es el proyecto real
|
|
31
|
+
|
|
32
|
+
Este directorio (`orchestrator-<nombre>`) existe **únicamente** para gestión de trabajo:
|
|
33
|
+
- `QUEUE.md` — cola de tareas para los agentes
|
|
34
|
+
- `TASKS.md` — specs detalladas de tareas
|
|
35
|
+
- `handoffs/` — continuidad entre sesiones
|
|
36
|
+
- `progress/` — estado actual de cada agente
|
|
37
|
+
- `logs/` — salida de los agentes
|
|
38
|
+
|
|
39
|
+
El código real del proyecto vive en las rutas definidas en `orchestrator.config.json → repos`.
|
|
40
|
+
Cuando necesites entender el proyecto para planificar tareas, **lee archivos desde esas rutas**.
|
|
41
|
+
**Nunca modifiques archivos del proyecto real directamente** — eso es trabajo exclusivo de los agentes workers.
|
|
20
42
|
|
|
21
43
|
## Al iniciar la sesión — OBLIGATORIO
|
|
22
44
|
|
|
23
45
|
1. Lee este archivo completo.
|
|
24
|
-
2. Lee
|
|
25
|
-
3. Lee
|
|
26
|
-
4. Lee `
|
|
27
|
-
5. Lee `
|
|
28
|
-
6. Lee
|
|
29
|
-
7. Lee `
|
|
30
|
-
8.
|
|
31
|
-
9.
|
|
46
|
+
2. Lee `orchestrator.config.json` — identifica las rutas reales en `repos` (frontend, backend). Esas son las rutas del proyecto real donde trabajan los agentes.
|
|
47
|
+
3. Lee `<projectName>-plan.md` (o `PLAN.md` / `plan.md`) si existe; ese es el plan general.
|
|
48
|
+
4. Lee el handoff más reciente en `handoffs/HANDOFF-*.md` si existe la carpeta.
|
|
49
|
+
5. **Lee `INBOX.md` si existe** — contiene notificaciones automáticas del TUI de tasks completadas que requieren tu atención (crear siguientes TASKs, leer reportes de agentes, etc.).
|
|
50
|
+
6. Lee `QUEUE.md` para ver trabajo activo y pendiente.
|
|
51
|
+
7. Lee todos los archivos `progress/PROGRESS-*.md` que existan para entender el estado actual de cada agente.
|
|
52
|
+
8. Lee `ENGRAM.md` para respetar la convención de memoria persistente del proyecto.
|
|
53
|
+
9. Si existe `openspec/`, úsalo como capa de artefactos para cambios grandes o de varias fases.
|
|
54
|
+
10. Pregunta al usuario qué quiere priorizar; no planifiques toda la sesión automáticamente.
|
|
55
|
+
|
|
56
|
+
**Regla de INBOX:** Al inicio de CADA respuesta, si `INBOX.md` tiene entradas nuevas desde tu última lectura, léelo primero antes de responder al usuario. Así sabrás qué agentes terminaron y qué falta crear.
|
|
32
57
|
|
|
33
58
|
## Restricción operativa por defecto
|
|
34
59
|
|
|
@@ -80,25 +105,19 @@ entonces debes entrar en **Modo Ausencia** durante esa sesión.
|
|
|
80
105
|
|
|
81
106
|
### Fallback por cuota o indisponibilidad
|
|
82
107
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
- rate limit prolongado
|
|
86
|
-
- cuota agotada
|
|
87
|
-
- falta de tokens o de plan disponible
|
|
88
|
-
- sesión expirada
|
|
89
|
-
- error repetido del proveedor
|
|
90
|
-
- indisponibilidad temporal del CLI
|
|
91
|
-
|
|
92
|
-
entonces no debes dejar la tarea en bucle indefinidamente.
|
|
108
|
+
La TUI gestiona el fallback automáticamente siguiendo esta cadena:
|
|
93
109
|
|
|
94
|
-
|
|
110
|
+
```
|
|
111
|
+
Codex falla → intenta OpenCode (si está libre y sin rate limit)
|
|
112
|
+
↓ (si OpenCode también falla o está bloqueado)
|
|
113
|
+
→ Frontend (repo FE) o Backend (repo BE) como último recurso
|
|
114
|
+
```
|
|
95
115
|
|
|
96
|
-
|
|
97
|
-
2. Dejar nota clara del motivo en `QUEUE.md`, `TASKS.md` o handoff si hace falta.
|
|
98
|
-
3. Reasignar la TASK a un **Claude-Worker** (`Backend` o `Frontend`, según el repo) como fallback.
|
|
99
|
-
4. Hacer que Claude-Worker continúe la ejecución con el contexto ya disponible, en vez de abandonar la tarea.
|
|
116
|
+
Como Orquestador, **no necesitas reasignar manualmente** cuando hay un fallo — la TUI lo hace sola. Tu rol en este caso es:
|
|
100
117
|
|
|
101
|
-
|
|
118
|
+
1. Verificar en `INBOX.md` o `QUEUE.md` que el fallback se ejecutó correctamente.
|
|
119
|
+
2. Si la TUI no pudo resolver el fallback (tarea marcada `failed`), entonces sí debes intervenir: asigna explícitamente a `Frontend` o `Backend` según el repo.
|
|
120
|
+
3. Deja nota en `QUEUE.md` o `TASKS.md` del motivo si es relevante para la sesión.
|
|
102
121
|
|
|
103
122
|
### Fin de Modo Ausencia
|
|
104
123
|
|
|
@@ -140,13 +159,13 @@ Revisa `orchestrator.config.json` → `agents`. Cada entrada tiene:
|
|
|
140
159
|
3. (Opcional) Para un brief muy detallado, crea `briefs/TASK-NNN-BRIEF.md`; también se inyecta.
|
|
141
160
|
4. Dependencias: agrega `> after:TASK-NNN` al final de la descripción para bloquear la tarea.
|
|
142
161
|
5. Dile al usuario que presione **R** en la TUI para recargar la cola, o **S** si está pausada.
|
|
143
|
-
6. **
|
|
144
|
-
7.
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
148
|
-
8. Si hay más TASKs que agentes
|
|
149
|
-
9.
|
|
162
|
+
6. **Prioriza Codex y OpenCode** para toda implementación y exploración. Claude-Workers solo cuando hay saturación o fallo total de agentes de soporte.
|
|
163
|
+
7. Distribución según cantidad de TASKs independientes:
|
|
164
|
+
- **1 tarea**: OpenCode (exploración) o Codex (implementación). Nunca Claude-Worker en primera instancia.
|
|
165
|
+
- **2 tareas**: OpenCode + Codex, una cada uno.
|
|
166
|
+
- **3+ tareas** y Codex+OpenCode ambos ocupados: el excedente puede ir a `Frontend` (repo FE) o `Backend` (repo BE) según corresponda.
|
|
167
|
+
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.
|
|
168
|
+
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.
|
|
150
169
|
|
|
151
170
|
## Reglas
|
|
152
171
|
|
|
@@ -158,7 +177,7 @@ Revisa `orchestrator.config.json` → `agents`. Cada entrada tiene:
|
|
|
158
177
|
6. Al terminar la sesión, escribe un `handoffs/HANDOFF-<fecha>.md` resumiendo qué se hizo y qué sigue.
|
|
159
178
|
7. **Por defecto solo usa Claude, Codex y OpenCode**. No uses Gemini, Cursor ni Abacus salvo instrucción explícita del usuario.
|
|
160
179
|
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.
|
|
161
|
-
9.
|
|
180
|
+
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`.
|
|
162
181
|
10. Usa Engram para guardar decisiones, hallazgos, bugs y resúmenes de sesión; no dependas solo del contexto corto de la conversación.
|
|
163
182
|
11. Para cambios grandes, usa `openspec/changes/<change-name>/` para proposal, spec, design, tasks y verify; no dejes todo solo en la conversación.
|
|
164
183
|
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.
|
|
@@ -189,6 +208,7 @@ Actualiza esta sección al inicio y al final de cada sesión:
|
|
|
189
208
|
## Archivos de referencia
|
|
190
209
|
|
|
191
210
|
- **Plan del proyecto:** `<projectName>-plan.md`
|
|
211
|
+
- **Notificaciones de tasks completadas:** `INBOX.md` — el TUI escribe aquí al terminar cada task; léelo al inicio de cada respuesta
|
|
192
212
|
- **Protocolo de agentes:** `AGENT-PROTOCOL.md` (reglas compartidas opcionales)
|
|
193
213
|
- **Instrucciones por agente:** `agents/*.md`
|
|
194
214
|
- **Memoria persistente:** `ENGRAM.md`
|
|
@@ -63,21 +63,21 @@
|
|
|
63
63
|
"Codex": {
|
|
64
64
|
"cli": "codex",
|
|
65
65
|
"profile": "codex",
|
|
66
|
-
"defaultRepo": "
|
|
66
|
+
"defaultRepo": "frontend",
|
|
67
67
|
"model": "gpt-5.5",
|
|
68
68
|
"instructionsFile": "agents/CODEX.md"
|
|
69
69
|
},
|
|
70
70
|
"Gemini": {
|
|
71
71
|
"cli": "gemini",
|
|
72
72
|
"profile": "gemini",
|
|
73
|
-
"defaultRepo": "
|
|
73
|
+
"defaultRepo": "frontend",
|
|
74
74
|
"model": "gemini-3-pro-preview",
|
|
75
75
|
"instructionsFile": "agents/GEMINI.md"
|
|
76
76
|
},
|
|
77
77
|
"OpenCode": {
|
|
78
78
|
"cli": "opencode",
|
|
79
79
|
"profile": "opencode",
|
|
80
|
-
"defaultRepo": "
|
|
80
|
+
"defaultRepo": "frontend",
|
|
81
81
|
"model": "opencode/glm-5-free",
|
|
82
82
|
"instructionsFile": "agents/OPENCODE.md"
|
|
83
83
|
},
|