Skip to content

fix(sync): wake Core coverage after scope expansion - #2046

Open
branarakic wants to merge 2 commits into
codex/rfc64-m1-on-demand-lifetimefrom
codex/rfc64-m1-core-discovery-wakeup
Open

fix(sync): wake Core coverage after scope expansion#2046
branarakic wants to merge 2 commits into
codex/rfc64-m1-on-demand-lifetimefrom
codex/rfc64-m1-core-discovery-wakeup

Conversation

@branarakic

@branarakic branarakic commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

User impact

Core nodes no longer leave a newly discovered public Context Graph outside automatic RFC-64 coverage until the ordinary peer-staleness window expires.

The automatic set remains bounded by syncCorePublicBatchSize. Edge behavior is unchanged: Edge nodes still synchronize only explicitly selected graphs. This PR does not increase concurrency, rescan the catalogue on every tick, or broaden private-CG admission.

Problem

A peer round freezes its bounded automatic scope before fetching ontology. If that fetch materializes a new public CG, discovery admits it to the Core scheduler only after the frozen plan has already run. The same round could then stamp the peer fresh, suppressing the follow-up round that would actually request the new graph.

A count-based in-round check was also insufficient: peer A could finish an old-scope round after peer B expanded the catalogue and incorrectly restore freshness for A.

The formal three-node M1 gate reproduced the original symptom as timed out waiting for core automatic journal entry: the Core possessed the public definitions but had no automatic coverage journal entry for the new corpus.

Before

sequenceDiagram
    participant A as "Core peer round A"
    participant B as "Core peer round B"
    participant C as "Coverage scheduler"

    A->>C: Freeze bounded old scope
    B->>C: Freeze bounded old scope
    B->>C: Discover and admit new public CG
    C-->>B: Catalogue expanded
    B->>B: Avoid freshness stamp
    A->>A: Finish later and stamp old scope fresh
    Note over A,C: New CG can remain uncovered on peer A
Loading

After

sequenceDiagram
    participant A as "Core peer round A"
    participant B as "Core peer round B"
    participant C as "Coverage scheduler"
    participant R as "Core reconciler"

    A->>C: Plan at coverage epoch N
    B->>C: Plan at coverage epoch N
    B->>C: Discover and admit new public CG
    C->>C: Advance to epoch N plus 1
    B->>C: Complete with planned epoch N
    C-->>B: Stale epoch; do not refresh
    A->>C: Complete later with planned epoch N
    C-->>A: Stale epoch; do not refresh
    R->>C: Retry peers against epoch N plus 1
Loading

Implementation

  • Maintain a monotonic scheduler-owned coverage epoch that advances only on real register/unregister mutations.
  • Capture that epoch with each frozen Core peer-round plan.
  • Associate peer success/progress timestamps with the epoch they actually attempted.
  • Refuse to restore freshness when the planned epoch differs from the current catalogue epoch, including across concurrent peers.
  • Make both connection-open scheduling and the periodic reconciler treat an older peer epoch as stale.
  • Keep transport backoff independent; catalogue expansion does not claim that an unhealthy peer became healthy.
  • Prune the per-peer epoch marker with the existing sync lifecycle state.

Validation

  • sync-on-connect-retry.test.ts, sync-on-connect-churn.test.ts, and core-public-coverage-scheduler.test.ts: 92 passed
  • discovery-subscription-boundary.test.ts: 20 passed
  • New deterministic two-peer regression proves that neither old-scope round can refresh the newer epoch.
  • pnpm --filter @origintrail-official/dkg-agent build: TypeScript, type tests, and package-root test passed
  • git diff --check: passed

Stack

Comment thread packages/agent/src/dkg-agent-lifecycle.ts Outdated
Comment thread packages/agent/src/dkg-agent-lifecycle.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants