@hraness/oh 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +598 -0
- package/dist/canonical.d.ts +32 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +3419 -0
- package/dist/contract.d.ts +33 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/graph.d.ts +67 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1988 -0
- package/dist/libsql.d.ts +57 -0
- package/dist/libsql.d.ts.map +1 -0
- package/dist/libsql.js +2662 -0
- package/dist/memory.d.ts +366 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +3650 -0
- package/dist/ontology.d.ts +242 -0
- package/dist/ontology.d.ts.map +1 -0
- package/dist/operation.d.ts +24 -0
- package/dist/operation.d.ts.map +1 -0
- package/dist/projection-public.d.ts +59 -0
- package/dist/projection-public.d.ts.map +1 -0
- package/dist/projection-public.js +1682 -0
- package/dist/projection-suss.d.ts +17 -0
- package/dist/projection-suss.d.ts.map +1 -0
- package/dist/projection-suss.js +1721 -0
- package/dist/projection.d.ts +315 -0
- package/dist/projection.d.ts.map +1 -0
- package/dist/schema.d.ts +45 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/sdk.d.ts +51 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +3072 -0
- package/dist/search.d.ts +34 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/semantic.d.ts +83 -0
- package/dist/semantic.d.ts.map +1 -0
- package/dist/semantic.js +706 -0
- package/dist/sqlite/driver.d.ts +6 -0
- package/dist/sqlite/driver.d.ts.map +1 -0
- package/dist/sqlite/index.d.ts +5 -0
- package/dist/sqlite/index.d.ts.map +1 -0
- package/dist/sqlite/index.js +2840 -0
- package/dist/sqlite/migrations.d.ts +10 -0
- package/dist/sqlite/migrations.d.ts.map +1 -0
- package/dist/sqlite/port.d.ts +40 -0
- package/dist/sqlite/port.d.ts.map +1 -0
- package/dist/sqlite/runtime.d.ts +23 -0
- package/dist/sqlite/runtime.d.ts.map +1 -0
- package/dist/sqlite/store.d.ts +85 -0
- package/dist/sqlite/store.d.ts.map +1 -0
- package/dist/store.d.ts +236 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +996 -0
- package/dist/sync.d.ts +57 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +1328 -0
- package/package.json +121 -0
- package/skills/oh/SKILL.md +206 -0
- package/skills/oh/agents/openai.yaml +4 -0
- package/spec/README.md +74 -0
- package/spec/manifest.json +41 -0
- package/spec/v1/canonical-json.md +59 -0
- package/spec/v1/contract.json +28 -0
- package/spec/v1/contract.schema.json +58 -0
- package/spec/v1/embedding-profile.json +11 -0
- package/spec/v1/embedding.md +56 -0
- package/spec/v1/graph.md +87 -0
- package/spec/v1/memory.md +193 -0
- package/spec/v1/migration.md +92 -0
- package/spec/v1/ontology.json +55 -0
- package/spec/v1/ontology.md +80 -0
- package/spec/v1/operation.schema.json +138 -0
- package/spec/v1/projection-identity.schema.json +58 -0
- package/spec/v1/projection-query.schema.json +60 -0
- package/spec/v1/projection-result.schema.json +452 -0
- package/spec/v1/projection-rule-pack.schema.json +182 -0
- package/spec/v1/projection.md +165 -0
- package/spec/v1/record.schema.json +95 -0
- package/spec/v1/schema-evolution.md +51 -0
- package/spec/v1/schema-revision.schema.json +178 -0
- package/spec/v1/storage.md +88 -0
- package/spec/v1/store.md +131 -0
- package/spec/v1/sync-bundle.schema.json +51 -0
- package/spec/v1/sync.md +67 -0
- package/src/canonical.test.ts +46 -0
- package/src/canonical.ts +203 -0
- package/src/cli.test.ts +103 -0
- package/src/cli.ts +308 -0
- package/src/contract.ts +87 -0
- package/src/contracts.test.ts +147 -0
- package/src/graph.ts +248 -0
- package/src/index.ts +8 -0
- package/src/libsql.test.ts +657 -0
- package/src/libsql.ts +1687 -0
- package/src/memory.test.ts +783 -0
- package/src/memory.ts +1684 -0
- package/src/ontology.ts +573 -0
- package/src/operation.ts +80 -0
- package/src/projection-public.ts +53 -0
- package/src/projection-suss.ts +129 -0
- package/src/projection.test.ts +418 -0
- package/src/projection.ts +1457 -0
- package/src/schema.ts +156 -0
- package/src/sdk.ts +96 -0
- package/src/search.ts +66 -0
- package/src/semantic.test.ts +480 -0
- package/src/semantic.ts +333 -0
- package/src/sqlite/driver.ts +47 -0
- package/src/sqlite/index.ts +4 -0
- package/src/sqlite/migrations.test.ts +44 -0
- package/src/sqlite/migrations.ts +178 -0
- package/src/sqlite/port.test.ts +127 -0
- package/src/sqlite/port.ts +120 -0
- package/src/sqlite/runtime.test.ts +68 -0
- package/src/sqlite/runtime.ts +53 -0
- package/src/sqlite/store.test.ts +295 -0
- package/src/sqlite/store.ts +988 -0
- package/src/store.test.ts +121 -0
- package/src/store.ts +701 -0
- package/src/sync.test.ts +117 -0
- package/src/sync.ts +227 -0
package/spec/v1/graph.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Graph and operation contract V1
|
|
2
|
+
|
|
3
|
+
The graph format version is `1`. It stores canonical JSON records behind stable
|
|
4
|
+
logical keys and records every change in a content-addressed operation chain.
|
|
5
|
+
|
|
6
|
+
## Record envelope
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"dependencies": [],
|
|
11
|
+
"key": "entity:ada-lovelace",
|
|
12
|
+
"kind": "entity",
|
|
13
|
+
"recordSha256": "<64 lowercase hex characters>",
|
|
14
|
+
"v": 1,
|
|
15
|
+
"value": { "name": "Ada Lovelace" }
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
A logical key begins with a lowercase letter, contains at most 512 characters,
|
|
20
|
+
and uses lowercase alphanumeric segments separated by `.`, `_`, `:`, `/`, or
|
|
21
|
+
`-`. Dependencies use the same grammar. They MUST be strictly ordered, unique,
|
|
22
|
+
non-reflexive, and present after the operation settles.
|
|
23
|
+
|
|
24
|
+
V1 record kinds are:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
activity assertion context dependency-manifest edition entity evidence
|
|
28
|
+
identity-operation inquiry inquiry-event review-decision rights-decision
|
|
29
|
+
schema shape statement type-membership view vocabulary
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The `value` is arbitrary canonical JSON. A registered codec MAY impose a
|
|
33
|
+
stricter value contract for a kind. The generic envelope parser remains the
|
|
34
|
+
wire boundary.
|
|
35
|
+
|
|
36
|
+
## Changes
|
|
37
|
+
|
|
38
|
+
A put change contains `{ "kind": "put", "record": ..., "v": 1 }`. A
|
|
39
|
+
tombstone contains the logical key and exact prior record digest. Changes in an
|
|
40
|
+
operation MUST be sorted by logical key and unique. A tombstone fails if its
|
|
41
|
+
prior digest does not match the current record.
|
|
42
|
+
|
|
43
|
+
One operation contains 1 through 8,192 changes. Each record has no more than
|
|
44
|
+
4,096 dependencies and a value no larger than 1,048,576 canonical UTF-8 bytes.
|
|
45
|
+
A bounded snapshot contains no more than 65,536 records under the V1 graph
|
|
46
|
+
limit.
|
|
47
|
+
|
|
48
|
+
## Graph revisions
|
|
49
|
+
|
|
50
|
+
A graph revision binds the canonical changes, stable operation ID, parent graph
|
|
51
|
+
revision digest, sorted complete record references, complete record-set digest,
|
|
52
|
+
positive revision, and revision digest. Replaying a revision chain MUST reject
|
|
53
|
+
gaps, forks, duplicate operation IDs, false record snapshots, missing
|
|
54
|
+
dependencies, and digest mismatches.
|
|
55
|
+
|
|
56
|
+
Each record reference contains `dependencies`, `key`, `kind`, `sha256`, and
|
|
57
|
+
`v`. Dependencies are ordered, unique, non-reflexive keys. The complete
|
|
58
|
+
reference set therefore carries enough information to reject a tombstone that
|
|
59
|
+
would strand an unchanged record. `recordsSha256` hashes the ordered complete
|
|
60
|
+
reference array. `graphRevisionSha256` hashes the canonical transition fields
|
|
61
|
+
listed in [`canonical-json.md`](canonical-json.md); `recordRefs` are bound
|
|
62
|
+
through `recordsSha256` and are not duplicated in that digest preimage.
|
|
63
|
+
|
|
64
|
+
Creators, parsers, reducers, and stores MUST reject a resulting snapshot above
|
|
65
|
+
65,536 records, including growth accumulated across multiple operations.
|
|
66
|
+
|
|
67
|
+
## Operations
|
|
68
|
+
|
|
69
|
+
An operation adds the actor ID, contract ID, canonical UTC instant, operation
|
|
70
|
+
chain, space ID, and sequence to the graph transition. Sequence starts at one
|
|
71
|
+
with a null parent operation digest. Every later operation increments sequence
|
|
72
|
+
by one and binds the prior operation digest.
|
|
73
|
+
|
|
74
|
+
`operationId` gives a writer idempotency. Reusing it with the same actor and
|
|
75
|
+
changes returns the existing operation. Reusing it for different content is a
|
|
76
|
+
conflict.
|
|
77
|
+
|
|
78
|
+
The complete operation is at most 67,108,864 bytes. Its `operationSha256`
|
|
79
|
+
hashes the payload without that field.
|
|
80
|
+
|
|
81
|
+
## Concurrency
|
|
82
|
+
|
|
83
|
+
A commit supplies the expected generation and operation digest. The store
|
|
84
|
+
acquires an immediate transaction, reads the current head, computes the full
|
|
85
|
+
transition, appends the operation, materializes records and dependencies, and
|
|
86
|
+
moves the head with compare-and-swap. A stale expected head fails without a
|
|
87
|
+
partial mutation.
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# Experimental composite agent memory
|
|
2
|
+
|
|
3
|
+
`@hraness/oh/experimental/memory` is the first consumer-facing composition of
|
|
4
|
+
the stable store and projection contracts. It is experimental API, not a new
|
|
5
|
+
ontology or a third storage authority.
|
|
6
|
+
|
|
7
|
+
## One kernel, two authorities
|
|
8
|
+
|
|
9
|
+
A host MUST bind two distinct physical authorities before it creates the
|
|
10
|
+
facade:
|
|
11
|
+
|
|
12
|
+
- a working-profile store, writable only through codec-enforced semantic
|
|
13
|
+
bundles; and
|
|
14
|
+
- a canonical-profile store pinned at one exact host-selected head and never
|
|
15
|
+
writable through the returned agent object.
|
|
16
|
+
|
|
17
|
+
The host supplies opaque authority IDs plus the exact expected binding digests.
|
|
18
|
+
The factory rejects equal authority IDs, a binding mismatch, or the wrong
|
|
19
|
+
profile. Authority IDs identify custody in results without revealing a database
|
|
20
|
+
path, URL, credential, or purge handle. An Oh space, a semantic context, a
|
|
21
|
+
runtime tenant/session, and a physical authority remain different boundaries.
|
|
22
|
+
The host also binds the working actor, every named program's purpose, and every
|
|
23
|
+
named nomination route. None of those authority-bearing labels comes from
|
|
24
|
+
agent input.
|
|
25
|
+
|
|
26
|
+
The returned object exposes only `remember`, `query`, `explain`, and
|
|
27
|
+
`nominate`. It has no generic commit, store selection, path, sync, rule
|
|
28
|
+
registration, canonical write, or purge operation.
|
|
29
|
+
|
|
30
|
+
`remember` accepts only an expected working head, semantic puts and tombstones,
|
|
31
|
+
and an idempotency request ID. The facade supplies its host-bound actor, uses
|
|
32
|
+
its non-regressing host clock, derives the operation ID, and returns an
|
|
33
|
+
immutable, locator-free receipt with the working authority ID, binding digest,
|
|
34
|
+
resulting complete head, operation digest, actor, and actual instant. It never
|
|
35
|
+
returns raw operation changes or accepts a caller-asserted actor or timestamp.
|
|
36
|
+
|
|
37
|
+
## Composite projection
|
|
38
|
+
|
|
39
|
+
Every query reads the current working head and the factory-pinned canonical
|
|
40
|
+
head. It builds a disposable composite dataset with lane-tagged
|
|
41
|
+
`memory.record` and `memory.dependency` facts. Equal logical keys with different
|
|
42
|
+
record digests produce an explicit `memory.conflict` fact and result entry;
|
|
43
|
+
working data never shadows canonical data by recency. Equal digests produce
|
|
44
|
+
`memory.agreement`.
|
|
45
|
+
|
|
46
|
+
Trusted host code may register digest-identified domain fact extractors. Each
|
|
47
|
+
extractor declares a disjoint set of relations it owns. The facade supplies a
|
|
48
|
+
deeply immutable record and its exact physical source, bounds invocation and
|
|
49
|
+
output counts, and forbids custom ownership of reserved `memory.*` or `oh.*`
|
|
50
|
+
relations. Every fact proof identifies the built-in fact pack or exact domain
|
|
51
|
+
extractor ID and digest that emitted it. Trusted host code also registers a
|
|
52
|
+
bounded set of parsed rule-pack/query pairs and their fixed purposes under
|
|
53
|
+
names. Agent input selects a name; it cannot submit a purpose, rule, query AST,
|
|
54
|
+
or inert validity label.
|
|
55
|
+
|
|
56
|
+
The composite identity binds:
|
|
57
|
+
|
|
58
|
+
- both opaque authority IDs, binding digests, complete heads, projection
|
|
59
|
+
snapshots, and lane dataset digests;
|
|
60
|
+
- the composite fact dataset;
|
|
61
|
+
- the named program, exact rule pack and query;
|
|
62
|
+
- evaluation and engine identity inherited from the projection result;
|
|
63
|
+
- the host-bound program purpose and fixed visible-conflict policy.
|
|
64
|
+
|
|
65
|
+
Changing any of these values produces a different memory digest and a full
|
|
66
|
+
rebuild. Results and proofs remain `derived`. A rule cannot upgrade the
|
|
67
|
+
authority of its premises. Each public row is labeled from its visible physical
|
|
68
|
+
premise lanes; a truncated or missing witness is `unknown` rather than
|
|
69
|
+
silently canonical. Returned result, row, value, proof, source, and receipt
|
|
70
|
+
graphs are detached and deeply immutable, so a caller cannot mutate bytes after
|
|
71
|
+
their digest or explanation capability is issued.
|
|
72
|
+
|
|
73
|
+
## Additive parameterized pagination (V2 experimental API)
|
|
74
|
+
|
|
75
|
+
`createOhMemoryAgentV2` is an additive experimental query surface. It does not
|
|
76
|
+
change a V1 request, result, digest preimage, factory, or type. Its `remember`
|
|
77
|
+
and `nominate` methods continue to use the V1 semantic-bundle and nomination
|
|
78
|
+
contracts. Only its `query` and `explain` envelopes use V2.
|
|
79
|
+
|
|
80
|
+
A V2 named program is still entirely host-owned. In addition to the fixed
|
|
81
|
+
purpose, rule pack, query, and extractor registry, the host declares:
|
|
82
|
+
|
|
83
|
+
- the exact query-body variables that may receive parameters;
|
|
84
|
+
- every projection evaluation limit;
|
|
85
|
+
- the maximum complete result row count;
|
|
86
|
+
- a page size of at most 256 rows; and
|
|
87
|
+
- a canonical byte ceiling for each outward page.
|
|
88
|
+
|
|
89
|
+
The host query limit MUST equal the declared maximum row count. A parameter
|
|
90
|
+
variable MUST occur in the query body and MUST NOT be a projected output
|
|
91
|
+
variable. Agent input supplies one exact object of bounded JSON primitive
|
|
92
|
+
values for those names plus a program ID and either `null` or a continuation.
|
|
93
|
+
It cannot supply a purpose, rule, query AST, evaluator option, page size, or
|
|
94
|
+
source selector. Binding substitutes constants only into the fixed query body;
|
|
95
|
+
the rules and projected output remain the registered program.
|
|
96
|
+
|
|
97
|
+
The V2 identity includes the canonical bindings and their digest, the template
|
|
98
|
+
and bound query digests, the complete program digest, and the same physical
|
|
99
|
+
source and projection identities as V1. Thus a parameter value is part of both
|
|
100
|
+
the projection identity and the memory identity, not an unrecorded filter.
|
|
101
|
+
This supports a host extractor that emits bounded primitive value chunks while
|
|
102
|
+
a named program binds `lane` and `key` and projects only chunk position and
|
|
103
|
+
chunk content. Each chunk remains subject to the V1 16 KiB atom limit and the
|
|
104
|
+
extractor's existing count and source rules.
|
|
105
|
+
|
|
106
|
+
The evaluator computes one canonical, ordered result no larger than the
|
|
107
|
+
host-declared row limit before it selects a page. A projection `query-limit` or
|
|
108
|
+
`result-bytes` truncation returns no page. The outward page reports its start,
|
|
109
|
+
end, configured and returned row counts, total rows, `hasMore`, `complete` or
|
|
110
|
+
`partial` status, and explicit empty truncation evidence. Its configured slice
|
|
111
|
+
must fit the host-declared page byte ceiling; the facade fails closed instead
|
|
112
|
+
of silently shortening the slice. Every returned page therefore has
|
|
113
|
+
`truncation.truncated: false`; `partial` means more exact pages exist, not that
|
|
114
|
+
the projection is incomplete. Proof-budget truncation remains visible on
|
|
115
|
+
the affected row as `proofsTruncated` and yields `unknown` premise authority,
|
|
116
|
+
as in V1.
|
|
117
|
+
|
|
118
|
+
A continuation is an authenticated bearer cursor, not knowledge authority. Its
|
|
119
|
+
canonical envelope contains an unsigned cursor identity, a public
|
|
120
|
+
`continuationSha256` digest of that identity, and a domain-separated
|
|
121
|
+
HMAC-SHA-256. The identity binds the next offset to the exact program, bindings,
|
|
122
|
+
complete projection result, page size, total row count, and composite memory
|
|
123
|
+
identity. The HMAC makes only host-issued offsets usable; recomputing the public
|
|
124
|
+
digest does not issue a cursor. The envelope is authenticated, not encrypted,
|
|
125
|
+
and the same token can be replayed for the same exact page.
|
|
126
|
+
|
|
127
|
+
By default the facade generates a private random continuation key, so its
|
|
128
|
+
cursors are scoped to that facade instance. A host that must reconstruct the
|
|
129
|
+
facade or route a cursor to another replica supplies the same 32 through 64 raw
|
|
130
|
+
key bytes through `continuationKey`; the factory clones those bytes. The host
|
|
131
|
+
keeps that key out of agent input and persisted results. Changing the key
|
|
132
|
+
invalidates outstanding cursors.
|
|
133
|
+
|
|
134
|
+
The request parser first establishes an exact shallow envelope, a bounded
|
|
135
|
+
primitive binding map, and bounded strings before canonical serialization.
|
|
136
|
+
After resolving the registered program and exact bindings, it authenticates a
|
|
137
|
+
continuation and checks its program, binding, page-size, range, and alignment
|
|
138
|
+
before reading the working store, invoking extractors, evaluating rules, or
|
|
139
|
+
mapping proofs. Every valid continued call then rereads the current working
|
|
140
|
+
head and rebuilds the projection. A head, source, result, or row-count change
|
|
141
|
+
fails with an integrity error before proof mapping rather than mixing pages
|
|
142
|
+
from two snapshots.
|
|
143
|
+
|
|
144
|
+
An outward result publishes `continuationSha256` beside the opaque token, or
|
|
145
|
+
`null` beside `null` on the final page. `resultSha256` commits that deterministic
|
|
146
|
+
digest instead of the key-dependent token, so the same exact result identity is
|
|
147
|
+
stable across signing keys. The actual token still counts toward the outward
|
|
148
|
+
page-byte ceiling. A V2 explanation capability retains only its exact outward
|
|
149
|
+
page and mapped physical proofs, and requires that page's result digest and
|
|
150
|
+
page-local row index.
|
|
151
|
+
|
|
152
|
+
## Explanations and nominations
|
|
153
|
+
|
|
154
|
+
Query returns an opaque, random, short-lived explanation capability bound to
|
|
155
|
+
that exact deterministic result. Its expiry uses a non-regressing monotonic
|
|
156
|
+
clock; the wall-clock instant is display metadata. A capability may explain
|
|
157
|
+
multiple rows until expiry or eviction. Count, per-entry bytes, and aggregate
|
|
158
|
+
retained evidence are bounded. `explain` also requires the exact result digest
|
|
159
|
+
and row index. It maps every projection fact witness back to an authority ID,
|
|
160
|
+
binding digest, complete pinned head, lane, original record key and digest. A
|
|
161
|
+
wrong, expired, evicted, or result-mismatched capability fails closed.
|
|
162
|
+
|
|
163
|
+
`nominate` selects one host-registered route by opaque name, then exports and
|
|
164
|
+
re-verifies an exact dependency closure and exact requested root set from the
|
|
165
|
+
current working head. Its
|
|
166
|
+
output is only a content-addressed `prepared` proposal for that route's fixed
|
|
167
|
+
destination purpose. It does not sync the working operation chain, mutate the
|
|
168
|
+
canonical store, import a derived tuple, grant rights, record a review, or turn
|
|
169
|
+
a proposed assertion into reviewed knowledge. Destination-owned application
|
|
170
|
+
code must perform those steps under its own policy and compare-and-swap head.
|
|
171
|
+
|
|
172
|
+
## Lifecycle and custody boundary
|
|
173
|
+
|
|
174
|
+
Oh deliberately does not choose a tenant, session, retention deadline,
|
|
175
|
+
physical database, credential, scheduler, or backup policy. The application
|
|
176
|
+
host owns those lifecycle controls and retains the separate working store host
|
|
177
|
+
object. Purge removes a working authority through that host-only
|
|
178
|
+
capability; tombstoning is not erasure because operation history retains prior
|
|
179
|
+
bytes. Database credentials or same-UID filesystem access remain outside this
|
|
180
|
+
API boundary.
|
|
181
|
+
|
|
182
|
+
The facade requests at most 8,192 records per lane, rejects a lane snapshot
|
|
183
|
+
over 32 MiB, rejects a remember request over 8 MiB, bounds extractor
|
|
184
|
+
invocations and emitted facts, limits the public result to 32 MiB, and retains
|
|
185
|
+
at most 64 MiB of explanation evidence. A trusted store still constructs the
|
|
186
|
+
snapshot before returning it, and a trusted synchronous fact extractor can
|
|
187
|
+
consume time or temporary memory before it returns. Provider response limits,
|
|
188
|
+
host storage quotas, callback review, isolation, deadlines, and cancellation
|
|
189
|
+
remain application responsibilities.
|
|
190
|
+
|
|
191
|
+
Suss is an optional differential evaluator behind the separate projection
|
|
192
|
+
compatibility subpath. The memory facade uses the package-owned bounded
|
|
193
|
+
reference evaluator. Cozo is neither evaluated nor loaded.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Compatibility and migration V1
|
|
2
|
+
|
|
3
|
+
This document defines the supported migration path for one conforming Oh V1
|
|
4
|
+
space to another storage location or Oh installation. Source and target MUST
|
|
5
|
+
use contract `oh.ontology.v1` with contract digest
|
|
6
|
+
`e53ae573c2af417082be9f554d0f6f3e317f054daf745181f462608e3f622594` and
|
|
7
|
+
the same space ID.
|
|
8
|
+
|
|
9
|
+
V1 does not ship a cross-contract transformer. A different contract digest,
|
|
10
|
+
protocol identifier, or space ID fails closed before an operation is applied.
|
|
11
|
+
|
|
12
|
+
## Preserved authority
|
|
13
|
+
|
|
14
|
+
The append-only operation chain is the migration unit. Every imported operation
|
|
15
|
+
MUST retain its canonical fields, record envelopes, logical keys, dependencies,
|
|
16
|
+
sequence, parent digest, record-set digest, graph-revision digest, and operation
|
|
17
|
+
digest. A migration MUST NOT rename identifiers, rewrite record values, replace
|
|
18
|
+
timestamps, recompute operations under a different contract, or reconstruct the
|
|
19
|
+
chain from current-row snapshots.
|
|
20
|
+
|
|
21
|
+
SQLite current-record and dependency tables are checked materializations of the
|
|
22
|
+
operation chain. Search documents, FTS5 rows, and the QMD semantic directory are
|
|
23
|
+
derived state and are not migration authority.
|
|
24
|
+
|
|
25
|
+
## Offline migration
|
|
26
|
+
|
|
27
|
+
Use the shipped CLI to move a space:
|
|
28
|
+
|
|
29
|
+
1. Stop or coordinate writers to keep the source head stable during export.
|
|
30
|
+
2. Run `oh contract` and confirm its printed contract ID and digest match the
|
|
31
|
+
required values above. Then run `oh verify --db <source> --space <space>`
|
|
32
|
+
against the source database and space.
|
|
33
|
+
3. Initialize an empty target with the same space ID.
|
|
34
|
+
4. Export operations in ascending sequence with
|
|
35
|
+
`oh sync export --after <sequence> --limit <count>`. The limit MUST be from
|
|
36
|
+
1 through 1,000. Begin after sequence `0` and continue from the last exported
|
|
37
|
+
sequence until the bundle is empty.
|
|
38
|
+
5. Transfer each complete JSON bundle without changing its parsed content.
|
|
39
|
+
6. Import the bundles in order with `oh sync import --file <path>`. Import
|
|
40
|
+
verifies the protocol, contract digest, bundle digest, space ID, operation
|
|
41
|
+
digests, contiguous sequence, parent head, and reproduced graph head.
|
|
42
|
+
7. Run `oh verify` against the target.
|
|
43
|
+
8. Compare the source and target `head` objects returned by `oh verify`. The
|
|
44
|
+
`generation`, `sequence`, `operationSha256`, `graphRevisionSha256`, and
|
|
45
|
+
`recordsSha256` values MUST match exactly before the target becomes
|
|
46
|
+
authoritative.
|
|
47
|
+
|
|
48
|
+
Re-importing an operation already present with the same digest and canonical
|
|
49
|
+
content is idempotent. An operation that does not extend the target head is a
|
|
50
|
+
conflict. Equal sequence numbers with different operation digests are also a
|
|
51
|
+
conflict. Oh does not merge divergent histories automatically.
|
|
52
|
+
|
|
53
|
+
## Connected migration
|
|
54
|
+
|
|
55
|
+
`synchronizeOhStoreV1` provides the same fast-forward rule through an
|
|
56
|
+
`OhOperationSyncTransportV1`. The transport handshake compares the complete V1
|
|
57
|
+
contract manifest before exchanging operations. Settlement succeeds only when
|
|
58
|
+
both heads have the same sequence and operation digest. Applications own
|
|
59
|
+
transport credentials, availability, retries, backups, and any explicit merge
|
|
60
|
+
policy.
|
|
61
|
+
|
|
62
|
+
## Search state
|
|
63
|
+
|
|
64
|
+
Keyword search remains available from the SQLite store after operation import.
|
|
65
|
+
Semantic state MAY be rebuilt with the exact profile in
|
|
66
|
+
[`embedding-profile.json`](embedding-profile.json). A semantic result is current
|
|
67
|
+
only after it rejoins a record with the same record digest. Copying a semantic
|
|
68
|
+
directory does not establish migration parity.
|
|
69
|
+
|
|
70
|
+
## Rollback
|
|
71
|
+
|
|
72
|
+
Keep the verified source database read-only until the target head has matched
|
|
73
|
+
and the application has accepted the cutover. If the target fails verification
|
|
74
|
+
or serving checks, restore routing to that unchanged source. Do not make
|
|
75
|
+
rollback depend on reversing a content or identifier rewrite.
|
|
76
|
+
|
|
77
|
+
SQLite schema migrations are separate from space transfer. The store records
|
|
78
|
+
each applied migration name and SQL digest in `oh_migrations` and refuses to
|
|
79
|
+
open when an applied version has different migration bytes.
|
|
80
|
+
|
|
81
|
+
SQLite schema version 2 appends `0002_store_realms` without changing the
|
|
82
|
+
released `0001_oh_core` SQL. Existing spaces remain unbound after upgrade. A
|
|
83
|
+
host may bind one through the promise-based store authority; once persisted,
|
|
84
|
+
the exact realm and profile bytes cannot be replaced. A purged working space
|
|
85
|
+
cannot be used as a migration source or recreated under the same identifier.
|
|
86
|
+
|
|
87
|
+
The direct libSQL authority has its own `oh_authority_` schema digest. It emits
|
|
88
|
+
the same V1 record and operation bytes, but it is not a destination for the
|
|
89
|
+
offline CLI import procedure above. Applications moving authority between
|
|
90
|
+
adapters MUST prove an exact complete operation chain and matching head through
|
|
91
|
+
a separately reviewed migration workflow. A dependency-closure capsule is a
|
|
92
|
+
selective content export for adoption, not proof of full authority migration.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"contractId": "oh.ontology.v1",
|
|
3
|
+
"idPatterns": {
|
|
4
|
+
"assertion": "^kast_[a-z0-9]{24}$",
|
|
5
|
+
"entity": "^kent_[a-z0-9]{24}$",
|
|
6
|
+
"evidence": "^kevd_[a-z0-9]{24}$",
|
|
7
|
+
"inquiry": "^kinq_[a-z0-9]{24}$"
|
|
8
|
+
},
|
|
9
|
+
"kernelConcepts": [
|
|
10
|
+
{
|
|
11
|
+
"code": "entity",
|
|
12
|
+
"description": "A stable identity anchor for something that can be referred to.",
|
|
13
|
+
"label": "Entity"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"code": "statement",
|
|
17
|
+
"description": "An immutable proposition with a subject, predicate, object, and qualifiers.",
|
|
18
|
+
"label": "Statement"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"code": "assertion",
|
|
22
|
+
"description": "An attributable stance toward a statement.",
|
|
23
|
+
"label": "Assertion"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"code": "evidence",
|
|
27
|
+
"description": "A typed account of how an observation bears on an assertion.",
|
|
28
|
+
"label": "Evidence"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"code": "context",
|
|
32
|
+
"description": "The scenario and dimensions in which knowledge applies.",
|
|
33
|
+
"label": "Context"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"code": "inquiry",
|
|
37
|
+
"description": "A question and its durable investigation trail.",
|
|
38
|
+
"label": "Inquiry"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"code": "projection",
|
|
42
|
+
"description": "A reproducible view derived from exact knowledge.",
|
|
43
|
+
"label": "Projection"
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
"limits": {
|
|
47
|
+
"dimensions": 64,
|
|
48
|
+
"listValues": 256,
|
|
49
|
+
"qualifiers": 128,
|
|
50
|
+
"statementBytes": 262144,
|
|
51
|
+
"textBytes": 65536
|
|
52
|
+
},
|
|
53
|
+
"ontologyVersion": "1.0.0",
|
|
54
|
+
"v": 1
|
|
55
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Ontology V1
|
|
2
|
+
|
|
3
|
+
Ontology V1 is identified by `oh.ontology.v1` and version `1.0.0`. Its contract
|
|
4
|
+
manifest digest is
|
|
5
|
+
`e53ae573c2af417082be9f554d0f6f3e317f054daf745181f462608e3f622594`.
|
|
6
|
+
|
|
7
|
+
## Kernel concepts
|
|
8
|
+
|
|
9
|
+
| Concept | Meaning |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Entity | A stable identity anchor for something that can be referred to. |
|
|
12
|
+
| Statement | An immutable proposition with a subject, predicate, object, and qualifiers. |
|
|
13
|
+
| Assertion | An attributable stance toward a statement. |
|
|
14
|
+
| Evidence | A typed account of how an observation bears on an assertion. |
|
|
15
|
+
| Context | The scenario and dimensions in which knowledge applies. |
|
|
16
|
+
| Inquiry | A question and its durable investigation trail. |
|
|
17
|
+
| Projection | A reproducible view derived from exact knowledge. |
|
|
18
|
+
|
|
19
|
+
The kernel separates a proposition from a person's stance toward it, evidence
|
|
20
|
+
from the assertion it bears on, and authored knowledge from a derived view.
|
|
21
|
+
Product vocabularies can refine these concepts without changing the graph
|
|
22
|
+
envelope.
|
|
23
|
+
|
|
24
|
+
## Identities
|
|
25
|
+
|
|
26
|
+
V1 retains four opaque identity grammars:
|
|
27
|
+
|
|
28
|
+
| Identity | Pattern |
|
|
29
|
+
| --- | --- |
|
|
30
|
+
| Entity | `kent_[a-z0-9]{24}` |
|
|
31
|
+
| Assertion | `kast_[a-z0-9]{24}` |
|
|
32
|
+
| Evidence | `kevd_[a-z0-9]{24}` |
|
|
33
|
+
| Inquiry | `kinq_[a-z0-9]{24}` |
|
|
34
|
+
|
|
35
|
+
These identifiers are opaque. A consumer MUST NOT infer time, authorship, or
|
|
36
|
+
ordering from their suffixes.
|
|
37
|
+
|
|
38
|
+
Schema references contain the exact `namespace`, `code`, positive `revision`,
|
|
39
|
+
`schemaSha256`, and `v: 1`. Namespaces and codes use lowercase safe-code
|
|
40
|
+
segments separated by `.`, `_`, `:`, `/`, or `-`.
|
|
41
|
+
|
|
42
|
+
## Values
|
|
43
|
+
|
|
44
|
+
A `KnowledgeValueV1` is one of:
|
|
45
|
+
|
|
46
|
+
- an entity reference;
|
|
47
|
+
- NFC text with a lowercase BCP 47-style language tag;
|
|
48
|
+
- a bounded string or boolean;
|
|
49
|
+
- a canonical integer or decimal represented as a string;
|
|
50
|
+
- a canonical absolute URI without credentials and without the `data`, `file`,
|
|
51
|
+
or `javascript` scheme;
|
|
52
|
+
- a list that preserves order;
|
|
53
|
+
- a set in strict canonical order with no duplicates; or
|
|
54
|
+
- an extension bound to a schema, canonicalizer digest, canonical value, media
|
|
55
|
+
type, and value digest.
|
|
56
|
+
|
|
57
|
+
Lists and sets contain at most 256 values and nest at most eight levels.
|
|
58
|
+
General text is at most 65,536 UTF-8 bytes.
|
|
59
|
+
|
|
60
|
+
## Contexts, statements, and inquiries
|
|
61
|
+
|
|
62
|
+
A context contains at most 64 canonically ordered, unique predicate-value
|
|
63
|
+
dimensions and one scenario: `actual`, `counterfactual`, `hypothetical`, or
|
|
64
|
+
`planned`. `contextSha256` binds the complete context payload.
|
|
65
|
+
|
|
66
|
+
A statement binds an entity subject, schema predicate, typed object, and at
|
|
67
|
+
most 128 canonically ordered, unique qualifiers. Its canonical payload is at
|
|
68
|
+
most 262,144 UTF-8 bytes. `statementSha256` binds that payload.
|
|
69
|
+
|
|
70
|
+
An inquiry binds its opaque ID, author entity, question, answer form, language,
|
|
71
|
+
privacy, status, optional context digest, creation instant, and ordered parent
|
|
72
|
+
inquiry IDs. The creation instant uses exact UTC millisecond form such as
|
|
73
|
+
`2026-08-27T12:00:00.000Z`.
|
|
74
|
+
|
|
75
|
+
## Errors
|
|
76
|
+
|
|
77
|
+
Ontology parsers return a field and one stable issue class:
|
|
78
|
+
`dependency-missing`, `digest-mismatch`, `invalid-input`, `limit-exceeded`, or
|
|
79
|
+
`noncanonical-input`. A result identifies a contract failure, not whether the
|
|
80
|
+
underlying research claim is true.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$defs": {
|
|
3
|
+
"change": {
|
|
4
|
+
"oneOf": [
|
|
5
|
+
{
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"properties": {
|
|
8
|
+
"kind": {
|
|
9
|
+
"const": "put"
|
|
10
|
+
},
|
|
11
|
+
"record": {
|
|
12
|
+
"$ref": "./record.schema.json"
|
|
13
|
+
},
|
|
14
|
+
"v": {
|
|
15
|
+
"const": 1
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"required": [
|
|
19
|
+
"kind",
|
|
20
|
+
"record",
|
|
21
|
+
"v"
|
|
22
|
+
],
|
|
23
|
+
"type": "object"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"additionalProperties": false,
|
|
27
|
+
"properties": {
|
|
28
|
+
"key": {
|
|
29
|
+
"$ref": "#/$defs/recordKey"
|
|
30
|
+
},
|
|
31
|
+
"kind": {
|
|
32
|
+
"const": "tombstone"
|
|
33
|
+
},
|
|
34
|
+
"priorSha256": {
|
|
35
|
+
"$ref": "#/$defs/sha256"
|
|
36
|
+
},
|
|
37
|
+
"v": {
|
|
38
|
+
"const": 1
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"required": [
|
|
42
|
+
"key",
|
|
43
|
+
"kind",
|
|
44
|
+
"priorSha256",
|
|
45
|
+
"v"
|
|
46
|
+
],
|
|
47
|
+
"type": "object"
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"recordKey": {
|
|
52
|
+
"maxLength": 512,
|
|
53
|
+
"pattern": "^[a-z][a-z0-9]*(?:[._:/-][a-z0-9]+)*$",
|
|
54
|
+
"type": "string"
|
|
55
|
+
},
|
|
56
|
+
"safeCode": {
|
|
57
|
+
"maxLength": 128,
|
|
58
|
+
"pattern": "^[a-z][a-z0-9]*(?:[._:/-][a-z0-9]+)*$",
|
|
59
|
+
"type": "string"
|
|
60
|
+
},
|
|
61
|
+
"sha256": {
|
|
62
|
+
"pattern": "^[a-f0-9]{64}$",
|
|
63
|
+
"type": "string"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"$id": "https://oh.computer/spec/v1/operation.schema.json",
|
|
67
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
68
|
+
"$comment": "Runtime conformance additionally requires canonical ordered unique changes, a contiguous parent chain, exact graph and record-set digests, the 64 MiB byte bound, and a recomputed operationSha256.",
|
|
69
|
+
"additionalProperties": false,
|
|
70
|
+
"properties": {
|
|
71
|
+
"actorId": {
|
|
72
|
+
"$ref": "#/$defs/safeCode"
|
|
73
|
+
},
|
|
74
|
+
"changes": {
|
|
75
|
+
"items": {
|
|
76
|
+
"$ref": "#/$defs/change"
|
|
77
|
+
},
|
|
78
|
+
"maxItems": 8192,
|
|
79
|
+
"minItems": 1,
|
|
80
|
+
"type": "array"
|
|
81
|
+
},
|
|
82
|
+
"contractId": {
|
|
83
|
+
"const": "oh.ontology.v1"
|
|
84
|
+
},
|
|
85
|
+
"graphRevisionSha256": {
|
|
86
|
+
"$ref": "#/$defs/sha256"
|
|
87
|
+
},
|
|
88
|
+
"instant": {
|
|
89
|
+
"pattern": "^[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])T(?:[01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\\.[0-9]{3}Z$",
|
|
90
|
+
"type": "string"
|
|
91
|
+
},
|
|
92
|
+
"operationId": {
|
|
93
|
+
"$ref": "#/$defs/safeCode"
|
|
94
|
+
},
|
|
95
|
+
"operationSha256": {
|
|
96
|
+
"$ref": "#/$defs/sha256"
|
|
97
|
+
},
|
|
98
|
+
"parentOperationSha256": {
|
|
99
|
+
"anyOf": [
|
|
100
|
+
{
|
|
101
|
+
"type": "null"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"$ref": "#/$defs/sha256"
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"recordsSha256": {
|
|
109
|
+
"$ref": "#/$defs/sha256"
|
|
110
|
+
},
|
|
111
|
+
"sequence": {
|
|
112
|
+
"minimum": 1,
|
|
113
|
+
"type": "integer"
|
|
114
|
+
},
|
|
115
|
+
"spaceId": {
|
|
116
|
+
"$ref": "#/$defs/safeCode"
|
|
117
|
+
},
|
|
118
|
+
"v": {
|
|
119
|
+
"const": 1
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"required": [
|
|
123
|
+
"actorId",
|
|
124
|
+
"changes",
|
|
125
|
+
"contractId",
|
|
126
|
+
"graphRevisionSha256",
|
|
127
|
+
"instant",
|
|
128
|
+
"operationId",
|
|
129
|
+
"operationSha256",
|
|
130
|
+
"parentOperationSha256",
|
|
131
|
+
"recordsSha256",
|
|
132
|
+
"sequence",
|
|
133
|
+
"spaceId",
|
|
134
|
+
"v"
|
|
135
|
+
],
|
|
136
|
+
"title": "Oh operation V1",
|
|
137
|
+
"type": "object"
|
|
138
|
+
}
|