Skip to content

docs(dev-cycle): §4.7 expand-only + flag-gate, amend §10.5.1 triage eligibility#389

Merged
jinhongkuan merged 1 commit into
devfrom
docs/dev-cycle-expand-only-flag-gate
May 16, 2026
Merged

docs(dev-cycle): §4.7 expand-only + flag-gate, amend §10.5.1 triage eligibility#389
jinhongkuan merged 1 commit into
devfrom
docs/dev-cycle-expand-only-flag-gate

Conversation

@jinhongkuan

Copy link
Copy Markdown
Contributor

Summary

  • Adds §4.7 "Schema-touching PRs — expand-only + flag-gate" to DEV_CYCLE.md. Two complementary rules for any PR that touches ledger/schema.py or its _MIGRATIONS registry: migrations must be additive only (destructive ops live in dedicated later-release commits), and code paths that depend on new schema must be feature-flag gated default-off in prod.
  • Amends §10.5.1 to replace the blanket "schema-migrating changes are not triage-eligible" rule with "schema migrations CAN ride a triage release if they comply with §4.7." Destructive schema changes and flag-flip releases stay non-triage-eligible.

Linked issues

No tracked issue — doctrine amendment surfaced during the v0.15.0 release planning (PR #388), where the existing rule blocked a v17 → v24 migration chain from ever reaching main through triage and forced an all-or-nothing full release.

Linked decisions

Closes decision:cp25jfz1nt6h3u2gjzmu — Schema migrations must be expand-only; destructive ops live in dedicated commits.
Closes decision:adklplvfhthkdch05pe9 — Code paths depending on new schema must be feature-flag gated, default off in prod.
Closes decision:0ok1249n2tdrfud2a5j9 — DEV_CYCLE.md §10.5.1 (triage eligibility) amended: triage releases CAN carry schema migrations when (a) every migration is expand-only and (b) every feature is flag-gated.

Plan / Audit / Seal

  • Plan: doctrine-only change to docs/DEV_CYCLE.md. No code, no behavior change. Rules apply prospectively to PRs landing after this merges.
  • Audit: rationale rooted in a cross-tool research survey of migration patterns (2026-05-15) — Rails, Django, Alembic, EF Core, Flyway, Liquibase, sqlx, golang-migrate. All converge on the same answer: migration chains are append-only; the workaround is to decouple schema from features. Stripe, GitHub (gh-ost), Thoughtworks, and Harness all advocate the expand-only + flag-gate pattern this PR encodes.
  • Risk: L1 — doctrine-only, single-file change. No CI behavior change (the §4.7.1 CI lint is planned, not shipped in this PR).

Backwards compatibility with current state

  • The v0.15.0 release PR (release: v0.15.0 — PII archive, hard-delete remove_decision, schema v17→v24 chain #388) drains the existing dev → main backlog under the old rule (all-or-nothing). The v18 → v24 migration chain that PR carries was not authored under §4.7's discipline — it predates this PR. That's fine; the rules apply prospectively.
  • After this PR merges to dev, every subsequent schema-touching PR is evaluated under §4.7. The next triage release can carry expand-only migrations.

Test plan

  • markdownlint docs/DEV_CYCLE.md would catch syntax issues (not currently run in CI — verified by inspection).
  • Manual read-through to verify §4.7 cross-references (§4.7.1, §4.7.2, §4.7.3) resolve and the §10.5.1 amendment references §4.7 correctly.
  • CI lint workflow (pr-body-refs-lint.yml) checks Closes #N / Closes decision:… formatting in this PR body.

Follow-up work (not in this PR)

  • scripts/lint_schema_destructive.py — CI gate that parses ledger/schema.py diffs and flags REMOVE / breaking ALTER / tightening-ASSERT operations in any commit that also modifies non-migration code. §4.7.1 references this as planned. Separate PR with a tracked issue.
  • Audit the existing _MIGRATIONS chain on dev (v17 → v24) against §4.7.1 retrospectively — most are already additive, but the audit produces a clean baseline for future "every migration in the chain since vN complies with §4.7" claims.

🤖 Generated with Claude Code

… (triage eligibility)

Encodes the three architectural decisions ratified 2026-05-15
(decision:cp25jfz1nt6h3u2gjzmu, decision:adklplvfhthkdch05pe9,
decision:0ok1249n2tdrfud2a5j9):

§4.7 — new subsection enforcing two complementary rules for any PR
that touches ledger/schema.py or its _MIGRATIONS registry:

  §4.7.1 — schema migrations must be expand-only. Destructive operations
  (REMOVE / DROP / breaking ALTER / tightening ASSERT) live in their own
  commits and ship in a later release after the prior reader surface is
  validated as gone from prod. Includes an allowed/forbidden table for
  reviewer ease. CI lint planned via scripts/lint_schema_destructive.py.

  §4.7.2 — code paths that depend on new schema must be feature-flag
  gated and default OFF in prod (env var or .bicameral/config.yaml
  setting). Schema ships immediately; flag flips later in a separate
  release. If the experiment is killed, the flag never flips on and a
  follow-up cleanup migration drops the slot. Exception: invariant
  bugfixes (e.g. fixing a unique-index collision that breaks the
  dashboard for everyone) don't need flag-gating — that's not feature
  surface.

  §4.7.3 — concrete PR-review checklist for schema-touching PRs.

§10.5.1 — triage eligibility rule rewritten. Previously: "schema-migrating
changes are not triage-eligible" (blanket). Now: schema migrations CAN ride
a triage release if they comply with §4.7 (expand-only AND feature code is
flag-gated). The blanket ban is replaced by enumerated exclusions
(destructive schema, flag-flip releases, breaking public-API changes,
multi-PR epics, v1 patches).

Motivation: the prior rule was correct under the implicit assumption that
schema and feature ship together — then you can't ship one without the
other. Once §4.7 decouples them, schema can drain to main on every triage
instead of accumulating on dev waiting for a "real" release. The current
v18→v24 backlog (drained by the v0.15.0 release PR #388) is the symptom
the prior rule produced; this amendment prevents recurrence.

Refs decision:cp25jfz1nt6h3u2gjzmu, decision:adklplvfhthkdch05pe9, decision:0ok1249n2tdrfud2a5j9.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jinhongkuan jinhongkuan added the flow:feature Standard feature/fix PR targeting BicameralAI/dev (the default flow) label May 16, 2026
@coderabbitai

coderabbitai Bot commented May 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 82e9bdd6-814c-4029-9107-a2b0eb3d27a7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/dev-cycle-expand-only-flag-gate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@jinhongkuan jinhongkuan merged commit b11ecc0 into dev May 16, 2026
9 checks passed
@jinhongkuan jinhongkuan deleted the docs/dev-cycle-expand-only-flag-gate branch May 16, 2026 06:48
jinhongkuan pushed a commit that referenced this pull request May 16, 2026
Introduces .github/CODEOWNERS to enforce the §4.7 expand-only + flag-gate
discipline at PR time. Pairs with the dev branch-protection update
(require_code_owner_reviews: true) landed alongside.

Initial scope is minimal — only ledger/schema.py. The migration registry
(_MIGRATIONS) and SCHEMA_VERSION live in that file, so every schema-chain
change routes through Jin's review.

Caveat: @jinhongkuan-authored PRs touching ledger/schema.py will still
need a second reviewer (GitHub does not let users approve their own PRs)
or an admin override. That's the spirit of the rule — schema changes
warrant explicit second-pair-of-eyes attention regardless of author.

Refs DEV_CYCLE.md §4.4 (Reviewers) and §4.7 (Schema-touching PRs —
expand-only + flag-gate). #389 is the doctrine PR that introduces §4.7;
this PR enforces it mechanically.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flow:feature Standard feature/fix PR targeting BicameralAI/dev (the default flow)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant