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
25 changes: 22 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,25 @@ Health Agent reasons over Heart's output, it does not re-derive it. Full detail
- `readiness` rolls these into the authoritative verdict (URL hygiene is
monitoring only and does **not** gate it).

See [`CLAUDE.md`](CLAUDE.md) for Heart's internals — the check framework, the
<30s tick budget, how to add a check, and the hard rules (observer-only, colour
coding, atomic state writes).
See [`docs/internals.md`](docs/internals.md) for Heart's internals — the check
framework, the <30s tick budget, how to add a check, and the hard rules
(observer-only, colour coding, atomic state writes). Read it when changing
Heart's own code, not by default.

## Never rewrite history

NEVER perform these operations on any repo with a remote:

- `git init` in a directory already tracked by git
- `rm -rf .git && git init`
- Commit with subject "Initial commit", "Fresh start", "Start fresh",
"Reset for AI workflow", or any equivalent message on a branch with a remote
- `git push --force` to `main`
- `git filter-repo` / `git filter-branch` on shared branches
- `git rebase -i` rewriting commits already pushed to a shared branch

If the working tree needs a clean state, the **only** correct sequence is:

git fetch origin
git reset --hard origin/main
git clean -fd
112 changes: 7 additions & 105 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,107 +1,9 @@
# PyAutoHeart — Agent Guidance
# PyAutoHeart — Claude guidance

This file is for AI coding agents (Claude Code, Codex, Cursor, etc.)
discovering this repository.
Read [`AGENTS.md`](AGENTS.md) in this directory. It is the shared source of
truth for PyAutoHeart — the health authority of the PyAuto organism — and for
the Brain / Heart / Build boundary.

## What this repo is

PyAutoHeart is the **health and vital-signs authority** of the PyAuto organism.
It owns health and release-readiness checking: continuous monitoring (CI status,
dirty checkouts, branch ahead/behind, open PRs, worktree state, script-timing
regressions, version skew) plus deep on-demand/cloud checks (install
verification, URL hygiene), workspace validation, and generated-artifact/noise
classification, all green/yellow/red colour coded. `pyauto-heart readiness` is
the **authoritative** "is it safe to release?" gate.

It is **separate** from PyAutoHands / PyAutoBuild on purpose: Hands is a pure
executor (it produces PyPI releases and runs no readiness checks); Heart owns
the checking. Heart shells out to `autobuild` primitives but never imports
PyAutoBuild Python, never writes into other repos, and never triggers Hands.

See [`AGENTS.md`](AGENTS.md) for the canonical Brain/Heart/Hands boundary and
the `Brain → Heart → Hands` call chain, and `README.md` for user-facing docs.

## Hard rules

1. **Color coding everywhere**: green = passing, yellow = warning,
red = failing. Use the `c_ok / c_warn / c_fail / c_info / c_meta`
helpers in `heart/_color.sh` (bash) and `heart/heart_color.py`
(Python). Honour `NO_COLOR` and `--no-color`.
2. **Never write outside `~/.pyauto-heart/`** in any check module.
The daemon must be a pure observer; mutations belong in
`pyauto-heart fix <topic>` which only EMITS context for a fresh
Claude session.
3. **Polling must be cheap**. A full `tick` should complete in <30s
total. If a check would take longer, run it less often (move to a
v2 daily cron, not the watch loop).
4. **Lightweight test footprint**. Heart's own test suite runs on the
standard library plus PyYAML only — no scientific/ML stack (numba,
matplotlib, JAX, the PyAuto libraries). This keeps the suite fast and
flake-free so it runs anywhere (CI, mobile, sandbox). It is a property of
*Heart's* tests, not a claim about the projects Heart watches — Heart may
perfectly well monitor non-JAX (or JAX-heavy) repos; that's their concern,
not the suite's.
5. **State writes are atomic**. Use `heart.state.atomic_write_json` or
the bash equivalent (`heart_write_json` in `_common.sh`). Concurrent
ticks must not corrupt `state.json`.

## Repo structure

```
bin/pyauto-heart # bash dispatcher
heart/ # all logic, shell-first
_color.sh, _common.sh
daemon.sh, tick.sh # the loop + one cycle
state.py, status.py, fix.py # Python side
heart_color.py
checks/ # one file per check class
config/repos.yaml # polled repo registry + thresholds
tests/ # pytest
```

## Adding a new check

1. Create `heart/checks/<name>.{sh,py}` following the existing patterns.
2. Each check writes per-repo JSON sidecars to
`$HEART_PER_REPO_DIR/<repo>.<check_kind>.json` OR a global file at
`$HEART_STATE_DIR/<check_name>.json`.
3. Print a single colour-coded summary line to stdout (logged to the
daemon log by `heart_log`).
4. Add a section to `heart/status.py:render` that surfaces the result.
5. Add tests in `tests/test_<name>.py` covering classification edges.
6. Wire into `heart/tick.sh` in the appropriate position.

## Running locally

```bash
pip install -e .[dev]
pytest tests/ -v
HEART_FORCE_COLOR=1 pyauto-heart tick # one cycle, with colour
pyauto-heart status
```

## Codex / sandboxed runs

```bash
NUMBA_CACHE_DIR=/tmp/numba_cache MPLCONFIGDIR=/tmp/matplotlib \
pytest tests/
```

## Never rewrite history

NEVER perform these operations on any repo with a remote:

- `git init` in a directory already tracked by git
- `rm -rf .git && git init`
- Commit with subject "Initial commit", "Fresh start", "Start fresh",
"Reset for AI workflow", or any equivalent message on a branch with
a remote
- `git push --force` to `main`
- `git filter-repo` / `git filter-branch` on shared branches
- `git rebase -i` rewriting commits already pushed to a shared branch

If the working tree needs a clean state, the **only** correct sequence is:

git fetch origin
git reset --hard origin/main
git clean -fd
Internals (the check framework, the <30s tick budget, how to add a check, the
hard rules) are in [`docs/internals.md`](docs/internals.md) — read it when
working on Heart's own code, not by default.
75 changes: 75 additions & 0 deletions docs/internals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# PyAutoHeart — internals

Operational detail for working **inside** this repo: the check framework, the
tick budget, how to add a check, and the hard rules. What PyAutoHeart *is* and
the Brain/Heart/Build boundary live in [`AGENTS.md`](../AGENTS.md) — read that
first; read this only when changing Heart's own code.

## Hard rules

1. **Color coding everywhere**: green = passing, yellow = warning,
red = failing. Use the `c_ok / c_warn / c_fail / c_info / c_meta`
helpers in `heart/_color.sh` (bash) and `heart/heart_color.py`
(Python). Honour `NO_COLOR` and `--no-color`.
2. **Never write outside `~/.pyauto-heart/`** in any check module.
The daemon must be a pure observer; mutations belong in
`pyauto-heart fix <topic>` which only EMITS context for a fresh
Claude session.
3. **Polling must be cheap**. A full `tick` should complete in <30s
total. If a check would take longer, run it less often (move to a
v2 daily cron, not the watch loop).
4. **Lightweight test footprint**. Heart's own test suite runs on the
standard library plus PyYAML only — no scientific/ML stack (numba,
matplotlib, JAX, the PyAuto libraries). This keeps the suite fast and
flake-free so it runs anywhere (CI, mobile, sandbox). It is a property of
*Heart's* tests, not a claim about the projects Heart watches — Heart may
perfectly well monitor non-JAX (or JAX-heavy) repos; that's their concern,
not the suite's.
Comment on lines +21 to +27
5. **State writes are atomic**. Use `heart.state.atomic_write_json` or
the bash equivalent (`heart_write_json` in `_common.sh`). Concurrent
ticks must not corrupt `state.json`.

## Repo structure

```
bin/pyauto-heart # bash dispatcher
heart/ # all logic, shell-first
_color.sh, _common.sh
daemon.sh, tick.sh # the loop + one cycle
state.py, status.py, fix.py # Python side
heart_color.py
checks/ # one file per check class
config/repos.yaml # polled repo registry + thresholds
tests/ # pytest
```

## Adding a new check

1. Create `heart/checks/<name>.{sh,py}` following the existing patterns.
2. Each check writes per-repo JSON sidecars to
`$HEART_PER_REPO_DIR/<repo>.<check_kind>.json` OR a global file at
`$HEART_STATE_DIR/<check_name>.json`.
3. Print a single colour-coded summary line to stdout (logged to the
daemon log by `heart_log`).
4. Add a section to `heart/status.py:render` that surfaces the result.
5. Add tests in `tests/test_<name>.py` covering classification edges.
6. Wire into `heart/tick.sh` in the appropriate position.

## Running locally

```bash
pip install -e .[dev]
pytest tests/ -v
HEART_FORCE_COLOR=1 pyauto-heart tick # one cycle, with colour
pyauto-heart status
```

## Codex / sandboxed runs

```bash
NUMBA_CACHE_DIR=/tmp/numba_cache MPLCONFIGDIR=/tmp/matplotlib \
pytest tests/
```

The never-rewrite-history rules live in [`AGENTS.md`](../AGENTS.md) and apply
here as everywhere.
2 changes: 1 addition & 1 deletion health_agent/capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,5 @@ sidecars, rolling `timings/`, `url_check.json`, `verify_install.json`, daemon
## Documentation describing health checks

`README.md` (user-facing), `AGENTS.md` (the Brain/Heart/Hands boundary + call
chain), `CLAUDE.md` (internals: the check framework, the `<30s` tick budget, how
chain), `docs/internals.md` (internals: the check framework, the `<30s` tick budget, how
to add a check, the observer-only / colour / atomic-write hard rules).
2 changes: 1 addition & 1 deletion health_agent/capabilities.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# treats Heart as an abstract health provider: when Heart gains or renames a
# check, update this manifest and the agent adapts without code changes.
#
# Maintained alongside the checks. If you add a check (see CLAUDE.md "Adding a
# Maintained alongside the checks. If you add a check (see docs/internals.md "Adding a
# new check"), add an entry here too.

provider:
Expand Down
2 changes: 1 addition & 1 deletion heart/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
Agent uploads/downloads this artifact and later feeds it to ``--ingest``
alongside the ``commit_shas`` it read while orchestrating the build.

**Boundary (non-negotiable, mirrors CLAUDE.md).** This module NEVER dispatches
**Boundary (non-negotiable, mirrors AGENTS.md).** This module NEVER dispatches
a build, never talks to GitHub, never mutates any repo. All dispatching / polling
/ artifact download is the Brain Release Agent's job; Heart is spec + ingest +
verdict, credential-free. It writes ONLY under ``~/.pyauto-heart/`` (``--ingest``)
Expand Down
Loading