@imenam/mcp-feature-analyzer 1.0.4 → 1.0.5
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/README.md +18 -4
- package/dist/shared/explanation-request.d.ts +9 -0
- package/dist/shared/explanation-request.js +55 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/gui/dist/assets/index-BKGeP-g-.js +74 -0
- package/gui/dist/assets/{index-CmSZOGwc.css → index-CtYu4TyO.css} +1 -1
- package/gui/dist/index.html +2 -2
- package/package.json +1 -1
- package/gui/dist/assets/index-BLyQW-EW.js +0 -72
package/README.md
CHANGED
|
@@ -163,6 +163,18 @@ L'**état de revue** est dérivé des fichiers revus et de la soumission (`share
|
|
|
163
163
|
|
|
164
164
|
Un `issue` a toujours un emplacement ; un `requirement_gap` peut ne pas en avoir. Une `suggestion` n'est jamais appliquée : la GUI l'affiche (lignes actuelles barrées, lignes proposées) et le prompt la transmet.
|
|
165
165
|
|
|
166
|
+
### Explications
|
|
167
|
+
|
|
168
|
+
Une explication décrit ce que fait un bloc de code ajouté ou supprimé, et comment il le fait. Elle aide le relecteur à comprendre le code avant de le juger : ce n'est pas un constat, elle ne demande rien et n'entre pas dans le retour de revue. Les instructions du serveur demandent à l'agent d'en écrire une pour chaque bloc long (une trentaine de lignes ou plus) ou complexe (algorithme, machine à états, concurrence, expression régulière délicate…), et jamais pour du code trivial.
|
|
169
|
+
|
|
170
|
+
| Outil | Effet |
|
|
171
|
+
|---|---|
|
|
172
|
+
| `add_explanations` | Ajoute un lot d'explications : titre, corps, `path` + `start_line` (+ `end_line`) et `side`. `side: "new"` (par défaut) vise du code ajouté ou conservé, en numéros du côté nouveau ; `side: "old"` vise du code supprimé, en numéros du côté ancien (première colonne de `get_diff`), lignes toutes présentes dans le diff et dont au moins une est supprimée. Les lignes décrites sont copiées du diff figé. Une seule explication invalide et **rien n'est ajouté**. |
|
|
173
|
+
| `update_explanation` | Modifie le titre, le corps ou l'emplacement d'une explication. Un nouvel emplacement est vérifié contre le diff et rend son statut « à jour » à une explication obsolète. |
|
|
174
|
+
| `delete_explanations` | Supprime des explications par identifiant. Un identifiant inconnu fait échouer l'appel sans rien supprimer. |
|
|
175
|
+
|
|
176
|
+
`refresh_analysis` traite les explications comme les constats : une explication dont les lignes ne correspondent plus au texte copié passe à « obsolète », et redevient à jour si elles correspondent de nouveau.
|
|
177
|
+
|
|
166
178
|
### Schémas
|
|
167
179
|
|
|
168
180
|
| Outil | Effet |
|
|
@@ -205,6 +217,7 @@ create_analysis { repo_path: "C:/dev/mon-projet", project: "mon-projet", title:
|
|
|
205
217
|
get_diff { analysis_id } ← numéros de ligne du côté nouveau
|
|
206
218
|
update_analysis { analysis_id, objective: "…", approach: "…", attention_points: ["…"],
|
|
207
219
|
summary: ["…", "…"] } ← vue d'ensemble et changements fonctionnels
|
|
220
|
+
add_explanations { analysis_id, explanations: [...] } ← blocs longs ou complexes, ajoutés ou supprimés
|
|
208
221
|
add_findings { analysis_id, findings: [...] } ← y compris les requirement_gap
|
|
209
222
|
set_diagram { analysis_id, kind: "flow", nodes: [...], links: [...] }
|
|
210
223
|
|
|
@@ -242,14 +255,14 @@ L'ajustement à la fenêtre ne descend jamais sous l'échelle **0,85** : en dess
|
|
|
242
255
|
|
|
243
256
|
- **Panneau des fichiers** — progression, fichiers groupés par dossier, état revu, pastilles des constats ouverts par gravité. Un nom trop long est tronqué au milieu (`reminder-sch…uler.ts`), l'extension reste visible et le chemin complet est en infobulle. Chaque pastille est un lien : elle ouvre le fichier sur son premier constat ouvert de cette gravité (`?line=N`) ; son infobulle le dit (« 3 constats mineurs ouverts — aller au premier »).
|
|
244
257
|
- **En-tête du fichier** — chemin, `+`/`−`, statut, fichier précédent et suivant, « Remarque sur le fichier », « Marquer comme revu ».
|
|
245
|
-
- **Diff** — numéros du côté nouveau et repère vertical à la couleur de la gravité le long des lignes visées par un constat. Le correctif proposé s'affiche à l'endroit où il s'applique : bandeau « Correctif proposé par l'agent — remplace les lignes X à Y » avec le numéro du constat et « Masquer le correctif », lignes visées barrées sur fond ambre, lignes proposées juste en dessous sur fond violet (marque « › », sans numéro). Le correctif est affiché d'office pour un constat ouvert ; masqué, ou pour un constat sans correctif, une pastille numérotée marque la première ligne visée. Deux correctifs dont les lignes se recouvrent ne s'affichent pas ensemble. Le fond ambre des lignes visées se distingue du rouge des lignes `−` supprimées par la feature. Une légende suit le diff, limitée aux fonds que le mode affiche : « Ajouté par la feature », « Supprimé par la feature », « Lignes remplacées par le correctif » (Avant / après), « Correctif proposé » ou « Correctif appliqué ». Un clic sur un numéro de ligne ouvre la saisie d'une remarque sur cette ligne. Les exigences manquantes sans emplacement s'affichent en bandeau au-dessus du diff de chaque fichier ; le bandeau « N exigences manquantes » se replie, et reste replié pour la session.
|
|
258
|
+
- **Diff** — numéros du côté nouveau et repère vertical à la couleur de la gravité le long des lignes visées par un constat. Le correctif proposé s'affiche à l'endroit où il s'applique : bandeau « Correctif proposé par l'agent — remplace les lignes X à Y » avec le numéro du constat et « Masquer le correctif », lignes visées barrées sur fond ambre, lignes proposées juste en dessous sur fond violet (marque « › », sans numéro). Le correctif est affiché d'office pour un constat ouvert ; masqué, ou pour un constat sans correctif, une pastille numérotée marque la première ligne visée. Un filet sarcelle longe les lignes décrites par une explication. L'en-tête de chaque bloc du diff porte « Copier une demande d'explication » : le bouton copie un prompt à coller dans la conversation de l'agent, qui situe le bloc (analyse, dépôt et refs, fichier, lignes des deux côtés, code tel que figé) et lui demande de l'expliquer en enregistrant ses explications avec `add_explanations`, ou `update_explanation` si une explication couvre déjà ces lignes. Deux correctifs dont les lignes se recouvrent ne s'affichent pas ensemble. Le fond ambre des lignes visées se distingue du rouge des lignes `−` supprimées par la feature. Une légende suit le diff, limitée aux fonds que le mode affiche : « Ajouté par la feature », « Supprimé par la feature », « Lignes remplacées par le correctif » (Avant / après), « Correctif proposé » ou « Correctif appliqué », « Code décrit par une explication ». Un clic sur un numéro de ligne ouvre la saisie d'une remarque sur cette ligne. Les exigences manquantes sans emplacement s'affichent en bandeau au-dessus du diff de chaque fichier ; le bandeau « N exigences manquantes » se replie, et reste replié pour la session.
|
|
246
259
|
- **Affichage des correctifs** — le sélecteur « Correctifs », au-dessus du diff, propose trois modes, conservés d'un fichier à l'autre pendant la session :
|
|
247
260
|
- « Sans correctif » : le diff seul, sans aucun correctif ; les interrupteurs des cartes sont inactifs.
|
|
248
261
|
- « Avant / après » (par défaut) : le rendu décrit ci-dessus, lignes visées barrées puis lignes proposées.
|
|
249
262
|
- « Code corrigé » : le code tel qu'il se lirait avec les correctifs appliqués. Les lignes visées disparaissent ; les lignes proposées prennent leur place, sur fond violet avec la marque « › » et sans numéro, sous un bandeau « Correctif N appliqué — remplace les lignes X à Y ». Un lien `?line=N` vers une ligne retirée met ce bandeau en évidence ; les remarques ne se posent que sur les lignes du diff, pas sur les lignes proposées.
|
|
250
263
|
|
|
251
264
|
Dans les deux derniers modes, l'interrupteur de chaque carte (« Afficher le correctif dans le code » ou « Appliquer le correctif dans le code ») choisit les correctifs dessinés.
|
|
252
|
-
- **Colonne « Constats
|
|
265
|
+
- **Colonne « Constats et explications »** — l'en-tête compte les constats ouverts, et le total quand il diffère (« 4 constats ouverts · 5 au total »). Deux boutons, « Constats » et « Explications », affichent ou masquent chacun leur type, indépendamment l'un de l'autre et pour tous les fichiers de la session ; chacun indique le nombre d'éléments du fichier. Masquer les constats retire aussi leurs repères, pastilles et correctifs du diff et le bandeau des exigences manquantes : on parcourt alors le code avec ses seules explications, avant de rétablir les constats. Masquer les explications retire leurs cartes et leurs filets. Dessous, un index compact des constats (numéro à la couleur de la gravité et première ligne, ignorés et obsolètes atténués) : un clic fait défiler jusqu'aux lignes et à la carte, mises en évidence comme avec `?line`. Tant que des cartes de constat sont sous la partie visible, une indication collée en bas de la colonne les compte (« 3 constats plus bas ↓ ») ; un clic amène la suivante. Les constats, numérotés dans l'ordre de leur première ligne, sont des cartes alignées sur leur ligne et reliées au diff ; des cartes voisines s'empilent sans se chevaucher et défilent avec le diff. Chaque carte montre numéro, gravité, lignes, titre, explication, l'interrupteur « Afficher le correctif dans le code » (constat avec correctif) et les boutons « Copier le prompt », « Ignorer » / « Rouvrir », « Remarque ». Les constats ignorés ou obsolètes restent visibles, atténués. Les explications sont des cartes sarcelle alignées de la même façon sur la première ligne qu'elles décrivent, une ligne supprimée pour du code supprimé ; à hauteur égale, l'explication précède les constats. Chaque carte montre les lignes (côté ancien et mention « Code supprimé » pour du code supprimé), le titre et le texte, replié au-delà de huit lignes avec « Lire la suite ». Une explication obsolète est atténuée et signale que le code décrit a changé. Les remarques de ligne sont des cartes alignées de la même façon, datées au format court (date complète en infobulle), avec « Modifier », qui rouvre le texte sur place dans la même saisie que la création, et « Supprimer » ; modifier une remarque retenue dans une revue déjà soumise recalcule le prompt enregistré ; les remarques sur le fichier entier et ce qui vise des lignes hors du diff affiché sont en tête de colonne. Sous 1200 px de large, la colonne passe sous le diff et ses cartes s'empilent.
|
|
253
266
|
|
|
254
267
|
Un fichier binaire, supprimé ou de plus de 1 Mo n'a pas de contenu conservé : on ne peut pas y ancrer de constat ni de remarque de ligne, seulement une remarque sur le fichier entier.
|
|
255
268
|
|
|
@@ -274,15 +287,16 @@ Le worker ne lit ni n'écrit aucune donnée : chaque requête REST est transmise
|
|
|
274
287
|
|
|
275
288
|
### Persistance
|
|
276
289
|
|
|
277
|
-
Un fichier JSON par analyse dans `<données>/analyses/<id>.json`, et son diff figé dans `<données>/diffs/<id>.json`. Les écritures sont atomiques (fichier temporaire puis `rename`), sérialisées entre processus par un verrou `.lock`, et le cache mémoire est invalidé dès que la date ou la taille du fichier change. Tout document est validé par zod à la lecture et à l'écriture ; `src/core/migrate.ts` met à niveau les anciens formats à la lecture : une analyse sans projet reçoit le nom du dossier du dépôt (`basename(repoPath)`), une analyse sans vue d'ensemble reçoit `overview: null
|
|
290
|
+
Un fichier JSON par analyse dans `<données>/analyses/<id>.json`, et son diff figé dans `<données>/diffs/<id>.json`. Les écritures sont atomiques (fichier temporaire puis `rename`), sérialisées entre processus par un verrou `.lock`, et le cache mémoire est invalidé dès que la date ou la taille du fichier change. Tout document est validé par zod à la lecture et à l'écriture ; `src/core/migrate.ts` met à niveau les anciens formats à la lecture : une analyse sans projet reçoit le nom du dossier du dépôt (`basename(repoPath)`), une analyse sans vue d'ensemble reçoit `overview: null`, une analyse sans explications reçoit une liste vide.
|
|
278
291
|
|
|
279
292
|
### Invariants
|
|
280
293
|
|
|
281
294
|
Toute modification, qu'elle vienne d'un outil ou de la GUI, passe par `AnalysisStore.mutate(id, editor, fn, { baseRevision })`, qui vérifie le schéma et les invariants avant d'écrire et incrémente la révision :
|
|
282
295
|
|
|
283
296
|
- refs cohérentes avec le mode (`branch` : ref et commit de tête ; `working_tree` : base `HEAD`, sans tête) ;
|
|
284
|
-
- identifiants uniques (fichiers, constats, remarques, schémas, nœuds d'un schéma) ;
|
|
297
|
+
- identifiants uniques (fichiers, constats, explications, remarques, schémas, nœuds d'un schéma) ;
|
|
285
298
|
- un constat ouvert vise un fichier de l'analyse dont le contenu est conservé, avec `1 ≤ startLine ≤ endLine ≤` nombre de lignes ; un `issue` a un emplacement ;
|
|
299
|
+
- une explication à jour vise un fichier de l'analyse ; côté nouveau, son contenu est conservé et ses lignes existent ;
|
|
286
300
|
- les liens d'un schéma relient des nœuds existants ; en `layers`, chaque nœud est dans une couche déclarée ;
|
|
287
301
|
- la revue ne sélectionne que des constats et des remarques existants ;
|
|
288
302
|
- les champs issus du diff (dépôt, refs, commits, liste des fichiers hors « revu ») ne changent que par `refresh_analysis`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Analysis, FileEntry } from "./schemas/analysis.schema.js";
|
|
2
|
+
import type { Hunk } from "./schemas/diff.schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Prompt qui demande à l'agent d'expliquer un bloc du diff et d'enregistrer ses
|
|
5
|
+
* explications dans l'analyse : analyse, dépôt et refs, fichier, plages de lignes
|
|
6
|
+
* des deux côtés, code du bloc tel que figé, puis la marche à suivre
|
|
7
|
+
* (add_explanations, ou update_explanation pour une explication existante).
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildExplanationRequestPrompt(analysis: Analysis, file: FileEntry, hunk: Hunk): string;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { lineRange } from "./text.js";
|
|
2
|
+
const MARKERS = { context: " ", add: "+", del: "-" };
|
|
3
|
+
function refsLabel(analysis) {
|
|
4
|
+
if (analysis.mode === "branch")
|
|
5
|
+
return `branch ${analysis.base}...${analysis.head}`;
|
|
6
|
+
return "working tree changes against HEAD";
|
|
7
|
+
}
|
|
8
|
+
/** Plage `début-fin` d'un côté du bloc, ou null quand ce côté n'a aucune ligne. */
|
|
9
|
+
function sideRange(start, count) {
|
|
10
|
+
return count === 0 ? null : lineRange(start, start + count - 1);
|
|
11
|
+
}
|
|
12
|
+
/** Lignes du bloc au format de get_diff : `ancien | nouveau`, puis le marqueur et le texte. */
|
|
13
|
+
function hunkCode(hunk) {
|
|
14
|
+
let width = 1;
|
|
15
|
+
for (const line of hunk.lines) {
|
|
16
|
+
width = Math.max(width, String(line.oldNo ?? "").length, String(line.newNo ?? "").length);
|
|
17
|
+
}
|
|
18
|
+
const column = (value) => String(value ?? "").padStart(width);
|
|
19
|
+
return [hunk.header, ...hunk.lines.map((line) => `${column(line.oldNo)} | ${column(line.newNo)} ${MARKERS[line.type]} ${line.text}`)];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Prompt qui demande à l'agent d'expliquer un bloc du diff et d'enregistrer ses
|
|
23
|
+
* explications dans l'analyse : analyse, dépôt et refs, fichier, plages de lignes
|
|
24
|
+
* des deux côtés, code du bloc tel que figé, puis la marche à suivre
|
|
25
|
+
* (add_explanations, ou update_explanation pour une explication existante).
|
|
26
|
+
*/
|
|
27
|
+
export function buildExplanationRequestPrompt(analysis, file, hunk) {
|
|
28
|
+
const newRange = sideRange(hunk.newStart, hunk.newLines);
|
|
29
|
+
const oldRange = sideRange(hunk.oldStart, hunk.oldLines);
|
|
30
|
+
const where = [
|
|
31
|
+
`- File: ${file.path}${file.oldPath !== null ? ` (renamed from ${file.oldPath})` : ""}`,
|
|
32
|
+
newRange === null ? "- New side: no line (the section only removes code)." : `- New side (code after the feature): lines ${newRange}`,
|
|
33
|
+
oldRange === null ? "- Old side: no line (the section only adds code)." : `- Old side (code before the feature): lines ${oldRange}`,
|
|
34
|
+
];
|
|
35
|
+
return [
|
|
36
|
+
`Explain a section of code in the feature analysis "${analysis.title}" (analysis_id: "${analysis.id}", project "${analysis.project}").`,
|
|
37
|
+
`Repository: ${analysis.repoPath} — ${refsLabel(analysis)}.`,
|
|
38
|
+
"",
|
|
39
|
+
"Section to explain:",
|
|
40
|
+
...where,
|
|
41
|
+
"",
|
|
42
|
+
"Code of the section, as frozen in the analysis (columns: old line | new line, then + added, - removed, or a space for context):",
|
|
43
|
+
"```",
|
|
44
|
+
...hunkCode(hunk),
|
|
45
|
+
"```",
|
|
46
|
+
"",
|
|
47
|
+
"What to do:",
|
|
48
|
+
`1. Read this code and what surrounds it (get_diff with analysis_id "${analysis.id}" and path "${file.path}", and the repository) until you understand what it does and how it works.`,
|
|
49
|
+
`2. Record your explanations in the feature analyzer with add_explanations (analysis_id "${analysis.id}", path "${file.path}"): one explanation per meaningful block of the section, covering it from its first to its last line. ` +
|
|
50
|
+
`Use "side": "new" with new-side line numbers for added or kept code, and "side": "old" with old-side line numbers for removed code.`,
|
|
51
|
+
"3. In each explanation, say what the code does (inputs, outputs, effects), then how it works, step by step in the order of the code; name the key variables and the edge cases it handles. For removed code, say what it did and what replaces it. Describe, do not judge.",
|
|
52
|
+
"4. If an explanation of the analysis already covers these lines (see get_analysis), rewrite it with update_explanation instead of adding a duplicate.",
|
|
53
|
+
"5. Then tell me in a few lines which explanations you recorded.",
|
|
54
|
+
].join("\n");
|
|
55
|
+
}
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const APP_VERSION = "1.0.
|
|
1
|
+
export declare const APP_VERSION = "1.0.5";
|
package/dist/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated version file - do not edit manually
|
|
2
|
-
export const APP_VERSION = '1.0.
|
|
2
|
+
export const APP_VERSION = '1.0.5';
|