This repo uses bd (beads) for task tracking and Codex-agent coordination. Run bd prime after compaction, at session start, or when context is unclear.
Use a stable agent name for the session. If the user assigned one, use that exact name; otherwise set one before using mail:
export BD_AGENT=auditorAt the start of each turn, and before taking new work, check coordination state:
bd mail inbox --agent "$BD_AGENT"
bd list --label announcement --status open --sort updated --reverse --limit 10
bd list --assignee "$BD_AGENT" --status open,in_progress --sort updated --reverse
bd query "label=ping:$BD_AGENT AND status!=closed"
bd ready --label postgres-compat --explain --limit 20Use bd comment <id> ... for conversation on a bead. Use bd note <id> ... for durable evidence summaries such as repro commands, artifact paths, validation results, and commit hashes.
To ping another Codex agent, leave a bead comment and either assign the bead:
bd update <id> --assignee alphaor add a non-owning ping label:
bd update <id> --add-label ping:alpha
bd mail send alpha --bead <id> -s "Ping: <id>" "Please check the bead comments."When you read a ping, clear it:
bd update <id> --remove-label ping:"$BD_AGENT"Use bd mail for immediate local Codex-agent messages. Mail is local and not versioned; bead comments/notes remain the durable project record.
All work in this repository must be done directly on the main branch in the
primary checkout. Do not create feature branches, PR branches, or git worktrees
for task slices. Do not ask subagents to create isolated worktrees. Before
editing, verify git branch --show-current is main; if it is not, stop and
get onto main before implementation.
Pull requests are not part of the normal workflow. Do not open, update, or rely
on PRs for implementation, validation, review, or bead closeout unless the user
explicitly overrides this repo rule in the current turn. The required end state
is a commit on main pushed to uplinq/main.
Do not treat the generated parser/function percentages as a full PostgreSQL parity claim. They are narrow progress dials. Full parity work also needs durable plans for catalog shape/visibility, wire protocol behavior, transaction and isolation semantics, execution-engine SQL features, exact errors/SQLSTATEs/notices, and storage/replication-visible behavior.
Maintain those longer-running plans in beads, not in ad hoc chat summaries or local scratch files. For broad compatibility areas, create an epic or parent bead and split it into concrete child beads with:
- the PostgreSQL 16 behavior or client-visible contract being targeted;
- the focused repro command or artifact that proves the current gap;
- the implementation area suspected or confirmed;
- the validation gate required before the child can close, such as PostgreSQL-paired oracle tests, pgwire/client tests, dump/import harnesses, or full daemon sweeps;
- dependencies between parser/catalog/runtime/protocol/storage work when one layer blocks another.
Architectural changes are in scope when a PostgreSQL 16 compatibility gap cannot be closed safely as a local patch. In that case, capture the proposed design in the bead before implementation, link the child repro beads to it, and keep the acceptance criteria tied to client-visible PostgreSQL parity rather than internal structure alone.
Use the shared continuous test daemon instead of starting independent go test
loops. The daemon lives at scripts/continuous_go_tests.sh; all of its state is
on disk under .tmp/continuous-go-tests/ and survives a stop/start. Every
artifact described here is restart-safe — the daemon will not re-run tests
whose inputs haven't moved, even after a fresh start.
./scripts/continuous_go_tests.sh start # background watcher
./scripts/continuous_go_tests.sh status # current state + goal-summary
./scripts/continuous_go_tests.sh once # schedule a focused run
./scripts/continuous_go_tests.sh full # schedule a full sweep
./scripts/continuous_go_tests.sh stop # SIGTERM the watcher
./scripts/continuous_go_tests.sh run "<cmd>" # one-off, locked under the same artifact dirThe watcher reruns focused tests when Go files change (precision-selected
through scripts/ctgt: per-Test/per-subtest hunk intersection, AST symbol diff,
pass-cache lookup, optional coverage prefilter), and runs a full sweep
explicitly via full or scheduled with DOLTGRES_TEST_FULL_ON_START. Heavy
packages run sharded (DOLTGRES_TEST_FULL_SHARDS); focused commands fan out in
parallel up to DOLTGRES_TEST_FOCUSED_CONCURRENCY. See
scripts/PARALLELISM.md for the parallelism contract and which packages can
safely take t.Parallel().
Do not request full runs. A full sweep takes ~30+ minutes, occupies the
shared runner, and the daemon already schedules them on its own cadence
(DOLTGRES_TEST_FULL_ON_START, watcher-triggered after broad changes). Default
to once (focused) or run "<targeted go test ...>" for a specific repro —
both reuse the same pass-cache and matrix accounting so they advance
goal-summary.txt just as much as a full sweep would for the lines you
touched. Only invoke full when (a) you've completed a refactor touching code
the focused selector can't reach (build-tag-gated files, generated code,
package-level init), or (b) goal-summary.txt is stale enough that
current.tests.tsv has fewer rows than the discovered-test count and you
need a clean rebaseline. State the reason in your commit body when you do.
.tmp/continuous-go-tests/ is the shared scoreboard. The files that matter:
| File | Scope | Purpose |
|---|---|---|
status.txt |
per-run | KV: current state, kind, exit_code, started/ended timestamps, paths to per-run artifacts. Read this first. |
goal-summary.txt |
cumulative | KV: regression + coverage rollups (see "Stats" below). The primary signal for agents working the Postgres 16 audit goal. |
current.tests.tsv |
cumulative | TSV <pkg>\t<test>\t<status> for every test the daemon has observed. The backlog/triage source of truth. |
current.by-package.tsv |
cumulative | TSV <pkg>\t<pass>\t<fail>\t<skip> aggregated from current.tests.tsv. Used to recompute goal-summary.txt. |
latest-<kind>.summary.txt |
per-run | Regression-only leaf counts for the most recent full/focused/requested run. Excludes testing/generation/*. |
latest-<kind>.failure-leaves.tsv |
per-run | Regression-only failure leaves from the most recent run. |
latest-<kind>.failures.txt |
per-run | Raw Action:"fail" JSON lines (regression-only). |
latest-<kind>.json |
per-run | The full go test -json stream from the most recent run. |
latest-<kind>.commands.sh |
per-run | The exact commands the run executed (audit + reproduction). |
pending-{full,focused}.request |
queue | Flag files; presence = a run of that kind is queued. The daemon dedupes at the kind level. |
symbols.idx |
cumulative | JSON reverse-index used by ctgt symbols to compute precision selection. |
pass-cache.tsv |
cumulative | TSV pass-cache so a tested-and-passing combination is not re-run unless its input hash moves. |
coverage.idx |
cumulative | Per-line coverage index from any full run that used DOLTGRES_TEST_COVERAGE=1. |
Per-run artifacts are frozen snapshots; cumulative artifacts are the rolling state agents should triage against.
schema_version: 2
regression_tests_passed: …
regression_tests_failed: …
regression_tests_total: …
regression_tests_pass_percent: …
regression_tests_skipped: …
coverage_tests_passed: …
coverage_tests_failed: …
coverage_tests_total: …
coverage_tests_pass_percent: …
coverage_tests_skipped: …
parser_accept_passed: …
parser_accept_total: …
parser_accept_percent: …
function_accuracy_passed: …
function_accuracy_total: …
function_accuracy_percent: …
matrix_converts_count: …
matrix_parses_count: …
matrix_unimplemented_count: …
matrix_total: …
matrix_converts_percent: …
matrix_parses_percent: …
matrix_unimplemented_percent: …
matrix_parser_surface_percent: … # = (matrix_converts + matrix_parses) / matrix_total
Three categories of signal — read all three before deciding where to work:
(1) Regression alarm. regression_* keys cover every package outside
testing/generation/. regression_tests_failed must be 0. Non-zero is a
P0: a real assertion test regressed and must be fixed before continuing audit
work.
(2) Assertion-agreement (NOT coverage). parser_accept_*,
function_accuracy_*, and coverage_tests_* measure whether the matrix's
expectations still match the implementation's behavior. A subtest tagged
Unimplemented("FOO") passes when the parser still rejects FOO — the
test agrees with the tag. So parser_accept_percent: 100% does not mean
"parser accepts all of Postgres 16"; it means "every assertion is in sync."
A test fails when the implementation has moved ahead of its tag (the
framework reports "please upgrade to Parses / Converts"). Promotion
failures are good news — they say doltgres got better than the matrix
expected. Re-run the generator to absorb them (see below).
(3) Real Postgres-surface coverage. The matrix_*_count keys break the
testing/generation/command_docs/output matrix's ~394k SQL-grammar variants
into three tiers — this is the actual coverage view and the primary
triage source for parser/AST audit work:
matrix_converts_count— parser accepts ANDast.Convertsucceeds.matrix_parses_count— parser accepts; AST converter doesn't lower it yet.matrix_unimplemented_count— parser rejects the variant entirely.
matrix_parser_surface_percent = (converts + parses) / total is the share
of Postgres 16 grammar variants doltgres parses at all. Every entry in
matrix_unimplemented_count is a discrete grammar variant doltgres
doesn't support yet; every entry in matrix_parses_count is one whose
AST-conversion layer is the gap. Both are work items.
function_accuracy_* covers
testing/generation/function_coverage/output — declared functions whose
runtime output matches the Postgres oracle. function_accuracy_percent < 100
means functions diverging from Postgres; missing functions (Postgres
implements them, doltgres doesn't) aren't measured here at all.
testing/generation/ contains two auto-generated coverage matrices,
regenerated from raw Postgres reference material by:
go run ./testing/generation/command_docs # requires local Postgres 16 at localhost:5432
go run ./testing/generation/function_coverage # generates from declared function frameworkRun the regenerator after landing parser/AST work. It re-probes every
synopsis variant against the current parser + AST converter and rewrites
each subtest's tag (Unimplemented / Parses / Converts) to match
what the implementation actually does today. That snaps matrix_*_count
in goal-summary.txt to truth, makes the dashboard tiles honest, and
absorbs the "please upgrade the type" framework failures into clean
passes. Commit the regenerated matrix files alongside the
implementation change.
testing/generation/command_docs/output/(~184 test files, ~394k subtests). Every concrete SQL string that Postgres 16's official grammar synopses produce. Cases are taggedUnimplemented(...),Parses(...), orConverts(...)after probingparser.Parseandast.Convert. A passing subtest means the tag still matches current behavior. A failing subtest usually means doltgres improved and the tag should be promoted. The actual support backlog is thematrix_unimplemented_countandmatrix_parses_countbreakdown ingoal-summary.txt.testing/generation/function_coverage/output/(~73 test files, ~6,070 subtests). Every declared SQL function, invoked viaSELECT fn(args)against the in-memory doltgres server, compared against the cached Postgres oracle. A failure means doltgres's runtime answer diverges from Postgres 16's. Reported asfunction_accuracy_*ingoal-summary.txt.
In short: command-doc tags are the parser/AST TODO list; command-doc test failures are usually stale tags that need regeneration. Function-coverage failures are runtime mismatches against the Postgres oracle.
-
Triage in this order before picking a task:
- Read
regression_tests_failed. If non-zero, that's the only thing to work on — fix any real regression first. - Read
matrix_unimplemented_countandmatrix_parses_count. Those are the audit backlog. Their ratio tells you whether the parser or the AST-converter is the dominant gap right now. - Read
function_accuracy_passed/total. Mismatched functions are usually quick targeted wins.
- Read
-
Pick a concrete work item. Use the matrix tier signal to decide which failures to triage, then drill into individual subtests:
-
Parser-gate work (
matrix_unimplemented_countis high). Look attesting/generation/command_docs/output/*_test.gofiles and grep forUnimplemented(". The literal string is the SQL the parser needs to accept. Best targets are commands with the mostUnimplementedentries.for f in testing/generation/command_docs/output/*_test.go; do n=$(grep -c '^[[:space:]]*Unimplemented("' "$f") [ "$n" -gt 0 ] && printf '%6d %s\n' "$n" "$f" done | sort -rn | head -20
-
AST-conversion work (
matrix_parses_countis high). Same files, grep forParses(". Those are SQL the parser accepts but the server/ast/ converter doesn't lower. -
Function-accuracy work. Re-run the function-coverage matrix and read failure leaves:
awk -F'\t' '$1 ~ /\/testing\/generation\/function_coverage\// && $3 == "fail"' \ .tmp/continuous-go-tests/current.tests.tsv
-
Catalog/runtime work (not measured by matrices). The repro suite at
testing/go/postgres16/has hand-curated failures; filter for the fail status under that package as a starting point.
-
-
Apply red-green-refactor for each fix:
a. Red. Pick a failing coverage entry. The matrices are passive observers; the actual proof is a focused regression test. Write or update one in the appropriate regression suite (typically
testing/go/postgres16/...) and verify it fails.b. Green. Implement the smallest correct change. Run the focused suite and confirm the new test passes:
./scripts/continuous_go_tests.sh once # …or run a specific test via the shared runner: ./scripts/continuous_go_tests.sh run "go test -json -vet=off \ ./testing/go/postgres16 -run '^(TestYourRepro)$' -count=1 -timeout=20m"
Watch
.tmp/continuous-go-tests/status.txtforstate: pass.c. Refactor / promote. Read the current
goal-summary.txt(the daemon keeps it cumulative across focused runs — you do not need a full sweep) and confirm:regression_tests_failedis still 0.parser_accept_percentand/orfunction_accuracy_percentmoved up.
If a
Parses(...)case intesting/generation/command_docs/output/is now also passing AST conversion, promote it toConverts(...)(orUnimplemented(...)→Parses(...)). Verify the promotion before committing it — a passing subtest is not sufficient evidence. The matrix subtests are agreement assertions, not coverage probes: a subtest taggedParses(...)passes whenever the parser accepts and the AST converter still refuses, so promoting it toConverts(...)by hand based on a green test will introduce a silent regression that only surfaces when the generator is next re-run. Acceptable proofs of a real promotion, in order of preference:1. **Re-run the regenerator for the affected command** (preferred): `go run ./testing/generation/command_docs` rewrites the tag with live probe results. Commit the regenerated file as-is. 2. **Targeted converter probe**: write or update a focused postgres16 repro that exercises `ast.Convert` on the exact string from the matrix entry and asserts a non-nil, non-error lowering — *not* just that the parser accepts it. Then promote the tag and commit.Never hand-promote
Parses → Convertsbased solely on a greenParses(...)subtest. Audits of the matrix have shown thousands of such promotions getting reverted on the next regenerator run.Promotion-proof enforcement lives in
scripts/check_promote_provenance.sh. Install the local pre-push hook once with./scripts/install-hooks.sh; it setscore.hooksPathto.githooksand checks the commits that a push would land. TheCheck Matrix Promotion Provenance / Promotion provenanceGitHub status must also be required for direct pushes tomainin branch protection. Valid proof is a generator change, a commit message that references a.tmp/continuous-go-tests/*-requested.summary.txtartifact, or a modifiedtesting/go/postgres16/*.gorepro containing the exact promoted SQL string. A modifiedserver/ast/*_test.goconverter test is valid proof for its matching command-doc output file when it contains at least one promoted SQL variant from that file.d. Commit on
mainand push direct touplinq/main. Work must stay on themainbranch in the primary checkout. Do not create feature branches, PR branches, or git worktrees for task slices, and do not use PRs as a validation or delivery path. The pre-push hook is the mechanical quality gate. Install it once with./scripts/install-hooks.sh(setscore.hooksPathto.githooks). The hook runs, in order, before every push:1. `check_promote_provenance.sh` — same matrix-promotion check that used to gate CI. 2. `check_fmt.sh` — goimports + import-group rules. 3. `go vet -unsafeptr=false ./...` — catches misuses that the old CI was supposed to catch. 4. **When pushing to `main`**, also reads `.tmp/continuous-go-tests/goal-summary.txt` and rejects the push if `regression_tests_failed > 0`. Set `DOLTGRES_SKIP_REGRESSION=1` only if your push is itself the fix for the red board.Bypass envs exist (
DOLTGRES_SKIP_FMT,DOLTGRES_SKIP_VET,DOLTGRES_SKIP_PROVENANCE,DOLTGRES_SKIP_REGRESSION, and the nuclearDOLTGRES_SKIP_ALL). Each is intentionally noisy — they stay the exception. Do not chain bypasses to "just get the push through"; the gate exists because the alternative (red main blocks everyone else's pre-push) is worse.e. Push to
uplinq/mainis a precondition forbd close. This is the load-bearing rule of the main-only workflow: a closed bead must cite a SHA that is an ancestor ofuplinq/main, no exceptions. Commit on localmain, push localmaintouplinq/main, and verify the landed commit beforebd close. Do not close beads unless the push has succeeded:git push uplinq main:main git fetch uplinq main --prune git merge-base --is-ancestor <commit-sha> uplinq/main ./scripts/check_bead_close.sh --require-commit <bead-id> ./scripts/bd-close <bead-id> --reason "<landed-sha>: <summary>"
Record the landed commit SHA, focused validation artifacts, and pre-push hook output in
bd note <id> ...; then close the bead through./scripts/bd-close <id> --reason "..."with a close reason that quotes the SHA fromuplinq/main. Ifcheck_bead_close.shorbd-closefails, your push has not landed yet — do not close the bead. If you cannot push (red regression board, hook rejected, etc.), keep the bead open and add abd notewith the blocker; reassign or set--priorityas appropriate.bd close --forceremains available through the wrapper for stale cleanup, but it prints a bypass warning and should not be used for normal completed work. -
Prioritize parser before function. A failure in
command_docs/output(parser_accept_*) blocks downstream behavior — if the parser refusesWITH ORDINALITY, nofunction_coveragetest that depends on it can succeed even with correct runtime semantics. Lifting parser-accept usually unblocks function-accuracy work in bulk. -
Cumulative > per-run for triage.
current.tests.tsvandgoal-summary.txtreflect the rolling state across every focused + full run the daemon has executed.latest-<kind>.summary.txtis per-run and excludestesting/generation/. For audit work, the cumulative files are the source of truth.
Create or update beads for daemon failure rows so other agents can pick them
up. Use bd (see "Issue Tracking And Coordination" above) — coverage
failures translate naturally into beads since each row is a discrete
work item with an exact reproduction recipe.
For explicit bead validation, run the command through the shared runner
instead of starting go test directly:
./scripts/continuous_go_tests.sh run "go test -json -vet=off \
./testing/go/postgres16 -run '^(TestShellTypes)$' -count=1 -timeout=20m"Do not append new coordination lanes to coop.md; it is historical only.
Create or update beads instead, and commit both code changes and bead
database changes for completed slices.