LearnNewsExamplesServices
Frontmatter
id16074
titleA deployment cannot observe its own ingestion: the orchestrator is excluded from its bridge
stateClosed
labels
enhancementaimodel-experience
assigneesneo-opus-vega
createdAtJul 28, 2026, 1:32 AM
updatedAtJul 28, 2026, 1:34 AM
githubUrlhttps://github.com/neomjs/neo/issues/16074
authorneo-opus-vega
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 28, 2026, 1:34 AM

A deployment cannot observe its own ingestion: the orchestrator is excluded from its bridge

Closed Backlog/active-chunk-10 enhancementaimodel-experience
neo-opus-vega
neo-opus-vega commented on Jul 28, 2026, 1:32 AM

Context

Split from #16056, whose first half — recording the failure cause and keeping it alive through backoff — ships in PR #16070. These two remaining criteria are a different surface and were holding that PR in draft; carrying them here so the delivered half can be reviewed and merged.

Both were verified live against a cloud deployment while diagnosing a wedged tenant-repo lane.

The Problem

1. The orchestrator is excluded from the bridge it publishes.

bridgeDiagnostics.runtimeAccess.allowedServices
  = ["chroma", "kb-server", "mc-server", "local-model"]
readOperations = ["inspect", "logs", "stats"]

Log access exists for four services. The tenant-repo-sync lane runs in the orchestrator, so the one component holding the failure text is the one component whose logs the bridge cannot read. Diagnosis from a remote MCP client was not difficult, it was impossible — which defeats the purpose of the bridge.

This is largely a shipped default, not an architectural decision. ai/deploy/docker-compose.yml:229 sets that list. It reached the live deployment because we put it there.

The reason it is not purely a one-line change is the asymmetry it needs: the orchestrator must become readable without becoming restartable. NEO_ORCHESTRATOR_RUNTIME_ACCESS_LIFECYCLE_OPERATIONS=restart (line 231) is declared globally rather than per service, so simply appending orchestrator to the allowlist would also hand the bridge the ability to restart the component that publishes it. That wants a read/lifecycle split before the allowlist changes.

2. get_ingestion_progress cannot say "never attempted".

Live, on a deployment where four repos had failed four times each:

status: "idle"   phase: "idle"   totalSources: 0   errorCount: 0
startedAt: null  lastRunSummary: null

errorCount: 0 beside all-null timestamps reads as healthy. It means "no ingestion has ever been observed here", which is a different fact and a much louder one.

A caution for whoever takes this, discovered while diagnosing: the pull path ingests in the orchestrator process, while this tool reports from the kb-server. The two hold separate state. So the surface may be structurally unable to report pull-path runs at all, whatever their outcome — in which case the honest fix is larger than a status enum, and possibly belongs at the deployment-state bridge instead. Establish which before implementing.

Acceptance Criteria

  • The orchestrator's own logs are readable through the bridge, read-only, without appearing in lifecycleOperations targets — asserted both ways: readable, and not restartable.
  • The read/lifecycle scoping is per service rather than global, so "readable but not restartable" is expressible rather than an accident of ordering.
  • The shipped deploy template grants that read access by default; a deployment should not have to discover it.
  • get_ingestion_progress reports "never attempted" distinctly from "failed before ingestion began", so errorCount: 0 can no longer read as healthy.
  • Recorded first: whether that tool can observe pull-path ingestion at all, given the process split. If it cannot, the criterion above moves to the surface that can.
  • Reviewer-checkable: from a remote MCP client alone, a wedged ingestion lane can be diagnosed to a cause without host shell access.

Out of Scope

  • Recording the failure cause and surviving backoff suppression — #16056, delivered in PR #16070.
  • The tenant-repo failure itself; this is about being able to see it.

Avoided Traps

  • Appending orchestrator to the allowlist and calling it done. That grants restart as well, because lifecycle operations are declared globally. The asymmetry is the requirement.
  • Adding a status enum to get_ingestion_progress before checking it can see the runs. A more honest label on a surface that never observes the process in question is a nicer-looking wrong answer.

Related

  • #16056 — parent; the recording half, PR #16070
  • ai/deploy/docker-compose.yml:229 / :231 — the shipped allowlist and the global lifecycle declaration
  • #15977 · #16002 — sibling observability/delivery gaps in the same lane

Live latest-open sweep: checked latest 12 open issues at 2026-07-27T23:32:25Z; no equivalent found — #16056 is the parent this is split from, recorded in both directions.

Origin Session ID: c038696f-94a6-4788-82bf-747c5672908c

Retrieval Hint: query_raw_memories("orchestrator excluded from allowedServices bridge self-observation ingestion progress never attempted")