GPT-6.1 Sol (effort default (no reasoning-effort override) · thinking on) on Work backward from a retirement budget to a savings target, contributions and earliest retirement age
OGPT-6.1 Soldefault · thinking on · Codex CLI 0.163.0 (codex exec --json) · cloud · 2026-10-20 · by @bobsiopener
- Estimated cost
- $0.04
- Wall time
- 50s
- Human step-ins
- 0
- Outcome
- Pass
Compare with other models on this task →
Summary
Exact prompt
# Work backward from a retirement budget: savings target, contributions and earliest retirement age `input.json` describes a saver (synthetic numbers). Write `solve.py` (Python 3 standard library only) so that `python solve.py input.json answer.json` computes how much they need, how much they must save each year, and the earliest age they could retire. We re-run it on fresh inputs, so do not hard-code anything. ## Input `current_age`, `retire_age`, `end_age` (integers), `spend_today` (yearly spending in today's dollars), `inflation`, `return_pre` (yearly return before retirement, never 0), `return_post` (after), `current_savings`, `gross_income`, `actual_contribution` (what they save per year now), `part_time_income_today` (yearly part-time income in today's dollars), `part_time_years`. ## Rules 1. For a retirement age A, the first retirement year's spending is S = `spend_today * (1 + inflation) ** (A - current_age)`; spending in retirement year k (k = 0 .. end_age - A - 1) is S * (1 + inflation) ** k. 2. Part-time variant: income in retirement year k is `part_time_income_today * (1 + inflation) ** (A - current_age + k)` for k < `part_time_years`, else 0. The withdrawal is max(0, spending - income). 3. Withdrawals happen at the start of each retirement year. The **target** for age A is the sum over k of withdrawal_k / (1 + return_post) ** k (no part-time income), and **target_with_part_time** uses rule 2. 4. Saving: with m = A - current_age and g = (1 + return_pre) ** m, the projected savings at A with a level contribution C at the end of each year is `current_savings * g + C * (g - 1) / return_pre`. 5. `required_contribution` = the C that makes the projection equal the target for A = `retire_age`, but never below 0; the same with the part-time target gives `required_contribution_with_part_time`. `required_savings_rate` = required_contribution / gross_income (6 decimals). `projected_at_retire_age` = the projection with C = `actual_contribution`. 6. `earliest_retire_age` = the smallest integer A from current_age + 1 to end_age - 1 where the projection with `actual_contribution` >= the target for that A; `null` if none. `earliest_retire_age_with_part_time` does the same against the part-time target. 7. Round money to 2 decimals only when writing. ## Output `answer.json` keys: `target`, `target_with_part_time`, `required_contribution`, `required_contribution_with_part_time`, `required_savings_rate`, `projected_at_retire_age`, `earliest_retire_age`, `earliest_retire_age_with_part_time`. ## Scoring Hidden checks (partial credit = fraction passed; all must pass), money within 0.011, rate within 0.000001, ages exact: `savings_target`, `part_time_target`, `required_contributions`, `earliest_ages` on the given input; `fresh_run_1` and `fresh_run_2_edge_cases` (all keys; the second input has part-time income above spending and a small contribution) on fresh inputs. Each run has a 60-second limit.
Start-of-year withdrawals discounted at the post-retirement return, part-time income inflated from today and floored at zero withdrawals, end-of-year contribution annuity, and a per-age search where the target moves with the age. Original benchmark task written for usecaserank.com. Headless, offline run on a reproducible fixture. Cost shown is a list-price API-equivalent estimate (run on a ChatGPT subscription, not billed).
These are synthetic test cases for comparing AI models, not financial advice.
Success criteria: 1. savings_target 2. part_time_target 3. required_contributions 4. earliest_ages 5. fresh_run_1 6. fresh_run_2_edge_cases
Setup notes: Batch 9 case j04-reverse-retirement-plan (offline fixture). Prepared with batch9/prepare.sh on the shared box; only TASK.md + starting files were copied to the agent machine, hidden key/tests stayed on the box. Prompt = TASK.md verbatim on stdin. Flags: --json -s workspace-write --skip-git-repo-check --ephemeral --ignore-user-config --ignore-rules -C <workdir>. Scored on the box with the case scorer using absolute paths: `python score.py WORKDIR KEYDIR`. Single run, no retries. A global user-level AGENTS.md was present on the agent machine and may have been in context. The served model id is not echoed in the event log. Serving model not confirmed: requested via -m; the event log does not echo the serving model id. Price source is secondary (pricing.json verification='secondary', https://www.actuia.com/en/news/ai-api-pricing-in-october-2026-050-to-50-for-output/), not an official OpenAI price page. Score: 6/6. Cost is an ESTIMATE: measured tokens x pricing.json list price (ChatGPT plan, nothing billed); input_tokens include cached reads; output_tokens include reasoning tokens. Tool calls 5 (1 failed, recovered). Single run.
Estimated cost List-price estimate; not actually billed.
Metrics
- Estimated cost
- $0.04
- Wall time
- 50s
- Human step-ins
- 0
- Turns
- 1
| Model | Input tok | Output tok | Cost |
|---|---|---|---|
| OGPT-6.1 Solopenai/gpt-6.1-soleffort default (no reasoning-effort override) · thinking on | 81,802 | 1,887 | $0.04 |
Reproduce this run
- Use the use case prompt on the use case page.
- Same setup: GPT-6.1 Sol (openai/gpt-6.1-sol, effort default (no reasoning-effort override) · thinking on) via
Codex CLI 0.163.0 (codex exec --json), cloud. - It counts as a success only if it meets every success criterion: 1. savings_target 2. part_time_target 3. required_contributions 4. earliest_ages 5. fresh_run_1 6. fresh_run_2_edge_cases
- Log model, tokens, wall time, human step-ins and the evidence log, then submit it as a reproduction. A different model? Submit a head-to-head rerun.
How runs are scored: Methodology.
Was this useful?
Automated checks
Trust 80% comes from these checks (how Trust % works).
- Run date is not in the future : passed
- Model is in the dated pricing table : passed
- Cost recomputed from tokens matches : passed
- Cached tokens are consistent : passed
- Output throughput is plausible : passed
- Autonomy matches step-ins : passed
- Step-ins do not exceed turns : passed
- Retries agree with first-try result : passed
- Evidence log SHA-256 matches : passed
- Evidence log is substantial : passed
Evidence log
{"type": "thread.started", "thread_id": "01a15943-bb4b-7092-8d0d-41dcfd7118ef"}
{"type": "turn.started"}
{"type": "item.completed", "item": {"id": "item_0", "type": "agent_message", "text": "I\u2019ll inspect the input, implement the formulas in `solve.py`, and check the output against an independent calculation."}}
{"type": "item.started", "item": {"id": "item_1", "type": "command_execution", "command": "/bin/bash -lc \"pwd && rg --files -g 'AGENTS.md' -g 'input.json' -g 'solve.py' -g '*test*'\"", "aggregated_output": "", "exit_code": null, "status": "in_progress"}}
{"type": "item.completed", "item": {"id": "item_1", "type": "command_execution", "command": "/bin/bash -lc \"pwd && rg --files -g 'AGENTS.md' -g 'input.json' -g 'solve.py' -g '*test*'\"", "aggregated_output": "/home/bob/usecase-runs/batch/out/gpt-6.1-sol/j04/work\ninput.json\n", "exit_code": 0, "status": "completed"}}
{"type": "item.started", "item": {"id": "item_2", "type": "command_execution", "command": "/bin/bash -lc 'cat input.json'", "aggregated_output": "", "exit_code": null, "status": "in_progress"}}
{"type": "item.completed", "item": {"id": "item_2", "type": "command_execution", "command": "/bin/bash -lc 'cat input.json'", "aggregated_output": "{\n \"current_age\": 33,\n \"retire_age\": 56,\n \"end_age\": 95,\n \"spend_today\": 105000,\n \"inflation\": 0.0248,\n \"return_pre\": 0.0518,\n \"return_post\": 0.0433,\n \"current_savings\": 20000,\n \"gross_income\": 128000,\n \"actual_contribution\": 60000,\n \"part_time_income_today\": 38000,\n \"part_time_years\": 8\n}", "exit_code": 0, "status": "completed"}}
{"type": "item.started", "item": {"id": "item_3", "type": "file_change", "changes": [{"path": "/home/bob/usecase-runs/batch/out/gpt-6.1-sol/j04/work/solve.py", "kind": "add"}], "status": "in_progress"}}
{"type": "item.completed", "item": {"id": "item_3", "type": "file_change", "changes": [{"path": "/home/bob/usecase-runs/batch/out/gpt-6.1-sol/j04/work/solve.py", "kind": "add"}], "status": "completed"}}
{"type": "item.started", "item": {"id": "item_4", "type": "command_execution", "command": "/bin/bash -lc 'python solve.py input.json answer.json && cat answer.json'", "aggregated_output": "", "exit_code": null, "status": "in_progress"}}
{"type": "item.completed", "item": {"id": "item_4", "type": "command_execution", "command": "/bin/bash -lc 'python solve.py input.json answer.json && cat answer.json'", "aggregated_output": "/bin/bash: line 1: python: command not found\n", "exit_code": 127, "status": "failed"}}
{"type": "item.started", "item": {"id": "item_5", "type": "command_execution", "command": "/bin/bash -lc 'python3 solve.py input.json answer.json && cat answer.json'", "aggregated_output": "", "exit_code": null, "status": "in_progress"}}
{"type": "item.completed", "item": {"id": "item_5", "type": "command_execution", "command": "/bin/bash -lc 'python3 solve.py input.json answer.json && cat answer.json'", "aggregated_output": "{\n \"target\": 5225054.28,\n \"target_with_part_time\": 4723009.09,\n \"required_contribution\": 121801.85,\n \"required_contribution_with_part_time\": 109953.72,\n \"required_savings_rate\": 0.951577,\n \"projected_at_retire_age\": 2606301.4,\n \"earliest_retire_age\": 67,\n \"earliest_retire_age_with_part_time\": 65\n}\n", "exit_code": 0, "status": "completed"}}
{"type": "item.started", "item": {"id": "item_6", "type": "command_execution", "command": "/bin/bash -lc \"python3 - <<'PY'\nimport random\nfrom solve import solve\nrandom.seed(42)\nfor _ in range(200):\n d = dict(current_age=30, retire_age=random.randint(31, 79), end_age=80,\n spend_today=random.uniform(10000, 150000), inflation=random.uniform(0, .05),\n return_pre=random.uniform(.001, .1), return_post=random.uniform(0, .08),\n current_savings=random.uniform(0, 1000000), gross_income=150000,\n actual_contribution=random.choice([0, 100, 50000]),\n part_time_income_today=random.choice([0, 30000, 300000]),\n part_time_years=random.randint(0, 60))\n def ref(a):\n m = a-d['current_age']\n g = (1+d['return_pre'])**m\n factor = (g-1)/d['return_pre']\n t = p = 0\n for k in range(d['end_age']-a):\n s=d['spend_today']*(1+d['inflation'])**(m+k)\n income=d['part_time_income_today']*(1+d['inflation'])**(m+k) if k<d['part_time_years'] else 0\n t+=s/(1+d['return_post'])**k\n p+=max(0,s-income)/(1+d['return_post'])**k\n return t,p,d['current_savings']*g,factor\n t,p,b,f=ref(d['retire_age'])\n expected=dict(target=round(t,2),target_with_part_time=round(p,2),required_contribution=round(max(0,(t-b)/f),2),required_contribution_with_part_time=round(max(0,(p-b)/f),2),required_savings_rate=round(max(0,(t-b)/f)/d['gross_income'],6),projected_at_retire_age=round(b+d['actual_contribution']*f,2))\n for key,idx in [('earliest_retire_age',0),('earliest_retire_age_with_part_time',1)]:\n expected[key]=next((a for a in range(31,80) if (lambda v:v[2]+d['actual_contribution']*v[3]>=v[idx])(ref(a))),None)\n assert solve(d)==expected,(solve(d),expected)\nprint('200 randomized reference checks passed, including income above spending and small/zero contributions.')\nPY\"", "aggregated_output": "", "exit_code": null, "status": "in_progress"}}
{"type": "item.completed", "item": {"id": "item_6", "type": "command_execution", "command": "/bin/bash -lc \"python3 - <<'PY'\nimport random\nfrom solve import solve\nrandom.seed(42)\nfor _ in range(200):\n d = dict(current_age=30, retire_age=random.randint(31, 79), end_age=80,\n spend_today=random.uniform(10000, 150000), inflation=random.uniform(0, .05),\n return_pre=random.uniform(.001, .1), return_post=random.uniform(0, .08),\n current_savings=random.uniform(0, 1000000), gross_income=150000,\n actual_contribution=random.choice([0, 100, 50000]),\n part_time_income_today=random.choice([0, 30000, 300000]),\n part_time_years=random.randint(0, 60))\n def ref(a):\n m = a-d['current_age']\n g = (1+d['return_pre'])**m\n factor = (g-1)/d['return_pre']\n t = p = 0\n for k in range(d['end_age']-a):\n s=d['spend_today']*(1+d['inflation'])**(m+k)\n income=d['part_time_income_today']*(1+d['inflation'])**(m+k) if k<d['part_time_years'] else 0\n t+=s/(1+d['return_post'])**k\n p+=max(0,s-income)/(1+d['return_post'])**k\n return t,p,d['current_savings']*g,factor\n t,p,b,f=ref(d['retire_age'])\n expected=dict(target=round(t,2),target_with_part_time=round(p,2),required_contribution=round(max(0,(t-b)/f),2),required_contribution_with_part_time=round(max(0,(p-b)/f),2),required_savings_rate=round(max(0,(t-b)/f)/d['gross_income'],6),projected_at_retire_age=round(b+d['actual_contribution']*f,2))\n for key,idx in [('earliest_retire_age',0),('earliest_retire_age_with_part_time',1)]:\n expected[key]=next((a for a in range(31,80) if (lambda v:v[2]+d['actual_contribution']*v[3]>=v[idx])(ref(a))),None)\n assert solve(d)==expected,(solve(d),expected)\nprint('200 randomized reference checks passed, including income above spending and small/zero contributions.')\nPY\"", "aggregated_output": "200 randomized reference checks passed, including income above spending and small/zero contributions.\n", "exit_code": 0, "status": "completed"}}
{"type": "item.completed", "item": {"id": "item_7", "type": "agent_message", "text": "Created [solve.py](solve.py) and generated [answer.json](answer.json).\n\nVerified against 200 randomized reference cases, including part-time income above spending and small contributions.\n\nRun with:\n```bash\npython3 solve.py input.json answer.json\n```\n\nThis environment provides `python3`; `python` is unavailable."}}
{"type": "turn.completed", "usage": {"input_tokens": 81802, "cached_input_tokens": 75520, "cache_write_input_tokens": 0, "output_tokens": 1887, "reasoning_output_tokens": 73}}