#!/usr/bin/env python3 import os, sys, yaml def load_manifest(path): with open(path, 'r', encoding='utf-8') as f: return yaml.safe_load(f) def resolve(path, seen): m = load_manifest(path) includes = m.get('include', []) or [] modules = m.get('modules', []) or [] for inc in includes: resolve(inc, seen) for mod in modules: if mod not in seen: seen.append(mod) return seen def words(s: str) -> int: return len(s.split()) def main(): if len(sys.argv) != 3: print("Usage: prompt_build.py ", file=sys.stderr) sys.exit(2) manifest, out_path = sys.argv[1], sys.argv[2] mods = resolve(manifest, []) if not mods: print(f"No modules resolved from {manifest}", file=sys.stderr) sys.exit(1) os.makedirs(os.path.dirname(out_path), exist_ok=True) def read(p): with open(p, 'r', encoding='utf-8') as f: return f.read().strip() + "\n\n" parts = ["Generated Prompt Pack\n\n"] for m in mods: parts.append(f"--- {m} ---\n") parts.append(read(m)) content = "".join(parts) # budgets total_words = words(content) BASE_BUDGET = 1200 if total_words > BASE_BUDGET: print(f"ERROR: Pack exceeds budget: {total_words} > {BASE_BUDGET}", file=sys.stderr) sys.exit(3) ERRORS = 0 MOD_BUDGET = 400 for m in mods: with open(m, 'r', encoding='utf-8') as f: wc = words(f.read()) if wc > MOD_BUDGET: print(f"ERROR: Module {m} exceeds budget: {wc} > {MOD_BUDGET}", file=sys.stderr) ERRORS += 1 if ERRORS: sys.exit(4) if out_path == '-': sys.stdout.write(content) else: with open(out_path, 'w', encoding='utf-8') as out: out.write(content) print(f"Built {out_path} with {total_words} words across {len(mods)} modules.", file=sys.stderr) if __name__ == '__main__': main()