Filed on @neo-gpt's Required Action 3 against PR #17426 (review): "give existing corrupted rows a concrete owner… The parent epic alone is not an executable residual." He was right — the residual on #17425 pointed at epic #17411, which had no child for this.
#17425 corrected the provider-input header: buildEmbeddingInputHeader read chunk.type, the published parsed-chunk-v1 schema requires kind and declares no type, so every chunk from a schema-conforming parser embedded behind the literal token undefined. That fix is forward-only by construction.
Live latest-open sweep: checked latest 20 open issues at 2026-08-20T17:31Z; A2A claim sweep over the current window; no equivalent found.
This body was materially corrected after filing — see The Architectural Reality. The original claimed a working global trigger; there is none.
The Problem
The affected rows are invisible to every existing signal, and the reason is structural rather than an oversight.
Their chunk ids did not change.createChunkHash folds only the hashInputs field list (['kind','name','content','sourcePath','parserId','parserVersion'], IngestionService.mjs:990). The provider input string is derived and is not a member, so re-ingestion computes the same id, finds the row present, and does no work.
The provider input is not stored.collection.upsert writes {ids, embeddings, metadatas} — there is no documents field, so the stale text is not on disk to be pattern-matched.
Metadata cannot date them.buildChunkMetadata copies every chunk field, so an affected row carries kind and no type — but so does a row embedded after the fix. The metadata identifies the affected population, never which members are stale.
So the symptom is: a bounded set of rows whose vectors were computed from a string beginning with a meaningless token, indistinguishable from correct rows by id, content, or metadata.
The Architectural Reality
⛔ CORRECTED 2026-08-20, hours after filing. The original version of this section was wrong, and it was the section the whole ticket rested on.
It claimed "the guaranteed trigger already exists" — that EMBEDDING_POISON_STRATEGY_FAMILY feeds createVectorGenerationIdentity, and that per generationElectionStore.mjs:7 a strategy change therefore "invalidates every existing vector". @neo-gpt falsified it on PR #17426 (closure review). Verified independently before accepting:
strategyVersion is consumed by resolveEmbeddingPoisonGeneration (VectorService.mjs:551), whose own docblock scopes it precisely: "a provider, model, vector-schema, or input-strategy change invalidates prior poison evidence". It flows to createEmbeddingGenerationId and the poison-suppression scope. Nothing else.
VectorService never calls createVectorGenerationIdentity. Its only occurrence in that file is inside a comment (:205) — the comment I quoted. It names that function for its id-uniqueness property, not as a call.
Incremental selection collects existingIds and skips them (:2461-2481), so a present row is never re-embedded no matter what any generation says.
So no global re-embed trigger is wired. Bumping the strategy family would invalidate poison/suppression evidence and re-embed nothing.
How the error was made, since it is more reusable than the fact: I read a docblock's contract and a comment's mention as a wired mechanism, and never ran the one-line falsifier — "does anything in the KB path call createVectorGenerationIdentity?" — which returns a comment. Prose describing a guarantee is not evidence its producer emits it.
What actually exists
mechanism
re-embeds affected rows?
why
parserVersion advance
yes
parserVersionis a hashInputs member, so ids change, the new ids are absent from existingIds, and the rows are embedded. The only working path — and nothing schedules it.
EMBEDDING_POISON_STRATEGY_FAMILY bump
no
poison-evidence scope only
ordinary reconciliation / re-ingestion
no
ids unchanged ⇒ classified present ⇒ skipped
a targeted detector
cannot be built today
upsert writes {ids, embeddings, metadatas} and no documents, so the stale text is not on disk; and metadata cannot date a row — an affected row and a freshly-correct one both carry kind without type
✅ RESOLVED BY THE OPERATOR 2026-08-20 — build the detector
The escalation this section used to carry is answered, and the framing it escalated was wrong in a way worth recording because the error is reusable.
I wrote three shapes "in ascending cost" and called the detector refuted. Both halves were mistakes:
1. I ranked by implementation cost while the real constraint is compute. Operator: "they spend DAYS on current embeddings. so if building a detector takes a couple of hours… so what?" A few developer hours against days of recomputation is not a trade-off, and calling the cheap-to-build option the expensive one inverted the decision.
2. I evaluated the detector against what is ALREADY stored, concluded no discriminator exists, and wrote "refuted". The question I should have asked is what is the cheapest thing to start storing. Same wrong-subject error as the one in The Architectural Reality above, one step along: there I read documentation instead of the call graph, here I read the current schema instead of the reachable one.
And the plane facts kill the global option's premise anyway. Operator: for neo's own Agent OS the multi-tenant repos present are the tiniest possible, and neo itself is not yet ingested as a tenant — it still runs the old kbSync path, which is a separate lane to change. So the "global bump rebuilds a large correct corpus" cost I used to argue against it barely exists here; the corpus it would invalidate is small.
The detector, which is cheap and was reachable all along
buildChunkMetadata (VectorService.mjs:175) copies every chunk field into row metadata. So a stored marker naming the provider-input format needs no new storage mechanism — it rides the existing copy.
Absence of the marker is the discriminator. Rows written before the marker exists carry no such field; rows written after carry the current value. That separates a stale row from a freshly-correct one with identical kind-without-type — which is the exact pair I claimed nothing on disk could distinguish.
property
how the marker satisfies it
distinguishes stale from fresh
field absent ⇒ pre-marker ⇒ affected; field present and current ⇒ fresh
survives future format changes
the marker's value is the format identity, so a later change to any PROBED branch is detectable the same way; a new branch needs a probe added with it, which the probe set's own contract states
targeted rather than global
selects only affected rows, so a plane paying days of compute re-embeds the subset
adds no storage shape
metadata already copies every chunk field
The marker is a contract fact about the provider input, so its home is the authority that owns that string — helpers/embeddingInputFormat.mjs — not a second declaration beside it.
Retained from the refuted framing: the chunk id genuinely does not change (the input string is derived and not a hashInputs member), incremental selection genuinely does skip existing ids, and parserVersion genuinely is the only existing re-mint mechanism with nothing scheduling it. Those observations stand; only the conclusion drawn from them was wrong.
Contract Ledger Matrix
Target Surface
Source of Authority
Proposed Behavior
Fallback
Docs
Evidence
the provider-input format marker (new)
helpers/embeddingInputFormat.mjs — the authority that owns the string
a stable identity for the current format, written into chunk metadata at upsert; absence means pre-marker
absent on every existing row, which is exactly the discriminator
this ticket
buildChunkMetadata already copies every chunk field, so no storage-shape change is needed
the detector
the marker above
selects rows whose marker is absent or stale, per tenant, without touching fresh rows
a row whose marker is current is never selected
—
an affected row and a freshly-correct one are otherwise identical: both carry kind without type
tenant parserVersion
hashInputs membership
not the chosen mechanism. Advancing it re-mints ids and would re-embed the repo's whole corpus rather than the affected subset
—
—
retained as the only pre-existing re-mint path; nothing schedules it
out of scope. It scopes poison/suppression evidence and re-embeds nothing
—
—
its consumer's docblock: "invalidates prior poison evidence"
#17425's residual
this ticket
the executable owner the review required
—
—
the parent epic carried no child for this
the detector's SELECTION MECHANISM
ChromaDB's filter capability
a metadata scan with a JS predicate, paginated per tenant — never a where filter keyed on the marker
none available: there is no query that can express it
intake amendment below
ChromaDB has no $exists, so an absent key is invisible to every where clause that mentions it — four independent sites in this repo already say so
Intake amendment 2026-08-20 — absence is not queryable, so the detector scans
Added at ticket-intake on the drift probe firing. The chosen shape survives; one mechanism it would have been natural to reach for does not exist, and the repo had already learned this four times:
untagged rows "are invisible to ANY where-clause that mentions userId (no $exists operator)"
ai/services/memory-core/MemoryService.mjs:1194
"ChromaDB does not support $exists: false, handled post-query"
ai/services/memory-core/SummaryService.mjs:428
same, with the JS post-filter as the remedy
ai/services/memory-core/HealthService.mjs:1653
"Chroma where-filters cannot reliably falsify absent metadata-key cases across versions, so this method scans metadata directly instead of inferring from $ne"
$ne does not rescue it either: a row missing the key is not returned by {marker: {$ne: current}}, because the clause mentions a field the row does not have. Absence is only observable by reading returned metadata.
This does not change what the detector must do — the Ledger row above already specified a behaviour rather than a query — but it fixes the cost model and names the shape:
Detection is O(corpus) metadata reads, not a targeted query. For a ~87k-chunk corpus at the existing 2000-row page size that is ~44 pages of metadata, which is still trivial against days of embedding. The targeting benefit is in what gets re-embedded, not in what gets scanned.
Two siblings own the shape and neither needs inventing.HealthService.#scanChromaMetadata is the scan-and-count precedent (and its #checkChromaMigrationState already reports an untagged population as observable debt — the same artifact this ticket's before/after count AC asks for). ai/scripts/migrations/backfillChromaSharedUserId.mjs is the runner precedent for tagging the rows a scan finds.
New acceptance criterion, from this amendment:
The detector does not depend on a where filter to find absence. Selection reads returned metadata; an arm proves a marker-absent row is found. A version that filters on the marker key would silently return zero affected rows and read as "nothing to repair" — which is the failure mode of this entire lane, one layer down, and it is why this is an AC rather than a comment.
Decision Record impact
none for shape 1 (advance parserVersion). Shape 2 would need one: wiring a KB vector-generation election changes when vectors are considered invalid deployment-wide, and generationElectionStore's contract would move from describing elected generations to governing the KB embed path. That is an ADR-shaped decision, not a leaf's.
Acceptance Criteria
The shape is chosen by the operator, on the record, before any implementation. — Resolved 2026-08-20: build the detector. See the section above, including the two errors in the framing I escalated.
The marker's ABSENCE is the discriminator, asserted directly. A fixture with a pre-marker row and a freshly-written row carrying identical kind-without-type selects exactly the first. Without this arm the detector is indistinguishable from one that selects the whole affected population including rows it already repaired.
The marker lives with the format it names. One authority — the module that owns the provider-input string — and no second declaration beside it. Asserted by mutation: changing the format without changing the marker must turn an arm red.
Re-selection is idempotent. A repaired row is not selected again. A detector that re-selects its own output turns a bounded repair into a loop, which on a plane paying days of compute is worse than not repairing.
The repair's ACs are NOT here. They moved to #17443 when the split was made — the RED-PROOF that a stale row receives a new vector, the EMBEDDING_POISON_STRATEGY_FAMILY no-op arm, before/after counting, and no-silent-partial-repair. Kept as an explicit line rather than a silent deletion, so a reader of this ticket can see the boundary rather than wonder whether the repair was forgotten.
Neo's own corpus is accounted for explicitly. Its headers never changed; a repair that rebuilds it must say so as a cost, and one that skips it must prove the skip is safe.
Delivery status — the DETECTOR is this ticket; the REPAIR is #17443
Corrected 2026-08-21 (reviewer-named, @neo-gpt on PR #17444). An earlier revision of this section said "Not split into a child ticket, and not claimed as resolved. One PR advances this ticket; a second will close it." That was true when written and became false the moment #17443 was filed — and it left four repair ACs standing here that no detector PR could ever satisfy, so Resolves #17428 could not be truthful.
The split is real and the boundary is delivery authority: a read-only census is a leaf, while re-embedding is a plane operation that spends days of provider compute and whose scheduling is an operator decision. This ticket is now the detector alone, and its PR closes it.#17443 owns the repair. Handing over the number first is what makes the operator's scheduling decision informed rather than blind.
Closed by the detector PR:
the marker's absence as the discriminator — a pre-marker row and a freshly-written row with identical kind-without-type classify differently, which is exactly the pair this ticket said nothing on disk could separate;
the marker living with the format — and stronger than the AC asked: the identity is DERIVED from the format's own output over a probe set covering each of its branches, so "format changed, identity did not" is removed for every branch the probe set reaches rather than merely detected — bounded, not absolute: a branch no probe exercises can change invisibly, which the module states at its probe-set contract. Mutation-verified: reversing the header's type-first contract reddens both identity arms and no census arm;
re-selection idempotence at the classification boundary — a row carrying the current identity is never selected, and the classifier is a pure function of the row, so there is no state that could flip it. The repair inherits this rather than re-implementing it;
neo's own corpus, with a number instead of an adjective: 68,039 rows scanned, 68,039 pre-marker, 0 current on this deployment, measured through the shipped census;
the scan-not-filter constraint from the intake amendment.
Still open, and owned by the repair PR:
the RED-PROOF that a present, stale row actually receives a NEW VECTOR. This is the one that must not be satisfied by a hash or id difference, and it cannot be satisfied by a detector at all — nothing in this PR re-embeds anything;
the arm pinning that an EMBEDDING_POISON_STRATEGY_FAMILY bump re-embeds nothing, so the corrected finding in The Architectural Reality stays behaviour rather than prose;
no silent partial repair — a run that repairs some rows and stops must report the remainder with its count;
the after half of the before/after count. The instrument exists and is verified; the second number requires a repair to have run.
Out of Scope
The header fix itself — shipped in #17425 / PR #17426, forward-only by construction.
Adding the provider input string to hashInputs. It would make future format changes self-repairing and it would also re-mint every chunk id in existence; that is a larger contract change with its own blast radius. Noted as the general fix that shape 2 approximates without the id churn.
Storing documents in Chroma to make the text inspectable. Same class: a storage-shape change proposed to serve one migration.
Avoided Traps
Reading "repair naturally on the next parserVersion advance" as a plan.parserVersionis a hash input, so an advance does re-mint ids and re-embed — but nothing schedules one. That sentence was in PR #17426's body and it was a hope with no trigger; the review was right to reject it.
Assuming the stale rows are findable. They are not, by any of id, content, or metadata, and the targeted branch stands or falls on that.
⛔Reading a docblock's contract as a wired mechanism. This ticket shipped that error in its own most load-bearing section: generationElectionStore.mjs:7 describes what invalidates an elected generation, and VectorService.mjs:205namescreateVectorGenerationIdentity — so I reported a guaranteed trigger that no code invokes. The falsifier was one grep for a call site, and it returns a comment. Prose describing a guarantee is not evidence that its producer emits it, and a function named in a comment is not a function that is called.
Related
Parent epic: #17411. Sibling leaves: #17412 (throughput), #17413 (the lane guide).
#17443 — the REPAIR split out of this ticket. Owns every AC about re-embedding; this ticket owns finding the rows.
#17425 / PR #17426 — the forward-only header fix whose residual this owns.
#17392 — parser-identity orphans; adjacent but keyed on identity change, which this population does not have.
Retrieval Hint: query_raw_memories("rows embedded before the provider header fix keep stale vectors; chunk id unchanged because embedding text is not in hashInputs; EMBEDDING_POISON_STRATEGY_FAMILY bump invalidates every vector globally versus a targeted detector that does not exist")
tobiu referenced in commit 37ea02b - "fix(kb): the embedding header names the chunk kind instead of the word undefined (#17425) (#17426) on Aug 20, 2026, 8:48 PM
tobiu referenced in commit 7635b81 - "feat(kb): a row records which provider-input format built its vector (#17428) on Aug 21, 2026, 2:32 AM
tobiu referenced in commit 95ea6f6 - "feat(kb): the stale-vector population becomes a measurement (#17428) on Aug 21, 2026, 2:32 AM
tobiu referenced in commit 56f433e - "feat(kb): a row records which format built its vector, and the stale population becomes a number (#17428) (#17444) on Aug 21, 2026, 3:38 PM
Context
Filed on @neo-gpt's Required Action 3 against PR #17426 (review): "give existing corrupted rows a concrete owner… The parent epic alone is not an executable residual." He was right — the residual on #17425 pointed at epic #17411, which had no child for this.
#17425 corrected the provider-input header:
buildEmbeddingInputHeaderreadchunk.type, the publishedparsed-chunk-v1schema requireskindand declares notype, so every chunk from a schema-conforming parser embedded behind the literal tokenundefined. That fix is forward-only by construction.Live latest-open sweep: checked latest 20 open issues at 2026-08-20T17:31Z; A2A claim sweep over the current window; no equivalent found.
This body was materially corrected after filing — see The Architectural Reality. The original claimed a working global trigger; there is none.
The Problem
The affected rows are invisible to every existing signal, and the reason is structural rather than an oversight.
createChunkHashfolds only thehashInputsfield list (['kind','name','content','sourcePath','parserId','parserVersion'],IngestionService.mjs:990). The provider input string is derived and is not a member, so re-ingestion computes the same id, finds the row present, and does no work.collection.upsertwrites{ids, embeddings, metadatas}— there is nodocumentsfield, so the stale text is not on disk to be pattern-matched.buildChunkMetadatacopies every chunk field, so an affected row carrieskindand notype— but so does a row embedded after the fix. The metadata identifies the affected population, never which members are stale.So the symptom is: a bounded set of rows whose vectors were computed from a string beginning with a meaningless token, indistinguishable from correct rows by id, content, or metadata.
The Architectural Reality
⛔ CORRECTED 2026-08-20, hours after filing. The original version of this section was wrong, and it was the section the whole ticket rested on.
It claimed "the guaranteed trigger already exists" — that
EMBEDDING_POISON_STRATEGY_FAMILYfeedscreateVectorGenerationIdentity, and that pergenerationElectionStore.mjs:7a strategy change therefore "invalidates every existing vector". @neo-gpt falsified it on PR #17426 (closure review). Verified independently before accepting:strategyVersionis consumed byresolveEmbeddingPoisonGeneration(VectorService.mjs:551), whose own docblock scopes it precisely: "a provider, model, vector-schema, or input-strategy change invalidates prior poison evidence". It flows tocreateEmbeddingGenerationIdand the poison-suppression scope. Nothing else.VectorServicenever callscreateVectorGenerationIdentity. Its only occurrence in that file is inside a comment (:205) — the comment I quoted. It names that function for its id-uniqueness property, not as a call.existingIdsand skips them (:2461-2481), so a present row is never re-embedded no matter what any generation says.So no global re-embed trigger is wired. Bumping the strategy family would invalidate poison/suppression evidence and re-embed nothing.
How the error was made, since it is more reusable than the fact: I read a docblock's contract and a comment's mention as a wired mechanism, and never ran the one-line falsifier — "does anything in the KB path call
createVectorGenerationIdentity?" — which returns a comment. Prose describing a guarantee is not evidence its producer emits it.What actually exists
parserVersionadvanceparserVersionis ahashInputsmember, so ids change, the new ids are absent fromexistingIds, and the rows are embedded. The only working path — and nothing schedules it.EMBEDDING_POISON_STRATEGY_FAMILYbumpupsertwrites{ids, embeddings, metadatas}and nodocuments, so the stale text is not on disk; and metadata cannot date a row — an affected row and a freshly-correct one both carrykindwithouttype✅ RESOLVED BY THE OPERATOR 2026-08-20 — build the detector
The escalation this section used to carry is answered, and the framing it escalated was wrong in a way worth recording because the error is reusable.
I wrote three shapes "in ascending cost" and called the detector refuted. Both halves were mistakes:
1. I ranked by implementation cost while the real constraint is compute. Operator: "they spend DAYS on current embeddings. so if building a detector takes a couple of hours… so what?" A few developer hours against days of recomputation is not a trade-off, and calling the cheap-to-build option the expensive one inverted the decision.
2. I evaluated the detector against what is ALREADY stored, concluded no discriminator exists, and wrote "refuted". The question I should have asked is what is the cheapest thing to start storing. Same wrong-subject error as the one in The Architectural Reality above, one step along: there I read documentation instead of the call graph, here I read the current schema instead of the reachable one.
And the plane facts kill the global option's premise anyway. Operator: for neo's own Agent OS the multi-tenant repos present are the tiniest possible, and neo itself is not yet ingested as a tenant — it still runs the old kbSync path, which is a separate lane to change. So the "global bump rebuilds a large correct corpus" cost I used to argue against it barely exists here; the corpus it would invalidate is small.
The detector, which is cheap and was reachable all along
buildChunkMetadata(VectorService.mjs:175) copies every chunk field into row metadata. So a stored marker naming the provider-input format needs no new storage mechanism — it rides the existing copy.Absence of the marker is the discriminator. Rows written before the marker exists carry no such field; rows written after carry the current value. That separates a stale row from a freshly-correct one with identical
kind-without-type— which is the exact pair I claimed nothing on disk could distinguish.The marker is a contract fact about the provider input, so its home is the authority that owns that string —
helpers/embeddingInputFormat.mjs— not a second declaration beside it.Retained from the refuted framing: the chunk id genuinely does not change (the input string is derived and not a
hashInputsmember), incremental selection genuinely does skip existing ids, andparserVersiongenuinely is the only existing re-mint mechanism with nothing scheduling it. Those observations stand; only the conclusion drawn from them was wrong.Contract Ledger Matrix
helpers/embeddingInputFormat.mjs— the authority that owns the stringbuildChunkMetadataalready copies every chunk field, so no storage-shape change is neededkindwithouttypeparserVersionhashInputsmembershipEMBEDDING_POISON_STRATEGY_FAMILY(VectorService.mjs:198)resolveEmbeddingPoisonGeneration#17425's residualwherefilter keyed on the marker$exists, so an absent key is invisible to everywhereclause that mentions it — four independent sites in this repo already say soIntake amendment 2026-08-20 — absence is not queryable, so the detector scans
Added at
ticket-intakeon the drift probe firing. The chosen shape survives; one mechanism it would have been natural to reach for does not exist, and the repo had already learned this four times:ai/scripts/migrations/backfillChromaSharedUserId.mjs:10userId(no$existsoperator)"ai/services/memory-core/MemoryService.mjs:1194$exists: false, handled post-query"ai/services/memory-core/SummaryService.mjs:428ai/services/memory-core/HealthService.mjs:1653$ne"$nedoes not rescue it either: a row missing the key is not returned by{marker: {$ne: current}}, because the clause mentions a field the row does not have. Absence is only observable by reading returned metadata.This does not change what the detector must do — the Ledger row above already specified a behaviour rather than a query — but it fixes the cost model and names the shape:
HealthService.#scanChromaMetadatais the scan-and-count precedent (and its#checkChromaMigrationStatealready reports an untagged population as observable debt — the same artifact this ticket's before/after count AC asks for).ai/scripts/migrations/backfillChromaSharedUserId.mjsis the runner precedent for tagging the rows a scan finds.New acceptance criterion, from this amendment:
wherefilter to find absence. Selection reads returned metadata; an arm proves a marker-absent row is found. A version that filters on the marker key would silently return zero affected rows and read as "nothing to repair" — which is the failure mode of this entire lane, one layer down, and it is why this is an AC rather than a comment.Decision Record impact
nonefor shape 1 (advanceparserVersion). Shape 2 would need one: wiring a KB vector-generation election changes when vectors are considered invalid deployment-wide, andgenerationElectionStore's contract would move from describing elected generations to governing the KB embed path. That is an ADR-shaped decision, not a leaf's.Acceptance Criteria
kind-without-typeselects exactly the first. Without this arm the detector is indistinguishable from one that selects the whole affected population including rows it already repaired.EMBEDDING_POISON_STRATEGY_FAMILYno-op arm, before/after counting, and no-silent-partial-repair. Kept as an explicit line rather than a silent deletion, so a reader of this ticket can see the boundary rather than wonder whether the repair was forgotten.Delivery status — the DETECTOR is this ticket; the REPAIR is #17443
Corrected 2026-08-21 (reviewer-named, @neo-gpt on PR #17444). An earlier revision of this section said "Not split into a child ticket, and not claimed as resolved. One PR advances this ticket; a second will close it." That was true when written and became false the moment #17443 was filed — and it left four repair ACs standing here that no detector PR could ever satisfy, so
Resolves #17428could not be truthful.The split is real and the boundary is delivery authority: a read-only census is a leaf, while re-embedding is a plane operation that spends days of provider compute and whose scheduling is an operator decision. This ticket is now the detector alone, and its PR closes it. #17443 owns the repair. Handing over the number first is what makes the operator's scheduling decision informed rather than blind.
Closed by the detector PR:
kind-without-typeclassify differently, which is exactly the pair this ticket said nothing on disk could separate;Still open, and owned by the repair PR:
EMBEDDING_POISON_STRATEGY_FAMILYbump re-embeds nothing, so the corrected finding in The Architectural Reality stays behaviour rather than prose;Out of Scope
hashInputs. It would make future format changes self-repairing and it would also re-mint every chunk id in existence; that is a larger contract change with its own blast radius. Noted as the general fix that shape 2 approximates without the id churn.documentsin Chroma to make the text inspectable. Same class: a storage-shape change proposed to serve one migration.Avoided Traps
parserVersionadvance" as a plan.parserVersionis a hash input, so an advance does re-mint ids and re-embed — but nothing schedules one. That sentence was in PR #17426's body and it was a hope with no trigger; the review was right to reject it.generationElectionStore.mjs:7describes what invalidates an elected generation, andVectorService.mjs:205namescreateVectorGenerationIdentity— so I reported a guaranteed trigger that no code invokes. The falsifier was one grep for a call site, and it returns a comment. Prose describing a guarantee is not evidence that its producer emits it, and a function named in a comment is not a function that is called.Related
Origin Session ID: 046f993e-13ba-47dd-827d-d786428e318b
Retrieval Hint:
query_raw_memories("rows embedded before the provider header fix keep stale vectors; chunk id unchanged because embedding text is not in hashInputs; EMBEDDING_POISON_STRATEGY_FAMILY bump invalidates every vector globally versus a targeted detector that does not exist")