Skip to content

CBM Lens Beta: graph exploration and architecture workspace - #2068

Open
DeusData wants to merge 289 commits into
mainfrom
feat/codeatlas-web
Open

DeusData wants to merge 289 commits into
mainfrom
feat/codeatlas-web

Conversation

@DeusData

@DeusData DeusData commented Sep 5, 2026 •

Copy link
Copy Markdown
Owner

CBM Lens Beta turns the indexed code graph into a repository exploration workspace. It combines a source explorer, focused graph tracing, 3D architecture views, and an optional browser-local agent that explains the current selection.

The workspace includes repository maps, routes and service relationships, hotspots, system structure and behavior, editable project ADRs, index coverage, and daemon configuration. Graph and source evidence remain available independently of generated explanations. Model downloads are opt-in.

This brings the complete Atlas and CodeAtlasWeb stream into main and preserves its original commits. It includes Bernhard Jackiewicz's contributions and subsequent Lens improvements. Thank you, Bernhard, for building and improving this together 🙂

Integration with main preserves subprocess isolation, indexing safeguards, test selection, and watcher behavior. Review fixes reject ambiguous ADR RPC arguments, guard trace ingestion against concurrent project mutation, correct its MCP write annotations, and omit private command text from newly generated agent events. Git history reads isolate inherited Git configuration and remove credentials from repository links. The obsolete runtime setting is removed.

The interface uses the CBM Lens Beta name, an amber Beta badge, a subtle version label, and compact architecture history. Development notes, intermediate media, and stale hook captures have been removed. Retained guides and provenance notes are concise English; license texts and fixture evidence are preserved.

The security audit now distinguishes raw process calls from their reviewed wrappers. A build inventory verifies the narrow exclusion of an unused optional Node package from the browser distribution. It covers application and worker inputs, generated assets, and copied runtime files; the license allow-list is unchanged. The license CI job builds the browser assets before checking their inventory.

Validation

The integration run passed 1,414 native tests across 13 affected suites with ASan/UBSan; seven explicitly Windows-only cases were skipped on macOS. The subsequent history fixes passed all 42 affected UI tests. New native and hook regressions were verified RED, GREEN, and RED again on production-only reversion; the hook suite passed all ten tests.

The cleanup passed 115 focused frontend tests, five operational-reference checks, all 198 acceptance checks, style and promise checks, and a production build. The final security matcher passed 16 cases, and the browser license inventory passed 22 cases plus verification of the actual build. Reverting the relevant fixes reproduced their original failures. The full static audit and the UI dependency license check passed locally. The UI URL scanner passed 18 additional regression cases and 17 focused API/security tests; it scans all matching files and limits fixture exceptions to reviewed paths. The full UI audit and vendored integrity check (1,083 files) also passed. A fresh production build and browser-license verification passed after the final URL parsing adjustment.

Normal remote checks remain required before merge. The full local three-platform ladder was waived for this change. An earlier subprocess cancellation assertion failed once; later passes do not establish that the earlier failure is fixed.

DeusData and others added 18 commits August 27, 2026 20:48
cbm_mkdtemp copies the expanded path back into the caller's template;
on Windows that is %TEMP%\..., far longer than the literal. The two
literal-sized arrays (symbol-history, why) were stack overflows there —
caught by the real-Windows leg as an fopen failure. CBM_SZ_256 buffers,
like every other call site.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The stub counted the traces array, answered 'accepted', and discarded
everything. Now: traces are call paths of qualified names (adjacent =
caller→callee; bare {caller, callee} pairs still accepted), stored in
observed_calls/observed_paths — SEPARATE from the graph tables and
keyed by qualified name, because node ids are reassigned on every
reindex and id-keyed observation would silently rot. Counts accumulate
per run label; whole runs age out together past the 200k-pair cap
(oldest first, deterministic under the one-second timestamp resolution
via rowid tiebreaks — eviction is never a timing lottery). The response
is honest about resolution: only pairs whose both endpoints are indexed
get stored, and up to ten unresolved names come back so producers can
fix their naming instead of silently losing data.

Atlas joins observation at read time: trace and flow-detail hops that
actually ran gain observed {count, label, last_seen}; absence adds
nothing — an unobserved hop is merely possible, never 'dead'.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Trace hops and flow steps that actually fired render '▶ observed ×N'
with the run label and date; a fully-observed trace says so in one
line, and the footer states the honesty rule: unmarked hops are
possible, not dead — runs only cover what they exercised. The wiki
gains the observed entry (first-class, with its caps), and F5's gap
narrows to what is still missing (automatic capture).

Live-smoke fix on the C side: resolve_store hands handlers a
query-only connection, so ingest writes silently no-op'd against real
project stores — ingest_traces now takes the dedicated read-write
connection (open_store_for_write, né open_adr_store_for_write), whose
open also creates the observed tables in pre-existing databases.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Both predispatch-cancel tests probed the follow-up request with
ingest_traces traces:[] and expected the stub's 'accepted'; empty
traces are a tool error under the real contract. The outer-scope test
now probes with a valid ingest (unresolved names store nothing); the
raw-index test — where no project exists by design — probes with the
project-free list_projects. Clean means what it always meant: the next
request runs unpoisoned by the cancel.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…guard

Three test families leaned on ingest_traces being a discard-stub:
- the daemon-runtime usability probe sent traces:[] and grepped for the
  stub's traces_received; it now sends a valid minimal ingest for the
  seeded project (the daemon requires the project argument) and checks
  the honest pairs_unmatched report
- cypher_wide_return_projection_bounded forked the sanitized runner for
  crash isolation; a fork that then does real store setup is
  byte-fragile on macOS — a 1.5KB schema addition got the child killed
  before the query ran (bisected: any equal growth flips it, even with
  a 1-column query). The parse-time bound is the contract; assert it
  in-process. A regression still fails loudly, and the test now runs
  on Windows too instead of skipping

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
/api/who answers the most-sought information type in the developer-
questions literature for one file, from the churn scan the dashboard
already pays for: people with recorded history here, each with their
evidence — commits in this file, repo-wide breadth, and last-touched
where the retained newest commits prove it (absent otherwise, stated
honestly). Deliberate constraints hold: no cross-person performance
framing, no bare percentages, capped list with the distinct-author
denominator.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…hinese

Wiki entries and question families carry co-located zh content
(sentence, why, caps, not-covered, hints, gaps — 24 entries, 18
questions) with per-field English fallback; metric terms stay
English-canonical with a zh gloss in the panel header, so the zh UI
keeps teaching the tokens users meet in code and issues. The impact,
history, and observed surfaces move their remaining hardcoded strings
into the message catalog (en+zh, same interpolation shapes). zh
sentences are budget-tested at ≤45 characters like their English
counterparts at ≤30 words; the refusal rationale of the four
refused-metric pages is translated at full bluntness.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Names as plain text with their evidence line (commits to this file this
year, repo-wide breadth, last touched when the retained commits prove
it), honest empty and no-history states, en+zh from birth. The
question index stops claiming the view is planned: F13's remaining gap
is the region-level rollup — and, as ever, never a leaderboard.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
An aborted incremental run preserves the previous index by design, but
the response said generic 'error — check repo_path exists', sending
people to debug a path that was fine. The abort and persist-failure
codes move to the public pipeline header (the contract always said
callers may distinguish them) and index_repository now answers with
what actually happened: aborted_previous_preserved (retry; the old
index still serves) vs persist_failed (disk/permissions) vs the
generic failure.

The incremental test helper goes fail-closed on error responses,
surfacing the real cause once at the source — a transient abort used
to slip past the non-NULL assert and cascade into dozens of mysterious
count failures downstream (the 99-test Windows pile-up).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The remaining hardcoded chrome moves into the catalog (en byte-
preserved, zh added with identical interpolation shapes): symbol
section titles and states, the flows trace bar and journey chrome, the
overview slots/findings/regions/reference blocks, and the wiki
fallback. Metric vocabulary stays English-canonical; computed sentences
(Dashboard takeaways, TriggerTree guard assembly, firstread content)
are flagged for their own pass rather than half-translated.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The watcher-poll family gets its production fix and its doctrine
rebuild in one pass:

- the dirty-state signature statted files through stat(), whose
  st_mtime is SECOND-granularity on Windows — two same-second edits
  hashed identically and a reindex went missing (the Windows leg
  caught it as test_watcher:2045). The signature now reads
  cbm_path_info_utf8 (FILETIME 100ns ticks, wide-path correct) and
  retries once when a just-written file is transiently unreadable
  under AV real-time scanning
- a test seam exposes the committed/pending signatures, and the suite
  gains self-diagnosing count asserts — the family blocked two
  releases because a bare count mismatch could not say whether
  detection missed or the reindex path misbehaved; now it names which
- reach-assertions get a bounded wait-for-state helper (safe: an
  unchanged dirty tree never increments, so extra polls cannot
  overshoot); must-stay-quiet asserts keep their fixed polls

py_lsp_scale's quadratic detector samples min-of-N so scheduler noise
on a loaded host cannot inflate the calibrated ratio (noise only adds
time; the minimum approximates uncontended cost — the assert failed
the 18-job mac leg while passing isolated on the same tree).

The full-pipeline probe suites join the slow scheduler tier with their
reasons stated: a fresh checkout's first run pays a deterministic
AV-scan-cold tax that killed node_creation_probe at exactly 900s.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The takeaway/cost sentences, the trigger tree's guard grammar, and the
first-read content each build their own full sentence in the viewer's
language from shared parameters — never word substitution into an
English frame (zh restructures where zh reads better: 只要 X 运行,它就
一定运行——调用点上没有任何条件). The load-bearing discipline holds
bilingually: the complexity takeaway's simple/exceed claims are parsed
back out of BOTH languages and asserted against the same CPLX_BINS
metadata, so a bin edit moves every locale or fails loudly. The
server's region-why templates get parsed and recomposed client-side
with byte-identical English reproduction and verbatim pass-through for
unknown shapes. English output is byte-identical everywhere, guarded
by the untouched en expectations.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
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>
…d the CSP

Maintainer glue for the imported frontend; no product behaviour of the
UI itself changes.

- Makefile.cbm: `npm ci` runs with PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1.
  The UI's dev dependencies include playwright for its local browser
  proofs, and a plain install would download browsers that no build or
  gate launches.
- graph-ui/vite.config.ts: the dev server listens on 5173 with the two
  literal loopback origins, which is what
  tests/test_ui_dev_proxy_security.sh pins.
- graph-ui/index.html: lang="en"; the catalog is English.
- CSP: the directive string moves to http_server.h as CBM_UI_CSP_VALUE
  so a test can pin it, and connect-src now admits the two loopback
  services the UI may talk to when the reader starts them, the
  local-model sidecar on 127.0.0.1:4141 and the agent-event bridge on
  127.0.0.1:4142. Under connect-src 'self' both fetches were silently
  blocked in the embedded build. Every other host stays forbidden; a
  new httpd test asserts that the only hosts in the policy are those
  two loopback ports.
- scripts/security-ui.sh: two false positives that bit on the imported
  source. The analytics pattern matched the English word "plausible"
  (now plausible.io), and `\s` inside an ERE bracket is a literal
  backslash and 's', which cut every localhost URL at its first 's' and
  then failed the allowlist (now [:space:]).

Verified: httpd suite 64 passed; dev-proxy contract and UI security
audit pass; graph-ui builds and its 2024 vitest tests pass.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
… in the browser

The previous graph-ui let a reader index a repository from the browser,
delete an index, edit the project's decision record and look at the
server's log and processes. CodeAtlasWeb is read-only by design and sent
all of that to the command line, which for a fresh install means a page
that says "nothing indexed" with no way forward. This adds a [p]rojects
panel (alt+p) in Bernhard's idiom so nothing users have today is cut.

What it does, and how it says so:

- Projects on this server: the list from list_projects over /rpc, with
  root path and counts when the server sends them ("counts not sent"
  when it does not), open (reloads with ?project=), check
  (GET /api/project-health as a sentence), reindex (POST /api/index with
  the root the server reported; no root, no button, a sentence instead)
  and delete (DELETE /api/project) as a two-step question in place.
- Index a repository: path and name (suggested from the last segment),
  a folder browser over GET /api/browse, the index button only once
  both fields are there, the acknowledgement of POST /api/index, and
  the job table from GET /api/index-status polled every 1.5 s while a
  job runs; the list reloads exactly when a job finishes.
- Decision record: GET/POST /api/adr for the open project, with
  "busy" told apart from "refused" by the 423 status.
- This server: GET /api/processes and the GET /api/logs tail.

Every block names its source route, a number the server did not send is
shown as not sent, and no control is on the screen that cannot act
(his promise-scan and style gates stay green; the panel is in the
hardcoded-string scan's file list).

Wiring: AtlasApi grows the routes above with a method-aware request;
the catalog gets a projects section, the menu entry, the help panel
entry and the help wording about what this window can ask the server
to do; WIRED_MENU_SHORTCUTS gains 'p' and the help table picks it up
structurally; the no-project status line points at alt+p.

index.html gets an inline SVG favicon so a fresh page stops logging a
404 for /favicon.ico.

Verified: 2073 vitest tests pass (49 new: model readers, the API
routes with a recording fetch, the panel in jsdom); in the embedded
build against a live server, POST /api/index returned 202, the job
table was polled to "done" and the list refreshed with the new project.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The recorded proof runs of CodeAtlasWeb at 1825f9c850ac794066e02606012508b9d393c6aa:
screenshots, contact sheets, two screen recordings and the JSON reports
of every cycle's smoke run, gate run and audit (227 files, 65 MB).
Bernhard Jackiewicz's work, imported unchanged.

They sit in their own commit on purpose: his frozen acceptance checks
read them (tests/scaffold), his help page points readers at them, and
the maintainer may still decide to keep this history out of the public
tree. Dropping this commit removes exactly the artifacts and nothing
else; the four acceptance checks that bind the report to his
repository's own commits are not part of the CI gate either way.

Co-authored-by: Bernhard Jackiewicz <bj@techport.io>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
- .github/workflows/_test.yml: a `test-ui` job (ubuntu, node 22) runs
  the frontend's vitest suite, its hardcoded-string and promise scans,
  the portable frozen acceptance checks and a production build, with
  the same browser-download skip the product build uses. The browser
  proofs (tools/smoke-*.mjs) need a running server and Playwright
  browsers and stay a local, manually dispatched venue.
- graph-ui/package.json: `test:acceptance` runs every frozen check except
  the two release-binding files, which tie the recorded release report
  to the commits of the frontend's original repository and cannot pass
  anywhere else (203 checks pass here; the full `npm test` fails exactly
  those four assertions).
- README.md: the Atlas section describes CodeAtlasWeb, credits
  Bernhard Jackiewicz and points at #1964.
- graph-ui/README.md: a maintainers' preface on how this repository
  builds, embeds, proxies and gates the frontend, and what it added;
  his README follows unchanged.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
tests/test_venue_parity_contract.sh holds every venue to one harness: a
workflow step may provision, move artifacts, or call a canonical leg
entry, and the product-exercising commands live inside scripts/. The
test-ui job ran npm inline and tripped it on the local ladder.

scripts/ci/test-ui.sh is now the whole leg (install without a browser
download, vitest, the style and promise scans, the portable frozen
acceptance checks, the production build); the job calls it, and running
the same script locally is the same leg. Contract green again
(22 workflows marker-checked, 10 walked).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The Atlas screenshot the README embeds still showed the previous
frontend. This is CodeAtlasWeb from a clean-tree embedded build: the
explorer, the Monaco reader on the sample fixture, the twin, the galaxy
and the menu row with the [p]rojects entry.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

DeusData commented Sep 6, 2026

Copy link
Copy Markdown
Owner Author

Verification record for the tip as pushed (453d6cc9, plus the screenshot commit that follows).

Decision (maintainer): verify on macOS for this stacked draft; the Linux and Windows legs run when it is rebased onto main with #1860. The two container legs were additionally blocked tonight by the Colima disk floor until 94 stale post-mortem volumes (~60 GB) were swept.

macOS leg (scripts/test.sh, ASan+UBSan, full parallel suite): All tests passed, 181 suites. One earlier attempt on a memory-starved machine (another session's index workers; the harness killed the legs) had a single red in subprocess_cancel_grace_is_hard_capped, a bounded-poll timing probe this branch does not touch; it passed on this calm wide rerun and is ledgered as a starvation flake.

Frontend leg (scripts/ci/test-ui.sh, the same script the new test-ui CI job runs): 2073 vitest tests, style gate (0 dashes, 0 attribution, 0 hardcoded chrome strings), promise scan (0 promises, 0 silent controls), 203/203 portable acceptance checks, production build.

No dead controls: Bernhard's own W12 proof (npm run smoke:w12: every button, [role=button], link, input, tab, slider and separator in every UI state, pressed once with the mouse and once with the keyboard; anything that does nothing is a finding) was run against this repository's embedded binary and fixture: green, pass 6 complete: 22 states, 80 to 85 controls found per full state, 0 findings, and every filter (edge kinds, actor filters, effect switches) shown to remove and restore what it toggles. Note that W12 serves dist/ through his static proxy, so it proves the controls, not our CSP; the CSP path is covered by the browser check below.

Contracts: dev-proxy security, UI security audit, venue parity (22 workflows), httpd suite 64 passed with the new loopback-only CSP test, clang-format clean.

Browser check under the embed (our CSP, not his dev proxy): reader, twin, galaxy and the why-dialog render; no blocked request; in the [p]rojects panel a real POST /api/index returned 202, the job table was polled to done and the project list refreshed.

Brings the Atlas branch up to current main (7b0f553). Eight files
conflicted; how each was settled:

- src/mcp/mcp.c: the real ingest_traces description stays, in main's tool
  row shape (main dropped the title column); index_repository keeps the
  truthful abort branches (aborted_previous_preserved, persist_failed)
  and gains main's format_migration flag in the success branch.
- src/ui/http_server.c and tests/test_httpd.c: the branch's twelve-tool
  read allowlist for /rpc (#1663) over main's three, with main's %zu
  and initialised counter.
- README.md: main's surface count (45), the branch's Atlas line.
- graph-ui (the previous frontend, replaced by the stacked #2068 but
  kept building and green here): the branch's node-selection wiring
  (onSelectNode) is kept consistently, so main's duplicate
  handleSelectPath and its 3-argument call go; main's version chip is
  added to the branch's header; useProjects keeps the branch's
  render-first flow on top of main's paginated JSON helpers
  (fetchAllProjects, fetchFullSchema), which the lean output contract
  requires, and a project whose size the server did not send now gets
  its schema too. main's GraphTab.selection.test.tsx, written against
  main's GraphTab, is dropped in favour of the branch's own #1197
  coverage in GraphTab.regions.test.tsx ("reports selected nodes to
  the route for deep links"); main's useProjects pagination test waits
  for the lazy schema enrichment instead of asserting before it runs.

Verified: mcp, httpd and ui suites 414 passed; the old frontend builds
and its 149 tests pass.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Three findings scripts/security-ui.sh raised on this branch, none new to
the merge:

- The analytics pattern matched the English word "plausible" in the
  wiki text, and `\s` inside an ERE bracket is a literal backslash and
  's', which cut every localhost URL at its first 's' and then failed
  the allowlist. Same two regex fixes as on the stacked branch
  (plausible.io; [:space:]).
- graph-ui/src/lib/rationale.ts carried a literal GitHub URL in a doc
  comment, and its test built forge links from a literal GitHub base.
  The audit forbids external URLs anywhere in the UI source, tests
  included; the comment now describes the shape, and the test composes
  the same links from a loopback base (the composition is
  host-agnostic).

Audit passes; rationale tests 5 passed.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Re-stacks the CodeAtlasWeb branch on the updated base (feat/atlas-r1 at
a44732b, which merges main 7b0f553). Ten conflicts, all in the seam
between the previous frontend and its replacement:

- README.md: main's surface count (45) with this branch's Atlas line.
- graph-ui/package-lock.json, graph-ui/src/App.tsx: CodeAtlasWeb's own
  files stay; the previous frontend's edits to the same paths do not
  apply.
- Seven previous-frontend files main had modified (GraphTab,
  NodeDetailPanel and its test, StatsTab test, useProjects, rationale
  and its test) stay deleted, and two tests main added for that
  frontend (App.test.tsx, useProjects.test.tsx) are not brought in;
  their subjects no longer exist in this tree.

Nothing under graph-ui changes relative to this branch; the C side
takes main's lean-output work and the branch's merge resolution.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…t parser

On current main the compact text form of query_graph and search_graph
carries footer lines the frontend's parser did not know (returned,
total_relation, truncated; search_mode now follows the head):

    rows: 2  (cols: n.name n.file_path)
      loadConfig src/config.ts
      isProduction src/config.ts
    returned: 2
    total: 2
    total_relation: eq
    has_more: false
    truncated: false

The parser refused the first unknown line, and since the reader resolves
a file's module symbol through query_graph before it asks for the
source, no file could be opened on main ("query_graph: Antwort war nicht
lesbar: unbekannte Fusszeile einer kompakten Antwort: returned: 1").

Both parsers now read the new keys as fields (returned, totalRelation,
hasMore, truncated) rather than skipping them, so a capped answer stays
nameable, and refuse anything else as before. Two tests carry main's
exact output for the fixture. The recorded fixtures from before the
contract keep passing, as the fields are optional.

Verified against the embedded build on the re-stacked branch: files
open, the twin answers, search returns hits; provider tests 126 passed.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

DeusData commented Sep 6, 2026

Copy link
Copy Markdown
Owner Author

Re-stacked on the updated base: feat/atlas-r1 now merges current main (7b0f553c, see the note on #1860), and this branch merges that in 7cd5c931. Ten conflicts, all in the seam between the previous frontend and its replacement (its files stay deleted; two tests main added for it are not brought in; README keeps main's surface count with this branch's Atlas line).

One real finding on main, fixed in 6928c8a1: the lean output contract (#1597) adds footer lines to the compact text form of query_graph and search_graph (returned, total_relation, has_more, truncated; search_mode now follows the head). CodeAtlasWeb's compact parser refused the first unknown footer line, and since the reader resolves a file's module symbol through query_graph before it asks for the source, no file could be opened on main. Both parsers now read the new keys as fields (so a capped answer stays nameable) and still refuse anything else; two tests carry main's exact output. The JSON tools were never affected: his client asks for format: "json".

Verified on the re-stacked embedded build: files open (32 lines rendered from get_code_snippet), the twin answers for createUser (facts, steps, callers, data, error paths, all /rpc calls 200), the command line returns 10 hits for createUser, 0 console errors; provider tests 126 passed; style and promise gates green. Bernhard's W12 every-control proof is running against this build and its result follows here.

@DeusData

DeusData commented Sep 6, 2026

Copy link
Copy Markdown
Owner Author

W12 on the re-stacked build (6928c8a1, main's lean output underneath): green, pass 6 complete, 22 states, 0 findings, every filter removes and restores what it toggles. Same proof as before the re-stack, now against current main.

Second drift of the lean output contract (#1597), found on a real
project: get_code_snippet now outlines any container of 200 lines or
more unless source_mode is "full", and full source arrives in pages of
at most 500 lines with next_start_line and original_end_line. The
reader loaded a file through its module node with the old request, so
on main every file longer than 200 lines came back as an outline with
no source ("get_code_snippet returned no source for ..."), and even with
"full" only the first 500 lines would have shown.

- rpc-client: getCodeSnippet sends source_mode "full" and takes an
  optional page window (start_line, max_lines); the provider's symbol
  snippets benefit the same way.
- rpc-schemas: the page fields are read (source_mode, source_truncated,
  next_start_line, original_end_line), optional so recorded answers from
  before the contract keep parsing.
- file-source: pages are fetched one after the other and joined; a page
  that does not arrive ends the loading and the note under the source
  names the missing lines. The single-window behaviour of servers
  before the contract is unchanged. The server's "(source not
  available)" placeholder, sent when the indexed file is no longer on
  disk where the index expects it, is refused as source and reported as
  what it is.

Tests: two pages joined with the calls the server needs, a missing page
named, the placeholder refused; the client's request pinned. Reader and
provider suites 149 passed; full suite green with both gates.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData

DeusData commented Sep 6, 2026

Copy link
Copy Markdown
Owner Author

Second drift of the lean contract, found on a real project and fixed in a338c1ca: on main get_code_snippet outlines any container of 200+ lines unless source_mode: "full" is requested, and full source arrives in pages of at most 500 lines (next_start_line, original_end_line). The reader loaded files through their module node with the old request, so every file longer than 200 lines came back as an outline with no source. The client now asks for full source and the reader pages through the file and joins the pages; a page that does not arrive is named under the source, and the server's "(source not available)" placeholder (the indexed file no longer where the index expects it) is reported as such instead of being shown as text. Six tests; suite 2079; gates green.

Verified on a copy of the maintainer's real index of this repository (20,338 symbols, 127,767 edges): search finds cbm_http_server_port, the 2,244-line src/ui/http_server.c loads in full through the pages, the twin answers, 0 console errors, every /rpc call 200. The coverage chip honestly reports the index as stale against the working tree, which it is.

BernhardJackiewicz and others added 19 commits October 4, 2026 15:06
The hand test asked for every Refresh button to say what it did; only the
four in Architecture did. Measured in the browser, three more showed
nothing that lasted: Refresh in ADR changed nothing for a single frame,
Refresh projects in the project picker showed "Loading projects..." for
about 150 ms and then the same list, and Refresh in the file impact of
Explore folded the details into "Reading dependencies…" for two seconds
and brought back the same numbers.

The control and its hook move from architecture/ to ui/refresh/, with the
shared words "Up to date at …: no changes since the last load" and
"Refresh failed at …", and these three buttons use it: they read
"Refreshing…" while they run and then name the time and whether anything
changed. Where the view already shows an error in its own words, the
status names only the time. The file impact keeps its details on screen
while a refresh of the same file runs. In the project picker the status
stands on its own line under the buttons.

The System buttons already show it ("Updated" and "Read" with the time),
and the Refresh buttons of Settings, of the projects panel and of the
daemon alerts are not mounted anywhere in the app, so they stay as they
are.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
The lines read from JSONBAgg ended mid-template at the panel edge, behind
the scrollbar macOS hides. Code blocks in chat answers now wrap long lines,
as the Source block does since K15.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
…story

After a few answers built from facts, "Explain the marked code line by
line" got the first fact line back from the model ("Marked lines 50-54 of
general.py"). The history of a later request now carries a grounded answer
as its model sentence (its facts only when the sentence was left out), a
file outline as its heading and purpose and a listed answer as its list.
The code lines and the note on who wrote what stay out: the request carries
the source anyway, and a model answer must not say "not generated by the
model".

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
The outline of django's pyproject.toml showed "dependencies [; authors [".
An array or inline table that runs over several lines is now read to its
end, and its items are split at its own commas only, so an inline table
such as an author stays one item.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
…and hint while loading, steady tab row, current start apart, Refresh feedback across the app

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
…answers, code file questions, topic return, probe words, INI outline and file purpose

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
…ence, dropped sentence reason, token note, unknown names, German answers, Architecture card

Both chat branches touched the same places. The grounded answer keeps the
lines read from the code and takes the reason of a dropped sentence; the
divider says "Back to" for a returning topic and "New topic" in the
language of the turn otherwise; examples follow the kind of the selection
and the hint offers no model. The new tests of the behaviour branch now
expect the reworded texts, and the German follow up answer quotes the
prompt like the other German hints.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
…tch restated answers

With .github selected in the Galaxy hierarchy, "kkannst du mir die heirarchie
erklären" and "erkläre die aktuelle hierarchy" went to the free model, which
answered "Ich kann dir die Heirarchy erklären." and "Die aktuelle Hierarchie
erklärt.".

Questions about the current view (die Hierarchie, die Ansicht, den Graphen,
den Ausschnitt, die Struktur, this view, the hierarchy, what am I looking at,
was sehe ich hier), typos included, now get a listed answer from the loaded
scope in the language of the question: the root with its kind in the middle,
incoming and outgoing relationships by type with count and bounded names, how
far the scope reaches and how the picture is read. The Galaxy evidence carries
which picture is shown; switching it keeps the content identity, so the
automatic explanation is not written again.

A free model answer that only restates its question is no longer shown as an
answer: the turn says the model gave no answer, lists the facts of the
selection and offers Ask again, which tells the model not to restate the
question. A restating sentence under the facts of a general question is left
out. Short real answers such as "Ja, 11." stay.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
…eside Explore

N1: The index puts a Branch node above the top level folders and files,
named after the branch, "DETACHED" for a detached HEAD and "working-tree"
where no branch is known. Galaxy showed that bare name, and in the
hierarchy of .github it read like a folder. One helper
(galaxy/node-names.ts) now names it from the label Branch or the qualified
name pattern <project>.__branch__.<slug>: "django-demo · detached HEAD",
"cbm · working tree", "django-demo · branch main". Galaxy labels in both
views, root markers, the hover card, the search, the toolbar root, history,
Path to, Selection details and the chat evidence, topic and listed answers
use it; German answers read "losgelöster HEAD", "Arbeitsverzeichnis" and
"Branch-Knoten". Tooltips and the hover card keep the name in the index.
The "{}" the index stores as the file of a Branch node is no file any more
(no file "{}" in the search, no open source button), the scoped hierarchy
frames the wider name instead of cutting it at the left edge, and line 0 is
no line range in the hover card. Scopes, history keys and the chat snapshot
keep the names of the index, so typed names match as before.

N2: The note "nothing of this walk is in focus: the ring follows the symbol
in front of the reader" stood under the scoped hierarchy in the Galaxy tab,
where the root stands in the middle and Explore is not open. It now shows
only beside Explore's reader, when no node of the walk is open there, and
says "None of these nodes is open in Explore; the ring marks the symbol
open there." Both hierarchy strings moved to galaxy-strings.ts in plain
words.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
…ng note beside Explore (K47, K48)

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
…scope and catch restated answers (K45, K46)

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
The server writes next_offset and truncation_reason under a full page,
candidate_window_saturated for very many candidates, and the lines of a
too small output budget. The search parser knew none of them, so every
search with more than one page fell back to "Index search unavailable".

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
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>
Since the branch node reads "cbm · working tree", a search for "working"
ranked it behind the folders of the other hits and cut it from the list.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
Preserve unfinished model operations across repeated project switches, retain truncated graph metadata for file and folder scopes, and give each browser hand test a fresh profile directory without deleting existing data.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Rename the reading workspace to CBM Lens Beta, distinguish Beta with an amber badge, and keep build diagnostics out of the header. Put architecture history beside the active context and record meaningful exploration steps.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData DeusData changed the title feat(ui): CodeAtlasWeb replaces graph-ui (Bernhard Jackiewicz's Atlas frontend) CBM Lens Beta: graph exploration and architecture workspace Oct 11, 2026
Merge validated environment overrides into a child-owned environment on POSIX and Windows, preserving caller PATH lookup for executable names. Forward each ObjectScript export parse timeout to the extractor.

Cover inherited and replaced values, empty values, duplicate overrides, parent isolation, invalid names, executable lookup, and timeout forwarding.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData
DeusData changed the base branch from feat/atlas-r1 to main October 11, 2026 14:47
Reconcile the complete Atlas and Lens stream with current main while retaining both histories. Preserve architecture functionality, current process and watcher safeguards, test infrastructure, and dependency security updates. Add coverage for Git-environment isolation combined with child-local overrides.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData
DeusData marked this pull request as ready for review October 11, 2026 15:35
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request javascript Pull requests that update javascript code priority/normal Standard review queue; useful PR with ordinary maintainer urgency. ux/behavior Display bugs, docs, adoption UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants