# Workspace — Shared Agent Configuration This file contains shared rules for all repositories in this workspace. Each member repository may have its own ``.muse/agent.md`` with repo-specific additions. Managed by `muse agent-config` — regenerate adapters with `muse agent-config sync`. --- ## Workspace Members | Repo | Path | Branch | |------|------|--------| | **muse** | `muse` | `dev` | | **musehub** | `musehub` | `dev` | | **agentception** | `agentception` | `dev` | | **contracts** | `contracts` | `dev` | | **Stori** | `Stori` | `dev` | | **maestro** | `maestro` | `dev` | | **muse-zsh** | `muse-zsh` | `dev` | --- ## Version Control This workspace uses **Muse** for version control — not git, not GitHub. - Never run `git`, `gh`, or any git subcommand. - Never reference GitHub, GitHub Actions, or GitHub URLs. - Use `muse -C ~/path/to/repo ` when CWD differs from the target repo. If you find a `git` or `gh` call anywhere — delete it in the same commit. --- ## Commit Convention — Agent-First This workspace is **agent-first**: agents do the work, humans provision agents. Every commit made by an agent must carry full provenance. Human commits (direct manual changes without an agent) are the exception, not the norm. ### Agent commit — always use this ```bash muse commit -m "feat: ..." \ --agent-id claude-code \ --model-id claude-sonnet-4-6 \ --sign ``` - `--agent-id` — identifies the agent type (`claude-code`, `codex`, `agentception/worker`, …) - `--model-id` — the specific model that produced the change (`claude-sonnet-4-6`, …) - `--sign` — embeds Ed25519 public key + signature; traces back to gabriel's root mnemonic in `~/.muse/identity.toml` Use the model you are actually running. For Claude Code the current model is `claude-sonnet-4-6`. ### Human commit — manual actions only ```bash muse commit -m "chore: manual config change" ``` No provenance flags. Their absence is itself a signal that a human acted directly. ### Provenance chain ``` ~/.muse/identity.toml ← root mnemonic (HD wallet seed, gabriel's root identity) ↓ HD derivation Ed25519 key pair ← signer_public_key embedded in every --sign commit ↓ signs CommitRecord ← agent_id + model_id + signature stored per-commit ↓ content-addressed sha256: ← tamper-evident, auditable forever ``` Agents spawned by agentception receive a derived key via `MUSE_AGENT_KEY` env var — their commits sign with that key, which itself traces back to gabriel's root identity. --- ## Branch Flow Always work on a feature branch — never commit directly to `main` or `dev`. ```bash muse -C ~/path/to/repo checkout dev muse -C ~/path/to/repo checkout -b task/my-thing muse rm # delete from disk + stage deletion (mirrors git rm) muse code add . # stage additions + modifications + already-deleted files muse commit -m "feat: ..." --agent-id claude-code --model-id claude-sonnet-4-6 --sign muse -C ~/path/to/repo checkout dev muse -C ~/path/to/repo merge task/my-thing muse -C ~/path/to/repo branch -d task/my-thing muse -C ~/path/to/repo push local dev ``` --- ## Code Intelligence | Task | Command | |------|---------| | Find symbol declaration | `muse code grep "Name" --json` | | Read one symbol | `muse code cat "file.py::Symbol" --json` | | File structure | `muse code symbols --file file.py --json` | | Blast radius | `muse code impact "file.py::Symbol" --json` | | Dependencies | `muse code deps "file.py" --json` | | Tests for changed code | `muse code test --json` | --- ## Testing Rules **Never run the full test suite.** It is slow and gabriel runs it when he's ready. 1. **Start with `muse code test --json`** — runs only tests relevant to changed files. 2. **Run one file at a time** when fixing a specific failure: ```bash python3 -m pytest tests/test_foo.py -q --tb=short ``` 3. **Run one test by name** to verify a fix: ```bash python3 -m pytest tests/test_foo.py::test_bar -q --tb=short ``` ### Forbidden - `python3 -m pytest tests/` — runs everything, never do this - `python3 -m pytest` with no path — same as above - `pytest -x tests/` or any whole-suite invocation - Looping retries on the same command after a failure — diagnose first # musehub — Agent Configuration This repository is a member of a workspace. Shared workspace rules live in the parent ``.muse/agent.md``. This file contains only musehub-specific additions. Managed by `muse agent-config` — regenerate adapters with `muse agent-config sync`. --- ## Proposal Titles Proposal titles must be plain English — not branch-name style. The branch (`feat/auth-v2`, `task/proposal-models-v2`) already encodes the type prefix. The title is what a human reads in the list; it should describe the change, not echo the branch. | Branch | Bad title | Good title | |--------|-----------|------------| | `feat/auth-v2` | `feat: auth v2` | `Ed25519 key rotation and MSign auth v2` | | `task/proposal-models-v2` | `feat: proposal models v2` | `Proposal type badges, 7-state tabs, and ghost object integrity fix` | | `fix/wire-timeout` | `fix: wire timeout` | `Increase push stream timeout to prevent drops on large repos` | Rule: if the title could be mistaken for a branch name or a commit message subject line, rewrite it. --- ## Localhost Container — ALWAYS Restart After Code Changes The localhost container (`musehub`) runs uvicorn **without** `--reload`. Code changes to the live-mounted volume are **not picked up until the container restarts**. This is non-negotiable: ```bash docker restart musehub && sleep 5 && curl -sk https://localhost:1337/healthz ``` **Do this immediately after every edit to musehub Python source.** No exceptions. Every cycle spent debugging "why aren't my logs showing up" is wasted because the container is running stale code. --- ## Repo-Specific Notes ### Staging Deploy ```bash bash deploy/push.sh staging # build, push to ECR, blue-green deploy bash deploy/push.sh prod # same for prod bash deploy/push.sh staging prod # staging then prod ``` ### Recovering a Down Staging Instance If staging returns 502 or the webserver is down: 1. **Restart the container** — containers use `--restart unless-stopped` so a reboot brings them back, but a manual `docker stop` does not: ```bash sudo docker start musehub-blue # or musehub-green, whichever is active ``` 2. **Switch the active slot** — the ONLY correct way to change which slot nginx points to: ```bash sudo musehub-set-slot blue # blue = port 1337 sudo musehub-set-slot green # green = port 1338 ``` This script lives at `/usr/local/bin/musehub-set-slot` on the instance. It is the only sanctioned way to write `/etc/nginx/musehub-active-port`. **Never write to that file directly** — it must contain a full nginx upstream directive (`server 127.0.0.1:1337;`), not a bare port number. Writing a bare port breaks nginx config parsing and causes 502s. 3. **Check current state**: ```bash cat /opt/musehub/.active-slot # which slot is active (blue or green) cat /etc/nginx/musehub-active-port # what nginx is pointing at sudo docker ps --format "{{.Names}} {{.Status}}" # container health ``` 4. **If SSM commands are stuck as Pending** — reboot the instance. Containers with `--restart unless-stopped` come back automatically: ```bash aws ec2 reboot-instances --region us-east-1 --instance-ids i-07547cd20bee2dea5 ``` Then poll until SSM is back before sending new commands: ```bash aws ssm describe-instance-information --region us-east-1 \ --filters "Key=InstanceIds,Values=i-07547cd20bee2dea5" \ --query 'InstanceInformationList[0].PingStatus' --output text ``` ### Instance IDs | Environment | Instance ID | |-------------|-------------| | staging | `i-07547cd20bee2dea5` | | prod | `i-0855d6efe7fa1a49d` |