Decisions and manual work
Two schema snapshots show facts, not intent. If display_name disappears while full_name appears, that could be a rename, a replacement with different meaning, or two unrelated changes. onwardpg stops and prints a fingerprinted hint.
Confirm a rename
Section titled “Confirm a rename”onwardpg plan rename-display-name \ --hint '{"kind":"rename","object":"column","from":["app","accounts","display_name"],"to":["app","accounts","full_name"]}'For an eligible same-type rename, the planner can create a temporary second column and deterministic dual-write bridge. Existing rows still need an explicit strategy: reviewed manual SQL, an acknowledged single transaction for a known-small table, or a split plan.
Change text to integer
Section titled “Change text to integer”The catalog proves the types differ. It cannot decide whether an empty string becomes NULL, fails, or maps to a product value.
ALTER TABLE app.accounts ALTER COLUMN age TYPE integer USING NULLIF(trim(age), '')::integer;Choose manual_sql for a one-deployment bridge, then replace the generated ONWARDPG TODO in the relevant phase file. Add assertions for every data-dependent assumption:
-- onwardpg:assert account_age_is_convertibleSELECT NOT EXISTS ( SELECT 1 FROM app.accounts WHERE age IS NOT NULL AND trim(age) !~ '^[0-9]+$');manual_sql hints never carry SQL. The editable file is the reviewed artifact, and its exact bytes become receipted only after clone verification succeeds.
Why decisions expire
Section titled “Why decisions expire”Answers are bound to exact source and desired graph fingerprints. If a later edit changes the participating objects, stale or unused answers fail. This prevents a previous approval for one destructive shape from silently authorizing another.