Atenea documentation
v1 contracts
On this page
v1 contracts#
Fases 10 y 11 convierten las preguntas de diseño restantes en contratos explícitos. Una capacidad está completa cuando su comportamiento tiene código y tests; una función que necesita otro provider o una decisión interactiva queda registrada como límite deliberado, no implícita en la configuración. La matriz operativa completa está en v1.0 policy.
Structural search#
symbol.search retains its language-aware declaration search contract, including
qualified names, kinds, source ranges and ranks through Kivgraph.
symbol.implementations adds declared and structural compiler evidence.
symbol.unresolved is not advertised by tools/list; direct calls return not_offered.
code.search remains literal or regex text search.
Security and permissions#
Effects are granted before dispatch, and an effect outside the grant is refused.
The CLI’s --allow is the explicit escalation mechanism.
There is no implicit interactive permission prompt, and that is the deliberate limit: no adapter and no daemon path stops to ask. A process running unattended under systemd or launchd has no terminal to be asked on, so a prompt introduced there would either hang the run or be answered by nobody. Introducing one would require a separate UI/session contract.
What does exist is an interactive permission gate the caller asks for by name.
--confirm on task, ask, decide --run and agent prints the execution
summary – the budget and the effects about to be granted – and requires a
confirmation on a TTY before anything is dispatched; without a TTY it refuses
rather than proceeding. It is a floor for one command, opted into per
invocation. agent goes further and requires it for any type declaring write
or external effects, so the shortest form of that command cannot cause them.
backup discard requires the same word for the same reason.
The distinction matters because the two are easy to conflate: Atenea will never interrupt a run to ask, and Atenea will always ask when the caller said to.
Provider boundaries#
OpenCode has an opt-in local-model backend through [model].backend = "opencode". Its event parser is isolated from Claude Code and requires a
completed step_finish event plus text before accepting an answer. It supports
model selection, repository confinement, cancellation, observed usage and MCP
configuration translation. Once a JSON event reports a token or cost overrun,
the runner kills the contained process before reading later events; this is a
local stop, not a provider-side hard cap. Its local boundary also validates
the structured answer’s required fields, primitive types, numeric bounds and closed object
properties, rejects trailing JSON values and records provider tool-use events;
it does not pretend that OpenCode’s JSON stream is Claude’s final envelope. A
tool-enabled turn is bounded at four intermediate tool steps; when that limit
is reached, Atenea resumes the persisted OpenCode session with a finalization
request so a provider outage or tool loop becomes an auditable partial answer
rather than an unbounded timeout. It does not pass OpenCode --pure, because
the authenticated server rejects that mode on the current provider path.
scripts/opencode-smoke.sh runs an opt-in real-provider smoke test when
ATENEA_OPENCODE_SMOKE=1 and ATENEA_OPENCODE_MODEL are supplied. It is not
part of ordinary CI because it may consume provider allowance.
The backend remains deliberately narrower than Claude Code: OpenCode has no
native JSON-schema flag or provider-independent budget flag. Atenea asks for
structured JSON in the prompt, records step_finish usage/cost when present,
rejects a completed result whose observed cost exceeds a positive requested
budget, and the core repeats that rejection at the common runner boundary for
every adapter. The check happens after the provider reports the turn; it
cannot prevent an already-running event from overspending.
Provider boundary errors are mapped into the shared bins: permission and
budget refusals become permission_denied, authentication, rate limits and
quota exhaustion become unavailable, and context overflow becomes
invalid_input. Timeout and caller cancellation remain distinct.
Agent limits.max_tokens is carried, validated and used by the planner to
narrow the model client’s observed incremental read boundary when a grant
exists. budget_usd is a forecast and authorization check, not a hard
provider-side ceiling. The observed boundary is not equivalent to preventing
the provider from finishing an in-flight event; Atenea deliberately does not
claim an exact provider cap.
Citation evidence is a hard acceptance gate for prose results. Every non-empty
prose field must contain at least one recognized path:line or Line N of path
citation. The reviewer rejects invented paths, out-of-range lines, incorrect
adjacent excerpts and uncited prose fields. Each result retains citation_count,
existence_only, content_checked, uncited_fields and one citations row per
location with the written path, the repository-relative resolved_path, line,
optional quote and outcome. A unique basename may resolve an abbreviated path;
a rename with a different basename remains unresolved rather than being guessed.
The gate validates the cited evidence, not the semantic meaning of surrounding
narrative. internal/agent/review_integration_test.go also exercises this
contract through the real internal/agent.Runner and the shipped
agent-exec reviewer, so the strict result schema is checked at the process
boundary rather than only through direct package tests.
Acceptance#
The implementation and all boundaries are checked by:
bash scripts/v1-readiness.shThe historical design ledger remains in
What is not built yet; this page and
v1 readiness describe the current tree.