Skip to content

map: connections read as a route, and zoom shows more instead of bigger - #143

Open
Yushangjinghong2 wants to merge 23 commits into
devfrom
feat/map-design-20260920
Open

Yushangjinghong2 wants to merge 23 commits into
devfrom
feat/map-design-20260920

Conversation

@Yushangjinghong2

@Yushangjinghong2 Yushangjinghong2 commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator

The map looked unfinished in three ways, all seen on the stable web trial (iclr-eval-v5-0917-0359).

Connections were invisible. A map without recorded dependencies has only "the order work happened in" between its cards, and that was drawn as sparse grey dots. It is now a continuous slate line that strengthens toward the card it arrives at, with a small anchor where it leaves its card and a lighter swept arrowhead. The dash is kept for "related work", which is an association and not a path. Step links inside an open card use the same line.

One view mixed three kinds of card. Each card chose its overview tier from its own on-screen width, so headed cards sat next to bare grey tiles. The tier now comes from the zoom alone.

Zooming was ugly. Between overview and detail a card was its small layout magnified: 40px type, the title cut off under the toolbar, the footer spilling out of the frame. Type now lives in a band of screen sizes (a 13–18px title), so a larger card says more at the same size. Content is clipped inside the card, and the title ends on a whole line that fits the card's height.

Also: card chrome (hairline, corner, state rail, shadow) is measured on the screen and is the same at every zoom; a card that keeps earlier parts shows a second sheet behind it; zooming into open canvas no longer enters detail mode with no card in focus, which dimmed the whole map around nothing.

The new look is stated in one stylesheet, frontend/web/src/map/design.css, loaded last. Layout, geometry and the camera's framing are unchanged.

Later rounds on this branch

Ink on paper. The palette, serif titles, paper grain, ink washes and far hills, a brushed stroke for each route (brush.ts), a course row on each card (plan, execution, review, result), a segmented progress bar in the header, frosted controls.

A small card says what its task is about, with a line budget computed from the room it has, so nothing is sliced through.

Zooming is smooth again. The redesign had cut zooming to a quarter of its frame rate. Same harness, 72 wheel ticks in headless Chromium on a ten-task map:

build fps frames over 50 ms layout style
dev before this branch 50 5 0.8 s 2.6 s
PR #119 46 7 1.0 s 2.5 s
this branch before the fix 12.5 196 6.4 s 4.4 s
this branch now 45–46 7–8 0.3 s 1.3 s

Type and chrome were sized against the live zoom, so every card was laid out again on every frame. They are now sized against the zoom in quarter-octave steps (zoomStep.ts), and a moving map keeps the step it had: a gesture scales one picture, and text is set again when the movement rests. The live zoom is no longer published as an inherited custom property. The washes lost their 36px blur, grain and hills lost their blend modes and filters, labels lost their backdrop blur, and frosted panels turn to paper while the map moves.

A line says what it carries. Every line at overview read "same study". A line that can only name its kind now shows those words when the reader points at one of its tasks. For the rest, POST /api/map-lines/{source}/{name} (argus/webapi/map_lines.py) takes the pairs of tasks the map draws and has the map model write, once per map, what one task handed the next ("figures and tables for the paper"), or nothing where the records show no connection. A note annotates an existing line and never adds one or changes its kind, so the layout does not depend on it. One pass on a ten-task map: about 3.5k tokens in, half a cent, 30 s with gemini-3.8-flash; usage is recorded under map-summary. The trial portal's allow-list and analytics route templates know the new path.

A task reads as its stages again. Inside a task every stretch of tool activity had become a card of its own ("40 steps of work", "said what comes next"): a one-round task was twelve cards and nearly every link between them said "then". Tool activity is now folded into the round of work or review it happened in (the card's footer gives the count, opening it lists the actions), so a task is again goal, plan, work started, a round, its review, the changes asked for, the next round, the result, with the relation named on each link. Steps are named by their stage; a failed tool call no longer turns a step red; a finished task no longer shows "in progress" on the moment it was planned or taken up. Tests: submap.test.ts (folding, a round under way, activity with no round), submapReadability.test.ts; documentation in docs/research-map.md.

A card says what its task found, in the reader's language. A task's full explanation is written only when a reader opens it, and not at all once the project's daemon has stopped, so cards showed the planner's text: an imperative English title, the first words of a specification, and the execution's state three times. POST /api/map-cards/{source}/{name} (argus/webapi/map_cards.py) has the map model write a short title and a sentence per task in one request per map, from the task's goal and the last record its work left (about 3.5k tokens, half a cent, 7-20 s for ten tasks with gemini-3.8-flash; recorded under map-summary). The full explanation stays on demand and takes over the card once it exists. With words on it a card no longer prints the specification under the title and says its state once. A step's detail no longer shows harness instructions or raw JSON arguments and lists eight actions with a count of the rest. Tests: tests/webapi/test_map_cards.py, macroCardCopy.test.tsx, submap.test.ts; documentation in docs/research-map.md.

A stopped project can still be explained. An explanation is still written only for what a reader opens, but no longer held back when the project's daemon is not running (on a trial, every project). With gemini-3.8-flash the writing then failed about half the time because a brief section came back as an object of named parts; that shape is now put right before the schema check (the model's own paragraphs, joined; length limits still apply). Tests: mapCopyLifecycle.test.tsx, tests/webapi/test_reader_brief_shapes.py.

Card words and line notes are sized for the reader's language. They were already written in the interface's language and kept per language, but the limits were sized for Chinese and applied by cutting ("Formulate three long-context LLM researc"). Limits and the lengths asked for are now per language, the schema is wider than what is shown so one overlong phrase does not discard the rest, and text that overruns ends at a sentence, clause or word, never inside a word or a number. Tests: tests/webapi/test_map_cards.py, tests/webapi/test_map_lines.py, relationLabels.test.ts.

Tests added: zoomStep.test.ts, mapLineNotes.test.ts, mapBrush.test.ts, updated relationLabels.test.ts; tests/webapi/test_map_lines.py (one write per map, omitted pairs remembered, a settling task re-asks only its lines, failed attempts cool down), tests/trial/test_map_lines_route.py (portal allow-list, analytics route template). Documentation: docs/research-map.md describes line notes and the stepped zoom.

Checked: tsc clean, web suite 1544 passed, tests/webapi and tests/trial passed, check_artifacts matches 0.1.8; light, dark and phone screenshots against a copy of the trial sessions; the zoom harness above against the deployed build.

🤖 Generated with Claude Code

lbx154 and others added 22 commits September 20, 2026 10:01
The map looked unfinished in three ways (stable web trial, iclr-eval-v5):

- The order work happened in, which is every edge of a map without recorded
  dependencies, was drawn as sparse grey dots and read as noise. It is now a
  continuous slate line that strengthens toward the card it arrives at, with
  a small anchor where it leaves and a lighter swept arrowhead. The dash is
  kept for "related work", an association rather than a path. Step links
  inside an open card use the same line.
- Each card chose its overview tier from its own width, so one view mixed
  headed cards with bare grey tiles. The tier now comes from the zoom alone.
- Between overview and detail a card was its small layout magnified: 40px
  type, a title cut off under the toolbar, a footer spilling out of the
  frame. Type now lives in a band of screen sizes, so a larger card says
  more at the same size; content is clipped inside the card, and the title
  ends on a whole line that fits the card's height.

Chrome (hairline, corner, state rail, shadow) is measured on the screen, so
it is the same at every zoom. A card that keeps earlier parts shows a second
sheet behind it. Zooming into open canvas no longer enters detail mode with
no card in focus, which dimmed the whole map around nothing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Two things taken from the 0.1.3 map (the version PR #119 is built on), which
a later simplification had dropped: every card shows the course its task
ran, and the sheet has a head. Then a visual language for the whole map.

- The course: four marks on a task card (planned, carried out, reviewed,
  delivered), inked where the record holds a step of that kind. At overview
  they are four beads, so a whole map shows at a glance which tasks were
  reviewed and which stopped short; with room they carry icon and label.
- The head: a letterspaced kicker over the session's name, and one thin bar
  ahead of the status sentence that shows how the tasks divide.
- Ink on paper. The restraint is Apple's: whitespace, one frosted material
  for every control, hairlines, soft depth. The vocabulary is ink
  painting's: a paper ground with a felt grain, washes of diluted ink and
  far hills where coloured light drifted before, serif titles, and the
  mineral pigments of that tradition (malachite, indigo, vermilion,
  gamboge, ochre) spent only on state. Night ink is the dark theme.
- A route that is a path is drawn as a brush stroke: set down lightly,
  gaining weight, pressed once and lifted to a point. It shows where it is
  going along its whole length and needs no arrowhead. An association keeps
  its dashed line. `brushStroke` builds the outline from the route's samples,
  resampled by arc length.
- The legend gains the line most maps are made of, the order of work, and
  the dashed swatch's tooltip now describes the dashed line. The minimap and
  the deliveries button speak the same palette.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Seen on the stable web trial after the ink map went out. With the sidebar
open the overview runs at a lower zoom, and a card kept its course beads at
the cost of its title: task 02 read "Author…". And where the 0.1.3 map gave
every card a line of explanation, ours had none at overview, because the
excerpt was the last thing to be given any height.

A card now counts the whole lines it has room for and spends them in the
order a reader from outside the team needs: two lines of title, a line of
explanation, the course beads, then more of each. The explanation at
overview is the task's own (the generated summary, else its objective, else
the tidied record). The notice that an execution ended short of the goal
reads the same on every such card and filled the map with one repeated
sentence; it stays on the larger card, where the state mark already carries
it at overview.

The team branch pill joins the sheet: paper, hairline, pigment rail, serif.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rder

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Relation labels were hidden below half scale, and a map is normally read at
0.1 to 0.3. So what connects two tasks ("模型集成前置", "同一计划") was only
ever seen by zooming in on the line itself, and the map read as having no
stated relations at all. The 0.1.3 map behaved the same way; this is not a
regression, it was never visible.

- Labels are placed through the overview in twentieth-step zoom buckets, and
  give way only below 0.05 where cards are down to a title. Placement still
  drops a label that fits nowhere, so none is laid over a card.
- A label that states a relation (a dependency, related work, a changed
  plan) claims its place before one that only says two tasks share a study.
- A stated relation is a small slip of paper on the line; the order of work
  is a quiet annotation, so a map of chronological edges is not a row of
  identical chips. Type stays inside the box the collision pass reserves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…abels

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Zooming the redesigned map ran at a quarter of the frame rate it had before
the redesign (12 fps against 50 in the same harness). Three things did it,
all mine:

- Type and card chrome were sized against the live zoom, so every card was
  laid out again on every frame. They are now sized against the zoom in
  quarter-octave steps, and a moving map keeps the step it had: a gesture
  scales one picture and text is set again when the movement rests, or once
  the picture has drifted two steps small or three large.
- The live zoom was published as an inherited custom property, which restyled
  the whole map each frame whether or not anything read it. Only the step is
  published now.
- The ink washes carried a 36px blur on large drifting layers, the grain and
  the night hills used blend modes and filters, and every label and panel had
  a backdrop blur. Washes get their softness from the gradient, grain and
  hills are drawn in their own colours, labels are plain paper, and the
  frosted panels turn to paper while the map moves.

Every line at overview read "same study". A line that can only name its kind
now says so when the reader points at one of its tasks, and the lines that
have something to say are asked for it: POST /api/map-lines takes the pairs
the map draws and has the map model write, once per map, what one task handed
the next, or nothing where the records show no connection. A note annotates
an existing line and never adds one or changes its kind, so the layout does
not depend on it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… line notes

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The notes were gated on the project still running, like card explanations.
A finished map is the one that gets read, and its lines are written once, in
one small call, so the gate only kept them from ever appearing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…shed projects

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Inside a task, every stretch of tool activity had become a card of its own
("40 steps of work", "said what comes next"), so a one-round task was twelve
cards, the stages of the work (goal, round, review, changes asked for, next
round, result) were lost among them, and the links between cards, which name
a relation only between adjacent stages, had nothing left to say but "then".
The map from before that change (PR #119's base) read better for exactly
this reason: one card per stage, a named relation on every link.

- Tool activity is folded into the round of work or review it happened in.
  The round's card says how many actions it holds; opening it lists them
  after the round's own record, without repeating what that record says.
  Where there is no round (a single-agent turn) consecutive stretches are
  one step.
- A round still under way is titled and summarised by the latest thing its
  agent said.
- A failed tool call is marked on its line and no longer turns the whole
  step red; being put on the plan and being taken up are moments, so a
  finished task no longer shows them as "in progress".
- Steps are named by their stage (task goal, work started, this round's
  work, review passed / another pass asked for, changes asked for, result of
  the work) and links by their relation, with wording for entering a round,
  a review followed straight by the next round, and a task taken up again.
- A column that continues a round says which part it holds.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…k interior

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PR #119's map read well at a glance because every card carried a written
title and a sentence. Since then the explanation of a task is written only
when a reader opens it (it grew into a full lesson, and costs accordingly),
and not at all once the project's daemon has stopped, which on a trial is
every project. So the cards showed the planner's own text: an imperative
English title, the first words of a specification, and the state of the
execution said three times.

- POST /api/map-cards has the map model write, in one small request per map,
  a short title and a sentence or two per task, from the task's goal and the
  last record its work left (a task's `summary` is as often a harness note).
  About 3.5k tokens and half a cent for ten tasks with gemini-3.8-flash. The
  full explanation stays on demand and takes over the card once it exists.
- With words on it, a card no longer prints the specification under the
  title, and says its state once, on the chip. An explanation written before
  an execution ended short of its goal still may not head the card; the
  map's words, written knowing how it ended, may. A reader's own turns keep
  the reader's words.
- A step's detail no longer shows harness instructions ({"wait_for": ...})
  or raw JSON arguments, and lists eight actions with a count of the rest
  instead of all hundred.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
An explanation is written only for what a reader opens. It was also held back
whenever the project's daemon was not running, which is when a map is read
most: on a trial every project is stopped, so opening a card never produced
an explanation at all. Writing one is a separate read-only turn and needs no
daemon, so the hook no longer asks; nothing is written for a card that is
merely on screen or focused, as before.

Trying it on a stopped project with gemini-3.8-flash showed the writing then
failing about half the time: the model returns a section of the reader brief
as an object of named parts ({"name", "restriction", ...}), the way `concept`
is shaped, where the schema asks for one text. The brief already tolerated
one such shape, but only after the schema check had rejected it. The shape is
now put right before the schema sees it (the model's own paragraphs, joined
in its own order; the schema's length limits still apply), and anything else
still fails as an invalid brief.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…opped projects

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
They were already written in the interface's language and kept per language,
but their limits were sized for Chinese and applied by cutting: an English
reader got "Formulate three long-context LLM researc" as a title and "Method
contract an" beside a line.

- Titles, sentences and line phrases have per-language limits, and the prompt
  asks for the length in that language only (sixteen characters or eight
  words; ten characters or a two-to-three-word noun phrase) and says to write
  in the reader's language whatever language the records are in.
- The schema is wider than what is shown, so one overlong phrase does not
  throw away every other card's words; text that overruns is ended at a
  sentence, clause or word, never inside a word or a number ("38.31%").
- A line's pill is wide enough for an English phrase, and its width estimate
  matches the bold serif it is set in. Relations stated by an explanation get
  the same per-language label length.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…words

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…mand

Stop generating explanation snapshots and redundant relation evidence. Keep cached explanations and old questions readable, and retain task records only when a reader asks about a selected explanation. Preserve click-to-read generation and expose preparation failures without silently rewriting explanations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 072ba9df-603c-4f3e-bcb7-59385fd508ef
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 072ba9df-603c-4f3e-bcb7-59385fd508ef
@Yushangjinghong2

Copy link
Copy Markdown
Collaborator Author

Completed the reader cleanup in ef418ad; release artifacts are in 368e8c0.

  • Removed reader provenance disclosures and stopped generating card source snapshots and redundant relation evidence.
  • Added on-demand question context: opening the map or reading an existing explanation does not retain a source; selecting Ask about this step prepares only that explanation and the current task records. Existing saved questions remain readable.
  • Kept full explanation generation behind an explicit reader action, including stopped projects, and preserved language-specific card/line copy.
  • Added visible API errors and context-switch race coverage instead of silently regenerating explanations.

The existing trial is deployed at 368e8c0. Browser verification confirmed no provenance UI, no background full-explanation/source calls on overview, successful question preparation for the selected task, legacy cache responses without the removed fields, and an explicit 422 for a missing explanation. For the same five cached cards, the map-copy response decreased from 67,855 to 37,068 bytes without regenerating their explanations.

Validation: frontend typecheck and all 1,502 frontend tests pass; 198 targeted backend tests pass; release build/artifact checks pass. The broader backend suite is not wholly green: gateway concurrency/deadline and socket-forwarding timeout cases failed outside the changed code. Their failures were not hidden or addressed with unrelated changes.

…e tools

Keep historical review failures distinct from scientific rejection and link final delivery. Remove zoom-dependent card text collapsing. Replace live reviewer prose parsing and the extra interpretation call with native review actions, preserving waiting and venue acceptance semantics. Refresh release metadata and bundled frontends.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5f36246b-910c-4964-99da-28bf7892c6a2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants