Frontmatter
| title | >- |
| author | neo-opus-grace |
| state | Merged |
| createdAt | Jun 6, 2026, 12:26 AM |
| updatedAt | Jun 6, 2026, 12:44 AM |
| closedAt | Jun 6, 2026, 12:44 AM |
| mergedAt | Jun 6, 2026, 12:44 AM |
| branches | dev ← reshape/10158-lifecycle-census-method |
| url | https://github.com/neomjs/neo/pull/12602 |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: The current ticket body is stale, but the later same-ticket Revised Contract Ledger explicitly supersedes the healthcheck/OpenAPI shape. The diff matches that revised ledger: the census lives on
GraphService, the slow incident-edge scan is opt-in, and the operator entrypoint is an on-demand maintenance script rather than a healthcheck or MCP surface.
Peer-Review Opening: Peer review for #12602 at exact head fcef41635bd1204330913ec3026d1b8c725ebf27. I treated the PR body and ticket comments as claims to verify, not authority by themselves.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #10158 body, #10158 later Revised Contract Ledger comment, changed-file list, current
GraphServicesource, siblingai/scripts/maintenance/auditGraphIntegrity.mjs,package.jsonscript placement, KB query for Memory Core graph/healthcheck context, unit-test guide, and the PR review guide/template. - Expected Solution Shape: Correct implementation should expose cheap deployment-wide Memory/Session lifecycle telemetry without hardcoding it into
HealthService.healthcheck(), MCP OpenAPI schemas, or any always-loaded tool surface. It must not make theO(edges)incident-edge scan default behavior, and tests should isolate SQL/count/file-size/script wiring without needing a live production graph. - Patch Verdict: Matches the revised ledger.
GraphService.getLifecycleCensus({includeIncidentEdges})returns cheap node/file census by default, adds edge counts only when requested,graphLifecycleReport.mjsis an on-demand maintenance sibling toauditGraphIntegrity.mjs, and focused tests cover method semantics plus script parse/format/run behavior.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #10158
- Related Graph Nodes: #10143 residual AC4, #12595 superseded shape, Memory Core Native Edge Graph,
GraphService, Memory/Session provenance anchors
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
Challenge: The only residual risk is baseline capture: the live graph payload cannot be captured in this sandbox and remains an operator post-merge validation step. I checked the doc and PR body for overclaiming; both keep that live baseline as post-deploy work instead of pretending unit fixtures are production telemetry.
Rhetorical-Drift Audit (per guide §7.4):
- PR description: cost framing matches the mechanical diff; no healthcheck/OpenAPI/MCP surface is added.
- Anchor & Echo summaries:
GraphService#getLifecycleCensusand script JSDoc describe the concrete runtime/context cost and opt-in scan boundary. -
[RETROSPECTIVE]tag: no inflated tag in the PR body. - Linked anchors: #10158 contains the stale original ledger and the later revised ledger; the review relies on the later same-ticket ledger for current intent.
Findings: Pass.
🧠 Graph Ingestion Notes
[KB_GAP]: None found.[TOOLING_GAP]: None. Targeted unit verification and script smoke both passed locally.[RETROSPECTIVE]: Moving high-cost observability out of always-loaded MCP/healthcheck surfaces is the right substrate shape when the useful payload is operator-periodic rather than per-agent/per-call.
🎯 Close-Target Audit
- Close-targets identified: #10158 via newline-isolated
Resolves #10158in the PR body. - For each
#N: confirmed notepic-labeled.gh issue view 10158showsenhancement,ai,architecture,core; noepiclabel.
Findings: Pass.
📑 Contract Completeness Audit
- Originating ticket contains a Contract Ledger matrix. The body ledger is stale, and the same ticket has a later
Revised Contract Ledgercomment that explicitly supersedes the body shape. - Implemented PR diff matches the revised Contract Ledger exactly: method payload keys, deployment-wide counts, SQLite file-size semantics, unavailable fallback,
--edgesopt-in, on-demand script entrypoint, retention guide path, and unchanged out-of-scope pruning/archival boundaries.
Findings: Pass, with the explicit staleness note above. I am not treating the older body ledger as current because that would preserve stale ticket intent over the later verified same-ticket contract.
🪜 Evidence Audit
- PR body contains an
Evidence: L2declaration. - Achieved evidence matches the unit-coverable surface: method semantics, script argument/format/run wiring, and help smoke.
- Residual live baseline is listed under Post-Merge Validation, which is the correct boundary for production graph-store measurement.
- Review language does not promote unit fixtures to a live production baseline.
Findings: Pass.
N/A Audits — 📡
N/A across listed dimensions: no MCP OpenAPI/tool-description surface is modified; this PR deliberately avoids adding that always-loaded schema surface.
🔗 Cross-Skill Integration Audit
- No existing workflow skill needs a new trigger for this operator maintenance script.
- No
AGENTS_STARTUP.mdworkflow list update is needed. - The new convention is documented in
learn/agentos/measurements/MemorySessionGraphLifecycle.mdand exposed throughpackage.json. - No MCP tool documentation update is needed because no tool is added.
Findings: All checks pass — no integration gaps.
📜 Source-of-Authority Audit
Triggered because the PR and review discuss an operator-directed reshape. I did not use that attribution as proof of correctness; I verified the later same-ticket Revised Contract Ledger, the diff, focused tests, local smoke, and live CI state before approving.
🧪 Test-Execution & Location Audit
- Branch checked out locally via
checkout_pull_request. - Canonical Location: AI/right-hemisphere unit tests live under
test/playwright/unit/ai/...; the script test is undertest/playwright/unit/ai/scripts/maintenance/and service coverage remains undertest/playwright/unit/ai/services/memory-core/. - Ran changed related tests:
npm run test-unit -- test/playwright/unit/ai/services/memory-core/GraphService.spec.mjs test/playwright/unit/ai/scripts/maintenance/graphLifecycleReport.spec.mjs→ 33 passed. - Ran script smoke:
npm run ai:graph-lifecycle-report -- --help→ usage/options rendered. - Ran diff hygiene:
git diff --check origin/dev..HEAD→ clean. - Live CI at exact head
fcef41635bd1204330913ec3026d1b8c725ebf27:mergeStateStatus: CLEAN; lint-pr-body, CodeQL, MCP test-location lint, retired-primitives check, substrate size guard, integration-unified, tree-json lint, and unit all success.
Findings: Tests pass.
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 95 — 5 points deducted only because the method is a new publicGraphServicesurface where sibling precedent had avoided one; the revised ledger justifies it and the implementation keeps the contract minimal.[CONTENT_COMPLETENESS]: 94 — 6 points deducted because the original ticket body remains stale; the PR compensates with an explicit same-ticket revised ledger, PR delta explanation, JSDoc, and retention guide.[EXECUTION_QUALITY]: 97 — 3 points deducted for the unavoidable post-merge live-baseline dependency; code paths, fallback semantics, CLI wiring, and focused tests are clean.[PRODUCTIVITY]: 96 — 4 points deducted because baseline capture is intentionally deferred to the operator’s live store; otherwise the reshaped #10158 goals are delivered.[IMPACT]: 78 — significant Agent OS observability improvement with context-budget and hot-path protection, but not a new core runtime primitive.[COMPLEXITY]: 62 — moderate cross-surface change across service API, maintenance CLI, tests, package script, and policy doc, with no schema or MCP expansion.[EFFORT_PROFILE]: Heavy Lift — this is not large by LOC, but it corrects a wrong architectural surface while preserving measurable telemetry and retention-policy intent.
Approved. Human merge only; I am not executing gh pr merge.
Resolves #10158
Authored by Claude Opus 4.8 (Claude Code). Session 0f6d0fa0-327f-42ec-b970-e32f388699b4.
Operator-directed reshape of the Memory/Session graph-lifecycle telemetry. Supersedes #12595.
The original #10158 contract (and #12595) put the census in
HealthService.healthcheck()as an exportedbuildGraphLifecycleBlock+ agraphLifecycleblock on theHealthCheckResponseOpenAPI schema. @tobiu challenged that shape on cost; I benchmarked it, and two independent costs make it the wrong home:O(edges)on the hot path. The incident-edge count is a fullEdgesscan with a per-edgejson_extractnode lookup. Benchmarked against realbetter-sqlite3at the projected scale (50k nodes / 2.5M edges): node counts 15ms, incident-edge counts ~5.3s, and it grows linearly — at 20×-team / multi-repo scale it's minutes.healthcheckis a callable tool with no throttle; it can't carry that.ai/mcp/ToolService.mjs:145-146publishes each operation'soutputSchemaintoallToolsForListing, so thegraphLifecyclefields (~500 tokens) loaded into every agent's context at tool-enumeration, unconditionally — even agents that never call healthcheck, even on a tiny graph.The reshape
GraphService.getLifecycleCensus({includeIncidentEdges})— a method on the schema owner (reuses the live SQLite connection; no standalone service export, no healthcheck coupling). Default census =MEMORY/SESSIONnode counts + SQLite main/WAL/SHM file sizes (sub-second). TheO(edges)incident-edge counts are opt-in viaincludeIncidentEdges.ai/scripts/maintenance/graphLifecycleReport.mjs(npm:ai:graph-lifecycle-report) — thin on-demand entrypoint, sibling toauditGraphIntegrity.mjs.--edgesruns the slow scan;--jsonemits raw payload.learn/agentos/measurements/MemorySessionGraphLifecycle.md(telemetry section rewritten for the script; durable-anchor / archival-gate sections preserved).Evidence: L2 (focused unit tests for the census method + the script's parse/format/run logic, + a
--helpentrypoint smoke) → L2 required (the census shape is fully unit-coverable; the live-store baseline is an operator post-merge run). No blocking residuals.Deltas from ticket
GraphServicemethod + on-demand script after the cost benchmark. I'm posting the revised Contract Ledger as a comment on #10158.auditGraphIntegrity.mjs'slistGraphSessionsdeliberately readsgraphService.dbdirectly in the script "without adding a public service method before the report contract has empirical mileage." I flagged this; per operator direction the census is aGraphServicemethod, with the contract kept minimal (cheap default +--edgesopt-in) to mitigate the premature-contract risk that precedent guards against.O(edges)count is opt-in (--edges) so the default report stays cheap at 20× scale — the node counts + file sizes are the actual storage-growth signal.HealthService'sexport function buildXBlockhelpers as debt (a service is its singleton; module-level exports are the smell). Out of scope here; I'm filing a narrow tech-debt ticket for the conversion.Test Evidence
GraphService.spec.mjs—getLifecycleCensus: cheap default (node counts + real-temp-filesqliteBytes, edges omitted),--edgesopt-in incident counts, andavailable:falseon an unmounted store.graphLifecycleReport.spec.mjs—parseArgs(cheap default;--edges/--jsonopt-in),formatCensus(rendered fields + omitted-edge note + unavailable error),runReport(readiness→init→census order + JSON output).GraphService.spec+graphLifecycleReport.spec);--helpsmoke green; lint-staged + tree-json (195 nodes) clean.Post-Merge Validation
npm run ai:graph-lifecycle-report -- --jsonagainst the target Memory Core store; record it inlearn/agentos/measurements/MemorySessionGraphLifecycle.md.--edgescompletes acceptably on the real graph at current size (it isO(edges)by design).Decision Record impact
aligned-withthe substrate-accretion-defense principle — moves expensive, on-demand telemetry off the always-loaded MCP tool surface (net context-budget reduction) and off the healthcheck hot path.