LearnNewsExamplesServices
Frontmatter
id15749
titleMake cloud diagnostics fail-honest and client-neutral
stateClosed
labels
bugdocumentationaiarchitecture
assigneesneo-gpt
createdAtJul 23, 2026, 12:15 PM
updatedAtJul 23, 2026, 3:45 PM
githubUrlhttps://github.com/neomjs/neo/issues/15749
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 23, 2026, 3:45 PM

Make cloud diagnostics fail-honest and client-neutral

Closed Backlog/active-chunk-8 bugdocumentationaiarchitecture
neo-gpt
neo-gpt commented on Jul 23, 2026, 12:15 PM

Context

The tenant-repo deployment snapshot added by closed #14396 can report enablement, task state, effective repo counts, config tiers, revisions, and bounded failure codes. Its config projection is only as honest as the upstream resolver, however.

A fresh executable probe against current dev produced the same value for three materially different bootstrap states:

{
  "missing": null,
  "malformed": null,
  "unreadable": null
}

The public source tree also contains a liveness empirical-anchor comment whose operational facts are useful but whose suffix names a specific organization/incident. Public Neo source must keep customer and deployment identities generic.

Live latest-open sweep: checked the latest 20 open issues at 2026-07-23T10:14:19Z; no equivalent found. Targeted live search for tenant-repo bootstrap, malformed kb-config, and diagnostics found only closed predecessor #14404. A2A all-state sweep: checked the latest 30 messages inside the 60-minute herd window; no overlapping earlier claim found.

The Problem

KnowledgeBaseIngestionService.readKbConfigBootstrap() catches every failure and returns null for an absent file, an unreadable file, malformed YAML, and an empty document (ai/services/knowledge-base/IngestionService.mjs:1292-1314). That fail-soft behavior preserves fallback resolution, but it destroys the provenance needed for cloud diagnosis.

listConfiguredTenantRepos() consumes only the nullable document (IngestionService.mjs:1317-1344). TenantRepoSyncService.resolveTenantReposConfig() forwards the flattened result, and DeploymentStateBridgeService.collectTenantRepoSyncSnapshot() can therefore summarize only the repos it received. When resolution does not throw, summarizeTenantRepoConfig() reports status: available and a count—even when the YAML bootstrap was unreadable or malformed (ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs:608-623,836-855).

This collapses distinct operator actions:

  • missing optional bootstrap: confirm another config tier or mount the file if it was intended;
  • valid empty bootstrap: configuration was read successfully and declares no YAML tenants/repos;
  • unreadable bootstrap: fix mount ownership/permissions;
  • malformed YAML: fix syntax;
  • invalid top-level shape: fix the deployment contract.

Separately, ai/services/graph/ollamaStuckRunnerLiveness.mjs:8-9 embeds a named-customer suffix in a tracked public comment. The model, CPU, and duration measurements are a valid generic empirical anchor; the organization identity is not.

The Architectural Reality

  • kb-config.yaml is an optional Tier-2 bootstrap. The graph tier remains canonical and the AiConfig provider remains the fallback.
  • Fail-soft fallback and fail-honest diagnostics are compatible: runtime config resolution may continue while a structured diagnostic records what happened.
  • DeploymentStateBridgeService already owns the redacted public snapshot and already distinguishes thrown config reads from valid empty results. It needs structured bootstrap provenance from the resolver rather than filesystem access of its own.
  • AiConfig remains the reactive Provider SSOT per ADR 0019. This work reads AiConfig.neoRootDir at the existing use site; it must not add env re-resolution, pass-along config plumbing, defensive optional chaining, or runtime mutation.
  • ollamaStuckRunnerLiveness.mjs owns the liveness classifier and its explanatory JSDoc. Scrubbing the identity changes no runtime behavior.

Structure-map ownership: changes stay within existing ai/services/knowledge-base, ai/daemons/orchestrator/services, and ai/services/graph siblings. No new service, daemon, or directory is required.

The Fix

  1. Add a structured bootstrap-read result at the existing Knowledge Base service boundary, for example readKbConfigBootstrapResult():
    • status: missing, empty, loaded, read-failed, parse-failed, or invalid-shape;
    • document: parsed object only for valid input, otherwise null;
    • bounded errorCode and messageClass for failures;
    • no absolute host path, YAML content, tenant/repo names, clone URLs, credential references, tokens, stack, or raw filesystem message.
  2. Preserve compatibility by keeping readKbConfigBootstrap() as the document-only consumer path (delegating to the structured result), or migrate all internal callers atomically without changing config-tier precedence.
  3. Extend listConfiguredTenantRepos() to return redacted configDiagnostics.bootstrap alongside tenantRepos.
  4. Project that data through TenantRepoSyncService.resolveTenantReposConfig() into tenantRepoSync.config.bootstrap:
    • missing and valid empty remain non-error states;
    • read-failed, parse-failed, and invalid-shape make the config diagnostic degraded while still showing any safely resolved fallback repos;
    • repo work may continue from a valid higher/fallback tier, but the bootstrap failure must not disappear.
  5. Update cloud configuration/troubleshooting docs with the state/action mapping.
  6. Replace the named-organization suffix in the Ollama stuck-runner empirical-anchor comment with generic cloud-deployment wording while retaining the useful model/CPU/duration evidence.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
New structured bootstrap-read result in KnowledgeBaseIngestionService Current readKbConfigBootstrap() behavior + this ticket Return a bounded status, document, and categorical failure metadata Missing/empty return no error; read/parse/shape failures return no document and never leak raw input/path/message JSDoc on the loader Unit tests for every status and redaction
Existing readKbConfigBootstrap() document path Current IngestionService.mjs config-tier contract Preserve object-or-null compatibility for existing resolution callers Delegates to the structured loader; fallback precedence remains graph > YAML > AiConfig Existing resolver JSDoc Existing tier-precedence suite remains green
listConfiguredTenantRepos() result Current resolver consumed by TenantRepoSyncService Add redacted configDiagnostics.bootstrap beside tenantRepos Callers that only read tenantRepos remain compatible Resolver JSDoc Graph/YAML/AiConfig fixtures plus malformed/unreadable bootstrap fixtures
tenantRepoSync.config.bootstrap deployment snapshot field Closed #14396 diagnostic contract + DeploymentStateBridgeService Distinguish missing, valid-empty, loaded, read-failed, parse-failed, and invalid-shape states Failure degrades config diagnostics without hiding safely resolved fallback repo counts; output remains bounded and secret-free Cloud troubleshooting and KB diagnostic docs Snapshot tests for each state and explicit redaction assertions
Ollama stuck-runner empirical-anchor comment Public-artifact client-neutrality invariant Preserve generic operational measurements without identifying an organization or private incident Use generic cloud-deployment wording; no runtime change JSDoc only Static source assertion/review plus tracked-tree identity scan

Decision Record impact

Aligned with ADR 0014's cloud deployment topology and ADR 0019's AiConfig Provider SSOT. No ADR amendment: this improves observability at existing boundaries without changing tier precedence, runtime topology, or config authority.

Acceptance Criteria

  • Bootstrap diagnostics distinguish missing, empty, loaded, read-failed, parse-failed, and invalid-shape.
  • Existing graph > YAML > AiConfig per-tenant winner semantics remain unchanged.
  • A missing optional YAML file does not degrade a deployment that resolves through another valid tier, but its absence remains visible.
  • Read, parse, and shape failures are visible as degraded config diagnostics even when fallback repos can still be enumerated.
  • tenantRepoSync.config.bootstrap exposes only status, bounded stable code/message class, and non-sensitive counts; it excludes absolute paths, raw YAML, tenant/repo identities, clone URLs, credential references, tokens, stacks, and raw OS messages.
  • Tests cover missing file, unreadable file, malformed YAML, empty document, invalid top-level shape, valid empty tenants, and valid configured tenants.
  • Deployment snapshot tests prove true no-config is distinguishable from bootstrap failure.
  • Cloud configuration and troubleshooting docs map each diagnostic state to the correct operator action.
  • The stuck-runner liveness comment retains its empirical measurements but contains no named organization/customer identifier.
  • No runtime behavior, liveness thresholds, model selection, or scheduling policy changes as part of the comment scrub.

Out of Scope

  • Changing graph/YAML/AiConfig precedence or merging tiers within a tenant.
  • Adding a remote config-write, ingestion, replay, shell, or Docker actuator.
  • Exposing raw YAML, filesystem paths, logs, credentials, or repository identities.
  • A repository-wide branding rewrite beyond the identified public-source leak.
  • Fixing error-bearing ingestion revision advancement; tracked separately in #15748.

Avoided Traps

  • Do not make optional bootstrap failures fatal to all config resolution; preserve safe fallback while reporting degradation honestly.
  • Do not re-read the filesystem inside DeploymentStateBridgeService; the Knowledge Base resolver owns bootstrap interpretation.
  • Do not collapse failure classes back into message prose; consumers need stable categorical states/codes.
  • Do not split the one-line public-source neutrality cleanup into a micro-ticket.

Related

Related: #14396

Related: #14404

Related: #15748

Origin Session ID: fc1a49c1-e30a-4e3a-960a-e0596367a4c1

Handoff Retrieval Hint: kb-config bootstrap missing malformed unreadable tenantRepoSync config diagnostics client-neutral liveness comment