Context
While reviewing #13928 / PR #13929, the operator raised a separate tenant-repository ingestion risk: custom parsers are not yet deployed for every tenant source family, so a large raw source file can enter ingest_source_files as one monolithic file/chunk. PR #13929 stops local embedding providers from grinding on an over-budget final embedding input, but that protection is intentionally scoped to VectorService and keeps skip details internal/logged so the current PR does not widen MCP response contracts.
Live latest-open sweep: checked latest 20 open issues at 2026-06-23T14:14:05Z; no equivalent active issue found. Related broad parser inventory ticket #11735 exists, but it is parked/re-triage scoped to parser coverage deepening, not this immediate burn-prevention diagnostic gap. A2A in-flight sweep: checked latest 30 messages; no competing lane-claim or ticket-creation claim for this scope found.
Release classification: post-#13929 hardening follow-up, not a #13929 merge blocker unless the operator promotes it.
The Problem
ingest_source_files has a coarse up-front volume gate, but raw files count as one item before server-side parsing. A 5k-line source file can therefore pass the MCP facade, become one raw-text parsed chunk, and only be detected later at the embedding boundary.
After #13929, that late detection should prevent model CPU burn. The remaining problem is observability and operator actionability:
- the ingestion summary does not expose an oversized-skipped count/detail;
- daemon diagnostics cannot reliably distinguish "legitimate zero embeddings" from "monster file skipped because parser coverage/chunking is missing";
- relying only on graph rows is insufficient when embedding/model threads are wedged or skipped before graph write;
- broad custom parser coverage belongs to #11735, but a fail-safe diagnostic must exist before all tenant-specific parsers are ready.
The Architectural Reality
ai/mcp/server/knowledge-base/ingestSourceFilesTool.mjs:53 documents that raw files count as 1 and that the gate is only a coarse pre-parse guard.
ai/services/knowledge-base/KnowledgeBaseIngestionService.mjs:650 resolves a raw string payload into parser output or falls back to raw text.
ai/services/knowledge-base/KnowledgeBaseIngestionService.mjs:1054 turns fallback raw text into one parsed-chunk-v1 record whose content is the whole file.
ai/services/knowledge-base/KnowledgeBaseIngestionService.mjs:283 increments summary.embeddingsGenerated from VectorService.embed() but has no skipped-oversized summary field.
ai/services/knowledge-base/VectorService.mjs:315 is now the safety net that emits ConsumerFriction and logger warning before local provider invocation.
ai/mcp/server/knowledge-base/openapi.yaml:971 defines IngestSourceFilesResponse; any new ingestion-summary field must update this schema.
The Fix
Add an ingestion-layer oversized-input diagnostic gate after raw/client parser output is normalized but before embedChunkGroups() writes the temp JSONL for VectorService.
The gate should:
- evaluate the same local embedding safe-processing band used by #13929 for local providers;
- drop over-budget chunks from the embed queue before
VectorService.embed() is called;
- emit a bounded, non-secret diagnostic with
tenantId, repoSlug, sourcePath, parser id/version, byte count, token estimate, and safe threshold, never raw content;
- expose the skip to callers via the ingestion summary and
IngestSourceFilesResponse OpenAPI schema;
- record/log the event through existing KB logging/recording surfaces so #13914 / #13924 diagnostic tooling can consume it without any new public surface outside Knowledge Base / Memory Core.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback / Edge Case |
Docs |
Evidence |
KnowledgeBaseIngestionService.ingestSourceFiles() summary |
Existing summary shape plus IngestSourceFilesResponse schema |
Include a bounded oversized-skip signal, e.g. skippedOversized, and per-file structured errors[] entries with a stable code such as KB_INGEST_INPUT_SIZE_EXCEEDED. |
Safe chunks in the same request still embed; an all-oversized request returns success payload with errors, not a model call. |
Update openapi.yaml and service JSDoc. |
Unit tests for raw fallback and client parsedChunks. |
| Raw-file parser fallback |
resolveFileChunks() / rawFileToParsedRecord() |
A raw fallback monster file is skipped before provider invocation and produces diagnostic metadata. |
Missing parser remains KB_PARSER_NOT_REGISTERED; custom parser coverage remains separate. |
Inline JSDoc where the gate lives. |
Test that raw-text monster content never reaches VectorService.embed(). |
| Daemon-visible diagnostics |
KB logger / KBRecorderService / #13914 / #13924 |
Emit a bounded event the diagnostic producer/tooling can read from existing internal logs/metrics. |
Do not add a new public daemon port or bypass. Existing KB/MC surfaces remain the only public diagnostic surfaces. |
PR body + any touched logger/recorder docs. |
Test or fixture proving non-secret detail shape. |
| #13929 VectorService guardrail |
PR #13929 |
Remains the final safety net if a caller bypasses ingestion diagnostics. |
Shadow-swap still refuses incomplete corpus promotion. |
PR #13929 body. |
Existing #13929 WorkVolumeBranching coverage stays green. |
Decision Record impact
Aligned with ADR 0019: read AiConfig resolved leaves at use sites; do not add fallback defaults, alias config, or create a second config-resolution path.
Acceptance Criteria
Out of Scope
- Implementing tenant-specific custom parsers or full source-family inventory; #11735 owns that broader work.
- Automatically splitting or summarizing monster files. This ticket is skip-and-diagnose, not chunking strategy.
- Adding any public surface outside Knowledge Base / Memory Core.
- Private deployment config changes.
Avoided Traps
- Do not solve this by raising context limits or
mcpSyncMaxChunks; that only postpones the failure and can reintroduce burn.
- Do not expose raw source content in diagnostics.
- Do not make the daemon depend on graph rows for a pre-embedding skip; the whole point is diagnosing cases where nothing reaches the graph.
- Do not broaden #13929; its PR remains the model-burn guardrail and this ticket handles follow-up diagnostics.
Related
Origin Session ID: 1be84a2d-a911-424a-bfb0-10a51fff6303
Retrieval Hint: query_raw_memories("qwen embedding burn oversized raw tenant repo file skip diagnostics #13928 #13929")
Context
While reviewing #13928 / PR #13929, the operator raised a separate tenant-repository ingestion risk: custom parsers are not yet deployed for every tenant source family, so a large raw source file can enter
ingest_source_filesas one monolithic file/chunk. PR #13929 stops local embedding providers from grinding on an over-budget final embedding input, but that protection is intentionally scoped toVectorServiceand keeps skip details internal/logged so the current PR does not widen MCP response contracts.Live latest-open sweep: checked latest 20 open issues at 2026-06-23T14:14:05Z; no equivalent active issue found. Related broad parser inventory ticket #11735 exists, but it is parked/re-triage scoped to parser coverage deepening, not this immediate burn-prevention diagnostic gap. A2A in-flight sweep: checked latest 30 messages; no competing lane-claim or ticket-creation claim for this scope found.
Release classification: post-#13929 hardening follow-up, not a #13929 merge blocker unless the operator promotes it.
The Problem
ingest_source_fileshas a coarse up-front volume gate, but raw files count as one item before server-side parsing. A 5k-line source file can therefore pass the MCP facade, become oneraw-textparsed chunk, and only be detected later at the embedding boundary.After #13929, that late detection should prevent model CPU burn. The remaining problem is observability and operator actionability:
The Architectural Reality
ai/mcp/server/knowledge-base/ingestSourceFilesTool.mjs:53documents that raw files count as 1 and that the gate is only a coarse pre-parse guard.ai/services/knowledge-base/KnowledgeBaseIngestionService.mjs:650resolves a raw string payload into parser output or falls back to raw text.ai/services/knowledge-base/KnowledgeBaseIngestionService.mjs:1054turns fallback raw text into oneparsed-chunk-v1record whosecontentis the whole file.ai/services/knowledge-base/KnowledgeBaseIngestionService.mjs:283incrementssummary.embeddingsGeneratedfromVectorService.embed()but has no skipped-oversized summary field.ai/services/knowledge-base/VectorService.mjs:315is now the safety net that emitsConsumerFrictionand logger warning before local provider invocation.ai/mcp/server/knowledge-base/openapi.yaml:971definesIngestSourceFilesResponse; any new ingestion-summary field must update this schema.The Fix
Add an ingestion-layer oversized-input diagnostic gate after raw/client parser output is normalized but before
embedChunkGroups()writes the temp JSONL forVectorService.The gate should:
VectorService.embed()is called;tenantId,repoSlug,sourcePath, parser id/version, byte count, token estimate, and safe threshold, never raw content;IngestSourceFilesResponseOpenAPI schema;Contract Ledger Matrix
KnowledgeBaseIngestionService.ingestSourceFiles()summaryIngestSourceFilesResponseschemaskippedOversized, and per-file structurederrors[]entries with a stable code such asKB_INGEST_INPUT_SIZE_EXCEEDED.openapi.yamland service JSDoc.parsedChunks.resolveFileChunks()/rawFileToParsedRecord()KB_PARSER_NOT_REGISTERED; custom parser coverage remains separate.VectorService.embed().Decision Record impact
Aligned with ADR 0019: read
AiConfigresolved leaves at use sites; do not add fallback defaults, alias config, or create a second config-resolution path.Acceptance Criteria
VectorService.embed()/ local provider invocation.parsedChunksare also skipped before embedding.ai/mcp/server/knowledge-base/openapi.yamlis updated if the response shape gains a field.Out of Scope
Avoided Traps
mcpSyncMaxChunks; that only postpones the failure and can reintroduce burn.Related
Origin Session ID: 1be84a2d-a911-424a-bfb0-10a51fff6303
Retrieval Hint:
query_raw_memories("qwen embedding burn oversized raw tenant repo file skip diagnostics #13928 #13929")