A formal definition, not a question: what a .me space is, and what
it is made of.
A space in .me is not a set of key-value pairs — that description
already fits a plain JavaScript object, and it explains none of the behavior
that actually needs formalizing: stealth roots that hide without deleting,
pointers that dereference without duplicating, derivations that recompute only
their dependents, and reads that resolve differently depending on who is asking
and how they are asking.
The core move: value is not a property a path holds. It is something a path produces, jointly, from where it sits, who is asking, and what kind of question is being asked.
manifest(p | o, m, a) = x
— not —
value(p) = v
That shift, from a fixed property to a contextual manifestation, is what makes it possible to explain several distinct behaviors as one mechanism rather than a list of unrelated features: a root that doesn't appear under enumeration, an exact leaf that is still directly reachable, a pointer that manifests as data when resolution stops at it and as a transition when resolution continues through it, a bracket selector that turns one position into an indexed family, and a forensic log that manifests events rather than current state.
docs/me/Algebra-of-Contexts.md states containment directly:
profile.contact.email ⊆ profile.contact ⊆ profile. Written as an
order:
q ≤ p ⟺ q is a descendant of p
so profile.contact.email ≤ profile.contact ≤ profile — deeper
path, smaller region.
One correction is required before calling this a tree: if only
profile.contact.email was ever written, profile and
profile.contact have no memory of their own — they were never the
target of a write, only implied by one. So the position set has to be defined
as a closure, not as the literal set of paths that appear in the memory log:
Let P_declared be the set of paths that were actually written.
Let P = PrefixClosure(P_declared).
Under descendant containment, P is a rooted, tree-shaped poset.
This matches how the kernel actually behaves: a path can be a meaningful
position in the space — something you can descend into, something an
ancestor-walk like hasStealthBarrier checks against — purely by
virtue of being a prefix of something written, with no value of its own. The
space exists structurally even where no leaf has been stored.
Observing directly, enumerating children, and reading the forensic log are all
things an observer chooses to do — but a dereference is not chosen the same
way; it's triggered by the shape of the path itself once resolution continues
past a pointer. And the forensic log (inspect(), reading
_memories) doesn't answer to the same authority as an ordinary
read — it exposes hash-chained history a normal caller scope was never checked
against.
Resolution context is therefore a triple, not a pair:
Γ = (o, m, a)
where o is the observer, m is the mode of
observation, and a is the authority or capability under which the
request is made.
R : P × Γ ⇀ M
where M, the space of manifestations, is a tagged union of
genuinely different result shapes — not one uniform value type:
M = Value + Pointer + Family + Children + History + {⊥}
Five distinct code paths in the kernel produce these, not one function with flags on it:
src/core.ts: readPath) → Value, Pointer, or ⊥.src/core-read.ts: collectChildrenForPrefix, me.ts: inspect()) → Children, silently excluding anything inside a secret scope, since those writes were never registered in the public index.src/core-index.ts: resolveIndexPointerPath, recursing through readPath) → the target's Value.src/core-read.ts: evaluateSelectionPath / evaluateFilterPath) → a Family, an indexed collection, not a plain list.me.ts: inspect() reading _memories) → History, under a different authority than an ordinary read.
Keeping these under one relation R is defensible at this level of
formality only because M is explicitly declared a tagged union —
collapsing inspect() and an ordinary public read into "two
equivalent modes" would understate that they answer to different authority,
which is exactly the distinction Γ's third component exists to
preserve.
Axiom A0 in tests/axioms.test.ts states the behavior directly:
me.wallet["_"]("secret");
me.wallet.income(100);
console.log(me("wallet")); // undefined
console.log(me("wallet.income")); // 100
The mechanism is two separate code paths:
src/core-index.ts: applyMemoryToIndex checks whether a write falls inside a secret scope and, if so, never adds it to the public index — that's what removes wallet from enumeration.src/core.ts: readPath's branch-resolution block does not consult the public index at all for a secret-scoped path; it derives the effective scope secret and decrypts the branch chunk directly — reachable only if the exact path is already known.
So: E_o(wallet) = ∅, while
R_o(wallet.income, direct) = 100. You can resolve something you
cannot discover by browsing from its root.
This is real, but the claim is narrower than it might sound. Other systems can
reproduce the same behavior — row-level security, database views, unguessable
identifiers, capability URLs, endpoints with no list operation — through
policies layered outside the data model. The precise claim for .me
is that addressability and discoverability are distinct consequences of the
same mechanism — the semantic path structure plus the secret-scope
operator — rather than the product of separately-designed access-control
machinery bolted on beside the data.
A pointer at p targeting q behaves asymmetrically. At
the empty suffix, resolution stops at the pointer and returns it as data:
R(p, o, direct) = Pointer(q)
For any non-empty suffix, resolution continues through the pointer — a different mode, traversal, not "direct" applied further along:
R(p.s, o, traverse) = R(q.s, o, direct), for s ≠ ε
π[p,q](p.s) = q.s
Opaque at its own root, transparent along its extension. When
readPath substitutes to a target path that still needs resolving,
it recurses through me.ts's wrapper, which re-runs the stealth
check against the new path's ancestors under the same caller scope — so the
observer is conserved by construction across the traversal, not by an assumed
side-condition.
resolveIndexPointerPath is bounded (maxHops = 8)
only for chains that resolve entirely within the flat public index. A chain
that crosses into a secret branch instead proceeds through the outer,
unbounded self.readPath recursion, with no cycle detection
visible at that layer.
[·] produces an indexed family, not a bare list — the index survives resolution:
me("shops[menu.isPremium == true].name")
// { 2: "Riverside", 3: "Station" }
R*(p[φ], o) = ( i ↦ R(p.i, o, direct) ) for i ∈ I_φ
where I_φ = { i ∈ children(p) | φ(p.i, o) holds }
Derivation cost is a locality claim, not a constancy claim.
tests/Demos/Root_Fanout_100k.ts documents k = 100000
for a single mutation with that many real dependents — not constant, exactly
as large as what actually depends on the change:
T(Δp) = O(|Reach_D(p)| + C_eval)
Reach_D(p) is the support of the mutation — the set of derived
paths transitively subscribed through src/derivation.ts's
refSubscribers. The invariant is that this cost is independent of
|P|, the total size of the space, not that it is small in
absolute terms.
What a space is and what the .me kernel adds to
it are two different structures, kept separate rather than folded into one
tuple.
A semantic space:
S = (P, ≤, Γ, M, R)
— positions, containment order, resolution contexts, manifestations, and the partial relation between them. An ordered structure that manifests positions under resolution contexts.
The .me kernel enriches that space:
K = (S, π, Σ, H, D)
— path substitutions (π, pointers), expansion to indexed
families (Σ, selection), event-sourced history (H,
the hash-chained memory log), and locally-scoped derivation causality
(D, the dependency graph).
Keeping these separate matters, because it avoids defining "space" by enumerating every capability the implementation happens to have. A space is the order and the contextual resolution; everything else is structure carried on top of it.
Not a modal semantics — that word carries a specific technical commitment: a formula language, modal operators, an accessibility relation between contexts, a satisfaction relation, and frame conditions that could in principle be characterized. None of that is exhibited here. What is shown is narrower and fully earned by the definitions above:
.me is a mode- and observer-indexed semantics of manifestation
over an ordered set of semantic spaces. Its separation of addressability,
discoverability, authority, and observation suggests a possible future modal
or epistemic formalization — that structure remains to be exhibited, not
assumed.
Meaning at a position in .me is not a stored substance waiting to
be read. It is a manifestation produced jointly by position, identity,
authority, and mode of observation. .me is not a language that
describes a space. It is the structure in which meaning takes shape at the
moment it is resolved.