Skip to content

feat(health): add pure classify_health_v2 (four classes, most-severe-wins) - #66

Merged
belarusian merged 1 commit into
mainfrom
build15/classify-health-v2
Aug 20, 2026
Merged

feat(health): add pure classify_health_v2 (four classes, most-severe-wins)#66
belarusian merged 1 commit into
mainfrom
build15/classify-health-v2

Conversation

@belarusian

Copy link
Copy Markdown
Owner

Cycle 15 — Health v2: Outcome + Classify

Adds the v2 health classifier to fleet/health.py as a PURE function (module + tests only; NOT wired into assess — that is Cycle 17).

What

  • classify_health_v2(days: int | None, last_outcome: str | None, git_state: GitState) -> str — returns exactly one of stranded / active / paused / dead (most-severe-wins: stranded > active > paused > dead).
  • Module constant DEAD_MIN_DAYS = 30 (reuses existing ACTIVE_MAX_DAYS = 7).
  • from fleet.gittest import GitState (the git-side input from Cycle 14).
  • Module docstring updated to document both the v1 and v2 schemes.

Semantics (pinned by tests)

  • stranded = unmerged build* branch OR unpushed commits on main, regardless of recency
  • active = touched <=7d AND work in flight (last outcome max_steps_reached)
  • paused = recently touched but done, or 8-29d idle, nothing in flight
  • dead = 30+ days untouched AND nothing in flight, or no activity signal

Only max_steps_reached counts as work in flight. The v2 dead boundary is >= 30 while v1's is > 30 — intentionally different, documented, not unified.

Tests

16 hermetic unit tests in tests/test_health.py (construct GitState(...) directly — no git subprocess, no tmp_path, no fourseer), covering all 16 acceptance cases including the 7d/30d boundaries and the alloc-pipeline / deepseek-deharness canaries. No existing v1 test modified or removed.

Gate

  • pytest tests/ — 133 passed (was 117)
  • ruff check fleet/ — clean
  • mypy fleet/ --ignore-missing-imports — clean (8 source files)

Out of scope (deferred)

TICKET-057 (export gittest in fleet/__init__.py) is recorded but deferred — the briefing forbids changing any other fleet/ source file this cycle.

Closes #64, #65

…wins)

Add classify_health_v2(days, last_outcome, git_state) -> str to fleet/health.py:
a PURE function returning one of stranded/active/paused/dead (most-severe-wins:
stranded > active > paused > dead). Add module constant DEAD_MIN_DAYS = 30 (reuse
ACTIVE_MAX_DAYS = 7) and import GitState from fleet.gittest.

Semantics:
- stranded = unmerged build* branch OR unpushed commits (any recency)
- active   = recent (<=7d) AND work in flight (last outcome max_steps_reached)
- paused   = recently touched but done, or 8-29d idle, nothing in flight
- dead     = 30+ days untouched AND nothing in flight, or no activity signal

Only max_steps_reached counts as work in flight. NOT wired into assess this
cycle. Update the module docstring to document the v2 scheme and note the
deliberate v1/v2 30-day boundary divergence (v1 dead > 30, v2 dead >= 30).

Add 16 hermetic unit tests (tests/test_health.py) covering all acceptance cases
including the 7d/30d boundaries and the alloc-pipeline / deepseek-deharness
canaries. No other fleet/ source file changed.

Tickets: TICKET-055 (core), TICKET-056 (tests), TICKET-058 (docstring),
TICKET-059 (30-day boundary note). TICKET-057 (export gittest in __init__.py)
is recorded but deferred (out of scope: no other fleet/ source file changed).

Closes #64, #65
@belarusian
belarusian merged commit 794ec75 into main Aug 20, 2026
2 checks passed
@belarusian
belarusian deleted the build15/classify-health-v2 branch August 20, 2026 03:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

health: add pure classify_health_v2 (four classes, most-severe-wins)

1 participant