Skip to content

feat(brain): hold the push until the brain is built, and land the browser on it - #422

Merged
anirudhkumar-nanonets merged 1 commit into
mainfrom
feat/brain-push-watches-the-build
Sep 18, 2026
Merged

anirudhkumar-nanonets merged 1 commit into
mainfrom
feat/brain-push-watches-the-build

Conversation

@anirudhkumar-nanonets

Copy link
Copy Markdown
Collaborator

Three changes, all on the same failure: roughly a third of the repo brains attempted in production die inside the miner — after the push has already succeeded — and nothing on either side ever says so.

1. brain push follows the build

It used to end here:

✓ sent acme/payments-api to "acme/payments-api"
· it is being mined into rules now — a few minutes. Watch it finish in your browser.

…and hand the prompt back. That sentence is the last thing the process says about the work, and it is said before the part that fails. On a CI runner or over SSH, where nobody is going to open a browser, the failure exists nowhere at all.

Now it holds, and prints the same four stages Trail's build screen shows, off the same row:

· building the brain — Ctrl-C detaches, it keeps going without you
  ✓ reaching the repository
  ✓ reading its history — 412 commits, 89 discussions
  ✗ mining the rules
✗ mine repository history: parse response: unexpected end of JSON input
  Nothing was lost — the brain is still there. Run `graft brain push` again to retry the read.

A failure is reported at the stage it happened at. A repo that was read successfully and then lost in the miner says so, rather than looking unreachable — which matters, because that wrong reading sends someone off to fix repository access for a problem that has nothing to do with it.

  • Exits non-zero on a real failure, so a CI step hears about it like any other failure.
  • A host that cannot be reached is reported as unreachable, not as a failed build. One is our problem, the other is the user's, and they lead to opposite next steps.
  • Still running after 15 minutes is a timeout that says the build continues — because it does.
  • Ctrl-C detaches and cancels nothing; --no-watch restores the old fire-and-forget ending.

2. The handoff lands on the build screen

The 303 pointed at /brain/<id>. That route redirects to the brain's graph, and it fires the instant the row exists — minutes before it holds a single rule. So every terminal signup landed on an empty visualisation of a brain that was, at that moment, building perfectly well. It now lands on /get-started?step=build&brain=<id>, which is the same wait the browser-first flow shows and leads to the graph once there is one.

Pairs with NanoNets/assign#2760, which adds that screen. Merge that first — until it deploys, this URL lands on the get-started picker rather than the build screen. Not broken, just not yet better.

3. writeLink gitignores .graft/ — please read this one

BrainLink's own comment has described that directory as "git-ignored" since the day it was written, and nothing ever made it true. ensureGitignored only ever ran for the graph cache (/graft/), never for .graft/config.json, which is where the brain id and its read token get written.

So every repository anyone has run graft brain connect or graft brain push in is one git add -A away from publishing a credential. Found it because an automated scan flagged exactly that file in my own checkout of another repo.

The token is a signature over one brain id, scoped to reading that brain and regenerable server-side, so this is not a five-alarm leak — but it is a credential in an unignored file, sitting in every user's working tree, contradicting the comment right above it. Worth a look from someone who knows whether any of these have already been committed anywhere.

Testing

npm test — 1243 pass, 0 fail. 11 new cases covering where a failure lands, that a log line prints once, that unreachable and timed-out and failed are three different outcomes, and that the handoff URL can never go back to /brain/. One existing test updated: it asserted the old redirect target, which is the thing being changed.

…wser on it

Three things, all on the same failure. Roughly a third of the repo brains
attempted in production die inside the miner, AFTER the push has succeeded —
and nothing on either side says so.

- `brain push` now follows the build instead of printing "watch it finish in
  your browser" and handing the prompt back. Four stages off the same row the
  browser reads, each printed once as it settles, and a failure reported at the
  stage it happened at: a repo read successfully and then lost in the miner says
  so rather than looking unreachable. Exits non-zero on a real failure, so a CI
  step hears about it. Ctrl-C detaches without cancelling; --no-watch restores
  the old fire-and-forget ending.

- The handoff's 303 now lands on Trail's build screen. It pointed at
  /brain/<id>, which redirects to the graph the instant the row exists — minutes
  before it holds a rule — so every terminal signup saw an empty visualisation
  of a brain that was building fine.

- writeLink gitignores .graft/. BrainLink's own comment has called that
  directory "git-ignored" since it was written and nothing ever made it true;
  ensureGitignored only ever ran for the graph cache. Every repo anyone ran
  `graft brain connect` in was one `git add -A` from publishing a read token.
@trailhq-graft

trailhq-graft Bot commented Sep 18, 2026

Copy link
Copy Markdown

🌱 graft blast radius

3 areas changed → 4 areas can be affected. 8 dependent symbols, depth 2.
Tests: Gitignore Management has tests the diff did not touch; 1 area updated its tests.
Tag: @shhdwi — 4 of 7 areas · @Frankie-Xu — Gitignore Management, Graph Engine · @qoole — Workspace Graph Building

flowchart TB
  A0(("Workspace Graph Building<br/>3 symbols"))
  A1(("Brain Connection<br/>2 symbols"))
  A2(("Pull Request Review<br/>2 symbols"))
  A3(("Graph Engine<br/>1 symbol"))
  classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
  class A0,A1,A2,A3 reached;
Loading
Can be affected Symbols Nearest hop Reached from
Workspace Graph Building 3 src/graph/build.ts:L151-L410 buildGraph — calls, depth 1 Gitignore Management
Brain Connection 2 src/brain/connect.ts:L67-L86 connectBrain — calls, depth 1 brainUrl, Gitignore Management
Pull Request Review 2 src/app/brain-build.ts:L251-L358 readRepository — calls, depth 2 Gitignore Management
Graph Engine 1 src/engine.ts:L91-L101 graph — calls, depth 2 Gitignore Management
Who knows this code — 3 people across 7 areas
Area Who knows it
Gitignore Management · changed @Frankie-Xu — 3 commits, last 18d ago · @shhdwi — 1 commit, last 1mo ago
CLI · changed @shhdwi — 23 commits, last 1mo ago
Workspace Graph Building · affected @shhdwi — 7 commits, last 1mo ago · @qoole — 4 commits, last 2mo ago
Graph Engine · affected @shhdwi — 3 commits, last 1mo ago · @Frankie-Xu — 1 commit, last 18d ago
brainUrl · changed only you — nobody else has touched these files
Brain Connection · affected only you — nobody else has touched these files
Pull Request Review · affected only you — nobody else has touched these files

Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no @ has no GitHub handle in its commit email — tag them by hand, or add a .mailmap entry. A suggestion from history, not a CODEOWNERS rule.

All 8 dependent symbols, grouped by area

Workspace Graph Building — 3 symbols in 3 files

  • src/graph/build.ts:L151-L410 — buildGraph (calls, depth 1)
    371: // (`ensureGitignored` writes `.gitignore`, which a read has no business doing),
  • src/graph/workspace-cli.ts:L48-L86 — runWorkspaceBuild (calls, depth 1)
    83: ensureGitignored(root, contextDirFor(root, opts.override));
  • src/graph/refresh.ts:L150-L227 — ensureFreshGraph (calls, depth 2)

Brain Connection — 2 symbols in 1 file

  • src/brain/connect.ts:L67-L86 — connectBrain (calls, depth 1)
    72: writeLink(repo, link);
  • src/brain/connect.ts:L92-L99 — pullBrain (calls, depth 2)

Pull Request Review — 2 symbols in 2 files

  • src/app/brain-build.ts:L251-L358 — readRepository (calls, depth 2)
  • src/app/review.ts:L45-L99 — reviewPullRequest (calls, depth 2)

Graph Engine — 1 symbol in 1 file

  • src/engine.ts:L91-L101 — graph (calls, depth 2)
Test signal per changed area — 1 ✓ · 1 ⚠ · 1 –

Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.

  • Gitignore Management — 1 of 1 reached · 1 test file reaches it, none changed here
  • brainUrl — 3 of 8 reached · 1 test file changed here: test/brain-watch.test.ts
    • not reached: writeLink, fetchRepoState, num, detail, state
  • CLI — no function, method or class changed here
33 test suites also reference this code

35 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.

  • test/ask-index.test.ts
  • test/ask.test.ts
  • test/container-extract.test.ts
  • test/context-only-dir.test.ts
  • test/context.test.ts
  • test/covers.test.ts
  • test/generic-extract.test.ts
  • test/graph-go.test.ts
  • test/graph-incremental.test.ts
  • test/graph-invariants.test.ts
  • test/graph-java.test.ts
  • test/graph-languages.test.ts
  • test/graph-php.test.ts
  • test/graph-posix-paths.test.ts
  • test/graph-python.test.ts
  • test/graph-r-classes.test.ts
  • test/graph-r-phase3.test.ts
  • test/graph-r-phase4.test.ts
  • test/graph-r-phase5.test.ts
  • test/graph-r.test.ts
  • …13 more

graft blast · origin/main...HEAD · depth 2 · 7 changed files

Open the interactive graph → — click an area to see its dependent symbols at file:line.

github-actions Bot added a commit that referenced this pull request Sep 18, 2026
@anirudhkumar-nanonets
anirudhkumar-nanonets merged commit 8c05769 into main Sep 18, 2026
8 checks passed
@anirudhkumar-nanonets
anirudhkumar-nanonets deleted the feat/brain-push-watches-the-build branch September 18, 2026 09:58
github-actions Bot added a commit that referenced this pull request Sep 18, 2026
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