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
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,22 @@ bin/pyauto-brain vitals # read the Heart's readiness verdict
bash bin/install.sh # symlink every organ's skills into ~/.claude
```

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
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