chore(db): add sqlite-init and sqlite-seed wrappers, update ticket skill

Complete the set of whitelistable wrapper scripts so all SQLite
access goes through db/connectors/sqlite-* (query, exec, init, seed).
Update the ticket skill to reference wrappers instead of calling
sqlite_connector.py directly, making permissions allowlisting clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-11 00:04:58 +01:00
co-authored by Claude Opus 4.6
parent 5bb7ded841
commit 0ecf7b4d8b
3 changed files with 39 additions and 22 deletions
+31 -22
View File
@@ -14,42 +14,46 @@ Manage the Commonwealth project ticketing database at `db/commonwealth.db`.
## Access Method
**Always use the connector script, never the sqlite3 CLI:**
```bash
python3 db/connectors/sqlite_connector.py <command> [args]
```
**Always use the wrapper scripts, never the sqlite3 CLI or python3 directly:**
| Script | Purpose |
|--------|---------|
| `db/connectors/sqlite-query "<SQL>"` | Run SELECT queries |
| `db/connectors/sqlite-exec "<SQL>"` | Run INSERT/UPDATE/DELETE |
| `db/connectors/sqlite-init` | Create/update database from schema |
| `db/connectors/sqlite-seed` | Seed initiatives from DECISIONS.md |
## Commands
### List tickets
Show tickets filtered by status, type, or assignee:
```bash
python3 db/connectors/sqlite_connector.py query "SELECT id, type, title, status, priority, assigned_to FROM tickets WHERE status != 'cancelled' ORDER BY priority, id"
db/connectors/sqlite-query "SELECT id, type, title, status, priority, assigned_to FROM tickets WHERE status != 'cancelled' ORDER BY priority, id"
```
Filter examples:
```bash
# By status
python3 db/connectors/sqlite_connector.py query "SELECT id, type, title, status FROM tickets WHERE status='in_progress'"
db/connectors/sqlite-query "SELECT id, type, title, status FROM tickets WHERE status='in_progress'"
# By type
python3 db/connectors/sqlite_connector.py query "SELECT id, title, status FROM tickets WHERE type='initiative'"
db/connectors/sqlite-query "SELECT id, title, status FROM tickets WHERE type='initiative'"
# By assignee
python3 db/connectors/sqlite_connector.py query "SELECT id, title, status FROM tickets WHERE assigned_to='tyre'"
db/connectors/sqlite-query "SELECT id, title, status FROM tickets WHERE assigned_to='tyre'"
# Current sprint
python3 db/connectors/sqlite_connector.py query "SELECT t.id, t.title, t.status, t.assigned_to FROM tickets t JOIN sprints s ON t.sprint_id=s.id WHERE s.status='active'"
db/connectors/sqlite-query "SELECT t.id, t.title, t.status, t.assigned_to FROM tickets t JOIN sprints s ON t.sprint_id=s.id WHERE s.status='active'"
```
### Show ticket detail
```bash
python3 db/connectors/sqlite_connector.py query "SELECT * FROM tickets WHERE id=<N>"
db/connectors/sqlite-query "SELECT * FROM tickets WHERE id=<N>"
```
### Create ticket
```bash
python3 db/connectors/sqlite_connector.py execute "INSERT INTO tickets (type, title, description, priority, decision_ref, parent_id) VALUES ('<type>', '<title>', '<description>', '<priority>', '<decision_ref>', <parent_id_or_NULL>)"
db/connectors/sqlite-exec "INSERT INTO tickets (type, title, description, priority, decision_ref, parent_id) VALUES ('<type>', '<title>', '<description>', '<priority>', '<decision_ref>', <parent_id_or_NULL>)"
```
Types: `initiative`, `epic`, `story`, `task`, `bug`
@@ -58,42 +62,47 @@ Statuses: `backlog`, `ready`, `in_progress`, `review`, `done`, `cancelled`
### Update ticket
```bash
python3 db/connectors/sqlite_connector.py execute "UPDATE tickets SET status='in_progress', assigned_to='tyre', updated_at=datetime('now') WHERE id=<N>"
db/connectors/sqlite-exec "UPDATE tickets SET status='in_progress', assigned_to='tyre', updated_at=datetime('now') WHERE id=<N>"
```
### Ticket tree (parent-child hierarchy)
```bash
python3 db/connectors/sqlite_connector.py query "SELECT t.id, t.type, t.title, t.status, p.title as parent_title FROM tickets t LEFT JOIN tickets p ON t.parent_id=p.id ORDER BY COALESCE(t.parent_id, t.id), t.id"
db/connectors/sqlite-query "SELECT t.id, t.type, t.title, t.status, p.title as parent_title FROM tickets t LEFT JOIN tickets p ON t.parent_id=p.id ORDER BY COALESCE(t.parent_id, t.id), t.id"
```
### Sprint management
```bash
# Create sprint
python3 db/connectors/sqlite_connector.py execute "INSERT INTO sprints (name, goal, start_date, end_date) VALUES ('<name>', '<goal>', '<start>', '<end>')"
db/connectors/sqlite-exec "INSERT INTO sprints (name, goal, start_date, end_date) VALUES ('<name>', '<goal>', '<start>', '<end>')"
# Activate sprint
python3 db/connectors/sqlite_connector.py execute "UPDATE sprints SET status='active' WHERE id=<N>"
db/connectors/sqlite-exec "UPDATE sprints SET status='active' WHERE id=<N>"
# Assign ticket to sprint
python3 db/connectors/sqlite_connector.py execute "UPDATE tickets SET sprint_id=<sprint_id> WHERE id=<ticket_id>"
db/connectors/sqlite-exec "UPDATE tickets SET sprint_id=<sprint_id> WHERE id=<ticket_id>"
# Sprint status
python3 db/connectors/sqlite_connector.py query "SELECT s.name, s.goal, s.status, COUNT(t.id) as tickets, SUM(CASE WHEN t.status='done' THEN 1 ELSE 0 END) as done FROM sprints s LEFT JOIN tickets t ON t.sprint_id=s.id WHERE s.status='active' GROUP BY s.id"
db/connectors/sqlite-query "SELECT s.name, s.goal, s.status, COUNT(t.id) as tickets, SUM(CASE WHEN t.status='done' THEN 1 ELSE 0 END) as done FROM sprints s LEFT JOIN tickets t ON t.sprint_id=s.id WHERE s.status='active' GROUP BY s.id"
```
### Dependencies
```bash
# Add blocker
python3 db/connectors/sqlite_connector.py execute "INSERT INTO ticket_deps (blocker_id, blocked_id) VALUES (<blocker>, <blocked>)"
db/connectors/sqlite-exec "INSERT INTO ticket_deps (blocker_id, blocked_id) VALUES (<blocker>, <blocked>)"
# Show blockers for a ticket
python3 db/connectors/sqlite_connector.py query "SELECT t.id, t.title, t.status FROM ticket_deps d JOIN tickets t ON d.blocker_id=t.id WHERE d.blocked_id=<N>"
db/connectors/sqlite-query "SELECT t.id, t.title, t.status FROM ticket_deps d JOIN tickets t ON d.blocker_id=t.id WHERE d.blocked_id=<N>"
```
### Seed from decisions
To re-seed the database with initiatives from DECISIONS.md:
```bash
python3 db/connectors/sqlite_connector.py seed-decisions
db/connectors/sqlite-seed
```
### Initialise database
```bash
db/connectors/sqlite-init
```
## Workflow
@@ -109,8 +118,8 @@ python3 db/connectors/sqlite_connector.py seed-decisions
## Labels
```bash
# Add label
python3 db/connectors/sqlite_connector.py execute "INSERT INTO ticket_labels (ticket_id, label) VALUES (<id>, '<label>')"
db/connectors/sqlite-exec "INSERT INTO ticket_labels (ticket_id, label) VALUES (<id>, '<label>')"
# Find by label
python3 db/connectors/sqlite_connector.py query "SELECT t.id, t.title FROM tickets t JOIN ticket_labels l ON t.id=l.ticket_id WHERE l.label='<label>'"
db/connectors/sqlite-query "SELECT t.id, t.title FROM tickets t JOIN ticket_labels l ON t.id=l.ticket_id WHERE l.label='<label>'"
```
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
# Initialise the ticketing database from schema.sql. Whitelistable command.
# Usage: sqlite-init
exec python3 "$(dirname "$0")/sqlite_connector.py" init "$@"
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env bash
# Seed the ticketing database with initiatives from DECISIONS.md. Whitelistable command.
# Usage: sqlite-seed
exec python3 "$(dirname "$0")/sqlite_connector.py" seed-decisions "$@"