From be76605b76bafca4f438e295b81df88b4e2b94ef Mon Sep 17 00:00:00 2001 From: AIOSAI Date: Sun, 10 May 2026 16:38:10 -0700 Subject: [PATCH] feat(system): fix(flow): close_ops handles relocated plans + memory_bank ref purge Co-Authored-By: @devpulse --- .claude/hooks/.diagnostics_state.json | 1 - .../flow/apps/handlers/plan/close_ops.py | 60 ++++++++++++++++--- src/aipass/memory/.seedgo/bypass.json | 6 +- .../memory/apps/handlers/central_writer.py | 2 +- 4 files changed, 56 insertions(+), 13 deletions(-) delete mode 100644 .claude/hooks/.diagnostics_state.json diff --git a/.claude/hooks/.diagnostics_state.json b/.claude/hooks/.diagnostics_state.json deleted file mode 100644 index c128b44f..00000000 --- a/.claude/hooks/.diagnostics_state.json +++ /dev/null @@ -1 +0,0 @@ -{"file": "/home/patrick/Projects/AIPass/src/aipass/memory/apps/handlers/search/vector_search.py", "errors": [{"line": 42, "message": "E402: Module level import not at top of file"}]} \ No newline at end of file diff --git a/src/aipass/flow/apps/handlers/plan/close_ops.py b/src/aipass/flow/apps/handlers/plan/close_ops.py index cd0f2fb5..5dbd8091 100644 --- a/src/aipass/flow/apps/handlers/plan/close_ops.py +++ b/src/aipass/flow/apps/handlers/plan/close_ops.py @@ -98,6 +98,30 @@ def _find_plan_across_registries(plan_key: str, load_registry_fn: Any) -> str | # ============================================= +def _find_relocated_plan(plan_file: Path) -> Path | None: + """Search common locations for a plan file that was manually moved. + + Returns the found path, or None if not found anywhere. + """ + from aipass.flow.apps.handlers.mbank.process import PROCESSED_PLANS_DIR + + filename = plan_file.name + branch_dir = plan_file.parent + + search_dirs = [ + branch_dir / ".archive", + branch_dir / "docs.local", + PROCESSED_PLANS_DIR, + ] + + for search_dir in search_dirs: + candidate = search_dir / filename + if candidate.exists(): + return candidate + + return None + + def _spawn_background_runner(): """Spawn post_close_runner.py as a fully detached background process""" bg_runner = FLOW_ROOT / "apps" / "modules" / "post_close_runner.py" @@ -275,6 +299,17 @@ def close_plan_impl( "cancelled": False, } + # --- File location resolution --- + # If plan file was manually moved, find it before proceeding + if not plan_file.exists(): + relocated = _find_relocated_plan(plan_file) + if relocated: + messages.append( + {"type": "warning", "text": f" Plan file not at expected path, found at: {relocated.parent.name}/"} + ) + logger.info(f"[{MODULE_NAME}] Relocated {plan_label}: {relocated}") + plan_file = relocated + # --- Step 1/5: Template check (may fast-delete) --- messages.append({"type": "step", "text": "[1/5] Checking template status..."}) try: @@ -308,9 +343,11 @@ def close_plan_impl( "cancelled": False, } - except FileNotFoundError as e: - logger.warning(f"[{MODULE_NAME}] Template check - file not found: {e}") - messages.append({"type": "warning", "text": " Plan file not found, continuing with registry close"}) + except FileNotFoundError: + logger.warning(f"[{MODULE_NAME}] Plan file not found at any location: {plan_file}") + messages.append( + {"type": "warning", "text": " Plan file not found at any location, closing in registry only"} + ) except Exception as e: logger.warning(f"[{MODULE_NAME}] Template check failed: {e}") messages.append( @@ -355,11 +392,17 @@ def close_plan_impl( # --- Step 3/5: Archive plan to processed_plans --- messages.append({"type": "step", "text": "[3/5] Archiving plan..."}) try: - from aipass.flow.apps.handlers.mbank.process import archive_plan + from aipass.flow.apps.handlers.mbank.process import archive_plan, PROCESSED_PLANS_DIR + + # If file is already in processed_plans (found via relocation search), skip move + if plan_file.exists() and plan_file.parent == PROCESSED_PLANS_DIR: + archive_success = True + logger.info(f"[{MODULE_NAME}] {plan_label} already in processed_plans/, skipping move") + messages.append({"type": "dim", "text": " Already in processed_plans/ — skipping move"}) + else: + archive_success = archive_plan(plan_file) - archive_success = archive_plan(plan_file) if archive_success: - # Set flags on same registry object we already have in memory plan_info["processed"] = True plan_info["processed_date"] = datetime.now(timezone.utc).isoformat() plan_info["cleanup_completed"] = True @@ -368,8 +411,9 @@ def close_plan_impl( save_registry(registry, registry_file=reg_file) else: save_registry(registry) - logger.info(f"[{MODULE_NAME}] Archived {plan_label} to processed_plans") - messages.append({"type": "dim", "text": " Plan archived to processed_plans/"}) + if plan_file.parent != PROCESSED_PLANS_DIR: + logger.info(f"[{MODULE_NAME}] Archived {plan_label} to processed_plans") + messages.append({"type": "dim", "text": " Plan archived to processed_plans/"}) else: logger.error(f"[{MODULE_NAME}] Failed to archive {plan_label}") messages.append({"type": "warning", "text": " Archive failed — plan file not moved"}) diff --git a/src/aipass/memory/.seedgo/bypass.json b/src/aipass/memory/.seedgo/bypass.json index fbe17c84..af83b618 100644 --- a/src/aipass/memory/.seedgo/bypass.json +++ b/src/aipass/memory/.seedgo/bypass.json @@ -64,7 +64,7 @@ { "file": "apps/modules/symbolic.py", "standard": "modules", - "reason": "Symbolic module is 1669 lines — legacy port from old memory bank. Functions flagged as implementation are CLI-display orchestration, not raw logic." + "reason": "Symbolic module is 1669 lines — legacy port from old memory system. Functions flagged as implementation are CLI-display orchestration, not raw logic." }, { "file": "apps/modules/rollover.py", @@ -219,7 +219,7 @@ { "file": "apps/modules/symbolic.py", "standard": "documentation", - "reason": "Large legacy module (1672 lines) ported from old memory bank. Multiline signatures cause false-positive missing docstring detection." + "reason": "Large legacy module (1672 lines) ported from old memory system. Multiline signatures cause false-positive missing docstring detection." }, { "file": "apps/modules/search.py", @@ -269,7 +269,7 @@ { "file": "apps/modules/symbolic.py", "standard": "architecture", - "reason": "1672 lines — legacy port from old memory bank. Full refactor into handler split deferred." + "reason": "1672 lines — legacy port from old memory system. Full refactor into handler split deferred." }, { "file": "apps/handlers/learnings/manager.py", diff --git a/src/aipass/memory/apps/handlers/central_writer.py b/src/aipass/memory/apps/handlers/central_writer.py index 4809a626..cd9bedf0 100644 --- a/src/aipass/memory/apps/handlers/central_writer.py +++ b/src/aipass/memory/apps/handlers/central_writer.py @@ -9,7 +9,7 @@ """ Central File Writer Handler -Updates memory_bank.central.json with current statistics. +Updates memory.central.json with current statistics. This file is memory's "API output" - used to populate dashboards. Purpose: