Skip to content

feat: Reach the MCP endpoint and read a review as a page - #1

Merged
nfebe merged 27 commits into
mainfrom
feat/review-page-and-mcp
Aug 30, 2026
Merged

feat: Reach the MCP endpoint and read a review as a page#1
nfebe merged 27 commits into
mainfrom
feat/review-page-and-mcp

Conversation

@nfebe

@nfebe nfebe commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

The agent proxies MCP through to the core, so a coding session is pointed at the one address that is always up and knows which port the core landed on this time. The core is told a second address for reaching back, because the one a person clicks is loopback, and inside a container that is the container.

Routes are paths rather than fragments after a hash, so a link somebody is handed opens, pastes and bookmarks like any other. Anything that is not a file answers with the page, and a missing asset still answers with nothing.

Everything the core says about a review now survives the trip through here. Responses are decoded into a struct and encoded again on the way out, so the commits a branch is ahead by and the code a suggestion replaces were dropped in silence, and the page drawing them looked empty rather than broken.

A review reads as a pull request does: the branch leads the header with the verdict beside it, the summary opens the overview, commits have a tab, and what it was read against sits with the tabs. Reviews and knowledge can be looked at across every repository at once.

Checks run for the first time here. The view is checked out beside the design package it depends on by relative path, and built before the binary, because the binary embeds it.

Companion to sourceant/sourceant#128 and sourceant/design#1, both merged.

nfebe added 26 commits August 28, 2026 21:34
The agent is the process that stays up on a developer's machine. It starts
the indexer on a free port, waits for it to answer, and starts it again when
it dies, backing off as failures repeat. Stopping the agent stops everything
the indexer started, not only the process it launched directly.

Its own surface reports whether the indexer is answering and how many times
it has been started, and reads the repositories and graphs the indexer holds.
Clients talk to the agent rather than to the indexer, because the agent is
the half that is always up and the half that knows where the indexer landed.

It never parses code. The grammars and the graph shape stay in one place.
The agent now serves a graph view alongside its API. Assets are embedded in
the binary, so it works with nothing to download and cannot drift from the
agent serving it.

What opens is the repository's shape: its folders and its files, every one
named. Symbols, imports and the test suite are there to be asked for, because
a repository's every function is a texture rather than a picture. Four
layouts, a search that dims everything it does not match, and a panel for
whatever is clicked.

The index stores no folders. Files hold their symbols and their imports and
nothing holds the files, so drawing the index as stored scatters a repository
into one island per file. The folders here are read out of the paths the
index already carries, and are marked as this view's arrangement rather than
as something that was found.

Colours and tokens are the shared ones, so every surface reads as one product.
The agent now reads what the installer put on this machine and starts that,
rather than expecting the core on PATH. A container and a program need
different command lines for the same thing: a container binding loopback
binds its own, which nothing can reach, so it binds every interface inside
and is published to loopback outside.

It also runs a container as whoever installed. The image has a user of its
own, and where that id differs, everything the container writes into the
mounted index belongs to somebody who does not exist on that machine.

With nothing installed it still looks for the core on PATH, which is what
somebody working on the core itself already has, and naming one explicitly
still wins over both.
The graph is now one section of an app rather than the whole of it. Header,
tabs, cards, badges and buttons follow one design system, so every surface
reads as one product.

Four sections. What is on this machine, the folders being read, the graph,
and what is known about the code. Folders can be added, dropped and re-read
without touching a terminal: a browser will not tell a page the absolute path
of a folder somebody picked, so the agent lists the machine and the page
navigates what it lists.

Knowledge is the same store agents reach over MCP, for a person instead: the
decisions, conventions and constraints behind the code, written down where
they will be read.

The graph now labels each link at its midpoint.

The container runtime can now see the repositories it indexes. Your home is
mounted at the path it already has, which is what lets one registry of
absolute paths mean the same thing whichever runtime reads it.
The local view is Vue now, built by Vite into what the binary embeds. It uses
one set of tokens and components rather than copies of them: the same
Card, Button, Badge, Avatar and Logo, lucide for icons, force-graph in 2D and
3d-force-graph for Tree, Radial, Layered and Force.

Copying a design by hand is what let the two drift apart. The mark was a glyph
somebody drew instead of the ant, the navigation used names nothing else uses, the theme sat on a bare button rather than under the account, and
every mode but the flat one had quietly stopped being three-dimensional.

Navigation covers what a machine has. Anything needing a pull request or
another person is absent, because nothing on a machine produces one.

Nobody signs in to their own machine, so the avatar is generated from the
machine's name. It is there because the shell has a shape people know, not
because there is an account behind it.
Nodes sized by how much meets at them, named only where a name is worth the room, coloured by which
part of the repository they belong to, lines fading as there are more of them,
and every seat remembered so a refetch settles rather than restarting. Six
modes, and the ones past the first are three-dimensional as they are there.

What was here before force-simulated everything into a blob, which reads as a
cloud of parts rather than as something with a direction.

Navigation is Overview, Knowledge, Graphs, Repositories, Settings.

The parts rail, the search, the focus and the depth walk all come with the
workbench. The inspector beside it does not: it reads advisories and repository
contexts, which need a workspace and another person.
Comments and prose named things that are not this repository's to name, and
described its surfaces in terms of ones nobody reading here can see. What is
true of this code is said plainly instead.

Also drops a module the workbench replaced, and reads a file's kind directly
now that the index answers with it.
The button worked and looked broken, which amounts to the same thing. It asked
for an update, so a repository nobody had touched reported nothing and the page
did not change; there was no way to tell that from a button doing nothing at
all. It now says what the reading found, including that nothing had changed.

It also reads the repository again rather than only what changed since last
time. How a file is read changes with the indexer, and an update pass sees an
unchanged file and skips it, so the button named for re-indexing was the one
thing that could not pick up a change to indexing. Reading only what changed is
still there for whatever watches a working tree.
The tokens, the primitives and the graph renderer now come from
@sourceant/design, pinned by commit. They were copies before, and a copy drifts
the moment either side changes without anybody noticing until the products stop
looking like one.

Pinned rather than tracking a branch: a change to the design should not break a
build here until somebody moves the pin, and a stranger hitting that breakage
cannot see why. No version numbers, because there is nothing stable enough yet
to promise one.

The package ships source, so it is compiled with the application rather than
pre-bundled, and Tailwind scans it for the classes its own components carry.
A machine can now be told which model to ask, where to reach it, and with whose
key. The key is written and never read back: what comes the other way says only
whether one is set.

Onboarding asks for a folder and then for that, once. Somebody who skips it is
not asked again, because a box that keeps reappearing is one people learn to
dismiss without reading; both answers live in Settings afterwards.

Knowledge can also be read straight off what a repository already states, which
needs no model at all. Everything it finds says where it came from and arrives
proposed, because nobody has agreed to it.
Reading what a repository states is always there. Asking a model for what it
never wrote down appears only once a model is configured, because the button
costs whatever the model costs and one that always fails is worse than one that
is not there.
…kage

Every page had its own spelling of a labelled field, a text box, a
picker and a row in a list, so a repository and a recorded fact looked
like two different products. They now come from one place and look the
same.

The design package is linked from a sibling checkout rather than copied,
so editing a primitive shows up here without reinstalling it.
The local view could show what a repository is and what is known about
it, but not whether the work sitting in it is ready to be proposed to
anyone. It now can: what changed against the branch the work is going
back to, which of the team's written rules bear on it, and what those
rules make of it.

The rules come from the folders people have been filling for their
coding agents, which live in the person's home rather than the core's.
A containerised core is now told where that is, or it would look in a
home nobody has ever put anything in.

Asking a model to propose knowledge was offered on screen but never
carried past this process, so pressing it read the repository's own
words and nothing more.
A repository was a row that did nothing when clicked. It now opens on what
came of covering it: how much was read, what has been recorded, which rules
apply, and its graph.

Skills were a list read from somebody's agent folders with nothing to do to
them. A rule can now be written down, edited and forgotten, or copied out of
your own folders into the repository so the team gets it.

Settings was one long page. It opens on an overview saying whether the thing
is working and what it was told to use, and the rest are tabs the core
declares rather than a list kept here. Every setting is now drawn from what
the core says it has, so one it starts declaring appears without a change
here; the model form was a second, hand-written copy of that list.

One deadline covered every call to the core, so a review that asks a model
about several rules was cut off after thirty seconds. Calls that do real work
now get their own budget.
The overview counted the parts a repository falls into by rendering the list
of them, which printed a row of objects. Each part is named after what it
holds, which is worth more than a number, so they are listed with their
sizes. The three oversized figures beside it are one line now.

A review says which checkout it read and what it compared against, so
somebody with a worktree open elsewhere can see whose work is on screen.

Every control in a page head is the compact size, and they are all the same
compact size, which they were not.
A rule is a document, frequently a long one, and a box inside a dialog is not
somewhere anybody writes a document: no room, no rendering, and the list
underneath it going nowhere.

Opening a rule is now a page. The text gets the full height, what it will
look like sits beside it on a wide screen and behind a tab on a narrow one,
and the rendering is the same markdown a person or a model is given when work
is checked against the rule.

A rule kept in somebody's own agent folder opens read-only and says why,
with saving offering to write a copy into the repository instead.
A review takes tens of seconds and will take longer on a bigger repository.
Answering it on the request that started it meant a browser connection held
open for all of that, and anything that interrupted it threw away work that
had already been paid for, with nothing to show but a network error.

The agent runs it and holds the answer. Starting one returns immediately and
the page asks how it went, which survives a slow provider, a reload, and
somebody walking away from the screen. The last twenty answers are kept, so a
page that comes back late still collects one.

A skill can now be written onto the machine as well as into a repository, and
the page says which it is going to. The word rule is gone from what a person
reads: plenty of skills explain a procedure rather than state a requirement.
A skill can now say which files it is about and whether it belongs in a
review at all, both written into its own frontmatter where every other agent
can still read them. Not everything somebody teaches an agent is about
judging a change, and until now everything was treated as though it were.

The list says which of those a skill has, so it is clear why one keeps being
picked and another never is. Where a skill is kept reads as global rather
than as this machine, which is what it means.

Settings gained a place to name folders to read skills from, for the ones
discovery cannot reach: a checkout kept off on its own, a package of a
monorepo. A setting that is a list of things now gets room to be one.

Asking for skills asked for the first fifty. A person with a folder per
coding agent easily has more, and a screen quietly showing half of them was
lying about what a review had to choose from.
A skill was filed against whichever repository the list happened to be
filtering by, and nothing on the screen said so. That is how one of a
person's own skills ended up saved into an unrelated project: they opened it,
saved it, and the page read a selector that was there to filter.

There is one control now, and its options are the destinations by name:
everywhere, or a repository. Nothing is written into the checkout either way,
so a skill for a project no longer leaves a folder in somebody's working
tree.

Folders and globs are lists, and are edited as lists rather than typed into a
box of lines.
Everything written down arrived proposed and there was no way to agree to
it, so it sat there, and nothing proposed is given to an agent reading the
repository. Each one can be accepted or thrown out, all of them at once
where somebody trusts the reading, and how sure the model said it was is on
the card beside it.

Good news was being announced in the brand colour, which is a red, so
finishing successfully looked like failing.

Reading repositories again, and looking for what they have started stating
about themselves, now happen on whatever schedule was set rather than only
when somebody presses a button. This is the process that is always up, which
is what makes it the one to do it, and it asks a model only where somebody
has said which model to ask.
A repository's page listed the parts its code falls into. On most
repositories those parts came out named after the directories they live in,
which told somebody their own folder structure with extra steps.

It says where to look first instead: the files that have been changing and
that the rest of the code leans on. On a repository nobody here has worked
in, that puts the model half the application imports at the top, which is
where a change is most likely to catch somebody out and where a person
reading it for the first time should start.
Four tabs of lists is not a review. What changed showed file names with no
diff, what the skills said sat in one tab and which skills applied in
another, and a finding about line 40 of a file was a sentence in a list with
the file path written out beside it.

It reads the way a pull request does now: the changed files down the side
worst first, the diff of whichever one is selected, and what a skill said
about a line drawn against that line. Anything said about the change as a
whole, a commit message or a missing description, sits at the top where it
belongs rather than against a line of code.

What is being reviewed is stated: the branch, what it is going back to, how
many commits ahead it is and how many files that comes to. Somebody with a
worktree open elsewhere can see whose work is on screen.

Two boxes asking what the work is called have gone. Where the choosing picks
the wrong skills, there is a selector naming one to run instead of arguing
with the matcher.
A review lived in this process, so a link to one stopped working the moment
the agent restarted, and nothing outside this process could hand anybody one.
The core keeps them now and this asks; the agent tells it where the screen is
listening, so a review asked for over MCP answers with a link somebody can
click rather than a path they have to assemble.

Running one puts its name in the address, so it can be come back to, and
opening that address reads it whether it finished a second ago or yesterday.

What a review is read against is a row of chips now, not a dropdown that
could only ever hold one. Whatever applied comes back into that row when the
reading finishes, so taking one off and running again is the obvious next
move. What each of them made of the change is a row of the same chips,
tinted by their verdict, at the top where an overview belongs.
A review opened straight into a list of changed files. That is the second
thing anybody wants. The first is what the review says: what the change does,
what is worth stopping for, what is worth changing, and the verdict.

So it opens on that, with the files behind a tab beside it. Every suggestion
names the line it is about and jumps there, and once there it is drawn
against that line with the code it is offering underneath, next to whatever a
skill said about the same place.

The landing lists earlier reviews rather than an empty page. A review has a
name and somebody may have been handed one, or run one this morning, and
until now there was no way back to either.
The tab switcher sat below two ribbons, so the thing that decides what the
whole page shows was the third thing on it. It is first now, with what the
review was read against and how it went underneath.

A row of chips saying six rules were satisfied was not news. What is news is
the one that was not, so only those are listed, and they say what was not met
rather than restating each rule's name and a tick.
The agent proxies MCP through to the core, so a coding session is
pointed at the one address that is always up and knows which port the
core landed on this time. The core is told a second address for reaching
back, because the one a person clicks is loopback and inside a container
that is the container.

Routes are paths rather than fragments after a hash, so a link somebody
is handed opens, pastes and bookmarks like any other. Anything that is
not a file answers with the page, and a missing asset still answers with
nothing.

Everything the core says about a review now survives the trip through
here. This is decoded into a struct and encoded again on the way out, so
the commits a branch is ahead by and the code a suggestion replaces were
dropped in silence, and the page that drew them looked empty rather than
broken.

A review reads as a pull request does: the branch leads the header with
the verdict beside it, the summary opens the overview, commits have a
tab, and what it was read against sits with the tabs. Reviews and
knowledge can be looked at across every repository at once.
@nfebe
nfebe force-pushed the feat/review-page-and-mcp branch from 4316c1a to 91030b5 Compare August 30, 2026 02:51
The view is checked out beside the design package it depends on by path,
and built before the binary, because the binary embeds it.
@nfebe
nfebe force-pushed the feat/review-page-and-mcp branch from 91030b5 to b5303ae Compare August 30, 2026 02:52
@nfebe
nfebe merged commit 2d9b6b7 into main Aug 30, 2026
1 check passed
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.

1 participant