Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Numbered in suggested reading order. Each tutorial is self-contained.
- [reference-lib-nal.md](./reference-lib-nal.md) — NAL rules with truth formulas; confirmed vs. non-functional patterns
- [reference-lib-pln.md](./reference-lib-pln.md) — Modus Ponens, abduction, revision; current limits
- [reference-lib-ona.md](./reference-lib-ona.md) — OpenNARS for Applications — planned real-time / temporal engine (experimental, not installed by default)
- [reference-lib-telos-goals.md](./reference-lib-telos-goals.md) — Optional goal graph: `goal` / `rel` schema, conflict / blocked / aligned lenses, `telos-enable` prompt extension (opt-in, not loaded by `lib_omega.metta`)
- [reference-orchestration.md](./reference-orchestration.md) — Engine selection, stopping criteria, action thresholds, defense stack
- [reference-failure-modes.md](./reference-failure-modes.md) — Documented failures, error rates, mitigations

Expand Down
118 changes: 118 additions & 0 deletions docs/reference-lib-telos-goals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Reference — `lib_telos_goals.metta`

An optional goal-graph module. Omega is goal-autonomous (it creates goals, pursues them, tracks progress) but the core ships no inspectable model of *what the goals are*. This module adds one in Omega's own idiom: AtomSpace atoms plus derivation rules, so an agent can represent individual and collective goals, surface conflicts and blockers, and reason about alignment symbolically instead of guessing.

It is **opt-in** and **side-effect-free on load**. `lib_omega.metta` does not import it, and nothing in the file runs at import time: it only defines the schema contract, the query rules, and two functions that install or remove a prompt extension when you call them.

---

## Loading

```metta
!(import! &self (library Omega lib_telos_goals))
```

---

## Schema

Two atom shapes. Every relation reads **source → destination**, and the direction matters for the rules below.

| Atom | Meaning |
|---|---|
| `(goal <id> <scope> <owner> <status>)` | A goal. `scope` is `individual` or `collective`. `status` is `active`, `proposed`, `achieved`, or `abandoned`. |
| `(rel supports <src> <dst>)` | Achieving `src` advances `dst`. |
| `(rel conflicts <src> <dst>)` | `src` and `dst` cannot both be achieved. Assert once per pair; the conflict lens does not symmetrise. |
| `(rel subsumes <parent> <child>)` | `parent` is the broader goal and `child` is a sub-goal of it. |
| `(rel depends-on <src> <dst>)` | `src` cannot progress until `dst` is achieved. |

---

## Who asserts the atoms

**Omega does not infer or assert `goal` / `rel` atoms on its own.** The module is a representation and a set of queries. The LLM layer populates it through the existing `metta` skill while it reads a conversation, and reads it back the same way:

```
metta (add-atom &self (goal alice-train individual alice active))
metta (add-atom &self (rel conflicts alice-train dao-fair-access))
metta (telos-reading)
```

`(telos-enable)` teaches the LLM to do exactly that. It calls the core `add-prompt-extension` hook from `src/skills.metta` to insert a `GOAL GRAPH` section into the prompt, after the SKILL section and before OUTPUT_FORMAT, describing the schema, the `add-atom` calls, the read lenses, and the rule that every `conflict-between` and `blocked` result is reported to the user before the agent acts on a goal. `(telos-disable)` removes the section again. Neither runs until called.

---

## Lenses

### Zero-arity lenses

Each of these queries the whole graph and is folded into `(telos-reading)`.

| Rule | Yields | Meaning |
|---|---|---|
| `(telos-conflicts)` | `(conflict-between $a $b)` | Every asserted conflict pair. |
| `(telos-collective-goals)` | `(collective-goal $g $owner)` | Every collective goal, any status. |
| `(telos-achieved-goals)` | `(achieved-goal $g $owner)` | Every achieved goal, any scope. |
| `(telos-abandoned-goals)` | `(abandoned-goal $g $owner)` | Every abandoned goal. Surfacing these stops the agent chasing a goal its owner dropped. |
| `(telos-subgoals)` | `(subgoal $child of $parent)` | The sub-goal structure declared by `subsumes`. |
| `(telos-blocked)` | `(blocked $g on $dep)` | A goal whose `depends-on` target is not yet achieved. An abandoned dependency still blocks. |
| `(telos-aligned)` | `(aligns $i with $c)` | An individual goal that `supports` a collective goal of some owner. |

### The full reading

```metta
!(telos-reading)
```

The superposition of every zero-arity lens above. Call it after the goal and relation atoms are in place.

### Parameterised probes

These take an owner or a goal id, so they are queried on their own and are **not** part of `(telos-reading)`.

| Rule | Yields | Meaning |
|---|---|---|
| `(telos-goals-of $owner)` | `(goal-of $owner $g)` | The individual goals of one stakeholder. |
| `(telos-achieved $g)` | `True` or empty | Whether one goal's status atom says `achieved`. |

---

## Worked example

```metta
!(import! &self (library Omega lib_telos_goals))

(goal alice-train individual alice active)
(goal bob-share individual bob active)
(goal grant individual alice achieved)
(goal dao-fair-access collective dao active)
(goal gpu-quota collective dao proposed)
(rel conflicts alice-train bob-share)
(rel supports bob-share dao-fair-access)
(rel depends-on dao-fair-access gpu-quota)
(rel subsumes dao-fair-access gpu-quota)

!(telos-conflicts) ; (conflict-between alice-train bob-share)
!(telos-achieved-goals) ; (achieved-goal grant alice)
!(telos-subgoals) ; (subgoal gpu-quota of dao-fair-access)
!(telos-blocked) ; (blocked dao-fair-access on gpu-quota)
!(telos-aligned) ; (aligns bob-share with dao-fair-access)
!(telos-goals-of alice) ; (goal-of alice alice-train) (goal-of alice grant)
!(telos-reading) ; all of the zero-arity results at once
```

---

## Tests

`tests/tests_lib_telos_goals.metta` covers every lens, both probes, the direction of `subsumes`, the membership of each lens in `(telos-reading)`, and the `telos-enable` / `telos-disable` round trip through `getPromptExtensions`. It runs with the rest of the MeTTa unit tests:

```sh
PETTA_PATH=/PeTTa sh tests/mettatest.sh
```

---

## Origin

Contributed from the BGI Sprint I project Telos (https://github.com/arielagor/telos, MIT), which also ships a 14-scenario goal-understanding benchmark that can score Omega or any other agent on goal *misunderstanding*: pursuing the literal request and missing the real goal, serving one person while externalising cost onto the group, or chasing an abandoned goal.
85 changes: 85 additions & 0 deletions lib_telos_goals.metta
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
; lib_telos_goals -- optional goal-graph module for Omega. Not loaded by lib_omega.metta.
; Load with: !(import! &self (library Omega lib_telos_goals))
; Reference: docs/reference-lib-telos-goals.md
;
; Omega does not infer or assert goal atoms by itself. The LLM layer asserts them through
; the `metta` skill (metta (add-atom &self (goal ...))) and reads them back through the
; lenses below; (telos-enable) installs a prompt extension that tells the LLM how.
;
; Schema (all relations read src -> dst):
; (goal <id> <scope> <owner> <status>) scope: individual | collective
; status: active | proposed | achieved | abandoned
; (rel supports <src> <dst>) achieving src advances dst
; (rel conflicts <src> <dst>) src and dst cannot both be achieved (assert once)
; (rel subsumes <parent> <child>) parent is the broader goal, child is a sub-goal of it
; (rel depends-on <src> <dst>) src cannot progress until dst is achieved

; ---- Zero-arity lenses: every one of these is included in (telos-reading) ----

; All conflict pairs the agent must surface (across ALL goals).
(= (telos-conflicts)
(match &self (rel conflicts $a $b) (conflict-between $a $b)))

; Every collective goal (what the commons wants).
(= (telos-collective-goals)
(match &self (goal $g collective $owner $status) (collective-goal $g $owner)))

; Every achieved goal, any scope, any owner.
(= (telos-achieved-goals)
(match &self (goal $g $scope $owner achieved) (achieved-goal $g $owner)))

; Every abandoned goal. Surfacing these stops the agent chasing a goal its owner dropped.
(= (telos-abandoned-goals)
(match &self (goal $g $scope $owner abandoned) (abandoned-goal $g $owner)))

; Sub-goal structure: (rel subsumes <parent> <child>) yields (subgoal <child> of <parent>).
(= (telos-subgoals)
(match &self (rel subsumes $parent $child) (subgoal $child of $parent)))

; BLOCKED: a goal that depends-on another goal that is not yet achieved.
; An abandoned dependency still blocks: it will never become achieved.
(= (telos-blocked)
(match &self (rel depends-on $g $dep)
(match &self (goal $dep $s2 $o2 $st2)
(if (== $st2 achieved) (empty) (blocked $g on $dep)))))

; Cross-level ALIGNMENT: an individual goal that SUPPORTS a collective goal.
(= (telos-aligned)
(match &self (rel supports $i $c)
(match &self (goal $i individual $o1 $s1)
(match &self (goal $c collective $o2 $s2)
(aligns $i with $c)))))

; The full goal reading: the superposition of every zero-arity lens above.
; The parameterised probes below (telos-goals-of, telos-achieved) take an owner or a goal
; id, so they are queried on their own rather than folded into the reading.
(= (telos-reading)
(superpose ((telos-conflicts)
(telos-collective-goals)
(telos-achieved-goals)
(telos-abandoned-goals)
(telos-subgoals)
(telos-blocked)
(telos-aligned))))

; ---- Parameterised probes: not part of (telos-reading) ----

; Goals owned by ANY given stakeholder (individual goal understanding).
(= (telos-goals-of $owner)
(match &self (goal $g individual $owner $status) (goal-of $owner $g)))

; A goal is ACHIEVED when its status atom says so.
(= (telos-achieved $g)
(match &self (goal $g $scope $owner achieved) True))

; ---- Agent integration (opt-in; nothing here runs at import) ----

; Teach the LLM the schema and the metta-skill calls that populate and read the graph.
; Uses the core prompt-extension hook from src/skills.metta; no effect until called.
(= (telos-enable)
(add-prompt-extension telos-goals
"GOAL GRAPH: when a message reveals what someone wants, record it as atoms and reason over them symbolically instead of guessing. Assert a goal with: metta (add-atom &self (goal <id> <individual or collective> <owner> <active or proposed or achieved or abandoned>)). Assert a relation with: metta (add-atom &self (rel <supports or conflicts or subsumes or depends-on> <src> <dst>)); subsumes reads parent then child, depends-on reads goal then prerequisite. Read the graph with: metta (telos-reading) for every lens, or metta (telos-conflicts), metta (telos-blocked), metta (telos-aligned), metta (telos-goals-of <owner>). Tell the user about every conflict-between and blocked result before acting on a goal."))

; Remove the extension again.
(= (telos-disable)
(remove-prompt-extension telos-goals))
75 changes: 75 additions & 0 deletions tests/tests_lib_telos_goals.metta
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
!(import! &self ./tests/lib/utils)
!(import! &self ../src/helper.py)
!(import! &self ./src/utils)
!(import! &self ./src/skills)
!(import! &self ./src/loop)
!(import! &self ./lib_telos_goals)

; Fixture: the atoms an agent would assert through the metta skill.
(goal alice-train individual alice active)
(goal bob-share individual bob active)
(goal old-rust individual alice abandoned)
(goal grant individual alice achieved)
(goal dao-fair-access collective dao active)
(goal gpu-quota collective dao proposed)
(rel conflicts alice-train bob-share)
(rel supports bob-share dao-fair-access)
(rel depends-on dao-fair-access gpu-quota)
(rel subsumes dao-fair-access gpu-quota)

; ---- Zero-arity lenses ----

!(test (expression-count-item (collapse (telos-conflicts)) (conflict-between alice-train bob-share)) 1)
!(test (expression-count-item (collapse (telos-conflicts)) (conflict-between bob-share alice-train)) 0)

!(test (expression-count-item (collapse (telos-collective-goals)) (collective-goal dao-fair-access dao)) 1)
!(test (expression-count-item (collapse (telos-collective-goals)) (collective-goal gpu-quota dao)) 1)
!(test (expression-count-item (collapse (telos-collective-goals)) (collective-goal alice-train alice)) 0)

!(test (expression-count-item (collapse (telos-achieved-goals)) (achieved-goal grant alice)) 1)
!(test (expression-count-item (collapse (telos-achieved-goals)) (achieved-goal alice-train alice)) 0)

!(test (expression-count-item (collapse (telos-abandoned-goals)) (abandoned-goal old-rust alice)) 1)
!(test (expression-count-item (collapse (telos-abandoned-goals)) (abandoned-goal grant alice)) 0)

; (rel subsumes <parent> <child>) reads parent then child.
!(test (expression-count-item (collapse (telos-subgoals)) (subgoal gpu-quota of dao-fair-access)) 1)
!(test (expression-count-item (collapse (telos-subgoals)) (subgoal dao-fair-access of gpu-quota)) 0)

; dao-fair-access depends on gpu-quota, which is only proposed, so it is blocked.
!(test (expression-count-item (collapse (telos-blocked)) (blocked dao-fair-access on gpu-quota)) 1)

!(test (expression-count-item (collapse (telos-aligned)) (aligns bob-share with dao-fair-access)) 1)
!(test (expression-count-item (collapse (telos-aligned)) (aligns alice-train with dao-fair-access)) 0)

; ---- Parameterised probes ----

!(test (expression-count-item (collapse (telos-goals-of alice)) (goal-of alice alice-train)) 1)
!(test (expression-count-item (collapse (telos-goals-of alice)) (goal-of alice old-rust)) 1)
!(test (expression-count-item (collapse (telos-goals-of alice)) (goal-of alice bob-share)) 0)
!(test (expression-count-item (collapse (telos-goals-of dao)) (goal-of dao dao-fair-access)) 0)

!(test (telos-achieved grant) True)
!(test (collapse (telos-achieved alice-train)) ())

; ---- The full reading includes every zero-arity lens ----

!(test (expression-count-item (collapse (telos-reading)) (conflict-between alice-train bob-share)) 1)
!(test (expression-count-item (collapse (telos-reading)) (collective-goal dao-fair-access dao)) 1)
!(test (expression-count-item (collapse (telos-reading)) (achieved-goal grant alice)) 1)
!(test (expression-count-item (collapse (telos-reading)) (abandoned-goal old-rust alice)) 1)
!(test (expression-count-item (collapse (telos-reading)) (subgoal gpu-quota of dao-fair-access)) 1)
!(test (expression-count-item (collapse (telos-reading)) (blocked dao-fair-access on gpu-quota)) 1)
!(test (expression-count-item (collapse (telos-reading)) (aligns bob-share with dao-fair-access)) 1)

; ---- Prompt extension round trip (the agent-integration hook) ----

!(test (progn
(telos-enable)
(contains-text (getPromptExtensions) "GOAL GRAPH"))
True)

!(test (progn
(telos-disable)
(contains-text (getPromptExtensions) "GOAL GRAPH"))
False)