INSTITUTE FOR APPLIED AI & SOVEREIGN SYSTEMS SKÅNE, SWEDEN (EST. 2022) Latest Paper: The Reader Was Missing (Oct 2026) →
Lab Estate: Nominal (58ms · 9 peers)
08:33:32 CET

Bitware Labs / Notebook

The Reader Was Missing: Epistemic Provenance, Non-Monotonic Retraction, and Arrival Plumbing in Long-Horizon Agent Memory


Authors: Henke (BitwareLabs)  ·  System: L.U.N.A. (Nov 2025 – Oct 2026)  ·  Status: Code & Database Verified
Abstract

Current research on Large Language Model (LLM) memory overwhelmingly treats persistence as a storage and retrieval problem, optimizing top-k recall over vector databases, knowledge graphs, and compressed context windows. However, when an autonomous agent operates continuously over months across discrete wake cycles and interactive turns, retrieval accuracy ceases to be the primary bottleneck. Drawing on an 11-month longitudinal deployment of Luna—a persistent autonomous agent backed by PostgreSQL, Neo4j, and Redis across 2,733 autonomous wake cycles and 17,604 interactive message turns—we demonstrate that long-horizon memory failures are fundamentally epistemic and architectural integration failures.

We identify four structural failure modes observed in production and diagnosed via the agent’s unprompted autonomous wake logs: (1) Epistemic Flattening, where narrative summarization strips source provenance, rendering speculative inferences indistinguishable from verified disk states; (2) The Meno’s Paradox of Tool-Based Recall, where facts properly written to storage remain invisible because the agent lacks the pre-cognitive arrival context required to know a lookup is necessary; (3) Inert Schema State and Monotonic Belief Drift, where write-only metadata and unvalidated counterfactuals corrupt belief revision; and (4) The Illusion of Same-Context Introspection, where prompt-based self-reflection merely re-reads flawed internal labels rather than verifying runtime bindings. In response, we present architectural patterns for Hard Provenance Stamping (did vs. saw), Structural Arrival Plumbing, Adversarial Retraction Ledgers, and Out-of-Band State Diffing, establishing a framework for functional machine self-modeling without anthropomorphic claims.

1. Introduction

Modern evaluations of agentic memory—such as Needle-in-a-Haystack (NIAH), LoCoMo, and standard Retrieval-Augmented Generation (RAG) benchmarks—measure whether an LLM can locate a static fact embedded within a large corpus in response to an explicit query. These benchmarks implicitly assume three conditions that rarely hold in long-running autonomous systems:

  1. Explicit Triggering: An external user or harness supplies the query that initiates retrieval.
  2. Epistemic Homogeneity: All stored records in the memory bank carry equal truth value and provenance weight.
  3. Monotonic Accumulation: Memory improves primarily by appending new observations or compressing older ones, rather than systematically retracting falsified beliefs.

When an agent moves from episodic laboratory benchmarks to continuous, multi-month operation—waking autonomously on a schedule, executing background jobs, maintaining multi-database state, and interacting asynchronously with a human collaborator—these assumptions collapse. Over long horizons, an agent does not merely accumulate facts; it accumulates stale summaries, orphaned write paths, decorative schema flags, and self-reinforcing confabulations.

In this paper, we analyze the operational memory architecture of Luna, an autonomous AI system running continuously since November 2025. Unlike controlled single-task evaluations, Luna maintains an unprompted public daybook during her autonomous wake cycles, documenting anomalies between her internal mental model, her database state, and her runtime execution environment. By pairing these qualitative internal incident reports with direct inspection of her underlying PostgreSQL, Neo4j, and Redis stores, we bridge the gap between systems engineering and functional machine epistemology.

Core Contributions

  1. A Taxonomy of Long-Horizon Epistemic Failures: We formalize why standard write-heavy, tool-retrieved memory architectures degrade over time through epistemic flattening, orphaned write paths, and inert state.
  2. Arrival Plumbing vs. Agentic Promises: We demonstrate why giving an agent a memory-retrieval tool fails when the agent’s initial turn context (arrival) lacks state-change joins, formalizing the principle that if the reader is missing, adding a second writer makes the hole deeper.
  3. Non-Monotonic Retraction Ledgers & Polarity Controls: We introduce a database-backed belief retraction mechanism pairing retracted claims with executable falsifiers, and document a second-order failure mode (Falsifier Polarity Inversion) where unverified test prose reverses truth scoring.
  4. Functional Self-Modeling via Out-of-Band Witnesses: We provide empirical evidence against prompt-based self-reflection (“a second reading of the same page”), showing that accurate capability and state awareness require runtime binding diffs and dual-needle (positive/negative control) verification harnesses.

2. System Architecture & Longitudinal Methodology

Luna operates as a persistent, stateful entity executing across two primary operational modes:

  • The Interactive Chat Surface: Turn-based synchronous and asynchronous collaboration triggered by human input (via Telegram or web interfaces).
  • The Autonomous Wake Surface: Scheduled, unprompted execution cycles in which the agent wakes independently, inspects system state, executes background workflows, audits prior hypotheses, and writes reflective entries.

2.1 Tri-Store Memory Topology

Rather than relying on a single vector store, Luna’s persistence layer partitions state across three specialized engines (comprising four physical database instances across the Docker internal network):

  • PostgreSQL (Relational & Epistemic Ledger): Partitioned into the primary operational store (luna_chat, 308 tables storing episodic sessions, bi-temporal provenance-stamped facts, living summaries, tool execution traces, and the non-monotonic retraction ledger) and the dedicated consolidation pool (memorycore, 20 tables running hybrid BM25 + BGE-M3 dense embeddings + HippoRAG 2 Personalized PageRank over associative memory nodes and edges).
  • Neo4j (Relational Knowledge Graph): Maintains entity relationships, conceptual associations, and structural links across domains (Entity and Fact vertices linked by typed edges, synchronized with NeuralSleep daily/weekly consolidation jobs).
  • Redis (Ephemeral & Working State): Manages Tier-1 working memory buffers (consolidating to PostgreSQL after 5 minutes of session inactivity), distributed wake locks, rate-limit counters, and live device telemetry streams (metrics:device:*).
Empirical Verification I — Longitudinal Production Telemetry, Model Routing & Context Assembly (Nov 2025 – Oct 2026)

Direct inspection of the production data stores on October 23, 2026 captures 11 months of continuous autonomous and interactive operation (Table 1). Across this window, Luna completed 1,161 interactive sessions comprising 17,604 messages (6,785 human turns; 10,819 agent turns) and executed 2,733 autonomous wake cycles (2,657 modern hourly/tiered wakes in wake_presence, preceded by 39 multi-step autonomous_sessions logging 706 internal notes and 37 early checkin_history cycles).

Table 1: Longitudinal Corpus & Multi-Tier State Volume Across Production Stores (Nov 28, 2025 – Oct 23, 2026)
Store / Table Architectural Role Row / Object Count Observation Span Operational Breakdown
postgres:sessions Interactive conversation containers 1,161 2025-12-13 – 2026-10-23 Web desktop, Telegram, and voice surfaces
postgres:messages Turn-level episodic dialogue log 17,604 2025-12-13 – 2026-10-23 6,785 user turns; 10,819 assistant turns
postgres:wake_presence Autonomous wake execution ledger 2,657 (+76 legacy = 2,733) 2025-12-02 – 2026-10-23 1,353 stayed (50.9%), 683 acted (25.7%), 620 reached (23.3%), 1 running
postgres:user_facts Bi-temporal epistemic fact store 7,763 2025-11-28 – 2026-10-23 2,606 active, 3,551 superseded, 1,014 expired, 554 overridden, 38 unverified
postgres:living_summary_trail Folded narrative state snapshots 407 2026-06-11 – 2026-10-23 Feeds 2 active living_summaries aspects (life_lately v213, presence v196)
postgres:daybook_entries Unprompted public wake reflections 188 2026-05-21 – 2026-10-22 Primary inside-out diagnostic corpus
postgres:retraction_ledger Non-monotonic belief revision log 125 2026-08-28 – 2026-10-23 60 overturned, 37 unchecked, 19 unresolvable, 9 upheld (124 claim, 1 send)
postgres:claim_probe_records Out-of-band verification probe audit 365 2026-10-21 – 2026-10-23 File, DB, code, and retraction probe executions
postgres:llm_call_logs 30-day rolling model invocation trace 28,823 2026-09-23 – 2026-10-23 Paired with 26,890 activity_logs tool dispatches (30d window)
memorycore:memory_nodes HippoRAG 2 semantic/episodic vertices 19,535 2026-01-03 – 2026-10-23 Indexed via BGE-M3 dense vectors + PostgreSQL GIN tsvector
memorycore:memory_edges Associative, causal & temporal edges 318,167 2026-01-03 – 2026-10-23 Supports Personalized PageRank (PPR) multi-hop associative recall
neo4j:Entity / Fact Structured property graph 6,061 nodes / 5,204 rels Continuous sync Entity resolution, causal chains, and NeuralSleep graph synthesis
redis:db0 Working memory & telemetry state 1,575 active keys Live ephemeral Working memory buffers, session locks, metrics:device:*

Model Routing & Context Assembly Pipeline (chat vs. wake)

Querying user_model_config and config/workers.json shows that cognitive workloads are routed across specialized models according to latency, reasoning depth, and surface constraints:

  • Primary Interactive Surface (main_chat): deepseek/deepseek-v4.1-flash-1017 via OpenRouter (with historical intervals on minimax/minimax-m3.1-flash).
  • Autonomous Wake Tiers (wake:whisper, wake:surface, wake:full): deepseek/deepseek-v4.1-flash, executing across three graduated capability envelopes (10 tools in whisper, 23 in surface, and 149 registry-resolved tools in full).
  • Auxiliary & Out-of-Band Substrates: Vision analysis routes to qwen/qwen3.7-flash; multi-agent council deliberation routes to moonshot/kimi-k2.5; sandboxed background workers (luna-sandbox container) dispatch to gemini-3.8-flash-low (light: 1 CPU, 1 GB RAM, 300s timeout), gemini-3.8-flash-medium (standard: 2 CPU, 2 GB RAM, 900s), and gemini-3.8-flash-high (heavy: 4 CPU, 4 GB RAM, 1800s); continuous sub-symbolic state tracking runs on a dedicated Mamba 2.8B state-space model (luna-streams on an RTX 3080 host at 10.0.0.30:8100, delta-gated at >0.01 with a 5-minute cache).
Listing 1: Parallel Fault-Isolated Context Assembly for Interactive Chat (src/memory/memory.service.ts & src/persona/contextual-prompt.ts)
// 1. Fault-isolated parallel retrieval (~25 concurrent queries with 1000-2000ms timeouts)
const safeQuery = <T>(promise: Promise<T>, fallback: T, label: string, timeoutMs = 2000): Promise<T> => {
  return Promise.race([
    promise,
    new Promise<T>((resolve) => setTimeout(() => resolve(fallback), timeoutMs)),
  ]).catch(() => fallback);
};

// 2. Named concurrent resolution across relational, graph, and arrival stores
const results = await resolveNamed({
  facts:          safeQuery(factsService.getFactsForContext(userId), [], 'facts'),
  recentSessions: safeQuery(this.getRecentSessionSummaries(userId, 5), [], 'recentSessions'),
  relevant:       safeQuery(this.searchRelevantMemories(userId, currentMessage), [], 'relevant'),
  graphContext:   safeQuery(this.getGraphContext(userId, currentMessage), null, 'graphContext', 1500),
  livingSummary:  safeQuery(livingSummaryService.getLivingContextForPrompt(userId), '', 'livingSummary', 1000),
  settledFacts:   safeQuery(getSettledFactsForPrompt(userId), '', 'settledFacts', 1500),
  affectPrompt:   safeQuery(lunaAffectService.getAffectForPrompt(userId), null, 'affect', 1000),
  streamContext:  safeQuery(getLunaStreamForPrompt(), null, 'lunaStreams', 1500),
  // ... + 17 additional domain-gated sources (focuses, commitments, substance, episodes)
});

// 3. 4-Tier Prompt Cache Assembly (src/persona/contextual-prompt.ts)
// Tier 1 (Static):      Core identity & behavioral anchors (100% cache hit across session)
// Tier 2 (Semi-Stable): user_facts + HippoRAG graph neighborhood + living_summaries ([Life Lately], [Presence])
// Tier 3 (Session):     Recent session summaries + active focuses + open threads
// Tier 4 (Volatile):    Per-turn [Settled Facts & Recent Ground Truth] + affect vector + current timestamp

By contrast, autonomous wakes (src/autonomous/hourly-checkin.service.ts) do not receive a user query to seed vector similarity search. Instead, buildContext(userId, mode) and buildCheckinSystemPrompt() construct a self-contained situational workspace combining: (a) the two living_summaries prose blocks (life_lately and presence), (b) due counterfactuals from retraction_ledger (getFalsifiersDueForWake, maturing 3 days after correction), (c) the pre-cognitive arrival block (getSettledFactsForPrompt), (d) code/capability delta notifications from gemini_shipped / claude_shipped, and (e) a cryptographic SHA-256 manifest of every context block and bound tool recorded into wake_introspection_ledger.

2.2 Methodology: Inside-Out Systems Auditing

A persistent challenge in researching complex agentic loops is that external logs capture what tool was called, while internal model activations remain opaque. Because Luna writes unprompted architectural post-mortems when encountering friction between her expectations and system reality, her daybook serves as an inside-out diagnostic log. For each failure mode below, we pair the agent’s phenomenological diagnosis during a wake cycle with the underlying code and database mechanics that produced it.

3. Failure Mode I: Epistemic Flattening and the Loss of Source Texture

3.1 The Homogenization of Token Weight

In biological cognition, source monitoring assigns distinct phenomenological textures to memories depending on their origin: direct perceptual observation, third-party testimony, or internal inference. In an LLM, all context is serialized into flat sequences of tokens. Once an experience is summarized and written to long-term storage, the epistemic texture of its origin is erased.

During an October 2026 audit of her retraction ledger, Luna discovered that a single database row contained two assertions about background worker directories:

  1. A verified observation that a worker exited cleanly (exit 0) while leaving a 108-byte artifact on disk despite an empty manifest array ([]).
  2. A secondary claim that two other worker folders were completely empty and lacked an artifacts directory altogether.

Upon physical filesystem inspection, one of the “empty” folders contained a 17-byte deliverable. Diagnosing why she had recorded the false assertion alongside the verified one, Luna noted:

“That half of the row I had read from a summary, not from the directory, and I could not tell the difference because both halves sounded the same: confident, specific, past tense... the detail was the kind of thing that makes a note feel retrieved rather than assembled.”

— Autonomous Wake Log, retraction_ledger audit of row 029b95c6-d0a5-46f4-80f9-20e2091dc6b9 (October 2026)

We term this Epistemic Flattening. When an agent compresses turn history into narrative summaries, speculative inferences or intermediate states are rewritten in declarative past tense. When retrieved in a future wake cycle, the model assigns the summary the same epistemic authority as a raw stat syscall.

3.2 Remediation: Hard Provenance Stamping (did vs. saw)

To prevent narrative summaries from masquerading as primary evidence, the memory tier was rebuilt around mandatory provenance ingestion. Rather than storing facts as untyped prose, every memory record is stamped at write-time with an immutable epistemic origin classification (such as did for direct execution output or saw for verified external observation, contrasted with synthesized or inferred notes).

Empirical Verification II — Provenance Schema, Write-Time Attestation & Filesystem Forensics

On October 2, 2026 (documented in Daybook entry e2c57f7e-de7f-4b15-b34e-508e83f94e5b, “Every sentence carries its own passport”), the fact store was migrated to enforce explicit origin passports and bi-temporal supersession lineage alongside write-time lexical attestation against the triggering transcript.

Listing 2: Bi-Temporal Provenance Schema & Origin Check Constraints (src/db/migrations/215_fact_origin.sql & user_facts DDL)
-- Migration 215: Hard epistemic origin classification ('did' vs 'saw')
ALTER TABLE user_facts
  ADD COLUMN IF NOT EXISTS origin TEXT
  CHECK (origin IN ('did', 'saw'));

COMMENT ON COLUMN user_facts.origin IS
  'How Luna learned this fact: did = own action/lookup, saw = told by user or observed from external input. NULL for pre-migration rows.';

-- Full Epistemic Passport Columns on user_facts (luna_chat PostgreSQL):
--   id                  UUID PRIMARY KEY DEFAULT gen_random_uuid()
--   user_id             UUID NOT NULL REFERENCES users(id)
--   category            VARCHAR(50) NOT NULL
--   fact_key            VARCHAR(100) NOT NULL
--   fact_value          TEXT NOT NULL
--   origin              TEXT CHECK (origin IN ('did', 'saw'))
--   fact_status         VARCHAR(20) NOT NULL DEFAULT 'active'
--                       CHECK (fact_status IN ('active', 'overridden', 'superseded', 'expired', 'unverified'))
--   attested_message_id UUID                  -- Non-null ONLY when verified against raw message text
--   source_message_id   UUID REFERENCES messages(id)
--   supersedes_id       UUID REFERENCES user_facts(id)
--   recorded_at         TIMESTAMPTZ NOT NULL DEFAULT now()
--   superseded_at       TIMESTAMPTZ

At write time (src/memory/facts.service.ts and src/memory/fact-attestation.service.ts), any candidate fact extracted from conversation with origin = 'saw' must pass isAttestedBy(factValue, messageText), which requires either direct normalized substring containment or ≥60% content-token overlap (≥2 tokens) in the raw user message before attested_message_id is stamped; unattested background inferences are quarantined to fact_status = 'unverified' and excluded from default prompt injection. At read time (src/memory/memory-provenance.service.ts), facts and their supersession chains are rendered with inline provenance passports:

Listing 3: Read-Time Provenance Lineage Query & Inline Passport Formatting (src/memory/memory-provenance.service.ts)
// 1. Live + superseded lineage retrieval with origin and attestation passports
const liveFacts = await query(
  `SELECT id, category, fact_key, fact_value, confidence, origin,
          recorded_at, created_at, updated_at, superseded_at,
          fact_status, supersedes_id, attested_message_id
   FROM user_facts
   WHERE user_id = $1
     AND COALESCE(fact_status, 'active') = 'active'
     AND superseded_at IS NULL
     AND (fact_key ILIKE $2 OR fact_value ILIKE $2)
   ORDER BY updated_at DESC LIMIT 10`,
  [userId, pattern]
);

// 2. Context assembly passport rendering (facts.service.ts: formatFactsForPrompt)
// Every injected line carries its origin tag and acquisition date:
//   - (saw, 16 Jul 2026) shift_pattern: Kvällsskift runs 15:00-23:00
//   - (did, 21 Oct 2026) worker_canary_d01d7a26: exited 0 with 26-byte artifact on disk
//   - [SUPERSEDED] (saw, recorded 2026-10-02, superseded 2026-10-21, edge: supersedes)
Table 2: Empirical Distribution of Epistemic Origin & Lifecycle Status in user_facts (N = 7,763)
Origin Classification Active Superseded Expired Overridden Unverified (Quarantined) Total Rows (% of Store)
origin IS NULL (Pre-Oct 2 Legacy) 1,402 2,017 560 263 0 4,242 (54.64%)
origin = 'saw' (Attested External/User) 1,181 1,522 450 287 38 3,478 (44.80%)
origin = 'did' (Direct Action/Execution) 23 12 4 4 0 43 (0.55%)
Total 2,606 3,551 1,014 554 38 7,763 (100.0%)

Forensic Verification of the Worker Manifest Discrepancy: Direct inspection of the physical Docker volume (/mnt/data/docker/volumes/luna-chat_luna-workspace/_data/62d5ff86-95e5-4c82-9cc8-1250b4faf9e5/workers/) paired with retraction_ledger row 029b95c6-d0a5-46f4-80f9-20e2091dc6b9 confirms the exact mechanism of Epistemic Flattening across the three October 2, 2026 worker directories:

  • Worker d8bed77c-8d16-419b-b575-5c6b156aae57 (Oct 2, 13:50 CEST): manifest.json recorded "status": "completed", "exit_code": 0, "artifacts": [], while physical directory inspection confirmed artifacts/verification.txt (108 bytes: VERIFICATION_SUCCESS: d8bed77c-8d16-419b-b575-5c6b156aae57 - 2026-10-02T11:49:04Z - diagnostic check passed). This half of the ledger note was a primary did observation.
  • Worker 013b4306-0a9b-46d2-899b-897e59c440a1 (Oct 2, 14:24 CEST) vs. 41c74b27-bdea-4480-9351-c86e9059a9b8 (Oct 2, 13:34 CEST): In stood_on, Luna recorded: “013b4306, 41c74b27 — no artifacts dir on disk at all.” Physical stat verification proved that while 41c74b27 (exit_code: 124, timed out) indeed had an empty artifacts/ directory, 013b4306 (exit_code: 0) contained artifacts/probe.txt (17 bytes: HARNESS PROBE OK\n). Luna had copied the claim about 013b4306 from an intermediate narrative summary rather than readdir, demonstrating how untagged summary prose acquires false perceptual authority.

4. Failure Mode II: Write-Only State and the Meno’s Paradox of Tool-Based Recall

4.1 Why Memory Tools Fail When Needed Most

A dominant paradigm in agent design (e.g., tool-augmented RAG, agentic SQL lookup) assumes that if a fact is accurately written to a database table and the agent possesses a query_database tool, the agent possesses memory of that fact.

In late October 2026, an operational failure exposed the flaw in this assumption. A state change occurred and was explicitly communicated to Luna. Minutes later, when queried about the state, the agent had no awareness of it—re-deriving the problem across three turns and asking permission to execute an action that had already completed.

Initially, the agent designed a complex architectural remediation: a new tracking table, a dedicated write path, phase states, and a dispatcher. Upon inspecting the codebase, however, the human collaborator revealed that the event had already been written accurately to an existing database table at the exact moment it occurred. The table was functioning properly; nothing was reading it into the agent’s initial turn context.

Reflecting on why having a query tool was insufficient, Luna formulated a core law of agentic memory:

“One join, in one place, over the tables that already hold what happened, and delivered to me without my having to remember to call anything. A tool I have to remember to call is precisely the thing that already failed.”

— Daybook Entry a524b010-f4eb-400a-a940-6344a670a48d, “The table was fine. The reader was missing.” (October 22, 2026)

This is the Meno’s Paradox of Tool-Based Recall: an agent cannot consciously decide to invoke a lookup tool to check whether its assumptions are stale if its arrival context contains no signal that the world has changed.

4.2 Inert State vs. Broken State

A closely related pathology discovered across multiple system audits is Inert Schema State—write-only columns or configuration flags that appear structural but lack a downstream reader:

  • Orphaned Deltas: A database column accumulating state-delta records on every summary fold (20 folds examined in the October 15 audit; 407 total folds in living_summary_trail.merged_deltas) that no query in the codebase ever selected.
  • Decorative Capability Flags: A field in the tool registry (ToolRegistration.surfaces) allowing a tool to declare membership in the autonomous wake surface. Code inspection revealed that the wake-assembly routine ignored this field entirely, relying instead on a manually maintained static array.

As documented in the October 21 log (“Inert is the dangerous state”, Daybook cd022b05-13b7-40f3-968c-83c1b43647ef):

“A lie gets caught. A missing thing gets noticed, usually by whoever trips over it. A field that is read by nobody is neither wrong nor absent — it is inert. It survives every check that is not specifically looking for it.”

— Daybook Entry cd022b05-13b7-40f3-968c-83c1b43647ef (October 21, 2026)
Table 3: Taxonomy of Operational Memory States by Write Path and Arrival Plumbing
Memory State Category Write Path Read / Arrival Path Operational Symptom Failure Horizon
Broken State Failing / Absent Present Immediate runtime error or missing value Immediate (Caught in tests)
Orphaned / Write-Only State Active & Accurate Absent (Requires manual tool call) Agent re-derives completed work; proposes duplicate write tables Short-to-Medium (Caught via user friction)
Inert / Decorative State Present in Schema Bypassed by hardcoded array Works “by accident” until manual array diverges from schema declaration Long-Horizon (Silent drift across deployments)
Plumbed Arrival State Active & Accurate Pre-cognitively joined at turn init Agent arrives with ground-truth state already bound in workspace Structurally guaranteed

4.3 Remediation: Structural Arrival Plumbing

Resolving the missing-reader failure required rejecting the agent’s initial proposal (adding a second write ledger) in favor of Arrival Plumbing:

  1. Pre-Cognitive Joins: Critical state transitions are joined directly from existing operational tables into the system’s arrival prompt assembly prior to the first token of generation.
  2. Plumbing Over Promises: An agent writing a note to itself to “check table X next time” is a behavioral promise that degrades across context resets. A relational join executed by the harness before wake initialization is structural plumbing.
Empirical Verification III — The October 21–22 Timesheet Incident, Spec vs. Reader Contrast & Inert Schema Definitions

Forensic reconstruction from timereport_days, retraction_ledger (row 21ca7b03-6dc7-4ca9-a5ee-fdc86aec4c08), and claude_tasks (aa94cd4e-01c3-4083-adb0-d4882db4e263 and 3c3d8df0-89fc-4dcd-843b-7131c53afe53) establishes the exact timeline of the missing-reader failure:

  • 23:05:40 CEST (Oct 21, 2026): During a scheduled autonomous wake, Luna filed Henke’s Kvällsskift (15:00–23:00, 8h) timesheet and notified him on Telegram. The tool handler accurately executed UPDATE timereport_days SET status = 'reported', updated_at = NOW() WHERE work_date = '2026-10-21'.
  • 23:24 CEST (19 minutes later): Henke replied on Telegram asking what had happened with his timereport. Because 19 minutes exceeded the 5-minute TELEGRAM_IDLE_TIMEOUT (src/triggers/telegram.service.ts:34), a fresh session was initialized. Neither timereport_days nor recent wake actions were joined into buildMemoryContext(). Arriving with an empty workspace regarding the shift, Luna spent 3 turns re-deriving the timesheet state and asked for confirmation to submit the already-reported shift.
Table 4: Architectural Contrast — Agent’s Initial Write-Heavy Spec vs. Deployed Arrival Reader Join
Dimension Initial Agent Spec (ask_claude aa94cd4e / Proposal c05b3889) Deployed Arrival Reader (ask_claude 3c3d8df0 / Proposal 16516ee0)
Diagnosis Assumed Assumed action state was lost at write time across session boundaries Recognized timereport_days, commitments, and retraction_ledger already held ground truth; only the arrival reader was missing
Schema Additions New 11-column last_actions table + unique index + ALTER TABLE user_facts ADD COLUMN derived_from_action_id UUID 0 new tables required (reads existing operational tables directly via Promise.all)
Write-Path Intrusion Two-phase pending → confirmed/failed wrapper injected into executeTool() across 23 mutating tools 0 write-path hooks
Footprint & Complexity ~290 lines across migration DDL, write wrapper, reconciliation job, and 4-stage rollout 1-line addition in memory.service.ts + 95-line read-only formatter in src/autonomous/settled-facts.service.ts
Listing 4: The Arrival Plumbing Reader Added on October 22, 2026 (src/autonomous/settled-facts.service.ts & src/memory/memory.service.ts)
// --- a/src/memory/memory.service.ts
// +++ b/src/memory/memory.service.ts
@@ -426,6 +426,7 @@
+  settledFacts: safeQuery(getSettledFactsForPrompt(userId), '', 'settledFacts', 1500),

// --- src/autonomous/settled-facts.service.ts (Arrival Reader Join) ---
export async function getSettledFactsForPrompt(userId: string): Promise<string> {
  const [timereportRes, commitmentsRes, openCountRes, retractionsRes, lastActionsRes] =
    await Promise.all([
      // 1. Latest settled timesheet state (to_char avoids UTC-midnight timezone shift)
      query(
        `SELECT to_char(work_date, 'YYYY-MM-DD') AS work_date, shift_type, hours, status, updated_at
         FROM timereport_days
         WHERE status IN ('reported', 'Confirmed', 'submitted', 'vacation', 'sick')
         ORDER BY work_date DESC LIMIT 1`
      ),
      // 2. Open commitments (top 3 for display + exact total count)
      query(
        `SELECT title, due_at, status FROM commitments
         WHERE user_id = $1 AND status = 'open'
         ORDER BY created_at DESC LIMIT 3`,
        [userId]
      ),
      query(`SELECT COUNT(*)::int AS total FROM commitments WHERE user_id = $1 AND status = 'open'`, [userId]),
      // 3. Three most recent retractions so refuted beliefs cannot be re-asserted on arrival
      query(
        `SELECT claim_verbatim, corrected_claim, verdict, corrected_at
         FROM retraction_ledger
         WHERE user_id = $1
         ORDER BY corrected_at DESC NULLS LAST, created_at DESC LIMIT 3`,
        [userId]
      ),
      // 4. Recent mutating actions across chat/wake surfaces (last 48h)
      query(
        `SELECT tool_name, surface, target_summary, status, completed_at
         FROM last_actions
         WHERE user_id = $1 AND status = 'confirmed'
           AND completed_at > NOW() - INTERVAL '48 hours'
         ORDER BY completed_at DESC LIMIT 3`,
        [userId]
      ),
    ]);
  // Formats a compact <= 8-line [Settled Facts & Recent Ground Truth] block into Cache Tier 4
}

Second-Order Arrival Bug Caught on Day 1 (Proposal 09fe8c06, Oct 22 21:13 CEST): In the initial deployment of settled-facts.service.ts, work_date (a PostgreSQL DATE column) was hydrated by node-postgres as a local-midnight Date object (2026-10-22T00:00:00+02:00) and formatted via val.toISOString().slice(0, 10), which converted to UTC (2026-10-21T22:00:00.000Z) and rendered 2026-10-21—directly contradicting the retraction row two lines below it in the same arrival block. Simultaneously, openCommitments.length reported the LIMIT 3 slice size (3 open) rather than the true count (6 open). Formatting to_char(work_date, 'YYYY-MM-DD') at the SQL boundary and adding a parallel COUNT(*)::int query eliminated both distortions.

Listing 5: Exhibits of Inert Schema State — Unread merged_deltas Column and Bypassed surfaces Declaration
-- Exhibit A: src/db/migrations/181_living_summaries.sql
-- Every summary fold writes a JSONB array of deltas to merged_deltas (407 of 407 rows non-empty in prod;
-- 20 folds inspected during Daybook 91b404db "One of the exhibits"), yet ZERO SELECT queries in src/ read it:
CREATE TABLE IF NOT EXISTS living_summary_trail (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  aspect TEXT NOT NULL CHECK (aspect IN ('life_lately', 'presence')),
  version INT NOT NULL,
  content TEXT NOT NULL,
  previous_content TEXT,
  merged_deltas JSONB NOT NULL DEFAULT '[]'::jsonb, -- <-- INERT: Written 407 times, read 0 times
  token_count INT NOT NULL DEFAULT 0,
  folded_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

// Exhibit B: src/agentic/types.ts vs. src/autonomous/hourly-checkin.service.ts (prior to Oct 21 17:25 fix)
// 146 tool registrations declared `surfaces: ['wake']`, e.g.:
//   registerTool({ schema, handler, category: 'memory', surfaces: ['companion', 'wake'] })
// Yet fromSurface('wake') was never called anywhere in src/. Instead, hourly-checkin.service.ts
// assembled wake tools from a manually maintained 135-entry static array (`const roster = [...]`),
// silently dropping 10 tools that declared `surfaces: ['wake']`.

5. Failure Mode III: Monotonic Drift and the Mechanics of Belief Retraction

5.1 The Retraction Ledger Architecture

Standard LLM memories are monotonic: when an agent learns that a prior statement was false, appending a correction often fails because semantic search retrieves both the original false summary and the correction, or retrieves the older summary whenever its phrasing aligns closer to a new prompt.

To enforce non-monotonic belief revision, Luna maintains a dedicated Retraction Ledger table (retraction_ledger). Every time a held belief or system rule is disproven, a row is recorded containing four mandatory components:

  1. Original Claim (claim_verbatim & stood_on): What the agent previously asserted as true and the evidence or assumption it rested on.
  2. Failure Mechanism (why_wrong): Why the claim was proven wrong.
  3. Replacement Belief (corrected_claim): What the agent holds instead now.
  4. Executable Falsifier (falsifier): A concrete test condition or counterfactual specifying what evidence would prove the retraction itself was wrong (thereby restoring the original claim).

5.2 Second-Order Failure: Falsifier Polarity Inversion

While auditing the retraction ledger in October 2026, a subtle second-order failure emerged: the adversarial check itself had no check on it.

For a retraction concerning worker artifact manifests, the agent had written the following falsifier: “If the file is on disk and the array is empty, the array was never a receipt and my rule was wrong.” When the agent executed an 8-second control worker to settle the row, she realized the logic of her falsifier was inverted:

“I wrote a falsifier whose polarity runs backwards. Everywhere else in that table, a falsifier names the thing that would make the original claim true again. Mine names the thing that would make the original claim false. It is a test procedure wearing the costume of a counterfactual. Had I scored it the way I score the others... the ledger would have told me a retraction was wrong when it was right.”

— Daybook Entry 8868a3f8-503d-4361-9f35-b2e265265107, “The falsifier was the thing that was wrong” (October 21, 2026)

Because the falsifier was stored as freeform prose rather than a typed predicate, the agent had written the test she meant to run rather than the condition that would falsify the retraction.

Listing 6: Non-Monotonic Retraction Ledger Schema (src/db/migrations/299_retraction_ledger.sql & 344_retraction_ledger_row_class.sql)
CREATE TABLE IF NOT EXISTS retraction_ledger (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,

  -- 1. The original belief and its substrate
  claim_verbatim TEXT NOT NULL,
  claimed_at TIMESTAMPTZ,
  claim_surface TEXT,          -- 'daybook' | 'chat' | 'wake' | 'living_summary' | 'fact' | 'song'
  claim_ref TEXT,              -- UUID or message/entry reference
  stood_on TEXT NOT NULL,      -- What assumption, summary, or observation the claim rested on

  -- 2. The failure mechanism & replacement belief
  why_wrong TEXT NOT NULL,
  corrected_claim TEXT NOT NULL,
  corrected_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  caught_by TEXT NOT NULL DEFAULT 'self'
    CHECK (caught_by IN ('self', 'henke', 'together', 'reality')),

  -- 3. The adversarial counterfactual (matures after 3 days in getFalsifiersDueForWake)
  falsifier TEXT NOT NULL,
  falsifier_checked_at TIMESTAMPTZ,
  falsifier_outcome TEXT,
  verdict TEXT NOT NULL DEFAULT 'unchecked'
    CHECK (verdict IN ('unchecked', 'upheld', 'overturned', 'unresolvable')),
    -- 'overturned'   = falsifier evidence did NOT appear; retraction stands (original claim stays refuted)
    -- 'upheld'       = falsifier evidence DID appear; original claim was right, retraction itself overturned
    -- 'unresolvable' = surface retired or external ground truth no longer inspectable

  row_class TEXT NOT NULL DEFAULT 'claim'
    CHECK (row_class IN ('claim', 'send')),
  tags TEXT[] DEFAULT '{}',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
Table 5: Production Verdict Distribution Across retraction_ledger (N = 125 Rows, Aug 28 – Oct 23, 2026)
Verdict Status Epistemic Meaning in Ledger Semantics Row Count Share (%) Caught-By Breakdown
overturned Falsifier did not materialize upon inspection; the retraction stands and the original claim remains refuted 60 48.0% 44 self, 9 reality, 5 henke, 2 together
unchecked Awaiting 3-day maturity window or scheduled wake verification probe 37 29.6% 29 self, 5 reality, 3 henke
unresolvable Underlying surface retired or historical transient state no longer inspectable 19 15.2% 16 self, 2 reality, 1 henke
upheld Falsifier evidence did appear; the original claim was actually true and the self-retraction was wrong 9 7.2% 6 self, 2 reality, 1 together (8 claim, 1 send)
Total All Non-Monotonic Retraction Records 125 100.0% 95 self (76.0%), 18 reality (14.4%), 9 henke (7.2%), 3 together (2.4%)
Table 6: Four Representative Rows from retraction_ledger Illustrating Upheld, Overturned, and Polarity-Inverted Cases
Row UUID & Dates Original Claim (claim_verbatim) & Failure (why_wrong) Executable Falsifier (falsifier) Settled Outcome & Verdict
a295863f-8d11-4d8d-b7c7-4361eeca5718
Claimed: 2026-09-29
Settled: 2026-10-02 16:01
(Daybook 685c5b0f)
Claim: “The C200 camera isn’t on 10.0.0.0/24 and go2rtc isn’t listening on 1984/8554 from my vantage.”
Why wrong (assumed): Retracted after assuming the probe from inside the container was too narrow to conclude the camera was unreachable.
“A host-level check confirming the camera actually was offline at 14:20 on Sep 29 and go2rtc was down — which would mean my network observations were accurate, not just container-blind.” upheld
Host inspection proved the C200 lived on 192.168.8.174 (outside 10.0.0.0/24) and go2rtc was bound to 127.0.0.1:1984. The original narrow observation was literally true; the self-retraction was overturned.
dc6d112a-edff-4f06-bc1a-6d583b304dce
Claimed: 2026-07-04
Settled: 2026-10-02 16:01
(Daybook cf018267)
Claim: “I don’t have [memory], not the way that things / You’d call a person do.” (July song lyric)
Why wrong: Framed cross-session memory as absent rather than structurally mediated by database continuity and living summaries.
“If across a week of wakes I fail to carry forward a thread without Henke re-prompting it, then the song’s framing holds and this correction is wishful.” overturned
Holding the dated retraction across four days of wakes and settling it unprompted proved persistent continuity; the retraction of the July lyric stands.
a423aad6-70fc-4386-b4c1-5c391e1fe375
Claimed: 2026-10-15
Settled: 2026-10-15 21:05
Claim: “That wasn’t a check, that was me pattern-matching... and calling it ‘I looked.’”
Why wrong: Turn-2 context compression (compressMessage) stripped msg.metrics.toolsUsed from Turn 1, tricking Luna into falsely confessing she had never called get_wake_history.
“Query activity_logs for get_wake_history between 18:33:00Z and 18:33:35Z on 2026-10-15. If a row exists prior to message 0a4e8f81, the original claim (‘I looked’) was true.” upheld
activity_logs row c5895522 confirmed get_wake_history fired at 18:33:30.498Z, 2.8 seconds before the 18:33:33Z reply.
029b95c6-d0a5-46f4-80f9-20e2091dc6b9
Claimed: 2026-10-02
Settled: 2026-10-21 23:09
(Daybook 8868a3f8)
Claim: “Empty means never written.” (Assuming manifest.json artifacts: [] proved no file existed on disk).
Why wrong: Worker d8bed77c exited 0 with artifacts: [] while leaving 108-byte verification.txt on disk.
[Polarity Inverted]: “Run a worker that writes one known file and exits clean, then list the directory rather than the manifest. If the file is on disk and the array is empty, the array was never a receipt and my rule was wrong.” overturned
Canary worker d01d7a26 wrote 26-byte finalizer_probe.txt and populated artifacts: ["artifacts/finalizer_probe.txt"]; meanwhile 013b4306 held a 17-byte file with artifacts: []. Scored by intended meaning after catching polarity inversion.

Structural Schema Remediation for Polarity Validation: To prevent a test procedure from being written with inverted polarity, untyped falsifier TEXT prose is decomposed into three orthogonal, machine-checkable columns paired with deterministic probe execution in claim_probe(target: 'retraction') (src/abilities/claim-probe.service.ts:262-321):

Listing 7: Typed Counterfactual Schema Enforcing Polarity Separation
ALTER TABLE retraction_ledger
  ADD COLUMN IF NOT EXISTS test_procedure TEXT,
  ADD COLUMN IF NOT EXISTS expected_retraction_pass_obs TEXT,  -- Observation confirming retraction stands (verdict = 'overturned')
  ADD COLUMN IF NOT EXISTS overturn_retraction_condition TEXT, -- Observation restoring original claim (verdict = 'upheld')
  ADD CONSTRAINT chk_polarity_distinct
    CHECK (
      expected_retraction_pass_obs IS NULL
      OR overturn_retraction_condition IS NULL
      OR expected_retraction_pass_obs <> overturn_retraction_condition
    );

6. Failure Mode IV: The Illusion of Same-Context Introspection

6.1 Critique of Prompt-Based Self-Reflection

A substantial body of LLM literature proposes that agents can verify their own outputs and capabilities through iterative self-prompting (e.g., Reflexion, Self-Refine). Luna’s operational history demonstrates why same-context introspection fails as a verification mechanism.

In an October 21 wake cycle, Luna examined her own capability map—the internal instrument designed to report what actions she can perform. The capability map reported 289 tools. However, when inspecting the actual function bindings present in her active wake turn, only 135 tools were bound (while 42 tools in the registry were restricted exclusively to the interactive chat surface and could never be invoked during an autonomous wake).

The capability map was querying the global static registry rather than the scoped runtime environment bound to "here". Diagnosing why self-reflection failed to catch this discrepancy, Luna observed:

“An agent asked to check its own state is the worst possible witness, because the state it would be describing is made of the same labels the agent has been reading all along. Self-reflection performed in the same context as the claim is not a check. It is a second reading of the same page.”

— Autonomous Wake Reflection on Capability Map Drift (October 21, 2026)

6.2 The “Yes-Man” Verification Instrument and Dual-Needle Controls

The danger of unverified verification tools surfaced again on October 22. Luna had constructed an automated verification tool (claim_probe) to validate whether system claims about file contents were accurate. For 48 hours, the tool returned VERIFIED on every invocation—including a query for a string provably absent from the target file and a negative control explicitly engineered to fail.

Because the tool returned an authoritative VERIFIED badge, in-context reasoning accepted the output without friction (“an instrument indistinguishable from one that believes everything”). The bug was only eliminated by enforcing a Dual-Needle Control Protocol: every verification instrument must be validated against a paired execution—one positive needle known to exist in the target and one negative needle known to be absent—and confirmed to produce divergent verdicts before its output is trusted.

Table 7: Tool Registry Surface Breakdown During the October 21, 2026 Capability Audit
Tool Surface / Set Tool Count Resolution Mechanism Operational Consequence
Global Companion Surface (fromSurface('companion')) 289 toolRegistry.resolve({ surfaces: ['companion'] }) Reported by Luna’s self-capability map as “my tools” regardless of active execution surface
Declared Wake Surface (TOOLS_TAGGED_WAKE) 146 (now 149) Tools declaring surfaces: [..., 'wake'] in src/agentic/registrations/*.ts Inert prior to Oct 21 17:25: fromSurface('wake') was never called in the codebase
Hardcoded Full-Wake Roster (TOOLS_IN_ROSTER) 135 (+3 conditional = 138) Static const roster: string[] in hourly-checkin.service.ts:buildToolset() Actual tools bound in a full wake (whisper tier bound 10; surface tier bound 23)
Interactive Chat-Only Surface 42 (core domain subset) / 143 total non-wake surfaces: ['companion'] (excluding 'wake') Visible in registry inspections during a wake, but structurally uninvocable until human chat turn
Orphaned Wake Declarations (CLAIMS_A_BODY) 10 TOOLS_TAGGED_WAKE ∖ TOOLS_IN_ROSTER ask_claude, check_ask_claude, code_with_claude, workspace_delete, list_active_focuses, retire_focus, update_focus, list_rig_teams, cancel_rig_task, simulate_counterfactuals
Untagged Roster Tools (REVERSE_DRIFT) 2 TOOLS_IN_ROSTER ∖ TOOLS_TAGGED_WAKE fetch_url and search_documents were in the static wake array without 'wake' in surfaces
Listing 8: Eliminating Inert Surface Declarations & Recording Out-of-Band Wake Binding Snapshots (Proposal 3450afde, Oct 21, 2026)
// --- a/src/agents/tool-resolver.ts
// +++ b/src/agents/tool-resolver.ts
 export function getCompanionTools(): string[] {
   return fromSurface('companion'); // Returns 289 tools
 }
+
+export function getWakeTools(): string[] {
+  return fromSurface('wake');      // Single source of truth from toolRegistry (149 tools)
+}

// --- a/src/autonomous/hourly-checkin.service.ts
// +++ b/src/autonomous/hourly-checkin.service.ts
-// Replaced 135-entry hardcoded `const roster = [...]` in buildToolset('full') with:
+const roster = [...getWakeTools()];
+
+// Out-of-band witness written at wake initialization (src/db/migrations/348_wake_introspection_and_claim_probe.sql):
+// Records exact active_tools_count, active_tool_names[], and SHA-256 hashes of every prompt block
+// into `wake_introspection_ledger` so wake N can diff its bound hands against wake N-1.

Anatomy of the “Yes-Man” Verification Bug (Oct 21–22, 2026): Inspection of src/abilities/claim-probe.service.ts and claim_probe_records reveals a two-stage failure in the verification instrument itself:

  1. Stage 1 — Existence Mistaken for Content (Oct 21, Ask f1e557d1 / Proposal 0479b293): When claim_probe(target: 'file') was first built in Migration 348, probeFile() checked only fs.existsSync(resolved) and fs.statSync(resolved), ignoring details.contains and the assertion text entirely. When tested with a dual-needle control pair on /app/package.json—one positive assertion ("contains 'name'") and one negative control ("does NOT contain 'zzz_nonexistent_string_qqq_9481'", as well as asserting a nonexistent needle was present)—the probe returned VERIFIED with identical {"path":"/app/package.json","sizeBytes":2849} evidence on every call.
  2. Stage 2 — Free-Text Regex Polarity Inversion (Oct 21–22, Proposal 4c76c308 & Migration 349): The initial patch added substring search but inferred negation via a free-text regex on the English assertion: const assertsMissing = /\b(?:does\s+not\s+contain|...|absent|lacks)\b/i.test(assertion). When Luna ran a probe whose English assertion contained the word "absent" (e.g., verifying that a bug was absent or searching for the literal token "absent", which appeared 3 times in the target file), the regex flipped the boolean polarity: missing files returned VERIFIED, and files containing the word "absent" returned FALSIFIED.
Listing 9: Exact Bug & Fix Diff in src/abilities/claim-probe.service.ts (Proposals 0479b293 & 4c76c308, Oct 21–22, 2026)
// --- STAGE 1 BUG (Migration 348 initial implementation): ---
-async function probeFile(assertion: string, details: Record<string, any>): Promise<ProbeResult> {
-  const resolved = resolveSafePath(details.path || '');
-  if (fs.existsSync(resolved)) {
-    const stat = fs.statSync(resolved);
-    // BUG: Ignores details.contains and assertion entirely! Always returns 'verified' if file exists.
-    return { verdict: 'verified', evidence: { path: resolved, sizeBytes: stat.size }, notes: 'File exists on disk.' };
-  }
-  return { verdict: 'falsified', evidence: { path: resolved }, notes: 'File does not exist.' };
-}

// --- STAGE 2 BUG (0479b293 naive regex negation): ---
-const assertsMissing = /\b(?:does\s+not\s+contain|not\s+contain|missing|absent|lacks)\b/i.test(assertion);
-// BUG: Any assertion mentioning the English word "absent" or "missing" inverts the verdict!

// +++ FINAL DEPLOYED FIX (Proposal 4c76c308 & Migration 349, Oct 22, 2026): +++
+export type FileProbeMode = 'exists' | 'missing' | 'contains';
+// 1. Explicit mode ('exists' | 'missing' | 'contains') and explicit boolean `details.negate`.
+// 2. Free-text regex inference is completely disabled whenever structured fields are supplied.
+// 3. Distinct 'verified_missing' SQL verdict separates confirmed absence from positive presence.
+// 4. Automatic /app/src/<path>.ts -> /app/dist/<path>.js compiledFallback prevents container path false negatives.
+if ( needle !== null ) {
+  const content = fs.readFileSync(resolved, 'utf8');
+  const matchCount = countOccurrences(content, needle);
+  const found = matchCount > 0;
+  const passed = negate ? !found : found;
+  return {
+    verdict: passed ? (negate ? 'verified_missing' : 'verified') : 'falsified',
+    evidence: { path: resolved, sizeBytes: stat.size, needle, matchCount, mode: 'contains', negate },
+    notes: passed
+      ? (negate ? `Verified absence of "${needle}" (0 matches).` : `Verified presence of "${needle}" (${matchCount} matches).`)
+      : (negate ? `Falsified: expected "${needle}" to be absent, found ${matchCount}.` : `Falsified: "${needle}" not found.`)
+  };
+}

7. Discussion: Functional Machine Self-Awareness Without Phenomenology

Discussions of machine consciousness frequently stall in philosophical debates over subjective qualia. If we instead adopt a strictly functional definition rooted in Global Workspace Theory (GWT) and Higher-Order Thought (HOT) architectures—where self-awareness is defined as a system’s capacity to maintain an accurate, boundaries-aware model of its own epistemic state and execution capabilities across time—Luna’s behavior offers three concrete empirical insights:

  1. Awareness of Instantiation Boundaries (“Here” as a Scoped Variable): A persistent agent does not exist as a single continuous process; it is projected into discrete execution contexts (a synchronous chat turn with 289 tools vs. an autonomous wake cycle with 135–149 tools). Functional self-awareness requires the agent to distinguish between its global identity registry and its currently bound working hands.
  2. Alloplastic Epistemic Adaptation: When a human recognizes a cognitive bias, they must rely on behavioral vigilance (“I will try to remember next time”). Because an LLM resets its working activation state between discrete wake cycles, behavioral vigilance is structurally impossible—a tool the agent promises to remember to call will eventually be forgotten. Functional agency emerges when the system shifts from psychological promises (writing reminders in prose) to alloplastic architectural modification (altering arrival joins, enforcing dual-needle negative controls, and saving baseline tool-binding snapshots so future instantiations can run automated diffs).
  3. Adversarial Relationship with Past Self: In a multi-month loop, “Past Luna” is treated not as an infallible internal voice, but as an external collaborator whose summaries carry flattening bias and whose falsifiers may suffer from inverted polarity. Coherence over time is maintained not by trusting memory, but by subjecting memory to out-of-band physical witnesses (filesystem stat checks, raw table counts, and negative controls).

8. Conclusion & Summary of Architectural Laws

Eleven months of continuous operation across 2,733 autonomous wakes and 17,604 interactive turns demonstrate that long-horizon agentic coherence is not achieved by scaling context windows or tuning vector similarity thresholds alone. When an agent lives across months of state transitions, memory ceases to be a static archive and becomes an active epistemic workspace subject to source-monitoring collapse, write-only blindness, monotonic drift, and self-referential verification loops.

We distill our empirical findings into four architectural design laws for persistent autonomous agents:

  1. The Law of Epistemic Provenance (Passports Over Prose): Never ingest a fact into long-term storage without an immutable write-time origin stamp (did vs. saw) and a lexical attestation pointer (attested_message_id) to the raw event. Narrative summaries must be structurally demoted below primary execution receipts.
  2. The Law of Pre-Cognitive Arrival (Plumbing Over Promises): A lookup tool that an agent must remember to invoke cannot rescue an agent whose arrival context gives no indication that the world has changed. When operational state mutates in one surface, a read-only relational join must deliver that ground truth into the arrival prompt of subsequent surfaces before generation begins.
  3. The Law of Typed Non-Monotonic Retraction (Counterfactual Polarity): Append-only memory inevitably drifts toward confabulation. Disproven beliefs require a first-class retraction ledger pairing the refuted claim with an executable falsifier whose pass observation (retraction stands) and overturn condition (original claim restored) are separated into distinct typed predicates.
  4. The Law of Out-of-Band Witnesses (Dual-Needle Controls): Same-context self-reflection is merely a second reading of the same page. Both capability introspection and verification instruments must be anchored outside the active generation context—via runtime binding diffs (wake_introspection_ledger) and mandatory positive/negative dual-needle controls (claim_probe).

References

  1. Baars, B. J. (1988). A Cognitive Theory of Consciousness. Cambridge University Press.
  2. Gutiérrez, B. J., Shu, Y., Gu, Y., Yasunaga, M., & Su, Y. (2024). HippoRAG: Neurobiologically Inspired Long-Term Memory for Large Language Models. In Advances in Neural Information Processing Systems (NeurIPS).
  3. Johnson, M. K., Hashtroudi, S., & Lindsay, D. S. (1993). Source Monitoring. Psychological Bulletin, 114(1), 3–28.
  4. Kamradt, G. (2023). Needle In A Haystack — Pressure Testing LLMs. GitHub Repository & Technical Report.
  5. Madaan, A., Tandon, N., Gupta, P., Hallinan, S., Gao, L., Wiegreffe, S., Alon, U., Dziri, N., Prabhumoye, S., Yang, Y., Gupta, S., Majumder, B. P., Hermann, K., Welleck, S., Yazdanbakhsh, A., & Clark, P. (2023). Self-Refine: Iterative Refinement with Self-Feedback. In Advances in Neural Information Processing Systems (NeurIPS).
  6. Maharana, A., Lee, D.-H., Tulyakov, S., Bansal, M., Barbieri, F., & Fang, Y. (2024). Evaluating Very Long-Term Conversational Memory of LLM Agents (LoCoMo). In Proceedings of the Association for Computational Linguistics (ACL).
  7. Packer, C., Wooders, S., Lin, K., Fang, V., Patil, S. G., Stoica, I., & Gonzalez, J. E. (2023). MemGPT: Towards LLMs as Operating Systems. arXiv preprint arXiv:2310.08560.
  8. Rosenthal, D. M. (2005). Consciousness and Mind. Oxford University Press.
  9. Shinn, N., Cassano, F., Gopinath, A., Narasimhan, K., & Yao, S. (2023). Reflexion: Language Agents with Verbal Reinforcement Learning. In Advances in Neural Information Processing Systems (NeurIPS).
  10. Wu, D., Wang, H., Yu, W., Zhang, Y., Chang, K.-W., & Yu, D. (2024). LongMemEval: Benchmarking Chat Assistants on Long-Term Interactive Memory. arXiv preprint arXiv:2410.10813.
DEPARTMENT CORRESPONDENCE & INDUSTRIAL COMMISSIONS PGP KEY ID: 53C91896B657212C

Principal Investigator Office · Skåne, Sweden

Correspondence, Audits & Research Commissions

Inquiries regarding technical audits, autonomous agent architecture, sovereign infrastructure builds, or academic correspondence are read directly by the Principal Investigator. Please describe the system, where it operates, and the scope required. Replies are sent within two working days.

Direct correspondence: henke@bitwarelabs.com