Skip to content

Commit 8d4eb55

Browse files
adamatdevopsclaude
andauthored
docs(changelog): backfill PR #67 SHA reference for AB-037C entry (#68)
Claude-Session: https://claude.ai/code/session_01CuLBcBaRt4kS2WhFZgnaf8 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 1cc6d7e commit 8d4eb55

1 file changed

Lines changed: 1 addition & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
### Added
1313

14-
- **AB-037C Alembic drift enforcement CI gate** — closes the Alembic drift initiative (AB-037A/B/C series) by adding an ongoing gate that prevents the F1-F6 drift class from silently re-landing. New step in `.github/workflows/ci.yml` `test-backend` job, inserted between "Install dependencies" and "Run tests": runs `alembic upgrade head` (proves migrations apply cleanly against a fresh PG — the same `postgres:14` service the job already provisions) followed by `alembic check` (proves SQLAlchemy models match the head schema via env.py's `compare_server_default=True` + `compare_type=True` flags set in AB-037B). The step is placed BEFORE the pytest run deliberately so a migration or drift failure surfaces early with a clear cause rather than manifesting as a downstream test failure. `DATABASE_URL` env var is set explicitly on the step (GitHub Actions steps do not inherit each other's env). Root cause the gate addresses: F1 (actions.metadata rename), F4 (users.email index), F5 (6 ENUM values_callable drift), F6 (refresh_tokens.token_hash type + unique), F3 (14 missing index=True), and F7 (33 server_default drift) all landed in the repo undetected because CI provisioned PostgreSQL but never asked "does `alembic upgrade head` produce a schema matching the models against PG?" — pytest ran against SQLite `:memory:` (see conftest.py) which silently accepted PG ENUM/JSONB/ARRAY types as untyped columns. What this PR does NOT do: switch `src/backend/tests/conftest.py` from SQLite to PG + Alembic migrations. That optional AB-037C scope carve-out was spun out to AB-038 to keep this PR tactically small — conftest rewrite would risk breaking every backend test on dialect differences (case sensitivity, JSONB comparisons, ENUM binding) and needs its own PR with a per-test transaction-rollback isolation redesign; the `alembic check` gate already covers the model↔migration drift class that AB-037A/B fixed, and AB-038 exists to also catch migration↔runtime-behavior drift. Post-merge manual verification (AC #3-#4 — not blocking closure): introduce a deliberate model-column addition without a migration in a test PR, confirm CI catches it; revert, confirm CI green again. Introduced by PR-C landing under this initiative — see `research/db_audit/ALEMBIC_DRIFT_RECON.md` for the full drift-recon story that motivated AB-037A/B/C.
14+
- **AB-037C Alembic drift enforcement CI gate** — closes the Alembic drift initiative (AB-037A/B/C series) by adding an ongoing gate that prevents the F1-F6 drift class from silently re-landing. New step in `.github/workflows/ci.yml` `test-backend` job, inserted between "Install dependencies" and "Run tests": runs `alembic upgrade head` (proves migrations apply cleanly against a fresh PG — the same `postgres:14` service the job already provisions) followed by `alembic check` (proves SQLAlchemy models match the head schema via env.py's `compare_server_default=True` + `compare_type=True` flags set in AB-037B). The step is placed BEFORE the pytest run deliberately so a migration or drift failure surfaces early with a clear cause rather than manifesting as a downstream test failure. `DATABASE_URL` env var is set explicitly on the step (GitHub Actions steps do not inherit each other's env). Root cause the gate addresses: F1 (actions.metadata rename), F4 (users.email index), F5 (6 ENUM values_callable drift), F6 (refresh_tokens.token_hash type + unique), F3 (14 missing index=True), and F7 (33 server_default drift) all landed in the repo undetected because CI provisioned PostgreSQL but never asked "does `alembic upgrade head` produce a schema matching the models against PG?" — pytest ran against SQLite `:memory:` (see conftest.py) which silently accepted PG ENUM/JSONB/ARRAY types as untyped columns. What this PR does NOT do: switch `src/backend/tests/conftest.py` from SQLite to PG + Alembic migrations. That optional AB-037C scope carve-out was spun out to AB-038 to keep this PR tactically small — conftest rewrite would risk breaking every backend test on dialect differences (case sensitivity, JSONB comparisons, ENUM binding) and needs its own PR with a per-test transaction-rollback isolation redesign; the `alembic check` gate already covers the model↔migration drift class that AB-037A/B fixed, and AB-038 exists to also catch migration↔runtime-behavior drift. Post-merge manual verification (AC #3-#4 — not blocking closure): introduce a deliberate model-column addition without a migration in a test PR, confirm CI catches it; revert, confirm CI green again. Introduced by [PR #67](https://github.com/adamatdevops/forge-works/pull/67) at [`1cc6d7e`](https://github.com/adamatdevops/forge-works/commit/1cc6d7e); both gate steps green on the PR's own CI run — evidence PR-A + PR-B canonicalization was complete with no residual drift. See `research/db_audit/ALEMBIC_DRIFT_RECON.md` for the full drift-recon story that motivated AB-037A/B/C.
1515

1616
- **AB-029 Option A sibling-Flink prototype v0.1.0** — first real placement prototype for the AB-029 runtime placement benchmark. Ships as new `src/flink-jobs/dr-predictor/` Maven module (Java, Flink 1.20.3, matches pattern-matcher's structure) plus a real `SiblingFlinkPrototype` class in `src/runtime-placement-benchmark/forge_works/dr/ab029_spike/prototypes.py` that replaces `SiblingFlinkStub`'s NOT_IMPLEMENTED measurements with actual OK measurements for D1 (replay behavior), D3 (model rollout mechanics), D4 (failure isolation), D7 (cognitive load), and explicit NOT_APPLICABLE with reasoning for D2 (backpressure — needs running cluster + load generator), D5 (cost — needs real prediction volume + infra pricing), D6 (latency — needs Kafka broker + Prometheus scrape). Java pipeline: `DrPredictorJob.java` (main entry — Kafka source `forge.events.normalized.v1` → filter deploys → keyBy service:environment slice → score → Kafka sink `forge.predictions.dynamic_reliability.v1`), `NormalizedEvent.java` (input DTO mirroring pattern-matcher's `EventEnvelope`), `PredictionEnvelope.java` (output DTO per PC §3 shape — signal_role=recommendation, type=score, estimand_id=`deploy_slo_breach_60m_association_v0` per AB-033, horizon=next_1h, slice=(service, environment); `score()` + `abstain()` factory methods), `EventDeserializer.java` + `PredictionSerializer.java` (Jackson-based Kafka schemas, transient ObjectMapper re-initialized in Flink's `open()` per house lifecycle pattern), `model/ScoringModel.java` (pluggable interface), `model/ConstantPredictor.java` (final class, placeholder that returns 0.05 as base-rate placeholder from AB-028 RFC §4.4 — real MLflow-loaded predictor comes from AB-028 spike + AB-032 MLflow readiness), `model/DeployFeatureExtractor.java` (extracts plan_diff_size / resources_touched / touched_sensitive_resource from payload — placeholder; four-family feature families from AB-028 §4.3 require stateful rolling windows and land when AB-028 executes). Includes `input_freshness` gate: if `now - event.timestamp > 300s`, emit `abstain` prediction with reason `input_stale` per PC §3.0 eligibility rules. `src/flink-jobs/spotbugs-exclude.xml` updated to add `dr.EventDeserializer` + `dr.PredictionSerializer` to the SE_TRANSIENT_FIELD_NOT_RESTORED filter (documented Flink lifecycle pattern; identical suppression to the sibling schema impls). Python-side `SiblingFlinkPrototype` measurements are derived from static inspection of the module (pom.xml existence, source file count, documented Flink semantics from Kafka OffsetsInitializer + savepoint restore + JobManager isolation model); D4 scored 5.0 as reference for full isolation (standalone job, dedicated slots, no shared state with sibling jobs beyond Kafka topics), D7 scored 5.0 as top reuse of existing platform knowledge (same conceptual footprint as pattern-matcher/event-router/insight-generator, no new tools/languages/deploy paths). 10 new tests in `tests/test_prototypes.py`: protocol conformance, option code = "A", contract implications mention topic/placeholder/estimand, D1 qualitative mentions savepoint+kafka, D3 mentions 3-step/savepoint, D4 = 5.0 value, D7 = 5.0 value + Java file count in qualitative, D2/D5/D6 all NOT_APPLICABLE with notes, unknown-dimension raises ValueError, measure_all shape (D1/D3/D4/D7 OK, D2/D5/D6 NOT_APPLICABLE). Test count: 54 (44 pre-existing + 10 new). Java build clean under strict spotbugs (`Max` effort, `Low` threshold, `failOnError=true`) after fixing three findings: EI_EXPOSE_REP on `PredictionEnvelope.getPools()` / `getSlice()` (wrapped in List.copyOf + Collections.unmodifiableMap(new HashMap(...))) and CT_CONSTRUCTOR_THROW on `ConstantPredictor` (made class final to close finalizer-attack vector). Spotless (google-java-format AOSP) clean. Ruff clean under repo-wide config. What this DOES NOT include: the real AB-028 model (spike hasn't executed), the four-family feature extraction from AB-028 §4.3 (needs stateful rolling windows), MLflow model-loading (needs AB-032 readiness assessment), integration tests via Flink MiniCluster (no sibling Flink job has tests either — house style is production-code-only in the Flink modules; the AB-029 prototype layer measures placement properties at the correct level of abstraction). Blockers acknowledged (upstream — not addressed by this PR): AB-028 spike execution still needed for a real model; AB-029 scoping-approval meeting still needed to lock the §6.2 weighted-score rubric weights + confirm 7 dimensions; the other 4 stub prototypes (B/C/D/E) remain stubs pending their own real-prototype PRs. Introduced by [PR #31](https://github.com/adamatdevops/forge-works/pull/31) at [`0a1c406`](https://github.com/adamatdevops/forge-works/commit/0a1c406).
1717

0 commit comments

Comments
 (0)