Make the region-count injector audible, and stop double-writing the answer - #30
Merged
Merged
Conversation
The curated neuron counts in config/fly-neuron-counts.json never reached an answer, and the reason could not be established from the container log: maybeInjectRegionNeuronCountStep called log() only on success, and log() appends to the per-request trace, which is printed only under VFB_HARNESS_TRACE=true. The absence of an inject line in three production runs was therefore not evidence that the injector declined. It was not evidence either way. Put the decision on stderr, on both paths, alongside the grounding audit and the absence gate — and only once the question has count intent, so it stays quiet on questions this has nothing to say about. Ontology ids, gate names and term flags only; the question is the user's text and is not logged. Also stop declining on a second resolved region. VFB answers "fly brain" with 224 documents that are almost all painted domains on JRC_FlyEM_Hemibrain, and each one is Anatomy-and-not-a-neuron, so each one satisfies isRegionTerm exactly as brain (FBbt_00005095) does. One survivor was enough to take the count off the table. Prefer the ontology class; two classes is a real ambiguity and still declines, now audibly.
Absence escalation runs a second synthesis when a draft denies data the run never looked for. Synthesis streams token by token into one live bubble on the client, and the only event that ends that bubble is the final result, so the second draft was appended to the first. Production, 11 August, on "How many neurons are in the fly brain?": the same paragraph twice, in two slightly different wordings, one after the other. The tokens are already sent, so the server cannot unsend them. It tells the client instead: a draft_discarded event fires the moment escalation is accepted, and the client drops the bubble and clears its ref so the replacement opens a fresh one. The status line that already accompanies escalation says what is happening while the second answer is written. Best-effort like onStatus — an unwired or throwing hook costs the run nothing, so a client that has not been updated behaves exactly as before.
Resolves the generated task-battery latest.json in favour of this branch's run; it is regenerated on main by the battery workflow. # Conflicts: # test-results/task-battery/latest.json
Robbie1977
pushed a commit
that referenced
this pull request
Aug 14, 2026
lib/orchestrator.mjs: #30 added discardDraft() immediately after the ABSENCE ESCALATION log line that this branch rewrites. Both are kept — the line no longer quotes the user's sentence, and the streamed draft is still withdrawn. latest.json is generated and takes this branch's run. # Conflicts: # lib/orchestrator.mjs # test-results/task-battery/latest.json
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 from the 11 August review, both on the flagship "how many neurons are in the fly brain?" question.
The injector was never actually silent about declining — it was inaudible
maybeInjectRegionNeuronCountStepcalledlog()only on success.log()appends to the per-request trace, and the trace is printed only underVFB_HARNESS_TRACE=true. So the absence of aninjectline in the three production runs we read was not evidence that the injector declined. It was not evidence either way, and the diagnosis built on it could not have been supported.The decision now goes on stderr, on both paths, alongside
ABSENCE ESCALATIONandGROUNDING— and only once the question has count intent, so it stays quiet on the questions it has nothing to say about. Ontology ids, gate names and term flags only; the question is the user's text and is not logged.While there: the gate
regionTerms.length === 1declined whenever a second region resolved. VFB answers "fly brain" with 224 documents that are almost all painted domains onJRC_FlyEM_Hemibrain—AB(L),AL(R),AL-DA1(R)— and every one of them is Anatomy-and-not-a-neuron, so every one satisfiesisRegionTermexactly asbrain(FBbt:00005095) does. One survivor was enough to take the curated counts off the table. It now prefers the ontology class; two classes is a real ambiguity and still declines, audibly.The answer could be written out twice
Absence escalation runs a second synthesis. Synthesis streams token by token into one live bubble on the client and the only event that ends that bubble is
result, so the second draft was appended to the first — the same paragraph twice, in two slightly different wordings.The tokens are already sent, so the server cannot unsend them. It tells the client instead: a
draft_discardedevent fires the moment escalation is accepted, and the client drops the bubble so the replacement opens a fresh one. Best-effort likeonStatus— an unwired or throwing hook costs the run nothing.How to test
npm test(5 new cases inorchestrator_run.test.mjs, 3 inabsence.test.mjs). Live: ask "How many neurons are in the fly brain?" on the deployed build and read the container log forREGION COUNT INJECTOR. That line now names the gate whatever happens.Follow-ups
no-region-termoralready-planned, the remaining fault is upstream of this gate./docs/concepts/neuron-counts/still 404s until VFB2 is redeployed.