Skip to content

feat: execution-limit admission (#1773-#1786) - #1792

Merged
jhgaylor merged 17 commits into
mainfrom
codex/execution-limits-admission
Sep 10, 2026
Merged

jhgaylor merged 17 commits into
mainfrom
codex/execution-limits-admission

Conversation

@BinaryBourbon

Copy link
Copy Markdown
Contributor

Combines the reviewed and approved execution-limit admission stack — #1773 through #1786, minus the host-ceiling work — into one PR against main.

What this is

Execution limits (wall_time_seconds, max_model_turns, max_estimated_cost_usd) get a typed policy resolver, versioned per-conversation storage, owner-scoped write operations, and a refusal at every door that could otherwise promise a bounded execution it cannot deliver.

Nothing is enforced yet, and that is the point. Every control is refused end-to-end via require_controls(limits, []), so a saved allowance is always %{} today. The stack makes it impossible to accept a limit the runtime cannot honour, ahead of the runtime work that will honour them.

What it contains

PR Change
#1773 Fountain.Conversations.ExecutionLimits — the pure resolver: validate, inherit ceilings, narrow, refuse widening
#1774 Refuse requested limits at launch, attach and channel mutation, before any write
#1775 execution_allowances — versioned storage, opaque revision, optimistic locking
#1776 Check the saved allowance inside the turn transaction, under row locks
#1777 Refuse before wake probes a provider or starts a worker; interrupt stays reachable
#1778 Refuse before a prompt supersedes autonomous work on a live server
#1779 Same for the queued initial-prompt cast
#1780 Refuse before a channel resume replaces caller tools (native, OpenAI, AG-UI)
#1781 Close the boot-recovery bypass in Rehydrator.spawn_server/1
#1782 A saved JSON null is corrupt, not an unrestricted allowance to narrow
#1783 Conversations.narrow_execution_allowance/4 — owner-scoped, audited
#1784 Typed operator-owned account ceiling storage on users
#1785 Resolve launch requests against the current account ceiling
#1786 Conversations.create_execution_allowance/4 — owner-scoped, audited

Two new migrations: 20260909090000_create_execution_allowances, 20260910020000_add_account_execution_limits.

What it deliberately excludes

#1787 (host ceilings / FOUNTAIN_EXECUTION_LIMITS) is left out — it has changes requested for a missing .env.example entry. #1788 (the two-stack join) is made moot by this PR. #1789 through #1791 (allowance persistence at launch, rotation) also have changes requested, mostly about row locks taken inside the global fleet advisory lock.

How the merge was built

Three merges on top of the #1786 chain: #1782, then the #1784 -> #1774 -> #1785 chain, then current main.

Only one textual conflict, in fallback_controller.ex — resolved by keeping the execution_limits_widen clause, plus dropping a duplicate ExecutionLimits alias in conversations.ex. Both match the resolution CI already verified on #1788.

The result was checked structurally rather than by eye: the merged tree equals #1788's CI-verified tree minus #1787's commit plus #1782's commit, with both deltas fully accounted for and nothing else. All eight guard call sites survive the main merge intact.

#1774's commit appears once, not twice — 71ce96c8 and d4ea7e76 have identical patch-ids, and the copy on the #1785 chain is the one included.

Validation

Run locally on the merged tree, on a dedicated database:

  • mix compile --warnings-as-errors — clean
  • mix format --check-formatted at the root and in apps/fountain — clean, exit 0
  • mix credo --strict — 769 files, 6963 mods/funs, no issues
  • mix deps.unlock --unused — clean
  • Both migrations apply from empty
  • 191 tests across the ten execution-limit suites — 0 failures
  • 280 tests across the suites main's two new commits touched (conversations_start, conversations_context, changeset, conversation_controller, conversations_wake, conversation_server_acp) — 0 failures
  • The dedicated database was empty afterward, confirming the unboxed_run race fixtures clean up their committed rows

Closes #1773
Closes #1774
Closes #1775
Closes #1776
Closes #1777
Closes #1778
Closes #1779
Closes #1780
Closes #1781
Closes #1782
Closes #1783
Closes #1784
Closes #1785
Closes #1786

🤖 Generated with Claude Code

https://claude.ai/code/session_01EzUPkXKdmnZYeJ1sqjpnp9

jhgaylor and others added 17 commits September 9, 2026 01:36
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
Signed-off-by: Jake Gaylor <jhgaylor@gmail.com>
A saved JSON null is corrupt, not an unrestricted allowance to narrow.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EzUPkXKdmnZYeJ1sqjpnp9
Joins the requested-limit refusal, typed account ceiling storage and the
launch preflight that resolves a request against the current account
ceiling. Resolution keeps the execution_limits_widen error clause and
drops a duplicate ExecutionLimits alias, matching the resolution CI
already verified on #1788.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EzUPkXKdmnZYeJ1sqjpnp9
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EzUPkXKdmnZYeJ1sqjpnp9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release:skip-sdk Explicitly allows an SDK surface change without releasing a new package version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants