xonecode 0.38.15 → 0.38.31
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/apps/web/dist/assets/{EditorDeFichero-C9BEoDWh.js → EditorDeFichero-CT2vAqMI.js} +1 -1
- package/apps/web/dist/assets/index-DjZ3hYu-.js +506 -0
- package/apps/web/dist/assets/index-oppsOrF4.css +1 -0
- package/apps/web/dist/assets/{php-DIdt3Vgn.js → php-B5s63fYs.js} +1 -1
- package/apps/web/dist/assets/{ruby-DYEvg0Dr.js → ruby-D9QLqlM3.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- package/dist/agent/conectores/gestorJira.js +118 -1
- package/dist/agent/conectores/gestorJira.js.map +1 -1
- package/dist/agent/dispositivos/decodificarImagen.js +8 -0
- package/dist/agent/dispositivos/decodificarImagen.js.map +1 -1
- package/dist/agent/dispositivos/juezVisual.js +43 -40
- package/dist/agent/dispositivos/juezVisual.js.map +1 -1
- package/dist/agent/grafo/aprendido.js +60 -0
- package/dist/agent/grafo/aprendido.js.map +1 -0
- package/dist/agent/grafo/criticaVisual.js +17 -5
- package/dist/agent/grafo/criticaVisual.js.map +1 -1
- package/dist/agent/grafo/xoneAgent.js +2 -0
- package/dist/agent/grafo/xoneAgent.js.map +1 -1
- package/dist/agent/motores/trueforge/capacidades.js +4 -2
- package/dist/agent/motores/trueforge/capacidades.js.map +1 -1
- package/dist/agent/motores/trueforge/convertirAP.js +86 -0
- package/dist/agent/motores/trueforge/convertirAP.js.map +1 -0
- package/dist/agent/motores/trueforge/sesionTrueforge.js +197 -11
- package/dist/agent/motores/trueforge/sesionTrueforge.js.map +1 -1
- package/dist/agent/motores/trueforge/traerDeStitch.js +65 -5
- package/dist/agent/motores/trueforge/traerDeStitch.js.map +1 -1
- package/dist/agent/subagentes/agentesEnDisco.js +28 -3
- package/dist/agent/subagentes/agentesEnDisco.js.map +1 -1
- package/dist/agent/subagentes/escrituraExterna.js +8 -1
- package/dist/agent/subagentes/escrituraExterna.js.map +1 -1
- package/dist/agent/subagentes/pluginDeSkills.js +31 -6
- package/dist/agent/subagentes/pluginDeSkills.js.map +1 -1
- package/dist/agent/subagentes/subagenteExterno.js +28 -9
- package/dist/agent/subagentes/subagenteExterno.js.map +1 -1
- package/dist/agent/tareas/aumentador.js +13 -2
- package/dist/agent/tareas/aumentador.js.map +1 -1
- package/dist/agent/tareas/juezDeTarea.js +13 -8
- package/dist/agent/tareas/juezDeTarea.js.map +1 -1
- package/dist/agent/tareas/reflejoEnElGestor.js +120 -0
- package/dist/agent/tareas/reflejoEnElGestor.js.map +1 -0
- package/dist/agent/tareas/sondeoDelGestor.js +201 -0
- package/dist/agent/tareas/sondeoDelGestor.js.map +1 -0
- package/dist/agent/turno/resumenDeTool.js +2 -0
- package/dist/agent/turno/resumenDeTool.js.map +1 -1
- package/dist/agent/turno/turnoReal.js +1 -0
- package/dist/agent/turno/turnoReal.js.map +1 -1
- package/dist/cli/consola.js.map +1 -1
- package/dist/cli/main.js +5 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/core/agentes.js +87 -2
- package/dist/core/agentes.js.map +1 -1
- package/dist/core/aprendido.js +68 -0
- package/dist/core/aprendido.js.map +1 -0
- package/dist/core/comandoExterno.js +29 -0
- package/dist/core/comandoExterno.js.map +1 -1
- package/dist/core/compararCapturas.js +62 -4
- package/dist/core/compararCapturas.js.map +1 -1
- package/dist/core/config.js +29 -0
- package/dist/core/config.js.map +1 -1
- package/dist/core/convertirAP.js +87 -0
- package/dist/core/convertirAP.js.map +1 -0
- package/dist/core/entrega.js +78 -10
- package/dist/core/entrega.js.map +1 -1
- package/dist/core/geometriaDePantalla.js +107 -5
- package/dist/core/geometriaDePantalla.js.map +1 -1
- package/dist/core/gestorDeTareas.js +2 -0
- package/dist/core/gestorDeTareas.js.map +1 -1
- package/dist/core/idiomaDeLaRespuesta.js +43 -0
- package/dist/core/idiomaDeLaRespuesta.js.map +1 -1
- package/dist/core/metodoDeComparacionVisual.js +71 -0
- package/dist/core/metodoDeComparacionVisual.js.map +1 -0
- package/dist/core/notify.js +4 -0
- package/dist/core/notify.js.map +1 -1
- package/dist/core/nucleoXone.js +42 -0
- package/dist/core/nucleoXone.js.map +1 -1
- package/dist/core/paqueteDeSoporte.js +2 -0
- package/dist/core/paqueteDeSoporte.js.map +1 -1
- package/dist/core/ports.js +36 -2
- package/dist/core/ports.js.map +1 -1
- package/dist/core/stitch.js +43 -0
- package/dist/core/stitch.js.map +1 -1
- package/dist/core/tareas.js.map +1 -1
- package/dist/core/tareasEnElGestor.js +197 -0
- package/dist/core/tareasEnElGestor.js.map +1 -0
- package/dist/core/textos.js +10 -3
- package/dist/core/textos.js.map +1 -1
- package/dist/web/servidor/arranque.js +483 -42
- package/dist/web/servidor/arranque.js.map +1 -1
- package/dist/web/servidor/consolaDeTarea.js +5 -6
- package/dist/web/servidor/consolaDeTarea.js.map +1 -1
- package/dist/web/servidor/corredorDeTareas.js +33 -4
- package/dist/web/servidor/corredorDeTareas.js.map +1 -1
- package/dist/web/servidor/transporte.js +11 -0
- package/dist/web/servidor/transporte.js.map +1 -1
- package/package.json +2 -2
- package/skills/xone-development/lib/aUtf8.mjs +68 -0
- package/skills/xone-development/references/css/selectores-unidades-colores.md +2 -0
- package/skills/xone-development/scripts/xone-a-utf8 +60 -0
- package/apps/web/dist/assets/index-BpDt_1vN.js +0 -506
- package/apps/web/dist/assets/index-D_Z-V9n1.css +0 -1
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
*/
|
|
26
26
|
import { TOPE_DE_PREGUNTAS_CONTESTADAS_SOLAS, opcionRecomendada } from "../../../core/modoDeEscritura.js";
|
|
27
27
|
import { claseDeTrabajo } from "../../../core/esfuerzo.js";
|
|
28
|
-
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
28
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
29
29
|
import { join } from "node:path";
|
|
30
30
|
import winston from "winston";
|
|
31
31
|
import { AgentThread, AgentThreadOrchestrator, EventType, NOOP_AGENT_TRACING, askUserQuestion, contextCompaction, dynamicSubAgents } from "./trueforge.js";
|
|
@@ -37,7 +37,7 @@ import { sumarPorModelo } from "../../../core/actos.js";
|
|
|
37
37
|
import { ColaDeEventos, entrelazar } from "../../../core/entrelazar.js";
|
|
38
38
|
import { modeloExternoParaTrueforge } from "./modeloExterno.js";
|
|
39
39
|
import { diferenciasDelContraste, metricasDeTrueforge } from "./metricasTrueforge.js";
|
|
40
|
-
import { respuestaEnChinoSinPedirlo, textoDeReescritura } from "../../../core/idiomaDeLaRespuesta.js";
|
|
40
|
+
import { respuestaEnChinoSinPedirlo, TOPE_DE_RECORDATORIOS_DE_IDIOMA, textoDeReescritura, textoDeRecordatorioDeIdioma, textoEnInglesSinPedirlo, } from "../../../core/idiomaDeLaRespuesta.js";
|
|
41
41
|
import { cambiosQueSeVerifican, huellaDeErrores, repartirHallazgos, textoDeReparacion, tocaCriticarPantalla, TOPE_REPARACIONES } from "../../turno/verificacion.js";
|
|
42
42
|
import { correrTurno } from "../../../core/turno.js";
|
|
43
43
|
import { createTokenTracker } from "../../../vendor/tokenTracking.js";
|
|
@@ -45,7 +45,9 @@ import { MAX_APPROVAL_ROUNDS } from "../../../vendor/hitl.js";
|
|
|
45
45
|
import { artefactosNuevos, backendDeAgente, entornoDeLaShellDelProyecto, fotoDeArtefactos, lectorDelDispositivoDeSesion, scriptsDeLasSkills } from "../../grafo/proyecto.js";
|
|
46
46
|
import { carpetaDeHotswap } from "../../../core/hotswap.js";
|
|
47
47
|
import { cargarAgentes } from "../../subagentes/agentesEnDisco.js";
|
|
48
|
-
import {
|
|
48
|
+
import { bloqueDeAprendido, NOMBRE_APUNTAR_APRENDIZAJE, USO_DE_APRENDIDO_EXTERNO, USO_DE_APUNTAR_APRENDIZAJE } from "../../../core/aprendido.js";
|
|
49
|
+
import { crearApuntarAprendizaje, leerAprendido } from "../../grafo/aprendido.js";
|
|
50
|
+
import { fichaDeAgente, promptDeAgente, recibeMarcarCriterios, recibeNucleoDeTrabajo, repartirSkills, skillsConLasDeQuienLlama, textoDeCarpetasDeLaSesion, textoDeTrabajoSinLlamar } from "../../../core/agentes.js";
|
|
49
51
|
import { PERFIL_DEL_ORQUESTADOR, promptOrquestador } from "../../grafo/xoneAgent.js";
|
|
50
52
|
import { permisosDe, seDetieneEn, TEXTO_HITL } from "../../grafo/perfiles.js";
|
|
51
53
|
import { cambioDe } from "../../turno/interrupts.js";
|
|
@@ -65,6 +67,7 @@ import { avisoDeReparto } from "../../../core/repartoDeEncargo.js";
|
|
|
65
67
|
import { leerTareasDelPlan, RUTA_DE_TASKS } from "../../../core/tareasDelPlan.js";
|
|
66
68
|
import { esDeLaMaqueta } from "../../../core/stitch.js";
|
|
67
69
|
import { recibeConectores } from "../../../core/conectores.js";
|
|
70
|
+
import { crearConvertirAP, NOMBRE_CONVERTIR_A_P, recibeConvertirAP } from "./convertirAP.js";
|
|
68
71
|
import { buscarMaqueta, medirContraMaqueta, resumenDeMedida, textoDeMedidaAutomatica, ultimaCaptura } from "./medidaAutomatica.js";
|
|
69
72
|
import { anotarEscritura, capacidadDeInformesDeHijos, esEscrituraBinaria, escrituraConExito, textoDelInforme } from "./informesDeHijos.js";
|
|
70
73
|
import { crearDiagnosticoDeTools } from "../../turno/diagnosticoDeTools.js";
|
|
@@ -72,7 +75,8 @@ import { encenderTrazaDeErrores } from "../../trazaDeErroresEnDisco.js";
|
|
|
72
75
|
import { anotarPaso } from "../../../core/trazaDeErrores.js";
|
|
73
76
|
import { entornoConDepuracion } from "../../turno/depuracion.js";
|
|
74
77
|
import { detalleDe, parametrosDe } from "../../turno/resumenDeTool.js";
|
|
75
|
-
import { lineaDeComprobacion, soloDocumentacion, TOPE_DE_COMPROBACIONES_AL_JUEZ } from "../../../core/entrega.js";
|
|
78
|
+
import { lineaDeComprobacion, omisionExplicada, soloDocumentacion, TOPE_DE_COMPROBACIONES_AL_JUEZ } from "../../../core/entrega.js";
|
|
79
|
+
import { bloqueantesDelInforme } from "../../../core/geometriaDePantalla.js";
|
|
76
80
|
import { apartarMemoria, cargarMemoria, fotoSaneada, guardarMemoria, saldarColgadas, textoDeInterrupcion, textoDeMemoriaDescartada } from "./memoriaTrueforge.js";
|
|
77
81
|
import { crearNota, sobrantes } from "./notas.js";
|
|
78
82
|
import { crearMemoriaDeEspecialistas } from "./memoriaDeEspecialistas.js";
|
|
@@ -126,6 +130,22 @@ const BUCLE_DE_CALIDAD = [
|
|
|
126
130
|
"repite. Para cuando la distancia estructural baje del 10 % en vertical y en horizontal y el crítico no señale diferencias de forma con el diseño, o tras TRES vueltas, y",
|
|
127
131
|
"di lo que sigue faltando en vez de darlo por hecho.",
|
|
128
132
|
].join("\n");
|
|
133
|
+
/**
|
|
134
|
+
* Cuando quien MAQUETA es un hijo de Claude Code con ejecución, el bucle lo hace ÉL: despliega, captura, compara con la
|
|
135
|
+
* maqueta y corrige (`textoDeTrabajoSinLlamar`). Medido en Maset: el orquestador, con `BUCLE_DE_CALIDAD`, volvía a pasar el
|
|
136
|
+
* crítico y le encargaba otra vuelta —y otra al diseñador por un SVG—, y cada vuelta era un Claude Code NUEVO que releía
|
|
137
|
+
* todo: unos quince minutos cada una, con las piezas ya bien. Dos bucles uno encima de otro.
|
|
138
|
+
*/
|
|
139
|
+
export function textoDeMaquetadorExterno(nombres) {
|
|
140
|
+
return [
|
|
141
|
+
`${nombres.join(", ")} corre en Claude Code con su shell: despliega, captura, COMPARA con la maqueta y CORRIGE él mismo hasta`,
|
|
142
|
+
"cumplir. Con él: dale en UN encargo el diseño, la tabla de recursos y el criterio; a su vuelta pasa el crítico UNA vez, y solo",
|
|
143
|
+
"vuelve a encargarle si queda algo BLOQUEANTE (una pieza que falta, algo tapado o fuera de pantalla) o que él no comprobó. Las",
|
|
144
|
+
"diferencias de detalle van en tu resumen final, no en otra vuelta: cada vuelta suya empieza de cero. Si un recurso del",
|
|
145
|
+
"diseñador está mal (proporción, color, un icono equivocado), díselo a él y que lo corrija en esa misma vuelta: puede escribir en",
|
|
146
|
+
"`icons/`, y otra ronda diseñador → desarrollador cuesta dos arranques.",
|
|
147
|
+
].join("\n");
|
|
148
|
+
}
|
|
129
149
|
/**
|
|
130
150
|
* Lo que el orquestador tiene que saber para DELEGAR en ESTE motor. Su prompt es el de siempre
|
|
131
151
|
* (`promptOrquestador`), que habla de `task` y de la ficha que va en su descripción: aquí la
|
|
@@ -161,6 +181,41 @@ export const SIN_HABLAR_DEL_HARNESS = "CON QUIÉN HABLAS: con un desarrollador d
|
|
|
161
181
|
"DE ANÁLISIS…), la foto o el contexto que te llega al empezar, ni lo que vas a medir o no: cuéntale lo que encontraste, " +
|
|
162
182
|
"lo que hiciste en su proyecto y lo que necesitas de él. Si pregunta cómo trabajas, entonces sí.";
|
|
163
183
|
/** Lo que recibe el agente en modo autónomo cuando pregunta sin marcar ninguna opción como recomendada. */
|
|
184
|
+
/**
|
|
185
|
+
* Al raíz de una TAREA DE FONDO (`trabajoSinPersona`). Preguntar no está prohibido —la pregunta se contesta sola con su
|
|
186
|
+
* recomendada, y pasado el tope aparca la tarea—, pero cada una es una parada: se le pide decidir antes. Y como nadie
|
|
187
|
+
* ha visto el trabajo, la respuesta final es lo que la persona leerá: un resumen con lo que decidió sin preguntar.
|
|
188
|
+
*/
|
|
189
|
+
export const TRABAJO_SIN_PERSONA = [
|
|
190
|
+
"TAREA DE FONDO: trabajas SIN nadie delante; la persona leerá el resultado cuando acabes.",
|
|
191
|
+
"- Resuelve tú las dudas: elige la opción más razonable con lo que dicen el encargo, el plan y el proyecto, y sigue.",
|
|
192
|
+
" Pregunta solo si sin la respuesta no puedes hacer nada útil; si preguntas, marca tu opción recomendada con",
|
|
193
|
+
" `(Recommended)`: se contestará sola con ella.",
|
|
194
|
+
"- Tu RESPUESTA FINAL es el resumen de la tarea, en tres apartados: lo que cambiaste (cada fichero y para qué), las",
|
|
195
|
+
" DECISIONES que tomaste tú sin preguntar (cada duda, lo que elegiste y por qué) y lo que no pudiste comprobar o",
|
|
196
|
+
" queda pendiente.",
|
|
197
|
+
].join("\n");
|
|
198
|
+
/**
|
|
199
|
+
* Lo aprendido, para el ORQUESTADOR: lo que hay apuntado y cuándo apuntar él. Le toca sobre todo lo que le cuente un
|
|
200
|
+
* hijo de motor externo en su apartado «Aprendido:» (ese hijo no tiene la tool).
|
|
201
|
+
*/
|
|
202
|
+
export function textoDeAprendidoDelRaiz(lista) {
|
|
203
|
+
return [
|
|
204
|
+
bloqueDeAprendido(lista),
|
|
205
|
+
`${USO_DE_APUNTAR_APRENDIZAJE} Y si un especialista te devuelve un apartado «Aprendido:», apúntalo tú.`,
|
|
206
|
+
]
|
|
207
|
+
.filter((l) => l !== undefined)
|
|
208
|
+
.join("\n");
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* La respuesta a una pregunta del agente cuando nadie la contesta y tenía opción recomendada. No es la opción a secas:
|
|
212
|
+
* medido en Maset, con solo «Opción A (Recommended)» el agente cerraba diciendo «lo decidiste tú», como si la hubiera
|
|
213
|
+
* elegido la persona. Es SU recomendación aplicada, y así tiene que contarla.
|
|
214
|
+
*/
|
|
215
|
+
export function respuestaAutonomaRecomendada(elegida) {
|
|
216
|
+
return (`Nadie ha contestado (modo autónomo): se aplica TU opción recomendada, «${elegida}». No la eligió el usuario: ` +
|
|
217
|
+
"cuéntala en tu respuesta final entre las decisiones que tomaste tú sin preguntar.");
|
|
218
|
+
}
|
|
164
219
|
export const RESPUESTA_AUTONOMA_SIN_RECOMENDADA = "Modo autónomo: no hay nadie a quien preguntar. Decide tú con lo que dicen el encargo y el plan, sigue, y di en tu respuesta final qué elegiste y por qué.";
|
|
165
220
|
/** Un comando que saca una captura de pantalla del aparato. */
|
|
166
221
|
export const COMANDO_DE_CAPTURA = /xone-captura-android|xone-hotswap\s+shot\b|\bscreencap\b/;
|
|
@@ -328,6 +383,11 @@ export function notaDeDelegacion(agentes, opciones = {}) {
|
|
|
328
383
|
"entiende `create_sub_agent` y `name`. Las fichas de los especialistas:",
|
|
329
384
|
...agentes.map((a) => `- ${a.nombre}: ${fichaDeAgente(a, opciones)}`),
|
|
330
385
|
...(opciones.conComparacion === true ? ["", BUCLE_DE_CALIDAD] : []),
|
|
386
|
+
// Si quien maqueta corre en Claude Code con su shell, el bucle es SUYO: el orquestador no lo repite encima.
|
|
387
|
+
...(() => {
|
|
388
|
+
const externos = agentes.filter((a) => a.motor === "claude-code" && a.ejecucion === true && !a.soloLectura).map((a) => a.nombre);
|
|
389
|
+
return opciones.conComparacion === true && externos.length > 0 ? ["", textoDeMaquetadorExterno(externos)] : [];
|
|
390
|
+
})(),
|
|
331
391
|
...(opciones.conEsperas === true
|
|
332
392
|
? [
|
|
333
393
|
"",
|
|
@@ -380,6 +440,13 @@ const LIMITES_DE = {
|
|
|
380
440
|
*/
|
|
381
441
|
export const USO_DE_XONE_ATRIBUTOS = "Para saber si un atributo XML existe en un nodo (coll, group, frame, prop) y qué hace, pregunta PRIMERO a `xone_atributos`: " +
|
|
382
442
|
"contesta en una línea desde las tablas de la skill. Lee la referencia de la skill solo si no lo encuentra, o si necesitas ejemplos o matices.";
|
|
443
|
+
/**
|
|
444
|
+
* CUÁNDO convertir las medidas de una maqueta, por lo mismo que `USO_DE_XONE_ATRIBUTOS`: una tool nombrada solo en la
|
|
445
|
+
* lista no se usa. Medido en Maset: con la regla en la skill, el desarrollador copió los px de la maqueta como `p` y los
|
|
446
|
+
* iconos salieron unas 2,6 veces más pequeños.
|
|
447
|
+
*/
|
|
448
|
+
export const USO_DE_CONVERTIR_A_P = "Los px de una maqueta (su code.html, su imagen) NO son p: toda medida que copies de ella —anchos, altos, márgenes, " +
|
|
449
|
+
"paddings, tamaño de iconos— pasa ANTES por `convertir_a_p`, todas de una vez, y escribes lo que devuelve.";
|
|
383
450
|
export function notaDeTools(nombres, limite) {
|
|
384
451
|
return `NOTA DEL HARNESS: aunque tu identidad diga lo contrario, NO tienes las mismas tools que quien te delega. Tienes ${nombres
|
|
385
452
|
.map((n) => `\`${n}\``)
|
|
@@ -437,6 +504,25 @@ function preguntaDeLaFoto(foto) {
|
|
|
437
504
|
};
|
|
438
505
|
}
|
|
439
506
|
const claveDe = (hilo, id) => `${hilo}:${id}`;
|
|
507
|
+
/**
|
|
508
|
+
* ¿Cambió algún fichero del proyecto (fuera de `.xonecode/`) después de `desde`? Por la hora de modificación del disco,
|
|
509
|
+
* que es lo que vale para los dos motores: un hijo de Claude Code escribe con sus tools y no pasa por las nuestras. Lo
|
|
510
|
+
* que no se puede mirar no cuenta como cambio.
|
|
511
|
+
*/
|
|
512
|
+
export function cambioDespuesDe(raiz, desde) {
|
|
513
|
+
for (const virtual of ficherosDelProyecto(raiz)) {
|
|
514
|
+
if (virtual.startsWith("/.xonecode/"))
|
|
515
|
+
continue;
|
|
516
|
+
try {
|
|
517
|
+
if (statSync(join(raiz, virtual)).mtimeMs > desde)
|
|
518
|
+
return true;
|
|
519
|
+
}
|
|
520
|
+
catch {
|
|
521
|
+
// Borrado entre medias, o sin permiso: no se afirma nada.
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return false;
|
|
525
|
+
}
|
|
440
526
|
/**
|
|
441
527
|
* `agregarNota` no vive todavía en `SesionReal` (IXCODE-4, Task 6 se la añade ahí como opcional,
|
|
442
528
|
* compartida con deepagents): se ensancha el tipo de retorno AQUÍ, en vez de esperar a esa task,
|
|
@@ -554,6 +640,9 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
554
640
|
let capturasDelTurno = [];
|
|
555
641
|
/** Lo que dieron las comprobaciones visuales del turno, una línea cada una, para el juez de QA (`ResultadoDeTurno`). */
|
|
556
642
|
let comprobacionesDelTurno = [];
|
|
643
|
+
let bloqueantesVisualesDelTurno = [];
|
|
644
|
+
// Cuándo llegó esa crítica: si el proyecto cambia DESPUÉS, sus bloqueantes ya no son la pantalla final (`cambioDespuesDe`).
|
|
645
|
+
let horaDeLaUltimaCritica;
|
|
557
646
|
const anotarComprobacion = (linea) => {
|
|
558
647
|
comprobacionesDelTurno = [...comprobacionesDelTurno, linea].slice(-TOPE_DE_COMPROBACIONES_AL_JUEZ);
|
|
559
648
|
};
|
|
@@ -577,6 +666,30 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
577
666
|
const detencion = crearControlDeDetencion(HILO_RAIZ);
|
|
578
667
|
/** Tool calls tiradas por DETENER en la sesión: si se queda en cero, el filtro es solo red. */
|
|
579
668
|
let llamadasTiradasPorDetener = 0;
|
|
669
|
+
/**
|
|
670
|
+
* **El recordatorio del idioma**, para el raíz que escribe en INGLÉS entre herramientas (`textoEnInglesSinPedirlo`,
|
|
671
|
+
* medido en Maset). Lo pone el turno al cerrarse un mensaje suyo, y entra como mensaje de usuario antes de su siguiente
|
|
672
|
+
* llamada —la del raíz, no la de un hijo—; como mucho `TOPE_DE_RECORDATORIOS_DE_IDIOMA` por turno.
|
|
673
|
+
*/
|
|
674
|
+
let recordatorioDeIdioma;
|
|
675
|
+
let recordatoriosEnElTurno = 0;
|
|
676
|
+
const capacidadDeIdioma = {
|
|
677
|
+
nombre: "idioma",
|
|
678
|
+
tools: [],
|
|
679
|
+
capability: {
|
|
680
|
+
preLLMProcessors: [
|
|
681
|
+
{
|
|
682
|
+
async *processPreLLM() {
|
|
683
|
+
const texto = recordatorioDeIdioma;
|
|
684
|
+
if (texto === undefined)
|
|
685
|
+
return;
|
|
686
|
+
recordatorioDeIdioma = undefined;
|
|
687
|
+
yield { type: "internal.agent.context.append", context: [{ role: "user", content: texto }], output: [] };
|
|
688
|
+
},
|
|
689
|
+
},
|
|
690
|
+
],
|
|
691
|
+
},
|
|
692
|
+
};
|
|
580
693
|
const capacidadDeNotasDeLaSesion = capacidadDeNotas(notas, {
|
|
581
694
|
detencion,
|
|
582
695
|
nombreDe: (h) => quienEs.get(h) ?? h,
|
|
@@ -783,6 +896,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
783
896
|
...herramientasDeJuicio(),
|
|
784
897
|
...(carpeta === undefined ? [] : [crearTraerDeLaMaquina({ carpeta, alEscribir: anotarArtefacto })]),
|
|
785
898
|
...traerDeStitch(),
|
|
899
|
+
// Lo aprendido: el orquestador también apunta, sobre todo lo que le cuenta un hijo de motor externo (que no tiene la tool).
|
|
900
|
+
crearApuntarAprendizaje({ raiz, quien: "orquestador" }),
|
|
786
901
|
...(opciones.puedeProponerTareas === true
|
|
787
902
|
? [crearProponerTareas((p) => void propuestasPorAnunciar.push(p))]
|
|
788
903
|
: []),
|
|
@@ -820,11 +935,23 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
820
935
|
: []),
|
|
821
936
|
// Fondos SVG: pura y sin red, sin puerto; a quien escribe el proyecto, como deepagents.
|
|
822
937
|
...(recibeGenerarFondo(agente) ? [crearGenerarFondoSvg()] : []),
|
|
938
|
+
// Las medidas de una maqueta a `p`: pura, a quien escribe el proyecto. La resolución la lee del app.xml de la raíz.
|
|
939
|
+
...(recibeConvertirAP(agente)
|
|
940
|
+
? [
|
|
941
|
+
crearConvertirAP({
|
|
942
|
+
raiz,
|
|
943
|
+
...(carpeta === undefined ? {} : { artefactos: carpeta }),
|
|
944
|
+
...(opciones.adjuntos === undefined ? {} : { adjuntos: opciones.adjuntos }),
|
|
945
|
+
}),
|
|
946
|
+
]
|
|
947
|
+
: []),
|
|
823
948
|
// ¿Cambió la zona tras el toque? Al conductor, que es quien saca las capturas: comprueba una
|
|
824
949
|
// ACCIÓN suya, no juzga la pantalla (eso sigue siendo del crítico y de `comparar_capturas`).
|
|
825
950
|
...(carpeta !== undefined && agente.ejecucion === true
|
|
826
951
|
? [crearDiferenciaDeCapturas({ leerArtefacto: async (nombre) => readFileSync(join(carpeta, nombre)) })]
|
|
827
952
|
: []),
|
|
953
|
+
// Lo aprendido del proyecto y del aparato, para los encargos siguientes: a quien trabaja (`recibeNucleoDeTrabajo`).
|
|
954
|
+
...(recibeNucleoDeTrabajo(agente) ? [crearApuntarAprendizaje({ raiz, quien: agente.nombre })] : []),
|
|
828
955
|
// Y marcar en el plan lo comprobado, con el reparto de deepagents (`recibeMarcarCriterios`).
|
|
829
956
|
...(recibeMarcarCriterios(agente) ? [crearMarcarCriteriosDelPlan({ raiz })] : []),
|
|
830
957
|
// El BUCLE del desarrollador: quien puede llamar al de pruebas también tiene el crítico y la medida, para
|
|
@@ -890,13 +1017,18 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
890
1017
|
* su nombre; el entorno de NUESTRA shell; y la lectura de ESTAS dos carpetas de la sesión, que
|
|
891
1018
|
* es donde sus scripts dejan las capturas. Codex y OpenCode siguen sin shell.
|
|
892
1019
|
*/
|
|
893
|
-
const
|
|
1020
|
+
const conEjecucion = agente.ejecucion === true && motor === "claude-code" && carpeta !== undefined;
|
|
1021
|
+
// Con ejecución, también las skills de a quien llamaría: no puede llamarlo, así que lo hace él (`skillsConLasDeQuienLlama`).
|
|
1022
|
+
const delHijo = conEjecucion ? { ...agente, skills: skillsConLasDeQuienLlama(agente, especialistas()) } : agente;
|
|
1023
|
+
const ejecucion = conEjecucion
|
|
894
1024
|
? {
|
|
895
|
-
scripts: scriptsDeLasSkills(raiz,
|
|
1025
|
+
scripts: scriptsDeLasSkills(raiz, delHijo.skills),
|
|
896
1026
|
entorno: entornoDeLaShellDelProyecto(raiz, carpeta),
|
|
897
1027
|
lecturas: [carpeta, carpetaDeHotswap(carpeta)],
|
|
898
1028
|
}
|
|
899
1029
|
: undefined;
|
|
1030
|
+
// Las carpetas de la sesión se LEEN aunque no ejecute: es donde el orquestador le deja la maqueta y las capturas.
|
|
1031
|
+
const lecturasDeSesion = motor === "claude-code" && carpeta !== undefined ? [carpeta, carpetaDeHotswap(carpeta)] : undefined;
|
|
900
1032
|
/**
|
|
901
1033
|
* Lo que sus comandos dejen en `/artefactos/` se ANUNCIA al volver, con la MISMA foto que nuestra
|
|
902
1034
|
* shell (`fotoDeArtefactos`): por nuestra shell se anunciaba y por la suya no, y una captura
|
|
@@ -929,12 +1061,23 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
929
1061
|
peticion: () => ({
|
|
930
1062
|
motor,
|
|
931
1063
|
cwd: raiz,
|
|
932
|
-
instrucciones:
|
|
1064
|
+
instrucciones: [
|
|
1065
|
+
promptDeAgente(delHijo, repartirSkills(delHijo, disponibles)),
|
|
1066
|
+
...(conEjecucion && (agente.llama ?? []).length > 0 ? [textoDeTrabajoSinLlamar(agente.llama ?? [], carpeta)] : []),
|
|
1067
|
+
...(lecturasDeSesion === undefined ? [] : [textoDeCarpetasDeLaSesion(lecturasDeSesion[0], lecturasDeSesion[1])]),
|
|
1068
|
+
...[bloqueDeAprendido(leerAprendido(raiz))].filter((b) => b !== undefined),
|
|
1069
|
+
USO_DE_APRENDIDO_EXTERNO,
|
|
1070
|
+
inventarioDelProyecto(ficherosDelProyecto(raiz)),
|
|
1071
|
+
].join("\n\n"),
|
|
933
1072
|
tarea: params.request.input,
|
|
934
1073
|
...(agente.modelo === undefined ? {} : { modelo: agente.modelo }),
|
|
935
1074
|
permitirEscritura: !agente.soloLectura,
|
|
936
1075
|
agente: agente.nombre,
|
|
1076
|
+
skills: repartirSkills(delHijo, disponibles).suyas,
|
|
937
1077
|
...(ejecucion === undefined ? {} : { ejecucion }),
|
|
1078
|
+
...(lecturasDeSesion === undefined ? {} : { lecturas: lecturasDeSesion }),
|
|
1079
|
+
// El esfuerzo de su `.md`, que Claude Code aplica como `effort`; los otros dos no tienen dónde recibirlo.
|
|
1080
|
+
...(motor === "claude-code" && agente.esfuerzo !== undefined ? { esfuerzo: agente.esfuerzo } : {}),
|
|
938
1081
|
}),
|
|
939
1082
|
senal: () => aborto?.signal,
|
|
940
1083
|
}),
|
|
@@ -1006,6 +1149,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1006
1149
|
notas: capacidadDeNotasDeLaSesion,
|
|
1007
1150
|
puedeLlamar: (a) => conBucleDelDesarrollador && (a.llama?.length ?? 0) > 0,
|
|
1008
1151
|
informes: capacidadDeInformes,
|
|
1152
|
+
// Una tarea de fondo no tiene a quién preguntar: sus escrituras locales no esperan al control de la librería.
|
|
1153
|
+
...(opciones.trabajoSinPersona === true ? { escribeSinPreguntar: true } : {}),
|
|
1009
1154
|
vueltas: (a) => a.ejecucion === true
|
|
1010
1155
|
? capacidadDeAvisoDeVueltas({ vueltasDe: (hilo) => capturasDeCadaHilo.get(hilo) ?? 0, umbrales: UMBRALES_DE_CAPTURAS, texto: textoDeCapturas })
|
|
1011
1156
|
: conBucleDelDesarrollador && (a.llama?.length ?? 0) > 0
|
|
@@ -1025,7 +1170,11 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1025
1170
|
const nota = [
|
|
1026
1171
|
notaDeTools(nombres, agente === undefined ? LIMITE_DEL_GENERICO : LIMITES_DE[clase]),
|
|
1027
1172
|
...(nombres.includes(NOMBRE_ATRIBUTOS_XONE) ? [USO_DE_XONE_ATRIBUTOS] : []),
|
|
1173
|
+
...(nombres.includes(NOMBRE_CONVERTIR_A_P) ? [USO_DE_CONVERTIR_A_P] : []),
|
|
1174
|
+
...(nombres.includes(NOMBRE_APUNTAR_APRENDIZAJE) ? [USO_DE_APUNTAR_APRENDIZAJE] : []),
|
|
1028
1175
|
].join("\n");
|
|
1176
|
+
// Lo aprendido en encargos anteriores, leído AHORA (otro encargo pudo apuntar algo hace un momento).
|
|
1177
|
+
const aprendido = bloqueDeAprendido(leerAprendido(raiz));
|
|
1029
1178
|
const instrucciones = agente === undefined
|
|
1030
1179
|
? `${IDIOMA_DEL_ESPECIALISTA}\n\n${nota} Contesta con lo que encuentres y dónde.`
|
|
1031
1180
|
: [
|
|
@@ -1035,6 +1184,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1035
1184
|
"",
|
|
1036
1185
|
nota,
|
|
1037
1186
|
anuncioDeSkills(agente, catalogo),
|
|
1187
|
+
...(aprendido === undefined ? [] : ["", aprendido]),
|
|
1038
1188
|
...(conBucleDelDesarrollador && (agente.llama?.length ?? 0) > 0 ? ["", textoDelBucle(agente.llama ?? [], { conCritica: carpeta !== undefined, conFuentes: opciones.fuentes !== undefined })] : []),
|
|
1039
1189
|
]
|
|
1040
1190
|
.filter((l) => l !== undefined)
|
|
@@ -1130,7 +1280,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1130
1280
|
hijosConMemoria.clear();
|
|
1131
1281
|
const definicion = {
|
|
1132
1282
|
modelClient: llm,
|
|
1133
|
-
instruction: [IDIOMA_DE_LA_RESPUESTA, SIN_HABLAR_DEL_HARNESS, promptOrquestador(especialistas()), notaDeDelegacion(especialistas(), { conIconos: opciones.iconos !== undefined, conFuentes: opciones.fuentes !== undefined, conComparacion: carpeta !== undefined, conMemoria: conMemoriaDeEspecialistas, conBucle: conBucleDelDesarrollador, conEsperas }), opciones.puedeProponerTareas === true ? REPARTIR_EN_TAREAS : ""].filter((l) => l !== "").join("\n\n"),
|
|
1283
|
+
instruction: [IDIOMA_DE_LA_RESPUESTA, SIN_HABLAR_DEL_HARNESS, promptOrquestador(especialistas()), notaDeDelegacion(especialistas(), { conIconos: opciones.iconos !== undefined, conFuentes: opciones.fuentes !== undefined, conComparacion: carpeta !== undefined, conMemoria: conMemoriaDeEspecialistas, conBucle: conBucleDelDesarrollador, conEsperas }), opciones.puedeProponerTareas === true ? REPARTIR_EN_TAREAS : "", opciones.trabajoSinPersona === true ? TRABAJO_SIN_PERSONA : "", textoDeAprendidoDelRaiz(leerAprendido(raiz))].filter((l) => l !== "").join("\n\n"),
|
|
1134
1284
|
// Por TURNO, porque el raíz se rehace desde su foto al final de cada uno (ver `turno`).
|
|
1135
1285
|
iterationLimit: LIMITE_DE_LLAMADAS_DEL_RAIZ,
|
|
1136
1286
|
};
|
|
@@ -1149,6 +1299,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1149
1299
|
capacidadDeFecha(),
|
|
1150
1300
|
capacidadDeNotasDeLaSesion,
|
|
1151
1301
|
capacidadDeInformes,
|
|
1302
|
+
capacidadDeIdioma,
|
|
1152
1303
|
]),
|
|
1153
1304
|
/**
|
|
1154
1305
|
* **La conversación se RESUME a un umbral que depende de la ventana del modelo**
|
|
@@ -1354,6 +1505,12 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1354
1505
|
// Las comprobaciones VISUALES, para el juez: lo que dijeron, medido aquí y no contado por el agente.
|
|
1355
1506
|
if (llamada !== undefined && (llamada.nombre === NOMBRE_COMPARAR_CAPTURAS || llamada.nombre === "xone_critica_visual") && typeof evento.content === "string") {
|
|
1356
1507
|
anotarComprobacion(lineaDeComprobacion(llamada.nombre, detalleDe(llamada.nombre, llamada.args), evento.content));
|
|
1508
|
+
// Lo BLOQUEANTE de la ÚLTIMA crítica: es el estado final de la pantalla, y el cierre de una tarea lo pone en
|
|
1509
|
+
// su `## CRITICAL` (`bloqueantesDelInforme`).
|
|
1510
|
+
if (llamada.nombre === "xone_critica_visual") {
|
|
1511
|
+
bloqueantesVisualesDelTurno = bloqueantesDelInforme(evento.content);
|
|
1512
|
+
horaDeLaUltimaCritica = Date.now();
|
|
1513
|
+
}
|
|
1357
1514
|
}
|
|
1358
1515
|
const chars = typeof evento.content === "string" ? evento.content.length : 0;
|
|
1359
1516
|
diagnostico?.resultado?.(llamada?.nombre, llamada === undefined ? undefined : detalleDe(llamada.nombre, llamada.args), chars);
|
|
@@ -1476,6 +1633,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1476
1633
|
throw new Error("la sesión está cerrada");
|
|
1477
1634
|
const t0 = Date.now();
|
|
1478
1635
|
cancelado = false;
|
|
1636
|
+
recordatoriosEnElTurno = 0;
|
|
1637
|
+
recordatorioDeIdioma = undefined;
|
|
1479
1638
|
detencion.reiniciar();
|
|
1480
1639
|
const instantanea = await tomarInstantanea(raiz, opciones.entorno.git);
|
|
1481
1640
|
const tope = opciones.topeDeRondas ?? MAX_APPROVAL_ROUNDS;
|
|
@@ -1486,6 +1645,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1486
1645
|
externosDelTurno = 0;
|
|
1487
1646
|
capturasDelTurno = [];
|
|
1488
1647
|
comprobacionesDelTurno = [];
|
|
1648
|
+
bloqueantesVisualesDelTurno = [];
|
|
1649
|
+
horaDeLaUltimaCritica = undefined;
|
|
1489
1650
|
/** El encargo de ESTE turno tal cual se pidió, y el mismo con la última pregunta y su
|
|
1490
1651
|
* respuesta al lado, que es lo que se juzga y se repara (ver `flujo`). Ausente = no consta. */
|
|
1491
1652
|
let encargoDelTurno;
|
|
@@ -1531,7 +1692,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1531
1692
|
* recomendada, la otra no— y no se contestó ninguna, se enseñó solo la primera y la segunda se perdió. Con
|
|
1532
1693
|
* tope, para que no dé vueltas.
|
|
1533
1694
|
*/
|
|
1534
|
-
if (preguntas.length > 0 && opciones.sinAprobacion?.() === true && preguntasSolas + preguntas.length <= TOPE_DE_PREGUNTAS_CONTESTADAS_SOLAS) {
|
|
1695
|
+
if (preguntas.length > 0 && (opciones.trabajoSinPersona === true || opciones.sinAprobacion?.() === true) && preguntasSolas + preguntas.length <= TOPE_DE_PREGUNTAS_CONTESTADAS_SOLAS) {
|
|
1535
1696
|
preguntasSolas += preguntas.length;
|
|
1536
1697
|
const respuestas = [];
|
|
1537
1698
|
for (const q of preguntas) {
|
|
@@ -1543,7 +1704,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1543
1704
|
type: "user.tool_response",
|
|
1544
1705
|
thread_id: q.hilo,
|
|
1545
1706
|
tool_call_id: q.id,
|
|
1546
|
-
content: elegida
|
|
1707
|
+
content: elegida === undefined ? RESPUESTA_AUTONOMA_SIN_RECOMENDADA : respuestaAutonomaRecomendada(elegida),
|
|
1547
1708
|
});
|
|
1548
1709
|
}
|
|
1549
1710
|
lote = respuestas;
|
|
@@ -1719,8 +1880,17 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1719
1880
|
mensajeCerrado = false;
|
|
1720
1881
|
ultimoMensaje += evento.texto;
|
|
1721
1882
|
}
|
|
1722
|
-
else if (evento.tipo !== "razonamiento")
|
|
1883
|
+
else if (evento.tipo !== "razonamiento") {
|
|
1884
|
+
// Un mensaje del raíz se CIERRA aquí: si salió en inglés y el usuario no escribe en inglés, su siguiente
|
|
1885
|
+
// llamada lleva el recordatorio (`capacidadDeIdioma`). Sin reescribir lo dicho.
|
|
1886
|
+
if (!mensajeCerrado &&
|
|
1887
|
+
recordatoriosEnElTurno < TOPE_DE_RECORDATORIOS_DE_IDIOMA &&
|
|
1888
|
+
textoEnInglesSinPedirlo(ultimoMensaje, encargoDelTurno ?? peticion)) {
|
|
1889
|
+
recordatoriosEnElTurno += 1;
|
|
1890
|
+
recordatorioDeIdioma = textoDeRecordatorioDeIdioma(encargoDelTurno ?? peticion);
|
|
1891
|
+
}
|
|
1723
1892
|
mensajeCerrado = true;
|
|
1893
|
+
}
|
|
1724
1894
|
yield evento;
|
|
1725
1895
|
}
|
|
1726
1896
|
/**
|
|
@@ -1811,6 +1981,9 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1811
1981
|
*/
|
|
1812
1982
|
let observacionesVisuales = [];
|
|
1813
1983
|
if (carpeta !== undefined &&
|
|
1984
|
+
// Si el turno ya pasó `xone_critica_visual` (con la maqueta), este, que mira la captura SOLA, sobra y la
|
|
1985
|
+
// contradice: medido en Maset, tomó por defecto la franja granate con su punto verde, que ES del diseño.
|
|
1986
|
+
horaDeLaUltimaCritica === undefined &&
|
|
1814
1987
|
tocaCriticarPantalla({ hayCritico: opciones.criticaVisual !== undefined, capturas: capturasDelTurno.length, yaDisparo: visualYaDisparo, intento })) {
|
|
1815
1988
|
visualYaDisparo = true;
|
|
1816
1989
|
const captura = capturasDelTurno[capturasDelTurno.length - 1];
|
|
@@ -2000,7 +2173,20 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
2000
2173
|
verificador: veredicto,
|
|
2001
2174
|
pendientes: sinResolver,
|
|
2002
2175
|
...(cortadoPorTope ? { topeAgotado: tope } : {}),
|
|
2176
|
+
// La pregunta que deja ESTE turno: la de un turno anterior se consume al empezar (`enEspera`).
|
|
2177
|
+
...(preguntaEnEspera === undefined ? {} : { preguntaPendiente: consultaDe(preguntaEnEspera.args).pregunta }),
|
|
2003
2178
|
...(comprobacionesDelTurno.length === 0 ? {} : { comprobacionesVisuales: comprobacionesDelTurno }),
|
|
2179
|
+
// Lo que su respuesta final EXPLICA (lo nombra) no es crítico: va aparte (`omisionExplicada`).
|
|
2180
|
+
...(() => {
|
|
2181
|
+
const explicadas = bloqueantesVisualesDelTurno.filter((b) => omisionExplicada(b, respuestaDeLaPasada));
|
|
2182
|
+
const sinExplicar = bloqueantesVisualesDelTurno.filter((b) => !explicadas.includes(b));
|
|
2183
|
+
// Si el proyecto cambió DESPUÉS de esa crítica, lo que vio ya no es la pantalla final: no es crítico.
|
|
2184
|
+
const desfasada = sinExplicar.length > 0 && horaDeLaUltimaCritica !== undefined && cambioDespuesDe(raiz, horaDeLaUltimaCritica);
|
|
2185
|
+
return {
|
|
2186
|
+
...(sinExplicar.length === 0 ? {} : desfasada ? { bloqueantesDesfasados: sinExplicar } : { bloqueantesVisuales: sinExplicar }),
|
|
2187
|
+
...(explicadas.length === 0 ? {} : { omisionesExplicadas: explicadas }),
|
|
2188
|
+
};
|
|
2189
|
+
})(),
|
|
2004
2190
|
...(hallazgosDelTurno.length === 0 ? {} : { hallazgos: hallazgosDelTurno }),
|
|
2005
2191
|
...(preexistentesDelTurno === undefined ? {} : { preexistentes: preexistentesDelTurno }),
|
|
2006
2192
|
...(motivoSinVerificar === undefined ? {} : { motivoSinVerificar }),
|