KB-7501
Lifecycle DDL Ratification · 02 Repo Placement Decision
6 min read Revision 1
dot-iu-cutterv0.5lifecycle-ddl-ratificationrepo-placementg2-passdieu442026-05-20
dot-iu-cutter v0.5 — Lifecycle DDL Ratification · Repo Placement Decision
doc 2 of 6 · 2026-05-20
phase : G2 — least-surprising location for operator-runbook SQL outcome : sql/lifecycle/ (new top-level dir) — PASS
1. Discovery — what already exists in the repo
repo : /Users/nmhuyen/iu-cutter-build/repo/iu-cutter
head_pre_commit : 32cfa93 (main = feature, both pointed at 32cfa93)
existing_top_level :
- README.md
- cli.py
- constitution-normalized-17660443e0f23e99.md (data; source snapshot)
- cutter_agent/ (Python package)
- tests/ (Python regression)
- .gitignore (ignores __pycache__/*.pyc)
existing_sql_dirs : NONE (`find -type d \( -name sql -o -name ddl -o
-name migrations -o -name runbooks -o
-name specs -o -name schema \)` returned 0)
existing_sql_files : NONE (`find -name '*.sql'` returned 0)
migration_framework : NONE (no Alembic/Flyway/sqlx-migrate/django-migrations)
README_doctrine : "DRY-RUN-SAFE SKELETON ONLY. No production DB connection."
2. Options considered
OPT_P1_new_top_level_sql_lifecycle:
path : sql/lifecycle/
pros :
- clearly separated from Python (cutter_agent/) so no auto-apply temptation
- top-level visibility for operators
- room for future sql/governance/ or sql/cutter_governance/ siblings
- matches README's "skeleton, not auto-applied" doctrine
cons :
- new top-level dir; minor repo churn
recommended: YES
OPT_P2_inside_cutter_agent:
path : cutter_agent/sql/lifecycle/
pros : co-located with Python module that conceptually owns it
cons :
- cutter_agent/ is a Python package; import-time scans might find .sql
- operator runbook = NOT application code; mixing roles is confusing
- README states Python module does NOT connect to production
recommended: NO
OPT_P3_inside_tests_fixtures:
path : tests/fixtures/sql/
pros : single existing data-ish folder; minimal churn
cons :
- "fixtures" implies test-only data, not an operator runbook
- would confuse anyone running `pytest --collect-only`
recommended: NO
OPT_P4_inside_specs_or_runbooks:
path : specs/ or runbooks/
pros : explicit "runbook" naming
cons :
- neither directory exists; creating them adds top-level dir anyway
- "specs" suggests an unimplemented design; this is the opposite
- "runbooks" is unspecific (operator runbooks for what?)
recommended: NO (P1 is more descriptive)
3. Decision
chosen : OPT_P1 — sql/lifecycle/
rationale :
- LOWEST surprise: top-level `sql/` is the canonical convention for
SQL artefacts in mixed-language repos; `lifecycle/` scopes the
M3a substrate without claiming all-future-SQL territory
- MOST honest: name reflects role (operator runbook), not pretends
to be a migration framework
- MOST extensible: leaves room for sql/governance/ etc. without
re-organizing
- MOST isolated: Python code in cutter_agent/ cannot accidentally
import or auto-execute these files
4. Inner layout (chosen)
sql/lifecycle/
├── README.md operator usage + warnings
├── bundle_a_vocab_and_log.sql TXN-1
├── bundle_b_immutability.sql TXN-2
├── bundle_c_fn_iu_enact.sql TXN-3
├── bundle_d_gateway_and_grants.sql TXN-4
├── bundle_e_fn_iu_apply_edit_draft_patch.sql TXN-5
├── verify_preflight.sql pre-apply absence probes
├── verify_postapply.sql post-apply presence probes
├── verify_behavioral_probes.sql B-1..B-8 ROLLBACK-only
├── rollback_runbook.sql reverse order + safety
└── fingerprints.yaml md5 / count pins
Naming conventions:
bundle_<letter>_<short_name>.sql— apply-order is encoded in the letter, matching the M3a-retry TXN sequence.verify_<phase>.sql— explicit "what phase to run this in" prefix.rollback_runbook.sql— singular file because rollback is one operator decision, not five.fingerprints.yaml— machine-readable manifest; consumed by future audit macros.README.md— first thing an operator reads; the WARNING block lives at the top so it cannot be missed.
5. No duplication
duplicate_check :
KB authoring docs (v0.5-lifecycle-enactment-implementation-authoring/)
are NOT mirrored verbatim into the repo. The repo SQL contains only the
ratified live bodies; the authoring docs remain the design narrative.
KB_role : design intent + authoring decisions
repo_role : reproducible bytes
SSOT_for_apply : repo SQL files + fingerprints.yaml
SSOT_for_why : KB authoring docs
6. Forbidden actions baked into the layout
no_auto_apply_hook :
- .gitignore does NOT reference sql/
- no setup.py / pyproject.toml entry point reads sql/
- no CI workflow in repo (repo has no .github/ tree)
- Python tests intentionally do NOT import or read sql/
no_silent_drift :
- fingerprints.yaml pins md5(prosrc) for every function
- verify_postapply.sql asserts the same md5s after apply
- any future edit to bundle bodies must update fingerprints.yaml +
cross-reference the M3a-retry KB trail (drift would invalidate the
runbook's promise)
7. Gate disposition
G2_repo_layout_discovered : PASS
G2_no_existing_SQL_directory_found : PASS
G2_least_surprising_location_chosen : PASS (sql/lifecycle/)
G2_no_duplication_introduced : PASS
G2_no_auto_apply_wiring : PASS (operator-runbook semantics
enforced by layout)
8. STOP
Repo placement decided. Proceed to doc 03 (runbook artefact summary).