@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.
Files changed (51) hide show
  1. package/README.md +32 -17
  2. package/dist/actions/index.d.ts +28 -1
  3. package/dist/actions/index.d.ts.map +1 -1
  4. package/dist/actions/index.js +12 -0
  5. package/dist/actions/index.js.map +1 -1
  6. package/dist/enrich/domain-range.d.ts +25 -0
  7. package/dist/enrich/domain-range.d.ts.map +1 -0
  8. package/dist/enrich/domain-range.js +60 -0
  9. package/dist/enrich/domain-range.js.map +1 -0
  10. package/dist/enrich/index.d.ts +50 -0
  11. package/dist/enrich/index.d.ts.map +1 -0
  12. package/dist/enrich/index.js +67 -0
  13. package/dist/enrich/index.js.map +1 -0
  14. package/dist/enrich/tier.d.ts +27 -0
  15. package/dist/enrich/tier.d.ts.map +1 -0
  16. package/dist/enrich/tier.js +38 -0
  17. package/dist/enrich/tier.js.map +1 -0
  18. package/dist/enrich/types.d.ts +101 -0
  19. package/dist/enrich/types.d.ts.map +1 -0
  20. package/dist/enrich/types.js +11 -0
  21. package/dist/enrich/types.js.map +1 -0
  22. package/dist/enrich/validate.d.ts +32 -0
  23. package/dist/enrich/validate.d.ts.map +1 -0
  24. package/dist/enrich/validate.js +104 -0
  25. package/dist/enrich/validate.js.map +1 -0
  26. package/dist/extract/deterministic.d.ts.map +1 -1
  27. package/dist/extract/deterministic.js +20 -0
  28. package/dist/extract/deterministic.js.map +1 -1
  29. package/dist/extract/types.d.ts +1 -1
  30. package/dist/extract/types.d.ts.map +1 -1
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -0
  34. package/dist/index.js.map +1 -1
  35. package/dist/sqlite/index.d.ts +1 -1
  36. package/dist/sqlite/index.d.ts.map +1 -1
  37. package/dist/sqlite/schema.d.ts +1 -1
  38. package/dist/sqlite/schema.d.ts.map +1 -1
  39. package/dist/sqlite/schema.js +38 -0
  40. package/dist/sqlite/schema.js.map +1 -1
  41. package/dist/sqlite/store.d.ts +70 -1
  42. package/dist/sqlite/store.d.ts.map +1 -1
  43. package/dist/sqlite/store.js +244 -1
  44. package/dist/sqlite/store.js.map +1 -1
  45. package/dist/writeback.d.ts +60 -0
  46. package/dist/writeback.d.ts.map +1 -0
  47. package/dist/writeback.js +138 -0
  48. package/dist/writeback.js.map +1 -0
  49. package/package.json +4 -2
  50. package/scripts/enrich-ontos.mjs +182 -0
  51. 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.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]]`), with **no
16
- screen perception and no background daemon** (those are Phase 2, only if Phase 1
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 15/15; confirmed on a real
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
- - **`extract/`** the deterministic extractor (Phase 1 §4): failure ledger →
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. LLM enrichment is a documented `TODO`.
31
- - **`actions/`** — `recurringFailureGuard` (the §5A fast-proof) and `why`
32
- (§5B decision archaeology, evidence-first 3 hops).
33
- - **`scripts/rebuild-ontos.mjs`** read-only walk of `data/_failures`,
34
- `data/decision-log`, `data/_memory` extract true-rebuild the index.
35
-
36
- **Deferred** (Phase 1 follow-ups): frontmatter `ontos:` writeback, LLM
37
- enrichment, confirmation UX, identity embedding-candidates (optional reuse of
38
- `@vortex-os/memory-extended`'s embedder when present), and the `vortex ontos`
39
- CLI / session-start trigger wiring.
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).
@@ -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;AAE5C;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,QAAQ,EAAE,CAKhF;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"}
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"}
@@ -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":"AAGA;;;;;;;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;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"}
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"}