Skip to content

Commit a2543d0

Browse files
authored
Rename PyAutoPulse to PyAutoHeart (#18)
Rename the PyAutoPulse project identity to PyAutoHeart across docs, code, workflows, package metadata, and CLI surfaces. Keep compatibility wrappers for legacy pulse imports, pyautopulse package access, pyauto-pulse CLI usage, PULSE_* environment aliases, and stable reusable workflow filenames during the transition. Validation: - git diff --check - NUMBA_CACHE_DIR=/tmp/numba_cache MPLCONFIGDIR=/tmp/matplotlib pytest tests/ -q
1 parent dad94cf commit a2543d0

68 files changed

Lines changed: 4528 additions & 4306 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/lib-tests.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Library Tests (reusable)
22

3-
# Pulse-owned reusable unit-test workflow for the 5 PyAuto libraries
3+
# Heart-owned reusable unit-test workflow for the 5 PyAuto libraries
44
# (Stage 4 Phase A). Each library's own .github/workflows/main.yml is now a thin
55
# caller:
66
#
@@ -10,8 +10,12 @@ name: Library Tests (reusable)
1010
# with: { package: autolens }
1111
# secrets: inherit
1212
#
13+
# Keep the PyAutoPulse owner/repo in copy-paste examples until the GitHub
14+
# repository rename is complete and redirects are confirmed. The workflow
15+
# filename is intentionally stable for downstream callers.
16+
#
1317
# PR-time gating is preserved: the caller's `unittest` job runs on push/PR and is
14-
# the required status check. Pulse owns the test definition; the library just
18+
# the required status check. Heart owns the test definition; the library just
1519
# triggers it. Dependency-aware (conf→none, fit/array→conf, galaxy→conf+fit+array,
1620
# lens→all) so lightweight libs don't install the heavy stack. GitHub-hosted +
1721
# pip caching.

.github/workflows/pulse-health.yml

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
name: Pulse Health
1+
name: Heart Health
22

3-
# Scheduled cloud-safe half of the PyAutoPulse hybrid CI layer.
3+
# Scheduled cloud-safe half of the PyAutoHeart hybrid CI layer.
44
#
55
# Runs the two checks that need only the GitHub API (no local working tree) —
66
# CI status and open PRs — across every polled repo, then opens-or-updates a
7-
# single "[pulse-health]" tracking issue when anything is red/degraded, and
7+
# single "[heart-health]" tracking issue when anything is red/degraded, and
88
# closes it when everything is clean again. No agent, no Slack, no secret
99
# beyond the auto-provisioned GITHUB_TOKEN — mirrors the url_check.yml pattern.
1010
#
@@ -21,11 +21,11 @@ permissions:
2121
issues: write
2222

2323
jobs:
24-
pulse-health:
24+
heart-health:
2525
name: Cloud health checks
2626
runs-on: ubuntu-latest
2727
steps:
28-
- name: Checkout PyAutoPulse
28+
- name: Checkout PyAutoHeart
2929
uses: actions/checkout@v4
3030

3131
- name: Set up Python
@@ -42,21 +42,21 @@ jobs:
4242
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4343
# Force colour off; write sidecars under a workspace-local state dir.
4444
NO_COLOR: "1"
45-
PULSE_STATE_DIR: ${{ github.workspace }}/.pulse-state
45+
HEART_STATE_DIR: ${{ github.workspace }}/.heart-state
4646
run: |
4747
set +e
48-
bash pulse/checks/ci_status.sh
49-
bash pulse/checks/open_prs.sh
48+
bash heart/checks/ci_status.sh
49+
bash heart/checks/open_prs.sh
5050
exit 0
5151
5252
- name: Classify results
5353
id: classify
5454
env:
55-
PULSE_STATE_DIR: ${{ github.workspace }}/.pulse-state
55+
HEART_STATE_DIR: ${{ github.workspace }}/.heart-state
5656
run: |
5757
python3 - <<'PY'
5858
import json, os, glob, pathlib
59-
state = pathlib.Path(os.environ["PULSE_STATE_DIR"]) / "per-repo"
59+
state = pathlib.Path(os.environ["HEART_STATE_DIR"]) / "per-repo"
6060
red, yellow = [], []
6161
for f in sorted(state.glob("*.ci_status.json")):
6262
d = json.loads(f.read_text())
@@ -69,44 +69,44 @@ jobs:
6969
red.append(f"- **{d['name']}**: open PR {age}d old (>30d)")
7070
elif d.get("open_count", 0) and age >= 7:
7171
yellow.append(f"- {d['name']}: open PR {age}d old")
72-
lines = ["# Pulse health report", ""]
72+
lines = ["# Heart health report", ""]
7373
if red:
7474
lines += ["## 🔴 Red", *red, ""]
7575
if yellow:
7676
lines += ["## 🟡 Yellow", *yellow, ""]
7777
if not red and not yellow:
7878
lines += ["✅ All cloud checks green (CI passing, no stale PRs)."]
7979
body = "\n".join(lines)
80-
pathlib.Path("/tmp/pulse_health_body.md").write_text(body + "\n")
80+
pathlib.Path("/tmp/heart_health_body.md").write_text(body + "\n")
8181
status = "red" if red else ("yellow" if yellow else "green")
8282
with open(os.environ["GITHUB_OUTPUT"], "a") as out:
8383
out.write(f"status={status}\n")
8484
print(body)
8585
PY
8686
87-
- name: Open or update [pulse-health] tracking issue
87+
- name: Open or update [heart-health] tracking issue
8888
if: steps.classify.outputs.status != 'green'
8989
env:
9090
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9191
run: |
92-
existing=$(gh issue list --search '"[pulse-health]"' --state open --json number --jq '.[0].number // empty')
92+
existing=$(gh issue list --search '"[heart-health]"' --state open --json number --jq '.[0].number // empty')
9393
if [ -n "$existing" ]; then
94-
gh issue comment "$existing" --body-file /tmp/pulse_health_body.md
94+
gh issue comment "$existing" --body-file /tmp/heart_health_body.md
9595
else
9696
gh issue create \
97-
--title "[pulse-health] Degraded ecosystem health" \
98-
--body-file /tmp/pulse_health_body.md \
99-
--label pulse-health 2>/dev/null \
97+
--title "[heart-health] Degraded ecosystem health" \
98+
--body-file /tmp/heart_health_body.md \
99+
--label heart-health 2>/dev/null \
100100
|| gh issue create \
101-
--title "[pulse-health] Degraded ecosystem health" \
102-
--body-file /tmp/pulse_health_body.md
101+
--title "[heart-health] Degraded ecosystem health" \
102+
--body-file /tmp/heart_health_body.md
103103
fi
104104
105-
- name: Close [pulse-health] issue when clean
105+
- name: Close [heart-health] issue when clean
106106
if: steps.classify.outputs.status == 'green'
107107
env:
108108
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
109109
run: |
110-
for n in $(gh issue list --search '"[pulse-health]"' --state open --json number --jq '.[].number'); do
110+
for n in $(gh issue list --search '"[heart-health]"' --state open --json number --jq '.[].number'); do
111111
gh issue close "$n" --comment "Cloud health checks are green — closing automatically."
112112
done

.github/workflows/url-check.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ name: URL Check (central)
44
#
55
# Replaces the 12 per-repo .github/workflows/url_check.yml workflows: instead of
66
# each repo running its own offline + live URL audit and opening its own
7-
# [url-check] issue, PyAutoPulse sweeps every repo here and consolidates into a
8-
# SINGLE [url-check] tracking issue. Mirrors the pulse-health.yml pattern.
7+
# [url-check] issue, PyAutoHeart sweeps every repo here and consolidates into a
8+
# SINGLE [url-check] tracking issue. Mirrors the heart-health.yml pattern.
99
#
10-
# Monitoring only — URL hygiene does not gate releases (Pulse owns the release
10+
# Monitoring only — URL hygiene does not gate releases (Heart owns the release
1111
# gate via `readiness`, which this does not touch).
1212

1313
on:
@@ -31,10 +31,10 @@ jobs:
3131
name: Central URL sweep
3232
runs-on: ubuntu-latest
3333
steps:
34-
- name: Checkout PyAutoPulse
34+
- name: Checkout PyAutoHeart
3535
uses: actions/checkout@v4
3636
with:
37-
path: pulse
37+
path: heart
3838

3939
- name: Set up Python
4040
uses: actions/setup-python@v5
@@ -60,10 +60,10 @@ jobs:
6060
continue
6161
fi
6262
# Offline forbidden-pattern guard.
63-
off="$(bash pulse/pulse/checks/url_check.sh "checkout/$repo" 2>/dev/null)"
63+
off="$(bash heart/heart/checks/url_check.sh "checkout/$repo" 2>/dev/null)"
6464
off_rc=$?
6565
# Live HTTP audit (honours the repo's .url_check_allowlist.txt).
66-
live="$(bash pulse/pulse/checks/url_check_live.sh "checkout/$repo" 2>/dev/null)"
66+
live="$(bash heart/heart/checks/url_check_live.sh "checkout/$repo" 2>/dev/null)"
6767
live_rc=$?
6868
if [ "$off_rc" -ne 0 ] || [ "$live_rc" -ne 0 ]; then
6969
body+=$'\n'"## $repo"$'\n'

.github/workflows/workspace-validation.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
name: Workspace Validation
22

3-
# Pulse-owned workspace-integration validation (Stage 4 Phase B).
3+
# Heart-owned workspace-integration validation (Stage 4 Phase B).
44
#
55
# This is the "heavy validation CI" that used to live in PyAutoBuild's
66
# release.yml (find_scripts / generate_notebooks / run_scripts / run_notebooks /
7-
# analyze_results). Pulse owns it now: Build is a pure executor. It runs every
7+
# analyze_results). Heart owns it now: Build is a pure executor. It runs every
88
# workspace's scripts AND generated notebooks against the CURRENT source `main`
99
# of the 5 libraries (source-shadowed via PYTHONPATH), aggregates into the same
1010
# report.json contract, and uploads it as the `workspace-validation-report`
11-
# artifact. Pulse's test_run check reads that run's
11+
# artifact. Heart's test_run check reads that run's
1212
# conclusion + timestamp into the authoritative `readiness` verdict (with a
1313
# staleness window).
1414
#
@@ -17,7 +17,7 @@ name: Workspace Validation
1717
#
1818
# Triggers: weekly schedule (the continuous readiness signal), manual dispatch,
1919
# and workflow_call (so a release path can invoke it on demand). Heavy, so never
20-
# in the <30s pulse tick.
20+
# in the <30s heart tick.
2121

2222
on:
2323
schedule:
@@ -299,7 +299,7 @@ jobs:
299299
- name: Post summary
300300
if: always()
301301
run: cat report.md >> "$GITHUB_STEP_SUMMARY" || true
302-
- name: Upload report (consumed by pyauto-pulse readiness)
302+
- name: Upload report (consumed by pyauto-heart readiness)
303303
if: always()
304304
uses: actions/upload-artifact@v4
305305
with:

AGENTS.md

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,35 @@
1-
# PyAutoPulse — Agent Guidance
1+
# PyAutoHeart — Agent Guidance
22

3-
PyAutoPulse is the **health authority** of the PyAuto release ecosystem: it owns
4-
all health and release-readiness checking plus continuous monitoring of the
5-
PyAuto repos. `pyauto-pulse readiness` is the authoritative "is it safe to
3+
PyAutoHeart is the **health and vital-signs authority** of the PyAuto organism:
4+
it owns health checks, release-readiness checking, workspace validation, URL
5+
hygiene, generated-artifact/noise classification, and continuous monitoring of
6+
the PyAuto repos. `pyauto-heart readiness` is the authoritative "is it safe to
67
release?" gate.
78

89
## The boundary (one description, mirrored in all three repos)
910

10-
- **PyAutoPulse — the health authority.** All health/readiness logic lives here:
11+
- **PyAutoHeart — the health authority.** All health/readiness logic lives here:
1112
version drift, install-path, URL hygiene, CI/worktree/timing monitoring.
12-
`pyauto-pulse readiness` is the **authoritative** green/yellow/red verdict —
13-
the single "is it safe to release?" gate. Pulse is an observer: it reads and
13+
`pyauto-heart readiness` is the **authoritative** green/yellow/red verdict —
14+
the single "is it safe to release?" gate. Heart is an observer: it reads and
1415
emits verdicts; it never writes into other repos and never triggers Build.
15-
- **PyAutoBuild — the executor.** Packaging, tagging, notebook generation, and
16-
PyPI publication via `release.yml`. Build runs **no** readiness checks of its
17-
own and never re-derives a gate decision; it just executes.
18-
- **PyAutoAgent — the brain.** Hosts the agents that connect the two. It owns no
19-
checks and no release steps; it gates on Pulse and delegates execution to
20-
Build.
16+
- **PyAutoHands / PyAutoBuild — the executor.** Packaging, tagging, notebook
17+
generation, and PyPI publication via `release.yml`. Hands runs **no**
18+
readiness checks of its own and never re-derives a gate decision; it just
19+
executes.
20+
- **PyAutoBrain / PyAutoAgent — the brain.** Hosts the agents that connect the
21+
two. It owns no checks and no release steps; it gates on Heart and delegates
22+
execution to Hands.
2123

2224
## The call chain (always this order)
2325

2426
```
25-
AgentPulse (gate) → Build (execute)
27+
BrainHeart (gate) → Hands (execute)
2628
```
2729

28-
The agent asks `pyauto-pulse readiness --json`; only on a **green** verdict does
29-
it trigger Build's release. Pulse never triggers Build; Build never re-derives a
30-
gate decision the agent already made.
30+
The brain asks `pyauto-heart readiness --json`; only on a **green** verdict does
31+
it trigger Hands' release work. Heart never triggers Hands; Hands never
32+
re-derives a gate decision the brain already made.
3133

3234
## Where things live
3335

@@ -39,6 +41,6 @@ gate decision the agent already made.
3941
- `readiness` rolls these into the authoritative verdict (URL hygiene is
4042
monitoring only and does **not** gate it).
4143

42-
See [`CLAUDE.md`](CLAUDE.md) for Pulse's internals — the check framework, the
44+
See [`CLAUDE.md`](CLAUDE.md) for Heart's internals — the check framework, the
4345
<30s tick budget, how to add a check, and the hard rules (observer-only, colour
4446
coding, atomic state writes).

CLAUDE.md

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,78 @@
1-
# PyAutoPulse — Agent Guidance
1+
# PyAutoHeart — Agent Guidance
22

33
This file is for AI coding agents (Claude Code, Codex, Cursor, etc.)
44
discovering this repository.
55

66
## What this repo is
77

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

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

20-
See [`AGENTS.md`](AGENTS.md) for the canonical Build/Pulse/Agent boundary and the
21-
`AgentPulseBuild` call chain, and `README.md` for user-facing docs.
21+
See [`AGENTS.md`](AGENTS.md) for the canonical Brain/Heart/Hands boundary and
22+
the `BrainHeartHands` call chain, and `README.md` for user-facing docs.
2223

2324
## Hard rules
2425

2526
1. **Color coding everywhere**: green = passing, yellow = warning,
2627
red = failing. Use the `c_ok / c_warn / c_fail / c_info / c_meta`
27-
helpers in `pulse/_color.sh` (bash) and `pulse/pulse_color.py`
28+
helpers in `heart/_color.sh` (bash) and `heart/heart_color.py`
2829
(Python). Honour `NO_COLOR` and `--no-color`.
29-
2. **Never write outside `~/.pyauto-pulse/`** in any check module.
30+
2. **Never write outside `~/.pyauto-heart/`** in any check module.
3031
The daemon must be a pure observer; mutations belong in
31-
`pyauto-pulse fix <topic>` which only EMITS context for a fresh
32+
`pyauto-heart fix <topic>` which only EMITS context for a fresh
3233
Claude session.
3334
3. **Polling must be cheap**. A full `tick` should complete in <30s
3435
total. If a check would take longer, run it less often (move to a
3536
v2 daily cron, not the watch loop).
36-
4. **No JAX in tests** — library convention. Pulse tests run with
37+
4. **No JAX in tests** — library convention. Heart tests run with
3738
stdlib + PyYAML only.
38-
5. **State writes are atomic**. Use `pulse.state.atomic_write_json` or
39-
the bash equivalent (`pulse_write_json` in `_common.sh`). Concurrent
39+
5. **State writes are atomic**. Use `heart.state.atomic_write_json` or
40+
the bash equivalent (`heart_write_json` in `_common.sh`). Concurrent
4041
ticks must not corrupt `state.json`.
4142

4243
## Repo structure
4344

4445
```
45-
bin/pyauto-pulse # bash dispatcher
46-
pulse/ # all logic, shell-first
46+
bin/pyauto-heart # bash dispatcher
47+
heart/ # all logic, shell-first
4748
_color.sh, _common.sh
4849
daemon.sh, tick.sh # the loop + one cycle
4950
state.py, status.py, fix.py # Python side
50-
pulse_color.py
51+
heart_color.py
5152
checks/ # one file per check class
5253
config/repos.yaml # polled repo registry + thresholds
5354
tests/ # pytest
5455
```
5556

5657
## Adding a new check
5758

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

6869
## Running locally
6970

7071
```bash
7172
pip install -e .[dev]
7273
pytest tests/ -v
73-
PULSE_FORCE_COLOR=1 pyauto-pulse tick # one cycle, with colour
74-
pyauto-pulse status
74+
HEART_FORCE_COLOR=1 pyauto-heart tick # one cycle, with colour
75+
pyauto-heart status
7576
```
7677

7778
## Codex / sandboxed runs

0 commit comments

Comments
 (0)