diff --git a/scripts/complete_statehub_bootstrap.py b/scripts/complete_statehub_bootstrap.py new file mode 100644 index 0000000..68f7fa7 --- /dev/null +++ b/scripts/complete_statehub_bootstrap.py @@ -0,0 +1,418 @@ +#!/usr/bin/env python3 +"""Complete ready statehub-bootstrap workplans (T01–T03) for attached repos.""" +from __future__ import annotations + +import re +import sys +from pathlib import Path + +HOME = Path("/home/worsch") + +REGISTRY_STACK = """## Stack + +- **Language:** Markdown-first registry and planning repo (no application runtime yet) +- **Key deps:** State Hub ADR-001 workplans, `registry/indexes/capabilities.yaml` + +## Dev Commands + +```bash +# Orient (offline-safe) +cat .custodian-brief.md +cat INTENT.md +cat SCOPE.md +ls workplans/ + +# After workplan or registry edits — from ~/state-hub +make fix-consistency REPO={repo_slug} + +# Sanity-check markdown / registry edits +git diff --check +``` +""" + +DOCS_STACK = """## Stack + +- **Language:** Markdown-first control/planning repository (no application runtime) +- **Key deps:** State Hub workplans, agent instructions, optional `registry/` scaffold + +## Dev Commands + +```bash +cat .custodian-brief.md +cat INTENT.md +ls workplans/ + +# After workplan edits — from ~/state-hub +make fix-consistency REPO={repo_slug} +``` +""" + + +def wp0002_template( + *, + prefix: str, + num: str, + slug: str, + title: str, + domain: str, + repo: str, + topic_slug: str, + summary: str, + task_title: str, + task_body: str, +) -> str: + wid = f"{prefix}-{num}" + return f"""--- +id: {wid} +type: workplan +title: "{title}" +domain: {domain} +repo: {repo} +status: ready +owner: codex +topic_slug: {topic_slug} +created: "2026-06-22" +updated: "2026-06-22" +--- + +# {title} + +{summary} + +## {task_title} + +```task +id: {wid}-T01 +status: todo +priority: high +``` + +{task_body} +""" + + +def close_wp0001(path: Path, *, t01_note: str, t02_note: str, t03_note: str) -> None: + text = path.read_text(encoding="utf-8") + text = re.sub(r"^status: ready$", "status: finished", text, count=1, flags=re.M) + text = re.sub(r"^(updated: ).*$", r'\1"2026-06-22"', text, count=1, flags=re.M) + for tid, note in [ + ("T01", t01_note), + ("T02", t02_note), + ("T03", t03_note), + ]: + text = re.sub( + rf"(id: [A-Z0-9-]+-{tid}\nstatus: )todo", + r"\1done", + text, + count=1, + ) + pattern = rf"(```task\nid: [A-Z0-9-]+-{tid}\nstatus: done\n.*?```)" + block = re.search(pattern, text, re.DOTALL) + if block and note: + after = f"{block.group(1)}\n\nResult 2026-06-22: {note}" + if note not in text: + text = text.replace(block.group(1), after, 1) + path.write_text(text, encoding="utf-8") + + +def fill_scope_template(path: Path, *, oneliner: str, core: str, in_scope: list[str], out_scope: list[str]) -> None: + text = path.read_text(encoding="utf-8") + if "