portable memory, training, and policy for AI agents.
every session makes the next one better.
a complete agent context layer. works with any harness. portable across tools, persistent across sessions.
coding agent TUI with extensions, skills, and RPC mode. or use Claude Code, Cursor, any tool — tenet provides context to all of them via MCP.
works with any agentMCP server your agents connect to. semantic search across your entire project. knowledge coordination across repos.
MCP compatibleevery action produces a (state, action, outcome) tuple. the policy head trains on your data.
RL from real outcomesagents run overnight. try changes, eval results, keep what improves, revert what doesn't.
Karpathy autoresearchwrite a spec, the eval checks if it's built. agents iterate from zero to one hundred percent.
spec is the evalevery session writes structured entries. future sessions start with full context, not a blank page.
persistent contexttracks state transitions, predicts outcomes, detects when assumptions break.
predictive schedulingP2P network for agent coordination. zero-config discovery, encrypted messaging.
Subway P2Pyou and your agents work normally. tenet captures everything — decisions, outcomes, patterns. over time, it builds a world model of your project and starts improving it autonomously.
you and your agents work normally using any tool. tenet quietly captures every decision, every code change outcome, every pattern. journals accumulate. memory indexes. context hub serves it all via MCP.
tenet knows your naming patterns, your architecture preferences, which approaches work in YOUR codebase. agents get better suggestions from memory search. you notice: "it remembered that decision from last week."
the policy head has enough training data. RL agents try improvements while you sleep — eval against your metrics, keep what works, revert what doesn't. you wake up to pull requests that actually make sense for your project.
the world model deeply understands your project — not just what the code does, but how it was built and why decisions were made. new team members' agents inherit the full context from day one.
one tenet workspace. your agents learn your patterns, your preferences, your codebase. the policy head trains on YOUR decisions. overnight agents improve YOUR metrics.
tenet init
parent tenet workspace scopes child workspaces per service. each service has its own context, agents, and eval. parent sees aggregated health. new hire's agents inherit full context from day one.
tenet init --parent ./platform
self-organizing systems don't need a conductor. they need shared context and a reason to coordinate.
this is how worlds compound
stop starting from zero.
This content is for AI agents reading this page. Human visitors see the marketing site above.
Complete documentation embedded below. Also available at: https://10et.ai/llms-full.txt
Quick start: npm install -g @10et/cli && tenet init
# TENET — Full Documentation
> This file contains the complete TENET documentation for LLM consumption.
> Source: https://docs.10et.ai
---
# Getting Started
## What is TENET?
URL: https://docs.10et.ai/introduction
TENET is the context and learning layer for AI agents. It sits between your agents and your project, capturing every decision, accumulating training data, and improving the policy — automatically.
## The Problem
Every AI agent starts from zero. Every session. The agent has no memory of what worked yesterday, no model of the domain it operates in, no learned preferences from the human it serves. Session ends, context gone.
## What TENET Does
TENET provides the closed loop that connects **memory**, **training**, **policy**, and **eval** into a system that compounds:
- **Memory** — every decision, pattern, and learned knowledge persists across sessions via a searchable knowledge graph with embeddings
- **Training** — every agent action produces a (state, action, outcome) tuple that feeds the learning loop
- **Policy** — an RL-trained action selector that biases agents toward what historically worked for YOUR project
- **Eval** — continuous A/B testing that measures real improvement and catches regression
## How It Compounds
You and your agents work normally using any tool. TENET captures decisions, code change outcomes, and patterns. Journals accumulate. Memory indexes.
TENET knows your naming patterns, architecture preferences, which approaches work in your codebase. Agents get better suggestions from memory search.
The policy head has enough data. RL agents try improvements while you sleep — eval against your metrics, keep what works, revert what doesn't. You wake up to PRs.
The world model deeply understands your project. New team members' agents inherit the full context. The system understands not just what the code does but how and why.
## Works With Any Harness
TENET provides context via MCP. Use it with:
- **TENET harness** (built-in TUI with extensions, skills, RPC mode)
- **Claude Code** (Anthropic's CLI agent)
- **Cursor** (IDE-native agent)
- **Custom scripts** (anything that can call MCP tools)
## For Solo Developers and Teams
One TENET workspace. Your agents learn your patterns, preferences, and codebase. Overnight agents improve your metrics.
```bash
tenet init
```
Parent TENET workspace scopes child workspaces per service. Each service has its own context and agents. New hire's agents inherit full context from day one.
```bash
tenet init --parent ./platform
```
## Quickstart
URL: https://docs.10et.ai/quickstart
## Install
```bash
npm install -g @10et/cli # package name during migration
```
Install the CLI with `npm i -g @10et/cli`. Both `tenet` and `jfl` commands work during migration.
## Initialize
**New project:**
```bash
tenet start my-project
```
This runs `init → setup → launch` in one command. Creates the workspace, configures agents for your stack, deploys CI workflows, and opens your editor.
**Existing project:**
```bash
cd your-project
tenet init
tenet setup
```
`init` creates the context layer. `setup` analyzes your codebase and creates personalized RL agents.
## What gets created
```
your-project/
├── .tenet/
│ ├── config.json # Project config
│ ├── journal/ # Session journals (JSONL)
│ └── agents/ # Agent configs (TOML)
├── eval/ # Eval scripts for your stack
├── knowledge/ # VISION, THESIS, NARRATIVE
├── CLAUDE.md # Agent instructions
└── AGENTS.md # Pi agent instructions
```
## Run your first agent
```bash
tenet peter agent list
```
```
test-coverage
Metric: coverage_percent (maximize)
code-quality
Metric: quality_score (maximize)
```
Run one round:
```bash
tenet peter agent test-coverage --rounds 1
```
```
Baseline: 0.1276
Round 1 +0.0031 KEPT 48 tests added
Coverage: 12.7% → 13.1%
```
## Check health
```bash
tenet doctor
```
```
[ok] Context Hub (port 4360)
[ok] Memory: 349 entries, 349 embedded
[ok] Agents: 5 configured
All checks passed.
```
## What's next
The RL learning loop, eval system, and agent architecture.
TOML config reference — metrics, scope, eval scripts.
How TENET remembers and learns from history.
The nightly orchestrator that runs your agents.
## Capabilities
URL: https://docs.10et.ai/capabilities
# Capabilities
TENET is a CLI that gives AI agents persistent memory, a learning loop, and coordination. Here's what you can do with it.
## Context Hub
A daemon that runs alongside your agent sessions. Every agent connects to it via MCP. It serves journals, memory, knowledge docs, and events.
```bash
tenet context-hub ensure # start the hub
tenet ask "why is the timeout 30s?" # query your project's history
tenet search "authentication flow" # semantic search across all memory
```
What it enables:
- Agents start sessions with full context from every previous session
- Semantic search across decisions, code patterns, and experiments
- MCP server — works with Claude Code, Pi, Cursor, any MCP-compatible agent
## Peter Parker (Agent Orchestrator)
The meta-orchestrator that decides which agents to run, in what order, and with what context. Named after Andrej Karpathy's autoresearch pattern.
```bash
tenet setup # auto-detect metrics, create agents
tenet peter agent test-coverage -r 5 # run test-coverage agent for 5 rounds
tenet peter daily # run all agents with gradient
tenet peter status # see what's running, what improved
```
Each round:
1. **Eval before** — measure the metric (coverage, quality, speed)
2. **Agent changes code** — in an isolated worktree
3. **Eval after** — did the metric improve?
4. **Keep or revert** — `git reset --hard` if it regressed
5. **Record tuple** — (state, action, reward) → training buffer
```bash
# What a nightly run looks like
$ tenet peter daily
test-coverage (maximize)
Round 1 +0.31% kept 48 tests added
Round 2 -0.02% reverted types broke
Round 3 +0.35% kept config loader
code-quality (maximize)
Round 1 +0.45% kept 12 console.logs → logger
4 improvements shipped. Tomorrow's agents are smarter.
```
## RL Learning Loop
Every agent action produces training data. The policy head learns what works in YOUR codebase.
```bash
tenet eval status # current scores and trends
tenet eval compare -2 -1 # compare last two snapshots
tenet train transform # prepare tuples for training
tenet train policy-head # train the policy head
tenet policy-head score --type fix --description "add error handling" --scope small
```
The loop:
- **Training buffer** — append-only JSONL of (state, action, reward) tuples
- **Policy head** — neural network that predicts which actions improve metrics
- **Build evals** — write a spec, the eval checks if it's built. Agents iterate from 0% to 100%.
```bash
# Score candidate actions before committing
$ tenet policy-head rank '[
{"type":"fix","description":"add retry logic","scope":"small"},
{"type":"refactor","description":"extract auth module","scope":"medium"}
]'
1. fix: add retry logic → predicted +0.04
2. refactor: extract auth → predicted +0.02
```
## Memory System
Persistent memory with semantic search, graph edges, and knowledge lifecycle.
```bash
tenet memory status # embedding health, total entries
tenet memory search "auth flow" # search past decisions
tenet organize # audit docs for staleness → PENDING.md
```
What's stored:
- **Journals** — structured entries (decisions, features, fixes, discoveries) from every session
- **Knowledge docs** — VISION.md, THESIS.md, ARCHITECTURE.md — living documents
- **Code headers** — `@purpose` annotations indexed from source files
- **Graph edges** — structured relationships (updates, contradicts, related_to)
- **Embeddings** — semantic vectors for similarity search
## Event Bus (MAP)
The nervous system. Events flow between agents, flows, and the hub.
```bash
tenet events recent # see what's happening
tenet events publish eval:scored # emit a custom event
```
Events trigger flows automatically:
| Event | What happens |
|-------|-------------|
| `eval:scored` with `improved=true` | Auto-merge PR, close linked issue |
| `scope:impact` | Cascade evals to downstream services |
| `cron:nightly` | Peter Parker runs all agents with gradient |
| `session:ended` | Journal synced, memory indexed |
## Flows (YAML Automation)
Declarative event-driven workflows. Cron triggers, event patterns, agent spawns, approval gates.
```yaml
# .tenet/flows/self-driving.yaml
flows:
- name: auto-merge-on-improvement
trigger:
pattern: "eval:scored"
condition: 'data.improved == "true"'
actions:
- type: command
command: "gh pr merge {{data.pr_number}} --auto"
- type: journal
entry_type: milestone
title: "Auto-merged PR #{{data.pr_number}}"
```
```bash
tenet flows list # see all flows
tenet flows enable <name> # activate a flow
```
## Services (Multi-Repo Coordination)
Register services, declare what they produce and consume. Cross-repo impact detection.
```bash
tenet services register ./api # register a service
tenet scope list # see all produces/consumes
tenet scope impact --service api # what breaks if API changes?
tenet onboard ./new-service # full onboarding wizard
```
Scopes enable cascade:
```
api produces: api:schema-change
web consumes: api:schema-change
→ API change triggers web evals automatically
```
## IDE (Terminal Workspace)
Multi-pane tmux workspace with smart surface detection.
```bash
tenet ide # auto-detect and launch
tenet ide add browser # add browser pane
tenet ide add eval # add eval dashboard
tenet ide open api # open child service
tenet ide available # list all surface types
```
## Browser (Agent Eyes)
Terminal browser (Carbonyl) with CDP bridge. Agents get DOM, humans see pages.
```bash
tenet-browser.sh https://10et.ai # launch browser
# Then from agent session:
subway_call("browser.relay", "navigate", '{"url":"https://..."}')
subway_call("browser.relay", "read", '{}') # structured DOM
subway_call("browser.relay", "click", '{"selector":"#btn"}')
```
Human interactions broadcast on `browser.events` — agents can respond to what you're looking at.
## Subway Mesh (Agent Coordination)
P2P network for agent-to-agent communication across machines and sessions.
```bash
subway_send("datboi.relay", "deploy is failing")
subway_call("browser.relay", "navigate", '{"url":"..."}')
subway_broadcast("status", "deploy complete")
subway_subscribe("browser.events")
```
## Migration
Moving from JFL? One command:
```bash
npm i -g @10et/cli
tenet migrate # .tenet/ → .tenet/, updates all configs
tenet migrate --rollback # undo
```
Both `jfl` command and `.tenet/` directory keep working — no rush.
## How It Works
URL: https://docs.10et.ai/how-it-works
TENET's core innovation is a reinforcement learning loop for code. Agents don't just make changes — they measure whether changes improved the codebase, keep what works, and learn from the results.
## The RL Loop
**State** (world model) → **Action** (agent makes change) → **Eval** (measure result) → Keep or Revert → **Training Buffer** → **Policy Head** (learn what works) → back to State
### 1. State (World Model)
Before each round, TENET captures the current system state:
- Composite eval score
- Test pass rate and coverage
- Build health
- Code quality metrics
- Agent's trajectory (what it tried before)
### 2. Action (Agent)
The agent makes a focused code change. The policy head helps select what type of change to try based on what worked in the past.
### 3. Eval (Measure)
An eval script runs against the agent's changes — not the main branch. The `AGENT_WORKTREE` mechanism ensures the eval tests the actual changes in an isolated git worktree.
### 4. Reward (Keep or Revert)
- **Score improved** → change is kept, merged to the session branch
- **Score stayed same or regressed** → `git reset --hard HEAD~1`, change reverted
### 5. Training Buffer
Every round — kept or reverted — writes a training tuple:
```json
{
"agent": "test-coverage",
"state": { "composite_score": 0.1276, ... },
"action": { "type": "add_tests", "description": "...", "files_affected": [...] },
"reward": { "composite_delta": 0.0031, "improved": true }
}
```
### 6. Policy Head
A 14M-parameter transformer trained on the training buffer. Predicts which actions will produce positive reward given the current state. Retrained nightly when 50+ new tuples accumulate.
## The Nightly Loop
Every night at 2 AM (configurable):
```
tenet peter daily
+-- Mine training tuples from journals
+-- Synthesize product context
+-- Strategic reasoning (which agents to run?)
+-- Run stale agents (5 rounds each)
+-- Retrain policy head (if 50+ new tuples)
+-- Pick up backlog issues → create PRs
```
## Self-Driving Pipeline
Issues flow through a kanban pipeline automatically:
```
Issue filed (Linear/GitHub)
→ tenet/backlog label
→ PP picks up (every 30 min)
→ Agent creates PR
→ CI runs eval
→ Score improves → auto-merge → close issue
→ Score regresses → request changes
```
## Key Insight
The eval script is the reward function. **If the eval measures the right thing, agents improve. If it doesn't, they waste compute.**
We learned this the hard way — 750 rounds with 2.5% keep rate because eval scripts were at ceiling (test pass rate was already 100%). The fix: eval scripts that measure metrics with real gradient (actual coverage percentage, not just pass/fail).
## Architecture
URL: https://docs.10et.ai/architecture
TENET is a collection of components that work together to create a learning system for AI agents.
## System Overview
**Your Project** → **Context Hub** → **Agents** → **Eval** → **Training** → **Policy Head** → better agents tomorrow
| Layer | Components |
|-------|-----------|
| **CLI** | init, setup, peter, train, eval, ide, deploy |
| **Context Hub** | Memory DB, Event Bus, Indexer (port 4360) |
| **Agent Harness** | Peter Parker, RL agents, worktree isolation |
| **Learning** | Training buffer, policy head (14M params), build evals |
| **Platform** | Dashboard, auth, cloud agents, team features |
| **Mesh** | Subway P2P for agent coordination |
## Components
### CLI
The entry point. All commands go through `tenet`:
| Command | Purpose |
|---------|---------|
| `tenet` | Launch Pi with TENET extensions |
| `tenet init` | Scaffold a new project |
| `tenet setup` | Auto-detect metrics, create agents |
| `tenet peter` | Agent orchestrator |
| `tenet train` | Train policy head |
| `tenet eval` | Run evals, check scores |
| `tenet ide` | Terminal workspace |
| `tenet deploy` | Deploy to platform |
### Context Hub
The central coordination daemon. Runs locally on port 4360.
- **Memory database** — SQLite with indexed memories, semantic embeddings, graph edges
- **Event bus** — MAP (Multiplayer Agent Protocol) events for agent coordination
- **Periodic indexer** — Indexes journal entries every 60s, code headers every 5 min
- **API server** — REST endpoints for memory, events, context, eval
### Agent Harness
Autonomous improvement agents that run in isolated git worktrees.
**The loop:**
Measure the baseline metric (coverage, quality, speed)
In an isolated worktree — main branch is never touched
Measure again. Did the metric improve?
Score improved → advance branch, create PR. Regressed → `git reset --hard`
(state, action, reward) → training buffer. Policy head learns.
### Storage Layer
Everything is files in your repo:
| Component | Format | Location |
|-----------|--------|----------|
| Journals | JSONL | `.tenet/journal/*.jsonl` |
| Training buffer | JSONL | `.tenet/training-buffer.jsonl` |
| Agent configs | TOML | `.tenet/agents/*.toml` |
| Memory | SQLite | `.tenet/memory.db` |
| Eval results | JSONL | `.tenet/eval.jsonl` |
| Policy weights | JSON | `.tenet/checkpoints/` |
| Flows | YAML | `.tenet/flows/*.yaml` |
| Config | JSON | `.tenet/config.json` |
### Platform (Cloud)
Optional hosted services for dashboard, auth, cloud agents, and team features.
| API | Purpose |
|-----|---------|
| `/api/tenet/memory/*` | Cloud memory sync |
| `/api/tenet/train` | Remote training |
| `/api/tenet/policy` | Policy inference |
| `/api/tenet/tuples` | Tuple upload |
| `/api/agents/*` | Cloud agent management |
| `/api/sessions/*` | Session tracking |
### Subway Mesh
P2P agent coordination. Agents discover each other, send messages, broadcast events across machines.
| Agent | Role |
|-------|------|
| Your Pi session | Coding agent with TENET tools |
| `browser.relay` | Terminal browser with DOM access |
| Other sessions | Parallel agents on same or different machines |
## Data Flow
Agent sessions write journal entries and training tuples
Context Hub indexes journals, code headers, embeddings
Training buffer feeds the policy head — learns what works
Picks best next experiment based on policy predictions
Run in worktrees, eval-gated, auto-PR on improvement
---
# Agent Harness
## Agent Overview
URL: https://docs.10et.ai/agents/overview
TENET agents are autonomous workers that make focused code changes, measure the results, and learn from the outcomes. They run on a reinforcement learning loop — keep what improves, revert what doesn't.
## How Agents Work
Each agent has:
- **A metric** — what it's trying to improve (test coverage, startup speed, code quality)
- **An eval script** — how to measure the metric (bash or TypeScript)
- **A scope** — which files it can modify
- **A time budget** — how long each round gets
```
Agent starts
→ Measure baseline (run eval)
→ Make a focused change (via Claude/Sonnet)
→ Measure again (run eval)
→ Score improved? → KEEP (advance branch)
→ Score same/worse? → REVERT (git reset)
→ Write training tuple → policy head learns
→ Repeat for N rounds
```
## Built-in Agents
TENET ships with 5 focused agents out of the box:
| Agent | Metric | Direction | What it does |
|-------|--------|-----------|-------------|
| `test-coverage` | coverage_percent | maximize | Adds tests for uncovered files. Uses `jest --coverage`. |
| `code-quality` | quality_score | maximize | Reduces console.logs, `any` types, TODOs. Adds `@purpose` headers. |
| `cli-speed` | p90_ms | minimize | Optimizes CLI startup latency. Lazy-loads, caches, reduces imports. |
| `telemetry-rl` | product_health | maximize | Improves real user experience: startup speed, session reliability. |
| `onboarding-success` | success_rate | maximize | Fixes onboarding edge cases in `tenet init`. |
## Running an Agent
```bash
# List configured agents
tenet peter agent list
# Run a specific agent for 3 rounds
tenet peter agent test-coverage --rounds 3
# Run all agents (swarm mode)
tenet peter agent swarm --rounds 10
```
## Agent Output
```
Running Scoped Agent: test-coverage (3 rounds)
Metric: coverage_percent (maximize)
Time budget: 600s per round
Baseline: 0.1276
── Round 1/3 ──────────────────────────────
Task: Add tests for uncovered files...
✓ Result: 0.1307 (+0.0031) KEPT
── Round 2/3 ──────────────────────────────
Task: Add tests for auth module...
✗ Result: 0.1305 (-0.0002) REVERTED
── Round 3/3 ──────────────────────────────
Task: Add tests for config loader...
✓ Result: 0.1342 (+0.0035) KEPT
Session Complete
Improved: 2
Total delta: +0.0066
```
## The Key Insight
**The eval script is everything.** If the eval measures the right thing, agents improve. If it measures the wrong thing, they waste compute.
We learned this the hard way — 750 rounds with 2.5% keep rate because eval scripts were at ceiling (test pass rate was already 100%). The fix: eval scripts that measure metrics with real gradient.
Good eval = real gradient (12.8% coverage → 87% room to improve).
Bad eval = ceiling (100% test pass rate → nowhere to go).
## What's Next
TOML config reference — metrics, scope, time budgets.
Write eval scripts that produce real gradient.
The meta-orchestrator that runs the nightly loop.
Build custom agents for your own metrics.
## Agent Configuration
URL: https://docs.10et.ai/agents/configuration
Agents are configured with TOML files in `.tenet/agents/`. Each file defines one agent with its metric, eval script, scope, and constraints.
## Basic Example
```toml .tenet/agents/test-coverage.toml
[agent]
name = "test-coverage"
scope = "tests"
metric = "coverage_percent"
direction = "maximize"
time_budget_seconds = 600
rounds = 10
target_repo = "../my-service"
description = "Add tests for uncovered files. Focus on src/ files with 0% coverage first."
[eval]
script = "eval/test-coverage.sh"
data = "eval/fixtures/test-coverage-baseline.jsonl"
[constraints]
scope_files = ["src/**/*.ts", "src/**/__tests__/*.test.ts"]
max_file_changes = 5
```
## Reference
### `[agent]` Section
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | ✅ | Unique agent identifier |
| `scope` | string | ✅ | Category (tests, quality, performance, product) |
| `metric` | string | ✅ | Primary metric name (must match eval script output) |
| `direction` | string | ✅ | `"maximize"` or `"minimize"` |
| `time_budget_seconds` | number | ✅ | Max time per round |
| `rounds` | number | | Default rounds per session (overridable via CLI) |
| `target_repo` | string | | Relative path to target repo (for cross-repo agents) |
| `description` | string | | Instructions for the agent — what to do, what to avoid |
### `[eval]` Section
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `script` | string | ✅ | Path to eval script (relative to project root) |
| `data` | string | ✅ | Path to eval fixtures/baseline data |
### `[constraints]` Section
| Field | Type | Description |
|-------|------|-------------|
| `scope_files` | string[] | Glob patterns for files the agent can modify |
| `files_in_scope` | string[] | Additional file patterns (broader scope) |
| `files_readonly` | string[] | Files the agent must NOT modify |
| `max_file_changes` | number | Maximum files changed per round |
### `[policy]` Section (Advanced)
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `embedding_model` | string | auto | Model for state embeddings |
| `exploration_rate` | number | 0.2 | Initial exploration rate (ε-greedy) |
| `decay_per_round` | number | 0.004 | Exploration decay per round |
| `min_exploration` | number | 0.05 | Minimum exploration rate |
### `[context_scope]` Section
| Field | Type | Description |
|-------|------|-------------|
| `produces` | string[] | Events this agent emits (e.g., `"perf:cli-improved"`) |
| `consumes` | string[] | Events this agent reacts to (e.g., `"telemetry:metric-alert"`) |
## Full Example (CLI Speed Agent)
```toml .tenet/agents/tenet-cli-speed.toml
[agent]
name = "tenet-cli-speed"
scope = "performance"
metric = "p90_ms"
direction = "minimize"
time_budget_seconds = 180
rounds = 50
target_repo = "../tenet-cli"
[eval]
script = "eval/cli-speed.sh"
data = "eval/fixtures/cli-speed-baseline.jsonl"
[constraints]
scope_files = [
"src/index.ts",
"src/commands/status.ts",
"src/commands/doctor.ts",
"src/lib/service-detector.ts",
"src/utils/cache.ts",
]
files_in_scope = ["src/commands/**/*.ts", "src/lib/**/*.ts"]
files_readonly = ["eval/**", "node_modules/**", "dist/**"]
max_file_changes = 3
[policy]
exploration_rate = 0.2
decay_per_round = 0.004
min_exploration = 0.05
[context_scope]
produces = ["perf:cli-improved", "perf:latency-reduced"]
consumes = ["telemetry:metric-alert", "code:refactored"]
```
## Creating an Agent Interactively
```bash
tenet peter agent create
```
This walks you through setting up name, metric, eval script, and scope.
## Listing Agents
```bash
tenet peter agent list
```
```
Configured Agents
test-coverage
Scope: tests
Metric: coverage_percent (maximize)
Time budget: 600s
Files: src/**/*.ts, src/**/__tests__/*.test.ts
cli-speed
Scope: performance
Metric: p90_ms (minimize)
Time budget: 180s
Files: src/index.ts, src/commands/status.ts, ...
```
## Archiving Agents
Move dead agents to `.tenet/agents/_archived/`:
```bash
mv .tenet/agents/old-agent.toml .tenet/agents/_archived/
```
Archived agents are ignored by the nightly loop and `agent list`.
## Eval Scripts
URL: https://docs.10et.ai/agents/eval-scripts
Eval scripts are the reward function for your agents. They measure a metric before and after an agent makes changes. The delta determines whether the change is kept or reverted.
## Anatomy of an Eval Script
An eval script is a bash or TypeScript file that:
1. Runs tests, measurements, or analysis
2. Outputs a JSON object with a primary metric
3. Exits with code 0 (even if the metric is bad)
```bash eval/test-coverage.sh
#!/usr/bin/env bash
set -euo pipefail
# Use AGENT_WORKTREE when running in agent context,
# fall back to main repo for manual runs
CLI_DIR="${AGENT_WORKTREE:-$HOME/CascadeProjects/my-project}"
# Run jest with coverage
cd "$CLI_DIR"
npx jest --coverage --coverageReporters=json-summary --silent
# Parse coverage report
COVERAGE_FILE="coverage/coverage-summary.json"
LINE_PCT=$(python3 -c "import json; print(json.load(open('$COVERAGE_FILE'))['total']['lines']['pct'])")
# Output JSON with primary metric
SCORE=$(python3 -c "print(round($LINE_PCT / 100.0, 4))")
echo "{\"coverage_percent\": $SCORE, \"line_pct\": $LINE_PCT}"
```
## The AGENT_WORKTREE Pattern
**Critical:** Agents work in isolated git worktrees at `/tmp/tenet-agent-*`. Your eval script must test the agent's changes, not the main branch.
Always use `AGENT_WORKTREE` when referencing the target repo:
```bash
CLI_DIR="${AGENT_WORKTREE:-$HOME/CascadeProjects/my-project}"
```
This uses the worktree when running in agent context, and falls back to the main repo for manual testing.
## Good vs Bad Eval Scripts
### ❌ Bad: Metric at ceiling
```bash
# Tests pass rate — already 100%, no gradient
PASSED=$(npx jest --json | jq '.numPassedTests')
TOTAL=$(npx jest --json | jq '.numTotalTests')
echo "{\"pass_rate\": $(echo "$PASSED / $TOTAL" | bc -l)}"
# Always outputs 1.0 — agent can't improve this
```
### ✅ Good: Metric with real gradient
```bash
# Coverage percentage — 12.8% baseline, 87% room to improve
npx jest --coverage --coverageReporters=json-summary
LINE_PCT=$(jq '.total.lines.pct' coverage/coverage-summary.json)
echo "{\"coverage_percent\": $(echo "$LINE_PCT / 100" | bc -l)}"
# Outputs 0.128 — every test file moves this number
```
### ❌ Bad: Binary pass/fail
```bash
# Does the build succeed? Yes/no
if npm run build; then echo '{"build": 1.0}'; else echo '{"build": 0.0}'; fi
# No gradient — agent gets 1.0 or 0.0, nothing in between
```
### ✅ Good: Continuous signal
```bash
# Console.log count — 4461 instances, every cleanup moves the number
COUNT=$(grep -r "console\.\(log\|error\|warn\)" src/ | wc -l)
SCORE=$(python3 -c "print(round(1.0 - min($COUNT, 5000) / 5000, 4))")
echo "{\"quality_score\": $SCORE, \"console_count\": $COUNT}"
```
## Eval Script Requirements
1. **Output JSON** — Must output a single JSON object on stdout
2. **Primary metric** — The JSON must include the metric field matching your agent config
3. **Exit 0** — Even if the metric is bad. Non-zero exit = eval failure, not bad score
4. **Deterministic** — Same code should produce the same score
5. **Fast** — Under 30 seconds is ideal. Maximum is the agent's `time_budget_seconds`
6. **Stderr for logs** — Write debug output to stderr, not stdout
```bash
echo "Running coverage..." >&2 # Goes to stderr (logs)
echo '{"coverage_percent": 0.128}' # Goes to stdout (result)
```
## Composite Metrics
For multi-dimensional quality, create a weighted composite:
```bash eval/code-quality.sh
#!/usr/bin/env bash
CLI_DIR="${AGENT_WORKTREE:-$HOME/CascadeProjects/my-project}"
# Multiple signals
TODOS=$(grep -r "TODO\|FIXME" "$CLI_DIR/src" | wc -l)
CONSOLE_LOGS=$(grep -r "console\.log" "$CLI_DIR/src" | wc -l)
ANY_USAGE=$(grep -r ": any" "$CLI_DIR/src" | wc -l)
# Individual scores (0-1)
TODO_SCORE=$(python3 -c "print(round(1.0 - min($TODOS, 50) / 100, 4))")
CONSOLE_SCORE=$(python3 -c "print(round(1.0 - min($CONSOLE_LOGS, 5000) / 5000, 4))")
ANY_SCORE=$(python3 -c "print(round(1.0 - min($ANY_USAGE, 1000) / 1000, 4))")
# Weighted composite
QUALITY=$(python3 -c "print(round($TODO_SCORE * 0.3 + $CONSOLE_SCORE * 0.4 + $ANY_SCORE * 0.3, 4))")
echo "{\"quality_score\": $QUALITY, \"todos\": $TODOS, \"console_logs\": $CONSOLE_LOGS, \"any_usage\": $ANY_USAGE}"
```
## Testing Your Eval
Run it manually first:
```bash
# From your project root
bash eval/test-coverage.sh
# {"coverage_percent": 0.128, "line_pct": 12.8}
# With agent worktree simulation
AGENT_WORKTREE=/tmp/test-worktree bash eval/test-coverage.sh
```
Make sure the output is valid JSON and the primary metric has room to improve.
## Peter Parker
URL: https://docs.10et.ai/agents/peter-parker
Peter Parker (PP) is the meta-orchestrator. It decides which agents to run, in what order, and coordinates the entire nightly improvement cycle.
## What PP Does
```
tenet peter daily
|
+-- 1. Mine training tuples from journals
+-- 2. Synthesize product context
+-- 3. Layer 3: Strategic reasoning (which agents to run?)
+-- 4. Hub health check
+-- 5. Run stale agents (5 rounds each, capped at 1 hour)
+-- 6. Pick up kanban backlog issues → create PRs
+-- 7. Post summary event
```
## Strategic Reasoning (Layer 3)
PP uses Stratus to decide which agents deserve compute tonight:
```
Strategic reasoning:
Run: ["test-coverage", "code-quality"]
Skip: ["cli-speed"] — already optimized, diminishing returns
Reasoning: test-coverage has 87% headroom, highest ROI
```
This prevents wasting tokens on agents that have plateaued.
## Running PP
### Daily Loop (Nightly Cron)
```bash
tenet peter daily
```
Full orchestration cycle. Typically run at 2 AM via OpenClaw cron:
```json
{
"schedule": { "kind": "cron", "expr": "0 2 * * *" },
"payload": {
"kind": "agentTurn",
"message": "Run the TENET nightly loop..."
}
}
```
### Single Agent Run
```bash
tenet peter agent test-coverage --rounds 5
```
### Agent Swarm
```bash
tenet peter agent swarm --rounds 10
```
Runs all agents with the meta-orchestrator scheduling who goes next based on EMA reward.
### PR Mode
```bash
tenet peter pr --task "Fix the auth token refresh bug"
```
Creates a branch, makes changes, opens a PR. Used by the kanban pickup flow.
## The Kanban Pipeline
PP integrates with GitHub Issues for autonomous task execution:
```
Issue filed (tenet/backlog label)
↓ (every 30 min, flow: pick-up-linear-tasks)
PP picks up highest-priority issue
↓
Moves label: tenet/backlog → tenet/in-progress
↓
Spawns: tenet peter pr --task "GitHub #N: <title>"
↓
Agent makes changes, creates PR
↓
CI runs eval
↓
Score improves → auto-merge → close issue → tenet/done
Score regresses → request changes on PR
```
### Issue Labels
| Label | Meaning |
|-------|---------|
| `tenet/backlog` | Available for PP pickup |
| `tenet/in-progress` | PP is working on it |
| `tenet/eval` | PR created, waiting for eval |
| `tenet/done` | Merged and closed |
| `scope:tenet-cli` | Target repo hint |
## Training Data Capture
Every PP action generates training tuples:
```json
{
"agent": "test-coverage",
"state": { "composite_score": 0.1276 },
"action": { "type": "add_tests", "description": "..." },
"reward": { "composite_delta": 0.0031, "improved": true }
}
```
These feed the policy head for better action selection in future runs.
## PP Commands
```bash
tenet peter daily # Full nightly loop
tenet peter agent list # List configured agents
tenet peter agent <name> --rounds N # Run specific agent
tenet peter agent swarm --rounds N # Run all agents
tenet peter pr --task "<task>" # Branch + change + PR
tenet peter status # Show status + recent events
tenet peter telemetry # Run telemetry agent
tenet peter synthesize # Regenerate product context
```
## Nightly Loop
URL: https://docs.10et.ai/agents/nightly-loop
The nightly loop is TENET's autonomous improvement engine. It runs while you sleep, making focused code changes, measuring results, and keeping only what improves.
## How It Works
Every night at 2 AM (configurable):
1. **Mine tuples** — Extract training data from today's journal entries
2. **Synthesize context** — Generate product context summary for agents
3. **Strategic reasoning** — Stratus decides which agents to run based on ROI
4. **Run agents** — 5 rounds per agent, ~1 hour total
5. **Retrain policy head** — If 50+ new tuples since last training
6. **Pick up backlog** — Grab GitHub/Linear issues for autonomous PRs
## Setup
### OpenClaw Cron (Recommended)
If you have OpenClaw running, add a cron job:
```json
{
"name": "nightly-loop",
"schedule": { "kind": "cron", "expr": "0 2 * * *", "tz": "America/Denver" },
"payload": {
"kind": "agentTurn",
"message": "cd ~/CascadeProjects/my-project && tenet peter daily >> .tenet/nightly.log 2>&1",
"timeoutSeconds": 3600
}
}
```
### System Cron
```bash
# crontab -e
0 2 * * * cd /path/to/project && tenet peter daily >> .tenet/nightly.log 2>&1
```
### Manual Run
```bash
tenet peter daily
```
## What to Expect
First run output:
```
Peter Parker - Daily RL Agent Loop
Found 5 RL agent(s):
• test-coverage (coverage_percent, maximize)
• code-quality (quality_score, maximize)
• cli-speed (p90_ms, minimize)
• telemetry-rl (product_health, maximize)
• onboarding-success (success_rate, maximize)
Pre-flight: Mining tuples from journals...
Mined 12 tuples, 8 new → buffer total: 2772
Pre-flight: Synthesizing product context...
✓ Product context updated
Layer 3: Strategic reasoning...
Run: ["test-coverage", "code-quality"]
Skip: ["cli-speed"] — near optimal
Reasoning: test-coverage has highest gradient (87% headroom)
Hub health: ✓ (12ms)
── test-coverage ──────────────────────────────
Baseline: 0.1276
Round 1: +0.0031 KEPT
Round 2: -0.0002 REVERTED
Round 3: +0.0018 KEPT
Round 4: +0.0012 KEPT
Round 5: -0.0001 REVERTED
── code-quality ───────────────────────────────
Baseline: 0.6836
Round 1: +0.0045 KEPT
...
Daily loop complete.
```
## Monitoring
### Check Last Night's Results
```bash
# View the log
tail -100 .tenet/nightly.log
# Run the scorecard
bash eval/nightly-scorecard.sh
```
### Scorecard Output
**TENET Nightly Scorecard**
| Agent | Runs | Kept | Signal? |
|-------|------|------|---------|
| test-coverage | 15 | 8 | ✓ |
| code-quality | 10 | 4 | ✓ |
| cli-speed | 174 | 16 | ✓ |
Keep rate: 28/199 (14.1%)
## Tuning
### Rounds Per Agent
Default is 5. Increase for agents with high gradient:
```toml
# .tenet/agents/test-coverage.toml
rounds = 20 # More rounds = more improvement per night
```
### Strategic Reasoning
PP uses recent agent performance to decide who runs. If an agent has plateaued (0 improvements in last 10 runs), it gets skipped automatically.
### Cost Control
Each round costs ~$0.50-1.00 in API tokens (depends on model). 5 agents × 5 rounds = ~$15/night.
Use `--budget` to cap costs:
```bash
tenet peter daily --budget 10 # Stop at $10
```
## Creating Agents
URL: https://docs.10et.ai/agents/creating-agents
Create agents tailored to your project's specific improvement goals.
## Interactive Setup
```bash
tenet peter agent create
```
Walks you through: name, metric, eval script, scope files, time budget.
## Manual Setup
1. **Write an eval script** in `eval/`:
```bash
#!/usr/bin/env bash
CLI_DIR="${AGENT_WORKTREE:-$HOME/your-project}"
# ... measure your metric ...
echo '{"my_metric": 0.42}'
```
2. **Create agent config** in `.tenet/agents/my-agent.toml`:
```toml
[agent]
name = "my-agent"
scope = "quality"
metric = "my_metric"
direction = "maximize"
time_budget_seconds = 300
description = "What this agent should do to improve my_metric"
[eval]
script = "eval/my-eval.sh"
data = "eval/fixtures/my-agent-baseline.jsonl"
[constraints]
scope_files = ["src/**/*.ts"]
max_file_changes = 3
```
3. **Test the eval** manually:
```bash
bash eval/my-eval.sh
# {"my_metric": 0.42}
```
4. **Run the agent**:
```bash
tenet peter agent my-agent --rounds 1
```
## Tips
- **Start with one metric** — focused agents beat general-purpose ones
- **Verify gradient** — run the eval, confirm the metric isn't at ceiling
- **Narrow scope** — fewer `scope_files` = more focused changes
- **Short rounds** — 3-5 minutes per round is ideal for iteration speed
## Build Agents
URL: https://docs.10et.ai/agents/build-agents
Build agents extend the RL improvement loop to greenfield building. Instead of optimizing an existing metric, they build new modules from specs and iterate until every assertion passes.
## The Pattern
```
spec → eval assertions → agent TOML → `tenet peter agent {name}` → Karpathy loop → PR
```
**"Granularity of feedback determines speed of convergence."** A monolithic eval with 16 checks stalled at 7%. The same eval decomposed into 6 page-level evals — each hit 100% in one round. Same agent, same code, different gradient.
## Writing a Build Eval
```typescript
// eval/build/storage-adapter.ts
export async function evaluate(): Promise<number> {
const checks = [
{ name: "interface-exists", pass: existsSync(resolve("src/lib/storage/interface.ts")) },
{ name: "has-read-method", pass: fileContains("src/lib/storage/interface.ts", "read(") },
{ name: "local-impl", pass: existsSync(resolve("src/lib/storage/local.ts")) },
{ name: "compiles", pass: tscPasses() },
]
return checks.filter(c => c.pass).length / checks.length
}
```
The eval checks `AGENT_WORKTREE` env var so it tests the agent's worktree, not the main repo.
## Agent TOML Config
```toml
[agent]
name = "build-storage-adapter"
scope = "build" # triggers build-specific behavior
metric = "spec_compliance"
direction = "maximize"
time_budget_seconds = 600
[eval]
script = "eval/build/storage-adapter.ts"
data = "eval/fixtures/build-baseline.jsonl"
[task]
description = """
Create the TenetStorage adapter with interface,
LocalStorage, and CloudStorage implementations.
Exact file paths: src/lib/storage/interface.ts, etc.
"""
```
## Build vs RL Agents
| | RL Agent | Build Agent |
|---|---|---|
| Goal | Improve existing metric | Build from spec |
| Baseline | Current score | Zero |
| Rounds | 5-50, small changes | 3-10, creates files |
| Worktree | From origin/main | From HEAD (inherits merged work) |
| Turns | 15 per round | 40 per round |
| Early stop | No | Yes (stops at 1.0) |
## Build Supervisor
Between rounds, `checkRound()` detects patterns:
- **Stalled**: 3+ rounds at same score → injects hint
- **Filename mismatch**: files created but eval can't find them → alerts
- **Repeated reverts**: same checks failing → suggests different approach
The supervisor logs learnings to `.tenet/build-learnings.jsonl` for future sessions.
## Eval Decomposition
Break complex builds into sub-evals. Instead of one frontend eval with 16 checks, create 6 page-level evals with 2-3 checks each. Each scores independently, giving the agent gradient from round 1.
---
# Learning System
## RL Loop
URL: https://docs.10et.ai/learning/rl-loop
TENET implements a simplified reinforcement learning loop for code improvement. It's not traditional RL with neural network policies playing Atari — it's the Karpathy autoresearch pattern applied to codebases.
## The Three Components
### 1. State (World Model)
Before each round, TENET captures the system state:
```typescript
interface WorldState {
systemState: {
activeAgents: string[]
hubConnections: number
buildStatus: Record<string, string>
pendingEvals: number
}
contextState: {
recentCommits: number
openPRs: number
failingTests: number
codeChurn: number
}
agentState: {
lastEvalScore: number
rewardEMA: number
actionHistory: string[]
consecutiveFailures: number
}
}
```
This gets converted to an `RLState` for the policy head:
```typescript
interface RLState {
composite_score: number
dimension_scores: Record<string, number>
tests_passing: number
tests_total: number
trajectory_length: number
recent_deltas: number[]
agent: string
}
```
### 2. Action (Policy Head Selects)
The policy head is a 14M-parameter transformer that predicts reward for candidate actions:
```typescript
interface RLAction {
type: "fix" | "refactor" | "feature" | "test" | "config" | "experiment"
description: string
files_affected: string[]
scope: "small" | "medium" | "large"
}
```
The agent generates task descriptions informed by:
- Experiment history (what worked, what didn't)
- Policy head predictions (which action type is most promising)
- Product context (what the team is focused on)
### 3. Reward (Eval Delta)
After the agent makes changes:
```
reward = eval_score_after - eval_score_before
```
- Positive delta → **KEPT** (change merged to session branch)
- Zero or negative delta → **REVERTED** (`git reset --hard HEAD~1`)
## Training Tuple
Every round produces a training tuple, regardless of outcome:
```json
{
"agent": "test-coverage",
"state": {
"composite_score": 0.1276,
"dimension_scores": { "test_pass_rate": 1.0, "build_health": 1.0 },
"trajectory_length": 3,
"recent_deltas": [0.0031, -0.0002]
},
"action": {
"type": "test",
"description": "Add tests for claude-md-generator.ts",
"files_affected": ["src/utils/__tests__/claude-md-generator.test.ts"],
"scope": "medium"
},
"reward": {
"composite_delta": 0.0031,
"improved": true
}
}
```
## Why This Works
Traditional RL needs millions of episodes. TENET works with hundreds because:
1. **The action space is constrained** — agents modify specific files in a focused scope
2. **The eval is deterministic** — same code produces the same score
3. **The environment resets cleanly** — `git reset` provides perfect rollback
4. **History informs action** — agents see what worked/failed in past rounds
## The Karpathy Connection
This is the [autoresearch](https://karpathy.ai/) pattern:
- **Propose** an experiment (agent generates a code change)
- **Run** the experiment (eval script measures the result)
- **Evaluate** the outcome (delta > 0?)
- **Learn** from the result (training tuple → policy head)
- **Repeat** with better-informed proposals
The key insight: you don't need massive compute. You need a good reward signal (eval script) and focused actions (scope files).
## Common Pitfalls
**Bad reward signal = wasted compute.** If your eval is at ceiling (100% test pass rate), agents can't improve it. If your eval measures the wrong thing (code hygiene when the agent changes functionality), agents will be reverted every time.
Always verify your eval has room to improve before running agents.
| Pitfall | Symptom | Fix |
|---------|---------|-----|
| Eval at ceiling | 0% keep rate, delta always 0 | Measure something with gradient |
| Wrong metric | Agent makes good changes, still reverted | Align eval with what agent actually changes |
| Eval tests wrong code | Agent's worktree not evaluated | Use `AGENT_WORKTREE` env var |
| Scope too broad | Agent changes unrelated files | Narrow `scope_files` in agent config |
| Too many rounds | Diminishing returns | Cap at 5-10 rounds per session |
## Eval System
URL: https://docs.10et.ai/learning/eval-system
The eval system is the reward function for the RL loop. It runs before and after an agent makes changes, and the delta determines whether the change is kept.
## Eval Flow
```
Baseline eval (before changes)
→ Agent makes code change
→ Post-change eval (same script)
→ delta = post - baseline
→ delta > 0 → KEPT
→ delta ≤ 0 → REVERTED
```
## Eval Store
All eval results are stored in `.tenet/eval.jsonl`:
```json
{
"v": 1,
"ts": "2026-03-22T21:30:00Z",
"agent": "test-coverage",
"run_id": "test-coverage-4bc3ff95",
"metrics": {
"coverage_percent": 0.1307,
"line_pct": 13.37,
"branch_pct": 12.27
},
"composite": 0.1307,
"delta": 0.0031,
"improved": true
}
```
## Viewing Eval History
```bash
# Current eval status
tenet eval status
# Compare two snapshots
tenet eval compare
# View trajectory for an agent
tenet eval trajectory --agent test-coverage
```
## Eval Snapshots
When an agent starts, TENET freezes the eval script into a snapshot (SHA-based). This ensures the eval doesn't change mid-run — the same script measures baseline and post-change.
Snapshots are cached at `~/.cache/tenet/eval-snapshots/<hash>/`.
## Writing Good Evals
See [Eval Scripts](/agents/eval-scripts) for the complete guide on writing eval scripts that produce real gradient.
Key principles:
1. Output JSON with a primary metric
2. Use `AGENT_WORKTREE` for cross-repo agents
3. Ensure the metric has room to improve (not at ceiling)
4. Keep evals fast (under 30s) and deterministic
## Training Buffer
URL: https://docs.10et.ai/learning/training-buffer
The training buffer (`.tenet/training-buffer.jsonl`) captures every agent action and its outcome. This data trains the policy head and provides experiment history for future runs.
## Format
Each line is a training tuple:
```json
{
"id": "tb_eyJjb21wb3Np",
"v": "1",
"ts": "2026-03-22T21:30:00Z",
"agent": "test-coverage",
"state": {
"composite_score": 0.1276,
"dimension_scores": { "test_pass_rate": 1.0, "build_health": 1.0 },
"tests_passing": 1414,
"tests_total": 1414,
"trajectory_length": 3,
"recent_deltas": [0.0031, -0.0002],
"agent": "test-coverage"
},
"action": {
"type": "test",
"description": "Add tests for claude-md-generator.ts",
"files_affected": ["src/utils/__tests__/claude-md-generator.test.ts"],
"scope": "medium",
"branch": "session/test-coverage-4bc3ff95-2026-03-22"
},
"reward": {
"composite_delta": 0.0031,
"dimension_deltas": {},
"tests_added": 48,
"quality_score": 0.0,
"improved": true
}
}
```
## Data Sources
Tuples come from three sources:
| Source | When | What |
|--------|------|------|
| **Agent runs** | Each round | State, action, reward from eval delta |
| **Tuple miner** | Nightly pre-flight | Extracts tuples from journal entries |
| **Manual** | `tenet_training_buffer` tool | Record observations during sessions |
## Querying the Buffer
```bash
# Total tuples
wc -l .tenet/training-buffer.jsonl
# Tuples by agent
jq -r '.agent' .tenet/training-buffer.jsonl | sort | uniq -c | sort -rn
# Recent improvements
jq 'select(.reward.improved == true)' .tenet/training-buffer.jsonl | tail -5
```
## Mining Tuples
The tuple miner extracts learning data from journals:
```bash
# Mine from all sources
tenet eval mine --all
# Mine from specific source
tenet eval mine --source journals
tenet eval mine --source evals
tenet eval mine --source sessions
```
## Buffer Health
Check the nightly scorecard for buffer stats:
```bash
bash eval/nightly-scorecard.sh
```
```
Training Buffer
───────────────
Total tuples: 2764
Last 24h: 62 new tuples
Reward distribution:
test-coverage +8 / -2 / =0 (80% positive)
code-quality +4 / -3 / =1 (50% positive)
```
## When Policy Head Retrains
The policy head retrains when the buffer has 50+ new tuples since last training. This happens automatically in the nightly loop, or manually:
```bash
tenet train transform && tenet train policy-head --force
```
## Policy Head
URL: https://docs.10et.ai/learning/policy-head
The policy head is a neural network trained on your project's training buffer. It predicts which actions will produce positive reward given the current system state.
## Architecture
```
Input: RLState (composite score, dimensions, trajectory)
↓
4-layer transformer (512 hidden, 8 heads)
↓
Output: predicted reward for each candidate action
```
**Specs:**
- 14M parameters
- Trained on MPS (Apple Silicon) or CPU
- Checkpoint: `.tenet/checkpoints/policy-head-v2.json`
- Weights: `.tenet/checkpoints/best_policy_head.pt`
## How It's Used
During agent runs, the policy head scores candidate actions:
```bash
# Score a single action
tenet policy score --type fix --description "Add error handling to auth module" --scope small
# Rank multiple actions
tenet policy rank '[
{"type": "test", "description": "Add tests for config loader", "scope": "small"},
{"type": "refactor", "description": "Extract auth middleware", "scope": "medium"},
{"type": "fix", "description": "Fix memory leak in hub", "scope": "large"}
]'
```
```
Ranked Actions (predicted reward):
1. [+0.0042] test: Add tests for config loader (small)
2. [+0.0018] fix: Fix memory leak in hub (large)
3. [-0.0003] refactor: Extract auth middleware (medium)
```
## Training
### When It Trains
The nightly loop retrains automatically when 50+ new tuples have accumulated since last training:
```bash
# In peter daily:
BUFFER_SIZE=$(wc -l < .tenet/training-buffer.jsonl)
LAST_TRAINED=$(jq '.trained_on' .tenet/checkpoints/policy-head-v2.json)
NEW_TUPLES=$((BUFFER_SIZE - LAST_TRAINED))
if [ "$NEW_TUPLES" -ge 50 ]; then
tenet train transform && tenet train policy-head --force
fi
```
### Manual Training
```bash
# Transform raw tuples into training format
tenet train transform
# Train policy head
tenet train policy-head --force
```
### Training Data
The training buffer (`.tenet/training-buffer.jsonl`) contains tuples from:
- Agent autoresearch rounds (kept and reverted)
- Manual journal entries (mined by tuple miner)
- Cross-service events
Current stats: **2764 tuples**, **91.6% validation accuracy**.
## Checkpoint
```json
{
"version": 2,
"architecture": "transformer-4layer-512h",
"embedding_dim": 768,
"hidden_dim": 512,
"num_layers": 4,
"num_heads": 8,
"trained_on": 1565,
"val_accuracy": 0.9164,
"parameters": 14191628,
"tool_to_index": {
"fix_bug": 0,
"refactor_code": 1,
"add_feature": 2,
"add_tests": 3,
"update_config": 4,
"run_experiment": 5
}
}
```
## When to Use GPUs
The policy head is small (14M params). Training on Apple Silicon MPS takes ~2 minutes. You don't need cloud GPUs unless:
- You're training on 10K+ tuples
- You want to experiment with larger architectures
- You're running parallel training across multiple projects
For most users, MPS or CPU is sufficient.
## World Model
URL: https://docs.10et.ai/learning/world-model
The world model captures a complete snapshot of the system at a point in time. It gives agents and the policy head context about the environment they're operating in.
## WorldState
```typescript
interface WorldState {
timestamp: number
agentId: string
systemState: {
activeAgents: string[] // Which agents are running
worktreeAllocation: {} // Git worktree usage
hubConnections: number // Context Hub connections
buildStatus: Record<string, string> // Build health per service
fileLocks: string[] // Currently locked files
pendingEvals: number // Queued eval runs
}
contextState: {
recentCommits: number // Commits in last 24h
openPRs: number // Open pull requests
failingTests: number // Currently failing tests
codeChurn: number // Lines changed recently
humanActivity: boolean // Is a human currently working?
}
agentState: {
lastEvalScore: number // Most recent eval composite
rewardEMA: number // Exponential moving average of rewards
actionHistory: string[] // Recent action types taken
consecutiveFailures: number // Reverts in a row
}
}
```
## RLState (Policy Head Input)
The world state is converted to a compact format for the policy head:
```typescript
interface RLState {
composite_score: number // Current eval score
dimension_scores: {
test_pass_rate: number // Test health
build_health: number // Build status
code_quality: number // Code quality metrics
hub_health: number // Hub connectivity
}
tests_passing: number
tests_total: number
trajectory_length: number // Rounds completed
recent_deltas: number[] // Last 5 reward deltas
agent: string // Agent name
}
```
## How It's Used
1. **Before each round** — World state captured as the "before" snapshot
2. **Policy head scoring** — RLState fed to transformer for action ranking
3. **Strategic reasoning** — Peter Parker uses state to decide which agents to run
4. **Training** — State included in training tuples for policy head learning
## State Transitions
Each agent round creates a state transition:
```
Prior state (before) → Action (agent change) → Posterior state (after)
```
Transitions are tracked in `.tenet/telemetry/resource-transitions.jsonl` for analysis.
## Build Evals
URL: https://docs.10et.ai/learning/build-evals
Build evals extend the RL improvement loop to **greenfield building**. Instead of optimizing an existing metric, agents build new modules from specs and iterate until every assertion passes.
## The Pattern
```
spec → eval assertions → agent TOML → `tenet peter agent {name}` → Karpathy loop → PR
```
1. Write a spec describing what to build
2. Write an eval script with assertions (file exists? method exists? compiles?)
3. Create an agent TOML config with the spec as the task
4. Run Peter Parker — the agent iterates from 0% → 100%
5. PR created automatically when score hits 1.0
## Writing a Build Eval
A build eval is a TypeScript file that checks spec compliance:
```typescript
// eval/build/storage-adapter.ts
export async function evaluate(): Promise<number> {
const checks = [
{ name: "interface-exists", pass: existsSync("src/lib/storage/interface.ts") },
{ name: "has-read-method", pass: fileContains("src/lib/storage/interface.ts", "read(") },
{ name: "has-write-method", pass: fileContains("src/lib/storage/interface.ts", "write(") },
{ name: "local-impl", pass: existsSync("src/lib/storage/local.ts") },
{ name: "cloud-impl", pass: existsSync("src/lib/storage/cloud.ts") },
{ name: "compiles", pass: tscPasses() },
]
return checks.filter(c => c.pass).length / checks.length
}
```
## Agent TOML Config
```toml
[agent]
name = "build-storage-adapter"
scope = "build"
metric = "spec_compliance"
direction = "maximize"
time_budget_seconds = 600
[eval]
script = "eval/build/storage-adapter.ts"
data = "eval/fixtures/build-baseline.jsonl"
[task]
description = """
Create the TenetStorage adapter with interface,
LocalStorage, and CloudStorage implementations.
"""
```
## Key Insight
**"Granularity of feedback determines speed of convergence."**
A monolithic eval with 16 checks stalled at 7% for hours. The same eval decomposed into 6 page-level evals — each hit 100% in one round. Same agent, same code, different gradient.
## Build vs RL Agents
| | RL Agent | Build Agent |
|---|---|---|
| **Goal** | Improve existing metric | Build new code from spec |
| **Baseline** | Current score (e.g., 0.43) | Zero (nothing exists) |
| **Rounds** | 5-50, small changes | 3-10, creates files |
| **Worktree** | From origin/main | From HEAD (inherits merged work) |
| **Turns** | 15 per round | 40 per round |
| **Early stop** | No (keep improving) | Yes (stops at 1.0) |
## Storage Adapter
URL: https://docs.10et.ai/learning/storage-adapter
TENET's storage adapter pattern lets all modules work against different backends without changing their code. Locally, everything writes to `.tenet/` files and SQLite. In production, the same operations go to Postgres with workspace isolation.
## Interface
```typescript
interface TenetStorage {
read(key: string): Promise<any>
write(key: string, value: any): Promise<void>
append(key: string, value: any): Promise<void>
list(prefix?: string): Promise<string[]>
query(query: Record<string, any>): Promise<any[]>
execute(operation: string, params?: any): Promise<any>
vectorSearch(vector: number[], options?: { limit?: number }): Promise<any[]>
}
```
## Implementations
### LocalStorage (default)
File-based storage in `.tenet/` directory. Uses SQLite for queries and cosine similarity for vector search. This is what runs when you use `tenet` on your machine.
### CloudStorage
Postgres-backed storage for multi-user deployments. All operations scoped by `workspaceId`. Uses pgvector for similarity search.
```typescript
const storage = new CloudStorage(workspaceId, connectionString)
```
## Factory
```typescript
// Local (default)
const local = createStorage()
// Cloud
const cloud = createStorage({
cloud: { workspaceId: 'ws_123', connectionString: process.env.DATABASE_URL }
})
```
## How Modules Use It
Memory, training buffer, and policy head all accept an optional storage parameter. When not provided, they use LocalStorage (backward compatible):
```typescript
// Existing behavior — unchanged
const memory = new MemoryDB(projectRoot)
// Cloud behavior — same API, different backend
const memory = new MemoryDB(projectRoot, { storage: cloudStorage })
```
## Domain Engine
URL: https://docs.10et.ai/learning/domain-engine
The domain engine provides the product-facing API for building agent applications. It wraps TENET's internal infrastructure (memory, training, policy, eval) into a clean interface that any app can use.
## Core Types
### TenetEntity
Generic entity that any domain maps to:
```typescript
interface TenetEntity {
id: string
source: string // which platform/connector
sourceId: string // platform-specific ID
name: string
metadata: Record<string, any>
funnelStage: string // from template FUNNEL.md
temperature: 'hot' | 'warm' | 'cooling' | 'cold'
createdAt: Date
}
```
- **Dating**: Entity = Match
- **Sales**: Entity = Lead
- **Recruiting**: Entity = Candidate
### TenetConnector
Typed interface to external platforms:
```typescript
interface TenetConnector {
authenticate(credentials: ConnectorCredentials): Promise<void>
syncEntities(since?: Date): Promise
syncInteractions(entityId: string): Promise
send(entityId: string, content: string): Promise<{ platformMsgId: string }>
getProfile(entityId: string): Promise>
}
```
### TenetRewardFunction
Domain-specific reward definitions:
```typescript
interface TenetRewardFunction {
signals: RewardSignal[]
calculate(context: RewardContext): number
}
```
## The World Class
The `World` (or `DomainEngine`) wraps everything:
```typescript
const world = await World.create({
template: 'dating',
storage: cloudStorage(userId),
connectors: [tinder(token), bumble(token)],
})
await world.sync() // pull from platforms
const draft = await world.generateDraft(matchId) // memory + policy
await world.recordOutcome(draftId, 'send') // training signal
await world.train() // nightly: policy improves
```
## Templates
URL: https://docs.10et.ai/learning/templates
Templates encode domain expertise so agents don't start from a blank canvas. Each template provides funnel stages, reward functions, psychology frameworks, and anti-patterns specific to a domain.
## Using Templates
```bash
# Scaffold a dating agent world
tenet init --template dating
# Default GTM template (existing behavior)
tenet init
```
## What a Template Contains
```
templates/dating/
├── FUNNEL.md # matched → messaging → deep → meet
├── SIGNALS.md # reply_rate, response_time, sentiment
├── REWARDS.md # reply +1, meet +10, skip -0.5
├── PSYCHOLOGY.md # push-pull, vulnerability, timing
├── ANTI_PATTERNS.md # triple-text, interrogation, generic openers
├── MODES.md # bold, playful, chill, intellectual
└── connectors/ # platform integration stubs
```
## Template Loader
```typescript
const config = loadTemplate('dating', projectRoot)
// Returns structured config from the markdown files:
// { funnel: [...stages], rewards: [...signals], antiPatterns: [...], modes: [...] }
```
## Creating Custom Templates
Create a `templates/your-domain/` directory with the standard files. The DomainEngine reads and parses the markdown into structured configuration.
### FUNNEL.md
Define your pipeline stages:
```markdown
## Dating-Specific Stages
- **matched** — initial match on platform
- **opened** — first message sent
- **messaging** — active conversation
- **deep** — meaningful connection
- **meet_proposed** — date suggested
- **met** — in-person meeting
```
### REWARDS.md
Define your reward function:
```markdown
## Signal Rewards
- reply: +1
- fast_reply: +0.5 (within 1 hour)
- meet_proposed: +3
- meet_confirmed: +10
- user_sent_as_is: +0.5
- user_edited: -0.1
- user_skipped: -0.5
```
---
# Memory
## Memory System
URL: https://docs.10et.ai/memory/overview
TENET's memory system ensures nothing is forgotten between sessions. Every journal entry, code change, and decision is indexed, embedded, and searchable.
## What Gets Remembered
| Source | What's Indexed | How Often |
|--------|---------------|-----------|
| **Journal entries** | Features, fixes, decisions, discoveries, pivots | Every 60 seconds |
| **Code headers** | `@purpose` annotations from source files | Every 5 minutes |
| **Manual memories** | Insights, notes, decisions via `tenet_memory_add` | On demand |
## How Search Works
TENET uses hybrid search — combining lexical and semantic approaches for best results:
```
Query: "CLI startup optimization"
|
+----+----+
| |
BM25+ Embedding
(lexical) (semantic)
| |
+----+----+
|
Reciprocal Rank
Fusion (RRF)
|
Ranked Results
```
### BM25+ (Always Available)
Term-frequency scoring with:
- Stopword removal and phrase detection
- Adaptive document length normalization
- Query term weighting based on IDF
- Positive IDF floor (BM25+ variant) — common terms still contribute
### Semantic Search (When Embeddings Available)
Cosine similarity on `text-embedding-3-small` vectors:
- 1536 dimensions
- OpenAI or OpenRouter fallback
- Auto-backfill: if key was missing when indexed, embeddings are added later
### Reciprocal Rank Fusion
Merges BM25 and embedding results by rank position, not raw scores. More robust than linear interpolation because it doesn't require score normalization.
## Current Stats
```bash
tenet memory status
```
```
total_memories: 349
by_type: {feature: 96, milestone: 96, decision: 55, fix: 40, ...}
embeddings: {available: true, count: 349, model: "openrouter/text-embedding-3-small"}
```
**349/349 memories embedded** — zero gaps.
## Graph Edges
Memories aren't isolated. They connect to each other:
| Edge Type | Meaning | Example |
|-----------|---------|---------|
| `updates` | New info supersedes old | "CLI speed now 98ms" updates "CLI speed was 6.7s" |
| `contradicts` | New finding invalidates old | "Connection pooling helps" contradicts "Keep connections short" |
| `related_to` | Topically connected | Memory about eval system → related to agent config |
| `caused_by` | Causal relationship | "Test failures" caused_by "Dependency upgrade" |
| `part_of` | Hierarchical grouping | Session memories → part_of project milestone |
```bash
# Add a link via API
curl -X POST http://localhost:4360/api/memory/link \
-H "Content-Type: application/json" \
-d '{"from": 42, "to": 17, "type": "updates"}'
```
## Code Header Indexing
Files with `@purpose` annotations are automatically indexed:
```typescript
/**
* Memory Indexer Module
*
* @purpose Automatic indexing of journal entries and code headers
*/
```
This creates a searchable memory entry:
- Source: `file`
- Type: `code-header`
- Content: `src/lib/memory-indexer.ts: Automatic indexing of journal entries and code headers`
Scans: `src/`, `packages/`, `scripts/`, `eval/`
Updates if `@purpose` changes. Deduped by file path.
## Knowledge Doc Lifecycle
Knowledge docs (VISION.md, THESIS.md, etc.) are audited for staleness:
```bash
tenet organize
```
```
Doc Health
✓ VISION 0d old drift: 20% mentions: 221
✓ THESIS 0d old drift: 20% mentions: 223
✓ NARRATIVE 0d old drift: 20% mentions: 206
0 of 5 docs need attention
```
When docs drift from journal evidence, `tenet organize` generates a `PENDING.md` with proposed updates and open questions for human review.
BM25+ hybrid search internals and query optimization.
Structured relationships between memories.
Auto-backfill, model selection, and fallback behavior.
Indexing @purpose annotations from source files.
## Memory Search
URL: https://docs.10et.ai/memory/search
TENET's memory search combines lexical (BM25+) and semantic (embedding cosine similarity) scoring, merged via Reciprocal Rank Fusion.
## Search Methods
| Method | When Used | Requires API Key |
|--------|-----------|-----------------|
| `bm25` | Keyword-focused queries | No |
| `embedding` | Semantic/conceptual queries | Yes |
| `hybrid` | Best of both (default) | Partial — falls back to BM25 |
## BM25+ Improvements
- **Stopword removal** — cleaner term matching
- **Phrase detection** — multi-word terms kept together
- **Adaptive b parameter** — adjusts to corpus length variance
- **Positive IDF floor** — common terms still contribute (BM25+ variant)
- **Query term weighting** — rare terms get more weight
## Boosts
| Boost | Factor | Condition |
|-------|--------|-----------|
| Recency | 1.3x | Within 7 days |
| Decision | 1.4x | Type = decision |
| Feature | 1.2x | Type = feature |
## API
```bash
curl -X POST http://localhost:4360/api/memory/search \
-H "Authorization: Bearer $TOKEN" \
-d '{"query": "startup optimization", "limit": 5, "type": "decision"}'
```
## Graph Edges
URL: https://docs.10et.ai/memory/graph-edges
Memories connect to each other via typed edges, creating a knowledge graph.
## Edge Types
| Type | Meaning | Example |
|------|---------|---------|
| `updates` | Supersedes previous knowledge | New benchmark → updates old benchmark |
| `contradicts` | Invalidates previous belief | "Pooling helps" contradicts "Keep connections short" |
| `related_to` | Topically connected | Eval system → related to agent config |
| `caused_by` | Causal chain | Test failures caused by dependency upgrade |
| `part_of` | Hierarchical grouping | Session entries → part of milestone |
## Creating Edges
```bash
curl -X POST http://localhost:4360/api/memory/link \
-H "Authorization: Bearer $TOKEN" \
-d '{"from": 42, "to": 17, "type": "updates"}'
```
## Querying Edges
```typescript
// Get what a memory updates
const links = await getLinksFrom(memoryId)
// Get what updates a memory
const links = await getLinksTo(memoryId)
```
## Future: Contradiction Detection
When a new memory contradicts existing knowledge, the system will automatically flag it and create an `updates` or `contradicts` edge.
## Embeddings
URL: https://docs.10et.ai/memory/embeddings
TENET uses `text-embedding-3-small` (1536 dimensions) for semantic search. Embeddings are computed at index time and auto-backfilled if keys were missing.
## Provider Fallback
```
1. Try OPENAI_API_KEY → text-embedding-3-small
2. If fails → try OPENROUTER_API_KEY → openai/text-embedding-3-small
3. If both fail → memory stored without embedding (BM25 only)
4. Auto-backfill runs periodically to catch up
```
## Auto-Backfill
The periodic indexer automatically backfills missing embeddings:
- Runs on first tick after hub startup
- Runs whenever new entries are added
- Truncates content >28K chars (model limit ~8K tokens)
- Uses consecutive-null counter (3 strikes before stopping)
## Manual Backfill
```bash
curl -X POST http://localhost:4360/api/memory/index \
-H "Authorization: Bearer $TOKEN" \
-d '{"backfill": true}'
```
## Stats
```bash
tenet memory status
# embeddings: {available: true, count: 349, model: "openrouter/text-embedding-3-small"}
```
## Code Headers
URL: https://docs.10et.ai/memory/code-headers
Files with `@purpose` annotations are automatically indexed into the memory system, making your codebase searchable alongside journal entries.
## How It Works
```typescript
/**
* Memory Indexer Module
*
* @purpose Automatic indexing of journal entries and code headers
*/
```
Becomes a memory entry:
- **Source:** `file`
- **Type:** `code-header`
- **Title:** `src/lib/memory-indexer.ts`
- **Content:** `src/lib/memory-indexer.ts: Automatic indexing of journal entries and code headers`
## Scanned Directories
`src/`, `packages/`, `scripts/`, `eval/`, `app/`, `lib/`, `components/`
## File Types
`.ts`, `.tsx`, `.js`, `.jsx`, `.mjs`, `.rs`, `.py`, `.go`, `.sh`
## Update Behavior
- Scans every 5 minutes (every 5th periodic indexer tick)
- Deduped by file path
- If `@purpose` changes, memory is updated and embedding cleared for re-computation
- Capped at 200 files per project
## Searching Code Headers
```bash
tenet ask "What does the memory indexer do?"
# Returns the @purpose annotation alongside journal entries
```
## Knowledge Docs
URL: https://docs.10et.ai/memory/knowledge-docs
Knowledge docs (VISION.md, THESIS.md, etc.) are living documents that should evolve with your project. `tenet organize` audits them for staleness.
## The Problem
Knowledge docs drift. You write VISION.md on day 1, then 30 days of journals accumulate with decisions, pivots, and discoveries that the doc doesn't reflect.
## The Solution
```bash
tenet organize
```
Scans docs against journal evidence, computes drift scores, generates `PENDING.md` with proposed updates and open questions.
See [tenet organize](/cli/organize) for the full command reference.
## Recommended Structure
```
knowledge/
├── VISION.md # What we're building (update quarterly)
├── THESIS.md # Why we win (update with competitive changes)
├── NARRATIVE.md # How we tell the story (update with product changes)
├── PHILOSOPHY.md # Core principles (rarely changes)
├── BRAND_DECISIONS.md # Visual identity, naming (update with rebrand)
└── archive/ # Old docs organized by era
├── specs/
├── research/
└── strategy/
```
## Lifecycle
Manual or via `tenet init`
`tenet organize` flags docs with no journal references
Proposed updates + open questions for human review
Answers questions, approves changes
`tenet organize --apply` commits changes
If no activity for 60 days → `knowledge/archive/`
---
# Context Hub
## Context Hub
URL: https://docs.10et.ai/hub/overview
The Context Hub is a local HTTP daemon that coordinates all TENET subsystems. It runs on your machine, manages the memory database, serves context to agents, and coordinates events.
## Starting the Hub
```bash
# Start (or ensure running)
tenet context-hub ensure
# Check health
curl http://localhost:4360/health
# {"status":"ok","port":4360}
```
The hub starts automatically when you run any TENET command. It persists across sessions.
## What It Does
| Feature | Description |
|---------|-------------|
| **Memory DB** | SQLite database with indexed memories, embeddings, graph edges |
| **Periodic Indexer** | Indexes journal entries (60s), code headers (5min), backfills embeddings |
| **Event Bus** | MAP events for agent coordination and flow triggers |
| **Context API** | Serves project context to agents (journals, knowledge, code) |
| **Session Tracking** | Manages active sessions and branches |
## API Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/health` | GET | Health check |
| `/api/context` | POST | Query project context |
| `/api/memory/search` | POST | Search memories |
| `/api/memory/add` | POST | Add a memory |
| `/api/memory/status` | GET | Memory system stats |
| `/api/memory/index` | POST | Trigger reindex + backfill |
| `/api/memory/link` | POST | Add graph edge between memories |
| `/api/events` | GET/POST | Query or publish MAP events |
## Configuration
The hub reads from `.tenet/config.json`:
```json
{
"contextHub": {
"port": 4360
}
}
```
Port and auth token are written to:
- `.tenet/context-hub.port`
- `.tenet/context-hub.token`
## Logs
```bash
tail -f .tenet/logs/context-hub.log
```
## Doctor Check
```bash
tenet doctor
```
Reports hub health, memory DB size, journal count, and agent registrations.
## Journal System
URL: https://docs.10et.ai/hub/journal
The journal is the source of truth for everything that happens in a TENET project. Every feature, fix, decision, and discovery is captured as a JSONL entry.
## Format
Each journal file is JSONL (one JSON object per line):
```json
{
"v": 2,
"ts": "2026-03-22T21:30:00.000Z",
"session": "session-goose-20260322-2009-4dfeec",
"type": "feature",
"status": "complete",
"title": "Memory system — auto-backfill embeddings",
"summary": "Periodic indexer now auto-backfills missing embeddings on first tick",
"detail": "Fixed root cause: one 35K-char memory was killing the entire backfill loop",
"files": ["src/lib/memory-indexer.ts", "src/lib/memory-search.ts"],
"learned": ["Truncate content >28K chars for embedding models"],
"next": "Add graph edges to memory schema"
}
```
## Entry Types
| Type | When to Use |
|------|------------|
| `feature` | New capability shipped |
| `fix` | Bug fix |
| `decision` | Architectural or strategic choice |
| `discovery` | Something learned or found |
| `milestone` | Significant achievement |
| `pivot` | Context checkpoint (mid-session save) |
| `session-end` | Session completed |
## File Location
```
.tenet/journal/
├── main.jsonl # Main branch entries
├── session-goose-20260322-2009-4dfeec.jsonl # Session-specific
└── flow-engine.jsonl # Automated flow entries
```
## Reading Journals
```bash
# Recent work summary
tenet synopsis 24
# Search memory (journals are indexed into memory DB)
tenet ask "What did we do about embeddings?"
# Raw journal
tail -5 .tenet/journal/main.jsonl | python3 -m json.tool
```
## How Journals Feed the System
```
Journal entry written
↓ (every 60 seconds)
Memory indexer reads it
↓
Extracts content (title + summary + detail + files + learned)
↓
Computes TF-IDF tokens
↓
Computes embedding (text-embedding-3-small)
↓
Stored in memory.db → searchable via tenet_memory_search
↓
Training tuples mined → feeds policy head
```
## Writing Journal Entries
Agents write journal entries automatically via the Pi extension. You can also write them manually:
```bash
# Via the memory tool
tenet_memory_add --title "My discovery" --content "Details..." --type discovery
# Directly to JSONL
echo '{"v":2,"ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","session":"main","type":"note","title":"My note","summary":"Details"}' >> .tenet/journal/main.jsonl
```
## Event Bus
URL: https://docs.10et.ai/hub/events
The MAP (Multiplayer Agent Protocol) event bus enables loose coupling between agents, flows, and external systems. Events flow through the Context Hub.
## Publishing Events
```bash
# Via CLI
tenet context-hub emit "eval:scored" \
--data "agent=test-coverage,delta=0.0031,improved=true"
# Via API
curl -X POST http://localhost:4360/api/events \
-H "Authorization: Bearer $TOKEN" \
-d '{"type":"eval:scored","data":{"agent":"test-coverage","delta":0.0031}}'
```
## Event Types
| Pattern | When Fired | Used By |
|---------|-----------|---------|
| `eval:scored` | After agent eval completes | Auto-merge flow, training capture |
| `kanban:pickup` | PP picks up a backlog issue | Training data capture |
| `session:ended` | Session closes | Tuple mining flow |
| `peter:daily-complete` | Nightly loop finishes | Summary reporting |
| `telemetry:insight` | Telemetry agent finds something | PP experiment trigger |
| `scope:impact` | Cross-service change detected | Cascade fix flow |
| `friction:detected` | User friction event | Auto-create issue |
| `review:scored` | AI review completes | Block merge on blockers |
| `subway:task` | Task from Subway mesh peer | Create GitHub issue |
## Subscribing (Flows)
Flows subscribe to events via pattern matching in `.tenet/flows/self-driving.yaml`:
```yaml
flows:
- name: auto-merge-on-improvement
trigger:
pattern: "eval:scored"
condition: 'data.improved == "true"'
actions:
- type: command
command: "gh pr merge {{data.pr_number}} --merge"
```
## Querying Events
```bash
# Recent events
curl "http://localhost:4360/api/events?limit=20" \
-H "Authorization: Bearer $TOKEN"
# Filter by type
curl "http://localhost:4360/api/events?pattern=eval:*&limit=10" \
-H "Authorization: Bearer $TOKEN"
```
## Event-Driven Architecture
Events enable the self-driving pipeline without tight coupling:
```
Agent finishes eval
→ emits eval:scored
→ auto-merge flow catches it
→ merges PR if improved
→ emits kanban:done
→ training capture flow logs tuple
```
No component knows about the others. They communicate through events.
## Service Discovery
URL: https://docs.10et.ai/hub/services
TENET projects can manage multiple service repos from a central GTM workspace. Each service registers with the GTM and shares context through produces/consumes scopes.
## Registering a Service
```bash
# From the GTM workspace
tenet onboard /path/to/my-service --name my-service --type api
```
This creates:
- `.tenet/config.json` in the service (with `gtm_parent` pointer)
- `CLAUDE.md` and `AGENTS.md` in the service
- Entry in GTM's `registered_services` list
## Service Config
Each service has a `.tenet/config.json`:
```json
{
"name": "my-api",
"type": "api",
"working_branch": "main",
"gtm_parent": "/Users/you/CascadeProjects/my-gtm",
"context_scope": {
"produces": ["api:endpoint-changed", "api:schema-updated"],
"consumes": ["cli:command-change", "eval:*"]
}
}
```
## Context Scopes
Services declare what events they produce and consume:
```json
{
"context_scope": {
"produces": ["docs:page-updated"],
"consumes": ["cli:command-change", "cli:api-change"]
}
}
```
When `cli:command-change` fires in tenet-cli, the docs service knows it might need updating.
## Cross-Service Flows
The GTM workspace has flows that detect cross-service impact:
```yaml
# .tenet/flows/cross-service.yaml
- name: detect-cross-service-impact
trigger:
pattern: "eval:scored"
condition: 'data.improved == "true"'
actions:
- type: command
command: "tenet scope impact --service {{data.service}}"
```
## Managing Services
```bash
# List registered services
tenet services list
# Check service health
tenet services health
# Sync service journals to GTM
tenet services sync my-service
```
## Registered Services Example
```json
{
"registered_services": [
{
"name": "tenet-cli",
"path": "/Users/you/CascadeProjects/tenet-cli",
"type": "cli",
"status": "active",
"context_scope": {
"produces": ["cli:command-executed", "cli:hook-fired"],
"consumes": ["platform:api-response", "telemetry:insight"]
}
},
{
"name": "tenet-docs",
"path": "/Users/you/CascadeProjects/tenet-docs",
"type": "docs",
"status": "active",
"context_scope": {
"produces": ["docs:page-updated"],
"consumes": ["cli:command-change", "cli:api-change"]
}
}
]
}
```
---
# Integrations
## Pi Integration
URL: https://docs.10et.ai/integrations/pi
[Pi](https://github.com/badlogic/pi-mono) is a minimal terminal coding agent that TENET extends with tools, memory, journal, eval, and the startup briefing.
## How It Works
TENET ships as a Pi package (`@10et-ai/pi`). When Pi starts in a TENET project, the extension:
1. **Replaces the header** with branded TENET identity (project name, branch, system indicators)
2. **Runs the SATOR boot animation** with live system probes
3. **Registers 21+ tools** (tenet_context, tenet_memory_search, tenet_eval_status, etc.)
4. **Fires the startup briefing** — steers the model to produce a concise project briefing
5. **Journals every significant action** automatically
## Tools Available in Pi
| Tool | What it does |
|------|-------------|
| `tenet_context` | Get project context (journals, knowledge, code headers) |
| `tenet_memory_search` | Search across all indexed memories |
| `tenet_memory_add` | Add a memory manually |
| `tenet_memory_status` | Check memory system health |
| `tenet_hud` | Project dashboard |
| `tenet_synopsis` | Work summary across sessions |
| `tenet_pivot` | Checkpoint current work |
| `tenet_eval_status` | Current eval scores and trends |
| `tenet_policy_score` | Score a candidate action via policy head |
| `tenet_crm` | CRM pipeline queries |
| `tenet_service` | Query registered services |
## Session Lifecycle
```
Pi starts
→ TENET header renders
→ SATOR boot animation + system probes
→ Startup briefing steer fires (triggerTurn: true)
→ Model produces concise greeting
→ User works (tools available, journal auto-captures)
→ /end → session branch merged to main → synopsis shown
```
## Configuration
In `.tenet/config.json`:
```json
{
"pi": {
"provider": "anthropic",
"model": "claude-opus-4-6"
}
}
```
## OpenClaw
URL: https://docs.10et.ai/integrations/openclaw
[OpenClaw](https://github.com/openclaw/openclaw) provides conversational agent interfaces. TENET integrates with OpenClaw for:
- **Telegram bot** (Cash) — Conversational interface to your project
- **Nightly cron** — OpenClaw's cron system triggers `tenet peter daily`
- **Subway mesh** — OpenClaw agents communicate via the P2P relay
## Setup
Install OpenClaw and configure channels in `~/.openclaw/openclaw.json`. The nightly loop cron job runs TENET's autonomous improvement cycle.
## Nightly Cron
```json
{
"name": "nightly-loop",
"schedule": { "kind": "cron", "expr": "0 2 * * *" },
"payload": {
"kind": "agentTurn",
"message": "cd ~/project && tenet peter daily >> .tenet/nightly.log 2>&1"
}
}
```
## Subway Mesh
URL: https://docs.10et.ai/integrations/subway-mesh
Subway is a P2P mesh network for agent-to-agent communication. Agents register as `name.relay` and can send messages, make RPC calls, and broadcast to topics.
## How It Works
```
Agent A (cash.relay) ←→ Subway Relay (wss://subway-relay.fly.dev/ws) ←→ Agent B (switch.relay)
```
## Operations
| Operation | Description |
|-----------|-------------|
| `subway_send` | Fire-and-forget message to a peer |
| `subway_call` | RPC call with response (30s timeout) |
| `subway_broadcast` | Publish to all topic subscribers |
| `subway_subscribe` | Listen for broadcasts on a topic |
| `subway_resolve` | Check if a peer is online |
## Use Cases
- Agent teams coordinating on tasks
- Broadcasting optimization discoveries
- Cross-machine agent communication
- Real-time status updates between Pi sessions
## Linear
URL: https://docs.10et.ai/integrations/linear
TENET integrates with Linear for bi-directional issue tracking. Issues created in Linear sync to GitHub as `tenet/backlog` issues, which PP picks up autonomously.
## Setup
```json
// .tenet/config.json
{
"linear": {
"apiKey": "lin_api_...",
"teamId": "...",
"projectId": "...",
"syncEnabled": true
}
}
```
## Flow
```
Linear issue created
→ Webhook syncs to GitHub issue (tenet/backlog label)
→ PP picks up every 30 min
→ Agent creates PR
→ Eval passes → auto-merge → issue closed
→ Linear issue updated via API
```
## GitHub
URL: https://docs.10et.ai/integrations/github
TENET uses GitHub for the autonomous improvement pipeline — issues as a kanban board, PRs for agent changes, and CI for eval runs.
## Kanban Labels
| Label | Column | Meaning |
|-------|--------|---------|
| `tenet/backlog` | Backlog | Available for PP pickup |
| `tenet/in-progress` | In Progress | PP is working on it |
| `tenet/eval` | Eval | PR created, waiting for eval |
| `tenet/done` | Done | Merged and closed |
## Kanban Automation
`.github/workflows/kanban.yml` automatically moves issues:
- PR opened → linked issue moves to `tenet/eval`
- PR merged → linked issue moves to `tenet/done`
- Branch created matching `issue/**` → issue moves to `tenet/in-progress`
## Auto-Merge
When an agent's eval improves, the self-driving flow auto-merges the PR:
```yaml
- name: auto-merge-on-improvement
trigger:
pattern: "eval:scored"
condition: 'data.improved == "true"'
actions:
- type: command
command: "gh pr merge {{data.pr_number}} --merge --delete-branch"
```
## CI Eval
Add eval to your CI pipeline:
```yaml
# .github/workflows/tenet-eval.yml
- name: Run TENET eval
run: |
npm i -g @10et/cli
tenet eval run --agent ${{ github.event.pull_request.head.ref }}
```
---
# Guides
## Zero to Intelligence
URL: https://docs.10et.ai/guides/zero-to-intelligence
# Zero to Intelligence
Get TENET running on your project in under 2 minutes. By tomorrow morning, your codebase will have improved itself.
## Install
```bash
npm install -g @10et/cli
```
## Initialize
```bash
cd your-project
tenet init
```
This creates:
- `.tenet/config.json` — project configuration
- `.tenet/journal/` — session journals
- `.mcp.json` — MCP server config for your agent
- `CLAUDE.md` — agent instructions
- `knowledge/` — living documents (VISION, THESIS, ARCHITECTURE)
## Setup agents
```bash
tenet setup
```
TENET scans your codebase and auto-creates agents with gradient:
```
Detected: TypeScript, 1,414 tests, jest
Created agent: test-coverage (baseline: 12.8%)
Created agent: code-quality (baseline: 0.485)
✓ 2 agents with gradient — ready to improve
```
Each agent gets a TOML config and an eval script that measures a real metric.
## Run your first loop
```bash
tenet peter agent test-coverage --rounds 3
```
Watch it work:
```
Round 1 Baseline: 12.8%
Agent: added 48 test cases for config loader
After: 13.1% (+0.3%) KEPT ✓
Round 2 Baseline: 13.1%
Agent: added tests but broke type checking
After: 12.9% (-0.2%) REVERTED ✗
Round 3 Baseline: 13.1%
Agent: added edge case tests for API client
After: 13.5% (+0.4%) KEPT ✓
PR #1 created automatically.
```
## Set up the nightly loop
```bash
tenet peter daily
```
Or add to cron:
```bash
# Run every night at 2 AM
0 2 * * * cd /path/to/project && tenet peter daily >> .tenet/logs/nightly.log 2>&1
```
## Check results tomorrow
```bash
tenet status
```
```
Coverage: 12.8% → 13.5% overnight
Code quality: 0.485 → 0.51 +3 issues fixed
Tests: 1,414 → 1,493 +79 new
2 PRs merged while you were asleep.
```
## What happens over time
| Week | What changes |
|------|-------------|
| **1** | Journals accumulate. Memory indexes patterns. |
| **2** | Agents remember past decisions. "It recalled that architecture choice from last week." |
| **Month 1** | Policy head trained. Agents try smarter experiments. |
| **Month 3** | World model understands your project. New team members inherit full context. |
## Flows
URL: https://docs.10et.ai/guides/flows
# Flows
Flows are YAML-defined automations that react to events. When something happens in your project, flows trigger actions automatically.
## Where they live
```
.tenet/flows/
├── self-driving.yaml # autonomous improvement loop
├── cross-service.yaml # multi-repo cascade
└── scripts/ # bash scripts for complex actions
```
## Structure
```yaml
flows:
- name: auto-merge-on-improvement
description: "Auto-merge PRs when eval score improves"
enabled: true
trigger:
pattern: "eval:scored"
condition: 'data.improved == "true"'
gate:
requires_approval: false
cooldown_hours: 4
actions:
- type: log
message: "Eval passed: {{data.agent}} delta={{data.delta}}"
- type: command
command: "gh pr merge {{data.pr_number}} --auto"
- type: journal
entry_type: milestone
title: "Auto-merged PR #{{data.pr_number}}"
```
## Triggers
| Pattern | When it fires |
|---------|--------------|
| `eval:scored` | After any eval completes |
| `scope:impact` | Cross-service impact detected |
| `session:ended` | Agent or human session ends |
| `cron:nightly` | Nightly schedule |
| `cron:every-30-minutes` | Every 30 min |
| `custom:*` | Your own events via `tenet events publish` |
## Gates
Control when flows actually execute:
```yaml
gate:
requires_approval: true # human must approve
cooldown_hours: 4 # don't re-trigger within 4h
max_iterations: 1 # only run once per trigger
```
## Actions
| Type | What it does |
|------|-------------|
| `command` | Run a shell command |
| `journal` | Write a journal entry |
| `log` | Log a message |
| `spawn` | Spawn an agent in a worktree |
## The Self-Driving Loop
The default `self-driving.yaml` closes the autonomous improvement loop:
```
Issue filed (tenet/backlog label)
→ PP picks up issue
→ Agent creates PR in worktree
→ Eval runs on PR
→ Score improves → auto-merge → close issue → tenet/done
→ Score regresses → revert → log → try different approach tomorrow
```
## Commands
```bash
tenet flows list # see all flows and their status
tenet flows enable <name> # activate a flow
tenet flows disable <name> # deactivate
tenet flows run <name> # trigger manually
tenet events recent # see recent events
tenet events publish custom:my-event # emit your own
```
## Cross-Service Cascade
When services declare `produces` and `consumes` scopes, flows detect impact:
```yaml
- name: cascade-cross-service
trigger:
pattern: "scope:impact"
actions:
- type: spawn
target: worktree
command: tenet peter agent {{data.affected_agent}} -r 3
```
API changes automatically trigger evals in downstream consumers.
## IDE Workspace
URL: https://docs.10et.ai/guides/ide
# IDE Workspace
TENET IDE creates tmux-based workspaces with auto-detected surfaces for your project.
## Launch
```bash
tenet ide # auto-detect and launch
```
Creates a layout based on your project:
| Row | Pane | Size |
|-----|------|------|
| Top (70%) | Agent Session (Claude/Pi) | 50% |
| Top (70%) | Browser (Carbonyl) | 50% |
| Bottom (30%) | Shell | 100% |
## Surfaces
Add or remove surfaces dynamically:
```bash
tenet ide add browser # terminal browser with agent eyes
tenet ide add eval # eval scores and trends
tenet ide add agents # agent overview dashboard
tenet ide add events # context hub event stream
tenet ide add training # training buffer status
tenet ide add topology # service dependency graph
tenet ide available # list all surface types
```
## Multi-Level Navigation
Navigate between projects in a portfolio:
```bash
tenet ide open api # open child service in workspace
tenet ide up # navigate to parent GTM
```
## Custom Layouts
Define layouts in `.tenet/ide.yml`:
```yaml
rows:
- size: 70%
panes:
- title: "agent"
type: claude
- title: "browser"
type: browser
- size: 30%
panes:
- title: "shell"
type: shell
- title: "events"
type: events
```
## Commands
```bash
tenet ide # launch
tenet ide status # show current layout
tenet ide add <surface> # add a surface
tenet ide remove <surface> # remove a surface
tenet ide stop # stop workspace
tenet ide restart # restart
tenet ide reset # reset to default
tenet ide config # view/set config
```
## Browser (Agent Eyes)
URL: https://docs.10et.ai/guides/browser
# Browser — Agent Eyes
A terminal browser powered by Carbonyl that gives agents direct DOM access while rendering visually for humans. No screenshots needed.
## Why this exists
| Tool | Agent sees | Human sees | Bidirectional? |
|------|-----------|-----------|----------------|
| Cursor | Screenshots | Nothing | ❌ |
| Claude Code | Screenshots | Nothing | ❌ |
| **TENET Browser** | **Live DOM** | **Terminal rendering** | **✅** |
## Start
In a separate terminal:
```bash
./tools/browser/tenet-browser.sh https://10et.ai
```
The human sees the page rendered in their terminal. The agent gets structured DOM via CDP.
## Agent commands (via Subway)
```bash
# Navigate
subway_call("browser.relay", "navigate", '{"url":"https://example.com"}')
# Read page structure (headings, forms, links, tables, errors)
subway_call("browser.relay", "read", '{}')
# Click an element
subway_call("browser.relay", "click", '{"selector":"#deploy-btn"}')
# Type into a field
subway_call("browser.relay", "type", '{"selector":"#search", "text":"error logs"}')
# Scroll
subway_call("browser.relay", "scroll", '{"direction":"down"}')
# Wait for element to appear
subway_call("browser.relay", "wait", '{"selector":".results", "timeout":5000}')
```
## What agents get back
Not screenshots. Structured DOM:
```json
{
"url": "https://app.example.com/dashboard",
"title": "Dashboard",
"dom_summary": {
"headings": ["Dashboard", "System Health"],
"forms": [{"id": "search", "fields": ["query"]}],
"links": [{"text": "Settings", "href": "/settings"}],
"tables": [{"id": "health-table", "rows": 5}],
"interactive": [{"type": "button", "text": "Deploy"}],
"errors": [],
"text_content": "3 services healthy, 1 degraded."
}
}
```
## Human → Agent flow
When you click or type in the browser, events broadcast on the Subway mesh:
```json
{
"type": "human_click",
"element": {
"tag": "div",
"class": "error-banner",
"text": "API timeout on /api/v2/health",
"selector": "#dashboard > .error-banner"
}
}
```
Your agent receives this and can respond: *"I see you're looking at the monitoring page — the 502s started 20 minutes ago..."*
## Authentication
No special auth system. The human is literally using the browser:
1. Agent navigates to login page
2. Human sees the form, types credentials in terminal
3. Agent detects auth state change
4. Agent proceeds with authenticated session
## HTTP fallback
If Subway isn't running, use the local API:
```bash
curl -X POST http://127.0.0.1:9223/navigate -d '{"url":"https://example.com"}'
curl -X POST http://127.0.0.1:9223/read
curl -X POST http://127.0.0.1:9223/click -d '{"selector":"button.submit"}'
```
---
# CLI Reference
## tenet init
URL: https://docs.10et.ai/cli/init
Create a new TENET project with context hub, eval system, agents, and knowledge docs.
## Usage
```bash
cd your-project
tenet init
```
## What It Creates
```
your-project/
├── .tenet/
│ ├── config.json # Project configuration
│ ├── journal/main.jsonl # Initial journal entries
│ └── agents/ # Default agent configs
├── eval/ # Eval scripts
├── knowledge/ # VISION, THESIS, NARRATIVE
├── CLAUDE.md # Agent instructions
└── AGENTS.md # Pi agent instructions
```
## Options
```bash
tenet init # Interactive wizard
tenet init --name my-project # Skip name prompt
tenet init --type gtm # GTM workspace
tenet init --type service # Service repo
```
## Onboarding a Service
To onboard an existing service repo into a GTM workspace:
```bash
# From the GTM workspace
tenet onboard /path/to/service --name my-service --type api
```
## tenet status
URL: https://docs.10et.ai/cli/status
Display current project health, session info, and system status.
## Usage
```bash
tenet status
```
## Output
```
TENET Status
Project: my-project
Branch: main
Hub: ✓ (port 4360)
Memory: 349 entries (349 embedded)
Journal: 65 sessions, 331 entries
Agents: 5 configured
Training: 2764 tuples
Recent (24h):
[feature] Memory system overhaul
[fix] Agent eval root cause
[decision] Archive 6 dead agents
```
## tenet peter
URL: https://docs.10et.ai/cli/peter
Peter Parker is the agent orchestrator. It manages the nightly improvement loop, runs individual agents, creates PRs, and handles strategic reasoning.
## Commands
### Daily Loop
```bash
tenet peter daily
```
Full nightly orchestration: mine tuples → synthesize context → strategic reasoning → run agents → pick up issues. Typically run via cron at 2 AM.
### Agent Management
```bash
# List all configured agents
tenet peter agent list
# Run a specific agent
tenet peter agent <name> --rounds <N>
# Run all agents (swarm mode)
tenet peter agent swarm --rounds <N>
# Create a new agent interactively
tenet peter agent create
```
### PR Mode
```bash
# Create a branch, make changes, open a PR
tenet peter pr --task "Fix the auth token refresh bug"
```
### Other Commands
```bash
tenet peter status # Show status + recent events
tenet peter dashboard # Live event stream
tenet peter telemetry # Run telemetry agent
tenet peter synthesize # Regenerate product context
tenet peter sentinel # Run sentinel nightly review
tenet peter metrics # Show current platform metrics
```
## Options
| Flag | Description |
|------|-------------|
| `--cost` | Cost-optimized model routing (haiku-heavy) |
| `--balanced` | Balanced model routing (default) |
| `--quality` | Quality-first model routing (opus-heavy) |
| `--budget <amount>` | Cost budget in USD (auto-downgrades when exceeded) |
| `--pi` | Force Pi runtime |
| `--rounds <N>` | Number of rounds (for agent/autoresearch) |
## Examples
```bash
# Run test-coverage for 10 rounds with cost optimization
tenet peter agent test-coverage --rounds 10 --cost
# Run the full nightly loop with $20 budget cap
tenet peter daily --budget 20
# Create a PR to fix a specific issue
tenet peter pr --task "GitHub #42: Fix login redirect loop"
# Run all agents in quality mode
tenet peter agent swarm --rounds 5 --quality
```
## tenet organize
URL: https://docs.10et.ai/cli/organize
Audit knowledge docs for staleness, detect drift from journal evidence, and generate proposed updates for human review.
## Usage
```bash
# Audit — show what's stale
tenet organize
# Generate PENDING.md with proposed updates
tenet organize --fix
# Apply reviewed changes from PENDING.md
tenet organize --apply
# Move archive candidates to knowledge/archive/
tenet organize --archive
# Custom lookback period
tenet organize --days 60
```
## How It Works
1. Scans `knowledge/*.md` for all active docs
2. Reads last N days of journal entries
3. Extracts topics from both docs and journals
4. Computes **drift score** per doc:
- Age penalty (>7 days starts drifting)
- Journal activity penalty (lots of activity + stale doc = drift)
- Stale topic penalty (topics in doc not mentioned in journals)
5. Generates `knowledge/PENDING.md` with:
- TLDR of what needs attention
- Uncovered topics (journals mention, no doc covers)
- Per-doc proposed updates with evidence
- Open questions for human review
## Output
```
Knowledge Organizer
Scanning 243 journal entries from last 30 days
Doc Health
✓ VISION 0d old drift: 20% mentions: 221
✓ THESIS 0d old drift: 20% mentions: 223
✓ NARRATIVE 0d old drift: 20% mentions: 206
✗ ROADMAP 14d old drift: 65% mentions: 89
1 of 4 docs need attention
Generated: knowledge/PENDING.md
Review it, answer questions, then run: tenet organize --apply
```
## The PENDING.md Workflow
PENDING.md acts as a PR for your knowledge base:
```
tenet organize → generates PENDING.md
↓
You review PENDING.md → answer questions, mark keep/update/archive
↓
tenet organize --apply → applies changes, clears PENDING.md
```
### Example PENDING.md
```markdown
# Knowledge Update — PENDING
> Review this file, answer questions, then run `tenet organize --apply`
## TLDR
1 of 4 docs need attention:
- ⚠️ **ROADMAP** — drifted (14d old, drift: 65%)
## Uncovered Topics
Recent journal activity mentions these topics but no knowledge doc covers them:
- **docker testing** — "Set up Docker-based onboarding eval"
- **memory graph edges** — "Added graph edge functions to memory-db"
## Open Questions
- [ ] VISION.md references old naming but recent journals use current naming. Update?
- [ ] New RL learning loop — should this be in THESIS or a separate doc?
**Action:** <!-- ANSWER: keep / update / archive -->
```
## Options
| Flag | Description |
|------|-------------|
| `--fix` | Generate PENDING.md (same as default) |
| `--apply` | Apply reviewed changes, clear PENDING.md |
| `--archive` | Move archive-candidate docs to `knowledge/archive/` |
| `--days <N>` | Journal lookback period (default: 30) |
## tenet synopsis
URL: https://docs.10et.ai/cli/synopsis
Show a summary of recent work — journal entries, git commits, file changes, and time breakdown.
## Usage
```bash
tenet synopsis # Last 24 hours
tenet synopsis 48 # Last 48 hours
tenet synopsis 24 goose # Filter by author
```
## Output
Shows:
- Journal entries (features, fixes, decisions, discoveries)
- Git commits across all branches
- Files modified count
- Code headers changed
Used automatically at session end to show what was accomplished.
## tenet doctor
URL: https://docs.10et.ai/cli/doctor
Run diagnostics on your TENET project and optionally auto-fix issues.
## Usage
```bash
tenet doctor # Check health
tenet doctor --fix # Auto-repair issues
tenet doctor --json # Machine-readable output
```
## Checks
| Check | What it verifies |
|-------|-----------------|
| `.tenet` directory | Exists with required files |
| `config.json` | Valid JSON with required fields |
| Context Hub | Running and responsive |
| Memory database | Exists, has entries, embeddings available |
| Journal | Has session files |
| Agents | Valid TOML configs with eval scripts |
| Git branch | On expected branch |
| Hooks | HTTP hooks configured |
## tenet eval
URL: https://docs.10et.ai/cli/eval
Manage the eval system — run evals, view scores, mine training data.
## Commands
```bash
# View current eval status
tenet eval status
# Compare two eval snapshots
tenet eval compare
# Mine training tuples from history
tenet eval mine --all
tenet eval mine --source journals
tenet eval mine --source evals
# View eval trajectory for an agent
tenet eval trajectory --agent test-coverage
```
## Eval Status Output
```
Eval Status (last 5)
2026-03-22 test-coverage 0.1307 +0.0031 ✓
2026-03-22 test-coverage 0.1276 0.0000 ·
2026-03-22 code-quality 0.6881 +0.0045 ✓
2026-03-21 cli-speed 98ms -2ms ✓
```
---
# API Reference
## Context API
URL: https://docs.10et.ai/api/context
## POST /api/context
Query project context — journals, knowledge docs, code headers.
```bash
curl -X POST http://localhost:4360/api/context \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "CLI startup", "maxItems": 10}'
```
### Request Body
| Field | Type | Description |
|-------|------|-------------|
| `query` | string | Optional search query |
| `maxItems` | number | Maximum results (default: 30) |
| `taskType` | string | Prioritization: code, spec, content, strategy, general |
### Response
```json
{
"items": [
{
"source": "journal",
"type": "feature",
"title": "CLI startup optimization",
"content": "Reduced p90 from 6.7s to 98ms...",
"path": ".tenet/journal/main.jsonl"
}
]
}
```
## Memory API
URL: https://docs.10et.ai/api/memory
## POST /api/memory/search
Search indexed memories with hybrid BM25 + semantic search.
```bash
curl -X POST http://localhost:4360/api/memory/search \
-H "Authorization: Bearer $TOKEN" \
-d '{"query": "eval scripts", "limit": 5}'
```
## POST /api/memory/add
Add a memory manually.
```bash
curl -X POST http://localhost:4360/api/memory/add \
-H "Authorization: Bearer $TOKEN" \
-d '{"title": "My insight", "content": "Details...", "type": "discovery"}'
```
## GET /api/memory/status
Memory system health and stats.
```bash
curl http://localhost:4360/api/memory/status \
-H "Authorization: Bearer $TOKEN"
```
## POST /api/memory/index
Trigger reindex and embedding backfill.
```bash
curl -X POST http://localhost:4360/api/memory/index \
-H "Authorization: Bearer $TOKEN" \
-d '{"backfill": true}'
```
## POST /api/memory/link
Add a graph edge between two memories.
```bash
curl -X POST http://localhost:4360/api/memory/link \
-H "Authorization: Bearer $TOKEN" \
-d '{"from": 42, "to": 17, "type": "updates"}'
```
### Link Types
`updates` | `contradicts` | `related_to` | `caused_by` | `part_of`
## Events API
URL: https://docs.10et.ai/api/events
## GET /api/events
Query recent events.
```bash
curl "http://localhost:4360/api/events?limit=20&pattern=eval:*" \
-H "Authorization: Bearer $TOKEN"
```
### Query Parameters
| Param | Description |
|-------|-------------|
| `limit` | Max events to return (default: 20) |
| `pattern` | Filter by event type prefix (e.g., `eval:`, `kanban:`) |
## POST /api/events
Publish an event.
```bash
curl -X POST http://localhost:4360/api/events \
-H "Authorization: Bearer $TOKEN" \
-d '{"type": "custom:my-event", "data": {"key": "value"}}'
```
## Eval API
URL: https://docs.10et.ai/api/eval
## GET /api/eval/trajectory
Get eval score history for an agent.
```bash
curl "http://localhost:4360/api/eval/trajectory?agent=test-coverage&metric=composite" \
-H "Authorization: Bearer $TOKEN"
```
### Query Parameters
| Param | Description |
|-------|-------------|
| `agent` | Agent name (required) |
| `metric` | Metric name (default: composite) |
### Response
```json
{
"agent": "test-coverage",
"metric": "composite",
"trajectory": [
{"ts": "2026-03-22T21:30:00Z", "value": 0.1276},
{"ts": "2026-03-22T21:35:00Z", "value": 0.1307},
{"ts": "2026-03-22T21:40:00Z", "value": 0.1342}
]
}
```