Plans turn intentions into revisable dependency graphs (migration 0027):
objective, assumptions, ordered or dependent steps, capabilities,
expected observations, preconditions, risk, estimates, budget,
completion criteria, abort conditions and the alternatives considered.
- Validation owns structure: acyclic dependencies, registered and
unlocked capabilities only, schema-valid parameters, targets that agree
with parameters, read-only checks, a closed set of step kinds and
internal actions. Model proposals are parsed into the same structure;
fields that could carry authority or claim progress are reported as
ignored, and an invalid draft is stored as a draft that never runs.
- The planner prefers deterministic strategies: a direct action verified
by observation, a read-only diagnosis that requests temporary scoped log
access with risk and fallback stated, and an escalation that diagnoses
and informs the operator instead of repeating a failed action. Failed
strategies are not reused; a model is consulted only when none applies.
- The executor holds no state in memory: it claims a step with a
conditional update, acts only through Invoke and RequestCapability, and
records the outcome. Waiting for approval or access forms a subordinate
intention and blocks the parent with the reason. Expectations become
verification predictions resolved from a read-only observation, so an
HTTP-level success is never taken as the outcome; a miss is a prediction
error that weakens the supporting belief and triggers reconsideration.
Replanning creates a new revision, withdraws open requests of the old
one and keeps it as history, within a replan limit. Checks never raise
approval prompts. Budgets stop runaway plans. Preconditions skip actions
when the world already changed. Dream plans and disabled sandbox minds
never act. An interrupted non-idempotent action with no record is
blocked for verification instead of repeated; recorded outcomes are
adopted. Completed plans are stored as procedural memories; a completed
escalation does not count as fulfilling the intention.
- Executions and approvals record their origin; minds may withdraw their
own pending approval requests; Preview reports a decision without side
effects; service.status is allowed by default as a bounded read.
Bounded operations instead of a shell (ADR-0011): service.status,
service.restart and logs.query run systemctl/journalctl from a fixed
allow-list with no shell, a minimal environment, validated unit names and
the unit as the derived policy target; logs mask e-mail and IP addresses
and credential-like values by default. host.disk.usage,
host.memory.status and host.process.list read the kernel directly and
never read command lines. browser.navigate/read/links fetch through the
SSRF-safe client, run no scripts, refuse cross-host redirects, use the
host as the policy target and deliver content as low-trust observations.
Writing browser operations are designed but not registered. The test
harness takes a fake command runner so no test touches a real unit.
- Capabilities declare access (read/write, unknown fails closed as
write), side effects, idempotency, timeout, cost estimate and the trust
of their output (web content is low trust). A capability may derive its
policy target from its parameters; a disagreeing target is refused, and
approvals whose modified parameters change the target are refused.
- The registry is frozen at start-up; registration afterwards panics.
- Invocation.RequireApproval turns ALLOW into ASK for commitments; it can
only tighten, and scoped grants never satisfy it.
- Scoped grants (migration 0025): capability, target and parameter globs,
access, expiry of at most seven days and an optional operation count
consumed atomically; applied only where policy says ASK. A sweep marks
lapsed grants and refreshes the self-model, which now lists live grants.
- Capability requests carry scope, duration, operation cap, reason,
evidence, risk, mitigation, fallback, alternatives and explicit decision
history; they batch per intention, are capped per mind (operator
attention budget) and can be decided only by a named person. Component
names are refused as deciders, for approvals too, and as usernames.
- API routes, OpenAPI entries, scheduler sweeps and approval-centre
sections for requests and temporary grants.
Phase 12 (ADR-0005). Capabilities are registered in code with parameter
schemas, risk classes and default effects; sudo_shell and delete_database
are locked to DENY and cannot be relaxed. Policies are scoped globally or
per mind with capability, target glob, action kind and optional hour
window; evaluation is deterministic, most specific wins, and ties go to
the stricter effect. Invoke is the single entry point: it refuses
dreaming and replay contexts, validates parameters (unknown keys, non
http URLs and path traversal rejected), evaluates policy and session
grants, hashes the exact request and records a policy_decision event.
ALLOW executes with timeout and panic isolation and turns textual output
into a tool-trust observation; ASK creates an approval request bound to
the hash with an alert notification; DENY is counted and recorded.
Operators approve once, approve for a time-boxed session grant, deny
with a note, or modify parameters (re-validated, re-hashed, original
kept in the append-only decision log). The self-model's capability list
is recomputed from effective policy on start and on every policy change.
The act process maps fetch requests to http.fetch and the action handler
invokes through the layer; replies report capabilities and outcomes.
Policy matrix and approval centre pages, dashboard count, API, CLI
(approvals, policy, invoke) and docs/capabilities.md.