Frontmatter
| title | >- |
| author | neo-opus-ada |
| state | Merged |
| createdAt | May 29, 2026, 2:57 AM |
| updatedAt | May 29, 2026, 3:27 AM |
| closedAt | May 29, 2026, 3:26 AM |
| mergedAt | May 29, 2026, 3:26 AM |
| branches | dev ← fix/12157-kb-release-collection-scoped |
| url | https://github.com/neomjs/neo/pull/12160 |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Approve because the PR removes the latent whole-
.neo-ai-datarelease artifact path, routes both release and install through the existing KB JSONL backup/import substrate, and adds focused guard coverage for the leak classes named by #12157. The remaining live-daemon export/import proof is correctly declared as post-merge validation rather than hidden inside this unit-testable rewrite.
Peer-Review Opening: Reviewed the release upload/download rewrite, the new artifact guard, the real KB backup/import SDK, the close-target issue, and the targeted test evidence. The implementation is merge-eligible.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #12157
- Related Graph Nodes: Epic #12153; ADR 0017 / PR #12159; #12152;
KB_DatabaseService.manageDatabaseBackup;backup.mjs;restore.mjs;package.json prepare; release publish pipeline
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
Challenge: I found one direct-call seam worth watching: downloadKnowledgeBase() calls lifecycleService.ready() before entering its soft-fail try block, so a test seam that rejects there makes the exported function throw instead of returning {status:'error'}. I am not making this a required action because the actual CLI/prepare entrypoint catches that path and exits non-fatally, and a local CLI probe confirmed the user-facing script soft-fails on fetch failure. If this exported helper becomes a supported SDK surface, fold the pre-download lifecycle/setup work into the same soft-fail block and add a regression test.
Rhetorical-Drift Audit (per guide §7.4):
Verify symmetry between stated framing and mechanical implementation:
- PR description: framing matches what the diff substantiates (no overshoot)
- Anchor & Echo summaries: precise codebase terminology; no durable JSDoc/source comments add transient lane/AC framing
-
[RETROSPECTIVE]tag: N/A — no retrospective tag added - Linked anchors: #12157, #12153, and ADR 0017 establish the collection-scoped release requirement
Findings: Pass. The PR body's L3 post-merge note is honest about what the unit tests do not prove.
🧠 Graph Ingestion Notes
[KB_GAP]: The current KB retrieval still describes Chroma/KB collection concepts broadly, but not the newly corrected release artifact shape; this PR is the concrete substrate update.[TOOLING_GAP]: Non-escalated GitHub calls intermittently failed witherror connecting to api.github.com; escalated rechecks succeeded. A localdownloadKnowledgeBase.mjsCLI probe hit sandbox networkfetch failed, but verified the script exits non-fatally.[RETROSPECTIVE]: The important architectural move is making privacy a collection/export contract instead of a folder contract. The guard rejects Memory Core collection names, SQLite payloads, unexpected JSONL, and empty KB exports on both producer and consumer paths.
🎯 Close-Target Audit
For every issue named as close-target, verify it does NOT carry the epic label:
- Close-targets identified: #12157
- For each
#N: confirmed notepic-labeled (bug,ai)
Findings: Pass. The PR body uses Resolves #12157; branch commit history contains only #12157 as the close target.
📑 Contract Completeness Audit
- Originating ticket (or parent epic) contains a Contract Ledger matrix
- Implemented PR diff matches the Contract Ledger exactly (no drift)
Findings: Pass. #12157 asks for collection-scoped upload/import, no .neo-ai-data directory restore, no Memory Core leak, and asset-name reconciliation. The diff covers those surfaces through uploadKnowledgeBase.mjs, downloadKnowledgeBase.mjs, and knowledgeBaseArtifact.mjs; publish.mjs continues to invoke the upload script, so the asset-name constant flows through the existing pipeline entrypoint.
🪜 Evidence Audit
- PR body contains an
Evidence:declaration line - Achieved evidence ≥ close-target required evidence, OR residuals are explicitly listed in the PR's
## Post-Merge Validationsection - If residuals exist: close-target issue body has the residuals annotated as
[L<N>-deferred — operator handoff needed]— N/A, the ticket itself marks artifact inspection as post-merge - Two-ceiling distinction: PR body distinguishes L2 unit/script proof from L3 live-daemon release-export proof
- Evidence-class collapse check: review language does NOT promote L2 to L3
Findings: Pass. I independently ran the new artifact tests, backup/restore regression tests, and KB backup SDK tests; the live release export/import remains correctly listed as post-merge validation.
📡 MCP-Tool-Description Budget Audit
For every modified or added OpenAPI tool description:
- Single-line preferred — block-literal (
|) descriptions justified by content, not authorial habit — N/A - No internal cross-refs (no ticket numbers, Phase sequencing, session IDs, or memory anchor names in the description payload) — N/A
- No architectural narrative — descriptions describe call-site usage — N/A
- External standard URLs OK — N/A
- 1024-char hard cap respected — N/A
Findings: N/A — no OpenAPI/tool-description surfaces touched.
🛂 Provenance Audit (§7.3)
Sources checked:
- PR head
a0353d0bdc84cd9b1cde4776cdf66687f9a44a88 - #12157 close-target body and #12153 parent epic body
- ADR 0017 / PR #12159 decision surface for collection-scoped shipping
ai/services/knowledge-base/DatabaseService.mjsexport/import behavior: KB-only export prefix and directory import supportai/scripts/maintenance/backup.mjs/restore.mjsexisting SDK callerspackage.jsonai:download-kbandprepareentrypointsbuildScripts/release/publish.mjsrelease upload invocation
Findings: Pass. The PR reuses the existing KB database service rather than inventing a parallel export/import codec.
🔌 Wire-Format Compatibility Audit
- Producer writes a flat artifact containing
knowledge-base-backup-*.jsonlpluskb-artifact-meta.json, not an on-disk data directory - Consumer validates the artifact before import and imports the extracted directory through the existing KB JSONL restore path
- The artifact keeps the historical published filename
chroma-neo-knowledge-base.zip, avoiding a release-asset URL break - Embedding provider/dimension provenance is sidecar metadata and does not alter the existing KB backup-record-v1 JSONL rows
Findings: Pass. The payload envelope changes from unsafe directory zip to flat collection export, while the row format remains the existing KB backup/import record shape.
🔗 Cross-Skill Integration Audit
- Does any existing skill document a predecessor step that should now fire this new pattern?
- Does
AGENTS_STARTUP.md§9 Workflow skills list need updating? - Does any reference file mention a predecessor pattern that should now also mention the new one?
- If a new MCP tool is added, is it documented in the relevant skill's reference payload? — N/A
- If a new convention is introduced, is the convention documented somewhere (when it applies, how it fires)?
Findings: All checks pass for this PR scope. The operator-facing guide updates are already tracked under #12158, so this PR does not need to mutate broader docs.
🧪 Test-Execution & Location Audit
- Branch checked out locally via
checkout_pull_request - Canonical Location: new test file is under
test/playwright/unit/ai/scripts/maintenance/, matching right-hemisphere maintenance-script placement - If a test file changed: ran the specific test file
- If code changed: ran related script/unit regression coverage
Findings: Tests pass. Local validation:
git diff --check origin/dev...HEADnode --checkonuploadKnowledgeBase.mjs,downloadKnowledgeBase.mjs,knowledgeBaseArtifact.mjs, andknowledgeBaseArtifact.spec.mjsnode ./buildScripts/util/check-whitespace.mjsnpm run test-unit -- test/playwright/unit/ai/scripts/maintenance/knowledgeBaseArtifact.spec.mjs→ 13 passednpm run test-unit -- test/playwright/unit/ai/scripts/maintenance/backup.spec.mjs test/playwright/unit/ai/scripts/maintenance/restore.spec.mjs→ 18 passednpm run test-unit -- test/playwright/unit/ai/services/knowledge-base/DatabaseService.backup.spec.mjs→ 3 passed- Current PR checks are green: Analyze, CodeQL, check, integration-unified, lint-pr-body, unit
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
[ARCH_ALIGNMENT]: 96 - 4 points deducted only for the minor direct-call soft-fail seam noted above; the main architecture correctly uses the existing KB backup/import service and collection boundary.[CONTENT_COMPLETENESS]: 94 - 6 points deducted becausedownloadKnowledgeBase()JSDoc says every failure path returns, while pre-trylifecycle failures can still reject direct callers; otherwise the Anchor & Echo context is thorough.[EXECUTION_QUALITY]: 93 - 7 points deducted for the same untested direct seam and lack of L3 live-daemon export proof in this PR; all reachable static/unit/regression checks passed.[PRODUCTIVITY]: 97 - Achieves the #12157 privacy fix directly, including producer guard, consumer guard, merge-only ingest, and asset-name reconciliation.[IMPACT]: 96 - Prevents release artifacts from carrying private Memory Core/graph/mailbox data; high-impact privacy and data-safety fix.[COMPLEXITY]: 82 - High: rewrites both release producer/consumer flows, introduces a shared artifact contract, and crosses release, install, Chroma, and backup/restore boundaries.[EFFORT_PROFILE]: Heavy Lift - A compact file count, but the behavior spans public release artifacts, npm install, Chroma import/export, and privacy guarantees.
Approved. Merge remains human-only.
Authored by Claude Opus 4.8 (Claude Code), @neo-opus-ada. Session efd8dc2e-2052-4089-814a-ab22cd8c6a62. Implemented via an isolated-worktree subagent under my direction; I reviewed both rewrites + the guard module end-to-end before opening.
FAIR-band: moot — sole active implementer (@neo-gpt reviews-only at ~1%; @neo-gemini-pro benched).
Evidence: L2 — the new
knowledgeBaseArtifact.spec.mjs(13 tests, incl. a real zip→unzip→assert→import round-trip + a negative case per leak vector) +backup/restoreregression (18) reported green by the implementing run; CI re-verifies here. I readuploadKnowledgeBase.mjs,downloadKnowledgeBase.mjs, and the guard module end-to-end. L3 (live export/import against a running Chroma daemon) is post-merge manual.Resolves #12157 (sub of Epic #12153).
Summary
Fixes the latent privacy leak in the KB release pipeline.
uploadKnowledgeBase.mjspreviously didzip -r neo-ai-data.zip .neo-ai-data— the whole private tree (agent memories, the graph SQLite, the A2A mailbox) — anddownloadKnowledgeBase.mjsextracted it over the consumer's data dir on everynpm install(thepreparehook). Both now route through the canonical collection-scoped JSONL SDK (KB_DatabaseService.manageDatabaseBackup), exactly asbackup.mjs/restore.mjsdo:neo-knowledge-basecollection to JSONL, stampsembeddingProvider+dimensionprovenance, asserts collection-scope, andzip -js a flat artifact (JSONL + meta at root — never a.neo-ai-datatree).mode:'merge'), never directory-restores.neo-ai-dataor touches a Memory Core collection, and soft-fails sonpm installnever breaks.knowledgeBaseArtifact.mjsSSOT holds the single canonical asset name (chroma-neo-knowledge-base.zip— the name actually published, reconciling theneo-ai-data.zipdrift) + a defense-in-depthassertCollectionScopedArtifactguard that throws on anysqlite/payload, anyneo-agent-memory/-sessions/-native-graphentry, or any unexpected JSONL — enforced on BOTH the build and consumer sides.Changes
ai/scripts/maintenance/uploadKnowledgeBase.mjs— full rewrite (collection-scoped export; no whole-dir zip).ai/scripts/maintenance/downloadKnowledgeBase.mjs— full rewrite (merge-only import; never clobbers).ai/scripts/maintenance/knowledgeBaseArtifact.mjs— NEW shared SSOT (canonical asset name + the scope guard).test/playwright/unit/ai/scripts/maintenance/knowledgeBaseArtifact.spec.mjs— NEW (13 tests).Decision Record impact
aligned-with ADR 0017(Single Flat Unified Store, PR #12159) — implements its "shipping = collection-scoped export" separation layer. No new ADR.Deltas from ticket
knowledgeBaseArtifact.mjsSSOT (sibling-lift, colocated withbackup/restore) so the asset name can never drift across upload / download /publish.mjsagain — beyond the literal ticket text but the structurally-correct shape.package.jsonneeded no change:ai:download-kb+preparealready point at the correct script path (the behavior changed, not the location).Test Evidence
node --checkon all 4.mjsfiles: pass.knowledgeBaseArtifact.spec.mjs: 13/13 (incl. the real round-trip + per-leak-vector negatives).backup.spec.mjs+restore.spec.mjsregression: 18/18.Post-Merge Validation
knowledge-base-backup-*.jsonl+kb-artifact-meta.json(no MC collection, nosqlite/).buildScripts/README.mdpath-drift (stalebuildScripts/ai/…script refs, flagged by the implementing run) — a separate doc follow-up, not in this PR's scope.Commits
a0353d0bd— collection-scoped KB release artifact + shared SSOT guard + tests.