Commit Graph
3098 Commits
Author SHA1 Message Date
Bernhard Jackiewicz 1b696eaada fix(ui): read "test" as a prompt without a question in any open file
Every word of the open file counted as a name the prompt could ask about,
so "test" went to the model whenever the file contained the word, and the
model echoed it. Greetings and probe words (test, hallo, hi, ok, ja, danke
and the like) now never count as names unless one of them is exactly the
selection's own name.

The hint for such a prompt no longer offers "Ask the model": the model had
nothing to answer there.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 14:32:21 +02:00
Bernhard Jackiewicz a3432f8b8e fix(ui): keep the listed answer when the model is asked about it
"Ask the model" under a listed, grounded or file answer put the model's
text in place of that turn, so the 11 listed callers became one sentence
naming one of them. The model's reply is now a turn of its own below the
listed one, with the same question and the line "Asked the local model".

Every answer the model wrote freely now says so under it, in the language
of the question ("Generated by the local model; it can be wrong."), also on
an explanation card without listed facts. The button under such an answer
reads "Ask again" instead of "Retry"; after an error it stays "Retry".

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 14:30:04 +02:00
Bernhard Jackiewicz dc931f7fe9 fix(ui): state that a selection's symbols are outside the loaded scope
The new German sentence said "noch nicht", which the promise scan reads as
a promise; both languages now state the condition.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 14:03:47 +02:00
Bernhard Jackiewicz 789b18d171 Merge second hand test fixes: chat facts, listed answers, name check, language, grounded general questions, empty prompts, configuration files, output limit (K32 to K39)
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 14:00:51 +02:00
Bernhard Jackiewicz 6002e391fe Merge second hand test fixes: Architecture navigation, Recent menus, Refresh feedback, Behavior start list, workspace in the address (K40 to K44)
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 14:00:51 +02:00
Bernhard Jackiewicz bc7433a3aa Merge second hand test fixes: Galaxy labels, hierarchy band title, Expand +1 warning (K29 to K31)
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 14:00:51 +02:00
Bernhard Jackiewicz 63e2f40469 test(ui): expect file questions answered from the file in the chat check (C7)
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:59:11 +02:00
Bernhard Jackiewicz 0db683605d fix(ui): read a single unnamed list item of a configuration file without parentheses (C7)
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:53:44 +02:00
Bernhard Jackiewicz 7c02114709 fix(ui): keep the workspace in the address on a project switch (A5)
The project switcher turned "?project=django-demo&workspace=galaxy" into
"?project=cbm", so a reload could open another workspace. The new
address now keeps the page-wide parameters App names (the workspace and
the walk bounds) and nothing of the old project, and the address always
names the workspace in view, also one carried over a switch or chosen
from storage. Browser Back and Forward between projects work as before.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:47:12 +02:00
Bernhard Jackiewicz 1d861f6e64 fix(ui): answer general questions, empty prompts and file questions without guessing (C5, C6, C7)
A short general question about a Galaxy selection ("was macht diese
Klasse?", "what does this do") now gets the shape of its explanation:
the listed facts in the language of the question and one model sentence,
checked for unknown names and unsupported claims (German forms included).
Questions that ask for detail still go to the model.

A prompt without a question ("test", "hallo", "?") is answered locally
with example questions for the selection or the open file.

"What does this file do" and "explain this file (in detail)" about a
YAML, JSON or TOML file are answered with an outline read from the file;
a workflow keeps its counted facts.

Every local answer offers "Ask the model".

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:45:54 +02:00
Bernhard Jackiewicz edf241786f fix(ui): make the Behavior start list findable: suggestions, alphabetical, filter (A4)
The Behavior "Start" field of django-demo offered 62 operations in the
order the server returned them, with look-alikes such as six times
"database_backwards · django/db/migrations/operations/models.py", and
"handle · .../loaddata.py" could not be found.

The field now opens with a Suggested group (the start the page or the
projection chose, then the five best ranked flows in the server's order),
followed by every operation alphabetically by name and then path. Look-
alikes carry their class, "database_backwards (CreateModel)", with the
name first so the list still reads alphabetically; the line or the
position when the class does not tell them apart. Ranked flow starts have
no qualified name, so the look-alikes among them are named with one index
query by name and file, matched by node id; only plain identifiers enter
the query. A "Filter operations..." field before the select narrows both
groups and always keeps the chosen start.

The strings of the field moved to architecture/strings.ts. The "From"
select in SystemArchitecture is not rendered (Behavior returns the journey
before it) and is left as it was.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:43:35 +02:00
Bernhard Jackiewicz 3d51f86d43 fix(ui): make the Expand +1 warning true and show it at once
At two layers of JSONBAgg the tooltip said "Likely past the render
limit", then that growing like the last layer adds about 402 nodes (90
plus 402 stays far below 5,000), and that loading stops at the render
limit of 5,000 nodes, while the layer then ended at 5,548 nodes.

- The warning names the limit and the number behind it: the 9,031 calls
  the index counts at the 75 edge nodes, with the loaded count. The
  growth estimate only stands where it is the larger number.
- The limit sentence says what loading does: it stops after the first
  request that takes the layer past the node or edge limit, so the layer
  can end above it, is marked partial, and the scene draws up to the
  limit. The partial status and the blocked Expand say the same. The
  Explore mini-Galaxy loads without limits and the hint claims none.
- The text moves from a native title (shown after the browser's delay)
  to the Galaxy's own tooltip: at once on hover and keyboard focus, below
  the button, also in its compact +1 form, closed on leave, blur and
  Escape, with aria-describedby.
- Expand is blocked with aria-disabled instead of disabled, so pointer
  and keyboard still reach the reason why it is blocked.

handtest-fixes-galaxy.mjs K8 reads the text from data-hint and matches
the new wording.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:43:06 +02:00
Bernhard Jackiewicz 57090cbd2e fix(ui): let tooltips ignore fields of closed menus
Hint protected every input and select of the page, also those inside a
closed <details>. Their content is not drawn, but the browser still gives
it a box, so the closed Path to and Edge types menus of the Galaxy
toolbar pushed the Expand +1 tooltip from its place below the button
into the page header.

Only drawn elements are protected now: checkVisibility where the browser
has it, and the content of a closed <details> (other than its summary)
everywhere. The readability probe applies the same rule.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:43:06 +02:00
Bernhard Jackiewicz 282df0ac39 fix(ui): keep path labels off the hierarchy band title
In the hierarchy a path through the mixed-directions band laid its edge
label onto the band title (DEFINES on "Mixed directions · 55 nodes" for
JSONBAgg <-DEFINES- general.py -DEFINES-> __init__): path labels only
avoided the path and root names, never the band title.

Every edge label of the scene now avoids one shared list of texts, the
path names, the root marker names and the band title. When the usual
spots along an edge are all covered (a wide title across a steep edge),
the label tries the points where it just leaves an obstacle before it
settles for the least overlap.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:43:03 +02:00
Bernhard Jackiewicz 91d47cb187 fix(ui): make the Architecture Refresh buttons say what they did (A3)
"Refresh connections" read every route relationship again and nothing on
screen changed; Service map "Refresh", "Refresh analysis" and the
Behavior "Refresh" did the same. All four now share one control
(architecture/refresh-feedback.tsx): while the reading runs the button
reads "Refreshing …" and ignores a second press, afterwards a status
beside it names the time and whether anything changed ("Up to date at
13:29:43: no changes since the last load") or the error.

A refresh of the same index keeps the route connections on screen until
the new ones arrive instead of dropping back to "Reading …". The strings
live in architecture/strings.ts.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:31:37 +02:00
Bernhard Jackiewicz 5046bd266c fix(ui): ask the local model to answer in the language of the question (C4)
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:31:30 +02:00
Bernhard Jackiewicz 7b19d3c25b fix(ui): list callers apart from other incoming relationships, with readable totals (C2)
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:28:55 +02:00
Bernhard Jackiewicz 03bbf2c3aa fix(ui): tell the chat when a Galaxy layer stopped at the render limit (C1)
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:25:11 +02:00
Bernhard Jackiewicz 397b5dc68d fix(ui): put Architecture Back and Forward first, as in Galaxy, and close Recent menus (A1, A2)
Architecture showed bare arrows at the right end of its subtab row while
Galaxy has "← Back", "Forward →" and "▾" at the start of its toolbar.
The controls now come first in the row with Galaxy's words and tooltips;
the row measures itself with the shared toolbar fit and shows the glyphs
alone once the tabs would scroll.

The Recent menus of both workspaces stayed open over the content. One
shared hook (graph/use-dismissible-menu.ts) closes them on a press, wheel
or focus outside, on Escape (which no longer reaches the page), on a chosen
entry and whenever the place changes.

The K27 browser check counts an in-view "← Back" outside the shared
history group only, since the shared one now carries the same words.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:24:00 +02:00
Bernhard Jackiewicz 26bfbf5865 fix(ui): compare named identifiers with the given text case-insensitively (C3)
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:19:29 +02:00
Bernhard Jackiewicz 81e470bc89 fix(ui): keep Galaxy scene labels below its overlay panels
drei hangs every Html label of the scene into the canvas wrapper and gives
it a z-index from its zIndexRange (up to 10, agent layer up to 80). The
wrapper formed no stacking context, so those numbers competed with the
Galaxy overlays: the path target's name was painted over Selection
details (z-index 4) and the fit view button (3).

The wrapper now isolates its stacking context. The labels keep their order
among themselves, stay above the canvas, and sit below every overlay with
a z-index of 1 or more, in the Galaxy and in the Explore mini-Galaxy.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:19:17 +02:00
Bernhard Jackiewicz a93edb223d fix(ui): hide Change the output limit when the limit is at its maximum (C8)
Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:15:21 +02:00
Bernhard Jackiewicz 1d4c4ad125 test(ui): run the acceptance and architecture checks without a window
Both opened a visible browser window that took the foreground. Like the
Galaxy and chat checks they now run headless; --headed shows the window.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 13:02:04 +02:00
Bernhard Jackiewicz 6bd3bef65b docs(ui): record the hand test round K1 to K28 and its checks
Summary of the 28 hand-test findings, how they were checked on the final tree, and the known limits.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 05:24:23 +02:00
Bernhard Jackiewicz ea8c623c5d test(ui): measure the typed-then-Back window inside the page (K27)
Date.now() around click() also counted Playwright's own wait for the
button and exceeded 600 ms under load, so the check measured the case
after the pause. The page now records the last input and the click that
reaches the button.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 05:24:23 +02:00
Bernhard Jackiewicz 04255f6fb0 Merge completeness fixes: chat, agent and in-page project switch gaps (K1, K7, K12, K16, K24) 2026-10-04 04:42:09 +02:00
Bernhard Jackiewicz 035ebe5c7e Merge completeness fixes: galaxy completeness gaps (K2, K3, K5, K12, K13) 2026-10-04 04:42:09 +02:00
Bernhard Jackiewicz b824b34206 test(ui): browser checks for the K24 switch situations and the YAML facts
A switch with the chat closed, with an answer running, while the old
project still loads, and a log line written after it; YAML lists of
mappings in the file facts; the opened-area card counting the parts the
view counts. The check that deletes the cached model and downloads it
again during a switch runs only with --with-download.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 04:06:45 +02:00
Bernhard Jackiewicz f2f30e8751 fix(ui): keep the download progress across a project switch (K24)
A model download still running at a switch went to the dock of the new
project, but its progress stayed bound to the old dock, so the new
configuration showed an empty bar until the load ended. The progress of
a load now travels with the hand-over: the new dock shows how far the
download got and follows it from there.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 01:36:28 +02:00
Bernhard Jackiewicz 0bb4c3783f fix(ui): post each log line under the page it was written on (K24)
A project switch now stays in the page and only changes the address,
but the log buffer took the page once at start, so every line written
in cbm after a switch was filed under "/?project=django-demo". The
server stores one page per post. Each entry now keeps the address it
was recorded on, a batch ends where an entry of another page starts,
and a page that is going away sends the entries of each page it was on.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 01:36:05 +02:00
Bernhard Jackiewicz 83c62200fc fix(ui): count the parts outside an opened area in its card (K7)
The card of the opened django area said "Parts shown (18, largest
first)" while the view said "Browse map · 23 parts" and "23 parts · 100
connections": the 5 parts outside the area were left out of the count
and named only inside the connection list. The parts line now counts
what the view counts and names both groups: "Parts shown (23): 18 inside
the area, largest first: ...; 5 outside it: (root), docs, js_tests,
scripts, tests."

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 01:20:53 +02:00
Bernhard Jackiewicz 701ac90cfd fix(ui): count a YAML list of mappings as a list in the file facts (K12)
The keys of a list's items stand at the same indent as the keys of a
mapping, so the facts of django's .pre-commit-config.yaml read "repos
(10 keys: rev, hooks, rev, hooks, ...)" for a list of 5 items, under
"Read from the file; not generated by the model". A key that holds any
item is now a list: its items are counted and their keys are named as
item keys, "repos (list of 5; item keys: repo, rev, hooks)".

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 01:20:28 +02:00
Bernhard Jackiewicz b864f93371 test(ui): browser checks for the Galaxy completeness gaps (K2, K3, K5, K12, K13)
tools/handtest-fixes-galaxy.mjs now runs headless (Chromium channel, so
WebGL draws on the GPU; --headed shows the window) and adds:

- K5: at two layers around JSONBAgg no node the first incoming column calls
  or defines (index truth via query_graph) stands in an incoming column
  unless it also leads into one; outer outgoing nodes come from the first
  outgoing column; the band below holds every mixed node, its heading counts
  them and overlaps no name; every edge label carries a type and an arrow;
  one layer has no band; Aggregate at two layers (651 nodes) keeps the names
  of the root and its 34 direct neighbours with a visible note; call_command
  (554 direct neighbours) keeps its own name and its 11 callees.
- K12: in Explore with .github/workflows/new_contributor_pr.yml open, the
  mini-Galaxy has no overlapping label rects in the DOM with the chat closed
  and open, and every root in view keeps its name.
- K13: "Lines 42 to 65 · end of file" and 65 as the last drawn line.
- K2: "← Back" and "Forward →" at the full level, the arrows alone at the
  compact level, tooltips unchanged.
- K3: at the full level the root name is never squeezed below its text.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:40:23 +02:00
Bernhard Jackiewicz 7e73441881 feat(ui): spell out Back and Forward while the Galaxy toolbar has room (K2)
K2 planned "← Back" and "Forward →"; the buttons showed only the arrows,
the words were in the accessible name and the tooltip. At the full toolbar
level the buttons now read "← Back" and "Forward →"; in the compact, tight
and wrapped levels they keep the arrows alone. Accessible names and
tooltips stay as they were.

Seen in the browser: with the words, the scoped toolbar kept the full level
with the chat open at 1600 px while the root name shrank to "JS…", because
nothing stuck out. The full level now also needs the root name whole
(data-fit-whole); a name cut only by its maximum width does not count.
With the chat open the toolbar then takes the compact level and the root
name stands in full.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:40:15 +02:00
Bernhard Jackiewicz bd02f3f506 fix(ui): keep a Galaxy hierarchy truthful from two layers on (K5)
Completeness check of K5: from two layers on every node stood on its
parent's side, so the far-left "incoming" column of JSONBAgg held the
callees of its tests (len, str, print) and the classes general.py defines,
next to real callers. The edge labels merged fans into "CALLS · TESTS ×8"
without a direction, and above 150 nodes no name was drawn at all.

- A node stands in an incoming or outgoing column only when the whole chain
  from the root runs one way: left, each node points at its neighbour closer
  to the root; right, the other way round. Nodes reached through both
  directions (a callee of a caller, another caller of a callee) stand in a
  band below the columns, centred under the root, inside a dashed frame
  with the heading "Mixed directions · N nodes" on its top edge.
- Every line carries its own label with its types and an arrow from source
  to target as the picture shows them ("CALLS · TESTS →",
  "DEFINES_METHOD → · ← USAGE"); no fan is merged any more. A label stays on
  its line or right beside it, avoids the band heading, and its measured
  size follows its text, not the node pair, whose ids change with every
  picture.
- Above 150 nodes the root and its direct neighbours keep their names, single
  columns and edge labels. A root with more direct neighbours than that
  keeps its own name and the side that fits (call_command: its 11 callees).
  A note in the picture says who carries names and what brings the rest
  back; the hint and the legend describe the band and are right for every
  depth and trace direction.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:40:05 +02:00
Bernhard Jackiewicz 33c3098f68 fix(ui): keep the root names in the Explore mini-Galaxy apart (K12)
Hand-test finding K12 (the mini-Galaxy part): with
.github/workflows/new_contributor_pr.yml open in Explore, the file scope
marks its six definitions as roots, and every root marker carried its name
fixed under its ring. In the 419 x 186 px panel "permissions",
"new_contributor_pr.yml", ".github/workflows/new_contributor_pr.yml" and
"jobs" lay on top of each other.

The same rule as for the edge labels of a path and of the hierarchy now
applies: a name stands at a free place or not at all. Every few frames each
root name takes the first place around its own ring (under, above, right,
left, one row further out) that overlaps no other name and stays inside the
canvas; among those, the one that covers the least of the other rings. A
name under or above its ring near the edge moves sideways into the canvas
while it still spans the ring. A name with no free place is hidden; the
hover card of its node still names it. A single root keeps its name under
the ring as before. The place is on the marker as data-name-slot.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:38:57 +02:00
Bernhard Jackiewicz 90de5135be test(ui): acceptance G7 also measures the toolbar with the chat open (K3)
K3 asked for the acceptance check G7 to cover the open chat as well; it
measured only with the chat closed at 1600 px, where the toolbar never
wrapped. G7 now measures the scoped Galaxy toolbar with the chat closed and
then open at 1600 px (bar about 1170 px), counts rows by the centres of the
toolbar's own items, and passes only when both measurements are one row
without overflow. The chat is closed again for the checks that follow.
A small vitest guard reads the G7 section and keeps both measurements in it.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:38:34 +02:00
Bernhard Jackiewicz 2e6db07017 fix(ui): end the source pager at the file's real last line (K13)
Completeness check of K13: at the end of django/contrib/postgres/aggregates/
general.py the pager read "Lines 42 to 66 · end of file" and drew an empty
line 66, while the file has 65 lines and the title of the disabled "Next
lines" already said "Line 65 is the last line of this file." The Module
range counts the empty segment after the final line break. On the last page
that segment is no longer drawn and the range ends at the real last line,
so range text, drawn lines and title agree. A file that ends without a final
line break keeps its last line.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:38:29 +02:00
Bernhard Jackiewicz 1a60ba8352 test(ui): browser checks for the in-page project switch and the chat gaps (K24, K16, K12, K7, K1)
Extends the chat stream script of the hand test (tools/handtest-fixes-
chat.mjs) with the points the completeness check of 2026-10-04 found
open:

- K24: django-demo with the agent active, a selection and a listed
  answer, then cbm and django-demo through the project switcher, then
  Back and Forward. Each leg measures that the page did not reload, no
  model worker was created and nothing was prepared again, the lamp
  reads "Agent active" at 0, 250, 1000 and 3000 ms, the workspace stays,
  the chat shows the new project's history, and no request sent once
  the address named the new project names the old one. After each
  switcher leg all twelve views (Explore, Galaxy, Architecture Overview,
  Entry points, Service map, Endpoints, Hotspots, System structure,
  Behavior, ADR, Coverage, System logs) carry no marker of the old
  project and are compared with a fresh page load of the new one. The
  auto-load tooltip is read too.
- K16: three word orders with "wo" are listed, four misspelled names are
  offered for the selection with the right wording; none reaches the
  model.
- K12: the workflow's automatic card is facts only and offers "Ask the
  model"; asking marks the model text as generated; tox.ini,
  pyproject.toml and README.rst show facts only without a model call.
- K7: the django area opened with nothing selected lists its lines,
  languages, parts, hotspot findings and connections.
- K1: an automatic explanation cut at 32 output tokens names both
  limits.

The browser runs headless unless --headed is given; ANGLE on Metal gives
it the GPU with shader-f16 the local model needs.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:33:33 +02:00
Bernhard Jackiewicz 090cf0d941 fix(ui): name the input limit in the note under a cut automatic explanation (K1)
Hand-test finding K1, minor point of the completeness check of
2026-10-04: the note under an automatic explanation that ran into its
token limit named only the output limits. It now names both limits of
automatic explanations and of a chat question: "Automatic explanations
stop after 128 output tokens so they stay short, and read at most 1,536
input tokens of source and facts. A question in the chat may read up to
2,048 input tokens and answer with up to 512 output tokens."

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:33:32 +02:00
Bernhard Jackiewicz a3224f7db1 fix(ui): describe an opened Architecture area with nothing selected (K7)
Hand-test finding K7, Architecture part (completeness check of
2026-10-04): an area opened in the Overview with nothing selected inside
it (the hand test opened "django" at 17:55) was explained by a single
fact, "Opened: django", because the view published only the path.

SpatialArchitecture now publishes what it shows of an opened area, file
or hotspot area: its measure, the parts shown with their files and
indexed lines, its hotspot findings and the connections of its parts,
with the areas outside it named so. The chat lists them as facts: the
opened area, indexed lines and languages, "Parts shown (N, largest
first)", the hotspot findings and "Connections of its parts". Without
source the facts are the explanation and the model is not asked, as for
a selected area.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:33:17 +02:00
Bernhard Jackiewicz c46b3b22b9 fix(ui): explain configuration and text files by their facts only (K12)
Hand-test finding K12, prose part (completeness check of 2026-10-04): the
automatic Explore card of the open workflow still added model text that
went beyond the file ("allows us to interact with GitHub repositories
directly from the command line"); the names-not-in check only catches
identifiers.

The automatic card of a configuration, data or text file (YAML, JSON,
TOML, INI and its relatives, .env, properties, Markdown,
reStructuredText, XML, ignore and attribute files) is now the facts read
from the file and nothing else, marked "Read from the file; not generated
by the model." The model writes about the file only on request: "Ask the
model" on the card (its text stays marked as generated and is left out
when it names what the file does not show) or a question in the chat
(with the names-not-in note as before).

browser-ai/file-facts.ts reads the facts without a parser library: the
kind and length of the file; a workflow's name, triggers, jobs and
actions as before; the top-level keys of YAML and JSON with what they
hold; TOML tables and INI sections with their key counts; the title,
sections and code blocks of Markdown; patterns of ignore files; the root
element of XML. A marked part is named as that part, a cut excerpt only
by its kind and the note on what was left out. The same facts go into the
prompt of a question about the file.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:32:44 +02:00
Bernhard Jackiewicz ecf8618bd2 fix(ui): offer the selection for a misspelled caller question and read "wo" as a question word (K16)
Hand-test finding K16 (completeness check of 2026-10-04): two kinds of
uncertain caller questions still went straight to the model.

A typo in the selected name ("wer ruft JSONBAg auf", "wer ruft jsonbgg
auf?", "who calls jsonbag", "callers of jsonbag") was recognized as a
caller question, rejected as a question about another symbol and never
offered. A subject up to two edits from the selection's name (one for
names of four to six letters, none below), in any case, now gets the
suggestion with the listed answer one click away, and the reply says that
the name, not the question, is what is uncertain. An exact name of another
symbol in the scope stays that symbol.

"jsonbagg wird wo aufgerufen" took "wo" for the subject. Question words
(wo, woher, wohin, wann, where, when) are never a subject now, and the
name may come first ("JSONBAgg wird wo überall aufgerufen", "... wird
aufgerufen von wem", "jsonbagg is called by whom"). The words between name
and verb may carry umlauts.

Table-driven tests cover 26 word orders and 21 misspellings in German and
English and the questions that must still go elsewhere.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:32:08 +02:00
Bernhard Jackiewicz 3b909a06b6 fix(ui): switch projects in the page and keep the loaded agent (K24)
Hand-test finding K24 (completeness check of 2026-10-04): a project switch
still reloaded the whole page (window.location.assign). The worker with the
loaded model went with it and the lamp showed "Agent loading" for about
3 s while the next page loaded the model again from the cache.

A switch now stays in the page (app/project-windows.tsx): the address
changes with pushState, Back and Forward switch the same way (popstate),
and each project gets a fresh window, the same tree under a new key. Every
panel starts from fresh state as after a reload, so no workspace can show
the old project, and the window's RPC and /api requests carry a signal
that aborts once the new window is mounted. The window hands its
successor only what it reports: the workspace in view, whether the chat
is open, and the agent's lamp and model name.

The chat dock of the old project hands its worker to the dock of the new
one (browser-ai/agent-handover.ts) inside the switch, before the new
window renders, so its first frame is already loaded: no new worker, no
second load, no "off" or "loading" frame. A running answer is stopped and
settles before the new project uses the model; a model still loading
finishes loading there. A model no dock takes is unloaded when the switch
ends, and an unmount outside a switch unloads as before. The sessionStorage
resume note (agent-resume.ts) is gone. The first project of a window is no
switch for the dock, so it keeps a model it was handed while the project
resolves.

The auto-load tooltip now says what happens: a switch keeps the model in
the page, the option only matters when the page is opened or reloaded.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-04 00:31:29 +02:00
Bernhard Jackiewicz 80dd23d5a3 Merge hand-test fix: Architecture back and forward on the shared history (K27) 2026-10-03 23:04:45 +02:00
Bernhard Jackiewicz e617e70e4b test(ui): browser check for Architecture cameras, call chain and typed filter (K27)
The K27 browser run now also checks that System structure and Behavior show
no Back of their own, that Plan or 3D in System structure and Behavior is a
step Back restores, that the Behavior path and the operation on the call
chain come back after Back and Forward, and that text typed in the Routes
filter survives an immediate Back. Screenshots reset every scrolled
container so each one shows the subtabs and the history controls.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-03 23:02:58 +02:00
Bernhard Jackiewicz 8e6edc81f6 fix(ui): keep Architecture cameras and call-chain position in the history (K27)
Review follow-up for K27:

- The opened Overview area or file reaches only Overview, and the hotspot
  area only Hotspots. Endpoints, Entry points and Hotspots no longer draw
  or report an area opened in Overview, so the chat context names nothing
  that is not on screen.
- Plan or 3D in System structure and in Behavior is part of the entry and a
  step, as on the shared map. The Behavior path to a destination is a step;
  the operation on the call chain and the page of direct calls stay with the
  entry without being steps, so Back and Forward return to them.
- The in-view "Back" buttons of System structure and Behavior are absorbed
  into the one Back beside the subtabs.
- Back, Forward or a Recent jump while typing in the Routes filter first
  records the typed text as a step instead of dropping it.
- replaceNavigation also merges with the step after it, so no two equal
  steps end up next to each other.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-03 23:02:53 +02:00
Bernhard Jackiewicz d354983e84 test(ui): browser check for Architecture back and forward (K27)
tools/handtest-fixes-k27.mjs drives the hand-test flow on django-demo in a
headless browser: Overview, open django, Routes, Endpoints, open the /edit
route group, System structure, expand a group, Behavior, start handle in
loaddata.py, follow a call. It then goes back step by step to the start and
forward again, checking at every step the subtab, location trail, route
perspective and filter, system focus and expanded groups, Behavior start
and the Back and Forward tooltips. It also checks Alt+Left and Alt+Right
(and that they do nothing while typing in the filter), a jump from Recent,
that a new navigation after Back drops Forward, that Alt+Left in Galaxy
leaves the Architecture history alone, and that switching to cbm starts a
fresh history. Every step writes a screenshot and index.md.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-03 22:25:26 +02:00
Bernhard Jackiewicz 9901f9776f feat(ui): Architecture back and forward on the shared history (K27)
Hand-test finding K27: Architecture had scattered ways back with different
meanings (the Overview trail, a "Back" in System structure that walked the
focus, a "Back" in Behavior that walked the starts) and no way back from
"Show these N routes". Nothing went forward.

Architecture now keeps one place (subtab; opened area or file and Plan or
3D; route perspective and filter; System structure focus and expanded
groups; Behavior start, destination and where followed calls began) and
records it in the bounded model Galaxy uses (graph/navigation-history.ts),
with the same rules: at most 25 steps, consecutive duplicates merge, a new
navigation after Back drops the forward branch, no pushState, a Recent list
of 8 places, Alt+Left and Alt+Right only in the active workspace and not
while typing or while another surface takes the keys, a fresh history per
project.

Back, Forward and Recent sit beside the subtabs; their tooltips name the
target ("Back to Overview · django"). The old "Back" buttons in System
structure and Behavior stay in place and take the same step. "Whole system"
and the Overview trail stay as ordinary steps.

Architecture adds three refinements: typing in the route filter becomes one
step once it pauses; a choice the page makes itself (the suggested Behavior
start, a reset after reindexing) replaces the current step
(replaceNavigation), so Back never bounces on it; and the current step
keeps the newest details of its place (refreshNavigation), so a step whose
suggested start was rejected for a stale snapshot is still named after the
start the journey shows.

The views read their part of the place from the workspace and report
changes back; rendered on their own, as in their unit tests, they keep it
as their own state and offer no Back. A new tab row class avoids the
existing atlas-arch-bar meter. The concept doc now covers both workspaces.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-03 22:25:26 +02:00
Bernhard Jackiewicz 844d4129c1 test(ui): accept grounded explanations and wait for route evidence
The automatic explanation now lists the indexed facts itself and sends
the model only the source (K7, K14): check the card facts against the
index and the source in the prompt instead of caller names in the prompt.
Endpoints are measured after the route evidence is read.

Signed-off-by: Bernhard Jackiewicz <bj@techport.io>
2026-10-03 21:46:35 +02:00