Fix two live bugs reported in the PR backlog - #173
Merged
Conversation
Adjacent string literals concatenate silently in Python, so a missing comma turns two column names into one. `molecular_interaction` had three such sites, collapsing seven columns into three: "Interaction detection method(s) Publication 1st author(s)" -> 2 columns "Host organism(s)Interaction parameter(s)" -> 2 columns "Annotation(s) interactor A" ... "Creation date" -> 6 columns Those metadata fields were never populated on Alliance documents. `genetic_interaction` is the same MITAB schema written correctly, and the two lists now match exactly: 41 columns each, identical sets. Reported by @AaryanCode69 in #120, which caught two of the three sites. This also fixes the "Interaction detection method(s) Publication 1st author(s)" case, which was a single literal with a space rather than an implicit concatenation and so did not appear in that diff. A linter cannot guard this. ruff's ISC001 flags implicit concatenation on one line, but it is disabled because it conflicts with the formatter -- and running `ruff format` earlier today joined `"Host organism(s)" "Interaction parameter(s)"` into a single literal, destroying the syntactic evidence that a rule could have matched. So the guard is a test instead: one comparing the two MITAB lists against each other, and one rejecting any column name that begins with another column name. Both were checked against the pre-fix source to confirm they fail on the real bug rather than passing vacuously. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
__del__ called asyncio.run() unconditionally, which raises RuntimeError when a loop is already running -- and __del__ fires at arbitrary moments, including inside the running server. Exceptions in __del__ are swallowed and printed, so it surfaced as log noise with the pool still open. Reported independently by @bleedblack1 in #156 and @bhavyakeerthi3 in #147. Neither proposed fix is taken as-is. #147 schedules the close with loop.create_task(), but a task created from __del__ is not guaranteed to run if the loop is shutting down, which is exactly when a graph is usually collected -- so it reports success while leaking the pool. #156 rewrites the module more broadly than the bug warrants. Instead: close the pool only when there is no running loop, and otherwise warn that it is still open rather than pretend otherwise. Errors from the close are caught, because __del__ must not raise. This is containment, not a cure. Nothing calls close_pool() explicitly, so __del__ is the only cleanup that exists, and it is fundamentally unreliable -- writing the test surfaced that even the warning fails at interpreter shutdown, once logging's handlers are closed. The real fix is closing the pool from an application shutdown hook, which belongs with the agent-API work. Four tests cover the loop-running case, the no-loop case, no pool at all, and a close that raises. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
preprocess made three LLM calls back to back. The safety check needs the rephrased text so it must follow the rephrase, but language detection reads the raw user input and does not -- so those two now run concurrently, saving one round trip on every message, on the path every profile shares. Idea from @bleedblack1 in #111. That patch parallelised the same two calls; this is the same change written against current main, since the PR predates 34 commits and its diff no longer applies. Two tests, both checked against the sequential version to confirm they fail on it: one asserting the two calls actually overlap in wall-clock time, one asserting the rephrase still completes before the safety check starts, which is the ordering constraint that must not be lost. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PT018: the overlap check asserted two conditions at once, so a failure would not say which interval was wrong. Split, with a message for each. Caught by CI rather than locally, because the local check had its output redirected to /dev/null and the && chain short-circuited silently. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This was referenced Sep 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two defects that were still present on
main, both reported by contributors. Neither contributor PR is merged as-is; see below.Alliance MITAB columns — reported by @AaryanCode69 in #120
Adjacent string literals concatenate silently in Python, so a missing comma turns two column names into one.
molecular_interactionhad three such sites, collapsing seven columns into three:Those metadata fields were never populated on Alliance documents.
genetic_interactionis the same MITAB schema written correctly, so it serves as an oracle: both lists are now 41 columns with identical sets.#120 caught two of the three. The third —
"Interaction detection method(s) Publication 1st author(s)"— was a single literal containing a space rather than an implicit concatenation, so it did not appear in that diff.Why this is guarded by a test, not a lint rule
ruff's
ISC001flags implicit concatenation on one line, but it is disabled because ruff itself warns it conflicts with the formatter. And runningruff formatjoined"Host organism(s)" "Interaction parameter(s)"into a single literal, destroying the syntax a rule could match on. Two tests instead: one comparing the MITAB lists against each other, one rejecting any column name that begins with another. Both were run against the pre-fix source to confirm they fail on the real bug rather than passing vacuously.AgentGraph.del — reported by @bleedblack1 in #156 and @bhavyakeerthi3 in #147
__del__calledasyncio.run()unconditionally, which raisesRuntimeErrorwhen a loop is already running — and__del__fires at arbitrary moments, including inside the running server. Exceptions there are swallowed and printed, so it appeared as log noise with the pool still open.Neither proposed fix is taken as-is:
loop.create_task(). A task created from__del__is not guaranteed to run if the loop is shutting down — which is exactly when a graph is usually collected — so it reports success while leaking the pool.This closes the pool only when no loop is running, and otherwise warns that it is still open rather than pretending otherwise. Errors from the close are caught, because
__del__must not raise.This is containment, not a cure. Nothing calls
close_pool()explicitly, so__del__is the only cleanup that exists, and it is fundamentally unreliable — writing the test surfaced that even the warning fails at interpreter shutdown once logging's handlers are closed. The real fix is closing the pool from an application shutdown hook, which belongs with the agent-API work.Tests
97 total, up from 91. Four cover the destructor: loop running, no loop, no pool, and a close that raises.
Closes #120. Supersedes #147 and #156.
🤖 Generated with Claude Code