Skip to content

Docs/guardrail: never hand-edit a versioned install script once it's no longer the current default_version #52

Description

@jnasbyupgrade

What happened

While fixing an unrelated comment in test_factory (jnasby/test_factory PR #20), an AI agent hand-edited the checked-in versioned install scripts directly (sql/test_factory--0.5.0.sql, sql/test_factory_pgtap--0.1.0.sql) instead of editing the base sql/<ext>.sql and letting the build regenerate them.

It turns out control.mk.sh already generates a real Make rule for this:

$(EXTENSION_<ext>_VERSION_FILE): sql/<ext>.sql <control_file>
	@echo '/* DO NOT EDIT - AUTO-GENERATED FILE */' > $(EXTENSION_<ext>_VERSION_FILE)
	@cat sql/<ext>.sql >> $(EXTENSION_<ext>_VERSION_FILE)

So the versioned file matching the current default_version is safe to regenerate (edit the base file, run make) -- but nothing in the docs states the flip side clearly: once a version is no longer the current default_version, its file is a frozen historical record (the whole point of committing per-version install scripts per #51/#42 is to test upgrade paths and PG-version compatibility of exactly what shipped). Hand-editing an old versioned file after the fact silently corrupts that record, and there's no guard (lint, CI check, or even a comment beyond the generic "DO NOT EDIT - AUTO-GENERATED FILE" header) that would catch it -- that header doesn't distinguish "auto-regenerated every build" (current version) from "was auto-generated once, now frozen" (old version).

Ask

  1. Document this explicitly (README/CLAUDE.md guidance, near the docs: explain when to track version-specific install scripts (and when not to) #51 tracking-tradeoff docs): editing the base sql/<ext>.sql + rebuilding is correct for the current default_version's file; editing any other versioned file directly is never correct -- the fix is always to bump the version and add a proper --old--new.sql upgrade script.
  2. Consider a cheap guardrail: a make or CI check (e.g. in the test/lint target) that fails if a versioned SQL file other than the current $(EXTENSION_<ext>_VERSION_FILE) differs from what's committed at the tag/release point it belongs to, or at minimum a pre-commit/CI diff check that flags modifications to any sql/*--*.sql file that isn't the current default_version's file.
  3. This is especially relevant for AI coding agents, which won't know this convention exists unless it's spelled out -- the generic "DO NOT EDIT - AUTO-GENERATED FILE" comment reads the same for both the safe-to-regenerate current file and the must-never-touch old ones.

Related: #51 (why/when to commit versioned scripts), #20 (bumping default_version post-release, which would reduce how often this ambiguity comes up in practice).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions