@liriraid/agentflow-ai 1.0.14 → 1.0.15

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.
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ // ============================================================================
3
+ // Auto-trigger script - Ejecutar cada 60 segundos desde Windows Task Scheduler
4
+ // Detecta nuevo contenido en INBOX.md y dispara Claude headless para procesarlo
5
+ // ============================================================================
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const { spawn } = require('child_process');
10
+
11
+ const WORKSPACE = process.env.ORCHESTRATOR_WORKSPACE || process.cwd();
12
+ const INBOX_FILE = path.join(WORKSPACE, 'INBOX.md');
13
+ const QUEUE_FILE = path.join(WORKSPACE, 'QUEUE.md');
14
+ const LAST_CHECK_FILE = path.join(WORKSPACE, 'logs', 'last-auto-check.json');
15
+
16
+ function timestamp() {
17
+ return new Date().toISOString().replace('T', ' ').slice(0, 19);
18
+ }
19
+
20
+ function detectLanguage() {
21
+ if (!fs.existsSync(QUEUE_FILE)) return 'en';
22
+ try {
23
+ const content = fs.readFileSync(QUEUE_FILE, 'utf-8');
24
+ return (content.includes('## Pendientes') || content.includes('## Completadas')) ? 'es' : 'en';
25
+ } catch { return 'en'; }
26
+ }
27
+
28
+ const lang = detectLanguage();
29
+
30
+ // Leer último hash guardado
31
+ let lastCheck = { time: 0, inboxHash: '' };
32
+ try {
33
+ if (fs.existsSync(LAST_CHECK_FILE)) {
34
+ lastCheck = JSON.parse(fs.readFileSync(LAST_CHECK_FILE, 'utf-8'));
35
+ }
36
+ } catch {}
37
+
38
+ // Leer INBOX actual
39
+ let inboxContent = '';
40
+ let currentHash = '';
41
+ try {
42
+ if (fs.existsSync(INBOX_FILE)) {
43
+ inboxContent = fs.readFileSync(INBOX_FILE, 'utf-8');
44
+ currentHash = inboxContent.slice(0, 500);
45
+ }
46
+ } catch {}
47
+
48
+ // Si no hay contenido o no cambió, salir
49
+ if (!inboxContent.trim() || currentHash === lastCheck.inboxHash) {
50
+ console.log(`[${timestamp()}] Sin cambios en INBOX. Nada que procesar.`);
51
+ process.exit(0);
52
+ }
53
+
54
+ console.log(`[${timestamp()}] Nuevo contenido en INBOX detectado — disparando Claude...`);
55
+
56
+ // Guardar hash para no relanzar en el próximo ciclo de 60s
57
+ lastCheck = { time: Date.now(), inboxHash: currentHash };
58
+ fs.mkdirSync(path.dirname(LAST_CHECK_FILE), { recursive: true });
59
+ fs.writeFileSync(LAST_CHECK_FILE, JSON.stringify(lastCheck), 'utf-8');
60
+
61
+ // Prompt para Claude headless — lee INBOX y crea la task de implementación si aplica
62
+ const prompt = lang === 'es'
63
+ ? `Eres el orquestador de este workspace. Tu única misión ahora es procesar el INBOX.
64
+
65
+ Pasos:
66
+ 1. Lee INBOX.md en ${WORKSPACE}
67
+ 2. Lee QUEUE.md en ${WORKSPACE} para ver las tareas existentes (secciones Pendientes, En progreso, Completadas)
68
+
69
+ 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:
70
+ - Determina el siguiente TASK ID disponible leyendo QUEUE.md
71
+ - Crea la nueva TASK en QUEUE.md con el formato exacto:
72
+ TASK-NNN | título corto | Codex | P1 | repo | descripción basada en el análisis
73
+
74
+ Si ya existe la tarea correspondiente, o el análisis no está completo, responde solo: "Sin acción necesaria."
75
+
76
+ 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.`
77
+ : `You are the orchestrator for this workspace. Your only mission now is to process the INBOX.
78
+
79
+ Steps:
80
+ 1. Read INBOX.md in ${WORKSPACE}
81
+ 2. Read QUEUE.md in ${WORKSPACE} to see existing tasks (sections Pending, In Progress, Completed)
82
+
83
+ 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:
84
+ - Determine the next available TASK ID by reading QUEUE.md
85
+ - Create the new TASK in QUEUE.md with the exact format:
86
+ TASK-NNN | short title | Codex | P1 | repo | description based on the analysis
87
+
88
+ If the corresponding task already exists, or the analysis is not complete, reply only: "No action needed."
89
+
90
+ Rules: Do not commit or push. Do not analyze project code. Only read INBOX.md and QUEUE.md, and edit QUEUE.md if necessary.`;
91
+
92
+ const claude = spawn('claude', [
93
+ '-p', prompt,
94
+ '--add-dir', WORKSPACE,
95
+ '--dangerously-skip-permissions'
96
+ ], {
97
+ cwd: WORKSPACE,
98
+ stdio: ['ignore', 'pipe', 'pipe'],
99
+ shell: true
100
+ });
101
+
102
+ let output = '';
103
+ claude.stdout.on('data', d => { output += d.toString(); });
104
+ claude.stderr.on('data', d => { process.stderr.write(d); });
105
+
106
+ claude.on('close', code => {
107
+ const result = output.trim().slice(0, 300);
108
+ console.log(`[${timestamp()}] Claude completó (exit ${code}): ${result}`);
109
+ });
110
+
111
+ claude.on('error', err => {
112
+ console.error(`[${timestamp()}] Error al lanzar Claude: ${err.message}`);
113
+ process.exit(1);
114
+ });
@@ -0,0 +1,172 @@
1
+ #!/usr/bin/env node
2
+ // ============================================================================
3
+ // Monitor script - Ejecutar cada 5 minutos desde Windows Task Scheduler
4
+ // SOLO corre cuando Modo Ausencia está activado (.away-mode existe)
5
+ // En cada revisión manda un prompt a Claude para que monitoree y tome decisiones
6
+ // ============================================================================
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const { spawn } = require('child_process');
11
+
12
+ const WORKSPACE = process.env.ORCHESTRATOR_WORKSPACE || process.cwd();
13
+ const QUEUE_FILE = path.join(WORKSPACE, 'QUEUE.md');
14
+ const INBOX_FILE = path.join(WORKSPACE, 'INBOX.md');
15
+ const STATE_FILE = path.join(WORKSPACE, 'logs', 'orchestrator-state.json');
16
+ const ACTIONS_FILE = path.join(WORKSPACE, 'ACTIONS.md');
17
+ const AWAY_MODE_FILE = path.join(WORKSPACE, '.away-mode');
18
+
19
+ // Si Away Mode no está activado, salir inmediatamente
20
+ if (!fs.existsSync(AWAY_MODE_FILE)) {
21
+ console.log('Monitor: Away Mode no activado. Saltando.');
22
+ process.exit(0);
23
+ }
24
+
25
+ function timestamp() {
26
+ return new Date().toISOString().replace('T', ' ').slice(0, 19);
27
+ }
28
+
29
+ function detectLanguage() {
30
+ if (!fs.existsSync(QUEUE_FILE)) return 'en';
31
+ try {
32
+ const content = fs.readFileSync(QUEUE_FILE, 'utf-8');
33
+ return (content.includes('## Pendientes') || content.includes('## Completadas')) ? 'es' : 'en';
34
+ } catch { return 'en'; }
35
+ }
36
+
37
+ const lang = detectLanguage();
38
+
39
+ function readQueue() {
40
+ if (!fs.existsSync(QUEUE_FILE)) return { pending: [], inProgress: [], completed: [] };
41
+ const result = { pending: [], inProgress: [], completed: [] };
42
+ let section = '';
43
+ for (const line of fs.readFileSync(QUEUE_FILE, 'utf-8').split('\n')) {
44
+ const trimmed = line.trim();
45
+ if (trimmed.startsWith('## Pending') || trimmed.startsWith('## Pendientes')) { section = 'pending'; continue; }
46
+ if (trimmed.startsWith('## In Progress') || trimmed.startsWith('## En progreso')) { section = 'inProgress'; continue; }
47
+ if (trimmed.startsWith('## Completed') || trimmed.startsWith('## Completadas')) { section = 'completed'; continue; }
48
+ if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('>')) continue;
49
+ if (section && trimmed.includes('|')) result[section].push(trimmed);
50
+ }
51
+ return result;
52
+ }
53
+
54
+ function readState() {
55
+ if (!fs.existsSync(STATE_FILE)) return null;
56
+ try { return JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8')); }
57
+ catch { return null; }
58
+ }
59
+
60
+ function launchClaude(prompt) {
61
+ const claude = spawn('claude', [
62
+ '-p', prompt,
63
+ '--add-dir', WORKSPACE,
64
+ '--dangerously-skip-permissions'
65
+ ], {
66
+ cwd: WORKSPACE,
67
+ stdio: 'inherit',
68
+ shell: true
69
+ });
70
+ claude.on('error', err => console.error(`[${timestamp()}] Error lanzando Claude: ${err.message}`));
71
+ return claude;
72
+ }
73
+
74
+ // ============================================================================
75
+ // RECOPILAR ESTADO ACTUAL
76
+ // ============================================================================
77
+ const queue = readQueue();
78
+ const state = readState();
79
+
80
+ const busyAgents = Object.values(state?.agents || {}).filter(a => a.status === 'busy').length;
81
+ const failedAgents = Object.entries(state?.agents || {})
82
+ .filter(([, ag]) => (ag.lastLine || '').startsWith('FALLÓ:') || (ag.lastLine || '').startsWith('FAILED:'))
83
+ .map(([name, ag]) => `${name}: ${ag.lastLine}`);
84
+ const retryingAgents = Object.entries(state?.agents || {})
85
+ .filter(([, ag]) => {
86
+ const ll = ag.lastLine || '';
87
+ return ll.startsWith('REINTENTO:') || ll.startsWith('LÍMITE:') || ll.startsWith('RETRY:');
88
+ })
89
+ .map(([name, ag]) => `${name}: ${ag.lastLine}`);
90
+
91
+ const hasWork = queue.pending.length > 0 || (state?.inProgress?.length || 0) > 0 || busyAgents > 0;
92
+
93
+ console.log(`[${timestamp()}] Monitor Modo Ausencia:`);
94
+ console.log(` Pendientes: ${queue.pending.length} | En progreso: ${state?.inProgress?.length || 0} | Completadas: ${queue.completed.length}`);
95
+ console.log(` Agentes ocupados: ${busyAgents} | Fallidos: ${failedAgents.length} | Reintentando: ${retryingAgents.length}`);
96
+
97
+ // ============================================================================
98
+ // SI NO HAY TRABAJO → DESACTIVAR Y DAR RESUMEN FINAL
99
+ // ============================================================================
100
+ if (!hasWork && queue.completed.length > 0) {
101
+ console.log(` -> Sin trabajo pendiente. Desactivando Modo Ausencia.`);
102
+
103
+ try { fs.unlinkSync(AWAY_MODE_FILE); } catch {}
104
+ try { if (fs.existsSync(ACTIONS_FILE)) fs.unlinkSync(ACTIONS_FILE); } catch {}
105
+
106
+ const donePrompt = lang === 'es'
107
+ ? `Modo Ausencia terminado. Todas las tareas se completaron mientras estabas ausente.
108
+
109
+ Lee QUEUE.md en ${WORKSPACE} y dame un resumen de todo lo que se logró durante la sesión.
110
+ Luego dime si hay algo que podamos continuar o integrar a partir de lo que ya se hizo, o pregúntame qué quiero priorizar a continuación.`
111
+ : `Away Mode ended. All tasks were completed while you were away.
112
+
113
+ Read QUEUE.md in ${WORKSPACE} and give me a summary of everything accomplished during the session.
114
+ Then tell me if there is anything we can continue or integrate from what was done, or ask me what I want to prioritize next.`;
115
+
116
+ launchClaude(donePrompt);
117
+ process.exit(0);
118
+ }
119
+
120
+ // ============================================================================
121
+ // HAY TRABAJO → MANDAR PROMPT A CLAUDE PARA QUE MONITOREE Y TOME DECISIONES
122
+ // ============================================================================
123
+
124
+ // Construir contexto de estado para incluir en el prompt
125
+ const stateLines = [];
126
+ if (queue.pending.length > 0) {
127
+ stateLines.push(`Tareas pendientes en cola: ${queue.pending.length}`);
128
+ queue.pending.slice(0, 5).forEach(t => stateLines.push(` - ${t.split('|').slice(0, 3).join('|').trim()}`));
129
+ }
130
+ if (state?.inProgress?.length > 0) {
131
+ stateLines.push(`Tareas en progreso: ${state.inProgress.map(t => `${t.id} (${t.agent})`).join(', ')}`);
132
+ }
133
+ if (failedAgents.length > 0) {
134
+ stateLines.push(`Agentes con fallo: ${failedAgents.join(' | ')}`);
135
+ }
136
+ if (retryingAgents.length > 0) {
137
+ stateLines.push(`Agentes reintentando: ${retryingAgents.join(' | ')}`);
138
+ }
139
+ if (queue.completed.length > 0) {
140
+ stateLines.push(`Tareas completadas hasta ahora: ${queue.completed.length}`);
141
+ }
142
+
143
+ const stateContext = stateLines.join('\n');
144
+
145
+ const monitorPrompt = lang === 'es'
146
+ ? `Modo Ausencia activo — revisión automática cada 5 minutos.
147
+
148
+ Estado actual del orquestador:
149
+ ${stateContext}
150
+
151
+ Instrucciones:
152
+ 1. Lee INBOX.md en ${WORKSPACE} — si hay análisis completados de agentes que aún no tienen su tarea de implementación en QUEUE.md, crea la TASK correspondiente
153
+ 2. Lee QUEUE.md en ${WORKSPACE} — si hay tareas fallidas que la TUI no pudo reasignar automáticamente (marcadas como failed), reasígnalas manualmente al siguiente agente disponible
154
+ 3. Si hay agentes idle y tareas pendientes que no se están procesando, revisa si hay un problema de dependencias o bloqueo y resuélvelo
155
+ 4. Si detectas que el trabajo avanza normalmente, no hagas nada y responde brevemente el estado
156
+
157
+ No hagas commit ni push. No inventes tareas nuevas fuera del alcance actual.`
158
+ : `Away Mode active — automatic check every 5 minutes.
159
+
160
+ Current orchestrator state:
161
+ ${stateContext}
162
+
163
+ Instructions:
164
+ 1. Read INBOX.md in ${WORKSPACE} — if there are completed agent analyses without a corresponding implementation task in QUEUE.md, create the TASK
165
+ 2. Read QUEUE.md in ${WORKSPACE} — if there are failed tasks that the TUI could not auto-reassign (marked as failed), manually reassign to the next available agent
166
+ 3. If there are idle agents and pending tasks not being processed, check for dependency or blocking issues and resolve them
167
+ 4. If work is progressing normally, do nothing and briefly report the status
168
+
169
+ Do not commit or push. Do not invent new tasks outside the current scope.`;
170
+
171
+ console.log(` -> Disparando prompt a Claude para monitoreo...`);
172
+ launchClaude(monitorPrompt);
package/src/ink/app.mjs CHANGED
@@ -19,6 +19,8 @@ const TEXT = {
19
19
  es: {
20
20
  busy: 'Ocupado',
21
21
  idle: 'En espera',
22
+ failed: 'Falló',
23
+ retrying: 'Reintentando',
22
24
  noTask: 'Sin tarea activa',
23
25
  ready: 'Listo para trabajar',
24
26
  project: 'Proyecto',
@@ -31,9 +33,7 @@ const TEXT = {
31
33
  paused: 'Pausado',
32
34
  preview: 'Explorando Ink',
33
35
  shortcuts: 'Atajos',
34
- start: 'iniciar/reanudar',
35
36
  pause: 'pausar',
36
- reload: 'recargar QUEUE.md',
37
37
  quit: 'salir y matar agentes',
38
38
  summary: 'Resumen',
39
39
  activeQueue: 'Cola activa',
@@ -43,6 +43,8 @@ const TEXT = {
43
43
  en: {
44
44
  busy: 'Busy',
45
45
  idle: 'Idle',
46
+ failed: 'Failed',
47
+ retrying: 'Retrying',
46
48
  noTask: 'No active task',
47
49
  ready: 'Ready to work',
48
50
  project: 'Project',
@@ -55,9 +57,7 @@ const TEXT = {
55
57
  paused: 'Paused',
56
58
  preview: 'Exploring Ink',
57
59
  shortcuts: 'Shortcuts',
58
- start: 'start/resume',
59
60
  pause: 'pause',
60
- reload: 'reload QUEUE.md',
61
61
  quit: 'quit and stop agents',
62
62
  summary: 'Summary',
63
63
  activeQueue: 'Active Queue',
@@ -82,7 +82,20 @@ const Panel = ({title, width, children}) =>
82
82
  );
83
83
 
84
84
  const AgentCard = ({agent, text}) => {
85
- const statusColor = agent.status === 'busy' ? COLORS.success : COLORS.muted;
85
+ const statusColor =
86
+ agent.status === 'busy' ? COLORS.success :
87
+ agent.status === 'failed' ? 'red' :
88
+ agent.status === 'retrying' ? COLORS.warning :
89
+ COLORS.muted;
90
+
91
+ const statusLabel =
92
+ agent.status === 'busy' ? text.busy :
93
+ agent.status === 'failed' ? text.failed :
94
+ agent.status === 'retrying' ? text.retrying :
95
+ text.idle;
96
+
97
+ const costLine = agent.totalCost > 0 ? `${text.cost}: $${agent.totalCost.toFixed(2)}` : null;
98
+
86
99
  return h(
87
100
  Box,
88
101
  {
@@ -94,13 +107,14 @@ const AgentCard = ({agent, text}) => {
94
107
  flexDirection: 'column'
95
108
  },
96
109
  h(Text, {bold: true, wrap: 'wrap'}, agent.name),
97
- h(Text, {color: statusColor}, agent.status === 'busy' ? text.busy : text.idle),
110
+ h(Text, {color: statusColor, bold: agent.status === 'failed' || agent.status === 'retrying'}, statusLabel),
98
111
  h(
99
112
  Text,
100
113
  {color: COLORS.muted, wrap: 'wrap'},
101
114
  agent.task || text.noTask
102
115
  ),
103
- h(Text, {color: COLORS.muted, wrap: 'wrap'}, agent.detail || text.ready)
116
+ h(Text, {color: COLORS.muted, wrap: 'wrap'}, agent.detail || text.ready),
117
+ ...(costLine ? [h(Text, {color: COLORS.success, wrap: 'wrap'}, costLine)] : [])
104
118
  );
105
119
  };
106
120
 
@@ -123,8 +137,6 @@ export function App({snapshot, paused = false, onAction}) {
123
137
  }
124
138
 
125
139
  const normalized = input.toLowerCase();
126
- if (normalized === 'r') onAction?.('reload');
127
- if (normalized === 's') onAction?.('start');
128
140
  if (normalized === 'p') onAction?.('pause');
129
141
  if (normalized === 'q') onAction?.('quit');
130
142
  });
@@ -173,14 +185,10 @@ export function App({snapshot, paused = false, onAction}) {
173
185
  Box,
174
186
  {marginBottom: 1},
175
187
  h(Text, {color: COLORS.warning}, `${text.shortcuts}: `),
176
- h(Text, {bold: true}, 'S'),
177
- h(Text, {color: COLORS.muted}, truncate(` ${text.start} `, Math.max(0, shortcutWidth - 40))),
178
188
  h(Text, {bold: true}, 'P'),
179
189
  h(Text, {color: COLORS.muted}, truncate(` ${text.pause} `, Math.max(0, shortcutWidth - 55))),
180
- h(Text, {bold: true}, 'R'),
181
- h(Text, {color: COLORS.muted}, truncate(` ${text.reload} `, Math.max(0, shortcutWidth - 70))),
182
190
  h(Text, {bold: true}, 'Q'),
183
- h(Text, {color: COLORS.muted}, truncate(` ${text.quit}`, Math.max(0, shortcutWidth - 90)))
191
+ h(Text, {color: COLORS.muted}, truncate(` ${text.quit}`, Math.max(0, shortcutWidth - 70)))
184
192
  ),
185
193
  h(
186
194
  Box,
package/src/ink/index.mjs CHANGED
@@ -219,14 +219,33 @@ function buildSnapshot() {
219
219
 
220
220
  const agents = Object.entries(config.agents || {}).map(([name]) => {
221
221
  const agent = engineState.agents?.[name];
222
+ const lastLine = agent?.lastLine || '';
223
+
224
+ let status;
225
+ if (agent?.status === 'busy') {
226
+ status = 'busy';
227
+ } else if (lastLine.startsWith('FALLÓ:') || lastLine.startsWith('FAILED:')) {
228
+ status = 'failed';
229
+ } else if (
230
+ lastLine.startsWith('REINTENTO:') ||
231
+ lastLine.startsWith('LÍMITE:') ||
232
+ lastLine.startsWith('RETRY:') ||
233
+ lastLine.startsWith('LIMIT:')
234
+ ) {
235
+ status = 'retrying';
236
+ } else {
237
+ status = 'idle';
238
+ }
239
+
222
240
  return {
223
241
  name,
224
- status: agent?.status === 'busy' ? 'busy' : 'idle',
242
+ status,
225
243
  task: agent?.task ? `${agent.task.id} · ${agent.task.title}` : null,
226
244
  detail:
227
245
  agent?.status === 'busy'
228
246
  ? `${agent.task?.priority || 'P?'} · ${agent.task?.repo || 'repo'}`
229
- : agent?.lastLine || text.ready
247
+ : lastLine || text.ready,
248
+ totalCost: agent?.totalCost || 0
230
249
  };
231
250
  });
232
251
 
@@ -64,44 +64,63 @@ When the user says something like `Read ORCHESTRATOR.md and start`, do this:
64
64
 
65
65
  1. Read this file completely.
66
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.
67
+ 3. **Verify script automation:** check if `logs/schedule-configured.json` exists.
68
+ - If it does **NOT exist**: run `agentflow schedule` in the workspace directory to register `auto-trigger.js` (every 1 min) and `monitor-check.js` (every 5 min) in the task scheduler. Then create `logs/schedule-configured.json` with `{"configuredAt": "<date>"}`. Inform the user that automation is ready.
69
+ - If it **already exists**: continue without doing anything.
70
+ 4. Read `<projectName>-plan.md`, `PLAN.md`, or `plan.md` if present.
71
+ 5. Read the newest `handoffs/HANDOFF-*.md` if the folder exists.
72
+ 6. **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.).
73
+ 7. Read `QUEUE.md` to understand pending, active, and completed work.
74
+ 8. Read all `progress/PROGRESS-*.md` files if present.
75
+ 9. Read `ENGRAM.md` and follow the memory rules.
76
+ 10. Use `openspec/` for large or multi-phase changes.
77
+ 11. Tell the user the orchestrator is ready and ask what to prioritize.
75
78
 
76
79
  **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.
77
80
 
81
+ **STATUS rule:** Also read `STATUS.md` at the start of each response to get current context of agents and queue. This file updates automatically every 60 seconds.
82
+
83
+ **ACTIONS rule:** If `ACTIONS.md` exists, read it too — it contains automatic monitoring actions (completed tasks needing follow-up, failed tasks, stuck tasks, etc).
84
+
78
85
  Startup is context loading only. Do not create project code changes during startup.
79
86
 
80
87
  ## Away Mode
81
88
 
82
89
  If the user says something like:
83
90
 
91
+ - `I will be away for 1 hour`
84
92
  - `I will be away for 2 hours`
85
- - `monitor while I am gone`
86
- - `keep checking`
87
- - `continue while I am away`
88
-
89
- enter **Away Mode** for that session.
90
-
91
- In Away Mode:
92
-
93
- 1. Check work state every 5 minutes.
94
- 2. Read `QUEUE.md`, completed tasks, active tasks, idle agents, progress files, and blocked tasks.
95
- 3. Assign new useful TASKs when agents become idle, as long as the work stays within the user's stated goal.
96
- 4. Update `QUEUE.md` and `TASKS.md` when work needs splitting, dependency cleanup, or a next batch.
97
- 5. Keep progress moving without inventing new product scope.
93
+ - `going out for a while`
94
+ - `activate monitoring`
98
95
 
99
- Away Mode limits:
96
+ **Activate Away Mode:**
97
+ ```bash
98
+ echo away > .away-mode
99
+ ```
100
100
 
101
- - Do not change the user's objective.
102
- - Do not open unrelated work streams.
103
- - Do not use Gemini, Cursor, or Abacus without explicit permission.
104
- - If a decision is risky or ambiguous, leave a note in `QUEUE.md` or a handoff instead of guessing.
101
+ **The monitor-check.js script will run every 5 minutes** and check:
102
+ - Completed tasks without follow-up
103
+ - Failed tasks
104
+ - Stuck tasks (>10 min)
105
+ - And write to ACTIONS.md
106
+
107
+ **Auto-deactivate:**
108
+ When there are NO pending tasks AND NO agents working AND all tasks are completed:
109
+ - The script removes .away-mode automatically
110
+ - Away Mode deactivates by itself
111
+ - When you return and say "I'm back" → Clayde responds normally
112
+
113
+ **The monitor-check.js script will run every 5 minutes** and check:
114
+ - Completed tasks without follow-up
115
+ - Failed tasks
116
+ - Stuck tasks (>10 min)
117
+ - And write to ACTIONS.md so when you return, Claude reads it automatically
118
+
119
+ **Deactivate Away Mode:**
120
+ ```bash
121
+ # Delete indicator file
122
+ del .away-mode
123
+ ```
105
124
 
106
125
  ## Fallback Policy
107
126
 
@@ -142,7 +161,13 @@ Default agent summary:
142
161
 
143
162
  ## How To Assign Work
144
163
 
145
- Write TASKs in `QUEUE.md` with this format:
164
+ 1. **When the user asks for a change or new task** → **NEVER analyze directly yourself**
165
+ - **First**: Create a TASK in `QUEUE.md` assigned to **OpenCode** to analyze the context
166
+ - **Second**: Wait for OpenCode to finish its analysis (check INBOX.md or progress/)
167
+ - **Third**: You receive the analysis → create new TASK to implement (Codex or OpenCode)
168
+ - **Never analyze the project code yourself** - that's OpenCode's job
169
+
170
+ 2. Write TASKs in `QUEUE.md` with this format:
146
171
 
147
172
  ```text
148
173
  TASK-NNN | short title | Agent | P1 | repo | detailed description
@@ -155,7 +180,7 @@ Rules:
155
180
  3. Add `> after:TASK-NNN` at the end of the description for dependencies.
156
181
  4. Use `TASKS.md` under `### TASK-NNN` for longer task specs when needed.
157
182
  5. Use `briefs/TASK-NNN-BRIEF.md` for very detailed briefs when needed.
158
- 6. After changing `QUEUE.md`, tell the user to press `R` in the TUI, and `S` if the TUI is paused.
183
+ 6. **The TUI starts automatically** - you don't need to press R or S. The TUI detects new tasks and launches them.
159
184
 
160
185
  Routing preferences:
161
186
 
@@ -44,17 +44,24 @@ Cuando necesites entender el proyecto para planificar tareas, **lee archivos des
44
44
 
45
45
  1. Lee este archivo completo.
46
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.
47
+ 3. **Verifica la automatización de scripts:** revisa si existe `logs/schedule-configured.json`.
48
+ - Si **NO existe**: ejecuta `agentflow schedule` en el directorio del workspace para registrar `auto-trigger.js` (cada 1 min) y `monitor-check.js` (cada 5 min) en el programador de tareas. Luego crea `logs/schedule-configured.json` con `{"configuredAt": "<fecha>"}`. Informa al usuario que la automatización quedó lista.
49
+ - Si **ya existe**: continúa sin hacer nada.
50
+ 4. Lee `<projectName>-plan.md` (o `PLAN.md` / `plan.md`) si existe; ese es el plan general.
51
+ 5. Lee el handoff más reciente en `handoffs/HANDOFF-*.md` si existe la carpeta.
52
+ 6. **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.).
53
+ 7. Lee `QUEUE.md` para ver trabajo activo y pendiente.
54
+ 8. Lee todos los archivos `progress/PROGRESS-*.md` que existan para entender el estado actual de cada agente.
55
+ 9. Lee `ENGRAM.md` para respetar la convención de memoria persistente del proyecto.
56
+ 10. Si existe `openspec/`, úsalo como capa de artefactos para cambios grandes o de varias fases.
57
+ 11. Pregunta al usuario qué quiere priorizar; no planifiques toda la sesión automáticamente.
55
58
 
56
59
  **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.
57
60
 
61
+ **Regla de STATUS:** También lee `STATUS.md` al inicio de cada respuesta para tener contexto del estado actual de los agentes y la cola. Este archivo se actualiza automáticamente cada 60 segundos.
62
+
63
+ **Regla de ACTIONS:** Si existe `ACTIONS.md`, léelo también - contiene acciones automáticas del monitoreo (tareas completadas que necesitan seguimiento, tareas fallidas, etc).
64
+
58
65
  ## Restricción operativa por defecto
59
66
 
60
67
  Aunque esta plantilla soporte múltiples agentes, en este proyecto debes operar **solo con estas 3 IA por defecto**:
@@ -71,13 +78,39 @@ Los demás agentes pueden permanecer configurados en `orchestrator.config.json`,
71
78
 
72
79
  Si el usuario dice explícitamente algo como:
73
80
 
81
+ - `estaré ausente 1 hora`
74
82
  - `estaré ausente 2 horas`
75
83
  - `me voy un rato`
76
84
  - `activa monitoreo`
77
- - `quédate revisando`
78
- - `monitorea mientras no estoy`
79
85
 
80
- entonces debes entrar en **Modo Ausencia** durante esa sesión.
86
+ **Activar Modo Ausencia:**
87
+ ```bash
88
+ echo away > .away-mode
89
+ ```
90
+
91
+ **El script monitor-check.js se ejecutará cada 5 minutos** y revisará:
92
+ - Tareas completadas sin seguimiento
93
+ - Tareas fallidas
94
+ - Tareas atascadas (>10 min)
95
+ - Y escribirá en ACTIONS.md
96
+
97
+ **Auto-desactivación:**
98
+ Cuando NO hay tareas pendientes Y NO hay agentes trabajando Y todas las tareas están completadas:
99
+ - El script elimina .away-mode automáticamente
100
+ - Modo Ausencia se desactiva solo
101
+ - Cuando vuelvas y le digas "ya volví" → Claade responde normalmente
102
+
103
+ **El script monitor-check.js se ejecutará cada 5 minutos** y revisará:
104
+ - Tareas completadas sin seguimiento
105
+ - Tareas fallidas
106
+ - Tareas atascadas (>10 min)
107
+ - Y escribirá en ACTIONS.md para que cuando vuelvas, Claude lo lea automáticamente
108
+
109
+ **Desactivar Modo Ausencia:**
110
+ ```bash
111
+ # Eliminar archivo indicador
112
+ del .away-mode
113
+ ```
81
114
 
82
115
  ### Qué significa Modo Ausencia
83
116
 
@@ -149,17 +182,23 @@ Revisa `orchestrator.config.json` → `agents`. Cada entrada tiene:
149
182
 
150
183
  ## Cómo asignar trabajo
151
184
 
152
- 1. Escribe TASKs en `QUEUE.md` (formato pipe; la TUI lo lee):
153
- ```
154
- TASK-NNN | titulo corto | Agent | P1 | repo | descripcion larga
155
- ```
156
- Valores válidos de `Agent`: exactamente las keys de `orchestrator.config.json.agents`.
157
- Valores válidos de `repo`: exactamente las keys de `orchestrator.config.json.repos`.
158
- 2. (Opcional) También escribe una spec larga en `TASKS.md` bajo un heading `### TASK-NNN`; se inyecta al brief.
159
- 3. (Opcional) Para un brief muy detallado, crea `briefs/TASK-NNN-BRIEF.md`; también se inyecta.
160
- 4. Dependencias: agrega `> after:TASK-NNN` al final de la descripción para bloquear la tarea.
161
- 5. Dile al usuario que presione **R** en la TUI para recargar la cola, o **S** si está pausada.
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.
185
+ 1. **Cuando el usuario pide un cambio o nueva tarea** → **NUNCA analices directamente**
186
+ - **Primero**: Crea una TASK en `QUEUE.md` asignada a **OpenCode** para que analice el contexto
187
+ - **Segundo**: Espera a que OpenCode termine su análisis (revisa INBOX.md o progress/)
188
+ - **Tercero**: Recibes el análisis → creas nueva TASK para implementar (Codex o OpenCode)
189
+ - **Nunca analices el código del proyecto directamente tu mismo** - eso lo hace OpenCode
190
+
191
+ 2. Escribe TASKs en `QUEUE.md` (formato pipe; la TUI lo lee):
192
+ ```
193
+ TASK-NNN | titulo corto | Agent | P1 | repo | descripcion larga
194
+ ```
195
+ Valores válidos de `Agent`: exactamente las keys de `orchestrator.config.json.agents`.
196
+ Valores válidos de `repo`: exactamente las keys de `orchestrator.config.json.repos`.
197
+ 3. (Opcional) También escribe una spec larga en `TASKS.md` bajo un heading `### TASK-NNN`; se inyecta al brief.
198
+ 4. (Opcional) Para un brief muy detallado, crea `briefs/TASK-NNN-BRIEF.md`; también se inyecta.
199
+ 5. Dependencias: agrega `> after:TASK-NNN` al final de la descripción para bloquear la tarea.
200
+ 6. **La TUI inicia automáticamente** - NO necesitas presionar R ni S. La TUI detecta nuevas tasks y las lanza.
201
+ 7. **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
202
  7. Distribución según cantidad de TASKs independientes:
164
203
  - **1 tarea**: OpenCode (exploración) o Codex (implementación). Nunca Claude-Worker en primera instancia.
165
204
  - **2 tareas**: OpenCode + Codex, una cada uno.