diff --git a/cc-ci-plan/launch.py b/cc-ci-plan/launch.py index 6695682..575f2ad 100644 --- a/cc-ci-plan/launch.py +++ b/cc-ci-plan/launch.py @@ -215,12 +215,27 @@ def resolve_state(repo_dir, basename): p = Path(repo_dir) / "machine-docs" / basename return p if p.exists() else Path(repo_dir) / basename +# A "## DONE" heading marks real completion ONLY when its body is a substantive completion +# statement. A Builder that scaffolds a "## DONE / Not yet ..." placeholder section must not +# trip the auto-advance — that false-completed and SKIPPED the mailu phase once (2026-06-11). +_DONE_PLACEHOLDER_RE = re.compile( + r"^\s*(not yet|not done|not complete|incomplete|pending\b|tbd\b|n/?a\b|" + r"written here only|only when|to be (written|filled)|when all|<.*>)", re.I) + def phase_done(status_basename): path = resolve_state(BUILDER_DIR, status_basename) try: - return any(line.startswith("## DONE") for line in path.open()) + lines = path.read_text().splitlines() except FileNotFoundError: return False + for i, line in enumerate(lines): + if not line.startswith("## DONE"): + continue + body = next((nxt for nxt in lines[i+1:] if nxt.strip()), "") # first non-empty body line + if _DONE_PLACEHOLDER_RE.match(body): + continue # placeholder section ("Not yet ...") — keep scanning, not real + return True + return False # ── kickoff prompt ────────────────────────────────────────────────────────────