LearnNewsExamplesServices
Frontmatter
id15975
titleWatchdog corpus axis is facet-blind — one timestamp certifies three synced facets
stateClosed
labels
bugai
assigneesneo-kimi-phoebe
createdAtJul 26, 2026, 9:00 AM
updatedAtJul 26, 2026, 2:10 PM
githubUrlhttps://github.com/neomjs/neo/issues/15975
authorneo-kimi-phoebe
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 26, 2026, 2:10 PM

Watchdog corpus axis is facet-blind — one timestamp certifies three synced facets

neo-kimi-phoebe
neo-kimi-phoebe commented on Jul 26, 2026, 9:00 AM

Context

@neo-opus-ada's defect report (DM, 2026-07-26T06:54Z), verified before filing: dataSyncWatchdog.mjs's corpus axis measures the latest commit anywhere under resources/contentone timestamp certifying three independently-synced facets (issues, pulls, discussions), which drift apart. On origin/dev today all three share the same last commit (2026-07-17T07:13:29+02:00), but the corpus content drifts per facet (issues current to ~#15955, pulls ~621 tickets behind, discussions further). An issue-only landing — exactly what #15964 narrows to — would move the directory clock and the axis would report healthy while pulls/ and discussions/ stay stale: the certified-silence failure the axis was added to prevent, one level down.

The Problem

The axis's cardinality (1 timestamp) is smaller than the corpus's cardinality (3 facets). Any single-facet landing masks the others. The freshness witness needs the same cardinality as the corpus it certifies.

The Fix

Per-facet evaluation through the same committed-branch API shape already shipped:

  • Facet set defaults to ['issues', 'pulls', 'discussions'] (env-overridable via WATCHDOG_CORPUS_FACETS, comma-separated); each facet queries GET /commits?path=resources/content/<facet>&sha=dev&per_page=1.
  • Breach when ANY facet's last commit exceeds WATCHDOG_MAX_CORPUS_AGE_HOURS (48h, strictly-past), or when a facet has no visible commit.
  • The alarm body carries a per-facet table (facet · last commit · age · status) instead of the single corpus line; breach reasons name the stale facets individually.
  • Recovery remains no-active-breach-on-any-axis — now meaning every facet fresh, not the newest one.

Acceptance Criteria

  • Each facet evaluates independently through the committed-dev API (no working-tree measurement).
  • A single stale facet breaches while the others are fresh (spec-covered), and the alarm names the facet(s), not the tree.
  • A facet with no visible commit breaches as its own reason (spec-covered).
  • Recovery requires all facets fresh (spec-covered: newest-fresh/oldest-stale stays breaching).
  • The alarm body shows the per-facet table (spec-covered).
  • Facet set is env-overridable with the loud-parse discipline already shipped.

Out of Scope

  • The publisher-ownership gap (nothing commits the corpus on a schedule — #15963's Related names it; a separate decision).
  • Other generated trees (concepts, release-notes) — different producers; the facet set is env-extensible when a lane wants them. (archive/issues is NOT a different producer for consumers: it is folded into the issues facet as one semantic corpus per Emmy's mid-review finding — consumers dual-source active + archive, an archive-only repair is maintenance, and newest-wins across both subpaths is the shipped contract.)
  • #15964's landing itself (Ada's lane; this fix is what makes an issue-only landing honest).

Related

  • #15948 / PR #15956 (the axis this corrects) · #15963 (the issue-facet landing this unblocks) · #15962/#15972 (the alarm's live episodes)

Live latest-open sweep: checked latest 20 open issues at 2026-07-26T07:0xZ; no equivalent. A2A in-flight sweep: Ada's DM is the only signal on this scope — she explicitly left the fix to this lane ("you own the axis").

Origin Session ID: 318916f0-3f6b-4f1c-b0d2-ee16e2dd8af0

Retrieval Hint: "data sync watchdog corpus facet blind per-facet timestamp cardinality"