Skip to content

Latest commit

 

History

History
440 lines (361 loc) · 21.7 KB

File metadata and controls

440 lines (361 loc) · 21.7 KB

Issue Tracking And Coordination

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=auditor

At 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 20

Use 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 alpha

or 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.

Main-Only Workflow

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.

Long-Term Compatibility Planning

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.

Continuous Go Test Daemon

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.

Lifecycle

./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 dir

The 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.

On-disk artifacts agents read

.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.

Stats in goal-summary.txt

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 AND ast.Convert succeeds.
  • 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/* — what it is, how to use it

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 framework

Run 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 tagged Unimplemented(...), Parses(...), or Converts(...) after probing parser.Parse and ast.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 the matrix_unimplemented_count and matrix_parses_count breakdown in goal-summary.txt.
  • testing/generation/function_coverage/output/ (~73 test files, ~6,070 subtests). Every declared SQL function, invoked via SELECT 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 as function_accuracy_* in goal-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.

Goal-driven workflow

  1. 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_count and matrix_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.
  2. 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_count is high). Look at testing/generation/command_docs/output/*_test.go files and grep for Unimplemented(". The literal string is the SQL the parser needs to accept. Best targets are commands with the most Unimplemented entries.

      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_count is high). Same files, grep for Parses(". 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.

  3. 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.txt for state: 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_failed is still 0.
    • parser_accept_percent and/or function_accuracy_percent moved up.

    If a Parses(...) case in testing/generation/command_docs/output/ is now also passing AST conversion, promote it to Converts(...) (or Unimplemented(...)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 tagged Parses(...) passes whenever the parser accepts and the AST converter still refuses, so promoting it to Converts(...) 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 → Converts based solely on a green Parses(...) 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 sets core.hooksPath to .githooks and checks the commits that a push would land. The Check Matrix Promotion Provenance / Promotion provenance GitHub status must also be required for direct pushes to main in branch protection. Valid proof is a generator change, a commit message that references a .tmp/continuous-go-tests/*-requested.summary.txt artifact, or a modified testing/go/postgres16/*.go repro containing the exact promoted SQL string. A modified server/ast/*_test.go converter 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 main and push direct to uplinq/main. Work must stay on the main branch 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 (sets core.hooksPath to .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 nuclear DOLTGRES_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/main is a precondition for bd close. This is the load-bearing rule of the main-only workflow: a closed bead must cite a SHA that is an ancestor of uplinq/main, no exceptions. Commit on local main, push local main to uplinq/main, and verify the landed commit before bd 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 from uplinq/main. If check_bead_close.sh or bd-close fails, 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 a bd note with the blocker; reassign or set --priority as appropriate. bd close --force remains available through the wrapper for stale cleanup, but it prints a bypass warning and should not be used for normal completed work.

  4. Prioritize parser before function. A failure in command_docs/output (parser_accept_*) blocks downstream behavior — if the parser refuses WITH ORDINALITY, no function_coverage test that depends on it can succeed even with correct runtime semantics. Lifting parser-accept usually unblocks function-accuracy work in bulk.

  5. Cumulative > per-run for triage. current.tests.tsv and goal-summary.txt reflect the rolling state across every focused + full run the daemon has executed. latest-<kind>.summary.txt is per-run and excludes testing/generation/. For audit work, the cumulative files are the source of truth.

Tracking work with beads

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.