idea_world_labDEV JOURNAL
sábado, 27 de junio de 2026

Seguimiento de la línea desde la entrada de código fuente hasta el AST y el Retriever

Fecha de redacción: 27 de junio de 2026

Propósito

Este documento reorganiza, a fecha del 27, la parte que había perdido consistencia en docs/roadmaps/2026-06-26-source-to-ast-input-flow.md.

El punto clave no es redefinir la nueva unidad de diseño. La arquitectura completa y la dirección del diseño de la base de datos ya están documentadas por separado. Aquí se rastrea hasta el final qué línea de qué archivo entra en el AST Parser cuando se recibe una entrada real, qué fragmento se utiliza en la búsqueda del Retriever y qué candidato de evidencia regresa para la decisión del LLM.

El principio a mantener es simple.

Se adjunta la ruta del archivo para rastrear la ubicación.  
En el Retriever no se incluye la ruta del archivo, sino fragmentos de código/texto.  
Los archivos .gd son divididos por el AST Parser en unidades de funciones y declaraciones.  
Los demás archivos de texto necesarios se recortan directamente por rangos de líneas.  
Cada fragmento pasa por el Retriever y la evaluación del LLM en orden.

Formato de entrada

Al clonar o subir el proyecto, primero se despliegan los archivos con rutas relativas.

El formato se ve así.

# <ruta relativa>
<contenido del archivo>

# <ruta relativa>
<contenido del archivo>

Esta notación es solo para que una persona pueda depurar. Un encabezado como # player.gd solo indica “de qué archivo proviene el contenido a continuación”.

El buscador Retriever no incluye # player.gd. El AST Parser tampoco incluye # player.gd. Lo que se incluye es el contenido real del archivo bajo el encabezado.

Entrada de ejemplo

A continuación se muestra un pequeño proyecto de Godot desplegado. Los números como E001, E002 son números de línea para la explicación y no forman parte del texto de entrada real.

E001 # project.godot
E002 config_version=5
E003
E004 [application]
E005 config/name="Mini Dodge"
E006 run/main_scene="res://player.tscn"
E007
E008 # player.gd
E009 extends Area2D
E010
E011 signal hit
E012
E013 @export var speed = 400
E014 var screen_size
E015
E016 func _ready():
E017 	screen_size = get_viewport_rect().size
E018 	hide()
E019
E020 func _process(delta):
E021 	var velocity = Vector2.ZERO
E022 	if Input.is_action_pressed(&"move_right"):
E023 		velocity.x += 1
E024 	if Input.is_action_pressed(&"move_left"):
E025 		velocity.x -= 1
E026
E027 	if velocity.length() > 0:
E028 		velocity = velocity.normalized() * speed
E029 		$AnimatedSprite2D.play()
E030 	else:
E031 		$AnimatedSprite2D.stop()
E032
E033 	position += velocity * delta
E034 	position = position.clamp(Vector2.ZERO, screen_size)
E035
E036 func start(pos):
E037 	position = pos
E038 	show()
E039 	$CollisionShape2D.disabled = false
E040
E041 # player.tscn
E042 [gd_scene load_steps=3 format=3 uid="uid://mini"]
E043
E044 [ext_resource type="Script" path="res://player.gd" id="1"]
E045
E046 [node name="Player" type="Area2D"]
E047 script = ExtResource("1")

Paso 1: Dividir los límites de archivo

Primero, divide los archivos basándote en el encabezado # <ruta relativa>.

project.godot comienza en E001. El contenido real es de E002 a E006. E001 es una marca de límite de archivo, por lo que no es parte del cuerpo a analizar.

player.gd comienza en E008. El cuerpo real es de E009 a E039. E008 es una marca de límite de archivo, por lo que no entra en el AST Parser.

player.tscn comienza en E041. El cuerpo real es de E042 a E047. E041 es una marca de límite de archivo, por lo que no es el cuerpo de búsqueda del Retriever.

En esta etapa, la UI puede mostrarse como “Actualmente procesa E009‑E039 de player.gd”. Sin embargo, aún no se crea la palabra de búsqueda.

2ª etapa: Determinar la dirección del procesamiento según el tipo de archivo

player.gd es un archivo GDScript. Por lo tanto, todo E009-E039 se envía al AST Parser.

project.godot es un archivo de configuración. No se envía al AST Parser, se fragmenta directamente por secciones necesarias.

player.tscn es un archivo de escena. No se envía al AST Parser, se fragmenta directamente por bloques de nodo/recurso.

Los documentos README o de descripción en Markdown se excluyen por defecto en el modo de análisis de código fuente. Los archivos excluidos también deben mostrarse en la UI. La razón es que una persona debe verificar “qué se ha omitido”.

Por ejemplo, si existe README.md, debe estar excluido del análisis y la razón de exclusión debe mostrarse como “Los archivos de documentación se excluyen por defecto en el modo de análisis de código fuente”. Sin embargo, esta decisión de exclusión es solo el valor predeterminado del modo de análisis y, si más adelante se necesita un modo que también lea la documentación, se manejará por separado.

Paso 3: Pasar el archivo .gd al AST Parser

La entrada que entra al AST Parser desde player.gd es E009-E039.

El cuerpo que realmente recibe el AST Parser es el siguiente:

extends Area2D

signal hit

@export var speed = 400
var screen_size

func _ready():
	screen_size = get_viewport_rect().size
	hide()

func _process(delta):
	var velocity = Vector2.ZERO
	if Input.is_action_pressed(&"move_right"):
		velocity.x += 1
	if Input.is_action_pressed(&"move_left"):
		velocity.x -= 1

	if velocity.length() > 0:
		velocity = velocity.normalized() * speed
		$AnimatedSprite2D.play()
	else:
		$AnimatedSprite2D.stop()

	position += velocity * delta
	position = position.clamp(Vector2.ZERO, screen_size)

func start(pos):
	position = pos
	show()
	$CollisionShape2D.disabled = false

Aquí no está # player.gd.

El AST Parser lee este texto de arriba a abajo y lo divide en unidades de declaraciones y funciones.

El primer fragmento es una línea E009.

extends Area2D

El segundo fragmento es una línea E011.

signal hit

El tercer fragmento es E013-E014.

@export var speed = 400
var screen_size

El cuarto fragmento es E016-E018.

func _ready():
	screen_size = get_viewport_rect().size
	hide()

La quinta pieza es E020-E034.

func _process(delta):
	var velocity = Vector2.ZERO
	if Input.is_action_pressed(&"move_right"):
		velocity.x += 1
	if Input.is_action_pressed(&"move_left"):
		velocity.x -= 1

	if velocity.length() > 0:
		velocity = velocity.normalized() * speed
		$AnimatedSprite2D.play()
	else:
		$AnimatedSprite2D.stop()

	position += velocity * delta
	position = position.clamp(Vector2.ZERO, screen_size)

El sexto fragmento es E036-E039.

func start(pos):
	position = pos
	show()
	$CollisionShape2D.disabled = false

Importante es que, incluso después de que el fragmento se haya creado, no pierda el rango de líneas original. Por ejemplo, el fragmento _process sigue siendo rastreado como “fragmento extraído de player.gd en E020-E034”.

Paso 4: Procesar fragmentos manualmente

Si también se necesitan archivos de texto que no son objetivo del AST Parser, divídelos en fragmentos.

En project.godot, E004-E006 se convierten en el fragmento de configuración de la aplicación.

[application]
config/name="Mini Dodge"
run/main_scene="res://player.tscn"

Este fragmento puede usarse para encontrar la escena de inicio del proyecto debido a run/main_scene="res://player.tscn". Si se realiza una búsqueda con Retriever, contenidos como run/main_scene, res://player.tscn, application dentro del texto se convierten en material de búsqueda. La propia ruta del archivo project.godot no se convierte en término de búsqueda.

En player.tscn, la línea E044 se convierte en un fragmento de referencia al script.

[ext_resource type="Script" path="res://player.gd" id="1"]

E046-E047 se convierte en un fragmento de nodo.

[node name="Player" type="Area2D"]
script = ExtResource("1")

Este fragmento directo no es un chunk de AST, pero el flujo posterior es el mismo. Se toma una parte del cuerpo del texto, se busca en el Retriever y el LLM vuelve a verificar los candidatos encontrados.

Paso 5: Contenido que realmente ingresa al Retriever

En el Retriever no se coloca la “ruta del archivo”, sino el “cuerpo del fragmento actual y las pistas de búsqueda extraídas del cuerpo”.

Por ejemplo, al procesar el fragmento _process, el cuerpo que sirve como criterio de búsqueda es E020‑E034.

func _process(delta):
	var velocity = Vector2.ZERO
	if Input.is_action_pressed(&"move_right"):
		velocity.x += 1
	if Input.is_action_pressed(&"move_left"):
		velocity.x -= 1

	if velocity.length() > 0:
		velocity = velocity.normalized() * speed
		$AnimatedSprite2D.play()
	else:
		$AnimatedSprite2D.stop()

	position += velocity * delta
	position = position.clamp(Vector2.ZERO, screen_size)

En este texto, las pistas que pueden usarse para la búsqueda aparecen de la siguiente manera.

Input.is_action_pressed
Vector2.ZERO
velocity.normalized
position.clamp
AnimatedSprite2D
_process
Godot 3
Godot 4
migration

Entre las pistas anteriores, Godot 3, Godot 4, migration se añaden cuando la solicitud del usuario es algo como “Verifica si este proyecto es Godot 3 o Godot 4 y, si es necesario, encuentra la base para la conversión”.

La búsqueda Retriever utiliza el cuerpo de este fragmento y las pistas.

La búsqueda vectorial incluye todo el cuerpo de la función _process y los símbolos principales.

La búsqueda de palabras clave incluye símbolos como Input.is_action_pressed, Vector2.ZERO, position.clamp.

La ruta del archivo player.gd no se usa como término de búsqueda. Sin embargo, se utiliza más adelante para añadir en los registros y la interfaz de usuario frases como “Esta búsqueda se produjo en player.gd de la E020 a la E034”.

Paso 6: Qué busca el Retriever

Retriever busca docs_chunks, api_mapping, label_prototypes de la misma manera con el mismo fragmento. No trata de forma especial a ninguna de las tres tablas.

En docs_chunks pueden aparecer candidatos de descripción de la documentación oficial como Input.is_action_pressed, Vector2.ZERO, position, Area2D.

En api_mapping pueden aparecer candidatos de nombres de funciones, clases y propiedades que cambiaron de Godot 3 a Godot 4. Por ejemplo, si el fragmento de código contiene pistas como KinematicBody2D, yield, Color8, pueden aparecer candidatos de migración relacionados.

En label_prototypes pueden aparecer candidatos que representen un “patrón en el que el modo de uso de una función cambia por completo” o un “ejemplo en el que la composición de los argumentos y la forma de llamada cambian”. No se trata simplemente de un cambio de nombre, sino de casos en los que es necesario describir el propio modo de uso.

Por ejemplo, en el fragmento _process pueden aparecer los siguientes candidatos.

docs_chunks candidato:
  Input.is_action_pressed descripción de la documentación oficial
  Vector2.ZERO descripción de la documentación oficial
  Node2D.position descripción de la documentación oficial

api_mapping candidato:
  En este fragmento puede que no haya candidatos de cambio de nombre especiales de Godot 3 -> 4

label_prototypes candidato:
  Ejemplo de código de movimiento en Godot 4 usando Input.is_action_pressed y Vector2.ZERO

Estos candidatos no son la respuesta. Sólo son “evidencias que podrían estar relacionadas con este fragmento de código”.

Paso 7: Pasar los resultados del Retriever al LLM

Al LLM se le suministran el prompt del usuario, el fragmento de código actual y los candidatos del Retriever.

Por ejemplo, en el fragmento _process se incluye lo siguiente:

**Solicitud del usuario:**  
Verifica si este proyecto está usando Godot 3 o Godot 4 y, de ser necesario, proporciona la base para la conversión.

**Fragmento de código actual:**  
`player.gd` de la línea E020 a la E034

func _process(delta):
	var velocity = Vector2.ZERO
	if Input.is_action_pressed(&"move_right"):
		velocity.x += 1
	if Input.is_action_pressed(&"move_left"):
		velocity.x -= 1

	if velocity.length() > 0:
		velocity = velocity.normalized() * speed
		$AnimatedSprite2D.play()
	else:
		$AnimatedSprite2D.stop()

	position += velocity * delta
	position = position.clamp(Vector2.ZERO, screen_size)

**Candidatos de recuperación:**  
- Documento oficial de `Input.is_action_pressed` en *docs_chunks*  
- Documento oficial de `Vector2.ZERO` en *docs_chunks*  
- Documento oficial de `Node2D.position` en *docs_chunks*  
- Ejemplo de manejo de entrada en Godot 4 en *label_prototypes*

LLM aquí determina dos cosas.

Primero, verifica si el candidato encontrado está realmente relacionado con el fragmento de código actual.

Segundo, decide si el fragmento de código actual corresponde a una señal de Godot 3, a una señal de Godot 4, o si requiere una migración.

En este ejemplo, Input.is_action_pressed, Vector2.ZERO y position.clamp pueden interpretarse como bases de código que también son utilizables en Godot 4. Por lo tanto, es probable que este fragmento se acumule bajo la categoría “Se puede considerar código de Godot 4, no se necesita migración”.

8. Paso: Flujo del fragmento de ejemplo de Godot 3

Supongamos que hay el siguiente fragmento en otro archivo.

G101 # enemy.gd
G102 extends KinematicBody2D
G103
G104 var velocity = Vector2.ZERO
G105
G106 func _physics_process(delta):
G107 	velocity = move_and_slide(velocity)

enemy.gd es un archivo .gd, por lo que el cuerpo G102‑G107 se incluye en el AST Parser.

El primer fragmento es G102.

extends KinematicBody2D

El segundo fragmento es G106‑G107.

func _physics_process(delta):
	velocity = move_and_slide(velocity)

Si pasas el fragmento extends KinematicBody2D al Retriever, la pista de búsqueda se captura como sigue.

KinematicBody2D
Godot 3
Godot 4
migration

En este caso, en api_mapping puede aparecer un candidato donde KinematicBody2D se migra a la familia CharacterBody2D en Godot 4.

En docs_chunks pueden aparecer candidatos de documentación oficial relacionados con CharacterBody2D o cuerpos físicos.

En label_prototypes puede aparecer un ejemplo donde el código de movimiento basado en KinematicBody2D se transforma a CharacterBody2D usando velocity y el método move_and_slide().

Así es como se introduce en el LLM.

**Solicitud del usuario:**  
Verifica si este proyecto es Godot 3 o Godot 4 y, si es necesario, busca la base para la conversión.

**Fragmento de código actual:**  
`enemy.gd` en la línea G102

extends KinematicBody2D

**Candidatos para el recuperador:**  
- `api_mapping` → candidato de migración de **KinematicBody2D** a **CharacterBody2D**  
- `docs_chunks` → candidato de documentación oficial de **CharacterBody2D**  
- `label_prototypes` → ejemplo de conversión de código de movimiento de **KinematicBody2D**

El LLM puede juzgar este fragmento como “Señal de Godot 3 fuerte y necesita migración”.

Posteriormente, el fragmento G106‑G107 también se procesará por separado.

func _physics_process(delta):
	velocity = move_and_slide(velocity)

En este fragmento, la forma de invocación move_and_slide(velocity) se convierte en una pista de búsqueda. No solo se observa el nombre de la función, sino también la forma de llamada con sus argumentos.

En este caso, si solo cambia el nombre de la función, el candidato api_mapping es importante, y si cambia toda la forma de invocación, también lo es el candidato label_prototypes.

Paso 9: Acumulación de resultados del fragmento

Cada fragmento se evalúa individualmente.

Los códigos E020‑E034 de player.gd pueden acumularse como señales de Godot 4.

El código G102 de enemy.gd puede acumularse como señal de Godot 3.

Los códigos G106‑G107 de enemy.gd también pueden acumularse como señales de migración a Godot 3.

La evaluación del proyecto completo no se basa en el nombre del archivo. La ruta del archivo sirve solo para rastreo. La evaluación del proyecto completo se determina a partir de la acumulación de los juicios de cada fragmento de código.

Por ejemplo, si en un proyecto la mayoría de las señales indican Godot 4 pero aparecen algunas señales de migración a Godot 3, la valoración puede acercarse a mixed. Por el contrario, si la mayoría de las señales son de migración a Godot 3, el proyecto puede clasificarse como de Godot 3.

Interrupción y reanudación

RunPod o un servidor web local pueden detenerse a mitad de proceso. Por eso el procesamiento debe poder continuar por fragmentos, no por archivos completos.

Por ejemplo, si se procesaron los códigos E009, E011, E013‑E014 de player.gd y se detuvo en E016‑E018, al reiniciar se debe comenzar nuevamente a partir de E016‑E018.

No se deben volver a procesar los códigos ya completados E009, E011, E013‑E014.

En la interfaz web debe mostrarse lo siguiente.

player.gd E009 Procesado  
player.gd E011 Procesado  
player.gd E013-E014 Procesado  
player.gd E016-E018 Procesamiento detenido  
player.gd E020-E034 En espera  
player.gd E036-E039 En espera

Así se puede verificar si “el procesamiento existente continúa o si se reinicia desde el principio”.

Lo que debe mostrarse en la pantalla de depuración

La pantalla de depuración es necesaria para el seguimiento.

Al menos debe mostrarse lo siguiente.

**Archivo actual:** `player.gd`  
**Rango de líneas actual:** `E020-E034`  
**Fragmento actual:**
func _process(delta):
	...

**Pistas de búsqueda introducidas en el Retriever:**
- `Input.is_action_pressed`
- `Vector2.ZERO`
- `position.clamp`

**Candidatos encontrados:**
- `docs_chunks: Input.is_action_pressed`
- `docs_chunks: Vector2.ZERO`
- `label_prototypes: Godot 4 input polling example`

**Juicio del LLM:**
- Señal de Godot 4
- No se requiere migración

Aquí lo importante es que se ve separada la diferencia entre “qué se incluye en la búsqueda” y “qué solo se adjunta para rastreo”.

La ruta player.gd puede mostrarse en la visualización actual del archivo. Sin embargo, no debe incluirse en la lista de pistas de búsqueda de Retriever.

Resumen

El flujo fijado en el documento a partir del día 27 es el siguiente.

# <ruta relativa>
<cuerpo>

-> Separar solo los límites del archivo con encabezados.  
-> El cuerpo del archivo .gd se procesa con el AST Parser.  
-> El AST Parser corta funciones y declaraciones en orden.  
-> El cuerpo real y la pista de símbolos de cada fragmento se envían a la búsqueda del Retriever.  
-> Se buscan docs_chunks, api_mapping y label_prototypes de la misma manera.  
-> Se pasan los candidatos de búsqueda y el fragmento actual al LLM juntos.  
-> Se guarda el juicio del LLM por fragmento y se acumula por proyecto.

El propósito de este documento no es establecer una nueva estructura, sino permitir verificar en qué línea se corta la entrada real y qué contenido pasa a la siguiente etapa. Al implementarlo, también se debe mostrar en la interfaz web, siguiendo este criterio, el archivo actual, el rango de líneas actual, el contenido real transmitido, la pista de búsqueda del Retriever, los candidatos de búsqueda y el juicio del LLM, todo junto.