@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/package.json
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hraness/oh",
|
|
3
|
+
"version": "0.2.3",
|
|
4
|
+
"description": "open-source tools for agentic research",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Hraness",
|
|
8
|
+
"homepage": "https://oh.computer",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/hraness/oh.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/hraness/oh/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"agentic-research",
|
|
18
|
+
"knowledge-graph",
|
|
19
|
+
"ontology",
|
|
20
|
+
"sqlite"
|
|
21
|
+
],
|
|
22
|
+
"private": false,
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"packageManager": "bun@1.3.14",
|
|
25
|
+
"engines": {
|
|
26
|
+
"bun": ">=1.3.14",
|
|
27
|
+
"node": ">=24"
|
|
28
|
+
},
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"bin": {
|
|
32
|
+
"oh": "./dist/cli.js"
|
|
33
|
+
},
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"import": "./dist/index.js"
|
|
38
|
+
},
|
|
39
|
+
"./sdk": {
|
|
40
|
+
"types": "./dist/sdk.d.ts",
|
|
41
|
+
"import": "./dist/sdk.js"
|
|
42
|
+
},
|
|
43
|
+
"./store": {
|
|
44
|
+
"types": "./dist/store.d.ts",
|
|
45
|
+
"import": "./dist/store.js"
|
|
46
|
+
},
|
|
47
|
+
"./libsql": {
|
|
48
|
+
"types": "./dist/libsql.d.ts",
|
|
49
|
+
"import": "./dist/libsql.js"
|
|
50
|
+
},
|
|
51
|
+
"./sqlite": {
|
|
52
|
+
"types": "./dist/sqlite/index.d.ts",
|
|
53
|
+
"import": "./dist/sqlite/index.js"
|
|
54
|
+
},
|
|
55
|
+
"./sync": {
|
|
56
|
+
"types": "./dist/sync.d.ts",
|
|
57
|
+
"import": "./dist/sync.js"
|
|
58
|
+
},
|
|
59
|
+
"./semantic": {
|
|
60
|
+
"types": "./dist/semantic.d.ts",
|
|
61
|
+
"import": "./dist/semantic.js"
|
|
62
|
+
},
|
|
63
|
+
"./projection": {
|
|
64
|
+
"types": "./dist/projection-public.d.ts",
|
|
65
|
+
"import": "./dist/projection-public.js"
|
|
66
|
+
},
|
|
67
|
+
"./experimental/projection-suss": {
|
|
68
|
+
"types": "./dist/projection-suss.d.ts",
|
|
69
|
+
"import": "./dist/projection-suss.js"
|
|
70
|
+
},
|
|
71
|
+
"./experimental/memory": {
|
|
72
|
+
"types": "./dist/memory.d.ts",
|
|
73
|
+
"import": "./dist/memory.js"
|
|
74
|
+
},
|
|
75
|
+
"./package.json": "./package.json"
|
|
76
|
+
},
|
|
77
|
+
"files": [
|
|
78
|
+
"dist",
|
|
79
|
+
"src",
|
|
80
|
+
"spec",
|
|
81
|
+
"skills",
|
|
82
|
+
"README.md",
|
|
83
|
+
"LICENSE"
|
|
84
|
+
],
|
|
85
|
+
"publishConfig": {
|
|
86
|
+
"access": "public"
|
|
87
|
+
},
|
|
88
|
+
"scripts": {
|
|
89
|
+
"build": "bun run build:js && bun run build:portable && bun run build:types",
|
|
90
|
+
"build:js": "bun build ./src/index.ts ./src/sdk.ts ./src/sqlite/index.ts ./src/sync.ts ./src/semantic.ts ./src/cli.ts --outdir ./dist --target bun --format esm --external bun:sqlite",
|
|
91
|
+
"build:portable": "bun build ./src/store.ts ./src/libsql.ts ./src/projection-public.ts ./src/projection-suss.ts ./src/memory.ts --outdir ./dist --target node --format esm --external @suss/datalog",
|
|
92
|
+
"build:types": "tsc -p tsconfig.build.json",
|
|
93
|
+
"check": "bun run typecheck && bun run test && bun run build && bun run test:types:node && bun run test:node && bun run test:node-projection",
|
|
94
|
+
"test:node": "node ./tests/node-portable.mjs",
|
|
95
|
+
"test:types:node": "tsc -p tsconfig.node-portable.json --noEmit",
|
|
96
|
+
"test": "bun test ./src ./tests ./site/tests/source.test.ts",
|
|
97
|
+
"test:node-projection": "node --test ./scripts/projection-node.test.mjs",
|
|
98
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
99
|
+
},
|
|
100
|
+
"devDependencies": {
|
|
101
|
+
"@suss/datalog": "0.20.0",
|
|
102
|
+
"@types/bun": "1.3.14",
|
|
103
|
+
"typescript": "5.9.3"
|
|
104
|
+
},
|
|
105
|
+
"peerDependencies": {
|
|
106
|
+
"@libsql/client": ">=0.17.4 <1",
|
|
107
|
+
"@suss/datalog": "0.20.0",
|
|
108
|
+
"@tobilu/qmd": "2.5.3"
|
|
109
|
+
},
|
|
110
|
+
"peerDependenciesMeta": {
|
|
111
|
+
"@libsql/client": {
|
|
112
|
+
"optional": true
|
|
113
|
+
},
|
|
114
|
+
"@suss/datalog": {
|
|
115
|
+
"optional": true
|
|
116
|
+
},
|
|
117
|
+
"@tobilu/qmd": {
|
|
118
|
+
"optional": true
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: oh
|
|
3
|
+
description: Operate a local hraness/oh ontology store through its checked CLI or SDK. Use when a coding agent needs to initialize, inspect, write, search, verify, export, import, or synchronize content-addressed research records in an Oh SQLite space.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Operate Oh
|
|
7
|
+
|
|
8
|
+
Keep the selected SQLite space authoritative. Inspect its contract and head
|
|
9
|
+
before writing, use generation-checked mutations, and verify replay after a
|
|
10
|
+
batch of changes.
|
|
11
|
+
|
|
12
|
+
## Preserve authorization and location
|
|
13
|
+
|
|
14
|
+
- Resolve the repository instructions that apply to the target files first.
|
|
15
|
+
- Resolve the exact database path and space. Use `.oh/oh.sqlite` and `default`
|
|
16
|
+
only when they already exist or the user chose the defaults.
|
|
17
|
+
- Do not run a database command against a missing path merely to inspect it.
|
|
18
|
+
Oh opens and initializes the selected database as part of normal commands.
|
|
19
|
+
- Creating a database, tombstoning a record, importing a bundle, or syncing a
|
|
20
|
+
remote requires the user's request to include that write or its direct
|
|
21
|
+
workflow.
|
|
22
|
+
- Never put credentials, authentication tokens, or sensitive source text into
|
|
23
|
+
a record unless the user explicitly selected an appropriately protected
|
|
24
|
+
database and destination.
|
|
25
|
+
|
|
26
|
+
`oh --help` and `oh version` are side-effect-free installation checks:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
oh --help
|
|
30
|
+
oh version
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The supported CLI is `@hraness/oh@0.2.3` from the immutable `v0.2.3` GitHub
|
|
34
|
+
tag. It requires Bun 1.3.14 or newer. The versioned contract is published at
|
|
35
|
+
<https://oh.computer/spec/>.
|
|
36
|
+
|
|
37
|
+
## Open an existing space
|
|
38
|
+
|
|
39
|
+
Confirm that the exact database is a regular file before a read command. First
|
|
40
|
+
inspect the installed runtime contract, then replay the database operation log:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
test -f .oh/oh.sqlite
|
|
44
|
+
oh contract
|
|
45
|
+
oh verify --db .oh/oh.sqlite --space default
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Stop if the installed contract differs from `oh.ontology.v1`, opening the
|
|
49
|
+
database reports a stored-contract mismatch, replay fails, or the user named
|
|
50
|
+
another database. Do not repair an integrity or contract failure by deleting
|
|
51
|
+
state.
|
|
52
|
+
|
|
53
|
+
Use the narrowest read:
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
oh get entity:ada-lovelace --db .oh/oh.sqlite --space default
|
|
57
|
+
oh list --kind statement --limit 50 --db .oh/oh.sqlite --space default
|
|
58
|
+
oh log --limit 20 --db .oh/oh.sqlite --space default
|
|
59
|
+
oh search "analytical engine" --mode keyword --limit 10 \
|
|
60
|
+
--db .oh/oh.sqlite --space default
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
A missing `get` exits with status 3 and prints no record. Treat it as absence,
|
|
64
|
+
not a corrupt database. CLI output is canonical JSON, so parse it rather than
|
|
65
|
+
scraping presentation text.
|
|
66
|
+
|
|
67
|
+
## Initialize only when requested
|
|
68
|
+
|
|
69
|
+
Choose a confined path owned by the user's task. Do not overwrite or merge an
|
|
70
|
+
unrelated database.
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
oh init --db .oh/oh.sqlite --space default
|
|
74
|
+
oh verify --db .oh/oh.sqlite --space default
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Record the returned head. Add the database directory to the repository's
|
|
78
|
+
ignore rules when it is local working state.
|
|
79
|
+
|
|
80
|
+
## Write one checked record
|
|
81
|
+
|
|
82
|
+
Choose a stable lowercase logical key and one V1 kind. Current kinds include
|
|
83
|
+
`entity`, `statement`, `assertion`, `evidence`, `context`, `inquiry`, `schema`,
|
|
84
|
+
`vocabulary`, and the remaining kinds printed by `oh contract`.
|
|
85
|
+
|
|
86
|
+
1. Read every declared dependency with `oh get`.
|
|
87
|
+
2. Run `oh verify` and take `head.generation` from its JSON result.
|
|
88
|
+
3. Prepare one valid JSON value. Prefer `--file` for structured or multiline
|
|
89
|
+
content and `--json` for a short literal.
|
|
90
|
+
4. Use a stable operation ID when an exact retry must be idempotent.
|
|
91
|
+
5. Pass the reviewed generation.
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
oh put \
|
|
95
|
+
--kind statement \
|
|
96
|
+
--key statement:ada-program \
|
|
97
|
+
--depends-on entity:ada-lovelace \
|
|
98
|
+
--file /absolute/path/to/statement.json \
|
|
99
|
+
--actor agent.local \
|
|
100
|
+
--operation op_ada_program_v1 \
|
|
101
|
+
--expected-generation 4 \
|
|
102
|
+
--db .oh/oh.sqlite \
|
|
103
|
+
--space default
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
If the expected generation is stale, read the new head and affected records,
|
|
107
|
+
reconcile the intended change, and create a new operation. Do not loop on a
|
|
108
|
+
conflict or change the expected generation without reviewing intervening work.
|
|
109
|
+
|
|
110
|
+
After a write batch, run:
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
oh verify --db .oh/oh.sqlite --space default
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Tombstone deliberately
|
|
117
|
+
|
|
118
|
+
A tombstone removes the current record from the materialized graph while the
|
|
119
|
+
operation remains in history. Confirm the exact key and current digest. Check
|
|
120
|
+
that no retained record depends on it. Then require the reviewed generation:
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
oh tombstone statement:obsolete \
|
|
124
|
+
--expected-generation 5 \
|
|
125
|
+
--operation op_remove_obsolete_v1 \
|
|
126
|
+
--db .oh/oh.sqlite \
|
|
127
|
+
--space default
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Run replay verification immediately. Do not edit SQLite tables directly to
|
|
131
|
+
bypass dependency or compare-and-swap checks.
|
|
132
|
+
|
|
133
|
+
## Search with explicit evidence lanes
|
|
134
|
+
|
|
135
|
+
Use `keyword` for the model-free CLI path. `semantic` and `hybrid` need an SDK
|
|
136
|
+
instance configured with the optional local QMD backend. If a response contains
|
|
137
|
+
`semantic-unavailable`, report that diagnostic and preserve any keyword result;
|
|
138
|
+
do not substitute a hosted model.
|
|
139
|
+
|
|
140
|
+
Treat a search score as retrieval evidence, not proof that a research claim is
|
|
141
|
+
true. Open the returned record and its dependencies before relying on it.
|
|
142
|
+
|
|
143
|
+
## Export or import an operation bundle
|
|
144
|
+
|
|
145
|
+
An export is read-only but writes a file when redirected. Choose the output
|
|
146
|
+
path explicitly and protect it like the source research:
|
|
147
|
+
|
|
148
|
+
```sh
|
|
149
|
+
oh sync export --after 0 --limit 1000 \
|
|
150
|
+
--db .oh/oh.sqlite --space default > /absolute/path/to/oh-bundle.json
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Before import, preserve the destination, inspect its contract and head, and
|
|
154
|
+
confirm the bundle belongs to the same space. Import is sequential rather than
|
|
155
|
+
bundle-atomic: if a later operation conflicts, an earlier valid prefix may
|
|
156
|
+
already be present. After an error, inspect the destination head and run replay
|
|
157
|
+
verification before retrying.
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
oh sync import --file /absolute/path/to/oh-bundle.json \
|
|
161
|
+
--db .oh/oh.sqlite --space default
|
|
162
|
+
oh verify --db .oh/oh.sqlite --space default
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Remote libSQL or Turso sync is an SDK workflow. The user must select the remote
|
|
166
|
+
and credential source. Never print credentials or embed them in records. Oh
|
|
167
|
+
settles fast-forward histories only; preserve both logs when it reports a
|
|
168
|
+
divergence.
|
|
169
|
+
|
|
170
|
+
## Use composite memory only through host bindings
|
|
171
|
+
|
|
172
|
+
`@hraness/oh/experimental/memory` is an SDK-only surface. Do not let a model
|
|
173
|
+
construct its options. Trusted application code must bind two distinct
|
|
174
|
+
authority handles, exact binding digests, a pinned canonical head, working
|
|
175
|
+
codecs, a working actor, domain extractor relation ownership and digests,
|
|
176
|
+
host-purposed named rule/query programs, and named nomination routes before
|
|
177
|
+
giving the returned object to an agent.
|
|
178
|
+
|
|
179
|
+
The agent-facing object may call only `remember`, `query`, `explain`, and
|
|
180
|
+
`nominate`. Never add a tool parameter for a database path or URL, authority,
|
|
181
|
+
realm, space, store profile, rule pack, raw query, sync destination, canonical
|
|
182
|
+
write, caller-asserted actor/time, or purge operation. Preserve lane, conflict,
|
|
183
|
+
fact-policy, and premise-authority labels in query output. Treat every result
|
|
184
|
+
as derived. A nomination may select only a host-registered route and is a
|
|
185
|
+
prepared dependency-closure candidate for destination-owned review, not
|
|
186
|
+
permission to write durable knowledge or import the working operation chain.
|
|
187
|
+
|
|
188
|
+
Use `createOhMemoryAgentV2` only when the host has registered primitive
|
|
189
|
+
query-body parameters and fixed all projection, row, page, and page-byte
|
|
190
|
+
limits. Expose only the exact bindings object, program ID, and continuation to
|
|
191
|
+
the model. Do not expose parameter declarations, page size, or evaluator
|
|
192
|
+
options as tool input. Follow `hasMore` until the continuation is `null`, and
|
|
193
|
+
restart the named query after an integrity error; never combine pages across a
|
|
194
|
+
working-head change. A V2 `query-limit` or `result-bytes` condition is a failed
|
|
195
|
+
query, not a partial answer. Treat each continuation as a bearer cursor: pass
|
|
196
|
+
it back unchanged only to the exact query and do not log or edit it. If the
|
|
197
|
+
host reconstructs the facade or routes across replicas, it must provide the
|
|
198
|
+
same private 32 through 64 byte `continuationKey` in host options; never expose
|
|
199
|
+
that key as tool input. Keep row-level `proofsTruncated` evidence visible.
|
|
200
|
+
|
|
201
|
+
## Finish with evidence
|
|
202
|
+
|
|
203
|
+
Report the exact database and space, reads or mutations performed, final head
|
|
204
|
+
generation and operation digest, replay result, search diagnostics, and any
|
|
205
|
+
sync counts. Do not claim success from a command exit alone when `oh verify`
|
|
206
|
+
was part of the requested workflow.
|
package/spec/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Oh specification
|
|
2
|
+
|
|
3
|
+
This directory is the versioned public contract for Oh. It defines the
|
|
4
|
+
canonical bytes, ontology identities, graph envelopes, schema revisions,
|
|
5
|
+
SQLite and direct libSQL authority, operation sync, store profiles, and local
|
|
6
|
+
embedding profile that independent implementations need to interoperate.
|
|
7
|
+
|
|
8
|
+
[`manifest.json`](manifest.json) is the discovery document. V1 is current and
|
|
9
|
+
binds these versions:
|
|
10
|
+
|
|
11
|
+
| Component | Version |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| Ontology | `1.0.0` |
|
|
14
|
+
| Contract ID | `oh.ontology.v1` |
|
|
15
|
+
| Graph format | `1` |
|
|
16
|
+
| Schema format | `1` |
|
|
17
|
+
| SQLite schema | `2` |
|
|
18
|
+
| Sync protocol | `oh.sync.v1` |
|
|
19
|
+
| Embedding profile | `1` |
|
|
20
|
+
| Projection semantics | `oh.projection.positive-datalog.v1` |
|
|
21
|
+
| Composite memory | `experimental v1` |
|
|
22
|
+
|
|
23
|
+
## V1 documents
|
|
24
|
+
|
|
25
|
+
- [Canonical JSON and digests](v1/canonical-json.md)
|
|
26
|
+
- [Ontology](v1/ontology.md)
|
|
27
|
+
- [Schema evolution](v1/schema-evolution.md)
|
|
28
|
+
- [Graph and operations](v1/graph.md)
|
|
29
|
+
- [SQLite storage](v1/storage.md)
|
|
30
|
+
- [Store ports, profiles, and direct libSQL authority](v1/store.md)
|
|
31
|
+
- [Sync protocol](v1/sync.md)
|
|
32
|
+
- [Local embedding profile](v1/embedding.md)
|
|
33
|
+
- [Derived projections](v1/projection.md)
|
|
34
|
+
- [Experimental composite agent memory](v1/memory.md)
|
|
35
|
+
- [Compatibility and migration](v1/migration.md)
|
|
36
|
+
|
|
37
|
+
Machine-readable V1 artifacts:
|
|
38
|
+
|
|
39
|
+
- [`contract.json`](v1/contract.json)
|
|
40
|
+
- [`ontology.json`](v1/ontology.json)
|
|
41
|
+
- [`embedding-profile.json`](v1/embedding-profile.json)
|
|
42
|
+
- [`contract.schema.json`](v1/contract.schema.json)
|
|
43
|
+
- [`record.schema.json`](v1/record.schema.json)
|
|
44
|
+
- [`schema-revision.schema.json`](v1/schema-revision.schema.json)
|
|
45
|
+
- [`operation.schema.json`](v1/operation.schema.json)
|
|
46
|
+
- [`sync-bundle.schema.json`](v1/sync-bundle.schema.json)
|
|
47
|
+
- [`projection-rule-pack.schema.json`](v1/projection-rule-pack.schema.json)
|
|
48
|
+
- [`projection-query.schema.json`](v1/projection-query.schema.json)
|
|
49
|
+
- [`projection-identity.schema.json`](v1/projection-identity.schema.json)
|
|
50
|
+
- [`projection-result.schema.json`](v1/projection-result.schema.json)
|
|
51
|
+
|
|
52
|
+
## Conformance
|
|
53
|
+
|
|
54
|
+
The words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY state interoperability
|
|
55
|
+
requirements. JSON Schemas validate exchange structure. The narrative
|
|
56
|
+
documents and runtime parsers also define canonical order, digest preimages,
|
|
57
|
+
byte limits, dependency laws, and replay behavior that JSON Schema cannot
|
|
58
|
+
express.
|
|
59
|
+
|
|
60
|
+
An implementation conforms to V1 only when it reproduces exact canonical JSON
|
|
61
|
+
and digests, rejects malformed or noncanonical input, preserves ordered
|
|
62
|
+
operation history, and passes the same replay laws. Accepting more input is not
|
|
63
|
+
conformance when the extra input changes persisted or exchanged bytes.
|
|
64
|
+
|
|
65
|
+
## Versioning
|
|
66
|
+
|
|
67
|
+
An existing version is immutable. A change to serialized keys, accepted value
|
|
68
|
+
grammar, ordering, a digest preimage, a record kind, a limit, migration SQL, or
|
|
69
|
+
protocol meaning needs a new version. New convenience APIs may retain the
|
|
70
|
+
current contract when they produce the same checked bytes.
|
|
71
|
+
|
|
72
|
+
Schema records inside an Oh graph have their own namespace, code, revision, and
|
|
73
|
+
content digest. Their evolution rules are separate from the version of the Oh
|
|
74
|
+
envelope itself.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"current": "v1",
|
|
3
|
+
"homepage": "https://oh.computer",
|
|
4
|
+
"package": "@hraness/oh",
|
|
5
|
+
"repository": "https://github.com/hraness/oh",
|
|
6
|
+
"v": 1,
|
|
7
|
+
"versions": [
|
|
8
|
+
{
|
|
9
|
+
"contract": "./v1/contract.json",
|
|
10
|
+
"contractId": "oh.ontology.v1",
|
|
11
|
+
"contractSha256": "e53ae573c2af417082be9f554d0f6f3e317f054daf745181f462608e3f622594",
|
|
12
|
+
"embeddingProfile": "./v1/embedding-profile.json",
|
|
13
|
+
"id": "v1",
|
|
14
|
+
"memory": {
|
|
15
|
+
"specification": "./v1/memory.md"
|
|
16
|
+
},
|
|
17
|
+
"ontology": "./v1/ontology.json",
|
|
18
|
+
"projection": {
|
|
19
|
+
"identitySchema": "./v1/projection-identity.schema.json",
|
|
20
|
+
"querySchema": "./v1/projection-query.schema.json",
|
|
21
|
+
"resultSchema": "./v1/projection-result.schema.json",
|
|
22
|
+
"rulePackSchema": "./v1/projection-rule-pack.schema.json",
|
|
23
|
+
"specification": "./v1/projection.md"
|
|
24
|
+
},
|
|
25
|
+
"schemas": [
|
|
26
|
+
"./v1/contract.schema.json",
|
|
27
|
+
"./v1/record.schema.json",
|
|
28
|
+
"./v1/schema-revision.schema.json",
|
|
29
|
+
"./v1/operation.schema.json",
|
|
30
|
+
"./v1/sync-bundle.schema.json",
|
|
31
|
+
"./v1/projection-rule-pack.schema.json",
|
|
32
|
+
"./v1/projection-query.schema.json",
|
|
33
|
+
"./v1/projection-identity.schema.json",
|
|
34
|
+
"./v1/projection-result.schema.json"
|
|
35
|
+
],
|
|
36
|
+
"specification": "./v1/ontology.md",
|
|
37
|
+
"status": "current",
|
|
38
|
+
"v": 1
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Canonical JSON and digests V1
|
|
2
|
+
|
|
3
|
+
Every content digest in Oh is SHA-256 over UTF-8 canonical JSON. The lowercase
|
|
4
|
+
64-character hexadecimal digest is part of the record, operation, schema,
|
|
5
|
+
vocabulary, contract, or sync envelope that names it.
|
|
6
|
+
|
|
7
|
+
## Accepted JSON
|
|
8
|
+
|
|
9
|
+
V1 accepts JSON null, booleans, strings, finite numbers other than negative
|
|
10
|
+
zero, arrays, and plain objects. It rejects non-finite numbers, `-0`, unpaired
|
|
11
|
+
UTF-16 surrogates, cycles, non-plain objects, `undefined`, bigint, symbols, and
|
|
12
|
+
functions.
|
|
13
|
+
|
|
14
|
+
Canonical encoding has these rules:
|
|
15
|
+
|
|
16
|
+
1. Sort object keys by JavaScript's default UTF-16 code-unit order.
|
|
17
|
+
2. Preserve array order exactly.
|
|
18
|
+
3. Encode strings and finite numbers with the ECMAScript JSON representation.
|
|
19
|
+
4. Emit no insignificant whitespace.
|
|
20
|
+
5. Preserve a valid string's code points. General canonical JSON does not
|
|
21
|
+
normalize text. Ontology text fields separately require NFC where stated.
|
|
22
|
+
|
|
23
|
+
The result is RFC 8785-style canonical JSON for the narrower JSON subset
|
|
24
|
+
accepted by Oh. Implementations MUST reproduce Oh's exact V1 ordering and
|
|
25
|
+
number rules instead of substituting a serializer whose edge cases differ.
|
|
26
|
+
|
|
27
|
+
## Parsing canonical bytes
|
|
28
|
+
|
|
29
|
+
A canonical JSON parser MUST bound input before parsing, parse JSON, encode the
|
|
30
|
+
value again with the V1 rules, and require byte-for-byte equality with the
|
|
31
|
+
input. Pretty-printed or differently ordered JSON can be accepted as user
|
|
32
|
+
input only when the receiving command explicitly canonicalizes it before the
|
|
33
|
+
value reaches a persisted or exchanged boundary.
|
|
34
|
+
|
|
35
|
+
## Digest preimages
|
|
36
|
+
|
|
37
|
+
Each creator hashes the envelope without its own digest field:
|
|
38
|
+
|
|
39
|
+
- `recordSha256` hashes `dependencies`, `key`, `kind`, `v`, and `value`.
|
|
40
|
+
- `schemaSha256` hashes the schema revision without `schemaSha256`.
|
|
41
|
+
- `vocabularySha256` hashes the vocabulary revision without
|
|
42
|
+
`vocabularySha256`.
|
|
43
|
+
- `recordsSha256` hashes the ordered complete record-reference array. Each
|
|
44
|
+
reference contains `dependencies`, `key`, `kind`, `sha256`, and `v`.
|
|
45
|
+
- `graphRevisionSha256` hashes `changes`, `operationId`,
|
|
46
|
+
`parentGraphRevisionSha256`, `recordsSha256`, `revision`, and `v`.
|
|
47
|
+
- `operationSha256` hashes the operation without `operationSha256`.
|
|
48
|
+
- `bundleSha256` hashes the sync bundle without `bundleSha256`.
|
|
49
|
+
- `contractSha256` hashes the contract manifest without `contractSha256`.
|
|
50
|
+
|
|
51
|
+
Parsers MUST recompute and compare the digest. They MUST NOT trust a digest
|
|
52
|
+
because its syntax is valid.
|
|
53
|
+
|
|
54
|
+
## Bounds
|
|
55
|
+
|
|
56
|
+
V1 bounds a graph record value at 1,048,576 canonical UTF-8 bytes and an
|
|
57
|
+
operation at 67,108,864 bytes. The general canonical text parser defaults to
|
|
58
|
+
16 MiB. More specific ontology fields may have smaller limits. A receiver MUST
|
|
59
|
+
apply the smallest applicable bound before unbounded allocation or work.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"contractId": "oh.ontology.v1",
|
|
3
|
+
"contractSha256": "e53ae573c2af417082be9f554d0f6f3e317f054daf745181f462608e3f622594",
|
|
4
|
+
"graphFormatVersion": 1,
|
|
5
|
+
"ontologyVersion": "1.0.0",
|
|
6
|
+
"recordKinds": [
|
|
7
|
+
"activity",
|
|
8
|
+
"assertion",
|
|
9
|
+
"context",
|
|
10
|
+
"dependency-manifest",
|
|
11
|
+
"edition",
|
|
12
|
+
"entity",
|
|
13
|
+
"evidence",
|
|
14
|
+
"identity-operation",
|
|
15
|
+
"inquiry",
|
|
16
|
+
"inquiry-event",
|
|
17
|
+
"review-decision",
|
|
18
|
+
"rights-decision",
|
|
19
|
+
"schema",
|
|
20
|
+
"shape",
|
|
21
|
+
"statement",
|
|
22
|
+
"type-membership",
|
|
23
|
+
"view",
|
|
24
|
+
"vocabulary"
|
|
25
|
+
],
|
|
26
|
+
"schemaFormatVersion": 1,
|
|
27
|
+
"v": 1
|
|
28
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$id": "https://oh.computer/spec/v1/contract.schema.json",
|
|
3
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"properties": {
|
|
6
|
+
"contractId": {
|
|
7
|
+
"const": "oh.ontology.v1"
|
|
8
|
+
},
|
|
9
|
+
"contractSha256": {
|
|
10
|
+
"const": "e53ae573c2af417082be9f554d0f6f3e317f054daf745181f462608e3f622594"
|
|
11
|
+
},
|
|
12
|
+
"graphFormatVersion": {
|
|
13
|
+
"const": 1
|
|
14
|
+
},
|
|
15
|
+
"ontologyVersion": {
|
|
16
|
+
"const": "1.0.0"
|
|
17
|
+
},
|
|
18
|
+
"recordKinds": {
|
|
19
|
+
"const": [
|
|
20
|
+
"activity",
|
|
21
|
+
"assertion",
|
|
22
|
+
"context",
|
|
23
|
+
"dependency-manifest",
|
|
24
|
+
"edition",
|
|
25
|
+
"entity",
|
|
26
|
+
"evidence",
|
|
27
|
+
"identity-operation",
|
|
28
|
+
"inquiry",
|
|
29
|
+
"inquiry-event",
|
|
30
|
+
"review-decision",
|
|
31
|
+
"rights-decision",
|
|
32
|
+
"schema",
|
|
33
|
+
"shape",
|
|
34
|
+
"statement",
|
|
35
|
+
"type-membership",
|
|
36
|
+
"view",
|
|
37
|
+
"vocabulary"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
"schemaFormatVersion": {
|
|
41
|
+
"const": 1
|
|
42
|
+
},
|
|
43
|
+
"v": {
|
|
44
|
+
"const": 1
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"required": [
|
|
48
|
+
"contractId",
|
|
49
|
+
"contractSha256",
|
|
50
|
+
"graphFormatVersion",
|
|
51
|
+
"ontologyVersion",
|
|
52
|
+
"recordKinds",
|
|
53
|
+
"schemaFormatVersion",
|
|
54
|
+
"v"
|
|
55
|
+
],
|
|
56
|
+
"title": "Oh contract manifest V1",
|
|
57
|
+
"type": "object"
|
|
58
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dimensions": 768,
|
|
3
|
+
"distance": "cosine",
|
|
4
|
+
"documentFormat": "title: {title} | text: {content}",
|
|
5
|
+
"documentation": "https://ai.google.dev/gemma/docs/embeddinggemma",
|
|
6
|
+
"engine": "@tobilu/qmd@2.5.3",
|
|
7
|
+
"model": "hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf",
|
|
8
|
+
"normalization": "l2",
|
|
9
|
+
"queryFormat": "task: search result | query: {query}",
|
|
10
|
+
"v": 1
|
|
11
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Local embedding profile V1
|
|
2
|
+
|
|
3
|
+
Oh semantic search is optional, local, and derived. SQLite records remain
|
|
4
|
+
authoritative. Keyword search remains available without a model.
|
|
5
|
+
|
|
6
|
+
## Exact profile
|
|
7
|
+
|
|
8
|
+
| Field | Value |
|
|
9
|
+
| --- | --- |
|
|
10
|
+
| Engine | `@tobilu/qmd@2.5.3` |
|
|
11
|
+
| Model | `hf:ggml-org/embeddinggemma-300M-GGUF/embeddinggemma-300M-Q8_0.gguf` |
|
|
12
|
+
| Dimensions | `768` |
|
|
13
|
+
| Distance | `cosine` |
|
|
14
|
+
| Normalization | `l2` |
|
|
15
|
+
| Documentation | `https://ai.google.dev/gemma/docs/embeddinggemma` |
|
|
16
|
+
| Query format | `task: search result | query: {query}` |
|
|
17
|
+
| Document format | `title: {title} \| text: {content}` |
|
|
18
|
+
| Profile version | `1` |
|
|
19
|
+
|
|
20
|
+
The native 768-dimensional output follows the
|
|
21
|
+
[EmbeddingGemma model profile](https://ai.google.dev/gemma/docs/embeddinggemma).
|
|
22
|
+
Implementations MUST NOT silently truncate it to another Matryoshka dimension
|
|
23
|
+
under profile V1.
|
|
24
|
+
|
|
25
|
+
## Derived document contract
|
|
26
|
+
|
|
27
|
+
For each current record, Oh writes one local Markdown document whose filename
|
|
28
|
+
is the SHA-256 digest of the logical key. The document includes the key, kind,
|
|
29
|
+
and canonical JSON value. A canonical manifest binds that filename to the
|
|
30
|
+
logical key and exact `recordSha256`.
|
|
31
|
+
|
|
32
|
+
Before returning a semantic hit, Oh resolves the filename through the manifest,
|
|
33
|
+
loads the current SQLite record, and requires its digest to match. Stale,
|
|
34
|
+
unknown, duplicate, non-finite, or out-of-range results are discarded.
|
|
35
|
+
|
|
36
|
+
## Search modes
|
|
37
|
+
|
|
38
|
+
- `keyword` uses the local FTS5 index only.
|
|
39
|
+
- `semantic` uses the configured local backend only.
|
|
40
|
+
- `hybrid` combines keyword and semantic ranks while preserving lane, rank,
|
|
41
|
+
and score as evidence.
|
|
42
|
+
|
|
43
|
+
When no semantic backend is configured, semantic and hybrid requests return a
|
|
44
|
+
`semantic-unavailable` diagnostic rather than contacting a hosted provider.
|
|
45
|
+
Hybrid can still return its keyword lane.
|
|
46
|
+
|
|
47
|
+
## Deployment boundary
|
|
48
|
+
|
|
49
|
+
The base package MUST remain usable without QMD. A serverless or browser bundle
|
|
50
|
+
SHOULD exclude QMD and model artifacts. Cloud applications SHOULD keep exact
|
|
51
|
+
and keyword retrieval on the request path and run semantic indexing in a
|
|
52
|
+
bounded, long-lived local-model worker. Unavailable semantic search should be
|
|
53
|
+
visible as a diagnostic, never replaced silently by a different model.
|
|
54
|
+
|
|
55
|
+
The cache directory can contain derived record text. It needs the same local
|
|
56
|
+
confidentiality treatment as the source data even though it can be rebuilt.
|