)]}'
{"watcher_dashboard/api/watcher.py":[{"robot_id":"zuul","robot_run_id":"3eb2c513b7ab4b588c6e0ba9212c69b9","url":"https://zuul.teim.app/t/main/buildset/3eb2c513b7ab4b588c6e0ba9212c69b9","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":"bf865f8fc241fa74fdabb340625ddbb7b1ac60c1","patch_set":1,"id":"9d89afcc_2d30d651","line":49,"updated":"2026-02-28 12:36:15.000000000","message":"Line exceeds 79 character limit (91 chars). While the type ignore comment is functional, this should be wrapped for OpenStack style compliance. Consider using ruff-format to auto-fix during pre-commit.\n\n**Severity**: SUGGESTION | **Confidence**: 0.9\n\n**Benefit**: Ensures strict compliance with OpenStack\u0027s 79-character line length standard (E501). Auto-formatting tools can handle this.\n\n**Recommendation**:\nEither:\n1. Wrap the line to stay under 79 chars: if TYPE_CHECKING:  # noqa: F401\n   from typing import cast, TypeVar, overload\n\nOr ensure ruff-format pre-commit hook is configured to auto-fix this.","commit_id":"a4c24b6b9287289e98a1436d840d398714ab41d4"},{"robot_id":"zuul","robot_run_id":"1d8b84a0a84d42c192b0877df3e775ee","url":"https://zuul.teim.app/t/main/buildset/1d8b84a0a84d42c192b0877df3e775ee","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":"827396959410460a0e8055b924c5a556e4cb9d2a","patch_set":2,"id":"1e675256_d2f97e15","line":1,"updated":"2026-03-30 15:56:18.000000000","message":"Commit subject line is 72 characters, exceeding the OpenStack recommended 50-character limit for commit subjects.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Non-standard commit subject may be flagged during human review; OpenStack convention strongly recommends \u003c\u003d50 chars for the first line.\n\n**Suggestion**:\nShorten the subject line. For example: \u0027feat(A5-1): type-annotate watcher API and errors\u0027 (49 chars) or \u0027feat(A5-1): add type hints to api/watcher.py\u0027 (46 chars).","commit_id":"d92f9e0aff9df98aca202c959f849dc086ea9db0"},{"robot_id":"zuul","robot_run_id":"1d8b84a0a84d42c192b0877df3e775ee","url":"https://zuul.teim.app/t/main/buildset/1d8b84a0a84d42c192b0877df3e775ee","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":"827396959410460a0e8055b924c5a556e4cb9d2a","patch_set":2,"id":"1d9b9b68_2e5e819e","line":20,"updated":"2026-03-30 15:56:18.000000000","message":"The TYPE_CHECKING block imports only django.http.HttpRequest. If additional Django types are needed in future annotations, they should be added to this block.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Sets a clear pattern for future contributors to follow when adding more Django type imports.\n\n**Recommendation**:\nThis is already well-structured. No immediate action needed, but a brief comment above the TYPE_CHECKING block explaining its purpose would help future contributors.","commit_id":"d92f9e0aff9df98aca202c959f849dc086ea9db0"},{"robot_id":"zuul","robot_run_id":"1d8b84a0a84d42c192b0877df3e775ee","url":"https://zuul.teim.app/t/main/buildset/1d8b84a0a84d42c192b0877df3e775ee","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":"827396959410460a0e8055b924c5a556e4cb9d2a","patch_set":2,"id":"341b69d4_34340d2c","line":53,"updated":"2026-03-30 15:56:18.000000000","message":"Line 53 exceeds the 79-character line-length limit enforced by ruff. The type-ignore comment pushes the line to 102 characters, which will trigger an E501 lint failure.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: CI lint failure (E501). The ruff configuration in pyproject.toml sets line-length\u003d79 and selects E5 rules.\n\n**Priority**: Before merge\n**Why This Matters**: The project uses ruff with line-length\u003d79 as a gating CI check. This line will fail the pep8 equivalent tox environment.\n\n**Recommendation**:\nMove the # type: ignore comment to the line above the assignment, or break the line so the type comment fits within 79 characters. For example:\n    client \u003d common_client.get_client(\n        request, required\u003dmicroversion\n    )  # type: ignore[no-untyped-call]","commit_id":"d92f9e0aff9df98aca202c959f849dc086ea9db0"},{"robot_id":"zuul","robot_run_id":"1d8b84a0a84d42c192b0877df3e775ee","url":"https://zuul.teim.app/t/main/buildset/1d8b84a0a84d42c192b0877df3e775ee","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":"827396959410460a0e8055b924c5a556e4cb9d2a","patch_set":2,"id":"ed7f63d1_749f0031","line":189,"updated":"2026-03-30 15:56:18.000000000","message":"Stale docstring type annotations: multiple methods document parameter types as \u0027int\u0027 but the new type annotations use \u0027str\u0027. Affected: Audit.get, Audit.delete, AuditTemplate.get, AuditTemplate.delete, ActionPlan.get, ActionPlan.delete, ActionPlan.start, Action.delete, and Goal.get.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Docstrings now contradict the type annotations, which could confuse developers and produce incorrect documentation.\n\n**Suggestion**:\nUpdate the `:type:` entries in docstrings from \u0027int\u0027 to \u0027str\u0027 to match the new type annotations. For example, `:type  audit_id: int` should become `:type  audit_id: str`.","commit_id":"d92f9e0aff9df98aca202c959f849dc086ea9db0"},{"robot_id":"zuul","robot_run_id":"1d8b84a0a84d42c192b0877df3e775ee","url":"https://zuul.teim.app/t/main/buildset/1d8b84a0a84d42c192b0877df3e775ee","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":"827396959410460a0e8055b924c5a556e4cb9d2a","patch_set":2,"id":"c503b44d_042c999e","line":287,"updated":"2026-03-30 15:56:18.000000000","message":"The AuditTemplate.create docstring documents a non-existent parameter \u0027audit_template\u0027 with type \u0027string\u0027 that does not appear in the function signature.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: The phantom docstring parameter could confuse API consumers and may be a leftover from a previous refactoring.\n\n**Suggestion**:\nRemove the `:param audit_template:` and `:type  audit_template:` lines from the AuditTemplate.create docstring.","commit_id":"d92f9e0aff9df98aca202c959f849dc086ea9db0"},{"robot_id":"zuul","robot_run_id":"1d8b84a0a84d42c192b0877df3e775ee","url":"https://zuul.teim.app/t/main/buildset/1d8b84a0a84d42c192b0877df3e775ee","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":"827396959410460a0e8055b924c5a556e4cb9d2a","patch_set":2,"id":"b094d358_2effc543","line":566,"updated":"2026-03-30 15:56:18.000000000","message":"Action.update() on line 567 is the only classmethod that was not annotated with type hints in this patch, despite the commit message claiming all classmethods were annotated.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Incomplete annotation coverage. The commit message states all classmethods were annotated but Action.update was skipped, which is misleading to reviewers.\n\n**Suggestion**:\nEither annotate Action.update() to match the other classmethods, or update the commit message to clarify that it was intentionally deferred.","commit_id":"d92f9e0aff9df98aca202c959f849dc086ea9db0"},{"robot_id":"zuul","robot_run_id":"1d8b84a0a84d42c192b0877df3e775ee","url":"https://zuul.teim.app/t/main/buildset/1d8b84a0a84d42c192b0877df3e775ee","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":"827396959410460a0e8055b924c5a556e4cb9d2a","patch_set":2,"id":"f337642d_4cd1d65a","line":762,"updated":"2026-03-30 15:56:18.000000000","message":"The get_strategy_display_name free function at line 762 was not annotated despite the rest of the module receiving type hints.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Complete annotation coverage of the public API surface for consistency and better IDE support.\n\n**Recommendation**:\nAdd a type annotation for the strategy parameter and return value. For example: `def get_strategy_display_name(strategy: Strategy) -\u003e str:`","commit_id":"d92f9e0aff9df98aca202c959f849dc086ea9db0"},{"robot_id":"zuul","robot_run_id":"d8f77a24e890499d84f27326db76f54d","url":"https://zuul.teim.app/t/main/buildset/d8f77a24e890499d84f27326db76f54d","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":"e74d38e95e8d410c41952dd6ddd3961e78be1240","patch_set":3,"id":"72e41e8a_9a6641f1","line":15,"updated":"2026-04-04 02:05:43.000000000","message":"Consider using `from __future__ import annotations` to enable PEP 604 union syntax in annotations without requiring string quotes for forward references. This would eliminate the need for `\u0027HttpRequest\u0027`, `\u0027Audit\u0027`, `\u0027list[Audit]\u0027` string literals.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Cleaner annotations without string-quoting overhead. PEP 604 unions (X | Y) already used throughout would work natively in annotations rather than relying on Python 3.10+ eval-time support.\n\n**Recommendation**:\nThis is a stylistic preference. The current approach is correct and functional. If the team prefers cleaner annotations, add `from __future__ import annotations` at the top and remove the string quotes. Be aware this changes annotation semantics from eager to lazy evaluation.","commit_id":"1835bd0304c604ff3783f9b0ec6f7d1435cb555a"},{"robot_id":"zuul","robot_run_id":"d8f77a24e890499d84f27326db76f54d","url":"https://zuul.teim.app/t/main/buildset/d8f77a24e890499d84f27326db76f54d","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":"e74d38e95e8d410c41952dd6ddd3961e78be1240","patch_set":3,"id":"648de323_20f7afa7","line":61,"updated":"2026-04-04 02:05:43.000000000","message":"The `interval` parameter is typed as `int | None` in the Audit.create() signature, but the docstring says `:type interval: str or int or None`. The annotation and docstring disagree about whether str is a valid type.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: If the API truly accepts str values for interval, the annotation is too narrow and a type checker would reject valid call sites passing strings. If the API only accepts int, the docstring is misleading.\n\n**Suggestion**:\nVerify the Watcher API spec for the interval field. If it accepts both str and int, change the annotation to `str | int | None` to match the docstring. If it only accepts int, update the docstring to `:type interval: int or None`.","commit_id":"1835bd0304c604ff3783f9b0ec6f7d1435cb555a"},{"robot_id":"zuul","robot_run_id":"d8f77a24e890499d84f27326db76f54d","url":"https://zuul.teim.app/t/main/buildset/d8f77a24e890499d84f27326db76f54d","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":"e74d38e95e8d410c41952dd6ddd3961e78be1240","patch_set":3,"id":"add6159d_27c1e050","line":128,"updated":"2026-04-04 02:05:43.000000000","message":"The comment `# Build the parameters to pass to watcherclient` on line 128 is self-evident from the code (`payload: dict[str, object] \u003d {`). It adds noise without providing additional context.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Slightly cleaner code by removing a comment that restates what the next line clearly expresses.\n\n**Recommendation**:\nRemove the comment on line 128. The variable name `payload` and the dict literal make the intent clear.","commit_id":"1835bd0304c604ff3783f9b0ec6f7d1435cb555a"},{"robot_id":"zuul","robot_run_id":"d8f77a24e890499d84f27326db76f54d","url":"https://zuul.teim.app/t/main/buildset/d8f77a24e890499d84f27326db76f54d","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":"e74d38e95e8d410c41952dd6ddd3961e78be1240","patch_set":3,"id":"636ceb2b_77da7809","line":175,"updated":"2026-04-04 02:05:43.000000000","message":"Type annotation mismatch: @handle_errors-decorated get() methods (Audit.get, Goal.get, etc.) are annotated as returning non-optional types, but the decorator returns None on the error path. Return types should include None.\n\n**Severity**: HIGH | **Confidence**: 0.9\n\n**Risk**: Static type checkers (mypy, pyright) will accept the declared type but the annotations are misleading. Callers relying on the annotated type may skip None checks, leading to AttributeError at runtime when the error path fires.\n\n**Priority**: Before merge\n**Why This Matters**: The whole point of adding type annotations is to provide accurate type information. If the annotations are narrower than actual runtime behaviour, they undermine the safety guarantees the annotations are supposed to provide.\n\n**Recommendation**:\nEither: (a) change the decorated get() return types to include None, e.g. `-\u003e \u0027Audit | None\u0027`, `-\u003e \u0027Goal | None\u0027`, etc.; or (b) if the project considers error-path returns unreachable for callers (because Horizon shows an error page), document this with a comment and use a `# type: ignore[return-value]` or adjust the decorator\u0027s TypeVar signature to return T (not T | None) when error_default is explicitly None.","commit_id":"1835bd0304c604ff3783f9b0ec6f7d1435cb555a"},{"robot_id":"zuul","robot_run_id":"d8f77a24e890499d84f27326db76f54d","url":"https://zuul.teim.app/t/main/buildset/d8f77a24e890499d84f27326db76f54d","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":"e74d38e95e8d410c41952dd6ddd3961e78be1240","patch_set":3,"id":"eed2a633_86c9166f","line":563,"updated":"2026-04-04 02:05:43.000000000","message":"Action.update() classmethod is completely missing type annotations while every other classmethod in the file has been annotated in this change. This is an inconsistency within the same patch.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Breaks the consistency goal of this annotation change. A reviewer or future contributor will need to add these annotations later, and the current patchset creates an incomplete annotation story.\n\n**Suggestion**:\nAdd type annotations to Action.update() to match the rest of the file. The return type should be `-\u003e \u0027Action | None\u0027` given the try/except that catches MethodNotAllowed and returns None.","commit_id":"1835bd0304c604ff3783f9b0ec6f7d1435cb555a"},{"robot_id":"zuul","robot_run_id":"d8f77a24e890499d84f27326db76f54d","url":"https://zuul.teim.app/t/main/buildset/d8f77a24e890499d84f27326db76f54d","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":"e74d38e95e8d410c41952dd6ddd3961e78be1240","patch_set":3,"id":"49af2b1e_ead6fd87","line":759,"updated":"2026-04-04 02:05:43.000000000","message":"The `get_strategy_display_name()` module-level function at the bottom of watcher.py is not type-annotated, while all class methods have been annotated.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: Completes the annotation coverage for the file and improves type safety for callers of this utility function.\n\n**Recommendation**:\nAdd annotations: `def get_strategy_display_name(strategy: \u0027Strategy\u0027) -\u003e str:`.","commit_id":"1835bd0304c604ff3783f9b0ec6f7d1435cb555a"},{"robot_id":"zuul","robot_run_id":"cc3ad90ee96f4052b8087b86b3db17db","url":"https://zuul.teim.app/t/main/buildset/cc3ad90ee96f4052b8087b86b3db17db","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":"c7a51bd6cd8df1af4f31850092867f504a53815f","patch_set":4,"id":"e02c858b_cb3c8469","line":1,"updated":"2026-04-30 19:06:40.000000000","message":"The commit message bullet points wrap at varying widths and one bullet exceeds the conventional 72-character body limit, but this is cosmetic and does not affect CI.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Consistent wrapping in commit bodies improves readability in git log --format\u003dmedium.\n\n**Recommendation**:\nNo action required for this patch. Future commit messages could benefit from rewrapping the bullet list to 72 characters for consistency.","commit_id":"c751dea942fbb77b72465cd2416bcfa7ef210f93"},{"robot_id":"zuul","robot_run_id":"cc3ad90ee96f4052b8087b86b3db17db","url":"https://zuul.teim.app/t/main/buildset/cc3ad90ee96f4052b8087b86b3db17db","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":"c7a51bd6cd8df1af4f31850092867f504a53815f","patch_set":4,"id":"143a81a0_6a266618","line":61,"updated":"2026-04-30 19:06:40.000000000","message":"Audit.create() interval parameter is annotated as int | None but the docstring says :type interval: str or int or None. The type annotation is narrower than what the API actually accepts and what the docstring documents.\n\n**Severity**: WARNING | **Confidence**: 0.8\n\n**Impact**: A type checker would reject valid string interval values (e.g. cron expressions) passed to Audit.create(interval\u003d\u00270 * * * *\u0027). The Watcher API supports both integer seconds and cron-style string intervals.\n\n**Suggestion**:\nWiden the annotation to interval: str | int | None \u003d None to match the docstring and the real API contract. This is also more accurate for downstream type checking.","commit_id":"c751dea942fbb77b72465cd2416bcfa7ef210f93"},{"robot_id":"zuul","robot_run_id":"cc3ad90ee96f4052b8087b86b3db17db","url":"https://zuul.teim.app/t/main/buildset/cc3ad90ee96f4052b8087b86b3db17db","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":"c7a51bd6cd8df1af4f31850092867f504a53815f","patch_set":4,"id":"7980305a_adaf02b7","line":231,"updated":"2026-04-30 19:06:40.000000000","message":"The `id` property on every wrapper class uses `cast(str, self.uuid)`, but APIDictWrapper.__getattr__ already returns the raw value from the backing dict. Adding a comment explaining why cast() is used would aid future maintainers.\n\n**Severity**: SUGGESTION | **Confidence**: 0.8\n\n**Benefit**: A brief inline comment on one representative id property explaining the cast rationale (bridging APIDictWrapper\u0027s dynamic __getattr__ to typed str) would prevent future reviewers from mistaking this for unnecessary casting.\n\n**Recommendation**:\nConsider adding a brief inline comment on one representative id property (e.g. Audit.id) explaining the cast rationale: `# cast: APIDictWrapper exposes uuid via __getattr__; cast bridges the dynamic access to a typed str`. This single comment covers the identical pattern repeated across all seven classes.","commit_id":"c751dea942fbb77b72465cd2416bcfa7ef210f93"},{"robot_id":"zuul","robot_run_id":"cc3ad90ee96f4052b8087b86b3db17db","url":"https://zuul.teim.app/t/main/buildset/cc3ad90ee96f4052b8087b86b3db17db","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":"c7a51bd6cd8df1af4f31850092867f504a53815f","patch_set":4,"id":"36dca460_6194ae97","line":563,"updated":"2026-04-30 19:06:40.000000000","message":"Action.update() is the only public classmethod across all seven wrapper classes that was not annotated in this patch, breaking the consistent annotation pattern established for every other CRUD method.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Inconsistency undermines the type-safety goal stated in the commit subject. Callers of Action.update() get no static-type feedback on parameters or return value, unlike every other wrapper method.\n\n**Suggestion**:\nAnnotate Action.update() to match the pattern used by all other methods: request: \u0027HttpRequest\u0027, action_id: str, state: str | None \u003d None, reason: str | None \u003d None, api_version: str | None \u003d None -\u003e Action | None. The docstring already documents these types, so this is a direct mechanical translation.","commit_id":"c751dea942fbb77b72465cd2416bcfa7ef210f93"},{"robot_id":"zuul","robot_run_id":"cc3ad90ee96f4052b8087b86b3db17db","url":"https://zuul.teim.app/t/main/buildset/cc3ad90ee96f4052b8087b86b3db17db","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":"c7a51bd6cd8df1af4f31850092867f504a53815f","patch_set":4,"id":"b45eb9e9_c989c781","line":747,"updated":"2026-04-30 19:06:40.000000000","message":"EfficacyIndicatorSpec uses `attrs` (no underscore) while every other wrapper class uses `_attrs`. This may cause the superclass APIDictWrapper to not find the attribute tuple, since it typically looks up _attrs.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Fixing this ensures EfficacyIndicatorSpec instances properly expose name, description, unit, and schema as attribute accessors via APIDictWrapper.\n\n**Recommendation**:\nVerify whether APIDictWrapper uses _attrs or attrs. If it uses _attrs, rename to _attrs in a follow-up patch. Since this is pre-existing code outside this patch\u0027s diff, it belongs in a separate change.","commit_id":"c751dea942fbb77b72465cd2416bcfa7ef210f93"},{"robot_id":"zuul","robot_run_id":"cc3ad90ee96f4052b8087b86b3db17db","url":"https://zuul.teim.app/t/main/buildset/cc3ad90ee96f4052b8087b86b3db17db","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":"c7a51bd6cd8df1af4f31850092867f504a53815f","patch_set":4,"id":"02fc4a3f_db02acd0","line":759,"updated":"2026-04-30 19:06:40.000000000","message":"The module-level helper get_strategy_display_name() receives a strategy parameter but lacks both parameter and return type annotations, inconsistent with the annotated watcherclient() and insert_watcher_policy_file() above it.\n\n**Severity**: WARNING | **Confidence**: 0.9\n\n**Impact**: Reduces the value of the py.typed marker for downstream consumers. Any caller importing this public helper gets no type information.\n\n**Suggestion**:\nAdd annotations: def get_strategy_display_name(strategy: \u0027Strategy\u0027) -\u003e str:. The function accesses strategy.display_name and strategy.name which are declared in Strategy._attrs.","commit_id":"c751dea942fbb77b72465cd2416bcfa7ef210f93"}],"watcher_dashboard/utils/errors.py":[{"robot_id":"zuul","robot_run_id":"1d8b84a0a84d42c192b0877df3e775ee","url":"https://zuul.teim.app/t/main/buildset/1d8b84a0a84d42c192b0877df3e775ee","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":"827396959410460a0e8055b924c5a556e4cb9d2a","patch_set":2,"id":"90dccf17_9796637d","line":29,"updated":"2026-03-30 15:56:18.000000000","message":"The errors.py handle_errors decorator\u0027s TypeVar T correctly models the generic return, but the request_arg parameter type of int | None may look unusual to reviewers unfamiliar with the positional-index pattern.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Adding a brief inline comment explaining why request_arg is int (it indexes into positional args) would improve readability.\n\n**Recommendation**:\nAdd a comment like `# positional-argument index` next to the request_arg parameter. The type itself (int | None) is correct as-is.","commit_id":"d92f9e0aff9df98aca202c959f849dc086ea9db0"},{"robot_id":"zuul","robot_run_id":"cc3ad90ee96f4052b8087b86b3db17db","url":"https://zuul.teim.app/t/main/buildset/cc3ad90ee96f4052b8087b86b3db17db","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":"c7a51bd6cd8df1af4f31850092867f504a53815f","patch_set":4,"id":"780f3d44_90fe7077","line":26,"updated":"2026-04-30 19:06:40.000000000","message":"The handle_errors return-type annotation Callable[..., T | None] accurately models that the wrapper may return error_default on exception paths. However, the inner function\u0027s actual return type on the success path is always T, never T | None.\n\n**Severity**: SUGGESTION | **Confidence**: 0.7\n\n**Benefit**: Using @overload could give callers more precise type information: one overload for error_default\u003dNone (returns T | None) and one for error_default: T (returns T). This is a type-nicety, not a correctness issue.\n\n**Recommendation**:\nConsider adding @overload signatures in a follow-up if more precise narrowing is desired. The current annotation is correct and safe as-is; this is purely about optimal type precision for callers.","commit_id":"c751dea942fbb77b72465cd2416bcfa7ef210f93"}]}
