mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-09 09:11:00 +08:00
Imports the CodeAtlasWeb companion frontend verbatim from BernhardJackiewicz/CodeAtlasWeb at commit 1825f9c850ac794066e02606012508b9d393c6aa as the new graph-ui and removes the previous React frontend. This is Bernhard Jackiewicz's work, contributed with his agreement and squashed here from his development history (41 commits, cycles W0 through W15). The maintainer only relocates it: every product decision, line of code and test below graph-ui/ is his. The seven galaxy files that originate in this repository's previous graph-ui, and the pinned 3D libraries, are listed in graph-ui/THIRD_PARTY.md. What it is: a local reading IDE on the CBM read surface. A read-only Monaco source reader, a semantic twin that follows the caret, entry, bug-hunt, change-scope and flow reading modes, deterministic source-cited explanations with an optional local-model wording pass (llama-server sidecar, off unless the reader starts one; no model or binary ships), a persistent galaxy with focus following in both directions, a live-agent overlay fed by a loopback bridge, explicit air-gap, provenance and index-limit messaging, and an offline acceptance and browser verification harness. It consumes POST /rpc (the read-only tool allowlist), GET /api/layout, and the atlas routes /api/tree, /api/trace, /api/flows and /api/flow, plus the real ingest_traces store for observed calls; all of these are on feat/atlas-r1 (#1860), which this change stacks on. Not imported: CLAUDE.md (an agent-instruction file, which stays local-only in this repository), and the recorded proof artifacts under graph-ui/verification/, which follow in a separate commit so they can be reviewed and dropped on their own. Build wiring, the dev-proxy port contract, the CSP allowance for the sidecar and bridge ports, and the control surfaces the previous frontend had (project indexing, ADR editor, logs) follow in separate maintainer commits. Design and tracking: #1964. Co-authored-by: Bernhard Jackiewicz <bj@techport.io> Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
136 lines
4.9 KiB
TypeScript
136 lines
4.9 KiB
TypeScript
/*
|
|
* Die Coverage-Saetze: geprueft wird, was sie NICHT sagen.
|
|
*
|
|
* Ein Satz, der einen Grund erfindet, faellt in einem Beweisbild nicht auf; er
|
|
* liest sich sogar besser. Darum steht hier zu jedem Satz ein Fall ohne Grund
|
|
* daneben, und der Test verlangt, dass die Formulierung dann ohne Grund endet.
|
|
*/
|
|
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
COVERAGE_DESCRIPTIONS,
|
|
COVERAGE_LABELS,
|
|
COVERAGE_MARKS,
|
|
COVERAGE_SOURCE_NOTE,
|
|
coverageTooltip,
|
|
folderTooltip,
|
|
freshnessNote,
|
|
freshnessNoteNeeded,
|
|
partialFileNote,
|
|
readerUnavailableNote,
|
|
} from './coverage-strings';
|
|
import { COVERAGE_ORDER } from './tree-model';
|
|
|
|
describe('die Tabellen decken jede Stufe ab', () => {
|
|
|
|
it('hat zu jeder Stufe ein Wort, ein Zeichen und einen Satz', () => {
|
|
for (const state of COVERAGE_ORDER) {
|
|
expect(COVERAGE_LABELS[state].length).toBeGreaterThan(0);
|
|
expect(COVERAGE_DESCRIPTIONS[state].length).toBeGreaterThan(0);
|
|
expect(typeof COVERAGE_MARKS[state]).toBe('string');
|
|
}
|
|
});
|
|
|
|
it('laesst genau die vollstaendige Stufe ohne Zeichen', () => {
|
|
expect(COVERAGE_MARKS.indexed).toBe('');
|
|
expect(COVERAGE_MARKS.partial).toBe('!');
|
|
});
|
|
});
|
|
|
|
describe('COVERAGE_SOURCE_NOTE', () => {
|
|
|
|
it('benennt die Grenze des Baums und nicht seinen Inhalt', () => {
|
|
expect(COVERAGE_SOURCE_NOTE).toContain('as the index discovery saw them');
|
|
expect(COVERAGE_SOURCE_NOTE).toContain('never met are invisible');
|
|
});
|
|
});
|
|
|
|
describe('coverageTooltip', () => {
|
|
|
|
it('nennt bei partial Zeilenbereiche und keine Symbolzahl', () => {
|
|
const text = coverageTooltip('partial', '12-18,24');
|
|
expect(text).toContain('partially parsed');
|
|
expect(text).toContain('12-18,24');
|
|
// Der Server meldet Bereiche, keine Zahl. Eine Zahl waere gezaehlt,
|
|
// und gezaehlt hat sie niemand.
|
|
expect(text).not.toMatch(/\d+ symbols/);
|
|
});
|
|
|
|
it('endet ohne Grund, wenn der Server keinen genannt hat', () => {
|
|
expect(coverageTooltip('skipped')).toContain('named no reason');
|
|
expect(coverageTooltip('not-indexed')).toContain('named no rule');
|
|
});
|
|
|
|
it('sagt bei einem Grund den Grund des Servers', () => {
|
|
expect(coverageTooltip('skipped', 'unsupported extension'))
|
|
.toContain('unsupported extension');
|
|
expect(coverageTooltip('not-indexed', '.gitignore')).toContain('.gitignore');
|
|
});
|
|
|
|
it('behauptet fuer indexed keine Vollstaendigkeit, nur Befundfreiheit', () => {
|
|
expect(coverageTooltip('indexed')).toContain('no source recorded an issue');
|
|
});
|
|
});
|
|
|
|
describe('folderTooltip', () => {
|
|
|
|
it('spricht ueber den Inhalt und nicht ueber den Ordner selbst', () => {
|
|
expect(folderTooltip('skipped')).toContain('worst stage below this folder');
|
|
expect(folderTooltip('indexed')).toContain('every file below it');
|
|
});
|
|
});
|
|
|
|
describe('readerUnavailableNote', () => {
|
|
|
|
const note = readerUnavailableNote('assets/beleg.png', 'skipped', 'unsupported extension');
|
|
|
|
it('erklaert die Grenze der Server-Flaeche statt einen Fehler zu melden', () => {
|
|
expect(note).toContain('get_code_snippet');
|
|
expect(note).toContain('Upstream-Ask 1');
|
|
expect(note).not.toMatch(/error|failed/i);
|
|
});
|
|
|
|
it('sagt ausdruecklich, dass die Datei existiert', () => {
|
|
expect(note).toContain('is on disk');
|
|
});
|
|
|
|
it('nennt den Grund des Servers, wenn es einen gibt, und sonst keinen', () => {
|
|
expect(note).toContain('unsupported extension');
|
|
expect(readerUnavailableNote('a.bin', 'not-indexed')).toContain('named no rule');
|
|
});
|
|
});
|
|
|
|
describe('partialFileNote', () => {
|
|
|
|
it('qualifiziert den Text, statt ihn zu verdaechtigen', () => {
|
|
const text = partialFileNote('src/broken.ts', '12-18');
|
|
expect(text).toContain('12-18');
|
|
expect(text).toContain('The text below is the file');
|
|
});
|
|
});
|
|
|
|
describe('freshnessNoteNeeded', () => {
|
|
|
|
it('schweigt genau dann, wenn der Server nichts zu melden hat', () => {
|
|
expect(freshnessNoteNeeded('no_recorded_issue', 'metadata_match')).toBe(false);
|
|
});
|
|
|
|
it('meldet eine geaenderte Datei und einen aufgezeichneten Befund', () => {
|
|
expect(freshnessNoteNeeded('no_recorded_issue', 'metadata_changed')).toBe(true);
|
|
expect(freshnessNoteNeeded('partial', 'metadata_match')).toBe(true);
|
|
expect(freshnessNoteNeeded('coverage_unavailable', 'unavailable')).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('freshnessNote', () => {
|
|
|
|
it('nennt Frische, Befund und Empfehlung in dieser Reihenfolge', () => {
|
|
expect(freshnessNote('partial', 'metadata_changed', 'read_source_and_reindex'))
|
|
.toBe('metadata_changed / partial / read_source_and_reindex');
|
|
});
|
|
|
|
it('laesst weg, was der Server nicht geschrieben hat', () => {
|
|
expect(freshnessNote('', 'metadata_changed', '')).toBe('metadata_changed');
|
|
expect(freshnessNote('', '', '')).toBe('unknown');
|
|
});
|
|
});
|