Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ See the **[PyAutoBrain Dashboard](https://pyautolabs.github.io/PyAutoBrain/)**
for the organism's morning and general starting point: what ran overnight, the
Heart's readiness headline, who in the community is waiting on a reply, what
to resume, and the upkeep doors — each actionable row with a one-tap 📋
copy-for-Claude command. Regenerated each morning; the local sync/clean leg is
copyable agent command. Regenerated each morning; the local sync/clean leg is
one terminal command, `bash bin/morning.sh` — or schedule it overnight on the
dev box with `bash bin/morning_timer.sh install`, so the board is already
fresh when you wake.

## How PyAutoBrain works

You drive it in plain English, through short slash commands in a Claude Code
You drive it in plain English, through discoverable skills in Codex or slash commands in Claude Code
chat: `/intake` to file an idea, `/start_dev` to begin a task, `/health` for a
check-up — or just `/route <what you want>` and the Brain picks the right
door. The generated table in [AGENTS.md](AGENTS.md) is the roster — every
Expand Down Expand Up @@ -60,9 +60,25 @@ CLI, which runs straight from this checkout (no pip install):
bin/pyauto-brain help # list every conductor and faculty
bin/pyauto-brain route "fix the failing lens smoke test" # plain English in
bin/pyauto-brain vitals # read the Heart's readiness verdict
bash bin/install.sh # symlink every organ's skills into ~/.claude
bash bin/install.sh # install shared skills for Claude Code and Codex
```

Project discovery is generated separately from the registered repository body
map. For example, after adding an assistant skill:

```bash
bash bin/install.sh --write-project-discovery autolens_assistant
bash bin/install.sh --check-project-discovery autolens_assistant
```

Without repository arguments these commands cover registered checkouts with
canonical `skills/` content. Flat assistant skills keep their Claude names and
get namespaced Codex adapters; workspace skills use neutral
`skills/<name>/SKILL.md` bodies. Codex discovery descriptions are bounded summaries;
the linked canonical file retains the full instructions. Commit the generated
adapters with the skill. Regeneration checks name collisions across the installed
repository inventory and refuses conflicting user-owned destinations.

The eight organs the Brain coordinates — Brain (reasoning), Mind (intent),
Cortex (learning what is true), Memory (knowledge), Heart (health), Hands
(release), Nerves (configuration), Gut (shedding) — are defined once in
Expand Down
7 changes: 7 additions & 0 deletions agents/conductors/clone/_clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@
".claude/hooks/*", ".claude/settings.json", ".codex/hooks.json", ".gemini/*",
".claude/skills/_*", ".claude/skills/start-new-project*",
".claude/skills/contribute-upstream*",
".claude/commands/_*", ".claude/commands/start-new-project*",
".claude/commands/contribute-upstream*",
]

# Domain content a newborn regenerates/stubs rather than copies blind, shared
Expand All @@ -105,6 +107,8 @@
# in a domain assistant, but the near-empty framework scaffold (generic) in the
# domain-agnostic base — so each profile places it, not this shared set.
_SHARED_DOMAIN = [
# Generated names/targets belong to the parent; regenerate for the newborn.
".codex/skills/*",
"dataset/*",
"README.md", # science framing + the example prompts
"hpc/*",
Expand Down Expand Up @@ -133,6 +137,8 @@
),
"generic": _SHARED_GENERIC,
"domain": [
".claude/commands/al_*.md",
".claude/commands/euclid_*.md", ".claude/commands/init-slam.md",
"skills/al_*.md", # every al_* skill body
".claude/skills/al_*.md", # ... and their harness mirrors
"skills/init-slam.md", ".claude/skills/init-slam.md", # SLAM = lensing
Expand Down Expand Up @@ -166,6 +172,7 @@
*_SHARED_GENERIC,
"skills/af_*.md", # generic inference skills
".claude/skills/af_*.md", # ... and their harness mirrors
".claude/commands/af_*.md",
"wiki/core/*", # statistics/inference reference
"wiki/literature/*", # the near-empty literature scaffold
],
Expand Down
3 changes: 2 additions & 1 deletion agents/faculties/memory/_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ def surfaces(memory: Path | None, assistant: Path | None, mind: Path | None):
# queue, the bibliography workflow, and the wiki schema. Without
# these the front door PyAutoMemory/AGENTS.md points every agent at
# ("index first") was invisible to this faculty (PyAutoBrain#239).
schema = "wiki/AGENTS.md" if (memory / "wiki/AGENTS.md").is_file() else "wiki/CLAUDE.md"
for rel in ("index.md", "reading-queue.md",
"bibliography/README.md", "wiki/CLAUDE.md"):
"bibliography/README.md", schema):
f = memory / rel
if f.is_file():
yield "PyAutoMemory/root", memory, f
Expand Down
96 changes: 9 additions & 87 deletions bin/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# Claude-only command files remain available as slash commands. Roots that
# aren't checked out are simply skipped.
#
# Discovery roots (scanned in order):
# User-level install roots (scanned in order):
# - admin_jammy/skills/ — vestigial: admin_jammy hosts no skills and is
# slated to leave PyAutoLabs/; kept only so an old
# checkout still resolves, auto-skipped once gone
Expand Down Expand Up @@ -276,100 +276,22 @@ workspace_policy() {

# ---------- Committed per-tool discovery (web/cloud) ----------
#
# The user-level ~/.claude / ~/.codex symlinks (below) are NOT loaded in cloud/
# web sessions — only committed repo files travel. So each skill-hosting repo
# also COMMITS a project-level discovery tree — .claude/commands, .claude/skills
# and .codex/skills — as relative symlinks into that repo's own skills/, so the
# slash commands and skills register on web with no user-level install. Per-repo:
# each repo mirrors its OWN skills/ (no cross-repo duplication); a Brain-loaded
# web session gets Brain's verbs, and every other repo's commands register when it
# is checked out. The AGENTS.md command surface (above) still advertises the full
# verb set + hosting organ. Generated + drift-checked — do not hand-edit these
# dirs. Symlinks (single source = skills/), matching the user-level install.
DISCOVERY_REPOS=(PyAutoBrain PyAutoMind PyAutoHeart PyAutoHands autolens_profiling)
DISCOVERY_DIRS=(.claude/commands .claude/skills .codex/skills)

# Emit the (link<TAB>target) pairs a repo's committed discovery should contain,
# derived from its skills/. Link is relative to the repo root; target relative to
# the link's own directory. Mirrors the user-level install rules: a SKILL.md dir
# becomes a Claude + Codex skill (Codex uses the frontmatter `name:` when valid);
# a <name>.md becomes a Claude slash command.
_discovery_manifest() {
local repo_dir="$1" skills_dir="$1/skills" entry name sk
[ -d "$skills_dir" ] || return 0
for entry in "$skills_dir"/*/; do
[ -d "$entry" ] || continue
name=$(basename "$entry")
if [ -f "$entry/SKILL.md" ]; then
printf '.claude/skills/%s\t../../skills/%s\n' "$name" "$name"
sk=$(sed -n 's/^name:[[:space:]]*//p' "$entry/SKILL.md" | head -1)
if [ -n "$sk" ] && [[ "$sk" != *[!a-z0-9-]* ]]; then
printf '.codex/skills/%s\t../../skills/%s\n' "$sk" "$name"
fi
fi
if [ -f "$entry/$name.md" ]; then
printf '.claude/commands/%s.md\t../../skills/%s/%s.md\n' "$name" "$name" "$name"
fi
done | sort
}

# All currently-present managed symlinks in a repo, as (link<TAB>target), sorted.
_discovery_actual() {
local repo_dir="$1" d link
for d in "${DISCOVERY_DIRS[@]}"; do
[ -d "$repo_dir/$d" ] || continue
for link in "$repo_dir/$d"/*; do
[ -L "$link" ] || continue
printf '%s\t%s\n' "${link#"$repo_dir"/}" "$(readlink "$link")"
done
done | sort
}

# Project discovery is generated from every registered repository in the Mind
# body map. Claude links remain relative to canonical skills/; Codex adapters
# expose flat assistant and workspace skills under stable namespaced names.
# This committed tree is available in cloud/web sessions without user-level setup.
# The Python generator uses the registered body map and preserves user-owned files.
write_project_discovery() {
local repo repo_dir link target d
for repo in "${DISCOVERY_REPOS[@]}"; do
repo_dir="$(pyauto_repo_path "$repo" "$PYAUTO_ROOT")"
if [ ! -d "$repo_dir/skills" ]; then echo "skipped (no skills/): $repo_dir"; continue; fi
# Drop our managed symlinks (only symlinks — never real files) so a removed
# or renamed skill does not leave a stale committed link.
for d in "${DISCOVERY_DIRS[@]}"; do
[ -d "$repo_dir/$d" ] && find "$repo_dir/$d" -maxdepth 1 -type l -delete 2>/dev/null || true
done
while IFS=$'\t' read -r link target; do
[ -n "$link" ] || continue
mkdir -p "$repo_dir/$(dirname "$link")"
ln -sf "$target" "$repo_dir/$link"
done < <(_discovery_manifest "$repo_dir")
echo "wrote discovery: $repo (.claude/{commands,skills}, .codex/skills)"
done
python3 "$SCRIPT_DIR/project_discovery.py" write --root "$PYAUTO_ROOT" "$@"
}

# Optional trailing repo names narrow the check to those repos (the pytest leg
# checks PyAutoBrain alone, so a local run is not reddened by a sibling's drift).
check_project_discovery() {
local repo repo_dir want got drift=0
local repos=("${DISCOVERY_REPOS[@]}")
[ "$#" -gt 0 ] && repos=("$@")
for repo in "${repos[@]}"; do
repo_dir="$(pyauto_repo_path "$repo" "$PYAUTO_ROOT")"
[ -d "$repo_dir/skills" ] || continue
want="$(_discovery_manifest "$repo_dir")"
got="$(_discovery_actual "$repo_dir")"
if [ "$want" = "$got" ]; then
echo "OK: $repo"
else
echo "DRIFT: $repo — run: bash PyAutoBrain/bin/install.sh --write-project-discovery"
diff <(printf '%s\n' "$want") <(printf '%s\n' "$got") | sed 's/^/ /'
drift=1
fi
done
return "$drift"
python3 "$SCRIPT_DIR/project_discovery.py" check --root "$PYAUTO_ROOT" "$@"
}

case "${1:-}" in
--write-agents-surface) write_agents_surface; exit 0 ;;
--check-agents-surface) check_agents_surface; exit $? ;;
--write-project-discovery) write_project_discovery; exit 0 ;;
--write-project-discovery) shift; write_project_discovery "$@"; exit $? ;;
--check-project-discovery) shift; check_project_discovery "$@"; exit $? ;;
--write-workspace-policy) workspace_policy write; exit $? ;;
--check-workspace-policy) workspace_policy check; exit $? ;;
Expand Down
Loading
Loading