add Python stopgap planning tooling under tools/scripts/plan

Ports settled-reach's decisions_sync.py + ticket + decision scripts,
Scrum-stripped. Writes to .pql/pql.db (gitignored). Verb shape
mirrors the eventual `pql` subcommands so migration is a call-site
find-replace once pql ships feature parity (D-040, R-011).

Ticket IDs are T-NNN (TEXT PKs) — reshape from settled-reach's
integer auto-increment so the stopgap's writes are compatible with
pql's future reads without a data migration. No `sprints` table; the
pyramid is kanban / waterfall (D-035).

Verified end-to-end: sync parses 71 records (39 confirmed, 23 open
questions, 9 rejected) with 62 cross-refs and zero broken links;
`ticket new`, `ticket status`, `ticket board`, and `decisions show
--with-refs` all round-trip correctly.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-04-21 17:28:10 +02:00
co-authored by Claude
parent cede971646
commit a96a54ec7f
13 changed files with 1201 additions and 1 deletions
+34
View File
@@ -0,0 +1,34 @@
"""SQLite wrapper — opens `.pql/pql.db` at the repo root, applies schema.
Discovery: walk up from CWD looking for a .git/ sibling; the repo root
hosts .pql/pql.db. If .pql/ doesn't exist, it's created on first open.
"""
from __future__ import annotations
import sqlite3
from pathlib import Path
from .schema import SCHEMA_SQL
def repo_root(start: Path | None = None) -> Path:
path = (start or Path.cwd()).resolve()
for parent in (path, *path.parents):
if (parent / ".git").exists():
return parent
raise RuntimeError(f"not inside a git repository (starting from {path})")
def db_path(root: Path | None = None) -> Path:
root = root or repo_root()
return root / ".pql" / "pql.db"
def connect(root: Path | None = None) -> sqlite3.Connection:
path = db_path(root)
path.parent.mkdir(parents=True, exist_ok=True)
conn = sqlite3.connect(path)
conn.row_factory = sqlite3.Row
conn.execute("PRAGMA foreign_keys=ON")
conn.executescript(SCHEMA_SQL)
return conn