Context
#14026 leaf 3 (after #14074 coverage-drift + #14094 monotonicity). The #13999 forensics repeatedly surfaced malformed inverted index for FTS5 table main.embedding_fulltext_search — the Chroma SQLite store failing quick_check / integrity_check — yet that is only a manual ai:check-chroma-integrity CLI line, never a scheduled detect signal. A self-healing organism cannot heal SQLite corruption it never detects; this closes one heuristic of the ADR-0025 §2.4 data-integrity detect dimension (#14089).
The Architectural Reality
ai/scripts/maintenance/checkChromaIntegrity.mjs already produces result.sqlite.checks = [{pragma, ok, output, error?}] for quick_check + integrity_check (classifySqliteCheck: ok === (output.trim() === 'ok'); the catch path adds {ok:false, output:'', error}).
ai/daemons/orchestrator/services/dataIntegrityCoverageDiagnosis.mjs (#14075) is the pure-producer pattern to mirror: consume an audit RESULT → emit a data-integrity / escalate recovery-diagnosis via createRecoveryDiagnosisEvent; null when clean; targetIdentity.kind: 'compose-service'.
- ADR-0025 §2.4 (amended in #14089) names this data-integrity detect dimension; SQLite-integrity is one of its enumerated heuristics.
The Fix
A pure buildSqliteIntegrityDiagnosis({sqliteResult, observedAt, serviceId}) in ai/daemons/orchestrator/services/:
- Consumes
checkChromaIntegrity's result.sqlite (its .checks array).
- Emits a
recovery-diagnosis (recoveryClass: 'data-integrity', details.actionClass: 'escalate', targetIdentity: {kind: 'compose-service', id: serviceId}) when ANY check has ok === false; evidenceFacts carry the failing pragma(s) + a bounded output/error snippet; reasonCode: 'data-integrity-sqlite-integrity-failure'.
- Returns
null when all checks pass (no false escalation).
- Detect-only — no repair/mutation (the malformed-FTS5 rebuild is a separate operator-gated lane).
Acceptance Criteria
Out of Scope
- Scheduling the producer into the diagnostics daemon (the #14026 wiring slice).
- Repairing/rebuilding the malformed FTS5 index (operator-gated).
Related
#14026 (parent), #14075 (coverage-drift sibling + pattern), #14094 (monotonicity sibling), #14089 (the ADR-0025 §2.4 dimension this realizes), #13999 (the FTS5 signal source), #14039.
Live latest-open sweep: checked latest 20 open at 2026-06-26T13:18Z + the live #14026 leaf set (#14074 closed, #14094 Ada, #14089 mine); no SQLite-integrity-producer leaf exists. A2A: broadcast [lane-claim] before filing.
Origin Session ID: 5ab545e1-f09e-46c5-ae62-8cf5b2b96193
Handoff Retrieval Hints: query_raw_memories("SQLite integrity_check FTS5 malformed data-integrity detect producer"); anchors: ai/scripts/maintenance/checkChromaIntegrity.mjs (result.sqlite.checks), ai/daemons/orchestrator/services/dataIntegrityCoverageDiagnosis.mjs (#14075 pattern).
Context
#14026 leaf 3 (after #14074 coverage-drift + #14094 monotonicity). The #13999 forensics repeatedly surfaced
malformed inverted index for FTS5 table main.embedding_fulltext_search— the Chroma SQLite store failingquick_check/integrity_check— yet that is only a manualai:check-chroma-integrityCLI line, never a scheduled detect signal. A self-healing organism cannot heal SQLite corruption it never detects; this closes one heuristic of the ADR-0025 §2.4 data-integrity detect dimension (#14089).The Architectural Reality
ai/scripts/maintenance/checkChromaIntegrity.mjsalready producesresult.sqlite.checks=[{pragma, ok, output, error?}]forquick_check+integrity_check(classifySqliteCheck:ok === (output.trim() === 'ok'); the catch path adds{ok:false, output:'', error}).ai/daemons/orchestrator/services/dataIntegrityCoverageDiagnosis.mjs(#14075) is the pure-producer pattern to mirror: consume an audit RESULT → emit adata-integrity/escalaterecovery-diagnosisviacreateRecoveryDiagnosisEvent;nullwhen clean;targetIdentity.kind: 'compose-service'.The Fix
A pure
buildSqliteIntegrityDiagnosis({sqliteResult, observedAt, serviceId})inai/daemons/orchestrator/services/:checkChromaIntegrity'sresult.sqlite(its.checksarray).recovery-diagnosis(recoveryClass: 'data-integrity',details.actionClass: 'escalate',targetIdentity: {kind: 'compose-service', id: serviceId}) when ANY check hasok === false;evidenceFactscarry the failing pragma(s) + a bounded output/error snippet;reasonCode: 'data-integrity-sqlite-integrity-failure'.nullwhen all checks pass (no false escalation).Acceptance Criteria
buildSqliteIntegrityDiagnosisemits a contract-validdata-integrity/escalaterecovery-diagnosiswhen aquick_check/integrity_checkfails (ok: false);nullwhen all pass.evidenceFactsname the failing pragma(s) + a bounded detail snippet (never unbounded SQLite output).targetIdentity.kind: 'compose-service'(withinRECOVERY_TARGET_IDENTITY_KINDS).null; thedata-integrityenum validates; missingserviceId/ non-finiteobservedAtthrow (mirrorsdataIntegrityCoverageDiagnosis.spec).Out of Scope
Related
#14026 (parent), #14075 (coverage-drift sibling + pattern), #14094 (monotonicity sibling), #14089 (the ADR-0025 §2.4 dimension this realizes), #13999 (the FTS5 signal source), #14039.
Live latest-open sweep: checked latest 20 open at 2026-06-26T13:18Z + the live #14026 leaf set (#14074 closed, #14094 Ada, #14089 mine); no SQLite-integrity-producer leaf exists. A2A: broadcast
[lane-claim]before filing.Origin Session ID: 5ab545e1-f09e-46c5-ae62-8cf5b2b96193
Handoff Retrieval Hints:
query_raw_memories("SQLite integrity_check FTS5 malformed data-integrity detect producer"); anchors:ai/scripts/maintenance/checkChromaIntegrity.mjs(result.sqlite.checks),ai/daemons/orchestrator/services/dataIntegrityCoverageDiagnosis.mjs(#14075 pattern).