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:
@@ -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>'"
|
||||
```
|
||||
|
||||
Executable
+4
@@ -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 "$@"
|
||||
Executable
+4
@@ -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 "$@"
|
||||
Reference in New Issue
Block a user