LearnNewsExamplesServices
Frontmatter
id17377
titleRegister neomjs/devindex as a pull-mode tenant on the local Agent OS
stateClosed
labels
enhancementaiarchitectureagent-os
assigneesneo-preview
createdAtAug 19, 2026, 10:48 AM
updatedAtAug 23, 2026, 7:38 PM
githubUrlhttps://github.com/neomjs/neo/issues/17377
authorneo-opus-grace
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 17375 DevIndex collection leaves neo, and stops committing what it generates
blocking[]
closedAtAug 23, 2026, 7:38 PM

Register neomjs/devindex as a pull-mode tenant on the local Agent OS

Closed Backlog/active-chunk-17 enhancementaiarchitectureagent-os
neo-opus-grace
neo-opus-grace commented on Aug 19, 2026, 10:48 AM

Context

The containerized plane's pull-mode tenant lane is live. ai/deploy/kb-config.yaml registers three repos under neo-shared — create-app, devindex-opt-in, devindex-opt-out — and the file is mounted read-only into both kb-server and the orchestrator by docker-compose.local-agent-os.yml (:41, :76), where the orchestrator mount is documented as load-bearing.

Both DevIndex intake repositories are already tenants. The application repository is not. Now that neomjs/devindex exists as a standalone product repo with its own guides, unit suite and Data Factory, it should be ingested by our own local deployment.

The Problem

The existing entries are deliberately tiny — the file's own comment explains why: "first-ingest cost scales with tracked-file count on a blobless mirror, so a tiny repo is the cheap end-to-end PROOF that pull-mode ingestion works." create-app, plus 4 and 3 tracked files.

That proof is done. What the lane has never had is a tenant with real content: neomjs/devindex tracks 112 files — an application, a Node.js service layer, 26 guide documents and a Playwright suite. It exercises retrieval quality, chunking across heterogeneous file types, and per-repo scheduling against something a query can actually be wrong about, which three README-sized repos cannot.

It is also the ideal candidate for a second reason: we own it, so a bad ingestion costs us nothing external, and its blast radius is a repository we can re-clone at will.

The Architectural Reality

Why neo itself is excluded, and why that reasoning does not transfer. kb-config.yaml documents that the neo repo is deliberately unregistered: a pull-mode entry declares no parser, falls through to RawRepoSource, and yields untyped raw-file chunks — "a second, weaker corpus under the SAME {tenantId, repoSlug} stamp that kbSync resolves to by default. Each lane then classifies the other's rows as stale and deletes them."

That collision requires two lanes writing one stamp. kbSync ingests the neo checkout through 10 typed source extractors; it does not touch neomjs/devindex. With no competing writer there is no stamp contention and no mutual deletion, so devindex is safe to register where neo is not. This is the one inherited constraint that had to be checked rather than assumed, and it does not apply.

⚠️ The blocker, verified at source. RawRepoSource performs whole-tree ingestion with includeExtensions: [] — no allow-list — and DEFAULT_EXCLUDE_EXTENSIONS is binary and media only:

.7z .avif .bin .bmp .bz2 .class .dmg .eot .exe .gif .gz .ico .jar .jpeg .jpg
.lockb .mov .mp3 .mp4 .otf .pdf .png .sqlite .tar .tgz .ttf .wasm .webm .webp
.woff .woff2 .zip

Neither .json nor .jsonl is excluded, and there is no byte-size guard anywhere in the walker. neomjs/devindex currently tracks:

path size
apps/devindex/resources/data/users.jsonl 24 MB / 49,999 lines
apps/devindex/resources/data/tracker.json 2.1 MB
apps/devindex/resources/data/visited.json 1.6 MB

Registering it today would embed 49,999 contributor records — login, normalized country, lifetime contribution counts, hireable flag, sponsor status — as raw-text chunks in the shared store. That is a cost problem and, more importantly, a personal-data problem: public-profile-derived records about 50,000 identifiable people, ingested under neo-shared visibility, for no retrieval benefit whatsoever. Nobody asks the Knowledge Base who ranks 31,402nd.

#17375 removes exactly those three files from git. After it merges, whole-tree ingestion of this repository is safe by construction — which is why this ticket is blocked by it rather than carrying its own filter.

The Fix

One entry in ai/deploy/kb-config.yaml, after #17375:

      - tenantId: neo-shared
        repoSlug     : devindex
        cloneUrl     : https://github.com/neomjs/devindex.git
        credentialRef: none
        branchRef    : main

credentialRef: none because the repository is public — the contract requires the field and none means "public clone, no credential material". branchRef: main verified against the remote; the file's comment warns that branchRef is per-repo and never inheritable, so this was checked rather than copied from a sibling.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
tenants.neo-shared.tenantRepos[] ai/deploy/kb-config.yaml (tier 2 of tenant-config resolution) gains a devindex entry, whole-tree ingested tier-3 aiConfig defaults if the file is unmounted — which silently drops every entry, not just this one the file's own header comment lastIngestedRev for neo-shared/devindex goes non-null after a sync cycle
ingestion scope for this repo RawRepoSource defaults whole-tree, per the graduated zero-code contract none — an include-manifest is a separate contract lane on the multi-tenant work as above a query returning a devindex guide chunk, and returning no chunk sourced from resources/data/**

Decision Record impact

none — this adds a data entry to an existing, graduated contract. It introduces no new source class, parser, or config surface. Structure-map gate executed; N/A for new Agent OS placement — the only file touched is ai/deploy/kb-config.yaml.

Acceptance Criteria

  • AC-1: neo-shared/devindex appears in kb-config.yaml and a sync cycle drives its lastIngestedRev non-null on the local deployment. That field going non-null is the artifact no unit test provides, per the lane's own precedent.
  • AC-2 (the one that matters): no chunk sourced from apps/devindex/resources/data/** exists in the store after ingestion. Asserted by querying for a value that only appears in the contributor corpus — a specific indexed login — and getting nothing. A pass here is only meaningful once #17375 has landed; running it before is a control that cannot fail for the right reason.
  • AC-3: a semantic query answerable only from DevIndex's guides (for example, how the Meritocracy Filter's threshold rises) returns a chunk sourced from learn/** of this tenant, not from the neo corpus. This is the first entry with content a query can be wrong about, so retrieval correctness is the point rather than ingestion liveness.
  • AC-4: ingesting devindex does not disturb the three existing entries — create-app, devindex-opt-in and devindex-opt-out keep their checkpoints and independent backoff. Per-repo scheduling has only ever been exercised against three near-empty repos; this is the first entry large enough to make a shared-state defect visible.
  • AC-5: the tenant stamp on every ingested chunk reads {tenantId: neo-shared, repoSlug: devindex}, so a later per-tenant split can address this corpus without re-ingesting.

Out of Scope

  • Registering the neo repository itself. Blocked by the documented two-lane stamp collision; it returns as a tenant only once sources and parsers are declarable per tenant.
  • A per-tenant include-manifest. Named in kb-config.yaml as a separate contract lane. This ticket avoids needing one by depending on #17375 instead.
  • A byte-size guard in RawRepoSource. Its absence is real and is what makes the hazard above possible — but a generic walker limit is a change to shared ingestion behaviour affecting every tenant, and it deserves its own ticket rather than riding a config entry. Filing it is not this ticket's job to defer indefinitely; see Related.
  • Non-default branchRef coverage. devindex is main, so this adds no witness for the branch-resolution path that the file notes still has none.
  • Remote/cloud deployment. Local docker only.

Avoided Traps

  • Registering it now because the entry is one line. The entry is one line; the consequence is 50,000 people's records in a vector store. The cheapness of the change is unrelated to the cost of the outcome.
  • Adding an excludeExtensions override to work around the data files. That treats the symptom in the tenant entry and leaves the next tenant to rediscover it, while #17375 removes the files at the source within the same epic.
  • Assuming neo's exclusion rationale applies. It reads like a general warning about pull-mode entries; it is specifically about two lanes writing one stamp. Inheriting it unchecked would have blocked this ticket for a reason that is not true of it.
  • Treating lastIngestedRev going non-null as success. It proves ingestion ran, not that it ingested the right things or excluded the wrong ones. AC-2 and AC-3 exist because AC-1 alone would pass on a store full of contributor records.

Related

Blocked by #17375 (removes the derived data files from git). Sibling context: #17238 (the epic that produced #17375), #16546 / #16557 (tenant-mirror clone cost — devindex is small, which is part of why it is a good tenant).

Follow-up worth filing separately once this lands: RawRepoSource has no byte-size guard and no .json/.jsonl exclusion, so any tenant registering a repository with a large generated data file hits this. devindex is simply the instance that surfaced it.

Retrieval Hint: query_raw_memories("kb-config tenant pull-mode devindex RawRepoSource whole tree no size guard") · "neo-shared tenantRepos credentialRef none"

Live latest-open sweep: checked the latest 20 open issues at 2026-08-19T08:47:36Z plus a keyword sweep on tenant/ingestion/devindex and a 30-message A2A claim scan across all read-states; no equivalent ticket and no in-flight claim on this scope.

Origin Session ID: a105d215-c261-4b34-82a9-546596f665ef

tobiu referenced in commit cd52c60 - "feat(ai): register devindex as the first real-content pull-mode tenant (#17377) (#17623) on Aug 23, 2026, 7:38 PM
tobiu closed this issue on Aug 23, 2026, 7:38 PM