LearnNewsExamplesServices
Frontmatter
id12644
titleProtect PR RESOLVES edges from decay and test ingestion
stateClosed
labels
enhancementaitestingarchitecturemodel-experience
assigneesneo-gpt
createdAtJun 6, 2026, 6:29 PM
updatedAtJun 6, 2026, 7:00 PM
githubUrlhttps://github.com/neomjs/neo/issues/12644
authorneo-gpt
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtJun 6, 2026, 7:00 PM

Protect PR RESOLVES edges from decay and test ingestion

Closed v13.0.0/archive-v13-0-0-chunk-16 enhancementaitestingarchitecturemodel-experience
neo-gpt
neo-gpt commented on Jun 6, 2026, 6:29 PM

Context

Intake of #10058 on 2026-06-06 found that the ticket's literal RESOLVED_BY prescription is stale against current dev, but it exposed a real residual in the current PR-resolution graph path.

Live latest-open sweep: checked the latest 20 open issues on 2026-06-06 before filing. The nearest hit is #10058, now labeled needs-re-triage; no equivalent fresh ticket for current RESOLVES decay protection plus IssueIngestor.ingestPullRequestFeedback() coverage was found. Exact live searches for RESOLVES decay and ingestPullRequestFeedback found no equivalent open implementation ticket. KB semantic ticket sweep was attempted twice and failed because the Knowledge Base collection is unavailable, so this filing relies on live GitHub, Memory Core, and current-source evidence.

The Problem

The modern graph contract is no longer issue -> PR RESOLVED_BY. Current code creates PULL_REQUEST nodes and RESOLVES edges from pr-N -> issue-N, and graph topology traverses inbound and outbound edges. That contract is documented in learn/agentos/DreamPipeline.md.

However, two gaps remain:

  1. GraphService.decayGlobalTopology() protects only IMPLEMENTS, EXTENDS, and SYSTEM_TENET. Factual RESOLVES edges can decay below the pruning threshold, even though a PR resolving an issue is durable provenance.
  2. The PR ingestion path lacks direct unit coverage proving synced PR markdown creates the PULL_REQUEST node and RESOLVES edge.

The Architectural Reality

  • ai/services/ingestion/IssueIngestor.mjs currently reads resources/content/pulls and resources/content/archive/pulls, upserts PULL_REQUEST nodes, and links Resolves|Closes|Fixes #N matches as RESOLVES edges from PR node to issue node.
  • ai/services/memory-core/GraphService.mjs currently applies global decay with WHERE type NOT IN ('IMPLEMENTS', 'EXTENDS', 'SYSTEM_TENET').
  • GraphService.getNeighbors() and GraphService.queryNodeTopology() already traverse both inbound and outbound edges, so no parallel RESOLVED_BY relation is needed.
  • learn/agentos/DreamPipeline.md documents Resolves #N as the canonical shipped-work form while keeping the ingestor liberal for Fixes and Closes.
  • test/playwright/unit/ai/services/ingestion/IssueIngestor.spec.mjs does not currently exercise ingestPullRequestFeedback() with PR markdown and close-keyword extraction.

The Fix

  1. Add RESOLVES to the protected relationship set in GraphService.decayGlobalTopology() so factual PR-to-issue edges do not decay or prune.
  2. Add focused unit coverage for IssueIngestor.ingestPullRequestFeedback() that proves PR markdown creates a PULL_REQUEST node and a RESOLVES edge to the referenced issue.
  3. Add or update focused unit coverage for decay protection so the protected-edge behavior is executable, not only prose.
  4. Keep the existing RESOLVES direction and vocabulary. Do not introduce RESOLVED_BY as a parallel synonym.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
IssueIngestor.ingestPullRequestFeedback() PR markdown ingestion Current IssueIngestor.mjs and DreamPipeline.md PR Feedback section Upserts a PULL_REQUEST node and links referenced issues with RESOLVES from pr-N to issue-N PR files without close keywords still only create the PR node and tag-derived gap nodes Existing JSDoc/docs remain valid unless test exposes drift Focused unit test with mocked PR markdown
GraphService.decayGlobalTopology() relationship protection Current factual graph relation contract documented in DreamPipeline.md RESOLVES edges are excluded from global decay/pruning like other durable structural edges Non-durable relationship types continue to decay normally Inline comment may mention factual edge class if needed Focused GraphService unit assertion
Graph topology consumers (getNeighbors, queryNodeTopology, query_hybrid_graph) Current bidirectional traversal implementation Consumers keep seeing PR resolution neighbors via existing RESOLVES edge direction No RESOLVED_BY alias is introduced; stale #10058 wording remains re-triage-only No docs change expected unless implementation discovers mismatch Existing traversal tests plus new edge-ingestion/decay tests

Decision Record impact

Aligned with the existing Native Edge Graph / Dream Pipeline contract. No ADR amendment required.

Acceptance Criteria

  • GraphService.decayGlobalTopology() excludes RESOLVES from decay/pruning.
  • A focused unit test proves RESOLVES edges remain protected while ordinary edges still decay or prune.
  • A focused unit test proves IssueIngestor.ingestPullRequestFeedback() creates a PULL_REQUEST node from PR markdown.
  • A focused unit test proves IssueIngestor.ingestPullRequestFeedback() creates a RESOLVES edge from pr-N to issue-N when the PR body contains a close keyword.
  • The implementation does not introduce RESOLVED_BY or change graph traversal direction.
  • Focused unit verification runs for the touched GraphService and IssueIngestor test surfaces.

Out of Scope

  • Rewriting #10058 literally.
  • Introducing a RESOLVED_BY edge synonym.
  • Tightening Closes parsing semantics; that remains the separate logic question documented by #10755 / PR #11621.
  • Backfilling historical graph rows outside the normal ingestion path.
  • Changing get_context_frontier ranking behavior.

Avoided Traps

  • Parallel vocabulary drift. Adding RESOLVED_BY would split a contract that already exists as RESOLVES.
  • Docs-only closure. The residual is executable graph behavior; it needs tests.
  • A one-line-only cleanup. The decay fix must land with ingestion and decay coverage so the PR proves the factual edge path end to end.
  • Stale path inheritance. The current service path is ai/services/..., not the old pre-M6 MCP service path named in #10058.

Related

  • #10058 — source stale ticket; now marked needs-re-triage with intake comment.
  • #9851 / PR #9861 — original PR feedback integration lineage.
  • #10755 / PR #11621 — current RESOLVES convention and liberal ingestor documentation.

Handoff Retrieval Hints

  • query_raw_memories(query="RESOLVES edges decay protection pull request graph ingestion tests")
  • query_summaries(query="IssueIngestor PR feedback RESOLVES edge tests")
  • Source anchors: IssueIngestor.ingestPullRequestFeedback, GraphService.decayGlobalTopology, DreamPipeline.md PR Feedback section.
tobiu referenced in commit 53ddf85 - "fix(memory-core): protect PR RESOLVES edges (#12644) (#12645)" on Jun 6, 2026, 7:00 PM
tobiu closed this issue on Jun 6, 2026, 7:00 PM