AGENTS.md@apps/coding_agent · git:20260927.6027bc7 · 2026-09-27 · sha256 9d9a27651d957bd5

AGENTS.md@apps/coding_agent git:20260927.6027bc7A

Immutable. This exact content never changes and is served at /api/v1/blob/9d9a27651d957bd5.

# CodingAgent contributor guide

`coding_agent` owns native coding sessions, tool execution/policy, JSONL session
history, compaction and supervised delegation. The loop/model runtime comes from
`lemon_agent`; provider protocols come from `lemon_ai`. See [README](README.md).

## Session and prompt boundaries

- Keep `CodingAgent.Session` as the public GenServer; lifecycle, persistence,
  notifier, compaction and overflow helpers own their internal concerns.
- JSONL history is a tree of entries with stable IDs/parents. Preserve branch,
  compaction and async-followup provenance when restoring context. Unknown retired
  custom entries may be skipped; do not rewrite old history destructively.
- Profiles derive assistant workspace from validated `meta.profile_id` through
  `ProfileStore`, never a caller-supplied path. Default workspace is
  `~/.lemon/agent/workspace/`; profile homes stay isolated.
- Main bootstrap includes identity/user/memory files. Subagents receive only
  `AGENTS.md` and `TOOLS.md`; do not leak personal workspace memory to children.
- Compose static system prefix before volatile context. Capture environment once
  per session, not on every refresh. Stable skill metadata belongs in the prefix;
  turn-local relevance and recall do not. Preserve model replay bytes while
  stripping injected recall from user-visible transcripts/hooks.
- `remember` writes workspace `USER.md`/`MEMORY.md`; `recall` searches scoped past
  runs and workspace notes. Automatic recall is bounded local volatile context,
  skips short/subagent/unscoped requests and makes no model call. See
  [memory](../../docs/user-guide/memory.md).

## Tools and trust

- Register coding tools in the existing tool registry; assistant-platform tools
  belong in `lemon_skills`. Reuse common tool/result types and abort signals.
- Policy/approval checks run before execution. Tool precedence and extension
  conflict behavior belong to the registry, not per-tool fallback logic.
- Pre-LLM composition is guardrails → untrusted boundary → custom transform.
  Bound oversized output with stable spill references, fence external/file/shell/
  community-skill data, strip unsafe controls, and keep the entire envelope inside
  its budget. An opaque ephemeral marker provides idempotence; tool-returned
  metadata cannot claim wrapping already happened. Persisted output is unchanged.
- Background process ownership is session-scoped. Keep terminal backends under
  `ProcessManager` so policy, logs, cancellation and restart lineage are shared.
- Validate backend allow/deny policy and Docker/SSH settings before launch.
  Approvals expose command/cwd hashes and env keys, not commands, raw targets or
  env values. Validate env names/string values and checkpoint path lists first.
  Risky-command checkpoints occur before process start.

## Tasks and background work

- `task`/`@name` personas launch native in-process sessions via `Coordinator`;
  `agent` delegates through router and can choose a named node. Do not restore
  vendor CLI runners or another agent engine.
- Async launch receipts are not completed answers. Explicit joins suppress the
  corresponding followup; `wait_any` suppresses only its completed winner and
  releases other reservations. Crashed joiners cannot suppress completion forever.
- `TaskStoreServer` serializes event/suppression/lifecycle writes. Terminal result
  is first-writer-wins; late running events cannot revive it. RunGraph persistence
  loads before accepting writes, not in a later fold that can overwrite them.
- Supervisor admission failure terminalizes task/graph/budget/progress state.
  Worker/session death must end bounded waits. Completion followup failure does
  not turn a completed task into a failed worker.
- Delegated router watcher timeout is tracking loss, not proof that the remote
  run failed. Preserve fixed task/run identity for reconciliation.
- `BackgroundRun` gives `/bg` its own full-tool session without appending to a
  parent. Channel callers use scoped APIs and receive not-found for foreign IDs.
  Unresumable queued/running work becomes lost on restart.
- `SideQuery` uses an atomic frozen snapshot, no tools and a distinct ephemeral
  session. It never mutates/steers its source conversation. Public background/
  side-query failures are bounded classifications, not raw provider/store terms.
- Parent questions bind parent session/agent and child run lineage. Creation and
  terminal transitions are serialized; joins yield on pending questions rather
  than deadlock parent and child. Only the authorized parent can answer.
- Public task results contain visible assistant output and safe metadata, not
  hidden thinking, raw event history or tool-call internals.

## Named execution nodes

- Pairing stores session/recovery credentials in private node-ID-keyed records
  (0700 directory, 0600 files) bound to the exact controller URL. ID lookup without
  that URL returns no credentials. Re-pair renews the same identity; legacy repair
  requires explicit operator authorization.
- Prefer `LEMON_NODE_OPERATOR_TOKEN` / `LEMON_NODE_TOKEN` to flags. Off-loopback
  uses `wss://`; plaintext requires explicit opt-in over a verified secure overlay.
- The worker accepts the native run method, validates local cwd and strips routing
  `meta.node`. Only JSON-safe execution data crosses the wire; source callbacks,
  executor options, provider credentials and BEAM state never do.
- Destination credentials/cwd are local. Relative cwd resolves from worker cwd.
  Disconnect, caller death, explicit cancel, timeout or node replacement cancels
  destination work. Steer/redirect text is bounded and invocation/session-bound;
  acknowledge only after the live native session accepts it.
- Respect payload/depth/item limits and bounded streaming accumulation. Preserve
  protocol ping/idle-timeout compatibility without another session-liveness API.
  See [CLI](../../docs/user-guide/cli.md) for launch commands.

## Verification

From the umbrella root: `mix test apps/coding_agent/test`.
Use temporary workspaces, controlled providers and supervised process cleanup.
Tests touching global extension caches/process stores/env run non-async and
restore state. Globally named test recorders must not be linked to a dying test;
use monitor-confirmed teardown rather than `whereis`/stop races.
Test user-visible output/details, policy refusal, cancellation, restart and
cross-session access. See [bootstrap](../../docs/assistant_bootstrap_contract.md)
and [parent questions](../../docs/subagent-parent-questions.md) for detailed contracts.