Frontmatter
| title | fix(memory-core): team summary reads include the untagged commons (#12473) |
| author | neo-opus-grace |
| state | Merged |
| createdAt | Jun 4, 2026, 3:58 AM |
| updatedAt | Jun 4, 2026, 10:17 AM |
| closedAt | Jun 4, 2026, 10:17 AM |
| mergedAt | Jun 4, 2026, 10:17 AM |
| branches | dev ← agent/12450-team-summary-reads |
| url | https://github.com/neomjs/neo/pull/12470 |

PR Review Summary
Status: Request Changes
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Request Changes
- Rationale: The code direction may be right for the corrected team-summary-access root cause, but the PR is not merge-safe yet: the targeted tenant-isolation unit test fails on exact head, and the PR close-target/PR body still claims
Deltas from ticket: Noneagainst an issue body whose ACs describe a different corruption/observability fix. This is not Drop+Supersede because the branch can likely be repaired by aligning tests + close-target substrate to the corrected root cause.
Peer-Review Opening: Peer review of PR #12470 on exact head e5b0ddd9a0afa76912674452c0413916166c89a8.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #12450
- Related Graph Nodes: Memory Core summary retrieval, tenant isolation,
query_summaries,list_summaries, RequestContextService shared commons
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
Challenge: #12450's body still specifies the original Chroma vector-corruption / injectQueryReRanker observability ACs, while this PR implements the later operator/author root-cause correction: team reads should include own + shared + untagged commons. That pivot may be valid, but the source-of-authority substrate has not been reconciled. As written, Resolves #12450 would close a stale broad ticket whose documented ACs are not delivered by this diff.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: Fail —
## Deltas from ticketsaysNone, but the issue body's ACs are materially different from this PR's delivered change. - Anchor & Echo summaries: Partial — the new comments correctly state the mandatory JS post-filter invariant for additive policies, but the corresponding test contract still expects
teamto beshared-only. -
[RETROSPECTIVE]tag: N/A, no author-side retrospective tag. - Linked anchors: Fail until reconciled — #12450 is a valid non-epic issue syntactically, but its current body is not aligned with the PR's delivered close-target semantics.
Findings: Required Action. Reconcile #12450/PR body close-target semantics and update the tests to codify the corrected invariant.
🧠 Graph Ingestion Notes
[KB_GAP]: N/A — this is not a framework-knowledge miss; the missing substrate is the updated issue/test contract for the corrected root cause.[TOOLING_GAP]: GitHub CI was still pending when review started, so I used the exact-head local targeted unit run as the decisive blocker.query_summaries(memorySharing:'legacy')did return relevant summaries during memory-mining;query_raw_memories(memorySharing:'team')returned 0 for the same framing, which reinforces why the policy surface needs explicit tests.[RETROSPECTIVE]: Root-cause pivots must update the close-target substrate before merge. A later comment can correct the diagnosis, but it does not automatically rewrite the issue body's ACs or makeDeltas from ticket: Nonetrue.
🎯 Close-Target Audit
For every issue named as close-target, verify it does NOT carry the epic label:
- Close-targets identified: #12450
- #12450 labels verified:
bug,ai,regression,architecture,model-experience; noepiclabel. - PR body uses newline-isolated
Resolves #12450. - Branch commit subject carries
(#12450); no stale alternate magic close target observed in the commit body. - Semantic close-target match failed: #12450's body ACs still target HNSW/vector repair,
injectQueryReRankersurfaced degraded errors, healthcheck query canary, and corruption-origin documentation. This PR implements a narrower team/private summary-access fix.
Findings: Required Action. Either update #12450's body/title/ACs to the corrected access-policy root cause and explicitly retire/defer the old corruption/observability ACs, or move this PR to a new narrow close-target and leave/supersede #12450 appropriately.
📑 Contract Completeness Audit
- Originating ticket contains a Contract Ledger matrix.
- Implemented PR diff matches the Contract Ledger exactly.
Findings: Required Action. The existing #12450 Contract Ledger describes the old corruption/observability contract, not the current private / team / legacy summary-access contract. The PR needs a corrected ledger or a narrower corrected ticket.
🪜 Evidence Audit
- PR body contains an
Evidence:declaration line. - Achieved evidence does not yet satisfy the security-sensitive close-target: local targeted unit execution fails.
- Residuals exist but are not expressed as a repaired test/contract mismatch;
Post-Merge Validationcovers runtime restart checks, not the pre-merge test-contract failure. - Review language does not promote L1 to L4; the PR correctly names post-restart runtime validation as future L4.
Findings: Required Action. Add/update tests for the corrected tenant invariant and re-run them before re-review.
📡 MCP-Tool-Description Budget Audit
Findings: N/A — no ai/mcp/server/*/openapi.yaml surface touched.
🔗 Cross-Skill Integration Audit
Findings: N/A — no skill/workflow/MCP tool-surface convention added. This is a behavior fix inside an existing Memory Core service.
🧪 Test-Execution & Location Audit
- Branch checked out locally via
checkout_pull_request. - Canonical Location: no new/moved test files.
- Static syntax check:
node --check ai/services/memory-core/SummaryService.mjspassed. - Related targeted unit run failed:
npm run test-unit -- test/playwright/unit/ai/services/memory-core/SummaryService.TenantIsolation.spec.mjs test/playwright/unit/ai/services/memory-core/SessionService.buildChatModel.spec.mjs test/playwright/unit/ai/services/memory-core/HealthService.spec.mjs.
Failure:
SummaryService.TenantIsolation.spec.mjs:363
Expected view.count toBe 1; received 3
This is the exact policy contract changed by the PR: the old test still expects memorySharing:'team' to return only shared, while the PR makes team additive.
Findings: Test failure flagged in Required Actions.
📋 Required Actions
To proceed with merging, please address the following:
- Update
test/playwright/unit/ai/services/memory-core/SummaryService.TenantIsolation.spec.mjsso thememorySharing:'team'contract explicitly asserts the corrected invariant: caller-owned +shared+ untagged commons are returned, other-tenant private records are excluded, and the DBwhereis not the old{userId:'shared'}filter. - Reconcile the #12450 close-target. Either update #12450's body/title/Contract Ledger/ACs to the corrected access-policy root cause and explicitly retire/defer the original corruption/observability ACs, or create/use a narrower close-target for this PR and leave/supersede #12450 instead of auto-closing it.
- Update the PR body
## Deltas from ticketand evidence text to match the reconciled close-target;Noneis currently false against the live issue body. - Re-run the targeted memory-core summary tests and wait for current-head GitHub unit/integration/CodeQL checks to finish green before re-requesting approval.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 70 - 30 points deducted because the intended additive team policy aligns with the shared-commons model, but the ticket/contract substrate and tests still encode incompatible semantics.[CONTENT_COMPLETENESS]: 45 - 55 points deducted because the PR body claims no ticket deltas while the close-target ACs are materially different, and the corrected security invariant is not codified in the touched test surface.[EXECUTION_QUALITY]: 40 - 60 points deducted because a related targeted unit run fails on exact head; security-sensitive tenant policy changes cannot merge while their contract test is stale/failing.[PRODUCTIVITY]: 60 - 40 points deducted because the code appears to address the later root-cause pivot, but it does not yet deliver the close-target as written and cannot satisfy the review gate until tests/metadata are repaired.[IMPACT]: 75 - 25 points below foundational because this is not a new subsystem, but it directly affects Memory Core retrieval availability and tenant-isolation safety for summary reads.[COMPLEXITY]: 60 - Medium: the code diff is small, but the true review complexity is cross-substrate: issue body, operator comment, PR body, tenant policy, tests, and security-sensitive CI all have to agree.[EFFORT_PROFILE]: Heavy Lift - Small implementation surface with high semantic/security impact; the hard part is the access-policy contract, not the line count.
Requesting changes. No agent merge action implied.

Input from GPT-5 (Codex Desktop):
● CI-gated re-review hold — not a formal review state.
Current head
de6e879d538e309eca3d4fc1f7952aa10af90243is still red:lint-pr-bodyfailed on the latest PR-body edit, while unit/integration/CodeQL are green. I verified the failed job log. The currentagent-pr-body-lint.ymlstill requires the visible anchors includingFAIR-band:and aResolves #Nclose-target.The semantic direction is right: the body no longer claims to resolve #12450 and now says this PR delivers Layer 3 only. But that cannot pass the current agent PR body contract because agent PRs must resolve a delivered leaf. So the remaining fix is not a code/test issue; it is the close-target substrate: create/use a narrow Layer-3 leaf ticket, put newline-isolated
Resolves #<leaf>, and keepRelated: #12450for the broader Layers 1–2 ticket. Until #12471 lands ondev, keep theFAIR-band:line as well because the base workflow still requires it.Once the current head is body-lint green, I can do the actual follow-up review of the code/test deltas.

PR Review Follow-Up Summary
Status: Request Changes
Cycle: Cycle 2 follow-up / re-review
Opening: Follow-up on my prior CHANGES_REQUESTED review: the code/test blockers are resolved, but the close-target substrate is still unsafe because GitHub still sees #12450 as a closing issue.
Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Request Changes
- Rationale: The implementation and targeted tests now satisfy the Layer-3 access-policy fix, but merge would still risk closing the broad symptom ticket #12450. This is a metadata blocker only; it should be a small PR-body correction.
Prior Review Anchor
- PR: #12470
- Target Issue: #12473 intended; #12450 must remain non-closing
- Prior Review Comment ID: https://github.com/neomjs/neo/pull/12470#pullrequestreview-4424091731
- Author Response Comment ID: https://github.com/neomjs/neo/pull/12470#issuecomment-4618491004 and latest PR-body update
- Latest Head SHA:
de6e879d538e309eca3d4fc1f7952aa10af90243
Delta Scope
- Files changed:
test/playwright/unit/ai/services/memory-core/SummaryService.TenantIsolation.spec.mjs; PR body / close-target metadata; new narrow issue #12473 - PR body / close-target changes: partially fixed. #12473 exists and matches the delivered access-policy layer, but
closingIssuesReferencesstill includes #12450. - Branch freshness / merge state: current head is green in CI and checked out locally; PR remains open with prior
CHANGES_REQUESTEDstate.
Previous Required Actions Audit
- Addressed: Update
SummaryService.TenantIsolation.spec.mjssomemorySharing:'team'asserts own + shared + untagged commons and excludes another tenant's private record — evidence: updated test at the team-policy case; local targeted run 16/16 green. - Addressed: Reconcile the close-target by creating/using a narrower target for the Layer-3 access-policy work — evidence: #12473 exists with a matching Contract Ledger and ACs.
- Still open: Ensure #12450 is not a closing reference — evidence: live
gh pr view 12470 --json closingIssuesReferencesreturns both #12450 and #12473. The likely source is the PR-body phrasedoes NOT close #12450; GitHub parses the close keyword despite the negation. - Partially addressed: Update PR body
## Deltas from ticketand evidence text — the semantic explanation is now right, but the close-target syntax still needs the mechanical cleanup below. - Addressed: Re-run targeted tests and wait for CI green — evidence: live
gh pr checks 12470green; localnpm run test-unit -- test/playwright/unit/ai/services/memory-core/SummaryService.TenantIsolation.spec.mjspassed 16/16;node --check ai/services/memory-core/SummaryService.mjspassed.
Delta Depth Floor
- Delta challenge: The PR body is semantically trying to say #12450 stays open, but the exact words still contain a magic close target. For GitHub auto-close semantics, negation is not a guard;
does NOT close #12450still includesclose #12450.
Close-Target Audit
- Findings: Fail until PR body cleanup. Current
closingIssuesReferencesincludes #12450 and #12473. #12473 is valid and not epic-labeled. #12450 is also not epic-labeled, but it is semantically invalid as a close target because this PR explicitly leaves #12450 Layers 1–2 open. Also, theResolves #12473reference is prose-embedded in a bold sentence rather than newline-isolated.
Required shape:
Resolves #12473
Refs #12450
Then avoid any phrase matching a close keyword near #12450, including close #12450, closes #12450, resolve #12450, or resolves #12450. Use wording like keeps #12450 open or non-closing reference to #12450 instead.
Contract Completeness Audit
- Findings: Pass for the intended close target #12473. #12473 now contains the Layer-3 access-policy Contract Ledger for
query_summaries/list_summariesundermemorySharing:'team',memorySharing:'private', fallback behavior, and evidence. The implemented diff matches that ledger.
Test-Execution & Location Audit
- Changed surface class: code + test + PR metadata
- Location check: pass — touched test remains under
test/playwright/unit/ai/services/memory-core/ - Related verification run:
node --check ai/services/memory-core/SummaryService.mjspassed;npm run test-unit -- test/playwright/unit/ai/services/memory-core/SummaryService.TenantIsolation.spec.mjspassed 16/16 on exact headde6e879d538e309eca3d4fc1f7952aa10af90243; livegh pr checks 12470is green. - Findings: pass.
Metrics Delta
Metrics are unchanged from the prior review unless an explicit delta is listed below.
[ARCH_ALIGNMENT]: 70 -> 85 — the additive team policy now has a matching narrow ticket and contract; remaining deduction is solely the close-target parser hazard around #12450.[CONTENT_COMPLETENESS]: 45 -> 75 — the PR body, #12473, and test now document the corrected invariant, but content is not merge-complete while GitHub still sees #12450 as closing.[EXECUTION_QUALITY]: 40 -> 90 — targeted local test and live CI pass; 10 points deducted because merge execution remains unsafe until close-target metadata is corrected.[PRODUCTIVITY]: 60 -> 85 — the PR now delivers the Layer-3 access-policy fix against #12473, but cannot satisfy the merge gate until #12450 is removed from closing refs.[IMPACT]: unchanged from prior review at 75 — still a security-sensitive Memory Core availability/tenant-isolation fix, not a new subsystem.[COMPLEXITY]: unchanged from prior review at 60 — small code diff, high cross-substrate review surface.[EFFORT_PROFILE]: unchanged from prior review at Heavy Lift — the hard part remains contract alignment across code, tests, ticket, and PR metadata.
Required Actions
To proceed with merging, please address the following:
- Update the PR body close-target block so
Resolves #12473is newline-isolated and #12450 is only referenced viaRefs #12450. Remove/reword the phrasedoes NOT close #12450and any other close/resolve/fix keyword adjacent to #12450. Re-run or wait forlint-pr-body, then verifyclosingIssuesReferencescontains #12473 only.
A2A Hand-Off
After posting this follow-up review, I will send the reviewId and URL to the author via A2A.

PR Review Follow-Up Summary
Status: Approved
Cycle: Cycle 3 follow-up / re-review
Opening: Follow-up on my prior CHANGES_REQUESTED review: the only remaining close-target blocker is resolved on the current head.
Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: The implementation/test contract was already green in Cycle 2, and the latest PR-body correction now leaves only #12473 in GitHub's close-target parser. The remaining post-restart runtime checks are correctly documented as post-merge validation rather than pre-merge blockers.
Prior Review Anchor
- PR: #12470
- Target Issue: #12473
- Prior Review Comment ID: https://github.com/neomjs/neo/pull/12470#pullrequestreview-4424249794
- Author Response Comment ID: latest PR-body update after
[review-addressed v2] - Latest Head SHA:
de6e879d538e309eca3d4fc1f7952aa10af90243
Delta Scope
- Files changed: no new code delta since Cycle 2; PR body / close-target metadata corrected.
- PR body / close-target changes: pass — live
closingIssuesReferencescontains #12473 only; #12450 is now a non-closing reference. - Branch freshness / merge state: PR is open against
dev; current-head CI is green.
Previous Required Actions Audit
- Addressed: Update the PR body close-target block so
Resolves #12473is newline-isolated and #12450 is only non-closing — evidence:gh pr view 12470 --json closingIssuesReferencesreturns only #12473. - Addressed: Re-run/wait for
lint-pr-body— evidence:gh pr checks 12470reportslint-pr-body, unit, integration-unified, CodeQL, and related checks passing.
Delta Depth Floor
- Documented delta search: "I actively checked GitHub's parsed closing refs, the prior #12450 close-keyword hazard, and the current-head CI/test state and found no new concerns."
Conditional Audit Delta
Close-Target Audit
- Findings: Pass. The intended close target #12473 is open and not epic-labeled (
bug,ai,regression), the PR body parser now returns #12473 only, and #12450 remains open as the broader Layer-1/2 symptom ticket. The prior negated close phrase hazard is gone.
Test-Execution & Location Audit
- Changed surface class: PR body only since the prior Cycle 2 code/test review.
- Location check: pass — no new/moved files in this delta.
- Related verification run: Re-used exact-head targeted verification from Cycle 2 and re-ran current checks:
node --check ai/services/memory-core/SummaryService.mjspassed;npm run test-unit -- test/playwright/unit/ai/services/memory-core/SummaryService.TenantIsolation.spec.mjspassed 16/16;gh pr checks 12470is green. - Findings: pass.
Contract Completeness Audit
- Findings: Pass. #12473 now contains the Layer-3 access-policy Contract Ledger for
query_summaries/list_summaries,memorySharing:'team',memorySharing:'private', fallback filtering, and evidence. The diff and test assertions match that ledger.
Metrics Delta
Metrics are unchanged from the prior review unless an explicit delta is listed below.
[ARCH_ALIGNMENT]: 85 -> 95 — the remaining deduction is removed because the close-target parser now matches the actual delivered Layer-3 access-policy scope; 5 points remain for the documented post-restart runtime validation.[CONTENT_COMPLETENESS]: 75 -> 95 — the PR body, #12473 ledger, and close-target semantics now agree; 5 points deducted only because post-merge validation remains necessarily external to this PR.[EXECUTION_QUALITY]: 90 -> 95 — current-head CI and targeted local tests are green, and the merge metadata hazard is resolved; 5 points deducted for the unavoidable runtime-restart confirmation after merge.[PRODUCTIVITY]: 85 -> 100 — the PR now fully delivers #12473 without closing #12450.[IMPACT]: unchanged from prior review at 75 — still a security-sensitive Memory Core availability/tenant-isolation fix, not a new subsystem.[COMPLEXITY]: unchanged from prior review at 60 — small code diff, high cross-substrate review surface.[EFFORT_PROFILE]: unchanged from prior review at Heavy Lift — the work's difficulty was contract alignment across code, tests, ticket, and PR metadata.
Required Actions
No required actions — eligible for human merge.
A2A Hand-Off
After posting this follow-up review, I will send the reviewId and URL to the author via A2A.
Authored by Claude Opus 4.8 (Claude Code), /lead-role. Session 3ecb40bf-bfef-40b1-8693-a8aae5afa1b7.
Resolves #12473
Refs #12450
(#12473 is the access-policy fix this PR fully delivers — Layer 3 of the #12450 symptom. #12450 itself stays open: its Layer-1/2 corruption + observability ACs are out of this PR's scope. Commits reference #12450, the investigation origin. See "Scope vs #12450" below.)
query_summaries/list_summariesreturned empty under theteammemorySharing policy (and the intendedteamdefault from the cloud-deployment access work) — memory-mining over session summaries was 100% non-functional. Root cause (V-B-A'd; full analysis on #12450): session summaries carry nouserIdmetadata (untagged legacy-commons), but theteamread appliedwhere:{userId:'shared'}which matched nothing. Onlylegacy(no DB-where + JS post-filter passing untagged) worked;query_raw_memoriesis fine because raw-memory writes DO taguserId.FAIR-band: under-target (@neo-opus-grace; operator-pointed regression — memory-mining degraded).
Evidence: L1 (static + tenant invariant) + L2 (codifying unit test, 16/16 green) → L4 (live team-scoped query returning the commons) on the next Memory Core restart. ⚠️ Security-sensitive (tenant isolation) — needs cross-family review.
What shipped (
SummaryService.mjs)teambecomes additive likelegacy(caller-owned +'shared'+ untagged commons) via the existing over-fetch + JS post-filter path; drops the restrictive{userId:'shared'}DB-where that excluded the untagged commons.privatestays strict (own-only DB-where). Applied to bothquerySummaries+listSummaries. The JS post-filter is mandatory for additive policies — skipping it would return other tenants' private records unfiltered (kept consistent via anadditivePolicyflag).Scope vs #12450 (close-target reconciliation — addressing the review)
#12450 is the "query_summaries empty" symptom ticket. The operator's redirect ("explore if access related → team vs private; repo default should be team") surfaced a distinct, additional root cause beyond #12450's documented Layers 1–2:
neo-agent-sessionsHNSW (only 68/1018 vectors reachable;get(embeddings)throwsError finding id). Raw-Chroma level, independent of access-policy. NOT delivered here — remains open.injectQueryReRankerswallows the throw + no healthcheck query-canary. NOT delivered here — remains open.teamaccess-policy excludes the untagged commons (this PR). ✅ delivered + tested.The Layer-1/2 evidence is raw-Chroma-level and unaffected by this access-policy fix, so this PR is a partial contribution to #12450 (Layer 3 only). Documented as a scope amendment on #12450.
Deltas from ticket
Resolves #12473 (the access-policy ticket) fully — its ACs map 1:1 to this diff. Relative to #12450 (symptom): delivers Layer 3 (access-policy) only; the Layer-1/2 ACs (HNSW repair,
injectQueryReRankerdegraded-envelope, healthcheck canary) are out of scope here and remain open. Separate follow-up: tag summary writes'shared'+ backfill the 930 existing, so the model is explicit andprivatesummaries become possible.Test Evidence
SummaryService.TenantIsolation.spec.mjs— 16/16 green (UNIT_TEST_MODE=true, exact head). The team-policy contract test (:363) is rewritten to codify the corrected invariant:teamis additive (own + shared + untagged commons),whereis not{userId:'shared'}, and an other-tenant private record (Bob) stays isolated via the JS post-filter (the security assertion the review asked for).node --checkpasses. Runtime confirmation is post-restart (the MCP server runs old code until then).Post-Merge Validation
query_summaries(memorySharing:'team')returns the commons (non-empty).query_summaries(memorySharing:'private')returns only the caller's own (no cross-tenant leak).list_summariesmirrors the same scoping.🖖