xonecode 0.38.20 → 0.38.33
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-DySw4j79.js → EditorDeFichero-D4RtS6Rn.js} +1 -1
- package/apps/web/dist/assets/{index-D7OcbgXE.css → index-CHaxhucE.css} +1 -1
- package/apps/web/dist/assets/{index-vvfKjRva.js → index-Ctwi_MCD.js} +77 -77
- package/apps/web/dist/assets/{php-CSyDZ6m1.js → php-CM0UiqCU.js} +1 -1
- package/apps/web/dist/assets/{ruby-3bX3v6o_.js → ruby-CqaQ9j7r.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- 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/sesionTrueforge.js +161 -10
- 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/escrituraExterna.js +3 -3
- package/dist/agent/subagentes/escrituraExterna.js.map +1 -1
- package/dist/agent/subagentes/pluginDeSkills.js +10 -0
- package/dist/agent/subagentes/pluginDeSkills.js.map +1 -1
- package/dist/agent/subagentes/subagenteExterno.js +22 -8
- 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 +21 -19
- package/dist/agent/tareas/juezDeTarea.js.map +1 -1
- package/dist/agent/turno/resumenDeTool.js +2 -0
- package/dist/agent/turno/resumenDeTool.js.map +1 -1
- package/dist/cli/main.js +3 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/core/agentes.js +53 -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/entrega.js +55 -10
- package/dist/core/entrega.js.map +1 -1
- package/dist/core/geometriaDePantalla.js +74 -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 +2 -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.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/textos.js +10 -3
- package/dist/core/textos.js.map +1 -1
- package/dist/web/servidor/arranque.js +40 -3
- package/dist/web/servidor/arranque.js.map +1 -1
- package/dist/web/servidor/consolaDeTarea.js +3 -6
- package/dist/web/servidor/consolaDeTarea.js.map +1 -1
- package/dist/web/servidor/corredorDeTareas.js +21 -4
- package/dist/web/servidor/corredorDeTareas.js.map +1 -1
- package/dist/web/servidor/transporte.js +1 -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/scripts/xone-a-utf8 +60 -0
|
@@ -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";
|
|
@@ -73,7 +75,8 @@ import { encenderTrazaDeErrores } from "../../trazaDeErroresEnDisco.js";
|
|
|
73
75
|
import { anotarPaso } from "../../../core/trazaDeErrores.js";
|
|
74
76
|
import { entornoConDepuracion } from "../../turno/depuracion.js";
|
|
75
77
|
import { detalleDe, parametrosDe } from "../../turno/resumenDeTool.js";
|
|
76
|
-
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";
|
|
77
80
|
import { apartarMemoria, cargarMemoria, fotoSaneada, guardarMemoria, saldarColgadas, textoDeInterrupcion, textoDeMemoriaDescartada } from "./memoriaTrueforge.js";
|
|
78
81
|
import { crearNota, sobrantes } from "./notas.js";
|
|
79
82
|
import { crearMemoriaDeEspecialistas } from "./memoriaDeEspecialistas.js";
|
|
@@ -127,6 +130,22 @@ const BUCLE_DE_CALIDAD = [
|
|
|
127
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",
|
|
128
131
|
"di lo que sigue faltando en vez de darlo por hecho.",
|
|
129
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
|
+
}
|
|
130
149
|
/**
|
|
131
150
|
* Lo que el orquestador tiene que saber para DELEGAR en ESTE motor. Su prompt es el de siempre
|
|
132
151
|
* (`promptOrquestador`), que habla de `task` y de la ficha que va en su descripción: aquí la
|
|
@@ -176,6 +195,27 @@ export const TRABAJO_SIN_PERSONA = [
|
|
|
176
195
|
" DECISIONES que tomaste tú sin preguntar (cada duda, lo que elegiste y por qué) y lo que no pudiste comprobar o",
|
|
177
196
|
" queda pendiente.",
|
|
178
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
|
+
}
|
|
179
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é.";
|
|
180
220
|
/** Un comando que saca una captura de pantalla del aparato. */
|
|
181
221
|
export const COMANDO_DE_CAPTURA = /xone-captura-android|xone-hotswap\s+shot\b|\bscreencap\b/;
|
|
@@ -343,6 +383,11 @@ export function notaDeDelegacion(agentes, opciones = {}) {
|
|
|
343
383
|
"entiende `create_sub_agent` y `name`. Las fichas de los especialistas:",
|
|
344
384
|
...agentes.map((a) => `- ${a.nombre}: ${fichaDeAgente(a, opciones)}`),
|
|
345
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
|
+
})(),
|
|
346
391
|
...(opciones.conEsperas === true
|
|
347
392
|
? [
|
|
348
393
|
"",
|
|
@@ -459,6 +504,25 @@ function preguntaDeLaFoto(foto) {
|
|
|
459
504
|
};
|
|
460
505
|
}
|
|
461
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
|
+
}
|
|
462
526
|
/**
|
|
463
527
|
* `agregarNota` no vive todavía en `SesionReal` (IXCODE-4, Task 6 se la añade ahí como opcional,
|
|
464
528
|
* compartida con deepagents): se ensancha el tipo de retorno AQUÍ, en vez de esperar a esa task,
|
|
@@ -576,6 +640,9 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
576
640
|
let capturasDelTurno = [];
|
|
577
641
|
/** Lo que dieron las comprobaciones visuales del turno, una línea cada una, para el juez de QA (`ResultadoDeTurno`). */
|
|
578
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;
|
|
579
646
|
const anotarComprobacion = (linea) => {
|
|
580
647
|
comprobacionesDelTurno = [...comprobacionesDelTurno, linea].slice(-TOPE_DE_COMPROBACIONES_AL_JUEZ);
|
|
581
648
|
};
|
|
@@ -599,6 +666,30 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
599
666
|
const detencion = crearControlDeDetencion(HILO_RAIZ);
|
|
600
667
|
/** Tool calls tiradas por DETENER en la sesión: si se queda en cero, el filtro es solo red. */
|
|
601
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
|
+
};
|
|
602
693
|
const capacidadDeNotasDeLaSesion = capacidadDeNotas(notas, {
|
|
603
694
|
detencion,
|
|
604
695
|
nombreDe: (h) => quienEs.get(h) ?? h,
|
|
@@ -805,6 +896,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
805
896
|
...herramientasDeJuicio(),
|
|
806
897
|
...(carpeta === undefined ? [] : [crearTraerDeLaMaquina({ carpeta, alEscribir: anotarArtefacto })]),
|
|
807
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" }),
|
|
808
901
|
...(opciones.puedeProponerTareas === true
|
|
809
902
|
? [crearProponerTareas((p) => void propuestasPorAnunciar.push(p))]
|
|
810
903
|
: []),
|
|
@@ -857,6 +950,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
857
950
|
...(carpeta !== undefined && agente.ejecucion === true
|
|
858
951
|
? [crearDiferenciaDeCapturas({ leerArtefacto: async (nombre) => readFileSync(join(carpeta, nombre)) })]
|
|
859
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 })] : []),
|
|
860
955
|
// Y marcar en el plan lo comprobado, con el reparto de deepagents (`recibeMarcarCriterios`).
|
|
861
956
|
...(recibeMarcarCriterios(agente) ? [crearMarcarCriteriosDelPlan({ raiz })] : []),
|
|
862
957
|
// El BUCLE del desarrollador: quien puede llamar al de pruebas también tiene el crítico y la medida, para
|
|
@@ -922,13 +1017,18 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
922
1017
|
* su nombre; el entorno de NUESTRA shell; y la lectura de ESTAS dos carpetas de la sesión, que
|
|
923
1018
|
* es donde sus scripts dejan las capturas. Codex y OpenCode siguen sin shell.
|
|
924
1019
|
*/
|
|
925
|
-
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
|
|
926
1024
|
? {
|
|
927
|
-
scripts: scriptsDeLasSkills(raiz,
|
|
1025
|
+
scripts: scriptsDeLasSkills(raiz, delHijo.skills),
|
|
928
1026
|
entorno: entornoDeLaShellDelProyecto(raiz, carpeta),
|
|
929
1027
|
lecturas: [carpeta, carpetaDeHotswap(carpeta)],
|
|
930
1028
|
}
|
|
931
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;
|
|
932
1032
|
/**
|
|
933
1033
|
* Lo que sus comandos dejen en `/artefactos/` se ANUNCIA al volver, con la MISMA foto que nuestra
|
|
934
1034
|
* shell (`fotoDeArtefactos`): por nuestra shell se anunciaba y por la suya no, y una captura
|
|
@@ -961,12 +1061,23 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
961
1061
|
peticion: () => ({
|
|
962
1062
|
motor,
|
|
963
1063
|
cwd: raiz,
|
|
964
|
-
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"),
|
|
965
1072
|
tarea: params.request.input,
|
|
966
1073
|
...(agente.modelo === undefined ? {} : { modelo: agente.modelo }),
|
|
967
1074
|
permitirEscritura: !agente.soloLectura,
|
|
968
1075
|
agente: agente.nombre,
|
|
1076
|
+
skills: repartirSkills(delHijo, disponibles).suyas,
|
|
969
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 } : {}),
|
|
970
1081
|
}),
|
|
971
1082
|
senal: () => aborto?.signal,
|
|
972
1083
|
}),
|
|
@@ -1038,6 +1149,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1038
1149
|
notas: capacidadDeNotasDeLaSesion,
|
|
1039
1150
|
puedeLlamar: (a) => conBucleDelDesarrollador && (a.llama?.length ?? 0) > 0,
|
|
1040
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 } : {}),
|
|
1041
1154
|
vueltas: (a) => a.ejecucion === true
|
|
1042
1155
|
? capacidadDeAvisoDeVueltas({ vueltasDe: (hilo) => capturasDeCadaHilo.get(hilo) ?? 0, umbrales: UMBRALES_DE_CAPTURAS, texto: textoDeCapturas })
|
|
1043
1156
|
: conBucleDelDesarrollador && (a.llama?.length ?? 0) > 0
|
|
@@ -1058,7 +1171,10 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1058
1171
|
notaDeTools(nombres, agente === undefined ? LIMITE_DEL_GENERICO : LIMITES_DE[clase]),
|
|
1059
1172
|
...(nombres.includes(NOMBRE_ATRIBUTOS_XONE) ? [USO_DE_XONE_ATRIBUTOS] : []),
|
|
1060
1173
|
...(nombres.includes(NOMBRE_CONVERTIR_A_P) ? [USO_DE_CONVERTIR_A_P] : []),
|
|
1174
|
+
...(nombres.includes(NOMBRE_APUNTAR_APRENDIZAJE) ? [USO_DE_APUNTAR_APRENDIZAJE] : []),
|
|
1061
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));
|
|
1062
1178
|
const instrucciones = agente === undefined
|
|
1063
1179
|
? `${IDIOMA_DEL_ESPECIALISTA}\n\n${nota} Contesta con lo que encuentres y dónde.`
|
|
1064
1180
|
: [
|
|
@@ -1068,6 +1184,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1068
1184
|
"",
|
|
1069
1185
|
nota,
|
|
1070
1186
|
anuncioDeSkills(agente, catalogo),
|
|
1187
|
+
...(aprendido === undefined ? [] : ["", aprendido]),
|
|
1071
1188
|
...(conBucleDelDesarrollador && (agente.llama?.length ?? 0) > 0 ? ["", textoDelBucle(agente.llama ?? [], { conCritica: carpeta !== undefined, conFuentes: opciones.fuentes !== undefined })] : []),
|
|
1072
1189
|
]
|
|
1073
1190
|
.filter((l) => l !== undefined)
|
|
@@ -1163,7 +1280,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1163
1280
|
hijosConMemoria.clear();
|
|
1164
1281
|
const definicion = {
|
|
1165
1282
|
modelClient: llm,
|
|
1166
|
-
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 : ""].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"),
|
|
1167
1284
|
// Por TURNO, porque el raíz se rehace desde su foto al final de cada uno (ver `turno`).
|
|
1168
1285
|
iterationLimit: LIMITE_DE_LLAMADAS_DEL_RAIZ,
|
|
1169
1286
|
};
|
|
@@ -1182,6 +1299,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1182
1299
|
capacidadDeFecha(),
|
|
1183
1300
|
capacidadDeNotasDeLaSesion,
|
|
1184
1301
|
capacidadDeInformes,
|
|
1302
|
+
capacidadDeIdioma,
|
|
1185
1303
|
]),
|
|
1186
1304
|
/**
|
|
1187
1305
|
* **La conversación se RESUME a un umbral que depende de la ventana del modelo**
|
|
@@ -1387,6 +1505,12 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1387
1505
|
// Las comprobaciones VISUALES, para el juez: lo que dijeron, medido aquí y no contado por el agente.
|
|
1388
1506
|
if (llamada !== undefined && (llamada.nombre === NOMBRE_COMPARAR_CAPTURAS || llamada.nombre === "xone_critica_visual") && typeof evento.content === "string") {
|
|
1389
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
|
+
}
|
|
1390
1514
|
}
|
|
1391
1515
|
const chars = typeof evento.content === "string" ? evento.content.length : 0;
|
|
1392
1516
|
diagnostico?.resultado?.(llamada?.nombre, llamada === undefined ? undefined : detalleDe(llamada.nombre, llamada.args), chars);
|
|
@@ -1509,6 +1633,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1509
1633
|
throw new Error("la sesión está cerrada");
|
|
1510
1634
|
const t0 = Date.now();
|
|
1511
1635
|
cancelado = false;
|
|
1636
|
+
recordatoriosEnElTurno = 0;
|
|
1637
|
+
recordatorioDeIdioma = undefined;
|
|
1512
1638
|
detencion.reiniciar();
|
|
1513
1639
|
const instantanea = await tomarInstantanea(raiz, opciones.entorno.git);
|
|
1514
1640
|
const tope = opciones.topeDeRondas ?? MAX_APPROVAL_ROUNDS;
|
|
@@ -1519,6 +1645,8 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1519
1645
|
externosDelTurno = 0;
|
|
1520
1646
|
capturasDelTurno = [];
|
|
1521
1647
|
comprobacionesDelTurno = [];
|
|
1648
|
+
bloqueantesVisualesDelTurno = [];
|
|
1649
|
+
horaDeLaUltimaCritica = undefined;
|
|
1522
1650
|
/** El encargo de ESTE turno tal cual se pidió, y el mismo con la última pregunta y su
|
|
1523
1651
|
* respuesta al lado, que es lo que se juzga y se repara (ver `flujo`). Ausente = no consta. */
|
|
1524
1652
|
let encargoDelTurno;
|
|
@@ -1576,7 +1704,7 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1576
1704
|
type: "user.tool_response",
|
|
1577
1705
|
thread_id: q.hilo,
|
|
1578
1706
|
tool_call_id: q.id,
|
|
1579
|
-
content: elegida
|
|
1707
|
+
content: elegida === undefined ? RESPUESTA_AUTONOMA_SIN_RECOMENDADA : respuestaAutonomaRecomendada(elegida),
|
|
1580
1708
|
});
|
|
1581
1709
|
}
|
|
1582
1710
|
lote = respuestas;
|
|
@@ -1752,8 +1880,17 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1752
1880
|
mensajeCerrado = false;
|
|
1753
1881
|
ultimoMensaje += evento.texto;
|
|
1754
1882
|
}
|
|
1755
|
-
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
|
+
}
|
|
1756
1892
|
mensajeCerrado = true;
|
|
1893
|
+
}
|
|
1757
1894
|
yield evento;
|
|
1758
1895
|
}
|
|
1759
1896
|
/**
|
|
@@ -1844,6 +1981,9 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
1844
1981
|
*/
|
|
1845
1982
|
let observacionesVisuales = [];
|
|
1846
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 &&
|
|
1847
1987
|
tocaCriticarPantalla({ hayCritico: opciones.criticaVisual !== undefined, capturas: capturasDelTurno.length, yaDisparo: visualYaDisparo, intento })) {
|
|
1848
1988
|
visualYaDisparo = true;
|
|
1849
1989
|
const captura = capturasDelTurno[capturasDelTurno.length - 1];
|
|
@@ -2036,6 +2176,17 @@ export async function abrirSesionTrueforge(opciones) {
|
|
|
2036
2176
|
// La pregunta que deja ESTE turno: la de un turno anterior se consume al empezar (`enEspera`).
|
|
2037
2177
|
...(preguntaEnEspera === undefined ? {} : { preguntaPendiente: consultaDe(preguntaEnEspera.args).pregunta }),
|
|
2038
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
|
+
})(),
|
|
2039
2190
|
...(hallazgosDelTurno.length === 0 ? {} : { hallazgos: hallazgosDelTurno }),
|
|
2040
2191
|
...(preexistentesDelTurno === undefined ? {} : { preexistentes: preexistentesDelTurno }),
|
|
2041
2192
|
...(motivoSinVerificar === undefined ? {} : { motivoSinVerificar }),
|