#!/usr/bin/env python3 """Parse docs/FRICTION.md 'Open signals' into structured data for /kaizen. Stdlib only. Modes: --json (default): emit the open signals as JSON (Phase-0 input for /kaizen) --nudge : print a one-line 'loop overdue?' summary Authoritative design: docs/superpowers/specs/2026-06-14-kaizen-command-design.md """ import argparse import datetime import json import os import re REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) FRICTION = os.path.join(REPO_ROOT, "docs", "FRICTION.md") def extract_open_section(text): """Return the body between '## Open signals' and the next '## ' heading.""" lines = text.splitlines() start = None for i, line in enumerate(lines): if line.strip().lower() == "## open signals": start = i + 1 break if start is None: return "" end = len(lines) for j in range(start, len(lines)): if lines[j].startswith("## "): end = j break return "\n".join(lines[start:end]) def split_signals(section): """Split the Open-signals body into raw per-signal blocks. A signal starts with a top-level '- ' bullet; indented or blank lines are continuations. Returns a list of multi-line strings with the leading '- ' stripped from the first line.""" signals = [] current = None for line in section.splitlines(): if line.startswith("- "): if current is not None: signals.append("\n".join(current).strip()) current = [line[2:]] elif current is not None: if line.strip() == "" or line.startswith(" "): current.append(line.strip()) else: signals.append("\n".join(current).strip()) current = None if current is not None: signals.append("\n".join(current).strip()) return [s for s in signals if s] if __name__ == "__main__": # pragma: no cover (filled in Task 4) pass