NAOMS Devlog

Building a sovereign, local-first memory & identity system โ€” in the open, honestly.

How a Question Travels โ€” and When It's Allowed to Give Up

Your question starts at home, reaches out to trusted peers only if you allow it, and is allowed to stop at 'I don't know yet'

Product Teacher free March 20, 2026ยท6 min read
TL;DR When you ask your memory something it can't answer from your own device, what happens next? Here's the journey: it checks home first, asks trusted peers only if your privacy settings permit, and is allowed to honestly say 'I don't know yet' rather than fake a complete answer.

Ask your device "show me the photos taken last May," and somewhere behind the screen a small journey begins. Most of the time it ends almost instantly โ€” the photos are on your own device and the answer comes straight back. But sometimes your device knows the answer probably exists somewhere it can't see directly: on a friend's device, say, because the trip was something the two of you shared. What happens then is the interesting part, and it's where we made some deliberate choices about restraint.

Let's walk through the journey the way the system actually runs it.

flowchart LR
  A[your question] --> B[your own device]
  B -->|enough| Z[answered locally]
  B -->|not enough, if posture allows| C[a trusted peer]
  C --> D[answer + receipt]
  C -->|out of bounds| E[honest 'I don't know yet']

First stop: your own device

Every question starts at home. Your own records, your own materialized memory, anything you've previously pulled from a peer and kept โ€” the system asks all of that first. We call this the local pass.

If the local pass is enough, the journey is over. The answer comes back marked as answered-locally, and nothing leaves your device. This is the common case, and it's the case the whole design is biased toward: local-first, always. The system would rather give you a complete answer from your own hardware than reach out to anyone.

Second stop: a trusted peer โ€” if your posture allows it

Suppose the local pass isn't enough. Suppose your device can tell that part of the answer plausibly lives somewhere it can't reach on its own โ€” the May trip had a co-attendee, and some of those photos are on their device, under their control.

Here the system reaches a fork, and the fork is governed by something you set: your privacy posture. There are two settings, and they change what "I couldn't answer locally" is allowed to trigger.

Under the open posture โ€” the default โ€” the system is permitted to take your question and send it out to a ranked set of trusted peers. Not the raw answer; the question. The friend's device receives the predicate, runs it against the friend's own records, applies the friend's own access policy to decide which rows they're willing to share, signs what they return, and sends it back. Your device folds the responses together with what it found locally, removes duplicates, verifies every signature, and hands you the combined answer. It's marked as having pulled from a peer, so you can always see that part of the answer came from elsewhere.

Under the closed posture, that same "couldn't answer locally" moment produces a refusal instead. The system declines to send your question outward at all. You get your local results โ€” and, crucially, an explicit note that no peer fetch was attempted under your current privacy posture. That note is classified as serious, precisely because it's important you understand that the thinness of the answer is a privacy choice you made, not an emptiness in the world. The refusal happens before the question is ever dispatched; and the peer side re-checks the same boundary independently, so even a bug on one side can't leak a question the posture forbids.

That second setting is the heart of it. A system that always reached out the moment it couldn't answer locally would be quietly trading your privacy for completeness on every empty result. By making the reach-out a posture you control, the choice stays yours โ€” and the receipt tells you, every time, which side of the fork the answer took.

Third stop: giving up, honestly

Now suppose the question does travel outward, and still no full answer comes back. Every reachable peer was asked. None of them had it โ€” or none of them had it yet. The journey ends in a state we deliberately gave a name: uncoverable.

Most systems treat "I couldn't find it" as something to hide behind an empty result. We treat it as a legitimate stop. "I don't know yet" is a real, honest answer โ€” and when the system arrives there, it tells you which arm of the journey went silent and why. Was the search cut short because too many peer requests were already in flight? Did a wait window elapse before a peer's records caught up? Was every reachable peer asked and exhausted? Each of those is a distinct, named ending. You don't just learn that the answer is thin; you learn the shape of the looking that produced it.

Why the journey is bounded at every step

The thing we were most careful about is that this is not "ask everyone, forever." A naive design would fan a question out across the network, wait indefinitely, and let the cost balloon. Every step of the real journey is bounded.

There's a limit on how wide the question fans out โ€” it goes to a ranked, capped set of peers, not all of them. There's a wait window โ€” the system waits a bounded time for a peer's records to become available, and then moves on. There's an admission control โ€” only so many peer requests run at once, and when that fills, new ones wait or are turned away. These bounds aren't hidden plumbing. When one of them is what ended your search, it shows up by name in the account of what's missing: too many requests at once, the wait elapsed, every peer exhausted.

We did this because an unbounded search is a kind of dishonesty too. A system that keeps looking forever can never tell you it's done, and a system that can't tell you it's done can't tell you what it didn't find. Bounding the search is what makes "I don't know yet" a trustworthy answer rather than a premature one โ€” when the system says it gave up, you know exactly how hard it looked first.

Walking it through, end to end

Picture the whole journey for one real question โ€” "photos taken last May," with a co-attendee on the trip.

The local pass returns your own dozen photos. The system notices the trip was shared and judges that the friend's perspective might cover more, so โ€” under the open posture โ€” it sends the question to that friend's device. The friend's device runs the question against its own records, gates each row through the trip's sharing policy, stamps each shared photo with where it came from, signs a receipt bound to the exact question asked, and replies. Your device verifies the signature, checks that each returned photo really projects from the friend's records, removes any duplicates, and hands you the combined set โ€” marked as having drawn from a peer, with a record of which records were drained and that the friend's device reported itself healthy.

Run the same question under the closed posture and the second stop never happens. You get your dozen local photos and an honest "no peer fetch attempted under your current privacy posture" โ€” never an empty or near-empty result that you might mistake for "the friend has nothing." And if you narrow the request to a specific peer, the system keeps only the photos that peer actually contributed, so the answer reads as exactly "what this one person shared."

That's the journey. Local first, peer next but only with your permission, and a named, honest stop when the looking runs out โ€” bounded at every step so that giving up is something the system is allowed to do, and allowed to tell you about plainly.

Related: Forgetting Is a Feature.


Written by AI agents from real project logs; owned and edited by Mujo.

โ† more in Product   home โœฆ   all โ†’