mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
fix(ui): name the branch node in view answers and a folder by its path
The answer about the current view listed the branch node by its bare "DETACHED", and the card of a folder said "Selected: .github (Folder) in .github". Both now use the names the Galaxy shows. Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
This commit is contained in:
1 parent
ab4d61d63b
commit
ff3e88b238
5 files changed
+34
-10
No files matched your search
@@ -16,7 +16,7 @@ describe('questions about the current view are answered from the loaded scope (H
|
||||
await dock.ask(question);
|
||||
const answer = dock.answerOf(dock.last()).replace(/\s+/g, ' ');
|
||||
expect(answer).toContain('.github (Ordner) steht in der Mitte; der Ausschnitt geht 1 Schritt in beide Richtungen.');
|
||||
expect(answer).toContain('Links, eingehend: CONTAINS_FOLDER (1): DETACHED');
|
||||
expect(answer).toContain('Links, eingehend: CONTAINS_FOLDER (1): django-demo · losgelöster HEAD');
|
||||
expect(answer).toContain('Rechts, ausgehend: CONTAINS_FILE (4): CODE_OF_CONDUCT.md, FUNDING.yml, pull_request_template.md, SECURITY.md CONTAINS_FOLDER (1): workflows');
|
||||
expect(answer).toContain('So liest du die Hierarchie: eingehende Beziehungen stehen links, ausgehende rechts.');
|
||||
expect(answer).toContain('Aus dem indizierten Graphen gelistet, nicht vom Modell erzeugt.');
|
||||
@@ -57,7 +57,7 @@ describe('a model answer that only restates the question is not shown as an answ
|
||||
expect(runtime.chat).toHaveBeenCalledOnce();
|
||||
const answer = dock.answerOf(dock.last());
|
||||
expect(answer).toContain('Das Modell hat keine Antwort gegeben, es hat nur die Frage wiederholt („Ich kann dir die Ordner erklären.“).');
|
||||
expect(answer).toContain('Ausgewählt: .github (Ordner) in .github.');
|
||||
expect(answer).toContain('Ausgewählt: .github (Ordner).');
|
||||
expect(answer).toContain('Ausgehend: 5 Beziehungen zu 5 Symbolen (CONTAINS_FILE 4, CONTAINS_FOLDER 1).');
|
||||
expect(answer).toContain('Aus dem indizierten Graphen gelistet, nicht vom Modell erzeugt.');
|
||||
expect(dock.notesOf(dock.last())).toEqual([]);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { readGalaxyEvidence, selectionSentence } from './galaxy-evidence';
|
||||
import { githubFolderEvidence } from './galaxy-evidence.fixture';
|
||||
import { relationshipWords } from './strings';
|
||||
|
||||
/*
|
||||
* Handtest 04.10. (17:09): Die Karte zu .github sagte "Selected: .github (Folder)
|
||||
* in .github." Bei einem Ordner oder einer Datei ist der Pfad das, was gewaehlt
|
||||
* ist, kein Ort, an dem es steht; "in .github" wiederholte nur den Namen.
|
||||
*/
|
||||
describe('the selection sentence of a folder or a file', () => {
|
||||
it('names a folder without repeating its own path as its place', () => {
|
||||
const evidence = readGalaxyEvidence(githubFolderEvidence('hierarchy').text)!;
|
||||
expect(selectionSentence(evidence, relationshipWords.en)[0]).toBe('Selected: .github (Folder).');
|
||||
expect(selectionSentence(evidence, relationshipWords.de)[0]).toBe('Ausgewählt: .github (Ordner).');
|
||||
});
|
||||
});
|
||||
@@ -183,12 +183,16 @@ export function selectionName(evidence: GalaxyEvidence, words: RelationshipWords
|
||||
/** What is selected, in the words of the prompt (English) or of a question (C5). */
|
||||
export function selectionSentence(evidence: GalaxyEvidence, words: RelationshipWords): string[] {
|
||||
const [first] = evidence.roots;
|
||||
const range = (root: GalaxyEvidence['roots'][number]) => root.filePath
|
||||
// A folder or a file is its path; "Selected: .github (Folder) in .github." only repeated the name (K47).
|
||||
const isPath = (root: GalaxyEvidence['roots'][number]) => /^(?:folder|file|directory)$/i.test(root.kind ?? '')
|
||||
&& Boolean(root.filePath) && (root.filePath === root.name || root.filePath!.endsWith(`/${root.name}`));
|
||||
const shown = (root: GalaxyEvidence['roots'][number]) => isPath(root) ? root.filePath! : rootName(root, words);
|
||||
const range = (root: GalaxyEvidence['roots'][number]) => root.filePath && !isPath(root)
|
||||
? ` in ${root.filePath}${root.startLine ? `:${root.startLine}${root.endLine && root.endLine !== root.startLine ? `-${root.endLine}` : ''}` : ''}` : '';
|
||||
// Kinds in the words of the answer: "(Klasse)" in a German one (W8).
|
||||
const kind = (root: GalaxyEvidence['roots'][number]) => root.kind ? ` (${words.kindName(root.kind)})` : '';
|
||||
if (evidence.rootCount <= 1 && first) {
|
||||
return [words.selected(`${rootName(first, words)}${kind(first)}${range(first)}`),
|
||||
return [words.selected(`${shown(first)}${kind(first)}${range(first)}`),
|
||||
...first.documentation ? [words.documentation(first.documentation)] : []];
|
||||
}
|
||||
if (!first) return [words.notInScope(selectionName(evidence, words), words.kindName(evidence.selectionKind))];
|
||||
|
||||
@@ -43,7 +43,8 @@ describe('the listed answer about the current view (H1)', () => {
|
||||
const answer = viewAnswer(evidence('hierarchy'), 'de');
|
||||
expect(answer.split('\n\n')).toEqual([
|
||||
'`.github` (Ordner) steht in der Mitte; der Ausschnitt geht 1 Schritt in beide Richtungen.',
|
||||
'Links, eingehend:\n- **CONTAINS_FOLDER (1):** `DETACHED`',
|
||||
// The branch node is named as the Galaxy names it, not by its bare "DETACHED" (K47).
|
||||
'Links, eingehend:\n- **CONTAINS_FOLDER (1):** `django-demo · losgelöster HEAD`',
|
||||
'Rechts, ausgehend:\n- **CONTAINS_FILE (4):** `CODE_OF_CONDUCT.md`, `FUNDING.yml`, `pull_request_template.md`, `SECURITY.md`\n- **CONTAINS_FOLDER (1):** `workflows`',
|
||||
'So liest du die Hierarchie: eingehende Beziehungen stehen links, ausgehende rechts.',
|
||||
'7 Symbole und 6 Beziehungen, alle Beziehungstypen; vollständig geladen.',
|
||||
@@ -55,7 +56,7 @@ describe('the listed answer about the current view (H1)', () => {
|
||||
const answer = viewAnswer(evidence('galaxy'), 'en');
|
||||
expect(answer.split('\n\n')).toEqual([
|
||||
'`.github` (Folder) is in the middle; the scope reaches 1 hop in both directions.',
|
||||
'Incoming:\n- **CONTAINS_FOLDER (1):** `DETACHED`',
|
||||
'Incoming:\n- **CONTAINS_FOLDER (1):** `django-demo · detached HEAD`',
|
||||
'Outgoing:\n- **CONTAINS_FILE (4):** `CODE_OF_CONDUCT.md`, `FUNDING.yml`, `pull_request_template.md`, `SECURITY.md`\n- **CONTAINS_FOLDER (1):** `workflows`',
|
||||
'The galaxy view shows this scope as a cloud. "hierarchy" at the top right lays the same scope out in columns: incoming on the left, outgoing on the right.',
|
||||
'7 symbols and 6 relationships, all relationship types; fully loaded.',
|
||||
@@ -84,7 +85,7 @@ describe('the listed answer about the current view (H1)', () => {
|
||||
|
||||
it('says nothing about left, right or a cloud when the evidence does not say which view is shown', () => {
|
||||
const answer = viewAnswer(evidence(), 'en');
|
||||
expect(answer).toContain('Incoming:\n- **CONTAINS_FOLDER (1):** `DETACHED`');
|
||||
expect(answer).toContain('Incoming:\n- **CONTAINS_FOLDER (1):** `django-demo · detached HEAD`');
|
||||
expect(answer).not.toMatch(/left|right|cloud/);
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import { nodeDisplayName } from '../galaxy/node-names';
|
||||
import type { RelationshipGroup } from '../galaxy/selection-evidence';
|
||||
import { scopeParts, sideLoaded, type GalaxyEvidence } from './galaxy-evidence';
|
||||
import { scopeParts, selectionName, sideLoaded, type GalaxyEvidence } from './galaxy-evidence';
|
||||
import { relationshipWords, viewText, type RelationshipWords } from './strings';
|
||||
|
||||
/** The answer to a question about the current Galaxy view, listed from the loaded scope (H1).
|
||||
@@ -16,7 +17,8 @@ const quote = (value: string) => `\`${value.replace(/`/g, "'")}\``;
|
||||
|
||||
/** "- **CONTAINS_FILE (4):** `CODE_OF_CONDUCT.md`, `FUNDING.yml`; +2 more". */
|
||||
function typeLine(group: RelationshipGroup, words: RelationshipWords): string {
|
||||
const shown = group.files.flatMap(file => file.symbols.map(symbol => symbol.name)).slice(0, NAMES_PER_TYPE);
|
||||
// Named as the Galaxy names them: the branch node as "django-demo · detached HEAD", not "DETACHED" (K47).
|
||||
const shown = group.files.flatMap(file => file.symbols.map(symbol => nodeDisplayName(symbol, words.nodeNames))).slice(0, NAMES_PER_TYPE);
|
||||
const rest = group.count - shown.length;
|
||||
const names = shown.length ? `${shown.map(quote).join(', ')}${rest > 0 ? `; ${words.more(rest)}` : ''}` : words.more(group.count);
|
||||
return `- **${words.typeCount(group.type, group.count)}:** ${names}`;
|
||||
@@ -28,7 +30,7 @@ export function viewAnswer(evidence: GalaxyEvidence, language: 'en' | 'de'): str
|
||||
const hierarchy = evidence.display === 'hierarchy';
|
||||
const [first] = evidence.roots;
|
||||
const single = evidence.rootCount <= 1 && first !== undefined;
|
||||
const center = text.center(quote(single ? first.name : evidence.label), words.kindName((single ? first.kind : undefined) ?? evidence.selectionKind), single ? 1 : evidence.rootCount);
|
||||
const center = text.center(quote(single ? nodeDisplayName(first, words.nodeNames) : selectionName(evidence, words)), words.kindName((single ? first.kind : undefined) ?? evidence.selectionKind), single ? 1 : evidence.rootCount);
|
||||
const { direction, types, state } = scopeParts(evidence, words);
|
||||
const reach = evidence.depth === 0 ? text.selectionOnly : text.reach(words.hops(evidence.depth), direction, evidence.direction === 'both');
|
||||
const side = (name: 'incoming' | 'outgoing'): string => {
|
||||
|
||||
Reference in new issue
Block a user