Repository navigation
Make limits runaway guards (supersedes #295, with review fixes) - #297
Merged
Merged
Conversation
Repository workflows (site.health_improve, product.code_map) failed on the workspace limits, and content delivery stopped on files over the 2 MB per-file limit. Raise the runaway guards: 100,000 files (GitHub's recursive tree truncates there anyway), 250 MB snapshot, 1 GB tarball, 10 MB per file, 500 blob fallbacks; selected-file reads 100 MB / 20,000 files. The byte bounds are set by the switchboard VM (an e2-small with about 1 GB of free RAM and under 5 GB of free disk), which every run in flight shares. The verified files now wait in a temporary file instead of a dict in memory, so the switchboard only holds the finished compressed archive. The isolated sandbox's per-root entry bound rises to 400,000 so a 100,000-file snapshot plus its .git objects fits (needs a template rebuild to take effect). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
project.memory d711b841 failed with "memory sources exceed 200000 bytes". The sources go whole into one gardener call and the index into later sessions, so both stay within ~200k tokens: 700,000 bytes. Older sources that no longer fit are left out instead of failing the run. The bounded project-file read rises to match the index. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed run 75 scheduled runs were refused for no sufficient standing limit and four manual starts for the $10 monthly limit. Only projects without a policy get the new defaults; saved policies, credits and the welcome grant are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…pshot A refresh delivery downloads up to a 1 GB tarball and rebuilds a snapshot of up to 250 MB on the shared-core switchboard before it commits; 5 minutes could run out for a large repository. Activity timeouts are not part of replay history, so running workflows replay unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…signals on receipts Production caps caused failures without saving money: billing charges the tokens a call actually used, so a cap only decides when a long answer fails. - ModelRequest.max_output_tokens defaults to 32,000 (was 4,096). Every native caller sets its own cap, so no current request or fingerprint changes. - Provider clients wait 600 seconds by default (was 90), and so does TIN_LITE_LUNA_TIMEOUT, which also feeds the Responses client. Activities that wrap a default wait now outlast it: project memory, scan report and weekly brief 12 minutes, visibility audit 35, answer page 25, character design 45, organic panel preparation 85, observation 25, brand checks 35, and keyword collection 60. Timeout values are not part of replayed commands. - An empty response at its cap, or one the provider says stopped there (Anthropic max_tokens, Gemini MAX_TOKENS, OpenRouter length), is output_truncated rather than invalid_result when its structured answer is empty or unparseable. Plain text at the cap is still returned. - native_model_usage_v1 and model external_usage_v1 receipts add max_output_tokens, stop_reason and output_truncated. The fields are additive; pricing reads none of them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v7 is deployed, so it stays as it is. In runs a59cded8 and de1a4d3e the screening call stopped at exactly 5,000 output tokens after 3.5-4.2k tokens of reasoning, and v7's 8,000/16,000 caps are sized like answer lengths rather than runaway guards. New definitions pin keyword-plan-v8 (catalog organic.keyword_plan 0.8.0): v7 with only the screening caps and their reservations changed. Batches stay at 50; reasoning effort stays the model's choice. - First attempts get 32,000 output tokens and the one retry 64,000, half of GPT-6 Luna's 128,000. - An 80,000-byte request is 84,096 input tokens to the recorder (standard band), so the largest first attempt costs $0.0265 and reserves $0.03, and the largest retry $0.0425 and reserves $0.045. Six batches and six retries reserve $0.45, and a full run at most $2.00: seeds $0.10, review $0.15, screening $0.45, 22 lookups $1.10, 40 samples $0.20. The $2 floor covers it exactly, so the floor, the catalog default and the organic system's keyword limit are unchanged. - Seeds and review keep their caps; raising either would pass the floor. - Screening waits up to 600 seconds per call (was 240) for every policy; waiting never changes a request. - v2-v7 stay registered and send exactly what they did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ning A cap only decides when a long answer fails; billing charges the tokens a step used. Runs pinned before keep their caps. - content.plan 0.9.0 pins content-editorial-v8: v7 with 32,000 output tokens (was 16,000). At its bounds a plan costs at most $0.088, still under the $0.10 its $1 share in the organic system is sized from. Definitions pinned to v7 resolve to v7. - style.capture 1.3.0 (policy 2, was 6,000), social.x_style 1.2.0 (policy 3, was 6,000) and social.x_revise 1.2.0 (x-feedback-v2, was 8,000). Style capture and X revisions now accept every policy version they shipped and send the pinned cap; contexts saved before keep 6,000. x_style's policy 1 no longer follows style capture's current cap. - growth.onboarding_plan steps all use 32,000 (were 6,000-16,000); the plan's contract digest changes, as with any change to its module. - creative.character (was 24,000; four Sol calls at every bound cost about $1.73 of its $2 ceiling) and the site-health fix (was 16,000), which pin no cap. - Skipped: the organic audit (its $2 ceiling is computed from 6,000-token calls), paid ads (Sol reservations sized from their caps), keyword seeds and review (would pass the $2 floor) and code workflows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Production runs kept hitting conservative code-workflow limits (#273's model wait, the 64 KB read cap worked around in #89, #239, #261, #270). Limits are now set well above real use, while model context stays bounded per run. - timeout_seconds max 60 -> 900 (still the package window and each model call's wait; the provider now waits as long instead of its 90 s default); execute_code_workflow start_to_close 4 -> 20 min, heartbeats unchanged. - Model routes: 8 -> 32 calls per run, 4 -> 16 per route, max_input_bytes 32,000 -> 256,000, max_output_tokens 4,096 -> 32,000; response 64,000 -> 1,000,000 bytes. - New run-level budget: at most 700,000 model input bytes (~200k tokens) across a run's calls, counted from each call's receipt so retries cannot resend it; a call past it fails with model_input_budget. - Run maximum: input priced at 3 bytes/token within the shared 700,000-byte budget, filled at the most expensive route first, plus each call's 4,096-token envelope and full output. Per-call reservations use the same rate, so every admissible call sequence fits the pinned maximum. Admitted runs keep the terms pinned in their budget. - File reads and output artifact 64,000 -> 1,000,000 bytes; file calls 64 -> 256, bridge calls 32 -> 128; bridge message 128 KB -> 4 MB and result envelope sized for a 1 MB artifact. - Service bindings: max_calls 8 -> 32 (per binding and total), responses 64,000 -> 1,000,000 bytes; gateway wait 25 -> 60 s, Google 22 -> 55 s, custom API 20 -> 55 s. - Authoring guide, creator contract and docs state the new bounds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er sandboxes New Codex admissions pin tin-codex-api-v5: v4's 128,000-token output and 8 MiB requests with a 256,000-token context that compacts from 200,000. Session-funded procedures keep no request/token stop; included, child, Studio, diagram, design and task work pin the same shape with 256-request and 8M-token runaway stops and a $1.93 per-request reservation. Funding is unchanged: Start here work stays included and Tin-funded. The default root Codex ceiling is $10 (children inside a parent budget keep $5). Runs and still-valid quotes from before v5 keep v1-v4 and $5. Procedure sandboxes may declare up to 7,200 s; design/task sandboxes default to 1,800 s; compute activities allow 3 h (6 h with retries); proxy grants cover the longest sandbox. Relay rejections (413 context bound, 422 contract, request/token limits, upstream errors) are stored on the attempt receipt as relay_rejection and named in the run's failure message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # docs/code-project-files.md # src/tin_lite/code_storage.py
# Conflicts: # src/tin_lite/catalog.py # tests/test_keyword_plan_v6.py # tests/test_keyword_plan_v7.py
# Conflicts: # docs/workflow-billing-coverage.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A run whose model calls pass 700,000 input bytes still sends the call; Tin logs one warning for the run with its ID, workflow, step and byte counts. The run maximum reserves every declared call at its full max_input_bytes (three bytes per token), since the bound no longer refuses anything. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # src/tin_lite/private_workflows.py
A session's admission estimate is its whole ceiling, so the new $10 default refused every Codex procedure in projects still on the $10/$10 hosted defaults once anything was spent that month, and in $10 welcome wallets after the first charge. A root run's default ceiling is now $10 when available credits, the per-run limit and the month's remainder all cover it, and the earlier $5 otherwise, so nothing is refused that was admitted before. The preview and admission share the room (run_room, month_usage); a quote keeps the ceiling it showed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
OpenAI can end a response as failed inside a 200 stream; the relay recorded nothing, so the run said only that Codex failed (on 2026-10-01 three sessions ended "Codex usage limit reached" this way). The relay now records rate_limited for OpenAI's rate limit and upstream_failed otherwise, by code only, and the run's failure message names them in plain words. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
At #295's limits a snapshot can download a 1 GB tarball and build a 250 MB archive, on a switchboard with about 2 GB of RAM and 4.7 GB of free disk shared by eight concurrent activities. The gateway now builds two at a time, and the finished archive stays in its temporary file: it streams to the sandbox and readers open it from the start, instead of a copy held in memory for the whole run. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…eft out newest_sources skipped a source that didn't fit and kept looking, so an older source could be kept while a newer one was dropped, and memory_gardened counted every source fetched. Keeping now stops at the first source that doesn't fit (one larger than the whole budget is skipped), and the activity records the kept and dropped counts and the kept run IDs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…token caps need Their caps rose to 32,000 tokens, but the provider wait stayed at 165 seconds inside a 180-second step budget and a five-minute Temporal step, so a long answer timed out before reaching the cap. Each now waits the provider's 600-second default with a 15-second step margin, and the Temporal step that makes the call gets 15 minutes. Activity options are not workflow commands, so histories replay unchanged. The forward proxy doc now states the 7,260-second grant maximum and the proxy host reinstall it needs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #295: demegire's commits unchanged, merged with main (one conflict, the authoring guide's bindings text in
private_workflows.pyagainst #296: both kept), plus the review fixes below.Before → after
max_output_tokensTIN_LITE_LUNA_TIMEOUT)timeout_secondsmax / activityReplaces the approach of #274. Limits become runaway guards set well above what production runs use, instead of estimates that stop ordinary runs. Model context stays bounded: no single call over about 200k tokens, and no code-workflow run over about 200k tokens of model input.
Why
Over the last 30 days in production:
Actual spend is far below the ceilings: audit at most $0.90, keyword plan at most $0.50, Codex p90 at most $2.30 except the code map. Billing charges verified usage, so the higher limits change worst-case reservations, not what a normal run costs.
Context sizes use the o200k tokenizer: 4.4–4.7 bytes per token on prose, code and JSON, about 3.5 on real workflow evidence. So 256 KB is about 70k tokens and 700 KB about 200k.
What changes
Model output and time
max_output_tokensgoes from 4,096 to 32,000, and the default provider wait from 90 s to 600 s (TIN_LITE_LUNA_TIMEOUTtoo).content-editorial-v8), style capture, X style, X revise and growth plan steps. Character design and site health use module constants, not pinned definitions, so their caps change without a version bump; billing stays within each run's pinned $2 ceiling.max_output_tokens, the provider's stop reason andoutput_truncated. An empty answer at its cap is labelledoutput_truncatedinstead ofinvalid_result.Code workflows
timeout_secondsmaximum 60 → 900 s; the activity's timeout goes from 4 to 20 minutes.stale_quoteonce.Codex
relay_rejection:context_bound,request_limit,token_limitand so on. The run's failure message names it.Sizes and billing
Deploy notes (not done in this PR)
sandbox/codex_api_config.py, and the runtime refuses a v5 procedure unless the image answers--check-v5. Tasks have no such check and fail on an old image before any model call.bounded_contextscenario for checking a rebuilt image.proxy_grants.py. Reinstall it before any procedure declares more than 3,600 s; none does today./etc/tin-lite/runtime.envsetsTIN_LITE_LUNA_TIMEOUT, it overrides the new 600 s default.Follow-ups
Tests
ruff format --check,ruff check,lint-imports,dump_catalog.py --checkandvalidate-community(32/32) pass.Review fixes (on top of #295)
default_maximum(room)gives $10 when the room covers $10, otherwise the earlier $5. The room is the smallest of available credits, the per-run limit and the month's remainder.quote) and admission compute the room the same way, so the preview shows what admission pins. A quote keeps its own ceiling.IntegrationServicesemaphore around download, blob fallbacks and archive build).files.writewith a file object) instead of being read into memory.technical_build_profile.archive_filescan still hold up to 100 MB briefly, as before (capped byARCHIVE_MAX_BYTES).newest_sourcesstops at the first source that doesn't fit, so an older source is never kept while a newer one is dropped. A single source larger than the whole budget is skipped.memory_gardenedrecordssource_count(kept) anddropped_source_count.MODEL_STEP_TIMEOUTapplies only tostyle_extract,x_style_extractandx_feedback_generate.failedresponse status remained. A streamed response that endsfailednow recordsrelay_rejectionasrate_limited(OpenAI'srate_limit_exceeded) orupstream_failed. The run says "OpenAI rate-limited this run's model calls." or "OpenAI failed one of this run's model requests." Only those codes are stored.incompleteisn't recorded, since Codex often recovers from it.docs/forward-proxy-security.mdnow says grants last 7,260 s (3,660 before Oct 2), with the proxy host reinstall.Left as is:
Deploy order (required)
tin-lite-codex-isolated,tin-lite-codex-browser-apiandtin-lite-codex-studio-apifrom the merged main:uv run python sandbox/template.py --only <alias>.no_changeoutcome no longer needs a PR title.proxy_grants.pyon the proxy host before any procedure declares more than 3,600 s. None does today./etc/tin-lite/runtime.envdoesn't pinTIN_LITE_LUNA_TIMEOUT.Verification (this branch)
localtimetests fail.lint-imports,dump_catalog.py --checkandvalidate-community(32/32) are clean.🤖 Generated with Claude Code