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
78 changes: 78 additions & 0 deletions .github/workflows/brain_board.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Brain Board

# Publishes the Brain's operational board — the organism's morning door — to
# this repo's GitHub Pages URL: the page (index.html), its badge.json (the
# cross-board headline contract the umbrella router consumes), the raw
# board.json, and the markdown twin board.md.
#
# The board replaces the interactive /wake_up skill: everything that skill
# assembled by driving doors in sequence (overnight scheduled-run sweep, the
# Heart's readiness headline, version-stamp consistency, the community scan,
# resume context from the Mind, the upkeep doors) is collected here on a
# schedule and rendered with one-tap copy-for-Claude payloads. The renderer is
# board/_board.py; its vocabulary is config/policy.yaml `board:`.
#
# Unlike the Mind dashboard (self-healed into the repo, because its state IS
# the repo), nothing here is committed: the board's data is time-varying, so
# it is served from the Pages artifact only — a daily refresh makes no commit
# noise and can never drift against a repo copy.
#
# Cadence: 05:30 UTC daily — after the 02:00 nightly release driver and the
# Heart's 05:00 heart-health refresh (which rewrites the badge this board
# reads), before the human's morning. GitHub cron jitters 0–3 h under load,
# so the page stamps its own generation time and every consumer should trust
# that stamp over the schedule. workflow_dispatch is the manual refresh
# (also what a human taps when the board says it is stale).

on:
schedule:
- cron: "30 5 * * *"
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: true

jobs:
publish:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
with:
path: PyAutoBrain
# The board composes, it does not recompute: the community scan reads
# the body map (repos.yaml) and the resume section reads the registry +
# the Mind's own generated dashboard counts, so the Mind is checked out
# as a sibling — the same two-repo layout tests.yml uses.
- uses: actions/checkout@v4
with:
repository: ${{ github.repository_owner }}/PyAutoMind
path: PyAutoMind
- name: render the board
env:
PYAUTO_ROOT: ${{ github.workspace }}
run: |
python3 -m pip install --quiet pyyaml
python3 PyAutoBrain/board/_board.py --apply --out _site
# enablement: true creates the Pages site on first run where the token
# may (Mind/Heart precedent); where it may not (the Hands hit "Resource
# not accessible by integration"), the site must be created once
# out-of-band: gh api -X POST repos/<owner>/PyAutoBrain/pages -f build_type=workflow
- uses: actions/configure-pages@v5
with:
enablement: true
- uses: actions/upload-pages-artifact@v3
with:
path: _site
- id: deployment
uses: actions/deploy-pages@v4
9 changes: 8 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,18 @@ via `/route`, and it routes to the right agent; normal usage never says
"PyAutoBrain". A few commands are compositions rather than single agents:
`/docs` and `/research` route through the dev-flow with their PyAutoMind
work-type fixed (no dedicated conductor — added only on demonstrated need, never
for symmetry); `/wake_up` composes sync + `/health` + `/hygiene`; `/prm` composes the
for symmetry); `/prm` composes the
end-of-task wrap-up (CI green → merge → `ship_*` completion); `/brain
<agent>` is the raw passthrough. Every command routes **through** the Brain;
none replaces it.

The morning routine is not a command at all: the **Brain board**
(`board/_board.py`, published to the Brain's GitHub Pages URL each morning by
`brain_board.yml`) carries what `/wake_up` used to assemble — overnight runs,
readiness, community, resume, upkeep — as one-tap 📋 payloads, and
`bin/morning.sh` is the local sync/clean leg you run in a terminal.
`/wake_up` remains only as the fallback door when the board is unreachable.

The command bodies live in `skills/<verb>/<verb>.md`; thin `SKILL.md` wrappers
make the same canonical workflows discoverable to skill-aware harnesses.
`bin/install.sh` installs both surfaces without duplicating their bodies. Shared
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ check-up — or just `/route <what you want>` and the Brain picks the right
door. The full command surface (13 conductors + 5 faculties) is the generated
table in [AGENTS.md](AGENTS.md).

Start the day on the **[Brain board](https://pyautolabs.github.io/PyAutoBrain/)**
— the organism's operational dashboard, regenerated each morning: 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 with a one-tap 📋
copy-for-Claude command. The local sync/clean leg is one terminal command,
`bash bin/morning.sh`.

## How PyAutoBrain works

1. **A task arrives.** Usually from the Mind's backlog — pick a task on the
Expand Down
45 changes: 45 additions & 0 deletions bin/morning.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
#
# morning.sh — the local half of the morning routine, as ONE terminal command.
#
# The Brain board (https://<org>.github.io/PyAutoBrain/ — rendered by
# board/_board.py, published by brain_board.yml) carries every remote signal
# the old /wake_up skill assembled: overnight runs, readiness, community,
# resume, upkeep. The two steps a cloud render cannot do are the ones that
# touch YOUR checkout — sync and clean-slate. This script is exactly those two
# steps, so the morning is: run this in a terminal, then open the board.
#
# bash PyAutoBrain/bin/morning.sh # sync + clean, then board URL
# bash PyAutoBrain/bin/morning.sh --digest # also print the board's
# # markdown digest (needs gh)
# DRY_RUN=1 bash PyAutoBrain/bin/morning.sh # preview clean-slate only
#
# Both steps are the recoverable, git-aware ones /wake_up auto-ran (its
# guardrail): sync skips any repo with real uncommitted work; clean-slate
# deletes only untracked REGENERABLE artifacts and reports orphans instead of
# removing them. Nothing else is deleted, edited, or bumped here.

set -u

HERE="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"

echo "== morning: sync every repo to main (ff-only; real work is skipped) =="
bash "$HERE/pull_all_main.sh"

echo
echo "== morning: clean slate (untracked regenerable artifacts + cruft) =="
bash "$HERE/clean_slate.sh"

echo
echo "== morning: done — the rest of the routine is on the board =="
# Board URL from the checkout's own remote (no hardcoded org).
origin="$(git -C "$HERE/.." remote get-url origin 2>/dev/null || true)"
owner="$(printf '%s' "$origin" | sed -E 's#\.git$##; s#.*[:/]([^/:]+)/[^/]+$#\1#')"
if [ -n "$owner" ]; then
echo " https://$(printf '%s' "$owner" | tr '[:upper:]' '[:lower:]').github.io/PyAutoBrain/"
fi

if [ "${1:-}" = "--digest" ]; then
echo
bash "$HERE/../board/board.sh" || echo "morning: board digest unavailable (gh auth?)"
fi
6 changes: 4 additions & 2 deletions bin/overnight_status.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ set -u
command -v gh >/dev/null 2>&1 || { echo "gh not found — cannot fetch run status" >&2; exit 1; }

# owner/repo:workflow-file (owner defaults to PyAutoLabs when omitted). The
# passive morning webhooks (morning_health / morning_status) are excluded —
# /wake_up is their interactive complement, not a re-run of them.
# passive morning webhooks (morning_health / morning_status) are excluded.
# The Brain board renders this same sweep on Pages (board/_board.py reads the
# list from config/policy.yaml `board: overnight_jobs`) — keep the two lists
# in step until this script reads that block too.
JOBS=(
"PyAutoBrain:nightly-release.yml"
"PyAutoHeart:heart-health.yml"
Expand Down
19 changes: 19 additions & 0 deletions bin/pyauto-brain
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
# PyAutoFit search catalogue, benchmark record, tier gaps
# pyauto-brain sizing [args] (faculty) read-only: the SizingSurface — difficulty estimate for
# a PyAutoMind prompt (the heuristic intake + feature both consult)
# pyauto-brain board [args] (surface) render the operational board — the morning
# page brain_board.yml publishes (md/html/json/badge)
# pyauto-brain help [name] list agents or show one agent's docs
#
# Renamed from `pyauto-agent`; the former back-compat shim has been removed now
Expand Down Expand Up @@ -95,6 +97,14 @@ CONDUCTOR_ORDER=(intake community feature bug refactor workspace eyes profiling
FACULTY_ORDER=(vitals review memory samplers sizing)
AGENT_ORDER=("${CONDUCTOR_ORDER[@]}" "${FACULTY_ORDER[@]}")

# Surfaces — generated pages, not agents (they neither act nor opine, they
# show). Dispatchable and help-able like agents, but kept out of the
# CONDUCTOR/FACULTY orders so the generated cross-organ command-surface block
# (install.sh --write-agents-surface) is untouched.
AGENT_SCRIPT[board]="$BRAIN_HOME/board/board.sh"
AGENT_DESC[board]="The operational board — render the morning surface (overnight runs, readiness, community, resume, upkeep) as md/html/json/badge; published to Pages by brain_board.yml"
SURFACE_ORDER=(board)

cmd_help() {
if [[ $# -gt 0 ]]; then
local name="$1"
Expand Down Expand Up @@ -131,6 +141,15 @@ EOF
printf ' %-10s %s\n' "$name" "${AGENT_DESC[$name]}"
done
echo
# Surfaces are listed as prose, not roster rows: the skill-install tests
# treat every 4-space roster row as a public AGENT (wrapper + generated
# cross-organ surface-block entry), and a surface is neither tier.
echo "Surfaces (generated pages — read-only renders, not agents):"
local surface
for surface in "${SURFACE_ORDER[@]}"; do
printf ' %s — %s\n' "$surface" "${AGENT_DESC[$surface]}"
done
echo
echo "Run 'pyauto-brain help <agent>' for that agent's full docs."
}

Expand Down
5 changes: 4 additions & 1 deletion bin/version_drift.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ else
fi
echo

# repo:path — the coupled release-train stamps (libraries only). The
# repo:path — the coupled release-train stamps (libraries only). The Brain
# board renders this same check on Pages (board/_board.py reads the list from
# config/policy.yaml `board: version_stamps`) — keep the two lists in step
# until this script reads that block too. The
# charge-transfer (CTI) calibration stack is intentionally excluded: it is
# not on the coupled train and carries its own version line. Workspaces
# carry no stamp since the floors-are-authoritative redesign dropped
Expand Down
62 changes: 62 additions & 0 deletions board/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# The Brain Board — the operational surface (the morning door)

> Tier: **surface** — a generated page, not an agent. It decides nothing and
> opines on nothing; it reads what the organs already publish and renders it.
> (Contrast conductors, which act, and faculties, which judge — this only
> shows. The precedent is the Mind dashboard, which lives with the intake
> conductor; the Heart and Hands boards are the sibling shapes.)

The sixth one-tap board, live at the Brain's GitHub Pages URL
(`https://<org>.github.io/PyAutoBrain/`): the organism's **morning and
general starting point**. It replaces the interactive `/wake_up` composition —
everything that skill assembled by driving doors in sequence is collected on a
schedule and rendered as one page, each actionable row carrying a one-tap 📋
copy-for-Claude payload:

| Section | Signal owner | One-tap payload |
|---------|--------------|-----------------|
| ⌨ Morning sync | `bin/morning.sh` (local) | the terminal command itself |
| 🌙 Overnight | scheduled workflows (`config/policy.yaml board: overnight_jobs`) | `/bug … — <run url>` on failures |
| ❤️ Readiness | the Heart board's `badge.json` (cross-board contract) | `/health` |
| 🏷️ Version consistency | the coupled-set stamps (`board: version_stamps`) | `/bug version drift: …` |
| 💬 Community | the Ears (`community scan`, reused wholesale) | `/community`, `/community triage <ref>` |
| 🔄 Resume | the Mind's registry + generated counts; pending-release PRs | `/start_dev …`, `/prm <url>` |
| 🧹 Upkeep | open-issue count; the cleanup doors | `/issue_cleanup`, `/hygiene`, `/repo_cleanup` |
| 🚪 All doors | `bin/pyauto-brain`'s own registry (never a second copy) | `/<verb>` |

**Compose, don't recompute** — the board re-derives nothing. The community
section imports the community conductor's `build_scan()`; the resume counts
are parsed from the Mind's own generated `dashboard.md`; readiness comes from
the Heart board's published badge. Every unreachable source degrades into an
honest "Degraded" row, never fabricated content.

**Read-only** — the collect half touches only read-only `gh` endpoints and
public Pages URLs. It never posts, labels, or edits anything on GitHub, and
never writes files outside `--apply`'s output directory.

## Running

```bash
bin/pyauto-brain board # markdown digest in the terminal
bin/pyauto-brain board --html # the one-tap page
bin/pyauto-brain board --badge # the cross-board headline contract
bin/pyauto-brain board --apply # write _site/ (what brain_board.yml serves)
```

Publishing is `.github/workflows/brain_board.yml`: a morning cron plus manual
dispatch renders `--apply` output and deploys it to GitHub Pages (page +
`badge.json` + `board.json` + `board.md`). Nothing is committed to the repo —
the board is served, not stored, so a daily refresh makes no commit noise.

## Configuration

Instance vocabulary lives in `config/policy.yaml` under `board:` (the declared
config surface an adopting fork replaces): `overnight_jobs` (repo:workflow
pairs for the sweep), `version_stamps` (repo:path pairs for the consistency
check), `reference_release_repo`, `heart_board`, and `boards` (the sibling
board links). The org/owner is derived from the Mind's body map
(`PyAutoMind/repos.yaml`) at runtime — never hardcoded here.

Env: `PYAUTO_ROOT` (workspace root holding `PyAutoMind/`), `BOARD_GH`
(the gh binary; hermetic tests point it at a stub), `BOARD_PAGES_BASE`
(sibling-board base URL; tests point it at `file://` fixtures).
Loading
Loading