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
115 changes: 80 additions & 35 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,118 @@
# PyAutoAgent — Agent Guidance
# PyAutoBrain — Agent Guidance

This file is for AI coding agents (Claude Code, Codex, Cursor, etc.) and humans
discovering this repository. It is the canonical description of the
Build / Pulse / Agent split; PyAutoBuild and PyAutoPulse point back here.
discovering this repository. It is the canonical description of PyAutoBrain — the
**reasoning layer** of the PyAuto organism — and of the Brain / Heart / Build
boundary; PyAutoBuild and PyAutoHeart point back here.

> Renamed from **PyAutoAgent** to **PyAutoBrain**. The CLI is now `pyauto-brain`;
> `pyauto-agent` remains as a back-compat shim. See "Renamed from PyAutoAgent".

## What this repo is

PyAutoAgent is the **orchestration brain** of the PyAuto release ecosystem. It
hosts named *agents* — each a documented role plus a deterministic entrypoint
script — that read tasks (from PyAutoPrompt and the developer), dispatch work,
and drive the release/health machinery at the right points.
PyAutoBrain is the **reasoning layer** of the PyAuto ecosystem as it grows into a
software organism. It figures out *how* work should be done and coordinates the
organs that do it. It hosts specialist **reasoning agents** — each a documented
role plus a deterministic entrypoint script — that read intent (from PyAutoMind
and the developer), reason about it, and drive the health/execution machinery at
the right points.

PyAutoBrain owns **no state, no health checks, and no execution mechanics**. It
only *reasons* and *delegates*: it asks PyAutoHeart whether the organism is
healthy, decides whether and how to proceed, and tells PyAutoBuild to execute
when it should.

## The organism

The PyAuto ecosystem is structured as a software organism. Each repo is an
organ with one job:

| Organ | Repo | Role |
|-------|------|------|
| **Mind** | PyAutoMind | Decides *what* should be done — intent, goals, priorities, future work. |
| **Brain** | **PyAutoBrain** (this repo) | Figures out *how* — reasoning, planning, decomposition, orchestration, agent coordination, decision-making. |
| **Hands** | PyAutoBuild | Builds and releases the software — packaging, tagging, notebooks, PyPI. (May later be renamed PyAutoHands.) |
| **Heart** | PyAutoHeart | Determines whether the organism is healthy — the authoritative readiness verdict. |
| **Memory** | PyAutoMemory | Long-term scientific, software and project knowledge. |

PyAutoAgent owns **no state, no checks, and no release mechanics**. It only
*decides* and *delegates*: it asks PyAutoPulse whether things are healthy, and
tells PyAutoBuild to execute when they are.
The clean boundary, in one line each:

## The boundary (one description, mirrored in all three repos)
- **Mind** → decides what should be done.
- **Brain** → figures out how.
- **Hands** → build and release the software.
- **Heart** → determines whether the organism is healthy.

- **PyAutoPulse — the health authority.** All health/readiness logic lives here:
PyAutoBrain does not build or release software (that belongs to the Hands /
PyAutoBuild) and does not measure health (that belongs to the Heart /
PyAutoHeart). The Brain determines *how* work should be done; the Hands build
and release it; the Heart says whether it is safe to.

## The boundary (one description, mirrored across the organs)

- **PyAutoHeart — the health authority.** All health/readiness logic lives here:
version drift, install-path, URL hygiene, CI/worktree/timing monitoring.
`pyauto-pulse readiness` is the **authoritative** green/yellow/red verdict —
the single "is it safe to release?" gate. Pulse is an observer: it reads and
`pyauto-heart readiness` is the **authoritative** green/yellow/red verdict —
the single "is it safe to release?" gate. Heart is an observer: it reads and
emits verdicts; it never writes into other repos and never triggers Build.
- **PyAutoBuild — the executor.** Packaging, tagging, notebook generation, and
PyPI publication via `release.yml`. Build runs **no** readiness checks of its
own and never re-derives a gate decision; it just executes.
- **PyAutoAgent — the brain.** Hosts the agents that connect the two. It owns no
checks and no release steps; it gates on Pulse and delegates execution to
Build.
- **PyAutoBuild — the executor (Hands).** Packaging, tagging, notebook
generation, and PyPI publication via `release.yml`. Build runs **no** readiness
checks of its own and never re-derives a gate decision; it just executes.
- **PyAutoBrain — the reasoning layer.** Hosts the specialist agents that connect
the organs. It owns no checks and no execution steps; it reasons over Heart's
verdict and delegates execution to Build.

## The call chain (always this order)

```
AgentPulse (gate) → Build (execute)
BrainHeart (gate) → Build (execute)
```

The agent asks `pyauto-pulse readiness --json`; only on a **green** verdict does
it trigger Build's release. Pulse never triggers Build; Build never re-derives a
gate decision the agent already made.
The Brain asks `pyauto-heart readiness --json`, reasons over the result, and only
on a **green** verdict triggers Build's release. Heart never triggers Build;
Build never re-derives a decision the Brain already made.

## Agents
## Specialist reasoning agents

Each agent is a directory under `agents/<name>/` with:

- `AGENTS.md` — what the agent is responsible for and how to run it.
- `AGENTS.md` — what the agent reasons about and how to run it.
- a deterministic entrypoint script (`*.sh` / `*.py`) — the part CI and humans
invoke identically, so behaviour isn't re-derived from prose each time.

Current agents:

- **`agents/release/`** — gates on `pyauto-pulse readiness`, and on green
- **`agents/release/`** — reasons over `pyauto-heart readiness`, and on green
triggers the PyAutoBuild release executor (`autobuild pre_build` → `release.yml`).
- **`agents/health/`** — drives the PyAutoPulse monitoring/readiness surface.
- **`agents/health/`** — reasons over the PyAutoHeart monitoring/readiness surface.

More agents are expected over time (e.g. several health agents each consuming a
different part of Pulse); add them as new `agents/<name>/` directories.
More specialist agents are expected over time (e.g. a Feature agent that reasons
over PyAutoMind tasks, a Build agent that coordinates execution, several health
agents each reasoning over a different part of Heart); add them as new
`agents/<name>/` directories.

## Running

```bash
bin/pyauto-agent help # list agents
bin/pyauto-agent release # readiness gate, then release on green
bin/pyauto-agent health # one health tick + readiness verdict
bin/pyauto-brain help # list agents
bin/pyauto-brain release # reason about readiness, then release on green
bin/pyauto-brain health # one health tick + readiness verdict
```

Like the other PyAuto repos, PyAutoAgent runs from its checkout (no pip install);
it resolves the sibling `pyauto-pulse` and `autobuild` binaries from PATH or the
Like the other PyAuto repos, PyAutoBrain runs from its checkout (no pip install);
it resolves the sibling `pyauto-heart` and `autobuild` binaries from PATH or the
`~/Code/PyAutoLabs/` checkouts.

## Renamed from PyAutoAgent

This repository was previously **PyAutoAgent**. The rename to **PyAutoBrain**
reflects the organism model above: it is the reasoning layer, not just a host of
"agents". Backwards compatibility is preserved where practical:

- `bin/pyauto-brain` is the canonical CLI; `bin/pyauto-agent` is a thin shim that
forwards to it.
- The sibling health authority moved from `pyauto-pulse`/PyAutoPulse to
`pyauto-heart`/PyAutoHeart (PyAutoHeart keeps a `pyauto-pulse` shim).

## Never rewrite history

NEVER perform these operations on any repo with a remote:
Expand Down
9 changes: 7 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# PyAutoAgent — Claude guidance
# PyAutoBrain — Claude guidance

Read [`AGENTS.md`](AGENTS.md) in this directory. It is the shared source of truth
for the Build / Pulse / Agent split and for how the agents in this repo work.
for PyAutoBrain — the reasoning layer of the PyAuto organism — for the
Brain / Heart / Build boundary, and for how the specialist reasoning agents in
this repo work.

> This repository was renamed from **PyAutoAgent** to **PyAutoBrain**. The CLI is
> now `pyauto-brain` (with `pyauto-agent` kept as a back-compat shim).
55 changes: 37 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,60 @@
# PyAutoAgent
# PyAutoBrain

The orchestration brain of the PyAuto release ecosystem. PyAutoAgent hosts named
**agents** that gate on [PyAutoPulse](https://github.com/PyAutoLabs/PyAutoPulse)
The **reasoning layer** of the PyAuto organism. PyAutoBrain figures out *how*
work should be done: it hosts specialist **reasoning agents** that reason over
the health verdict from [PyAutoHeart](https://github.com/PyAutoLabs/PyAutoHeart)
and delegate execution to [PyAutoBuild](https://github.com/PyAutoLabs/PyAutoBuild).

It owns no state, no checks, and no release mechanics — it only decides and
delegates.
It owns no state, no health checks, and no release mechanics — it only reasons
and delegates.

> Renamed from **PyAutoAgent**. The canonical CLI is now `pyauto-brain`;
> `pyauto-agent` remains as a back-compat shim.

## The organism

The PyAuto ecosystem is a software organism; each repo is an organ with one job:

| Organ | Repo | Role |
|-------|------|------|
| **Mind** | PyAutoMind | Decides *what* should be done — intent, goals, priorities. |
| **Brain** | **PyAutoBrain** | Figures out *how* — reasoning, planning, orchestration. |
| **Hands** | PyAutoBuild | Builds and releases the software — packaging, tagging, notebooks, PyPI. |
| **Heart** | PyAutoHeart | Determines whether the organism is healthy. |
| **Memory** | PyAutoMemory | Long-term scientific / software / project knowledge. |

In one line each: **Mind** decides what, **Brain** figures out how, **Hands**
build and release the software, **Heart** says whether it is healthy.

## The split

| Repo | Role |
|------|------|
| **PyAutoPulse** | Health authority. `pyauto-pulse readiness` is the authoritative green/yellow/red release gate. Observer-only. |
| **PyAutoBuild** | Executor. Packaging, tagging, notebooks, PyPI via `release.yml`. No checks. |
| **PyAutoAgent** | Brain. Gates on Pulse, delegates execution to Build. |
| **PyAutoHeart** | Health authority. `pyauto-heart readiness` is the authoritative green/yellow/red release gate. Observer-only. |
| **PyAutoBuild** | Executor (Hands). Packaging, tagging, notebooks, PyPI via `release.yml`. No checks. |
| **PyAutoBrain** | Reasoning layer. Reasons over Heart's verdict, delegates execution to Build. |

Call chain, always in this order:

```
AgentPulse (gate) → Build (execute)
BrainHeart (gate) → Build (execute)
```

## Agents
## Specialist reasoning agents

- **`agents/release/`** — `pyauto-pulse readiness` gate → on green, run the
PyAutoBuild release executor.
- **`agents/health/`** — drive the PyAutoPulse monitoring / readiness surface.
- **`agents/release/`** — reasons over `pyauto-heart readiness` → on green, runs
the PyAutoBuild release executor.
- **`agents/health/`** — reasons over the PyAutoHeart monitoring / readiness surface.

## Usage

```bash
bin/pyauto-agent help # list agents
bin/pyauto-agent release # gate, then release on green
bin/pyauto-agent health # one health tick + readiness verdict
bin/pyauto-brain help # list agents
bin/pyauto-brain release # reason about readiness, then release on green
bin/pyauto-brain health # one health tick + readiness verdict
```

PyAutoAgent runs from its checkout (no pip install), resolving the sibling
`pyauto-pulse` and `autobuild` binaries from PATH or `~/Code/PyAutoLabs/`.
PyAutoBrain runs from its checkout (no pip install), resolving the sibling
`pyauto-heart` and `autobuild` binaries from PATH or `~/Code/PyAutoLabs/`.

See [`AGENTS.md`](AGENTS.md) for the full description.
25 changes: 14 additions & 11 deletions agents/_common.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env bash
# agents/_common.sh — shared helpers for PyAutoAgent agents.
# agents/_common.sh — shared helpers for PyAutoBrain's specialist agents.
#
# Resolves the sibling PyAuto CLIs (pyauto-pulse, autobuild) the same way the
# autobuild shim resolves pyauto-pulse: prefer PATH, fall back to the sibling
# Resolves the sibling PyAuto organ CLIs (pyauto-heart, autobuild) the same way
# the autobuild shim resolves them: prefer PATH, fall back to the sibling
# checkout under ~/Code/PyAutoLabs/. Nothing here is pip-installed.

PYAUTO_ROOT="${PYAUTO_ROOT:-$HOME/Code/PyAutoLabs}"
Expand All @@ -19,23 +19,26 @@ _resolve_bin() {
printf '%s' "$fallback"
return 0
fi
echo "pyauto-agent: '$name' not found on PATH or at $fallback" >&2
echo "pyauto-brain: '$name' not found on PATH or at $fallback" >&2
echo " Clone the sibling repo under $PYAUTO_ROOT and add its bin/ to PATH." >&2
return 127
}

resolve_pulse() {
_resolve_bin pyauto-pulse "$PYAUTO_ROOT/PyAutoPulse/bin/pyauto-pulse"
# resolve_heart — locate the PyAutoHeart CLI (the health authority of the
# organism). The former name was `pyauto-pulse`; PyAutoHeart keeps that as a
# back-compat shim, but the canonical command is `pyauto-heart`.
resolve_heart() {
_resolve_bin pyauto-heart "$PYAUTO_ROOT/PyAutoHeart/bin/pyauto-heart"
}

resolve_autobuild() {
_resolve_bin autobuild "$PYAUTO_ROOT/PyAutoBuild/bin/autobuild"
}

# readiness_verdict — run `pyauto-pulse readiness --json` and echo the verdict
# string (green/yellow/red). Returns non-zero if Pulse can't be resolved/run.
# readiness_verdict — run `pyauto-heart readiness --json` and echo the verdict
# string (green/yellow/red). Returns non-zero if Heart can't be resolved/run.
readiness_verdict() {
local pulse
pulse="$(resolve_pulse)" || return $?
"$pulse" readiness --json | python3 -c 'import json,sys; print(json.load(sys.stdin).get("verdict","unknown"))'
local heart
heart="$(resolve_heart)" || return $?
"$heart" readiness --json | python3 -c 'import json,sys; print(json.load(sys.stdin).get("verdict","unknown"))'
}
27 changes: 14 additions & 13 deletions agents/health/AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
# Health agent

Drives the PyAutoPulse monitoring / readiness surface. It is a thin, named
driver of `pyauto-pulse` — never a second implementation of any check (all
health logic lives in Pulse).
A specialist **PyAutoBrain** reasoning agent. It reasons over the PyAutoHeart
monitoring / readiness surface — a thin, named driver of `pyauto-heart`, never a
second implementation of any check (all health logic lives in Heart). The Brain
reasons about health; PyAutoHeart measures it.

## Responsibility

- Default: run one refresh cycle (`pyauto-pulse tick`) and print the
authoritative readiness verdict (`pyauto-pulse readiness`).
- Any subcommand is forwarded verbatim to `pyauto-pulse` (`status`, `watch`,
- Default: run one refresh cycle (`pyauto-heart tick`) and print the
authoritative readiness verdict (`pyauto-heart readiness`).
- Any subcommand is forwarded verbatim to `pyauto-heart` (`status`, `watch`,
`logs`, `fix <topic>`, ...).

## Run

```bash
bin/pyauto-agent health # one tick + readiness verdict
bin/pyauto-agent health status # forward to: pyauto-pulse status
bin/pyauto-agent health watch 300 # forward to: pyauto-pulse watch 300
bin/pyauto-brain health # one tick + readiness verdict
bin/pyauto-brain health status # forward to: pyauto-heart status
bin/pyauto-brain health watch 300 # forward to: pyauto-heart watch 300
```

## Future

Several health agents may eventually each own a different slice of Pulse (CI
status, worktree drift, script timing, version skew). They would be added as
Several health agents may eventually each reason over a different slice of Heart
(CI status, worktree drift, script timing, version skew). They would be added as
sibling `agents/<name>/` directories, each forwarding to the relevant
`pyauto-pulse` checks. For now this single agent covers the whole surface.
`pyauto-heart` checks. For now this single agent covers the whole surface.

## What this agent must never do

- Implement or duplicate any health check (that is Pulse's job).
- Implement or duplicate any health check (that is Heart's job).
- Trigger a release or write into other repos.
31 changes: 16 additions & 15 deletions agents/health/health.sh
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
#!/usr/bin/env bash
# agents/health/health.sh — the health agent.
# agents/health/health.sh — the health agent (a PyAutoBrain reasoning agent).
#
# Drives the PyAutoPulse monitoring surface. By default it runs one refresh
# cycle and prints the authoritative readiness verdict. Any subcommand is
# forwarded straight to `pyauto-pulse`, so this agent is a thin, named driver
# of Pulse rather than a second implementation of any check.
# Reasons over the PyAutoHeart monitoring surface. By default it runs one
# refresh cycle and prints the authoritative readiness verdict. Any subcommand
# is forwarded straight to `pyauto-heart`, so this agent is a thin, named driver
# of Heart rather than a second implementation of any check. The Brain reasons
# about health; PyAutoHeart measures it.
#
# Usage:
# health.sh # one tick, then print readiness
# health.sh status # forward: pyauto-pulse status
# health.sh watch [secs] # forward: pyauto-pulse watch (continuous)
# health.sh <subcommand>... # forward verbatim to pyauto-pulse
# health.sh status # forward: pyauto-heart status
# health.sh watch [secs] # forward: pyauto-heart watch (continuous)
# health.sh <subcommand>... # forward verbatim to pyauto-heart
#
# Future: several health agents may each consume a different slice of Pulse
# Future: several health agents may each reason over a different slice of Heart
# (CI, worktree drift, timing, ...). For now this single agent covers the whole
# surface via pyauto-pulse.
# surface via pyauto-heart.

set -uo pipefail

HERE="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
source "$HERE/../_common.sh"

pulse="$(resolve_pulse)" || exit $?
heart="$(resolve_heart)" || exit $?

if [[ $# -eq 0 ]]; then
echo "== health agent: refreshing PyAutoPulse state =="
"$pulse" tick
echo "== health agent: refreshing PyAutoHeart state =="
"$heart" tick
echo
exec "$pulse" readiness
exec "$heart" readiness
fi

exec "$pulse" "$@"
exec "$heart" "$@"
Loading