Three analysis docs that were loose at the repo root: the 2026-05-26 codebase cleanliness audit, the dogfood self-analysis of whether Claude can work inside clide, and the pql improvement notes for upstream. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7.1 KiB
pql — improvement notes from a live session
Feedback for postmeridiem/pql, gathered
while using pql as the planning backend for the clide repo. Everything below
was observed first-hand, not inferred from docs.
Environment
- pql
1.5.0, commitab191fb, schema_version 1 (binary), DB schema_version 2. - Consumer: a single-dev repo using pql for decisions + tickets, with pql's
installed git hooks (
.pql/hooks/post-checkout,post-merge,post-rewrite,pre-commit) and a git-tracked.pql/changelog/+.pql/pql-plan.json.
The core is genuinely good — structural queries, the decision/ticket model, exit codes, and the changelog-as-source-of-truth idea all worked. The notes below are where it bit us or surprised us, roughly in priority order.
1. CRITICAL — ticket mutations aren't persisted, and rebuild-on-checkout silently destroys them
Observed. pql ticket new (and ticket status / ticket block) write only to
.pql/pql.db, which is gitignored. Nothing writes through to the git-tracked
.pql/changelog/ automatically. Separately, pql's installed post-checkout and
post-merge hooks run pql plan rebuild, which replays the committed
changelog and overwrites pql.db.
The two facts combine into silent data loss:
- Created an 18-ticket tree (an initiative + 4 epics + tasks, with blockers and
decision refs) via a series of
pql ticket newcalls. Verified present inpql ticket list. - A routine
git checkoutfiredpost-checkout→pql plan rebuild→pql.dbwas rebuilt from the changelog, which still ended at the previous max ticket. - All 18 tickets were gone. No warning, no prompt.
Impact. Total, silent loss of un-exported planning work on an ordinary git operation. The user did nothing wrong — they switched branches.
Repro.
pql ticket new task "scratch ticket" # lands in pql.db only
git checkout -b somebranch # post-checkout runs `pql plan rebuild`
pql ticket list | grep "scratch" # gone
Suggested fixes (any one closes the hole; (a) is the principled one):
- (a) Write-through. Have ticket/decision mutations append to the changelog
at mutation time, making the changelog the log of record and
pql.dba derived cache. Then rebuild is always safe. - (b) Divergence guard.
pql plan rebuild(and the hooks that call it) should detect whenpql.dbholds rows not represented in the changelog and refuse or loudly warn instead of overwriting — e.g. "pql.db has 18 un-exported rows; runpql plan exportfirst, or pass --force." - (c) Non-destructive rebuild. Merge the changelog into
pql.dbrather than replacing it.
At an absolute minimum, the post-checkout/post-merge hooks should not
discard local state without a word.
2. pql plan export writes the changelog, but docs/help say it writes a JSON snapshot
Observed. pql plan export wrote:
{"files_written":[".pql/changelog/ticket_deps/2026-06.sql",
".pql/changelog/tickets/2026-06.sql"],"rows_written":23}
It did not touch .pql/pql-plan.json, which stayed frozen at an older date
across every mutation and export this session. But the --help text and the
bundled skill both describe export as "Snapshot planning state to JSON (default:
pql-plan.json)" and recommend committing pql-plan.json.
Impact. Users (and the bundled skill) commit pql-plan.json believing it is
the durable artifact. It is stale. The actually-durable artifact is the
changelog. This directly compounds #1 — people think they've versioned their
planning state when they haven't.
Suggested fix. Make --help, docs, and the embedded skill match real
behavior. Clarify the role of pql-plan.json vs .pql/changelog/: is the JSON
snapshot deprecated in favor of the changelog? If both exist, document which one
pql plan import / pql plan rebuild prefer.
3. Schema upgrade is a hard break requiring multi-step manual recovery
Observed. After a pql binary upgrade, every planning command failed:
$ pql decisions sync
planning: decision_refs.created_at missing — pql.db is from an earlier schema.
$ pql plan status
planning: decisions.created_at missing — pql.db is from an earlier schema.
(exit 69). Recovery was manual and multi-step: delete pql.db, pql plan rebuild, then pql decisions sync.
Impact. All planning surfaces are dead until the user performs a manual
recovery they have to read out of the error text. Easy to get wrong (the error
also offers a --legacy pql-plan.json path — see #4).
Suggested fix. Auto-migrate the schema on open (additive column adds are
cheap), or ship a single pql plan repair / pql migrate command that performs
the safe delete-rebuild-sync sequence (with a backup of the old DB).
4. Schema-error recovery hint can point at the stale snapshot
Observed. The schema error (see #3) lists recovery options including
pql plan import --legacy .pql/pql-plan.json. Given #2 (that file is stale), a
user following that branch restores an out-of-date snapshot. The correct path
was the changelog rebuild.
Suggested fix. In the recovery list, prefer/recommend pql plan rebuild when
.pql/changelog/ is present, and annotate the pql-plan.json option as
potentially stale.
5. Scripting ergonomics — no id-only output from pql ticket new
Observed. Building a ticket tree means capturing each created ticket's id to
use as the next call's --parent/blocker. pql ticket new emits the full ticket
JSON, so a creation script must parse .id out of every call.
Suggested fix. A --quiet / --id-only (or -o id) flag that prints just
the new T-NNN, so tree-creation scripts stay simple. (Determinism is already a
strength: re-running the same new calls in order against a clean baseline
reproduces the same ids — which is what let us recover from #1.)
6. Minor — bundled skill assumes binary features the installed version lacks
Observed. The bundled pql skill documents pql ticket show --tree,
--leaf, --unblocked, --under, and pql ticket append (annotated "pql ≥
1.6.0"). The installed binary reports 1.5.0 as current (pql doctor /
pql skill status), and rejects them:
$ pql ticket show T-65 --tree
unknown flag: --tree # exit 64
Impact. A consumer following the skill hits unknown-flag errors and has to
discover the 1.5.0 fallbacks (--with-children, --with-blockers) by trial.
Suggested fix. Keep the embedded skill's documented surface in lockstep with
the binary it ships alongside, or have pql skill install stamp/gate
version-specific sections so the skill never advertises flags the paired binary
doesn't have.
Summary
The one that matters most is #1 — a routine git checkout can silently erase
planning work because mutations live only in a gitignored DB and the
pql-installed hooks rebuild that DB destructively. #2 makes it worse by
pointing users at the wrong file to commit. Fixing write-through (or a divergence
guard) plus aligning the export docs would remove a whole class of "where did my
tickets go" incidents.