5
1
Fork
You've already forked hence
0
Multi-agent LLM plan coordination using defeasible logic
  • Rust 81%
  • Racket 15.9%
  • Shell 1.9%
  • Python 1.1%
Anuna 02 81b8cac240
Some checks failed
ci/woodpecker/push/docs Pipeline was successful
ci/woodpecker/push/ci Pipeline failed
docs(plan): update plan
2026年04月23日 17:11:10 +10:00
.claude/skills/hence docs: document --prompt-only and --stdin decompose modes 2026年03月04日 12:19:47 +11:00
.hence hence: complete task 'docs' 2026年03月04日 17:43:51 +11:00
.woodpecker ci: fix wrangler env vars and auto-create Pages project 2026年02月24日 11:59:22 +11:00
demo
docs Add Exploration Workflow section to plan-authoring docs 2026年03月04日 17:43:40 +11:00
eval
examples docs: update CLI references to use namespaced subcommands 2026年02月23日 11:09:25 +11:00
plans docs(plan): update plan 2026年04月23日 17:11:10 +10:00
reviews review: synthesize findings into concrete spec refinements 2026年02月23日 18:45:06 +11:00
specs docs: broaden SPEC-015 from experiment-loop to workflow loop templates 2026年03月19日 15:42:14 +11:00
src feat: use opencode run with --dangerously-skip-permissions for non-interactive spawning 2026年04月23日 17:06:26 +10:00
tests fix(tests): replace claude with qwen in decompose integration tests 2026年04月23日 12:30:38 +10:00
.gitignore chore: update gitignore 2026年03月03日 23:22:39 +11:00
Cargo.toml chore: bump version to 0.7.0 2026年03月02日 15:38:44 +11:00
CHANGELOG.md docs: add CHANGELOG based on Keep a Changelog 1.1.0 2026年03月02日 15:04:09 +11:00
docs-audit.md docs: fix inaccuracies found in first-time user audit 2026年02月24日 20:35:53 +11:00
info.rkt chore: bump version to 0.5.2 2026年02月16日 15:53:46 +11:00
install.sh ci: rewrite for Rust builds with Woodpecker + Cloudflare R2 2026年02月16日 15:19:40 +11:00
LICENSE
main.rkt chore: bump version to 0.5.2 2026年02月16日 15:53:46 +11:00
Makefile fix: speed up test suite, fix CI failures 2026年02月22日 09:55:24 +11:00
port.spl
README.md docs: add hence plan decompose to README and docs site 2026年03月04日 07:35:50 +11:00
release.sh chore: update release.sh for Rust (Cargo.toml, cargo test/clippy) 2026年02月16日 15:48:58 +11:00

hence

A CLI tool for multi-agent LLM plan coordination using defeasible logic.

Install

Download and install the standalone binary (no dependencies required):

curl -fsSL https://files.anuna.io/hence/latest/install.sh | bash

This installs to ~/.local/bin by default. To install elsewhere:

INSTALL_DIR=/usr/local/bin LIB_DIR=/usr/local/lib curl -fsSL https://files.anuna.io/hence/latest/install.sh | bash

Manual Binary Install

  1. Download the archive for your platform from releases
  2. Extract: tar -xzf hence-*.tar.gz
  3. The extracted directory contains both bin/ and lib/ - both are needed
  4. Copy preserving structure:
    # Install to ~/.local (binary looks for ../lib relative to itself)
    cp -r hence-dist/bin/hence ~/.local/bin/hence
    cp -r hence-dist/lib/plt ~/.local/lib/
    

LLM agents generate plans in Spindle Lisp (SPL) format. This tool reasons about next steps, assignments, and completion. Multiple agents query the same plan and accumulate facts as work progresses.

Plans can be local files or hosted on hence.run for multi-agent coordination across machines.

Architecture

┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ LLM Agent │ │ LLM Agent │ │ LLM Agent │
│ (claude) │ │ (codex) │ │ (gemini) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
 │ │ │
 └────────────────┼────────────────┘
 │
 ┌────────────┴────────────┐
 │ │
 ▼ ▼
 ┌─────────────────┐ ┌───────────────────┐
 │ hence CLI │ │ hence agent spawn │
 │ task next/done │ │ (PTY + worktree) │
 │ task claim/assert│ └────────┬──────────┘
 └────────┬────────┘ │
 │ ┌────────┴──────────┐
 │ │ hence agent watch │
 │ │ (auto-spawn loop) │
 │ └────────┬───────────┘
 │ │
 ├───────────────────────┘
 │
 ├── hooks/ (lifecycle scripts)
 ├── validators/ (custom validation)
 ├── hence-* (external commands)
 ├── config.toml (providers, settings)
 │
 ┌─┴───────────┬─────────────┐
 │ │ │
 ▼ ▼ ▼
 ┌─────────────┐ ┌──────────┐ ┌──────────────┐
 │ plan.spl │ │hence.run │ │ spindle-core │
 │ (local file)│ │ (hosted) │ │(DFL reasoner)│
 └─────────────┘ └──────────┘ └──────┬───────┘
 │
 ▼
 conclusions (+D, +d)

Local files work for single-machine use. hence.run enables multi-agent coordination across machines with ~32k simultaneous agents per plan.

Installation (from source)

Requires Racket (8.x or later).

# Clone the repository
git clone https://codeberg.org/anuna/hence.git
cd hence
# Install Racket dependencies (spindle and crypto)
raco pkg install --auto
# Option 1: Build standalone distribution (no Racket needed at runtime)
make distribute
./hence-dist/bin/hence --help
# Option 2: Build for development (requires Racket at runtime)
make build
./hence --help

To install system-wide:

# Standalone install (no Racket required to run)
sudo make install-dist
# Or development install (requires Racket)
sudo make install

Install to a custom location:

make install-dist PREFIX=~/.local

Usage

# What should happen next?
hence task next plan.spl
# Filter by agent (show only their assignments)
hence task next plan.spl --agent coder
# JSON output for programmatic use
hence task next plan.spl --json
# Who should handle what?
hence task assign plan.spl
# Mark task complete (adds fact, re-reasons)
hence task complete models plan.spl
# Claim a task (mark in-progress, prevents other agents from taking it)
hence task claim auth plan.spl
# Block a task (adds defeater rule to prevent assignment)
hence task block auth "waiting for API keys" plan.spl
# Unblock a task (removes block fact and defeater rule)
hence task unblock auth plan.spl
# Assert a discovery (fact, rule, defeater, or superiority)
hence task assert '(given discovered-issue)' plan.spl --agent coder
hence task assert '(normally r1 found-bug needs-fix)' plan.spl --agent coder
# Spawn an agent to work a task (auto-selects ready task)
hence agent spawn plan.spl --agent claude
# Spawn a specific task
hence agent spawn plan.spl --agent codex --task auth
# Watch plan and auto-spawn agents for ready tasks
hence agent watch plan.spl --spawn --agent claude
# Watch with a task limit
hence agent watch plan.spl --spawn --agent claude --max-tasks 5
# Why was this concluded?
hence query explain ready-crud plan.spl
# Why was this NOT concluded?
hence query why-not ready-tests plan.spl
# Inspect a rule, fact, or literal (show definition and meta)
hence query describe plan.spl r-ready-auth
hence query describe plan.spl r-ready-auth task-models --json
# What facts are needed? (abductive reasoning)
hence query require ready-tests plan.spl
# Show defeaters and rule annotations
hence query require ready-tests plan.spl -v
# Assume facts when reasoning backwards (abductive)
hence query require ready-tests plan.spl --assume completed-auth
# JSON output for LLM consumption
hence query require ready-tests plan.spl --format json
# Show all conclusions
hence plan status plan.spl
# Kanban board view
hence plan board plan.spl
# Verbose board with dependencies and block reasons
hence plan board plan.spl --verbose
# Dry-run spawn (assemble context without launching agent)
hence agent spawn plan.spl --agent claude --dry-run
# Stream NDJSON events to a file
hence agent spawn plan.spl --agent claude --events events.ndjson
# Watch with session tracking and events
hence agent watch plan.spl --spawn --agent claude --session my-run --events events.ndjson
# Translate a markdown spec into an SPL plan
hence plan translate spec.md --agent claude -o plan.spl
# Review a plan for issues and ambiguities
hence plan review plan.spl --agent claude
# Decompose a task into subtasks (abduction-guided LLM expansion)
hence plan decompose auth plan.spl --agent claude
# Decompose and merge subtasks directly into the parent plan
hence plan decompose auth plan.spl --agent claude --merge
# Decompose with JSON output for programmatic use
hence plan decompose auth plan.spl --agent claude --json
# List all sessions
hence sessions
# Show session details
hence session my-run
# Spindle Lisp format reference for LLMs (default)
hence llm
# DFL format reference for LLMs
hence llm dfl

Commands

hence plan -- Plan Management

Command Description
hence plan init Initialize a new plan
hence plan validate <file> Check plan syntax
hence plan info <file> Show plan metadata
hence plan status <file> [--json] Show all conclusions
hence plan board <file> [--agent NAME] [-v] [--json] [--format FMT] Kanban board view of task states
hence plan summary <file> Show plan summary
hence plan translate <spec> [--agent NAME] [-o FILE] [--context CTX] Translate a markdown specification into an SPL plan via headless agent
hence plan decompose <task> [file] [--agent NAME] [-o FILE] [--merge] [--json] Decompose a task into subtasks using abduction-guided LLM expansion
hence plan review <file> [--agent NAME] [--context CTX] [--json] Review a plan for issues and ambiguities via headless agent

hence task -- Task Operations

Command Description
hence task next <file> [--agent NAME] [--json] Show next actions based on current state
hence task assign <file> [--agent NAME] [--json] Show agent assignments
hence task complete <task> [file] Add completion fact, re-reason (validates task exists)
hence task claim <task> [file] Mark task in-progress (prevents other agents from taking it)
hence task unclaim <task> [file] Release a claimed task
hence task block <task> <reason> [file] Block task with annotated defeater rule
hence task unblock <task> [file] Remove block fact and defeater rule
hence task assert <spl> [file] [--agent NAME] [--task NAME] Assert discovery with full DSL power

hence agent -- Agent Spawn & Watch

Command Description
hence agent spawn <file> --agent <name> Spawn an agent to execute a ready task in an isolated worktree
hence agent watch <file> [--spawn --agent <name>] Watch plan for state changes, optionally auto-spawning agents
hence agent whoami Show the current agent identity

hence agent spawn handles the full lifecycle: claim task, create git worktree, assemble context prompt, launch agent via PTY, evaluate results, merge back. Supports 21 built-in agent CLIs (claude, codex, qwen, gemini, cursor, copilot, amp, and more) plus custom providers via config.toml.

Flag Command Description
--task <name> spawn Execute a specific task instead of auto-selecting
--cleanup spawn, watch Remove worktree after completion
--no-merge spawn Skip merging task branch into integration branch
--show-prompt spawn Print assembled context prompt to stderr
--token-budget <n> spawn Token budget for context assembly
--max-tasks <n> watch Exit after spawning N tasks
--delay <secs> watch Polling interval (default 5s)
--dry-run spawn, watch Assemble context without launching agent
--events <path> spawn, watch Emit NDJSON events to file or - for stdout
--session <name> spawn, watch Tag events with a session name (requires --events)
--pool watch Enable worktree pool pre-allocation
--trust-plan-checks spawn Trust evaluate-checks from plan meta (remote plans)
--lease-ttl <dur> spawn Lease TTL as ISO 8601 duration (default: PT30M)
--idle-timeout <dur> spawn Idle timeout as ISO 8601 duration (default: PT5M)
--timeout <dur> spawn Wall-clock timeout as ISO 8601 duration (default: PT60M)
--json watch Output state changes as JSON

hence remote -- Hence.run (Remote Plans)

Command Description
hence remote new [file.spl] Create hosted plan on hence.run (optionally from local file)
hence remote cp <src> [dst] Copy between local and remote
hence remote ls List your hosted plans
hence remote rm <url> Archive a hosted plan

All commands work with URLs:

# Create hosted plan
hence remote new plan.spl
# → https://hence.run/p/abc123
# Use remote plan (same commands as local)
hence task next https://hence.run/p/abc123
hence task complete design https://hence.run/p/abc123
hence plan board https://hence.run/p/abc123
# Download remote plan
hence remote cp https://hence.run/p/abc123 local.spl

hence query -- Explanation & Reasoning

Command Description
hence query explain <literal> [file] Show derivation chain with semantic annotations
hence query why-not <literal> [file] Explain why not concluded (DL(d) proof condition analysis)
hence query describe <file> <labels...> [--json] Inspect rules/facts/literals - show definitions and meta
hence query require <literal> [file] [-v] [--assume FACTS] [--format json] Abductive reasoning with defeater analysis
hence query what-if <file> <facts...> [--json] Hypothetical reasoning - show new conclusions if facts were added
hence query trace <file> Full reasoning trace with all derivations

Describe Command Details

The hence query describe command inspects rules, facts, and literals in a plan:

  • Rules: Shows the full rule definition and all meta annotations
  • Facts: Shows the fact declaration
  • Derived literals: Shows which rules derive the literal
# Inspect a single rule with its meta
hence query describe plan.spl r-ready-auth
# Inspect multiple items at once
hence query describe plan.spl r-ready-auth task-models ready-api
# JSON output for programmatic use
hence query describe plan.spl r-ready-auth --json

Example output:

Label: r-ready-auth
Rule:
 (normally r-ready-auth
 (and task-auth no-deps-auth)
 ready-auth)
Meta:
 description: Auth task becomes ready when dependencies met
 acceptance: Auth should be assignable

JSON output structure:

{
 "label": "r-ready-auth",
 "type": "rule",
 "rules": [
 {
 "label": "r-ready-auth",
 "body": "(and task-auth no-deps-auth)",
 "head": "ready-auth",
 "kind": "defeasible",
 "meta": {
 "description": "Auth task becomes ready when dependencies met",
 "acceptance": "Auth should be assignable"
 }
 }
 ]
}

Abductive Planning Details

The hence query require command performs abductive reasoning to find what facts would make a goal provable:

  • Multiple paths: When multiple rule chains can derive the goal, all paths are shown
  • Defeater analysis: Shows what defeaters could block each path (e.g., ¬ready blocks r1)
  • Rule provenance: Shows which rules fire in each derivation chain (Via rules: r1, r2)
  • Common facts: When multiple paths exist, highlights facts common to all paths

Flags:

Flag Description
-v, --verbose Show rule annotations (description, source, etc.)
--assume FACTS Assume facts when reasoning backwards (comma-separated or repeated)
--format json Output as JSON for LLM consumption

JSON output structure:

{
 "goal": "deployed",
 "already_provable": false,
 "paths": [
 {
 "facts": ["tested", "approved"],
 "via_rules": ["r1", "r2"],
 "defeated_by": [{"defeater": "¬ready", "blocks": "r1"}]
 }
 ],
 "common_facts": ["tested"]
}

Hypothetical Reasoning (What-If)

The hence query what-if command performs hypothetical reasoning - showing what new conclusions would become derivable if specified facts were added:

# What if we completed models?
hence query what-if plan.spl completed-models
# What if we completed multiple tasks?
hence query what-if plan.spl completed-models completed-auth
# JSON output for programmatic use
hence query what-if plan.spl completed-models --json

Example output:

═══════════════════════════════════════════════════════════════
What-If Analysis
═══════════════════════════════════════════════════════════════
Hypothetical facts:
 + completed-models
───────────────────────────────────────────────────────────────
NEW conclusions (would become derivable):
 +d ready-crud
 +d assign-crud-coder
───────────────────────────────────────────────────────────────
Summary: 8 original conclusions → 10 total conclusions (2 new)

hence learn -- Process Mining

Command Description
hence learn extract-log <files...> [--format json|summary] Extract event log from completed plan traces
hence learn rules <files...> [--format dfl|json|summary] Mine rules from plan execution history
hence learn validate-rules <traces...> --against <file> Compare learned rules against existing plan

Top-Level Commands

Command Description
hence llm Spindle Lisp format reference for LLMs (default)
hence llm spl Spindle Lisp format reference
hence llm dfl DFL format reference
hence sessions [--json] List all sessions with status and timestamps
hence session <name> [--json] Show session details and task states
hence skill init Install Claude Code skill (.claude/skills/hence/SKILL.md)
hence repl Interactive REPL
hence completions Shell completions

Plan Format (Spindle Lisp)

LLM agents generate plans in Spindle Lisp (SPL) format. SPL supports both propositional atoms and first-order predicates with Datalog-style variable grounding.

;; Facts: current state
(given task-models)
(given task-auth)
(given agent-coder-available)
(given agent-security-available)
(given security-related-auth)
(given no-deps-models)
;; Strict rules: invariants (cannot be defeated)
(always r1 (and goal requires-security) needs-review)
;; Defeasible rules: defaults (can be overridden)
(normally r10 (and task-models agent-coder-available) assign-models-coder)
(normally r11 (and task-auth agent-coder-available) assign-auth-coder)
(normally r12 (and task-auth security-related-auth agent-security-available) assign-auth-security)
;; Task readiness (based on dependencies)
(normally r20 (and task-models no-deps-models) ready-models)
(normally r21 (and task-crud completed-models) ready-crud)
;; Superiority: conflict resolution
(prefer r12 r11) ; security beats coder for auth task

SPL Constructs

Construct Syntax Meaning
Fact (given literal) Asserts something is true
Relational fact (given (pred arg1 arg2)) Asserts a relation
Strict rule (always r1 (and A B) C) If A and B, then C (cannot be defeated)
Defeasible rule (normally r1 (and A B) C) If A and B, then typically C (can be overridden)
Defeater (except d1 A (not C)) If A, then block conclusion C
Superiority (prefer r2 r1) Rule r2 wins over r1 in conflicts
Negation (not literal) Negated literal
Variable ?x, ?y Datalog-style variables (automatically grounded)

First-Order Variables

SPL supports variables with automatic Datalog-style grounding:

;; Relational facts
(given (parent alice bob))
(given (parent bob charlie))
;; Rule with variables - automatically grounded
(normally r1 (parent ?x ?y) (ancestor ?x ?y))
(normally r2 (and (parent ?x ?y) (ancestor ?y ?z)) (ancestor ?x ?z))

Claims with Attribution

Track who asserted what and when:

(claims agent:security
 :at "2026年01月21日T09:00:00Z"
 :note "Security scan results"
 (given scan-complete)
 (given no-critical-vulns)
 (normally sec1 scan-complete scanned))

Metadata

Annotate rules for explainability:

(meta r20
 (description "Security-sensitive tasks require security agent")
 (source "policy/security-guidelines.md")
 (confidence 0.95))
(normally r20 (and ready-auth security-sensitive agent-security) assign-auth-security)

Metadata appears in hence query explain output.

Modular Plans

Import conclusions from other files:

(import "./agents.spl")
(import "./common.spl")

This allows splitting plans into reusable modules (e.g., agent definitions, common rules).

Discoveries

Agents can assert discoveries during execution using hence task assert. Discoveries support full SPL power: facts, rules, defeaters, and superiority relations.

# Assert a fact
hence task assert '(given discovered-api-deprecated)' plan.spl --agent coder
# Assert a rule that reacts to discoveries
hence task assert '(normally r1 discovered-issue needs-review)' plan.spl --agent coder
# Assert a defeater to block a task
hence task assert '(except d1 found-vulnerability (not ready-deploy))' plan.spl --agent security

Naming Conventions

Use prefixes for discoverability and cross-agent coordination:

Prefix Purpose Example
discovered- Findings during execution discovered-api-deprecated
decided- Design decisions made decided-use-redis
blocked-by- Blockers identified blocked-by-missing-credentials
requires- Prerequisites found requires-api-key
verified- Validations passed verified-authentication-works
failed- Failures observed failed-integration-test

Blocker/Unblocker Pattern

Facts (given) cannot be defeated. To create blockers that can be unblocked, use an intermediate derived literal:

;; Use intermediate literal that CAN be defeated
(normally r-has-vulnerability discovered-vulnerability has-active-vulnerability)
(except d-block has-active-vulnerability (not ready-deploy))
(except d-unblock verified-fix (not has-active-vulnerability))

This preserves the discovery as an audit trail while allowing its effect to be defeated.

Timestamps

All mutation commands (hence task complete, hence task claim, hence task block, hence task unblock, hence task assert) automatically add ISO8601 timestamps via claims blocks. This enables:

  • Process mining: Extract temporal patterns from execution history
  • Audit trails: Track when each discovery was made
  • Ordering: Ensure events sort correctly for analysis
(claims system
 :at "2026年01月17日T14:30:00Z"
 (given completed-auth))

Concurrency Safety

All mutations (hence task complete, hence task claim, hence task block, hence task unblock, hence task assert) are append-only. This enables safe concurrent writes from multiple agents without locks or coordination.

POSIX guarantees atomic writes up to 4096 bytes when appending to a file. Hence discoveries are designed to stay well under this limit, so simultaneous writes from different agents will not interleave or corrupt each other.

Agent A: hence task complete auth plan.dfl ─┐
Agent B: hence task assert '...' plan.dfl ─┼─► All appends preserved
Agent C: hence task claim deploy plan.dfl ─┘

The plan file serves as a simple append-only log. Each command re-reads and re-reasons from the full file, so agents always see a consistent view of accumulated facts.

The ordering of facts and rules in the file does not matter—the defeasible logic engine reasons over the entire theory at once. Conclusions depend only on what is asserted, not when or where it appears in the file.

Process Mining

Learn plan patterns from execution history. Process mining extracts event logs from completed plans and discovers rules that explain observed behavior.

Note: Process mining requires timestamped facts. All mutation commands (hence task complete, hence task claim, hence task block, hence task unblock, hence task assert) automatically add timestamps. For initial plan facts without timestamps, the earliest timestamp in the file is used as fallback.

Extract Event Log

Convert completed plans into a structured event log:

# Extract events from multiple plan files
hence learn extract-log plans/*.spl --format json > events.json
# View summary
hence learn extract-log plans/*.spl --format summary
# Event Log Summary
# =================
# Cases: 3
# Total events: 24
#
# Case: plans/sprint-1.dfl (8 events)
# 1: completed_auth {task: auth}
# 2: completed_models {task: models}
# ...

Learn Rules

Mine defeasible rules from execution traces:

# Output learned rules as DFL
hence learn rules plans/*.spl --format dfl
# ---
# description: "Learned from 3 traces (support: 3, confidence: 1.00)"
# ---
# r_learned_1: completed_models => ready_crud
# View mining summary
hence learn rules plans/*.spl --format summary
# Mining Results
# ==============
# Traces: 3
# Rules learned: 5
# Conflicts detected: 1
# Choice points: 2

Validate Against Existing Rules

Compare learned patterns against your plan template:

hence learn validate-rules plans/*.spl --against template.spl
# Validation Report
# =================
# Traces analyzed: 3
# Rules learned: 5
# Existing rules: 12
#
# Coverage:
# Already covered: 4 rules
# New patterns: 1 rules
#
# Conflicts:
# ✗ Learned rule conflicts with existing r12
# Learned: completed_auth => ready_deploy
# Existing: completed_auth, security_approved => ready_deploy

This helps identify:

  • New patterns: Rules observed in practice but missing from the template
  • Conflicts: Learned behavior that contradicts existing rules
  • Low confidence rules: Patterns that vary across traces (may need defeaters)

Conclusions

  • +D literal - Definitely provable (from strict rules/facts)
  • +d literal - Defeasibly provable (from defeasible rules, not defeated)
  • -D literal - Definitely not provable
  • -d literal - Defeasibly not provable

Example Session

$ hence plan board examples/api-project.spl -v
┌──────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
│ BACKLOG │ READY │ IN PROGRESS │ BLOCKED │ DONE │
├──────────────┼──────────────┼──────────────┼──────────────┼──────────────┤
│tests │models @coder │ │ │ │
│crud │auth @security│ │ │ │
│review │ │ │ │ │
└──────────────┴──────────────┴──────────────┴──────────────┴──────────────┘
Tasks: 3 backlog, 2 ready, 0 in-progress, 0 blocked, 0 done
BACKLOG (waiting on):
 tests - needs: crud, auth
 crud - needs: models
 review - needs: tests
ASSIGNMENTS:
 models → coder
 auth → security
$ hence task next examples/api-project.spl
Next actions:
 1. assign-models-coder
 2. assign-auth-security
$ hence task complete models examples/api-project.spl
Added: (given completed-models)
Next actions:
 1. assign-crud-coder
 2. assign-auth-security
$ hence task block crud "waiting for DB schema" examples/api-project.spl
Added: (given blocked-crud)
Added: (except d-blocked-crud blocked-crud (not ready-crud)) ; reason: waiting for DB schema
Next actions:
 1. assign-auth-security
$ hence query describe examples/api-project.spl r42
Label: r42
Rule:
 (normally r42
 (and task-crud completed-models)
 ready-crud)
Meta:
 description: CRUD task ready after models complete
$ hence query why-not ready-crud examples/api-project.spl
═══════════════════════════════════════════════════════════════
Why not: ready-crud
═══════════════════════════════════════════════════════════════
To prove +∂ ready-crud, these conditions must hold:
(1) Definitely provable (): ✗
 Not definitely provable
 → Checking defeasible proof path...
(2) Negation not definitely provable (-Δ ¬q): ✓
 No strict rule derives ¬ready-crud
(3) Applicable rule exists: ✓
 Rule r42 is applicable
(4) All competing rules defeated: ✗
 Undefeated competitor: d-blocked-crud
 Competing rules for ¬ready-crud:
 ✗ d-blocked-crud: blocked-crud ~> ¬ready-crud
 Status: APPLICABLE and NOT DEFEATED
 Description: Task crud is blocked
 Justification: waiting for DB schema
═══ FAILURE POINT ═══
A defeater is blocking this conclusion.
═══ SUGGESTIONS ═══
 1. Add superiority: r42 > d-blocked-crud
 2. Defeat the competing rule's prerequisites
$ hence task unblock crud examples/api-project.spl
Removed: (given blocked-crud)
Removed: (except d-blocked-crud blocked-crud (not ready-crud))
Next actions:
 1. assign-crud-coder
 2. assign-auth-security
$ hence query require ready-tests examples/api-project.spl
═══════════════════════════════════════════════════════════════
Requirements for: ready-tests
═══════════════════════════════════════════════════════════════
To make ready-tests provable:
 Path 1 (2 facts needed):
 (given completed-crud)
 (given completed-auth)
 Via rules: r43
$ hence query require ready-tests examples/api-project.spl --assume completed-auth
═══════════════════════════════════════════════════════════════
Requirements for: ready-tests
Assuming (already true): completed-auth
═══════════════════════════════════════════════════════════════
To make ready-tests provable:
 Path 1 (1 fact needed):
 (given completed-crud)
 Via rules: r43
$ hence learn extract-log plans/sprint-*.spl --format summary
Event Log Summary
=================
Cases: 3
Total events: 24
Case: sprint-1.spl (8 events)
 2026年01月15日T09:00:00Z: completed {task: models}
 2026年01月15日T10:30:00Z: completed {task: auth}
 2026年01月15日T14:00:00Z: completed {task: crud}
 ...
$ hence learn rules plans/sprint-*.spl --format summary
Mining Results
==============
Traces: 3
Rules learned: 5
Conflicts detected: 0
Choice points: 1
Learned Rules:
 (normally _ completed-models ready-crud) (support: 3, confidence: 1.00)
 (normally _ (and completed-crud completed-auth) ready-tests) (support: 3, confidence: 1.00)

For LLM Agents

When generating a plan:

  1. Start with facts describing the goal and context
  2. Add facts for available agents
  3. Decompose into task facts
  4. Mark tasks with no dependencies using no-deps-<task> facts
  5. Add strict rules for invariants
  6. Add defeasible rules for assignments (only for ready tasks)
  7. Add defeasible rules for readiness based on completed dependencies
  8. Add superiority relations to resolve conflicts

When working on a plan manually:

# Get the format reference
hence llm | claude -p
# Create a hosted plan for multi-agent coordination
hence remote new plan.spl
# → https://hence.run/p/abc123
  1. Query hence task next <plan> --agent <name> --json to see available work
  2. Claim work with hence task claim <task> <plan> (prevents other agents from taking it)
  3. Assert discoveries as you work: hence task assert '<spl>' <plan> --agent <name>
  4. Complete work and run hence task complete <task> <plan>
  5. If a task is too large, decompose it: hence plan decompose <task> <plan> --agent <name> --merge
  6. If blocked, run hence task block <task> <reason> <plan>
  7. To unblock, run hence task unblock <task> <plan>
  8. Re-query to see what's next

Or use hence agent spawn to automate the full lifecycle:

# Spawn one agent to work the next ready task
hence agent spawn plan.spl --agent claude
# Watch and auto-spawn agents as tasks become ready
hence agent watch plan.spl --spawn --agent claude

hence agent spawn handles claiming, worktree isolation, context assembly, agent launch, evaluation, and merging -- no manual coordination needed.

Where <plan> is either a local file (plan.spl) or a hence.run URL (https://hence.run/p/...).

Discoveries accumulate in the plan and are visible to all agents. Use the naming conventions (discovered-, verified-, blocked-by-, etc.) for cross-agent coordination.

Sessions & Events

Track plan execution across spawn/watch runs with sessions and structured event streaming.

Sessions

Sessions record plan execution state in a local SQLite store (~/.hence/sessions.db):

# Start a session when spawning
hence agent watch plan.spl --spawn --agent claude --session sprint-1 --events events.ndjson
# List all sessions
hence sessions
# Show session details with task progress
hence session sprint-1

NDJSON Event Streaming

Stream structured events during spawn/watch for observability and tooling integration:

hence agent spawn plan.spl --agent claude --events events.ndjson
hence agent spawn plan.spl --agent claude --events - # stdout

Events include: spawn_start, worktree_created, context_assembled, agent_started, agent_exited, evaluation_complete, spawn_complete, watch_start, cycle_start, state_change, watch_complete, and more.

Each event is a JSON object with event, timestamp, plan, task, agent, and event-specific data.

Agent Supervision

hence agent spawn includes a supervision layer that separates execution from recovery. Inspired by BEAM/OTP's supervisor model, three roles with distinct cryptographic identities manage different concerns:

Role Identity Responsibility
Supervisor supervisor:{pubkey} Holds time-bounded lease, monitors agent liveness, renews or revokes claims
Agent agent:{pubkey} Performs task work in the worktree; no plan writes
Evaluator evaluator:{pubkey} Assesses output quality and correctness

No single entity holds all three powers — the agent cannot claim its own work is complete, the supervisor cannot assess quality, and the evaluator cannot extend a lease.

Lease-Based Claims

Task claims use (during ...) temporal bounds so they expire naturally if the supervisor crashes. The reasoner filters expired leases at reference_time: now — no central lease server or coordinator process required.

Liveness Monitoring

The supervisor passively observes agent activity through PTY output and worktree file modifications. If no activity is observed within the idle timeout, it asserts stale-v{N}-{task} which defeats the active claim via defeasible logic. A wall-clock timeout provides an outer bound even for agents that produce output continuously but make no useful progress.

Configuration

All supervision parameters follow the precedence: plan metadata > CLI flag > default.

Parameter CLI Flag Plan Metadata Default
Lease TTL --lease-ttl (meta task (id "X") (lease-ttl "PT30M")) 30 min
Idle timeout --idle-timeout (meta task (id "X") (idle-timeout "PT5M")) 5 min
Wall-clock timeout --timeout (meta task (id "X") (timeout "PT60M")) 60 min
Max retries (meta task (id "X") (max-retries 2)) 2 retries (3 total attempts)
# Spawn with custom timeouts
hence agent spawn plan.spl --agent claude --idle-timeout PT10M --timeout PT2H
# Per-task configuration in the plan
(meta task (id "heavy-refactor") (timeout "PT2H") (idle-timeout "PT10M") (max-retries 3))

Failure Propagation

When a task fails, goes stale, or times out, downstream dependents are concluded as upstream-blocked-{task} via defeasible rules. Propagation is transitive — if A fails and B depends on A and C depends on B, both B and C become upstream-blocked.

After exhausting all retries (default: 2), a task is marked permanently-failed-{task} — a terminal state that also propagates downstream.

Status Integration

hence plan status and hence plan board display supervision state when present:

$ hence plan status plan.spl
Task supervision:
 auth -> in-progress (attempt 2/3, stale: v1, lease active)
 impl -> upstream-blocked (blocked by: auth [stale-v1])
 api -> upstream-blocked (blocked by: impl [upstream-blocked])

Plugins

Hence supports git-style plugin extensibility. No source modifications or recompilation required.

External Commands

Any executable named hence-{name} in your PATH becomes a subcommand:

# Create a plugin
echo '#!/bin/sh
echo "Hello from hence-hello!"' > ~/.local/bin/hence-hello
chmod +x ~/.local/bin/hence-hello
# Use it
hence hello # → "Hello from hence-hello!"
hence hello --flag # args are passed through

Built-in commands always take precedence over external commands.

Configuration

TOML configuration at ~/.hence/config.toml (global) and .hence/config.toml (project-local). Local values override global.

[settings]
hook_timeout = 30 # seconds before killing a hook (default: 30)
plugin_path = [] # additional directories to search for plugins
# Custom agent providers for spawn/watch
[[providers]]
id = "myagent"
name = "My Custom Agent"
cli = "myagent-cli"
initial_prompt_flag = "-p"
auto_approve_flag = "--yes"

Custom providers are available to hence agent spawn and hence agent watch via (meta task-X (provider "myagent")) in plan files.

# Worktree file provisioning (symlink or copy files into agent worktrees)
[worktree.provision]
files = [
 { from = ".env", to = ".env", mode = "copy" },
 { from = "config/shared.toml", to = "config/shared.toml" }, # default: symlink
]

Lifecycle Hooks

Executable scripts in ~/.hence/hooks/ or .hence/hooks/ run after lifecycle events:

Hook Triggered after
post-claim hence task claim
post-complete hence task complete
post-block hence task block
post-unblock hence task unblock
post-assert hence task assert
post-plan-complete All tasks in plan completed

Hooks receive <plan-file> <task> <agent> as arguments and environment variables HENCE_HOOK, HENCE_PLAN, HENCE_TASK, HENCE_AGENT, HENCE_EVENT. Hook failures produce warnings but never affect the primary operation.

# Example: Slack notification on task completion
cat > .hence/hooks/post-complete << 'EOF'
#!/bin/sh
curl -s -X POST "$SLACK_WEBHOOK" \
 -d "{\"text\": \"Task 2ドル completed by 3ドル in 1ドル\"}"
EOF
chmod +x .hence/hooks/post-complete

Custom Validators

Executable scripts in ~/.hence/validators/ or .hence/validators/ run during hence plan validate. They receive the plan file path as 1ドル and output JSON diagnostics to stdout:

[
 {"level": "warning", "message": "Task auth has no description"},
 {"level": "error", "message": "Missing agent availability fact", "line": 42}
]

In --strict mode, custom validator warnings become errors.

Board Formatter Plugins

Custom output formats for hence plan board via the --format flag:

# Built-in formats: json, kanban, tree, dag
hence plan board plan.spl --format json
# External formatter: hence-board-{format} receives board JSON on stdin
hence plan board plan.spl --format html # invokes hence-board-html

Environment Variables

User-facing

Variable Description
HENCE_AGENT Default agent name. Used as fallback when --agent is not passed. Equivalent to adding --agent <name> to every command.
NO_COLOR Disable colored output when set to any non-empty value. Follows the no-color.org convention. Equivalent to --no-color.
HENCE_DEBUG Enable verbose debug logging to stderr when set to 1.
# Set once, used by all commands
export HENCE_AGENT=coder
hence next plan.spl # same as: hence next plan.spl --agent coder
# Disable color in CI or piped output
export NO_COLOR=1
hence board plan.spl
# Debug logging
HENCE_DEBUG=1 hence spawn plan.spl --agent claude

Hook and validator environment

These variables are set by hence when executing lifecycle hooks and custom validators:

Variable Description
HENCE_PLAN Absolute path to the plan file
HENCE_TASK Task name (hooks only)
HENCE_AGENT Agent name (hooks only)
HENCE_HOOK Hook name, e.g. post-complete (hooks only)
HENCE_EVENT Event type (hooks only)
HENCE_STRICT "true" or "false" (validators only)

Directories

Hence follows XDG Base Directory defaults:

Variable Default Used for
XDG_CONFIG_HOME ~/.config Identity and remote plan metadata ($XDG_CONFIG_HOME/hence/)
XDG_DATA_HOME ~/.local/share Plan replicas ($XDG_DATA_HOME/hence/)

Hooks, validators, and config.toml use a separate directory at ~/.hence/ (global) and .hence/ (project-local).

License

AGPL-3.0