npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@x12i/xmemory-scoper

v1.9.11

Published

Retrieval + orchestration layer: ScopedView and ScopePlan for xmemory

Readme

@x12i/xmemory-scoper

Retrieval + orchestration layer for xmemory: produces ScopedView (layered, deduplicated subgraph around a root Thing) and ScopePlan (question-driven plan for what to scope and how).

Distribution: public npm package @x12i/xmemory-scoper (registry).

What it does

  • Thing scoping (scopeThing): Given a seed Thing, returns a ScopedView with layered nodes/edges, optional record enrichment, and deduplication via equality canonicalization.
  • Question scoping (scopeQuestion): Given a question (text or id), finds or creates a question Thing, determines targets, builds a ScopePlan, and optionally executes it to produce ScopedView[].
  • Execution (executeScopePlan): Runs a ScopePlan against its targets and returns ScopedView[].

Question id vs text (live graph)

scopeQuestion accepts question: { text?: string; id?: string }:

  • Text only — creates or reuses a question Thing; id is generated if absent.
  • Id — looked up as xmemory:question:{id}. Id-only fails with QuestionNotFoundError if that Thing does not exist; id + text creates the Thing with that id when missing.

This is the question Thing identity used for planning, not the scoping-map id.

Reading a precomputed scoped answer

After scopeAbout / processThingTypeScopeViews have written scoped_views, getScopedAnswer returns the clean { question, answer } for one (scoping question × field/thing). There the question string is either the map’s questionTitle or the full xmemory:scopemap:v1:… id — see Reading scoped answers and docs/client-clean-scoped-information.md.

Scoper avoids duplication (equality canonicalization), applies filters and budgets, and enriches using mapper-produced mappings (schema/record/collection relations). It supports “depths of knowledge” (layers), not just graph depth. Typically you run the mapper first to populate mapping edges and Thing metadata; then use scoper to scope by Thing or question.

What it does not do

  • Does not build mapping. Scoper consumes mapping outputs from the mapper. It never creates schema/record nodes or mapping edges.

Dependencies

  • Required: xmemory-equal, xmemory-relations, nx-mongo
  • DB contract tier: @x12i/xmemory-contracts — shared logical DB names, collection names, index specs (applyIndexes / Indexes), join keys (Joins), and document-oriented types. Scripts resolve env via resolveXmemoryEnv (see scripts/lib/resolved-contract-env.ts) so operators and other packages can rely on the same protocol. The scoper package also re-exports Collections, Joins, DefaultLogicalNames, resolveXmemoryEnv, Indexes, applyIndexes, and SchemaVersions from the package root so dependents can align without a second import path (you may still depend on @x12i/xmemory-contracts directly for validation helpers such as validateDoc).
  • Tier (maps / corpus reads / scoped views): @x12i/xmemory-store — scripts and E2E use scripts/lib/xmemory-data-tier.ts (initXmemoryDataTier, tier.mongoClient, tier.storeBindings). The package depends on @xmemory/scoper as a peer (satisfied in this repo via @xmemory/scoper: file:. pointing at the published @x12i/xmemory-scoper API).
  • Catalox (catalog / Firestore): @x12i/catalox ^3.5.0 — catalog init, simulate/apply, and reports (npm run catalog:xmemory:*, report:catalox:*). Matches the @x12i/funcx peer range >=3.4.0 <4.
  • Optional: nx-ai-api (LLM planning / relevance / summarization)
  • LLM + script diagnostics: @x12i/funcx (e.g. match() in npm run report:coverage) and @x12i/logxer via createScoperLogxer() (structured JSON; gated env — see Logging). logs-gateway is not a direct dependency of this package.

Scoper does not create Mongo clients directly; it uses the nx-mongo provider you pass in and the NxMongoClient you pass in (often tier.mongoClient from the store). Install may require npm install --legacy-peer-deps when peers disagree until the store’s peer is repointed to @x12i/xmemory-scoper.

Logging

By default @x12i/xmemory-scoper only emits error logs from its shared createScoperLogxer() helper (used by coverage reporting and available from the package root).

To enable richer local logs (debug / info / warn) set:

ENABLE_XMEMORY_SCOPER_LOGXER=true
XMEMORY_SCOPER_LOGS_LEVEL=debug

If ENABLE_XMEMORY_SCOPER_LOGXER is not exactly true (case-insensitive), the effective level stays error regardless of level variables. When rich logging is on, level is read from XMEMORY_SCOPER_LOGS_LEVEL, then legacy XMEMORY_SCOPER_LOG_LEVEL if unset; the default when both are unset is warn. Set XMEMORY_SCOPER_LOGS_LEVEL=off to suppress package log output while the enable flag remains on.

Use scoperConsole from the package root for ad-hoc console lines that follow the same gating.

Scope metadata

Scoper relies on metadata.db and metadata.collection on Things for scope filtering and record enrichment. These are written by the mapper and used by scoper for scope-aware traversal and enrichment.

Known limitation

Single (db, collection) per Thing only. Multi-db or cross-cluster scope is not representable in v1.

Budgets and caps (defaults)

| Option | Default | |-----------|--------| | maxNodes | 200 | | maxEdges | 500 | | maxRecords| 100 | | maxDepth | 2 | | maxTokens | 600 (LLM) |

LLM (optional, bounded)

When nx-ai-api is provided and llm.enabled is true, scoper can use the LLM for:

  • Question planning (planFromQuestion): Infer targets and layer suggestions from question text.
  • Relevance filter / Layer summary: Optional per-layer; v1 keeps these bounded (capped nodes/edges, maxTokens).

Safety: full records are not sent to the LLM by default; token budgets are enforced.

AI templates visibility

AI prompts and rules used by scoper flows are kept as human-editable markdown under ai-templates/ (not buried inline in prose):

  • ai-templates/question-plan-system-prompt.v1.md — system prompt for scoping-map question planning. npm run build embeds this file into dist/ via codegen so the published package does not depend on shipping ai-templates/ at runtime.
  • ai-templates/alternatives-by-field-prompt.v1.md - optional prompt for catalog-style field suggestions; scoping coverage uses match() instead (see npm run report:coverage).
  • ai-templates/link-improvement-hints.v1.md - prompt template used for AI link hypothesis suggestions.
  • ai-templates/required-item-property-match.v1.md - legacy placeholder; coverage reporting uses match() from @x12i/funcx/functions for indexed candidate matching (see scripts/report-scoping-coverage-with-alternatives.ts).

You can review/edit the markdown in-repo; regenerate the embedded question-plan string with npm run codegen:prompts (or npm run build).

Scoping coverage report — default input is docs/scoping-required.md (override with SCOPING_REQUIRED_DOC). Runs match() + optional evaluateRequirementGate, Mongo updates, and docs/reports/scoping-coverage-report.*: npm run report:coverage (tsx scripts/report-scoping-coverage-with-alternatives.ts). See docs/reports/ai-only-scoping-handoff.md.

Data-level scoped answers (x-scoped-data)

xmemory-op.x-scoped-data holds the answers to all scoping-map questions applied to every real record in x-snapshots. Each document = one (snapshot × scoping question) pair with actual field values, not schema descriptions.

Shape:

{
  "_meta": {
    "scopedAt":    "2026-04-05T08:34:07.052Z",
    "scopingMapId":"xmemory:scopemap:v1:...",
    "question":    "What data do we need to determine whether this vulnerability is actually applicable to this affected asset?",
    "entityType":  "vulnerability",
    "entityId":    "PLUGIN-160208",
    "source":      { "database": "poc-data-mapping", "collection": "vulnerabilities-rawdata" },
    "snapshotId":  "...",
    "sourceId":    "69155ce7..."
  },
  "question": "What data do we need...",
  "answer": {
    "vulnerability identifiers": {
      "value":       "PLUGIN-160208",
      "fieldPath":   "vulnerabilityId",
      "description": "Identifies the specific plugin/CVE check that flagged this finding.",
      "reasoning":   "Direct vulnerability identifier linking findings to a vulnerability definition."
    },
    "attack vector": {
      "value":       "Found 5 attack path(s) from 5 external source(s)…",
      "fieldPath":   "storyText.exploitabilityPaths",
      "description": "Narrative text describing the discovered exploitability/attack paths…",
      "reasoning":   "Direct evidence of attack path/exposure via exploitability paths."
    },
    "finding state": {
      "value":     false,
      "fieldPath": "assetMatched",
      "reasoning": "Direct indication of whether the vulnerability finding matched an asset."
    }
  }
}

By default, build-x-scoped-data uses sparse answers: requirement keys with missing diagnostics or no meaningful value in that snapshot are omitted from answer (set SCOPED_DATA_INCLUDE_EMPTY=1 to list every line with value: null for gaps, legacy style).

Graph entry / Memorix entity ids: Studio “current records” strips that pick memorix-entities families (for example subnets) must map to the singular _meta.entityType (subnet) for x-scoped-data queries. Use resolveGraphEntryMemorixEntityContext, countGraphEntryMemorixEntityRecords, and sampleGraphEntryMemorixEntityRecords from the package root; full contract is in docs/graph-entry-memorix-entity-bridge.md.

Subnet maps (XMSM): Stable questionId and expected answer keys for subnet reachability and exploit-impact are documented in docs/scoping-registry-integrators.md. For subnets-rawdata, getScopedDataFromSnapshot tries SUBNET_RAWDATA_SCOPED_DATA_FALLBACK_PATHS (exported from the package) when requiredDiagnostics.evidenceFieldPaths do not resolve to a value, so registry-aligned labels like reachabilityPaths, impactSummary, etc. can still populate from common alternate JSON shapes. Evidence paths from the map always take precedence.

Coverage (76,083 records total):

| Scoping question subject | Entity type | Snapshots processed | Maps applied | |--------------------------|----------------|---------------------|--------------| | vulnerability questions | vulnerability| 15,833 | 3 | | asset questions | asset | 7,095 | 4 | | subnet questions | subnet | 68 | 3-4 |

Build / refresh:

npm run build:scoped-data

The same run also refreshes x-scoped-question-stats (one doc per scoping map: scopingMap = meta row, materializedFrom = which snapshot corpus the question builds from, then numeric stats and issues) so it stays aligned with x-scoped-data. Set SKIP_SCOPED_QUESTION_STATS_REFRESH=1 only if you need to skip that step.

Catalox (meta-only discovery catalogs): Catalog payloads are built only from the meta database (scoping_maps and a configurable things collection). Nothing from the operational DB (for example scoped_views or x-scoped-data) is written into Catalox. The default Catalox app id is xmemory (CATALOX_APP_ID overrides).

If Catalox data lives in a named Firestore database (often catalox), set FIRESTORE_DATABASE_ID=catalox so apply and reports target the same database as your Catalox UIs (scripts/lib/get-catalox-firestore.ts). Omit it for the project default database.

Go-live checklist: docs/reports/catalox-go-live-runbook.md.

Catalox init (Firebase only, no Mongo): npm run catalog:xmemory:init-catalox — creates apps/xmemory, both native catalog shells (bindings + descriptors + index), on each Catalox Firestore environment. Run when the project id is configured but catalogs/app were never provisioned.

After init — publish meta from Mongo: npm run catalog:xmemory:sync (simulate + apply), or sync:prune with prune on apply. Then npm run catalog:xmemory:verify-all.

One-shot provision (init → sync → verify-all): npm run catalog:xmemory:provision — or provision:prune. Requires Mongo + Firebase env as in the runbook. Uses @x12i/catalox ^3.5 (createCataloxFromFirestore wires CatalogDataIndexStore).

Recommended pipeline (simulate → review → apply):

  1. npm run catalog:xmemory:simulate — reads meta tier, prints a markdown report, optional --out report.md and --json-summary summary.json. No Firestore writes. Requires a reachable MONGO_URI. If you only need the report shape without a cluster, npm run catalog:xmemory:simulate:offline writes docs/reports/xmemory-catalog-simulate.OFFLINE.{md,json} (empty inventory mock).

  2. After you approve the report, npm run catalog:xmemory:apply with Firebase ADC / GOOGLE_APPLICATION_CREDENTIALS. Optional --prune removes catalog items that are no longer in the simulated set. See scripts/catalog-xmemory.ts and env vars in .env.example (CATALOG_THINGS_*, CATALOX_ENTITY_CATALOG_ID, etc.).

  3. npm run report:catalox:firestore — read-only markdown table of Catalox-related Firestore collection counts (apps, bindings, catalogs, catalogData/*/items, etc.). Optional --out path.md. Project id resolution matches apply: see scripts/lib/resolve-firebase-project-id.ts (GOOGLE_CLOUD_PROJECT, project_id in service-account JSON under GOOGLE_APPLICATION_CREDENTIALS / .secrets/, FIREBASE_CONFIG, .firebaserc default project).

  4. npm run report:catalox:app-parity — app × catalog matrix (bindings, descriptors, catalogDefinitions, item counts); optional --worox-defaults for Worox catalog ids. See docs/reports/catalox-xmemory-publish-surface.md.

  5. npm run catalog:catalox:verify-list-non-god — optional; calls listCatalogItems with isGodMode: false to confirm production-style reads work for the xmemory catalogs.

Questions-only (legacy CLI): npm run catalog:publish:scoping-questions -- --dry-run or npm run catalog:publish:scoping-questions:apply — meta scoping_maps only; see scripts/catalox-publish-scoping-inventory.ts.

Programmatic API: simulateXmemoryCatalogPublish / applyXmemoryCatalogPublish in the package exports (and catalox-bridge).

After changing docs/scoping-required.md (for example adding subnet registry lines or the exploit-impact question), run your map preparation pipeline (e.g. prepare-all-scoping-maps) so xmemory-meta.scoping_maps picks up new requiredDiagnostics before relying on new x-scoped-data keys.

Safe to re-run — upserts on (_meta.scopingMapId, _meta.sourceId). Use env overrides to scope the run:

# Only one scoping map
X_SCOPED_DATA_MAP_ID=xmemory:scopemap:v1:... npm run build:scoped-data

# Limit snapshots per map (useful for testing)
X_SCOPED_DATA_LIMIT=100 npm run build:scoped-data

Performance: all field metadata (258 fields) is loaded into memory once at startup via a single bulk query. Records are processed in-memory and written in batches of 500. Full build of 76k records takes ~40 seconds.

Indexes (created automatically):

  • (_meta.scopingMapId, _meta.sourceId) (unique — upsert key)
  • _meta.entityType
  • _meta.entityId
  • _meta.source.collection
  • _meta.scopedAt (descending)

Script: scripts/build-x-scoped-data.ts
Prerequisite: x-snapshots must exist — run npm run build:snapshots first.
Env: MONGO_XMEMORY_META_DB (default xmemory-meta), MONGO_XMEMORY_OPERATIONAL_DB (default xmemory-op)

Reading scoped answers (client API)

Once views have been precomputed (scopeAbout / processThingTypeScopeViews), use getScopedAnswer to retrieve the clean answer to a scoping question for a specific field or thing:

import { getScopedAnswer } from "@x12i/xmemory-scoper";

const result = await getScopedAnswer(nx, {
  opDb:       "xmemory-op",    // database holding scoped_views
  metadataDb: "xmemory-meta",  // database holding xmemory_things

  // question — human-readable title or "xmemory:scopemap:v1:..." id
  question: "What data do we need to determine whether this vulnerability is actually applicable to this affected asset?",

  // about — refRaw field path, externalIdentifier, or 24-char hex aboutThingId
  about: "assets-rawdata.xdr.host_name",
});

Returns { question, answer } — or null when no fresh view exists:

{
  "question": "What data do we need to determine whether this vulnerability is actually applicable to this affected asset?",
  "answer": {
    "Host name": {
      "description": "The XDR-reported hostname of the endpoint, used as a human-readable device identifier for triage and correlation.",
      "samples": ["BGAK105-002", "CUB10715", "N00014034"]
    },
    "Has Vulnerabilities": {
      "description": "Boolean flag indicating whether the asset has any known vulnerabilities, used to separate clean hosts from those needing remediation.",
      "samples": ["false", "true"]
    }
  }
}

answer keys are human display names. Each value has description (what the field means and how it behaves in practice) and optionally samples (real values from the collection). No ids, timestamps, schema versions, graph structure, or traversal mechanics.

See docs/client-clean-scoped-information.md for the lower-level building blocks (fetchCleanScopedKnowledge, toScopedAnswer, pickScopedViewFromCacheDoc).

Data snapshots (x-snapshots)

xmemory-op.x-snapshots holds a full, clean copy of every record from the source database (poc-data-mapping). Each document is a two-part envelope:

_snapshot   ← provenance header (capturedAt, source, entityType, entityId …)
data        ← the complete source record, all fields, nothing removed

Shape:

{
  "_snapshot": {
    "capturedAt":  "2026-04-05T08:01:15.511Z",
    "source": { "database": "poc-data-mapping", "collection": "vulnerabilities-rawdata", "server": "default" },
    "entityType":  "vulnerability",
    "entityId":    "PLUGIN-160208",
    "idField":     "vulnerabilityId",
    "sourceId":    "69155ce7..."
  },
  "data": {
    "assetId":      "host:10.100.18.64",
    "assetIp":      "10.100.18.64",
    "pluginName":   "WSO2 Multiple Products File Upload RCE (CVE-2022-29464)",
    "severity":     "4",
    "enrichment":   { ... },
    "mitreAnalysis":{ ... }
  }
}

Current coverage (23,512 snapshots):

| entityType | Source collection | Count | |----------------------|------------------------------------|--------| | vulnerability | vulnerabilities-rawdata | 15,833 | | vulnerability-group| vulnerabilities-groups-rawdata | 516 | | asset | assets-rawdata | 7,095 | | subnet | subnets-rawdata | 68 |

Build / refresh snapshots:

npm run build:snapshots

Safe to re-run at any time — upserts on the stable _snapshot.sourceId key so no duplicates are created. Use X_SNAPSHOTS_COLLECTIONS to refresh only one collection:

X_SNAPSHOTS_COLLECTIONS=assets-rawdata npm run build:snapshots

Indexes (created automatically):

  • _snapshot.sourceId (unique — upsert key)
  • _snapshot.source.collection
  • _snapshot.entityType
  • _snapshot.entityId
  • _snapshot.capturedAt (descending)

Script: scripts/build-x-snapshots.ts
Env: MONGO_SOURCE_DB (default poc-data-mapping), MONGO_XMEMORY_OPERATIONAL_DB (default xmemory-op)

Things corpus repair (E11000 on uniq_things_ns_thingType_kind_refNorm)

If xmemory-equal’s ensureIndexes() fails with a duplicate key on { namespace, thingType, kind, refNorm }, the usual cause is legacy rows with null/missing key fields in xmemory_things, not bad env resolution. @x12i/xmemory-store (≥ 1.1.5) includes fix-bad-things-docs (dry-run by default; quarantine on apply).

From this repo (loads .env first):

npm run data-tier:fix-things-docs:dry-run
npm run data-tier:fix-things-docs:apply

Pass extra CLI flags after --, e.g. another database: npm run data-tier:fix-things-docs -- --things-db xmemory-op --layout auto.

Details: docs/xmemory-store-tier-bug-cr-assessment.md (Issue B).

Scoper API (summary)

createScoper({ nxMongo, xEqual, xRelations, ai? })

scopeThing(input: ScopeThingInput): Promise<ScopedView>
scopeThingLayer(input: ScopeThingInput & { depth: number }): Promise<ScopedView>
scopeQuestion(input: ScopeQuestionInput): Promise<{ plan: ScopePlan; views?: ScopedView[] }>
executeScopePlan(plan: ScopePlan, options?: ExecutePlanOptions): Promise<ScopedView[]>
prepareScopingMap(input: PrepareScopingMapInput): Promise<ScopingMap>
scopeAbout(input: ScopeAboutInput): Promise<{ scopingMap: ScopingMap; view: ScopedView; cache?: ScopedAboutCache }>
processThingTypeScopeViews(input: ProcessThingTypeScopeViewsInput): Promise<{ totalCandidates: number; processed: string[]; skippedFresh: string[]; failed: Array<{ thingId: string; error: string }> }>

Inputs use namespace and seed (thingId / externalIdentifier / thingRef). Outputs conform to JSON schemas xmemory.scoper.scopeplan.v1 and xmemory.scoper.scopedview.v1.

Scoping map flow

Scoper supports a 2-stage flow for deterministic scoping requests:

  1. Preparation stage (prepareScopingMap)
    • Input: questionTitle (display/title only), requiredScopingData[], and metadata store (database, optional collection, default scoping_maps).
    • It normalizes/sorts/deduplicates required data and builds a stable key:
      • xmemory:scopemap:v1:<sha256>
    • It stores the generated scoping map in metadata DB for reuse.
  2. Runtime stage (scopeAbout)
    • Input: an about seed plus either:
      • scopingMapId, or
      • questionTitle + requiredScopingData[] (id recomputed deterministically).
    • It loads the map and scopes data around the required about thing.

This lets you prepare once and reuse many times, while still allowing runtime fallback creation when question + required data are provided and map is missing.

Optional runtime cache/debug record

scopeAbout can optionally persist a full cache/debug payload (scopingMap + view) into a dedicated collection (default scoped_views) using:

  • key: (aboutThingId, scopingMapId) (single latest record)
  • status on scoped view cache: fresh or failed
  • staleness marker: aboutThingUpdatedAtAtScopeTime
  • optional per-record TTL via persistCache.ttlSeconds (expiresAt + TTL index)

When persisted, Scoper also writes a Thing metadata marker under:

  • metadata.scoping.views[scopingMapId] = { cachedAt, cacheDb, cacheCollection, lastThingUpdatedAtSeen }

Coverage processor by type

processThingTypeScopeViews scans Things by namespace + thingType and ensures scoped views exist and are fresh:

  • missing cache record → process
  • stale cache record (thing.updatedAt > aboutThingUpdatedAtAtScopeTime) → process
  • fresh cache record → skip

This is designed for relation-heavy environments where full scoped views should be precomputed for many Things and easy to inspect during debugging.

Scoping maps also carry status:

  • ready when map creation/build succeeded
  • failed when map creation failed and error details are persisted

Adapters

Use the provided adapters to wrap real clients:

  • createEqualAdapter(equalClient)XEqualClient
  • createRelationsAdapter(relationsClient, { getThingById })XRelationsClient
  • createNxMongoAdapter(nxMongoProvider)NxMongoClient
  • createAiAdapter(nxAiApiClient)NxAiApiClient

Then pass them into createScoper(deps).

Publishing (npm, public)

This package is @x12i/xmemory-scoper. package.jsonpublishConfig targets https://registry.npmjs.org with access: "public" (required once per scoped package on the public registry).

Some documentation or mirrors may still say @xronoces/xmemory-scoper; the canonical install and import path is @x12i/xmemory-scoper (see docs/graph-entry-memorix-entity-bridge.md).

Publish (maintainers): log in to npm (npm login) or use a NPM_TOKEN with publish rights for the @x12i scope in your user ~/.npmrc (do not commit tokens into the repo).

npm run build   # also runs via prepublishOnly before publish
npm publish     # uses publishConfig; first publish must allow public scoped access (already set)

Install in another project:

npm install @x12i/xmemory-scoper

Test data

  • Mongo troubleshooting spec (transport vs auth vs helper, diagnostics contract): docs/mongo-data-tier-troubleshooting-spec.md.

  • npm run test runs unit and integration tests only (test/e2e/** is excluded so CI and laptops without a healthy shared Mongo stay green). This includes checks that docs/scoping-required.md still contains the subnet XMSM lines and getScopedDataFromSnapshot fallback behavior for subnets-rawdata.

  • npm run test:e2e runs test/e2e/**/*.test.ts (real Mongo: acceptance + data-tier contract). E2E loads scripts/load-env.ts, which uses nx-config2 (loadDotenv) from the package root .env. If MONGO_URI / MONGO_CONNECTION_STRING appear in .env, those values are applied after load (so they override a preset MONGO_URI from the IDE shell). Set XMEMORY_SCOPER_PREFER_SHELL_MONGO=1 if you need the opposite. XMEMORY_SCOPER_DEBUG_ENV=1 logs env resolution to stderr. E2E requires a URI when running those files; there is no implicit fallback. Acceptance tests run runMongoDiagnostics from scripts/lib/mongo-diagnostics.ts (softTcp: true). If xmemory_things hits E11000 on uniq_things_header_refNorm, run npm run data-tier:fix-things-docs:dry-run (then :apply) or use a clean database — the acceptance file fails fast with that guidance. npm run report:coverage uses the same preflight before opening Mongo. XMEMORY_SCOPER_DIAG_RUNTIME=1 prints pid, cwd, Node path, Docker/WSL hints, and interfaces at the start of diagnostics; any failure also appends that snapshot.

  • npm run mongo:ping — standalone MongoClient + admin ping (same .env as tests; no Vitest / nx-mongo). Use it to see whether Node can reach Mongo outside the test harness; if results differ from Compass, compare where each runs (terminal vs IDE task, Docker, WSL).

  • To get a persistent test database with real Things and a sample relation (so you can inspect it in Compass or mongosh), run:

    npm run seed:testdb

    The script loads .env the same way and requires MONGO_URI or MONGO_CONNECTION_STRING (no default URI). If MONGO_XMEMORY_DB is set, that database name overrides the path in the URI. It creates a root Thing, a neighbor Thing, one record-relation edge, and a sample document in testdb.testcoll. MongoDB must be reachable at the URI you configure.