Conversation
…GISTERED_BUILTINS Fixes a pre-existing stale count (18 vs actual 19) that slipped through because sqlite_e2e tests are deselected by default. Sets up the regression lock for the batched NOT IN deprecation change.
|
CHANGELOG reminder — This PR has no changelog fragment. Add a file to |
Replace the per-row deprecation loop (SELECT + set-difference + N UPDATEs) with one UPDATE ... WHERE class_ref NOT IN (...) using dynamically-built placeholders. Empty-seen case falls back to deprecating all built-in rows. PR #606 review follow-up, Trello gw6MJIlG.
ReviewTight, well-scoped change. The N+1 → 1 round-trip is a clear win, the empty-seen edge case is correctly handled and locked by a new test, and the stale Issues1.
And Nits2. Placeholder generation could be a touch clearer ( placeholders = ", ".join(f"${i + 2}" for i in range(len(seen_class_refs)))Slightly clearer with placeholders = ", ".join(f"${i}" for i, _ in enumerate(seen_class_refs, start=2))The Correctness check — passes
Test coverage — good
SummaryLGTM once |
ReviewOverall: clean, targeted refactor. N+1 → 1 round trip is a real win, the empty-seen fallback is the right call, and the SQL is safe. Two workflow nits I'd want addressed before merge, and a couple of small code-level comments. 🟠 Workflow / merge hygiene
🟢 CorrectnessThe batched UPDATE is correct:
🟡 Minor code suggestions (non-blocking)
🟢 Performance & security
🟢 Tests
Note on PR scopeThe stale SummaryLGTM after (1) moving |
Code review — PR #793Overall the core change is solid: N+1 deprecation UPDATEs collapsed into one batched statement, behavior preserved, dynamic placeholder pattern matches what A few things to address before merge: 🚩 Blocking
No changelog fragment for the actual change in this PR. The existing 🟡 Nits (non-blocking)Placeholder offset deserves a one-line comment. The other dynamic- # $1 is the `True` bind; the IN list starts at $2.
placeholders = ", ".join(f"${i + 2}" for i in range(len(seen_class_refs)))Adjacent f-strings. Minor: ✅ Looking good
Verification I did
|
…laceholder nits - Move dev/OBJECTIVE.md to gitignored dev/scratch/ (untracked) per CLAUDE.md - Add changelog.d fragment for the batched deprecation UPDATE - Hardcode `deprecated = TRUE` in SQL and number the NOT IN placeholders from $1, matching the repo's other dynamic-IN sites and removing the `i + 2` offset reviewers flagged as fragile Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Autonomous overnight follow-up from the nightly sitrep agent — addressed review feedback in 3179f09. Needs human review; PR stays draft. Addressed:
Deliberately skipped (judgment/taste calls per reviews):
Validation: |
ReviewSmall, well-scoped change. The N+1 → 1 optimization is correct, the empty-seen edge case is properly handled with a dedicated test, and the changelog is in order. A few observations below. Correctness — minor behavioral improvement (worth noting)The rewrite isn't a strict 1:1 of the old logic — it's slightly more correct in one subtle way. The old loop ran: UPDATE policy_type SET deprecated = $1 WHERE class_ref = $2with no Code quality
Security
Performance
Test coverage
Nit on the changelog
SummaryLGTM. The behavioral improvement around |
|
Claude-generated merge-queue triage of all open Luthien PRs, requested by Scott (Jul 7, 2026). Advisory only; Scott has not yet acted on these recommendations. Recommendation: mark ready and merge (the code diff is roughly 20 lines). Still doubly relevant on main: the per-row deprecation UPDATE loop is still there, and the test suite still asserts 18 built-ins while |
Autonomous overnight work from nightly sitrep — needs human review.
Trello: https://trello.com/c/gw6MJIlG (low-priority follow-ups from PR #606 review).
Scope
The card has three items. Items 1 (acronym-then-word regex split in
derive_builtin_name) and 3 (intentional-coupling comment on the_apply_sqlite_migrationsimport in the integration test) were already landed in commit85872f5bonmain, so this PR only does item 2.Item 2 — batch the deprecation UPDATE
sync_policy_typesmarked stale built-in rows deprecated with oneUPDATEper row inside a Python loop (after aSELECT+ set-difference). Replaced with a single batchedUPDATE ... WHERE definition_type = 'built-in' AND class_ref NOT IN ($1, ..., $N), placeholders built dynamically from the seen class_refs. Thedb_sqlite$N->?translator handles the dynamic placeholder list, so it stays portable across asyncpg and SQLite.Empty-seen edge case (
NOT IN ()is invalid SQL): when no class_refs imported successfully, falls back to deprecating all built-in rows — matching the old loop's behavior. Locked by a new test,test_sync_deprecates_all_when_no_classes_seen.Incidental fix (required for validation)
The
sqlite_e2esync tests are deselected by default inaddopts, and a stale hardcoded== 18assertion had drifted from the actualREGISTERED_BUILTINSlength (19, after the DeAI preset was added in33dc4280). The suite was red before any change here. Rewrote the three count assertions to derive fromlen(REGISTERED_BUILTINS)so they can't go stale again.Validation
pytest tests/luthien_proxy/integration_tests/test_policy_type_sync.py -m sqlite_e2e— all passpytest tests/luthien_proxy/unit_tests/test_policy_types.py— all passNot done
Items 1 and 3 — already on
main. No code change needed; verified present and correct.