@vortex-os/ontos 0.1.0 → 0.2.0
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/README.md +32 -17
- package/dist/actions/index.d.ts +28 -1
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +12 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/enrich/domain-range.d.ts +25 -0
- package/dist/enrich/domain-range.d.ts.map +1 -0
- package/dist/enrich/domain-range.js +60 -0
- package/dist/enrich/domain-range.js.map +1 -0
- package/dist/enrich/index.d.ts +50 -0
- package/dist/enrich/index.d.ts.map +1 -0
- package/dist/enrich/index.js +67 -0
- package/dist/enrich/index.js.map +1 -0
- package/dist/enrich/tier.d.ts +27 -0
- package/dist/enrich/tier.d.ts.map +1 -0
- package/dist/enrich/tier.js +38 -0
- package/dist/enrich/tier.js.map +1 -0
- package/dist/enrich/types.d.ts +101 -0
- package/dist/enrich/types.d.ts.map +1 -0
- package/dist/enrich/types.js +11 -0
- package/dist/enrich/types.js.map +1 -0
- package/dist/enrich/validate.d.ts +32 -0
- package/dist/enrich/validate.d.ts.map +1 -0
- package/dist/enrich/validate.js +104 -0
- package/dist/enrich/validate.js.map +1 -0
- package/dist/extract/deterministic.d.ts.map +1 -1
- package/dist/extract/deterministic.js +20 -0
- package/dist/extract/deterministic.js.map +1 -1
- package/dist/extract/types.d.ts +1 -1
- package/dist/extract/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/sqlite/index.d.ts +1 -1
- package/dist/sqlite/index.d.ts.map +1 -1
- package/dist/sqlite/schema.d.ts +1 -1
- package/dist/sqlite/schema.d.ts.map +1 -1
- package/dist/sqlite/schema.js +38 -0
- package/dist/sqlite/schema.js.map +1 -1
- package/dist/sqlite/store.d.ts +70 -1
- package/dist/sqlite/store.d.ts.map +1 -1
- package/dist/sqlite/store.js +244 -1
- package/dist/sqlite/store.js.map +1 -1
- package/dist/writeback.d.ts +60 -0
- package/dist/writeback.d.ts.map +1 -0
- package/dist/writeback.js +138 -0
- package/dist/writeback.js.map +1 -0
- package/package.json +4 -2
- package/scripts/enrich-ontos.mjs +182 -0
- package/scripts/rebuild-ontos.mjs +1 -0
package/README.md
CHANGED
|
@@ -9,34 +9,49 @@ connects, and acts on recurring situations.
|
|
|
9
9
|
> Sibling add-ons, one line: **remember** (`memory-extended`) · **perceive**
|
|
10
10
|
> (`computer-use`) · **model** (`ontos`).
|
|
11
11
|
|
|
12
|
-
## Status — Phase 1 (0.
|
|
12
|
+
## Status — Phase 1 (0.2.0)
|
|
13
13
|
|
|
14
14
|
Phase 1 is **text-first**: the ontology is built only from existing markdown
|
|
15
|
-
records (the failure ledger, decision-log, memories, `[[wikilinks]]`),
|
|
16
|
-
screen perception and no background daemon** (those are Phase 2, only if
|
|
17
|
-
proves its value). Storage is **sqlite** (better-sqlite3) with recursive-CTE
|
|
15
|
+
records (the failure ledger, decision-log, memories, runbooks, `[[wikilinks]]`),
|
|
16
|
+
with **no screen perception and no background daemon** (those are Phase 2, only if
|
|
17
|
+
Phase 1 proves its value). Storage is **sqlite** (better-sqlite3) with recursive-CTE
|
|
18
18
|
traversal — no graph DB (TypeDB/Neo4j) and no formal OWL/RDF reasoner.
|
|
19
19
|
|
|
20
|
-
Implemented and verified (typecheck/build/verify
|
|
20
|
+
Implemented and verified (typecheck/build/verify 47/47; confirmed on a real
|
|
21
21
|
instance — e.g. `literal-control-bytes` → 6 occurrences, guard fires):
|
|
22
22
|
|
|
23
23
|
- **`sqlite/OntosStore`** — schema; idempotent object/relation upsert
|
|
24
24
|
(relId = `sha256(source⏎relation⏎target)`); alias-based identity resolution;
|
|
25
25
|
hop-capped (≤ 3) cycle-guarded recursive-CTE traversal; recurrence count;
|
|
26
|
-
`clear()` + a transaction wrapper for a true rebuild.
|
|
27
|
-
|
|
26
|
+
`clear()` + a transaction wrapper for a true rebuild. Plus the 0.2.0
|
|
27
|
+
`relation_proposals` table (kept SEPARATE from the trusted graph), additive
|
|
28
|
+
migration, and `confirmProposal` / `rejectProposal` / `proposalsFor`.
|
|
29
|
+
- **`extract/`** — the deterministic extractor (§4): failure ledger →
|
|
28
30
|
recurring-failure subgraph (`recurs-as` occurrence→class, `covered-by` →rule);
|
|
29
31
|
decision-log → `decision:` objects (+ wikilink candidates); memory → `rule:`
|
|
30
|
-
objects
|
|
31
|
-
- **`
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
objects; runbooks → `action:` objects (`resolved-by` targets).
|
|
33
|
+
- **`enrich/`** (0.2.0) — agent-mediated LLM enrichment: build an extraction
|
|
34
|
+
request, validate the agent's proposals (vocab + domain/range), tier them
|
|
35
|
+
(deterministic HIGH / cross-model MEDIUM / self LOW / disagreed rejected), and
|
|
36
|
+
store them as PROPOSALS only. A proposal never reaches the trusted graph until
|
|
37
|
+
human-confirmed.
|
|
38
|
+
- **`writeback`** (0.2.0, §5-bis) — on confirm, persist the relation to the source
|
|
39
|
+
record's `ontos:` frontmatter block via a format-preserving `parseDocument`
|
|
40
|
+
round-trip (idempotent; malformed/colliding/ambiguous frontmatter untouched), so
|
|
41
|
+
confirmed knowledge syncs across machines via git.
|
|
42
|
+
- **`actions/`** — `recurringFailureGuard` (the §5A fast-proof), `why` (§5B
|
|
43
|
+
decision archaeology, evidence-first ≤ 3 hops), and `proposalHints` (surface
|
|
44
|
+
unconfirmed links, hedged — actions read the trusted graph only).
|
|
45
|
+
- **`scripts/`** — `rebuild-ontos` (read-only deterministic rebuild from
|
|
46
|
+
`_failures`/`decision-log`/`_memory`/`runbooks`); `enrich-ontos --emit|--ingest`
|
|
47
|
+
(the agent I/O wrapper) and `--gc` (reconcile orphans after rename/delete).
|
|
48
|
+
- **CLI** — `vortex ontos check | why <target>` via `@vortex-os/base` (optional;
|
|
49
|
+
base works without ontos installed).
|
|
50
|
+
|
|
51
|
+
**Deferred** (later): identity embedding-candidates (optional reuse of
|
|
52
|
+
`@vortex-os/memory-extended`'s embedder when present), broader object coverage
|
|
53
|
+
(Component extraction beyond runbooks), session-start ambient surfacing, and
|
|
54
|
+
Phase 2 (vision / daemon).
|
|
40
55
|
|
|
41
56
|
Design: the concept and Phase 1 build spec live in the maintainer's VortEX
|
|
42
57
|
instance (Codex-reviewed, 2 rounds).
|
package/dist/actions/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { OntosStore } from "../sqlite/index.js";
|
|
2
|
-
import type { WalkStep } from "../types.js";
|
|
2
|
+
import type { RelationType, WalkStep } from "../types.js";
|
|
3
|
+
import type { Trust } from "../enrich/types.js";
|
|
3
4
|
/**
|
|
4
5
|
* §5B — decision archaeology. Walks the reasoning relations (supersedes /
|
|
5
6
|
* contradicts / causes) from an object, returning short, evidence-first chains
|
|
@@ -9,6 +10,32 @@ import type { WalkStep } from "../types.js";
|
|
|
9
10
|
* snippets (the store already carries `evidence` on each relation).
|
|
10
11
|
*/
|
|
11
12
|
export declare function why(store: OntosStore, objectId: string, maxHops?: number): WalkStep[];
|
|
13
|
+
/**
|
|
14
|
+
* A "possible (unverified)" connection touching an object — an LLM proposal that
|
|
15
|
+
* is NOT in the trusted graph. SEPARATE from `why()`/the guard on purpose: those
|
|
16
|
+
* read only confirmed relations, so this never silently colours an action. The
|
|
17
|
+
* agent fetches hints alongside a firm answer and may weave the strongest in,
|
|
18
|
+
* hedged ("a possible link, not confirmed — treat it as real?").
|
|
19
|
+
*
|
|
20
|
+
* Demand-driven usage (the asking heuristic lives in the agent, not here): only
|
|
21
|
+
* surface a hint when it would change the answer the user is already getting;
|
|
22
|
+
* skip HIGH/already-corroborated noise; respect a re-ask cooldown via `askedAt`
|
|
23
|
+
* (and stamp `store.markAsked` when you do ask); on "yes" call
|
|
24
|
+
* `store.confirmProposal`, on "no" `store.rejectProposal`; a non-answer leaves it
|
|
25
|
+
* as a hint (safe default). Highest trust first.
|
|
26
|
+
*/
|
|
27
|
+
export interface ProposalHint {
|
|
28
|
+
readonly relId: string;
|
|
29
|
+
readonly rel: RelationType;
|
|
30
|
+
readonly sourceId: string;
|
|
31
|
+
readonly targetId: string;
|
|
32
|
+
readonly trust: Trust;
|
|
33
|
+
readonly confidence: number;
|
|
34
|
+
readonly evidencePath: string;
|
|
35
|
+
/** ISO date last surfaced as a question (null = never) — for the agent's cooldown. */
|
|
36
|
+
readonly askedAt: string | null;
|
|
37
|
+
}
|
|
38
|
+
export declare function proposalHints(store: OntosStore, objectId: string): ProposalHint[];
|
|
12
39
|
export interface GuardHit {
|
|
13
40
|
readonly failureId: string;
|
|
14
41
|
readonly recurrence: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actions/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/actions/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,QAAQ,EAAE,CAKhF;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,sFAAsF;IACtF,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAWjF;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,MAAM,EACjB,SAAS,SAAI,GACZ,QAAQ,GAAG,IAAI,CASjB"}
|
package/dist/actions/index.js
CHANGED
|
@@ -12,6 +12,18 @@ export function why(store, objectId, maxHops = 3) {
|
|
|
12
12
|
rels: ["supersedes", "contradicts", "causes"],
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
|
+
export function proposalHints(store, objectId) {
|
|
16
|
+
return store.proposalsFor(objectId).map((p) => ({
|
|
17
|
+
relId: p.relId,
|
|
18
|
+
rel: p.rel,
|
|
19
|
+
sourceId: p.sourceId,
|
|
20
|
+
targetId: p.targetId,
|
|
21
|
+
trust: p.trust,
|
|
22
|
+
confidence: p.confidence,
|
|
23
|
+
evidencePath: p.evidencePath,
|
|
24
|
+
askedAt: p.askedAt ?? null,
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
15
27
|
/**
|
|
16
28
|
* §5A — recurring-failure guard. Given a situation already resolved to a failure
|
|
17
29
|
* object id (the §6 trigger surface does that resolution), report whether it
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/actions/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/actions/index.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAE,QAAgB,EAAE,OAAO,GAAG,CAAC;IAClE,OAAO,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE;QAC9B,OAAO;QACP,IAAI,EAAE,CAAC,YAAY,EAAE,aAAa,EAAE,QAAQ,CAAC;KAC9C,CAAC,CAAC;AACL,CAAC;AA4BD,MAAM,UAAU,aAAa,CAAC,KAAiB,EAAE,QAAgB;IAC/D,OAAO,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9C,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,IAAI;KAC3B,CAAC,CAAC,CAAC;AACN,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAiB,EACjB,SAAiB,EACjB,SAAS,GAAG,CAAC;IAEb,4EAA4E;IAC5E,6EAA6E;IAC7E,6EAA6E;IAC7E,wDAAwD;IACxD,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC;IAChG,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACvD,MAAM,UAAU,GAAG,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAClD,OAAO,UAAU,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7E,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* §1/§2 controlled vocabulary + domain/range, factored out so BOTH the proposal
|
|
3
|
+
* validator (id-prefix typing, at propose time) and the store's confirm path
|
|
4
|
+
* (the objects' STORED types, at promote time) can share one rule set with no
|
|
5
|
+
* import cycle. Pure; imports only types.
|
|
6
|
+
*/
|
|
7
|
+
import type { ObjectType, RelationType } from "../types.js";
|
|
8
|
+
import type { DomainRange } from "./types.js";
|
|
9
|
+
export declare const OBJECT_TYPES: readonly ObjectType[];
|
|
10
|
+
export declare const RELATION_TYPES: readonly RelationType[];
|
|
11
|
+
/**
|
|
12
|
+
* §2 domain/range. Empty domain/range = "any type". `Guard` is a subtype of
|
|
13
|
+
* `action`, so `resolved-by` ranges over `action`.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DOMAIN_RANGE: Readonly<Record<RelationType, DomainRange>>;
|
|
16
|
+
/** Read an object type from a canonical id prefix (`type:rest`). null = untyped/unresolved. */
|
|
17
|
+
export declare function typeFromId(id: string): ObjectType | null;
|
|
18
|
+
/**
|
|
19
|
+
* True when (srcType, tgtType) violates `rel`'s domain/range. A null type skips
|
|
20
|
+
* the side it can't determine (propose-time, unresolved ends); the confirm path
|
|
21
|
+
* passes the objects' STORED types (both non-null) so a wrong-type object cannot
|
|
22
|
+
* be promoted even though the id prefix conventionally matched.
|
|
23
|
+
*/
|
|
24
|
+
export declare function domainRangeViolated(rel: RelationType, srcType: ObjectType | null, tgtType: ObjectType | null): boolean;
|
|
25
|
+
//# sourceMappingURL=domain-range.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-range.d.ts","sourceRoot":"","sources":["../../src/enrich/domain-range.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAO7C,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EASjD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC,CASpE,CAAC;AAEF,+FAA+F;AAC/F,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAGxD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,YAAY,EACjB,OAAO,EAAE,UAAU,GAAG,IAAI,EAC1B,OAAO,EAAE,UAAU,GAAG,IAAI,GACzB,OAAO,CAMT"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* §1/§2 controlled vocabulary + domain/range, factored out so BOTH the proposal
|
|
3
|
+
* validator (id-prefix typing, at propose time) and the store's confirm path
|
|
4
|
+
* (the objects' STORED types, at promote time) can share one rule set with no
|
|
5
|
+
* import cycle. Pure; imports only types.
|
|
6
|
+
*/
|
|
7
|
+
export const OBJECT_TYPES = [
|
|
8
|
+
"component",
|
|
9
|
+
"problem",
|
|
10
|
+
"decision",
|
|
11
|
+
"rule",
|
|
12
|
+
"action",
|
|
13
|
+
"person",
|
|
14
|
+
];
|
|
15
|
+
export const RELATION_TYPES = [
|
|
16
|
+
"causes",
|
|
17
|
+
"affects",
|
|
18
|
+
"depends-on",
|
|
19
|
+
"supersedes",
|
|
20
|
+
"contradicts",
|
|
21
|
+
"resolved-by",
|
|
22
|
+
"covered-by",
|
|
23
|
+
"recurs-as",
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* §2 domain/range. Empty domain/range = "any type". `Guard` is a subtype of
|
|
27
|
+
* `action`, so `resolved-by` ranges over `action`.
|
|
28
|
+
*/
|
|
29
|
+
export const DOMAIN_RANGE = {
|
|
30
|
+
"covered-by": { domain: ["problem"], range: ["rule"] },
|
|
31
|
+
"resolved-by": { domain: ["problem"], range: ["action"] },
|
|
32
|
+
"recurs-as": { domain: ["problem"], range: ["problem"] },
|
|
33
|
+
causes: { domain: ["component", "problem", "decision"], range: [] },
|
|
34
|
+
affects: { domain: [], range: ["component"] },
|
|
35
|
+
"depends-on": { domain: ["component"], range: ["component"] },
|
|
36
|
+
supersedes: { domain: ["decision", "rule"], range: ["decision", "rule"] },
|
|
37
|
+
contradicts: { domain: ["decision", "rule"], range: ["decision", "rule"], symmetric: true },
|
|
38
|
+
};
|
|
39
|
+
/** Read an object type from a canonical id prefix (`type:rest`). null = untyped/unresolved. */
|
|
40
|
+
export function typeFromId(id) {
|
|
41
|
+
const prefix = id.split(":", 1)[0];
|
|
42
|
+
return OBJECT_TYPES.includes(prefix) ? prefix : null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* True when (srcType, tgtType) violates `rel`'s domain/range. A null type skips
|
|
46
|
+
* the side it can't determine (propose-time, unresolved ends); the confirm path
|
|
47
|
+
* passes the objects' STORED types (both non-null) so a wrong-type object cannot
|
|
48
|
+
* be promoted even though the id prefix conventionally matched.
|
|
49
|
+
*/
|
|
50
|
+
export function domainRangeViolated(rel, srcType, tgtType) {
|
|
51
|
+
const dr = DOMAIN_RANGE[rel];
|
|
52
|
+
if (srcType && dr.domain.length && !dr.domain.includes(srcType))
|
|
53
|
+
return true;
|
|
54
|
+
if (tgtType && dr.range.length && !dr.range.includes(tgtType))
|
|
55
|
+
return true;
|
|
56
|
+
if (dr.symmetric && srcType && tgtType && srcType !== tgtType)
|
|
57
|
+
return true;
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=domain-range.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-range.js","sourceRoot":"","sources":["../../src/enrich/domain-range.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,CAAC,MAAM,YAAY,GAA0B;IACjD,WAAW;IACX,SAAS;IACT,UAAU;IACV,MAAM;IACN,QAAQ;IACR,QAAQ;CACT,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAA4B;IACrD,QAAQ;IACR,SAAS;IACT,YAAY;IACZ,YAAY;IACZ,aAAa;IACb,aAAa;IACb,YAAY;IACZ,WAAW;CACZ,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAgD;IACvE,YAAY,EAAE,EAAE,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE;IACtD,aAAa,EAAE,EAAE,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE;IACzD,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE;IACxD,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;IACnE,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,EAAE;IAC7C,YAAY,EAAE,EAAE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,WAAW,CAAC,EAAE;IAC7D,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE;IACzE,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE;CAC5F,CAAC;AAEF,+FAA+F;AAC/F,MAAM,UAAU,UAAU,CAAC,EAAU;IACnC,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,OAAQ,YAAkC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAqB,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9F,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAiB,EACjB,OAA0B,EAC1B,OAA0B;IAE1B,MAAM,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,OAAO,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7E,IAAI,OAAO,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3E,IAAI,EAAE,CAAC,SAAS,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IAC3E,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vortex-os/ontos — agent-mediated LLM enrichment (0.2.0).
|
|
3
|
+
*
|
|
4
|
+
* The pure, testable core: build an extraction request, validate the agent's raw
|
|
5
|
+
* proposals (vocab + domain/range + id resolution), tier them (deterministic /
|
|
6
|
+
* cross-model / self), and store them as PROPOSALS — never into the trusted
|
|
7
|
+
* `relations` graph. The agent I/O (printing the request, reading JSON back) is a
|
|
8
|
+
* thin CLI wrapper layered on top (§6, a later item).
|
|
9
|
+
*/
|
|
10
|
+
import type { OntosStore } from "../sqlite/store.js";
|
|
11
|
+
import type { RecordInput } from "../extract/types.js";
|
|
12
|
+
import type { Resolver } from "./validate.js";
|
|
13
|
+
import type { IngestReport, RawProposal } from "./types.js";
|
|
14
|
+
export * from "./types.js";
|
|
15
|
+
export { OBJECT_TYPES, RELATION_TYPES, DOMAIN_RANGE, typeFromId, validateProposal, buildEnrichmentRequest, requestFor, } from "./validate.js";
|
|
16
|
+
export type { Resolver } from "./validate.js";
|
|
17
|
+
export { tierProposal } from "./tier.js";
|
|
18
|
+
/**
|
|
19
|
+
* Extraction hash for change detection (§4 step 3): a record needs (re-)enrichment
|
|
20
|
+
* only when its text changed. Hashes the body — frontmatter-only edits go through
|
|
21
|
+
* deterministic extraction, not the LLM gap-filler.
|
|
22
|
+
*/
|
|
23
|
+
export declare function extractionHash(record: Pick<RecordInput, "body">): string;
|
|
24
|
+
/**
|
|
25
|
+
* True when this record's text changed since it was last enriched.
|
|
26
|
+
*
|
|
27
|
+
* KNOWN LIMITATION (first cut, by design — proposals live in a disposable index):
|
|
28
|
+
* a RENAME/DELETE leaves the old path's `enrichment_state` and any proposals it
|
|
29
|
+
* produced as orphans, and a label resolved only LATER (unresolved at ingest →
|
|
30
|
+
* aliased afterwards) gets a fresh relId on re-ingest, so the old low-trust row is
|
|
31
|
+
* not upgraded in place. Both are low-harm (disposable, weakly surfaced) and are
|
|
32
|
+
* cleaned by a future reconcile/GC pass + `enrich --rebuild`; tracked as a 0.2.0
|
|
33
|
+
* follow-up, not a blocker (Codex review 2026-06-18).
|
|
34
|
+
*/
|
|
35
|
+
export declare function needsEnrichment(store: OntosStore, record: RecordInput): boolean;
|
|
36
|
+
export interface IngestOptions {
|
|
37
|
+
/** Resolve a proposed ref to a canonical object id (default: the store's alias table). */
|
|
38
|
+
readonly resolve?: Resolver;
|
|
39
|
+
/** Stamp stored proposals with the record's extraction hash (change-detection link). */
|
|
40
|
+
readonly sourceRecordHash?: string | null;
|
|
41
|
+
/** ISO timestamp for proposedAt (pass in — the addon never reads the wall clock itself). */
|
|
42
|
+
readonly proposedAt?: string | null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Ingest the agent's raw proposals for a record: validate → tier → store as
|
|
46
|
+
* proposals. Invalid or verifier-disagreed proposals are dropped into the report,
|
|
47
|
+
* never stored. The trusted graph and objects table are untouched.
|
|
48
|
+
*/
|
|
49
|
+
export declare function ingestProposals(store: OntosStore, raws: readonly RawProposal[], opts?: IngestOptions): IngestReport;
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/enrich/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAgB,MAAM,YAAY,CAAC;AAE1E,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,sBAAsB,EACtB,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,GAAG,MAAM,CAExE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAE/E;AAED,MAAM,WAAW,aAAa;IAC5B,0FAA0F;IAC1F,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC;IAC5B,wFAAwF;IACxF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,4FAA4F;IAC5F,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,IAAI,GAAE,aAAkB,GACvB,YAAY,CA0Bd"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vortex-os/ontos — agent-mediated LLM enrichment (0.2.0).
|
|
3
|
+
*
|
|
4
|
+
* The pure, testable core: build an extraction request, validate the agent's raw
|
|
5
|
+
* proposals (vocab + domain/range + id resolution), tier them (deterministic /
|
|
6
|
+
* cross-model / self), and store them as PROPOSALS — never into the trusted
|
|
7
|
+
* `relations` graph. The agent I/O (printing the request, reading JSON back) is a
|
|
8
|
+
* thin CLI wrapper layered on top (§6, a later item).
|
|
9
|
+
*/
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
|
+
import { validateProposal } from "./validate.js";
|
|
12
|
+
import { tierProposal } from "./tier.js";
|
|
13
|
+
export * from "./types.js";
|
|
14
|
+
export { OBJECT_TYPES, RELATION_TYPES, DOMAIN_RANGE, typeFromId, validateProposal, buildEnrichmentRequest, requestFor, } from "./validate.js";
|
|
15
|
+
export { tierProposal } from "./tier.js";
|
|
16
|
+
/**
|
|
17
|
+
* Extraction hash for change detection (§4 step 3): a record needs (re-)enrichment
|
|
18
|
+
* only when its text changed. Hashes the body — frontmatter-only edits go through
|
|
19
|
+
* deterministic extraction, not the LLM gap-filler.
|
|
20
|
+
*/
|
|
21
|
+
export function extractionHash(record) {
|
|
22
|
+
return createHash("sha256").update(record.body).digest("hex").slice(0, 16);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* True when this record's text changed since it was last enriched.
|
|
26
|
+
*
|
|
27
|
+
* KNOWN LIMITATION (first cut, by design — proposals live in a disposable index):
|
|
28
|
+
* a RENAME/DELETE leaves the old path's `enrichment_state` and any proposals it
|
|
29
|
+
* produced as orphans, and a label resolved only LATER (unresolved at ingest →
|
|
30
|
+
* aliased afterwards) gets a fresh relId on re-ingest, so the old low-trust row is
|
|
31
|
+
* not upgraded in place. Both are low-harm (disposable, weakly surfaced) and are
|
|
32
|
+
* cleaned by a future reconcile/GC pass + `enrich --rebuild`; tracked as a 0.2.0
|
|
33
|
+
* follow-up, not a blocker (Codex review 2026-06-18).
|
|
34
|
+
*/
|
|
35
|
+
export function needsEnrichment(store, record) {
|
|
36
|
+
return store.getExtractionHash(record.path) !== extractionHash(record);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Ingest the agent's raw proposals for a record: validate → tier → store as
|
|
40
|
+
* proposals. Invalid or verifier-disagreed proposals are dropped into the report,
|
|
41
|
+
* never stored. The trusted graph and objects table are untouched.
|
|
42
|
+
*/
|
|
43
|
+
export function ingestProposals(store, raws, opts = {}) {
|
|
44
|
+
const resolve = opts.resolve ?? ((ref) => store.resolveAlias(ref));
|
|
45
|
+
const hasDeterministic = (relId) => store.relationProvenance(relId) === "deterministic";
|
|
46
|
+
const rejected = [];
|
|
47
|
+
let accepted = 0;
|
|
48
|
+
for (const raw of raws) {
|
|
49
|
+
const v = validateProposal(raw, resolve);
|
|
50
|
+
if (!v.ok) {
|
|
51
|
+
rejected.push({ reason: v.reason, raw });
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const t = tierProposal(v.value, raw, hasDeterministic, {
|
|
55
|
+
sourceRecordHash: opts.sourceRecordHash,
|
|
56
|
+
proposedAt: opts.proposedAt,
|
|
57
|
+
});
|
|
58
|
+
if (!t.ok) {
|
|
59
|
+
rejected.push({ reason: t.reason, raw });
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
store.upsertProposal(t.value);
|
|
63
|
+
accepted++;
|
|
64
|
+
}
|
|
65
|
+
return { accepted, rejected };
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/enrich/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAGzC,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,UAAU,EACV,gBAAgB,EAChB,sBAAsB,EACtB,UAAU,GACX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAAiC;IAC9D,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,KAAiB,EAAE,MAAmB;IACpE,OAAO,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,cAAc,CAAC,MAAM,CAAC,CAAC;AACzE,CAAC;AAWD;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAiB,EACjB,IAA4B,EAC5B,OAAsB,EAAE;IAExB,MAAM,OAAO,GAAa,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7E,MAAM,gBAAgB,GAAG,CAAC,KAAa,EAAW,EAAE,CAClD,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,KAAK,eAAe,CAAC;IACtD,MAAM,QAAQ,GAAiD,EAAE,CAAC;IAClE,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACzC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACV,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACzC,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE;YACrD,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC,CAAC;QACH,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YACV,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACzC,SAAS;QACX,CAAC;QACD,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9B,QAAQ,EAAE,CAAC;IACb,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trust tiering — the safety core (2026-06-18 decision, refined this session).
|
|
3
|
+
* Pure: takes a `hasDeterministic` predicate instead of the store, so the rule is
|
|
4
|
+
* unit-testable in isolation. The actual cross-model (Codex) / self re-check is
|
|
5
|
+
* agent-mediated and arrives as a verdict on each RawProposal.
|
|
6
|
+
*
|
|
7
|
+
* deterministic core already has the same triple -> HIGH (corroborated)
|
|
8
|
+
* genuinely new + a DIFFERENT model agreed -> MEDIUM
|
|
9
|
+
* genuinely new + same model self-recheck agreed -> LOW
|
|
10
|
+
* verifier disagreed -> rejected
|
|
11
|
+
*
|
|
12
|
+
* HIGH is EXACT canonical-triple equality with a deterministic relation — never
|
|
13
|
+
* "a wikilink/prose suggests it". A HIGH (corroborated) proposal does NOT modify
|
|
14
|
+
* the deterministic row in `relations`; it is recorded only as a proposal.
|
|
15
|
+
*/
|
|
16
|
+
import type { RawProposal, RelationProposal, ValidatedProposal } from "./types.js";
|
|
17
|
+
export declare function tierProposal(v: ValidatedProposal, raw: Pick<RawProposal, "verifier" | "agreed">, hasDeterministic: (relId: string) => boolean, opts?: {
|
|
18
|
+
readonly sourceRecordHash?: string | null;
|
|
19
|
+
readonly proposedAt?: string | null;
|
|
20
|
+
}): {
|
|
21
|
+
ok: true;
|
|
22
|
+
value: RelationProposal;
|
|
23
|
+
} | {
|
|
24
|
+
ok: false;
|
|
25
|
+
reason: "verifier-disagreed";
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=tier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier.d.ts","sourceRoot":"","sources":["../../src/enrich/tier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEnF,wBAAgB,YAAY,CAC1B,CAAC,EAAE,iBAAiB,EACpB,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,QAAQ,CAAC,EAC7C,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,EAC5C,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACxF;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAE,CAoBrF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trust tiering — the safety core (2026-06-18 decision, refined this session).
|
|
3
|
+
* Pure: takes a `hasDeterministic` predicate instead of the store, so the rule is
|
|
4
|
+
* unit-testable in isolation. The actual cross-model (Codex) / self re-check is
|
|
5
|
+
* agent-mediated and arrives as a verdict on each RawProposal.
|
|
6
|
+
*
|
|
7
|
+
* deterministic core already has the same triple -> HIGH (corroborated)
|
|
8
|
+
* genuinely new + a DIFFERENT model agreed -> MEDIUM
|
|
9
|
+
* genuinely new + same model self-recheck agreed -> LOW
|
|
10
|
+
* verifier disagreed -> rejected
|
|
11
|
+
*
|
|
12
|
+
* HIGH is EXACT canonical-triple equality with a deterministic relation — never
|
|
13
|
+
* "a wikilink/prose suggests it". A HIGH (corroborated) proposal does NOT modify
|
|
14
|
+
* the deterministic row in `relations`; it is recorded only as a proposal.
|
|
15
|
+
*/
|
|
16
|
+
import { TRUST_RANK } from "./types.js";
|
|
17
|
+
export function tierProposal(v, raw, hasDeterministic, opts) {
|
|
18
|
+
const base = {
|
|
19
|
+
...v,
|
|
20
|
+
sourceRecordHash: opts?.sourceRecordHash ?? null,
|
|
21
|
+
proposedAt: opts?.proposedAt ?? null,
|
|
22
|
+
confirmed: null,
|
|
23
|
+
};
|
|
24
|
+
// A verifier-disagreed proposal is rejected FIRST — even if a deterministic
|
|
25
|
+
// triple matches. If the relation is genuinely deterministic it is already in the
|
|
26
|
+
// trusted graph; recording a doubted proposal as "HIGH corroborated" would only
|
|
27
|
+
// muddy provenance and contradict the "disagreed → rejected" rule (Codex round 2).
|
|
28
|
+
if (!raw.agreed)
|
|
29
|
+
return { ok: false, reason: "verifier-disagreed" };
|
|
30
|
+
if (hasDeterministic(v.relId)) {
|
|
31
|
+
return { ok: true, value: { ...base, trust: "high", trustRank: TRUST_RANK.high, verifiedBy: "deterministic" } };
|
|
32
|
+
}
|
|
33
|
+
if (raw.verifier === "cross-model") {
|
|
34
|
+
return { ok: true, value: { ...base, trust: "medium", trustRank: TRUST_RANK.medium, verifiedBy: "cross-model" } };
|
|
35
|
+
}
|
|
36
|
+
return { ok: true, value: { ...base, trust: "low", trustRank: TRUST_RANK.low, verifiedBy: "self" } };
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=tier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tier.js","sourceRoot":"","sources":["../../src/enrich/tier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxC,MAAM,UAAU,YAAY,CAC1B,CAAoB,EACpB,GAA6C,EAC7C,gBAA4C,EAC5C,IAAyF;IAEzF,MAAM,IAAI,GAAG;QACX,GAAG,CAAC;QACJ,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,IAAI,IAAI;QAChD,UAAU,EAAE,IAAI,EAAE,UAAU,IAAI,IAAI;QACpC,SAAS,EAAE,IAAI;KAChB,CAAC;IAEF,4EAA4E;IAC5E,kFAAkF;IAClF,gFAAgF;IAChF,mFAAmF;IACnF,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC;IACpE,IAAI,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,EAAE,CAAC;IAClH,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;QACnC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,EAAE,CAAC;IACpH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,CAAC;AACvG,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vortex-os/ontos — LLM enrichment types (0.2.0, agent-mediated).
|
|
3
|
+
*
|
|
4
|
+
* The ontos library has no generative LLM of its own (memory-extended ships only
|
|
5
|
+
* a local embedder). So enrichment is AGENT-MEDIATED: ontos emits an extraction
|
|
6
|
+
* REQUEST, the running agent (Claude Code) fulfils it and returns RAW proposals
|
|
7
|
+
* (already self/cross-checked), and the library validates → tiers → stores them as
|
|
8
|
+
* PROPOSALS — never into the trusted `relations` graph. See the 0.2.0 design.
|
|
9
|
+
*/
|
|
10
|
+
import type { ObjectType, RelationType } from "../types.js";
|
|
11
|
+
import type { ExtractResult, RecordInput } from "../extract/types.js";
|
|
12
|
+
/** Trust tier of a stored proposal (surfacing rank, NOT graph membership). */
|
|
13
|
+
export type Trust = "high" | "medium" | "low";
|
|
14
|
+
/** How a proposal earned its trust. */
|
|
15
|
+
export type VerifiedBy = "deterministic" | "cross-model" | "self";
|
|
16
|
+
export declare const TRUST_RANK: Readonly<Record<Trust, number>>;
|
|
17
|
+
/** Domain/range constraint for a relation type (object types, by id prefix). */
|
|
18
|
+
export interface DomainRange {
|
|
19
|
+
/** Allowed source object types; empty = any. */
|
|
20
|
+
readonly domain: readonly ObjectType[];
|
|
21
|
+
/** Allowed target object types; empty = any. */
|
|
22
|
+
readonly range: readonly ObjectType[];
|
|
23
|
+
/** Symmetric relations (contradicts): both ends must be the same type set. */
|
|
24
|
+
readonly symmetric?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* What ontos hands the agent for one record: the prose to read, what deterministic
|
|
28
|
+
* extraction already found (so the agent fills GAPS, not duplicates), the controlled
|
|
29
|
+
* vocabulary + domain/range, and the output contract. Pure data — no I/O.
|
|
30
|
+
*/
|
|
31
|
+
export interface EnrichmentRequest {
|
|
32
|
+
readonly path: string;
|
|
33
|
+
readonly category: string;
|
|
34
|
+
readonly prose: string;
|
|
35
|
+
/** Already-known objects/relations from deterministic extraction (don't re-propose). */
|
|
36
|
+
readonly alreadyFound: {
|
|
37
|
+
readonly objectIds: readonly string[];
|
|
38
|
+
readonly relations: readonly string[];
|
|
39
|
+
};
|
|
40
|
+
readonly vocabulary: {
|
|
41
|
+
readonly objectTypes: readonly ObjectType[];
|
|
42
|
+
readonly relationTypes: readonly RelationType[];
|
|
43
|
+
readonly domainRange: Readonly<Record<RelationType, DomainRange>>;
|
|
44
|
+
};
|
|
45
|
+
/** Existing canonical object ids the agent should REUSE rather than invent. */
|
|
46
|
+
readonly knownObjectIds: readonly string[];
|
|
47
|
+
readonly rules: readonly string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* One relation the agent proposes, with its own cross/self verification verdict.
|
|
51
|
+
* The agent does extract + check and submits the final verdict per proposal.
|
|
52
|
+
*/
|
|
53
|
+
export interface RawProposal {
|
|
54
|
+
readonly sourceRef: string;
|
|
55
|
+
readonly rel: string;
|
|
56
|
+
readonly targetRef: string;
|
|
57
|
+
readonly evidencePath: string;
|
|
58
|
+
readonly evidenceSpan?: string | null;
|
|
59
|
+
readonly confidence: number;
|
|
60
|
+
/** Which checker the agent used for this proposal. */
|
|
61
|
+
readonly verifier: "cross-model" | "self";
|
|
62
|
+
/** Did the checker agree the relation is real? */
|
|
63
|
+
readonly agreed: boolean;
|
|
64
|
+
}
|
|
65
|
+
/** A proposal that passed validation (vocab + domain/range + id resolution). */
|
|
66
|
+
export interface ValidatedProposal {
|
|
67
|
+
readonly relId: string;
|
|
68
|
+
readonly rel: RelationType;
|
|
69
|
+
readonly sourceId: string;
|
|
70
|
+
readonly targetId: string;
|
|
71
|
+
readonly sourceResolved: boolean;
|
|
72
|
+
readonly targetResolved: boolean;
|
|
73
|
+
readonly confidence: number;
|
|
74
|
+
readonly evidencePath: string;
|
|
75
|
+
readonly evidenceSpan: string | null;
|
|
76
|
+
}
|
|
77
|
+
/** A fully tiered proposal, ready to store in `relation_proposals`. */
|
|
78
|
+
export interface RelationProposal extends ValidatedProposal {
|
|
79
|
+
readonly trust: Trust;
|
|
80
|
+
readonly trustRank: number;
|
|
81
|
+
readonly verifiedBy: VerifiedBy;
|
|
82
|
+
readonly sourceRecordHash?: string | null;
|
|
83
|
+
readonly proposedAt?: string | null;
|
|
84
|
+
/** ISO date promoted into the trusted graph; null = still a proposal. */
|
|
85
|
+
readonly confirmed?: string | null;
|
|
86
|
+
/** ISO date a human rejected it (sticky — not re-surfaced or re-asked). */
|
|
87
|
+
readonly rejectedAt?: string | null;
|
|
88
|
+
/** ISO date last surfaced as an in-context question (cooldown for re-asking). */
|
|
89
|
+
readonly askedAt?: string | null;
|
|
90
|
+
}
|
|
91
|
+
/** Why a raw proposal was dropped (collected into the run report; never stored). */
|
|
92
|
+
export type RejectReason = "unknown-relation" | "domain-range" | "no-evidence" | "bad-confidence" | "bad-verdict" | "verifier-disagreed";
|
|
93
|
+
export interface IngestReport {
|
|
94
|
+
readonly accepted: number;
|
|
95
|
+
readonly rejected: readonly {
|
|
96
|
+
readonly reason: RejectReason;
|
|
97
|
+
readonly raw: RawProposal;
|
|
98
|
+
}[];
|
|
99
|
+
}
|
|
100
|
+
export type { ExtractResult, RecordInput };
|
|
101
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/enrich/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vortex-os/ontos — LLM enrichment types (0.2.0, agent-mediated).
|
|
3
|
+
*
|
|
4
|
+
* The ontos library has no generative LLM of its own (memory-extended ships only
|
|
5
|
+
* a local embedder). So enrichment is AGENT-MEDIATED: ontos emits an extraction
|
|
6
|
+
* REQUEST, the running agent (Claude Code) fulfils it and returns RAW proposals
|
|
7
|
+
* (already self/cross-checked), and the library validates → tiers → stores them as
|
|
8
|
+
* PROPOSALS — never into the trusted `relations` graph. See the 0.2.0 design.
|
|
9
|
+
*/
|
|
10
|
+
export const TRUST_RANK = { high: 3, medium: 2, low: 1 };
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/enrich/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,MAAM,CAAC,MAAM,UAAU,GAAoC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation for agent-mediated enrichment (0.2.0): the controlled vocabulary,
|
|
3
|
+
* the domain/range table, id-prefix typing, and the request builder. Pure — no
|
|
4
|
+
* I/O, no store; the caller passes a resolver so this stays testable.
|
|
5
|
+
*/
|
|
6
|
+
import type { ExtractResult, RecordInput } from "../extract/types.js";
|
|
7
|
+
import type { EnrichmentRequest, RawProposal, RejectReason, ValidatedProposal } from "./types.js";
|
|
8
|
+
export { OBJECT_TYPES, RELATION_TYPES, DOMAIN_RANGE, typeFromId } from "./domain-range.js";
|
|
9
|
+
/** A resolver maps a proposed ref to a canonical object id, or null if unknown. */
|
|
10
|
+
export type Resolver = (ref: string) => string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Validate one raw proposal against the vocabulary, domain/range, and id
|
|
13
|
+
* resolution order. Returns the validated proposal or a reject reason. Domain/range
|
|
14
|
+
* is enforced only when BOTH ends resolve to a typed id; an unresolved end keeps its
|
|
15
|
+
* raw label (sourceResolved/targetResolved=false) and skips the constraint it can't
|
|
16
|
+
* check (a later resolution/confirmation re-checks it).
|
|
17
|
+
*/
|
|
18
|
+
export declare function validateProposal(raw: RawProposal, resolve: Resolver): {
|
|
19
|
+
ok: true;
|
|
20
|
+
value: ValidatedProposal;
|
|
21
|
+
} | {
|
|
22
|
+
ok: false;
|
|
23
|
+
reason: RejectReason;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Build the extraction request for one record (Phase 1 §4 step 3). Pure: the
|
|
27
|
+
* caller supplies the known object ids the agent should reuse.
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildEnrichmentRequest(record: RecordInput, deterministic: ExtractResult, knownObjectIds?: readonly string[]): EnrichmentRequest;
|
|
30
|
+
/** Convenience: deterministic extraction + the request that fills its gaps. */
|
|
31
|
+
export declare function requestFor(record: RecordInput, knownObjectIds?: readonly string[]): EnrichmentRequest;
|
|
32
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/enrich/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGlG,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAM3F,mFAAmF;AACnF,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAEtD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,QAAQ,GAChB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAkD9E;AAYD;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,WAAW,EACnB,aAAa,EAAE,aAAa,EAC5B,cAAc,GAAE,SAAS,MAAM,EAAO,GACrC,iBAAiB,CAiBnB;AAED,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,GAAE,SAAS,MAAM,EAAO,GAAG,iBAAiB,CAEzG"}
|