Skip to content

feat(ai): give coding agents xNet's real retrieval, memory and a warm process (0415) - #667

Merged
crs48 merged 21 commits into
mainfrom
claude/0415-the-coding-agent-lane-retrieval-memory-and-self
Aug 1, 2026
Merged

feat(ai): give coding agents xNet's real retrieval, memory and a warm process (0415)#667
crs48 merged 21 commits into
mainfrom
claude/0415-the-coding-agent-lane-retrieval-memory-and-self

Conversation

@crs48

@crs48 crs48 commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Implements exploration 0415 — the coding-agent lane: retrieval, memory, speed and self-improvement.

The problem

Claude Code and Codex are xNet's primary AI interface, and they were running on the worst retrieval xNet owns. @xnetjs/brain's hybrid GraphRAG stack was wired into exactly one consumer — the workbench — while every agent lane built its AI surface with no retriever at all and fell back to a substring scan over the first 500 nodes. The degraded: true notice the AI surface computes was thrown away before the agent saw it, so a scan of 500 out of 40,000 nodes printed no results and sounded certain.

It was worse than the exploration claimed. Three lanes had no searchText, not two — the --db lane rated "half-equipped" turned out to drop it as well, sitting directly on top of a working nodes_fts index.

What landed

One retriever, every lane. createAgentRetrieval() is now the single construction path, used by the CLI, xnet mcp serve, the Electron bridge and the local API. authorize is required rather than optional — graph expansion walks edges out of matched nodes, and better retrieval widens whatever egress hole exists. scripts/guard-ai-surface-retrieval.mjs is a hard-zero CI gate, because omitting a retriever is invisible in review: the call reads fine, and it's what it doesn't pass that costs you.

A search that can't lie. runSearch leads with the tier it actually ran at and writes its notice to stderr — stderr because a warning on stdout is one | head away from vanishing.

xnet recall replaces "search, then read eight nodes": a budgeted pack where each hit carries the graph path it was reached by, plus the ids dropped for budget.

xnet serve keeps store, schemas and FTS warm behind a unix socket. Absent is silent; wrong is loud — a version mismatch or a mid-request death throws rather than falling back, because a killed daemon must never read as "no results".

Memory and a learning loop. remember / forget / memories / distill, a devtools console to see and edit what's stored, and a RetrievalProfile tuned from local traces that is only adopted when a pinned golden set doesn't regress. Nothing leaves the device; distillation reads AgentAction instructions that already exist rather than capturing anything new, requires three occurrences, and never reconstructs a redacted instruction from its digest.

Measurements

bench:agent-surfaces files-vs-legacy 0.118 (gate ≤ 0.12)
Daemon socket round-trip p50 0.14 ms, p95 0.26 ms
Cold xnet search ~0.22 s (node boot dominates — see below)
Full suite 11,704 passing

Three things the implementation corrected in the doc

  1. The 40 ms latency target was aimed at the wrong thing. Warm-through-the-CLI is only 0.19 s vs 0.22 s cold, because ~180 ms is node booting the client. The socket itself answers in 0.26 ms. The target is restated against the round-trip; the leverage is callers that are already processes.
  2. The ABI risk landed. @xenova/transformers pulls in sharp, which this repo builds for Electron's ABI, so xnet serve --vectors is honest and inert under system Node today. The tier is built and tested and reports hybrid-graph against an injected engine. A first draft swallowed the backfill error and announced hybrid-graph over an index holding zero documents — this exploration's own thesis biting its implementation.
  3. Two silent bugs only the end-to-end run caught. FTS5 ANDs bare terms, so a natural-language recall question matched nothing; and the two backends return different schema shapes, so the CLI lane's graph stage found zero edges while still reporting bm25-graph. Both fixed, both now tested.

Working end-to-end result on a workspace where the answer page contains none of the query's words:

$ xnet recall "how do we roll back the Acme renewal cutover"
tier  bm25-graph  entries=1 expanded=1 denied=0 dropped=0 tokens=36
id     title                 path
SLp7…  Acme renewal cutover  Acme renewal cutover
zW8C…  Rollback procedure    Acme renewal cutover→ (page) Rollback procedure

Not done, deliberately

hopDecay 0.2 beats the shipped 0.55 on every golden-set metric (all 0.81→0.85, graph 0.50→0.60, MRR 0.69→0.71). The default was not moved — the whole gap is one or two golden cases, which is this eval's resolution rather than a signal, and it's the same argument 0394 made. Recorded in the doc with the numbers so the next person can decide with a bigger corpus.

🤖 Generated with Claude Code

@crs48
crs48 temporarily deployed to pr-667 August 1, 2026 16:33 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@crs48, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 1 minute

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1631e976-7e58-440c-9166-aa6625a6506c

📥 Commits

Reviewing files that changed from the base of the PR and between 9a679b6 and 96067ca.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (80)
  • .changeset/agent-lane-retrieval-0415.md
  • .changeset/atproto-projection-and-snapshot.md
  • .changeset/brain-published-0415.md
  • .changeset/screen-recording-schemas.md
  • .github/workflows/ci.yml
  • apps/electron/src/main/agent-mcp-server.ts
  • apps/electron/src/main/renderer-store-proxy.test.ts
  • apps/electron/src/main/renderer-store-proxy.ts
  • apps/electron/src/renderer/main.tsx
  • docs/explorations/0415_[x]_THE_CODING_AGENT_LANE_RETRIEVAL_MEMORY_AND_SELF_IMPROVEMENT.md
  • package.json
  • packages/brain/LICENSE
  • packages/brain/package.json
  • packages/brain/src/__evals__/retrieval.eval.test.ts
  • packages/brain/src/index.test.ts
  • packages/brain/src/index.ts
  • packages/brain/src/memory-from-traces.test.ts
  • packages/brain/src/memory-from-traces.ts
  • packages/brain/src/retrieval-profile.test.ts
  • packages/brain/src/retrieval-profile.ts
  • packages/brain/src/workspace-retrieval.test.ts
  • packages/brain/src/workspace-retrieval.ts
  • packages/cli/package.json
  • packages/cli/plugin/skills/xnet/SKILL.md
  • packages/cli/src/__tests__/agent-backend.test.ts
  • packages/cli/src/__tests__/agent-commands.test.ts
  • packages/cli/src/__tests__/connect-command.test.ts
  • packages/cli/src/__tests__/memory-commands.test.ts
  • packages/cli/src/__tests__/remote-backend-tier.test.ts
  • packages/cli/src/__tests__/session-daemon.test.ts
  • packages/cli/src/__tests__/vector-tier.test.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/commands/agent.ts
  • packages/cli/src/commands/connect.ts
  • packages/cli/src/commands/data.ts
  • packages/cli/src/commands/mcp.ts
  • packages/cli/src/commands/memory.ts
  • packages/cli/src/commands/serve.ts
  • packages/cli/src/utils/agent-local.ts
  • packages/cli/src/utils/agent-remote.ts
  • packages/cli/src/utils/session-daemon.ts
  • packages/cli/src/utils/vector-tier.ts
  • packages/data/etc/data.api.md
  • packages/data/src/index.ts
  • packages/data/src/schema/index.ts
  • packages/data/src/schema/schemas/index.ts
  • packages/data/src/schema/schemas/memory.ts
  • packages/devtools/package.json
  • packages/devtools/src/panels/MemoryPanel/MemoryPanel.tsx
  • packages/devtools/src/panels/MemoryPanel/useMemories.test.ts
  • packages/devtools/src/panels/MemoryPanel/useMemories.ts
  • packages/devtools/src/panels/Shell.tsx
  • packages/devtools/src/panels/panel-registry.ts
  • packages/devtools/src/provider/DevToolsContext.ts
  • packages/hub/Dockerfile
  • packages/plugins/package.json
  • packages/plugins/src/__tests__/agent-api-recall.test.ts
  • packages/plugins/src/__tests__/mcp-server.test.ts
  • packages/plugins/src/__tests__/retrieval-relation-fields.test.ts
  • packages/plugins/src/ai-surface/index.ts
  • packages/plugins/src/ai-surface/retrieval.ts
  • packages/plugins/src/ai-surface/skill.ts
  • packages/plugins/src/sandbox/agent-api.ts
  • packages/plugins/src/services/local-api.ts
  • packages/plugins/src/services/mcp-server.ts
  • packages/plugins/src/services/node.ts
  • packages/vectors/package.json
  • scripts/check-api-report.mjs
  • scripts/check-hub-image-closure.mjs
  • scripts/check-packaging.mjs
  • scripts/check-publish-closure.mjs
  • scripts/check-surface-tokens.mjs
  • scripts/check-view-drift.mjs
  • scripts/check-visual-explorations.mjs
  • scripts/cloud-company-metrics.mjs
  • scripts/cloud-secrets-push.mjs
  • scripts/cloud-staging-stripe-prices.mjs
  • scripts/cloud-staging-stripe-webhook.mjs
  • scripts/guard-ai-surface-retrieval.mjs
  • site/src/data/changelog/2026-08-01-coding-agents-can-finally-search-your-wh.json
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/0415-the-coding-agent-lane-retrieval-memory-and-self

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

github-actions Bot added a commit that referenced this pull request Aug 1, 2026
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Preview removed for PR #667.

github-actions Bot added a commit that referenced this pull request Aug 1, 2026
github-actions Bot added a commit that referenced this pull request Aug 1, 2026
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🖼️ UI changes in this PR

No visual differences detected in the changed UI.

CI run

@crs48
crs48 temporarily deployed to pr-667 August 1, 2026 16:43 — with GitHub Actions Inactive
xNet Test and others added 17 commits August 1, 2026 09:45
…and self-improvement

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Signed-off-by: xNet Test <test@xnet.dev>
Adds createWorkspaceRetrieval() — the single construction path that
assembles the best retrieval a backend supports and reports the tier it
settled for, so a degraded search can never render identically to an
exhaustive one. authorize is required, not optional: graph expansion
walks edges out of matched nodes and needs a gate no call site can forget.

Also restores FTS to the two lanes that had lost it — the CLI's remote
backend now routes searchText to /api/v1/ai/search, and the Electron
store proxy asks the renderer (which owns nodes_fts) instead of scanning
500 nodes over IPC.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
createAgentRetrieval() is now the single call an agent lane makes. All
three lanes use it — the CLI's services, xnet mcp serve, and the Electron
bridge — plus the local API, whose /ai/context-pack was serving the same
keyword scan to every HTTP client.

The guard is the part that makes it stick: omitting a retriever is
invisible in review, because the call reads fine and it is what it
doesn't pass that costs you. scripts/guard-ai-surface-retrieval.mjs is a
hard-zero gate with a reasoned allowlist, wired into CI.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
runSearch now leads with a provenance line (tier, index, and the reason
when degraded) in tsv and md, carries tier into json, and writes the
notice to stderr for every format — stderr because a warning on stdout is
one `| head` away from vanishing, and an agent that loses it reports
"no such node" with total confidence.

Writing the test against a real SQLite store surfaced a fourth degraded
lane the exploration had rated half-equipped: createLocalAgentBackend
never forwarded searchText either, so the --db path scanned 500 nodes
while sitting on a working nodes_fts index. Fixed, and the doc corrected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
…bbering

The instruction files are the user's — in this repo CLAUDE.md is the entry
point to the whole instruction tree — and connect used to write them
wholesale. .mcp.json was carefully merged the whole time; these never got
the same care.

Writes are now fenced in a managed block: create when absent, replace
between markers on a re-run, append when the file exists without them.
Every existing byte survives.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
xnet recall and xnet_recall return a budgeted context pack: ranked hits
each carrying the graph path they were reached by, plus the ids dropped
for budget so the agent pulls them just-in-time rather than the CLI
guessing.

Both xnet_search and xnet_recall stand in the core tool set (0415 open
question 2). They answer different questions — find the node called X
versus answer this question — and a model with only recall would pay a
graph walk to look up a title it already knew. xnet_recall registers only
when the server has retrieval: a tool that exists to answer 'unavailable'
still costs its definition tokens every turn.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
Holds the store, schema registry and FTS open behind a unix socket keyed
on the invocation options, so a client finds it without paying the
backend resolution the daemon exists to avoid. search and recall try it
and fall back to a cold process when nothing is listening.

Absent is silent; wrong is loud. A version mismatch and a connection that
dies mid-request both throw named errors rather than falling back, because
quietly retrying would discard the one signal saying the answer was bad —
and a killed daemon must never read as 'no results'.

Measured: the socket round-trip is p50 0.14ms / p95 0.26ms, but the CLI
only improves 0.22s -> 0.19s because node's own boot dominates. The doc's
40ms target was aimed at the wrong thing and is restated against the
round-trip; the real leverage is callers that are already processes.

brain now ships a dist entry like every other dependency of plugins —
source-only worked for bundled apps but not for the CLI build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
…routes by cost

The code-execution lane was the cheapest one and the most blinkered: a
script could only see the slice the host preloaded. api.recall and
api.graph now reach the whole workspace with the same graph walk and the
same provenance paths the recall verb gets.

The sandbox bans await on purpose, so these are synchronous and the host
runs the script twice — a priming pass records the queries, the real pass
answers them. A query the priming pass never saw throws; returning an
empty array would be indistinguishable from 'nothing matches'.

The skill now leads with the cost gap (2.7k vs 18k tokens for the same 15
tasks) and puts code execution above ad-hoc reads, tells the agent to read
the tier line, and stays under its 1000-token standing budget — which the
benchmark caught me exceeding.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
Loads the embedding + HNSW tier once in the warm process, persists it via
brain's persist layer, and restores from the snapshot instead of
re-embedding. A cold verb never pays the model load — that is the whole
reason this is daemon-only.

Every failure degrades honestly. No model, no usearch, a corrupt
snapshot: each leaves the daemon serving bm25-graph and saying so. A
first draft swallowed the backfill error and announced hybrid-graph over
an index holding zero documents — this exploration's own thesis biting
its implementation, now covered by a test.

The ABI risk the doc rated medium has landed: transformers pulls in
sharp, which this repo builds for Electron's ABI, so --vectors is honest
and inert under system Node today. Recorded in the doc with follow-ups.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
consolidateMemory and applyMemoryOp existed and nothing called them, so
every coding-agent session rediscovered the workspace from zero.

xnet remember writes through the existing planner (a restatement
consolidates rather than piling up); xnet memories lists what is stored;
xnet forget deletes one, and refuses any node that is not a MemoryItem so
a typo cannot destroy workspace data. xnet skill --memories appends a
capped top-k preamble, so memory cannot re-bloat the context this
exploration just trimmed.

xnet distill reads AgentAction instructions that already exist — no new
capture, no new consent surface. Three occurrences required, so a one-off
task never becomes a standing preference, and redacted instructions
contribute nothing rather than being reconstructed from their digest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
RetrievalProfile is four numbers, deliberately not a MemoryItem: facts
about the user and tuning state obey different retention and privacy
rules, and collapsing them turns 'make search better' into 'profile the
user'. It is an ordinary private node — syncs, exports, deletes — and
nothing in this module takes a network dependency.

preferencePairs reads recall outcomes the session already produced; a
rolled-back episode yields nothing rather than inverted pairs.
proposeProfile nudges one knob by one step, because a real optimizer over
four numbers and a few dozen observations would fit noise. ratchetProfile
scores candidates against the PINNED corpus, never the behaviour that
produced them — scoring a profile on its own training signal is how a
retriever gets worse at everything the user hasn't done yet.

The ratchet found something on its first run: hopDecay 0.2 beats the
shipped 0.55 on every metric (all 0.81→0.85, graph 0.50→0.60, mrr
0.69→0.71). The default is NOT moved — the gap is one or two golden
cases, which is this eval's resolution, the same argument 0394 made.
Recorded in the doc with the numbers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
…bers

A memory the user cannot see is not a memory, it is a profile. The panel
lists MemoryItem nodes ranked the way retrieval ranks them (recency-decayed
salience, not creation order — a year-old 0.9 loses to yesterday's 0.6),
marks which ones actually reach a session's preamble, shows the evidence a
distilled memory came from, and lets any row be rewritten or removed.

It also surfaces the adopted RetrievalProfile and the ratchet's reason for
accepting it, so a tuning decision is something the user can read rather
than something the retriever just did.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
Two bugs the end-to-end run caught that no unit test would have, both
silent, both producing a lane that reported bm25-graph while doing much
less:

- FTS5 ANDs bare terms, so 'how do we roll back the Acme renewal cutover'
  required every one of those words in one node and matched nothing —
  recall's entire purpose defeated. queryVariants now tries the strict
  query first, then the content words OR'd together.
- The two backends return different schema shapes (JSON-LD array from the
  CLI registry, keyed record from the Electron renderer). The relation
  resolver handled only the record, so on the CLI lane the graph stage
  found zero edges. relationFieldNames now reads both.

Also adds getPort() to LocalAPIServer: port 0 could be listened on but
never connected to, which made the app-running lane untestable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
…nd self improvement

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
@crs48
crs48 force-pushed the claude/0415-the-coding-agent-lane-retrieval-memory-and-self branch from 9acc0b8 to b8d184d Compare August 1, 2026 16:45
@crs48
crs48 temporarily deployed to pr-667 August 1, 2026 16:46 — with GitHub Actions Inactive
Two CI failures, one mistake of mine: @xnetjs/plugins and @xnetjs/cli are
published to npm, and I gave them dependencies on @xnetjs/brain (private)
and @xnetjs/vectors (publish-ignored). Shipping that would break every
npm consumer on install.

- @xnetjs/brain is now published. It was private only because nothing
  outside the monorepo used it; it has zero runtime dependencies and is
  structural over whatever store you hand it, which is what makes that
  safe. Its own data/vectors deps were vestigial — the source imports
  neither — so data is dropped and vectors demoted to a devDependency
  used by one test.
- @xnetjs/cli drops @xnetjs/vectors to a devDependency. The import in
  vector-tier.ts is already dynamic and optional: createVectorTier
  returns null when the engine cannot load, which is the tested behaviour.
- The hub Dockerfile hand-lists the packages it COPYs, and brain joined
  the closure three packages away. Added, plus a guard: the stale list
  failed nothing until a six-minute image build died on 'Cannot find
  module', and that is the same build Railway runs, so the first symptom
  could have been a failed deploy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
github-actions Bot added a commit that referenced this pull request Aug 1, 2026
@crs48
crs48 temporarily deployed to pr-667 August 1, 2026 16:58 — with GitHub Actions Inactive
Demoting vectors to a devDependency in the previous commit had a
consequence I did not check: tsup externalizes dependencies but BUNDLES
devDependencies, so it followed the dynamic import into transformers and
then into sharp, whose native requires esbuild cannot resolve. The cli
build failed, and editor-ux, typecheck, build-and-smoke-test, capture and
deploy-preview all failed downstream of it.

Marking it external is also what the design wants: the import is a
runtime import() that is allowed to fail, and createVectorTier returns
null when it does. sharp is now absent from the bundle entirely.

The lesson is mine: I ran typecheck, lint and test locally but not
'pnpm build', which is the only thing that would have caught this.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
@crs48
crs48 temporarily deployed to pr-667 August 1, 2026 17:06 — with GitHub Actions Inactive
github-actions Bot added a commit that referenced this pull request Aug 1, 2026
…Y lists

The previous fix added brain to the builder stage and the image got
further — then died in the RUNTIME stage, which has its own two
hand-maintained lists (manifests and dists) that I had not looked at.

The guard I added alongside it checked exactly one of the four lists and
reported a clean run, which is the false confidence a gate exists to
remove — the same failure this whole PR is about, in my own tooling. It
now checks all four, names which stage each one breaks, and fails loudly
if a pattern matches nothing at all (the Dockerfile having been
restructured under it).

Verified by removing each of brain's four COPY lines in turn: each is
caught independently, with the right list named.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
@crs48
crs48 temporarily deployed to pr-667 August 1, 2026 17:17 — with GitHub Actions Inactive
github-actions Bot added a commit that referenced this pull request Aug 1, 2026
github-actions Bot added a commit that referenced this pull request Aug 1, 2026
github-actions Bot added a commit that referenced this pull request Aug 1, 2026
… workspace links

pnpm install --prod skips devDependencies but still RESOLVES every
workspace:* link it reads, so brain's devDependency on @xnetjs/vectors —
a package the hub image deliberately does not copy — failed the runtime
install with ERR_PNPM_WORKSPACE_PKG_NOT_FOUND. My guard modelled runtime
deps only and passed a Dockerfile that could not install.

Rather than copy vectors into an image that will never use it, brain no
longer depends on it at all. Its one consumer was an end-to-end test
using createSemanticSearch({ useMockModel: true }); that is now a local
fake, which is stronger coverage — brain's contract is that it is
structural over ANY conforming index, and testing it against the single
implementation we ship proved less. brain is now genuinely
zero-dependency, which is the property cited when making it publishable.

The guard now counts workspace:* devDependencies too, and its closure
grew from 19 to 20 as a result.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: xNet Test <test@xnet.dev>
@crs48
crs48 temporarily deployed to pr-667 August 1, 2026 17:31 — with GitHub Actions Inactive
github-actions Bot added a commit that referenced this pull request Aug 1, 2026
github-actions Bot added a commit that referenced this pull request Aug 1, 2026
github-actions Bot added a commit that referenced this pull request Aug 1, 2026
@crs48
crs48 merged commit bc279fc into main Aug 1, 2026
23 checks passed
@crs48
crs48 deleted the claude/0415-the-coding-agent-lane-retrieval-memory-and-self branch August 1, 2026 17:40
github-actions Bot added a commit that referenced this pull request Aug 1, 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