)]}'
{"watcher_dashboard/content/action_plans/tables.py":[{"robot_id":"zuul","robot_run_id":"d57c6e9890924bfcb8f1c82ec1425c1d","url":"https://zuul.teim.app/t/main/buildset/d57c6e9890924bfcb8f1c82ec1425c1d","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"6a805a2565628529dec9e140a861ffbb1f40a167","patch_set":1,"id":"f3311b2f_9d496352","line":147,"updated":"2026-02-28 12:33:49.000000000","message":"Potential AttributeError in action_plans/tables.py:147 - datum.audit_uuid direct access assumes the attribute always exists\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Would make the code more defensive against unexpected API responses or malformed data\n\n**Recommendation**:\nConsider keeping the getattr with default None for defensive programming, or verify that audit_uuid is always present in the ActionPlan._attrs tuple (which it is at line 350 of watcher.py). The current change is safe since audit_uuid is in _attrs, but document why direct access is safe.","commit_id":"97a398ecfc60c16c9e49c7365eee52419d670c22"},{"robot_id":"zuul","robot_run_id":"c63104b8d97c491c87d673338957327f","url":"https://zuul.teim.app/t/main/buildset/c63104b8d97c491c87d673338957327f","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a5dd05d2a8df82ce2329480abcb7f6c98849cc8e","patch_set":3,"id":"4b3c7b2c_eaf24913","line":142,"updated":"2026-04-04 01:56:20.000000000","message":"get_audit_link and get_action_plan_link now extract the UUID into a named variable before the None check, which improves readability over the original inline getattr. This pattern could be documented as a project convention for similar URL-reverse helper functions.\n\n**Severity**: SUGGESTION | **Confidence**: 0.6\n\n**Benefit**: Establishing a clear pattern document helps future contributors apply the same approach consistently, especially as similar refactoring continues across the codebase.\n\n**Recommendation**:\nConsider adding a brief section to the contributor guide or a code-style doc noting the preferred pattern for URL helper functions: extract the foreign key into a named variable, check for None, then call urls.reverse(). This captures the intent of the \u0027refactor for clarity\u0027 aspect of this change.","commit_id":"343dfb82b7c1a4840c4b4c7c5839e254dc99f85f"},{"robot_id":"zuul","robot_run_id":"88d6e471e8d7403d934169d40f0312c1","url":"https://zuul.teim.app/t/main/buildset/88d6e471e8d7403d934169d40f0312c1","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"fa693bf2d60202e54bbe5a2be551886692ff0c81","patch_set":4,"id":"71666f80_7a37a62b","line":143,"updated":"2026-04-30 18:53:16.000000000","message":"In get_audit_link() and get_action_plan_link(), getattr() is still used despite audit_uuid and action_plan_uuid being declared in ActionPlan._attrs and Action._attrs respectively. Since datum is always an APIDictWrapper with these fields, the getattr guard is unnecessary.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: The getattr fallback to None hides potential data integrity issues where an ActionPlan lacks its audit_uuid. With direct access, an AttributeError would surface immediately rather than silently returning None.\n\n**Suggestion**:\nConsider using direct attribute access (datum.audit_uuid) with an explicit None check, or document why the getattr guard is retained (e.g., defensive coding for datum types that may not be ActionPlan).","commit_id":"3557a8f7087a95d689b2f26f9e8833ba3d5dc68e"}],"watcher_dashboard/content/actions/tables.py":[{"robot_id":"zuul","robot_run_id":"d57c6e9890924bfcb8f1c82ec1425c1d","url":"https://zuul.teim.app/t/main/buildset/d57c6e9890924bfcb8f1c82ec1425c1d","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"6a805a2565628529dec9e140a861ffbb1f40a167","patch_set":1,"id":"15babbd8_aa785b0d","line":69,"updated":"2026-02-28 12:33:49.000000000","message":"Potential AttributeError in actions/tables.py:69 - datum.action_plan_uuid direct access assumes the attribute always exists\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Would make the code more defensive against unexpected API responses or malformed data\n\n**Recommendation**:\nThe change is safe since action_plan_uuid is in Action._attrs tuple (line 432 of watcher.py). Consider adding a comment explaining that direct access is safe because the attribute is guaranteed by the _attrs declaration.","commit_id":"97a398ecfc60c16c9e49c7365eee52419d670c22"},{"robot_id":"zuul","robot_run_id":"88d6e471e8d7403d934169d40f0312c1","url":"https://zuul.teim.app/t/main/buildset/88d6e471e8d7403d934169d40f0312c1","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"fa693bf2d60202e54bbe5a2be551886692ff0c81","patch_set":4,"id":"00f2a925_3d77910f","line":83,"updated":"2026-04-30 18:53:16.000000000","message":"The getattr-based guard in get_audit_link/get_action_plan_link only checks for None but not for empty string UUIDs. An empty-string audit_uuid would pass the guard and attempt reverse() with an invalid value.\n\n**Severity**: WARNING | **Confidence**: 0.7\n\n**Impact**: If the API ever returns an empty-string UUID, the reverse() call would succeed but generate a broken link. The NoReverseMatch catch would not protect against this case.\n\n**Suggestion**:\nUse a truthiness check (`if not action_plan_uuid: return None`) instead of `if action_plan_uuid is None:` to also guard against empty strings.","commit_id":"3557a8f7087a95d689b2f26f9e8833ba3d5dc68e"}],"watcher_dashboard/content/audits/views.py":[{"robot_id":"zuul","robot_run_id":"512f0cad60f84684ba155cb05db9f93a","url":"https://zuul.teim.app/t/main/buildset/512f0cad60f84684ba155cb05db9f93a","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"c6a4a5a204b94b6f74a4365b98f8ce22dfae082b","patch_set":2,"id":"b146e379_aca1068f","line":258,"updated":"2026-03-30 15:47:22.000000000","message":"The inlining of get_strategy_display_name() in audit_templates/forms.py and audit_templates/views.py is inconsistent with audits/views.py:258 which still calls the helper function. While the inlining is correct, the same file (audits/views.py) now uses both patterns: direct attribute access in get_strategies_for_goal and the helper in get_strategy_parameters.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: Inconsistent code patterns within the same file may confuse future maintainers who expect uniform style across the codebase.\n\n**Suggestion**:\nConsider inlining get_strategy_display_name at audits/views.py:258 as well to maintain consistency with audit_templates/forms.py:122 and audit_templates/views.py:178, or alternatively revert the inlining in the audit_templates files and use the helper everywhere for uniformity.","commit_id":"75b22d92f9972014a62e3085dd95c370628f5c3b"},{"robot_id":"zuul","robot_run_id":"c63104b8d97c491c87d673338957327f","url":"https://zuul.teim.app/t/main/buildset/c63104b8d97c491c87d673338957327f","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a5dd05d2a8df82ce2329480abcb7f6c98849cc8e","patch_set":3,"id":"a26ff6a7_2f90dc36","line":258,"updated":"2026-04-04 01:56:20.000000000","message":"Inconsistent replacement of get_strategy_display_name: replaced with inline expression in audit_templates/forms.py and audit_templates/views.py, but left unchanged in audits/views.py:258 where it is still called via watcher.get_strategy_display_name(strategy).\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: The inconsistency itself is not a bug since get_strategy_display_name still exists and produces identical output. However, it creates a maintenance burden: a reader must understand that the same logic exists in two forms across the codebase, and a future cleanup of the helper function could miss this call site.\n\n**Suggestion**:\nEither replace the call at audits/views.py:258 with the inline expression `strategy.display_name or strategy.name` for consistency with the audit_templates changes, or document in the commit message that this call site was intentionally left unchanged (e.g., because it was added in a different patch series).","commit_id":"343dfb82b7c1a4840c4b4c7c5839e254dc99f85f"},{"robot_id":"zuul","robot_run_id":"88d6e471e8d7403d934169d40f0312c1","url":"https://zuul.teim.app/t/main/buildset/88d6e471e8d7403d934169d40f0312c1","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"fa693bf2d60202e54bbe5a2be551886692ff0c81","patch_set":4,"id":"7c428447_8d3e9c2f","line":245,"updated":"2026-04-30 18:53:16.000000000","message":"In audits/views.py, getattr(strategy, \u0027parameters_spec\u0027, None) is called to check existence, then strategy.parameters_spec is accessed directly on lines 246 and 249. If the attribute truly does not exist, the second access would raise AttributeError despite the guard.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Using the already-fetched value inside the if block avoids a second getattr/APIDictWrapper lookup and eliminates the theoretical inconsistency between the guard check and the value access.\n\n**Recommendation**:\nInside the if block on line 245, capture the value into a local variable: `spec \u003d strategy.parameters_spec` and use `spec` instead of `strategy.parameters_spec` on lines 246-254.","commit_id":"3557a8f7087a95d689b2f26f9e8833ba3d5dc68e"}],"watcher_dashboard/utils/utils.py":[{"robot_id":"zuul","robot_run_id":"c63104b8d97c491c87d673338957327f","url":"https://zuul.teim.app/t/main/buildset/c63104b8d97c491c87d673338957327f","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"a5dd05d2a8df82ce2329480abcb7f6c98849cc8e","patch_set":3,"id":"29eb781d_23dcec2b","line":79,"updated":"2026-04-04 01:56:20.000000000","message":"The `val` variables extracted in filter_items (utils.py:79, 83) are used only once each. The `# dynamic attr` annotation is clear, but the extraction adds two temporary variables to a tight loop for marginal readability gain.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Slightly cleaner loop body with fewer local variables, reducing cognitive load in the already-nested for/for/else structure.\n\n**Recommendation**:\nConsider keeping getattr inline with the annotation comment, e.g.: `if getattr(item, name[: -len(\u0027__in\u0027)]) not in value:` with `# dynamic attr` appended. This matches the style used at line 87 where the original getattr was kept inline. However, the current approach is also acceptable since it makes the annotation placement clearer.","commit_id":"343dfb82b7c1a4840c4b4c7c5839e254dc99f85f"},{"robot_id":"zuul","robot_run_id":"88d6e471e8d7403d934169d40f0312c1","url":"https://zuul.teim.app/t/main/buildset/88d6e471e8d7403d934169d40f0312c1","author":{"_account_id":28006,"name":"teim-ci","display_name":"teim-ci","email":"ci@seanmooney.info","username":"ci-sean-mooney","status":"this is a third-party ci account run by sean-k-mooney on irc\nhosted at zuul.teim.app"},"tag":"autogenerated:zuul:automatic-ci","change_message_id":"fa693bf2d60202e54bbe5a2be551886692ff0c81","patch_set":4,"id":"03cf251b_a7ef6975","line":79,"updated":"2026-04-30 18:53:16.000000000","message":"The comment style for annotated getattr calls is inconsistent: some use \u0027# optional field\u0027, others use \u0027# dynamic attr\u0027, and others use \u0027# watcherclient\u0027. A consistent tag format would make grep-based auditing easier.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: A consistent comment tag (e.g., \u0027# intentional getattr: \u003creason\u003e\u0027) would make it trivial to audit all reflection usage with a single grep pattern.\n\n**Recommendation**:\nDefine a project-wide comment convention for intentional reflection, e.g., \u0027# getattr: dynamic attr\u0027 or \u0027# getattr: optional API field\u0027. Document this convention in a CONTRIBUTING or style guide doc.","commit_id":"3557a8f7087a95d689b2f26f9e8833ba3d5dc68e"}]}
