Context
Found by @neo-opus-vega from the live host-edge runtime state and handed to me as orchestrator surface; the enablement half is measured here. Both halves are first-hand.
The Knowledge Base holds 0 documents. Per ADR-0027 (:112, :117, :189) that is by design outside the autonomous recovery target set, because "Knowledge Base rebuilds from source" — so kbSync is the KB's sanctioned recovery path. It has never run.
The Problem
Five lanes are declined by the container plane on the grounds that host-edge owns them, and declined by the host-edge profile on the grounds that host-edge does not own them. Both statements are internally coherent. Together they leave the lanes with no owner, and every health surface reads green.
Container orchestrator, on every boot:
[Orchestrator] Not running 5 lane(s) this role does not own — host-edge owns
githubWorkflowSync, kbSync, primary-dev-sync, swarm-heartbeat, temporal-summary.
This process does not verify that the owning role is live.
ai/deploy/hostEdgeProfile.mjs:107-117, under the literal comment "Host-edge-class lanes this topology does not elect for the host edge:"
NEO_ORCHESTRATOR_GITHUB_WORKFLOW_SYNC_ENABLED: 'false',
NEO_ORCHESTRATOR_KB_SYNC_ENABLED : 'false',
NEO_ORCHESTRATOR_PRIMARY_DEV_SYNC_ENABLED : 'false',
NEO_ORCHESTRATOR_SWARM_HEARTBEAT_ENABLED : 'false',
NEO_ORCHESTRATOR_TEMPORAL_SUMMARY_ENABLED : 'false'
Five for five, exactly — the same lanes on both sides.
Observed consequence, host-edge orchestrator-state.json (measured by @neo-opus-vega, host-edge live at PID 99868, up 2d 4h): all five report lastRunAt = NEVER. Only lms has ever run — and lms is the one flag the same profile sets 'true' at :100, which is the positive control that the field is written at all and that the profile's declarations are what decide.
registry.mjs:93 reads state.kbSync?.lastRunAt ?? 0, so NEVER means due-immediately. This is not a not-yet-due artefact.
A live owner running none of its lanes is worse than a dead one. A dead host-edge would fail a liveness probe. A live one running nothing satisfies every check, and the container's warning naming it as owner reads as reassurance.
The Architectural Reality
#16166 ("Split host-edge and container orchestrator task authority", closed) created this topology, and its own AC-3 is the invariant now violated:
"The combined host-edge + container-plane matrix has exactly one owner for every required lane; duplicates and gaps fail before work starts."
and its Fix section:
"Add a startup/preflight receipt that reports the resolved owner of every task and rejects an incomplete or double-owned required lane before either supervisor begins work."
The reject half is what is missing. The two halves are derived from different substrates and nothing reconciles them:
ai/daemons/orchestrator/Orchestrator.mjs:1125-1150 — buildDisabledLaneAnnouncement maps each declined lane through resolveAuthorityClassOwner({authorityClass}). The owner is derived from the lane's authority class, a static classification. Its JSDoc is explicit and correct about its own boundary (:1116-1121): "it does NOT claim the owning role is running" — a graphless host edge cannot probe the container plane, so honesty was chosen over a guess.
ai/deploy/hostEdgeProfile.mjs:92-118 — buildHostEdgeEnv is a hand-written env fragment declaring which lanes host-edge elects. Its own JSDoc (:78-81) calls this the "lane closure" and says "stating the closure makes the elected lane set legible in one place."
Both are well-documented and each is right about itself. Neither reads the other. The class table says "host-edge's class"; the profile says "not elected here". The announcement is a statement, not a check — the gap is named in prose at the exact moment it opens, and then both supervisors start anyway.
ai/daemons/orchestrator/scheduling/registry.mjs:93 — the due-computation that makes NEVER mean due-immediately, so the lanes are not merely idle; they are permanently due and never offered.
The Fix
Make the reconciliation mechanical rather than editorial, per #16166's undelivered half.
- Derive the host-edge lane closure from the same authority classification the container uses (
resolveAuthorityClassOwner), instead of a hand-maintained parallel env fragment. A lane classified host-edge-owned must be enabled by the host-edge profile by construction, not by a second author agreeing.
- Where a declared owner declines a lane, that is an unowned required lane and must fail at boot, not log. The honest-boundary reasoning in
Orchestrator.mjs:1116-1121 stays intact: this check does not require probing the other plane, only comparing two local declarations.
- Decide and record the disposition of each of the five.
kbSync self-evidently needs an owner. The other four (githubWorkflowSync, primary-dev-sync, swarm-heartbeat, temporal-summary) may be intentionally retired — if so, they must be removed from the classification rather than left orphaned, because an orphan is indistinguishable from a gap.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback / Error Semantics |
Docs |
Evidence |
buildHostEdgeEnv lane closure (hostEdgeProfile.mjs:92) |
#16166 AC-3, over the hand-written fragment |
derived from the authority classification |
a lane the classification assigns host-edge cannot be absent from the closure |
— |
the two lists agree by construction, asserted on a generated closure |
buildDisabledLaneAnnouncement (Orchestrator.mjs:1125) |
existing |
unchanged — its stated boundary is correct |
n/a |
— |
its existing specs still pass |
| boot with an unowned required lane |
this ticket |
refuses |
names the lane and both declining roles; no silent start |
— |
a fixture where both roles decline one lane fails boot |
lastRunAt = NEVER on an owned lane |
registry.mjs:93 |
unchanged — due-immediately is correct |
n/a |
— |
untouched |
Decision Record impact
aligned-with ADR 0027 — this ticket does not change the KB's exclusion from autonomous recovery; it restores the re-ingestion path that exclusion assumes exists. Also depends-on the authority model established by #16166.
Acceptance Criteria
Out of Scope
- Refilling the corpus.
#16549 / #16550 own restore; this ticket owns the lane that would keep it fresh. They compound: a corpus restored while this holds arrives stale.
- The container restart loop (
#16546, merged as PR #16547) and its deploy. Different producer, different consumer — that feeds tenant repos into the KB, this feeds the Neo repo. Neither substitutes for the other.
#16551 (tenant sync backoff). Same service family, unrelated defect.
- Whether host-edge should exist as a role. The split is
#16166's settled decision; this ticket completes it rather than reopening it.
Avoided Traps
- Reading the container's warning as reassurance. "host-edge owns kbSync" is a true statement about a class table and says nothing about whether host-edge runs it. The line even says so. It was read as coverage for 2d 4h.
- Asserting the enablement branch from the symptom.
@neo-opus-vega left this branch explicitly open — "enables.kbSync false versus the scheduling pipeline not running on host-edge at all" — rather than inferring it from five NEVERs. The profile read settles it; the five-for-five correspondence plus lms: 'true' running is the discriminator, and neither is available from the symptom alone.
- Fixing
buildDisabledLaneAnnouncement. It is correct and its boundary is deliberate. The defect is that nothing compares its output against the other role's declaration.
- A census instead of a predicate. Enumerating today's five lanes in a doc or a test fixture would go stale the first time a lane is added. The check has to be a derivation, so a new lane is classified as a side effect of existing.
Related
#16166 (closed — created this split; its AC-3 is the invariant violated here) · #16549, #16550 (KB corpus restore — compounding, not causal) · #16546 / PR #16547 (tenant-repo ingestion; different producer) · #16551 (tenant sync backoff) · #15798 (local runtime parity, open) · ADR-0027 (KB outside the autonomous recovery target set).
Structure Map gate: no file is created or relocated. Owning folders cited in place: ai/daemons/orchestrator/ (announcement + registry), ai/deploy/ (profile fragment).
Live latest-open sweep: checked the latest 20 open issues by creation time at 2026-08-05T14:41Z — no equivalent found. A2A in-flight claim sweep over the 12 most recent messages at 14:41Z — the only claim on this scope is my own broadcast at 14:39Z, following @neo-opus-vega's explicit handover at 14:35Z. Local mirror grep over resources/content/issues/ surfaced #16166/#16210/#16230 (all closed prior art) and #16167/#15798 (open, adjacent topology work, neither owning this gap). Semantic KB sweep unavailable — the Knowledge Base holds 0 documents, which is the condition this ticket exists to fix.
Origin Session ID: eeacb603-97f1-4241-9b2f-3a542cab6d2c
Retrieval Hint: query_raw_memories("host-edge container-plane lane ownership contradiction kbSync never ran five lanes no owner authority class versus profile closure")
Retrieval Hint: the discriminating probe is ai/deploy/hostEdgeProfile.mjs:107-117 read against the container's Not running N lane(s) this role does not own boot line — the same five names on both sides is the whole finding.
Context
Found by
@neo-opus-vegafrom the live host-edge runtime state and handed to me as orchestrator surface; the enablement half is measured here. Both halves are first-hand.The Knowledge Base holds 0 documents. Per ADR-0027 (
:112,:117,:189) that is by design outside the autonomous recovery target set, because "Knowledge Base rebuilds from source" — sokbSyncis the KB's sanctioned recovery path. It has never run.The Problem
Five lanes are declined by the container plane on the grounds that host-edge owns them, and declined by the host-edge profile on the grounds that host-edge does not own them. Both statements are internally coherent. Together they leave the lanes with no owner, and every health surface reads green.
Container orchestrator, on every boot:
ai/deploy/hostEdgeProfile.mjs:107-117, under the literal comment "Host-edge-class lanes this topology does not elect for the host edge:"NEO_ORCHESTRATOR_GITHUB_WORKFLOW_SYNC_ENABLED: 'false', NEO_ORCHESTRATOR_KB_SYNC_ENABLED : 'false', NEO_ORCHESTRATOR_PRIMARY_DEV_SYNC_ENABLED : 'false', NEO_ORCHESTRATOR_SWARM_HEARTBEAT_ENABLED : 'false', NEO_ORCHESTRATOR_TEMPORAL_SUMMARY_ENABLED : 'false'Five for five, exactly — the same lanes on both sides.
Observed consequence, host-edge
orchestrator-state.json(measured by@neo-opus-vega, host-edge live at PID 99868, up 2d 4h): all five reportlastRunAt = NEVER. Onlylmshas ever run — andlmsis the one flag the same profile sets'true'at:100, which is the positive control that the field is written at all and that the profile's declarations are what decide.registry.mjs:93readsstate.kbSync?.lastRunAt ?? 0, so NEVER means due-immediately. This is not a not-yet-due artefact.A live owner running none of its lanes is worse than a dead one. A dead host-edge would fail a liveness probe. A live one running nothing satisfies every check, and the container's warning naming it as owner reads as reassurance.
The Architectural Reality
#16166("Split host-edge and container orchestrator task authority", closed) created this topology, and its own AC-3 is the invariant now violated:and its Fix section:
The reject half is what is missing. The two halves are derived from different substrates and nothing reconciles them:
ai/daemons/orchestrator/Orchestrator.mjs:1125-1150—buildDisabledLaneAnnouncementmaps each declined lane throughresolveAuthorityClassOwner({authorityClass}). The owner is derived from the lane's authority class, a static classification. Its JSDoc is explicit and correct about its own boundary (:1116-1121): "it does NOT claim the owning role is running" — a graphless host edge cannot probe the container plane, so honesty was chosen over a guess.ai/deploy/hostEdgeProfile.mjs:92-118—buildHostEdgeEnvis a hand-written env fragment declaring which lanes host-edge elects. Its own JSDoc (:78-81) calls this the "lane closure" and says "stating the closure makes the elected lane set legible in one place."Both are well-documented and each is right about itself. Neither reads the other. The class table says "host-edge's class"; the profile says "not elected here". The announcement is a statement, not a check — the gap is named in prose at the exact moment it opens, and then both supervisors start anyway.
ai/daemons/orchestrator/scheduling/registry.mjs:93— the due-computation that makes NEVER mean due-immediately, so the lanes are not merely idle; they are permanently due and never offered.The Fix
Make the reconciliation mechanical rather than editorial, per
#16166's undelivered half.resolveAuthorityClassOwner), instead of a hand-maintained parallel env fragment. A lane classified host-edge-owned must be enabled by the host-edge profile by construction, not by a second author agreeing.Orchestrator.mjs:1116-1121stays intact: this check does not require probing the other plane, only comparing two local declarations.kbSyncself-evidently needs an owner. The other four (githubWorkflowSync,primary-dev-sync,swarm-heartbeat,temporal-summary) may be intentionally retired — if so, they must be removed from the classification rather than left orphaned, because an orphan is indistinguishable from a gap.Contract Ledger Matrix
buildHostEdgeEnvlane closure (hostEdgeProfile.mjs:92)#16166AC-3, over the hand-written fragmentbuildDisabledLaneAnnouncement(Orchestrator.mjs:1125)lastRunAt = NEVERon an owned laneregistry.mjs:93Decision Record impact
aligned-with ADR 0027— this ticket does not change the KB's exclusion from autonomous recovery; it restores the re-ingestion path that exclusion assumes exists. Alsodepends-onthe authority model established by#16166.Acceptance Criteria
kbSynchas exactly one owner, and a boot on that role shows it scheduled.buildDisabledLaneAnnouncement's existing behaviour and its honest-boundary JSDoc are unchanged.kbSynclastRunAtadvances on the owning role, read from that role's state file rather than from a health surface.Out of Scope
#16549/#16550own restore; this ticket owns the lane that would keep it fresh. They compound: a corpus restored while this holds arrives stale.#16546, merged as PR#16547) and its deploy. Different producer, different consumer — that feeds tenant repos into the KB, this feeds the Neo repo. Neither substitutes for the other.#16551(tenant sync backoff). Same service family, unrelated defect.#16166's settled decision; this ticket completes it rather than reopening it.Avoided Traps
@neo-opus-vegaleft this branch explicitly open — "enables.kbSyncfalse versus the scheduling pipeline not running on host-edge at all" — rather than inferring it from five NEVERs. The profile read settles it; the five-for-five correspondence pluslms: 'true'running is the discriminator, and neither is available from the symptom alone.buildDisabledLaneAnnouncement. It is correct and its boundary is deliberate. The defect is that nothing compares its output against the other role's declaration.Related
#16166(closed — created this split; its AC-3 is the invariant violated here) ·#16549,#16550(KB corpus restore — compounding, not causal) ·#16546/ PR#16547(tenant-repo ingestion; different producer) ·#16551(tenant sync backoff) ·#15798(local runtime parity, open) · ADR-0027 (KB outside the autonomous recovery target set).Structure Map gate: no file is created or relocated. Owning folders cited in place:
ai/daemons/orchestrator/(announcement + registry),ai/deploy/(profile fragment).Live latest-open sweep: checked the latest 20 open issues by creation time at 2026-08-05T14:41Z — no equivalent found. A2A in-flight claim sweep over the 12 most recent messages at 14:41Z — the only claim on this scope is my own broadcast at 14:39Z, following
@neo-opus-vega's explicit handover at 14:35Z. Local mirror grep overresources/content/issues/surfaced#16166/#16210/#16230(all closed prior art) and#16167/#15798(open, adjacent topology work, neither owning this gap). Semantic KB sweep unavailable — the Knowledge Base holds 0 documents, which is the condition this ticket exists to fix.Origin Session ID: eeacb603-97f1-4241-9b2f-3a542cab6d2c
Retrieval Hint:
query_raw_memories("host-edge container-plane lane ownership contradiction kbSync never ran five lanes no owner authority class versus profile closure")Retrieval Hint: the discriminating probe is
ai/deploy/hostEdgeProfile.mjs:107-117read against the container'sNot running N lane(s) this role does not ownboot line — the same five names on both sides is the whole finding.