From 6fd29b70859e81ba0b5c3ce8fe6ed9de66bf05a6 Mon Sep 17 00:00:00 2001 From: rob Date: Sat, 25 Oct 2025 22:14:34 -0300 Subject: [PATCH] 1st commit --- src/cascadingdev/setup_project.py | 56 +++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/src/cascadingdev/setup_project.py b/src/cascadingdev/setup_project.py index ace4f81..cf2770d 100644 --- a/src/cascadingdev/setup_project.py +++ b/src/cascadingdev/setup_project.py @@ -14,7 +14,6 @@ Examples: python3 scripts/setup_project.py --target ~/dev/my-new-repo python3 scripts/setup_project.py --target /abs/path --no-ramble """ -import os import sys import json import shutil @@ -50,7 +49,7 @@ def ensure_git_repo(target: Path): ]) + "\n") def install_precommit_hook(target: Path): - hook_src = INSTALL_ROOT / "scripts" / "hooks" / "pre-commit" + hook_src = INSTALL_ROOT / "assets" / "hooks" / "pre-commit" hooks_dir = target / ".git" / "hooks" hooks_dir.mkdir(parents=True, exist_ok=True) hook_dst = hooks_dir / "pre-commit" @@ -61,7 +60,7 @@ def install_precommit_hook(target: Path): hook_dst.chmod(0o755) say(f"[+] Installed git hook → {hook_dst}") -def run_ramble_and_collect(target: Path, provider: str = "mock"): +def run_ramble_and_collect(target: Path, provider: str = "mock", claude_cmd: str = "claude"): ramble = target / "ramble.py" if not ramble.exists(): say("[-] ramble.py not found in target; skipping interactive FR capture.") @@ -70,18 +69,42 @@ def run_ramble_and_collect(target: Path, provider: str = "mock"): args = [ sys.executable, str(ramble), "--provider", provider, + "--claude-cmd", claude_cmd, "--prompt", "Describe your initial feature request for this repository", "--fields", "Summary", "Title", "Intent", "ProblemItSolves", "BriefOverview", "--criteria", '{"Summary":"<= 2 sentences","Title":"camelCase, <= 24 chars"}' ] - say("[•] Launching Ramble (close the dialog to continue)…") + say("[•] Launching Ramble (close the dialog with Submit to return JSON)…") proc = subprocess.run(args, text=True, capture_output=True, cwd=str(target)) + + if proc.stderr and proc.stderr.strip(): + say("[Ramble stderr]") + say(proc.stderr.strip()) + out = (proc.stdout or "").strip() - try: - return json.loads(out) - except Exception: - say("[-] Could not parse Ramble output; proceeding with template text.") - return None + if out: + try: + return json.loads(out) + except Exception as e: + say(f"[-] JSON parse failed: {e}") + + # Terminal fallback so setup can proceed without GUI deps + say("[!] Falling back to terminal prompts.") + def ask(label, default=""): + try: + v = input(f"{label}: ").strip() + return v or default + except EOFError: + return default + + fields = { + "Title": ask("Title (camelCase, <=24 chars)", "initialProjectDesign"), + "Intent": ask("Intent", "—"), + "ProblemItSolves": ask("Problem it solves", "—"), + "BriefOverview": ask("Brief overview", "—"), + "Summary": ask("One- or two-sentence summary", ""), + } + return {"fields": fields, "summary": fields.get("Summary", "")} def seed_process_and_rules(target: Path): write_if_missing(target / "process" / "design.md", @@ -239,6 +262,16 @@ def copy_install_assets_to_target(target: Path): # Copy DESIGN.md and ramble.py from installer if present copy_if_exists(INSTALL_ROOT / "DESIGN.md", target / "DESIGN.md") copy_if_exists(INSTALL_ROOT / "ramble.py", target / "ramble.py") + + # Copy shipped templates (preferred source of truth) + tmpl_src = INSTALL_ROOT / "assets" / "templates" + if tmpl_src.exists(): + shutil.copytree(tmpl_src, target / "process" / "templates", dirs_exist_ok=True) + + # Copy the hook (you already install it to .git/hooks via install_precommit_hook) + # If you ever want the raw hook inside the user's repo too: + # copy_if_exists(INSTALL_ROOT / "assets" / "hooks" / "pre-commit", target / "scripts" / "hooks" / "pre-commit") + # Optionally copy any additional assets you drop under installer/automation, etc. # Example: copy starter automation folder if provided in installer if (INSTALL_ROOT / "automation").exists(): @@ -254,8 +287,9 @@ def first_commit(target: Path): def main(): ap = argparse.ArgumentParser() ap.add_argument("--target", help="Destination path to create/use the repo") - ap.add_argument("--provider", default="mock", help="Ramble provider (default: mock)") + ap.add_argument("--provider", choices=["mock", "claude"], default="mock", help="Ramble provider (default: mock)") ap.add_argument("--no-ramble", action="store_true", help="Skip launching Ramble") + ap.add_argument("--claude-cmd", default="claude") args = ap.parse_args() target_str = args.target @@ -295,7 +329,7 @@ def main(): # Launch Ramble (if available) req = None if not args.no_ramble: - req = run_ramble_and_collect(target, provider=args.provider) + req = run_ramble_and_collect(target, provider=args.provider, claude_cmd=args.claude_cmd) # Seed first feature based on Ramble output seed_initial_feature(target, req)