Adopt the df12 Python lint suite - #220
Conversation
There was a problem hiding this comment.
Sorry @LodyAI[bot], your pull request is larger than the review limit of 150000 diff characters
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 41 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (267)
WalkthroughThe pull request expands the lint pipeline with DF12 Pylint checks and ChangesRepository modernisation
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 20✅ Passed checks (20 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph. If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced. tests/test_source_intake_api_contract.py Comment on lines +125 to +126 assert response.status_code == 404, "Expected values to match"
assert response.json()["code"] == "upload_not_found", "Expected values to match"❌ New issue: Code Duplication |
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph. If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced. tests/test_source_intake_api.py Comment on lines +105 to +121 assert replay_response.status_code == 201, "Expected values to match"
assert replay_response.json() == upload_response.json(), "Expected values to match"
assert upload_response.json()["content_hash"].startswith("sha256:"), (
"Expected value to have the required prefix"
)
assert job_response.status_code == 201, "Expected values to match"
assert job_response.json()["intake_state"] == "awaiting_sources", (
"Expected values to match"
)
assert source_response.status_code == 201, "Expected values to match"
assert source_response.json()["upload_id"] == upload_response.json()["id"], (
"Expected values to match"
)
assert status_response.status_code == 200, "Expected values to match"
assert status_response.json()["intake_state"] == "ready_for_generation", (
"Expected values to match"
)❌ New issue: Large Method |
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph. If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced. tests/test_orchestration_graph_invariant_properties.py Comment on lines +150 to +165 assert orchestration_result.total_usage.input_tokens >= 0, (
"Expected values to satisfy the required ordering"
)
assert orchestration_result.total_usage.output_tokens >= 0, (
"Expected values to satisfy the required ordering"
)
assert orchestration_result.total_usage.total_tokens >= 0, (
"Expected values to satisfy the required ordering"
)
assert orchestration_result.total_usage.total_tokens == expected_total_tokens, (
"Expected values to match"
)
assert state["planner_result"] == planner_result, "Expected values to match"
assert state["action_results"][0].model == "prop-exec-model", (
"Expected values to match"
)❌ New issue: Large Method |
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph. If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced. tests/test_binding_resolution.py Comment on file async def test_resolve_bindings_returns_empty_for_nonexistent_episode_id(
uow_with_fixtures, # noqa: ANN001
uow_with_fixtures, # noqa: ANN001 # Pytest injects this fixture dynamically, so no stable local type is available.❌ New issue: Code Duplication |
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph. If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced. episodic/orchestration/_checkpoint_resume.py Comment on lines +183 to +194 Returns
-------
dto.GenerationOrchestrationResult
Result produced by the operation.
Raises
------
TypeError
If the operation cannot be completed.
ValueError
If the operation cannot be completed.❌ New issue: Large Method |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph. If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced. tests/test_source_intake_api_contract.py Comment on lines +125 to +126 assert response.status_code == 404, "Expected values to match"
assert response.json()["code"] == "upload_not_found", "Expected values to match"❌ New issue: Code Duplication |
This comment was marked as resolved.
This comment was marked as resolved.
|
@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph. If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced. Excess Number of Function Argumentstests/test_source_intake_api.py: _post_text_upload What lead to degradation?_post_text_upload has 5 arguments, max arguments = 4 Why does this problem occur?Functions with many arguments indicate either a) low cohesion where the function has too many responsibilities, or b) a missing abstraction that encapsulates those arguments. How to fix it?Start by investigating the responsibilities of the function. Make sure it doesn't do too many things, in which case it should be split into smaller and more cohesive functions. Consider the refactoring INTRODUCE PARAMETER OBJECT to encapsulate arguments that refer to the same logical concept. |
This comment was marked as resolved.
This comment was marked as resolved.
There was a problem hiding this comment.
Sorry @leynos, your pull request is larger than the review limit of 150000 diff characters
9a51b77 to
f1fea27
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a51b77469
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| DF12_PYLINT_MESSAGES = R9101,C9102,R9103,R9104,C9105,C9106,C9107,R9108,R9109,R9110,R9111,C9112 | ||
| DF12_PYLINT = $(UV_ENV) $(UV) run --python $(DF12_PYTHON) pylint --disable=all \ | ||
| --load-plugins=df12_python_lints --enable=$(DF12_PYLINT_MESSAGES) | ||
| AMBRLEAKS = $(UV_ENV) $(UV) tool run --python $(DF12_PYTHON) \ | ||
| --from '$(DF12_PYTHON_LINTS)' ambrleaks |
There was a problem hiding this comment.
Document the new linting workflow
Add the df12 Pylint and ambrleaks commands, their supported scope, and the reason for running df12 separately on CPython 3.14 to the relevant developer documentation. This commit introduces a new dependency and a repository-wide internal quality-gate convention, but changes no files under docs/, leaving contributors without the documented source of truth required for reproducing or maintaining the lint workflow.
AGENTS.md reference: AGENTS.md:L45-L55
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
@coderabbitai Has this now been resolved in the latest commit?
Use codegraph analysis to determine your answer.
If this comment is now resolved, please mark it as such using the API. Otherwise, please provide an AI agent prompt for the remaining work to be done to address this comment.
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '== Makefile lint command graph =='
grep -nE '^(lint:|DF12_|AMBRLEAKS|PYLINT)' Makefile
echo
echo '== Documentation candidates =='
fd -HI -t f '^(AGENTS|CONTRIBUTING|README)(\..*)?$|\.md$' . \
-E .git -E .venv -E node_modules | sort
echo
echo '== Documentation references to the added lint workflow =='
rg -n -i -C 4 \
'(df12|ambrleaks|future.?annotations|C9112|R9101|CPython 3\.14|make lint|lint workflow)' \
-g 'AGENTS.md' -g 'CONTRIBUTING*' -g 'README*' -g '*.md' . || true
echo
echo '== Focused AGENTS.md structure and relevant lines =='
if [ -f AGENTS.md ]; then
ast-grep outline AGENTS.md --lang markdown --items all || true
nl -ba AGENTS.md | sed -n '1,180p'
fiLength of output: 201424
🏁 Script executed:
#!/bin/bash
set -euo pipefail
repo='leynos/episodic'
pr=220
comment_database_id=3660540510
gh api graphql \
-F owner="${repo%%/*}" \
-F name="${repo#*/}" \
-F number="$pr" \
-f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
id
isResolved
comments(first: 20) {
nodes {
databaseId
author { login }
body
url
}
}
}
}
}
}
}' \
--jq --argjson id "$comment_database_id" '
.data.repository.pullRequest.reviewThreads.nodes[]
| select(any(.comments.nodes[]; .databaseId == $id))
| {
thread_id: .id,
is_resolved: .isResolved,
matching_comment: (
.comments.nodes[]
| select(.databaseId == $id)
| {author: .author.login, url, body}
)
}
'Length of output: 1368
🏁 Script executed:
#!/bin/bash
set -euo pipefail
repo='leynos/episodic'
pr=220
comment_database_id=3660540510
threads_json="$(
gh api graphql \
-F owner="${repo%%/*}" \
-F name="${repo#*/}" \
-F number="$pr" \
-f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
id
isResolved
comments(first: 20) {
nodes {
databaseId
author { login }
body
url
}
}
}
}
}
}
}'
)"
printf '%s\n' "$threads_json" | jq \
--argjson id "$comment_database_id" '
.data.repository.pullRequest.reviewThreads.nodes[]
| select(any(.comments.nodes[]; .databaseId == $id))
| {
thread_id: .id,
is_resolved: .isResolved,
matching_comment: (
.comments.nodes[]
| select(.databaseId == $id)
| {author: .author.login, url, body}
)
}
'Length of output: 2185
@leynos, treat this finding as resolved.
The current command graph connects make lint to the df12 Pylint, future-annotations, and ambrleaks passes. docs/developers-guide.md documents:
- why df12 runs separately on CPython 3.14;
- the exact df12 and
ambrleakscommands; - the shared
PYLINT_TARGETSscope; - the C9112 pytest-bdd step-module exception; and
- the Makefile version/interpreter variables.
The GitHub thread remains unresolved, but it was created by chatgpt-codex-connector, not coderabbitai. Resolve it from that integration or manually; I must not resolve another account’s review thread through the API.
There was a problem hiding this comment.
Actionable comments posted: 30
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
alembic/env.py (1)
40-49: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winRaise a specific configuration error.
Replace the generic
RuntimeErrorwith a named database-configuration domain error, orValueErrorif this boundary exposes only built-in errors. Preserve the existing message.As per coding guidelines, “Raise specific built-in exceptions or domain-specific exceptions instead of generic
Exceptionor catch-allRuntimeError”.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@alembic/env.py` around lines 40 - 49, The _configure_database_url function should raise a specific database-configuration domain exception when neither DATABASE_URL nor sqlalchemy.url is available, falling back to ValueError if no domain error exists at this boundary. Preserve the existing error message and leave the valid URL configuration paths unchanged.Source: Coding guidelines
episodic/canonical/storage/repositories.py (1)
2-2: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftRemove the file-level
too-many-linessuppressions.Both modules suppress the file-size lint at module scope, but the path rules forbid file-level skips. Split each module or narrow any unavoidable suppression to a justified local scope.
episodic/canonical/storage/repositories.py#L2-L2: remove the module-level suppression and decompose the repository module.episodic/canonical/storage/source_intake_repositories.py#L2-L2: remove the module-level suppression and decompose the repository module.As per path instructions, file-level skips are forbidden.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@episodic/canonical/storage/repositories.py` at line 2, Remove the module-level too-many-lines suppressions from episodic/canonical/storage/repositories.py lines 2-2 and episodic/canonical/storage/source_intake_repositories.py lines 2-2, then decompose each repository module to satisfy the file-size lint; use only narrowly scoped suppressions where unavoidable and justified.Source: Path instructions
tests/steps/test_chapter_markers_steps.py (1)
14-14: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winRestore postponed annotations in these step modules. Each file still uses
TYPE_CHECKING-only names in annotations (cabc.*,LLMRequest, and similar), so importing them withoutfrom __future__ import annotationswill fail during step discovery. Keep the future import in everytests/steps/test_*_steps.pymodule.
tests/steps/test_chapter_markers_steps.pytests/steps/test_chrono_steps.pytests/steps/test_generation_run_lifecycle_steps.pytests/steps/test_guest_bios_steps.pytests/steps/test_http_service_scaffold_steps.py🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/steps/test_chapter_markers_steps.py` at line 14, Restore the postponed-annotations future import in every affected step module: tests/steps/test_chapter_markers_steps.py (14-14), tests/steps/test_chrono_steps.py (2-3), tests/steps/test_generation_run_lifecycle_steps.py (2-3), tests/steps/test_guest_bios_steps.py (14-14), and tests/steps/test_http_service_scaffold_steps.py (3-16). Place it with the module’s other future imports so TYPE_CHECKING-only annotation names remain safe during step discovery.Source: Path instructions
tests/steps/test_worker_service_scaffold_steps.py (1)
2-3: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winRestore deferred annotations in this pytest-bdd step module. Keep
from __future__ import annotationsbefore runtime imports; removing it can break pytest-bdd step discovery when annotations reference names imported only underTYPE_CHECKING.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/steps/test_worker_service_scaffold_steps.py` around lines 2 - 3, Restore `from __future__ import annotations` at the top of the pytest-bdd step module, before runtime imports such as `dataclasses`. Preserve deferred annotation evaluation so step discovery supports annotations referencing `TYPE_CHECKING`-only names.episodic/cost/recorder.py (1)
103-104: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRestore the documented exception contract.
Reinstate the
Raisessections, or document the actual domain exceptions propagated by the pricing ports. Removing the existingLookupErrorandCostAccountingErrorentries hides failure modes that remain part of these call paths.As per coding guidelines, document public interfaces with complete NumPy-style contracts, including relevant exceptions.
Also applies to: 215-216
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@episodic/cost/recorder.py` around lines 103 - 104, Restore the NumPy-style Raises documentation in the affected public interfaces near the recorder methods, including LookupError and CostAccountingError as propagated domain exceptions. Apply the same documentation update to the second affected interface while preserving the existing parameter, return, and description sections.Source: Coding guidelines
episodic/qa/chrono_langgraph.py (1)
52-67: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReplace the
Anyannotations with concrete Chrono types. UseChronoEvaluationRequest | None/ChronoRuntimeEstimate | NoneonChronoGraphState, and returndict[str, ChronoRuntimeEstimate]fromchrono_node; the Pedante LangGraph seam already uses concrete state annotations, andAnyonly weakens static checking.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@episodic/qa/chrono_langgraph.py` around lines 52 - 67, Replace the chrono_request and chrono_result Any annotations in ChronoGraphState with ChronoEvaluationRequest | None and ChronoRuntimeEstimate | None, respectively. Update chrono_node to return dict[str, ChronoRuntimeEstimate], importing or reusing the concrete Chrono types already defined for the evaluator seam.Sources: Coding guidelines, Path instructions
tests/fixtures/history_entries.py (1)
69-77: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a concrete usage example to the public history-entry contract.
Replace the generic Returns description with a NumPy-style
Examplessection showing a concrete history-entry class, parent field, revision, and resulting attributes.As per coding guidelines, function documentation must include clear examples demonstrating usage and outcome.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/fixtures/history_entries.py` around lines 69 - 77, Update the history-entry builder’s docstring to replace the generic Returns section with a NumPy-style Examples section. Use a concrete history-entry class and parent field, invoke it with a specific revision, and show the resulting attributes, including the parent identifier and revision.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@alembic/versions/20260203_000001_create_canonical_schema.py`:
- Around line 75-78: Remove the NumPy-style Returns section from the private
helper’s docstring, leaving only its concise single-line summary. Do not alter
the helper implementation or add replacement documentation.
In `@episodic/api/handlers.py`:
- Around line 73-74: Update the NumPy-style Raises sections in
episodic/api/handlers.py at lines 73-74 and 125-126 to name the concrete Falcon
exception mapped from EntityNotFoundError; at lines 172-175 document the
concrete mapped update exceptions; at line 227 restore the update handler’s
Raises section; and at lines 276-281 replace mapper/validation helper names with
the concrete validation and HTTP exception classes. In
episodic/orchestration/_show_notes_executor.py lines 239-240, restore execute’s
Raises documentation for unsupported actions, malformed responses, provider
failures, and translated tool failures, naming the actual exception classes
raised at each boundary.
In `@episodic/api/helpers.py`:
- Around line 68-69: Update every Raises entry in the documented helpers,
including the sections around validation_error at the referenced locations, to
name falcon.HTTPBadRequest as the raised exception instead of
validation_error(...). Retain the existing prose describing the validation
envelope and apply the same concrete exception wording consistently across all
listed sections.
In `@episodic/api/resources/series_profiles.py`:
- Around line 271-274: Update the Raises documentation for the affected series
profile operation to include falcon.HTTPBadRequest for malformed profile_id,
template_id, or episode_id UUIDs, while retaining HTTPNotFound for missing
entities.
In `@episodic/canonical/adapters/weighting.py`:
- Around line 59-63: Replace the placeholder function documentation at
episodic/canonical/adapters/weighting.py:59-63 with a structured contract
describing the quality, freshness, and reliability tuple, including a concise
usage example; update episodic/concurrent_interpreters.py:81-85 to specify when
the parser returns int versus None and show usage; update
episodic/concurrent_interpreters.py:337-341 to document executor selection,
caller-owned shutdown, and an example; update episodic/qa/langgraph.py:53-62 to
document the "pass"/"refine" rule, the missing-pedante_result KeyError, and
usage; update episodic/worker/topology.py:152-161 to describe workload-to-queue
mapping, the duplicate-workload ValueError, and usage. Preserve each function’s
existing behavior while making all return and failure contracts precise.
In `@episodic/canonical/reference_documents/_binding_queries.py`:
- Around line 47-50: Update the docstrings for get_reference_binding and
list_reference_bindings to document all validation exceptions still raised: add
ReferenceValidationError to get_reference_binding, add a Raises section to
list_reference_bindings covering UUID and pagination parsing failures, and
replace the generic ReferenceEntityNotFoundError description with the specific
missing-reference-binding case.
In `@episodic/canonical/reference_documents/resolution.py`:
- Around line 105-109: Shorten the docstrings of the underscore-prefixed helpers
in the resolution module, including the helpers at the referenced locations, by
removing their structured Returns sections and retaining only concise
single-line summaries. Leave public-interface docstrings unchanged.
In `@episodic/canonical/storage/integrity_helpers.py`:
- Around line 103-107: Update the Raises section of the relevant public helper
to document the domain exception produced by translate, or explicitly state that
the callback determines the raised exception type, while retaining the
IntegrityError documentation for unrecognized failures. Ensure the documentation
matches the translated exception raised by the existing translation path.
In `@episodic/canonical/storage/workflow_checkpoints.py`:
- Around line 215-224: Remove the duplicate NumPy-style Raises section from the
public method’s docstring near the Returns documentation, preserving the
existing single ValueError Raises block and all other documentation.
In `@episodic/cost/engine.py`:
- Around line 64-66: Update the stale field references in the relevant Raises
documentation to use request.operation, request.billing_period_key, and
request.usage, matching the PricingRequest parameter documented near the pricing
method. Remove the obsolete standalone parameter references without changing the
pricing logic.
In `@episodic/llm/openai_api/utils.py`:
- Around line 185-188: Reduce the private helper docstrings to single-line
summaries by removing the structured sections: remove the Returns section from
_estimate_token_count in episodic/llm/openai_api/utils.py lines 185-188, remove
the Raises section from _validate_llm_config in episodic/llm/openai_api/utils.py
lines 444-447, and remove the Returns sections from
_build_assistant_content_literal in tests/steps/test_pedante_steps.py lines
90-93 and tests/steps/test_show_notes_steps.py lines 104-107.
In `@episodic/orchestration/_checkpoint_resume.py`:
- Around line 197-209: Update the public operation’s docstring in the
checkpoint-resume flow to retain a single NumPy-style Raises section after
Returns. Document TypeError for malformed checkpoint payloads and ValueError for
missing checkpoints or invalid step counts, replacing the duplicated or
incomplete exception documentation.
In `@episodic/orchestration/_guest_bios_executor.py`:
- Around line 156-158: Update the generator-initialization guard in the executor
method containing self.generator to raise ToolExecutionError instead of
RuntimeError, preserving the existing message and behavior while ensuring
execute() classifies the invariant failure as a tool-domain error.
In `@episodic/orchestration/_show_notes_executor.py`:
- Around line 152-154: Replace the generic RuntimeError raised in the generator
guard with the domain-specific ShowNotesGeneratorNotInitializedError. Keep the
existing initialization check and message, and ensure the named exception is
available from the module’s existing error definitions or imports.
In `@tests/fixtures/database.py`:
- Around line 161-165: Update the NumPy-style Yields documentation for the
affected fixture functions to describe individual yielded values: use sa.Table
for the synchronous generator and SQLAlchemyAsyncPGliteManager for the
asynchronous generator. Keep the iterator types in the return documentation
rather than the Yields sections.
In `@tests/snapshot_redaction.py`:
- Around line 17-29: Expand the docstring for redact_snapshot_uuids with a
NumPy-style Parameters section documenting the value argument, including
supported recursively traversed structures and pass-through values, while
preserving the existing examples and Returns section.
In `@tests/steps/test_architecture_enforcement_steps.py`:
- Around line 12-19: The deferred-annotation import is missing from the
orchestration step module, causing TYPE_CHECKING-only cabc annotations to fail
at import time. Add deferred annotations at the top of
tests/steps/test_generation_orchestration_steps.py (line 2) so _run_async_step
and orchestration_context remain valid;
tests/steps/test_architecture_enforcement_steps.py (lines 12-19) and
tests/steps/test_canonical_ingestion_steps.py (lines 10-11) require no direct
changes.
In `@tests/steps/test_canonical_repositories_steps.py`:
- Around line 10-20: Add from __future__ import annotations at the top of the
step module and move imports used only in annotations, including asyncio,
collections.abc, and AsyncSession, behind a TYPE_CHECKING guard. Preserve
runtime imports required by pytest-bdd step discovery and ensure annotations
remain evaluable during collection.
In `@tests/steps/test_source_intake_steps.py`:
- Around line 219-221: In the source intake step, add an assertion that
len(items) equals 1 immediately after the items cast and before indexing
items[0]. Keep the existing total and upload_id assertions unchanged so empty or
mismatched pages report a contract failure instead of raising IndexError.
In `@tests/test_binding_resolution_api.py`:
- Around line 27-31: Remove the structured Returns sections from the private
helpers _create_series_profile_binding and _create_episode_template_binding in
tests/test_binding_resolution_api.py (lines 27-31 and 61-64), and from _load in
tests/test_mutation_workflow_contract.py (lines 45-49). Keep each docstring as a
single-line summary and retain full NumPy-style sections only for public
interfaces.
In `@tests/test_binding_resolution.py`:
- Around line 26-27: Update every uow_with_fixtures parameter in the listed
tests to use the BindingFixtures annotation from tests/fixtures/binding.py, and
remove the ANN001 suppressions and their explanatory comments. Keep the existing
test behavior unchanged while ensuring all affected fixture parameters are fully
typed.
In `@tests/test_chapter_markers.py`:
- Around line 103-105: Remove the duplicate enriched_xml-to-snapshot assertion
in the test, keeping the more descriptive assertion message that states the
expected enriched TEI must match the snapshot.
In `@tests/test_generation_run_domain.py`:
- Around line 287-308: Remove redact_snapshot_uuids from the generation-run
representation and error-message snapshot comparisons so deterministic
FIXED_RUN_ID, FIXED_EPISODE_ID, FIXED_SOURCE_BUNDLE_ID, and FIXED_CHECKPOINT_ID
remain visible and are compared directly. If runtime-generated UUIDs also
require normalization, redact only those values rather than the fixed
identifiers.
In `@tests/test_interpreter_executor_lifecycle.py`:
- Around line 60-66: Add a shutdown-entry Event around the executor.shutdown
call launched by asyncio.to_thread, set it when shutdown begins, and await that
event before releasing blocking_executor.release_map. Replace the
asyncio.sleep(0) synchronization in the lifecycle test while preserving the
assertion that shutdown_called remains unset until the map is released.
In `@tests/test_interpreter_executor_observability.py`:
- Around line 203-208: Replace the manual try/finally cleanup around
executor.map_ordered in the test with a context-managed lifecycle, using the
executor’s context-manager support or contextlib.ExitStack. Preserve the
assertion and ensure executor.shutdown is guaranteed automatically without
explicit teardown code.
In `@tests/test_llm_openai_adapter_retries.py`:
- Around line 49-53: Update the private helper _make_fail_once_handler docstring
to contain only a single-line summary, removing the added Returns section while
preserving its tuple return annotation.
In `@tests/test_reference_document_models.py`:
- Around line 30-33: Collapse the private helper docstrings for
_build_reference_binding in tests/test_reference_document_models.py:30-33 and
_create_two_series_profile_bindings in
tests/test_reference_document_service_queries.py:95-98 to single-line summaries,
removing their structured Returns sections.
In `@tests/test_serializers.py`:
- Around line 23-35: Update the _assert_serialized_fields helper’s actual
parameter from dict[str, typ.Any] to dict[str, object], preserving its existing
indexing, comparison, and required-key assertions.
In `@tests/test_show_notes_executor.py`:
- Around line 239-241: Update the assertion message accompanying the negated
isinstance check on exc_info.value to state that provider errors must not be
wrapped in ToolExecutionError, while leaving the assertion logic unchanged.
In `@tests/test_workflow_utils.py`:
- Around line 22-35: Update assert_validation_workflow_result to retrieve status
and execution_mode with data.get before asserting, so missing fields produce
assertion failures rather than KeyError. Replace its brief docstring with a
complete NumPy-style docstring documenting all parameters, assertion failure
behavior, and an example showing successful usage and outcome.
---
Outside diff comments:
In `@alembic/env.py`:
- Around line 40-49: The _configure_database_url function should raise a
specific database-configuration domain exception when neither DATABASE_URL nor
sqlalchemy.url is available, falling back to ValueError if no domain error
exists at this boundary. Preserve the existing error message and leave the valid
URL configuration paths unchanged.
In `@episodic/canonical/storage/repositories.py`:
- Line 2: Remove the module-level too-many-lines suppressions from
episodic/canonical/storage/repositories.py lines 2-2 and
episodic/canonical/storage/source_intake_repositories.py lines 2-2, then
decompose each repository module to satisfy the file-size lint; use only
narrowly scoped suppressions where unavoidable and justified.
In `@episodic/cost/recorder.py`:
- Around line 103-104: Restore the NumPy-style Raises documentation in the
affected public interfaces near the recorder methods, including LookupError and
CostAccountingError as propagated domain exceptions. Apply the same
documentation update to the second affected interface while preserving the
existing parameter, return, and description sections.
In `@episodic/qa/chrono_langgraph.py`:
- Around line 52-67: Replace the chrono_request and chrono_result Any
annotations in ChronoGraphState with ChronoEvaluationRequest | None and
ChronoRuntimeEstimate | None, respectively. Update chrono_node to return
dict[str, ChronoRuntimeEstimate], importing or reusing the concrete Chrono types
already defined for the evaluator seam.
In `@tests/fixtures/history_entries.py`:
- Around line 69-77: Update the history-entry builder’s docstring to replace the
generic Returns section with a NumPy-style Examples section. Use a concrete
history-entry class and parent field, invoke it with a specific revision, and
show the resulting attributes, including the parent identifier and revision.
In `@tests/steps/test_chapter_markers_steps.py`:
- Line 14: Restore the postponed-annotations future import in every affected
step module: tests/steps/test_chapter_markers_steps.py (14-14),
tests/steps/test_chrono_steps.py (2-3),
tests/steps/test_generation_run_lifecycle_steps.py (2-3),
tests/steps/test_guest_bios_steps.py (14-14), and
tests/steps/test_http_service_scaffold_steps.py (3-16). Place it with the
module’s other future imports so TYPE_CHECKING-only annotation names remain safe
during step discovery.
In `@tests/steps/test_worker_service_scaffold_steps.py`:
- Around line 2-3: Restore `from __future__ import annotations` at the top of
the pytest-bdd step module, before runtime imports such as `dataclasses`.
Preserve deferred annotation evaluation so step discovery supports annotations
referencing `TYPE_CHECKING`-only names.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: b3c7bab6-5c86-47f8-9911-45a8941ef84a
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (261)
Makefilealembic/env.pyalembic/versions/20260203_000001_create_canonical_schema.pyalembic/versions/20260220_000002_add_profile_template_history_schema.pyalembic/versions/20260226_000003_add_zstd_payload_columns.pyambrleaks.tomlepisodic/api/dependencies.pyepisodic/api/handlers.pyepisodic/api/helpers.pyepisodic/api/resources/episode_templates.pyepisodic/api/resources/reference_documents.pyepisodic/api/resources/series_profiles.pyepisodic/api/resources/source_intake.pyepisodic/api/serializers.pyepisodic/api/source_idempotency.pyepisodic/api/source_intake_support.pyepisodic/asyncio_tasks.pyepisodic/benchmarks/__init__.pyepisodic/benchmarks/interpreters.pyepisodic/canonical/adapters/generation_runs.pyepisodic/canonical/adapters/normalizer.pyepisodic/canonical/adapters/resolver.pyepisodic/canonical/adapters/weighting.pyepisodic/canonical/briefs.pyepisodic/canonical/ingestion_service.pyepisodic/canonical/object_store.pyepisodic/canonical/profile_templates/_brief_reference_documents.pyepisodic/canonical/profile_templates/brief.pyepisodic/canonical/profile_templates/services/_generic.pyepisodic/canonical/profile_templates/services/_typed.pyepisodic/canonical/prompts.pyepisodic/canonical/reference_documents/_binding_creation.pyepisodic/canonical/reference_documents/_binding_queries.pyepisodic/canonical/reference_documents/resolution.pyepisodic/canonical/reference_documents/revisions.pyepisodic/canonical/reference_documents/snapshots.pyepisodic/canonical/source_intake_runtime.pyepisodic/canonical/source_intake_service.pyepisodic/canonical/source_intake_types.pyepisodic/canonical/storage/compression.pyepisodic/canonical/storage/filesystem_object_store.pyepisodic/canonical/storage/ingestion_job_repositories.pyepisodic/canonical/storage/integrity_helpers.pyepisodic/canonical/storage/reference_document_schema.pyepisodic/canonical/storage/reference_repositories.pyepisodic/canonical/storage/repositories.pyepisodic/canonical/storage/repository_base.pyepisodic/canonical/storage/source_intake_models.pyepisodic/canonical/storage/source_intake_repositories.pyepisodic/canonical/storage/uow.pyepisodic/canonical/storage/workflow_checkpoints.pyepisodic/canonical/tei.pyepisodic/concurrent_interpreters.pyepisodic/cost/engine.pyepisodic/cost/ports.pyepisodic/cost/pricing_catalogue/file_loader.pyepisodic/cost/recorder.pyepisodic/generation/chapter_marker_segments.pyepisodic/generation/chapter_markers.pyepisodic/generation/show_notes.pyepisodic/generation/tei_payload.pyepisodic/llm/__init__.pyepisodic/llm/openai_api/adapter.pyepisodic/llm/openai_api/utils.pyepisodic/llm/openai_chat.pyepisodic/llm/ports.pyepisodic/logging.pyepisodic/observability.pyepisodic/orchestration/_checkpoint_resume.pyepisodic/orchestration/_guest_bios_executor.pyepisodic/orchestration/_show_notes_executor.pyepisodic/orchestration/checkpoints.pyepisodic/orchestration/langgraph.pyepisodic/qa/chrono.pyepisodic/qa/chrono_langgraph.pyepisodic/qa/langgraph.pyepisodic/worker/runtime.pyepisodic/worker/tasks.pyepisodic/worker/topology.pypyproject.tomlscripts/local_k8s/commands.pyscripts/local_k8s/config.pyscripts/local_k8s/orchestration.pyscripts/tests/test_typos_rollout.pyscripts/typos_rollout.pyscripts/typos_rollout_cache.pytests/__snapshots__/test_api_helpers.ambrtests/__snapshots__/test_architecture_enforcement.ambrtests/__snapshots__/test_architecture_hecate_config.ambrtests/__snapshots__/test_chapter_markers.ambrtests/__snapshots__/test_container_image_contract.ambrtests/__snapshots__/test_generation_run_domain.ambrtests/__snapshots__/test_guest_bios_binding.ambrtests/__snapshots__/test_guest_bios_executor.ambrtests/__snapshots__/test_guest_bios_generator.ambrtests/__snapshots__/test_health_endpoints.ambrtests/__snapshots__/test_helm_chart_contract.ambrtests/__snapshots__/test_ingestion_integration_e2e.ambrtests/__snapshots__/test_ingestion_resolver.ambrtests/__snapshots__/test_llm_guardrails.ambrtests/__snapshots__/test_llm_openai_adapter_usage_metering.ambrtests/__snapshots__/test_local_k8s_kind_tooling.ambrtests/__snapshots__/test_local_k8s_tooling.ambrtests/__snapshots__/test_logging.ambrtests/__snapshots__/test_serializers.ambrtests/__snapshots__/test_show_notes_prompting.ambrtests/__snapshots__/test_show_notes_tei_enrichment.ambrtests/__snapshots__/test_worker_routing_contract.ambrtests/_guest_bios_executor_helpers.pytests/_orchestration_fakes.pytests/_orchestration_property_support.pytests/canonical_storage/_workflow_checkpoint_support.pytests/canonical_storage/conftest.pytests/canonical_storage/test_approval_events.pytests/canonical_storage/test_episodes.pytests/canonical_storage/test_history_repositories.pytests/canonical_storage/test_ingestion_jobs.pytests/canonical_storage/test_repositories.pytests/canonical_storage/test_series_profiles.pytests/canonical_storage/test_source_documents.pytests/canonical_storage/test_source_intake_repositories.pytests/canonical_storage/test_source_intake_transition_properties.pytests/canonical_storage/test_tei_headers.pytests/canonical_storage/test_unit_of_work.pytests/canonical_storage/test_workflow_checkpoints.pytests/fixtures/architecture/allowed_case/api.pytests/fixtures/architecture/allowed_case/service.pytests/fixtures/architecture/allowed_case/storage.pytests/fixtures/architecture/api_imports_cyclic_star_reexported_outbound_adapter/__init__.pytests/fixtures/architecture/api_imports_cyclic_star_reexported_outbound_adapter/a.pytests/fixtures/architecture/api_imports_cyclic_star_reexported_outbound_adapter/b.pytests/fixtures/architecture/api_imports_nested_star_reexported_outbound_adapter/__init__.pytests/fixtures/architecture/api_imports_nested_star_reexported_outbound_adapter/barrel.pytests/fixtures/architecture/api_imports_outbound_adapter/api.pytests/fixtures/architecture/api_imports_star_reexported_outbound_adapter/api.pytests/fixtures/architecture/domain_imports_storage/domain.pytests/fixtures/database.pytests/fixtures/history_entries.pytests/fixtures/llm.pytests/fixtures/test_database.pytests/snapshot_redaction.pytests/steps/generation_orchestration_vidaimock.pytests/steps/multi_source_ingestion_support.pytests/steps/source_intake_api_helpers.pytests/steps/source_intake_support.pytests/steps/test_architecture_enforcement_steps.pytests/steps/test_binding_resolution_steps.pytests/steps/test_canonical_ingestion_steps.pytests/steps/test_canonical_repositories_steps.pytests/steps/test_chapter_markers_steps.pytests/steps/test_chrono_steps.pytests/steps/test_generation_orchestration_steps.pytests/steps/test_generation_run_lifecycle_steps.pytests/steps/test_guest_bios_steps.pytests/steps/test_http_service_scaffold_steps.pytests/steps/test_llm_adapter_steps.pytests/steps/test_pedante_steps.pytests/steps/test_profile_template_api_steps.pytests/steps/test_reference_document_api_steps.pytests/steps/test_reference_document_model_steps.pytests/steps/test_schema_migrations_steps.pytests/steps/test_show_notes_steps.pytests/steps/test_source_intake_steps.pytests/steps/test_worker_service_scaffold_steps.pytests/test_api_helpers.pytests/test_architecture_enforcement.pytests/test_architecture_hecate_config.pytests/test_binding_resolution.pytests/test_binding_resolution_api.pytests/test_binding_resolution_validation.pytests/test_brief_reference_documents.pytests/test_chapter_marker_dtos.pytests/test_chapter_marker_generation.pytests/test_chapter_marker_parsing.pytests/test_chapter_marker_prompt.pytests/test_chapter_markers.pytests/test_chrono.pytests/test_chrono_contracts.pytests/test_chrono_langgraph.pytests/test_compat.pytests/test_container_image_contract.pytests/test_cost_ports_protocols.pytests/test_cost_pricing_catalogue_file_loader.pytests/test_cost_pricing_engine_properties.pytests/test_cost_recorder.pytests/test_env_runtime_wiring.pytests/test_episode_template_service.pytests/test_filesystem_object_store.pytests/test_generation_orchestration_langgraph.pytests/test_generation_orchestration_snapshots.pytests/test_generation_run_domain.pytests/test_guest_bios_binding.pytests/test_guest_bios_enrichment.pytests/test_guest_bios_executor.pytests/test_guest_bios_executor_errors.pytests/test_guest_bios_generator.pytests/test_guest_bios_properties.pytests/test_health_endpoints.pytests/test_helm_chart_contract.pytests/test_http_service_scaffold_support.pytests/test_idempotency_properties.pytests/test_idempotency_service.pytests/test_ingestion_integration_e2e.pytests/test_ingestion_integration_support.pytests/test_ingestion_resolver.pytests/test_interpreter_executor.pytests/test_interpreter_executor_lifecycle.pytests/test_interpreter_executor_observability.pytests/test_lifespan_hooks.pytests/test_llm_guardrails.pytests/test_llm_openai_adapter_budgets.pytests/test_llm_openai_adapter_config.pytests/test_llm_openai_adapter_retries.pytests/test_llm_openai_adapter_usage_metering.pytests/test_local_k8s_kind_tooling.pytests/test_local_k8s_tooling.pytests/test_logging.pytests/test_mutation_workflow_contract.pytests/test_openai_type_guards.pytests/test_orchestration_config_model_tier_properties.pytests/test_orchestration_dto_validation.pytests/test_orchestration_graph_invariant_properties.pytests/test_orchestration_langgraph_properties.pytests/test_orchestration_orchestrator.pytests/test_orchestration_planner.pytests/test_orchestration_properties.pytests/test_orchestration_usage.pytests/test_pedante_langgraph.pytests/test_profile_template_api.pytests/test_profile_template_helpers.pytests/test_prompt_templates.pytests/test_protocol_stubs.pytests/test_reference_document_access.pytests/test_reference_document_api_support.pytests/test_reference_document_bindings_facade.pytests/test_reference_document_models.pytests/test_reference_document_service_alignment.pytests/test_reference_document_service_conflicts.pytests/test_reference_document_service_history.pytests/test_reference_document_service_locking.pytests/test_reference_document_service_queries.pytests/test_reference_document_service_validation.pytests/test_serializers.pytests/test_series_profile_service.pytests/test_show_notes_executor.pytests/test_show_notes_parsing.pytests/test_show_notes_prompting.pytests/test_show_notes_tei_enrichment.pytests/test_snapshot_sources.pytests/test_source_intake_api.pytests/test_source_intake_api_contract.pytests/test_source_intake_service.pytests/test_storage_compression.pytests/test_uuid_assertions.pytests/test_worker_interpreter_task_integration.pytests/test_worker_routing_contract.pytests/test_worker_service_scaffold.pytests/test_workflow_bootstrap_gitops_repo.pytests/test_workflow_provision_doks.pytests/test_workflow_test_utils.pytests/test_workflow_utils.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/hecate(auto-detected)leynos/femtologging(auto-detected)leynos/tei-rapporteur(auto-detected)leynos/falcon-correlate(auto-detected)leynos/shared-actions(auto-detected)
💤 Files with no reviewable changes (44)
- tests/test_openai_type_guards.py
- episodic/llm/init.py
- tests/canonical_storage/test_episodes.py
- episodic/canonical/tei.py
- episodic/api/resources/episode_templates.py
- episodic/canonical/reference_documents/_binding_creation.py
- tests/canonical_storage/test_tei_headers.py
- tests/steps/source_intake_support.py
- tests/test_uuid_assertions.py
- episodic/canonical/source_intake_types.py
- tests/test_storage_compression.py
- tests/steps/source_intake_api_helpers.py
- tests/steps/multi_source_ingestion_support.py
- tests/_guest_bios_executor_helpers.py
- tests/canonical_storage/conftest.py
- scripts/tests/test_typos_rollout.py
- episodic/benchmarks/init.py
- episodic/canonical/storage/compression.py
- scripts/typos_rollout_cache.py
- episodic/llm/ports.py
- episodic/benchmarks/interpreters.py
- episodic/canonical/prompts.py
- episodic/api/resources/source_intake.py
- tests/canonical_storage/test_repositories.py
- episodic/canonical/briefs.py
- tests/test_prompt_templates.py
- episodic/canonical/profile_templates/services/_typed.py
- episodic/canonical/profile_templates/brief.py
- episodic/canonical/storage/repository_base.py
- tests/canonical_storage/test_source_documents.py
- tests/canonical_storage/test_series_profiles.py
- episodic/canonical/profile_templates/services/_generic.py
- episodic/logging.py
- tests/canonical_storage/test_ingestion_jobs.py
- episodic/llm/openai_chat.py
- tests/canonical_storage/test_history_repositories.py
- tests/canonical_storage/test_unit_of_work.py
- episodic/api/source_intake_support.py
- episodic/asyncio_tasks.py
- episodic/generation/tei_payload.py
- episodic/api/source_idempotency.py
- alembic/versions/20260226_000003_add_zstd_payload_columns.py
- tests/canonical_storage/test_approval_events.py
- alembic/versions/20260220_000002_add_profile_template_history_schema.py
| map_profile_template_error | ||
| If the operation cannot be completed. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Document concrete exception contracts.
Name exception classes actually raised at each boundary; do not list mapper or validation helper functions as Raises entries.
episodic/api/handlers.py#L73-L74: document the concrete Falcon error mapped fromEntityNotFoundError.episodic/api/handlers.py#L125-L126: document the concrete Falcon error mapped fromEntityNotFoundError.episodic/api/handlers.py#L172-L175: document the concrete mapped update exceptions.episodic/api/handlers.py#L227-L227: restore the update handler’sRaisessection.episodic/api/handlers.py#L276-L281: replace helper-function names with the concrete validation and HTTP exception types.episodic/orchestration/_show_notes_executor.py#L239-L240: restoreexecuteexceptions for unsupported actions, malformed responses, provider failures, and translated tool failures.
As per path instructions, “Docstrings must follow the numpy style guide … full structured docs for all public interfaces.”
📍 Affects 2 files
episodic/api/handlers.py#L73-L74(this comment)episodic/api/handlers.py#L125-L126episodic/api/handlers.py#L172-L175episodic/api/handlers.py#L227-L227episodic/api/handlers.py#L276-L281episodic/orchestration/_show_notes_executor.py#L239-L240
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@episodic/api/handlers.py` around lines 73 - 74, Update the NumPy-style Raises
sections in episodic/api/handlers.py at lines 73-74 and 125-126 to name the
concrete Falcon exception mapped from EntityNotFoundError; at lines 172-175
document the concrete mapped update exceptions; at line 227 restore the update
handler’s Raises section; and at lines 276-281 replace mapper/validation helper
names with the concrete validation and HTTP exception classes. In
episodic/orchestration/_show_notes_executor.py lines 239-240, restore execute’s
Raises documentation for unsupported actions, malformed responses, provider
failures, and translated tool failures, naming the actual exception classes
raised at each boundary.
Source: Path instructions
| validation_error | ||
| If the operation cannot be completed. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Document the concrete exception class.
Name the exception returned by validation_error(...), rather than the factory itself, in every Raises section. Preserve the validation-envelope details in prose; the downstream contract accepts falcon.HTTPBadRequest. Based on runtime coverage in tests/test_api_helpers.py:254-264.
Also applies to: 93-94, 177-180, 225-226, 379-380, 409-410, 451-452, 483-484
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@episodic/api/helpers.py` around lines 68 - 69, Update every Raises entry in
the documented helpers, including the sections around validation_error at the
referenced locations, to name falcon.HTTPBadRequest as the raised exception
instead of validation_error(...). Retain the existing prose describing the
validation envelope and apply the same concrete exception wording consistently
across all listed sections.
|
@coderabbitai resume |
✅ Action performedReviews resumed. |
Add the lading-style Pylint gate alongside Ruff, run the pinned df12 Pylint plug-in and ambrleaks explicitly on CPython 3.14, and expand Ruff's preview, async, and documentation checks. Repair the resulting contracts throughout the codebase with explicit annotations, useful assertions, deterministic snapshots, and documented public behaviour so every configured quality gate remains clean.
Replace repeated field, error-envelope, checkpoint, and workflow result assertions with domain-focused helpers. Keep test bodies declarative while preserving precise failure messages at each behavioural boundary.
Move planner-result deserialization and single-step validation into a focused private helper. Keep the public resume flow and its side-effect ordering unchanged while reducing the orchestration function's size.
Move token-dependent planner and action construction plus usage invariant assertions into fully typed module helpers. Keep the Hypothesis graph flow and state assertions focused on orchestration behaviour.
Extend the multipart upload helper with optional JSON metadata and use it for the end-to-end upload and replay requests. Preserve existing callers, assertions, and request shapes when metadata is absent.
Centralize status and error-code checks for the HTTPX contract tests while keeping each endpoint and state contract independently exercised.
Replace the multi-argument test helper boundary with an immutable request object while preserving multipart bodies, authorization scope, and idempotent replay behaviour.
Retain stringified annotations in pytest-bdd step modules so runtime annotation inspection remains compatible with type-check-only imports. Keep C9112 enabled elsewhere through a dedicated CPython 3.14 lint pass. Document the df12 Pylint and `ambrleaks` workflow, including its scope and interpreter choice. Restore the concrete Falcon exceptions in the shared handler contracts without changing their error envelopes.
Keep annotation dependencies available at runtime after removing stringified future annotations from the spelling-policy scripts. Use `typing.Self` for nested response context managers whose class names are not available while their annotations are evaluated. Apply the spelling gate's pinned formatter and refresh the generated `typos.toml` from the current shared dictionary.
Restore concrete exception and return contracts in public documentation, and keep private helper documentation concise. Correct the remaining runtime, typing, snapshot, and synchronization findings confirmed against the current branch. Split the residual oversized source-intake repository support and binding scenario test into focused modules instead of retaining broad lint suppressions.
Name the df12 Python lint plug-in and `ambrleaks` stages in contributor guidance, including their CPython 3.14 requirement and package pin.
There was a problem hiding this comment.
Actionable comments posted: 21
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
tests/test_cost_pricing_engine_properties.py (1)
60-70: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winKeep the private helper docstring single-line and accurate.
_exact_ratesis private, so replace the new structuredReturnsblock with a single-line summary. The current description is also inaccurate: this helper returns generated per-metric rates, not an operation result.As per path instructions, private functions must use a single-line summary.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_cost_pricing_engine_properties.py` around lines 60 - 70, Update the private helper _exact_rates docstring to a single-line summary that accurately describes it as generating per-metric rates, and remove the structured Returns section.Source: Path instructions
alembic/env.py (1)
42-49: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winEscape
%inDATABASE_URLbefore callingset_main_option.
ConfigParsertreats%40and other encoded credentials as interpolation, so a valid URL can raiseValueErrorbefore migrations start. Replace%with%%, or bypassConfigParserwhen settingsqlalchemy.url.Suggested change
- config.set_main_option("sqlalchemy.url", db_url) + config.set_main_option("sqlalchemy.url", db_url.replace("%", "%%"))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@alembic/env.py` around lines 42 - 49, Update the DATABASE_URL handling in the alembic environment setup to escape percent signs before passing the value to config.set_main_option, preserving encoded credentials such as %40 without interpolation errors. Keep the existing fallback and validation behavior unchanged.episodic/generation/show_notes.py (1)
381-385: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winRestore the public error contract.
Document
ShowNotesResponseFormatError, whichgenerateexposes through
_result_from_response, in aRaisessection.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@episodic/generation/show_notes.py` around lines 381 - 385, Update the `generate` method docstring to add a `Raises` section documenting `ShowNotesResponseFormatError`, which may propagate through `_result_from_response`. Keep the existing return documentation unchanged.Source: Coding guidelines
tests/test_orchestration_graph_invariant_properties.py (1)
252-260: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winKeep the private helper docstring to one line.
Remove the
Returnssection. As per path instructions, “Use a single-line summary
for private functions and methods”.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_orchestration_graph_invariant_properties.py` around lines 252 - 260, Shorten the private helper’s docstring to a single-line summary by removing the Returns section and its detailed return description, while preserving a concise statement of the helper’s purpose.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@episodic/api/helpers.py`:
- Around line 173-184: Shorten the _parse_int_query_param docstring to a
single-line behavior summary, removing the generated Returns and Raises sections
and their associated noqa annotation while preserving the function’s behavior.
In `@episodic/canonical/storage/integrity_helpers.py`:
- Around line 28-32: Replace the generic Returns descriptions in
integrity_helpers.py: document the constraint-discovery helper as returning the
discovered PostgreSQL constraint name or None, and document the integrity-error
helper as returning whether the error represents a revision conflict. In
tests/test_source_intake_api.py, remove the newly added generic Returns section
from the private helper’s docstring.
In `@episodic/canonical/storage/source_intake_repository_runtime.py`:
- Around line 19-45: Expand the docstrings for the public
SourceIntakeStorageRuntime dataclass and source_intake_storage_runtime factory
with full NumPy-style Attributes, Parameters, and Returns sections. Document
each runtime provider field, factory argument including optional defaults, and
the returned SourceIntakeStorageRuntime; leave the private helper docstrings
unchanged.
- Around line 8-13: Update the observability imports in
source_intake_repository_runtime.py so MetricsPort and MonotonicClockPort are
imported only within a TYPE_CHECKING guard, while NoopMetrics and
PerfCounterClock remain runtime imports. Ensure annotations continue resolving
correctly without adding unnecessary runtime dependencies.
In `@episodic/cost/pricing_catalogue/file_loader.py`:
- Line 93: Update _is_string_mapping to use an explicit guard clause: return
False immediately when value is not a dictionary, then run the existing all()
check over value.items() without the type-checker suppression comment.
In `@episodic/generation/show_notes.py`:
- Around line 243-251: Update the docstring for the affected operation in
show_notes.py to state that it returns the input string unchanged or None, and
raises ShowNotesResponseFormatError only when value is neither a string nor
None. Replace the generic return and exception descriptions without changing the
implementation.
In `@episodic/orchestration/_show_notes_executor.py`:
- Line 74: Shorten the single-line docstring summaries for
_handle_generator_error at episodic/orchestration/_show_notes_executor.py:74-74
and _invoke_show_notes_generator at
episodic/orchestration/_show_notes_executor.py:214-214 so both stay within the
line limit, then remove their E501 noqa suppressions while preserving their
existing meaning.
In `@episodic/orchestration/langgraph.py`:
- Line 273: Update the inline rationale on the broad exception handler in the
callback handling path to describe deliberately swallowing callback failures so
the computed graph result is preserved. Remove the inaccurate reference to
translating failures, while leaving the exception handling, logging, and result
behavior unchanged.
- Around line 375-379: The return sections for _build_execute_node and
build_generation_orchestration_graph are too generic. Update each docstring to
explicitly describe its contract: _build_execute_node returns a tuple containing
the execute-node callable and graph target, while
build_generation_orchestration_graph returns the compiled graph containing the
plan, execute, and finish nodes.
In `@episodic/qa/langgraph.py`:
- Line 11: Update the inline noqa comment on the .pedante import in
episodic/qa/langgraph.py to explain that the import is required at runtime for
LangGraph state-annotation introspection, removing the incorrect SQLAlchemy
mapped-model rationale.
In `@episodic/worker/topology.py`:
- Around line 149-170: Shorten the private helper’s docstring to a single-line
summary describing that it maps each configured workload class to its queue.
Remove the Returns, Raises, and Examples sections from the docstring associated
with _validate_unique_workload_mappings.
In `@scripts/tests/test_typos_rollout.py`:
- Line 9: Move the annotation-only imports behind typ.TYPE_CHECKING guards:
update scripts/tests/test_typos_rollout.py at lines 9-9 for types,
scripts/typos_rollout.py at lines 3-3 for collections.abc as cabc, and
scripts/typos_rollout_cache.py at lines 3-3 for collections.abc as cabc;
preserve their availability for type annotations without loading them at
runtime.
In `@tests/canonical_storage/test_source_intake_repositories.py`:
- Around line 220-222: Update the assertion for the acquired result in the
source-intake test to require isinstance(acquired, Acquired) instead of
excluding Replay, Conflict, and InFlight. Preserve the existing failure message
if applicable and ensure the test explicitly verifies the Acquired outcome.
In `@tests/fixtures/database.py`:
- Around line 58-66: Update the _should_use_pglite private helper docstring to a
single-line summary by removing its Returns and Raises sections, while
preserving the summary’s description of the helper’s behavior.
In `@tests/fixtures/history_entries.py`:
- Around line 73-87: Update the public build_history_entry docstring to restore
a structured NumPy-style Returns section describing the constructed
history-entry instance, while retaining the existing Examples section. Remove
the DOC201 suppression because the docstring should satisfy the documentation
check.
In `@tests/fixtures/llm.py`:
- Around line 56-60: Update the fixture docstring’s Yields entry to document
_OpenAILogSpy, the value produced on each iteration, instead of
cabc.Generator[_OpenAILogSpy]. Preserve the existing NumPy-style Yields section
and description.
In `@tests/steps/test_llm_adapter_steps.py`:
- Line 105: Remove the inline pylint suppression above the parameter-rich
constructor in the test step; refactor that constructor signature to satisfy
too-many-arguments, or configure the exception through the approved lint
configuration. Preserve only permitted narrow inline noqa disables and do not
replace this with another line-level pylint disable.
In `@tests/test_helm_chart_contract.py`:
- Around line 67-72: In the manifest-redaction helper, remove the one-use
redacted_manifest assignment and return the re.sub(...).rstrip() result
directly, preserving the existing regex and replacement behavior so the code
satisfies R504.
In `@tests/test_llm_openai_adapter_budgets.py`:
- Line 84: Update the assertion message for estimated_tokens in the
non-negativity check to state that estimated_tokens must be non-negative,
replacing the inaccurate ordering-related text.
In `@tests/test_serializers.py`:
- Line 50: Replace the type suppression on all three defaults.update(overrides)
calls in tests/test_serializers.py at lines 50-50, 67-67, and 83-83 with the ty
suppression form # ty: ignore[invalid-argument-type], preserving the existing
fixture behavior and suppression style.
In `@tests/test_source_intake_api.py`:
- Around line 369-376: Update the _TextUploadRequest dataclass declaration to
include slots=True while preserving its frozen and keyword-only configuration
and existing fields.
---
Outside diff comments:
In `@alembic/env.py`:
- Around line 42-49: Update the DATABASE_URL handling in the alembic environment
setup to escape percent signs before passing the value to
config.set_main_option, preserving encoded credentials such as %40 without
interpolation errors. Keep the existing fallback and validation behavior
unchanged.
In `@episodic/generation/show_notes.py`:
- Around line 381-385: Update the `generate` method docstring to add a `Raises`
section documenting `ShowNotesResponseFormatError`, which may propagate through
`_result_from_response`. Keep the existing return documentation unchanged.
In `@tests/test_cost_pricing_engine_properties.py`:
- Around line 60-70: Update the private helper _exact_rates docstring to a
single-line summary that accurately describes it as generating per-metric rates,
and remove the structured Returns section.
In `@tests/test_orchestration_graph_invariant_properties.py`:
- Around line 252-260: Shorten the private helper’s docstring to a single-line
summary by removing the Returns section and its detailed return description,
while preserving a concise statement of the helper’s purpose.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: d02359b2-fd80-4b2d-ac2c-54e46a8211b0
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (267)
AGENTS.mdMakefilealembic/env.pyalembic/versions/20260203_000001_create_canonical_schema.pyalembic/versions/20260220_000002_add_profile_template_history_schema.pyalembic/versions/20260226_000003_add_zstd_payload_columns.pyambrleaks.tomldocs/developers-guide.mdepisodic/api/dependencies.pyepisodic/api/handlers.pyepisodic/api/helpers.pyepisodic/api/resources/episode_templates.pyepisodic/api/resources/reference_documents.pyepisodic/api/resources/series_profiles.pyepisodic/api/resources/source_intake.pyepisodic/api/serializers.pyepisodic/api/source_idempotency.pyepisodic/api/source_intake_support.pyepisodic/asyncio_tasks.pyepisodic/benchmarks/__init__.pyepisodic/benchmarks/interpreters.pyepisodic/canonical/adapters/generation_runs.pyepisodic/canonical/adapters/normalizer.pyepisodic/canonical/adapters/resolver.pyepisodic/canonical/adapters/weighting.pyepisodic/canonical/briefs.pyepisodic/canonical/ingestion_service.pyepisodic/canonical/object_store.pyepisodic/canonical/profile_templates/_brief_reference_documents.pyepisodic/canonical/profile_templates/brief.pyepisodic/canonical/profile_templates/services/_generic.pyepisodic/canonical/profile_templates/services/_typed.pyepisodic/canonical/prompts.pyepisodic/canonical/reference_documents/_binding_creation.pyepisodic/canonical/reference_documents/_binding_queries.pyepisodic/canonical/reference_documents/resolution.pyepisodic/canonical/reference_documents/revisions.pyepisodic/canonical/reference_documents/snapshots.pyepisodic/canonical/source_intake_runtime.pyepisodic/canonical/source_intake_service.pyepisodic/canonical/source_intake_types.pyepisodic/canonical/storage/compression.pyepisodic/canonical/storage/filesystem_object_store.pyepisodic/canonical/storage/ingestion_job_repositories.pyepisodic/canonical/storage/integrity_helpers.pyepisodic/canonical/storage/reference_document_schema.pyepisodic/canonical/storage/reference_repositories.pyepisodic/canonical/storage/repositories.pyepisodic/canonical/storage/repository_base.pyepisodic/canonical/storage/source_intake_models.pyepisodic/canonical/storage/source_intake_repositories.pyepisodic/canonical/storage/source_intake_repository_runtime.pyepisodic/canonical/storage/uow.pyepisodic/canonical/storage/workflow_checkpoints.pyepisodic/canonical/tei.pyepisodic/concurrent_interpreters.pyepisodic/cost/engine.pyepisodic/cost/ports.pyepisodic/cost/pricing_catalogue/file_loader.pyepisodic/cost/recorder.pyepisodic/generation/chapter_marker_segments.pyepisodic/generation/chapter_markers.pyepisodic/generation/show_notes.pyepisodic/generation/tei_payload.pyepisodic/llm/__init__.pyepisodic/llm/openai_api/adapter.pyepisodic/llm/openai_api/utils.pyepisodic/llm/openai_chat.pyepisodic/llm/ports.pyepisodic/logging.pyepisodic/observability.pyepisodic/orchestration/_checkpoint_resume.pyepisodic/orchestration/_guest_bios_executor.pyepisodic/orchestration/_show_notes_executor.pyepisodic/orchestration/_types.pyepisodic/orchestration/checkpoints.pyepisodic/orchestration/langgraph.pyepisodic/qa/chrono.pyepisodic/qa/chrono_langgraph.pyepisodic/qa/langgraph.pyepisodic/worker/runtime.pyepisodic/worker/tasks.pyepisodic/worker/topology.pypyproject.tomlscripts/local_k8s/commands.pyscripts/local_k8s/config.pyscripts/local_k8s/orchestration.pyscripts/tests/test_typos_rollout.pyscripts/typos_rollout.pyscripts/typos_rollout_cache.pytests/__snapshots__/test_api_helpers.ambrtests/__snapshots__/test_architecture_enforcement.ambrtests/__snapshots__/test_architecture_hecate_config.ambrtests/__snapshots__/test_container_image_contract.ambrtests/__snapshots__/test_guest_bios_binding.ambrtests/__snapshots__/test_guest_bios_executor.ambrtests/__snapshots__/test_guest_bios_generator.ambrtests/__snapshots__/test_health_endpoints.ambrtests/__snapshots__/test_helm_chart_contract.ambrtests/__snapshots__/test_ingestion_integration_e2e.ambrtests/__snapshots__/test_ingestion_resolver.ambrtests/__snapshots__/test_llm_guardrails.ambrtests/__snapshots__/test_llm_openai_adapter_usage_metering.ambrtests/__snapshots__/test_local_k8s_kind_tooling.ambrtests/__snapshots__/test_local_k8s_tooling.ambrtests/__snapshots__/test_logging.ambrtests/__snapshots__/test_serializers.ambrtests/__snapshots__/test_show_notes_prompting.ambrtests/__snapshots__/test_show_notes_tei_enrichment.ambrtests/__snapshots__/test_worker_routing_contract.ambrtests/_guest_bios_executor_helpers.pytests/_orchestration_fakes.pytests/_orchestration_property_support.pytests/canonical_storage/_workflow_checkpoint_support.pytests/canonical_storage/conftest.pytests/canonical_storage/test_approval_events.pytests/canonical_storage/test_episodes.pytests/canonical_storage/test_history_repositories.pytests/canonical_storage/test_ingestion_jobs.pytests/canonical_storage/test_repositories.pytests/canonical_storage/test_series_profiles.pytests/canonical_storage/test_source_documents.pytests/canonical_storage/test_source_intake_repositories.pytests/canonical_storage/test_source_intake_transition_properties.pytests/canonical_storage/test_tei_headers.pytests/canonical_storage/test_unit_of_work.pytests/canonical_storage/test_workflow_checkpoints.pytests/fixtures/architecture/allowed_case/api.pytests/fixtures/architecture/allowed_case/service.pytests/fixtures/architecture/allowed_case/storage.pytests/fixtures/architecture/api_imports_cyclic_star_reexported_outbound_adapter/__init__.pytests/fixtures/architecture/api_imports_cyclic_star_reexported_outbound_adapter/a.pytests/fixtures/architecture/api_imports_cyclic_star_reexported_outbound_adapter/b.pytests/fixtures/architecture/api_imports_nested_star_reexported_outbound_adapter/__init__.pytests/fixtures/architecture/api_imports_nested_star_reexported_outbound_adapter/barrel.pytests/fixtures/architecture/api_imports_outbound_adapter/api.pytests/fixtures/architecture/api_imports_star_reexported_outbound_adapter/api.pytests/fixtures/architecture/domain_imports_storage/domain.pytests/fixtures/database.pytests/fixtures/history_entries.pytests/fixtures/llm.pytests/fixtures/test_database.pytests/snapshot_redaction.pytests/steps/generation_orchestration_vidaimock.pytests/steps/multi_source_ingestion_support.pytests/steps/source_intake_api_helpers.pytests/steps/source_intake_support.pytests/steps/test_architecture_enforcement_steps.pytests/steps/test_binding_resolution_steps.pytests/steps/test_canonical_ingestion_steps.pytests/steps/test_canonical_repositories_steps.pytests/steps/test_chapter_markers_steps.pytests/steps/test_chrono_steps.pytests/steps/test_generation_orchestration_steps.pytests/steps/test_generation_run_lifecycle_steps.pytests/steps/test_guest_bios_steps.pytests/steps/test_http_service_scaffold_steps.pytests/steps/test_llm_adapter_steps.pytests/steps/test_local_k8s_preview_steps.pytests/steps/test_multi_source_ingestion_steps.pytests/steps/test_pedante_steps.pytests/steps/test_profile_template_api_steps.pytests/steps/test_reference_document_api_steps.pytests/steps/test_reference_document_model_steps.pytests/steps/test_schema_migrations_steps.pytests/steps/test_show_notes_steps.pytests/steps/test_source_intake_steps.pytests/steps/test_worker_service_scaffold_steps.pytests/test_api_helpers.pytests/test_architecture_enforcement.pytests/test_architecture_hecate_config.pytests/test_binding_resolution.pytests/test_binding_resolution_api.pytests/test_binding_resolution_scenarios.pytests/test_binding_resolution_validation.pytests/test_brief_reference_documents.pytests/test_chapter_marker_dtos.pytests/test_chapter_marker_generation.pytests/test_chapter_marker_parsing.pytests/test_chapter_marker_prompt.pytests/test_chapter_markers.pytests/test_chrono.pytests/test_chrono_contracts.pytests/test_chrono_langgraph.pytests/test_compat.pytests/test_container_image_contract.pytests/test_cost_ports_protocols.pytests/test_cost_pricing_catalogue_file_loader.pytests/test_cost_pricing_engine_properties.pytests/test_cost_recorder.pytests/test_env_runtime_wiring.pytests/test_episode_template_service.pytests/test_filesystem_object_store.pytests/test_generation_orchestration_langgraph.pytests/test_generation_orchestration_snapshots.pytests/test_generation_run_domain.pytests/test_guest_bios_binding.pytests/test_guest_bios_enrichment.pytests/test_guest_bios_executor.pytests/test_guest_bios_executor_errors.pytests/test_guest_bios_generator.pytests/test_guest_bios_properties.pytests/test_health_endpoints.pytests/test_helm_chart_contract.pytests/test_http_service_scaffold_support.pytests/test_idempotency_properties.pytests/test_idempotency_service.pytests/test_ingestion_integration_e2e.pytests/test_ingestion_integration_support.pytests/test_ingestion_resolver.pytests/test_interpreter_executor.pytests/test_interpreter_executor_lifecycle.pytests/test_interpreter_executor_observability.pytests/test_lifespan_hooks.pytests/test_llm_guardrails.pytests/test_llm_openai_adapter_budgets.pytests/test_llm_openai_adapter_config.pytests/test_llm_openai_adapter_retries.pytests/test_llm_openai_adapter_usage_metering.pytests/test_local_k8s_kind_tooling.pytests/test_local_k8s_tooling.pytests/test_logging.pytests/test_mutation_workflow_contract.pytests/test_openai_type_guards.pytests/test_orchestration_config_model_tier_properties.pytests/test_orchestration_dto_validation.pytests/test_orchestration_graph_invariant_properties.pytests/test_orchestration_langgraph_properties.pytests/test_orchestration_orchestrator.pytests/test_orchestration_planner.pytests/test_orchestration_properties.pytests/test_orchestration_usage.pytests/test_pedante_langgraph.pytests/test_profile_template_api.pytests/test_profile_template_helpers.pytests/test_prompt_templates.pytests/test_protocol_stubs.pytests/test_reference_document_access.pytests/test_reference_document_api_support.pytests/test_reference_document_bindings_facade.pytests/test_reference_document_models.pytests/test_reference_document_service_alignment.pytests/test_reference_document_service_conflicts.pytests/test_reference_document_service_history.pytests/test_reference_document_service_locking.pytests/test_reference_document_service_queries.pytests/test_reference_document_service_validation.pytests/test_serializers.pytests/test_series_profile_service.pytests/test_show_notes_executor.pytests/test_show_notes_parsing.pytests/test_show_notes_prompting.pytests/test_show_notes_tei_enrichment.pytests/test_snapshot_sources.pytests/test_source_intake_api.pytests/test_source_intake_api_contract.pytests/test_source_intake_service.pytests/test_storage_compression.pytests/test_uuid_assertions.pytests/test_worker_interpreter_task_integration.pytests/test_worker_routing_contract.pytests/test_worker_service_scaffold.pytests/test_workflow_bootstrap_gitops_repo.pytests/test_workflow_provision_doks.pytests/test_workflow_test_utils.pytests/test_workflow_utils.pytypos.toml
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
leynos/df12-python-lints(auto-detected)leynos/hecate(auto-detected)leynos/femtologging(auto-detected)leynos/tei-rapporteur(auto-detected)leynos/falcon-correlate(auto-detected)leynos/shared-actions(auto-detected)
💤 Files with no reviewable changes (42)
- episodic/api/source_idempotency.py
- episodic/api/resources/episode_templates.py
- episodic/llm/init.py
- episodic/canonical/briefs.py
- episodic/canonical/profile_templates/services/_typed.py
- episodic/logging.py
- episodic/canonical/source_intake_types.py
- episodic/canonical/profile_templates/services/_generic.py
- tests/canonical_storage/test_tei_headers.py
- episodic/llm/ports.py
- tests/steps/source_intake_support.py
- tests/steps/source_intake_api_helpers.py
- episodic/canonical/profile_templates/brief.py
- tests/canonical_storage/test_episodes.py
- tests/test_storage_compression.py
- tests/test_uuid_assertions.py
- tests/steps/multi_source_ingestion_support.py
- episodic/canonical/storage/compression.py
- episodic/asyncio_tasks.py
- episodic/canonical/tei.py
- episodic/benchmarks/init.py
- tests/canonical_storage/test_ingestion_jobs.py
- tests/canonical_storage/conftest.py
- tests/canonical_storage/test_unit_of_work.py
- episodic/benchmarks/interpreters.py
- episodic/api/source_intake_support.py
- episodic/canonical/storage/repository_base.py
- episodic/api/resources/source_intake.py
- episodic/canonical/reference_documents/_binding_creation.py
- episodic/llm/openai_chat.py
- tests/canonical_storage/test_series_profiles.py
- tests/_guest_bios_executor_helpers.py
- tests/test_openai_type_guards.py
- tests/test_prompt_templates.py
- tests/canonical_storage/test_history_repositories.py
- tests/canonical_storage/test_source_documents.py
- tests/canonical_storage/test_approval_events.py
- tests/canonical_storage/test_repositories.py
- episodic/canonical/prompts.py
- episodic/generation/tei_payload.py
- alembic/versions/20260220_000002_add_profile_template_history_schema.py
- alembic/versions/20260226_000003_add_zstd_payload_columns.py
|
|
||
| Returns | ||
| ------- | ||
| int | ||
| Result produced by the operation. | ||
|
|
||
| Raises | ||
| ------ | ||
| falcon.HTTPBadRequest | ||
| If a supplied value is not an integer; the exception carries the | ||
| validation error envelope for ``name``. | ||
| """ # noqa: DOC501, DOC502 # validation_error returns this concrete Falcon exception. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Keep the private helper docstring concise.
_parse_int_query_param now contains boilerplate Returns and Raises sections. Retain its concise behaviour summary and remove those generated sections.
As per path instructions, private functions and methods use a single-line summary.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@episodic/api/helpers.py` around lines 173 - 184, Shorten the
_parse_int_query_param docstring to a single-line behavior summary, removing the
generated Returns and Raises sections and their associated noqa annotation while
preserving the function’s behavior.
Source: Path instructions
|
|
||
| Returns | ||
| ------- | ||
| str | None | ||
| Result produced by the operation. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Replace the placeholder return contracts.
episodic/canonical/storage/integrity_helpers.py#L28-L32: state that the
result is the discovered PostgreSQL constraint name, orNonewhen absent.episodic/canonical/storage/integrity_helpers.py#L63-L67: state that the
result reports whether the integrity error represents a revision conflict.tests/test_source_intake_api.py#L240-L243: remove the newly added generic
Returnssection; this private helper does not need it.
As per coding guidelines, documentation must provide precise contracts, and path
instructions require NumPy-style documentation for public interfaces.
📍 Affects 2 files
episodic/canonical/storage/integrity_helpers.py#L28-L32(this comment)episodic/canonical/storage/integrity_helpers.py#L63-L67tests/test_source_intake_api.py#L240-L243
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@episodic/canonical/storage/integrity_helpers.py` around lines 28 - 32,
Replace the generic Returns descriptions in integrity_helpers.py: document the
constraint-discovery helper as returning the discovered PostgreSQL constraint
name or None, and document the integrity-error helper as returning whether the
error represents a revision conflict. In tests/test_source_intake_api.py, remove
the newly added generic Returns section from the private helper’s docstring.
Sources: Coding guidelines, Path instructions
| from episodic.observability import ( | ||
| MetricsPort, | ||
| MonotonicClockPort, | ||
| NoopMetrics, | ||
| PerfCounterClock, | ||
| ) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file='episodic/canonical/storage/source_intake_repository_runtime.py'
printf '\n== file outline ==\n'
ast-grep outline "$file" --view expanded || true
printf '\n== numbered excerpt ==\n'
cat -n "$file" | sed -n '1,220p'
printf '\n== symbol usages ==\n'
rg -n '\b(MetricsPort|MonotonicClockPort|NoopMetrics|PerfCounterClock)\b' "$file" || trueRepository: leynos/episodic
Length of output: 2804
Move the protocol-only imports behind TYPE_CHECKING. Keep NoopMetrics and PerfCounterClock as runtime imports; MetricsPort and MonotonicClockPort are used only in annotations here.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@episodic/canonical/storage/source_intake_repository_runtime.py` around lines
8 - 13, Update the observability imports in source_intake_repository_runtime.py
so MetricsPort and MonotonicClockPort are imported only within a TYPE_CHECKING
guard, while NoopMetrics and PerfCounterClock remain runtime imports. Ensure
annotations continue resolving correctly without adding unnecessary runtime
dependencies.
Source: Coding guidelines
| @dc.dataclass(frozen=True, slots=True) | ||
| class SourceIntakeStorageRuntime: | ||
| """Runtime providers used by source-intake SQLAlchemy adapters.""" | ||
|
|
||
| clock: Clock | ||
| uuid_factory: UuidFactory | ||
| metrics: MetricsPort | ||
| monotonic_clock: MonotonicClockPort | ||
|
|
||
|
|
||
| def _utc_now() -> dt.datetime: | ||
| """Return the current UTC timestamp for idempotency records.""" | ||
| return dt.datetime.now(dt.UTC) | ||
|
|
||
|
|
||
| def _new_uuid() -> uuid.UUID: | ||
| """Return a new idempotency record identifier.""" | ||
| return uuid.uuid4() | ||
|
|
||
|
|
||
| def source_intake_storage_runtime( | ||
| runtime: SourceIntakeStorageRuntime | None, | ||
| *, | ||
| metrics: MetricsPort | None = None, | ||
| monotonic_clock: MonotonicClockPort | None = None, | ||
| ) -> SourceIntakeStorageRuntime: | ||
| """Return SQLAlchemy source-intake providers with production defaults.""" |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Document the exported runtime API in full NumPy style.
Add structured Attributes, Parameters, and Returns sections for the
public dataclass and factory. The new public interfaces currently have only
summary docstrings. As per path instructions, “full structured docs” are
required for public interfaces.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@episodic/canonical/storage/source_intake_repository_runtime.py` around lines
19 - 45, Expand the docstrings for the public SourceIntakeStorageRuntime
dataclass and source_intake_storage_runtime factory with full NumPy-style
Attributes, Parameters, and Returns sections. Document each runtime provider
field, factory argument including optional defaults, and the returned
SourceIntakeStorageRuntime; leave the private helper docstrings unchanged.
Sources: Coding guidelines, Path instructions
| return isinstance(value, dict) and all( | ||
| isinstance(k, str) and isinstance(v, str) | ||
| for k, v in value.items() # type: ignore[union-attr] | ||
| for k, v in value.items() # type: ignore[union-attr] # Runtime shape checks narrow externally supplied values beyond static inference. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Replace the type-checker suppression with a guard clause.
Split the dictionary check from the generator: return False when value is not a dictionary, then iterate over value.items() without # type: ignore[union-attr]. This keeps narrowing explicit and avoids checker-specific suppression syntax.
Proposed refactor
def _is_string_mapping(value: object) -> bool:
"""Return True when *value* is a dict whose every key and value is a str."""
- return isinstance(value, dict) and all(
+ if not isinstance(value, dict):
+ return False
+ return all(
isinstance(k, str) and isinstance(v, str)
- for k, v in value.items() # type: ignore[union-attr] # Runtime shape checks narrow externally supplied values beyond static inference.
+ for k, v in value.items()
)As per path instructions, use guard clauses and reserve inline suppressions for last-resort cases.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@episodic/cost/pricing_catalogue/file_loader.py` at line 93, Update
_is_string_mapping to use an explicit guard clause: return False immediately
when value is not a dictionary, then run the existing all() check over
value.items() without the type-checker suppression comment.
Source: Path instructions
| """HTTP server carrying mutable test state.""" | ||
|
|
||
| # pylint: disable-next=too-many-arguments | ||
| # pylint: disable-next=too-many-arguments # The parameter-rich signature is fixed by the explicit port or fixture contract. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
Keep lint suppressions within the permitted form.
Remove # pylint: disable-next=too-many-arguments. Refactor the constructor signature or move the exception into the approved tool configuration; line-level Pylint disables are not permitted here. As per path instructions, “Only narrow in-line disables (# noqa: XYZ) are permitted”.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/steps/test_llm_adapter_steps.py` at line 105, Remove the inline pylint
suppression above the parameter-rich constructor in the test step; refactor that
constructor signature to satisfy too-many-arguments, or configure the exception
through the approved lint configuration. Preserve only permitted narrow inline
noqa disables and do not replace this with another line-level pylint disable.
Source: Path instructions
| redacted_manifest = re.sub( | ||
| r"(?m)(^\s*checksum/config:\s*)[0-9a-f]{64}$", | ||
| r"\1<checksum>", | ||
| manifest, | ||
| ) | ||
| return redacted_manifest.rstrip() |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Inline the redaction result before returning it.
Remove the one-use redacted_manifest assignment so this passes R504.
Proposed fix
- redacted_manifest = re.sub(
+ return re.sub(
r"(?m)(^\s*checksum/config:\s*)[0-9a-f]{64}$",
r"\1<checksum>",
manifest,
- )
- return redacted_manifest.rstrip()
+ ).rstrip()As per coding guidelines, “R504 - Avoid redundant variable assignment before
return.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| redacted_manifest = re.sub( | |
| r"(?m)(^\s*checksum/config:\s*)[0-9a-f]{64}$", | |
| r"\1<checksum>", | |
| manifest, | |
| ) | |
| return redacted_manifest.rstrip() | |
| return re.sub( | |
| r"(?m)(^\s*checksum/config:\s*)[0-9a-f]{64}$", | |
| r"\1<checksum>", | |
| manifest, | |
| ).rstrip() |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/test_helm_chart_contract.py` around lines 67 - 72, In the
manifest-redaction helper, remove the one-use redacted_manifest assignment and
return the re.sub(...).rstrip() result directly, preserving the existing regex
and replacement behavior so the code satisfies R504.
Source: Coding guidelines
| estimated_tokens = _estimate_token_count(chars_per_token, text) | ||
|
|
||
| assert estimated_tokens >= 0 | ||
| assert estimated_tokens >= 0, "Expected values to satisfy the required ordering" |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Describe the non-negativity invariant accurately.
Replace "Expected values to satisfy the required ordering" with a message stating that estimated_tokens must be non-negative. This assertion checks estimated_tokens >= 0, not an ordering relationship.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/test_llm_openai_adapter_budgets.py` at line 84, Update the assertion
message for estimated_tokens in the non-negativity check to state that
estimated_tokens must be non-negative, replacing the inaccurate ordering-related
text.
| "updated_at": dt.datetime(2026, 1, 1, tzinfo=dt.UTC), | ||
| } | ||
| defaults.update(overrides) # type: ignore[arg-type] | ||
| defaults.update(overrides) # type: ignore[arg-type] # The fixture builder intentionally accepts heterogeneous typed overrides. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- tests/test_serializers.py (relevant lines) ---\n'
nl -ba tests/test_serializers.py | sed -n '1,140p'
printf '\n--- ty / type ignore config search ---\n'
rg -n --hidden --glob '!**/.git/**' '(?:#\s*ty:\s*ignore|type:\s*ignore|ty\s*=|tool\.ty|ty)' pyproject.toml .rules .github tests src docs 2>/dev/null || trueRepository: leynos/episodic
Length of output: 244
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- repository files likely containing ty config ---\n'
fd -a 'pyproject.toml|ty.toml|ruff.toml|mypy.ini|setup.cfg|tox.ini' .
printf '\n--- search for ty-related settings and suppressions ---\n'
rg -n --hidden --glob '!**/.git/**' 'tool\.ty|^\[tool\.ty\]|ty:\s*ignore|type:\s*ignore|ignore\[arg-type\]|enable = \["ty"' . 2>/dev/null || trueRepository: leynos/episodic
Length of output: 244
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- pyproject.toml ---\n'
if [ -f pyproject.toml ]; then
nl -ba pyproject.toml | sed -n '1,260p'
fi
printf '\n--- suppressions in tests/test_serializers.py ---\n'
nl -ba tests/test_serializers.py | sed -n '35,95p'Repository: leynos/episodic
Length of output: 244
🌐 Web query:
ty suppression syntax ignore diagnostic code comment # ty: ignore[...] invalid-argument-type
💡 Result:
To suppress the invalid-argument-type diagnostic in the ty type checker, you can use an inline comment at the end of the affected line [1][2]. The primary syntax is: # ty: ignore[invalid-argument-type] [1][3] You can also use the standard PEP 484 type: ignore format, but when specifying ty error codes within it, you must prefix them with ty: to ensure they are correctly recognized [1][4]. The following is supported: # type: ignore[ty:invalid-argument-type] [1][5] Key details for suppression: - Multiple rules: You can suppress multiple ty rules or a combination of ty and other type checker rules (like mypy) by listing them, separated by commas, inside the brackets [1][3]. For example: # type: ignore[arg-type, ty:invalid-argument-type] [1][5]. - Bare ignore: Using # ty: ignore without specific codes will suppress all rule violations on that line [1][3]. - type: ignore behavior: By default, ty respects standard # type: ignore comments (which act as a blanket suppression) [6][3]. This behavior can be disabled in your configuration (pyproject.toml or ty.toml) by setting respect-type-ignore-comments = false under [tool.ty.analysis] [6]. - Unused ignores: If the unused-ignore-comment rule is enabled, ty will report comments that do not actually suppress any active errors [1][7]. These must be removed or suppressed themselves using # ty: ignore[unused-ignore-comment] [1]. For more information, consult the official ty documentation on suppression [1].
Citations:
- 1: https://docs.astral.sh/ty/suppression/
- 2: https://stackoverflow.com/questions/79628526/how-to-make-ty-ignore-a-single-line-in-a-source-file
- 3: https://realpython.com/python-ty/
- 4: Regression in 0.0.25:
# type: ignore[invalid-argument-type]no longer effective astral-sh/ty#3156 - 5: Consider best-effort supporting mypy error code names for some common cases astral-sh/ty#3127
- 6: https://docs.astral.sh/ty/reference/configuration/
- 7: https://github.com/astral-sh/ty/blob/0.0.26/docs/suppression.md
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- tests/test_serializers.py (relevant lines) ---'
nl -ba tests/test_serializers.py | sed -n '1,140p'
echo
echo '--- repository files likely containing ty config ---'
find . \( -name 'pyproject.toml' -o -name 'ty.toml' -o -name 'ruff.toml' -o -name 'mypy.ini' -o -name 'setup.cfg' -o -name 'tox.ini' \) -print
echo
echo '--- ty / type ignore config search ---'
rg -n --hidden --glob '!**/.git/**' 'tool\.ty|^\[tool\.ty\]|ty:\s*ignore|type:\s*ignore|ignore\[arg-type\]|respect-type-ignore-comments' . 2>/dev/null || trueRepository: leynos/episodic
Length of output: 244
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- tests/test_serializers.py (relevant lines) ---'
sed -n '1,140p' tests/test_serializers.py | awk '{printf "%4d %s\n", NR, $0}'
echo
echo '--- repository config files ---'
find . \( -name 'pyproject.toml' -o -name 'ty.toml' -o -name 'ruff.toml' -o -name 'mypy.ini' -o -name 'setup.cfg' -o -name 'tox.ini' \) -print | sort
echo
echo '--- ty / ignore config search ---'
rg -n --hidden --glob '!**/.git/**' 'tool\.ty|^\[tool\.ty\]|ty:\s*ignore|type:\s*ignore|ignore\[arg-type\]|respect-type-ignore-comments' . 2>/dev/null || trueRepository: leynos/episodic
Length of output: 8609
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo '--- pyproject.toml: ty-related settings ---'
sed -n '1,260p' pyproject.toml | awk '/^\[tool\.ty\]|\[tool\.ty\..*\]|respect-type-ignore-comments|invalid-argument-type|invalid-method-override|type: ignore|ty: ignore/ {print}'
echo
echo '--- tests/steps/test_llm_adapter_steps.py excerpt ---'
sed -n '88,104p' tests/steps/test_llm_adapter_steps.py | awk '{printf "%4d %s\n", NR+87, $0}'Repository: leynos/episodic
Length of output: 950
Use the ty suppression form here. Replace each # type: ignore[arg-type] on the three defaults.update(overrides) calls with # ty: ignore[invalid-argument-type] to match the checker’s diagnostic code and the existing suppression style in the test suite.
📍 Affects 1 file
tests/test_serializers.py#L50-L50(this comment)tests/test_serializers.py#L67-L67tests/test_serializers.py#L83-L83
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/test_serializers.py` at line 50, Replace the type suppression on all
three defaults.update(overrides) calls in tests/test_serializers.py at lines
50-50, 67-67, and 83-83 with the ty suppression form # ty:
ignore[invalid-argument-type], preserving the existing fixture behavior and
suppression style.
Source: Learnings
| @dataclasses.dataclass(frozen=True, kw_only=True) | ||
| class _TextUploadRequest: | ||
| """Describe a deterministic text-upload multipart request.""" | ||
|
|
||
| key: str | ||
| payload: bytes | ||
| authorization: str | None = None | ||
| metadata: str | None = None |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add slots to the request fixture.
Declare _TextUploadRequest with slots=True to meet the structured-data rule and
prevent accidental dynamic attributes.
Proposed fix
-@dataclasses.dataclass(frozen=True, kw_only=True)
+@dataclasses.dataclass(frozen=True, slots=True, kw_only=True)
class _TextUploadRequest:As per coding guidelines, use TypedDict or @dataclass(slots=True) for
structured data.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @dataclasses.dataclass(frozen=True, kw_only=True) | |
| class _TextUploadRequest: | |
| """Describe a deterministic text-upload multipart request.""" | |
| key: str | |
| payload: bytes | |
| authorization: str | None = None | |
| metadata: str | None = None | |
| `@dataclasses.dataclass`(frozen=True, slots=True, kw_only=True) | |
| class _TextUploadRequest: | |
| """Describe a deterministic text-upload multipart request.""" | |
| key: str | |
| payload: bytes | |
| authorization: str | None = None | |
| metadata: str | None = None |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/test_source_intake_api.py` around lines 369 - 376, Update the
_TextUploadRequest dataclass declaration to include slots=True while preserving
its frozen and keyword-only configuration and existing fields.
Source: Coding guidelines
Preserve the branch's complete Hecate group configuration alongside main's updated development dependency pins, then regenerate `uv.lock` from the combined dependency declarations.
836ef4d to
b572dd7
Compare
Summary
This branch adopts Pylint alongside Ruff, pins the df12 Python lint suite at
v0.1.0, and runs both the df12 Pylint plug-in and
ambrleaksexplicitly onCPython 3.14. It also enables Ruff preview rules, the
ASYNCandDOCrulegroups, and NumPy-style docstring enforcement.
The stricter checks exposed latent annotation, assertion, fixture, snapshot,
and documentation contract issues across the project. The branch repairs
those underlying issues, introduces deterministic redaction for incidental
snapshot identifiers, and extracts repeated assertion clusters into
domain-focused test helpers with precise failure diagnostics.
Review walkthrough
ambrleaksgates.Validation
make check-fmt: passed; 439 files formatted.make test: passed; 1,033 passed, 1 skipped, and 54 snapshots passed.make typecheck: passed with ty 0.0.32.make lint: passed; Hecate, Ruff, Pylint, df12 Pylint on CPython 3.14, andambrleaksare clean.git diff --cached --check: passed before each commit.References