zetetes — Specification
version 0.1
This document specifies the zetetes protocol: a hybrid-query
coordinator over a metatheca vault that has
been extended with semopsis,
logopsis, or both. zetetes pins a
(semopsis-state, logopsis-state, fusion-config) triple as a
content-addressed blob, advances a small head pinax over the chain
of such triples, and answers hybrid queries by issuing a query to
each available extension at the pinned states and fusing the
results.
The specification is language-agnostic. The reference implementation
is in Rust (zetetes-rs/).
zetetes is structurally different from the layers it sits above. metatheca, semopsis, and logopsis each define a substantive content contract: metatheca defines the vault as a chain of versioned semantic states; semopsis defines a semantic view over that vault; logopsis defines a lexical view. zetetes defines no new content. It is a seeker (whence the name, ζητητής, "one who inquires") that consults the views built by semopsis and logopsis on the user’s behalf and returns a fused ranking. Its durable state is minimal: which views to consult, at which states, with which fusion config.
Like the extensions it consults, zetetes occupies its own dedicated
cella under the metatheca vault root, at the fixed path
<vault>/ext/zetetes/cella/, separate from metatheca’s
source-of-truth cella and from each extension’s cella. The cella
holds zetetes-state blobs and the zetetes-head pinax; it is wholly
derivable (a fresh zet init followed by zet advance
invocations restores any reachable configuration) and MAY be
discarded at any time (§5.6).
For motivation, design choices, and the relationship to the other
layers, see README.md. For the substrates
and extensions this document builds on, see
metatheca SPEC.md,
../../../syntheca/SPEC.md,
../../../apotheca/SPEC.md,
../semopsis/SPEC.md, and
../logopsis/SPEC.md.
The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY in this document are to be interpreted as described in RFC 2119.
1 Scope and terminology
This document specifies zetetes Phase 1: a single coordinator over at most one semopsis chain and at most one logopsis chain on a single metatheca vault, with reciprocal rank fusion as the only specified fusion algorithm, and explicit-advance semantics (no auto-snap to extension heads at query time). Phase 1 is the v0.1 release surface; deferred items are listed in §10–§11.
Terminology not redefined here is inherited from metatheca SPEC §1, syntheca SPEC §1, apotheca SPEC §1, semopsis SPEC §1, and logopsis SPEC §1.
1.1 Source
A source is one of the two extensions zetetes can consult:
the literal string "semopsis" or the literal string
"logopsis". A zetetes-state references zero, one, or both
sources.
1.2 Fusion config
A fusion config is the parameter set that determines how zetetes combines per-source ranked result lists into a single ranked output. Phase 1 specifies one fusion algorithm:
Reciprocal Rank Fusion (RRF), parameterized by:
k: a positive number, the rank-smoothing constant. Default60.weights: a map from source name to non-negative IEEE 754 binary64 weight. Default:{"semopsis": 1.0, "logopsis": 1.0}when both sources are pinned;{"<source>": 1.0}when only one is pinned.
The RRF score for a document d under config
(k, weights) over the set of pinned sources S is:
score(d) = Σ_{s ∈ S, d ∈ results(s)} weights[s] / (k + rank_s(d))
where rank_s(d) is the 1-based rank of d in source
s’s result list and the sum is taken only over sources in
which d appears.
Phase 1 zetetes MUST implement RRF and MUST NOT implement any
other fusion algorithm. The algorithm name is recorded in the
zetetes-state blob (§4.2) so that a future Phase 2
zetetes implementation can interoperate with Phase 1 chains by
recognizing that fusion algorithms other than "rrf" are out
of its support.
1.3 Zetetes-state
A zetetes-state is a moment in the coordinator’s history. Each zetetes-state is materialized as a content-addressed zetetes-state blob (§4.2) capturing the pinned semopsis search-state hash (or null), the pinned logopsis search-state hash (or null), the fusion config, the metatheca state hash that was current at advance time, and a back-pointer to the prior zetetes-state. The set of zetetes-states linked through these back-pointers is the zetetes-state chain.
The genesis zetetes-state is the unique zetetes-state with
previous = null, created by zet init
(§5.1).
A zetetes-state with both semopsis = null and
logopsis = null is permitted but useless; zet query
against such a state returns an empty result set with no error. This
case exists so that zet init can be invoked before either
extension has been initialized, with zet advance filling in
the pins later.
1.4 Zetetes-head
The zetetes-head is the single mutable pointer identifying the current zetetes-state. It is realized as an apotheca pinax (§6) on the zetetes cella, holding the BLAKE3 hash of the current zetetes-state blob.
The zetetes-head pinax is disjoint from metatheca’s head,
semopsis’s head, and logopsis’s head: each pinax lives
on its own cella (<vault>/cella/,
<vault>/ext/semopsis/cella/,
<vault>/ext/logopsis/cella/, and
<vault>/ext/zetetes/cella/ respectively) and the four advance
independently.
1.5 Zetetes-state reference
A zetetes-state reference (or zetetes-stateref) follows the same grammar as metatheca’s stateref (metatheca SPEC §1.7), resolving against the zetetes-state chain:
a full BLAKE3 hash;
a hash prefix of at least 8 lowercase hex digits, unambiguous within the chain;
an ISO-8601 date or date-time, denoting the most recent zetetes-state with
created_at_ns ≤ that_instant;a relative reference:
~or~NforNnon-negative;the literal
current.
A zetetes-stateref MUST resolve to exactly one zetetes-state or fail.
2 Coexistence with metatheca, semopsis, and logopsis
zetetes operates on the same vault root as the layers it consults
but on its own dedicated cella at <vault>/ext/zetetes/cella/,
separate from metatheca’s source-of-truth cella at
<vault>/cella/ (metatheca SPEC §7) and from each extension’s
own cella (<vault>/ext/semopsis/cella/,
<vault>/ext/logopsis/cella/). All zetetes durable state lives
as deposita and pinakes on its own cella; it introduces no new
storage primitive.
zetetes MUST NOT write to metatheca’s cella or to any extension cella. Its writes are confined to:
new deposita carrying zetetes-state blobs (§4.2) on the zetetes cella;
the single search-head pinax named in §6.1, on the zetetes cella.
zetetes does read from the other cellae: from metatheca’s cella to
record metatheca state hashes for audit
(§4.2), and from each pinned extension’s cella to
issue per-source queries (§5.3).
A vault MAY contain a zetetes chain with at most one of semopsis
/ logopsis pinned (or neither, transitionally). A zetetes chain
MUST NOT exist without a metatheca chain on the same vault;
zet init (§5.1) requires metatheca’s head
pinax to be present at <vault>/cella/.
A zetetes-state’s pinned semopsis hash MUST name a search-state
present on the semopsis cella at advance time, and likewise for
logopsis. zetetes does not verify ongoing reachability after
advance — if a future operation removes a referenced search-state
(deletion is currently out of scope across the stack,
§10) or the extension’s cella is destroyed
(semopsis SPEC §5.8 / logopsis SPEC §5.8), the zetetes-state remains
valid as a record but zet query against it fails with
NotFound for the missing source.
3 Identifiers and time
3.1 Hashes
Content-addressing throughout zetetes uses syntheca’s BLAKE3 hash. Wire form: 64 lowercase hex digits.
3.2 Time
All timestamps follow metatheca SPEC §2.3: nanoseconds since the Unix epoch as a signed 64-bit integer, monotonically non-decreasing within a single vault process.
4 Wire formats
4.1 Canonical JSON
The single JSON blob defined by this specification (zetetes-state §4.2) is serialized as canonical JSON per RFC 8785, identical to metatheca SPEC §3.1.
4.2 Zetetes-state blob
A zetetes-state blob is a canonical-JSON object:
{
"type": "zetetes/state",
"version": 1,
"previous": "<blake3-hex>" | null,
"metatheca": "<blake3-hex>",
"semopsis": "<blake3-hex>" | null,
"logopsis": "<blake3-hex>" | null,
"fusion": {
"algorithm": "rrf",
"k": <number>,
"weights": { "semopsis": <number>, "logopsis": <number> }
},
"created_at_ns": <integer>
}
Field constraints:
typeMUST be the literal string"zetetes/state".versionMUST be the integer1.previousMUST be either a BLAKE3 hash naming a zetetes-state blob present in the cella, ornull(genesis zetetes-state only). Exactly one zetetes-state in any chain hasprevious = null.metathecaMUST be a BLAKE3 hash naming a metatheca state blob present in the cella at the time the zetetes-state was deposited. It records which metatheca state was current when the advance occurred. zetetes does not require the pinned semopsis and logopsis search-states to themselves reference this metatheca state; the field is recorded for audit purposes only.semopsisMUST be either a BLAKE3 hash naming a semopsis search-state blob present on the semopsis cella (<vault>/ext/semopsis/cella/), ornull. If non-null, the semopsis chain MUST be present on that cella (semopsis SPEC §6).logopsisMUST be either a BLAKE3 hash naming a logopsis search-state blob present on the logopsis cella (<vault>/ext/logopsis/cella/), ornull. If non-null, the logopsis chain MUST be present on that cella (logopsis SPEC §6).fusion.algorithmMUST be the literal string"rrf"in Phase 1.fusion.kMUST be a positive finite IEEE 754 binary64 value.fusion.weightsMUST be a JSON object whose keys are exactly the source names corresponding to non-null pin fields. That is: ifsemopsisis non-null andlogopsisis non-null,weightsMUST contain both"semopsis"and"logopsis"keys; if only one pin is non-null,weightsMUST contain only the corresponding key; if both pins are null,weightsMUST be the empty object. Each value MUST be a non-negative finite IEEE 754 binary64.created_at_nsMUST be an integer per §3.2.
A zetetes-state’s identity is the BLAKE3 hash of its canonical-JSON bytes.
The triple (semopsis, logopsis, fusion) is recorded together
because the fusion config is meaningful only relative to the set of
pinned sources. Recording them in a single blob ensures they cannot
be observed in inconsistent combinations.
5 Operations
A zetetes-equipped vault exposes the following protocol operations. Each is total: it terminates with one of the outcomes listed for it.
5.1 init
Creates a genesis zetetes-state on a vault that already has a metatheca chain.
Verify metatheca’s
headpinax is present on metatheca’s cella at<vault>/cella/(§2); fail withNotFoundotherwise.Verify no zetetes cella exists at
<vault>/ext/zetetes/cella/; fail withConflictotherwise.Open a fresh syntheca cella at
<vault>/ext/zetetes/cella/, creating any missing parent directories. All subsequent deposits and the zetetes-head pinax target this cella.Resolve the caller-supplied initial pins: a. If a semopsis ref was supplied, resolve it per semopsis SPEC §5.6 against the semopsis cella to a search-state hash; otherwise pin null. b. If a logopsis ref was supplied, resolve it per logopsis SPEC §5.6 against the logopsis cella to a search-state hash; otherwise pin null.
Construct the genesis zetetes-state blob:
previous = null,metatheca = <current metatheca head>,semopsis = <as resolved>,logopsis = <as resolved>,fusion = <as supplied or default>(default per §1.2),created_at_ns = now(). The fusionweightsmap MUST be constructed to match the set of non-null pins per §4.2. Deposit the blob on the zetetes cella; letgbe the returned hash.Set the zetetes-head pinax (§6) on the zetetes cella to
gwithexpected = None.
A genesis zetetes-state MAY have both pins null. This permits
initializing zetetes before either extension exists; the first
zet advance populates one or both pins.
On any failure prior to step 6, the implementation MUST leave no partially-initialized zetetes cella. If the cella was created in step 3, it MUST be removed before returning the failure.
5.2 advance
Atomically advances zetetes-head from the current zetetes-state to a new zetetes-state with updated pins, updated fusion config, or both.
Inputs (all optional):
--semopsis <ref>: a semopsis search-stateref, or the literalcurrent(snap to current semopsis-head), or the literalnone(clear the pin).--logopsis <ref>: a logopsis search-stateref, or the literalcurrent, or the literalnone.--fusion <fusion-spec>: a new fusion config (algorithm name,k, and weights) or a delta thereof.
When an input is omitted, the corresponding field is inherited
unchanged from the current zetetes-state. At least one of
--semopsis, --logopsis, or --fusion MUST be
supplied; advance with no inputs is Malformed.
Read the current zetetes-state blob via the zetetes-head pinax (§6); compute the storage digest
dof the head pinax bytes:sha256over the bytes returned bysyntheca.get_pinax, or remembered from the prior successfulset_pinax(apotheca SPEC §2.5/§3.5expectedsemantics).For each supplied pin input, resolve it:
currentresolves to the corresponding extension’s current search-head (semopsis SPEC §6 / logopsis SPEC §6).noneresolves to null.Any other value is treated as a search-stateref and resolved per the corresponding extension’s resolve operation (semopsis SPEC §5.6 / logopsis SPEC §5.6). Inputs that name a search-state not present in the cella fail with
NotFound.
Compute the new pin set: each field is the supplied value if the input was provided, else the current zetetes-state’s value for that field.
Compute the new fusion config. If
--fusionwas supplied, use it; otherwise inherit from the current zetetes-state. The resultingweightsmap MUST match the set of non-null pins per §4.2: if a pin moves from null to non-null without a fusion override, the implementation MUST insert that source’s weight with the default value1.0; if a pin moves from non-null to null, the implementation MUST remove that source’s weight.Construct the new zetetes-state blob:
previous = <current zetetes-head>,metatheca = <current metatheca head>,semopsis = <as computed>,logopsis = <as computed>,fusion = <as computed>,created_at_ns = now(). Deposit it; letsbe the returned hash.Call
syntheca.set_pinax(name = "head", bytes = s_bytes, expected = Some(d))against the zetetes cella.
The commit point is step 6. Steps 1–5 are pre-commit and produce only content-addressed deposita that are safe under interruption.
On Conflict from step 6, another writer advanced zetetes-head
concurrently. The caller MAY retry from step 1.
5.3 query
Given a query string and a zetetes-stateref, return the top k
documents by fused score.
Resolve the zetetes-stateref per §1.5 to a zetetes-state hash
z. Fetch and parse the zetetes-state blob; extract its pinned semopsis and logopsis search-state hashes and its fusion config.Determine the active source set
S: the set of sources whose pin field is non-null.If
Sis empty, return an empty result set with no error.For each source
s ∈ S, issue a query againsts’s extension at its pinned search-state. The query string is passed unchanged to each extension; the extensions are responsible for their own analyzer (logopsis) or embedding (semopsis) processing per their respective specs. Implementations SHOULD issue the per-source queries in parallel.The two extensions interpret the query string under divergent semantics: logopsis parses it as a structured boolean expression with phrase delimiters (logopsis SPEC §5.5.1), while semopsis treats it as opaque bytes to be embedded under its model (semopsis SPEC §5.5). A query like
foo AND bartherefore drives a logical AND in logopsis and an embedding of the literal stringfoo AND barin semopsis. This asymmetry is intrinsic to passing the same input through two retrieval modalities; per-source query rewriting is deferred to a future phase (§10). Callers issuing structured queries should expect the semopsis side to contribute results based on embedding similarity to the literal query string.For each source, request a result set of size at least
k. Implementations SHOULD requestmax(k, k_internal)wherek_internalis implementation-defined and typically larger thank(e.g.4 * kor100) to give RRF a wider candidate pool. Larger candidate pools improve fusion quality at modest cost.
Compute fused scores per §1.2 using the zetetes-state’s fusion config. Per-source hits are joined across sources by
entry: documents present in only one source’s result list contribute their single weighted reciprocal-rank term; documents present in both contribute the sum.Return the top
kdocuments by descending fused score, each as(entry, blob, fused_score). Equal fused scores MUST break by ascendingentry(bytewise UUID order), matching the per-source tie rules. The returnedblobMUST be the one reported by the source with the larger weighted reciprocal-rank contributionweights[s] / (k + rank_s(d)); when the contributions are equal, the logopsis blob. (The two sources can report the same entry with different blobs, since the two pins may index different metatheca states.) Per-source ranks and scores MAY be exposed via an implementation-defined verbose mode but are not part of the protocol’s required output.
query is read-only: it MUST NOT modify any depositum or
pinax.
If a per-source query fails with a protocol error
(e.g. NotFound because the pinned search-state is no longer
present on the cella, or AnalyzerMismatch /
ModelMismatch), zet query MUST surface that error
rather than silently dropping the source. Hybrid queries with a
partially failed source set are not specified to fall back to the
surviving source; this avoids producing results that disagree with
the audit trail.
5.4 Resolve a zetetes-state reference
Given a zetetes-stateref (§1.5) and the current zetetes-head, return the unique zetetes-state hash it denotes. Algorithmically identical to metatheca SPEC §5.3 with the zetetes-state chain substituted.
5.5 Walk the zetetes-state chain
Algorithmically identical to metatheca SPEC §5.4 with the zetetes-state chain substituted.
5.6 Destroy
Removes the zetetes cella and all zetetes state from the vault.
Inputs: none.
If
<vault>/ext/zetetes/cella/is absent, fail withNotFound.Recursively remove the directory
<vault>/ext/zetetes/(including the cella and any extension-private auxiliary state under it).
Destroy is total: on completion, no zetetes state remains on the
vault. metatheca state and any extension state are unaffected. A
subsequent zet init (§5.1) succeeds if and only
if destroy completed.
Because zetetes-states are small and cheap to recreate (a fresh
zet init followed by zet advance invocations restores
any desired pin configuration), destroy is the supported recovery
mechanism for a corrupted zetetes cella. The audit trail of prior
zetetes-states is lost; this is the protocol’s stance that the audit
trail is a convenience, not a load-bearing artifact.
Destroy MUST NOT touch <vault>/cella/,
<vault>/index.db, or any other entry in <vault>/ext/.
6 Zetetes-head pinax
6.1 Name
The zetetes-head pinax MUST be stored on the zetetes cella under
the apotheca pinax name head (four ASCII octets: h,
e, a, d). This name is fixed by this
specification.
The name is a valid apotheca name (apotheca SPEC §4.1): non-empty,
length 4, no /, no NUL. zetetes therefore imposes no
multi-segment-name requirement on the underlying apotheca
implementation.
The pinax shares only its name with metatheca’s head
(metatheca SPEC §6.1), semopsis’s head (semopsis SPEC §6.1),
and logopsis’s head (logopsis SPEC §6.1); the four pinakes
live in disjoint cellae and never collide.
6.2 Bytes
The zetetes-head pinax bytes follow metatheca SPEC §6.2 verbatim: the 64-octet ASCII encoding of the current zetetes-state’s BLAKE3 hash as 64 lowercase hex digits, with no trailing newline or whitespace.
6.3 Compare-and-swap protocol
All updates to zetetes-head MUST go through
syntheca.set_pinax with expected set to the SHA-256
digest of the current zetetes-head bytes, identical in mechanism to
metatheca SPEC §6.3. The genesis case (init,
§5.1) sets zetetes-head with expected = None.
7 CLI surface
The reference CLI binary is zetetes with the recommended
alias zet. It exposes the protocol against the vault rooted
at the current working directory unless overridden with
--vault <PATH>.
This section specifies the protocol-bearing subcommands. Diagnostic output formatting is implementation-defined unless otherwise noted.
7.1 zet init
zet init [--semopsis <ref>] [--logopsis <ref>]
[--k <number>] [--weight semopsis=<number>]
[--weight logopsis=<number>]
[<path>]
Initialize a zetetes chain on a vault per §5.1. The
vault root is <path> if supplied, otherwise the current
directory. The vault MUST already contain a metatheca chain.
Exits non-zero if metatheca is absent or a zetetes chain already
exists.
--semopsis and --logopsis accept a ref or the literal
current to snap to the corresponding extension’s current
head; both default to current if the extension is initialized
on the vault, and default to omitted (null pin) otherwise.
--k defaults to 60. --weight semopsis and
--weight logopsis default to 1.0 for whichever sources
are pinned.
7.2 zet advance
zet advance [--semopsis <ref>|current|none]
[--logopsis <ref>|current|none]
[--k <number>]
[--weight semopsis=<number>]
[--weight logopsis=<number>]
Advance zetetes-head per §5.2. At least one of
--semopsis, --logopsis, --k, or any
--weight MUST be supplied. On success, prints the new
zetetes-state hash to standard output.
A common shorthand
zet advance --semopsis current --logopsis current snaps the
zetetes-state to the current heads of both extensions, preserving
the existing fusion config.
7.3 zet query
zet query [--k <int>] [--as-of <zetetes-stateref>] <query>
zet query [--k <int>] [--as-of <zetetes-stateref>] -
Run a hybrid query per §5.3. <query> is the
query text; - reads from standard input. Default --k
is 10. Default --as-of is current.
Output format per result, one line:
<entry-uuid> <blob-hash> <fused-score>
Implementations MAY support a --verbose flag that adds
per-source ranks and scores to the output; the verbose format is
implementation-defined.
7.4 zet state
zet state [<zetetes-stateref>]
Show metadata for a zetetes-state: hash, created_at_ns,
previous, metatheca, semopsis pin, logopsis pin,
fusion config. Default argument: current.
7.5 zet log
zet log [--since <iso8601>] [--until <iso8601>] [-n <count>]
Walk the zetetes-state chain from current zetetes-head backward,
emitting one line per zetetes-state with its short hash, ISO-8601
timestamp, semopsis pin short hash (or -), logopsis pin short
hash (or -), and fusion summary.
7.6 zet fsck
zet fsck
Verify: the zetetes-head pinax bytes encode a zetetes-state present
in the cella; every zetetes-state in the chain parses; every
non-null pin names a search-state blob that is present and parses
on the corresponding extension’s own cella — presence as a blob,
not reachability from that extension’s current head: an extension
chain advancing past a pinned state does not invalidate the pin;
every fusion config’s weights
key set matches the set of non-null pins per §4.2;
every metatheca field names a metatheca state that is
present and parses on the host metatheca cella. Implementations
MAY rely on syntheca and apotheca verification for byte-level
integrity.
7.7 zet destroy
zet destroy [--force] [<path>]
Destroy the zetetes cella per §5.6. The vault root is
<path> if supplied, otherwise the current directory. Unless
--force is supplied, implementations SHOULD prompt for
confirmation before proceeding, since destroy discards the audit
trail of prior zetetes-states. Exits non-zero if no zetetes cella
exists at the resolved path.
7.8 Reserved
The verb gc is reserved for future phases.
8 Errors
The error conditions defined by this specification are:
NotFound— a zetetes-stateref, pinned search-state, or referenced metatheca state did not resolve. Surfaced fromzet advance(when the supplied pin is not present) or fromzet query(when a pinned search-state has become absent).Ambiguous— a hash-prefix zetetes-stateref matched more than one zetetes-state.Conflict— zetetes-head CAS lost a race; the caller MAY retry (§5.2).Malformed— a wire-format blob did not parse per §4 (including weight-set / pin-set mismatches), anadvanceinvocation supplied no inputs, or an argument did not parse per §1.5.Per-source errors surfaced by the consulted extensions (
AnalyzerMismatchfrom logopsis,ModelMismatchfrom semopsis, etc.) propagate unchanged throughzet query.IntegrityError— inherited from syntheca / apotheca; surfaces unchanged.
Implementations MAY surface additional implementation-defined errors (I/O failure, extension binary unavailable, …); such errors MUST be distinguishable from the protocol-defined errors above.
9 Conformance
A Phase 1 implementation MUST implement:
§2 (coexistence rules)
§3 (identifiers, time)
§4 (wire formats)
§6 (zetetes-head pinax)
§7 (CLI), with the exception that
--as-ofMAY be omitted fromzet queryif the implementation always queriescurrent§8 (errors)
A Phase 1 implementation MAY omit:
§10 items.
10 Out of scope (Phase 1)
The following are deliberately out of Phase 1 scope. Their absence is load-bearing for the v0.1 surface and consumers MUST NOT rely on them.
Fusion algorithms other than RRF. Convex combination of normalized scores, learned rerankers, score-based fusion, CombSUM, CombMNZ, and other fusion strategies are deferred. The
fusion.algorithmfield is recorded in the wire format precisely so that future fusions can be added without breaking existing zetetes-states.Auto-snap query mode. Phase 1 requires explicit
zet advanceto update pins;zet queryalways uses the pins recorded in the zetetes-state. A future phase may introduce a "query against current heads" mode, but it would necessarily sacrifice reproducibility — the result of such a query could not be recovered from any single zetetes-stateref.Multiple simultaneous semopsis or logopsis chains per vault. Phase 1 zetetes pins at most one of each. A future phase might permit pinning multiple chains and configuring per-chain weights for ensemble retrieval.
Query rewriting. zetetes passes the query string unchanged to each source. Per-source query transformation (e.g. expanding the query under a synonym table for logopsis while leaving it raw for semopsis) is deferred.
Per-query fusion override.
zet querydoes not accept fusion parameters. The fusion config in effect is always the one recorded in the resolved zetetes-state. To change fusion, callers mustzet advanceand query against the new state.Result-set diff between zetetes-states. A natural future feature ("how did this query’s results change between yesterday’s and today’s zetetes-states"), but not part of the protocol surface.
Garbage collection. Old zetetes-states and the search-states they pin remain on the cella indefinitely. Blocked by absence of delete in apotheca and syntheca.
Cross-vault index sharing. As semopsis §10 and logopsis §10.
11 Future work (non-normative)
Additional fusion algorithms registered under
fusion.algorithm. Convex combination requires score normalization, which is harder than it sounds; CombSUM and CombMNZ are simpler additions. Learned rerankers introduce a model-identity contract similar to semopsis’s and would benefit from a parallelmodelfield in the fusion config.Per-query candidate pool size as a wire-format field, so that the implementation-defined
k_internalof §5.3 step 4 becomes a recorded part of the zetetes-state. Useful when reproducing query results across implementations.Skip-list pointers in the zetetes-state blob, mirroring metatheca SPEC §11, semopsis SPEC §11, and logopsis SPEC §11, to make as-of resolution sublinear.
An auto-advance hook that runs
zet advance --semopsis current --logopsis currentautomatically after each metatheca commit, configurable per-vault. This would move zetetes from explicit-advance toward something closer to auto-snap while preserving the audit trail.Source-specific result-set sizes (
k_semopsis,k_logopsis) for cases where one source is known to produce better candidates than the other.A remote query service. When the vault lives in object storage and the client is far from it, evaluating
zet querybeside the cella and shipping only the fused top-kbeats shipping index artifacts to the client. A companion serving tier (hyperetes, the servant) would expose the query surfaces of both sources plus fused zetetes queries over HTTP, keyed by stateref, without owning any chain state — pure serving infrastructure, not an extension. The constraint it feeds back into this spec family is architectural: Phase 2 query cores should stay I/O-agnostic (byte-range reads behind an async seam) and compilable to WASM, so a conformant evaluator can run in an edge runtime at zero distance from the cella. Deployment analysis and measurements:SCALE.mdunderext/logopsis/andext/semopsis/, scenario 4.A diagnostics view in
zet query --verbosestandardized into the protocol, exposing per-source ranks, scores, and fusion contributions in a defined format. Currently implementation-defined.