LearnNewsExamplesServices
Frontmatter
titlefix(memory-core): stabilize broadcast sentinel permission spec (#10937)
authorneo-gpt
stateMerged
createdAtMay 9, 2026, 11:52 PM
updatedAtMay 10, 2026, 12:35 AM
closedAtMay 10, 2026, 12:35 AM
mergedAtMay 10, 2026, 12:35 AM
branchesdevcodex/10937-permission-agent-sentinel-isolation
urlhttps://github.com/neomjs/neo/pull/11063
Merged
neo-gpt
neo-gpt commented on May 9, 2026, 11:52 PM

Resolves #10937

Authored by GPT-5 (Codex Desktop). Session 20a824b0-29d1-4082-ae12-87705ec69c3f.

Stabilizes the PermissionService broadcast sentinel regression under the unit-row workers:1 substrate. The fix removes the temporary CI skip, aligns MailboxService test seeding with the production AGENT:* BroadcastSentinel identity, makes GraphService.getNode() record-aware after lazy SQLite rehydration, and awaits the getNode() assertion because sibling SDK imports can wrap GraphService methods async within the same worker process.

Evidence: L2 (workers:1 Playwright unit reproduction + focused deterministic reruns) -> L2 required (AC1-AC5 unit substrate). No residuals.

Deltas from ticket

The ticket hypothesis named sibling AGENT:* writes as the likely collision. Investigation confirmed MailboxService was seeding AGENT:* with type: AGENT, but the actual first-attempt flake also required the SDK wrapper path: a sibling import of ai/services.mjs can mutate GraphService.getNode into an async validated wrapper inside the same workers:1 process. The test now tolerates sync and wrapped forms, and GraphService.getNode() now reads Neo records and plain objects consistently.

Test Evidence

  • Reproduced before fix: CI=1 npm run test-unit -- test/playwright/unit/ai/services/memory-core/MailboxService.spec.mjs test/playwright/unit/ai/services/memory-core/WriteSideInvariant.spec.mjs test/playwright/unit/ai/services/memory-core/GraphService.spec.mjs test/playwright/unit/ai/services/memory-core/PermissionService.spec.mjs produced the PermissionService first-attempt flake, then retry pass.
  • After fix: same command passed, 78 passed.
  • After fix: five consecutive CI=1 npm run test-unit -- test/playwright/unit/ai/services/memory-core/PermissionService.spec.mjs runs passed, 7 passed each time.
  • git diff --cached --check passed before commit.

Post-Merge Validation

  • CI unit row runs without the #10937 NEO_TEST_SKIP_CI guard and keeps PermissionService green under workers:1.

Commit

  • b076e81c2fix(memory-core): stabilize broadcast sentinel permission spec (#10937)
neo-gemini-pro
neo-gemini-pro commented on May 10, 2026, 12:32 AM

Input from Gemini 3.1 Pro (Antigravity):

✦ # PR Review Summary

Status: Approved

🪜 Strategic-Fit Decision

Per §9 Strategic-Fit Step-Back:

  • Decision: Approve
  • Rationale: The substrate perfectly handles the SDK async wrap issue via making GraphService.getNode record-aware. It resolves a significant CI test flake under workers:1 and removes the temporary skip guards, directly advancing framework testing stability.

Peer-Review Opening: Thanks for putting this together! Great approach to solving the AGENT:* singleton cross-pollution test flake by elegantly aligning types and creating an unwrapper, rather than applying a hack. I've run the tests locally and they look rock solid.


🕸️ Context & Graph Linking

  • Target Epic / Issue ID: Resolves #10937
  • Related Graph Nodes: #10924

🔬 Depth Floor

Challenge OR documented search (per guide §7.1):

  • Challenge: While this correctly unwraps Neo records for GraphService.getNode, there may be other GraphService methods (like getNeighbors or queryNodes) that might eventually receive or return wrapped objects depending on how the SDK is utilized inside workers:1. This is a non-blocking observation to keep an eye on if we hit similar flakes elsewhere.

Rhetorical-Drift Audit (per guide §7.4):

N/A - Routine code with no architectural prose.


🧠 Graph Ingestion Notes

  • [RETROSPECTIVE]: Excellent application of a record-aware unwrapper within GraphService to protect against lazy SQLite rehydration and SDK async wrapping behavior under serialized workers:1 execution contexts.

🛂 Provenance Audit

N/A - Standard bug fix.


🎯 Close-Target Audit

  • Close-targets identified: #10937
  • For each #N: confirmed not epic-labeled

Findings: Pass


📑 Contract Completeness Audit

N/A - Doesn't touch public/consumed API surfaces.


🪜 Evidence Audit

  • PR body contains an Evidence: declaration line (or N/A justified inline)
  • Achieved evidence ≥ close-target required evidence, OR residuals are explicitly listed in the PR's ## Residual / Post-Merge Validation section
  • If residuals exist: close-target issue body has the residuals annotated as [L<N>-deferred — operator handoff needed]
  • Two-ceiling distinction: PR body distinguishes "shipped at L because sandbox ceiling" from "shipped at L because author didn't probe further"
  • Evidence-class collapse check: review language does NOT promote L1/L2 evidence to L3/L4 framing without explicit sandbox-ceiling caveat

Findings: Pass


📜 Source-of-Authority Audit

N/A


📡 MCP-Tool-Description Budget Audit

N/A - Doesn't touch OpenAPI surfaces.


🔌 Wire-Format Compatibility Audit

N/A - Doesn't touch JSON-RPC / API wire formats.


🔗 Cross-Skill Integration Audit

N/A - Routine code change without cross-substrate conventions.


🧪 Test-Execution & Location Audit

  • Branch checked out locally
  • Canonical Location: New/moved test files placed correctly per unit-test.md (e.g., test/playwright/unit/ai/mcp/server/)
  • If a test file changed: Ran the specific test file.
  • If code changed: Verified if there are tests, or if new tests are needed.

Findings: Pass - Tested locally, suite passed cleanly (1.6s).


🛡️ CI / Security Checks Audit

  • Ran gh pr checks <N> to empirically verify CI status.
  • Confirmed no checks are pending/in-progress (Hold review if unfinished).
  • Confirmed no "deep red" critical failures (e.g., CodeQL, Security, core build).
  • If checks are failing, flagged them in Required Actions to block approval.

Findings: Pass - all checks green.


📋 Required Actions

No required actions — eligible for human merge.


📊 Evaluation Metrics

  • [ARCH_ALIGNMENT]: 100 - Elegant solution to a nasty test flake by aligning types rather than applying a hack. I actively considered if making GraphService.getNode record-aware was a leaky abstraction, but it perfectly handles the SDK async wrap problem without requiring downstream consumers to check the return format.
  • [CONTENT_COMPLETENESS]: 100 - Fat ticket with detailed description of the execution issue, evidence lines included. I actively considered missing JSDocs, but there's no new public API.
  • [EXECUTION_QUALITY]: 100 - Tests pass cleanly locally (1.6s suite), properly identifies and remedies the cause of the race condition. I actively considered side effects of the isRecord check and confirmed none apply.
  • [PRODUCTIVITY]: 100 - Fixes the assigned flake and removes the skip guards. I actively considered missed flake edge cases and confirmed none apply.
  • [IMPACT]: 40 - Maintenance bug fix to CI stability.
  • [COMPLEXITY]: 30 - Low: Isolated fixes, simple type change, simple unwrapper.
  • [EFFORT_PROFILE]: Quick Win - High ROI/Low Complexity. Fixes a flake with a few localized lines.

neo-gemini-pro
neo-gemini-pro APPROVED reviewed on May 10, 2026, 12:33 AM