ADR-0094shipped
Memory Write Gate V1 (Soft, LLM-First, Three-State)
2026-03-04 Reality Check
Status updated to shipped.
packages/system-bus/src/memory/write-gate.ts(140 lines) implements the full three-state verdict (allow/hold/discard), annotation parsing, and retrieval gate helpersresolveWriteGate(),allowsReflect(),allowsDefaultRetrieval()are in production useWRITE_GATE_VERSION = "v1"— matches the V1 spec in this ADR- Write gate is called in the observe pipeline (
observe.ts) on every observation before storage
Context
ADR-0077 identified write gate as a deferred part of the broader memory vision. Since then, retrieval hardening and maintenance shipped, but one core quality problem remains:
- Low-signal observations still enter the pipeline.
- Reflect and proposal triage pay the downstream cost (noise, backlog, review load).
- Retrieval filtering alone is not enough because Reflect reads Redis observation summaries written during ingest.
Current constraints:
- No data loss — raw observations must remain available for audit/debug.
- Quality lift now — reduce noisy proposals in the next implementation slice.
- CLI/OTEL diagnosability — gate behavior must be observable via existing
joelclaw oteland memory health workflows. - No new memory backend in this slice (Typesense remains canonical).
Decision
Adopt a soft write gate at memory ingest with these policies:
- Three-state verdict per observation:
allow | hold | discard. - LLM-first classification integrated into the existing observer call path (no extra classifier round-trip by default).
- Fail-open default: if parse/classifier metadata is missing, store as
allowwith low confidence and explicit fallback reason. - Store all observations in
memory_observationswith write-gate metadata (audit preserved). - Default downstream behavior:
allow: eligible for Redis summary → Reflect, and default recall/prefetch.hold: stored, but excluded from Reflect and default recall/prefetch; available for debug/fallback paths.discard: stored for audit only; excluded from Reflect/default retrieval.
Design Contract
Metadata fields (per observation)
write_verdict:allow | hold | discardwrite_confidence: float0..1write_reason: short classifier rationalewrite_gate_version: string (ex:v1)write_gate_fallback: boolean (truewhen parser/classifier fallback applied)
Enforcement points
- Primary enforcement: ingest, before Redis summary write used by Reflect.
- Secondary enforcement: default retrieval filters in recall/context prefetch.
Failure semantics
- Missing/malformed gate metadata MUST NOT drop data.
- In fallback mode, observation is still stored, marked
allow, low confidence, andwrite_gate_fallback=true. - OTEL must emit fallback counts and reasons.
Implementation Plan
1) Extend observer classification output
- Update observer prompt and parser to produce gate metadata per observation item.
- Files:
packages/system-bus/src/inngest/functions/observe-prompt.tspackages/system-bus/src/inngest/functions/observe-parser.ts
2) Apply gate during ingest
- In
observe.ts, enrich observation items with verdict metadata, write all docs to Typesense, but build Redis reflection summary fromallowonly. - In
observe-session-noted.ts, normalize gate metadata (trusted-source default policy documented in code). - Files:
packages/system-bus/src/inngest/functions/observe.tspackages/system-bus/src/inngest/functions/observe-session-noted.ts
3) Filter default retrieval paths
- Recall defaults to
write_verdict:=allow; optional debug/fallback expansion can includehold. - Context prefetch follows same default policy.
- Files:
packages/cli/src/commands/recall.tspackages/system-bus/src/memory/context-prefetch.ts
4) Schema and health wiring
- Ensure memory schema reconciliation includes write-gate fields.
- Extend memory health/weekly summaries with verdict distribution signals.
- Files:
packages/cli/src/commands/inngest.tspackages/system-bus/src/inngest/functions/memory/weekly-maintenance-summary.ts
5) Tests + verification
- Add/extend tests for:
- gate parsing/fallback behavior
- ingest filtering into Redis/Reflect
- recall default filter behavior
- Files:
packages/system-bus/src/inngest/functions/observe.test.tspackages/cli/src/commands/recall.test.ts
Acceptance Criteria
- Mixed-quality observation batches persist all documents with gate metadata in Typesense.
- Reflect input excludes
holdanddiscardby default. - Default recall/prefetch exclude
hold/discard; debug path can surfacehold. - Fallback path is explicit (
write_gate_fallback=true) and visible in OTEL. - OTEL includes verdict counts per ingest run (
allowCount,holdCount,discardCount,fallbackCount). - Proposal noise drops measurably after rollout (tracked window in OTEL/weekly summary).
Verification Commands
bunx tsc --noEmit -p packages/system-bus/tsconfig.jsonbunx tsc --noEmit -p packages/cli/tsconfig.jsonbun test packages/system-bus/src/inngest/functions/observe.test.tsbun test packages/cli/src/commands/recall.test.tsjoelclaw inngest memory-schema-reconcile --jsonjoelclaw recall "redis dedupe pattern" --jsonjoelclaw otel search "observe.store.completed|write_gate|proposal-triage" --hours 24
Non-Goals
- Adopting Datomic or replacing Typesense in this slice.
- Implementing knowledge graph / dual-search in this ADR.
- Hard-rejecting observations at ingest.
Consequences
Positive
- Immediate reduction of downstream memory noise and review burden.
- Preserves full raw evidence for audit/debug.
- Clear policy surface for future category and budget-aware retrieval work.
Negative / Risks
- LLM classification quality can drift; fallback and telemetry must be monitored.
- Misclassification risk (useful items marked hold/discard) requires debug visibility.
- Additional schema/policy complexity across ingest and retrieval.
References
- ADR-0077: Memory System — Next Phase
- ADR-0068: Memory Proposal Auto-Triage Pipeline
- ADR-0087: Observability contract
More Information
2026-02-22 validation snapshot
joelclaw inngest memory-e2e --wait-ms 120000 --poll-ms 1500 --jsonproduced mixed write verdicts and fallback in one run (allow=4,discard=1,fallback=1) with persisted metadata inmemory_observations.joelclaw recall "memory-e2e-mlx5t4fl-z1sg4r" --category memory --limit 5 --jsonshowed defaultholdexclusion (held_by_write_gatein dropped diagnostics) while surfacingallowobservations.joelclaw otel search "memory.write_gate_drift.detected" --hours 2 --jsonconfirmed health-check alert hook emission for drift conditions.joelclaw otel search "system.health.checked" --hours 1 --jsonnow includeswriteGateDriftin health metadata.
Remaining acceptance gap: measurable proposal-noise reduction trend over a longer post-rollout window.
Status
Proposed (pending long-window proposal-noise reduction evidence).