diff --git a/.kyzn/.gitignore b/.kyzn/.gitignore new file mode 100644 index 0000000..101f1a8 --- /dev/null +++ b/.kyzn/.gitignore @@ -0,0 +1,3 @@ +# kyzn — gitignored local data +history/ +reports/ diff --git a/.kyzn/config.yaml b/.kyzn/config.yaml new file mode 100644 index 0000000..6058082 --- /dev/null +++ b/.kyzn/config.yaml @@ -0,0 +1,35 @@ +# kyzn configuration — commit this file +# Generated by: kyzn init +# Date: 2026-03-17T21:55:04Z + +project: + name: bloxcue + type: generic + +preferences: + mode: +How aggressive should improvements be? + 1) Deep — real improvements only (no cosmetic changes) + 2) Clean — dead weight cleanup (remove unused code, fix naming) + 3) Full — everything (maximum value per run) + +Choice [1]: 1 + budget: Budget per run (USD) [2.50]: 2.50 + max_turns: 30 + diff_limit: 2000 + trust: +Trust level for auto-merging? + 1) Guardian — always create PR, always wait for approval (recommended) + 2) Autopilot — auto-merge if build passes + tests pass + diff < threshold + +Choice [1]: 1 + on_build_fail: +If the build breaks after improvements, what should kyzn do? + 1) Write a report explaining what happened (recommended) + 2) Silently discard the branch + 3) Create a draft PR so you can see what was attempted + +Choice [1]: 1 + +focus: + priorities: [] diff --git a/scripts/indexer.py b/scripts/indexer.py index a803459..48d4cfa 100755 --- a/scripts/indexer.py +++ b/scripts/indexer.py @@ -1149,7 +1149,7 @@ def get_file_content(path: str) -> str: return "" if resolved_path.exists(): - content = resolved_path.read_text() + content = resolved_path.read_text(encoding="utf-8") _, body = parse_frontmatter(content) return body return "" diff --git a/scripts/pg_provider.py b/scripts/pg_provider.py index 21e46b9..d71a31f 100644 --- a/scripts/pg_provider.py +++ b/scripts/pg_provider.py @@ -69,6 +69,7 @@ def fetch_learnings(url: str, limit: int = 500, since: Optional[str] = None) -> if not HAS_PSYCOPG2 or not url: return [] + conn = None try: conn = psycopg2.connect(url, connect_timeout=5) conn.set_session(readonly=True) @@ -92,7 +93,6 @@ def fetch_learnings(url: str, limit: int = 500, since: Optional[str] = None) -> rows = cur.fetchall() cur.close() - conn.close() learnings = [] for row in rows: @@ -109,6 +109,12 @@ def fetch_learnings(url: str, limit: int = 500, since: Optional[str] = None) -> except Exception as e: print(f"[BloxCue PG] Failed to fetch learnings: {e}", file=sys.stderr) return [] + finally: + if conn is not None: + try: + conn.close() + except Exception: + pass def fetch_learning_content(url: str, learning_id: str) -> str: @@ -124,6 +130,7 @@ def fetch_learning_content(url: str, learning_id: str) -> str: if not HAS_PSYCOPG2 or not url or not learning_id: return "" + conn = None try: conn = psycopg2.connect(url, connect_timeout=5) conn.set_session(readonly=True) @@ -136,7 +143,6 @@ def fetch_learning_content(url: str, learning_id: str) -> str: row = cur.fetchone() cur.close() - conn.close() if not row: return "" @@ -171,6 +177,12 @@ def fetch_learning_content(url: str, learning_id: str) -> str: except Exception as e: print(f"[BloxCue PG] Failed to fetch learning {learning_id}: {e}", file=sys.stderr) return "" + finally: + if conn is not None: + try: + conn.close() + except Exception: + pass def learning_to_index_entry(learning: Dict, extract_keywords_fn: Callable) -> Optional[Dict]: