fix: preserve packet_feedback and created_at on packet re-save - #88
Open
clates wants to merge 4 commits into
Open
fix: preserve packet_feedback and created_at on packet re-save#88clates wants to merge 4 commits into
clates wants to merge 4 commits into
Conversation
… fp precision, cascade deletes - Add null guards for progress_blob/plan_rules_blob in logic.py, main.py, agent.py (issues #77, #78, #79) — new students with NULL blobs no longer crash - Fix generate_weekly_plan to use datetime.now(UTC) instead of local time (issue #80) — prevents off-by-one day in week_of on non-UTC servers - Fix _get_grade_level to fall back to student metadata instead of literal 0 (issue #81) — first-time plan generation no longer fails with no-standards error - Round activity_bias in process/reverse_quantity_feedback to 6 decimal places (issue #82) — prevents floating-point drift across feedback cycles - Replace delete-then-insert with INSERT OR REPLACE in save_weekly_packet (issue #83) — eliminates duplicate-packet race condition under concurrent saves - Cascade-delete weekly_packets before deleting student profile in delete_student (issue #84) — packet_feedback no longer left as orphans after student deletion Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Adds two rules to prevent direct commits to main: - All changes must go through a PR, no exceptions - Automated analysis/fix workflows must create a branch before making changes, then open a PR rather than committing directly Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…l test - delete_student() now catches OperationalError when weekly_packets table doesn't exist (minimal test DBs only have student_profiles) - Update test_get_grade_level_defaults_to_zero to expect 1 (the new safe default) and add a second test covering the metadata_fallback path Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Replace INSERT OR REPLACE with INSERT ... ON CONFLICT(packet_id) DO UPDATE SET in _insert_weekly_packet. SQLite's INSERT OR REPLACE internally does DELETE + INSERT, which cascades to packet_feedback and silently deletes all user feedback on every background re-generation. The new upsert updates the row in-place so no cascade fires. - Exclude created_at from the DO UPDATE SET list so the original creation timestamp is only written on the first insert and never overwritten on subsequent saves. - Add explicit DELETE FROM daily_lessons WHERE packet_id = ? in save_weekly_packet before calling _persist_daily_lessons, replacing the implicit cascade cleanup that the old DELETE approach provided. - Add regression tests: test_resave_preserves_packet_feedback and test_resave_does_not_overwrite_created_at. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
INSERT OR REPLACEin_insert_weekly_packettriggers a SQLite-internal DELETE + INSERT on primary key conflict. WithFOREIGN KEY ... ON DELETE CASCADEonpacket_feedback, this silently deletes all user-submitted feedback on every packet re-save. Sincegenerate_trio_for_studentis called as a background task after every feedback submission, feedback was being erased immediately after submission.created_atandupdated_atwere set tonowon every call, overwriting the original creation timestamp on re-saves.Changes
src/packet_store.py— ReplaceINSERT OR REPLACE INTO weekly_packetswithINSERT INTO ... ON CONFLICT(packet_id) DO UPDATE SET .... The upsert updates the row in-place without deleting it, so theON DELETE CASCADEtopacket_feedbacknever fires.created_atis intentionally excluded from theDO UPDATE SETlist so it is only written on the first insert.src/packet_store.py— Addconn.execute("DELETE FROM daily_lessons WHERE packet_id = ?", ...)insave_weekly_packetbefore_persist_daily_lessons. This explicit delete replaces the implicit cascade cleanup that the old DELETE approach provided, since_persist_daily_lessonsuses plainINSERT(notINSERT OR IGNORE) and would fail on UNIQUE constraint for(packet_id, day_label)without it.tests/test_packet_store.py— Addtest_resave_preserves_packet_feedback: saves a packet, saves feedback, re-saves the packet, asserts feedback is still present. Addtest_resave_does_not_overwrite_created_at: saves a packet, re-saves it, assertscreated_atis unchanged.Test plan
test_resave_preserves_packet_feedback— confirms feedback rows survive a packet re-savetest_resave_does_not_overwrite_created_at— confirmscreated_atis immutable after first inserttest_save_weekly_packet_persists_rows— confirms initial save still writes all rows correctlytest_save_weekly_packet_rolls_back_on_error— confirms transaction atomicity is preserveddatetime.UTCis available (local env is 3.10; import error is pre-existing)🤖 Generated with Claude Code