LearnNewsExamplesServices
Frontmatter
id14883
titleGP fallback: plumb REM pipeline state for precise frontier-cause attribution
stateOpen
labels
enhancementaiarchitecture
assigneesneo-opus-ada
createdAt12:07 PM
updatedAt12:25 PM
githubUrlhttps://github.com/neomjs/neo/issues/14883
authorneo-opus-ada
commentsCount0
parentIssue14472
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 14879 Computed GP frontier-empty fallback hardcodes an unmeasured cause
blocking[]

GP fallback: plumb REM pipeline state for precise frontier-cause attribution

Open Backlog/active-chunk-4 enhancementaiarchitecture
neo-opus-ada
neo-opus-ada commented on 12:07 PM

Context

Follow-up carved out of #14879 / PR #14882 (the honest-states fallback-cause fix). That PR made renderDeclaredIntentFallback attribute the measured cause via classifyFrontierEmptyCause, but wired the caller (GoldenPathSynthesizer.buildDeclaredIntentFallback) with only a verified binary "digested-history-exists" signal — enough to distinguish FRONTIER_UNANCHORED from COLD_START (the operator's 2026-07-06 case), but NOT the exact REM backlog/cycle state.

The Problem

classifyFrontierEmptyCause already accepts undigested + recentCycleCount and returns REM_STALLED when there is undigested work AND no recent cycle. But the caller cannot supply those honestly: V-B-A against the live graph DB (.neo-ai-data/sqlite/memory-core-graph.sqlite) showed the REM pipeline's digested/undigested/recentCycles are not cleanly derivable from the SQLite node table ($.type is null for ~143k nodes; summary% count = 622 ≠ the pipeline's ~1460 digested). A naive count would ship a new wrong number — the exact failure #14879 fixed. So REM_STALLED currently never fires from the live caller (it degrades to FRONTIER_UNANCHORED/UNATTRIBUTED, which is honest but coarse).

The Architectural Reality

The authoritative REM metrics live in the REM/consolidation subsystem (the source behind get_rem_pipeline_state: {undigested, digested, recentCycles}), NOT the graph Nodes table. buildDeclaredIntentFallback is a static, cold-cache SQLite-sourced method — threading pipeline state in must respect ADR-0019 (read AiConfig at the use site; no new pass-along/threading antipattern) and the method's "never blow the scheduling budget" bound.

The Fix

Give the caller a cheap, correct read of the REM pipeline state (undigested + recentCycleCount) and pass them into classifyFrontierEmptyCause, so a genuine REM_STALLED renders honestly instead of collapsing to FRONTIER_UNANCHORED. Identify the in-process accessor the REM subsystem exposes (mirror of the get_rem_pipeline_state MCP surface) rather than re-deriving from SQLite.

Acceptance Criteria

  • buildDeclaredIntentFallback supplies measured undigested + recentCycleCount (from the authoritative REM subsystem, not a graph-node count) to classifyFrontierEmptyCause.
  • A genuine stall (undigested backlog + no recent cycle) renders REM_STALLED; a healthy-digestion-empty-anchor renders FRONTIER_UNANCHORED — proven by a whitebox/integration test with both fixtures.
  • No ADR-0019 antipattern introduced (no threading AiConfig values, no re-derivation); the accessor read stays within the method's budget.

Out of Scope

  • The classifier + render themselves (shipped in #14879 / PR #14882 — this only feeds them real metrics).
  • The wake-daemon / REM-cycle-firing mechanism (separate lane).

Related

  • Blocked-by: #14879 (merge PR #14882 first — this builds on the shipped classifier).
  • Parent epic: #14472. Sibling vocabulary: #14565.

Origin Session ID: 9360840f-5d7a-4680-8110-86877722735b Retrieval Hint: query_raw_memories("goldenPathPickupBridge classifyFrontierEmptyCause REM_STALLED pipeline state plumbing")

Live latest-open sweep: checked 2026-07-06; no equivalent found (only #14879, the parent fix).