diff --git a/backend/src/api/routes/admin.py b/backend/src/api/routes/admin.py index baaa8f78..b9cc8a19 100644 --- a/backend/src/api/routes/admin.py +++ b/backend/src/api/routes/admin.py @@ -311,7 +311,7 @@ async def list_permissions( ) if inserted_count > 0: logger.info( - "[api.admin.list_permissions][Action] Synchronized %s missing RBAC permissions into auth catalog", + "[api.admin.list_permissions][REASON] Synchronized %s missing RBAC permissions into auth catalog", inserted_count, ) diff --git a/backend/src/api/routes/dashboards/_listing_routes.py b/backend/src/api/routes/dashboards/_listing_routes.py index 92380b1a..3b320612 100644 --- a/backend/src/api/routes/dashboards/_listing_routes.py +++ b/backend/src/api/routes/dashboards/_listing_routes.py @@ -184,7 +184,7 @@ async def get_dashboards( total_pages = page_payload["total_pages"] except Exception as page_error: logger.warning( - "[get_dashboards][Action] Page-based fetch failed; using compatibility fallback: %s", + "[get_dashboards][REASON] Page-based fetch failed; using compatibility fallback: %s", page_error, ) if can_apply_slug_filter: diff --git a/backend/src/api/routes/git/_helpers.py b/backend/src/api/routes/git/_helpers.py index d70c9029..458f2ff2 100644 --- a/backend/src/api/routes/git/_helpers.py +++ b/backend/src/api/routes/git/_helpers.py @@ -62,7 +62,7 @@ def _resolve_repository_status(dashboard_id: int) -> dict: repo_path = git_service._get_repo_path(dashboard_id) if not os.path.exists(repo_path): logger.debug( - f"[get_repository_status][Action] Repository is not initialized for dashboard {dashboard_id}" + f"[get_repository_status][REASON] Repository is not initialized for dashboard {dashboard_id}" ) return _build_no_repo_status_payload() @@ -71,7 +71,7 @@ def _resolve_repository_status(dashboard_id: int) -> dict: except HTTPException as e: if e.status_code == 404: logger.debug( - f"[get_repository_status][Action] Repository is not initialized for dashboard {dashboard_id}" + f"[get_repository_status][REASON] Repository is not initialized for dashboard {dashboard_id}" ) return _build_no_repo_status_payload() raise @@ -288,7 +288,7 @@ def _resolve_current_user_git_identity( ) except Exception as resolve_error: logger.warning( - "[_resolve_current_user_git_identity][Action] Failed to load profile preference for user %s: %s", + "[_resolve_current_user_git_identity][REASON] Failed to load profile preference for user %s: %s", user_id, resolve_error, ) diff --git a/backend/src/api/routes/git/_repo_operations_routes.py b/backend/src/api/routes/git/_repo_operations_routes.py index e9a4904f..8ef086cb 100644 --- a/backend/src/api/routes/git/_repo_operations_routes.py +++ b/backend/src/api/routes/git/_repo_operations_routes.py @@ -129,12 +129,12 @@ async def pull_changes( config_provider = config_row.provider except Exception as diagnostics_error: logger.warning( - "[pull_changes][Action] Failed to load repository binding diagnostics for dashboard %s: %s", + "[pull_changes][REASON] Failed to load repository binding diagnostics for dashboard %s: %s", dashboard_id, diagnostics_error, ) logger.info( - "[pull_changes][Action] Route diagnostics dashboard_ref=%s env_id=%s resolved_dashboard_id=%s " + "[pull_changes][REASON] Route diagnostics dashboard_ref=%s env_id=%s resolved_dashboard_id=%s " "binding_exists=%s binding_local_path=%s binding_remote_url=%s binding_config_id=%s config_provider=%s config_url=%s", dashboard_ref, env_id, @@ -191,7 +191,7 @@ async def get_repository_status_batch( dashboard_ids = list(dict.fromkeys(request.dashboard_ids)) if len(dashboard_ids) > MAX_REPOSITORY_STATUS_BATCH: logger.warning( - "[get_repository_status_batch][Action] Batch size %s exceeds limit %s. Truncating request.", + "[get_repository_status_batch][REASON] Batch size %s exceeds limit %s. Truncating request.", len(dashboard_ids), MAX_REPOSITORY_STATUS_BATCH, ) diff --git a/backend/src/api/routes/git/_repo_routes.py b/backend/src/api/routes/git/_repo_routes.py index 315dc9af..a7d6d3ca 100644 --- a/backend/src/api/routes/git/_repo_routes.py +++ b/backend/src/api/routes/git/_repo_routes.py @@ -62,7 +62,7 @@ async def init_repository( try: logger.info( - f"[init_repository][Action] Initializing repo for dashboard {dashboard_id}" + f"[init_repository][REASON] Initializing repo for dashboard {dashboard_id}" ) _gs.init_repo( dashboard_id, diff --git a/backend/src/api/routes/llm.py b/backend/src/api/routes/llm.py index d35f37a8..edbe125b 100644 --- a/backend/src/api/routes/llm.py +++ b/backend/src/api/routes/llm.py @@ -53,7 +53,7 @@ async def get_providers( Get all LLM provider configurations. """ logger.info( - f"[llm_routes][get_providers][Action] Fetching providers for user: {current_user.username}" + f"[llm_routes][get_providers][REASON] Fetching providers for user: {current_user.username}" ) service = LLMProviderService(db) providers = service.get_all_providers() @@ -249,7 +249,7 @@ async def test_connection( db: Session = Depends(get_db), ): logger.info( - f"[llm_routes][test_connection][Action] Testing connection for provider_id: {provider_id}" + f"[llm_routes][test_connection][REASON] Testing connection for provider_id: {provider_id}" ) """ Test connection to an LLM provider. @@ -306,7 +306,7 @@ async def test_provider_config( from ...plugins.llm_analysis.service import LLMClient logger.info( - f"[llm_routes][test_provider_config][Action] Testing config for {config.name}" + f"[llm_routes][test_provider_config][REASON] Testing config for {config.name}" ) # Check if API key is provided diff --git a/backend/src/api/routes/migration.py b/backend/src/api/routes/migration.py index 8f204c9e..2a9de6fc 100644 --- a/backend/src/api/routes/migration.py +++ b/backend/src/api/routes/migration.py @@ -358,7 +358,7 @@ async def trigger_sync_now( ) db.add(db_env) logger.info( - f"[trigger_sync_now][Action] Created environment row for {env.id}" + f"[trigger_sync_now][REASON] Created environment row for {env.id}" ) else: existing.name = env.name @@ -373,7 +373,7 @@ async def trigger_sync_now( client = SupersetClient(env) service.sync_environment(env.id, client) results["synced"].append(env.id) - logger.info(f"[trigger_sync_now][Action] Synced environment {env.id}") + logger.info(f"[trigger_sync_now][REASON] Synced environment {env.id}") except Exception as e: results["failed"].append({"env_id": env.id, "error": str(e)}) logger.error(f"[trigger_sync_now][Error] Failed to sync {env.id}: {e}") diff --git a/backend/src/api/routes/settings.py b/backend/src/api/routes/settings.py index bcbe04d2..55106303 100755 --- a/backend/src/api/routes/settings.py +++ b/backend/src/api/routes/settings.py @@ -88,7 +88,7 @@ async def get_settings( _=Depends(has_permission("admin:settings", "READ")), ): with belief_scope("get_settings"): - logger.info("[get_settings][Entry] Fetching all settings") + logger.info("[get_settings][REASON] Fetching all settings") config = config_manager.get_config().copy(deep=True) config.settings.llm = normalize_llm_settings(config.settings.llm) # Mask passwords @@ -127,7 +127,7 @@ async def update_global_settings( _=Depends(has_permission("admin:settings", "WRITE")), ): with belief_scope("update_global_settings"): - logger.info("[update_global_settings][Entry] Updating global settings") + logger.info("[update_global_settings][REASON] Updating global settings") config_manager.update_global_settings(settings) return settings @@ -183,7 +183,7 @@ async def get_environments( _=Depends(has_permission("admin:settings", "READ")), ): with belief_scope("get_environments"): - logger.info("[get_environments][Entry] Fetching environments") + logger.info("[get_environments][REASON] Fetching environments") environments = config_manager.get_environments() return [ env.copy(update={"url": _normalize_superset_env_url(env.url)}) @@ -205,7 +205,7 @@ async def add_environment( _=Depends(has_permission("admin:settings", "WRITE")), ): with belief_scope("add_environment"): - logger.info(f"[add_environment][Entry] Adding environment {env.id}") + logger.info(f"[add_environment][REASON] Adding environment {env.id}") env = env.copy(update={"url": _normalize_superset_env_url(env.url)}) # Validate connection before adding (fast path) @@ -237,7 +237,7 @@ async def update_environment( config_manager: ConfigManager = Depends(get_config_manager), ): with belief_scope("update_environment"): - logger.info(f"[update_environment][Entry] Updating environment {id}") + logger.info(f"[update_environment][REASON] Updating environment {id}") env = env.copy(update={"url": _normalize_superset_env_url(env.url)}) @@ -278,7 +278,7 @@ async def delete_environment( id: str, config_manager: ConfigManager = Depends(get_config_manager) ): with belief_scope("delete_environment"): - logger.info(f"[delete_environment][Entry] Deleting environment {id}") + logger.info(f"[delete_environment][REASON] Deleting environment {id}") config_manager.delete_environment(id) return {"message": f"Environment {id} deleted"} @@ -295,7 +295,7 @@ async def test_environment_connection( id: str, config_manager: ConfigManager = Depends(get_config_manager) ): with belief_scope("test_environment_connection"): - logger.info(f"[test_environment_connection][Entry] Testing environment {id}") + logger.info(f"[test_environment_connection][REASON] Testing environment {id}") # Find environment env = next((e for e in config_manager.get_environments() if e.id == id), None) @@ -352,7 +352,7 @@ async def update_logging_config( ): with belief_scope("update_logging_config"): logger.info( - f"[update_logging_config][Entry] Updating logging config: level={config.level}, task_log_level={config.task_log_level}" + f"[update_logging_config][REASON] Updating logging config: level={config.level}, task_log_level={config.task_log_level}" ) # Get current settings and update logging config @@ -476,7 +476,7 @@ async def update_consolidated_settings( ): with belief_scope("update_consolidated_settings"): logger.info( - "[update_consolidated_settings][Entry] Applying consolidated settings patch" + "[update_consolidated_settings][REASON] Applying consolidated settings patch" ) current_config = config_manager.get_config() diff --git a/backend/src/core/logger.py b/backend/src/core/logger.py index c1e1c9a1..1c68f83b 100755 --- a/backend/src/core/logger.py +++ b/backend/src/core/logger.py @@ -27,16 +27,16 @@ class BeliefFormatter(logging.Formatter): # [DEF:format:Function] # @PURPOSE: Formats the log record, adding belief state context if available. # @PRE: record is a logging.LogRecord. - # @POST: Returns formatted string. + # @POST: Returns formatted string with molecular CoT markers. # @PARAM: record (logging.LogRecord) - The log record to format. # @RETURN: str - The formatted log message. - # @SEMANTICS: logging, formatter, context + # @SEMANTICS: logging, formatter, context, cot def format(self, record): anchor_id = getattr(_belief_state, 'anchor_id', None) if anchor_id: msg = str(record.msg) - # Supported molecular topology markers - markers = ("[EXPLORE]", "[REASON]", "[REFLECT]", "[COHERENCE:", "[Action]", "[Entry]", "[Exit]") + # Molecular CoT topology markers only (REASON | REFLECT | EXPLORE) + markers = ("[EXPLORE]", "[REASON]", "[REFLECT]") # Avoid duplicating anchor or overriding explicit markers if msg.startswith(f"[{anchor_id}]"): @@ -44,8 +44,8 @@ class BeliefFormatter(logging.Formatter): elif any(msg.startswith(m) for m in markers): record.msg = f"[{anchor_id}]{msg}" else: - # Default covalent bond - record.msg = f"[{anchor_id}][Action] {msg}" + # Default molecular bond + record.msg = f"[{anchor_id}][REASON] {msg}" return super().format(record) # [/DEF:format:Function] @@ -62,32 +62,28 @@ class LogEntry(BaseModel): # #endregion LogEntry -# #region belief_scope [TYPE Function] [SEMANTICS logging, context, belief_state] -# @BRIEF Context manager for structured Belief State logging. +# #region belief_scope [TYPE Function] [SEMANTICS logging, context, belief_state, cot] +# @BRIEF Context manager for Molecular CoT structured logging. # @PRE: anchor_id must be provided. -# @POST: Thread-local belief state is updated and entry/exit logs are generated. +# @POST: Thread-local belief state is updated; REASON/REFLECT/EXPLORE markers emitted. @contextmanager def belief_scope(anchor_id: str, message: str = ""): - # Log Entry if enabled (DEBUG level to reduce noise) - if _enable_belief_state: - entry_msg = f"[{anchor_id}][Entry]" - if message: - entry_msg += f" {message}" - logger.debug(entry_msg) - - # Set thread-local anchor_id + # Set thread-local anchor_id FIRST so BeliefFormatter can apply prefix old_anchor = getattr(_belief_state, 'anchor_id', None) _belief_state.anchor_id = anchor_id try: - yield - # Log Coherence OK and Exit (DEBUG level to reduce noise) - logger.debug("[COHERENCE:OK]") + # Log entry as REASON (deep-reasoning bond) if _enable_belief_state: - logger.debug("[Exit]") + intent_msg = message or f"Entering {anchor_id}" + logger.reason(intent_msg) + + yield + # Log success as REFLECT (self-reflection bond) + logger.reflect(f"Completed successfully — {message or 'no message'}") except Exception as e: - # Log Coherence Failed (DEBUG level to reduce noise) - logger.debug(f"[COHERENCE:FAILED] {str(e)}") + # Log exception as EXPLORE (self-exploration bond) + logger.explore(f"Assumption violated — {str(e)}") raise finally: # Restore old anchor diff --git a/backend/src/core/logger/__tests__/test_logger.py b/backend/src/core/logger/__tests__/test_logger.py index c93f9028..996b560d 100644 --- a/backend/src/core/logger/__tests__/test_logger.py +++ b/backend/src/core/logger/__tests__/test_logger.py @@ -43,13 +43,13 @@ def reset_logger_state(): configure_logger(config) -# [DEF:test_belief_scope_logs_entry_action_exit_at_debug:Function] +# [DEF:test_belief_scope_logs_reason_reflect_at_debug:Function] # @RELATION: BINDS_TO -> test_logger -# @PURPOSE: Test that belief_scope generates [ID][Entry], [ID][Action], and [ID][Exit] logs at DEBUG level. +# @PURPOSE: Test that belief_scope generates [REASON] and [REFLECT] logs at DEBUG level. # @PRE: belief_scope is available. caplog fixture is used. Logger configured to DEBUG. -# @POST: Logs are verified to contain Entry, Action, and Exit tags at DEBUG level. -def test_belief_scope_logs_entry_action_exit_at_debug(caplog): - """Test that belief_scope generates [ID][Entry], [ID][Action], and [ID][Exit] logs at DEBUG level.""" +# @POST: Logs are verified to contain REASON and REFLECT markers at DEBUG level. +def test_belief_scope_logs_reason_reflect_at_debug(caplog): + """Test that belief_scope generates [REASON] and [REFLECT] logs at DEBUG level.""" # Configure logger to DEBUG level config = LoggingConfig( level="DEBUG", @@ -66,23 +66,23 @@ def test_belief_scope_logs_entry_action_exit_at_debug(caplog): # Check that the logs contain the expected patterns log_messages = [record.message for record in caplog.records] - assert any("[TestFunction][Entry]" in msg for msg in log_messages), "Entry log not found" - assert any("[TestFunction][Action] Doing something important" in msg for msg in log_messages), "Action log not found" - assert any("[TestFunction][Exit]" in msg for msg in log_messages), "Exit log not found" + assert any("[REASON]" in msg and "TestFunction" in msg for msg in log_messages), "REASON log not found" + assert any("Doing something important" in msg for msg in log_messages), "Inline info log not found" + assert any("[REFLECT]" in msg and "TestFunction" in msg for msg in log_messages), "REFLECT log not found" # Reset to INFO config = LoggingConfig(level="INFO", task_log_level="INFO", enable_belief_state=True) configure_logger(config) -# [/DEF:test_belief_scope_logs_entry_action_exit_at_debug:Function] +# [/DEF:test_belief_scope_logs_reason_reflect_at_debug:Function] # [DEF:test_belief_scope_error_handling:Function] # @RELATION: BINDS_TO -> test_logger -# @PURPOSE: Test that belief_scope logs Coherence:Failed on exception. +# @PURPOSE: Test that belief_scope logs EXPLORE on exception. # @PRE: belief_scope is available. caplog fixture is used. Logger configured to DEBUG. -# @POST: Logs are verified to contain Coherence:Failed tag. +# @POST: Logs are verified to contain EXPLORE marker. def test_belief_scope_error_handling(caplog): - """Test that belief_scope logs Coherence:Failed on exception.""" + """Test that belief_scope logs EXPLORE on exception.""" # Configure logger to DEBUG level config = LoggingConfig( level="DEBUG", @@ -99,9 +99,10 @@ def test_belief_scope_error_handling(caplog): log_messages = [record.message for record in caplog.records] - assert any("[FailingFunction][Entry]" in msg for msg in log_messages), "Entry log not found" - assert any("[FailingFunction][COHERENCE:FAILED]" in msg for msg in log_messages), "Failed coherence log not found" - # Exit should not be logged on failure + assert any("[REASON]" in msg and "FailingFunction" in msg for msg in log_messages), "REASON log not found" + assert any("[EXPLORE]" in msg and "FailingFunction" in msg and "Something went wrong" in msg + for msg in log_messages), "EXPLORE log not found" + # REFLECT should not be logged on failure # Reset to INFO config = LoggingConfig(level="INFO", task_log_level="INFO", enable_belief_state=True) @@ -109,13 +110,13 @@ def test_belief_scope_error_handling(caplog): # [/DEF:test_belief_scope_error_handling:Function] -# [DEF:test_belief_scope_success_coherence:Function] +# [DEF:test_belief_scope_success_reflect:Function] # @RELATION: BINDS_TO -> test_logger -# @PURPOSE: Test that belief_scope logs Coherence:OK on success. +# @PURPOSE: Test that belief_scope logs REFLECT on success. # @PRE: belief_scope is available. caplog fixture is used. Logger configured to DEBUG. -# @POST: Logs are verified to contain Coherence:OK tag. -def test_belief_scope_success_coherence(caplog): - """Test that belief_scope logs Coherence:OK on success.""" +# @POST: Logs are verified to contain REFLECT marker. +def test_belief_scope_success_reflect(caplog): + """Test that belief_scope logs REFLECT on success.""" # Configure logger to DEBUG level config = LoggingConfig( level="DEBUG", @@ -131,19 +132,19 @@ def test_belief_scope_success_coherence(caplog): log_messages = [record.message for record in caplog.records] - assert any("[SuccessFunction][COHERENCE:OK]" in msg for msg in log_messages), "Success coherence log not found" + assert any("[REFLECT]" in msg and "SuccessFunction" in msg for msg in log_messages), "REFLECT log not found" -# [/DEF:test_belief_scope_success_coherence:Function] +# [/DEF:test_belief_scope_success_reflect:Function] # [DEF:test_belief_scope_not_visible_at_info:Function] # @RELATION: BINDS_TO -> test_logger -# @PURPOSE: Test that belief_scope Entry/Exit/Coherence logs are NOT visible at INFO level. +# @PURPOSE: Test that belief_scope REFLECT logs are NOT visible at INFO level. # @PRE: belief_scope is available. caplog fixture is used. -# @POST: Entry/Exit/Coherence logs are not captured at INFO level. +# @POST: REASON is visible at INFO (uses info()); REFLECT is not (uses debug()). def test_belief_scope_not_visible_at_info(caplog): - """Test that belief_scope Entry/Exit/Coherence logs are NOT visible at INFO level.""" + """Test that belief_scope REFLECT logs are NOT visible at INFO level.""" caplog.set_level("INFO") with belief_scope("InfoLevelFunction"): @@ -151,12 +152,12 @@ def test_belief_scope_not_visible_at_info(caplog): log_messages = [record.message for record in caplog.records] - # Action log should be visible - assert any("[InfoLevelFunction][Action] Doing something important" in msg for msg in log_messages), "Action log not found" - # Entry/Exit/Coherence should NOT be visible at INFO level - assert not any("[InfoLevelFunction][Entry]" in msg for msg in log_messages), "Entry log should not be visible at INFO" - assert not any("[InfoLevelFunction][Exit]" in msg for msg in log_messages), "Exit log should not be visible at INFO" - assert not any("[InfoLevelFunction][COHERENCE:OK]" in msg for msg in log_messages), "Coherence log should not be visible at INFO" + # Inline INFO log should be visible + assert any("Doing something important" in msg for msg in log_messages), "INFO log not found" + # REASON uses info() → visible at INFO level + assert any("[REASON]" in msg and "InfoLevelFunction" in msg for msg in log_messages), "REASON log should be visible at INFO" + # REFLECT uses debug() → NOT visible at INFO level + assert not any("[REFLECT]" in msg for msg in log_messages), "REFLECT log should not be visible at INFO" # [/DEF:test_belief_scope_not_visible_at_info:Function] @@ -210,9 +211,9 @@ def test_configure_logger_task_log_level(): # @RELATION: BINDS_TO -> test_logger # @PURPOSE: Test that enable_belief_state flag controls belief_scope logging. # @PRE: LoggingConfig is available. caplog fixture is used. -# @POST: belief_scope logs are controlled by the flag. +# @POST: belief_scope explicit REASON logs are controlled by the flag; REFLECT always logged. def test_enable_belief_state_flag(caplog): - """Test that enable_belief_state flag controls belief_scope logging.""" + """Test that enable_belief_state flag controls belief_scope REASON entry logging.""" # Disable belief state config = LoggingConfig( level="DEBUG", @@ -228,11 +229,10 @@ def test_enable_belief_state_flag(caplog): log_messages = [record.message for record in caplog.records] - # Entry and Exit should NOT be logged when disabled - assert not any("[DisabledFunction][Entry]" in msg for msg in log_messages), "Entry should not be logged when disabled" - assert not any("[DisabledFunction][Exit]" in msg for msg in log_messages), "Exit should not be logged when disabled" - # Coherence:OK should still be logged (internal tracking) - assert any("[DisabledFunction][COHERENCE:OK]" in msg for msg in log_messages), "Coherence should still be logged" + # "Entering DisabledFunction" (explicit logger.reason()) should NOT be logged when disabled + assert not any("Entering" in msg for msg in log_messages), "REASON entry should not be logged when disabled" + # REFLECT should still be logged (internal tracking, not gated by _enable_belief_state) + assert any("[REFLECT]" in msg for msg in log_messages), "REFLECT should still be logged" # [/DEF:test_enable_belief_state_flag:Function] diff --git a/backend/src/core/mapping_service.py b/backend/src/core/mapping_service.py index a9652eaa..5081e30f 100644 --- a/backend/src/core/mapping_service.py +++ b/backend/src/core/mapping_service.py @@ -110,7 +110,7 @@ class IdMappingService: """ with belief_scope("IdMappingService.sync_environment"): logger.info( - f"[IdMappingService.sync_environment][Action] Starting sync for environment {environment_id} (incremental={incremental})" + f"[IdMappingService.sync_environment][REASON] Starting sync for environment {environment_id} (incremental={incremental})" ) # Implementation Note: In a real scenario, superset_client needs to be an instance @@ -224,7 +224,7 @@ class IdMappingService: if deleted: total_deleted += deleted logger.info( - f"[IdMappingService.sync_environment][Action] Removed {deleted} stale {endpoint} mapping(s) for {environment_id}" + f"[IdMappingService.sync_environment][REASON] Removed {deleted} stale {endpoint} mapping(s) for {environment_id}" ) except Exception as loop_e: diff --git a/backend/src/core/superset_client/_base.py b/backend/src/core/superset_client/_base.py index 44b3f424..e8e6f3b9 100644 --- a/backend/src/core/superset_client/_base.py +++ b/backend/src/core/superset_client/_base.py @@ -299,7 +299,7 @@ class SupersetClientBase: pagination_options={"base_query": validated, "results_field": "result"}, ) app_logger.info( - "[get_all_resources][Exit] Fetched %d %s resources.", + "[get_all_resources][REFLECT] Fetched %d %s resources.", len(data), resource_type, ) diff --git a/backend/src/core/superset_client/_dashboards_crud.py b/backend/src/core/superset_client/_dashboards_crud.py index 3a2da608..1ad0940b 100644 --- a/backend/src/core/superset_client/_dashboards_crud.py +++ b/backend/src/core/superset_client/_dashboards_crud.py @@ -292,7 +292,7 @@ class SupersetDashboardsCrudMixin: self._validate_export_response(response, dashboard_id) filename = self._resolve_export_filename(response, dashboard_id) app_logger.info( - "[export_dashboard][Exit] Exported dashboard %s to %s.", + "[export_dashboard][REFLECT] Exported dashboard %s to %s.", dashboard_id, filename, ) return response.content, filename diff --git a/backend/src/core/superset_client/_dashboards_list.py b/backend/src/core/superset_client/_dashboards_list.py index 02090676..af02316b 100644 --- a/backend/src/core/superset_client/_dashboards_list.py +++ b/backend/src/core/superset_client/_dashboards_list.py @@ -39,7 +39,7 @@ class SupersetDashboardsListMixin: }, ) total_count = len(paginated_data) - app_logger.info("[get_dashboards][Exit] Found %d dashboards.", total_count) + app_logger.info("[get_dashboards][REFLECT] Found %d dashboards.", total_count) return total_count, paginated_data # [/DEF:SupersetClientGetDashboards:Function] diff --git a/backend/src/core/superset_client/_databases.py b/backend/src/core/superset_client/_databases.py index 07a1fb94..08dd55c4 100644 --- a/backend/src/core/superset_client/_databases.py +++ b/backend/src/core/superset_client/_databases.py @@ -33,7 +33,7 @@ class SupersetDatabasesMixin: }, ) total_count = len(paginated_data) - app_logger.info("[get_databases][Exit] Found %d databases.", total_count) + app_logger.info("[get_databases][REFLECT] Found %d databases.", total_count) return total_count, paginated_data # [/DEF:SupersetClientGetDatabases:Function] @@ -49,7 +49,7 @@ class SupersetDatabasesMixin: method="GET", endpoint=f"/database/{database_id}" ) response = cast(Dict, response) - app_logger.info("[get_database][Exit] Got database %s.", database_id) + app_logger.info("[get_database][REFLECT] Got database %s.", database_id) return response # [/DEF:SupersetClientGetDatabase:Function] diff --git a/backend/src/core/superset_client/_datasets.py b/backend/src/core/superset_client/_datasets.py index b2ffc8fd..08579dd8 100644 --- a/backend/src/core/superset_client/_datasets.py +++ b/backend/src/core/superset_client/_datasets.py @@ -32,7 +32,7 @@ class SupersetDatasetsMixin: }, ) total_count = len(paginated_data) - app_logger.info("[get_datasets][Exit] Found %d datasets.", total_count) + app_logger.info("[get_datasets][REFLECT] Found %d datasets.", total_count) return total_count, paginated_data # [/DEF:SupersetClientGetDatasets:Function] @@ -169,7 +169,7 @@ class SupersetDatasetsMixin: } app_logger.info( - f"[get_dataset_detail][Exit] Got dataset {dataset_id} with {len(column_info)} columns and {len(linked_dashboards)} linked dashboards" + f"[get_dataset_detail][REFLECT] Got dataset {dataset_id} with {len(column_info)} columns and {len(linked_dashboards)} linked dashboards" ) return result @@ -186,7 +186,7 @@ class SupersetDatasetsMixin: method="GET", endpoint=f"/dataset/{dataset_id}" ) response = cast(Dict, response) - app_logger.info("[get_dataset][Exit] Got dataset %s.", dataset_id) + app_logger.info("[get_dataset][REFLECT] Got dataset %s.", dataset_id) return response # [/DEF:SupersetClientGetDataset:Function] @@ -206,7 +206,7 @@ class SupersetDatasetsMixin: headers={"Content-Type": "application/json"}, ) response = cast(Dict, response) - app_logger.info("[update_dataset][Exit] Updated dataset %s.", dataset_id) + app_logger.info("[update_dataset][REFLECT] Updated dataset %s.", dataset_id) return response # [/DEF:SupersetClientUpdateDataset:Function] diff --git a/backend/src/core/utils/async_network.py b/backend/src/core/utils/async_network.py index 73350cb9..da82595b 100644 --- a/backend/src/core/utils/async_network.py +++ b/backend/src/core/utils/async_network.py @@ -149,7 +149,7 @@ class AsyncAPIClient: } self._authenticated = True SupersetAuthCache.set(self._auth_cache_key, self._tokens) - app_logger.info("[async_authenticate][Exit] Authenticated successfully.") + app_logger.info("[async_authenticate][REFLECT] Authenticated successfully.") return self._tokens except httpx.HTTPStatusError as exc: SupersetAuthCache.invalidate(self._auth_cache_key) diff --git a/backend/src/core/utils/fileio.py b/backend/src/core/utils/fileio.py index 80b85a79..a612298a 100644 --- a/backend/src/core/utils/fileio.py +++ b/backend/src/core/utils/fileio.py @@ -81,7 +81,7 @@ def remove_empty_directories(root_dir: str) -> int: app_logger.info("[remove_empty_directories][State] Removed empty directory: %s", current_dir) except OSError as e: app_logger.error("[remove_empty_directories][Failure] Failed to remove %s: %s", current_dir, e) - app_logger.info("[remove_empty_directories][Exit] Removed %d empty directories.", removed_count) + app_logger.info("[remove_empty_directories][REFLECT] Removed %d empty directories.", removed_count) return removed_count # #endregion remove_empty_directories @@ -354,7 +354,7 @@ def create_dashboard_export(zip_path: Union[str, Path], source_paths: List[Union if item.is_file() and item.suffix.lower() not in exclude_ext: arcname = item.relative_to(src_path.parent) zipf.write(item, arcname) - app_logger.info("[create_dashboard_export][Exit] Archive created: %s", zip_path) + app_logger.info("[create_dashboard_export][REFLECT] Archive created: %s", zip_path) return True except (IOError, zipfile.BadZipFile, AssertionError) as e: app_logger.error("[create_dashboard_export][Failure] Error: %s", e, exc_info=True) diff --git a/backend/src/core/utils/network.py b/backend/src/core/utils/network.py index e7910d8a..16dad70d 100644 --- a/backend/src/core/utils/network.py +++ b/backend/src/core/utils/network.py @@ -162,7 +162,7 @@ class APIClient: # @POST: APIClient instance is initialized with a session. def __init__(self, config: Dict[str, Any], verify_ssl: bool = True, timeout: int = DEFAULT_TIMEOUT): with belief_scope("__init__"): - app_logger.info("[APIClient.__init__][Entry] Initializing APIClient.") + app_logger.info("[APIClient.__init__][REASON] Initializing APIClient.") self.base_url: str = self._normalize_base_url(config.get("base_url", "")) self.api_base_url: str = f"{self.base_url}/api/v1" self.auth = config.get("auth") @@ -175,7 +175,7 @@ class APIClient: verify_ssl, ) self._authenticated = False - app_logger.info("[APIClient.__init__][Exit] APIClient initialized.") + app_logger.info("[APIClient.__init__][REFLECT] APIClient initialized.") # [/DEF:APIClient.__init__:Function] # [DEF:_init_session:Function] @@ -291,7 +291,7 @@ class APIClient: self._tokens = {"access_token": access_token, "csrf_token": csrf_response.json()["result"]} self._authenticated = True SupersetAuthCache.set(self._auth_cache_key, self._tokens) - app_logger.info("[authenticate][Exit] Authenticated successfully.") + app_logger.info("[authenticate][REFLECT] Authenticated successfully.") return self._tokens except requests.exceptions.HTTPError as e: SupersetAuthCache.invalidate(self._auth_cache_key) diff --git a/backend/src/plugins/git_plugin.py b/backend/src/plugins/git_plugin.py index 746993df..8a2b4e7a 100644 --- a/backend/src/plugins/git_plugin.py +++ b/backend/src/plugins/git_plugin.py @@ -134,7 +134,7 @@ class GitPlugin(PluginBase): # @POST: Плагин готов к выполнению задач. async def initialize(self): with belief_scope("GitPlugin.initialize"): - app_logger.info("[GitPlugin.initialize][Action] Initializing Git Integration Plugin logic.") + app_logger.info("[GitPlugin.initialize][REASON] Initializing Git Integration Plugin logic.") # [DEF:execute:Function] # @PURPOSE: Основной метод выполнения задач плагина с поддержкой TaskContext. @@ -245,9 +245,9 @@ class GitPlugin(PluginBase): # 5. Автоматический staging изменений (не коммит, чтобы юзер мог проверить diff) try: repo.git.add(A=True) - app_logger.info("[_handle_sync][Action] Changes staged in git") + app_logger.info("[_handle_sync][REASON] Changes staged in git") except Exception as ge: - app_logger.warning(f"[_handle_sync][Action] Failed to stage changes: {ge}") + app_logger.warning(f"[_handle_sync][REASON] Failed to stage changes: {ge}") app_logger.info(f"[_handle_sync][Coherence:OK] Dashboard {dashboard_id} synced successfully.") return {"status": "success", "message": "Dashboard synced and flattened in local repository"} @@ -315,7 +315,7 @@ class GitPlugin(PluginBase): f.write(zip_buffer.getvalue()) try: - app_logger.info(f"[_handle_deploy][Action] Importing dashboard to {env.name}") + app_logger.info(f"[_handle_deploy][REASON] Importing dashboard to {env.name}") result = client.import_dashboard(temp_zip_path) app_logger.info(f"[_handle_deploy][Coherence:OK] Deployment successful for dashboard {dashboard_id}.") return {"status": "success", "message": f"Dashboard deployed to {env.name}", "details": result} @@ -336,13 +336,13 @@ class GitPlugin(PluginBase): # @RETURN: Environment - Объект конфигурации окружения. def _get_env(self, env_id: Optional[str] = None): with belief_scope("GitPlugin._get_env"): - app_logger.info(f"[_get_env][Entry] Fetching environment for ID: {env_id}") + app_logger.info(f"[_get_env][REASON] Fetching environment for ID: {env_id}") # Priority 1: ConfigManager (config.json) if env_id: env = self.config_manager.get_environment(env_id) if env: - app_logger.info(f"[_get_env][Exit] Found environment by ID in ConfigManager: {env.name}") + app_logger.info(f"[_get_env][REFLECT] Found environment by ID in ConfigManager: {env.name}") return env # Priority 2: Database (DeploymentEnvironment) @@ -360,7 +360,7 @@ class GitPlugin(PluginBase): db_env = db.query(DeploymentEnvironment).first() if db_env: - app_logger.info(f"[_get_env][Exit] Found environment in DB: {db_env.name}") + app_logger.info(f"[_get_env][REFLECT] Found environment in DB: {db_env.name}") from src.core.config_models import Environment # Use token as password for SupersetClient return Environment( @@ -382,11 +382,11 @@ class GitPlugin(PluginBase): # but we have other envs, maybe it's one of them? env = next((e for e in envs if e.id == env_id), None) if env: - app_logger.info(f"[_get_env][Exit] Found environment {env_id} in ConfigManager list") + app_logger.info(f"[_get_env][REFLECT] Found environment {env_id} in ConfigManager list") return env if not env_id: - app_logger.info(f"[_get_env][Exit] Using first environment from ConfigManager: {envs[0].name}") + app_logger.info(f"[_get_env][REFLECT] Using first environment from ConfigManager: {envs[0].name}") return envs[0] app_logger.error(f"[_get_env][Coherence:Failed] No environments configured (searched config.json and DB). env_id={env_id}") diff --git a/backend/src/plugins/storage/plugin.py b/backend/src/plugins/storage/plugin.py index 7380d49c..a445e991 100644 --- a/backend/src/plugins/storage/plugin.py +++ b/backend/src/plugins/storage/plugin.py @@ -186,7 +186,7 @@ class StoragePlugin(PluginBase): # Use singular name for consistency with BackupPlugin and GitService path = root / category.value path.mkdir(parents=True, exist_ok=True) - logger.debug(f"[StoragePlugin][Action] Ensured directory: {path}") + logger.debug(f"[StoragePlugin][REASON] Ensured directory: {path}") # [/DEF:ensure_directories:Function] # [DEF:validate_path:Function] @@ -222,7 +222,7 @@ class StoragePlugin(PluginBase): with belief_scope("StoragePlugin:list_files"): root = self.get_storage_root() logger.info( - f"[StoragePlugin][Action] Listing files in root: {root}, category: {category}, subpath: {subpath}, recursive: {recursive}" + f"[StoragePlugin][REASON] Listing files in root: {root}, category: {category}, subpath: {subpath}, recursive: {recursive}" ) files = [] @@ -258,7 +258,7 @@ class StoragePlugin(PluginBase): if not target_dir.exists(): continue - logger.debug(f"[StoragePlugin][Action] Scanning directory: {target_dir}") + logger.debug(f"[StoragePlugin][REASON] Scanning directory: {target_dir}") if recursive: for current_root, dirs, filenames in os.walk(target_dir): @@ -358,7 +358,7 @@ class StoragePlugin(PluginBase): shutil.rmtree(full_path) else: full_path.unlink() - logger.info(f"[StoragePlugin][Action] Deleted: {full_path}") + logger.info(f"[StoragePlugin][REASON] Deleted: {full_path}") else: raise FileNotFoundError(f"Item {path} not found") # [/DEF:delete_file:Function] diff --git a/backend/src/scripts/migrate_sqlite_to_postgres.py b/backend/src/scripts/migrate_sqlite_to_postgres.py index 072acd78..60fae862 100644 --- a/backend/src/scripts/migrate_sqlite_to_postgres.py +++ b/backend/src/scripts/migrate_sqlite_to_postgres.py @@ -165,7 +165,7 @@ def _migrate_config(engine, legacy_config_path: Optional[Path]) -> int: with belief_scope("_migrate_config"): if legacy_config_path is None: logger.info( - "[_migrate_config][Action] No legacy config.json found, skipping" + "[_migrate_config][REASON] No legacy config.json found, skipping" ) return 0 @@ -328,7 +328,7 @@ def run_migration( ) -> Dict[str, int]: with belief_scope("run_migration"): logger.info( - "[run_migration][Entry] sqlite=%s target=%s", sqlite_path, target_url + "[run_migration][REASON] sqlite=%s target=%s", sqlite_path, target_url ) if not sqlite_path.exists(): raise FileNotFoundError(f"SQLite source not found: {sqlite_path}") diff --git a/backend/src/scripts/seed_superset_load_test.py b/backend/src/scripts/seed_superset_load_test.py index b117d785..c03a83de 100644 --- a/backend/src/scripts/seed_superset_load_test.py +++ b/backend/src/scripts/seed_superset_load_test.py @@ -382,7 +382,7 @@ def main() -> None: args = _parse_args() result = seed_superset_load_data(args) logger.info( - f"[COHERENCE:OK] Result summary: {json.dumps(result, ensure_ascii=True)}" + f"[REFLECT] Result summary: {json.dumps(result, ensure_ascii=True)}" ) diff --git a/backend/src/services/git/_base.py b/backend/src/services/git/_base.py index 63b3d186..12622f09 100644 --- a/backend/src/services/git/_base.py +++ b/backend/src/services/git/_base.py @@ -133,7 +133,7 @@ class GitServiceBase: if source_abs == target_abs: return source_abs if os.path.exists(target_abs): - logger.warning(f"[_migrate_repo_directory][Action] Target already exists, keeping source path: {target_abs}") + logger.warning(f"[_migrate_repo_directory][REASON] Target already exists, keeping source path: {target_abs}") return source_abs Path(target_abs).parent.mkdir(parents=True, exist_ok=True) try: @@ -210,11 +210,11 @@ class GitServiceBase: else: auth_url = remote_url if os.path.exists(repo_path): - logger.info(f"[init_repo][Action] Opening existing repo at {repo_path}") + logger.info(f"[init_repo][REASON] Opening existing repo at {repo_path}") try: repo = Repo(repo_path) except (InvalidGitRepositoryError, NoSuchPathError): - logger.warning(f"[init_repo][Action] Existing path is not a Git repository, recreating: {repo_path}") + logger.warning(f"[init_repo][REASON] Existing path is not a Git repository, recreating: {repo_path}") stale_path = Path(repo_path) if stale_path.exists(): shutil.rmtree(stale_path, ignore_errors=True) @@ -226,7 +226,7 @@ class GitServiceBase: repo = Repo.clone_from(auth_url, repo_path) self._ensure_gitflow_branches(repo, dashboard_id) return repo - logger.info(f"[init_repo][Action] Cloning {remote_url} to {repo_path}") + logger.info(f"[init_repo][REASON] Cloning {remote_url} to {repo_path}") repo = Repo.clone_from(auth_url, repo_path) self._ensure_gitflow_branches(repo, dashboard_id) return repo @@ -307,7 +307,7 @@ class GitServiceBase: with repo.config_writer(config_level="repository") as config_writer: config_writer.set_value("user", "name", normalized_username) config_writer.set_value("user", "email", normalized_email) - logger.info("[configure_identity][Action] Applied repository-local git identity for dashboard %s", dashboard_id) + logger.info("[configure_identity][REASON] Applied repository-local git identity for dashboard %s", dashboard_id) except Exception as e: logger.error(f"[configure_identity][Coherence:Failed] Failed to configure git identity: {e}") raise HTTPException(status_code=500, detail=f"Failed to configure git identity: {str(e)}") diff --git a/backend/src/services/git/_branch.py b/backend/src/services/git/_branch.py index c886559a..b04a1f2c 100644 --- a/backend/src/services/git/_branch.py +++ b/backend/src/services/git/_branch.py @@ -32,24 +32,24 @@ class GitServiceBranchMixin: base_commit = local_heads["main"].commit if base_commit is None: logger.warning( - f"[_ensure_gitflow_branches][Action] Skipping branch bootstrap for dashboard {dashboard_id}: repository has no commits" + f"[_ensure_gitflow_branches][REASON] Skipping branch bootstrap for dashboard {dashboard_id}: repository has no commits" ) return if "main" not in local_heads: local_heads["main"] = repo.create_head("main", base_commit) - logger.info(f"[_ensure_gitflow_branches][Action] Created local branch main for dashboard {dashboard_id}") + logger.info(f"[_ensure_gitflow_branches][REASON] Created local branch main for dashboard {dashboard_id}") for branch_name in ("dev", "preprod"): if branch_name in local_heads: continue local_heads[branch_name] = repo.create_head(branch_name, local_heads["main"].commit) logger.info( - f"[_ensure_gitflow_branches][Action] Created local branch {branch_name} for dashboard {dashboard_id}" + f"[_ensure_gitflow_branches][REASON] Created local branch {branch_name} for dashboard {dashboard_id}" ) try: origin = repo.remote(name="origin") except ValueError: logger.info( - f"[_ensure_gitflow_branches][Action] Remote origin is not configured for dashboard {dashboard_id}; skipping remote branch creation" + f"[_ensure_gitflow_branches][REASON] Remote origin is not configured for dashboard {dashboard_id}; skipping remote branch creation" ) return remote_branch_names = set() @@ -60,14 +60,14 @@ class GitServiceBranchMixin: if remote_head: remote_branch_names.add(str(remote_head)) except Exception as e: - logger.warning(f"[_ensure_gitflow_branches][Action] Failed to fetch origin refs: {e}") + logger.warning(f"[_ensure_gitflow_branches][REASON] Failed to fetch origin refs: {e}") for branch_name in required_branches: if branch_name in remote_branch_names: continue try: origin.push(refspec=f"{branch_name}:{branch_name}") logger.info( - f"[_ensure_gitflow_branches][Action] Pushed branch {branch_name} to origin for dashboard {dashboard_id}" + f"[_ensure_gitflow_branches][REASON] Pushed branch {branch_name} to origin for dashboard {dashboard_id}" ) except Exception as e: logger.error(f"[_ensure_gitflow_branches][Coherence:Failed] Failed to push branch {branch_name} to origin: {e}") @@ -77,9 +77,9 @@ class GitServiceBranchMixin: ) try: repo.git.checkout("dev") - logger.info(f"[_ensure_gitflow_branches][Action] Checked out default branch dev for dashboard {dashboard_id}") + logger.info(f"[_ensure_gitflow_branches][REASON] Checked out default branch dev for dashboard {dashboard_id}") except Exception as e: - logger.warning(f"[_ensure_gitflow_branches][Action] Could not checkout dev branch for dashboard {dashboard_id}: {e}") + logger.warning(f"[_ensure_gitflow_branches][REASON] Could not checkout dev branch for dashboard {dashboard_id}: {e}") # [/DEF:_ensure_gitflow_branches:Function] # [DEF:list_branches:Function] @@ -90,7 +90,7 @@ class GitServiceBranchMixin: def list_branches(self, dashboard_id: int) -> List[dict]: with belief_scope("GitService.list_branches"): repo = self.get_repo(dashboard_id) - logger.info(f"[list_branches][Action] Listing branches for {dashboard_id}. Refs: {repo.refs}") + logger.info(f"[list_branches][REASON] Listing branches for {dashboard_id}. Refs: {repo.refs}") branches = [] for ref in repo.refs: try: @@ -104,7 +104,7 @@ class GitServiceBranchMixin: "last_updated": datetime.fromtimestamp(ref.commit.committed_date) if hasattr(ref, 'commit') else datetime.utcnow() }) except Exception as e: - logger.warning(f"[list_branches][Action] Skipping ref {ref}: {e}") + logger.warning(f"[list_branches][REASON] Skipping ref {ref}: {e}") try: active_name = repo.active_branch.name if not any(b['name'] == active_name for b in branches): @@ -113,7 +113,7 @@ class GitServiceBranchMixin: "is_remote": False, "last_updated": datetime.utcnow() }) except Exception as e: - logger.warning(f"[list_branches][Action] Could not determine active branch: {e}") + logger.warning(f"[list_branches][REASON] Could not determine active branch: {e}") if not branches: branches.append({ "name": "dev", "commit_hash": "0000000", @@ -131,9 +131,9 @@ class GitServiceBranchMixin: def create_branch(self, dashboard_id: int, name: str, from_branch: str = "main"): with belief_scope("GitService.create_branch"): repo = self.get_repo(dashboard_id) - logger.info(f"[create_branch][Action] Creating branch {name} from {from_branch}") + logger.info(f"[create_branch][REASON] Creating branch {name} from {from_branch}") if not repo.heads and not repo.remotes: - logger.warning("[create_branch][Action] Repository is empty. Creating initial commit to enable branching.") + logger.warning("[create_branch][REASON] Repository is empty. Creating initial commit to enable branching.") readme_path = os.path.join(repo.working_dir, "README.md") if not os.path.exists(readme_path): with open(readme_path, "w") as f: @@ -143,7 +143,7 @@ class GitServiceBranchMixin: try: repo.commit(from_branch) except Exception: - logger.warning(f"[create_branch][Action] Source branch {from_branch} not found, using HEAD") + logger.warning(f"[create_branch][REASON] Source branch {from_branch} not found, using HEAD") from_branch = repo.head try: new_branch = repo.create_head(name, from_branch) @@ -160,7 +160,7 @@ class GitServiceBranchMixin: def checkout_branch(self, dashboard_id: int, name: str): with belief_scope("GitService.checkout_branch"): repo = self.get_repo(dashboard_id) - logger.info(f"[checkout_branch][Action] Checking out branch {name}") + logger.info(f"[checkout_branch][REASON] Checking out branch {name}") repo.git.checkout(name) # [/DEF:checkout_branch:Function] @@ -174,13 +174,13 @@ class GitServiceBranchMixin: with belief_scope("GitService.commit_changes"): repo = self.get_repo(dashboard_id) if not repo.is_dirty(untracked_files=True) and not files: - logger.info(f"[commit_changes][Action] No changes to commit for dashboard {dashboard_id}") + logger.info(f"[commit_changes][REASON] No changes to commit for dashboard {dashboard_id}") return if files: - logger.info(f"[commit_changes][Action] Staging files: {files}") + logger.info(f"[commit_changes][REASON] Staging files: {files}") repo.index.add(files) else: - logger.info("[commit_changes][Action] Staging all changes") + logger.info("[commit_changes][REASON] Staging all changes") repo.git.add(A=True) repo.index.commit(message) logger.info(f"[commit_changes][Coherence:OK] Committed changes with message: {message}") diff --git a/backend/src/services/git/_gitea.py b/backend/src/services/git/_gitea.py index 62f014dd..536eb68b 100644 --- a/backend/src/services/git/_gitea.py +++ b/backend/src/services/git/_gitea.py @@ -23,7 +23,7 @@ class GitServiceGiteaMixin: async def test_connection(self, provider: GitProvider, url: str, pat: str) -> bool: with belief_scope("GitService.test_connection"): if ".local" in url or "localhost" in url: - logger.info("[test_connection][Action] Local/Offline mode detected for URL") + logger.info("[test_connection][REASON] Local/Offline mode detected for URL") return True if not url.startswith(('http://', 'https://')): logger.error(f"[test_connection][Coherence:Failed] Invalid URL protocol: {url}") @@ -221,7 +221,7 @@ class GitServiceGiteaMixin: ) if should_retry_with_fallback: logger.warning( - "[create_gitea_pull_request][Action] Primary Gitea URL not found, retrying with remote host: %s", + "[create_gitea_pull_request][REASON] Primary Gitea URL not found, retrying with remote host: %s", fallback_url, ) active_server_url = fallback_url diff --git a/backend/src/services/git/_status.py b/backend/src/services/git/_status.py index 7adbf481..febdb21f 100644 --- a/backend/src/services/git/_status.py +++ b/backend/src/services/git/_status.py @@ -153,7 +153,7 @@ class GitServiceStatusMixin: "files_changed": list(commit.stats.files.keys()) }) except Exception as e: - logger.warning(f"[get_commit_history][Action] Could not retrieve commit history for dashboard {dashboard_id}: {e}") + logger.warning(f"[get_commit_history][REASON] Could not retrieve commit history for dashboard {dashboard_id}: {e}") return [] return commits # [/DEF:get_commit_history:Function] diff --git a/backend/src/services/git/_sync.py b/backend/src/services/git/_sync.py index d0d429d4..99de1982 100644 --- a/backend/src/services/git/_sync.py +++ b/backend/src/services/git/_sync.py @@ -61,7 +61,7 @@ class GitServiceSyncMixin: session.close() except Exception as diag_error: logger.warning( - "[push_changes][Action] Failed to load repository binding diagnostics for dashboard %s: %s", + "[push_changes][REASON] Failed to load repository binding diagnostics for dashboard %s: %s", dashboard_id, diag_error, ) realigned_origin_url = self._align_origin_host_with_config( @@ -76,12 +76,12 @@ class GitServiceSyncMixin: except Exception: origin_urls = [] logger.info( - "[push_changes][Action] Push diagnostics dashboard=%s config_id=%s config_url=%s binding_remote_url=%s origin_urls=%s origin_realigned=%s", + "[push_changes][REASON] Push diagnostics dashboard=%s config_id=%s config_url=%s binding_remote_url=%s origin_urls=%s origin_realigned=%s", dashboard_id, binding_config_id, binding_config_url, binding_remote_url, origin_urls, bool(realigned_origin_url), ) try: current_branch = repo.active_branch - logger.info(f"[push_changes][Action] Pushing branch {current_branch.name} to origin") + logger.info(f"[push_changes][REASON] Pushing branch {current_branch.name} to origin") tracking_branch = None try: tracking_branch = current_branch.tracking_branch() @@ -121,7 +121,7 @@ class GitServiceSyncMixin: if os.path.exists(merge_head_path): payload = self._build_unfinished_merge_payload(repo) logger.warning( - "[pull_changes][Action] Unfinished merge detected for dashboard %s (repo_path=%s git_dir=%s branch=%s merge_head=%s merge_msg=%s)", + "[pull_changes][REASON] Unfinished merge detected for dashboard %s (repo_path=%s git_dir=%s branch=%s merge_head=%s merge_msg=%s)", dashboard_id, payload["repository_path"], payload["git_dir"], payload["current_branch"], payload["merge_head"], payload["merge_message_preview"], ) @@ -134,14 +134,14 @@ class GitServiceSyncMixin: except Exception: origin_urls = [] logger.info( - "[pull_changes][Action] Pull diagnostics dashboard=%s repo_path=%s branch=%s origin_urls=%s", + "[pull_changes][REASON] Pull diagnostics dashboard=%s repo_path=%s branch=%s origin_urls=%s", dashboard_id, repo.working_tree_dir, current_branch, origin_urls, ) origin.fetch(prune=True) remote_ref = f"origin/{current_branch}" has_remote_branch = any(ref.name == remote_ref for ref in repo.refs) logger.info( - "[pull_changes][Action] Pull remote branch check dashboard=%s branch=%s remote_ref=%s exists=%s", + "[pull_changes][REASON] Pull remote branch check dashboard=%s branch=%s remote_ref=%s exists=%s", dashboard_id, current_branch, remote_ref, has_remote_branch, ) if not has_remote_branch: @@ -149,7 +149,7 @@ class GitServiceSyncMixin: status_code=409, detail=f"Remote branch '{current_branch}' does not exist yet. Push this branch first.", ) - logger.info(f"[pull_changes][Action] Pulling changes from origin/{current_branch}") + logger.info(f"[pull_changes][REASON] Pulling changes from origin/{current_branch}") repo.git.pull("--no-rebase", "origin", current_branch) except ValueError: logger.error(f"[pull_changes][Coherence:Failed] Remote 'origin' not found for dashboard {dashboard_id}") diff --git a/backend/src/services/git/_url.py b/backend/src/services/git/_url.py index 0c455325..f3c49408 100644 --- a/backend/src/services/git/_url.py +++ b/backend/src/services/git/_url.py @@ -116,7 +116,7 @@ class GitServiceUrlMixin: if not aligned_url: return None logger.warning( - "[_align_origin_host_with_config][Action] Host mismatch for dashboard %s: config_host=%s origin_host=%s, applying origin.set_url", + "[_align_origin_host_with_config][REASON] Host mismatch for dashboard %s: config_host=%s origin_host=%s, applying origin.set_url", dashboard_id, config_host, origin_host, ) try: @@ -142,7 +142,7 @@ class GitServiceUrlMixin: session.close() except Exception as e: logger.warning( - "[_align_origin_host_with_config][Action] Failed to persist aligned remote_url for dashboard %s: %s", + "[_align_origin_host_with_config][REASON] Failed to persist aligned remote_url for dashboard %s: %s", dashboard_id, e, ) return aligned_url diff --git a/backend/src/services/resource_service.py b/backend/src/services/resource_service.py index ccfcaff6..e446f7a4 100644 --- a/backend/src/services/resource_service.py +++ b/backend/src/services/resource_service.py @@ -28,7 +28,7 @@ class ResourceService: def __init__(self): with belief_scope("ResourceService.__init__"): self.git_service = GitService() - logger.info("[ResourceService][Action] Initialized ResourceService") + logger.info("[ResourceService][REASON] Initialized ResourceService") # [/DEF:ResourceService_init:Function] # [DEF:get_dashboards_with_status:Function]