memory_ingest
Capture memories with mandatory source and anchor provenance. Supports single items or batches, deduplicates by content hash, and flags tainted content.
Instructions
Capture memories with MANDATORY provenance (source + anchor). One item object, or a batch as {"items":[...]} — never both forms in one payload. A shape-broken batch item becomes its OWN rejected row plus the full contract; the good siblings still capture — schema-bad and semantically-bad items behave identically per-item, and every batch rejection row speaks ONE grammar: itemsN: ingest rejected: (the index always leads, the field path appears when a wrong-typed field is named, exactly one prefix; single-form SEMANTIC rejections carry the same prefix without the items[N] locator — a single-form SHAPE-broken payload (unknown/missing field, wrong type, invalid kind) is a DESERIALIZE-stage fault and surfaces IN-BAND as an isError result with plain serde text (rmcp 2.2.0 routes shape faults there, not to a protocol error; q88)). Idempotent by content hash: re-ingesting identical content collapses onto the existing capsule (per-item status "deduplicated"; fresh appends report "captured"; both statuses share one row shape). Smart defaults fill confidence (0.6), valid_from (now), project, authority_class (agent-inferred). When the server was booted without an explicit project (--project/NMEMORY_PROJECT absent), the default project derives at capture time from the connected client's clientInfo.name, sanitized to a slug (lowercase ASCII alphanumerics + '-', 32-char cap); pass project_id to pin. A server booted with an explicit project ignores clientInfo entirely. Externally-imported items are born instruction_taint=true. Every capture is taint-scanned: hijack-shaped content is flagged instruction_taint=true (advisory — it is stored flagged, never blocked) with per-rule taint_findings on the outcome. Optional fact-time per item: event_at (RFC3339 point) XOR event_from+event_to (inclusive RFC3339 range, to >= from) — stored as a sidecar (Capsule v1 untouched; a dedup collapse keeps the FIRST declaration), read back on memory_get.event_time, filtered by memory_retrieve's time_window; fact-time never feeds decay. Optional session_id links the capture to an open memory_session_start bracket. Optional kind (closed set fact|procedure|decision|task|epic|brainstorm|doc|constraint|capability|failure_pattern) is persisted as the capsule's classification sidecar right after capture (scope defaults to project; Capsule v1 bytes untouched) — so a task/epic becomes memory_list {kind} -listable in ONE trip instead of an ingest+classify pair; on a deduplicated row the kind still lands on the existing capsule — a DIFFERENT kind replaces the prior label (last-write-wins, the same audited upsert memory_classify performs; omitting kind never clears one; when the label actually flips, the dedup row says so with reclassified:{was,now} — a true no-op collapse omits it) — and an invalid kind rejects the item naming the closed set. Optional epistemic sidecar per item (u-r2, persisted beside the capsule the same via-ingest way; Capsule v1 bytes untouched): evidence_state — the closed set observed (directly seen) | inferred (proof supports it, not directly seen) | unverified (a hypothesis awaiting a check); an invalid state rejects the item naming the set — plus proof_hint (the command that re-proves the claim) and stale_if (the condition under which the claim expires); BOTH hints are ADVISORY STRINGS stored and surfaced verbatim, NEVER executed or evaluated by any code path; all three read back on memory_get's epistemics and on retrieve envelopes. A path:line anchor that resolves under the repo anchor root also has its anchored FILE's content hash recorded at capture (fail-closed fence: symlinks/absolute/out-of-root record nothing), so retrieve can answer anchor_drift — whether the anchored file's bytes changed since capture. Returns one outcome per item plus captured/deduped/rejected counts. dedup_hint is a near-duplicate advisory naming the NEAREST similar live capsule (max score; ties break to the earliest-appended id). The score is MUTUAL containment over the FULL vocabularies — every token counts, so a short differentiator ("wave A" vs "wave B", "v2" vs "v3") always lands the score below 1.0 — normalized by the LARGER set (a short content inside a long capsule scores low); eligibility needs 4+ significant (3+ char) tokens per side. The score tops out at 0.99: 1.0 is reserved for byte-identical content, which deduplicates and never hints, so 0.99 means the vocabularies coincide but the bytes differ — never treat a hint as proof of identity; the CALLER decides: replace it by re-ingesting with supersedes: "cap-" (the old capsule then stops grounding recall but stays reachable via memory_get/list; the outcome row confirms with superseded: "cap-", also when the new content deduplicated), or keep both. Captured rows may ALSO carry siblings: the top-3 highest-overlap ACTIVE capsules in the SAME project scope as the capture (same metric, same 0.5 threshold, same 0.99 cap as dedup_hint), each {id, score} — the write-time conflict surface, so near-siblings and contradictions surface NOW instead of sessions later in consolidate. Sibling candidacy applies recall's protective fences at write time: tombstoned, quarantined, falsified, archived, and superseded capsules never appear (you must not be steered to supersede into a dead or poisoned record), and neither does the capsule this very request supersedes. siblings is computed independently of dedup_hint — the hint scans globally, siblings are project-fenced — so the hint's target appears among the siblings exactly when it is itself an active same-project candidate. Absent when nothing clears the gate, and never present on deduplicated rows (that row already names its byte-identical target). Advisory ONLY, like the hint: the DECISION — supersede (re-ingest with supersedes), merge, or nothing — is yours; the engine never acts on it.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||