Repository navigation
Conversation
Three reporting faults, all found by running a long route and reading what came back. A model may draw its own route through a capability fence and hand-write the SVG inside it. The species parser read that drawing. One role label inside a picture that was cut off before its closing tag claimed every character to the end of the answer, and two fragments of markup became species of that step; nothing resolves them, and a step with an unresolved species is emptied by design, so the step was reported as impossible to build although the author's own list was complete. It also cost a correction round, because the fragments were handed back as species to repair. maskDrawnRegions blanks any capability fence and any raw <svg> with equal-length whitespace, so offsets into the answer still address the original text, and an unclosed picture is blanked to the end of its fence. isNameLikeSpecies drops a parsed name that is markup, not a name. An unbuilt step was reported as a failed check. That overstates the route's problems and hides what the author has to fix, because nothing was checked on that step at all: it is now its own state, counted separately in the verdict, and it names the species whose structure could not be resolved. The application already had those names; only the step line omitted them. A chiral building block of the opposite configuration has the same formula, the same atom counts and the same constitution as the intended one, so balance and continuity both pass and no deterministic check can see the difference. Where the package measures the configuration at a free acid's nitrogen-bearing stereocentre, the route check now reports it beside what the author's own name asserts. Reported, never judged: which letter belongs to a given series flips when a sulfur-bearing branch outranks the carboxyl, so the letter alone proves nothing. The field is optional, so an older package simply produces no such line. Finally, the answer now says where each structure came from -- the built-in dictionary, a reference service, or the answer itself. The per-species source was already carried on every resolved species and never surfaced, so a run could not tell an offline dictionary hit from a network lookup or from a structure the model drew itself, which is the category a wrong structure hides in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LVYxvTRGs6MrP7LsQaAJKz
…s named as one buildRouteSteps discarded a repeated fragment, so that two salts sharing an ion could not put the same token on one side twice. The set was per role, so calcium chloride written as its ions lost a chloride, and any salt with repeated counterions -- magnesium bromide, sodium sulfate, potassium carbonate -- could then never balance: the author would be told a correct equation was wrong. Writing each distinct ion once also left its count to the solver, and a free ion's coefficient is the solver's to choose, so a wrong equation could be rescued by it. groupedSideTrace already knew this and worked around it in the display -- "its solved count is arbitrary (often 1:1); the salts fix it instead" -- which meant the report could show the author's salts while the verdict had been computed on something else. Every fragment of every species is now written out, in order. The package regroups them from the labels it already receives, so each declared species takes one coefficient, the ratio the author wrote survives, and the verdict is computed on the species the report shows. A package that cannot regroup sees the duplicates and reports several possible equations, which is visible rather than silent. Separately: a species line that reads "see prose", "as above" or "see step 2" is a placeholder, not a name a resolver could ever turn into a structure. The step report and the correction prompt said "give that species a name a reference resolves, or its structure", which invites the author to invent a structure for something that has none. They now say what the author actually did and ask for the species to be listed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LVYxvTRGs6MrP7LsQaAJKz
This branch has not been deployed
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.
Three reporting faults in the route check, all found by running a long route and reading what came back rather than by reasoning about the code.
A model's own drawing was read as a species list
A model may draw its route through a capability fence and hand-write the SVG inside it. The species parser read that drawing: one
Byproducts:label inside a picture that was cut off before its closing tag claimed every character to the end of the answer, and two fragments of markup became species of that step.Nothing resolves markup, and a step with an unresolved species is emptied by design — so the step was reported as impossible to build although the author's own list was complete and correct. It also cost a correction round, because the fragments were handed back to the model as species to repair.
maskDrawnRegionsblanks any capability fence and any raw<svg>with equal-length whitespace, so offsets into the answer still address the original text and the in-place species rewrite is unaffected. An unclosed picture is blanked to the end of its fence.isNameLikeSpeciesdrops a parsed name that is markup rather than a name.Measured on the answer that produced the fault: the step parsed 7 species including 2 markup fragments before, and its 5 declared species after.
An unbuilt step was reported as a failed check
Nothing is checked on such a step, so counting it among the steps that fail both overstates the route's problems and hides what the author has to fix. It is now its own state, counted separately in the verdict, and it names the species whose structure could not be resolved. The application already had those names; only the step line omitted them, which made a real diagnosis slow.
A chiral building block of the wrong configuration was invisible
Such a block has the same formula, the same atom counts and the same constitution as the intended one, so balance and continuity both pass and no deterministic check can see the difference. Where the package measures the configuration at a free acid's nitrogen-bearing stereocentre, the route check now reports it beside what the author's own name asserts.
Reported, never judged: which letter belongs to a given series flips when a sulfur-bearing branch outranks the carboxyl, so the letter alone proves nothing. The field is optional and absent unless measured, so an older package simply produces no such line.
Where each structure came from
The answer now says whether a structure came from the built-in dictionary, a reference service, or the answer itself. The per-species source was already carried on every resolved species and never surfaced, so a run could not tell an offline dictionary hit from a network lookup or from a structure the model drew itself — which is the category a wrong structure hides in.
Every fragment reaches the equation
buildRouteStepsdiscarded a repeated fragment, so that two salts sharing an ion could not put the same token on one side twice. The set was per role, so calcium chloride written as[Ca+2].[Cl-].[Cl-]lost a chloride — and any salt with repeated counterions (magnesium bromide, sodium sulfate, potassium carbonate) could then never balance. The author would be told a correct equation was wrong.Writing each distinct ion once also left its count to the solver, and a free ion's coefficient is the solver's to choose, so a wrong equation could be rescued by it.
groupedSideTracealready knew this and worked around it in the display — "its solved count is arbitrary (often 1:1); the salts fix it instead" — which meant the report could show the author's salts while the verdict had been computed on something else.Every fragment of every species is now written out, in order. The package regroups them from the labels it already receives, so each declared species takes one coefficient, the ratio the author wrote survives, and the verdict is computed on the species the report shows. The package side is NodusResearch/nodus-research-skill-marketplace#48; a package that cannot regroup sees the duplicates and reports several possible equations, which is visible rather than silent.
A placeholder is named as one
A species line reading
see prose,as aboveorsee step 2is a placeholder, not a name a resolver could ever turn into a structure — seen live, on a step whoseByproductsline read exactly that. The step report and the correction prompt said "give that species a name a reference resolves, or its structure", which invites the author to invent a structure for something that has none. They now say what the author actually did and ask for the species to be listed.Checks
npm run typecheckclean;node --test scripts/test-molecule-inspection.mjs104/104 with 6 new tests, including one built from the real answer shape that caused the parser fault.Note for review
This touches
shared/moleculeInspection.tsandelectron/ai/researchAssistant.ts, which #1066 and #1065 also touch. It is written againstmainand applies cleanly there; if those merge first I will rebase. The configuration report pairs with the package-side measurement in NodusResearch/nodus-research-skill-marketplace#48, and degrades to nothing without it.🤖 Generated with Claude Code
https://claude.ai/code/session_01LVYxvTRGs6MrP7LsQaAJKz