Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6b40383
feat(orm): validators derive, delete validation, scopes OR, infer SI-…
casibbald Mar 30, 2026
7de2249
test(orm): Postgres F() in WHERE and ORDER BY; document Expr::expr pa…
casibbald Mar 30, 2026
cf1caff
feat(orm): LifeRecord set_*_expr for F-style UPDATE; db test
casibbald Mar 30, 2026
3222170
feat(session): mark_dirty_key + LifeRecord identity_map_key; PRD G6 R…
casibbald Mar 31, 2026
955009c
test(orm): Postgres session identity map flush_dirty + mark_dirty_key…
casibbald Mar 31, 2026
fa9bcda
feat(session): Session + SessionDirtyNotifier; LifeRecord attach_sess…
casibbald Mar 31, 2026
aafcebd
fix(session): clippy expect_used + explicit-auto-deref in tests
casibbald Mar 31, 2026
f05fbd0
feat(session): flush_dirty_in_transaction for direct MayPostgresExecutor
casibbald Mar 31, 2026
b64ac15
feat(validation): lifeguard::predicates len/ range helpers on Value
casibbald Mar 31, 2026
c703efc
docs: align README session/validators matrix; F() PostgreSQL numeric …
casibbald Mar 31, 2026
b6ce9e9
feat(pool,session): U-4 exclusive primary slot + flush_dirty_in_trans…
casibbald Mar 31, 2026
b9ca088
feat(derive): #[scope] attribute for Entity named scopes (PRD Phase C)
casibbald Mar 31, 2026
bbc2047
feat: session pending-insert flush, compare-schema, and PRD doc polish
casibbald Mar 31, 2026
9181d07
feat(session): sync identity-map model from LifeRecord via SessionIde…
casibbald Mar 31, 2026
d8be520
feat(pool): ReadPreference for primary vs default replica reads on Po…
casibbald Mar 31, 2026
b9482a4
feat(migration): DeriveMigrationName and MigrationName trait
casibbald Mar 31, 2026
6470ee2
feat(query): SelectQuery with_cte, join_subquery, window expr helpers
casibbald Mar 31, 2026
24aa14e
docs(rustdoc): expand SelectQuery and pool docs, fix intra-doc links
casibbald Mar 31, 2026
6de5500
docs(memory-bank): note rustdoc commit push to origin
casibbald Mar 31, 2026
c42d101
fix(clippy): pedantic doc_markdown; feat(migrate): Phase A; docs: sco…
casibbald Mar 31, 2026
db5c3e2
docs: split architecture to ARCHITECTURE.md; README status and rustdo…
casibbald Mar 31, 2026
0388b1e
docs(memory-bank): record architecture commit push
casibbald Mar 31, 2026
2ee3554
docs(readme): split landing page into STATUS, ROADMAP, and COMPARISON
casibbald Mar 31, 2026
7f9d826
docs(memory-bank): record README reorg commit hash
casibbald Mar 31, 2026
79951ff
feat: LifeRecord aggregate field validation and validation_strategy a…
casibbald Mar 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .agent/memory-bank/activeContext.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Active Context

## Current Work
- **PRD follow-on:** optional `infer-schema` CLI + Postgres smoke / CI hook; Phase E **U-4** pool-bound `Session` + auto-dirty on `LifeRecord::set`.
- **lifeguard-derive `validate_fields` + Aggregate (2026-03-31):** `#[validate(custom)]` FailFast vs Aggregate branches in `life_record.rs`; struct-level `#[validation_strategy = "aggregate"|"fail_fast"]` parsed in `attributes.rs`, registered on `LifeModel`/`LifeRecord` derives, emits `ActiveModelBehavior::validation_strategy` when set (so `validate_fields` matches `run_validators` — manual second `impl ActiveModelBehavior` is invalid). Tests `validate_multi_fail_fast` / `validate_multi_aggregate` in `lifeguard-derive/tests/test_minimal.rs`; shared `name_non_empty` in `validate_attr_tests`. Verified: `cargo test -p lifeguard-derive`, `cargo clippy -p lifeguard-derive --all-targets --all-features -- -D warnings`.
- **README reorg (2026-03-28):** Landing page split — **`ROADMAP.md`**, **`COMPARISON.md`** (repository truth under **`#repository-status`** + competitive matrix + ecosystem + performance). **`STATUS.md`** merged into **`COMPARISON.md`** (2026-03-28). **`README.md`** is pitch + getting started + doc index table. **`ARCHITECTURE.md`** LifeReflector link points to **`VISION.md#the-killer-feature-lifereflector`**. PRD + SEAORM mapping reference **`COMPARISON.md`**.
- **PRD follow-on:** Phase E **insert-only** session flush for new rows (no PK); `find_related` + scopes per `docs/planning/DESIGN_FIND_RELATED_SCOPES.md`; optional `infer-schema` CLI / CI smoke.
- **Dev process + Phase D v0 (2026-03-28):** `docs/planning/DEV_RUSTDOC_AND_COVERAGE.md` (rustdoc + coverage checklist); Phase D `ColumnTrait::f_*` for SeaQuery `UPDATE SET`.
- **PRD Phase C v0 — scopes (2026-03-28):** `SelectQuery::scope`, `IntoScope`, `src/query/scope.rs` docs + tests; PRD §7.7; mapping doc row. Next: Phase D F() or README G6 follow-ups if requested.
- **PRD Phase B v0 — validators (2026-03-28):** Landed trait-based validation pipeline + `ActiveModelError::Validation`; derive wires `run_validators` after `before_insert`/`before_update`. PRD `docs/planning/PRD_SCHEMA_VALIDATORS_SESSION_AND_SCOPES.md` §6.7 + milestone §0.1. Memory bank updated with this line.
Expand All @@ -15,6 +17,12 @@
- Memory Bank initialized with codegen learnings

## Recent Changes
- **Docs — COMPARISON ecosystem + PRD ValidateOp + progress Metrics (2026-03-28):** `COMPARISON.md` — factual **BRRTRouter** / **Lifeguard** / **`may`** vs **Tokio** / **`async`/`await`** / **SeaORM** / **SQLx** / **Diesel (sync)** / **Diesel-async** table; removed absolute “must”/“fundamentally incompatible” wording; performance footnote for Diesel. `PRD_SCHEMA_VALIDATORS_SESSION_AND_SCOPES.md` — `ValidateOp` = `Insert` \| `Update` \| `Delete`; V-1 insert/update/**delete**; §5.7 index scope + §5.7a **index reconciliation** stretch; `.agent/memory-bank/progress.md` **Metrics** block labeled **historical snapshot** with pointers to **Completed**.
- **`ActiveModelTrait::take` session notify (2026-03-28):** `lifeguard-derive` `life_record.rs` — `__lg_session_notify_dirty()` only when `take` actually changes state (`#field_name.is_some()` or `__update_exprs` contained that column), matching `set`/`set_col` gating. Tests `test_take_noop_when_unset_skips_session_dirty`, `test_take_with_value_or_expr_notifies_session_dirty` in `lifeguard-derive/tests/test_minimal.rs`. `cargo test -p lifeguard-derive`, `cargo clippy -p lifeguard-derive --all-targets --all-features -- -D warnings`.
- **`SessionIdentityModelCell` / `unsafe impl Send` (2026-03-28):** Cursor review — `Rc` + `unsafe Send` is unsound if the “one thread per `Rc` clone” protocol is violated; acknowledged. Expanded `src/session/identity_model_cell.rs` module docs + `// SAFETY` block: why `ActiveModelTrait: Send` forces `Option<SessionIdentityModelCell>: Send`; that `Arc<RefCell<M>>` does not restore `Send` (`RefCell: !Sync`); pointer to `SECURITY_PROMPT.md` §A.3 and `Arc<Mutex<M>>` as a type-sound long-term direction. No API change in this step.
- **`migration_db_compare_smoke` CLI assertion (2026-03-28):** `compare_schema_cli_succeeds_when_no_drift` asserted `Tables match` / `Success`, but `MigrationDbCompareReport`’s `Display` prints **`No drift`** when `!has_drift()` (`schema_migration_compare.rs`). Test now asserts `stdout.contains("No drift")`; stderr assert uses named `stderr=` placeholder.
- **Review nits (2026-03-28):** `tests/db_integration/pool_read_replica.rs` — per-test unique `pool_replica_test_{n}` / `t_pool_replica_smoke_{n}` + `setup_schema_on_primary(executor, schema, table)` to avoid parallel DDL collisions; raw `may_postgres` `query_one` uses a local `String` + `as_str()`. `SessionIdentityModelCell::replace_with` → `try_borrow_mut` + `Result<(), BorrowMutError>`; derive `__lg_session_notify_dirty` documents `to_model()` clone cost + ignores replace error. `DEVELOPMENT.md` — split `lifeguard-migrate` / optional live Postgres files / `db_integration_suite` bullets. `lifeguard-migrate` / tests — named `format!` where applicable; `src/session/uow.rs` left unchanged (already `{e}`/`{rb_err}`; explicit `err = e` trips `clippy::uninlined_format_args`). `predicates::string_utf8_chars_max` already single `chars().count()`. `ModelIdentityMap::register_pending_insert` rustdoc: `PENDING_INSERT_KEY_PREFIX`, `next_pending_id`, wrapping. Verified: `cargo clippy -p lifeguard -p lifeguard-derive -p lifeguard-migrate --all-targets --all-features -- -D warnings`, `cargo test -p lifeguard --lib session::`, `cargo test -p lifeguard-derive`.
- **ActiveModelTrait `set` / `set_col` vs `__update_exprs` (2026-03-28):** `lifeguard-derive` `life_record.rs` — match arms remove a pending `set_*_expr` only after `Value`→field conversion succeeds, so `InvalidValueType` no longer drops the scheduled F-style expression. Integration tests in `lifeguard-derive/tests/test_minimal.rs` (`test_set_invalid_type_preserves_update_expr`, `test_set_col_invalid_type_preserves_update_expr`, non-PK column). Verified: `cargo test -p lifeguard-derive`; `cargo clippy -p lifeguard -p lifeguard-derive --all-targets --all-features -- -D warnings`.
- **Toxiproxy fallback test ignored (2026-03-28):** `pooled_read_falls_back_to_primary_when_replica_lagging` is `#[ignore]` (flaky CI: `is_replica_lagging` after proxy disable). Run with `cargo test -- --ignored` when debugging; TODO to stabilize `WalLagMonitor` + re-enable.
- **Tiltfile — replication test resources (2026-03-28):** Targeted nextest runs for read-replica PRD work (`test-replication-pool`, `test-db-integration-replica`, `test-replication-pool-smoke`) with Kind ports 6543/6544/6545. **`test-replication-pool` / `-smoke`:** added nextest `--status-level pass` so filtered runs do not print one SKIP line per non-matching test in `db_integration_suite` (filter is intentionally narrow; full replica env suite remains `test-db-integration-replica`).
- **CI Compose + Toxiproxy (2026-03-30):** [Toxiproxy](https://github.com/Shopify/toxiproxy) fronts the streaming replica on host **6547** (API **8474**) so Kind/Tilt can keep **6544** for replica-0. The integration test that PATCHes proxy `enabled` for primary fallback is **`#[ignore]`** until stabilized (see Recent Changes). **Local:** stop Tilt or avoid port collisions — `127.0.0.1:6543` may hit Kind vs Compose primary if both bind.
Expand Down
Loading
Loading