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
112 changes: 112 additions & 0 deletions .github/workflows/dashboard_refresh.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: Dashboard Refresh

# Keeps the generated task page (`dashboard.md`, linked from the README) in
# step with the Mind it describes. The page is rendered by PyAutoBrain's intake
# conductor from `draft/`, `active/` and the registry files, so any push that
# files, issues, parks or ships a task makes it stale.
#
# It went stale before this workflow existed: between its first commit and
# 2026-08-11 the page was regenerated by hand 4 times while 33 commits touched
# `draft/`. A dashboard nobody trusts is worse than no dashboard, and a linked
# one is read by people who were not in the session that changed the backlog.
#
# Same shape as lifecycle_drift.yml (issue #116): on pull requests a stale page
# is an error the author fixes on the branch; on pushes to main it is SELF-
# HEALED with a bot commit, because Mind pushes land directly on main from many
# concurrent agent sessions and an alarm-only check would just email a human.
#
# The generation stamp is excluded from the drift comparison (`--check`), so a
# re-render on an unchanged Mind is not drift and this never commits daily.

on:
push:
branches: [main]
paths:
- "draft/**"
- "active/**"
- "active.md"
- "parked.md"
- "planned.md"
- "dashboard.md"
pull_request:
paths:
- "draft/**"
- "active/**"
- "active.md"
- "parked.md"
- "planned.md"
- "dashboard.md"
workflow_dispatch:

# contents: write is needed by the self-heal push on main; PR runs never push.
permissions:
contents: write

jobs:
refresh:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
path: PyAutoMind
# The renderer lives with the intake conductor, not here — the Mind holds
# the state, the Brain reasons over it (ORGANISM.md).
- uses: actions/checkout@v4
with:
repository: PyAutoLabs/PyAutoBrain
path: PyAutoBrain
- name: dashboard freshness (self-healing on push to main)
working-directory: PyAutoMind
run: |
BRAIN=../PyAutoBrain/agents/conductors/intake/_intake.py
# Exit 1 is drift and nothing else. Any other non-zero code means the
# renderer itself could not run — a Brain/Mind version skew, say —
# and reporting that as "the page is stale" sends whoever reads the
# log to fix the wrong file. (This PR's own first run: PyAutoBrain
# main had no `--check` yet, argparse exited 2, and the step blamed
# dashboard.md.)
check() {
local rc=0
python3 "$BRAIN" --mind . dashboard --check || rc=$?
if [ "$rc" -gt 1 ]; then
echo "::error::the dashboard renderer exited ${rc} — that is not drift. Check that PyAutoBrain main still provides 'intake dashboard --check'."
exit 1
fi
return "$rc"
}
if check; then
exit 0
fi
if [ "${GITHUB_EVENT_NAME}" != "push" ]; then
echo "::error::dashboard.md is stale — run 'pyauto-brain intake --apply dashboard' on this branch and commit the result"
exit 1
fi
echo "dashboard.md is stale on main — self-healing"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
# Each attempt rebuilds on the current tip of main, so a concurrent
# push (the usual cause of a rejected push) never needs a rebase.
# The heal push uses the default GITHUB_TOKEN, which does not trigger
# workflow runs, so it cannot loop.
for attempt in 1 2 3; do
git fetch origin main
git reset --hard FETCH_HEAD
if check; then
echo "tip of main is already fresh (healed by a concurrent push)"
exit 0
fi
python3 "$BRAIN" --mind . --apply dashboard
if ! check; then
echo "::error::'--apply dashboard' did not converge — renderer bug, repair by hand"
exit 1
fi
git add dashboard.md
git commit -m "mind: self-heal stale dashboard.md"
if git push origin HEAD:main; then
echo "healed on attempt ${attempt}"
exit 0
fi
echo "push rejected (attempt ${attempt}) — retrying on the new tip of main"
done
echo "::error::could not push the healed dashboard after 3 attempts"
exit 1
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ For the full workflow narrative, conventions, and registry schemas, read
input for `register_and_iterate --queue`), `ideas.md` (raw inbox swept by
`$intake`, `/intake` in Claude). Mutate these only via the skills in `skills/` so commit
messages stay consistent.
`dashboard.md` is the **generated** read-only view over all of it (the page
the README links): regenerate with `pyauto-brain intake --apply dashboard`
after any registry or `draft/` change you want reflected immediately — never
hand-edit it. `dashboard_refresh.yml` self-heals it on pushes to `main`, so a
missed regeneration is drift that fixes itself, not a broken page.
`parked.md` holds tasks that were started or scoped but are not currently
in flight (e.g. work parked in a stash, orphan worktrees); move back to
`active.md` (or `planned.md` if re-scoping) when resuming.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

📖 **Full documentation → <https://pyautoscientist.readthedocs.io>** — the whole PyAutoScientist organism, including how to fork and run your own.

📋 **[Task dashboard → `dashboard.md`](dashboard.md)** — every task the Mind is
holding, on one page: what to pick up now, what is in flight, and the whole
backlog. Reads on a phone; regenerated from this repo, so it is never a
second copy of the truth.

The Mind of the PyAuto organism: every piece of work in the ecosystem starts
here, as a markdown file describing what you want in plain English. An AI
agent (or a human) picks the file up and turns it into a tracked GitHub
Expand All @@ -19,6 +24,7 @@ What lives here:

| File / folder | What it is |
|---------------|------------|
| [`dashboard.md`](dashboard.md) | **generated** — every task on one page, to pick from |
| `ideas.md` | raw incubating ideas, no structure required |
| `draft/<work-type>/<target>/*.md` | scoped prompts, **not started** (`feature/`, `bug/`, `docs/`, …) |
| `active/<name>.md` | **issued** prompts — an open issue, in flight |
Expand Down
2 changes: 2 additions & 0 deletions REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ over the registry without starting work:
```
PyAutoMind/
├── README.md ← short front page
├── dashboard.md ← GENERATED task page (picks / in flight / parked / planned / backlog)
│ `pyauto-brain intake --apply dashboard`; CI self-heals it on main
├── REFERENCE.md ← this file (schemas + conventions)
├── .gitignore
Expand Down
Loading
Loading