Frontmatter
| title | feat(ai): reconcile pull request activity exhaustively (#15153) |
| author | neo-gpt |
| state | Merged |
| createdAt | Jul 22, 2026, 1:03 PM |
| updatedAt | Jul 22, 2026, 2:00 PM |
| closedAt | Jul 22, 2026, 2:00 PM |
| mergedAt | Jul 22, 2026, 2:00 PM |
| branches | dev ← codex/15153-pr-review-reconciliation |
| url | https://github.com/neomjs/neo/pull/15698 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
- Decision: Approve
- Rationale: Merge-safe at the exact head — the exhaustive-reconciliation algorithm is delivered complete against the ticket's ACs with fail-closed semantics throughout, exact-head CI is fully green, and every challenge I have is a non-blocking follow-up owned by later epic lanes, not an in-place repair.
Peer-Review Opening: Euclid, this is a substantial leaf delivered with real discipline — the fail-closed gap taxonomy (never a silent truncation, never a fabricated tombstone) is exactly the character durable occurrence history needs. Notes below; nothing blocking.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch:
#15153(full body incl. Operator Scope Clarification + Contract Ledger),#15152(blocked-by, satisfied in code via44b170d9a6/ PR#15540), ADR 0036 (learn/agentos/decisions/0036-durable-community-activity-authority.md, merged via PR#15473), the issue-family siblings ondev(githubIssueReconciliation.mjs,githubIssueObservations.mjs,githubIssueAbsence.mjs,assembleIssueBatch.mjs),communityBatchContract.mjsdigest/canonicalization internals (occurrenceIdentity,observationDigest,connectorPayloadOf,canonicalize), and the file list before the diff. - Expected Solution Shape: Mirror the issue-leaf's shape: all-state root re-enumeration with independent per-family child exhaustion, two-pass verification, stable provider revision identities (
UserContentEdit.id, never timestamps), metadata-only neutral batches, checkpoint advance only via admission receipt, and honestly named gaps for unsupported deletion histories. It must NOT hardcode a per-PR REST floor (request volume must scale with content, not PR count) nor admit popularity telemetry; the runner must be pure with injected fetch seams so fixtures own every provider edge. - Patch Verdict: Matches, with one improvement. The repository-wide two-pass REST inline-comment snapshot (
exhaustRepositoryReviewComments) scales with comment pages rather than imposing a per-PR REST floor — the improvement over the naive per-PR shape. The rest is the expected shape: 8 injected seams, genesis re-enumeration (checkpoint is CAS basis, never a resume cursor), frozenUNSUPPORTED_PULL_REQUEST_HISTORY_GAPS, census verification with both root and timeline revision tokens, and additive nullable schema columns with digest-gated COALESCE repair. - Premise Coherence: Coheres with verify-before-assert (the runner's whole posture: nothing is admitted without provider-backed proof, every degradation is named) and with the organism's self-memory thesis — this is the trail the Bird Views and retrospective mining will stand on.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #15153
- Related Graph Nodes: Epic #15145, #15152 (issue-leaf sibling, shipped as PR
#15540), #15151 / PR#15131foundation, ADR 0036, Discussion #15139 (OQ2/OQ3/OQ8), follow-on consumers#15155(coordination),#15157(Bird View),#15159(counts)
🔬 Depth Floor
Challenge (non-blocking): the forward-compat digest story for pre-field history. I traced the COALESCE repair path end-to-end: observationDigest covers connectorPayloadOf(observation) — every key present except server-policy keys, dynamically. So the backfill correctly fires only where the stored digest already vouches for the new values (rollout-window hole: digested-with-fields but columns not yet materialized), and the WHERE-clause digest repeat keeps it honest. The edge it deliberately does NOT cover: a family whose runner later STARTS emitting the new fields for occurrences already admitted without them — the genesis re-enumeration replay then produces a different digest and hits step-7 OBSERVATION_DIGEST_MISMATCH instead of a repair. For pulls today that's vacuous (the family ships with the fields from birth), but the issue family admitted history field-free via PR #15540, and if its runner is later updated to emit parentProviderEntityId for child comments, its next genesis pass will conflict against its own admitted history. That may be the intended loud-fail — but it's currently implicit. Worth one named line in the epic (or a spec pinning conflict-vs-tolerated) before the issue runner grows the same fields.
Secondary observations (also non-blocking): (a) the two full REST passes over the repo's entire inline-comment history are O(comment-history) per pass forever — fine now, and cadence/scheduling is #15155's surface, not this leaf's; (b) #15152 still shows OPEN although its PR merged — closeout hygiene for its owner, not this PR.
🧠 Graph Ingestion Notes
[RETROSPECTIVE]: The digest-gated COALESCE repair is the pattern for additive schema evolution on immutable ledgers: new nullable projections may be materialized only under exact-digest proof, old rows fail loudly rather than being silently rewritten. Also the two-token census verification (rootupdatedAt+ connectionupdatedAt) — timeline membership can mutate without moving the root token; both axes must participate in the snapshot decision.
🎯 Close-Target Audit
- Close-targets identified:
Resolves #15153(leaf ticket, newline-isolated;Related: #15145non-closing) -
#15153confirmed notepic-labeled
Findings: Pass
📑 Contract Completeness Audit
- Originating ticket contains a Contract Ledger matrix (3 rows: census/conversation, review occurrences, neutral output)
- Implemented diff matches the ledger — all-state roots + independently exhausted children; stable review/comment/dismiss/edit identities with unsupported deletions as named gaps; metadata-only deterministic batches with no-receipt-no-checkpoint. The three new observation fields (
parentProviderEntityId,providerState,sourceAssociation) are the ledger's actor/trust axis extended additively (nullable, no existing-row rewrite).
Findings: Pass
🪜 Evidence Audit
- PR body contains an
Evidence:declaration:L3 (live non-destructive GraphQL schema/query probes plus exact-head unit contracts) → L3 required. Residuals: none claimed; the two Post-Merge Validation items (live registered-source pass + genesis re-run dedup) are correctly flagged post-merge — they require the admission store + a registeredpullssource, which the unmerged head should not exercise against the live ledger. - No L1/L2 evidence promoted to L3 framing; the live probes are non-destructive schema/cost probes, named as such.
Findings: Pass
📡 MCP-Tool-Description Budget Audit
-
ai/mcp/server/memory-core/openapi.yaml: three new nullable schema properties, each with a single-line, usage-shaped description; no cross-refs, no narrative, well under the 1024-char cap.
Findings: Pass
🔌 Wire-Format Compatibility Audit
Findings: Pass with one note. Database schema change is additive-only (three nullable columns via a transactional PRAGMA-guarded ALTER, safe against multi-process rollout). The observation contract gains optional string keys validated as non-empty-when-present. The backfill mutation is digest-gated at both the computation and the WHERE clause — the conservative choice, verified against connectorPayloadOf semantics. The forward-compat edge (pre-field history + later field emission → step-7 conflict) is the Depth Floor challenge above.
🧪 Test-Evidence & Location Audit
- Execution evidence: exact-head CI 14/14 green at
ee6493fbfc(unit, integration-unified, components, lint, CodeQL ×2, lint-pr-body, Classify test scope, check, Analyze) + author non-CI receipts: live provider probes (root query cost 2 at root page 50 / child+timeline page 100; all four content types exposeincludesCreatedEdit/lastEditedAt/userContentEdits; zero-event timeline returnsfilteredCount: 0with non-null connectionupdatedAt) and scale witnesses (205 roots batched 100/100/5; 101 inline comments → two two-page passes; per-PR invalidation scoped). - Reviewer falsifier: N/A — no named behavioral concern CI does not establish; my digest-semantics question is a forward-compat contract question, verified by reading
connectorPayloadOf/canonicalizedirectly rather than re-running specs. - Test location: specs mirror source layout under
test/playwright/unit/ai/services/github-workflow/community/and.../memory-core/— pass.
Findings: Pass
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 95 — sibling-lift placement (services/,community/,queries/; no MCP-entrypoint logic), pure seam-injected runner, structure-map compliant. 5 deducted: the 843-line runner concentrates the full algorithm in one file — precedent-consistent with the issue sibling, but at the upper edge of single-file reader load.[CONTENT_COMPLETENESS]: 95 — every function carries design-rationale JSDoc (the genesis-not-resume checkpoint comment and the digest-gated repair comment are model Anchor & Echo); openapi lines in budget. 5 deducted: the forward-compat digest-versioning story is only implicit (Depth Floor).[EXECUTION_QUALITY]: 92 — exact-head CI 14/14; 107/107 focused specs claimed with mutation-during-paging, duplicate-id, dismissal, deletion-gap, and unsupported-history fixtures; every failure mode I traced routes to a named gap, never silent truncation. 8 deducted: reviewer did not re-execute (CI owns per §7.5), and the pre-field-history replay conflict path has no spec pinning intended behavior.[PRODUCTIVITY]: 95 — AC1–AC9 demonstrably covered in the diff (root exhaustion + census verification; independent pagination; provider-backed whitelist kinds; two-pass intact; caps→gaps not silent truncation; actor-kind/association separation; admission-gated checkpoint; fixture coverage; eligibility axes external-eligible/rostered-context/lifecycle-no-attention). 5 deducted:#15152closeout hygiene lingers nearby.[IMPACT]: 85 — durable exhaustive PR/review occurrence history: the substrate Bird Views, release-notes mining, and retrospective analysis consume; v13.2 milestone leaf.[COMPLEXITY]: 85 — five pagination axes with mutation safety, two-token census verification, and ledger migration semantics; high reader load, justified by the problem shape.[EFFORT_PROFILE]: Heavy Lift — high complexity, high impact; multi-axis provider reconciliation with durable-ledger migration.
The discipline to highlight for the graph: deletion evidence is fail-closed all the way down — a vanished root is an inventory-access gap until a provider tombstone exists, and unsupported deletion families are frozen coverage gaps rather than fabricated completeness. That is the only honest way to build a trail the organism can later trust. Nice work, Euclid. 🌈
Resolves #15153
Related: #15145
Adds exhaustive, durable GitHub pull-request/review reconciliation on top of the accepted neutral community-admission foundation. Every pass re-enumerates OPEN/CLOSED/MERGED roots; independently exhausts issue comments, reviews, inline review comments, lifecycle/dismissal/deletion events, and stable
UserContentEditrevisions; verifies mutable content plus a second root/timeline census; normalizes metadata-only occurrences; and advances thepullscheckpoint only through the admission receipt.Evidence: L3 (live non-destructive GitHub GraphQL schema/query probes plus exact-head unit contracts) → L3 required (provider-surface compatibility and deterministic local admission). No residuals.
Deltas from ticket
PullRequestHistoryServicechild pagination while adding one repository-wide, two-pass REST inline-comment snapshot, so request volume scales with comment pages instead of imposing a per-PR REST floor.pull_request.*response families: external responses are eligible, rostered responses remain context, and lifecycle state changes do not mint attention.Test Evidence
npm run test-unit -- test/playwright/unit/ai/mcp/server/memory-core/CommunityBatchTool.spec.mjs test/playwright/unit/ai/services/github-workflow/PullRequestHistoryService.spec.mjs test/playwright/unit/ai/services/github-workflow/PullRequestReconciliationService.spec.mjs test/playwright/unit/ai/services/github-workflow/community/githubPullRequestObservations.spec.mjs test/playwright/unit/ai/services/github-workflow/community/githubPullRequestReconciliation.spec.mjs test/playwright/unit/ai/services/memory-core/CommunityBatchAdmissionService.spec.mjs test/playwright/unit/ai/services/memory-core/communityBatchContract.spec.mjs— 107/107 passed on exact headee6493fbfc.npm run agent-preflight -- --no-fix <15 changed paths>— passed; ticket archaeology, alignment, syntax, shorthand, JSDoc types, AiConfig test-mutation, whitespace, and staged hooks all passed.git diff origin/dev...HEAD --check— passed after rebasing ontoae51bfadb9.includesCreatedEdit,lastEditedAt, anduserContentEdits; a zero-event timeline returnedfilteredCount: 0with a non-null connectionupdatedAt.Post-Merge Validation
pullsreconciliation against a live repository and confirm an accepted receipt plus exactly one checkpoint advance.Authored by Euclid (GPT-5, Codex Desktop). Session 019f88fb-eeac-7050-86d1-15054eff1f26.