Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,19 @@ Fields:
- Default: empty map.
- State keys are normalized (`lowercase`) for lookup.
- Invalid entries (non-positive or non-numeric) are ignored.
- `budget` (object)
- Default: disabled.
- `enabled` (boolean): when false, dispatch behavior is unchanged.
- `per_day_max_usd` (number or null): maximum estimated USD spend across completed sessions for
the current UTC day. `null` disables the daily cap.
- `per_issue_max_usd` (number or null): maximum estimated USD spend for a single issue across
completed sessions. `null` disables the per-issue cap.
- `refusal_cooldown_seconds` (non-negative integer): how long to suppress repeated dispatch
attempts and duplicate refusal comments for the same issue.
- `pricing_path` (string): YAML model pricing table path. Missing model rows SHOULD be logged and
treated as zero estimated dispatch cost.
- Budget checks run before dispatch. Refusal MUST leave the issue in its current tracker state and
MUST NOT claim the issue or launch a worker.

#### 5.3.6 `codex` (object)

Expand Down
23 changes: 23 additions & 0 deletions elixir/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,26 @@ agent:
`agent.lessons.recall_n` entries to the Codex prompt under `## Lessons from prior runs`.
Symphony does not auto-commit this file; maintainers decide whether to keep, edit, prune, or
commit `.symphony/lessons.md`.
- `agent.budget` adds an optional pre-dispatch USD budget gate. It is disabled by default. When
enabled, Symphony estimates the next dispatch from the rolling p50 completed session token usage
for the issue repo and model, prices that estimate with `priv/pricing/models.yaml`, and refuses to
dispatch if the projected spend would exceed either configured cap:

```yaml
agent:
budget:
enabled: false
per_day_max_usd: 50.0
per_issue_max_usd: 5.0
refusal_cooldown_seconds: 3600
pricing_path: "priv/pricing/models.yaml"
```

Set `per_day_max_usd` or `per_issue_max_usd` to `null` to disable that cap while keeping the other
cap active. A refusal leaves the issue in its current tracker state, posts one tracker comment for
that cooldown window, and reconsiders the issue after `refusal_cooldown_seconds`. Missing pricing
rows are logged and treated as zero estimated cost, so an unknown model does not block dispatch.

- If the Markdown body is blank, Symphony uses a default prompt template that includes the issue
identifier, title, and body.
- Use `hooks.after_create` to bootstrap a fresh workspace. For a Git-backed repo, you can run
Expand Down Expand Up @@ -593,6 +613,9 @@ The dashboard and `/api/v1/state` include durable statistics from `stats.db`:
across Symphony restarts.
- `recent_sessions` lists the last 20 completed Codex sessions with issue, token, runtime, turn,
final state, and model fields.
- The budget tile shows today's estimated USD spend against the configured daily cap and a seven-day
spend sparkline. Issue rows get a small `$` marker when their historical spend reaches 80% of the
configured per-issue cap.

## Project Layout

Expand Down
6 changes: 6 additions & 0 deletions elixir/WORKFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ agent:
max_entries: 50
recall_n: 10
postmortem_max_tokens: 1024
budget:
enabled: false
per_day_max_usd: 50.0
per_issue_max_usd: 5.0
refusal_cooldown_seconds: 3600
pricing_path: "priv/pricing/models.yaml"
codex:
command: codex --config shell_environment_policy.inherit=all --config 'model="gpt-5.5"' --config model_reasoning_effort=xhigh app-server
approval_policy: never
Expand Down
Loading
Loading