nsbx: add one-command dev onboarding (branch + worktree + isolated engram)
El SDK CI - dev / build-and-test (pull_request) Successful in 6m30s

Add 'nsbx dev <name>' / 'nsbx dev-down <name>' plus a Makefile so a newcomer
goes from clone to coding on an isolated cloned engram in one command. The
worktree is created on a real named branch at a persistent path (never /tmp,
guarded), and the whole worktree is pinned to the clone via an emitted .nsbx-env
so live :8742 / ~/.neuron/engram is unreachable by accident. Optimizes the El
edit->build->run loop so provisional work is built in El against a throwaway
clone instead of prototyped in Python and re-ported. Additive over the proven
primitives; no live cutover.
This commit is contained in:
bigmerge
2026-08-14 17:24:06 -05:00
parent 112bb2540f
commit 6660becfdb
3 changed files with 295 additions and 0 deletions
+173
View File
@@ -623,10 +623,181 @@ cmd_status(){
[ -f "$(sdir "$name")/validate.json" ] && { echo "--- last validation ---"; python3 -m json.tool "$(sdir "$name")/validate.json"; }
}
# ================================================================ dev ==========
# ONE-COMMAND isolated dev environment. Everything a newcomer (Tim, any agent)
# needs to go from clone -> coding on an isolated running mind, in a single shot:
# 1) a git BRANCH (dev/<name>, or --prefix)
# 2) a git WORKTREE for it, at a visible path they can open + edit
# 3) an ISOLATED engram bound to a NON-default port, on a clone of the live store
# (stock prod binary by default — instant + safe; --build to compile the
# worktree's own runtime instead). Prod :$LIVE_BIND_PORT/:$SOUL_PORT is untouchable.
#
# This is additive sugar over the proven primitives (git worktree + cmd_create).
# It never binds a forbidden port and never touches ~/.neuron/engram (the live store)
# except the same READ-only snapshot cmd_create already performs.
#
# nsbx dev <name> [--repo R] [--base REF] [--worktree DIR] [--port N]
# [--prefix P] [--build] [--no-engram]
cmd_dev(){
local name="" repo="$EL_REPO" base="" wt="" port="" prefix="dev/" build=0 no_engram=0
[ $# -gt 0 ] && [ "${1#-}" = "$1" ] && { name="$1"; shift; } || die "usage: nsbx dev <name> [flags]"
while [ $# -gt 0 ]; do case "$1" in
--repo) repo="$2"; shift 2;;
--base) base="$2"; shift 2;;
--worktree|--wt) wt="$2"; shift 2;;
--port) port="$2"; shift 2;;
--prefix) prefix="$2"; shift 2;;
--build) build=1; shift;;
--no-engram) no_engram=1; shift;;
*) die "unknown flag: $1";;
esac; done
need git
git -C "$repo" rev-parse --git-dir >/dev/null 2>&1 || die "not a git repo: $repo"
local branch="${prefix}${name}"
local sbx="dev-${name}"
# default worktree path: a PERSISTENT, git-managed dir — NEVER /tmp (which is
# ablated on compaction). Default root = <repo-grandparent>/el-worktrees, i.e.
# ~/Development/neuron-technologies/el-worktrees/<name>. Override with NSBX_DEV_WT_ROOT.
local wt_root="${NSBX_DEV_WT_ROOT:-$(cd "$(dirname "$(dirname "$repo")")" && pwd -P)/el-worktrees}"
[ -n "$wt" ] || wt="${wt_root}/${name}"
case "$wt" in /tmp/*|/private/tmp/*|/var/tmp/*)
die "refusing worktree under a temp dir ($wt) — temp dirs are ablated on compaction; set NSBX_DEV_WT_ROOT to a persistent path";;
esac
# default base: whatever the repo's working checkout is on now
[ -n "$base" ] || base="$(git -C "$repo" rev-parse --abbrev-ref HEAD 2>/dev/null)"
# pre-flight (fail before creating anything)
[ "$no_engram" -eq 1 ] || ! mexists "$sbx" || die "engram sandbox '$sbx' already exists (nsbx dev-down $name first)"
[ -e "$wt" ] && die "worktree path already exists: $wt"
if [ -n "$port" ]; then
{ [ "$port" = "$LIVE_BIND_PORT" ] || [ "$port" = "$SOUL_PORT" ]; } && die "refusing forbidden port $port (live)"
fi
log "dev env '$name' (branch=$branch worktree=$wt base=$base)"
# ---- 1+2) branch + worktree in one shot ----
local gerr
if git -C "$repo" show-ref --verify --quiet "refs/heads/$branch"; then
info "branch $branch exists — checking it out into a new worktree"
gerr="$(git -C "$repo" worktree add "$wt" "$branch" 2>&1)" \
|| die "git worktree add failed for existing branch $branch:"$'\n'" $gerr"
else
gerr="$(git -C "$repo" worktree add -b "$branch" "$wt" "$base" 2>&1)" \
|| die "git worktree add -b $branch (base $base) failed:"$'\n'" $gerr"$'\n'" (a bare 'dev' branch blocks 'dev/*' names — try --prefix, e.g. nsbx dev $name --prefix wt/)"
fi
ok "worktree ready: $wt (branch $branch)"
# ---- 3) isolated engram ----
local eport="(none)"
if [ "$no_engram" -eq 1 ]; then
warn "--no-engram: skipped standing up an engram"
else
if [ "$build" -eq 1 ]; then
log "isolated engram: building the worktree's own runtime"
cmd_create "$sbx" ${port:+--port "$port"} --source "$wt" || die "engram create (--build) failed"
else
log "isolated engram: stock prod binary on a clone of the live store"
cmd_create "$sbx" ${port:+--port "$port"} || die "engram create failed"
fi
eport="$(mget "$sbx" "['port']")"
# record the dev linkage next to the sandbox so dev-down can clean up
python3 - "$(sdir "$sbx")/dev.json" "$name" "$branch" "$wt" "$repo" "$eport" <<'PY'
import json,sys
p,name,branch,wt,repo,port=sys.argv[1:7]
json.dump({"name":name,"branch":branch,"worktree":wt,"repo":repo,"port":int(port)},
open(p,'w'),indent=2)
PY
# ---- pin the WHOLE worktree to the CLONE ----
# Every var any El tooling in this worktree might read for an engram target now
# points at the isolated clone. Sourcing .nsbx-env makes hitting live :$LIVE_BIND_PORT
# or ~/.neuron/engram by accident structurally impossible from this shell.
local edata ekey eurl ebin
edata="$(sdir "$sbx")/data"; ekey="sbx-$sbx"; eurl="http://127.0.0.1:$eport"; ebin="$(sdir "$sbx")/bin/engram"
cat > "$wt/.nsbx-env" <<ENV
# nsbx dev env for '$name' — SOURCE this to pin THIS shell to the isolated clone.
# The live mind (:$LIVE_BIND_PORT engram / :$SOUL_PORT soul / $LIVE_DATA_DIR) is deliberately
# NOT referenced here. Regenerated by 'nsbx dev'. -> source .nsbx-env
export NSBX_NAME="$sbx"
export ENGRAM_URL="$eurl"
export ENGRAM_BIND=":$eport"
export ENGRAM_PORT="$eport"
export ENGRAM_HOST="127.0.0.1"
export ENGRAM_DATA_DIR="$edata"
export ENGRAM_API_KEY="$ekey"
export NEURON_ENGRAM_URL="$eurl"
export NEURON_ENGRAM_KEY="$ekey"
# nsbx run compatibility (same names 'nsbx run' exports)
export SBX_NAME="$sbx" SBX_PORT="$eport" SBX_URL="$eurl" SBX_KEY="$ekey" SBX_DATA="$edata" SBX_BIN="$ebin"
ENV
# direnv users get it automatically on cd; everyone else runs 'source .nsbx-env'
[ -e "$wt/.envrc" ] || printf 'source_env .nsbx-env 2>/dev/null || source .nsbx-env\n' > "$wt/.envrc"
ok "wrote $wt/.nsbx-env (pins this worktree to the clone)"
fi
# ---- summary ----
echo >&2
printf '%s DEV ENV READY — %s%s\n' "$C_BLD" "$name" "$C_0" >&2
printf ' %-10s %s\n' "worktree" "$wt" >&2
printf ' %-10s %s\n' "branch" "$branch" >&2
if [ "$no_engram" -ne 1 ]; then
printf ' %-10s %s\n' "engram" "http://127.0.0.1:$eport (isolated clone; prod :$LIVE_BIND_PORT untouchable)" >&2
printf ' %-10s %s\n' "sandbox" "$sbx" >&2
echo >&2
printf '%s env exported into %s/.nsbx-env (source it -> pinned to the clone):%s\n' "$C_DIM" "$wt" "$C_0" >&2
grep '^export' "$wt/.nsbx-env" | sed 's/^/ /' >&2
fi
echo >&2
info "code in: cd $wt && source .nsbx-env # now every engram var points at the clone"
[ "$no_engram" -ne 1 ] && info "poke it: nsbx run $sbx api /api/stats (or: make run NAME=$name)"
[ "$no_engram" -ne 1 ] && info "edit->test: make build NAME=$name && make run NAME=$name # El change -> clone, seconds"
info "tear down: nsbx dev-down $name (destroys engram + removes worktree; branch kept)"
}
# nsbx dev-down <name> [--delete-branch] [--repo R]
# Teardown counterpart: destroy the isolated engram, remove the git worktree,
# and (optionally) delete the branch. Live prod is never touched.
cmd_dev_down(){
local name="" repo="$EL_REPO" del_branch=0
[ $# -gt 0 ] && [ "${1#-}" = "$1" ] && { name="$1"; shift; } || die "usage: nsbx dev-down <name> [--delete-branch]"
while [ $# -gt 0 ]; do case "$1" in
--repo) repo="$2"; shift 2;;
--delete-branch) del_branch=1; shift;;
*) die "unknown flag: $1";;
esac; done
local sbx="dev-${name}" wt="" branch="dev/${name}"
# recover worktree/branch/repo from the dev linkage if present
if mexists "$sbx" && [ -f "$(sdir "$sbx")/dev.json" ]; then
local dj; dj="$(sdir "$sbx")/dev.json"
wt="$(python3 -c "import json;print(json.load(open('$dj'))['worktree'])" 2>/dev/null)"
branch="$(python3 -c "import json;print(json.load(open('$dj'))['branch'])" 2>/dev/null)"
repo="$(python3 -c "import json;print(json.load(open('$dj'))['repo'])" 2>/dev/null)"
fi
# 1) engram
if mexists "$sbx"; then cmd_destroy "$sbx"; else info "no engram sandbox '$sbx'"; fi
# 2) worktree
if [ -n "$wt" ] && [ -d "$wt" ]; then
log "removing git worktree $wt"
git -C "$repo" worktree remove --force "$wt" 2>/dev/null || rm -rf "$wt"
git -C "$repo" worktree prune 2>/dev/null || true
ok "worktree removed"
else info "no worktree to remove"; fi
# 3) branch (opt-in)
if [ "$del_branch" -eq 1 ]; then
git -C "$repo" branch -D "$branch" 2>/dev/null && ok "deleted branch $branch" || warn "could not delete branch $branch"
else info "branch $branch kept (use --delete-branch to remove)"; fi
ok "dev-down '$name' complete (live untouched)"
}
usage(){ cat >&2 <<EOF
${C_BLD}nsbx${C_0} — Neuron Sandbox: experiments + code changes against the REAL engram
runtime on an isolated snapshot of the live mind, with a gated promote-to-prod path.
nsbx dev <name> [--base REF] [--worktree DIR] ONE command onboarding: new branch (dev/<name>) + git
[--port N] [--prefix P] [--build] worktree (persistent, never /tmp) + isolated engram on a
[--no-engram] [--repo R] non-default port. clone -> coding on the mind in one shot.
nsbx dev-down <name> [--delete-branch] [--repo R] teardown: destroy the engram + remove the worktree
(branch kept unless --delete-branch). live untouched.
nsbx up [name] [flags…] one command: your private, isolated copy of the mind
(creates on first run, starts thereafter; prod untouchable)
nsbx create [name] [--port N] [--source DIR | --branch REF [--repo R] | --binary PATH]
@@ -647,6 +818,8 @@ EOF
main(){
local cmd="${1:-}"; shift || true
case "$cmd" in
dev) cmd_dev "$@";;
dev-down) cmd_dev_down "$@";;
up) cmd_up "$@";;
create) cmd_create "$@";;
build) cmd_build "$@";;