idea_world_labDEV JOURNAL
samedi 27 juin 2026

Flux de suivi de ligne du code source à l'AST jusqu'au Retriever

Date de rédaction : 27 juin 2026

Objectif

Ce document reprend, au 27, les parties qui manquaient de cohérence dans docs/roadmaps/2026-06-26-source-to-ast-input-flow.md.

L'essentiel n'est pas de redéfinir une nouvelle unité de conception. L'architecture globale et l'orientation de la conception de la base de données sont déjà documentées séparément. Ici, nous suivons jusqu'au bout quel fichier et quelle ligne sont transmis au parseur AST lorsqu'une entrée réelle arrive, quelle portion est utilisée pour la recherche du Retriever, et quels candidats de preuve reviennent pour être évalués par le LLM.

Le principe à retenir est simple.

Le chemin du fichier est ajouté pour suivre la position.  
Le Retriever contient des extraits de code/texte, pas le chemin du fichier.  
Les fichiers .gd sont découpés par l'AST Parser en unités de fonctions et de déclarations.  
Les autres fichiers texte nécessaires sont découpés directement par plage de lignes.  
Chaque extrait passe successivement par le Retriever et le jugement du LLM.

Forme d'entrée

Lorsque vous clonez ou téléchargez le projet, vous dépliez d'abord les fichiers avec le chemin relatif.

La forme ressemble à ceci.

# <chemin relatif>
<contenu du fichier>

# <chemin relatif>
<contenu du fichier>

Cette notation est destinée au débogage par l'homme. Un en‑tête comme # player.gd ne fait que indiquer « de quel fichier provient le texte ci‑dessous ».

La recherche Retriever n’inclut pas # player.gd. L’AST Parser n’inclut pas non plus # player.gd. Ce qui est inclus est le véritable contenu du fichier sous l’en‑tête.

Exemple d’entrée

Ci‑dessous est l’apparence d’un petit projet Godot. Les numéros comme E001, E002 sont des numéros de ligne à des fins d’explication et ne font pas partie du texte d’entrée réel.

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")

1ère étape : Division des limites de fichiers

Tout d'abord, divisez les fichiers en fonction de l’en‑tête # <chemin relatif>.

project.godot commence à E001. Le texte réel va de E002 à E006. E001 est un indicateur de limite de fichier, il ne fait pas partie du texte analysé.

player.gd commence à E008. Le texte réel va de E009 à E039. E008 est un indicateur de limite de fichier, il n’est pas envoyé à l’AST Parser.

player.tscn commence à E041. Le texte réel va de E042 à E047. E041 est un indicateur de limite de fichier, il ne fait pas partie du texte recherché par le Retriever.

À cette étape, l’UI peut afficher « Traitement de E009‑E039 du player.gd actuel ». Cependant, aucun terme de recherche n’est encore généré.

2ème étape : Déterminer la direction de traitement selon le type de fichier

player.gd est un fichier GDScript. Ainsi, l’ensemble E009‑E039 est envoyé à l’AST Parser.

project.godot est un fichier de configuration. Il n’est pas envoyé à l’AST Parser, mais découpé directement en sections nécessaires.

player.tscn est un fichier de scène. Il n’est pas envoyé à l’AST Parser, mais découpé directement en blocs node/resource.

Les fichiers README ou les documents Markdown sont, par défaut, exclus du mode d’analyse du code source. Les fichiers exclus doivent néanmoins être affichés dans l’UI, afin que l’utilisateur puisse vérifier « ce qui a été omis ».

Par exemple, si un README.md existe, il est exclu de l’analyse et la raison affichée doit être « Les fichiers de documentation sont exclus par défaut en mode d’analyse du code source ». Cette décision d’exclusion n’est qu’une valeur par défaut du mode d’analyse ; si un mode incluant les documents est nécessaire, il sera géré séparément.

3ème étape : Transmettre les fichiers .gd à l’AST Parser

L’entrée qui passe de player.gd à l’AST Parser est E009‑E039.

Le texte réellement reçu par l’AST Parser est le suivant.

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

Il n'y a pas # player.gd ici.

L'AST Parser lit ce texte de haut en bas et le découpe en unités de déclarations et de fonctions.

Le premier fragment est une ligne E009.

extends Area2D

Le deuxième morceau est une ligne E011.

signal hit

Le troisième morceau est E013‑E014.

@export var speed = 400
var screen_size

Le quatrième morceau est E016‑E018.

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

Le cinquième morceau est 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)

Le sixième morceau est E036‑E039.

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

Le point important est que, même après la création du fragment, il ne perd pas la plage de lignes d'origine. Par exemple, le fragment _process continue d'être suivi comme « fragment provenant de player.gd lignes E020‑E034 ».

Étape 4 : Traitement manuel des fragments

Divisez également en fragments les fichiers texte qui ne sont pas des cibles de l’AST Parser mais qui sont nécessaires.

Dans project.godot, les lignes E004‑E006 constituent le fragment de configuration de l’application.

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

Ce fragment peut être utilisé pour trouver la scène de démarrage du projet grâce à run/main_scene="res://player.tscn". Si vous effectuez une recherche Retriever, le contenu tel que run/main_scene, res://player.tscn, application dans le texte devient le matériau de recherche. Le chemin de fichier project.godot lui‑même ne constitue pas un terme de recherche.

Dans player.tscn, une ligne E044 devient un fragment de référence de script.

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

E046-E047 devient un fragment de nœud.

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

Cette sorte de fragment direct n’est pas un AST chunk, mais le flux suivant reste le même. On utilise une partie du texte comme requête pour le Retriever, puis le LLM re‑valide les candidats récupérés.

Étape 5 : Contenu réellement envoyé au Retriever

Le Retriever ne reçoit pas un « chemin de fichier », mais le « texte du fragment actuel et les indices de recherche extraits du texte ».

Par exemple, lors du traitement du fragment _process, le texte servant de critère de recherche est 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)

Dans ce texte, les indices utilisables pour la recherche sont présentés comme suit.

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

Parmi les indices ci‑dessus, les termes Godot 3, Godot 4, migration sont ajoutés lorsqu’une requête de l’utilisateur ressemble à « Vérifie si ce projet utilise Godot 3 ou Godot 4 et, si nécessaire, trouve les bases de la conversion ».

La recherche du Retriever s’appuie sur ce fragment de texte et sur les indices.

La recherche vectorielle inclut le corps complet de la fonction _process ainsi que les symboles principaux.

La recherche par mots‑clés comprend des noms de symboles tels que Input.is_action_pressed, Vector2.ZERO, position.clamp.

Le chemin de fichier player.gd n’est pas utilisé comme terme de recherche. Il ne sert qu’à être affiché plus tard dans les journaux et l’interface utilisateur, par exemple : « Cette recherche a eu lieu dans player.gd entre E020 et E034 ».

Étape 6 : ce que le Retriever recherche

Le Retriever interroge les tables docs_chunks, api_mapping et label_prototypes de la même façon, sans accorder de traitement spécial à l’une d’elles.

Dans docs_chunks, il peut apparaître des candidats provenant de la documentation officielle, comme Input.is_action_pressed, Vector2.ZERO, position, Area2D.

Dans api_mapping, on peut obtenir des candidats de fonctions, de classes ou d’attributs qui ont changé entre Godot 3 et Godot 4. Par exemple, si le fragment de code contient KinematicBody2D, yield, Color8, des suggestions de migration correspondantes peuvent être proposées.

Dans label_prototypes, on peut trouver des candidats décrivant des « modèles où l’utilisation d’une fonction change complètement » ou des exemples où la composition des arguments et la forme d’appel sont modifiées. Cela est pertinent lorsqu’il ne s’agit pas simplement d’un renommage, mais d’une explication du changement de mode d’utilisation.

Par exemple, pour le fragment _process, les candidats suivants peuvent être retournés.

docs_chunks candidat :
  Description de la documentation officielle de Input.is_action_pressed
  Description de la documentation officielle de Vector2.ZERO
  Description de la documentation officielle de Node2D.position

api_mapping candidat :
  Il se peut qu'il n'y ait aucun candidat de renommage spécial de Godot 3 → 4 dans cet extrait

label_prototypes candidat :
  Exemple de code de déplacement Godot 4 utilisant Input.is_action_pressed et Vector2.ZERO

Ces candidats ne sont pas la réponse. Ce ne sont que des « preuves susceptibles d’être liées à ce fragment de code ».

Étape 7 : Transmettre les résultats du Retriever au LLM

Le LLM reçoit la invite de l’utilisateur, le fragment de code actuel et les candidats du Retriever.

Par exemple, dans le fragment _process, cela se présente comme suit.

**Demande de l'utilisateur :**  
Vérifier si ce projet utilise Godot 3 ou Godot 4 et, le cas échéant, fournir les raisons de la conversion.

**Fragment de code actuel :**  
`player.gd` lignes 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)

**Candidats de récupération :**  
- `docs_chunks` : candidat de la documentation officielle pour `Input.is_action_pressed`  
- `docs_chunks` : candidat de la documentation officielle pour `Vector2.ZERO`  
- `docs_chunks` : candidat de la documentation officielle pour `Node2D.position`  
- `label_prototypes` : exemple de gestion d’entrée dans Godot 4

LLM détermine ici deux choses.

Premièrement, il vérifie si le candidat récupéré est réellement lié au fragment de code actuel.

Deuxièmement, il décide si le fragment de code actuel correspond à un signal de Godot 3, à un signal de Godot 4, ou s’il nécessite une migration.

Dans cet exemple, Input.is_action_pressed, Vector2.ZERO, position.clamp peuvent être interprétés comme des preuves de code utilisables également dans Godot 4. Ainsi, il est très probable que ce fragment soit classé comme « code Godot 4, aucune migration nécessaire ».

Étape 8 : Flux du fragment d’exemple Godot 3

Supposons qu’un autre fichier contienne le fragment suivant.

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 est un fichier .gd, il est donc inclus dans le corps G102-G107 de l'AST Parser.

Le premier fragment est G102.

extends KinematicBody2D

Deuxième morceau est G106-G107.

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

Lorsque vous transmettez le fragment extends KinematicBody2D au Retriever, l’indice de recherche est capturé comme suit.

KinematicBody2D
Godot 3
Godot 4
migration

À ce moment‑là, dans api_mapping, il se peut que le candidat de migration de KinematicBody2D vers la famille CharacterBody2D de Godot 4 apparaisse.

Dans docs_chunks, il peut y avoir des candidats de documentation officielle concernant CharacterBody2D ou les corps physiques.

Dans label_prototypes, il peut y avoir un exemple de code de déplacement basé sur KinematicBody2D qui passe à CharacterBody2D avec velocity et la méthode move_and_slide().

Le LLM reçoit les informations comme suit.

**Demande de l'utilisateur :**  
Vérifiez si ce projet utilise Godot 3 ou Godot 4 et, si nécessaire, trouvez les bases de la conversion.

**Extrait de code actuel :**  
enemy.gd, ligne G102

extends KinematicBody2D

**Candidats de récupération :**  
- Dans *api_mapping* : candidat de migration `KinematicBody2D` → `CharacterBody2D`  
- Dans *docs_chunks* : candidat de documentation officielle `CharacterBody2D`  
- Dans *label_prototypes* : exemple de conversion du code de déplacement `KinematicBody2D`

Le LLM peut juger ce fragment comme « le signal Godot 3 est fort et une migration est nécessaire ».

Ensuite, les fragments G106‑G107 seront également traités séparément.

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

Dans ce fragment, l’appel move_and_slide(velocity) constitue l’indice de recherche. On ne se contente pas de voir le nom de la fonction, mais on examine également la forme d’appel avec ses arguments.

Dans ce cas, si seul le nom de la fonction change, le candidat api_mapping devient important, et si la forme d’appel entière change, le candidat label_prototypes devient également crucial.

Étape 9 : Accumulation des résultats des fragments

Chaque fragment est évalué individuellement.

Les codes E020‑E034 de player.gd peuvent être accumulés comme des signaux de Godot 4.

Le code G102 de enemy.gd peut être accumulé comme un signal de Godot 3.

Les codes G106‑G107 de enemy.gd peuvent également être accumulés comme des signaux de migration vers Godot 3.

Le jugement global du projet ne se fait pas à partir du nom de fichier. Le chemin du fichier sert uniquement au suivi. Le jugement global du projet résulte de l’accumulation des jugements de chaque fragment de code.

Par exemple, si la plupart des signaux d’un projet indiquent Godot 4 mais que quelques signaux de migration vers Godot 3 apparaissent, le jugement peut être proche de « mixed ». Inversement, si la majorité des signaux indiquent une migration vers Godot 3, le projet peut être classé comme un projet Godot 3.

Interruption et reprise

RunPod ou le serveur web local peuvent s’arrêter en cours de route. Le traitement doit donc pouvoir se poursuivre fragment par fragment plutôt que fichier par fichier.

Par exemple, si les fragments E009, E011, E013‑E014 de player.gd ont été traités et que le processus s’est arrêté à E016‑E018, après redémarrage il faut reprendre à partir de E016‑E018.

Il ne faut pas retraiter les fragments déjà terminés : E009, E011, E013‑E014.

L’interface web doit afficher ce qui suit.

player.gd E009 traitement terminé
player.gd E011 traitement terminé
player.gd E013-E014 traitement terminé
player.gd E016-E018 traitement interrompu
player.gd E020-E034 en attente
player.gd E036-E039 en attente

Il doit être affiché ainsi pour pouvoir vérifier si le traitement existant se poursuit ou s'il recommence depuis le début.

Ce qui doit être affiché dans l'écran de débogage

L'écran de débogage est nécessaire pour le suivi.

Au minimum, les éléments suivants doivent être affichés.

Fichier actuel : player.gd  
Plage de lignes actuelle : E020-E034  
Contenu de l'extrait actuel :
func _process(delta):
	...

Indices de recherche entrés dans le Retriever :
- Input.is_action_pressed
- Vector2.ZERO
- position.clamp

Candidats trouvés :
- docs_chunks: Input.is_action_pressed
- docs_chunks: Vector2.ZERO
- label_prototypes: Godot 4 input polling example

Jugement du LLM :
- Signal Godot 4
- Pas de migration nécessaire

Ce qui est important ici, c’est que « ce qui a été entré dans la recherche » et « ce qui n’est attaché qu’à des fins de suivi » apparaissent séparément.

Le chemin player.gd peut être affiché dans la vue du fichier actuel, mais ne doit pas apparaître dans la liste des indices de recherche du Retriever.

Résumé

Au 27 du mois, le flux fixé dans le document est le suivant.

# <chemin relatif>
<corps>

- Séparer uniquement les limites du fichier avec un en‑tête.
- Le corps du fichier .gd est envoyé à l’AST Parser.
- L’AST Parser découpe les fonctions et les déclarations dans l’ordre.
- Le texte réel de chaque fragment et les indices de symbole sont utilisés pour la recherche Retriever.
- Les éléments docs_chunks, api_mapping, label_prototypes sont recherchés de la même manière.
- Les candidats de recherche et le fragment actuel sont transmis ensemble au LLM.
- Le jugement du LLM est enregistré par fragment et cumulé par projet.

Le but de ce document n’est pas de définir une nouvelle structure, mais de permettre de vérifier à quelle ligne l’entrée réelle est coupée et quel texte passe à l’étape suivante. Lors de l’implémentation, il faut également afficher dans l’interface Web, selon ce critère, le fichier actuel, la plage de lignes actuelle, le texte réellement transmis, l’indice de recherche du récupérateur, les candidats de recherche et le jugement du LLM.