fix(build): close real local-build gaps found in a hands-on build/run audit
Three verified, currently-live problems, each closed with real evidence (full trace kept in Neuron memory, tags neuron-technologies/neuron,build-audit): 1. dist/soul.c was stale relative to main's own chat.el (11 commits / 459 lines behind, missing PR #122's OpenAI-tools + agentic-loop work and its two "silently break chat" fixes). tools/soulc-stamp.sh --check confirmed it; tools/build-soul-from-dist.sh correctly refused to build (exit 9). Regenerated and re-stamped. No runnable regen script existed anywhere upstream — added tools/regenerate-soul-amalgam.sh, which reproduces the committed amalgam's exact symbol set (byte-for-byte content match, modulo the genuinely new PR #122 functions) and is documented end-to-end in AGENTS.md, including three real elc/elb toolchain gotchas found and root-caused along the way (stale .elh caches silently truncating builds; elb cannot produce this repo's single-TU amalgam; elc silently drops the first function(s) after a comment block in a flat-concatenated compile). 2. tools/build-soul-from-dist.sh failed to link on macOS (`ld: library 'ssl' not found` — Homebrew's openssl@3 is keg-only) and was missing -lssl -lcrypto entirely, drifted from CI's own working recipe. Fixed: adds -L$(brew --prefix openssl@3)/lib on Darwin, matches CI's link line. Verified: dist/neuron now builds and boots clean on a throwaway port/HOME (never touched the live :7770/:8742). 3. Untracked committed *.elh compiler-header caches (elc/elb prefer a stale cached header over recompiling its source, silently, with no error — this is what caused an under-resolved 251-2541-function amalgam multiple times during this audit before the cause was found). Removed from git, gitignored going forward. Also: AGENTS.md and README.md existed on disk but were never committed (git log on both returned nothing) and documented the pre-collapse ~90-tool MCP surface as current. Committed corrected versions reflecting the live 9-op surface (read/write/relate/supersede/think/attend/assert/ground/learn, merged in #153) and the audit-verified build recipe/port topology. Added connectd/ — a minimal local-dev stub for the neuron-connectd MCP sidecar. routes.el/chat.el call 127.0.0.1:7771 for it right now on every soul boot and agentic turn per a real, detailed 2026-06-13 spec (mcp-connectors-adoption-spec.md); the sidecar itself was never built. Meanwhile :7771 is a live three-way collision (axon's unbuilt-Rust default, this connectd contract, and council — the anti-confabulation service actually running there in prod, which live-answers both other things' requests with unrelated 404s instead of a clean bridge-down signal). This stub only implements the documented contract as "zero connectors configured" for local-dev correctness; it does not attempt OAuth or a real MCP client — that is a real, separate product decision. See connectd/README.md for the full trace and the open question left for Will.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
neuron-connectd — MCP connector bridge (LOCAL-DEV STUB).
|
||||
|
||||
THIS IS NOT THE FULL SIDECAR. The full design lives in
|
||||
neuron-technologies/docs/research/mcp-connectors-adoption-spec.md (2026-06-13,
|
||||
"Status: Draft for build"): a TypeScript/Python sidecar using the official MCP
|
||||
SDK that spawns real MCP servers (stdio or streamable-HTTP/SSE), does OAuth,
|
||||
and namespaces their tools as mcp__<serverId>__<toolName>. That sidecar was
|
||||
never built (build-audit, 2026-08-15: no neuron-connectd source existed
|
||||
anywhere on disk before this file).
|
||||
|
||||
WHY THIS STUB EXISTS: routes.el (handle_connectors, connectd_get/connectd_post)
|
||||
and chat.el (connector_tools_json, dispatch_tool's mcp__* routing,
|
||||
tool_auto_approved) were built to the spec and hardcoded to 127.0.0.1:7771 —
|
||||
they are LIVE and calling that port right now on every soul boot and every
|
||||
agentic turn. With nothing real listening there, three unrelated services
|
||||
collide on :7771 (see connectd/README.md): council (which IS what's bound
|
||||
there in Will's live environment today) silently answers with unrelated
|
||||
404 JSON, which is worse than a clean "connection refused" bridge-down
|
||||
response, because it can be misparsed as a real (if empty) reply instead of
|
||||
the "bridge unreachable" path the soul code already handles gracefully.
|
||||
|
||||
This stub implements ONLY the documented HTTP contract, with zero connectors
|
||||
ever configured: empty tool list, empty server list, "not configured" on any
|
||||
mutating call. It gives a fresh local soul the CORRECT graceful-degradation
|
||||
behavior the soul code already expects for "no connectors set up yet" — not
|
||||
the wrong-shaped 404 noise a port collision produces. It does not spawn any
|
||||
MCP server, does no OAuth, and reads no ~/.neuron/connectors.json (there is
|
||||
nothing to read yet). Building the real sidecar is a separate, larger,
|
||||
Will-decision-needed product task — see README.md.
|
||||
|
||||
Usage:
|
||||
python3 connectd_service.py [--port 7771]
|
||||
"""
|
||||
|
||||
import argparse
|
||||
|
||||
import uvicorn
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI(title="neuron-connectd (local-dev stub)")
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
|
||||
class ToolCall(BaseModel):
|
||||
name: str
|
||||
input: dict = {}
|
||||
|
||||
|
||||
@app.get("/healthz")
|
||||
def healthz():
|
||||
return {"status": "ok", "stub": True}
|
||||
|
||||
|
||||
@app.get("/mcp/tools")
|
||||
def mcp_tools():
|
||||
# Matches the spec's contract shape exactly (section 4, "HTTP contract").
|
||||
# Empty because zero connectors are configured — this is the correct,
|
||||
# intended-by-design empty state, not a failure.
|
||||
return {"tools": []}
|
||||
|
||||
|
||||
@app.post("/mcp/call")
|
||||
def mcp_call(body: ToolCall):
|
||||
return {"ok": False, "error": "no connectors configured (neuron-connectd stub)"}
|
||||
|
||||
|
||||
@app.get("/mcp/servers")
|
||||
def mcp_servers():
|
||||
return {"servers": []}
|
||||
|
||||
|
||||
@app.post("/mcp/servers/add")
|
||||
def mcp_servers_add():
|
||||
return {"ok": False, "error": "neuron-connectd stub does not implement connector management yet"}
|
||||
|
||||
|
||||
@app.post("/mcp/servers/toggle")
|
||||
def mcp_servers_toggle():
|
||||
return {"ok": False, "error": "neuron-connectd stub does not implement connector management yet"}
|
||||
|
||||
|
||||
@app.post("/mcp/servers/auto-approve")
|
||||
def mcp_servers_auto_approve():
|
||||
return {"ok": False, "error": "neuron-connectd stub does not implement connector management yet"}
|
||||
|
||||
|
||||
@app.post("/mcp/servers/remove")
|
||||
def mcp_servers_remove():
|
||||
return {"ok": False, "error": "neuron-connectd stub does not implement connector management yet"}
|
||||
|
||||
|
||||
@app.post("/mcp/servers/secret")
|
||||
def mcp_servers_secret():
|
||||
return {"ok": False, "error": "neuron-connectd stub does not implement connector management yet"}
|
||||
|
||||
|
||||
@app.post("/mcp/oauth/start")
|
||||
def mcp_oauth_start():
|
||||
return {"ok": False, "error": "oauth not implemented in the neuron-connectd stub"}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--port", type=int, default=7771)
|
||||
args = parser.parse_args()
|
||||
uvicorn.run(app, host="127.0.0.1", port=args.port, log_level="info")
|
||||
Reference in New Issue
Block a user