feat: Reach the MCP endpoint and read a review as a page - #1
Merged
Conversation
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
force-pushed
the
feat/review-page-and-mcp
branch
from
August 30, 2026 02:51
4316c1a to
91030b5
Compare
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
force-pushed
the
feat/review-page-and-mcp
branch
from
August 30, 2026 02:52
91030b5 to
b5303ae
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.