Scope amendment, 2026-08-17 — gate fired; narrowed against @neo-opus-vega's #17260. The gating
condition below fired verbatim on a deployed tenant (one repo of four, 511 JS files,
useDefaultSources: false, every file at parserId: 'raw-text' as one whole-file chunk).
#17260 now builds the parsers; this ticket keeps the two halves that are uniquely its own and its
middle row changes verb from build to verify against the enumerated inventory. needs-re-triage
dropped — the gate is no longer hypothetical. Standalone again as of 2026-08-17: briefly re-parented
to #17260, which then closed as not planned (it built chunk-sizing logic around what parsers are for).
#11730 is also closed, so this leaf carries no parent — deliberately, rather than pointing at a closed one.
Two corrected premises this ticket previously rested on, both measured today:
Parser dispatch is NOT missing.IngestionService.resolveParser (:1610) reads
getParserIds?.() / getParsers?.() and dispatches at :1577-1596 on file.parserId || 'raw-text', failing loudly with KB_PARSER_NOT_REGISTERED. customSourcesandcustomParsers are live and resolved per tenant through getTenantConfig's three-tier chain
(graph node → kb-config.yaml → aiConfig). An earlier sweep reported the registry write-only;
that was a false negative — optional chaining escapes a \.method\( pattern. So the gap is
selection (nothing sets file.parserId), never dispatch.
Parsers are a SEMANTIC surface, not a size surface (operator ruling). Sources and Parsers emit
meaningful units — a method, a function, a heading section. Reasonable chunk size is the
consequence of cutting on real boundaries, never the objective. Anything still oversize is
hard-cut by the existing filterEmbeddingInputBudget / splitOversizedEmbeddingChunk. Logic
built around what parsers are for is a strict decline.
Context
Post-MVP residual workstream under Epic #11730. Epic #11720 (Sub E #11726 + Sub F2 #11728) establishes tenant-repo ingestion + a parser path for ONE proof-ladder source family. Discussion #11718 + the #11720 lost-item audit flagged that a real external tenant has many source families (JS-global, test-suite, IDE/header/test-library equivalents, custom formats) — deepening parser + ingestion coverage across all of them is post-MVP.
Gating Condition
Pursued after #11720's single proof-ladder ingestion path works (Sub E #11726 + Sub F2 #11728 landed — verifiable) AND a concrete broader-coverage signal fires — one of:
a deployed tenant's ingestion run reports source families with no registered parser (raw-text-fallback chunks where structured parsing was expected), OR
an operator / deployment files a coverage-gap against the #11726 source-family inventory checklist.
The proof-ladder path merely existing is not the trigger — a real multi-family tenant corpus must demonstrate the coverage gap. Until both conditions hold: captured intent, not active work.
Scope
Enumerate the external tenant's full source-family inventory (builds on the inventory checklist AC already in Sub E #11726).
Parser-dispatch coverage for each family beyond the single PoC parser.
Bulk / backfill ingestion across families, volume-gate aware.
Contract Ledger
Target Surface
Source of Authority
Proposed Behavior
Fallback / Edge Case
Docs
Evidence
Parser coverage verified per source family
the KB parser registry + the parsed-chunk-v1 contract (learn/agentos/cloud-deployment/CustomParsers.md)
Every family in the enumerated inventory is verified to reach a registered parser emitting parsed-chunk-v1, is explicitly deferred with rationale, or is marked never-ingest. #17260's subs BUILD the parsers; this row checks the enumeration is covered and names what is not.
A family with no registered parser falls through to raw-text (one whole-file chunk) — reported as an inventory gap against a named family, not a failure.
CustomParsers.md
Inventory-vs-registry coverage report
Tenant source-family inventory, keyed on extraction shape
the source-family inventory checklist AC on Sub E #11726
The tenant's full inventory is enumerated with three outcomes per family, not two: has a parser · deferred with rationale · never ingested. Families are keyed on the meaningful unit a parser would cut — not on era. Measured on the live corpus: 795 prototype methods and 707 free functions against 7 ES classes in 6 of 511 files, so an ES/pre-ES split mis-cuts it and SourceParser's ClassDeclaration + static config + className keys reach almost none of it.
Families not yet inventoried remain raw-text-ingested, flagged against a named family.
TenantIngestionModel.md
The enumerated inventory artifact
Bulk / backfill multi-family ingestion
the ai:ingest-tenant bulk CLI + the #10572 MCP work-volume gate
Bulk/backfill ingests the multi-family corpus volume-gate-aware: incremental pushes via ingest_source_files, over-volume batches via the bulk CLI.
Over mcpSyncMaxChunks → KB_INGEST_VOLUME_EXCEEDED → the bulk CLI path.
HookWiring.md
Bulk-ingestion coverage across families
Acceptance Criteria
The tenant source-family inventory is fully enumerated, keyed on the meaningful unit a parser would cut rather than on language era.
Every enumerated family carries exactly one of three dispositions: has a parser · deferred with rationale · never ingested. A family with none is an incomplete inventory, not a coverage gap.
The never-ingested set is justified by measurement, not taste. Anchor refreshed 2026-08-17 (@neo-opus-vega) — the original cited ~1.98M→~1.11M tokens and "over-band files from 21 to 11", measured on one repo before parsers existed, and its second figure was a FILE count mislabelled as chunks. Current measurement across all three bound tenant repos, post-parser: Global 5,729 chunks / 23 over-band, IDE 87,019 / 45, Suite 766 / 0. Of the 68 surviving over-band chunks, 61 are vendor (3rdParty/, build/, .min.) — for IDE, all 45 of 45, so its non-vendor over-band count is zero. Suite is the control: no vendor tree, no over-band. Top offenders: a 2.7M-token moa-editor demo page, semantic.min.css, bundled Monaco and eslint at ~1M est. tokens each.
Coverage is verified against the registry, not built here — a report naming each family and the parser it reaches, or why it reaches none. #17260 owns building them.#17260 was closed as not planned (operator directive, 2026-08-17); parser construction now happens tenant-side. The tenant deployment's own source parser under kb-parsers/ is the live example, loaded through the per-tenant loader shipped in #17294 — so "the registry" for a tenant repo means its customParsers declaration plus the deployment-pinned parser root, not the global SourceRegistry.
Bulk/backfill ingestion handles the multi-family corpus within the volume gate.
A family's disposition is a decision, not an inference from whether a parser currently reads it. Recorded because I got this wrong: I proposed generated-dts/ for the never-ingest set on the grounds that it duplicated an API already extracted elsewhere and arrived as unusable ~784K-token blobs. Both halves were artifacts of my own shape gate refusing declare, and the operator corrected it — those 58 files are generated from a C++ repo and mapped in, so they are has-a-parser, not never-ingest. A gate's output is not a measurement of the corpus.
Out of Scope
The single proof-ladder ingestion path + its one client-side parser — owned by #11720 (Sub E #11726, Sub F2 #11728).
The source-family inventory checklist itself — already an AC on Sub E #11726; this workstream is the deepening, not the checklist.
Building the parsers — #17260's subs. This ticket enumerates and verifies; it does not implement.
Parser dispatch wiring — already live (resolveParser at IngestionService:1610). Not a deliverable anywhere; an earlier false negative suggested otherwise.
Any size-aware layer around parsers — a pre-splitter, a size-bounded chunker, a "geometry contract". Strict decline per operator ruling: parsers cut on semantic boundaries and the existing filterEmbeddingInputBudget / splitOversizedEmbeddingChunk is the hard cut-off.
Related
Parent: none — standalone. Both former candidates are closed: #11730 (Post-MVP Residual Workstreams) and #17260 (not planned).
Adjacent, not parent: the neo-side per-tenant registration + specifier→class loader gap, and the Global-corpus Source/Parser work — this ticket enumerates and verifies; neither builds.
Redaction note (2026-08-24, @neo-opus-ada): a private tenant's name, repository path and hosting platform were replaced with generic equivalents. No technical claim, measurement or attribution was altered.
tobiu removed the not-code-ready label on Jul 6, 2026, 3:21 PM
Context
Post-MVP residual workstream under Epic #11730. Epic #11720 (Sub E #11726 + Sub F2 #11728) establishes tenant-repo ingestion + a parser path for ONE proof-ladder source family. Discussion #11718 + the #11720 lost-item audit flagged that a real external tenant has many source families (JS-global, test-suite, IDE/header/test-library equivalents, custom formats) — deepening parser + ingestion coverage across all of them is post-MVP.
Gating Condition
Pursued after #11720's single proof-ladder ingestion path works (Sub E #11726 + Sub F2 #11728 landed — verifiable) AND a concrete broader-coverage signal fires — one of:
The proof-ladder path merely existing is not the trigger — a real multi-family tenant corpus must demonstrate the coverage gap. Until both conditions hold: captured intent, not active work.
Scope
Contract Ledger
parsed-chunk-v1contract (learn/agentos/cloud-deployment/CustomParsers.md)parsed-chunk-v1, is explicitly deferred with rationale, or is marked never-ingest. #17260's subs BUILD the parsers; this row checks the enumeration is covered and names what is not.raw-text(one whole-file chunk) — reported as an inventory gap against a named family, not a failure.CustomParsers.mdSourceParser'sClassDeclaration+static config+classNamekeys reach almost none of it.TenantIngestionModel.mdai:ingest-tenantbulk CLI + the #10572 MCP work-volume gateingest_source_files, over-volume batches via the bulk CLI.mcpSyncMaxChunks→KB_INGEST_VOLUME_EXCEEDED→ the bulk CLI path.HookWiring.mdAcceptance Criteria
The tenant source-family inventory is fully enumerated, keyed on the meaningful unit a parser would cut rather than on language era.
Every enumerated family carries exactly one of three dispositions: has a parser · deferred with rationale · never ingested. A family with none is an incomplete inventory, not a coverage gap.
The never-ingested set is justified by measurement, not taste. Anchor refreshed 2026-08-17 (@neo-opus-vega) — the original cited ~1.98M→~1.11M tokens and "over-band files from 21 to 11", measured on one repo before parsers existed, and its second figure was a FILE count mislabelled as chunks. Current measurement across all three bound tenant repos, post-parser: Global 5,729 chunks / 23 over-band, IDE 87,019 / 45, Suite 766 / 0. Of the 68 surviving over-band chunks, 61 are vendor (
3rdParty/,build/,.min.) — for IDE, all 45 of 45, so its non-vendor over-band count is zero. Suite is the control: no vendor tree, no over-band. Top offenders: a 2.7M-token moa-editor demo page,semantic.min.css, bundled Monaco and eslint at ~1M est. tokens each.Coverage is verified against the registry, not built here — a report naming each family and the parser it reaches, or why it reaches none.
#17260 owns building them.#17260 was closed as not planned (operator directive, 2026-08-17); parser construction now happens tenant-side. The tenant deployment's own source parser underkb-parsers/is the live example, loaded through the per-tenant loader shipped in #17294 — so "the registry" for a tenant repo means itscustomParsersdeclaration plus the deployment-pinned parser root, not the globalSourceRegistry.Bulk/backfill ingestion handles the multi-family corpus within the volume gate.
A family's disposition is a decision, not an inference from whether a parser currently reads it. Recorded because I got this wrong: I proposed
generated-dts/for the never-ingest set on the grounds that it duplicated an API already extracted elsewhere and arrived as unusable ~784K-token blobs. Both halves were artifacts of my own shape gate refusingdeclare, and the operator corrected it — those 58 files are generated from a C++ repo and mapped in, so they are has-a-parser, not never-ingest. A gate's output is not a measurement of the corpus.Out of Scope
resolveParseratIngestionService:1610). Not a deliverable anywhere; an earlier false negative suggested otherwise.filterEmbeddingInputBudget/splitOversizedEmbeddingChunkis the hard cut-off.Related
not planned).Origin Session ID
8e1dc8ca-b5a5-4479-b3cf-31918eb4a5b2Redaction note (2026-08-24, @neo-opus-ada): a private tenant's name, repository path and hosting platform were replaced with generic equivalents. No technical claim, measurement or attribution was altered.