chore(db): add decisions-orphan-tickets CLI (#887)

New `tooling/db/decision orphan-tickets` subcommand scans tickets with
a decision_ref that doesn't match any row in the decisions table.
Surfaces silently orphaned tickets from typo'd or renumbered D-IDs.
Makefile target: `make decisions-orphan-tickets`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-02 10:09:03 +02:00
co-authored by Claude Opus 4.6
parent f9fdfb7712
commit ffa638a46c
2 changed files with 38 additions and 2 deletions
+32
View File
@@ -457,6 +457,35 @@ def show_decision(cfg, decision_id):
conn.close()
def orphan_tickets(cfg):
"""List tickets whose decision_ref is set but does not match any decision in the DB."""
conn = get_connection(cfg)
try:
rows = conn.execute(
"""SELECT t.id, t.title, t.decision_ref, t.status, t.team
FROM tickets t
WHERE t.decision_ref IS NOT NULL
AND t.decision_ref != ''
AND t.decision_ref NOT IN (SELECT id FROM decisions)
ORDER BY t.decision_ref, t.id""",
).fetchall()
orphans = [dict(r) for r in rows]
return {
"ok": True,
"count": len(orphans),
"orphans": orphans,
"summary": (
f"{len(orphans)} orphan ticket(s) found"
if orphans
else "No orphan tickets — all decision_ref values are valid"
),
}
finally:
conn.close()
def check_dupes(cfg):
"""Check for duplicate decision IDs across all markdown files."""
# Pre-existing collisions too deeply embedded to renumber (139+ references).
@@ -508,6 +537,7 @@ Usage:
decisions_sync.py next [D|Q|R] Show next available ID (all prefixes or one)
decisions_sync.py claim <D|Q|R> <domain> [title] Claim next ID and insert placeholder
decisions_sync.py check-dupes Check for duplicate IDs across markdown files
decisions_sync.py orphan-tickets List tickets with invalid/missing decision_ref
decisions_sync.py --help Show this help message
ID claiming workflow:
@@ -554,6 +584,8 @@ def main():
result = claim_id(cfg, prefix, domain, title)
elif cmd == "check-dupes":
result = check_dupes(cfg)
elif cmd == "orphan-tickets":
result = orphan_tickets(cfg)
else:
result = {"ok": False, "error": f"Unknown command: {cmd}. Use --help for usage."}