1st commit

This commit is contained in:
rob 2025-10-25 22:14:34 -03:00
parent e4cf48b3ea
commit 6fd29b7085
1 changed files with 45 additions and 11 deletions

View File

@ -14,7 +14,6 @@ Examples:
python3 scripts/setup_project.py --target ~/dev/my-new-repo python3 scripts/setup_project.py --target ~/dev/my-new-repo
python3 scripts/setup_project.py --target /abs/path --no-ramble python3 scripts/setup_project.py --target /abs/path --no-ramble
""" """
import os
import sys import sys
import json import json
import shutil import shutil
@ -50,7 +49,7 @@ def ensure_git_repo(target: Path):
]) + "\n") ]) + "\n")
def install_precommit_hook(target: Path): 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 = target / ".git" / "hooks"
hooks_dir.mkdir(parents=True, exist_ok=True) hooks_dir.mkdir(parents=True, exist_ok=True)
hook_dst = hooks_dir / "pre-commit" hook_dst = hooks_dir / "pre-commit"
@ -61,7 +60,7 @@ def install_precommit_hook(target: Path):
hook_dst.chmod(0o755) hook_dst.chmod(0o755)
say(f"[+] Installed git hook → {hook_dst}") 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" ramble = target / "ramble.py"
if not ramble.exists(): if not ramble.exists():
say("[-] ramble.py not found in target; skipping interactive FR capture.") 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 = [ args = [
sys.executable, str(ramble), sys.executable, str(ramble),
"--provider", provider, "--provider", provider,
"--claude-cmd", claude_cmd,
"--prompt", "Describe your initial feature request for this repository", "--prompt", "Describe your initial feature request for this repository",
"--fields", "Summary", "Title", "Intent", "ProblemItSolves", "BriefOverview", "--fields", "Summary", "Title", "Intent", "ProblemItSolves", "BriefOverview",
"--criteria", '{"Summary":"<= 2 sentences","Title":"camelCase, <= 24 chars"}' "--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)) 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() out = (proc.stdout or "").strip()
try: if out:
return json.loads(out) try:
except Exception: return json.loads(out)
say("[-] Could not parse Ramble output; proceeding with template text.") except Exception as e:
return None 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): def seed_process_and_rules(target: Path):
write_if_missing(target / "process" / "design.md", 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 DESIGN.md and ramble.py from installer if present
copy_if_exists(INSTALL_ROOT / "DESIGN.md", target / "DESIGN.md") copy_if_exists(INSTALL_ROOT / "DESIGN.md", target / "DESIGN.md")
copy_if_exists(INSTALL_ROOT / "ramble.py", target / "ramble.py") 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. # Optionally copy any additional assets you drop under installer/automation, etc.
# Example: copy starter automation folder if provided in installer # Example: copy starter automation folder if provided in installer
if (INSTALL_ROOT / "automation").exists(): if (INSTALL_ROOT / "automation").exists():
@ -254,8 +287,9 @@ def first_commit(target: Path):
def main(): def main():
ap = argparse.ArgumentParser() ap = argparse.ArgumentParser()
ap.add_argument("--target", help="Destination path to create/use the repo") 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("--no-ramble", action="store_true", help="Skip launching Ramble")
ap.add_argument("--claude-cmd", default="claude")
args = ap.parse_args() args = ap.parse_args()
target_str = args.target target_str = args.target
@ -295,7 +329,7 @@ def main():
# Launch Ramble (if available) # Launch Ramble (if available)
req = None req = None
if not args.no_ramble: 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 first feature based on Ramble output
seed_initial_feature(target, req) seed_initial_feature(target, req)