Skip to content

Integration: all 5 refactor PRs merged + alignment fixes (the merge target)#6

Merged
kody-w merged 18 commits into
mainfrom
integration/all-phase1
Apr 21, 2026
Merged

Integration: all 5 refactor PRs merged + alignment fixes (the merge target)#6
kody-w merged 18 commits into
mainfrom
integration/all-phase1

Conversation

@kody-w

@kody-w kody-w commented Apr 21, 2026

Copy link
Copy Markdown
Owner

TL;DR

One integration branch that merges PRs #1#5 in order, resolves conflicts, and layers on two important corrections from the last review pass. Supersedes PRs #1#5 for merging to main — close those and merge this instead.

What's in it

PR What it adds
#1 Strip T2T federation + Articles XIV/XV
#5 Refine Article XV — /chat contract not transport
#2 Article XVI/XI — minimal root
#3 7 swarm-management agents (drop-in)
#4 Delete swarm_server.py + chat.py; rewrite function_app.py

Plus two post-merge corrections from user review:

Correction 1: agents/ stays at root; don't collapse it into the workspace

Original Article XVI implied all dynamic state moves to .brainstem_data/, which would have forced agents/ off the root. That defeats the training story — agents/ is the engine's public surface, the drag-and-drop-editable reference implementation users learn from.

Article rewritten (both src and rapp_brainstem copies): "The Root Is the Engine's Public Surface; the Brainstem's Workspace Is Separate." Two surfaces, two masters:

  • Engine's surface (root + agents/): what we ship. Curriculum. Editable. Visible.
  • Brainstem's workspace (~/.brainstem/…): scratch the brainstem writes while serving the user. Memory, deployed swarms, snapshots, calibration logs.

Correction 2: swarm agents use the memory-agent path pattern

PR #3's _swarms_root() had a 3-tier fallback with cwd sniffing. User: "use the same pattern that the memory_agents.py use." Simplified all 7 agents to match save_memory_agent.py:

def _swarms_root():
    p = os.environ.get("BRAINSTEM_SWARMS_PATH")
    return Path(p) if p else Path(os.path.expanduser("~/.brainstem/swarms"))

One env var, one home-relative default. Tier 2 sets the env to an Azure Files mount.

Conflicts resolved during merge

Test results

Suite Result
tests/test-t2t-removal.sh 16/16
tests/test-swarm-agents.sh 55/55
tests/test-function-app-chat.sh 32/32
tests/run-tests.mjs 59/59
Total 162/162

Live smoke test (brainstem.py on :7072 with LLM_FAKE=1)

  • /health returns 12 loaded agents (5 starters + 7 swarm-management).
  • Full lifecycle end-to-end against the running server:
    • DeploySwarm → success, new GUID
    • ListSwarms → sees 1 swarm
    • SwarmInfo → agents present, not sealed
    • InvokeSwarmAgent("Greet", args={name: "Kody"}) → "Hi, Kody"
    • SealSwarm(seal) → sealed=True
    • SnapshotSwarm(create) → refused because sealed
    • SealSwarm(unseal) → sealed=False
    • SnapshotSwarm(create) → success
    • DeleteSwarm(confirm=true) → success
    • ListSwarms → 0 swarms

Full integrated behavior works.

File summary

  • Deleted: rapp_brainstem/t2t.py, workspace.py, swarm_server.py, chat.py, tests/test-t2t.sh (net −~3500 lines).
  • Added: 7 swarm-management agents, 3 new tests (test-t2t-removal.sh, test-swarm-agents.sh, test-function-app-chat.sh), +Articles XIV/XV/XVI (src) and IX/X/XI (rapp_brainstem).
  • Rewritten: rapp_swarm/function_app.py (917 → 470 lines), rapp_swarm/build.sh (vendors llm.py/twin.py/_basic_agent_shim.py/agents/).
  • VERSION: 0.9.0 → 0.10.0.

Test plan before merging to main

  • bash tests/test-t2t-removal.sh → 16/16
  • bash tests/test-swarm-agents.sh → 55/55
  • bash tests/test-function-app-chat.sh → 32/32
  • node tests/run-tests.mjs → 59/59
  • bash rapp_swarm/build.sh produces a clean _vendored/ (no swarm_server, no chat.py, no t2t, no workspace)
  • PORT=7072 LLM_FAKE=1 python3 rapp_brainstem/brainstem.py boots, serves /health with all 12 agents, runs end-to-end swarm lifecycle

After merge

Close PRs #1#5 as superseded by this integration PR.

🤖 Generated with Claude Code

kody-w and others added 18 commits April 21, 2026 14:43
T2T (twin-to-twin cross-cloud federation) is a far-off feature that's
been shaping the architecture as if it were near-term. It is not: the
priority is adoption, and the relevant inter-swarm case is same-device
swarms talking through their own stems. This commit excises T2T and
adds two constitutional articles so the pattern doesn't creep back:

  • Article XIV — Swarms Are Directories, Not Routes.
    A swarm is local state; /chat reads it. No SwarmStore runtime
    abstraction, no /api/swarm/<guid>/* REST surfaces, no
    swarm-awareness in the brainstem core.

  • Article XV — Tier Parity Runs Deeper Than Agents.
    rapp_brainstem/brainstem.py and rapp_swarm/function_app.py must
    behave identically on /chat. Vendoring enforces one source of
    truth; tier parity is asserted per-PR, not deferred.

Concrete changes:
- Delete rapp_brainstem/t2t.py, rapp_brainstem/workspace.py
- Strip /api/t2t/* and /api/workspace/* route handlers from
  swarm_server.py and function_app.py
- Remove get_t2t_manager, get_workspace, related imports
- Drop t2t.py and workspace.py from rapp_swarm/build.sh vendor list
- Delete tests/test-t2t.sh; add tests/test-t2t-removal.sh covering
  structural + runtime absence of T2T/workspace surface (26 assertions)
- Scrub stale T2T references in CLAUDE.md, AGENTS.md, rapp_swarm/README.md,
  tests/run-tests.mjs, tests/test-twin-egg.sh, tests/test-hero-deploy.sh,
  rapp_brainstem/web/onboard/registry.json (collaboration_layers)
- Mirror the two new articles into rapp_brainstem/CONSTITUTION.md
- Bump rapp_brainstem/VERSION to 0.10.0 per Article VIII

Deferred to follow-up (secondary surfaces, ~1600 lines combined):
- rapp_swarm/twin-sim.sh still contains the T2T demo harness
- rapp_brainstem/web/mobile/rapp-mobile.js still mirrors t2t/workspace

Test results: 26/26 new + 60/60 JS + 10/10 hero-deploy (sections 1-2).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A new-user's first impression of rapp_brainstem/ is its root
directory. Every file at root competes for their attention. A
sprawling root signals complexity and pushes adoption downhill.

This amendment draws the line: root is the engine surface only.
Everything dynamic, user-generated, or session-scoped goes in
.brainstem_data/ — the "context of the digital twin living," the
twin's home on the user's device.

Scope:
  • src/CONSTITUTION.md — new Article XVI, Amendments pushed to XVII.
  • rapp_brainstem/CONSTITUTION.md — mirrored as Article XI,
    Amendments pushed to XII.

Enumerated what belongs at root (brainstem.py, soul.md, VERSION,
install scripts, docs, agents/, utils/, web/, base contracts) vs.
what belongs in .brainstem_data/ (memory, binder state, swarm
directories, snapshots, calibration logs, all runtime state).

Explicit rules-out:
  • No agent files or scratch Python at root — agents/ owns those.
  • No top-level JSON state files next to brainstem.py.
  • No new top-level directories "because it doesn't fit anywhere."
  • No seeded runtime state shipped with the engine.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Swarms are directories, not runtime abstractions (CONSTITUTION
Article XIV / rapp_brainstem Article IX). This commit delivers the
user-facing surface: seven *_agent.py files that let the LLM manage
sibling swarms through /chat, without any brainstem core changes.

Each agent is:
  • Single file, BasicAgent subclass (Article III / IV).
  • Stdlib + filesystem only — no imports from sibling agent files,
    no dependency on brainstem internals, no SwarmStore or equivalent.
  • Drop-in compatible with any brainstem.py: copy the file, the
    capability travels. Works unmodified in Tier 1 and Tier 2.
  • Operates on `<BRAINSTEM_HOME|cwd|~>/.brainstem_data/swarms/<guid>/`
    per Article XVI / XI (state lives in .brainstem_data/).

Agents shipped:

  1. swarm_deploy_agent   Installs a rapp-swarm/1.0 bundle, returns GUID.
  2. swarm_list_agent     Lists deployed swarms (reads manifest.json each).
  3. swarm_info_agent     Detailed view: manifest, agents, seal, snapshots.
  4. swarm_invoke_agent   Loads a sibling swarm's *_agent.py and runs its
                          perform(). The S2S primitive. Rebinds
                          BRAINSTEM_MEMORY_PATH so sibling writes land
                          in sibling swarm's memory, restores on exit.
  5. swarm_seal_agent     seal/unseal/status via .sealed marker file.
  6. swarm_snapshot_agent create/list snapshots. Refuses on sealed.
  7. swarm_delete_agent   Remove swarm. Requires confirm=true. Refuses
                          on sealed (unseal first).

Tests: tests/test-swarm-agents.sh — 55 assertions, stdlib-only, no
server. Covers happy path + error cases + end-to-end lifecycle
(deploy → invoke → snapshot → seal → refuse-delete → unseal → delete)
+ BRAINSTEM_HOME drop-in compat (two isolated roots, same agent
instances, state correctly scoped).

Note on PR stacking: this branch is off main, not refactor/strip-t2t.
The swarm agents are designed to work in any brainstem, including
unmodified older ones — no dependency on the T2T strip. VERSION
bumped to 0.10.0; if PR #1 merges first (also 0.10.0), rebase.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final phase of the one-stem-many-swarms refactor: Tier 2 becomes a
thin Azure Functions adapter over the /chat contract, matching Tier 1's
surface per CONSTITUTION Article XV — tier parity runs deeper than
agents.

Deletions (no remaining callers anywhere in the repo):
  • rapp_brainstem/swarm_server.py (1736 lines) — multi-swarm HTTP
    server. Its capabilities now ship as the 7 swarm-management agents
    in PR #3 (deploy/list/info/invoke/seal/snapshot/delete).
  • rapp_brainstem/chat.py (342 lines) — LLM tool-calling loop; logic
    inlined into function_app.py's run_chat (~100 lines).
  • rapp_brainstem/brainstem_admin_agent.py (root-level sprawl,
    Article XVI violation; an `experimental/` copy already exists).

New function_app.py (917 → 470 lines, -49%):
  • No SwarmStore, Binder, Assistant, STORE, or multi-tenant routing.
    /api/swarm/<guid>/* removed entirely — those capabilities flow
    through /api/chat via the PR #3 swarm-management agents.
  • Surface is /api/chat + /api/health + /api/llm/status + the OG
    aliases (/api/businessinsightbot_function, /api/trigger/copilot-studio).
  • Agent discovery from BRAINSTEM_HOME/agents/ (identical pattern to
    brainstem.py's own agents/).
  • Same tool-calling loop, same |||VOICE|||/|||TWIN||| split, same
    response envelope (response, voice_response, twin_response,
    session_id, agent_logs, provider, model).

build.sh now vendors only: llm.py, twin.py, _basic_agent_shim.py, and
agents/*.py (so Tier 2 ships with the same starter + swarm-management
agents Tier 1 users have).

Stale-reference cleanup:
  • tests/run-tests.mjs — removed chat.py from file-presence list.
  • brainstem.py load_agents — removed special-case always-load for
    the deleted brainstem_admin_agent.py.

Tests:
  • NEW: tests/test-function-app-chat.sh — 32 assertions. Exercises
    run_chat directly (no `func start`), verifies envelope parity
    with Tier 1, VOICE/TWIN split, agent discovery, tool-calling loop,
    BRAINSTEM_HOME swap, and Article XIV compliance (no /api/swarm/*,
    /api/t2t/*, /api/workspace/* routes).
  • run-tests.mjs: 61/61.

Known parity gap deferred to PR #5: brainstem.py's /chat still uses
Copilot-only (call_copilot at line 712). For full tier parity, it
should use llm.py's provider dispatch like function_app.py does — so
Tier 1 users can also point at Azure OpenAI / OpenAI / Anthropic from
one .env change. That's a separate, riskier change (touches the
one-liner install path, Article V) and lands independently.

VERSION bumped to 0.10.0 per Article VIII.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The original Article XV (and its mirror, Article X in
rapp_brainstem/CONSTITUTION.md) conflated two things: the /chat
contract that callers see (envelope + loop + split + agent behavior +
state layout) and the LLM transport that runs underneath it. The
bullet "❌ A Tier-1-only LLM provider path (e.g. Copilot-only) that
Tier 2 has to re-implement. Provider dispatch is shared." rules out
exactly the architecture we want.

Tier 1 is Copilot-only by design:
  • One auth chain (gh CLI), one provider, one training story.
  • Zero extra config for new users — the one-liner install is sacred
    (Article V).

Tier 2 is multi-provider by design:
  • Pushing to the RAPP cloud swarm is the moment the user declares
    WHICH AI their cloud deployment uses (Azure OpenAI, OpenAI,
    Anthropic, or whatever the deploy target gives access to).
  • Provider choice lives there because it's the cloud operator's
    constraint, not the learner's.

Both tiers still produce the same response envelope and run the same
tool-calling loop shape. That's the invariant tier parity actually
requires.

Changes:
  • Rename article: "Tier Parity Is a /chat Contract, Not a Transport"
    (both src/ and rapp_brainstem/ copies).
  • Enumerate what must be identical (envelope, loop shape, split,
    agent contract, state layout) vs. what may legitimately differ
    (mount point, LLM transport).
  • Replace the "provider dispatch is shared" rules-out with a clearer
    "don't add providers to Tier 1 that break the one-liner — put
    provider choice on the cloud-deploy side."
  • Call out explicitly that pushing to the cloud swarm is where
    LLM requirements get declared.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts:
#	rapp_brainstem/swarm_server.py
#	rapp_swarm/build.sh
#	rapp_swarm/function_app.py
PR #1 wrote this test when swarm_server.py + chat.py still existed
(stripped of T2T but present). PR #4 deletes both files entirely.
Post-merge, the runtime-grep sections reference files that are gone
and set -e kills the test mid-run.

Replace Section 2 (grep swarm_server.py for T2T refs) with a simpler
'swarm_server.py / chat.py entirely removed' check. Drop Section 5
(live swarm_server runtime test) — the server binary is gone. The
new test-function-app-chat.sh covers live function_app.py behavior.

16 assertions, all pass.
User feedback: (1) don't collapse agents/ into the brainstem's
workspace — agents/ is the engine's training surface, load-bearing for
drag-and-drop learning. (2) swarm agents should use the same path-
resolution pattern the memory agents have used since day one.

Swarm agent path resolution simplified:

  Before: 3-tier fallback with cwd sniffing —
    BRAINSTEM_HOME → cwd/.brainstem_data/swarms → ~/.brainstem_data/swarms

  After:  memory-agent pattern (one env, one default) —
    BRAINSTEM_SWARMS_PATH → ~/.brainstem/swarms/

All 7 agents updated (deploy, list, info, invoke, seal, snapshot,
delete). test-swarm-agents.sh updated to drive BRAINSTEM_SWARMS_PATH;
55/55 still pass. Full suite 162/162.

Article XVI (src) / Article XI (rapp_brainstem) rewritten: "The Root
Is the Engine's Public Surface; the Brainstem's Workspace Is
Separate." Two surfaces, two masters:

  • Engine's surface (root + agents/): what we ship to the user.
    Editable, drag-and-drop visible, the training curriculum. agents/
    stays at root; moving it would bury the learning path.

  • Brainstem's workspace (~/.brainstem/ or env-overridden): scratch
    the brainstem writes while serving the user. Memory, deployed
    swarms, snapshots, sealed markers, calibration logs, hatched
    projects. One env var per category, simple home-relative default.

Rules-out list updated accordingly: don't dump at root, don't move
agents/ out, don't use three-tier fallbacks, don't seed workspace
state on install.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…VII/XII)

User direction: agents/ should be the user-visible curriculum ONLY —
starter agents that teach what a RAPP agent looks like. Infrastructure
agents (swarm management, swarm factory) belong in a sibling system_agents/.
In-flight work in experimental_agents/. Turned-off agents in disabled_agents/.

Directory layout (enshrined):

  agents/              5 files — basic_agent + 4 starters (user curriculum)
  system_agents/       8 files — swarm_factory + 7 swarm-management agents
  experimental_agents/ 10 files — in-flight work (renamed from agents/experimental/)
  disabled_agents/     empty — move a file here to turn it off

Discovery changes:
  • brainstem.py load_agents() now globs agents/ + system_agents/ both.
    experimental_agents/ and disabled_agents/ never auto-load.
  • New SYSTEM_AGENTS_PATH env var override, matches AGENTS_PATH.
  • _register_shims() unchanged — agents.basic_agent shim still routes
    to agents/basic_agent.py, which is where the base class lives.
    System agents' `from agents.basic_agent import BasicAgent` works via
    the shim regardless of where the agent file lives.

Vendoring changes (rapp_swarm/build.sh):
  • Vendors agents/ + system_agents/ separately into _vendored/.
  • experimental_agents/ and disabled_agents/ NOT vendored (not
    production surface).

Tests updated (test-swarm-agents.sh):
  • Drops `from agents.swarm_X_agent import …` (no longer valid since
    the agents.* namespace only covers agents/ now).
  • Loads system agents by file path via importlib — mirrors the
    runtime discovery pattern.
  • 55/55 still pass.

Constitution:
  • src/CONSTITUTION.md — new Article XVII "Agents Live in Four
    Directories by Purpose" (Amendments pushed to XVIII).
  • rapp_brainstem/CONSTITUTION.md — mirrored as Article XII
    (Amendments pushed to XIII).

Full integrated test suite: 162/162 green
  • test-t2t-removal.sh:       16/16
  • test-swarm-agents.sh:      55/55
  • test-function-app-chat.sh: 32/32
  • run-tests.mjs:             59/59

Live smoke on :7072 confirms 12 agents load (4 user + 8 system).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Correction on the previous commit: directories should NOT be siblings
of agents/ — they should be INSIDE agents/. And discovery should
recurse so users can make their own subdirs to organize their swarms/
stacks ("drop a folder in, agents load").

Final layout:

  agents/                         ← user-organized recursive tree
    basic_agent.py                user curriculum (starter 5)
    hacker_news_agent.py
    learn_new_agent.py
    recall_memory_agent.py
    save_memory_agent.py
    system_agents/                ← engine infrastructure (auto-loads)
      swarm_{factory,deploy,list,info,invoke,seal,snapshot,delete}_agent.py
    experimental_agents/          ← never auto-loads (hand-load only)
      …in-flight work…
    disabled_agents/              ← never auto-loads (turned off)
    <user's own subdir>/          ← user's groupings, auto-load
      …their agents…

Discovery changes:
  • brainstem.py load_agents() now walks agents/ recursively via
    rglob("*_agent.py"). Skips any path containing experimental_agents/,
    disabled_agents/, or __pycache__ as an intermediate dir.
  • Dropped the SYSTEM_AGENTS_PATH env var — agents/system_agents/
    auto-loads because it's under agents/, no special-casing needed.
  • Added _AGENTS_EXCLUDED_SUBDIRS constant = frozenset of the three
    reserved names.

Tier 2 mirrors this:
  • function_app.py _load_agents() does the same recursive walk with
    the same exclusions.
  • rapp_swarm/build.sh vendors agents/ recursively via rsync with
    excludes for the reserved subdirs and __pycache__.

Constitution rewritten (both src and rapp_brainstem copies):
  • Article XVII / XII renamed "agents/ Is a User-Organized Tree."
  • Enumerates the starter 5 at top level.
  • Engine-provided subdirs (system_agents/, experimental_agents/,
    disabled_agents/) explained.
  • User-organized subdirs pattern documented: agents/sales_stack/,
    agents/personal_twin/, even nested like agents/ceo/roles/.
  • Rules-out: registry files, engine-imposed categories beyond
    the 3 reserved names, dumping beyond starter 5 at top level.

Live smoke (:7072, LLM_FAKE=1):
  • 12 agents on /health at startup (4 user + 8 system from
    system_agents/ subdir).
  • Dropped agents/smoke_stack/greet_agent.py → 13 agents on next
    /health request. No restart. Drop-a-folder-it-loads confirmed.

Tests: 162/162 green (test-swarm-agents.sh updated to load by file
path from the new agents/system_agents/ location).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User direction: make it explicit that agents/ is the ONE place users
operate to set up and manage their brainstem. Engine files are a
stable black box users never edit. All functional work the user ever
needs to do happens inside agents/.

Article edits (both src and rapp_brainstem):
  • Renamed from "…Is a User-Organized Tree" to "…IS the User's
    Workspace" (the stronger claim).
  • Opens with: "Engine files are for the engine. agents/ is for
    the user. Everything functional a user needs to do happens in
    agents/."
  • Explicit "no depth limit" on agents/ recursion — subdirs can
    contain subdirs indefinitely. Example worked end-to-end:
    agents/sales_stack/q4/prospects/outbound_agent.py auto-loads.

Rules-out list strengthened:
  • ❌ Making users touch engine files for brainstem-y things. The
    user's entire config surface is soul.md + .env + agents/ tree.
    Never "edit brainstem.py to…"
  • ❌ A "brainstem config" directory outside agents/ that users
    are expected to edit.
  • ❌ Any depth limit on agents/ recursion.

Live verification: dropped agents/sales_stack/q4/prospects/
outbound_agent.py on a running brainstem → /health picked it up on
the next request, no restart. 4-level-deep nesting works unchanged.

Tests: 162/162 still green. No code changes — just constitutional
clarification of existing behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
If agents/ is the user's workspace (Article XVII/XII), the UI that
manages it must mirror it exactly — no parallel organizational model,
no UI-only state, no hidden concepts that don't round-trip to disk.

New articles (src Article XVIII, rapp_brainstem Article XIII):

  • Every UI action maps 1:1 to a filesystem operation on agents/:
    - New agent        → write *_agent.py
    - New folder       → mkdir
    - Move / drag      → mv
    - Rename           → mv
    - Delete           → rm
    - Disable          → move into agents/disabled_agents/
    - Enable           → move back out
    - Mark experimental→ move into agents/experimental_agents/
    - Edit             → inline editor on the .py file

  • UI covers the user's full config surface per Article XII/XVII:
    soul.md (persona editor), .env (safe form), agents/ tree (main).
    Diagnostics (health, provider, copilot status) are read-only.

  • Reserved subdirs (system_agents/, experimental_agents/,
    disabled_agents/) are VISIBLE in the UI with their semantics
    explained — don't hide them. Users benefit from seeing where
    their swarm-management agents live and what's turned off.

Rules-out:
  • UI-only concepts (tags, categories) that don't round-trip to
    the filesystem.
  • Editing engine internals (brainstem.py, VERSION, requirements.txt,
    utils/) through the UI — those aren't the user's.
  • A separate registry alongside the filesystem. Disk IS the registry.
  • Hiding the reserved subdirs.
  • UI actions with no filesystem equivalent.

Amendments pushed one number further (XIX src, XIV rapp_brainstem).

No code changes — pure governance update. Tests 162/162 unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Moved root state → workspace (~/.brainstem/, env-overridable):
  • .swarms.json            → BRAINSTEM_SWARMS_FILE         (default ~/.brainstem/swarms.json)
  • .copilot_token          → BRAINSTEM_COPILOT_TOKEN_FILE  (default ~/.brainstem/copilot_token)
  • .copilot_session        → BRAINSTEM_COPILOT_SESSION_FILE (default ~/.brainstem/copilot_session)
  One-time auto-migration on first read moves existing files. No
  user loses state. Matches the memory-agent pattern.
  .agent_groups.json (legacy schema) is migrated-then-removed.

Moved root support modules → utils/:
  • twin.py, llm.py, _basic_agent_shim.py, local_storage.py
  • brainstem.py: `from local_storage import …` → `from utils.local_storage import …`
  • function_app.py: `from llm import …` → `from utils.llm import …`;
    same for twin and _basic_agent_shim.

Deleted from the repo:
  • pitchdemo.html (demo content, not engine surface)
  • local.settings.json (Azure secrets — MOVED to rapp_swarm/ where
    Azure Functions Core Tools expects it; still .gitignored)
  • .DS_Store (macOS junk — added to rapp_brainstem/.gitignore)

Vendoring updated (rapp_swarm/build.sh):
  • Now creates _vendored/utils/ and copies llm.py, twin.py,
    _basic_agent_shim.py there (mirrors Tier 1's utils/ layout).
  • agents/ tree recursive vendor unchanged.

Constitution updated (Article XVI/XI root-allowlist):
  • `utils/` now documented as holding llm.py/twin.py/local_storage.py/
    _basic_agent_shim.py/index_card.py — "anything brainstem.py
    imports beyond stdlib."
  • Dropped root-level listings for local_storage.py and
    _basic_agent_shim.py.

Tests updated:
  • test-t2t-removal.sh — Section 4 checks _vendored/utils/… paths.
  • run-tests.mjs — file-presence list points at utils/llm.py.

Final rapp_brainstem/ root: engine surface only.
  brainstem.py, VERSION, requirements.txt, start.sh/ps1,
  README.md, CLAUDE.md, CONSTITUTION.md, index.html, soul.md,
  agents/, utils/, web/, .env/.env.example/.gitignore.
  That's it.

162/162 tests green. Live smoke: 12 agents load, /health responds,
state files migrate cleanly, root stays clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Non-technical users now organize their brainstem entirely through a
browser UI at /manage. Power users drop into VS Code via a one-click
escape hatch. Every UI action = a filesystem operation on agents/ (no
UI-only state, no parallel model).

Backend (brainstem.py, +~450 lines):

  • _safe_agents_path() — path validator: resolves inside AGENTS_PATH,
    rejects path-traversal, null bytes, absolute inputs, symlink escape.
  • _agents_tree_json() — recursive tree as nested JSON with
    status/reserved/system flags for the UI to style.
  • _AGENT_TEMPLATES — 5 starter templates (echo, http_get, note_taker,
    persona, slack_notifier). Each renders with the user's chosen
    agent_name into a fully-formed *_agent.py.

  New routes:
    GET    /manage                    serve web/manage.html
    GET    /api/agents/tree           nested JSON of agents/
    POST   /api/agents/mkdir          create subdir
    POST   /api/agents/move           rename / drag-drop / enable/disable
    POST   /api/agents/new            create agent from template
    POST   /api/agents/delete         remove file or empty subdir
    GET    /api/agents/templates      list starter templates
    POST   /api/agents/open-in-vscode launch `code <path>` (localhost only)
    GET    /api/config                soul + whitelisted env + secret presence
    POST   /api/config/soul           overwrite soul.md
    POST   /api/config/env            update .env (whitelist-gated)

  Guardrails:
    - reserved dirs (system/experimental/disabled_agents) can't be deleted
    - open-in-vscode refuses non-loopback requesters
    - config/env silently drops non-whitelisted keys; secrets are
      presence-only, never round-tripped
    - SOUL_PATH/AGENTS_PATH resolve to absolute paths at boot so cwd
      changes don't redirect writes

Frontend (web/manage.html, ~550 lines, zero deps):

  • Header tabs: Agents | Persona | Settings + "← Chat" link back.
  • Agents tab:
    - Recursive tree view with folder/agent icons, collapsible.
    - Badges: reserved (system_agents/experimental_agents/
      disabled_agents), system (inside system_agents), experimental,
      disabled.
    - Toolbar: + New Agent (template modal), 📁 New Folder, ↻ Refresh,
      Open in VS Code.
    - Drag-drop agents between folders — drop on disabled_agents to
      turn them off.
    - Right-click menu per node: Rename, Disable/Enable, Delete,
      Open in VS Code.
    - Template modal with 5 cards, icon + description + name field.
    - First-run wizard explains the three tabs when agents/ looks
      like a fresh install.
  • Persona tab: soul.md textarea + Save/Reload.
  • Settings tab: model + voice/twin toggles + secret-presence chips.
  • Toast system for success/error feedback.

Tests (tests/test-agents-api.sh, 42 assertions):
  • tree, templates, mkdir (incl. nested + path-traversal rejection)
  • new agent (success, duplicate 409, unknown template 400)
  • move (rename, drag to disabled, re-enable, destination-conflict 409,
    path-traversal 400)
  • delete (file + reserved-dir 403 protection)
  • config: get shape, soul round-trip, env whitelist enforcement

Full suite: 204/204 green across 5 test files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@kody-w kody-w merged commit 75848c2 into main Apr 21, 2026
1 check passed
@kody-w kody-w deleted the integration/all-phase1 branch April 21, 2026 20:48
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