From a6753d092fd3705f6d36f7922969f6339f051f47 Mon Sep 17 00:00:00 2001 From: CC Worker Date: Mon, 8 Jun 2026 00:26:24 +0000 Subject: [PATCH] fix(reset): fold --user-subset cleanup into scope=all and scope=exam-corpus t_d1600327 added a standalone scope=user-subset, but a full reset (scope=all) and scope=exam-corpus still left the --user-subset cc.users storage objects orphaned (files rows are wiped by the table clear, but the Storage API objects are not). Call the same _clear_user_subset_files() helper in both paths so the finding-#2 gap is fully closed: storage removed before rows, idempotent. Closes overwatch review finding #2 (user-subset not cleaned by reset). Co-Authored-By: Claude Opus 4.8 --- run/initialization/reset_environment.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/run/initialization/reset_environment.py b/run/initialization/reset_environment.py index 70d0c84..b050c22 100644 --- a/run/initialization/reset_environment.py +++ b/run/initialization/reset_environment.py @@ -298,11 +298,12 @@ def reset(scope: str = "all") -> Dict[str, Any]: """Destructive reset. scope ∈ {all, exam-corpus, timetable, user-subset}. - all : full wipe (Neo4j + Supabase data + auth users) AND the entire - exam-marker subsystem listed below. + exam-marker subsystem listed below, including --user-subset copies. - exam-corpus : ONLY the entire exam-marker subsystem, not just public papers: public corpus/eb_* data, cc.examboards storage objects, exam templates, template layouts, questions, boundaries, response - areas, marking batches, student submissions, and mark entries. + areas, marking batches, student submissions, mark entries, and + --user-subset cc.users copies. - timetable : ONLY timetable/calendar materialization tables. - user-subset : ONLY files rows and cc.users storage objects created by seed_exam_corpus.py --user-subset. @@ -314,10 +315,11 @@ def reset(scope: str = "all") -> Dict[str, Any]: _assert_reset_allowed(url, scope) if scope == "exam-corpus": - logger.info("RESET (scope=exam-corpus) — entire exam-marker subsystem: public corpus/eb_* data, cc.examboards storage, templates/layout/questions/boundaries/response areas, marking batches, submissions, mark entries") + logger.info("RESET (scope=exam-corpus) — entire exam-marker subsystem: public corpus/eb_* data, cc.examboards storage, templates/layout/questions/boundaries/response areas, marking batches, submissions, mark entries, and --user-subset copies") + user_subset = _clear_user_subset_files() storage = _clear_exam_storage() cleared, failed = _clear_tables(url, headers, EXAM_CORPUS_TABLES) - return {"scope": scope, "exam_storage": storage, "tables_cleared": cleared, "tables_failed": failed} + return {"scope": scope, "user_subset": user_subset, "exam_storage": storage, "tables_cleared": cleared, "tables_failed": failed} if scope == "timetable": logger.info("RESET (scope=timetable) — timetable/calendar tables") @@ -341,6 +343,9 @@ def reset(scope: str = "all") -> Dict[str, Any]: results["neo4j"] = {"dropped": dropped} # ── 2. Supabase: clear all data tables (GAIS preserved) ────────────────── + # First remove --user-subset cc.users storage objects (+ their files rows) via the + # Storage API, so the generic files-table clear below doesn't strand orphaned objects. + results["user_subset"] = _clear_user_subset_files() logger.info("\n[Supabase] Clearing data tables (preserving gais_*)...") url, headers = _sb_headers() cleared, failed = [], []