Repository: cppa-cursor-browser
Assignee: Brad @bradjin8
Points: 3
Severity: High
Problem
Errors that survive the except Exception: pass discard layer arrive at the service tier as unstructured print() statements — e.g., in services/workspace_tabs.py and services/workspace_listing.py. These prints carry no severity level, no structured fields, and no correlation to the triggering request. In a production deployment behind a WSGI server (gunicorn, as documented in DEPLOYMENT.md), print() output may route to stdout, a log file, or nowhere, depending on capture configuration. The project's own SchemaError demonstrates that structured error design is understood — it was not applied to the parse-and-assemble layer where errors are most frequent.
Acceptance Criteria
Implementation Notes
This item naturally pairs with item 1 (except-pass replacement). In each affected file, add import logging and logger = logging.getLogger(__name__) at the top. Replace print(f"Error parsing composer {cid}: {e}") with logger.error("Failed to parse composer %s: %s", cid, e, exc_info=True). The exc_info=True parameter captures the full traceback without requiring a separate traceback.print_exc() call. In the Flask app factory, configure logging.basicConfig(level=logging.INFO) as a default. The DEPLOYMENT.md threading matrix already documents gunicorn deployment — ensure the logging guidance is compatible with gunicorn's log capture.
References
- Eval finding: Test 10 (Error Reporting / Observability) — part of the "Silent Failure Chain" compound
- Related files:
services/workspace_tabs.py, services/workspace_listing.py, services/workspace_resolver.py, app.py
Repository: cppa-cursor-browser
Assignee: Brad @bradjin8
Points: 3
Severity: High
Problem
Errors that survive the
except Exception: passdiscard layer arrive at the service tier as unstructuredprint()statements — e.g., inservices/workspace_tabs.pyandservices/workspace_listing.py. These prints carry no severity level, no structured fields, and no correlation to the triggering request. In a production deployment behind a WSGI server (gunicorn, as documented inDEPLOYMENT.md),print()output may route to stdout, a log file, or nowhere, depending on capture configuration. The project's ownSchemaErrordemonstrates that structured error design is understood — it was not applied to the parse-and-assemble layer where errors are most frequent.Acceptance Criteria
print(f"Error ...")andprint(f"Warning ...")calls inservices/are replaced withlogging.error()orlogging.warning()callslogger = logging.getLogger(__name__)app.pyor the Flask app factory) if one does not already existprint()calls for error reporting remain inservices/orapi/directoriesImplementation Notes
This item naturally pairs with item 1 (except-pass replacement). In each affected file, add
import loggingandlogger = logging.getLogger(__name__)at the top. Replaceprint(f"Error parsing composer {cid}: {e}")withlogger.error("Failed to parse composer %s: %s", cid, e, exc_info=True). Theexc_info=Trueparameter captures the full traceback without requiring a separatetraceback.print_exc()call. In the Flask app factory, configurelogging.basicConfig(level=logging.INFO)as a default. TheDEPLOYMENT.mdthreading matrix already documents gunicorn deployment — ensure the logging guidance is compatible with gunicorn's log capture.References
services/workspace_tabs.py,services/workspace_listing.py,services/workspace_resolver.py,app.py