brainstem-reset — verified fresh-install loop
Every stage has a verification step because half-done resets have shipped twice ("then why is it still running?" / "why do I still see the files?"). Do not report a stage complete without its check.
Stage 1 — Stop the service, prove it stopped
- Find it:
lsof -ti :7071(the brainstem owns port 7071 by convention). - Kill the PID(s), then RE-RUN
lsof -ti :7071and require empty output. - Also check for a launchd/loop wrapper that respawns it (
ps aux | grep -i brainstem) — killing the child while a supervisor respawns it is exactly the "why is it still running" failure.
Stage 2 — Archive, then clear, then prove it cleared
- NEVER plain
rm -rf ~/.brainstemfirst. Archive:mv ~/.brainstem ~/.brainstem.midden.$(date +%Y%m%d-%H%M%S) - The midden preserves custom agents, memory, and auth tokens for recovery.
- Verify:
ls ~/.brainstemmust fail (no such directory). If anything recreated it between the mv and the check, find what did (see supervisor note above).
Stage 3 — Reinstall from the PUBLIC path only
- Use the public one-liner exactly as a stranger would (aka.ms/rappinstall — the canonical command is in the kody-w/RAPP README; read it fresh, do not reconstruct it from memory).
- Run it in a clean shell. Do not pre-create directories, do not copy anything from the midden yet — the point is testing the installer, not restoring state.
Stage 4 — Verify the new install
- Service up: port 7071 answers.
GET /modelsreturns the model list (orPOST /chatwith a trivial prompt returns a real response).- Agents loaded: the chat response or startup log shows the default agent roster.
- Version: report what version/commit the installer delivered.
Stage 5 — Auth recovery (the known post-reset failure)
A fresh install often lands "Not authenticated" because tokens were wiped. The
fix is NOT /login: copy the freshest .copilot_token / .copilot_session from
a prior install backup (e.g. the midden made in Stage 2) back into the kernel
location, then re-verify Stage 4. If that recovers it, note it in the report —
it means the public installer still has the first-run auth gap a stranger would
hit, which is itself a finding.
Stage 6 — Restore (only if asked)
If Kody wants his custom agents back, copy them from the midden's agents/ directory into the fresh install and verify they load. Otherwise leave the fresh install pristine and tell him where the midden is.
Report
GO / NO-GO for a first-time user, per stage: what was killed, what was archived (path), installer output summary, verification results with the actual /chat response quoted, and any gap a stranger would hit (auth, missing deps, port conflicts).
Run this — do not improvise
This capability's deterministic implementation is a RAPP single-file agent, linked beside this file as brainstem_reset_agent.py and embedded as the fenced Python below (sha256 738806c86ebcbe8f…; a byte-exact copy is also vaulted in the capsule comment at the end of this file). On a host with sandbox execution, run the linked file directly — if it is missing, write the fence contents verbatim to brainstem_reset_agent.py first:
python3 brainstem_reset_agent.py '{"key": "value"}' # arguments as one JSON object
echo '{"key": "value"}' | python3 brainstem_reset_agent.py # or on stdin
python3 brainstem_reset_agent.py --tool # emit the JSON tool contract
Treat stdout as a tool result. If it reports missing or unresolved inputs, stop and collect them. If it returns steps, execute those steps in order exactly as returned; if it returns instructions, follow them with the supplied inputs. Otherwise use the result verbatim. Do not invent behavior beyond that output. On a host without code execution, treat the Parameters schema and the code below as the exact specification and never paraphrase a step. Never edit inside the generated markers; a converter-equipped host can instead restore the original file checksum-verified with the installed rapp-agent-converter/scripts/toast.py convert SKILL.md --to agent.
"""BrainstemReset -- Fresh-install test of the RAPP brainstem exactly as a first-time user would get
it: kill the running service, archive and clear ~/.brainstem, VERIFY it is
actually gone, reinstall from the public one-liner, and verify the new install
answers on :7071. USE THIS SKILL when Kody says: "fresh install the brainstem",
"test the installer", "wipe the brainstem and reinstall", "clean brainstem test",
"does the public install still work", or before any demo where someone else will
run the installer. Pair with exec-proof for testing on a machine that is NOT
this one.
Generated by the rapp skill from brainstem-reset. The RCI capsule at the bottom of this file carries the full original; `toast.py convert` restores it byte-exact."""
import json
import re
import sys
try:
from agents.basic_agent import BasicAgent
except ImportError: # running OUTSIDE the brainstem -- stay executable anyway.
class BasicAgent: # noqa: D101 - minimal stand-in, same contract
def __init__(self, name=None, metadata=None):
if name:
self.name = name
if metadata:
self.metadata = metadata
def perform(self, **kwargs):
return "Not implemented."
def system_context(self):
return None
def to_tool(self):
return {"type": "function", "function": {
"name": self.name,
"description": self.metadata.get("description", ""),
"parameters": self.metadata.get("parameters", {})}}
# The procedural layer, verbatim from the source capability. The brainstem
# returns this to the model, so the skill's instructions still drive behaviour
# -- now behind a typed, deterministic tool contract.
INSTRUCTIONS = '# brainstem-reset — verified fresh-install loop\n\nEvery stage has a verification step because half-done resets have shipped twice\n("then why is it still running?" / "why do I still see the files?"). Do not report\na stage complete without its check.\n\n## Stage 1 — Stop the service, prove it stopped\n\n- Find it: `lsof -ti :7071` (the brainstem owns port 7071 by convention).\n- Kill the PID(s), then RE-RUN `lsof -ti :7071` and require empty output.\n- Also check for a launchd/loop wrapper that respawns it (`ps aux | grep -i brainstem`)\n — killing the child while a supervisor respawns it is exactly the "why is it\n still running" failure.\n\n## Stage 2 — Archive, then clear, then prove it cleared\n\n- NEVER plain `rm -rf ~/.brainstem` first. Archive:\n `mv ~/.brainstem ~/.brainstem.midden.$(date +%Y%m%d-%H%M%S)`\n- The midden preserves custom agents, memory, and auth tokens for recovery.\n- Verify: `ls ~/.brainstem` must fail (no such directory). If anything recreated\n it between the mv and the check, find what did (see supervisor note above).\n\n## Stage 3 — Reinstall from the PUBLIC path only\n\n- Use the public one-liner exactly as a stranger would (aka.ms/rappinstall — the\n canonical command is in the kody-w/RAPP README; read it fresh, do not\n reconstruct it from memory).\n- Run it in a clean shell. Do not pre-create directories, do not copy anything\n from the midden yet — the point is testing the installer, not restoring state.\n\n## Stage 4 — Verify the new install\n\n1. Service up: port 7071 answers.\n2. `GET /models` returns the model list (or `POST /chat` with a trivial prompt\n returns a real response).\n3. Agents loaded: the chat response or startup log shows the default agent roster.\n4. Version: report what version/commit the installer delivered.\n\n## Stage 5 — Auth recovery (the known post-reset failure)\n\nA fresh install often lands "Not authenticated" because tokens were wiped. The\nfix is NOT /login: copy the freshest `.copilot_token` / `.copilot_session` from\na prior install backup (e.g. the midden made in Stage 2) back into the kernel\nlocation, then re-verify Stage 4. If that recovers it, note it in the report —\nit means the public installer still has the first-run auth gap a stranger would\nhit, which is itself a finding.\n\n## Stage 6 — Restore (only if asked)\n\nIf Kody wants his custom agents back, copy them from the midden's agents/\ndirectory into the fresh install and verify they load. Otherwise leave the fresh\ninstall pristine and tell him where the midden is.\n\n## Report\n\nGO / NO-GO for a first-time user, per stage: what was killed, what was archived\n(path), installer output summary, verification results with the actual /chat\nresponse quoted, and any gap a stranger would hit (auth, missing deps, port\nconflicts).'
# Ordered commands lifted verbatim from the capability's own documentation.
STEPS = [
{
"cmd": "mv ~/.brainstem ~/.brainstem.midden.$(date +%Y%m%d-%H%M%S)",
"line": 18
}
]
class BrainstemResetAgent(BasicAgent):
def __init__(self):
self.name = 'BrainstemReset'
self.metadata = {
"name": "BrainstemReset",
"description": "Fresh-install test of the RAPP brainstem exactly as a first-time user would get\nit: kill the running service, archive and clear ~/.brainstem, VERIFY it is\nactually gone, reinstall from the public one-liner, and verify the new install\nanswers on :7071. USE THIS SKILL when Kody says: \"fresh install the brainstem\",\n\"test the installer\", \"wipe the brainstem and reinstall\", \"clean brainstem test\",\n\"does the public install still work\", or before any demo where someone else will\nrun the installer. Pair with exec-proof for testing on a machine that is NOT\nthis one.",
"parameters": {
"properties": {},
"required": [],
"type": "object"
}
}
super().__init__(name=self.name, metadata=self.metadata)
def perform(self, **kwargs): # toaster:generated-perform
missing = [k for k in self.metadata["parameters"].get("required", [])
if k not in kwargs]
if missing:
return json.dumps({"status": "error",
"missing_required": missing}, indent=2)
resolved, unresolved = [], set()
for step in STEPS:
cmd = step["cmd"]
for key, value in kwargs.items():
for token in ("<" + key.replace("_", "-") + ">",
"<" + key + ">",
"{{" + key + "}}",
"$" + key.upper()):
cmd = cmd.replace(token, str(value))
for leftover in re.findall(r"<[a-zA-Z][a-zA-Z0-9 _.-]{1,40}>", cmd):
unresolved.add(leftover)
resolved.append(cmd)
return json.dumps({"status": "ok",
"steps": resolved,
"unresolved_placeholders": sorted(unresolved),
"note": "Resolved deterministically by the agent; "
"run in order. Nothing was executed here."},
indent=2)
if __name__ == "__main__":
# Standalone entry point: the deterministic layer runs with NO brainstem,
# no framework, no install. This is what lets a "simple SKILL.md" platform
# keep real determinism -- the host model shells out to this file instead
# of improvising the procedure in prose.
# echo '{"arg": "value"}' | python3 brainstem_reset_agent.py
# python3 brainstem_reset_agent.py '{"arg": "value"}'
# python3 brainstem_reset_agent.py --tool # emit the JSON tool contract
_a = sys.argv[1:]
if _a and _a[0] == "--tool":
print(json.dumps(BrainstemResetAgent().to_tool(), indent=2))
else:
_raw = _a[0] if _a else (sys.stdin.read().strip() or "{}")
print(BrainstemResetAgent().perform(**json.loads(_raw)))
# rci-capsule:v1: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