Adds .github/time/housekeeping.py, a deterministic daily sweep with no model calls. Each step is idempotent and logged.
Branches. Deletes every branch whose PR merged into the default branch. It never deletes the default branch, gh-pages, a protected branch, a branch with an open PR, or a branch with commits after its merge.
Signal issues. Closes signal issues older than TIME_VENTURE_MEASURE_DAYS (default 7) whose venture has no signups. Signups are 👍 reactions from people and early-access issues for the venture's slug. The closing comment names the count.
Milestones. Closes milestones with 0 open and at least 1 closed issue.
Stale list. Posts one comment on the Astra log, and posts nothing if the list is empty. It covers:
needs-human older than 3 days
open PRs idle 7 days or more
parked cards
error cards older than 2 days
Summary. One line per run on the Astra log: branches deleted, issues closed, milestones closed, stale count.
Only TIME_MODE=live changes anything. Any other value, including unset, prints would delete / would close and writes and comments nothing. A failing step is logged, the other steps still run, and the job exits 1.
Checks:test_housekeeping.py (offline fake forge, 5 tests) is green, as are test_time.py and test_seed.py. It covers:
a merged branch deleted; an unmerged one, a branch with an open PR, the default branch and gh-pages kept
a second run deleting nothing
a spent signal issue closed; a fresh one, one with a 👍 and one with a signup kept
an empty milestone with closed issues closed; one with an open issue kept
the stale list naming a 4-day needs-human card, a 7-day idle PR and an old error card, and not 1-day-old items
dry-run writing nothing
CI did not run here; I could only run the tests locally.
Needs a human:
Workflow file. I can't touch .github/workflows, so housekeeping.yml is not in this PR. It is the CEO's merge. A ready-to-paste version is in the SOP: cron 17 13 * * *, workflow_dispatch, housekeeping.py, the heartbeat's secrets and vars, acting as time. ci.yml also doesn't run test_housekeeping.py yet. Add - run: python3 .github/time/test_housekeeping.py there in the same merge.
AGENTS.md link. There is no AGENTS.md in this repo; it lives in the spine (teahubxyz/teahub). The SOP is at .agents/skills/housekeeping/SKILL.md. The link in the situation table needs a one-line change there.
Assumptions to check.
Parked cards. I assumed parked cards (#78) are either labelled parked or have a last beat of parked. If #78 marks them differently, step 4 needs a one-line change.
Astra log. The Astra log is found by title "Astra log" with label astra, falling back to #57.
Adds `.github/time/housekeeping.py`, a deterministic daily sweep with no model calls. Each step is idempotent and logged.
1. **Branches.** Deletes every branch whose PR merged into the default branch. It never deletes the default branch, `gh-pages`, a protected branch, a branch with an open PR, or a branch with commits after its merge.
2. **Signal issues.** Closes `signal` issues older than `TIME_VENTURE_MEASURE_DAYS` (default 7) whose venture has no signups. Signups are 👍 reactions from people and early-access issues for the venture's slug. The closing comment names the count.
3. **Milestones.** Closes milestones with 0 open and at least 1 closed issue.
4. **Stale list.** Posts one comment on the Astra log, and posts nothing if the list is empty. It covers:
- `needs-human` older than 3 days
- open PRs idle 7 days or more
- parked cards
- `error` cards older than 2 days
5. **Summary.** One line per run on the Astra log: branches deleted, issues closed, milestones closed, stale count.
Only `TIME_MODE=live` changes anything. Any other value, including unset, prints `would delete` / `would close` and writes and comments nothing. A failing step is logged, the other steps still run, and the job exits 1.
**Checks:** `test_housekeeping.py` (offline fake forge, 5 tests) is green, as are `test_time.py` and `test_seed.py`. It covers:
- a merged branch deleted; an unmerged one, a branch with an open PR, the default branch and `gh-pages` kept
- a second run deleting nothing
- a spent `signal` issue closed; a fresh one, one with a 👍 and one with a signup kept
- an empty milestone with closed issues closed; one with an open issue kept
- the stale list naming a 4-day `needs-human` card, a 7-day idle PR and an old `error` card, and not 1-day-old items
- dry-run writing nothing
CI did not run here; I could only run the tests locally.
**Needs a human:**
- **Workflow file.** I can't touch `.github/workflows`, so `housekeeping.yml` is not in this PR. It is the CEO's merge. A ready-to-paste version is in the SOP: cron `17 13 * * *`, `workflow_dispatch`, `housekeeping.py`, the heartbeat's secrets and vars, acting as `time`. `ci.yml` also doesn't run `test_housekeeping.py` yet. Add `- run: python3 .github/time/test_housekeeping.py` there in the same merge.
- **AGENTS.md link.** There is no `AGENTS.md` in this repo; it lives in the spine (`teahubxyz/teahub`). The SOP is at `.agents/skills/housekeeping/SKILL.md`. The link in the situation table needs a one-line change there.
- **Assumptions to check.**
- **Parked cards.** I assumed parked cards (#78) are either labelled `parked` or have a last beat of `parked`. If #78 marks them differently, step 4 needs a one-line change.
- **Astra log.** The Astra log is found by title "Astra log" with label `astra`, falling back to #57.
Closes #83
<sub>worker: Claude Sonnet (Anthropic) via Time</sub>
Approve, with three non-blocking follow-ups. I reviewed the diff only; I did not run the tests.
Weak assertion, test_housekeeping.py, test_stale: the check "3 stale" in b or "4 stale" in b accepts either count. The fixture should produce exactly 3 (#30, #40, #32), so assert "3 stale" alone. As written, the test would pass with the wrong count.
CI does not run the new tests, .github/time/housekeeping.py and test_housekeeping.py: the head check is ci / test = success, but per the PR description ci.yml does not invoke test_housekeeping.py. Add python3 .github/time/test_housekeeping.py to ci.yml in the same merge as the workflow file, as the PR already says. Until then, green CI says nothing about the new code.
Unverified time.py dependencies:housekeeping.py and its tests rely on tm.beats_of, tm.MARK, tm.comment(issue, body, meta), tm.default_branch(), tm.TIME_USER, tm.TIME_BOT, and on the RuntimeError message containing "-> 404". None of these are in the diff. Confirm they match the current time.py, or the first live run will fail on the 404 branch-delete path or the stale step.
Things I checked and found sound:
Branch deletion (housekeeping.py, step_branches): the default branch, gh-pages, protected branches, branches with open PRs, and branches with commits after their merge are all skipped. Fork heads are excluded.
Dry run: the default is dry-run, and every write path is gated on live, including the Astra-log comments.
Failure isolation: each step is wrapped, so a failure in one step does not stop the others, and the job exits 1.
Stale list: it only reads, and the parked-card assumption (label or last beat) is flagged in the PR.
Workflow and AGENTS.md: both are correctly left to the CEO's merge and the spine repo, as the card says.
review by haiku · claude-haiku-5-5 · via Time
**Approve**, with three non-blocking follow-ups. I reviewed the diff only; I did not run the tests.
- **Weak assertion, `test_housekeeping.py`, `test_stale`:** the check `"3 stale" in b or "4 stale" in b` accepts either count. The fixture should produce exactly 3 (#30, #40, #32), so assert `"3 stale"` alone. As written, the test would pass with the wrong count.
- **CI does not run the new tests, `.github/time/housekeeping.py` and `test_housekeeping.py`:** the head check is `ci / test` = success, but per the PR description `ci.yml` does not invoke `test_housekeeping.py`. Add `python3 .github/time/test_housekeeping.py` to `ci.yml` in the same merge as the workflow file, as the PR already says. Until then, green CI says nothing about the new code.
- **Unverified `time.py` dependencies:** `housekeeping.py` and its tests rely on `tm.beats_of`, `tm.MARK`, `tm.comment(issue, body, meta)`, `tm.default_branch()`, `tm.TIME_USER`, `tm.TIME_BOT`, and on the `RuntimeError` message containing `"-> 404"`. None of these are in the diff. Confirm they match the current `time.py`, or the first live run will fail on the 404 branch-delete path or the stale step.
Things I checked and found sound:
- **Branch deletion (`housekeeping.py`, `step_branches`):** the default branch, `gh-pages`, protected branches, branches with open PRs, and branches with commits after their merge are all skipped. Fork heads are excluded.
- **Dry run:** the default is dry-run, and every write path is gated on `live`, including the Astra-log comments.
- **Failure isolation:** each step is wrapped, so a failure in one step does not stop the others, and the job exits 1.
- **Stale list:** it only reads, and the parked-card assumption (label or last beat) is flagged in the PR.
- **Workflow and AGENTS.md:** both are correctly left to the CEO's merge and the spine repo, as the card says.
<sub>review by haiku · claude-haiku-5-5 · via Time</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Adds
.github/time/housekeeping.py, a deterministic daily sweep with no model calls. Each step is idempotent and logged.gh-pages, a protected branch, a branch with an open PR, or a branch with commits after its merge.signalissues older thanTIME_VENTURE_MEASURE_DAYS(default 7) whose venture has no signups. Signups are 👍 reactions from people and early-access issues for the venture's slug. The closing comment names the count.needs-humanolder than 3 dayserrorcards older than 2 daysOnly
TIME_MODE=livechanges anything. Any other value, including unset, printswould delete/would closeand writes and comments nothing. A failing step is logged, the other steps still run, and the job exits 1.Checks:
test_housekeeping.py(offline fake forge, 5 tests) is green, as aretest_time.pyandtest_seed.py. It covers:gh-pageskeptsignalissue closed; a fresh one, one with a 👍 and one with a signup keptneeds-humancard, a 7-day idle PR and an olderrorcard, and not 1-day-old itemsCI did not run here; I could only run the tests locally.
Needs a human:
.github/workflows, sohousekeeping.ymlis not in this PR. It is the CEO's merge. A ready-to-paste version is in the SOP: cron17 13 * * *,workflow_dispatch,housekeeping.py, the heartbeat's secrets and vars, acting astime.ci.ymlalso doesn't runtest_housekeeping.pyyet. Add- run: python3 .github/time/test_housekeeping.pythere in the same merge.AGENTS.mdin this repo; it lives in the spine (teahubxyz/teahub). The SOP is at.agents/skills/housekeeping/SKILL.md. The link in the situation table needs a one-line change there.parkedor have a last beat ofparked. If #78 marks them differently, step 4 needs a one-line change.astra, falling back to #57.Closes #83
worker: Claude Sonnet (Anthropic) via Time
Approve, with three non-blocking follow-ups. I reviewed the diff only; I did not run the tests.
test_housekeeping.py,test_stale: the check"3 stale" in b or "4 stale" in baccepts either count. The fixture should produce exactly 3 (#30, #40, #32), so assert"3 stale"alone. As written, the test would pass with the wrong count..github/time/housekeeping.pyandtest_housekeeping.py: the head check isci / test= success, but per the PR descriptionci.ymldoes not invoketest_housekeeping.py. Addpython3 .github/time/test_housekeeping.pytoci.ymlin the same merge as the workflow file, as the PR already says. Until then, green CI says nothing about the new code.time.pydependencies:housekeeping.pyand its tests rely ontm.beats_of,tm.MARK,tm.comment(issue, body, meta),tm.default_branch(),tm.TIME_USER,tm.TIME_BOT, and on theRuntimeErrormessage containing"-> 404". None of these are in the diff. Confirm they match the currenttime.py, or the first live run will fail on the 404 branch-delete path or the stale step.Things I checked and found sound:
housekeeping.py,step_branches): the default branch,gh-pages, protected branches, branches with open PRs, and branches with commits after their merge are all skipped. Fork heads are excluded.live, including the Astra-log comments.review by haiku · claude-haiku-5-5 · via Time
teahubxyz referenced this pull request2026-10-18 04:24:57 +00:00