Reproduce every point from the 2 October review call in a real browser against a Django 5.2.7 index and this repository as control, and record the plan with measured causes, priorities and open decisions. The capture script splits each interaction into numbered screenshots with a visible cursor ring and records canvas identity, camera and the prompt sent to the browser model, so resets, zoom direction and chat evidence are measurable rather than described. Only 17 downscaled images are committed; the full series stays local. Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
CodeAtlasWeb
In this repository
This directory is the frontend that codebase-memory-mcp --ui=true serves.
It came in as CodeAtlasWeb by Bernhard Jackiewicz (design and tracking in
issue #1964); the text below this section is his README, kept as written.
What the maintainers added on top:
-
Config at the right of the top bar groups daemon overrides, immediate browser preferences, and external configuration references. Saves validate the whole batch, detect concurrent changes, and show restart requirements. See configuration and precedence.
-
Focused exploration. Galaxy is the search surface for nodes, files and folder groups. Select a scope, then expand incoming/outgoing relationships one layer at a time, restricted to the chosen edge types. Natural clusters reflect connectivity, not inferred architectural components; existing nodes stay in place when another layer arrives. Return to the repository map at any time. Node and edge budgets control the overview. Explorer requests the current file or marked symbols' direct neighbors separately from the capped global layout. Verified neighborhoods and layout positions are reused in bounded session caches. Fresh index generations invalidate graph evidence; a capped layout never counts as a complete neighborhood. Expanding fetches missing adjacency.
-
Compact evidence. Explorer shows a file-level impact summary from the graph and local Git, with affected files on demand. Hotspots group findings by source area. Architecture keeps its spatial view without a duplicate report underneath. Moving arrows indicate edge direction, not runtime execution; reduced-motion preferences keep direction markers stationary.
-
Build and embed.
make -f Makefile.cbm cbm-with-uirunsnpm ci(withPLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1) andnpm run buildhere, then embedsdist/into the binary. The dev server (npm run dev) listens on 5173 and proxies/rpcand/apito a server on 9749, which is the contracttests/test_ui_dev_proxy_security.shpins. -
CSP. The served page may reach the server itself plus the loopback service explicitly allowed for optional local inference (
src/ui/http_server.h,CBM_UI_CSP_VALUE). Nothing else, and a test holds that. -
Add project index (project dropdown or alt+p,
src/projects/): choose a repository with the daemon's local folder picker, name its index, follow indexing status, then open it. Files are indexed in place, not uploaded. The dialog can close while indexing continues; reopen its activity in the project dropdown. Status comes from the daemon, without invented percentages. This replaces the broad project-management dialog; coverage details stay in Coverage and daemon activity stays in System. -
The ADR workspace (
?workspace=adr,src/adr/): read, create, and explicitly save one Markdown decision document per project. Its sections can hold multiple decisions. This uses the existingGET/POST /api/adrstore shared withmanage_adr; it does not edit repository files. Unpublished drafts are retained per project in this browser tab's session storage. Before saving, the UI compares the current server document with the editing baseline and retains the draft if it detects a change. The existing API has no atomic version check, so this is not a document lock. The editor limits new saves to 8,000 UTF-8 bytes for compatibility with MCP section updates, and checks the 16 KiB serialized request limit. Editable preview examples live infixtures/adr/; they are never automatically inserted into real projects or used as inferred graph facts. -
The frontend log (
src/app/ui-log.ts, installed insrc/main.tsx): the console keeps printing, and a copy of every console line, uncaught error, unhandled rejection and failed/rpcor/apicall is batched toPOST /api/ui-log, which the server appends as JSON lines to<cache_dir>/logs/ui.log(rotating once at 5 MiB).GET /api/ui-logtails it for diagnostics, and a bug report can attach the file. The caught request failures reach the log throughsrc/provider/error-observer.ts, the seam the two clients announce on before they throw. -
Gates in CI (
.github/workflows/_test.yml, jobtest-ui, which runsscripts/ci/test-ui.sh; run that script locally for the identical leg):npm run test:unit,npm run check:style,npm run check:promises,npm run test:acceptanceandnpm run build.test:acceptanceis every frozen check except the two release-binding files (release-current,release-proof-binding), which tie the recorded release report to the commits of the original repository and cannot pass here. The browser proofs (npm run smoke:*) need a running server and Playwright browsers and stay a local venue; run them by hand withnpx playwright install chromiumfirst.
Eine lokale Lese-IDE fuer ein indiziertes Repository: Baum, Editor,
Galaxie, Erklaerungen. Sie laeuft im Browser, sie hat kein eigenes Backend, und
sie ist per Vorgabe abgeschottet. Der genehmigte Plan steht in PLAN.md, die
Projektregeln in CLAUDE.md, der aufgenommene Fremdcode in THIRD_PARTY.md.
Was hier laeuft
npm run build # tsc + vite, Ergebnis in dist/
npm run test:unit # vitest
node --test tests/scaffold/ # die eingefrorenen Abnahmetests
npm run check:style # lange Striche, Attribution, hartkodierte Texte
npm run check:promises # Saetze, die etwas zusagen, und Flaechen ohne Wirkung
Die Beweislaeufe je Zyklus heissen npm run smoke:<zyklus> und schreiben ihr
Ergebnis nach verification/. Jeder von ihnen laeuft unter einem
Netz-Deny-Gate; was dabei an Verbindungen hinausging, steht als
outboundViolations im Artefakt.
Der Analyse-Server (cbm/) wird getrennt gebaut und indiziert die Repositories.
Diese Oberflaeche indiziert nichts selbst: sie liest /api und /rpc.
Die Vorschau: nach jedem Bau neu starten
Eine Vorschau-Instanz besteht aus zwei Prozessen: dem C-Server auf einem
eigenen Port und einem kleinen Auslieferer, der dist/ bedient und /api sowie
/rpc an den Server weiterreicht (tools/lib/static-proxy.mjs).
Der Auslieferer KOPIERT dist/ beim Start. Er tut das mit Absicht: sonst
liefe ein npm run build mitten in eine offene Seite hinein und ersetzte
Dateien, waehrend der Browser sie laedt. Die Folge ist aber, dass er spaetere
Bauten nie sieht. Wer baut und dann die alte Vorschau neu laedt, sieht den
Stand von vorhin, und nichts an der Oberflaeche sagt das.
Also gilt, ohne Ausnahme:
npm run build- die laufende Vorschau beenden (SIGTERM an ihren Prozess)
- die Vorschau neu starten
- pruefen, was wirklich ausgeliefert wird, bevor irgendetwas beurteilt wird
Der vierte Schritt ist der, den man weglassen moechte, und genau der, der den
Fehler findet. Er vergleicht die Bundle-Kennung im ausgelieferten index.html
mit der im gebauten dist/:
ls dist/assets/index-*.js # was der Bau erzeugt hat
curl -s http://127.0.0.1:<ui-port>/ | grep -o 'index-[A-Za-z0-9_-]*\.js'
Stimmen die beiden Kennungen nicht ueberein, liefert die Vorschau einen alten Bau aus, und jeder Befund an ihr ist ein Befund ueber Code von vorhin.
Warum das hier steht: zwischen 13:08 und 23:10 am 2026-08-29 sind fuenf Zyklen gebaut und nicht gesehen worden, weil die Vorschau vom Vormittag weiterlief. Ein Ablauf, der nur im Kopf einer Sitzung steht, ist beim naechsten Mal weg.
Explorer chat context
Local browser chat automatically includes the current reader source: the exact marked text when a selection exists, otherwise the loaded file. A caret alone does not narrow the context. The source is a single replaceable data block in the system message, followed by conversation history. Each new message captures the current source; previous source blocks are not appended to the conversation. Optional graph evidence remains explicitly attachable.
The composer shows which file or selection will be used. Missing source and partial file loads are disclosed. The exact request is token-counted before generation; oversized files are rejected without silently shortening them. Mark a smaller range or start a new conversation to reduce context. Navigation does not alter an in-flight request, and Retry replays its original snapshot. Model loading remains opt-in, and inference runs in the browser.
Die Agentenebene: was live arbeitende Agenten auf dem Graphen zeigen
Agent activity is experimental and hidden in normal builds. To include its
workspace, hook setup, graph overlay, commands, and display controls, explicitly
build with VITE_EXPERIMENTAL_AGENTS=true npm run build (or start the dev server
with VITE_EXPERIMENTAL_AGENTS=true npm run dev). The value must be exactly
true; URL parameters and saved preferences cannot enable it. Without this
flag, activity polling is disabled and an old Agents workspace selection opens
Explore. Browser-local chat is independent of this feature.
This is recorded tool activity from configured adapters, not automatic agent observability. The bundled adapter supports Claude Code PostToolUse; other clients need their own adapter. The flag does not install hooks or delete any existing events in the daemon's SQLite store. Even in an enabled build, the reader must turn activity on before the browser polls for events.
Arbeiten KI-Agenten in demselben Repository, kann die Galaxie sie zeigen: je Agent ein kleiner leuchtender Koerper, der den Symbolknoten umkreist, an dem er gerade arbeitet, und unten rechts ein kompaktes Instrument, das erklaert, was man sieht. Der Weg dorthin hat drei Stationen.
Recorded tool activity through the daemon
agents/hooks/atlas-trace.py is the supported PostToolUse producer. Configure
ATLAS_PROJECT to the exact indexed project name, ATLAS_AGENT_NAME for its
label, and (only for a custom port) ATLAS_DAEMON_URL=http://127.0.0.1:PORT.
The Connect your agent disclosure in Agent activity downloads this exact
hook and generates a project-specific install command using /api/repo-info.
On macOS/Linux with Python 3, run the reviewed command:
python3 ~/Downloads/cbm-atlas-trace.py --install-claude --root /absolute/repository --project INDEXED_NAME --daemon-url http://127.0.0.1:9749
Installation is explicit and local: it preserves unrelated Claude settings,
adds a PostToolUse entry to .claude/settings.local.json, and copies the hook
into .claude/hooks/. It refuses conflicting hooks, symlinks and malformed
configuration. It makes no network request or account change. Start a new Claude
Code session after installation, then load recorded activity in the browser.
Other coding clients require their own event adapter; they are not automatically
observed. For manual configuration, run python3 <path>/atlas-trace.py in the
client's PostToolUse hook. Its JSON tool event arrives on stdin. During normal
hook execution it always exits zero and does not change the tool call's result.
The hook records timestamp, tool name, run ID, sequence number, path and optional line span/command. The hook records no file contents and no tool output. Commands and paths may still contain sensitive information: the entire data path stays on this workstation. The hook refuses external destinations, proxies and redirects.
A transactional SQLite outbox at ~/.atlas-trace/events.jsonl.outbox.sqlite3
allocates sequence numbers safely across concurrent hooks. ATLAS_TRACE_FILE
changes this path prefix. Up to 10,000 pending events survive daemon downtime;
old pending entries expire at that limit. Delivery retries on the next hook,
or explicitly with python3 <repo>/graph-ui/agents/hooks/atlas-trace.py --flush.
A flush delivers up to 100 pending events from one project. No background bridge
or additional listener is required. The old JSONL watcher and replay bridge remain
historical fixture tools; they are not connected to the application by default.
Daemon log provenance is explicit. GET /api/logs?project=NAME&min_level=warn
returns only records attributed to that exact indexed project; the filter applies
before pagination and counts. Omitting project keeps the daemon-wide history;
scope=unattributed shows records without known project ownership. Migration v3
adds a nullable project column without assigning old records to the current
repository. Paths, page URLs and message text are never used to guess ownership.
Each record exposes project: string | null; responses expose scope and the
selected project. A failed scoped database read returns an error instead of
substituting unrelated memory-ring logs. New UI entries capture optional project
ownership when recorded, before buffering; an explicit empty/null entry project
stays unattributed even if a batch carries a project.
POST /api/agent-events accepts {project, events: [...]} with at most 100 events.
Required event fields are ts, agent, run, integer seq, phase: start|end
and tool. Optional fields include path, lines, detail, source, intent
(self-report), and explicit replay. Unknown fields are discarded.
The daemon owns <cache>/activity.db, independent of replaceable project indexes.
Its additive migrations use SQLite WAL and a busy timeout. Events have monotonic
daemon cursors and unique (project, run, seq) identities. A small per-run retired sequence floor prevents expired events from reappearing after a delayed retry.
10,000 events are retained globally; expired history is explicitly incomplete.
A database generation distinguishes a restart (same state) from a replaced database.
The view and logs
Agent activity is off until enabled by the reader. It then polls
GET /api/agent-events?project=NAME&after=CURSOR&limit=200 over the same origin and
port as the graph and MCP HTTP API. Failed requests retain the last accepted
cursor; reconnects do not duplicate retained rows. Changing repositories resets
the browser's activity state. ?agents=PORT no longer selects another server.
Daemon log callbacks and every accepted frontend log level persist in the same SQLite
journal. GET /api/logs preserves its lines/total response and adds structured
records, receipt timestamps, severity, source, durable IDs and a database
generation. min_level=warn selects warnings and errors, min_level=error only errors.
q=TEXT applies a literal, ASCII case-insensitive substring search to timestamps,
sources, messages and explicit project names. Scope, severity, search, counts and
cursors all apply before the display limit. System Logs uses these same filters; 2,000 warning/error records
are reserved independently of 3,000 routine records. after=CURSOR reads forward,
while requests without a cursor return a recent snapshot. A failed SQLite store
is reported as persistent:false, with the bounded in-memory fallback available.
GET /api/ui-log now reads frontend JSON lines from that same journal. Its
path names activity.db, export_path names the compatibility JSONL file, and
source: "sqlite" / persistent: true identify the source. Version 4 adds explicit
frontend origin and retains full bounded JSON evidence. On first open, at most the
last 256 KiB of each old ui.log.1 and ui.log are imported in one transaction;
original receipt timestamps are preserved, project ownership remains unknown,
and a partial import is disclosed. No log is reassigned to the selected project.
UI posts retain the existing accepted, dropped, path and file_error fields,
adding duplicates, persistent and storage_error; a failed journal write
returns HTTP 503 for retry. A retired per-session sequence floor prevents expired
UI events from returning on an old retry. JSONL remains a rotating local export
for existing tail workflows; changing it does not change the HTTP history.
No local report or event is published externally by these routes.
Was die Ansicht zeigt und was sie ausdruecklich nicht zeigt:
- Ein Agent ist ein Koerper, kein Knoten. Die Ebene legt sich ueber den Graphen; Knoten- und Kantenfarben bleiben unangetastet. Die Farbe eines Agenten kommt aus seiner Kennung und ist nach einem Reload dieselbe; dazu traegt jeder Koerper einen Buchstaben, damit die Unterscheidung nicht allein an der Farbe haengt.
- Die Art der Arbeit steht in Form und Verhalten: lesen ein weiter, ruhiger Orbit; schreiben ein enger; suchen kurze Pings an den Knoten, deren Name das Suchmuster traegt; testen ein pulsierender Koerper mit einer gestrichelten Linie zum geprueften Bereich, sofern der Befehl eine Datei nennt, die der Index kennt.
- Die Zuordnung ist so genau, wie sie sein kann. Datei plus Zeilenbereich trifft den engsten passenden Symbolknoten, nur Datei den Modulknoten, ein Knoten ohne Endzeile wird als unsicher gekennzeichnet, und was sich nicht verorten laesst, steht im Instrument samt dem Rohereignis, statt zu verschwinden.
- Nichts wird gedeutet. Kein Fortschritt, keine Prozentzahl, keine
Bewertung. Eine Absichtszeile erscheint nur, wenn das Ereignis ein
intent-Feld mitbringt, das der Agent selbst geschrieben hat, und dann gekennzeichnet als Selbstauskunft. - Der Leser ist auch ein Akteur. Welches Symbol er oeffnet, laeuft als eigener Akteur "you" durch dieselbe Ebene. Diese Ereignisse entstehen im Browser und gehen NICHT in die Ereignisdatei.
Der Schalter, der die ganze Ebene abschaltet, liegt im Einstellungen-Panel in der Gruppe "Drawing, and what it costs", zusammen mit allem anderen, was Rechenzeit kostet, und nennt dort seinen auf dieser Maschine gemessenen Effekt auf die Bildrate.
Die aufgezeichnete Datei, gegen die der Beweislauf faehrt, liegt unter
fixtures/agent-events/; woraus sie entstanden ist und was daran geaendert
wurde, steht vollstaendig in fixtures/agent-events/HERKUNFT.md.