8000
Skip to content

Latest commit

 

History

37 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oh-my-goals

A local MeTTa memory and reasoning MCP for coding agents.

You talk to a coding agent normally. Oh My Goals gives the agent a local memory: it turns the material parts of the conversation into short English propositions, parses them into Semantic Hypergraph structures through a real parser, and keeps them in a MeTTa space that survives across turns and MCP restarts. The agent queries that memory before it plans and ranks its candidate actions against the stored goals, norms, and evidence before it acts.

The reasoning is written in MeTTa and runs locally on MeTTa TS. Nobody writes MeTTa, a JSON decision packet, or a numeric score: the agent authors controlled English and the memory does the rest. The same package is an MCP server for Claude Code, Codex, and OpenCode, a matching Agent Skill, and a TypeScript library.

The same memory is also a self-contained scientific literature assistant. Give it a paper by DOI or arXiv id and it fetches, parses, and stores the work with its retraction status, reads it into checkable claims, tracks citations, and reasons across papers: it corroborates a claim several works assert, surfaces contradictions between them, and when a paper is retracted it deactivates every claim and conclusion that rested on it, with a proof. The differentiator is not retrieval. It is a persistent, verifiable, contradiction-aware knowledge base with retraction-aware invalidation, all of it symbolic.

Important

A recommendation from Oh My Goals is advice, not authorization. The agent must still enforce user approval, handler availability, and any operating-system security controls before it acts.

The memory loop

A coding agent reaches the loop through six MCP tools:

Tool What it does
remember Store controlled-English propositions (facts, goals, norms, actions) with their real sources, or a proof-backed derived conclusion.
query Answer an English question over memory, keeping exact, reasoned, and semantically related results distinct.
solve Rank the stored candidate actions against the goals, norms, and evidence, reporting a recommendation only for a clear, unblocked winner.
revise Supersede a proposition with a correction.
forget Retract or permanently purge exact propositions.
explain Read a proposition back to its premises, sources, and lifecycle.

From a built checkout, register the server and install the Agent Skill for your agent in one step:

node dist/cli.js install --agent claude --scope project

That merges the MCP server into the agent's config and installs the skill that teaches the agent when to use it. The Agent Skill describes the loop and the controlled-English contract; the MCP tool reference lists every field. Memory scopes, lifecycle, persistence, semantic retrieval, and the HyperBase, MeTTa, and MCP boundaries are documented in ARCHITECTURE.md.

The parser is the local mettabase AlphaBeta parser, reached through a replaceable adapter. Set OH_MY_GOALS_METTABASE_DIR and OH_MY_GOALS_HYPERBASE_PYTHON so the server can parse English; install and install-mcp carry those settings into the registered server when they are present in your environment.

Scientific literature assistant

Six more MCP tools turn the same knowledge base into a research assistant over the scientific literature. Every mechanical part is an existing, mostly keyless open tool; the novel part is the symbolic layer over them.

Tool What it does
find_papers Search Semantic Scholar and OpenAlex for candidate works, ranked across sources by reciprocal rank fusion, with the ones already in your library flagged.
ingest_paper Fetch a paper by DOI or arXiv id, parse it through GROBID into sections and references, store it as a work with its Crossref retraction status, seed its citation edges, and, when a model is configured, read it into validated claims.
add_claim Store one controlled-English claim drawn from a work, sourced with a section-and-quote locator.
citations Walk the citation graph of a work by MeTTa chaining: the works it cites or the works that cite it, one hop or transitively, with an option to fetch the wider graph from OpenAlex.
review Gather the claims about a topic and read agreement and conflict across works: which statements several works corroborate, which are contradicted, each with its supporting and opposing works, a projected opinion, and warnings for a corrected or flagged source.
check_retractions Re-check every work against Crossref, invalidate the claims of any newly retracted or withdrawn work, and flag corrections and expressions of concern; optionally flag the retracted works you cite.

A paper is a source, so marking a work retracted is the same operation as retracting a source: every claim sourced from it goes inactive, every conclusion resting on those claims goes inactive, and explain names the retraction as the cause. Corroboration and contradiction are read as paraconsistent evidence, where a statement can carry support and opposition at once, then projected to a Subjective-Logic opinion. The grouping and the invalidation are MeTTa chaining; the worker only fetches and parses.

The research worker is a resident Python subprocess configured by OH_MY_GOALS_RESEARCH_PYTHON (an interpreter with scipdf_parser), OH_MY_GOALS_GROBID_URL (a running GROBID service; without it ingestion degrades to metadata and references), and the polite-pool emails OH_MY_GOALS_CROSSREF_EMAIL and OH_MY_GOALS_OPENALEX_EMAIL. The claim extractor is an optional OpenAI-compatible model configured by OH_MY_GOALS_LLM_BASE_URL, OH_MY_GOALS_LLM_MODEL, and an optional OH_MY_GOALS_LLM_API_KEY, so a local runtime or a hosted provider both work. Without a model you supply claims through add_claim.

A decision in one minute

Underneath solve is a decision core you can also call directly with a complete JSON scenario. Suppose a coding agent can apply a verified change or apply the same change before verification.

Candidate action Required goal Explicit rule Evidence Result
Apply the verified change Satisfied None blocks it 9 of 10 checks passed, with 95% coverage Recommended
Apply the unverified change Missing Forbidden until verification passes No calibrated evidence Blocked

The abridged receipt is:

{
  "selected": "apply-verified",
  "status": "recommended",
  "selection_tied": false,
  "automatic_execution_allowed": true,
  "decisions": [
    {
      "action_id": "apply-verified",
      "score": 0.8649,
      "status": "recommended",
      "norm_status": "unregulated",
      "missing_required_goals": []
    },
    {
      "action_id": "apply-unverified",
      "score": -1,
      "status": "blocked",
      "norm_status": "forbidden",
      "norm_reasons": [
        "forbid:No passing verification result"
      ],
      "missing_required_goals": [
        "safe-change"
      ]
    }
  ]
}

The verified action wins because it satisfies the required goal and has attributable evidence. The other action is blocked by an explicit norm rather than merely receiving a lower score. The receipt preserves both outcomes so the choice can be reviewed later.

Why use it

A model can propose an action, but the proposal does not carry your goals, policies, or authority. A plain allow-or-deny check also cannot answer every choice. You may need to compare several permitted actions, account for required outcomes, weigh evidence of different quality, and refuse to break a tie silently.

Oh My Goals makes those inputs explicit and gives the caller one replayable result:

  • priority-aware obligations, permissions, and prohibitions;
  • weighted required and optional goals;
  • evidence with separate strength, confidence, and source;
  • ranked candidate actions with reasons and missing goals;
  • explicit tie detection and automatic-execution eligibility;
  • the complete scenario declaration needed to audit the result.

Quickstart

Node.js 22.13.0 or newer is required. The package is currently installed from a checkout because version 0.1.0 is not yet published to npm.

git clone https://github.com/MesTTo/oh-my-goals.git
cd oh-my-goals
npm ci
npm run build

Save this as scenario.json:

{
  "scenario": {
    "title": "Apply a change?",
    "goals": [
      {
        "id": "safe-change",
        "owner": "maintainers",
        "statement": "Ship only a verified change",
        "weight": 1,
        "kind": "collective",
        "required": true
      }
    ],
    "norms": [
      {
        "id": "require-verification",
        "mode": "forbid",
        "targetAction": "apply-unverified",
        "reason": "No passing verification result",
        "priority": 10
      }
    ],
    "actions": [
      {
        "id": "apply-verified",
        "label": "Apply the verified change",
        "description": "Apply after the required checks pass",
        "satisfies": ["safe-change"]
      },
      {
        "id": "apply-unverified",
        "label": "Apply the unverified change",
        "description": "Apply before the required checks pass",
        "satisfies": []
      }
    ]
  },
  "evidence": {
    "apply-verified": {
      "strength": 0.9,
      "confidence": 0.95,
      "source": "9 of 10 required checks passed with 95% check coverage"
    }
  }
}

Run the decision:

node dist/cli.js decide --input scenario.json --pretty

The command prints the complete version of the receipt shown above. Use --input - to read JSON from stdin. Invalid input exits with code 2. Runtime failures exit with code 1.

The input reference lists every field and default. Input is limited to 2 MiB.

Install the packed library into another project

Build and verify a tarball from the checkout:

cd /path/to/oh-my-goals
npm ci
npm run verify
mkdir -p ai-tmp
npm pack --pack-destination ai-tmp

cd /path/to/consumer-project
npm install /path/to/oh-my-goals/ai-tmp/oh-my-goals-0.1.0.tgz
npx --no-install oh-my-goals --help

The JavaScript entry point is ESM-only. CommonJS callers must use dynamic import().

What you provide

Input Meaning
Actions The choices that are actually available. Each action declares which goals it satisfies.
Goals Outcomes an action should advance. Goals can be weighted, required, and marked as individual or collective.
Norms Explicit rules that oblige, permit, or forbid an action. Higher-priority rules defeat lower-priority conflicts.
Evidence Support for an action as a strength, a confidence value, and an attributable source.

Oh My Goals does not invent any of these values. If a policy choice would change the result, the caller must obtain that choice from the user or another authoritative source.

Strength and confidence are different

strength measures how strongly the evidence supports the action. confidence measures the reliability or coverage of that estimate. A passing test supports only the behavior that test checks. It does not justify confidence about unrelated behavior.

When evidence is omitted, the action receives a neutral strength of 0.5 with confidence 0. That prior cannot produce a recommendation by itself.

How to read the receipt

Field What it tells you
selected The highest-ranked action after norms, goals, motivation, and evidence are evaluated.
status The selected action's status: recommended, candidate, weak, or blocked.
decisions[].score The exact score used for stable ranking. Blocked decisions use -1.
norm_status and norm_reasons Whether the action is unregulated, permitted, obligated, forbidden, or in conflict, plus the rules that caused it.
missing_required_goals Required outcomes the action does not satisfy.
selection_tied and tied_actions Whether more than one action shares the top score within the tie tolerance.
automatic_execution_allowed Whether the reasoning result is recommended and untied. It is not user authorization.
scenario_declaration The normalized goals, norms, actions, and notes needed to replay the decision.

Even when automatic_execution_allowed is true, an automatic caller should also confirm that the selected handler exists and that the user has already authorized the action.

How it works

caller-owned actions + goals + norms + evidence
                        |
                        v
        TypeScript validation and atom encoding
                        |
                        v
             native MeTTa decision rules
        norms -> goals -> scores -> ranking -> ties
                        |
                        v
            decoded, auditable JSON receipt
                        |
                        v
     caller checks authorization and handler availability
                        |
                        v
              optional caller-owned execution

The main rule module is metta/oh-my-goals.metta. MeTTa owns norm resolution, goal analysis, scoring, status assignment, stable ranking, tie handling, motivation consensus, automatic-execution eligibility, and the selected PLN and SNARS formulas.

TypeScript owns the runtime boundary. It validates input, encodes and decodes atoms, manages files and optional processes, and dispatches caller-provided action handlers. Large collections use bounded grounded operations for specific numeric and structural work, while MeTTa still makes the decision. The exact boundary is documented in ARCHITECTURE.md.

Use it with coding agents

An agent reaches Oh My Goals two ways, and the CLI sets up both. The MCP server makes the tools reachable; the Agent Skill teaches Claude Code, Codex, and OpenCode when and how to use them.

node dist/cli.js install --agent all --scope project

The install command registers the MCP server in the agent's config and installs the matching skill. install-mcp and install-skill do each step alone, and install-mcp --remove deregisters the server. Registration keeps three config formats and merges into an existing config without disturbing the user's other servers: Claude Code's .mcp.json, Codex's .codex/config.toml, and OpenCode's opencode.json. The registered server launches this same CLI, so the exact installed version runs.

--agent all sets up the shared .agents layout used by Codex and the .claude layout used by Claude Code; use --agent opencode for OpenCode. Use --scope user for the corresponding directories under your home directory. Existing differing skill files are preserved unless you pass --force.

Once installed, a request can be as direct as:

Remember that preserving the public API is required and that applying an unverified change is forbidden, then compare applying the verified change against gathering more evidence.

The agent stores the task's goals, norms, and candidate actions as controlled English through remember, ranks them with solve, and reads memory back with query and explain. Oh My Goals does not call a hosted model, read agent credentials, or gain permission to execute an action.

Upgrading from the former local skill name

Earlier local installs used a goalchainer directory. The installer does not delete user-owned skill trees. Install oh-my-goals, confirm that the new skill is discovered, then remove the old directory if you no longer need it. The goalchainer and goalchainer-ts binaries remain compatibility aliases during this transition.

TypeScript API

import { readFile } from "node:fs/promises";
import {
  GoalChainer,
  explainDecisions,
  goalChainerRunToJson,
} from "oh-my-goals";

const input = JSON.parse(await readFile("scenario.json", "utf8"));
const chainer = new GoalChainer();
const run = chainer.evaluate(input);

console.log(goalChainerRunToJson(run));
console.log(explainDecisions(run.decisions).join("\n"));

if (!run.automaticExecutionAllowed) {
  process.exitCode = 2;
}

GoalChainer rejects unknown fields, duplicate IDs, invalid probabilities, and dangling goal or action references. executeDecision refuses blocked decisions and requires a matching caller-owned handler.

After the caller separately confirms user authorization and handler availability, it can call executeDecision(run.selected, context, handlers). That call does not infer or grant authorization.

The CLI and runGoalChainer use static evidence. Applications that need queries against another reasoner can call evaluateScenario with a custom EvidenceReasoner. ContextualQueryEvidenceReasoner passes each action's evidenceQuery and evidenceAtoms to a caller-injected synchronous adapter.

Decision behavior

Norms

Norm modes are oblige, permit, and forbid. The highest-priority applicable norms decide the effective status. Opposing top-priority norms produce conflict instead of an arbitrary winner. Forbidden and conflicting actions are blocked.

Goals

Goal weights determine coverage. A required goal can prevent an otherwise high-scoring action from becoming recommended. Individual and collective goal membership also feeds the optional motivation consensus path.

Statuses and ties

Status Meaning
recommended Score is at least 0.72, the action is not blocked, and no required goal is missing.
candidate Score is at least 0.5, but the recommendation conditions are not all met.
weak Score is below 0.5 and the action is not blocked.
blocked A prohibition or unresolved norm conflict prevents selection for execution.

Scores within 1e-12 are treated as tied. The declaration order remains stable, but automatic_execution_allowed is false so input order cannot silently authorize one of the tied actions.

Exact default scoring model

With motivation enabled, the score is:

0.54 * normalized_motivation
+ 0.38 * strength * confidence
+ 0.10 when the action is obligated

Motivation uses individual and collective goal membership masks plus caller-supplied correlations and risks. Goal weights affect coverage, while membership feeds motivation. Consensus values are min-max normalized. Equal values normalize to 1.

With motivation disabled, the score is:

0.42 * goal_coverage
+ 0.38 * strength * confidence
+ 0.12 * min(individual_coverage, collective_coverage)
+ 0.10 when the action is obligated

Blocked decisions use score -1.

Library surfaces

Area Public entry points
Complete decision gate GoalChainer, runGoalChainer, evaluateScenario
Norm resolution resolveNorms, resolveNormsBatch
Scoring and ranking scoreActions, decideActions
Evidence and PLN StaticEvidenceReasoner, PlnEvidenceReasoner, ContextualQueryEvidenceReasoner, gradeBeliefs
Motivation consensusDecision
SNARS opinions assess, derive
Task directives createDirectivePlan, DirectiveLifecycle
Memory and HyperBase ingestion createMemorySpace, createHyperbaseParser, ingestStatements
Optional Prolog comparison decideActionsWithProlog, verifyScorePrologParity, checkDirectivePrologParity
Caller safety helpers redactRecord, detectLeaks, executeDecision

MeTTa and optional interop

The framework pins the MeTTa TS runtime packages to version 1.1.4. The native paths use standard-library operations such as foldl-atom, map-atom, filter-atom, msort, and is-member. Bounded host operations cover large compensated vector math, structural trees, stable ranking, and indexed PLN matching. They do not compare candidate scores or select a winner outside MeTTa.

SWI-Prolog is optional. The named score and directive relations can be compared with their MeTTa counterparts:

node dist/cli.js prolog-check --pretty

The command starts the local swipl executable and exits nonzero if a checked relation differs. It does not claim Prolog parity for every MeTTa relation.

ProbMeTTa is not ported or bundled. A separately managed PeTTa and ProbMeTTa process can be connected through an EvidenceReasoner or ContextualQueryEvidenceReasoner, returning strength, confidence, source, and proof data to this decision gate.

Scope and limits

  • Oh My Goals does not discover available actions or invent goals, norms, or evidence.
  • It does not intercept shell commands, isolate processes, filter prompts, or replace operating-system permissions.
  • It does not call Claude Code, Codex, OpenCode, or another hosted model. Agent authentication remains with the caller.
  • It contains no built-in scenario data or action handlers.
  • The JSON CLI accepts static evidence. Contextual evidence requires an injected TypeScript reasoner.
  • Its PLN, SNARS, deontic, motivation, and directive exports are the documented decision relations, not complete replacements for a theorem prover, planner, probabilistic logic runtime, or NARS system.

Do not put credentials, private keys, tokens, or unredacted sensitive text in the input. The receipt repeats the scenario and evidence provenance.

Troubleshooting

  • Parser not configured. remember, revise, and query need the HyperBase parser. Without OH_MY_GOALS_METTABASE_DIR and OH_MY_GOALS_HYPERBASE_PYTHON they fail with "HyperBase parser is not configured: set ...". Point both at a local mettabase checkout and its Python interpreter. solve, explain, and forget do not parse and keep working without it.
  • A statement is rejected. The parser stores only a faithful controlled-English proposition whose mood suits its kind. A question, an imperative stored as anything but a goal, or an unparseable sentence returns rewrite feedback and stores nothing. Rewrite it as a plain declarative sentence and retry.
  • A stale revision. revise and forget with an expectedRevision that no longer matches return { ok: false, code: "stale_revision", expected, actual } and change nothing. Read the current revision with explain and retry with it, or omit expectedRevision to skip the check.
  • An unsupported question. A question that does not compile to the one-slot subject form, such as an object question that needs do-support, returns an unsupported code and rewrite feedback rather than a wrong answer, and still lists semantic neighbours under related. Rephrase as "Which ...?" for an exact answer.
  • A semantic index without the contextual model. The default token-hash provider is deterministic but blind to paraphrase, and the contextual bge-small-en-v1.5 provider needs the optional @huggingface/transformers peer dependency. When it is absent the provider falls back to token-hash and the query receipt reports the active provider, so a fallback is never presented as contextual understanding. Insta 6F40 ll the peer dependency for paraphrase matching.
  • A failed purge. forget with mode: "purge" fails closed: it removes the record, scrubs the content with SQLite secure-delete and a WAL checkpoint, and returns not_found for an unknown id or stale_revision for a stale one. If a purge reports an error, nothing was removed; resolve the id or revision and retry.

Status and verification

Oh My Goals is at version 0.1.0 and is not yet published to npm.

npm run verify checks the native MeTTa module, the TypeScript API, the CLI, the packed tarball, optional named Prolog comparisons when SWI-Prolog is available, and the Agent Skill. The package smoke test installs the tarball into an isolated consumer and runs the packaged MeTTa source.

The memory loop is verified end to end against the real HyperBase parser and a real SQLite store. npm run test:mcp-e2e packs the tarball, installs it into a fresh consumer, registers and spawns the packed oh-my-goals mcp server over stdio, and drives the whole loop through it: registration, a natural-language query, ranking, a derived conflict that blocks an action, retraction that restores it, a purge whose canary string is then absent from the database and its journals, and a restart that keeps the memory. It is gated on the parser environment and skips without it, the same way the parser-dependent unit tests do, so the parser-free suite still runs anywhere.

A property-based test fuzzes the memory lifecycle. It replays generated sequences of remember, derive, retract, restore, supersede, add-proof, purge, and restart, and after each step checks the active set, revisions, scope boundaries, purge removal, and restart against a model of the MeTTa rules. It found a purged-id reuse across restart, now prevented by a persisted id high-water mark and pinned by a regression test.

The installer's config is read back by each agent's own MCP CLI: codex mcp list, opencode mcp list, and claude mcp get oh-my-goals each list the registered server, so a project proposition stored through one agent is reachable by another over the same project memory.

Query latency is dominated by the parser subprocess, not the reasoning. Over a representative project memory the HyperBase round-trip is about 52 ms at the median, and the query engine adds about 5 ms on top for both an exact match and a hybrid exact-plus-semantic query, because the token-hash index search is cheap at this size.

Boundary tests cover 5,000 goals, 1,000 ranked actions, 1,000 motivation candidates, large PLN rule sets, malformed inputs, non-finite values, and stable tie behavior.

Development

npm ci
npm run check:metta
npm test
npm run build
npm run test:package

See ARCHITECTURE.md for rule ownership, large-input boundaries, evaluator isolation, optional interop, and verification scope.

License

The package code and documentation are MIT licensed. See LICENSE.

About

A native MeTTa decision gate that ranks agent actions against explicit goals, policy norms, and graded evidence.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0