Skip to content

Agent feedback: schema introspection, static check, error codes, docs - #3

Merged
heryr merged 8 commits into
mainfrom
feat/agent-feedback
Jul 24, 2026
Merged

Agent feedback: schema introspection, static check, error codes, docs#3
heryr merged 8 commits into
mainfrom
feat/agent-feedback

Conversation

@heryr

@heryr heryr commented Jul 23, 2026

Copy link
Copy Markdown
Member

Implements the 8 friction points reported by an agent session that exercised miiigrate on a real workload (table creation + column reordering). One commit per point, most-severe first. Core behaviors (monotonic scaffolding, atomicity, checksums, codegen_on_up) needed no change — everything here is observability and ergonomics at the edges.

Features

  • migrate::schema — read-only structured report of the live schema: ordered columns with defaults, primary keys, foreign keys (multi-column pairs via pg_constraint + unnest … WITH ORDINALITY), indexes, triggers, Postgres enums. Optional { table } filter. Ends the era of hand-written information_schema queries through the CLI.
  • migrate::check — static validation of pending migrations (same splitter as migrate::up, empty files, naming scheme, checksum drift) without executing any SQL. Lists every problem at once; degrades to static-only when the database worker is down (db_checked: false).
  • SQLSTATE surfaced — database errors now name the driver-native code in the message (db error (SQLSTATE 42703)) instead of burying it in the raw body.
  • Structured future_dated — status entries carry { name, applied, hint } with the remediation spelled out (breaking, 0.x).

Docs & skill

  • Canonical Postgres table-recreate recipe (incoming FKs, sequence OWNED BY, indexes, triggers checklist).
  • Skill: database::query is read-only (SQLSTATE 25006); future_dated never blocks (create is monotonic); check-before-apply and schema-verification flows.
  • README: payload-quoting tips for the iii CLI (no native @file/stdin).

Validation

  • cargo fmt --check, clippy --all-targets -- -D warnings, 67 tests (new fixture suites for the pg/sqlite schema pipelines) — green on every commit.
  • E2E against the iii-postgres Docker bench, built from this branch: migrate::schema matches the real events/reservations/users schema (FK CASCADE, aggregated trigger events, tracking table excluded); migrate::check correctly reports stray names, unsplittable files, and future-dated hints; a deliberate duplicate-column migration fails with … (SQLSTATE 42701); full smoke test green.

heryr added 8 commits July 23, 2026 16:23
The database worker reports the driver-native code (inner_code — the
Postgres SQLSTATE, or the SQLite extended result code) but it was buried
inside the raw error body, invisible unless the caller dug into
database_error. Extract it once at error construction and suffix the
message — 'db error (SQLSTATE 42703)' — so every path (MIGRATION_FAILED,
config errors, logs) names the actual cause. The full structured body is
still attached unchanged.
migrate::status flagged future-dated files but left the caller to work out
what to do, and the answer depends on the state: an applied file is
harmless (it expires once the clock catches up), a pending one breaks
ordering and should be re-scaffolded. Each entry now carries { name,
applied, hint } with the remediation spelled out. Breaking (0.x): the
field was a list of bare names.
Forward-only migrations cannot be rolled back, yet the first feedback on a
hand-written file used to arrive while it was being applied. migrate::check
answers 'would migrate::up succeed?' without executing any SQL: same
statement splitter, empty-file detection, naming scheme, checksum drift.
It reports every problem at once (new migrations::scan_migrations keeps
collecting past invalid names; list_migrations keeps its fail-fast
contract), and stays useful while the database worker is down —
db_checked: false marks the drift lists as unknown.
Verifying a migration's effect (column order, foreign keys, triggers) used
to mean hand-writing information_schema/pg_catalog queries through the CLI
— exactly where quoting mistakes happen. The worker already introspects for
codegen; this exposes a full structured report instead: ordered columns
with defaults, primary keys, foreign keys (paired column-by-column via
pg_constraint + unnest WITH ORDINALITY — information_schema cannot express
multi-column pairings), indexes, triggers, and Postgres enums. SQLite goes
through the pragma functions. Pure rows-to-report pipeline, fixture-tested
without a database; optional { table } filter; tracking table excluded.
Reordering columns or making an incompatible type change on Postgres means
recreating the table, and the dangerous part is not the DDL — it is the
objects attached to the old table that die silently with DROP TABLE:
incoming foreign keys, the serial sequence (OWNED BY), indexes, triggers,
defaults. Canonical single-migration example plus the checklist, mirroring
the existing SQLite recreate recipe; verify with migrate::schema.
Discovered by agents through a live SQLSTATE 25006 — one Boundaries line
saves that round-trip every session: reads via database::query, ad-hoc
writes via database::execute or database::transaction.
The rule said 'resolve future_dated entries' without saying how, and a
careful agent can stall on an anomaly that is already handled: create's
timestamps are monotonic, so scaffolding as usual lands after any
future-dated file. Spell out both cases (applied: harmless; pending:
just use migrate::create), consistent with the status hints.
The only real failures of the feedback session were shell-quoting
accidents: SQL with single quotes inlined into --json '…'. The iii CLI has
no @file/stdin form, so document the two escape hatches — read the JSON
from a file with --json "$(cat …)", and key=value pairs for scalar
fields.
@heryr
heryr merged commit 6bea993 into main Jul 24, 2026
5 checks passed
@heryr
heryr deleted the feat/agent-feedback branch July 24, 2026 08:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant