#!/usr/bin/env python3 """workflow-init.py Interactive initializer for the AI workflow repo. - Replaces placeholders like ai-workflow-test, https://gitea.brrd.tech/rob/test-workflow, rob, 40 messages, main - Honors default syntax default - Optionally git init + first commit Usage: python3 workflow-init.py [--path .] [--no-git] """ import argparse, os, re, sys, subprocess from pathlib import Path PLACEHOLDER_PATTERN = re.compile(r"\{\{([^}|]+)(?:\|([^}]*))?\}\}") TEXT_EXTS = {".md", ".txt", ".yml", ".yaml", ".json", ".toml", ".py", ".sh", ".gitignore", ""} def prompt(question, default=None): val = input(f"{question}" + (f" [{default}]" if default else "") + ": ").strip() return val or (default or "") def is_text_file(p: Path): if p.name.startswith(".git"): return False if p.is_dir(): return False if p.suffix in TEXT_EXTS: return True try: p.read_bytes().decode("utf-8") return True except Exception: return False def replace_placeholders(text: str, mapping: dict) -> str: def sub(m): var, default = m.group(1), m.group(2) return mapping.get(var, default or "") return PLACEHOLDER_PATTERN.sub(sub, text) def replace_in_file(p: Path, mapping: dict): try: orig = p.read_text(encoding="utf-8") except Exception: return False new = replace_placeholders(orig, mapping) if new != orig: p.write_text(new, encoding="utf-8") return True return False def git(cmd, cwd): return subprocess.run(["git"] + cmd, cwd=cwd, check=False, capture_output=True, text=True) def main(): ap = argparse.ArgumentParser() ap.add_argument("--path", default=".", help="Repository root path") ap.add_argument("--no-git", action="store_true", help="Do not run git init/commit") args = ap.parse_args() root = Path(args.path).resolve() if not root.exists(): print(f"Path not found: {root}", file=sys.stderr); sys.exit(1) print("Welcome! Let's initialize your AI workflow repository.\n") mapping = { "PROJECT_NAME": prompt("Project name", "MyProject"), "PRIMARY_OWNER": prompt("Primary owner/handle (for CODEOWNERS)", "your-handle"), "REPO_URL": prompt("Gitea repo URL (you can set later)", "https://gitea.example.com/you/myproject"), "TIMEBOX": prompt("Default timebox (e.g., '40 messages or 60 minutes')", "40 messages or 60 minutes"), "DEFAULT_BRANCH": prompt("Default branch", "main"), } print("\nReplacing placeholders...") changed = 0 for p in root.rglob("*"): if is_text_file(p): if replace_in_file(p, mapping): changed += 1 print(f"Updated {changed} files with your settings.") (root / "reports").mkdir(parents=True, exist_ok=True) (root / "project/tasks.yaml").write_text("# tasks: []\n", encoding="utf-8") if not (root / "project/tasks.yaml").exists() else None if not args.no_git: if not (root / ".git").exists(): print("\nInitializing git repository...") r = git(["init"], cwd=root) if r.returncode != 0: print("git init failed:", r.stderr, file=sys.stderr) if mapping["DEFAULT_BRANCH"] != "master": r = git(["checkout", "-B", mapping["DEFAULT_BRANCH"]], cwd=root) if r.returncode != 0: print("git branch setup failed:", r.stderr, file=sys.stderr) git(["add", "-A"], cwd=root) r = git(["commit", "-m", "chore(init): bootstrap AI workflow repository"], cwd=root) if r.returncode != 0: print("git commit failed:", r.stderr, file=sys.stderr) print("\nDone. Next steps:") print(f" 1) Review {root/'project/plan.md'} and {root/'project/state.md'}") print(f" 2) Set remote: git remote add origin {mapping['REPO_URL']}") print(f" 3) Push: git push -u origin {mapping['DEFAULT_BRANCH']}") print(" 4) Start Mission Control with: python3 workflow.py start-mc") if __name__ == '__main__': main()