fix: use typed ToolExecutionData accessor in _first_pass (#1030)#1053
fix: use typed ToolExecutionData accessor in _first_pass (#1030)#1053
ToolExecutionData accessor in _first_pass (#1030)#1053Conversation
Replace raw dict access + isinstance check with the typed ev.as_tool_execution().model accessor in _first_pass, matching the pattern used by other event types in the same function. The raw dict access bypassed ToolExecutionData validation, risking silent contract divergence if the model field shape ever changes. The typed accessor ensures tool_model extraction follows the same Pydantic-validated path as all other event data. Wrap with try/except (ValidationError, ValueError) consistent with error handling used elsewhere in _first_pass for other event types. Tests: - Add test_first_pass_tool_model_from_typed_accessor: validates tool_model is correctly populated via the typed accessor. - Add test_first_pass_tool_model_validation_error: malformed data with a valid model string but invalid toolTelemetry is rejected by Pydantic validation, leaving tool_model as None. - Remove test_no_pydantic_validation_for_tool_model: no longer applicable since the fix intentionally uses Pydantic validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Updates the session summary “first pass” parsing to extract tool_model via the typed SessionEvent.as_tool_execution().model accessor (instead of raw ev.data inspection), aligning _first_pass with the project’s typed-event access patterns.
Changes:
- Use
ev.as_tool_execution().modelin_first_passfortool.execution_complete, withValidationError/ValueErrorhandling. - Update parser unit tests to validate the typed-accessor behavior, including the case where raw
modellooks valid but typed validation fails. - Remove the prior performance-focused test that asserted Pydantic validation was never invoked for tool model extraction.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/copilot_usage/parser.py |
Switch tool model extraction to typed accessor with exception handling in _first_pass. |
tests/copilot_usage/test_parser.py |
Add/adjust tests to enforce typed validation semantics for tool_model extraction. |
| except (ValidationError, ValueError): | ||
| m = None |
| if isinstance(m, str) and m: | ||
| try: | ||
| m = ev.as_tool_execution().model | ||
| except (ValidationError, ValueError): |
- Narrow except clause to ValidationError only (ValueError is unreachable since the event type is already checked before calling as_tool_execution) - Add debug logging on validation failure, matching the pattern used by SESSION_START and SESSION_SHUTDOWN branches in _first_pass Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Commit pushed:
|
The test_tool_execution_complete_bad_data_silently_skipped test asserted
that no debug logs were emitted for malformed tool.execution_complete
events. This was correct when _first_pass used raw dict access
(ev.data.get("model")), but the PR switched to the typed
as_tool_execution() accessor which now catches ValidationError and
emits a debug log — matching the pattern used for session.start and
session.shutdown handlers.
Rename the test to test_tool_execution_complete_bad_data_logs_debug and
flip the assertion from 'not any' to 'any' so it expects the debug
message.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
CI fix pushed ( The Fix: Renamed the test to Warning
|
|
❌ Pipeline orchestrator: CI still failing after ci-fixer attempt. Marking as stuck for human review. |
There was a problem hiding this comment.
Pull request overview
Updates the session summary “first pass” parsing to derive tool_model via the typed SessionEvent.as_tool_execution().model accessor, aligning _first_pass with the repository’s typed-event parsing approach and removing raw-dict + isinstance business-logic checks.
Changes:
- Switch
_first_pass’sTOOL_EXECUTION_COMPLETEhandling fromev.data.get("model")toev.as_tool_execution().model, with debug logging on Pydantic validation failure. - Update/replace tests to assert
tool_modelis populated via the typed accessor and remains unset when typed validation fails. - Adjust the existing debug-logging expectation for malformed
tool.execution_completeevents.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/copilot_usage/parser.py |
Uses as_tool_execution().model in _first_pass and logs+skips malformed tool events. |
tests/copilot_usage/test_parser.py |
Updates debug-log test and adds typed-accessor coverage for tool model extraction and validation failures. |
| try: | ||
| m = ev.as_tool_execution().model | ||
| except ValidationError as exc: | ||
| logger.debug( |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Manual unstick: applied |
Add defensive ValueError catch to TOOL_EXECUTION_COMPLETE handler in _first_pass, matching the documented exceptions of as_tool_execution(). The etype guard makes ValueError currently unreachable, but catching it prevents escape if the guard is ever restructured. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Commit pushed:
|
There was a problem hiding this comment.
Pull request overview
This PR updates the session summary parser to extract the tool model via the typed SessionEvent.as_tool_execution().model accessor instead of raw dict access, aligning _first_pass with the codebase’s typed-model parsing approach.
Changes:
- Switch
_first_pass’stool.execution_completehandling fromev.data.get("model")toev.as_tool_execution().model. - Add
try/except (ValidationError, ValueError)around the typed accessor and emit debug logs on malformed tool payloads (consistent with other event handlers). - Update/replace tests to validate the typed accessor behavior and the ValidationError skip path.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/copilot_usage/parser.py |
Uses as_tool_execution().model in _first_pass with ValidationError/ValueError handling and debug logging. |
tests/copilot_usage/test_parser.py |
Updates existing debug-log expectations for malformed tool events and adds direct _first_pass tests covering typed accessor success/failure paths. |
The diff-coverage check (≥90% on new lines) failed because the except-ValueError handler in _first_pass is explicitly unreachable defensive code with no test exercising it. Add a test that patches as_tool_execution to raise ValueError, verifying the handler keeps tool_model as None. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
CI fix pushed ( The Fix: Added Warning
|
|
❌ Pipeline orchestrator: review-response loop reached 5 rounds. Marking as stuck for human review. |
Closes #1030
Summary
Replaces the raw
ev.data.get("model")+isinstance(m, str)check in_first_passwith the typedev.as_tool_execution().modelaccessor, aligning with the coding guidelines that prohibitisinstancein business logic.Changes
src/copilot_usage/parser.pyev.as_tool_execution().modelin theTOOL_EXECUTION_COMPLETEhandlertry/except (ValidationError, ValueError)matching the error handling pattern used for other event types in_first_passtests/copilot_usage/test_parser.pytest_first_pass_tool_model_from_typed_accessor: verifies_first_passpopulatestool_modelcorrectly via the typed accessortest_first_pass_tool_model_validation_error: creates a malformed event whosemodelis a valid string (would pass the oldisinstancecheck) but whosetoolTelemetryis invalid — assertstool_modelremainsNoneand no exception escapestest_no_pydantic_validation_for_tool_model: no longer applicable since the fix intentionally uses Pydantic validationWhy
The raw dict access with
isinstancewas a performance optimization that bypassed theToolExecutionDatamodel, creating a risk of silent contract divergence if the shape ofToolExecutionData.modelever changes. The coding guidelines permitisinstanceonly at I/O boundaries when coercing untyped external data into typed models — not in business logic like_first_pass.Warning
The following domains were blocked by the firewall during workflow execution:
astral.shindex.crates.iopypi.orgreleaseassets.githubusercontent.comTo allow these domains, add them to the
network.allowedlist in your workflow frontmatter:See Network Configuration for more information.