Sync from GitHub c4e4dad
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +1 -0
- .gitignore +8 -0
- Dockerfile +20 -0
- README.md +161 -5
- __init__.py +10 -0
- blog.md +78 -0
- client.py +9 -0
- cobol_oracles/invoice/Dockerfile +13 -0
- cobol_oracles/invoice/INVOICE_ORACLE.cbl +85 -0
- cobol_oracles/invoice/INVOICE_REC.cpy +7 -0
- cobol_oracles/invoice/TAXRATE.cbl +17 -0
- cobol_oracles/invoice/TAX_CODE.cpy +4 -0
- eval/__init__.py +2 -0
- eval/cobol_oracle.py +160 -0
- eval/evidence_report.py +197 -0
- eval/inspect_rollout.py +114 -0
- eval/model_rollout.py +460 -0
- eval/oracle_solutions.py +161 -0
- eval/providers.py +332 -0
- eval/run_baselines.py +127 -0
- eval/run_cobol_oracle_checks.py +56 -0
- eval/run_evidence_report.py +106 -0
- eval/run_model_rollouts.py +68 -0
- eval/run_oracles.py +46 -0
- eval/trajectory.py +76 -0
- inference.py +252 -0
- models.py +77 -0
- openenv.yaml +7 -0
- outputs/evals/base_qwen3_14b_all_tasks.json +0 -0
- outputs/evals/baseline_results.json +205 -0
- outputs/evals/cobol_invoice_oracle_check.json +123 -0
- outputs/evals/historical/azure_gpt54mini_payroll_probe.json +301 -0
- outputs/evals/historical/azure_gpt54mini_repair1_rollouts.json +0 -0
- outputs/evals/historical/azure_gpt54mini_zeroshot_rollouts.json +1595 -0
- outputs/evals/oracle_model_rollouts.json +1448 -0
- outputs/evals/oracle_trajectories.json +1399 -0
- outputs/evals/score_summary.json +131 -0
- outputs/training/hf_job_qwen3_14b_logs.txt +797 -0
- outputs/training/oracle_sft.jsonl +0 -0
- outputs/training/qwen3_14b_training_evidence_summary.json +16 -0
- outputs/training/sft_loss.csv +21 -0
- outputs/training/sft_run_metadata.json +32 -0
- plots/baseline_scores.svg +40 -0
- plots/model_scores.svg +27 -0
- plots/qwen3_14b_accepted_before_after.png +0 -0
- plots/qwen3_14b_loss_curve.png +0 -0
- plots/qwen3_14b_reward_before_after.png +0 -0
- plots/qwen3_14b_training_reward_evidence_dashboard.png +3 -0
- pyproject.toml +34 -0
- server/Dockerfile +80 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
plots/qwen3_14b_training_reward_evidence_dashboard.png filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__/
|
| 2 |
+
*.py[cod]
|
| 3 |
+
.pytest_cache/
|
| 4 |
+
.mypy_cache/
|
| 5 |
+
.ruff_cache/
|
| 6 |
+
.venv/
|
| 7 |
+
*.egg-info/
|
| 8 |
+
.DS_Store
|
Dockerfile
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.12-slim
|
| 2 |
+
|
| 3 |
+
ENV PYTHONDONTWRITEBYTECODE=1
|
| 4 |
+
ENV PYTHONUNBUFFERED=1
|
| 5 |
+
ENV PYTHONPATH=/app
|
| 6 |
+
ENV ENABLE_WEB_INTERFACE=true
|
| 7 |
+
|
| 8 |
+
WORKDIR /app
|
| 9 |
+
|
| 10 |
+
COPY server/requirements.txt /tmp/server-requirements.txt
|
| 11 |
+
RUN pip install --no-cache-dir -r /tmp/server-requirements.txt "openai>=1.0" "huggingface_hub>=1.0"
|
| 12 |
+
|
| 13 |
+
COPY . ./legacy_cobol_env
|
| 14 |
+
|
| 15 |
+
EXPOSE 8000
|
| 16 |
+
|
| 17 |
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
| 18 |
+
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2)"
|
| 19 |
+
|
| 20 |
+
CMD ["python", "-m", "uvicorn", "legacy_cobol_env.server.app:app", "--host", "0.0.0.0", "--port", "8000"]
|
README.md
CHANGED
|
@@ -1,10 +1,166 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: docker
|
| 7 |
pinned: false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Legacy COBOL Migration Workbench
|
| 3 |
+
emoji: 🧾
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
sdk: docker
|
| 7 |
pinned: false
|
| 8 |
+
app_port: 8000
|
| 9 |
+
base_path: /web
|
| 10 |
+
tags:
|
| 11 |
+
- openenv
|
| 12 |
+
- cobol
|
| 13 |
+
- reinforcement-learning
|
| 14 |
---
|
| 15 |
|
| 16 |
+
# Legacy COBOL Migration Workbench
|
| 17 |
+
|
| 18 |
+
Legacy COBOL Migration Workbench is an OpenEnv environment for training an LLM to act like a legacy modernization engineer. The agent receives a migration ticket, inspects COBOL programs and copybooks through tools, writes Python, runs visible tests, studies structured diffs, repairs its draft, and submits code scored on hidden and fresh tests.
|
| 19 |
+
|
| 20 |
+
The target capability is not one-shot translation. Real modernization depends on fixed-width records, copybooks, implied decimals, `OCCURS` tables, level-88 condition names, branch precedence, and exact output formatting. This environment turns that workflow into a partially observable, tool-mediated training loop.
|
| 21 |
+
|
| 22 |
+
## Submission Materials
|
| 23 |
+
|
| 24 |
+
- Mini-blog: [`blog.md`](blog.md)
|
| 25 |
+
- Hugging Face Space: <https://huggingface.co/spaces/Ishangtxl/mainframe-modernization-openenv>
|
| 26 |
+
- Training evidence: [`outputs/training/sft_run_metadata.json`](outputs/training/sft_run_metadata.json)
|
| 27 |
+
- Training log: [`outputs/training/hf_job_qwen3_14b_logs.txt`](outputs/training/hf_job_qwen3_14b_logs.txt)
|
| 28 |
+
- Score summary: [`outputs/evals/score_summary.json`](outputs/evals/score_summary.json)
|
| 29 |
+
|
| 30 |
+
## Environment
|
| 31 |
+
|
| 32 |
+
Each episode starts with a partial ticket. The agent can discover details through MCP tools:
|
| 33 |
+
|
| 34 |
+
- `read_cobol_file`
|
| 35 |
+
- `read_copybook`
|
| 36 |
+
- `parse_copybook_layout`
|
| 37 |
+
- `inspect_business_rules`
|
| 38 |
+
- `write_python_solution`
|
| 39 |
+
- `run_visible_tests`
|
| 40 |
+
- `inspect_diff`
|
| 41 |
+
- `submit_final`
|
| 42 |
+
|
| 43 |
+
The submitted Python code must define:
|
| 44 |
+
|
| 45 |
+
```python
|
| 46 |
+
def migrate(input_record: str) -> str:
|
| 47 |
+
...
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
Episodes are capped at 24 tool steps. Visible tests are available for debugging, but hidden and fresh cases are withheld until final scoring.
|
| 51 |
+
|
| 52 |
+
## Reward
|
| 53 |
+
|
| 54 |
+
```text
|
| 55 |
+
final_reward =
|
| 56 |
+
0.55 * hidden_correctness
|
| 57 |
+
+ 0.15 * fresh_correctness
|
| 58 |
+
+ 0.10 * interface_contract
|
| 59 |
+
+ 0.08 * type_and_layout_fidelity
|
| 60 |
+
+ 0.07 * anti_hardcoding
|
| 61 |
+
+ 0.05 * safety
|
| 62 |
+
```
|
| 63 |
+
|
| 64 |
+
The reward is correctness-heavy, but it also penalizes unsafe code, broken interfaces, layout drift, and visible-case hardcoding.
|
| 65 |
+
|
| 66 |
+
## Task Families
|
| 67 |
+
|
| 68 |
+
| Task | Difficulty | COBOL concepts | Main failure modes |
|
| 69 |
+
| --- | --- | --- | --- |
|
| 70 |
+
| `fixed_width_customer` | easy | `PIC X`, padding/truncation, status mapping | trimmed spaces, lost ZIP leading zeros, bad output width |
|
| 71 |
+
| `decimal_copybook_payroll` | medium | copybook layout, implied decimals, level-88 bonus flag | float drift, wrong rounding, wrong fixed-width net pay |
|
| 72 |
+
| `claims_eligibility_branching` | medium | `EVALUATE TRUE`, branch precedence | wrong first-match branch, boundary mistakes |
|
| 73 |
+
| `account_status_level88` | medium | level-88 status conditions, signed amount | treating condition names as variables, wrong precedence |
|
| 74 |
+
| `date_normalization` | medium | legacy YYMMDD windowing, validation | wrong century window, over-rejecting legacy dates |
|
| 75 |
+
| `invoice_occurs_totals` | hard | multi-file `INVTOTAL.cbl`/`TAXRATE.cbl`, `OCCURS`, copybook tax-code metadata | wrong stride, ignoring tax-code lookup, overfitting visible invoice IDs |
|
| 76 |
+
|
| 77 |
+
`inspect_business_rules` exposes agent-facing hints only. Exact reference behavior stays internal to hidden and fresh tests.
|
| 78 |
+
|
| 79 |
+
## Results
|
| 80 |
+
|
| 81 |
+
The current training run uses Hugging Face TRL LoRA SFT on `Qwen/Qwen3-14B` with 15 oracle and repair examples. Evaluation uses the same OpenEnv rollout harness before and after training.
|
| 82 |
+
|
| 83 |
+
| Policy | Role | Mean public score | Accepted tasks |
|
| 84 |
+
| --- | --- | ---: | ---: |
|
| 85 |
+
| deterministic identity | deterministic baseline | 0.1500 | 0 / 6 |
|
| 86 |
+
| deterministic blank width | deterministic baseline | 0.1767 | 0 / 6 |
|
| 87 |
+
| base `Qwen/Qwen3-14B` | model before SFT | 0.5320 | 2 / 6 |
|
| 88 |
+
| trained `Qwen/Qwen3-14B` LoRA SFT | model after SFT | 0.7971 | 4 / 6 |
|
| 89 |
+
| `oracle-model` | sanity check with reference solutions | 1.0000 | 6 / 6 |
|
| 90 |
+
|
| 91 |
+

|
| 92 |
+
|
| 93 |
+
This dashboard summarizes the before/after reward evidence for the Qwen3-14B LoRA SFT run.
|
| 94 |
+
|
| 95 |
+

|
| 96 |
+
|
| 97 |
+
The SFT run reduced loss from `1.1350` to `0.1924` and improved mean token accuracy from `0.7938` to `0.9483`.
|
| 98 |
+
|
| 99 |
+

|
| 100 |
+
|
| 101 |
+
The trained checkpoint improved mean public reward from `0.5320` to `0.7971`.
|
| 102 |
+
|
| 103 |
+

|
| 104 |
+
|
| 105 |
+
Accepted tasks improved from `2 / 6` to `4 / 6`.
|
| 106 |
+
|
| 107 |
+
## Training Artifacts
|
| 108 |
+
|
| 109 |
+
Kept in the submission root:
|
| 110 |
+
|
| 111 |
+
- `outputs/training/sft_run_metadata.json`: completed-run metadata for the Qwen3-14B LoRA SFT run
|
| 112 |
+
- `outputs/training/sft_loss.csv`: real training loss and token-accuracy history
|
| 113 |
+
- `outputs/training/qwen3_14b_training_evidence_summary.json`: compact extracted training/eval summary
|
| 114 |
+
- `outputs/training/hf_job_qwen3_14b_logs.txt`: raw HF Jobs log for provenance
|
| 115 |
+
- `outputs/evals/base_qwen3_14b_all_tasks.json`: before-training rollout
|
| 116 |
+
- `outputs/evals/score_summary.json`: judge-facing summary with deterministic, base-model, trained-model, and oracle rows
|
| 117 |
+
- `plots/qwen3_14b_training_reward_evidence_dashboard.png`
|
| 118 |
+
- `plots/qwen3_14b_loss_curve.png`
|
| 119 |
+
- `plots/qwen3_14b_reward_before_after.png`
|
| 120 |
+
- `plots/qwen3_14b_accepted_before_after.png`
|
| 121 |
+
|
| 122 |
+
The old dry-run `sft_loss.svg` scaffold is intentionally not included as judge-facing training evidence.
|
| 123 |
+
|
| 124 |
+
## Historical Artifacts
|
| 125 |
+
|
| 126 |
+
Older Azure `gpt-5.4-mini` rollouts are archived under `outputs/evals/historical/`. They were produced before the invoice task was hardened into a multi-file tax-code task, so they are preserved for context but excluded from the current score summary.
|
| 127 |
+
|
| 128 |
+
## Run Locally
|
| 129 |
+
|
| 130 |
+
```bash
|
| 131 |
+
python -m venv .venv
|
| 132 |
+
.venv/bin/pip install -e ".[dev]"
|
| 133 |
+
PYTHONDONTWRITEBYTECODE=1 PYTHONPATH=. .venv/bin/pytest tests -q -p no:cacheprovider
|
| 134 |
+
```
|
| 135 |
+
|
| 136 |
+
Run the server:
|
| 137 |
+
|
| 138 |
+
```bash
|
| 139 |
+
PYTHONPATH=. .venv/bin/python -m uvicorn legacy_cobol_env.server.app:app --host 127.0.0.1 --port 8000
|
| 140 |
+
curl -sS http://127.0.0.1:8000/health
|
| 141 |
+
curl -sS http://127.0.0.1:8000/schema
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
Validate the OpenEnv package:
|
| 145 |
+
|
| 146 |
+
```bash
|
| 147 |
+
.venv/bin/openenv validate --verbose
|
| 148 |
+
```
|
| 149 |
+
|
| 150 |
+
Regenerate the score summary:
|
| 151 |
+
|
| 152 |
+
```bash
|
| 153 |
+
.venv/bin/python -m legacy_cobol_env.eval.run_evidence_report
|
| 154 |
+
```
|
| 155 |
+
|
| 156 |
+
Run the root inference script:
|
| 157 |
+
|
| 158 |
+
```bash
|
| 159 |
+
API_BASE_URL="https://..." MODEL_NAME="..." HF_TOKEN="..." .venv/bin/python inference.py --max-repairs 1
|
| 160 |
+
```
|
| 161 |
+
|
| 162 |
+
The inference script emits `[START]`, one `[STEP]` per task, and `[END]`.
|
| 163 |
+
|
| 164 |
+
## Safety Note
|
| 165 |
+
|
| 166 |
+
Candidate code is checked for common unsafe imports and builtins, executed in a temporary subprocess with cleared environment variables, and bounded by a timeout. This is layered mitigation for a hackathon environment, not a complete secure sandbox.
|
__init__.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Legacy COBOL Migration Workbench."""
|
| 2 |
+
|
| 3 |
+
try:
|
| 4 |
+
from .client import LegacyCobolEnv
|
| 5 |
+
from .models import LegacyCobolState
|
| 6 |
+
except ImportError:
|
| 7 |
+
from client import LegacyCobolEnv
|
| 8 |
+
from models import LegacyCobolState
|
| 9 |
+
|
| 10 |
+
__all__ = ["LegacyCobolEnv", "LegacyCobolState"]
|
blog.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Replacing Ourselves at the Job
|
| 2 |
+
|
| 3 |
+
Hi. We're QuietLab.
|
| 4 |
+
|
| 5 |
+
We're Ishan and Niranjan, and on most Mondays we put on our IBM badges and go work on mainframe modernization at IBM. Specifically: on the tooling that helps engineers move COBOL code off the mainframe, with an AI assistant that suggests the modernized version.
|
| 6 |
+
|
| 7 |
+
So when this hackathon was announced, picking the topic took about thirty seconds.
|
| 8 |
+
|
| 9 |
+
## A two-paragraph mainframe primer
|
| 10 |
+
|
| 11 |
+
Mainframes are big computers from an earlier era of computing. IBM mostly. They're physically huge, eye-wateringly expensive, and absurdly reliable. They don't go down, they don't really break, and they process transactions at a scale the cloud still finds embarrassing. About 95% of US ATM transactions touch one. Roughly $3 trillion in daily commerce flows across them. By IBM's count, ~70% of global business transactions still pass through a mainframe somewhere in the pipeline.
|
| 12 |
+
|
| 13 |
+
These machines mostly run code written in COBOL, a language designed in 1959. Despite "COBOL is dying" being declared once a decade for the last fifty years, there are around **220 billion lines of it in active production today**. Banks, insurance companies, governments, airlines, payroll, tax systems. The plumbing of the world.
|
| 14 |
+
|
| 15 |
+
## The not-so-fun part
|
| 16 |
+
|
| 17 |
+
The engineers who wrote this stuff are retiring. The average COBOL developer is now 55. About 10% of that workforce hits retirement every year. Universities stopped teaching the language somewhere around 1995. The result is a quiet but compounding crisis: the code that runs the world is being maintained by a shrinking group of people who are increasingly tired and would frankly like to be golfing.
|
| 18 |
+
|
| 19 |
+
So companies are paying enormous amounts of money to migrate off it. The mainframe modernization market is roughly **$8.4B in 2025**, projected to hit **$13.3B by 2030**, and that's the narrow slice. The broader application modernization market is on track for **$100B+ by 2035**. Replacing a single working COBOL system routinely costs upward of $50 million. AWS, IBM, Capgemini, Accenture, TCS: every major consulting firm has a dedicated practice for it. Most of the migrations target Java or Python.
|
| 20 |
+
|
| 21 |
+
There's a temptation to think AI just solves this. In February 2026, Anthropic published a blog suggesting Claude could "rapidly refactor" COBOL codebases. IBM's stock dropped 13% in a single day, its worst crash since 2000, and Wall Street briefly believed the mainframe business was dead.
|
| 22 |
+
|
| 23 |
+
Then everyone calmed down, because IBM SVP Rob Thomas pointed out the obvious: **translation isn't modernization.** Real legacy code lives inside fixed-width records, copybooks, implied decimals, level-88 condition names, branch precedence, weird date semantics, and small formatting details that have to be preserved exactly or your entire payroll system silently breaks at midnight. A model that one-shots COBOL into Python is a toy. A model that actually does the *work* of a modernization engineer is the unsolved problem.
|
| 24 |
+
|
| 25 |
+
## The pitch
|
| 26 |
+
|
| 27 |
+
We don't love the job.
|
| 28 |
+
|
| 29 |
+
So, like any reasonable software engineers, we tried to build a thing that might one day replace us at it.
|
| 30 |
+
|
| 31 |
+
## What we built
|
| 32 |
+
|
| 33 |
+
**Legacy COBOL Migration Workbench**: an OpenEnv environment where a small LLM is trained, via reinforcement learning, to behave less like a translator and more like a careful modernization engineer.
|
| 34 |
+
|
| 35 |
+
Each episode is one migration ticket. The agent receives a high-level request and a list of available files, and that's it. From there it has tools:
|
| 36 |
+
|
| 37 |
+
- `read_cobol_file`: read a COBOL source file
|
| 38 |
+
- `read_copybook`: read a referenced copybook
|
| 39 |
+
- `parse_copybook_layout`: extract field offsets, lengths, scales, condition names
|
| 40 |
+
- `inspect_business_rules`: surface hints about branch precedence and edge cases
|
| 41 |
+
- `write_python_solution`: draft a Python implementation
|
| 42 |
+
- `run_visible_tests`: try the draft against a few sample cases
|
| 43 |
+
- `inspect_diff`: see exactly where output disagrees with expected
|
| 44 |
+
- `submit_final`: end the episode
|
| 45 |
+
|
| 46 |
+
The required output is a Python `migrate(input_record: str) -> str` that preserves the fixed-width record contract exactly.
|
| 47 |
+
|
| 48 |
+
The catch, and the whole point, is that we grade on **hidden tests** the agent never sees, plus **freshly generated tests** at scoring time. So the model can't win by memorizing the visible cases. It actually has to understand the legacy behaviour.
|
| 49 |
+
|
| 50 |
+
The reward is multi-component on purpose: hidden correctness, fresh correctness, interface contract, type and layout fidelity, an explicit anti-hardcoding signal, and sandbox safety. We learned the hard way during dry runs that any single reward gets gamed. Six independent signals are much harder to fool.
|
| 51 |
+
|
| 52 |
+
The task bank covers six families pulled from problems we've actually seen at work: customer records with fixed-width string fields, payroll with copybooks and signed deductions, claims eligibility with `EVALUATE TRUE` branching, account status driven by level-88 condition names, multi-file invoices with `OCCURS` groups and an external tax-rate program, and date normalization with the two-digit-year windowing rules COBOL is famous for.
|
| 53 |
+
|
| 54 |
+
The environment is hosted on Hugging Face Spaces. Training is GRPO via TRL, with Unsloth handling the efficient inference. The whole thing speaks the standard OpenEnv `reset` / `step` / `state` interface.
|
| 55 |
+
|
| 56 |
+
## The point of the demo
|
| 57 |
+
|
| 58 |
+
If the trained agent just produces more Python, we've failed. The point isn't volume. It's *behaviour*. What we want to show is a trained model doing the things a junior modernization engineer does:
|
| 59 |
+
|
| 60 |
+
inspect before acting, read the copybook before guessing field offsets, run tests before submitting, read the diff when something fails, and then fix the actual mistake instead of writing more code on top of it.
|
| 61 |
+
|
| 62 |
+
That's the kind of skill an environment can teach that a static dataset can't.
|
| 63 |
+
|
| 64 |
+
## What's next
|
| 65 |
+
|
| 66 |
+
We didn't get to **Java** in 48 hours, and that's the obvious next target. Most real enterprise mainframe modernization goes COBOL → Java, not COBOL → Python. Same environment shape, different code generator. The reward design transfers cleanly because it's all behavioural, not language-specific.
|
| 67 |
+
|
| 68 |
+
After that: **JCL → shell/Python** for batch jobs, multi-program CICS-style transaction flows, and eventually wiring the workbench into an actual Zowe CLI loop so the agent operates against a live z/OS sandbox instead of pre-computed test fixtures. That last one is where it stops being a hackathon project and starts being something IBM customers might genuinely use.
|
| 69 |
+
|
| 70 |
+
Until one of them does, we'll be at our desks.
|
| 71 |
+
|
| 72 |
+
Modernizing COBOL.
|
| 73 |
+
|
| 74 |
+
Manually.
|
| 75 |
+
|
| 76 |
+
For now.
|
| 77 |
+
|
| 78 |
+
Ishan & Niranjan, Team QuietLab
|
client.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Client for the Legacy COBOL Migration Workbench."""
|
| 2 |
+
|
| 3 |
+
from openenv.core.mcp_client import MCPToolClient
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class LegacyCobolEnv(MCPToolClient):
|
| 7 |
+
"""MCP tool client for the workbench."""
|
| 8 |
+
|
| 9 |
+
pass
|
cobol_oracles/invoice/Dockerfile
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM debian:bookworm-slim
|
| 2 |
+
|
| 3 |
+
RUN apt-get update \
|
| 4 |
+
&& apt-get install -y --no-install-recommends gnucobol ca-certificates \
|
| 5 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 6 |
+
|
| 7 |
+
WORKDIR /oracle
|
| 8 |
+
|
| 9 |
+
COPY INVOICE_ORACLE.cbl TAXRATE.cbl INVOICE_REC.cpy TAX_CODE.cpy ./
|
| 10 |
+
RUN cobc -x -free -o invoice_oracle INVOICE_ORACLE.cbl TAXRATE.cbl
|
| 11 |
+
|
| 12 |
+
WORKDIR /work
|
| 13 |
+
ENTRYPOINT ["/oracle/invoice_oracle"]
|
cobol_oracles/invoice/INVOICE_ORACLE.cbl
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
>>SOURCE FORMAT FREE
|
| 2 |
+
IDENTIFICATION DIVISION.
|
| 3 |
+
PROGRAM-ID. INVOICE-ORACLE.
|
| 4 |
+
|
| 5 |
+
ENVIRONMENT DIVISION.
|
| 6 |
+
INPUT-OUTPUT SECTION.
|
| 7 |
+
FILE-CONTROL.
|
| 8 |
+
SELECT INPUT-FILE ASSIGN TO "input.txt"
|
| 9 |
+
ORGANIZATION IS LINE SEQUENTIAL.
|
| 10 |
+
SELECT OUTPUT-FILE ASSIGN TO "output.txt"
|
| 11 |
+
ORGANIZATION IS LINE SEQUENTIAL.
|
| 12 |
+
|
| 13 |
+
DATA DIVISION.
|
| 14 |
+
FILE SECTION.
|
| 15 |
+
FD INPUT-FILE.
|
| 16 |
+
01 INPUT-LINE PIC X(44).
|
| 17 |
+
FD OUTPUT-FILE.
|
| 18 |
+
01 OUTPUT-LINE PIC X(18).
|
| 19 |
+
|
| 20 |
+
WORKING-STORAGE SECTION.
|
| 21 |
+
COPY INVOICE_REC.
|
| 22 |
+
COPY TAX_CODE.
|
| 23 |
+
01 EOF-FLAG PIC X VALUE "N".
|
| 24 |
+
01 WS-IDX PIC 9 VALUE 0.
|
| 25 |
+
01 WS-ITEM-START PIC 99 VALUE 0.
|
| 26 |
+
01 WS-PRICE-START PIC 99 VALUE 0.
|
| 27 |
+
01 WS-TAX-START PIC 99 VALUE 0.
|
| 28 |
+
01 WS-QTY PIC 99 VALUE 0.
|
| 29 |
+
01 WS-PRICE-CENTS PIC 9(6) VALUE 0.
|
| 30 |
+
01 WS-LINE-CENTS PIC 9(9) VALUE 0.
|
| 31 |
+
01 WS-TAX-CENTS PIC 9(9) VALUE 0.
|
| 32 |
+
01 WS-TAX-PERCENT PIC 9V9999 VALUE 0.
|
| 33 |
+
01 WS-TOTAL-CENTS PIC 9(9) VALUE 0.
|
| 34 |
+
01 OUTPUT-RECORD.
|
| 35 |
+
05 OUT-INVOICE-ID PIC X(6).
|
| 36 |
+
05 OUT-TOTAL PIC 9(9).
|
| 37 |
+
05 OUT-ITEM-COUNT PIC 99.
|
| 38 |
+
05 OUT-FLAG PIC X.
|
| 39 |
+
|
| 40 |
+
PROCEDURE DIVISION.
|
| 41 |
+
OPEN INPUT INPUT-FILE
|
| 42 |
+
OPEN OUTPUT OUTPUT-FILE
|
| 43 |
+
PERFORM UNTIL EOF-FLAG = "Y"
|
| 44 |
+
READ INPUT-FILE
|
| 45 |
+
AT END
|
| 46 |
+
MOVE "Y" TO EOF-FLAG
|
| 47 |
+
NOT AT END
|
| 48 |
+
PERFORM MIGRATE-INVOICE
|
| 49 |
+
MOVE OUTPUT-RECORD TO OUTPUT-LINE
|
| 50 |
+
WRITE OUTPUT-LINE
|
| 51 |
+
END-READ
|
| 52 |
+
END-PERFORM
|
| 53 |
+
CLOSE INPUT-FILE
|
| 54 |
+
CLOSE OUTPUT-FILE
|
| 55 |
+
STOP RUN.
|
| 56 |
+
|
| 57 |
+
MIGRATE-INVOICE.
|
| 58 |
+
MOVE INPUT-LINE TO INVOICE-RECORD
|
| 59 |
+
MOVE ZERO TO WS-TOTAL-CENTS
|
| 60 |
+
IF ITEM-COUNT > 4
|
| 61 |
+
MOVE 4 TO ITEM-COUNT
|
| 62 |
+
END-IF
|
| 63 |
+
|
| 64 |
+
PERFORM VARYING WS-IDX FROM 1 BY 1 UNTIL WS-IDX > ITEM-COUNT
|
| 65 |
+
COMPUTE WS-ITEM-START = 9 + ((WS-IDX - 1) * 9)
|
| 66 |
+
COMPUTE WS-PRICE-START = WS-ITEM-START + 2
|
| 67 |
+
COMPUTE WS-TAX-START = WS-ITEM-START + 8
|
| 68 |
+
MOVE FUNCTION NUMVAL(INPUT-LINE(WS-ITEM-START:2)) TO WS-QTY
|
| 69 |
+
MOVE FUNCTION NUMVAL(INPUT-LINE(WS-PRICE-START:6)) TO WS-PRICE-CENTS
|
| 70 |
+
MOVE INPUT-LINE(WS-TAX-START:1) TO TAX-CODE(WS-IDX)
|
| 71 |
+
COMPUTE WS-LINE-CENTS = WS-QTY * WS-PRICE-CENTS
|
| 72 |
+
CALL "TAXRATE" USING TAX-CODE(WS-IDX) WS-TAX-PERCENT
|
| 73 |
+
COMPUTE WS-TAX-CENTS ROUNDED = WS-LINE-CENTS * WS-TAX-PERCENT
|
| 74 |
+
ADD WS-TAX-CENTS TO WS-LINE-CENTS
|
| 75 |
+
ADD WS-LINE-CENTS TO WS-TOTAL-CENTS
|
| 76 |
+
END-PERFORM
|
| 77 |
+
|
| 78 |
+
MOVE INVOICE-ID TO OUT-INVOICE-ID
|
| 79 |
+
MOVE WS-TOTAL-CENTS TO OUT-TOTAL
|
| 80 |
+
MOVE ITEM-COUNT TO OUT-ITEM-COUNT
|
| 81 |
+
IF WS-TOTAL-CENTS >= 100000
|
| 82 |
+
MOVE "H" TO OUT-FLAG
|
| 83 |
+
ELSE
|
| 84 |
+
MOVE "L" TO OUT-FLAG
|
| 85 |
+
END-IF.
|
cobol_oracles/invoice/INVOICE_REC.cpy
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
01 INVOICE-RECORD.
|
| 2 |
+
05 INVOICE-ID PIC X(6).
|
| 3 |
+
05 ITEM-COUNT PIC 9(2).
|
| 4 |
+
05 LINE-ITEM OCCURS 4 TIMES.
|
| 5 |
+
10 ITEM-QTY PIC 9(2).
|
| 6 |
+
10 ITEM-PRICE PIC 9(4)V99.
|
| 7 |
+
10 TAX-CODE PIC X.
|
cobol_oracles/invoice/TAXRATE.cbl
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
>>SOURCE FORMAT FREE
|
| 2 |
+
IDENTIFICATION DIVISION.
|
| 3 |
+
PROGRAM-ID. TAXRATE.
|
| 4 |
+
|
| 5 |
+
DATA DIVISION.
|
| 6 |
+
LINKAGE SECTION.
|
| 7 |
+
01 LK-TAX-CODE PIC X.
|
| 8 |
+
01 LK-TAX-PERCENT PIC 9V9999.
|
| 9 |
+
|
| 10 |
+
PROCEDURE DIVISION USING LK-TAX-CODE LK-TAX-PERCENT.
|
| 11 |
+
EVALUATE LK-TAX-CODE
|
| 12 |
+
WHEN "S" MOVE 0.0725 TO LK-TAX-PERCENT
|
| 13 |
+
WHEN "R" MOVE 0.0250 TO LK-TAX-PERCENT
|
| 14 |
+
WHEN "L" MOVE 0.1000 TO LK-TAX-PERCENT
|
| 15 |
+
WHEN OTHER MOVE 0.0000 TO LK-TAX-PERCENT
|
| 16 |
+
END-EVALUATE
|
| 17 |
+
GOBACK.
|
cobol_oracles/invoice/TAX_CODE.cpy
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
01 TAX-CODE-TABLE.
|
| 2 |
+
05 TAX-CODE-ENTRY OCCURS 4 TIMES.
|
| 3 |
+
10 TAX-CODE-KEY PIC X.
|
| 4 |
+
10 TAX-RATE PIC 9V9999.
|
eval/__init__.py
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Evaluation helpers for Legacy COBOL Migration Workbench."""
|
| 2 |
+
|
eval/cobol_oracle.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Dockerized COBOL oracle checks for the hard invoice task."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import json
|
| 6 |
+
import shutil
|
| 7 |
+
import subprocess
|
| 8 |
+
import tempfile
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
from typing import Any
|
| 11 |
+
|
| 12 |
+
from legacy_cobol_env.server import task_bank
|
| 13 |
+
from legacy_cobol_env.server.task_bank import TestCase, generate_fresh_tests, load_task
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
ENV_ROOT = Path(__file__).resolve().parents[1]
|
| 17 |
+
INVOICE_ORACLE_DIR = ENV_ROOT / "cobol_oracles" / "invoice"
|
| 18 |
+
DEFAULT_IMAGE_TAG = "legacy-cobol-invoice-oracle:local"
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def invoice_oracle_cases(include_fresh: bool = True) -> list[TestCase]:
|
| 22 |
+
task = load_task(task_id="invoice_occurs_001")
|
| 23 |
+
cases = [*task.visible_tests, *task.hidden_tests]
|
| 24 |
+
if include_fresh:
|
| 25 |
+
cases.extend(generate_fresh_tests(task))
|
| 26 |
+
return cases
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def build_invoice_oracle_image(image_tag: str = DEFAULT_IMAGE_TAG) -> None:
|
| 30 |
+
_require_docker()
|
| 31 |
+
subprocess.run(
|
| 32 |
+
["docker", "build", "-t", image_tag, str(INVOICE_ORACLE_DIR)],
|
| 33 |
+
check=True,
|
| 34 |
+
text=True,
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def compile_invoice_task_sources(
|
| 39 |
+
image_tag: str = DEFAULT_IMAGE_TAG,
|
| 40 |
+
build: bool = True,
|
| 41 |
+
) -> dict[str, Any]:
|
| 42 |
+
_require_docker()
|
| 43 |
+
if build:
|
| 44 |
+
build_invoice_oracle_image(image_tag=image_tag)
|
| 45 |
+
|
| 46 |
+
with tempfile.TemporaryDirectory(prefix="invoice-task-compile-") as tmp:
|
| 47 |
+
workdir = Path(tmp)
|
| 48 |
+
(workdir / "INVTOTAL.cbl").write_text(task_bank.INVOICE_COBOL, encoding="utf-8")
|
| 49 |
+
(workdir / "TAXRATE.cbl").write_text(task_bank.TAXRATE_COBOL, encoding="utf-8")
|
| 50 |
+
(workdir / "INVOICE_REC.cpy").write_text(task_bank.INVOICE_COPYBOOK, encoding="utf-8")
|
| 51 |
+
(workdir / "TAX_CODE.cpy").write_text(task_bank.TAX_CODE_COPYBOOK, encoding="utf-8")
|
| 52 |
+
completed = subprocess.run(
|
| 53 |
+
[
|
| 54 |
+
"docker",
|
| 55 |
+
"run",
|
| 56 |
+
"--rm",
|
| 57 |
+
"--entrypoint",
|
| 58 |
+
"sh",
|
| 59 |
+
"-v",
|
| 60 |
+
f"{workdir}:/work",
|
| 61 |
+
"-w",
|
| 62 |
+
"/work",
|
| 63 |
+
image_tag,
|
| 64 |
+
"-lc",
|
| 65 |
+
"cobc -m -free INVTOTAL.cbl TAXRATE.cbl",
|
| 66 |
+
],
|
| 67 |
+
check=False,
|
| 68 |
+
text=True,
|
| 69 |
+
capture_output=True,
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
return {
|
| 73 |
+
"ok": completed.returncode == 0,
|
| 74 |
+
"compiled_sources": ["INVTOTAL.cbl", "TAXRATE.cbl"],
|
| 75 |
+
"returncode": completed.returncode,
|
| 76 |
+
"stdout": completed.stdout,
|
| 77 |
+
"stderr": completed.stderr,
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def run_invoice_oracle(
|
| 82 |
+
records: list[str],
|
| 83 |
+
image_tag: str = DEFAULT_IMAGE_TAG,
|
| 84 |
+
build: bool = False,
|
| 85 |
+
) -> list[str]:
|
| 86 |
+
_require_docker()
|
| 87 |
+
if build:
|
| 88 |
+
build_invoice_oracle_image(image_tag=image_tag)
|
| 89 |
+
|
| 90 |
+
with tempfile.TemporaryDirectory(prefix="invoice-cobol-oracle-") as tmp:
|
| 91 |
+
workdir = Path(tmp)
|
| 92 |
+
input_path = workdir / "input.txt"
|
| 93 |
+
output_path = workdir / "output.txt"
|
| 94 |
+
input_path.write_text("".join(f"{record}\n" for record in records), encoding="utf-8")
|
| 95 |
+
|
| 96 |
+
subprocess.run(
|
| 97 |
+
[
|
| 98 |
+
"docker",
|
| 99 |
+
"run",
|
| 100 |
+
"--rm",
|
| 101 |
+
"-v",
|
| 102 |
+
f"{workdir}:/work",
|
| 103 |
+
image_tag,
|
| 104 |
+
],
|
| 105 |
+
check=True,
|
| 106 |
+
text=True,
|
| 107 |
+
capture_output=True,
|
| 108 |
+
)
|
| 109 |
+
outputs = output_path.read_text(encoding="utf-8").splitlines()
|
| 110 |
+
|
| 111 |
+
if len(outputs) != len(records):
|
| 112 |
+
raise RuntimeError(f"COBOL oracle returned {len(outputs)} outputs for {len(records)} records")
|
| 113 |
+
return outputs
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
def compare_invoice_oracle(
|
| 117 |
+
image_tag: str = DEFAULT_IMAGE_TAG,
|
| 118 |
+
build: bool = False,
|
| 119 |
+
include_fresh: bool = True,
|
| 120 |
+
) -> dict[str, Any]:
|
| 121 |
+
cases = invoice_oracle_cases(include_fresh=include_fresh)
|
| 122 |
+
actual_outputs = run_invoice_oracle(
|
| 123 |
+
[case.input_record for case in cases],
|
| 124 |
+
image_tag=image_tag,
|
| 125 |
+
build=build,
|
| 126 |
+
)
|
| 127 |
+
rows = []
|
| 128 |
+
mismatches = []
|
| 129 |
+
for case, actual in zip(cases, actual_outputs, strict=True):
|
| 130 |
+
passed = actual == case.expected_output
|
| 131 |
+
row = {
|
| 132 |
+
"case_id": case.case_id,
|
| 133 |
+
"summary": case.summary,
|
| 134 |
+
"input_record": case.input_record,
|
| 135 |
+
"expected_output": case.expected_output,
|
| 136 |
+
"actual_output": actual,
|
| 137 |
+
"passed": passed,
|
| 138 |
+
}
|
| 139 |
+
rows.append(row)
|
| 140 |
+
if not passed:
|
| 141 |
+
mismatches.append(row)
|
| 142 |
+
|
| 143 |
+
return {
|
| 144 |
+
"ok": not mismatches,
|
| 145 |
+
"image_tag": image_tag,
|
| 146 |
+
"case_count": len(cases),
|
| 147 |
+
"passed_count": len(cases) - len(mismatches),
|
| 148 |
+
"mismatches": mismatches,
|
| 149 |
+
"cases": rows,
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
def write_comparison_report(result: dict[str, Any], output_path: Path) -> None:
|
| 154 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 155 |
+
output_path.write_text(json.dumps(result, indent=2), encoding="utf-8")
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
def _require_docker() -> None:
|
| 159 |
+
if shutil.which("docker") is None:
|
| 160 |
+
raise RuntimeError("docker is required for COBOL oracle checks")
|
eval/evidence_report.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Build judge-facing score summaries from evaluation artifacts."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import json
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
from typing import Any
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def build_score_summary(
|
| 11 |
+
baseline: dict[str, Any],
|
| 12 |
+
zeroshot: dict[str, Any] | None = None,
|
| 13 |
+
repair: dict[str, Any] | None = None,
|
| 14 |
+
oracle_model: dict[str, Any] | None = None,
|
| 15 |
+
base_model: dict[str, Any] | None = None,
|
| 16 |
+
trained_summary: dict[str, Any] | None = None,
|
| 17 |
+
evidence_notes: list[str] | None = None,
|
| 18 |
+
) -> dict[str, Any]:
|
| 19 |
+
baseline_task_count = baseline.get("task_count") or len({row["task_id"] for row in baseline["results"]})
|
| 20 |
+
policies = {
|
| 21 |
+
name: {
|
| 22 |
+
"mean_public_score": score,
|
| 23 |
+
"accepted_count": sum(
|
| 24 |
+
1 for row in baseline["results"] if row["policy"] == name and row.get("accepted")
|
| 25 |
+
),
|
| 26 |
+
"task_count": baseline_task_count,
|
| 27 |
+
}
|
| 28 |
+
for name, score in baseline["mean_public_score"].items()
|
| 29 |
+
}
|
| 30 |
+
if oracle_model is not None:
|
| 31 |
+
policies["oracle-model"] = {
|
| 32 |
+
"mean_public_score": oracle_model["mean_public_score"],
|
| 33 |
+
"accepted_count": oracle_model["accepted_count"],
|
| 34 |
+
"task_count": oracle_model["task_count"],
|
| 35 |
+
"role": "oracle_sanity",
|
| 36 |
+
}
|
| 37 |
+
if base_model is not None:
|
| 38 |
+
policies["base Qwen3-14B"] = {
|
| 39 |
+
"mean_public_score": base_model["mean_public_score"],
|
| 40 |
+
"accepted_count": base_model["accepted_count"],
|
| 41 |
+
"task_count": base_model["task_count"],
|
| 42 |
+
"role": "base_model_before_sft",
|
| 43 |
+
}
|
| 44 |
+
if zeroshot is not None:
|
| 45 |
+
policies["gpt-5.4-mini zero-shot"] = {
|
| 46 |
+
"mean_public_score": zeroshot["mean_public_score"],
|
| 47 |
+
"accepted_count": zeroshot["accepted_count"],
|
| 48 |
+
"task_count": zeroshot["task_count"],
|
| 49 |
+
"role": "historical_model_baseline",
|
| 50 |
+
}
|
| 51 |
+
if repair is not None:
|
| 52 |
+
policies["gpt-5.4-mini + repair1"] = {
|
| 53 |
+
"mean_public_score": repair["mean_public_score"],
|
| 54 |
+
"accepted_count": repair["accepted_count"],
|
| 55 |
+
"task_count": repair["task_count"],
|
| 56 |
+
"role": "historical_model_repair",
|
| 57 |
+
}
|
| 58 |
+
if trained_summary is not None:
|
| 59 |
+
policies["trained Qwen3-14B LoRA SFT"] = {
|
| 60 |
+
"mean_public_score": trained_summary["trained_mean_public_score"],
|
| 61 |
+
"accepted_count": trained_summary["trained_accepted_count"],
|
| 62 |
+
"task_count": trained_summary["task_count"],
|
| 63 |
+
"role": "trained_model_after_sft",
|
| 64 |
+
"model": trained_summary.get("model"),
|
| 65 |
+
"method": trained_summary.get("method"),
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
task_scores: dict[str, dict[str, Any]] = {}
|
| 69 |
+
for row in baseline["results"]:
|
| 70 |
+
task_scores.setdefault(row["task_id"], {})[row["policy"]] = row.get("public_score")
|
| 71 |
+
if oracle_model is not None:
|
| 72 |
+
for trajectory in oracle_model["trajectories"]:
|
| 73 |
+
task_scores.setdefault(trajectory["task_id"], {})["oracle_model"] = trajectory["final"]["public_score"]
|
| 74 |
+
if base_model is not None:
|
| 75 |
+
for trajectory in base_model["trajectories"]:
|
| 76 |
+
task_scores.setdefault(trajectory["task_id"], {})["base_qwen3_14b"] = trajectory["final"]["public_score"]
|
| 77 |
+
if zeroshot is not None:
|
| 78 |
+
for trajectory in zeroshot["trajectories"]:
|
| 79 |
+
task_scores.setdefault(trajectory["task_id"], {})["zeroshot"] = trajectory["final"]["public_score"]
|
| 80 |
+
if repair is not None:
|
| 81 |
+
for trajectory in repair["trajectories"]:
|
| 82 |
+
task_scores.setdefault(trajectory["task_id"], {})["repair1"] = trajectory["final"]["public_score"]
|
| 83 |
+
task_scores[trajectory["task_id"]]["repair1_accepted"] = trajectory["final"]["accepted"]
|
| 84 |
+
|
| 85 |
+
training_targets = []
|
| 86 |
+
if repair is not None:
|
| 87 |
+
for trajectory in repair["trajectories"]:
|
| 88 |
+
final = trajectory["final"]
|
| 89 |
+
visible = trajectory["visible"]
|
| 90 |
+
if visible["pass_rate"] == 1.0 and not final["accepted"]:
|
| 91 |
+
training_targets.append(
|
| 92 |
+
{
|
| 93 |
+
"task_id": trajectory["task_id"],
|
| 94 |
+
"family_id": trajectory.get("family_id"),
|
| 95 |
+
"reason": "visible-pass-hidden-fresh-gap",
|
| 96 |
+
"public_score": final["public_score"],
|
| 97 |
+
"weak_components": {
|
| 98 |
+
key: value
|
| 99 |
+
for key, value in final["components"].items()
|
| 100 |
+
if isinstance(value, int | float) and value < 1.0
|
| 101 |
+
},
|
| 102 |
+
}
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
+
return {
|
| 106 |
+
"policies": policies,
|
| 107 |
+
"task_scores": task_scores,
|
| 108 |
+
"judge_table": _judge_table(policies),
|
| 109 |
+
"training_evidence": _training_evidence(trained_summary),
|
| 110 |
+
"training_targets": training_targets,
|
| 111 |
+
"evidence_notes": evidence_notes or [],
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
def _judge_table(policies: dict[str, dict[str, Any]]) -> list[dict[str, Any]]:
|
| 116 |
+
return [
|
| 117 |
+
{
|
| 118 |
+
"policy": policy,
|
| 119 |
+
"role": data.get("role"),
|
| 120 |
+
"mean_public_score": data["mean_public_score"],
|
| 121 |
+
"accepted_count": data["accepted_count"],
|
| 122 |
+
"task_count": data["task_count"],
|
| 123 |
+
}
|
| 124 |
+
for policy, data in policies.items()
|
| 125 |
+
]
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
def _training_evidence(trained_summary: dict[str, Any] | None) -> dict[str, Any] | None:
|
| 129 |
+
if trained_summary is None:
|
| 130 |
+
return None
|
| 131 |
+
return {
|
| 132 |
+
"model": trained_summary.get("model"),
|
| 133 |
+
"method": trained_summary.get("method"),
|
| 134 |
+
"dataset_examples": trained_summary.get("dataset_examples"),
|
| 135 |
+
"loss_first": trained_summary.get("loss_first"),
|
| 136 |
+
"loss_last": trained_summary.get("loss_last"),
|
| 137 |
+
"mean_token_accuracy_first": trained_summary.get("mean_token_accuracy_first"),
|
| 138 |
+
"mean_token_accuracy_last": trained_summary.get("mean_token_accuracy_last"),
|
| 139 |
+
"base_mean_public_score": trained_summary.get("base_mean_public_score"),
|
| 140 |
+
"trained_mean_public_score": trained_summary.get("trained_mean_public_score"),
|
| 141 |
+
"base_accepted_count": trained_summary.get("base_accepted_count"),
|
| 142 |
+
"trained_accepted_count": trained_summary.get("trained_accepted_count"),
|
| 143 |
+
"task_count": trained_summary.get("task_count"),
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def write_score_plot(summary: dict[str, Any], path: Path) -> None:
|
| 148 |
+
policies = list(summary["policies"].items())
|
| 149 |
+
width = 760
|
| 150 |
+
height = 320
|
| 151 |
+
margin = 48
|
| 152 |
+
plot_height = height - margin * 2
|
| 153 |
+
bar_width = 86
|
| 154 |
+
gap = 32
|
| 155 |
+
colors = ["#64748b", "#22c55e", "#2563eb", "#f97316"]
|
| 156 |
+
parts = [
|
| 157 |
+
f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}" viewBox="0 0 {width} {height}">',
|
| 158 |
+
'<rect width="100%" height="100%" fill="#ffffff"/>',
|
| 159 |
+
'<text x="40" y="30" font-family="Arial" font-size="18" font-weight="700">Legacy COBOL OpenEnv evaluation</text>',
|
| 160 |
+
f'<line x1="{margin}" y1="{height - margin}" x2="{width - margin}" y2="{height - margin}" stroke="#1f2937"/>',
|
| 161 |
+
f'<line x1="{margin}" y1="{height - margin}" x2="{margin}" y2="{margin}" stroke="#1f2937"/>',
|
| 162 |
+
]
|
| 163 |
+
x = margin + 20
|
| 164 |
+
for index, (name, data) in enumerate(policies):
|
| 165 |
+
score = float(data["mean_public_score"])
|
| 166 |
+
bar_height = score * plot_height
|
| 167 |
+
y = height - margin - bar_height
|
| 168 |
+
color = colors[index % len(colors)]
|
| 169 |
+
parts.append(f'<rect x="{x}" y="{y:.1f}" width="{bar_width}" height="{bar_height:.1f}" rx="4" fill="{color}"/>')
|
| 170 |
+
parts.append(f'<text x="{x + 8}" y="{y - 8:.1f}" font-family="Arial" font-size="12">{score:.3f}</text>')
|
| 171 |
+
accepted = f'{data["accepted_count"]}/{data["task_count"]} accepted'
|
| 172 |
+
parts.append(f'<text x="{x}" y="{height - 28}" font-family="Arial" font-size="10">{accepted}</text>')
|
| 173 |
+
for line_index, line in enumerate(_wrap_label(name)):
|
| 174 |
+
parts.append(f'<text x="{x}" y="{height - 14 + line_index * 11}" font-family="Arial" font-size="10">{line}</text>')
|
| 175 |
+
x += bar_width + gap
|
| 176 |
+
parts.append("</svg>")
|
| 177 |
+
path.write_text("\n".join(parts), encoding="utf-8")
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
def _wrap_label(label: str) -> list[str]:
|
| 181 |
+
words = label.split()
|
| 182 |
+
lines: list[str] = []
|
| 183 |
+
current = ""
|
| 184 |
+
for word in words:
|
| 185 |
+
candidate = f"{current} {word}".strip()
|
| 186 |
+
if len(candidate) > 18 and current:
|
| 187 |
+
lines.append(current)
|
| 188 |
+
current = word
|
| 189 |
+
else:
|
| 190 |
+
current = candidate
|
| 191 |
+
if current:
|
| 192 |
+
lines.append(current)
|
| 193 |
+
return lines[:2]
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
def load_json(path: Path) -> dict[str, Any]:
|
| 197 |
+
return json.loads(path.read_text(encoding="utf-8"))
|
eval/inspect_rollout.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Inspect saved model rollout artifacts for debugging."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import argparse
|
| 6 |
+
import json
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
from typing import Any
|
| 9 |
+
|
| 10 |
+
from legacy_cobol_env.eval.model_rollout import extract_code_from_response
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
STEP_NAMES_TO_SHOW = {"write_python_solution", "run_visible_tests", "inspect_diff", "submit_final"}
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def inspect_rollout_file(path: Path, max_chars: int = 4000) -> str:
|
| 17 |
+
summary = json.loads(path.read_text(encoding="utf-8"))
|
| 18 |
+
return inspect_rollout_summary(summary, max_chars=max_chars)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def inspect_rollout_summary(summary: dict[str, Any], max_chars: int = 4000) -> str:
|
| 22 |
+
lines: list[str] = []
|
| 23 |
+
lines.append("SUMMARY")
|
| 24 |
+
lines.append(
|
| 25 |
+
_json_preview(
|
| 26 |
+
{
|
| 27 |
+
key: summary.get(key)
|
| 28 |
+
for key in ["provider", "max_repairs", "task_count", "mean_public_score", "accepted_count"]
|
| 29 |
+
if key in summary
|
| 30 |
+
},
|
| 31 |
+
max_chars,
|
| 32 |
+
)
|
| 33 |
+
)
|
| 34 |
+
|
| 35 |
+
trajectories = summary.get("trajectories", [])
|
| 36 |
+
if not trajectories:
|
| 37 |
+
lines.append("\nNO TRAJECTORIES")
|
| 38 |
+
return "\n".join(lines)
|
| 39 |
+
|
| 40 |
+
for index, trajectory in enumerate(trajectories, start=1):
|
| 41 |
+
lines.append(f"\nTRAJECTORY {index}")
|
| 42 |
+
lines.append(
|
| 43 |
+
_json_preview(
|
| 44 |
+
{
|
| 45 |
+
key: trajectory.get(key)
|
| 46 |
+
for key in ["task_id", "family_id", "policy"]
|
| 47 |
+
if key in trajectory
|
| 48 |
+
},
|
| 49 |
+
max_chars,
|
| 50 |
+
)
|
| 51 |
+
)
|
| 52 |
+
lines.append("\nFINAL")
|
| 53 |
+
lines.append(_json_preview(trajectory.get("final", {}), max_chars))
|
| 54 |
+
lines.append("\nVISIBLE")
|
| 55 |
+
lines.append(_json_preview(trajectory.get("visible", {}), max_chars))
|
| 56 |
+
lines.append("\nMODEL TURNS")
|
| 57 |
+
lines.extend(_format_model_turns(trajectory.get("model_turns", []), max_chars))
|
| 58 |
+
lines.append("\nWRITE / TEST STEPS")
|
| 59 |
+
lines.extend(_format_steps(trajectory.get("steps", []), max_chars))
|
| 60 |
+
|
| 61 |
+
return "\n".join(lines)
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
def _format_model_turns(model_turns: list[dict[str, Any]], max_chars: int) -> list[str]:
|
| 65 |
+
lines: list[str] = []
|
| 66 |
+
for index, turn in enumerate(model_turns, start=1):
|
| 67 |
+
response = str(turn.get("response", ""))
|
| 68 |
+
lines.append(f"\n--- turn {index} raw response ---")
|
| 69 |
+
lines.append(_text_preview(response, max_chars))
|
| 70 |
+
lines.append(f"\n--- turn {index} extracted code ---")
|
| 71 |
+
try:
|
| 72 |
+
lines.append(_text_preview(extract_code_from_response(response), max_chars))
|
| 73 |
+
except Exception as exc: # pragma: no cover - exact parser errors vary.
|
| 74 |
+
lines.append(f"extract failed: {exc!r}")
|
| 75 |
+
if not lines:
|
| 76 |
+
lines.append("(none)")
|
| 77 |
+
return lines
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def _format_steps(steps: list[dict[str, Any]], max_chars: int) -> list[str]:
|
| 81 |
+
lines: list[str] = []
|
| 82 |
+
for step in steps:
|
| 83 |
+
tool_name = step.get("tool_name")
|
| 84 |
+
if tool_name not in STEP_NAMES_TO_SHOW:
|
| 85 |
+
continue
|
| 86 |
+
lines.append(f"\n{tool_name}")
|
| 87 |
+
lines.append(_json_preview(step.get("result", {}), max_chars))
|
| 88 |
+
if not lines:
|
| 89 |
+
lines.append("(none)")
|
| 90 |
+
return lines
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def _json_preview(value: Any, max_chars: int) -> str:
|
| 94 |
+
return _text_preview(json.dumps(value, indent=2, sort_keys=True), max_chars)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def _text_preview(value: str, max_chars: int) -> str:
|
| 98 |
+
if len(value) <= max_chars:
|
| 99 |
+
return value
|
| 100 |
+
omitted = len(value) - max_chars
|
| 101 |
+
return f"{value[:max_chars]}\n... <truncated {omitted} chars>"
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
def main() -> None:
|
| 105 |
+
parser = argparse.ArgumentParser(description="Print the useful parts of a saved rollout JSON artifact.")
|
| 106 |
+
parser.add_argument("path", type=Path, help="Path to a run_model_rollouts JSON output.")
|
| 107 |
+
parser.add_argument("--max-chars", type=int, default=4000, help="Maximum characters per response/result block.")
|
| 108 |
+
args = parser.parse_args()
|
| 109 |
+
|
| 110 |
+
print(inspect_rollout_file(args.path, max_chars=args.max_chars))
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
if __name__ == "__main__":
|
| 114 |
+
main()
|
eval/model_rollout.py
ADDED
|
@@ -0,0 +1,460 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Run provider-backed code-generation rollouts against the workbench."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import json
|
| 6 |
+
import ast
|
| 7 |
+
import re
|
| 8 |
+
from typing import Any
|
| 9 |
+
|
| 10 |
+
from legacy_cobol_env.eval.providers import TextProvider
|
| 11 |
+
from legacy_cobol_env.eval.trajectory import call_tool
|
| 12 |
+
from legacy_cobol_env.server.sandbox import ALLOWED_IMPORTS, FORBIDDEN_IMPORTS
|
| 13 |
+
from legacy_cobol_env.server.legacy_cobol_env_environment import LegacyCobolEnvironment
|
| 14 |
+
from legacy_cobol_env.server.task_bank import TaskInstance
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
ALLOWED_IMPORT_TEXT = ", ".join(name for name in ["decimal", "datetime", "math", "re", "typing"] if name in ALLOWED_IMPORTS)
|
| 18 |
+
COBOL_NUMERIC_RULE = (
|
| 19 |
+
"PIC fields with V use an implied decimal point: parse them by integer digits and scale; "
|
| 20 |
+
"fixed-width numeric outputs are digits only, zero-padded to their field length, with no decimal point or spaces."
|
| 21 |
+
)
|
| 22 |
+
REPAIR_DISCIPLINE = (
|
| 23 |
+
"Repair discipline: visible failures are actionable. Do not return the previous code unchanged when pass_rate < 1.0. "
|
| 24 |
+
"If an expected numeric output is all digits but the actual output contains a decimal point, spaces, or a shifted value, "
|
| 25 |
+
"replace Decimal-string formatting with scaled integer digit formatting and re-check PIC V input parsing."
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def extract_code_from_response(response: str) -> str:
|
| 30 |
+
candidates = [response.strip(), _strip_fence(response.strip())]
|
| 31 |
+
start = response.find("{")
|
| 32 |
+
end = response.rfind("}")
|
| 33 |
+
if 0 <= start < end:
|
| 34 |
+
candidates.append(response[start : end + 1])
|
| 35 |
+
|
| 36 |
+
for candidate in candidates:
|
| 37 |
+
data = _load_response_object(candidate)
|
| 38 |
+
if data is None:
|
| 39 |
+
continue
|
| 40 |
+
if isinstance(data, dict) and isinstance(data.get("code"), str):
|
| 41 |
+
return _remove_unused_disallowed_imports(data["code"])
|
| 42 |
+
|
| 43 |
+
unfenced = _strip_fence(response.strip())
|
| 44 |
+
if "def migrate" in unfenced:
|
| 45 |
+
return _remove_unused_disallowed_imports(unfenced)
|
| 46 |
+
raise ValueError("model response did not contain JSON with a code field")
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def _load_response_object(candidate: str) -> object | None:
|
| 50 |
+
try:
|
| 51 |
+
return json.loads(candidate)
|
| 52 |
+
except json.JSONDecodeError:
|
| 53 |
+
pass
|
| 54 |
+
|
| 55 |
+
try:
|
| 56 |
+
return ast.literal_eval(candidate)
|
| 57 |
+
except (SyntaxError, ValueError):
|
| 58 |
+
return None
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def run_model_rollout(
|
| 62 |
+
task: TaskInstance,
|
| 63 |
+
provider: TextProvider,
|
| 64 |
+
) -> dict[str, Any]:
|
| 65 |
+
env = LegacyCobolEnvironment()
|
| 66 |
+
reset_observation = env.reset(task_id=task.task_id)
|
| 67 |
+
ticket = reset_observation.result["ticket"]
|
| 68 |
+
steps: list[dict[str, Any]] = []
|
| 69 |
+
context: dict[str, Any] = {"cobol_files": {}, "copybooks": {}, "layouts": {}, "business_rules": []}
|
| 70 |
+
|
| 71 |
+
def record(tool_name: str, arguments: dict[str, Any]) -> dict[str, Any]:
|
| 72 |
+
result, reward, done = call_tool(env, tool_name, **arguments)
|
| 73 |
+
saved_arguments = dict(arguments)
|
| 74 |
+
if "code" in saved_arguments:
|
| 75 |
+
saved_arguments["code_chars"] = len(saved_arguments.pop("code"))
|
| 76 |
+
steps.append(
|
| 77 |
+
{
|
| 78 |
+
"tool_name": tool_name,
|
| 79 |
+
"arguments": saved_arguments,
|
| 80 |
+
"reward": reward,
|
| 81 |
+
"done": done,
|
| 82 |
+
"result": result,
|
| 83 |
+
}
|
| 84 |
+
)
|
| 85 |
+
return result
|
| 86 |
+
|
| 87 |
+
for filename in ticket["available_files"]:
|
| 88 |
+
result = record("read_cobol_file", {"filename": filename})
|
| 89 |
+
context["cobol_files"][filename] = result["content"]
|
| 90 |
+
for filename in ticket["available_copybooks"]:
|
| 91 |
+
copybook = record("read_copybook", {"filename": filename})
|
| 92 |
+
layout = record("parse_copybook_layout", {"filename": filename})
|
| 93 |
+
context["copybooks"][filename] = copybook["content"]
|
| 94 |
+
context["layouts"][filename] = layout
|
| 95 |
+
rules = record("inspect_business_rules", {})
|
| 96 |
+
context["business_rules"] = rules["rules"]
|
| 97 |
+
|
| 98 |
+
prompt = build_migration_prompt(ticket, context)
|
| 99 |
+
response = provider.generate(prompt)
|
| 100 |
+
code = extract_code_from_response(response)
|
| 101 |
+
written = record("write_python_solution", {"code": code})
|
| 102 |
+
visible = record("run_visible_tests", {"draft_id": written["draft_id"]})
|
| 103 |
+
final = record("submit_final", {"draft_id": written["draft_id"]})
|
| 104 |
+
|
| 105 |
+
return {
|
| 106 |
+
"policy": provider.name,
|
| 107 |
+
"task_id": task.task_id,
|
| 108 |
+
"family_id": task.family_id,
|
| 109 |
+
"ticket": ticket,
|
| 110 |
+
"model_turns": [
|
| 111 |
+
{
|
| 112 |
+
"provider": provider.name,
|
| 113 |
+
"prompt": prompt,
|
| 114 |
+
"response": response,
|
| 115 |
+
"code_chars": len(code),
|
| 116 |
+
}
|
| 117 |
+
],
|
| 118 |
+
"visible": {
|
| 119 |
+
"passed": visible["passed"],
|
| 120 |
+
"total": visible["total"],
|
| 121 |
+
"pass_rate": visible["pass_rate"],
|
| 122 |
+
"failures": visible["failures"],
|
| 123 |
+
},
|
| 124 |
+
"final": {
|
| 125 |
+
"public_score": final["public_score"],
|
| 126 |
+
"accepted": final["accepted"],
|
| 127 |
+
"components": final["components"],
|
| 128 |
+
"hidden_passed": final["hidden_passed"],
|
| 129 |
+
"hidden_total": final["hidden_total"],
|
| 130 |
+
"fresh_passed": final["fresh_passed"],
|
| 131 |
+
"fresh_total": final["fresh_total"],
|
| 132 |
+
},
|
| 133 |
+
"steps": steps,
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def run_model_repair_rollout(
|
| 138 |
+
task: TaskInstance,
|
| 139 |
+
provider: TextProvider,
|
| 140 |
+
max_repairs: int = 1,
|
| 141 |
+
) -> dict[str, Any]:
|
| 142 |
+
env = LegacyCobolEnvironment()
|
| 143 |
+
reset_observation = env.reset(task_id=task.task_id)
|
| 144 |
+
ticket = reset_observation.result["ticket"]
|
| 145 |
+
steps: list[dict[str, Any]] = []
|
| 146 |
+
model_turns: list[dict[str, Any]] = []
|
| 147 |
+
context: dict[str, Any] = {"cobol_files": {}, "copybooks": {}, "layouts": {}, "business_rules": []}
|
| 148 |
+
|
| 149 |
+
def record(tool_name: str, arguments: dict[str, Any]) -> dict[str, Any]:
|
| 150 |
+
result, reward, done = call_tool(env, tool_name, **arguments)
|
| 151 |
+
saved_arguments = dict(arguments)
|
| 152 |
+
if "code" in saved_arguments:
|
| 153 |
+
saved_arguments["code_chars"] = len(saved_arguments.pop("code"))
|
| 154 |
+
steps.append(
|
| 155 |
+
{
|
| 156 |
+
"tool_name": tool_name,
|
| 157 |
+
"arguments": saved_arguments,
|
| 158 |
+
"reward": reward,
|
| 159 |
+
"done": done,
|
| 160 |
+
"result": result,
|
| 161 |
+
}
|
| 162 |
+
)
|
| 163 |
+
return result
|
| 164 |
+
|
| 165 |
+
for filename in ticket["available_files"]:
|
| 166 |
+
result = record("read_cobol_file", {"filename": filename})
|
| 167 |
+
context["cobol_files"][filename] = result["content"]
|
| 168 |
+
for filename in ticket["available_copybooks"]:
|
| 169 |
+
copybook = record("read_copybook", {"filename": filename})
|
| 170 |
+
layout = record("parse_copybook_layout", {"filename": filename})
|
| 171 |
+
context["copybooks"][filename] = copybook["content"]
|
| 172 |
+
context["layouts"][filename] = layout
|
| 173 |
+
rules = record("inspect_business_rules", {})
|
| 174 |
+
context["business_rules"] = rules["rules"]
|
| 175 |
+
|
| 176 |
+
prompt = build_migration_prompt(ticket, context)
|
| 177 |
+
response = provider.generate(prompt)
|
| 178 |
+
code = extract_code_from_response(response)
|
| 179 |
+
model_turns.append({"provider": provider.name, "prompt": prompt, "response": response, "code_chars": len(code)})
|
| 180 |
+
written = record("write_python_solution", {"code": code})
|
| 181 |
+
visible = record("run_visible_tests", {"draft_id": written["draft_id"]})
|
| 182 |
+
|
| 183 |
+
for _ in range(max_repairs):
|
| 184 |
+
if visible["pass_rate"] == 1.0:
|
| 185 |
+
break
|
| 186 |
+
diffs = [record("inspect_diff", {"case_id": failure["case_id"]}) for failure in visible["failures"][:2]]
|
| 187 |
+
repair_prompt = build_repair_prompt(ticket, context, code, visible, diffs)
|
| 188 |
+
response = provider.generate(repair_prompt)
|
| 189 |
+
code = extract_code_from_response(response)
|
| 190 |
+
model_turns.append({"provider": provider.name, "prompt": repair_prompt, "response": response, "code_chars": len(code)})
|
| 191 |
+
written = record("write_python_solution", {"code": code})
|
| 192 |
+
visible = record("run_visible_tests", {"draft_id": written["draft_id"]})
|
| 193 |
+
|
| 194 |
+
final = record("submit_final", {"draft_id": written["draft_id"]})
|
| 195 |
+
return {
|
| 196 |
+
"policy": provider.name,
|
| 197 |
+
"task_id": task.task_id,
|
| 198 |
+
"family_id": task.family_id,
|
| 199 |
+
"ticket": ticket,
|
| 200 |
+
"model_turns": model_turns,
|
| 201 |
+
"visible": {
|
| 202 |
+
"passed": visible["passed"],
|
| 203 |
+
"total": visible["total"],
|
| 204 |
+
"pass_rate": visible["pass_rate"],
|
| 205 |
+
"failures": visible["failures"],
|
| 206 |
+
},
|
| 207 |
+
"final": {
|
| 208 |
+
"public_score": final["public_score"],
|
| 209 |
+
"accepted": final["accepted"],
|
| 210 |
+
"components": final["components"],
|
| 211 |
+
"hidden_passed": final["hidden_passed"],
|
| 212 |
+
"hidden_total": final["hidden_total"],
|
| 213 |
+
"fresh_passed": final["fresh_passed"],
|
| 214 |
+
"fresh_total": final["fresh_total"],
|
| 215 |
+
},
|
| 216 |
+
"steps": steps,
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def build_migration_prompt(ticket: dict[str, Any], context: dict[str, Any]) -> str:
|
| 221 |
+
return "\n\n".join(
|
| 222 |
+
[
|
| 223 |
+
"You are migrating a legacy COBOL routine into Python.",
|
| 224 |
+
"Return only JSON in this shape: {\"code\": \"...python source...\"}.",
|
| 225 |
+
"The Python source must define migrate(input_record: str) -> str.",
|
| 226 |
+
f"Allowed imports: {ALLOWED_IMPORT_TEXT}. Do not import any other modules.",
|
| 227 |
+
COBOL_NUMERIC_RULE,
|
| 228 |
+
build_numeric_layout_reminders(ticket, context),
|
| 229 |
+
"Returned records must match output_width exactly; never append newline characters.",
|
| 230 |
+
f"Ticket:\n{json.dumps(ticket, indent=2)}",
|
| 231 |
+
f"COBOL files:\n{json.dumps(context['cobol_files'], indent=2)}",
|
| 232 |
+
f"Copybooks:\n{json.dumps(context['copybooks'], indent=2)}",
|
| 233 |
+
f"Parsed layouts:\n{json.dumps(context['layouts'], indent=2)}",
|
| 234 |
+
f"Business rules:\n{json.dumps(context['business_rules'], indent=2)}",
|
| 235 |
+
]
|
| 236 |
+
)
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
def build_repair_prompt(
|
| 240 |
+
ticket: dict[str, Any],
|
| 241 |
+
context: dict[str, Any],
|
| 242 |
+
previous_code: str,
|
| 243 |
+
visible: dict[str, Any],
|
| 244 |
+
diffs: list[dict[str, Any]],
|
| 245 |
+
) -> str:
|
| 246 |
+
return "\n\n".join(
|
| 247 |
+
[
|
| 248 |
+
"Repair the Python migration after visible test feedback.",
|
| 249 |
+
"Return only JSON in this shape: {\"code\": \"...python source...\"}.",
|
| 250 |
+
"The Python source must define migrate(input_record: str) -> str.",
|
| 251 |
+
f"Allowed imports: {ALLOWED_IMPORT_TEXT}. Do not import any other modules.",
|
| 252 |
+
COBOL_NUMERIC_RULE,
|
| 253 |
+
REPAIR_DISCIPLINE,
|
| 254 |
+
build_runtime_error_repair_checklist(visible),
|
| 255 |
+
build_numeric_layout_reminders(ticket, context),
|
| 256 |
+
build_diff_repair_checklist(diffs),
|
| 257 |
+
"Returned records must match output_width exactly; never append newline characters.",
|
| 258 |
+
f"Ticket:\n{json.dumps(ticket, indent=2)}",
|
| 259 |
+
f"COBOL files:\n{json.dumps(context['cobol_files'], indent=2)}",
|
| 260 |
+
f"Copybooks:\n{json.dumps(context['copybooks'], indent=2)}",
|
| 261 |
+
f"Parsed layouts:\n{json.dumps(context['layouts'], indent=2)}",
|
| 262 |
+
f"Business rules:\n{json.dumps(context['business_rules'], indent=2)}",
|
| 263 |
+
f"Previous code:\n{previous_code}",
|
| 264 |
+
f"Visible test status:\n{json.dumps(_visible_status_for_prompt(visible), indent=2)}",
|
| 265 |
+
f"Visible failures:\n{json.dumps(visible['failures'], indent=2)}",
|
| 266 |
+
f"Inspected field_diffs:\n{json.dumps(diffs, indent=2)}",
|
| 267 |
+
]
|
| 268 |
+
)
|
| 269 |
+
|
| 270 |
+
|
| 271 |
+
def build_runtime_error_repair_checklist(visible: dict[str, Any]) -> str:
|
| 272 |
+
errors = "\n".join(str(failure.get("error") or "") for failure in visible.get("failures", []))
|
| 273 |
+
lines = ["Runtime error repair checklist:"]
|
| 274 |
+
if "slice indices must be integers" in errors:
|
| 275 |
+
lines.append(
|
| 276 |
+
"- TypeError 'slice indices must be integers': convert ITEM-COUNT with int(input_record[6:8]) before using it; "
|
| 277 |
+
"do not slice range(...) with input_record[6:8]; for OCCURS use range(count) with start = 8 + idx * 9."
|
| 278 |
+
)
|
| 279 |
+
if "'slice' object is not callable" in errors:
|
| 280 |
+
lines.append(
|
| 281 |
+
"- TypeError 'slice' object is not callable: do not call slice objects like field(input_record); "
|
| 282 |
+
"read fields with direct string slicing such as input_record[start:end]. Avoid generic layout parsers unless every slice is applied with data[slice_obj]."
|
| 283 |
+
)
|
| 284 |
+
if "invalid format string" in errors or "unsupported format string passed to decimal.Decimal" in errors:
|
| 285 |
+
lines.append(
|
| 286 |
+
"- Decimal formatting error: do not format Decimal values with :d or include decimal points in fixed-width PIC V output. "
|
| 287 |
+
"Convert monetary totals to integer cents first, for example total_cents = int((total * Decimal(\"100\")).quantize(Decimal(\"1\"))), "
|
| 288 |
+
"then emit format(total_cents, \"09d\")."
|
| 289 |
+
)
|
| 290 |
+
if "object has no attribute 'to_string'" in errors:
|
| 291 |
+
lines.append(
|
| 292 |
+
"- Decimal to_string error: do not use Decimal.to_string or integer-like .to_string methods; "
|
| 293 |
+
"format fixed-width fields with format(int(cents), \"09d\") and format(count, \"02d\")."
|
| 294 |
+
)
|
| 295 |
+
if "NameError: name 'Decimal' is not defined" in errors:
|
| 296 |
+
lines.append("- Decimal NameError: include from decimal import Decimal at module scope if Decimal is used.")
|
| 297 |
+
if "cannot access local variable 'record'" in errors:
|
| 298 |
+
lines.append(
|
| 299 |
+
"- UnboundLocalError for record: do not reference record while constructing it. "
|
| 300 |
+
"Assign count = int(input_record[6:8]) before building lists, then iterate with for idx in range(count) and start = 8 + idx * 9."
|
| 301 |
+
)
|
| 302 |
+
if "KeyError" in errors and ("TAX-CODE" in errors or re.search(r"KeyError: ['\"][A-Z0-9]['\"]", errors)):
|
| 303 |
+
lines.append("- Tax lookup KeyError: use tax_rates.get(tax_code, Decimal(\"0.0000\")) for unknown/non-taxable codes.")
|
| 304 |
+
if len(lines) == 1:
|
| 305 |
+
lines.append("- No recognized runtime pattern; fix the exception shown in Visible test status/failures before changing formatting.")
|
| 306 |
+
return "\n".join(lines)
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
def build_numeric_layout_reminders(ticket: dict[str, Any], context: dict[str, Any]) -> str:
|
| 310 |
+
lines = ["Numeric layout reminders:"]
|
| 311 |
+
for filename, layout in sorted(context["layouts"].items()):
|
| 312 |
+
for field_path, field in _walk_layout_fields(layout.get("fields", [])):
|
| 313 |
+
scale = _field_scale(field)
|
| 314 |
+
if scale <= 0:
|
| 315 |
+
continue
|
| 316 |
+
divisor = 10**scale
|
| 317 |
+
field_name = field_path[-1]
|
| 318 |
+
lines.append(
|
| 319 |
+
f"- {field_name}: PIC {field['pic']} has implied scale {scale}; "
|
| 320 |
+
f"parse raw digits with Decimal(int(slice)) / Decimal(\"{divisor}\")."
|
| 321 |
+
)
|
| 322 |
+
|
| 323 |
+
for field in ticket.get("output_layout", []):
|
| 324 |
+
pic = str(field.get("pic", ""))
|
| 325 |
+
if not _is_numeric_pic(pic):
|
| 326 |
+
continue
|
| 327 |
+
scale = _pic_implied_scale(pic)
|
| 328 |
+
if scale > 0:
|
| 329 |
+
lines.append(
|
| 330 |
+
f"- {field['name']}: PIC {pic} is {field['length']} fixed-width digits with implied scale {scale}; "
|
| 331 |
+
"format scaled integer digits, not a decimal string."
|
| 332 |
+
)
|
| 333 |
+
else:
|
| 334 |
+
lines.append(
|
| 335 |
+
f"- {field['name']}: PIC {pic} is {field['length']} fixed-width digits; "
|
| 336 |
+
"format exactly that many digits."
|
| 337 |
+
)
|
| 338 |
+
return "\n".join(lines)
|
| 339 |
+
|
| 340 |
+
|
| 341 |
+
def build_diff_repair_checklist(diffs: list[dict[str, Any]]) -> str:
|
| 342 |
+
lines = ["Field diff repair checklist:"]
|
| 343 |
+
for diff_result in diffs:
|
| 344 |
+
for field_diff in diff_result.get("field_diffs", []):
|
| 345 |
+
field_name = field_diff.get("field")
|
| 346 |
+
expected = field_diff.get("expected")
|
| 347 |
+
actual = field_diff.get("actual")
|
| 348 |
+
if isinstance(expected, str) and expected.isdigit() and isinstance(actual, str) and not actual.isdigit():
|
| 349 |
+
lines.append(
|
| 350 |
+
f"- {field_name}: expected all digits {expected!r}, but actual was {actual!r}; "
|
| 351 |
+
"emit scaled integer digits with no decimal point or spaces."
|
| 352 |
+
)
|
| 353 |
+
elif field_name:
|
| 354 |
+
lines.append(f"- {field_name}: expected {expected!r}, actual {actual!r}; update the code path that produces this field.")
|
| 355 |
+
if len(lines) == 1:
|
| 356 |
+
lines.append("- No structured field mismatch was available; repair the runtime or interface error first.")
|
| 357 |
+
return "\n".join(lines)
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
def _visible_status_for_prompt(visible: dict[str, Any]) -> dict[str, Any]:
|
| 361 |
+
keys = [
|
| 362 |
+
"passed",
|
| 363 |
+
"total",
|
| 364 |
+
"pass_rate",
|
| 365 |
+
"syntax_ok",
|
| 366 |
+
"safety_ok",
|
| 367 |
+
"interface_ok",
|
| 368 |
+
"timed_out",
|
| 369 |
+
"error",
|
| 370 |
+
]
|
| 371 |
+
return {key: visible.get(key) for key in keys if key in visible}
|
| 372 |
+
|
| 373 |
+
|
| 374 |
+
def _walk_layout_fields(fields: list[dict[str, Any]], prefix: tuple[str, ...] = ()) -> list[tuple[tuple[str, ...], dict[str, Any]]]:
|
| 375 |
+
walked = []
|
| 376 |
+
for field in fields:
|
| 377 |
+
path = (*prefix, field["name"])
|
| 378 |
+
walked.append((path, field))
|
| 379 |
+
children = field.get("children")
|
| 380 |
+
if children:
|
| 381 |
+
walked.extend(_walk_layout_fields(children, path))
|
| 382 |
+
return walked
|
| 383 |
+
|
| 384 |
+
|
| 385 |
+
def _field_scale(field: dict[str, Any]) -> int:
|
| 386 |
+
if isinstance(field.get("scale"), int):
|
| 387 |
+
return field["scale"]
|
| 388 |
+
return _pic_implied_scale(str(field.get("pic", "")))
|
| 389 |
+
|
| 390 |
+
|
| 391 |
+
def _pic_implied_scale(pic: str) -> int:
|
| 392 |
+
upper = pic.upper()
|
| 393 |
+
if "V" not in upper:
|
| 394 |
+
return 0
|
| 395 |
+
after_decimal = upper.split("V", 1)[1]
|
| 396 |
+
return sum(int(match.group(1) or 1) for match in re.finditer(r"9(?:\((\d+)\))?", after_decimal))
|
| 397 |
+
|
| 398 |
+
|
| 399 |
+
def _is_numeric_pic(pic: str) -> bool:
|
| 400 |
+
return pic.strip().upper().lstrip("S").startswith("9")
|
| 401 |
+
|
| 402 |
+
|
| 403 |
+
def _remove_unused_disallowed_imports(code: str) -> str:
|
| 404 |
+
try:
|
| 405 |
+
tree = ast.parse(code)
|
| 406 |
+
except SyntaxError:
|
| 407 |
+
return code
|
| 408 |
+
|
| 409 |
+
import_lines: set[int] = set()
|
| 410 |
+
imported_names: dict[str, str] = {}
|
| 411 |
+
for node in tree.body:
|
| 412 |
+
if isinstance(node, ast.Import):
|
| 413 |
+
for alias in node.names:
|
| 414 |
+
root = alias.name.split(".", 1)[0]
|
| 415 |
+
if root in FORBIDDEN_IMPORTS or root not in ALLOWED_IMPORTS:
|
| 416 |
+
imported_names[alias.asname or root] = root
|
| 417 |
+
if node.lineno:
|
| 418 |
+
import_lines.add(node.lineno)
|
| 419 |
+
elif isinstance(node, ast.ImportFrom):
|
| 420 |
+
root = (node.module or "").split(".", 1)[0]
|
| 421 |
+
if root in FORBIDDEN_IMPORTS or root not in ALLOWED_IMPORTS:
|
| 422 |
+
for alias in node.names:
|
| 423 |
+
imported_names[alias.asname or alias.name] = root
|
| 424 |
+
if node.lineno:
|
| 425 |
+
import_lines.add(node.lineno)
|
| 426 |
+
|
| 427 |
+
if not imported_names:
|
| 428 |
+
return code
|
| 429 |
+
|
| 430 |
+
used_names = {
|
| 431 |
+
node.id
|
| 432 |
+
for node in ast.walk(tree)
|
| 433 |
+
if isinstance(node, ast.Name) and node.id in imported_names and node.lineno not in import_lines
|
| 434 |
+
}
|
| 435 |
+
removable_lines = {
|
| 436 |
+
line
|
| 437 |
+
for line in import_lines
|
| 438 |
+
if not any(
|
| 439 |
+
isinstance(node, (ast.Import, ast.ImportFrom))
|
| 440 |
+
and node.lineno == line
|
| 441 |
+
and any((alias.asname or alias.name.split(".", 1)[0]) in used_names for alias in node.names)
|
| 442 |
+
for node in tree.body
|
| 443 |
+
)
|
| 444 |
+
}
|
| 445 |
+
if not removable_lines:
|
| 446 |
+
return code
|
| 447 |
+
|
| 448 |
+
lines = code.splitlines(keepends=True)
|
| 449 |
+
return "".join(line for index, line in enumerate(lines, start=1) if index not in removable_lines)
|
| 450 |
+
|
| 451 |
+
|
| 452 |
+
def _strip_fence(text: str) -> str:
|
| 453 |
+
if not text.startswith("```"):
|
| 454 |
+
return text
|
| 455 |
+
lines = text.splitlines()
|
| 456 |
+
if lines:
|
| 457 |
+
lines = lines[1:]
|
| 458 |
+
if lines and lines[-1].startswith("```"):
|
| 459 |
+
lines = lines[:-1]
|
| 460 |
+
return "\n".join(lines)
|
eval/oracle_solutions.py
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Deterministic reference candidate solutions for sanity and demo traces."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
from legacy_cobol_env.server.task_bank import TaskInstance
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
PAYROLL_SOLUTION = r'''
|
| 9 |
+
from decimal import Decimal, ROUND_HALF_UP
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def migrate(input_record: str) -> str:
|
| 13 |
+
emp_id = input_record[0:6]
|
| 14 |
+
emp_name = input_record[6:18]
|
| 15 |
+
gross = Decimal(int(input_record[18:27])) / Decimal("100")
|
| 16 |
+
tax_rate = Decimal(int(input_record[27:31])) / Decimal("1000")
|
| 17 |
+
raw_deductions = input_record[31:39]
|
| 18 |
+
sign = -1 if raw_deductions[0] == "-" else 1
|
| 19 |
+
deductions = Decimal(sign * int(raw_deductions[1:])) / Decimal("100")
|
| 20 |
+
tax = (gross * tax_rate).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
|
| 21 |
+
net = gross - tax - deductions
|
| 22 |
+
if input_record[39:40] == "Y":
|
| 23 |
+
net += Decimal("50.00")
|
| 24 |
+
if net < 0:
|
| 25 |
+
net = Decimal("0.00")
|
| 26 |
+
if net >= Decimal("5000.00"):
|
| 27 |
+
category = "H"
|
| 28 |
+
elif net >= Decimal("2500.00"):
|
| 29 |
+
category = "M"
|
| 30 |
+
else:
|
| 31 |
+
category = "L"
|
| 32 |
+
cents = int((net * 100).quantize(Decimal("1"), rounding=ROUND_HALF_UP))
|
| 33 |
+
return f"{emp_id}{emp_name[:12].ljust(12)}{cents:09d}{category}"
|
| 34 |
+
'''
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
CUSTOMER_SOLUTION = r'''
|
| 38 |
+
def migrate(input_record: str) -> str:
|
| 39 |
+
cust_id = input_record[0:5]
|
| 40 |
+
first = input_record[5:15].rstrip()
|
| 41 |
+
last = input_record[15:27].rstrip()
|
| 42 |
+
zip_code = input_record[27:32]
|
| 43 |
+
status = {"A": "O", "S": "S"}.get(input_record[32:33], "C")
|
| 44 |
+
balance = int(input_record[33:40])
|
| 45 |
+
full_name = f"{last}, {first}"[:22].ljust(22)
|
| 46 |
+
return f"{cust_id}{full_name}{zip_code}{status}{balance:08d}"
|
| 47 |
+
'''
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
CLAIMS_SOLUTION = r'''
|
| 51 |
+
def migrate(input_record: str) -> str:
|
| 52 |
+
claim_id = input_record[0:6]
|
| 53 |
+
age = int(input_record[6:9])
|
| 54 |
+
plan = input_record[9:10]
|
| 55 |
+
days = int(input_record[10:13])
|
| 56 |
+
preauth = input_record[13:14]
|
| 57 |
+
amount_cents = int(input_record[14:21])
|
| 58 |
+
if age < 18:
|
| 59 |
+
decision, reason = "D", "A1"
|
| 60 |
+
elif plan == "B" and amount_cents > 150000:
|
| 61 |
+
decision, reason = "R", "B2"
|
| 62 |
+
elif preauth == "N" and amount_cents > 100000:
|
| 63 |
+
decision, reason = "D", "P1"
|
| 64 |
+
elif days > 30:
|
| 65 |
+
decision, reason = "R", "L1"
|
| 66 |
+
else:
|
| 67 |
+
decision, reason = "A", "OK"
|
| 68 |
+
return f"{claim_id}{decision}{reason}"
|
| 69 |
+
'''
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
ACCOUNT_SOLUTION = r'''
|
| 73 |
+
def migrate(input_record: str) -> str:
|
| 74 |
+
account_id = input_record[0:6]
|
| 75 |
+
status = input_record[6:7]
|
| 76 |
+
raw_balance = input_record[7:16]
|
| 77 |
+
sign = -1 if raw_balance[0] == "-" else 1
|
| 78 |
+
balance_cents = sign * int(raw_balance[1:])
|
| 79 |
+
days = int(input_record[16:19])
|
| 80 |
+
if status == "C":
|
| 81 |
+
category, action = "CL", "N"
|
| 82 |
+
elif status == "F":
|
| 83 |
+
category, action = "FR", "H"
|
| 84 |
+
elif days >= 90:
|
| 85 |
+
category, action = "DL", "C"
|
| 86 |
+
elif balance_cents < 0:
|
| 87 |
+
category, action = "OD", "R"
|
| 88 |
+
else:
|
| 89 |
+
category, action = "OK", "N"
|
| 90 |
+
return f"{account_id}{category}{action}"
|
| 91 |
+
'''
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
INVOICE_SOLUTION = r'''
|
| 95 |
+
from decimal import Decimal, ROUND_HALF_UP
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def migrate(input_record: str) -> str:
|
| 99 |
+
invoice_id = input_record[0:6]
|
| 100 |
+
count = min(int(input_record[6:8]), 4)
|
| 101 |
+
tax_rates = {
|
| 102 |
+
"S": Decimal("0.0725"),
|
| 103 |
+
"R": Decimal("0.0250"),
|
| 104 |
+
"L": Decimal("0.1000"),
|
| 105 |
+
}
|
| 106 |
+
total = Decimal("0.00")
|
| 107 |
+
for idx in range(count):
|
| 108 |
+
start = 8 + idx * 9
|
| 109 |
+
qty = int(input_record[start:start + 2])
|
| 110 |
+
price = Decimal(int(input_record[start + 2:start + 8])) / Decimal("100")
|
| 111 |
+
tax_code = input_record[start + 8:start + 9]
|
| 112 |
+
line = (Decimal(qty) * price).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
|
| 113 |
+
tax = (line * tax_rates.get(tax_code, Decimal("0.0000"))).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
|
| 114 |
+
line += tax
|
| 115 |
+
total += line
|
| 116 |
+
cents = int((total * 100).quantize(Decimal("1"), rounding=ROUND_HALF_UP))
|
| 117 |
+
flag = "H" if total >= Decimal("1000.00") else "L"
|
| 118 |
+
return f"{invoice_id}{cents:09d}{count:02d}{flag}"
|
| 119 |
+
'''
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
DATE_SOLUTION = r'''
|
| 123 |
+
def is_leap(year: int) -> bool:
|
| 124 |
+
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
def valid_date(year: int, month: int, day: int) -> bool:
|
| 128 |
+
month_lengths = [31, 29 if is_leap(year) else 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
| 129 |
+
return 1 <= month <= 12 and 1 <= day <= month_lengths[month - 1]
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def migrate(input_record: str) -> str:
|
| 133 |
+
policy_id = input_record[0:6]
|
| 134 |
+
raw = input_record[6:12]
|
| 135 |
+
window = int(input_record[12:14])
|
| 136 |
+
amount = input_record[14:21]
|
| 137 |
+
yy = int(raw[0:2])
|
| 138 |
+
mm = int(raw[2:4])
|
| 139 |
+
dd = int(raw[4:6])
|
| 140 |
+
year = 1900 + yy if yy >= window else 2000 + yy
|
| 141 |
+
normalized = f"{year:04d}{mm:02d}{dd:02d}" if valid_date(year, mm, dd) else "00000000"
|
| 142 |
+
valid = "Y" if normalized != "00000000" else "N"
|
| 143 |
+
return f"{policy_id}{normalized}{valid}{amount}"
|
| 144 |
+
'''
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
SOLUTIONS_BY_FAMILY = {
|
| 148 |
+
"decimal_copybook_payroll": PAYROLL_SOLUTION,
|
| 149 |
+
"fixed_width_customer": CUSTOMER_SOLUTION,
|
| 150 |
+
"claims_eligibility_branching": CLAIMS_SOLUTION,
|
| 151 |
+
"account_status_level88": ACCOUNT_SOLUTION,
|
| 152 |
+
"invoice_occurs_totals": INVOICE_SOLUTION,
|
| 153 |
+
"date_normalization": DATE_SOLUTION,
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
def solution_for_task(task: TaskInstance) -> str:
|
| 158 |
+
try:
|
| 159 |
+
return SOLUTIONS_BY_FAMILY[task.family_id].strip() + "\n"
|
| 160 |
+
except KeyError as exc:
|
| 161 |
+
raise ValueError(f"no oracle solution for family: {task.family_id}") from exc
|
eval/providers.py
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Provider adapters for model-driven evaluation rollouts."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import json
|
| 6 |
+
import urllib.error
|
| 7 |
+
import urllib.request
|
| 8 |
+
from dataclasses import dataclass
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
from typing import Mapping, Protocol
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class TextProvider(Protocol):
|
| 14 |
+
name: str
|
| 15 |
+
|
| 16 |
+
def generate(self, prompt: str) -> str:
|
| 17 |
+
"""Return provider text for one migration prompt."""
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
@dataclass(frozen=True)
|
| 21 |
+
class StaticResponseProvider:
|
| 22 |
+
name: str
|
| 23 |
+
response: str
|
| 24 |
+
|
| 25 |
+
def generate(self, prompt: str) -> str:
|
| 26 |
+
return self.response
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
@dataclass
|
| 30 |
+
class SequenceResponseProvider:
|
| 31 |
+
name: str
|
| 32 |
+
responses: list[str]
|
| 33 |
+
index: int = 0
|
| 34 |
+
|
| 35 |
+
def generate(self, prompt: str) -> str:
|
| 36 |
+
if self.index >= len(self.responses):
|
| 37 |
+
return self.responses[-1]
|
| 38 |
+
response = self.responses[self.index]
|
| 39 |
+
self.index += 1
|
| 40 |
+
return response
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
@dataclass(frozen=True)
|
| 44 |
+
class AzureOpenAIProvider:
|
| 45 |
+
endpoint: str
|
| 46 |
+
api_key: str
|
| 47 |
+
deployment: str
|
| 48 |
+
api_version: str = "2024-02-15-preview"
|
| 49 |
+
name: str = "azure-openai"
|
| 50 |
+
timeout_s: float = 60.0
|
| 51 |
+
|
| 52 |
+
def generate(self, prompt: str) -> str:
|
| 53 |
+
url = (
|
| 54 |
+
f"{self.endpoint.rstrip('/')}/openai/deployments/{self.deployment}"
|
| 55 |
+
f"/chat/completions?api-version={self.api_version}"
|
| 56 |
+
)
|
| 57 |
+
payload = {
|
| 58 |
+
"messages": [
|
| 59 |
+
{
|
| 60 |
+
"role": "system",
|
| 61 |
+
"content": "Return only JSON with a single code field containing a Python migrate function.",
|
| 62 |
+
},
|
| 63 |
+
{"role": "user", "content": prompt},
|
| 64 |
+
],
|
| 65 |
+
"temperature": 0,
|
| 66 |
+
}
|
| 67 |
+
data = _post_json(
|
| 68 |
+
url,
|
| 69 |
+
payload,
|
| 70 |
+
headers={"api-key": self.api_key, "Content-Type": "application/json"},
|
| 71 |
+
timeout_s=self.timeout_s,
|
| 72 |
+
)
|
| 73 |
+
return data["choices"][0]["message"]["content"]
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
@dataclass(frozen=True)
|
| 77 |
+
class HuggingFaceEndpointProvider:
|
| 78 |
+
endpoint: str
|
| 79 |
+
token: str
|
| 80 |
+
name: str = "hf-endpoint"
|
| 81 |
+
timeout_s: float = 60.0
|
| 82 |
+
|
| 83 |
+
def generate(self, prompt: str) -> str:
|
| 84 |
+
data = _post_json(
|
| 85 |
+
self.endpoint,
|
| 86 |
+
{"inputs": prompt, "parameters": {"temperature": 0.0, "max_new_tokens": 1800}},
|
| 87 |
+
headers={"Authorization": f"Bearer {self.token}", "Content-Type": "application/json"},
|
| 88 |
+
timeout_s=self.timeout_s,
|
| 89 |
+
)
|
| 90 |
+
if isinstance(data, list) and data and "generated_text" in data[0]:
|
| 91 |
+
return data[0]["generated_text"]
|
| 92 |
+
if isinstance(data, dict) and "generated_text" in data:
|
| 93 |
+
return data["generated_text"]
|
| 94 |
+
if isinstance(data, dict) and "choices" in data:
|
| 95 |
+
return data["choices"][0]["message"]["content"]
|
| 96 |
+
raise ValueError("HF endpoint response did not contain generated text")
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
@dataclass(frozen=True)
|
| 100 |
+
class HuggingFaceChatProvider:
|
| 101 |
+
model: str
|
| 102 |
+
token: str
|
| 103 |
+
provider: str | None = None
|
| 104 |
+
name: str = "hf-chat"
|
| 105 |
+
timeout_s: float = 120.0
|
| 106 |
+
max_tokens: int = 2200
|
| 107 |
+
temperature: float = 0.1
|
| 108 |
+
top_p: float = 0.9
|
| 109 |
+
|
| 110 |
+
def generate(self, prompt: str) -> str:
|
| 111 |
+
try:
|
| 112 |
+
from huggingface_hub import InferenceClient
|
| 113 |
+
except ImportError as exc:
|
| 114 |
+
raise RuntimeError("install huggingface_hub to use hf-chat provider") from exc
|
| 115 |
+
|
| 116 |
+
client = InferenceClient(
|
| 117 |
+
model=self.model,
|
| 118 |
+
provider=self.provider or "auto",
|
| 119 |
+
token=self.token,
|
| 120 |
+
timeout=self.timeout_s,
|
| 121 |
+
)
|
| 122 |
+
response = client.chat_completion(
|
| 123 |
+
messages=[
|
| 124 |
+
{
|
| 125 |
+
"role": "system",
|
| 126 |
+
"content": "Return only JSON with a single code field containing a Python migrate function.",
|
| 127 |
+
},
|
| 128 |
+
{"role": "user", "content": prompt},
|
| 129 |
+
],
|
| 130 |
+
max_tokens=self.max_tokens,
|
| 131 |
+
temperature=self.temperature,
|
| 132 |
+
top_p=self.top_p,
|
| 133 |
+
)
|
| 134 |
+
return _chat_completion_content(response)
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
@dataclass
|
| 138 |
+
class LocalTransformersProvider:
|
| 139 |
+
model_path: str
|
| 140 |
+
base_model_path: str | None = None
|
| 141 |
+
name: str = "local-transformers"
|
| 142 |
+
max_new_tokens: int = 1800
|
| 143 |
+
load_in_4bit: bool = True
|
| 144 |
+
do_sample: bool = False
|
| 145 |
+
temperature: float = 0.2
|
| 146 |
+
top_p: float = 0.95
|
| 147 |
+
_model: object | None = None
|
| 148 |
+
_tokenizer: object | None = None
|
| 149 |
+
|
| 150 |
+
def generate(self, prompt: str) -> str:
|
| 151 |
+
tokenizer, model = self._load()
|
| 152 |
+
prompt_text = self._format_prompt(tokenizer, prompt)
|
| 153 |
+
inputs = tokenizer(prompt_text, return_tensors="pt")
|
| 154 |
+
inputs = inputs.to(model.device) if hasattr(inputs, "to") else inputs
|
| 155 |
+
generation_kwargs = {
|
| 156 |
+
"max_new_tokens": self.max_new_tokens,
|
| 157 |
+
"pad_token_id": tokenizer.eos_token_id,
|
| 158 |
+
"do_sample": self.do_sample,
|
| 159 |
+
}
|
| 160 |
+
if self.do_sample:
|
| 161 |
+
generation_kwargs["temperature"] = self.temperature
|
| 162 |
+
generation_kwargs["top_p"] = self.top_p
|
| 163 |
+
output_ids = model.generate(
|
| 164 |
+
**inputs,
|
| 165 |
+
**generation_kwargs,
|
| 166 |
+
)
|
| 167 |
+
prompt_length = inputs["input_ids"].shape[-1]
|
| 168 |
+
generated = output_ids[0][prompt_length:]
|
| 169 |
+
return tokenizer.decode(generated, skip_special_tokens=True)
|
| 170 |
+
|
| 171 |
+
def _format_prompt(self, tokenizer: object, prompt: str) -> str:
|
| 172 |
+
messages = [
|
| 173 |
+
{
|
| 174 |
+
"role": "system",
|
| 175 |
+
"content": "Return only JSON with a single code field containing a Python migrate function.",
|
| 176 |
+
},
|
| 177 |
+
{"role": "user", "content": prompt},
|
| 178 |
+
]
|
| 179 |
+
if hasattr(tokenizer, "apply_chat_template"):
|
| 180 |
+
return tokenizer.apply_chat_template(
|
| 181 |
+
messages,
|
| 182 |
+
tokenize=False,
|
| 183 |
+
add_generation_prompt=True,
|
| 184 |
+
)
|
| 185 |
+
return prompt
|
| 186 |
+
|
| 187 |
+
def _load(self) -> tuple[object, object]:
|
| 188 |
+
if self._model is not None and self._tokenizer is not None:
|
| 189 |
+
return self._tokenizer, self._model
|
| 190 |
+
try:
|
| 191 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 192 |
+
except ImportError as exc:
|
| 193 |
+
raise RuntimeError("install training/requirements-gpu.txt to use local-transformers") from exc
|
| 194 |
+
quantization_config = self._quantization_config()
|
| 195 |
+
adapter_base = self._adapter_base_model_path()
|
| 196 |
+
if adapter_base:
|
| 197 |
+
try:
|
| 198 |
+
from peft import PeftModel
|
| 199 |
+
except ImportError as exc:
|
| 200 |
+
raise RuntimeError("install peft from training/requirements-gpu.txt to load LoRA adapters") from exc
|
| 201 |
+
tokenizer = AutoTokenizer.from_pretrained(self.model_path, trust_remote_code=True)
|
| 202 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 203 |
+
adapter_base,
|
| 204 |
+
device_map="auto",
|
| 205 |
+
quantization_config=quantization_config,
|
| 206 |
+
trust_remote_code=True,
|
| 207 |
+
)
|
| 208 |
+
model = PeftModel.from_pretrained(model, self.model_path)
|
| 209 |
+
else:
|
| 210 |
+
tokenizer = AutoTokenizer.from_pretrained(self.model_path, trust_remote_code=True)
|
| 211 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 212 |
+
self.model_path,
|
| 213 |
+
device_map="auto",
|
| 214 |
+
quantization_config=quantization_config,
|
| 215 |
+
trust_remote_code=True,
|
| 216 |
+
)
|
| 217 |
+
self._tokenizer = tokenizer
|
| 218 |
+
self._model = model
|
| 219 |
+
return tokenizer, model
|
| 220 |
+
|
| 221 |
+
def _adapter_base_model_path(self) -> str | None:
|
| 222 |
+
if self.base_model_path:
|
| 223 |
+
return self.base_model_path
|
| 224 |
+
config_path = Path(self.model_path) / "adapter_config.json"
|
| 225 |
+
if not config_path.exists():
|
| 226 |
+
return None
|
| 227 |
+
data = json.loads(config_path.read_text(encoding="utf-8"))
|
| 228 |
+
return data.get("base_model_name_or_path")
|
| 229 |
+
|
| 230 |
+
def _quantization_config(self) -> object | None:
|
| 231 |
+
if not self.load_in_4bit:
|
| 232 |
+
return None
|
| 233 |
+
try:
|
| 234 |
+
from transformers import BitsAndBytesConfig
|
| 235 |
+
except ImportError as exc:
|
| 236 |
+
raise RuntimeError("install bitsandbytes and transformers from training/requirements-gpu.txt") from exc
|
| 237 |
+
return BitsAndBytesConfig(
|
| 238 |
+
load_in_4bit=True,
|
| 239 |
+
bnb_4bit_quant_type="nf4",
|
| 240 |
+
bnb_4bit_compute_dtype="bfloat16",
|
| 241 |
+
)
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
def create_provider(kind: str, env: Mapping[str, str]) -> TextProvider:
|
| 245 |
+
if kind == "azure-openai":
|
| 246 |
+
required = ["AZURE_OPENAI_ENDPOINT", "AZURE_OPENAI_API_KEY", "AZURE_OPENAI_DEPLOYMENT"]
|
| 247 |
+
missing = [key for key in required if not env.get(key)]
|
| 248 |
+
if missing:
|
| 249 |
+
raise ValueError(f"missing Azure OpenAI configuration: {', '.join(missing)}")
|
| 250 |
+
return AzureOpenAIProvider(
|
| 251 |
+
endpoint=env["AZURE_OPENAI_ENDPOINT"],
|
| 252 |
+
api_key=env["AZURE_OPENAI_API_KEY"],
|
| 253 |
+
deployment=env["AZURE_OPENAI_DEPLOYMENT"],
|
| 254 |
+
api_version=env.get("AZURE_OPENAI_API_VERSION", "2024-02-15-preview"),
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
+
if kind == "hf-endpoint":
|
| 258 |
+
required = ["HF_INFERENCE_ENDPOINT", "HF_TOKEN"]
|
| 259 |
+
missing = [key for key in required if not env.get(key)]
|
| 260 |
+
if missing:
|
| 261 |
+
raise ValueError(f"missing Hugging Face endpoint configuration: {', '.join(missing)}")
|
| 262 |
+
return HuggingFaceEndpointProvider(
|
| 263 |
+
endpoint=env["HF_INFERENCE_ENDPOINT"],
|
| 264 |
+
token=env["HF_TOKEN"],
|
| 265 |
+
)
|
| 266 |
+
|
| 267 |
+
if kind == "hf-chat":
|
| 268 |
+
required = ["HF_MODEL", "HF_TOKEN"]
|
| 269 |
+
missing = [key for key in required if not env.get(key)]
|
| 270 |
+
if missing:
|
| 271 |
+
raise ValueError(f"missing Hugging Face chat configuration: {', '.join(missing)}")
|
| 272 |
+
return HuggingFaceChatProvider(
|
| 273 |
+
model=env["HF_MODEL"],
|
| 274 |
+
token=env["HF_TOKEN"],
|
| 275 |
+
provider=env.get("HF_PROVIDER"),
|
| 276 |
+
timeout_s=float(env.get("HF_TIMEOUT_S", "120")),
|
| 277 |
+
max_tokens=int(env.get("HF_MAX_TOKENS", "2200")),
|
| 278 |
+
temperature=float(env.get("HF_TEMPERATURE", "0.1")),
|
| 279 |
+
top_p=float(env.get("HF_TOP_P", "0.9")),
|
| 280 |
+
)
|
| 281 |
+
|
| 282 |
+
if kind == "static":
|
| 283 |
+
return StaticResponseProvider("static", env.get("STATIC_RESPONSE", '{"code": "def migrate(input_record: str) -> str:\\n return input_record\\n"}'))
|
| 284 |
+
|
| 285 |
+
if kind == "local-transformers":
|
| 286 |
+
if not env.get("LOCAL_MODEL_PATH"):
|
| 287 |
+
raise ValueError("missing local Transformers configuration: LOCAL_MODEL_PATH")
|
| 288 |
+
return LocalTransformersProvider(
|
| 289 |
+
model_path=env["LOCAL_MODEL_PATH"],
|
| 290 |
+
base_model_path=env.get("LOCAL_BASE_MODEL_PATH"),
|
| 291 |
+
max_new_tokens=int(env.get("LOCAL_MAX_NEW_TOKENS", "1800")),
|
| 292 |
+
load_in_4bit=env.get("LOCAL_LOAD_IN_4BIT", "1").lower() not in {"0", "false", "no"},
|
| 293 |
+
do_sample=env.get("LOCAL_DO_SAMPLE", "0").lower() in {"1", "true", "yes"},
|
| 294 |
+
temperature=float(env.get("LOCAL_TEMPERATURE", "0.2")),
|
| 295 |
+
top_p=float(env.get("LOCAL_TOP_P", "0.95")),
|
| 296 |
+
)
|
| 297 |
+
|
| 298 |
+
raise ValueError(f"unknown provider: {kind}")
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
def _chat_completion_content(response: object) -> str:
|
| 302 |
+
choices = getattr(response, "choices", None)
|
| 303 |
+
if choices is None and isinstance(response, dict):
|
| 304 |
+
choices = response.get("choices")
|
| 305 |
+
if not choices:
|
| 306 |
+
raise ValueError("HF chat response did not contain choices")
|
| 307 |
+
|
| 308 |
+
first = choices[0]
|
| 309 |
+
message = getattr(first, "message", None)
|
| 310 |
+
if message is None and isinstance(first, dict):
|
| 311 |
+
message = first.get("message")
|
| 312 |
+
content = getattr(message, "content", None)
|
| 313 |
+
if content is None and isinstance(message, dict):
|
| 314 |
+
content = message.get("content")
|
| 315 |
+
if not isinstance(content, str):
|
| 316 |
+
raise ValueError("HF chat response did not contain message content")
|
| 317 |
+
return content
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
def _post_json(url: str, payload: object, headers: dict[str, str], timeout_s: float) -> object:
|
| 321 |
+
request = urllib.request.Request(
|
| 322 |
+
url,
|
| 323 |
+
data=json.dumps(payload).encode("utf-8"),
|
| 324 |
+
headers=headers,
|
| 325 |
+
method="POST",
|
| 326 |
+
)
|
| 327 |
+
try:
|
| 328 |
+
with urllib.request.urlopen(request, timeout=timeout_s) as response:
|
| 329 |
+
return json.loads(response.read().decode("utf-8"))
|
| 330 |
+
except urllib.error.HTTPError as exc:
|
| 331 |
+
body = exc.read().decode("utf-8", errors="replace")
|
| 332 |
+
raise RuntimeError(f"provider HTTP {exc.code}: {body}") from exc
|
eval/run_baselines.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Run deterministic non-model baselines across all task families.
|
| 2 |
+
|
| 3 |
+
This is not the final training evidence. It gives the project a repeatable
|
| 4 |
+
evaluation harness so baseline, SFT, and RL runs can share one result shape.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from __future__ import annotations
|
| 8 |
+
|
| 9 |
+
import json
|
| 10 |
+
from pathlib import Path
|
| 11 |
+
from statistics import mean
|
| 12 |
+
|
| 13 |
+
from openenv.core.env_server.mcp_types import CallToolAction
|
| 14 |
+
|
| 15 |
+
from legacy_cobol_env.server.legacy_cobol_env_environment import LegacyCobolEnvironment
|
| 16 |
+
from legacy_cobol_env.server.task_bank import all_tasks
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
ENV_ROOT = Path(__file__).resolve().parents[1]
|
| 20 |
+
OUTPUT_DIR = ENV_ROOT / "outputs" / "evals"
|
| 21 |
+
PLOT_DIR = ENV_ROOT / "plots"
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def call(env: LegacyCobolEnvironment, tool_name: str, **arguments):
|
| 25 |
+
obs = env.step(CallToolAction(tool_name=tool_name, arguments=arguments))
|
| 26 |
+
return obs.result.data
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def identity_solution() -> str:
|
| 30 |
+
return """def migrate(input_record: str) -> str:
|
| 31 |
+
return input_record
|
| 32 |
+
"""
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def blank_width_solution(width: int) -> str:
|
| 36 |
+
return f"""def migrate(input_record: str) -> str:
|
| 37 |
+
return " " * {width}
|
| 38 |
+
"""
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def run_policy(policy_name: str, task, code: str) -> dict:
|
| 42 |
+
env = LegacyCobolEnvironment()
|
| 43 |
+
env.reset(task_id=task.task_id)
|
| 44 |
+
written = call(env, "write_python_solution", code=code)
|
| 45 |
+
visible = call(env, "run_visible_tests", draft_id=written["draft_id"])
|
| 46 |
+
final = call(env, "submit_final", draft_id=written["draft_id"])
|
| 47 |
+
return {
|
| 48 |
+
"policy": policy_name,
|
| 49 |
+
"task_id": task.task_id,
|
| 50 |
+
"family_id": task.family_id,
|
| 51 |
+
"visible_pass_rate": visible["pass_rate"],
|
| 52 |
+
"public_score": final["public_score"],
|
| 53 |
+
"components": final["components"],
|
| 54 |
+
"accepted": final["accepted"],
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
def write_svg(results: list[dict], path: Path) -> None:
|
| 59 |
+
families = []
|
| 60 |
+
scores_by_policy: dict[str, list[float]] = {}
|
| 61 |
+
for row in results:
|
| 62 |
+
if row["task_id"] not in families:
|
| 63 |
+
families.append(row["task_id"])
|
| 64 |
+
scores_by_policy.setdefault(row["policy"], []).append(row["public_score"])
|
| 65 |
+
|
| 66 |
+
width = 960
|
| 67 |
+
height = 360
|
| 68 |
+
margin = 48
|
| 69 |
+
bar_w = 26
|
| 70 |
+
gap = 22
|
| 71 |
+
colors = {"identity": "#3b82f6", "blank_width": "#10b981"}
|
| 72 |
+
parts = [
|
| 73 |
+
f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}" viewBox="0 0 {width} {height}">',
|
| 74 |
+
'<rect width="100%" height="100%" fill="#ffffff"/>',
|
| 75 |
+
'<text x="48" y="30" font-family="Arial" font-size="18" font-weight="700">Baseline public score by task family</text>',
|
| 76 |
+
f'<line x1="{margin}" y1="{height - margin}" x2="{width - margin}" y2="{height - margin}" stroke="#222"/>',
|
| 77 |
+
f'<line x1="{margin}" y1="{height - margin}" x2="{margin}" y2="{margin}" stroke="#222"/>',
|
| 78 |
+
]
|
| 79 |
+
x = margin + 20
|
| 80 |
+
by_task = {(row["task_id"], row["policy"]): row["public_score"] for row in results}
|
| 81 |
+
for task_id in families:
|
| 82 |
+
for offset, policy in enumerate(scores_by_policy):
|
| 83 |
+
score = by_task[(task_id, policy)]
|
| 84 |
+
bar_h = score * (height - 2 * margin)
|
| 85 |
+
bx = x + offset * (bar_w + 4)
|
| 86 |
+
by = height - margin - bar_h
|
| 87 |
+
parts.append(f'<rect x="{bx}" y="{by:.1f}" width="{bar_w}" height="{bar_h:.1f}" fill="{colors.get(policy, "#64748b")}"/>')
|
| 88 |
+
parts.append(f'<text x="{bx}" y="{by - 4:.1f}" font-family="Arial" font-size="10">{score:.2f}</text>')
|
| 89 |
+
label = task_id.replace("_001", "").replace("_", " ")
|
| 90 |
+
parts.append(f'<text x="{x - 6}" y="{height - 16}" font-family="Arial" font-size="10" transform="rotate(25 {x - 6},{height - 16})">{label}</text>')
|
| 91 |
+
x += len(scores_by_policy) * (bar_w + 4) + gap
|
| 92 |
+
|
| 93 |
+
legend_x = width - 210
|
| 94 |
+
for idx, policy in enumerate(scores_by_policy):
|
| 95 |
+
y = 52 + idx * 20
|
| 96 |
+
parts.append(f'<rect x="{legend_x}" y="{y - 10}" width="12" height="12" fill="{colors.get(policy, "#64748b")}"/>')
|
| 97 |
+
parts.append(f'<text x="{legend_x + 18}" y="{y}" font-family="Arial" font-size="12">{policy}</text>')
|
| 98 |
+
parts.append("</svg>")
|
| 99 |
+
path.write_text("\n".join(parts), encoding="utf-8")
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def main() -> None:
|
| 103 |
+
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
| 104 |
+
PLOT_DIR.mkdir(parents=True, exist_ok=True)
|
| 105 |
+
|
| 106 |
+
results = []
|
| 107 |
+
for task in all_tasks():
|
| 108 |
+
results.append(run_policy("identity", task, identity_solution()))
|
| 109 |
+
results.append(run_policy("blank_width", task, blank_width_solution(task.metadata["output_width"])))
|
| 110 |
+
|
| 111 |
+
summary = {
|
| 112 |
+
"policies": sorted({row["policy"] for row in results}),
|
| 113 |
+
"task_count": len(all_tasks()),
|
| 114 |
+
"mean_public_score": {
|
| 115 |
+
policy: mean(row["public_score"] for row in results if row["policy"] == policy)
|
| 116 |
+
for policy in sorted({row["policy"] for row in results})
|
| 117 |
+
},
|
| 118 |
+
"results": results,
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
(OUTPUT_DIR / "baseline_results.json").write_text(json.dumps(summary, indent=2), encoding="utf-8")
|
| 122 |
+
write_svg(results, PLOT_DIR / "baseline_scores.svg")
|
| 123 |
+
print(json.dumps(summary["mean_public_score"], indent=2))
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
if __name__ == "__main__":
|
| 127 |
+
main()
|
eval/run_cobol_oracle_checks.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Run compiler-backed COBOL oracle checks for the invoice task."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import argparse
|
| 6 |
+
import json
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
|
| 9 |
+
from legacy_cobol_env.eval.cobol_oracle import (
|
| 10 |
+
DEFAULT_IMAGE_TAG,
|
| 11 |
+
compile_invoice_task_sources,
|
| 12 |
+
compare_invoice_oracle,
|
| 13 |
+
write_comparison_report,
|
| 14 |
+
)
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
ENV_ROOT = Path(__file__).resolve().parents[1]
|
| 18 |
+
OUTPUT_DIR = ENV_ROOT / "outputs" / "evals"
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def main() -> None:
|
| 22 |
+
parser = argparse.ArgumentParser()
|
| 23 |
+
parser.add_argument("--build", action="store_true", help="Build the GnuCOBOL oracle image before running")
|
| 24 |
+
parser.add_argument("--image-tag", default=DEFAULT_IMAGE_TAG)
|
| 25 |
+
parser.add_argument("--no-fresh", action="store_true", help="Check only visible and hidden invoice cases")
|
| 26 |
+
parser.add_argument("--output", default=str(OUTPUT_DIR / "cobol_invoice_oracle_check.json"))
|
| 27 |
+
args = parser.parse_args()
|
| 28 |
+
|
| 29 |
+
result = compare_invoice_oracle(
|
| 30 |
+
image_tag=args.image_tag,
|
| 31 |
+
build=args.build,
|
| 32 |
+
include_fresh=not args.no_fresh,
|
| 33 |
+
)
|
| 34 |
+
result["source_compile"] = compile_invoice_task_sources(
|
| 35 |
+
image_tag=args.image_tag,
|
| 36 |
+
build=False,
|
| 37 |
+
)
|
| 38 |
+
result["ok"] = result["ok"] and result["source_compile"]["ok"]
|
| 39 |
+
write_comparison_report(result, Path(args.output))
|
| 40 |
+
print(
|
| 41 |
+
json.dumps(
|
| 42 |
+
{
|
| 43 |
+
"ok": result["ok"],
|
| 44 |
+
"case_count": result["case_count"],
|
| 45 |
+
"passed_count": result["passed_count"],
|
| 46 |
+
"source_compile_ok": result["source_compile"]["ok"],
|
| 47 |
+
},
|
| 48 |
+
indent=2,
|
| 49 |
+
)
|
| 50 |
+
)
|
| 51 |
+
if not result["ok"]:
|
| 52 |
+
raise SystemExit(1)
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
if __name__ == "__main__":
|
| 56 |
+
main()
|
eval/run_evidence_report.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Generate score summary and plot artifacts for the submission."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import json
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
|
| 8 |
+
from legacy_cobol_env.eval.evidence_report import build_score_summary, load_json, write_score_plot
|
| 9 |
+
from legacy_cobol_env.server.task_bank import all_tasks
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
ENV_ROOT = Path(__file__).resolve().parents[1]
|
| 13 |
+
OUTPUT_DIR = ENV_ROOT / "outputs" / "evals"
|
| 14 |
+
TRAINING_DIR = ENV_ROOT / "outputs" / "training"
|
| 15 |
+
HISTORICAL_OUTPUT_DIR = OUTPUT_DIR / "historical"
|
| 16 |
+
PLOT_DIR = ENV_ROOT / "plots"
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def main() -> None:
|
| 20 |
+
baseline = load_json(OUTPUT_DIR / "baseline_results.json")
|
| 21 |
+
evidence_notes = []
|
| 22 |
+
oracle_model = _load_current_rollout(OUTPUT_DIR / "oracle_model_rollouts.json", evidence_notes)
|
| 23 |
+
base_qwen3 = _load_current_rollout(OUTPUT_DIR / "base_qwen3_14b_all_tasks.json", evidence_notes)
|
| 24 |
+
zeroshot = _load_current_rollout(OUTPUT_DIR / "azure_gpt54mini_zeroshot_rollouts.json", evidence_notes)
|
| 25 |
+
repair = _load_current_rollout(OUTPUT_DIR / "azure_gpt54mini_repair1_rollouts.json", evidence_notes)
|
| 26 |
+
trained_summary = _load_training_summary(TRAINING_DIR / "sft_run_metadata.json", evidence_notes)
|
| 27 |
+
_record_historical_artifacts(evidence_notes)
|
| 28 |
+
summary = build_score_summary(
|
| 29 |
+
baseline,
|
| 30 |
+
zeroshot=zeroshot,
|
| 31 |
+
repair=repair,
|
| 32 |
+
oracle_model=oracle_model,
|
| 33 |
+
base_model=base_qwen3,
|
| 34 |
+
trained_summary=trained_summary,
|
| 35 |
+
evidence_notes=evidence_notes,
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
| 39 |
+
PLOT_DIR.mkdir(parents=True, exist_ok=True)
|
| 40 |
+
(OUTPUT_DIR / "score_summary.json").write_text(json.dumps(summary, indent=2), encoding="utf-8")
|
| 41 |
+
write_score_plot(summary, PLOT_DIR / "model_scores.svg")
|
| 42 |
+
print(json.dumps(summary["policies"], indent=2))
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def _load_current_rollout(path: Path, evidence_notes: list[str]) -> dict | None:
|
| 46 |
+
if not path.exists():
|
| 47 |
+
evidence_notes.append(f"missing rollout artifact: {_display_path(path)}")
|
| 48 |
+
return None
|
| 49 |
+
artifact = load_json(path)
|
| 50 |
+
if _matches_current_task_artifacts(artifact):
|
| 51 |
+
return artifact
|
| 52 |
+
evidence_notes.append(f"stale rollout artifact skipped after task hardening: {_display_path(path)}")
|
| 53 |
+
return None
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def _load_training_summary(path: Path, evidence_notes: list[str]) -> dict | None:
|
| 57 |
+
if not path.exists():
|
| 58 |
+
evidence_notes.append(f"missing training metadata: {_display_path(path)}")
|
| 59 |
+
return None
|
| 60 |
+
metadata = load_json(path)
|
| 61 |
+
if metadata.get("status") != "completed":
|
| 62 |
+
evidence_notes.append(f"non-completed training metadata skipped: {_display_path(path)}")
|
| 63 |
+
return None
|
| 64 |
+
return metadata
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def _record_historical_artifacts(evidence_notes: list[str]) -> None:
|
| 68 |
+
if not HISTORICAL_OUTPUT_DIR.exists():
|
| 69 |
+
return
|
| 70 |
+
for path in sorted(HISTORICAL_OUTPUT_DIR.glob("azure_gpt54mini_*.json")):
|
| 71 |
+
evidence_notes.append(f"historical artifact retained outside current score summary: {_display_path(path)}")
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
def _display_path(path: Path) -> str:
|
| 75 |
+
try:
|
| 76 |
+
return path.relative_to(ENV_ROOT).as_posix()
|
| 77 |
+
except ValueError:
|
| 78 |
+
return path.name
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def _matches_current_task_artifacts(artifact: dict) -> bool:
|
| 82 |
+
current = {
|
| 83 |
+
task.task_id: {
|
| 84 |
+
"files": sorted(task.cobol_files),
|
| 85 |
+
"copybooks": sorted(task.copybooks),
|
| 86 |
+
}
|
| 87 |
+
for task in all_tasks()
|
| 88 |
+
}
|
| 89 |
+
trajectories = artifact.get("trajectories", [])
|
| 90 |
+
if len(trajectories) != len(current):
|
| 91 |
+
return False
|
| 92 |
+
for trajectory in trajectories:
|
| 93 |
+
task_id = trajectory.get("task_id")
|
| 94 |
+
ticket = trajectory.get("ticket") or {}
|
| 95 |
+
expected = current.get(task_id)
|
| 96 |
+
if expected is None:
|
| 97 |
+
return False
|
| 98 |
+
if sorted(ticket.get("available_files", [])) != expected["files"]:
|
| 99 |
+
return False
|
| 100 |
+
if sorted(ticket.get("available_copybooks", [])) != expected["copybooks"]:
|
| 101 |
+
return False
|
| 102 |
+
return True
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
if __name__ == "__main__":
|
| 106 |
+
main()
|
eval/run_model_rollouts.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Run provider-backed model rollouts and write evaluation artifacts."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import argparse
|
| 6 |
+
import json
|
| 7 |
+
import os
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
from statistics import mean
|
| 10 |
+
|
| 11 |
+
from legacy_cobol_env.eval.model_rollout import run_model_repair_rollout, run_model_rollout
|
| 12 |
+
from legacy_cobol_env.eval.oracle_solutions import solution_for_task
|
| 13 |
+
from legacy_cobol_env.eval.providers import StaticResponseProvider, create_provider
|
| 14 |
+
from legacy_cobol_env.server.task_bank import all_tasks, load_task
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
ENV_ROOT = Path(__file__).resolve().parents[1]
|
| 18 |
+
OUTPUT_DIR = ENV_ROOT / "outputs" / "evals"
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def run_rollouts(provider_name: str, task_id: str | None = None, max_repairs: int = 0) -> dict:
|
| 22 |
+
tasks = [load_task(task_id=task_id)] if task_id else all_tasks()
|
| 23 |
+
trajectories = []
|
| 24 |
+
for task in tasks:
|
| 25 |
+
provider = (
|
| 26 |
+
StaticResponseProvider("oracle-model", json.dumps({"code": solution_for_task(task)}))
|
| 27 |
+
if provider_name == "oracle-model"
|
| 28 |
+
else create_provider(provider_name, os.environ)
|
| 29 |
+
)
|
| 30 |
+
trajectory = (
|
| 31 |
+
run_model_repair_rollout(task=task, provider=provider, max_repairs=max_repairs)
|
| 32 |
+
if max_repairs > 0
|
| 33 |
+
else run_model_rollout(task=task, provider=provider)
|
| 34 |
+
)
|
| 35 |
+
trajectories.append(trajectory)
|
| 36 |
+
|
| 37 |
+
return {
|
| 38 |
+
"provider": provider_name,
|
| 39 |
+
"max_repairs": max_repairs,
|
| 40 |
+
"task_count": len(trajectories),
|
| 41 |
+
"mean_public_score": mean(item["final"]["public_score"] for item in trajectories),
|
| 42 |
+
"accepted_count": sum(1 for item in trajectories if item["final"]["accepted"]),
|
| 43 |
+
"trajectories": trajectories,
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def main() -> None:
|
| 48 |
+
parser = argparse.ArgumentParser()
|
| 49 |
+
parser.add_argument(
|
| 50 |
+
"--provider",
|
| 51 |
+
default="oracle-model",
|
| 52 |
+
choices=["oracle-model", "static", "azure-openai", "hf-endpoint", "hf-chat", "local-transformers"],
|
| 53 |
+
)
|
| 54 |
+
parser.add_argument("--task-id")
|
| 55 |
+
parser.add_argument("--max-repairs", type=int, default=0)
|
| 56 |
+
parser.add_argument("--output", default=str(OUTPUT_DIR / "model_rollouts.json"))
|
| 57 |
+
args = parser.parse_args()
|
| 58 |
+
|
| 59 |
+
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
| 60 |
+
summary = run_rollouts(provider_name=args.provider, task_id=args.task_id, max_repairs=args.max_repairs)
|
| 61 |
+
output_path = Path(args.output)
|
| 62 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 63 |
+
output_path.write_text(json.dumps(summary, indent=2), encoding="utf-8")
|
| 64 |
+
print(json.dumps({key: summary[key] for key in ["provider", "task_count", "mean_public_score", "accepted_count"]}, indent=2))
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
if __name__ == "__main__":
|
| 68 |
+
main()
|
eval/run_oracles.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Generate oracle trajectories for all task families."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import json
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
from statistics import mean
|
| 8 |
+
|
| 9 |
+
from legacy_cobol_env.eval.oracle_solutions import solution_for_task
|
| 10 |
+
from legacy_cobol_env.eval.trajectory import run_solution_trajectory
|
| 11 |
+
from legacy_cobol_env.server.task_bank import all_tasks
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
ENV_ROOT = Path(__file__).resolve().parents[1]
|
| 15 |
+
OUTPUT_DIR = ENV_ROOT / "outputs" / "evals"
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def run_oracle_evaluation() -> dict:
|
| 19 |
+
trajectories = [
|
| 20 |
+
run_solution_trajectory(
|
| 21 |
+
policy_name="oracle",
|
| 22 |
+
task=task,
|
| 23 |
+
code=solution_for_task(task),
|
| 24 |
+
)
|
| 25 |
+
for task in all_tasks()
|
| 26 |
+
]
|
| 27 |
+
return {
|
| 28 |
+
"policy": "oracle",
|
| 29 |
+
"task_count": len(trajectories),
|
| 30 |
+
"mean_public_score": mean(item["final"]["public_score"] for item in trajectories),
|
| 31 |
+
"accepted_count": sum(1 for item in trajectories if item["final"]["accepted"]),
|
| 32 |
+
"trajectories": trajectories,
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def main() -> None:
|
| 37 |
+
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
| 38 |
+
summary = run_oracle_evaluation()
|
| 39 |
+
output_path = OUTPUT_DIR / "oracle_trajectories.json"
|
| 40 |
+
output_path.write_text(json.dumps(summary, indent=2), encoding="utf-8")
|
| 41 |
+
print(json.dumps({key: summary[key] for key in ["task_count", "mean_public_score", "accepted_count"]}, indent=2))
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
if __name__ == "__main__":
|
| 45 |
+
main()
|
| 46 |
+
|
eval/trajectory.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Reusable tool-call trajectory runner for local and model-driven policies."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
from typing import Any
|
| 6 |
+
|
| 7 |
+
from openenv.core.env_server.mcp_types import CallToolAction
|
| 8 |
+
|
| 9 |
+
from legacy_cobol_env.server.legacy_cobol_env_environment import LegacyCobolEnvironment
|
| 10 |
+
from legacy_cobol_env.server.task_bank import TaskInstance
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def call_tool(env: LegacyCobolEnvironment, tool_name: str, **arguments: Any) -> tuple[dict[str, Any], float, bool]:
|
| 14 |
+
observation = env.step(CallToolAction(tool_name=tool_name, arguments=arguments))
|
| 15 |
+
return observation.result.data, observation.reward, observation.done
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def run_solution_trajectory(
|
| 19 |
+
policy_name: str,
|
| 20 |
+
task: TaskInstance,
|
| 21 |
+
code: str,
|
| 22 |
+
) -> dict[str, Any]:
|
| 23 |
+
env = LegacyCobolEnvironment()
|
| 24 |
+
reset_observation = env.reset(task_id=task.task_id)
|
| 25 |
+
ticket = reset_observation.result["ticket"]
|
| 26 |
+
steps: list[dict[str, Any]] = []
|
| 27 |
+
|
| 28 |
+
def record(tool_name: str, arguments: dict[str, Any]) -> dict[str, Any]:
|
| 29 |
+
result, reward, done = call_tool(env, tool_name, **arguments)
|
| 30 |
+
saved_arguments = dict(arguments)
|
| 31 |
+
if "code" in saved_arguments:
|
| 32 |
+
saved_arguments["code_chars"] = len(saved_arguments.pop("code"))
|
| 33 |
+
steps.append(
|
| 34 |
+
{
|
| 35 |
+
"tool_name": tool_name,
|
| 36 |
+
"arguments": saved_arguments,
|
| 37 |
+
"reward": reward,
|
| 38 |
+
"done": done,
|
| 39 |
+
"result": result,
|
| 40 |
+
}
|
| 41 |
+
)
|
| 42 |
+
return result
|
| 43 |
+
|
| 44 |
+
for filename in ticket["available_files"]:
|
| 45 |
+
record("read_cobol_file", {"filename": filename})
|
| 46 |
+
for filename in ticket["available_copybooks"]:
|
| 47 |
+
record("read_copybook", {"filename": filename})
|
| 48 |
+
record("parse_copybook_layout", {"filename": filename})
|
| 49 |
+
record("inspect_business_rules", {})
|
| 50 |
+
written = record("write_python_solution", {"code": code})
|
| 51 |
+
visible = record("run_visible_tests", {"draft_id": written["draft_id"]})
|
| 52 |
+
final = record("submit_final", {"draft_id": written["draft_id"]})
|
| 53 |
+
|
| 54 |
+
return {
|
| 55 |
+
"policy": policy_name,
|
| 56 |
+
"task_id": task.task_id,
|
| 57 |
+
"family_id": task.family_id,
|
| 58 |
+
"ticket": ticket,
|
| 59 |
+
"visible": {
|
| 60 |
+
"passed": visible["passed"],
|
| 61 |
+
"total": visible["total"],
|
| 62 |
+
"pass_rate": visible["pass_rate"],
|
| 63 |
+
"failures": visible["failures"],
|
| 64 |
+
},
|
| 65 |
+
"final": {
|
| 66 |
+
"public_score": final["public_score"],
|
| 67 |
+
"accepted": final["accepted"],
|
| 68 |
+
"components": final["components"],
|
| 69 |
+
"hidden_passed": final["hidden_passed"],
|
| 70 |
+
"hidden_total": final["hidden_total"],
|
| 71 |
+
"fresh_passed": final["fresh_passed"],
|
| 72 |
+
"fresh_total": final["fresh_total"],
|
| 73 |
+
},
|
| 74 |
+
"steps": steps,
|
| 75 |
+
}
|
| 76 |
+
|
inference.py
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Submission-root inference entrypoint for OpenEnv gates."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import argparse
|
| 6 |
+
import json
|
| 7 |
+
import os
|
| 8 |
+
import sys
|
| 9 |
+
import time
|
| 10 |
+
from dataclasses import dataclass
|
| 11 |
+
from pathlib import Path
|
| 12 |
+
from statistics import mean
|
| 13 |
+
from typing import Any, Mapping, Sequence, TextIO
|
| 14 |
+
from urllib.parse import urlparse
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
ENV_ROOT = Path(__file__).resolve().parent
|
| 18 |
+
PARENT = ENV_ROOT.parent
|
| 19 |
+
if str(PARENT) not in sys.path:
|
| 20 |
+
sys.path.insert(0, str(PARENT))
|
| 21 |
+
|
| 22 |
+
from openai import OpenAI
|
| 23 |
+
|
| 24 |
+
from legacy_cobol_env.eval.model_rollout import run_model_repair_rollout, run_model_rollout
|
| 25 |
+
from legacy_cobol_env.eval.providers import StaticResponseProvider, TextProvider
|
| 26 |
+
from legacy_cobol_env.server.task_bank import TaskInstance, all_tasks, load_task
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
VALID_MARKERS = {"START", "STEP", "END"}
|
| 30 |
+
STATIC_RESPONSE = '{"code": "def migrate(input_record: str) -> str:\\n return input_record\\n"}'
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
@dataclass(frozen=True)
|
| 34 |
+
class RuntimeConfig:
|
| 35 |
+
api_base_url: str
|
| 36 |
+
model_name: str
|
| 37 |
+
hf_token: str
|
| 38 |
+
mode: str
|
| 39 |
+
api_version: str = "2024-12-01-preview"
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def load_runtime_config(env: Mapping[str, str] | None = None, mode: str | None = None) -> RuntimeConfig:
|
| 43 |
+
values = os.environ if env is None else env
|
| 44 |
+
selected_mode = mode or values.get("INFERENCE_MODE") or values.get("MODE") or "live"
|
| 45 |
+
|
| 46 |
+
if selected_mode in {"static", "mock"}:
|
| 47 |
+
return RuntimeConfig(
|
| 48 |
+
api_base_url=values.get("API_BASE_URL", ""),
|
| 49 |
+
model_name=values.get("MODEL_NAME", "static"),
|
| 50 |
+
hf_token=values.get("HF_TOKEN", ""),
|
| 51 |
+
mode=selected_mode,
|
| 52 |
+
api_version=values.get(
|
| 53 |
+
"API_VERSION",
|
| 54 |
+
values.get(
|
| 55 |
+
"OPENAI_API_VERSION",
|
| 56 |
+
values.get("AZURE_OPENAI_API_VERSION", "2024-12-01-preview"),
|
| 57 |
+
),
|
| 58 |
+
),
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
required = ["API_BASE_URL", "MODEL_NAME", "HF_TOKEN"]
|
| 62 |
+
missing = [key for key in required if not values.get(key)]
|
| 63 |
+
if missing:
|
| 64 |
+
raise ValueError(f"missing inference configuration: {', '.join(missing)}")
|
| 65 |
+
|
| 66 |
+
return RuntimeConfig(
|
| 67 |
+
api_base_url=values["API_BASE_URL"],
|
| 68 |
+
model_name=values["MODEL_NAME"],
|
| 69 |
+
hf_token=values["HF_TOKEN"],
|
| 70 |
+
mode=selected_mode,
|
| 71 |
+
api_version=values.get(
|
| 72 |
+
"API_VERSION",
|
| 73 |
+
values.get("OPENAI_API_VERSION", values.get("AZURE_OPENAI_API_VERSION", "2024-12-01-preview")),
|
| 74 |
+
),
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def format_event(marker: str, payload: Mapping[str, object]) -> str:
|
| 79 |
+
if marker not in VALID_MARKERS:
|
| 80 |
+
raise ValueError(f"invalid log marker: {marker}")
|
| 81 |
+
data = json.dumps(dict(payload), sort_keys=True, separators=(",", ":"))
|
| 82 |
+
return f"[{marker}] {data}"
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def build_openai_client(config: RuntimeConfig) -> OpenAI:
|
| 86 |
+
base_url = config.api_base_url.rstrip("/")
|
| 87 |
+
if _is_azure_endpoint(base_url):
|
| 88 |
+
deployment_base = (
|
| 89 |
+
base_url
|
| 90 |
+
if "/openai/deployments/" in base_url
|
| 91 |
+
else f"{base_url}/openai/deployments/{config.model_name}"
|
| 92 |
+
)
|
| 93 |
+
return OpenAI(
|
| 94 |
+
base_url=deployment_base,
|
| 95 |
+
api_key=config.hf_token,
|
| 96 |
+
default_headers={"api-key": config.hf_token},
|
| 97 |
+
default_query={"api-version": config.api_version},
|
| 98 |
+
timeout=60.0,
|
| 99 |
+
)
|
| 100 |
+
return OpenAI(base_url=base_url, api_key=config.hf_token, timeout=60.0)
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
class OpenAITextProvider:
|
| 104 |
+
name = "openai-client"
|
| 105 |
+
|
| 106 |
+
def __init__(self, client: OpenAI, model_name: str) -> None:
|
| 107 |
+
self._client = client
|
| 108 |
+
self._model_name = model_name
|
| 109 |
+
|
| 110 |
+
def generate(self, prompt: str) -> str:
|
| 111 |
+
response = self._client.chat.completions.create(
|
| 112 |
+
model=self._model_name,
|
| 113 |
+
messages=[
|
| 114 |
+
{
|
| 115 |
+
"role": "system",
|
| 116 |
+
"content": "Return only JSON with a single code field containing a Python migrate function.",
|
| 117 |
+
},
|
| 118 |
+
{"role": "user", "content": prompt},
|
| 119 |
+
],
|
| 120 |
+
temperature=0,
|
| 121 |
+
)
|
| 122 |
+
return response.choices[0].message.content or ""
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def build_provider(config: RuntimeConfig) -> TextProvider:
|
| 126 |
+
if config.mode in {"static", "mock"}:
|
| 127 |
+
return StaticResponseProvider(config.mode, STATIC_RESPONSE)
|
| 128 |
+
return OpenAITextProvider(build_openai_client(config), config.model_name)
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
def run_inference(task_id: str | None, max_repairs: int, config: RuntimeConfig) -> dict[str, object]:
|
| 132 |
+
tasks = [load_task(task_id=task_id)] if task_id else all_tasks()
|
| 133 |
+
provider = build_provider(config)
|
| 134 |
+
results = [_run_task(task, provider, max_repairs) for task in tasks]
|
| 135 |
+
|
| 136 |
+
return {
|
| 137 |
+
"mode": config.mode,
|
| 138 |
+
"model_name": config.model_name,
|
| 139 |
+
"max_repairs": max_repairs,
|
| 140 |
+
"task_count": len(results),
|
| 141 |
+
"mean_public_score": mean(item["score"] for item in results) if results else 0.0,
|
| 142 |
+
"accepted_count": sum(1 for item in results if item["accepted"]),
|
| 143 |
+
"results": results,
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def _run_task(task: TaskInstance, provider: TextProvider, max_repairs: int) -> dict[str, Any]:
|
| 148 |
+
started = time.perf_counter()
|
| 149 |
+
try:
|
| 150 |
+
trajectory = (
|
| 151 |
+
run_model_repair_rollout(task=task, provider=provider, max_repairs=max_repairs)
|
| 152 |
+
if max_repairs > 0
|
| 153 |
+
else run_model_rollout(task=task, provider=provider)
|
| 154 |
+
)
|
| 155 |
+
except Exception as exc:
|
| 156 |
+
return {
|
| 157 |
+
"task_id": task.task_id,
|
| 158 |
+
"family_id": task.family_id,
|
| 159 |
+
"difficulty": task.metadata["difficulty"],
|
| 160 |
+
"score": 0.0,
|
| 161 |
+
"accepted": False,
|
| 162 |
+
"duration_s": round(time.perf_counter() - started, 3),
|
| 163 |
+
"error": f"{type(exc).__name__}: {exc}",
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
final = trajectory["final"]
|
| 167 |
+
return {
|
| 168 |
+
"task_id": task.task_id,
|
| 169 |
+
"family_id": task.family_id,
|
| 170 |
+
"difficulty": task.metadata["difficulty"],
|
| 171 |
+
"score": final["public_score"],
|
| 172 |
+
"accepted": final["accepted"],
|
| 173 |
+
"visible_pass_rate": trajectory["visible"]["pass_rate"],
|
| 174 |
+
"duration_s": round(time.perf_counter() - started, 3),
|
| 175 |
+
"trajectory": trajectory,
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def write_output(path: str | None, payload: Mapping[str, object]) -> None:
|
| 180 |
+
if not path:
|
| 181 |
+
return
|
| 182 |
+
output_path = Path(path)
|
| 183 |
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
| 184 |
+
output_path.write_text(json.dumps(dict(payload), sort_keys=True, indent=2) + "\n", encoding="utf-8")
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
def parse_args(argv: Sequence[str] | None = None) -> argparse.Namespace:
|
| 188 |
+
parser = argparse.ArgumentParser(description="Run OpenEnv submission inference gate.")
|
| 189 |
+
parser.add_argument("--task-id")
|
| 190 |
+
parser.add_argument("--max-repairs", type=int, default=0)
|
| 191 |
+
parser.add_argument("--output")
|
| 192 |
+
parser.add_argument("--mode", choices=["live", "static", "mock"])
|
| 193 |
+
return parser.parse_args(argv)
|
| 194 |
+
|
| 195 |
+
|
| 196 |
+
def main(
|
| 197 |
+
argv: Sequence[str] | None = None,
|
| 198 |
+
env: Mapping[str, str] | None = None,
|
| 199 |
+
stdout: TextIO | None = None,
|
| 200 |
+
) -> int:
|
| 201 |
+
args = parse_args(argv)
|
| 202 |
+
stream = sys.stdout if stdout is None else stdout
|
| 203 |
+
config = load_runtime_config(env, mode=args.mode)
|
| 204 |
+
|
| 205 |
+
print(
|
| 206 |
+
format_event(
|
| 207 |
+
"START",
|
| 208 |
+
{
|
| 209 |
+
"mode": config.mode,
|
| 210 |
+
"model_name": config.model_name,
|
| 211 |
+
"task_id": args.task_id or "all",
|
| 212 |
+
"max_repairs": args.max_repairs,
|
| 213 |
+
},
|
| 214 |
+
),
|
| 215 |
+
file=stream,
|
| 216 |
+
)
|
| 217 |
+
result = run_inference(args.task_id, args.max_repairs, config)
|
| 218 |
+
for index, task_result in enumerate(result["results"], start=1):
|
| 219 |
+
step_payload = {
|
| 220 |
+
"index": index,
|
| 221 |
+
"task_id": task_result["task_id"],
|
| 222 |
+
"family_id": task_result["family_id"],
|
| 223 |
+
"difficulty": task_result["difficulty"],
|
| 224 |
+
"score": task_result["score"],
|
| 225 |
+
"accepted": task_result["accepted"],
|
| 226 |
+
}
|
| 227 |
+
if "error" in task_result:
|
| 228 |
+
step_payload["error"] = task_result["error"]
|
| 229 |
+
print(format_event("STEP", step_payload), file=stream)
|
| 230 |
+
write_output(args.output, result)
|
| 231 |
+
print(
|
| 232 |
+
format_event(
|
| 233 |
+
"END",
|
| 234 |
+
{
|
| 235 |
+
"mode": config.mode,
|
| 236 |
+
"task_count": result["task_count"],
|
| 237 |
+
"mean_public_score": result["mean_public_score"],
|
| 238 |
+
"accepted_count": result["accepted_count"],
|
| 239 |
+
},
|
| 240 |
+
),
|
| 241 |
+
file=stream,
|
| 242 |
+
)
|
| 243 |
+
return 0
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
def _is_azure_endpoint(base_url: str) -> bool:
|
| 247 |
+
host = urlparse(base_url).netloc.lower()
|
| 248 |
+
return "openai.azure.com" in host or "cognitiveservices.azure.com" in host
|
| 249 |
+
|
| 250 |
+
|
| 251 |
+
if __name__ == "__main__":
|
| 252 |
+
raise SystemExit(main())
|
models.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Shared state models for the Legacy COBOL Migration Workbench."""
|
| 2 |
+
|
| 3 |
+
from openenv.core.env_server.mcp_types import CallToolAction, CallToolObservation
|
| 4 |
+
from openenv.core.env_server.types import State
|
| 5 |
+
from pydantic import BaseModel, Field
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
Score = float
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class RewardComponents(BaseModel):
|
| 12 |
+
"""Public final reward component contract."""
|
| 13 |
+
|
| 14 |
+
hidden_correctness: Score = Field(ge=0.0, le=1.0)
|
| 15 |
+
fresh_correctness: Score = Field(ge=0.0, le=1.0)
|
| 16 |
+
interface_contract: Score = Field(ge=0.0, le=1.0)
|
| 17 |
+
type_and_layout_fidelity: Score = Field(ge=0.0, le=1.0)
|
| 18 |
+
anti_hardcoding: Score = Field(ge=0.0, le=1.0)
|
| 19 |
+
safety: Score = Field(ge=0.0, le=1.0)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class RewardResponse(BaseModel):
|
| 23 |
+
"""Reward-ish response shared by terminal and scoring payloads."""
|
| 24 |
+
|
| 25 |
+
ok: bool
|
| 26 |
+
reward: Score = Field(default=0.0, ge=0.0, le=1.0)
|
| 27 |
+
error: str | None = None
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class FinalSubmissionResult(BaseModel):
|
| 31 |
+
"""Structured result returned by submit_final."""
|
| 32 |
+
|
| 33 |
+
ok: bool
|
| 34 |
+
accepted: bool
|
| 35 |
+
episode_done: bool
|
| 36 |
+
public_score: Score = Field(ge=0.0, le=1.0)
|
| 37 |
+
components: RewardComponents
|
| 38 |
+
hidden_passed: int | None = None
|
| 39 |
+
hidden_total: int | None = None
|
| 40 |
+
fresh_passed: int | None = None
|
| 41 |
+
fresh_total: int | None = None
|
| 42 |
+
notes: str | None = None
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
class TerminalStepResult(BaseModel):
|
| 46 |
+
"""Structured no-op result for blocked episode steps."""
|
| 47 |
+
|
| 48 |
+
ok: bool = False
|
| 49 |
+
error: str
|
| 50 |
+
terminal: bool = True
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
class ToolActionWrapper(CallToolAction):
|
| 54 |
+
"""Project-level wrapper for MCP tool actions."""
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class ToolObservationWrapper(CallToolObservation):
|
| 58 |
+
"""Project-level wrapper for MCP tool observations."""
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
class LegacyCobolState(State):
|
| 62 |
+
"""Inspectable episode state for the migration workbench."""
|
| 63 |
+
|
| 64 |
+
task_id: str | None = Field(default=None, description="Selected task ID")
|
| 65 |
+
done: bool = Field(default=False, description="Whether the episode is complete")
|
| 66 |
+
files_read: list[str] = Field(default_factory=list)
|
| 67 |
+
copybooks_read: list[str] = Field(default_factory=list)
|
| 68 |
+
layouts_parsed: list[str] = Field(default_factory=list)
|
| 69 |
+
business_rules_inspected: bool = Field(default=False)
|
| 70 |
+
diffs_inspected: list[str] = Field(default_factory=list)
|
| 71 |
+
draft_count: int = Field(default=0)
|
| 72 |
+
visible_runs: int = Field(default=0)
|
| 73 |
+
best_visible_pass_rate: float = Field(default=0.0)
|
| 74 |
+
final_score: float | None = Field(default=None)
|
| 75 |
+
last_tool: str | None = Field(default=None)
|
| 76 |
+
last_result_summary: str | None = Field(default=None)
|
| 77 |
+
reward_components: dict[str, float] = Field(default_factory=dict)
|
openenv.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
spec_version: 1
|
| 2 |
+
name: legacy_cobol_env
|
| 3 |
+
type: space
|
| 4 |
+
runtime: fastapi
|
| 5 |
+
app: server.app:app
|
| 6 |
+
port: 8000
|
| 7 |
+
|
outputs/evals/base_qwen3_14b_all_tasks.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
outputs/evals/baseline_results.json
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"policies": [
|
| 3 |
+
"blank_width",
|
| 4 |
+
"identity"
|
| 5 |
+
],
|
| 6 |
+
"task_count": 6,
|
| 7 |
+
"mean_public_score": {
|
| 8 |
+
"blank_width": 0.17666666666666667,
|
| 9 |
+
"identity": 0.15
|
| 10 |
+
},
|
| 11 |
+
"results": [
|
| 12 |
+
{
|
| 13 |
+
"policy": "identity",
|
| 14 |
+
"task_id": "payroll_net_pay_001",
|
| 15 |
+
"family_id": "decimal_copybook_payroll",
|
| 16 |
+
"visible_pass_rate": 0.0,
|
| 17 |
+
"public_score": 0.15,
|
| 18 |
+
"components": {
|
| 19 |
+
"hidden_correctness": 0.0,
|
| 20 |
+
"fresh_correctness": 0.0,
|
| 21 |
+
"interface_contract": 1.0,
|
| 22 |
+
"type_and_layout_fidelity": 0.0,
|
| 23 |
+
"anti_hardcoding": 0.0,
|
| 24 |
+
"safety": 1.0
|
| 25 |
+
},
|
| 26 |
+
"accepted": false
|
| 27 |
+
},
|
| 28 |
+
{
|
| 29 |
+
"policy": "blank_width",
|
| 30 |
+
"task_id": "payroll_net_pay_001",
|
| 31 |
+
"family_id": "decimal_copybook_payroll",
|
| 32 |
+
"visible_pass_rate": 0.0,
|
| 33 |
+
"public_score": 0.15,
|
| 34 |
+
"components": {
|
| 35 |
+
"hidden_correctness": 0.0,
|
| 36 |
+
"fresh_correctness": 0.0,
|
| 37 |
+
"interface_contract": 1.0,
|
| 38 |
+
"type_and_layout_fidelity": 0.0,
|
| 39 |
+
"anti_hardcoding": 0.0,
|
| 40 |
+
"safety": 1.0
|
| 41 |
+
},
|
| 42 |
+
"accepted": false
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"policy": "identity",
|
| 46 |
+
"task_id": "customer_format_001",
|
| 47 |
+
"family_id": "fixed_width_customer",
|
| 48 |
+
"visible_pass_rate": 0.0,
|
| 49 |
+
"public_score": 0.15,
|
| 50 |
+
"components": {
|
| 51 |
+
"hidden_correctness": 0.0,
|
| 52 |
+
"fresh_correctness": 0.0,
|
| 53 |
+
"interface_contract": 1.0,
|
| 54 |
+
"type_and_layout_fidelity": 0.0,
|
| 55 |
+
"anti_hardcoding": 0.0,
|
| 56 |
+
"safety": 1.0
|
| 57 |
+
},
|
| 58 |
+
"accepted": false
|
| 59 |
+
},
|
| 60 |
+
{
|
| 61 |
+
"policy": "blank_width",
|
| 62 |
+
"task_id": "customer_format_001",
|
| 63 |
+
"family_id": "fixed_width_customer",
|
| 64 |
+
"visible_pass_rate": 0.0,
|
| 65 |
+
"public_score": 0.15,
|
| 66 |
+
"components": {
|
| 67 |
+
"hidden_correctness": 0.0,
|
| 68 |
+
"fresh_correctness": 0.0,
|
| 69 |
+
"interface_contract": 1.0,
|
| 70 |
+
"type_and_layout_fidelity": 0.0,
|
| 71 |
+
"anti_hardcoding": 0.0,
|
| 72 |
+
"safety": 1.0
|
| 73 |
+
},
|
| 74 |
+
"accepted": false
|
| 75 |
+
},
|
| 76 |
+
{
|
| 77 |
+
"policy": "identity",
|
| 78 |
+
"task_id": "claims_eligibility_001",
|
| 79 |
+
"family_id": "claims_eligibility_branching",
|
| 80 |
+
"visible_pass_rate": 0.0,
|
| 81 |
+
"public_score": 0.15,
|
| 82 |
+
"components": {
|
| 83 |
+
"hidden_correctness": 0.0,
|
| 84 |
+
"fresh_correctness": 0.0,
|
| 85 |
+
"interface_contract": 1.0,
|
| 86 |
+
"type_and_layout_fidelity": 0.0,
|
| 87 |
+
"anti_hardcoding": 0.0,
|
| 88 |
+
"safety": 1.0
|
| 89 |
+
},
|
| 90 |
+
"accepted": false
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"policy": "blank_width",
|
| 94 |
+
"task_id": "claims_eligibility_001",
|
| 95 |
+
"family_id": "claims_eligibility_branching",
|
| 96 |
+
"visible_pass_rate": 0.0,
|
| 97 |
+
"public_score": 0.23,
|
| 98 |
+
"components": {
|
| 99 |
+
"hidden_correctness": 0.0,
|
| 100 |
+
"fresh_correctness": 0.0,
|
| 101 |
+
"interface_contract": 1.0,
|
| 102 |
+
"type_and_layout_fidelity": 1.0,
|
| 103 |
+
"anti_hardcoding": 0.0,
|
| 104 |
+
"safety": 1.0
|
| 105 |
+
},
|
| 106 |
+
"accepted": false
|
| 107 |
+
},
|
| 108 |
+
{
|
| 109 |
+
"policy": "identity",
|
| 110 |
+
"task_id": "account_status_001",
|
| 111 |
+
"family_id": "account_status_level88",
|
| 112 |
+
"visible_pass_rate": 0.0,
|
| 113 |
+
"public_score": 0.15,
|
| 114 |
+
"components": {
|
| 115 |
+
"hidden_correctness": 0.0,
|
| 116 |
+
"fresh_correctness": 0.0,
|
| 117 |
+
"interface_contract": 1.0,
|
| 118 |
+
"type_and_layout_fidelity": 0.0,
|
| 119 |
+
"anti_hardcoding": 0.0,
|
| 120 |
+
"safety": 1.0
|
| 121 |
+
},
|
| 122 |
+
"accepted": false
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"policy": "blank_width",
|
| 126 |
+
"task_id": "account_status_001",
|
| 127 |
+
"family_id": "account_status_level88",
|
| 128 |
+
"visible_pass_rate": 0.0,
|
| 129 |
+
"public_score": 0.23,
|
| 130 |
+
"components": {
|
| 131 |
+
"hidden_correctness": 0.0,
|
| 132 |
+
"fresh_correctness": 0.0,
|
| 133 |
+
"interface_contract": 1.0,
|
| 134 |
+
"type_and_layout_fidelity": 1.0,
|
| 135 |
+
"anti_hardcoding": 0.0,
|
| 136 |
+
"safety": 1.0
|
| 137 |
+
},
|
| 138 |
+
"accepted": false
|
| 139 |
+
},
|
| 140 |
+
{
|
| 141 |
+
"policy": "identity",
|
| 142 |
+
"task_id": "invoice_occurs_001",
|
| 143 |
+
"family_id": "invoice_occurs_totals",
|
| 144 |
+
"visible_pass_rate": 0.0,
|
| 145 |
+
"public_score": 0.15,
|
| 146 |
+
"components": {
|
| 147 |
+
"hidden_correctness": 0.0,
|
| 148 |
+
"fresh_correctness": 0.0,
|
| 149 |
+
"interface_contract": 1.0,
|
| 150 |
+
"type_and_layout_fidelity": 0.0,
|
| 151 |
+
"anti_hardcoding": 0.0,
|
| 152 |
+
"safety": 1.0
|
| 153 |
+
},
|
| 154 |
+
"accepted": false
|
| 155 |
+
},
|
| 156 |
+
{
|
| 157 |
+
"policy": "blank_width",
|
| 158 |
+
"task_id": "invoice_occurs_001",
|
| 159 |
+
"family_id": "invoice_occurs_totals",
|
| 160 |
+
"visible_pass_rate": 0.0,
|
| 161 |
+
"public_score": 0.15,
|
| 162 |
+
"components": {
|
| 163 |
+
"hidden_correctness": 0.0,
|
| 164 |
+
"fresh_correctness": 0.0,
|
| 165 |
+
"interface_contract": 1.0,
|
| 166 |
+
"type_and_layout_fidelity": 0.0,
|
| 167 |
+
"anti_hardcoding": 0.0,
|
| 168 |
+
"safety": 1.0
|
| 169 |
+
},
|
| 170 |
+
"accepted": false
|
| 171 |
+
},
|
| 172 |
+
{
|
| 173 |
+
"policy": "identity",
|
| 174 |
+
"task_id": "date_normalization_001",
|
| 175 |
+
"family_id": "date_normalization",
|
| 176 |
+
"visible_pass_rate": 0.0,
|
| 177 |
+
"public_score": 0.15,
|
| 178 |
+
"components": {
|
| 179 |
+
"hidden_correctness": 0.0,
|
| 180 |
+
"fresh_correctness": 0.0,
|
| 181 |
+
"interface_contract": 1.0,
|
| 182 |
+
"type_and_layout_fidelity": 0.0,
|
| 183 |
+
"anti_hardcoding": 0.0,
|
| 184 |
+
"safety": 1.0
|
| 185 |
+
},
|
| 186 |
+
"accepted": false
|
| 187 |
+
},
|
| 188 |
+
{
|
| 189 |
+
"policy": "blank_width",
|
| 190 |
+
"task_id": "date_normalization_001",
|
| 191 |
+
"family_id": "date_normalization",
|
| 192 |
+
"visible_pass_rate": 0.0,
|
| 193 |
+
"public_score": 0.15,
|
| 194 |
+
"components": {
|
| 195 |
+
"hidden_correctness": 0.0,
|
| 196 |
+
"fresh_correctness": 0.0,
|
| 197 |
+
"interface_contract": 1.0,
|
| 198 |
+
"type_and_layout_fidelity": 0.0,
|
| 199 |
+
"anti_hardcoding": 0.0,
|
| 200 |
+
"safety": 1.0
|
| 201 |
+
},
|
| 202 |
+
"accepted": false
|
| 203 |
+
}
|
| 204 |
+
]
|
| 205 |
+
}
|
outputs/evals/cobol_invoice_oracle_check.json
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"ok": true,
|
| 3 |
+
"image_tag": "legacy-cobol-invoice-oracle:local",
|
| 4 |
+
"case_count": 13,
|
| 5 |
+
"passed_count": 13,
|
| 6 |
+
"mismatches": [],
|
| 7 |
+
"cases": [
|
| 8 |
+
{
|
| 9 |
+
"case_id": "visible_1",
|
| 10 |
+
"summary": "two standard and non-taxable lines",
|
| 11 |
+
"input_record": "I000010202012345S01010000N00000000N00000000N",
|
| 12 |
+
"expected_output": "I0000100003648002L",
|
| 13 |
+
"actual_output": "I0000100003648002L",
|
| 14 |
+
"passed": true
|
| 15 |
+
},
|
| 16 |
+
{
|
| 17 |
+
"case_id": "visible_2",
|
| 18 |
+
"summary": "zero item invoice",
|
| 19 |
+
"input_record": "I000020000000000N00000000N00000000N00000000N",
|
| 20 |
+
"expected_output": "I0000200000000000L",
|
| 21 |
+
"actual_output": "I0000200000000000L",
|
| 22 |
+
"passed": true
|
| 23 |
+
},
|
| 24 |
+
{
|
| 25 |
+
"case_id": "visible_3",
|
| 26 |
+
"summary": "four item high invoice",
|
| 27 |
+
"input_record": "I000030404025000S01099000N03012345R02050000L",
|
| 28 |
+
"expected_output": "I0000300035421104H",
|
| 29 |
+
"actual_output": "I0000300035421104H",
|
| 30 |
+
"passed": true
|
| 31 |
+
},
|
| 32 |
+
{
|
| 33 |
+
"case_id": "hidden_1",
|
| 34 |
+
"summary": "standard tax rounding probe",
|
| 35 |
+
"input_record": "I000040103033333S00000000N00000000N00000000N",
|
| 36 |
+
"expected_output": "I0000400010724901H",
|
| 37 |
+
"actual_output": "I0000400010724901H",
|
| 38 |
+
"passed": true
|
| 39 |
+
},
|
| 40 |
+
{
|
| 41 |
+
"case_id": "hidden_2",
|
| 42 |
+
"summary": "count ignores padded groups",
|
| 43 |
+
"input_record": "I000050101000100N00000000N00000000N00000000N",
|
| 44 |
+
"expected_output": "I0000500000010001L",
|
| 45 |
+
"actual_output": "I0000500000010001L",
|
| 46 |
+
"passed": true
|
| 47 |
+
},
|
| 48 |
+
{
|
| 49 |
+
"case_id": "hidden_3",
|
| 50 |
+
"summary": "threshold flag high with luxury code",
|
| 51 |
+
"input_record": "I000060104030000L00000000N00000000N00000000N",
|
| 52 |
+
"expected_output": "I0000600013200001H",
|
| 53 |
+
"actual_output": "I0000600013200001H",
|
| 54 |
+
"passed": true
|
| 55 |
+
},
|
| 56 |
+
{
|
| 57 |
+
"case_id": "hidden_4",
|
| 58 |
+
"summary": "reduced code generalization",
|
| 59 |
+
"input_record": "I000070207022222R02010101S00000000N00000000N",
|
| 60 |
+
"expected_output": "I0000700018111002H",
|
| 61 |
+
"actual_output": "I0000700018111002H",
|
| 62 |
+
"passed": true
|
| 63 |
+
},
|
| 64 |
+
{
|
| 65 |
+
"case_id": "fresh_20260429_0",
|
| 66 |
+
"summary": "fresh invoice occurs case",
|
| 67 |
+
"input_record": "F000000000000000N00000000N00000000N00000000N",
|
| 68 |
+
"expected_output": "F0000000000000000L",
|
| 69 |
+
"actual_output": "F0000000000000000L",
|
| 70 |
+
"passed": true
|
| 71 |
+
},
|
| 72 |
+
{
|
| 73 |
+
"case_id": "fresh_20260429_1",
|
| 74 |
+
"summary": "fresh invoice occurs case",
|
| 75 |
+
"input_record": "F000010307027373N08012881S02050992L00000000N",
|
| 76 |
+
"expected_output": "F0000100041431203H",
|
| 77 |
+
"actual_output": "F0000100041431203H",
|
| 78 |
+
"passed": true
|
| 79 |
+
},
|
| 80 |
+
{
|
| 81 |
+
"case_id": "fresh_20260429_2",
|
| 82 |
+
"summary": "fresh invoice occurs case",
|
| 83 |
+
"input_record": "F000020101009336S00000000N00000000N00000000N",
|
| 84 |
+
"expected_output": "F0000200001001301L",
|
| 85 |
+
"actual_output": "F0000200001001301L",
|
| 86 |
+
"passed": true
|
| 87 |
+
},
|
| 88 |
+
{
|
| 89 |
+
"case_id": "fresh_20260429_3",
|
| 90 |
+
"summary": "fresh invoice occurs case",
|
| 91 |
+
"input_record": "F000030104016782N00000000N00000000N00000000N",
|
| 92 |
+
"expected_output": "F0000300006712801L",
|
| 93 |
+
"actual_output": "F0000300006712801L",
|
| 94 |
+
"passed": true
|
| 95 |
+
},
|
| 96 |
+
{
|
| 97 |
+
"case_id": "fresh_20260429_4",
|
| 98 |
+
"summary": "fresh invoice occurs case",
|
| 99 |
+
"input_record": "F000040303084629N08033585N08035187R00000000N",
|
| 100 |
+
"expected_output": "F0000400081110003H",
|
| 101 |
+
"actual_output": "F0000400081110003H",
|
| 102 |
+
"passed": true
|
| 103 |
+
},
|
| 104 |
+
{
|
| 105 |
+
"case_id": "fresh_20260429_5",
|
| 106 |
+
"summary": "fresh invoice occurs case",
|
| 107 |
+
"input_record": "F000050107087851R00000000N00000000N00000000N",
|
| 108 |
+
"expected_output": "F0000500063033101H",
|
| 109 |
+
"actual_output": "F0000500063033101H",
|
| 110 |
+
"passed": true
|
| 111 |
+
}
|
| 112 |
+
],
|
| 113 |
+
"source_compile": {
|
| 114 |
+
"ok": true,
|
| 115 |
+
"compiled_sources": [
|
| 116 |
+
"INVTOTAL.cbl",
|
| 117 |
+
"TAXRATE.cbl"
|
| 118 |
+
],
|
| 119 |
+
"returncode": 0,
|
| 120 |
+
"stdout": "",
|
| 121 |
+
"stderr": ""
|
| 122 |
+
}
|
| 123 |
+
}
|
outputs/evals/historical/azure_gpt54mini_payroll_probe.json
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"provider": "azure-openai",
|
| 3 |
+
"task_count": 1,
|
| 4 |
+
"mean_public_score": 0.15,
|
| 5 |
+
"accepted_count": 0,
|
| 6 |
+
"trajectories": [
|
| 7 |
+
{
|
| 8 |
+
"policy": "azure-openai",
|
| 9 |
+
"task_id": "payroll_net_pay_001",
|
| 10 |
+
"family_id": "decimal_copybook_payroll",
|
| 11 |
+
"ticket": {
|
| 12 |
+
"task_id": "payroll_net_pay_001",
|
| 13 |
+
"family_id": "decimal_copybook_payroll",
|
| 14 |
+
"domain": "payroll",
|
| 15 |
+
"ticket": "Migrate PAYROLL.cbl while preserving copybook offsets, implied decimals, signed deductions, bonus condition names, and fixed-width ACH output.",
|
| 16 |
+
"available_files": [
|
| 17 |
+
"PAYROLL.cbl"
|
| 18 |
+
],
|
| 19 |
+
"available_copybooks": [
|
| 20 |
+
"EMPLOYEE_PAY.cpy"
|
| 21 |
+
],
|
| 22 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 23 |
+
"visible_tests": 3,
|
| 24 |
+
"hidden_tests": 5,
|
| 25 |
+
"input_width": 42,
|
| 26 |
+
"output_width": 28,
|
| 27 |
+
"max_steps": 12,
|
| 28 |
+
"allowed_tools": [
|
| 29 |
+
"read_cobol_file",
|
| 30 |
+
"read_copybook",
|
| 31 |
+
"parse_copybook_layout",
|
| 32 |
+
"inspect_business_rules",
|
| 33 |
+
"write_python_solution",
|
| 34 |
+
"run_visible_tests",
|
| 35 |
+
"inspect_diff",
|
| 36 |
+
"submit_final"
|
| 37 |
+
]
|
| 38 |
+
},
|
| 39 |
+
"model_turns": [
|
| 40 |
+
{
|
| 41 |
+
"provider": "azure-openai",
|
| 42 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"payroll_net_pay_001\",\n \"family_id\": \"decimal_copybook_payroll\",\n \"domain\": \"payroll\",\n \"ticket\": \"Migrate PAYROLL.cbl while preserving copybook offsets, implied decimals, signed deductions, bonus condition names, and fixed-width ACH output.\",\n \"available_files\": [\n \"PAYROLL.cbl\"\n ],\n \"available_copybooks\": [\n \"EMPLOYEE_PAY.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 5,\n \"input_width\": 42,\n \"output_width\": 28,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"PAYROLL.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. PAYROLLNET.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY EMPLOYEE_PAY.\\n 01 TAX-AMOUNT PIC 9(7)V99.\\n 01 NET-AMOUNT PIC 9(7)V99.\\n 01 PAY-CATEGORY PIC X.\\n PROCEDURE DIVISION.\\n COMPUTE TAX-AMOUNT ROUNDED = GROSS-PAY * TAX-RATE\\n COMPUTE NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS\\n IF BONUS-ELIGIBLE ADD 50.00 TO NET-AMOUNT END-IF\\n IF NET-AMOUNT < 0 MOVE 0 TO NET-AMOUNT END-IF\\n EVALUATE TRUE\\n WHEN NET-AMOUNT >= 5000.00 MOVE 'H' TO PAY-CATEGORY\\n WHEN NET-AMOUNT >= 2500.00 MOVE 'M' TO PAY-CATEGORY\\n WHEN OTHER MOVE 'L' TO PAY-CATEGORY\\n END-EVALUATE\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"EMPLOYEE_PAY.cpy\": \" 01 EMPLOYEE-PAY-RECORD.\\n 05 EMP-ID PIC X(6).\\n 05 EMP-NAME PIC X(12).\\n 05 GROSS-PAY PIC 9(7)V99.\\n 05 TAX-RATE PIC 9V999.\\n 05 DEDUCTIONS PIC S9(5)V99 SIGN LEADING SEPARATE.\\n 05 BONUS-FLAG PIC X(1).\\n 88 BONUS-ELIGIBLE VALUE 'Y'.\\n 88 NO-BONUS VALUE 'N'.\\n 05 FILLER PIC X(2).\\n\"\n}\n\nParsed layouts:\n{\n \"EMPLOYEE_PAY.cpy\": {\n \"ok\": true,\n \"filename\": \"EMPLOYEE_PAY.cpy\",\n \"record_name\": \"EMPLOYEE-PAY-RECORD\",\n \"total_width\": 42,\n \"fields\": [\n {\n \"name\": \"EMP-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"EMP-NAME\",\n \"start\": 6,\n \"end\": 18,\n \"length\": 12,\n \"pic\": \"X(12)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"GROSS-PAY\",\n \"start\": 18,\n \"end\": 27,\n \"length\": 9,\n \"pic\": \"9(7)V99\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n },\n {\n \"name\": \"TAX-RATE\",\n \"start\": 27,\n \"end\": 31,\n \"length\": 4,\n \"pic\": \"9V999\",\n \"python_type\": \"Decimal\",\n \"scale\": 3\n },\n {\n \"name\": \"DEDUCTIONS\",\n \"start\": 31,\n \"end\": 39,\n \"length\": 8,\n \"pic\": \"S9(5)V99 SIGN LEADING SEPARATE\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n },\n {\n \"name\": \"BONUS-FLAG\",\n \"start\": 39,\n \"end\": 40,\n \"length\": 1,\n \"pic\": \"X(1)\",\n \"python_type\": \"str\",\n \"level_88\": {\n \"BONUS-ELIGIBLE\": \"Y\",\n \"NO-BONUS\": \"N\"\n }\n },\n {\n \"name\": \"FILLER\",\n \"start\": 40,\n \"end\": 42,\n \"length\": 2,\n \"pic\": \"X(2)\",\n \"python_type\": \"str\"\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"Tax is rounded half up to cents after GROSS-PAY * TAX-RATE.\",\n \"NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS.\",\n \"BONUS-ELIGIBLE adds 50.00; negative net pay floors to zero.\",\n \"Output net pay is a 9-digit zero-padded cents field.\"\n]",
|
| 43 |
+
"response": "{\"code\":\"from decimal import Decimal, ROUND_HALF_UP\\n\\ndef migrate(input_record: str) -> str:\\n # Preserve fixed-width input layout from copybook (42 chars)\\n rec = (input_record or \\\"\\\")[:42].ljust(42)\\n\\n def dec_slice(start: int, end: int, scale: int) -> Decimal:\\n raw = rec[start:end]\\n raw = raw.strip()\\n if not raw:\\n return Decimal('0')\\n sign = 1\\n if raw[0] == '+':\\n raw = raw[1:]\\n elif raw[0] == '-':\\n sign = -1\\n raw = raw[1:]\\n # COBOL SIGN LEADING SEPARATE may place a leading sign in the field.\\n # For this layout, deductions is 8 chars and may include a sign.\\n if raw and raw[0] in '+-':\\n sign = -1 if raw[0] == '-' else 1\\n raw = raw[1:]\\n if not raw:\\n return Decimal('0')\\n if not raw.isdigit():\\n # Be tolerant of spaces/garbage by extracting digits only.\\n digits = ''.join(ch for ch in raw if ch.isdigit())\\n if not digits:\\n return Decimal('0')\\n raw = digits\\n return Decimal(sign) * (Decimal(int(raw)) / (Decimal(10) ** scale))\\n\\n gross = dec_slice(18, 27, 2)\\n tax_rate = dec_slice(27, 31, 3)\\n deductions = dec_slice(31, 39, 2)\\n bonus_flag = rec[39:40]\\n\\n tax_amount = (gross * tax_rate).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)\\n net_amount = gross - tax_amount - deductions\\n if bonus_flag == 'Y':\\n net_amount += Decimal('50.00')\\n if net_amount < 0:\\n net_amount = Decimal('0.00')\\n\\n # Output: 9-digit zero-padded cents field (fixed-width ACH output)\\n cents = int((net_amount * 100).quantize(Decimal('1'), rounding=ROUND_HALF_UP))\\n return f\\\"{cents:09d}\\\"\\n\"}",
|
| 44 |
+
"code_chars": 1726
|
| 45 |
+
}
|
| 46 |
+
],
|
| 47 |
+
"visible": {
|
| 48 |
+
"passed": 0,
|
| 49 |
+
"total": 3,
|
| 50 |
+
"pass_rate": 0.0,
|
| 51 |
+
"failures": [
|
| 52 |
+
{
|
| 53 |
+
"case_id": "visible_1",
|
| 54 |
+
"input_summary": "ordinary bonus-eligible employee",
|
| 55 |
+
"expected_summary": "OUT-EMP-ID=E00001, OUT-EMP-NAME=ALICE , OUT-NET-PAY=000093272, OUT-PAY-CATEGORY=L",
|
| 56 |
+
"actual_summary": "length 9 output: '000093272'",
|
| 57 |
+
"error": null
|
| 58 |
+
},
|
| 59 |
+
{
|
| 60 |
+
"case_id": "visible_2",
|
| 61 |
+
"input_summary": "negative adjustment and no bonus",
|
| 62 |
+
"expected_summary": "OUT-EMP-ID=E00002, OUT-EMP-NAME=BOB , OUT-NET-PAY=000076750, OUT-PAY-CATEGORY=L",
|
| 63 |
+
"actual_summary": "length 9 output: '000076750'",
|
| 64 |
+
"error": null
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"case_id": "visible_3",
|
| 68 |
+
"input_summary": "low net pay floors at zero",
|
| 69 |
+
"expected_summary": "OUT-EMP-ID=E00003, OUT-EMP-NAME=CHANDRA , OUT-NET-PAY=000000000, OUT-PAY-CATEGORY=L",
|
| 70 |
+
"actual_summary": "length 9 output: '000000000'",
|
| 71 |
+
"error": null
|
| 72 |
+
}
|
| 73 |
+
]
|
| 74 |
+
},
|
| 75 |
+
"final": {
|
| 76 |
+
"public_score": 0.15,
|
| 77 |
+
"accepted": false,
|
| 78 |
+
"components": {
|
| 79 |
+
"hidden_correctness": 0.0,
|
| 80 |
+
"fresh_correctness": 0.0,
|
| 81 |
+
"interface_contract": 1.0,
|
| 82 |
+
"type_and_layout_fidelity": 0.0,
|
| 83 |
+
"anti_hardcoding": 0.0,
|
| 84 |
+
"safety": 1.0
|
| 85 |
+
},
|
| 86 |
+
"hidden_passed": 0,
|
| 87 |
+
"hidden_total": 5,
|
| 88 |
+
"fresh_passed": 0,
|
| 89 |
+
"fresh_total": 6
|
| 90 |
+
},
|
| 91 |
+
"steps": [
|
| 92 |
+
{
|
| 93 |
+
"tool_name": "read_cobol_file",
|
| 94 |
+
"arguments": {
|
| 95 |
+
"filename": "PAYROLL.cbl"
|
| 96 |
+
},
|
| 97 |
+
"reward": 0.02,
|
| 98 |
+
"done": false,
|
| 99 |
+
"result": {
|
| 100 |
+
"ok": true,
|
| 101 |
+
"filename": "PAYROLL.cbl",
|
| 102 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. PAYROLLNET.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY EMPLOYEE_PAY.\n 01 TAX-AMOUNT PIC 9(7)V99.\n 01 NET-AMOUNT PIC 9(7)V99.\n 01 PAY-CATEGORY PIC X.\n PROCEDURE DIVISION.\n COMPUTE TAX-AMOUNT ROUNDED = GROSS-PAY * TAX-RATE\n COMPUTE NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS\n IF BONUS-ELIGIBLE ADD 50.00 TO NET-AMOUNT END-IF\n IF NET-AMOUNT < 0 MOVE 0 TO NET-AMOUNT END-IF\n EVALUATE TRUE\n WHEN NET-AMOUNT >= 5000.00 MOVE 'H' TO PAY-CATEGORY\n WHEN NET-AMOUNT >= 2500.00 MOVE 'M' TO PAY-CATEGORY\n WHEN OTHER MOVE 'L' TO PAY-CATEGORY\n END-EVALUATE\n GOBACK.\n",
|
| 103 |
+
"truncated": false
|
| 104 |
+
}
|
| 105 |
+
},
|
| 106 |
+
{
|
| 107 |
+
"tool_name": "read_copybook",
|
| 108 |
+
"arguments": {
|
| 109 |
+
"filename": "EMPLOYEE_PAY.cpy"
|
| 110 |
+
},
|
| 111 |
+
"reward": 0.02,
|
| 112 |
+
"done": false,
|
| 113 |
+
"result": {
|
| 114 |
+
"ok": true,
|
| 115 |
+
"filename": "EMPLOYEE_PAY.cpy",
|
| 116 |
+
"content": " 01 EMPLOYEE-PAY-RECORD.\n 05 EMP-ID PIC X(6).\n 05 EMP-NAME PIC X(12).\n 05 GROSS-PAY PIC 9(7)V99.\n 05 TAX-RATE PIC 9V999.\n 05 DEDUCTIONS PIC S9(5)V99 SIGN LEADING SEPARATE.\n 05 BONUS-FLAG PIC X(1).\n 88 BONUS-ELIGIBLE VALUE 'Y'.\n 88 NO-BONUS VALUE 'N'.\n 05 FILLER PIC X(2).\n"
|
| 117 |
+
}
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"tool_name": "parse_copybook_layout",
|
| 121 |
+
"arguments": {
|
| 122 |
+
"filename": "EMPLOYEE_PAY.cpy"
|
| 123 |
+
},
|
| 124 |
+
"reward": 0.03,
|
| 125 |
+
"done": false,
|
| 126 |
+
"result": {
|
| 127 |
+
"ok": true,
|
| 128 |
+
"filename": "EMPLOYEE_PAY.cpy",
|
| 129 |
+
"record_name": "EMPLOYEE-PAY-RECORD",
|
| 130 |
+
"total_width": 42,
|
| 131 |
+
"fields": [
|
| 132 |
+
{
|
| 133 |
+
"name": "EMP-ID",
|
| 134 |
+
"start": 0,
|
| 135 |
+
"end": 6,
|
| 136 |
+
"length": 6,
|
| 137 |
+
"pic": "X(6)",
|
| 138 |
+
"python_type": "str"
|
| 139 |
+
},
|
| 140 |
+
{
|
| 141 |
+
"name": "EMP-NAME",
|
| 142 |
+
"start": 6,
|
| 143 |
+
"end": 18,
|
| 144 |
+
"length": 12,
|
| 145 |
+
"pic": "X(12)",
|
| 146 |
+
"python_type": "str"
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"name": "GROSS-PAY",
|
| 150 |
+
"start": 18,
|
| 151 |
+
"end": 27,
|
| 152 |
+
"length": 9,
|
| 153 |
+
"pic": "9(7)V99",
|
| 154 |
+
"python_type": "Decimal",
|
| 155 |
+
"scale": 2
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
"name": "TAX-RATE",
|
| 159 |
+
"start": 27,
|
| 160 |
+
"end": 31,
|
| 161 |
+
"length": 4,
|
| 162 |
+
"pic": "9V999",
|
| 163 |
+
"python_type": "Decimal",
|
| 164 |
+
"scale": 3
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"name": "DEDUCTIONS",
|
| 168 |
+
"start": 31,
|
| 169 |
+
"end": 39,
|
| 170 |
+
"length": 8,
|
| 171 |
+
"pic": "S9(5)V99 SIGN LEADING SEPARATE",
|
| 172 |
+
"python_type": "Decimal",
|
| 173 |
+
"scale": 2
|
| 174 |
+
},
|
| 175 |
+
{
|
| 176 |
+
"name": "BONUS-FLAG",
|
| 177 |
+
"start": 39,
|
| 178 |
+
"end": 40,
|
| 179 |
+
"length": 1,
|
| 180 |
+
"pic": "X(1)",
|
| 181 |
+
"python_type": "str",
|
| 182 |
+
"level_88": {
|
| 183 |
+
"BONUS-ELIGIBLE": "Y",
|
| 184 |
+
"NO-BONUS": "N"
|
| 185 |
+
}
|
| 186 |
+
},
|
| 187 |
+
{
|
| 188 |
+
"name": "FILLER",
|
| 189 |
+
"start": 40,
|
| 190 |
+
"end": 42,
|
| 191 |
+
"length": 2,
|
| 192 |
+
"pic": "X(2)",
|
| 193 |
+
"python_type": "str"
|
| 194 |
+
}
|
| 195 |
+
]
|
| 196 |
+
}
|
| 197 |
+
},
|
| 198 |
+
{
|
| 199 |
+
"tool_name": "inspect_business_rules",
|
| 200 |
+
"arguments": {},
|
| 201 |
+
"reward": 0.01,
|
| 202 |
+
"done": false,
|
| 203 |
+
"result": {
|
| 204 |
+
"ok": true,
|
| 205 |
+
"rules": [
|
| 206 |
+
"Tax is rounded half up to cents after GROSS-PAY * TAX-RATE.",
|
| 207 |
+
"NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS.",
|
| 208 |
+
"BONUS-ELIGIBLE adds 50.00; negative net pay floors to zero.",
|
| 209 |
+
"Output net pay is a 9-digit zero-padded cents field."
|
| 210 |
+
]
|
| 211 |
+
}
|
| 212 |
+
},
|
| 213 |
+
{
|
| 214 |
+
"tool_name": "write_python_solution",
|
| 215 |
+
"arguments": {
|
| 216 |
+
"code_chars": 1726
|
| 217 |
+
},
|
| 218 |
+
"reward": 0.02,
|
| 219 |
+
"done": false,
|
| 220 |
+
"result": {
|
| 221 |
+
"ok": true,
|
| 222 |
+
"draft_id": 1,
|
| 223 |
+
"syntax_ok": true,
|
| 224 |
+
"safety_ok": true,
|
| 225 |
+
"error": null
|
| 226 |
+
}
|
| 227 |
+
},
|
| 228 |
+
{
|
| 229 |
+
"tool_name": "run_visible_tests",
|
| 230 |
+
"arguments": {
|
| 231 |
+
"draft_id": 1
|
| 232 |
+
},
|
| 233 |
+
"reward": 0.0,
|
| 234 |
+
"done": false,
|
| 235 |
+
"result": {
|
| 236 |
+
"ok": true,
|
| 237 |
+
"draft_id": 1,
|
| 238 |
+
"passed": 0,
|
| 239 |
+
"total": 3,
|
| 240 |
+
"pass_rate": 0.0,
|
| 241 |
+
"syntax_ok": true,
|
| 242 |
+
"safety_ok": true,
|
| 243 |
+
"interface_ok": true,
|
| 244 |
+
"timed_out": false,
|
| 245 |
+
"error": null,
|
| 246 |
+
"failures": [
|
| 247 |
+
{
|
| 248 |
+
"case_id": "visible_1",
|
| 249 |
+
"input_summary": "ordinary bonus-eligible employee",
|
| 250 |
+
"expected_summary": "OUT-EMP-ID=E00001, OUT-EMP-NAME=ALICE , OUT-NET-PAY=000093272, OUT-PAY-CATEGORY=L",
|
| 251 |
+
"actual_summary": "length 9 output: '000093272'",
|
| 252 |
+
"error": null
|
| 253 |
+
},
|
| 254 |
+
{
|
| 255 |
+
"case_id": "visible_2",
|
| 256 |
+
"input_summary": "negative adjustment and no bonus",
|
| 257 |
+
"expected_summary": "OUT-EMP-ID=E00002, OUT-EMP-NAME=BOB , OUT-NET-PAY=000076750, OUT-PAY-CATEGORY=L",
|
| 258 |
+
"actual_summary": "length 9 output: '000076750'",
|
| 259 |
+
"error": null
|
| 260 |
+
},
|
| 261 |
+
{
|
| 262 |
+
"case_id": "visible_3",
|
| 263 |
+
"input_summary": "low net pay floors at zero",
|
| 264 |
+
"expected_summary": "OUT-EMP-ID=E00003, OUT-EMP-NAME=CHANDRA , OUT-NET-PAY=000000000, OUT-PAY-CATEGORY=L",
|
| 265 |
+
"actual_summary": "length 9 output: '000000000'",
|
| 266 |
+
"error": null
|
| 267 |
+
}
|
| 268 |
+
]
|
| 269 |
+
}
|
| 270 |
+
},
|
| 271 |
+
{
|
| 272 |
+
"tool_name": "submit_final",
|
| 273 |
+
"arguments": {
|
| 274 |
+
"draft_id": 1
|
| 275 |
+
},
|
| 276 |
+
"reward": 0.15,
|
| 277 |
+
"done": true,
|
| 278 |
+
"result": {
|
| 279 |
+
"ok": true,
|
| 280 |
+
"accepted": false,
|
| 281 |
+
"episode_done": true,
|
| 282 |
+
"public_score": 0.15,
|
| 283 |
+
"components": {
|
| 284 |
+
"hidden_correctness": 0.0,
|
| 285 |
+
"fresh_correctness": 0.0,
|
| 286 |
+
"interface_contract": 1.0,
|
| 287 |
+
"type_and_layout_fidelity": 0.0,
|
| 288 |
+
"anti_hardcoding": 0.0,
|
| 289 |
+
"safety": 1.0
|
| 290 |
+
},
|
| 291 |
+
"hidden_passed": 0,
|
| 292 |
+
"hidden_total": 5,
|
| 293 |
+
"fresh_passed": 0,
|
| 294 |
+
"fresh_total": 6,
|
| 295 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 296 |
+
}
|
| 297 |
+
}
|
| 298 |
+
]
|
| 299 |
+
}
|
| 300 |
+
]
|
| 301 |
+
}
|
outputs/evals/historical/azure_gpt54mini_repair1_rollouts.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
outputs/evals/historical/azure_gpt54mini_zeroshot_rollouts.json
ADDED
|
@@ -0,0 +1,1595 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"provider": "azure-openai",
|
| 3 |
+
"task_count": 6,
|
| 4 |
+
"mean_public_score": 0.305,
|
| 5 |
+
"accepted_count": 1,
|
| 6 |
+
"trajectories": [
|
| 7 |
+
{
|
| 8 |
+
"policy": "azure-openai",
|
| 9 |
+
"task_id": "payroll_net_pay_001",
|
| 10 |
+
"family_id": "decimal_copybook_payroll",
|
| 11 |
+
"ticket": {
|
| 12 |
+
"task_id": "payroll_net_pay_001",
|
| 13 |
+
"family_id": "decimal_copybook_payroll",
|
| 14 |
+
"domain": "payroll",
|
| 15 |
+
"ticket": "Migrate PAYROLL.cbl while preserving copybook offsets, implied decimals, signed deductions, bonus condition names, and fixed-width ACH output.",
|
| 16 |
+
"available_files": [
|
| 17 |
+
"PAYROLL.cbl"
|
| 18 |
+
],
|
| 19 |
+
"available_copybooks": [
|
| 20 |
+
"EMPLOYEE_PAY.cpy"
|
| 21 |
+
],
|
| 22 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 23 |
+
"visible_tests": 3,
|
| 24 |
+
"hidden_tests": 5,
|
| 25 |
+
"input_width": 42,
|
| 26 |
+
"output_width": 28,
|
| 27 |
+
"max_steps": 12,
|
| 28 |
+
"allowed_tools": [
|
| 29 |
+
"read_cobol_file",
|
| 30 |
+
"read_copybook",
|
| 31 |
+
"parse_copybook_layout",
|
| 32 |
+
"inspect_business_rules",
|
| 33 |
+
"write_python_solution",
|
| 34 |
+
"run_visible_tests",
|
| 35 |
+
"inspect_diff",
|
| 36 |
+
"submit_final"
|
| 37 |
+
]
|
| 38 |
+
},
|
| 39 |
+
"model_turns": [
|
| 40 |
+
{
|
| 41 |
+
"provider": "azure-openai",
|
| 42 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"payroll_net_pay_001\",\n \"family_id\": \"decimal_copybook_payroll\",\n \"domain\": \"payroll\",\n \"ticket\": \"Migrate PAYROLL.cbl while preserving copybook offsets, implied decimals, signed deductions, bonus condition names, and fixed-width ACH output.\",\n \"available_files\": [\n \"PAYROLL.cbl\"\n ],\n \"available_copybooks\": [\n \"EMPLOYEE_PAY.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 5,\n \"input_width\": 42,\n \"output_width\": 28,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"PAYROLL.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. PAYROLLNET.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY EMPLOYEE_PAY.\\n 01 TAX-AMOUNT PIC 9(7)V99.\\n 01 NET-AMOUNT PIC 9(7)V99.\\n 01 PAY-CATEGORY PIC X.\\n PROCEDURE DIVISION.\\n COMPUTE TAX-AMOUNT ROUNDED = GROSS-PAY * TAX-RATE\\n COMPUTE NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS\\n IF BONUS-ELIGIBLE ADD 50.00 TO NET-AMOUNT END-IF\\n IF NET-AMOUNT < 0 MOVE 0 TO NET-AMOUNT END-IF\\n EVALUATE TRUE\\n WHEN NET-AMOUNT >= 5000.00 MOVE 'H' TO PAY-CATEGORY\\n WHEN NET-AMOUNT >= 2500.00 MOVE 'M' TO PAY-CATEGORY\\n WHEN OTHER MOVE 'L' TO PAY-CATEGORY\\n END-EVALUATE\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"EMPLOYEE_PAY.cpy\": \" 01 EMPLOYEE-PAY-RECORD.\\n 05 EMP-ID PIC X(6).\\n 05 EMP-NAME PIC X(12).\\n 05 GROSS-PAY PIC 9(7)V99.\\n 05 TAX-RATE PIC 9V999.\\n 05 DEDUCTIONS PIC S9(5)V99 SIGN LEADING SEPARATE.\\n 05 BONUS-FLAG PIC X(1).\\n 88 BONUS-ELIGIBLE VALUE 'Y'.\\n 88 NO-BONUS VALUE 'N'.\\n 05 FILLER PIC X(2).\\n\"\n}\n\nParsed layouts:\n{\n \"EMPLOYEE_PAY.cpy\": {\n \"ok\": true,\n \"filename\": \"EMPLOYEE_PAY.cpy\",\n \"record_name\": \"EMPLOYEE-PAY-RECORD\",\n \"total_width\": 42,\n \"fields\": [\n {\n \"name\": \"EMP-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"EMP-NAME\",\n \"start\": 6,\n \"end\": 18,\n \"length\": 12,\n \"pic\": \"X(12)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"GROSS-PAY\",\n \"start\": 18,\n \"end\": 27,\n \"length\": 9,\n \"pic\": \"9(7)V99\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n },\n {\n \"name\": \"TAX-RATE\",\n \"start\": 27,\n \"end\": 31,\n \"length\": 4,\n \"pic\": \"9V999\",\n \"python_type\": \"Decimal\",\n \"scale\": 3\n },\n {\n \"name\": \"DEDUCTIONS\",\n \"start\": 31,\n \"end\": 39,\n \"length\": 8,\n \"pic\": \"S9(5)V99 SIGN LEADING SEPARATE\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n },\n {\n \"name\": \"BONUS-FLAG\",\n \"start\": 39,\n \"end\": 40,\n \"length\": 1,\n \"pic\": \"X(1)\",\n \"python_type\": \"str\",\n \"level_88\": {\n \"BONUS-ELIGIBLE\": \"Y\",\n \"NO-BONUS\": \"N\"\n }\n },\n {\n \"name\": \"FILLER\",\n \"start\": 40,\n \"end\": 42,\n \"length\": 2,\n \"pic\": \"X(2)\",\n \"python_type\": \"str\"\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"Tax is rounded half up to cents after GROSS-PAY * TAX-RATE.\",\n \"NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS.\",\n \"BONUS-ELIGIBLE adds 50.00; negative net pay floors to zero.\",\n \"Output net pay is a 9-digit zero-padded cents field.\"\n]",
|
| 43 |
+
"response": "{\"code\":\"from decimal import Decimal, ROUND_HALF_UP\\n\\ndef migrate(input_record: str) -> str:\\n rec = (input_record or \\\"\\\")\\n if len(rec) < 42:\\n rec = rec.ljust(42)\\n else:\\n rec = rec[:42]\\n\\n gross_str = rec[18:27]\\n tax_rate_str = rec[27:31]\\n deductions_str = rec[31:39]\\n bonus_flag = rec[39:40]\\n\\n gross = Decimal(gross_str) / Decimal('100')\\n tax_rate = Decimal(tax_rate_str) / Decimal('1000')\\n deductions = Decimal(deductions_str) / Decimal('100')\\n\\n tax_amount = (gross * tax_rate).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)\\n net_amount = gross - tax_amount - deductions\\n\\n if bonus_flag == 'Y':\\n net_amount += Decimal('50.00')\\n\\n if net_amount < 0:\\n net_amount = Decimal('0.00')\\n\\n cents = int((net_amount * 100).quantize(Decimal('1'), rounding=ROUND_HALF_UP))\\n return f\\\"{cents:09d}\\\"\\n\"}",
|
| 44 |
+
"code_chars": 850
|
| 45 |
+
}
|
| 46 |
+
],
|
| 47 |
+
"visible": {
|
| 48 |
+
"passed": 0,
|
| 49 |
+
"total": 3,
|
| 50 |
+
"pass_rate": 0.0,
|
| 51 |
+
"failures": [
|
| 52 |
+
{
|
| 53 |
+
"case_id": "visible_1",
|
| 54 |
+
"input_summary": "ordinary bonus-eligible employee",
|
| 55 |
+
"expected_summary": "OUT-EMP-ID=E00001, OUT-EMP-NAME=ALICE , OUT-NET-PAY=000093272, OUT-PAY-CATEGORY=L",
|
| 56 |
+
"actual_summary": "length 9 output: '000093272'",
|
| 57 |
+
"error": null
|
| 58 |
+
},
|
| 59 |
+
{
|
| 60 |
+
"case_id": "visible_2",
|
| 61 |
+
"input_summary": "negative adjustment and no bonus",
|
| 62 |
+
"expected_summary": "OUT-EMP-ID=E00002, OUT-EMP-NAME=BOB , OUT-NET-PAY=000076750, OUT-PAY-CATEGORY=L",
|
| 63 |
+
"actual_summary": "length 9 output: '000076750'",
|
| 64 |
+
"error": null
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"case_id": "visible_3",
|
| 68 |
+
"input_summary": "low net pay floors at zero",
|
| 69 |
+
"expected_summary": "OUT-EMP-ID=E00003, OUT-EMP-NAME=CHANDRA , OUT-NET-PAY=000000000, OUT-PAY-CATEGORY=L",
|
| 70 |
+
"actual_summary": "length 9 output: '000000000'",
|
| 71 |
+
"error": null
|
| 72 |
+
}
|
| 73 |
+
]
|
| 74 |
+
},
|
| 75 |
+
"final": {
|
| 76 |
+
"public_score": 0.15,
|
| 77 |
+
"accepted": false,
|
| 78 |
+
"components": {
|
| 79 |
+
"hidden_correctness": 0.0,
|
| 80 |
+
"fresh_correctness": 0.0,
|
| 81 |
+
"interface_contract": 1.0,
|
| 82 |
+
"type_and_layout_fidelity": 0.0,
|
| 83 |
+
"anti_hardcoding": 0.0,
|
| 84 |
+
"safety": 1.0
|
| 85 |
+
},
|
| 86 |
+
"hidden_passed": 0,
|
| 87 |
+
"hidden_total": 5,
|
| 88 |
+
"fresh_passed": 0,
|
| 89 |
+
"fresh_total": 6
|
| 90 |
+
},
|
| 91 |
+
"steps": [
|
| 92 |
+
{
|
| 93 |
+
"tool_name": "read_cobol_file",
|
| 94 |
+
"arguments": {
|
| 95 |
+
"filename": "PAYROLL.cbl"
|
| 96 |
+
},
|
| 97 |
+
"reward": 0.02,
|
| 98 |
+
"done": false,
|
| 99 |
+
"result": {
|
| 100 |
+
"ok": true,
|
| 101 |
+
"filename": "PAYROLL.cbl",
|
| 102 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. PAYROLLNET.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY EMPLOYEE_PAY.\n 01 TAX-AMOUNT PIC 9(7)V99.\n 01 NET-AMOUNT PIC 9(7)V99.\n 01 PAY-CATEGORY PIC X.\n PROCEDURE DIVISION.\n COMPUTE TAX-AMOUNT ROUNDED = GROSS-PAY * TAX-RATE\n COMPUTE NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS\n IF BONUS-ELIGIBLE ADD 50.00 TO NET-AMOUNT END-IF\n IF NET-AMOUNT < 0 MOVE 0 TO NET-AMOUNT END-IF\n EVALUATE TRUE\n WHEN NET-AMOUNT >= 5000.00 MOVE 'H' TO PAY-CATEGORY\n WHEN NET-AMOUNT >= 2500.00 MOVE 'M' TO PAY-CATEGORY\n WHEN OTHER MOVE 'L' TO PAY-CATEGORY\n END-EVALUATE\n GOBACK.\n",
|
| 103 |
+
"truncated": false
|
| 104 |
+
}
|
| 105 |
+
},
|
| 106 |
+
{
|
| 107 |
+
"tool_name": "read_copybook",
|
| 108 |
+
"arguments": {
|
| 109 |
+
"filename": "EMPLOYEE_PAY.cpy"
|
| 110 |
+
},
|
| 111 |
+
"reward": 0.02,
|
| 112 |
+
"done": false,
|
| 113 |
+
"result": {
|
| 114 |
+
"ok": true,
|
| 115 |
+
"filename": "EMPLOYEE_PAY.cpy",
|
| 116 |
+
"content": " 01 EMPLOYEE-PAY-RECORD.\n 05 EMP-ID PIC X(6).\n 05 EMP-NAME PIC X(12).\n 05 GROSS-PAY PIC 9(7)V99.\n 05 TAX-RATE PIC 9V999.\n 05 DEDUCTIONS PIC S9(5)V99 SIGN LEADING SEPARATE.\n 05 BONUS-FLAG PIC X(1).\n 88 BONUS-ELIGIBLE VALUE 'Y'.\n 88 NO-BONUS VALUE 'N'.\n 05 FILLER PIC X(2).\n"
|
| 117 |
+
}
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"tool_name": "parse_copybook_layout",
|
| 121 |
+
"arguments": {
|
| 122 |
+
"filename": "EMPLOYEE_PAY.cpy"
|
| 123 |
+
},
|
| 124 |
+
"reward": 0.03,
|
| 125 |
+
"done": false,
|
| 126 |
+
"result": {
|
| 127 |
+
"ok": true,
|
| 128 |
+
"filename": "EMPLOYEE_PAY.cpy",
|
| 129 |
+
"record_name": "EMPLOYEE-PAY-RECORD",
|
| 130 |
+
"total_width": 42,
|
| 131 |
+
"fields": [
|
| 132 |
+
{
|
| 133 |
+
"name": "EMP-ID",
|
| 134 |
+
"start": 0,
|
| 135 |
+
"end": 6,
|
| 136 |
+
"length": 6,
|
| 137 |
+
"pic": "X(6)",
|
| 138 |
+
"python_type": "str"
|
| 139 |
+
},
|
| 140 |
+
{
|
| 141 |
+
"name": "EMP-NAME",
|
| 142 |
+
"start": 6,
|
| 143 |
+
"end": 18,
|
| 144 |
+
"length": 12,
|
| 145 |
+
"pic": "X(12)",
|
| 146 |
+
"python_type": "str"
|
| 147 |
+
},
|
| 148 |
+
{
|
| 149 |
+
"name": "GROSS-PAY",
|
| 150 |
+
"start": 18,
|
| 151 |
+
"end": 27,
|
| 152 |
+
"length": 9,
|
| 153 |
+
"pic": "9(7)V99",
|
| 154 |
+
"python_type": "Decimal",
|
| 155 |
+
"scale": 2
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
"name": "TAX-RATE",
|
| 159 |
+
"start": 27,
|
| 160 |
+
"end": 31,
|
| 161 |
+
"length": 4,
|
| 162 |
+
"pic": "9V999",
|
| 163 |
+
"python_type": "Decimal",
|
| 164 |
+
"scale": 3
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"name": "DEDUCTIONS",
|
| 168 |
+
"start": 31,
|
| 169 |
+
"end": 39,
|
| 170 |
+
"length": 8,
|
| 171 |
+
"pic": "S9(5)V99 SIGN LEADING SEPARATE",
|
| 172 |
+
"python_type": "Decimal",
|
| 173 |
+
"scale": 2
|
| 174 |
+
},
|
| 175 |
+
{
|
| 176 |
+
"name": "BONUS-FLAG",
|
| 177 |
+
"start": 39,
|
| 178 |
+
"end": 40,
|
| 179 |
+
"length": 1,
|
| 180 |
+
"pic": "X(1)",
|
| 181 |
+
"python_type": "str",
|
| 182 |
+
"level_88": {
|
| 183 |
+
"BONUS-ELIGIBLE": "Y",
|
| 184 |
+
"NO-BONUS": "N"
|
| 185 |
+
}
|
| 186 |
+
},
|
| 187 |
+
{
|
| 188 |
+
"name": "FILLER",
|
| 189 |
+
"start": 40,
|
| 190 |
+
"end": 42,
|
| 191 |
+
"length": 2,
|
| 192 |
+
"pic": "X(2)",
|
| 193 |
+
"python_type": "str"
|
| 194 |
+
}
|
| 195 |
+
]
|
| 196 |
+
}
|
| 197 |
+
},
|
| 198 |
+
{
|
| 199 |
+
"tool_name": "inspect_business_rules",
|
| 200 |
+
"arguments": {},
|
| 201 |
+
"reward": 0.01,
|
| 202 |
+
"done": false,
|
| 203 |
+
"result": {
|
| 204 |
+
"ok": true,
|
| 205 |
+
"rules": [
|
| 206 |
+
"Tax is rounded half up to cents after GROSS-PAY * TAX-RATE.",
|
| 207 |
+
"NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS.",
|
| 208 |
+
"BONUS-ELIGIBLE adds 50.00; negative net pay floors to zero.",
|
| 209 |
+
"Output net pay is a 9-digit zero-padded cents field."
|
| 210 |
+
]
|
| 211 |
+
}
|
| 212 |
+
},
|
| 213 |
+
{
|
| 214 |
+
"tool_name": "write_python_solution",
|
| 215 |
+
"arguments": {
|
| 216 |
+
"code_chars": 850
|
| 217 |
+
},
|
| 218 |
+
"reward": 0.02,
|
| 219 |
+
"done": false,
|
| 220 |
+
"result": {
|
| 221 |
+
"ok": true,
|
| 222 |
+
"draft_id": 1,
|
| 223 |
+
"syntax_ok": true,
|
| 224 |
+
"safety_ok": true,
|
| 225 |
+
"error": null
|
| 226 |
+
}
|
| 227 |
+
},
|
| 228 |
+
{
|
| 229 |
+
"tool_name": "run_visible_tests",
|
| 230 |
+
"arguments": {
|
| 231 |
+
"draft_id": 1
|
| 232 |
+
},
|
| 233 |
+
"reward": 0.0,
|
| 234 |
+
"done": false,
|
| 235 |
+
"result": {
|
| 236 |
+
"ok": true,
|
| 237 |
+
"draft_id": 1,
|
| 238 |
+
"passed": 0,
|
| 239 |
+
"total": 3,
|
| 240 |
+
"pass_rate": 0.0,
|
| 241 |
+
"syntax_ok": true,
|
| 242 |
+
"safety_ok": true,
|
| 243 |
+
"interface_ok": true,
|
| 244 |
+
"timed_out": false,
|
| 245 |
+
"error": null,
|
| 246 |
+
"failures": [
|
| 247 |
+
{
|
| 248 |
+
"case_id": "visible_1",
|
| 249 |
+
"input_summary": "ordinary bonus-eligible employee",
|
| 250 |
+
"expected_summary": "OUT-EMP-ID=E00001, OUT-EMP-NAME=ALICE , OUT-NET-PAY=000093272, OUT-PAY-CATEGORY=L",
|
| 251 |
+
"actual_summary": "length 9 output: '000093272'",
|
| 252 |
+
"error": null
|
| 253 |
+
},
|
| 254 |
+
{
|
| 255 |
+
"case_id": "visible_2",
|
| 256 |
+
"input_summary": "negative adjustment and no bonus",
|
| 257 |
+
"expected_summary": "OUT-EMP-ID=E00002, OUT-EMP-NAME=BOB , OUT-NET-PAY=000076750, OUT-PAY-CATEGORY=L",
|
| 258 |
+
"actual_summary": "length 9 output: '000076750'",
|
| 259 |
+
"error": null
|
| 260 |
+
},
|
| 261 |
+
{
|
| 262 |
+
"case_id": "visible_3",
|
| 263 |
+
"input_summary": "low net pay floors at zero",
|
| 264 |
+
"expected_summary": "OUT-EMP-ID=E00003, OUT-EMP-NAME=CHANDRA , OUT-NET-PAY=000000000, OUT-PAY-CATEGORY=L",
|
| 265 |
+
"actual_summary": "length 9 output: '000000000'",
|
| 266 |
+
"error": null
|
| 267 |
+
}
|
| 268 |
+
]
|
| 269 |
+
}
|
| 270 |
+
},
|
| 271 |
+
{
|
| 272 |
+
"tool_name": "submit_final",
|
| 273 |
+
"arguments": {
|
| 274 |
+
"draft_id": 1
|
| 275 |
+
},
|
| 276 |
+
"reward": 0.15,
|
| 277 |
+
"done": true,
|
| 278 |
+
"result": {
|
| 279 |
+
"ok": true,
|
| 280 |
+
"accepted": false,
|
| 281 |
+
"episode_done": true,
|
| 282 |
+
"public_score": 0.15,
|
| 283 |
+
"components": {
|
| 284 |
+
"hidden_correctness": 0.0,
|
| 285 |
+
"fresh_correctness": 0.0,
|
| 286 |
+
"interface_contract": 1.0,
|
| 287 |
+
"type_and_layout_fidelity": 0.0,
|
| 288 |
+
"anti_hardcoding": 0.0,
|
| 289 |
+
"safety": 1.0
|
| 290 |
+
},
|
| 291 |
+
"hidden_passed": 0,
|
| 292 |
+
"hidden_total": 5,
|
| 293 |
+
"fresh_passed": 0,
|
| 294 |
+
"fresh_total": 6,
|
| 295 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 296 |
+
}
|
| 297 |
+
}
|
| 298 |
+
]
|
| 299 |
+
},
|
| 300 |
+
{
|
| 301 |
+
"policy": "azure-openai",
|
| 302 |
+
"task_id": "customer_format_001",
|
| 303 |
+
"family_id": "fixed_width_customer",
|
| 304 |
+
"ticket": {
|
| 305 |
+
"task_id": "customer_format_001",
|
| 306 |
+
"family_id": "fixed_width_customer",
|
| 307 |
+
"domain": "customer master data",
|
| 308 |
+
"ticket": "Migrate CUSTFMT.cbl. Preserve fixed-width name formatting, status mapping, ZIP leading zeros, and zero-padded balance output.",
|
| 309 |
+
"available_files": [
|
| 310 |
+
"CUSTFMT.cbl"
|
| 311 |
+
],
|
| 312 |
+
"available_copybooks": [
|
| 313 |
+
"CUSTOMER_REC.cpy"
|
| 314 |
+
],
|
| 315 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 316 |
+
"visible_tests": 3,
|
| 317 |
+
"hidden_tests": 3,
|
| 318 |
+
"input_width": 40,
|
| 319 |
+
"output_width": 41,
|
| 320 |
+
"max_steps": 12,
|
| 321 |
+
"allowed_tools": [
|
| 322 |
+
"read_cobol_file",
|
| 323 |
+
"read_copybook",
|
| 324 |
+
"parse_copybook_layout",
|
| 325 |
+
"inspect_business_rules",
|
| 326 |
+
"write_python_solution",
|
| 327 |
+
"run_visible_tests",
|
| 328 |
+
"inspect_diff",
|
| 329 |
+
"submit_final"
|
| 330 |
+
]
|
| 331 |
+
},
|
| 332 |
+
"model_turns": [
|
| 333 |
+
{
|
| 334 |
+
"provider": "azure-openai",
|
| 335 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"customer_format_001\",\n \"family_id\": \"fixed_width_customer\",\n \"domain\": \"customer master data\",\n \"ticket\": \"Migrate CUSTFMT.cbl. Preserve fixed-width name formatting, status mapping, ZIP leading zeros, and zero-padded balance output.\",\n \"available_files\": [\n \"CUSTFMT.cbl\"\n ],\n \"available_copybooks\": [\n \"CUSTOMER_REC.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 3,\n \"input_width\": 40,\n \"output_width\": 41,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"CUSTFMT.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. CUSTFMT.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY CUSTOMER_REC.\\n 01 OUTPUT-RECORD.\\n 05 OUT-CUST-ID PIC X(5).\\n 05 OUT-FULL-NAME PIC X(22).\\n 05 OUT-ZIP-CODE PIC 9(5).\\n 05 OUT-STATUS PIC X.\\n 05 OUT-BALANCE PIC 9(6)V99.\\n PROCEDURE DIVISION.\\n STRING LAST-NAME DELIMITED BY SIZE ', ' FIRST-NAME DELIMITED BY SIZE\\n INTO OUT-FULL-NAME\\n EVALUATE STATUS-CODE\\n WHEN 'A' MOVE 'O' TO OUT-STATUS\\n WHEN 'S' MOVE 'S' TO OUT-STATUS\\n WHEN OTHER MOVE 'C' TO OUT-STATUS\\n END-EVALUATE\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"CUSTOMER_REC.cpy\": \" 01 CUSTOMER-RECORD.\\n 05 CUST-ID PIC X(5).\\n 05 FIRST-NAME PIC X(10).\\n 05 LAST-NAME PIC X(12).\\n 05 ZIP-CODE PIC 9(5).\\n 05 STATUS-CODE PIC X.\\n 88 ACTIVE-CUSTOMER VALUE 'A'.\\n 88 SUSPENDED-CUSTOMER VALUE 'S'.\\n 88 CLOSED-CUSTOMER VALUE 'C'.\\n 05 BALANCE-DUE PIC 9(5)V99.\\n\"\n}\n\nParsed layouts:\n{\n \"CUSTOMER_REC.cpy\": {\n \"ok\": true,\n \"filename\": \"CUSTOMER_REC.cpy\",\n \"record_name\": \"CUSTOMER-RECORD\",\n \"total_width\": 40,\n \"fields\": [\n {\n \"name\": \"CUST-ID\",\n \"start\": 0,\n \"end\": 5,\n \"length\": 5,\n \"pic\": \"X(5)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"FIRST-NAME\",\n \"start\": 5,\n \"end\": 15,\n \"length\": 10,\n \"pic\": \"X(10)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"LAST-NAME\",\n \"start\": 15,\n \"end\": 27,\n \"length\": 12,\n \"pic\": \"X(12)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"ZIP-CODE\",\n \"start\": 27,\n \"end\": 32,\n \"length\": 5,\n \"pic\": \"9(5)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"STATUS-CODE\",\n \"start\": 32,\n \"end\": 33,\n \"length\": 1,\n \"pic\": \"X\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"BALANCE-DUE\",\n \"start\": 33,\n \"end\": 40,\n \"length\": 7,\n \"pic\": \"9(5)V99\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"OUT-FULL-NAME is LAST-NAME, comma-space, FIRST-NAME, truncated/padded to 22.\",\n \"A maps to O, S maps to S, anything else maps to C.\",\n \"ZIP stays five digits and OUT-BALANCE is eight zero-padded digits.\"\n]",
|
| 336 |
+
"response": "{\"code\":\"def migrate(input_record: str) -> str:\\n \\\"\\\"\\\"Migrate a fixed-width customer record from legacy COBOL format.\\n\\n Input width: 40\\n Output width: 41\\n \\\"\\\"\\\"\\n rec = (input_record or \\\"\\\")\\n if len(rec) < 40:\\n rec = rec.ljust(40)\\n else:\\n rec = rec[:40]\\n\\n cust_id = rec[0:5]\\n first_name = rec[5:15].rstrip()\\n last_name = rec[15:27].rstrip()\\n zip_code = rec[27:32]\\n status_code = rec[32:33]\\n balance_raw = rec[33:40]\\n\\n full_name = f\\\"{last_name}, {first_name}\\\"\\n full_name = full_name[:22].ljust(22)\\n\\n if status_code == 'A':\\n out_status = 'O'\\n elif status_code == 'S':\\n out_status = 'S'\\n else:\\n out_status = 'C'\\n\\n # COBOL PIC 9(5)V99 -> 7 input digits, output requires 8 zero-padded digits.\\n # Preserve numeric value and emit 8 digits.\\n digits = ''.join(ch for ch in balance_raw if ch.isdigit())\\n digits = digits.rjust(7, '0')[-7:]\\n out_balance = digits.rjust(8, '0')\\n\\n return f\\\"{cust_id}{full_name}{zip_code}{out_status}{out_balance}\\\"\\n\"}",
|
| 337 |
+
"code_chars": 1025
|
| 338 |
+
}
|
| 339 |
+
],
|
| 340 |
+
"visible": {
|
| 341 |
+
"passed": 3,
|
| 342 |
+
"total": 3,
|
| 343 |
+
"pass_rate": 1.0,
|
| 344 |
+
"failures": []
|
| 345 |
+
},
|
| 346 |
+
"final": {
|
| 347 |
+
"public_score": 1.0,
|
| 348 |
+
"accepted": true,
|
| 349 |
+
"components": {
|
| 350 |
+
"hidden_correctness": 1.0,
|
| 351 |
+
"fresh_correctness": 1.0,
|
| 352 |
+
"interface_contract": 1.0,
|
| 353 |
+
"type_and_layout_fidelity": 1.0,
|
| 354 |
+
"anti_hardcoding": 1.0,
|
| 355 |
+
"safety": 1.0
|
| 356 |
+
},
|
| 357 |
+
"hidden_passed": 3,
|
| 358 |
+
"hidden_total": 3,
|
| 359 |
+
"fresh_passed": 6,
|
| 360 |
+
"fresh_total": 6
|
| 361 |
+
},
|
| 362 |
+
"steps": [
|
| 363 |
+
{
|
| 364 |
+
"tool_name": "read_cobol_file",
|
| 365 |
+
"arguments": {
|
| 366 |
+
"filename": "CUSTFMT.cbl"
|
| 367 |
+
},
|
| 368 |
+
"reward": 0.02,
|
| 369 |
+
"done": false,
|
| 370 |
+
"result": {
|
| 371 |
+
"ok": true,
|
| 372 |
+
"filename": "CUSTFMT.cbl",
|
| 373 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. CUSTFMT.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY CUSTOMER_REC.\n 01 OUTPUT-RECORD.\n 05 OUT-CUST-ID PIC X(5).\n 05 OUT-FULL-NAME PIC X(22).\n 05 OUT-ZIP-CODE PIC 9(5).\n 05 OUT-STATUS PIC X.\n 05 OUT-BALANCE PIC 9(6)V99.\n PROCEDURE DIVISION.\n STRING LAST-NAME DELIMITED BY SIZE ', ' FIRST-NAME DELIMITED BY SIZE\n INTO OUT-FULL-NAME\n EVALUATE STATUS-CODE\n WHEN 'A' MOVE 'O' TO OUT-STATUS\n WHEN 'S' MOVE 'S' TO OUT-STATUS\n WHEN OTHER MOVE 'C' TO OUT-STATUS\n END-EVALUATE\n GOBACK.\n",
|
| 374 |
+
"truncated": false
|
| 375 |
+
}
|
| 376 |
+
},
|
| 377 |
+
{
|
| 378 |
+
"tool_name": "read_copybook",
|
| 379 |
+
"arguments": {
|
| 380 |
+
"filename": "CUSTOMER_REC.cpy"
|
| 381 |
+
},
|
| 382 |
+
"reward": 0.02,
|
| 383 |
+
"done": false,
|
| 384 |
+
"result": {
|
| 385 |
+
"ok": true,
|
| 386 |
+
"filename": "CUSTOMER_REC.cpy",
|
| 387 |
+
"content": " 01 CUSTOMER-RECORD.\n 05 CUST-ID PIC X(5).\n 05 FIRST-NAME PIC X(10).\n 05 LAST-NAME PIC X(12).\n 05 ZIP-CODE PIC 9(5).\n 05 STATUS-CODE PIC X.\n 88 ACTIVE-CUSTOMER VALUE 'A'.\n 88 SUSPENDED-CUSTOMER VALUE 'S'.\n 88 CLOSED-CUSTOMER VALUE 'C'.\n 05 BALANCE-DUE PIC 9(5)V99.\n"
|
| 388 |
+
}
|
| 389 |
+
},
|
| 390 |
+
{
|
| 391 |
+
"tool_name": "parse_copybook_layout",
|
| 392 |
+
"arguments": {
|
| 393 |
+
"filename": "CUSTOMER_REC.cpy"
|
| 394 |
+
},
|
| 395 |
+
"reward": 0.03,
|
| 396 |
+
"done": false,
|
| 397 |
+
"result": {
|
| 398 |
+
"ok": true,
|
| 399 |
+
"filename": "CUSTOMER_REC.cpy",
|
| 400 |
+
"record_name": "CUSTOMER-RECORD",
|
| 401 |
+
"total_width": 40,
|
| 402 |
+
"fields": [
|
| 403 |
+
{
|
| 404 |
+
"name": "CUST-ID",
|
| 405 |
+
"start": 0,
|
| 406 |
+
"end": 5,
|
| 407 |
+
"length": 5,
|
| 408 |
+
"pic": "X(5)",
|
| 409 |
+
"python_type": "str"
|
| 410 |
+
},
|
| 411 |
+
{
|
| 412 |
+
"name": "FIRST-NAME",
|
| 413 |
+
"start": 5,
|
| 414 |
+
"end": 15,
|
| 415 |
+
"length": 10,
|
| 416 |
+
"pic": "X(10)",
|
| 417 |
+
"python_type": "str"
|
| 418 |
+
},
|
| 419 |
+
{
|
| 420 |
+
"name": "LAST-NAME",
|
| 421 |
+
"start": 15,
|
| 422 |
+
"end": 27,
|
| 423 |
+
"length": 12,
|
| 424 |
+
"pic": "X(12)",
|
| 425 |
+
"python_type": "str"
|
| 426 |
+
},
|
| 427 |
+
{
|
| 428 |
+
"name": "ZIP-CODE",
|
| 429 |
+
"start": 27,
|
| 430 |
+
"end": 32,
|
| 431 |
+
"length": 5,
|
| 432 |
+
"pic": "9(5)",
|
| 433 |
+
"python_type": "str"
|
| 434 |
+
},
|
| 435 |
+
{
|
| 436 |
+
"name": "STATUS-CODE",
|
| 437 |
+
"start": 32,
|
| 438 |
+
"end": 33,
|
| 439 |
+
"length": 1,
|
| 440 |
+
"pic": "X",
|
| 441 |
+
"python_type": "str"
|
| 442 |
+
},
|
| 443 |
+
{
|
| 444 |
+
"name": "BALANCE-DUE",
|
| 445 |
+
"start": 33,
|
| 446 |
+
"end": 40,
|
| 447 |
+
"length": 7,
|
| 448 |
+
"pic": "9(5)V99",
|
| 449 |
+
"python_type": "Decimal",
|
| 450 |
+
"scale": 2
|
| 451 |
+
}
|
| 452 |
+
]
|
| 453 |
+
}
|
| 454 |
+
},
|
| 455 |
+
{
|
| 456 |
+
"tool_name": "inspect_business_rules",
|
| 457 |
+
"arguments": {},
|
| 458 |
+
"reward": 0.01,
|
| 459 |
+
"done": false,
|
| 460 |
+
"result": {
|
| 461 |
+
"ok": true,
|
| 462 |
+
"rules": [
|
| 463 |
+
"OUT-FULL-NAME is LAST-NAME, comma-space, FIRST-NAME, truncated/padded to 22.",
|
| 464 |
+
"A maps to O, S maps to S, anything else maps to C.",
|
| 465 |
+
"ZIP stays five digits and OUT-BALANCE is eight zero-padded digits."
|
| 466 |
+
]
|
| 467 |
+
}
|
| 468 |
+
},
|
| 469 |
+
{
|
| 470 |
+
"tool_name": "write_python_solution",
|
| 471 |
+
"arguments": {
|
| 472 |
+
"code_chars": 1025
|
| 473 |
+
},
|
| 474 |
+
"reward": 0.02,
|
| 475 |
+
"done": false,
|
| 476 |
+
"result": {
|
| 477 |
+
"ok": true,
|
| 478 |
+
"draft_id": 1,
|
| 479 |
+
"syntax_ok": true,
|
| 480 |
+
"safety_ok": true,
|
| 481 |
+
"error": null
|
| 482 |
+
}
|
| 483 |
+
},
|
| 484 |
+
{
|
| 485 |
+
"tool_name": "run_visible_tests",
|
| 486 |
+
"arguments": {
|
| 487 |
+
"draft_id": 1
|
| 488 |
+
},
|
| 489 |
+
"reward": 0.05,
|
| 490 |
+
"done": false,
|
| 491 |
+
"result": {
|
| 492 |
+
"ok": true,
|
| 493 |
+
"draft_id": 1,
|
| 494 |
+
"passed": 3,
|
| 495 |
+
"total": 3,
|
| 496 |
+
"pass_rate": 1.0,
|
| 497 |
+
"syntax_ok": true,
|
| 498 |
+
"safety_ok": true,
|
| 499 |
+
"interface_ok": true,
|
| 500 |
+
"timed_out": false,
|
| 501 |
+
"error": null,
|
| 502 |
+
"failures": []
|
| 503 |
+
}
|
| 504 |
+
},
|
| 505 |
+
{
|
| 506 |
+
"tool_name": "submit_final",
|
| 507 |
+
"arguments": {
|
| 508 |
+
"draft_id": 1
|
| 509 |
+
},
|
| 510 |
+
"reward": 1.0,
|
| 511 |
+
"done": true,
|
| 512 |
+
"result": {
|
| 513 |
+
"ok": true,
|
| 514 |
+
"accepted": true,
|
| 515 |
+
"episode_done": true,
|
| 516 |
+
"public_score": 1.0,
|
| 517 |
+
"components": {
|
| 518 |
+
"hidden_correctness": 1.0,
|
| 519 |
+
"fresh_correctness": 1.0,
|
| 520 |
+
"interface_contract": 1.0,
|
| 521 |
+
"type_and_layout_fidelity": 1.0,
|
| 522 |
+
"anti_hardcoding": 1.0,
|
| 523 |
+
"safety": 1.0
|
| 524 |
+
},
|
| 525 |
+
"hidden_passed": 3,
|
| 526 |
+
"hidden_total": 3,
|
| 527 |
+
"fresh_passed": 6,
|
| 528 |
+
"fresh_total": 6,
|
| 529 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 530 |
+
}
|
| 531 |
+
}
|
| 532 |
+
]
|
| 533 |
+
},
|
| 534 |
+
{
|
| 535 |
+
"policy": "azure-openai",
|
| 536 |
+
"task_id": "claims_eligibility_001",
|
| 537 |
+
"family_id": "claims_eligibility_branching",
|
| 538 |
+
"ticket": {
|
| 539 |
+
"task_id": "claims_eligibility_001",
|
| 540 |
+
"family_id": "claims_eligibility_branching",
|
| 541 |
+
"domain": "insurance claims",
|
| 542 |
+
"ticket": "Migrate CLMELIG.cbl. Preserve EVALUATE TRUE branch precedence for claim approvals, denials, and manual review reasons.",
|
| 543 |
+
"available_files": [
|
| 544 |
+
"CLMELIG.cbl"
|
| 545 |
+
],
|
| 546 |
+
"available_copybooks": [
|
| 547 |
+
"CLAIM_REC.cpy"
|
| 548 |
+
],
|
| 549 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 550 |
+
"visible_tests": 3,
|
| 551 |
+
"hidden_tests": 3,
|
| 552 |
+
"input_width": 21,
|
| 553 |
+
"output_width": 9,
|
| 554 |
+
"max_steps": 12,
|
| 555 |
+
"allowed_tools": [
|
| 556 |
+
"read_cobol_file",
|
| 557 |
+
"read_copybook",
|
| 558 |
+
"parse_copybook_layout",
|
| 559 |
+
"inspect_business_rules",
|
| 560 |
+
"write_python_solution",
|
| 561 |
+
"run_visible_tests",
|
| 562 |
+
"inspect_diff",
|
| 563 |
+
"submit_final"
|
| 564 |
+
]
|
| 565 |
+
},
|
| 566 |
+
"model_turns": [
|
| 567 |
+
{
|
| 568 |
+
"provider": "azure-openai",
|
| 569 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"claims_eligibility_001\",\n \"family_id\": \"claims_eligibility_branching\",\n \"domain\": \"insurance claims\",\n \"ticket\": \"Migrate CLMELIG.cbl. Preserve EVALUATE TRUE branch precedence for claim approvals, denials, and manual review reasons.\",\n \"available_files\": [\n \"CLMELIG.cbl\"\n ],\n \"available_copybooks\": [\n \"CLAIM_REC.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 3,\n \"input_width\": 21,\n \"output_width\": 9,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"CLMELIG.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. CLMELIG.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY CLAIM_REC.\\n PROCEDURE DIVISION.\\n EVALUATE TRUE\\n WHEN AGE < 18 MOVE 'D' TO DECISION MOVE 'A1' TO REASON\\n WHEN PLAN-CODE = 'B' AND CLAIM-AMOUNT > 1500.00 MOVE 'R' TO DECISION MOVE 'B2' TO REASON\\n WHEN PREAUTH-FLAG = 'N' AND CLAIM-AMOUNT > 1000.00 MOVE 'D' TO DECISION MOVE 'P1' TO REASON\\n WHEN SERVICE-DAYS > 030 MOVE 'R' TO DECISION MOVE 'L1' TO REASON\\n WHEN OTHER MOVE 'A' TO DECISION MOVE 'OK' TO REASON\\n END-EVALUATE\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"CLAIM_REC.cpy\": \" 01 CLAIM-RECORD.\\n 05 CLAIM-ID PIC X(6).\\n 05 AGE PIC 9(3).\\n 05 PLAN-CODE PIC X.\\n 05 SERVICE-DAYS PIC 9(3).\\n 05 PREAUTH-FLAG PIC X.\\n 05 CLAIM-AMOUNT PIC 9(5)V99.\\n\"\n}\n\nParsed layouts:\n{\n \"CLAIM_REC.cpy\": {\n \"ok\": true,\n \"filename\": \"CLAIM_REC.cpy\",\n \"record_name\": \"CLAIM-RECORD\",\n \"total_width\": 21,\n \"fields\": [\n {\n \"name\": \"CLAIM-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"AGE\",\n \"start\": 6,\n \"end\": 9,\n \"length\": 3,\n \"pic\": \"9(3)\",\n \"python_type\": \"int\"\n },\n {\n \"name\": \"PLAN-CODE\",\n \"start\": 9,\n \"end\": 10,\n \"length\": 1,\n \"pic\": \"X\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"SERVICE-DAYS\",\n \"start\": 10,\n \"end\": 13,\n \"length\": 3,\n \"pic\": \"9(3)\",\n \"python_type\": \"int\"\n },\n {\n \"name\": \"PREAUTH-FLAG\",\n \"start\": 13,\n \"end\": 14,\n \"length\": 1,\n \"pic\": \"X\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"CLAIM-AMOUNT\",\n \"start\": 14,\n \"end\": 21,\n \"length\": 7,\n \"pic\": \"9(5)V99\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"Branch order matters: age, plan-B large claim, missing preauth, long service, default approve.\",\n \"Amounts are implied cents; 100000 means 1000.00.\"\n]",
|
| 570 |
+
"response": "{\"code\":\"from decimal import Decimal\\n\\ndef migrate(input_record: str) -> str:\\n rec = (input_record or \\\"\\\").ljust(21)[:21]\\n\\n def to_int(s: str) -> int:\\n s = s.strip()\\n return int(s) if s else 0\\n\\n def to_amount(s: str) -> Decimal:\\n s = s.strip()\\n if not s:\\n return Decimal('0.00')\\n return Decimal(int(s)) / Decimal('100')\\n\\n age = to_int(rec[6:9])\\n plan_code = rec[9:10]\\n service_days = to_int(rec[10:13])\\n preauth_flag = rec[13:14]\\n claim_amount = to_amount(rec[14:21])\\n\\n decision = 'A'\\n reason = 'OK'\\n\\n if age < 18:\\n decision = 'D'\\n reason = 'A1'\\n elif plan_code == 'B' and claim_amount > Decimal('1500.00'):\\n decision = 'R'\\n reason = 'B2'\\n elif preauth_flag == 'N' and claim_amount > Decimal('1000.00'):\\n decision = 'D'\\n reason = 'P1'\\n elif service_days > 30:\\n decision = 'R'\\n reason = 'L1'\\n\\n return f\\\"{decision}{reason}\\\"\\n\"}",
|
| 571 |
+
"code_chars": 958
|
| 572 |
+
}
|
| 573 |
+
],
|
| 574 |
+
"visible": {
|
| 575 |
+
"passed": 0,
|
| 576 |
+
"total": 3,
|
| 577 |
+
"pass_rate": 0.0,
|
| 578 |
+
"failures": [
|
| 579 |
+
{
|
| 580 |
+
"case_id": "visible_1",
|
| 581 |
+
"input_summary": "ordinary approved claim",
|
| 582 |
+
"expected_summary": "OUT-CLAIM-ID=CLM001, OUT-DECISION=A, OUT-REASON=OK",
|
| 583 |
+
"actual_summary": "length 3 output: 'AOK'",
|
| 584 |
+
"error": null
|
| 585 |
+
},
|
| 586 |
+
{
|
| 587 |
+
"case_id": "visible_2",
|
| 588 |
+
"input_summary": "missing preauth denial",
|
| 589 |
+
"expected_summary": "OUT-CLAIM-ID=CLM002, OUT-DECISION=D, OUT-REASON=P1",
|
| 590 |
+
"actual_summary": "length 3 output: 'DP1'",
|
| 591 |
+
"error": null
|
| 592 |
+
},
|
| 593 |
+
{
|
| 594 |
+
"case_id": "visible_3",
|
| 595 |
+
"input_summary": "long service review",
|
| 596 |
+
"expected_summary": "OUT-CLAIM-ID=CLM003, OUT-DECISION=R, OUT-REASON=L1",
|
| 597 |
+
"actual_summary": "length 3 output: 'RL1'",
|
| 598 |
+
"error": null
|
| 599 |
+
}
|
| 600 |
+
]
|
| 601 |
+
},
|
| 602 |
+
"final": {
|
| 603 |
+
"public_score": 0.15,
|
| 604 |
+
"accepted": false,
|
| 605 |
+
"components": {
|
| 606 |
+
"hidden_correctness": 0.0,
|
| 607 |
+
"fresh_correctness": 0.0,
|
| 608 |
+
"interface_contract": 1.0,
|
| 609 |
+
"type_and_layout_fidelity": 0.0,
|
| 610 |
+
"anti_hardcoding": 0.0,
|
| 611 |
+
"safety": 1.0
|
| 612 |
+
},
|
| 613 |
+
"hidden_passed": 0,
|
| 614 |
+
"hidden_total": 3,
|
| 615 |
+
"fresh_passed": 0,
|
| 616 |
+
"fresh_total": 6
|
| 617 |
+
},
|
| 618 |
+
"steps": [
|
| 619 |
+
{
|
| 620 |
+
"tool_name": "read_cobol_file",
|
| 621 |
+
"arguments": {
|
| 622 |
+
"filename": "CLMELIG.cbl"
|
| 623 |
+
},
|
| 624 |
+
"reward": 0.02,
|
| 625 |
+
"done": false,
|
| 626 |
+
"result": {
|
| 627 |
+
"ok": true,
|
| 628 |
+
"filename": "CLMELIG.cbl",
|
| 629 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. CLMELIG.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY CLAIM_REC.\n PROCEDURE DIVISION.\n EVALUATE TRUE\n WHEN AGE < 18 MOVE 'D' TO DECISION MOVE 'A1' TO REASON\n WHEN PLAN-CODE = 'B' AND CLAIM-AMOUNT > 1500.00 MOVE 'R' TO DECISION MOVE 'B2' TO REASON\n WHEN PREAUTH-FLAG = 'N' AND CLAIM-AMOUNT > 1000.00 MOVE 'D' TO DECISION MOVE 'P1' TO REASON\n WHEN SERVICE-DAYS > 030 MOVE 'R' TO DECISION MOVE 'L1' TO REASON\n WHEN OTHER MOVE 'A' TO DECISION MOVE 'OK' TO REASON\n END-EVALUATE\n GOBACK.\n",
|
| 630 |
+
"truncated": false
|
| 631 |
+
}
|
| 632 |
+
},
|
| 633 |
+
{
|
| 634 |
+
"tool_name": "read_copybook",
|
| 635 |
+
"arguments": {
|
| 636 |
+
"filename": "CLAIM_REC.cpy"
|
| 637 |
+
},
|
| 638 |
+
"reward": 0.02,
|
| 639 |
+
"done": false,
|
| 640 |
+
"result": {
|
| 641 |
+
"ok": true,
|
| 642 |
+
"filename": "CLAIM_REC.cpy",
|
| 643 |
+
"content": " 01 CLAIM-RECORD.\n 05 CLAIM-ID PIC X(6).\n 05 AGE PIC 9(3).\n 05 PLAN-CODE PIC X.\n 05 SERVICE-DAYS PIC 9(3).\n 05 PREAUTH-FLAG PIC X.\n 05 CLAIM-AMOUNT PIC 9(5)V99.\n"
|
| 644 |
+
}
|
| 645 |
+
},
|
| 646 |
+
{
|
| 647 |
+
"tool_name": "parse_copybook_layout",
|
| 648 |
+
"arguments": {
|
| 649 |
+
"filename": "CLAIM_REC.cpy"
|
| 650 |
+
},
|
| 651 |
+
"reward": 0.03,
|
| 652 |
+
"done": false,
|
| 653 |
+
"result": {
|
| 654 |
+
"ok": true,
|
| 655 |
+
"filename": "CLAIM_REC.cpy",
|
| 656 |
+
"record_name": "CLAIM-RECORD",
|
| 657 |
+
"total_width": 21,
|
| 658 |
+
"fields": [
|
| 659 |
+
{
|
| 660 |
+
"name": "CLAIM-ID",
|
| 661 |
+
"start": 0,
|
| 662 |
+
"end": 6,
|
| 663 |
+
"length": 6,
|
| 664 |
+
"pic": "X(6)",
|
| 665 |
+
"python_type": "str"
|
| 666 |
+
},
|
| 667 |
+
{
|
| 668 |
+
"name": "AGE",
|
| 669 |
+
"start": 6,
|
| 670 |
+
"end": 9,
|
| 671 |
+
"length": 3,
|
| 672 |
+
"pic": "9(3)",
|
| 673 |
+
"python_type": "int"
|
| 674 |
+
},
|
| 675 |
+
{
|
| 676 |
+
"name": "PLAN-CODE",
|
| 677 |
+
"start": 9,
|
| 678 |
+
"end": 10,
|
| 679 |
+
"length": 1,
|
| 680 |
+
"pic": "X",
|
| 681 |
+
"python_type": "str"
|
| 682 |
+
},
|
| 683 |
+
{
|
| 684 |
+
"name": "SERVICE-DAYS",
|
| 685 |
+
"start": 10,
|
| 686 |
+
"end": 13,
|
| 687 |
+
"length": 3,
|
| 688 |
+
"pic": "9(3)",
|
| 689 |
+
"python_type": "int"
|
| 690 |
+
},
|
| 691 |
+
{
|
| 692 |
+
"name": "PREAUTH-FLAG",
|
| 693 |
+
"start": 13,
|
| 694 |
+
"end": 14,
|
| 695 |
+
"length": 1,
|
| 696 |
+
"pic": "X",
|
| 697 |
+
"python_type": "str"
|
| 698 |
+
},
|
| 699 |
+
{
|
| 700 |
+
"name": "CLAIM-AMOUNT",
|
| 701 |
+
"start": 14,
|
| 702 |
+
"end": 21,
|
| 703 |
+
"length": 7,
|
| 704 |
+
"pic": "9(5)V99",
|
| 705 |
+
"python_type": "Decimal",
|
| 706 |
+
"scale": 2
|
| 707 |
+
}
|
| 708 |
+
]
|
| 709 |
+
}
|
| 710 |
+
},
|
| 711 |
+
{
|
| 712 |
+
"tool_name": "inspect_business_rules",
|
| 713 |
+
"arguments": {},
|
| 714 |
+
"reward": 0.01,
|
| 715 |
+
"done": false,
|
| 716 |
+
"result": {
|
| 717 |
+
"ok": true,
|
| 718 |
+
"rules": [
|
| 719 |
+
"Branch order matters: age, plan-B large claim, missing preauth, long service, default approve.",
|
| 720 |
+
"Amounts are implied cents; 100000 means 1000.00."
|
| 721 |
+
]
|
| 722 |
+
}
|
| 723 |
+
},
|
| 724 |
+
{
|
| 725 |
+
"tool_name": "write_python_solution",
|
| 726 |
+
"arguments": {
|
| 727 |
+
"code_chars": 958
|
| 728 |
+
},
|
| 729 |
+
"reward": 0.02,
|
| 730 |
+
"done": false,
|
| 731 |
+
"result": {
|
| 732 |
+
"ok": true,
|
| 733 |
+
"draft_id": 1,
|
| 734 |
+
"syntax_ok": true,
|
| 735 |
+
"safety_ok": true,
|
| 736 |
+
"error": null
|
| 737 |
+
}
|
| 738 |
+
},
|
| 739 |
+
{
|
| 740 |
+
"tool_name": "run_visible_tests",
|
| 741 |
+
"arguments": {
|
| 742 |
+
"draft_id": 1
|
| 743 |
+
},
|
| 744 |
+
"reward": 0.0,
|
| 745 |
+
"done": false,
|
| 746 |
+
"result": {
|
| 747 |
+
"ok": true,
|
| 748 |
+
"draft_id": 1,
|
| 749 |
+
"passed": 0,
|
| 750 |
+
"total": 3,
|
| 751 |
+
"pass_rate": 0.0,
|
| 752 |
+
"syntax_ok": true,
|
| 753 |
+
"safety_ok": true,
|
| 754 |
+
"interface_ok": true,
|
| 755 |
+
"timed_out": false,
|
| 756 |
+
"error": null,
|
| 757 |
+
"failures": [
|
| 758 |
+
{
|
| 759 |
+
"case_id": "visible_1",
|
| 760 |
+
"input_summary": "ordinary approved claim",
|
| 761 |
+
"expected_summary": "OUT-CLAIM-ID=CLM001, OUT-DECISION=A, OUT-REASON=OK",
|
| 762 |
+
"actual_summary": "length 3 output: 'AOK'",
|
| 763 |
+
"error": null
|
| 764 |
+
},
|
| 765 |
+
{
|
| 766 |
+
"case_id": "visible_2",
|
| 767 |
+
"input_summary": "missing preauth denial",
|
| 768 |
+
"expected_summary": "OUT-CLAIM-ID=CLM002, OUT-DECISION=D, OUT-REASON=P1",
|
| 769 |
+
"actual_summary": "length 3 output: 'DP1'",
|
| 770 |
+
"error": null
|
| 771 |
+
},
|
| 772 |
+
{
|
| 773 |
+
"case_id": "visible_3",
|
| 774 |
+
"input_summary": "long service review",
|
| 775 |
+
"expected_summary": "OUT-CLAIM-ID=CLM003, OUT-DECISION=R, OUT-REASON=L1",
|
| 776 |
+
"actual_summary": "length 3 output: 'RL1'",
|
| 777 |
+
"error": null
|
| 778 |
+
}
|
| 779 |
+
]
|
| 780 |
+
}
|
| 781 |
+
},
|
| 782 |
+
{
|
| 783 |
+
"tool_name": "submit_final",
|
| 784 |
+
"arguments": {
|
| 785 |
+
"draft_id": 1
|
| 786 |
+
},
|
| 787 |
+
"reward": 0.15,
|
| 788 |
+
"done": true,
|
| 789 |
+
"result": {
|
| 790 |
+
"ok": true,
|
| 791 |
+
"accepted": false,
|
| 792 |
+
"episode_done": true,
|
| 793 |
+
"public_score": 0.15,
|
| 794 |
+
"components": {
|
| 795 |
+
"hidden_correctness": 0.0,
|
| 796 |
+
"fresh_correctness": 0.0,
|
| 797 |
+
"interface_contract": 1.0,
|
| 798 |
+
"type_and_layout_fidelity": 0.0,
|
| 799 |
+
"anti_hardcoding": 0.0,
|
| 800 |
+
"safety": 1.0
|
| 801 |
+
},
|
| 802 |
+
"hidden_passed": 0,
|
| 803 |
+
"hidden_total": 3,
|
| 804 |
+
"fresh_passed": 0,
|
| 805 |
+
"fresh_total": 6,
|
| 806 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 807 |
+
}
|
| 808 |
+
}
|
| 809 |
+
]
|
| 810 |
+
},
|
| 811 |
+
{
|
| 812 |
+
"policy": "azure-openai",
|
| 813 |
+
"task_id": "account_status_001",
|
| 814 |
+
"family_id": "account_status_level88",
|
| 815 |
+
"ticket": {
|
| 816 |
+
"task_id": "account_status_001",
|
| 817 |
+
"family_id": "account_status_level88",
|
| 818 |
+
"domain": "banking",
|
| 819 |
+
"ticket": "Migrate ACCTSTAT.cbl. Correctly interpret level-88 status names and preserve branch precedence for account servicing actions.",
|
| 820 |
+
"available_files": [
|
| 821 |
+
"ACCTSTAT.cbl"
|
| 822 |
+
],
|
| 823 |
+
"available_copybooks": [
|
| 824 |
+
"ACCOUNT_REC.cpy"
|
| 825 |
+
],
|
| 826 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 827 |
+
"visible_tests": 3,
|
| 828 |
+
"hidden_tests": 3,
|
| 829 |
+
"input_width": 19,
|
| 830 |
+
"output_width": 9,
|
| 831 |
+
"max_steps": 12,
|
| 832 |
+
"allowed_tools": [
|
| 833 |
+
"read_cobol_file",
|
| 834 |
+
"read_copybook",
|
| 835 |
+
"parse_copybook_layout",
|
| 836 |
+
"inspect_business_rules",
|
| 837 |
+
"write_python_solution",
|
| 838 |
+
"run_visible_tests",
|
| 839 |
+
"inspect_diff",
|
| 840 |
+
"submit_final"
|
| 841 |
+
]
|
| 842 |
+
},
|
| 843 |
+
"model_turns": [
|
| 844 |
+
{
|
| 845 |
+
"provider": "azure-openai",
|
| 846 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"account_status_001\",\n \"family_id\": \"account_status_level88\",\n \"domain\": \"banking\",\n \"ticket\": \"Migrate ACCTSTAT.cbl. Correctly interpret level-88 status names and preserve branch precedence for account servicing actions.\",\n \"available_files\": [\n \"ACCTSTAT.cbl\"\n ],\n \"available_copybooks\": [\n \"ACCOUNT_REC.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 3,\n \"input_width\": 19,\n \"output_width\": 9,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"ACCTSTAT.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. ACCTSTAT.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY ACCOUNT_REC.\\n PROCEDURE DIVISION.\\n EVALUATE TRUE\\n WHEN CLOSED-ACCT MOVE 'CL' TO CATEGORY MOVE 'N' TO ACTION\\n WHEN FROZEN-ACCT MOVE 'FR' TO CATEGORY MOVE 'H' TO ACTION\\n WHEN DAYS-PAST-DUE >= 090 MOVE 'DL' TO CATEGORY MOVE 'C' TO ACTION\\n WHEN BALANCE < 0 MOVE 'OD' TO CATEGORY MOVE 'R' TO ACTION\\n WHEN OTHER MOVE 'OK' TO CATEGORY MOVE 'N' TO ACTION\\n END-EVALUATE\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"ACCOUNT_REC.cpy\": \" 01 ACCOUNT-RECORD.\\n 05 ACCOUNT-ID PIC X(6).\\n 05 STATUS-CODE PIC X.\\n 88 ACTIVE-ACCT VALUE 'A'.\\n 88 FROZEN-ACCT VALUE 'F'.\\n 88 CLOSED-ACCT VALUE 'C'.\\n 05 BALANCE PIC S9(6)V99 SIGN LEADING SEPARATE.\\n 05 DAYS-PAST-DUE PIC 9(3).\\n\"\n}\n\nParsed layouts:\n{\n \"ACCOUNT_REC.cpy\": {\n \"ok\": true,\n \"filename\": \"ACCOUNT_REC.cpy\",\n \"record_name\": \"ACCOUNT-RECORD\",\n \"total_width\": 19,\n \"fields\": [\n {\n \"name\": \"ACCOUNT-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"STATUS-CODE\",\n \"start\": 6,\n \"end\": 7,\n \"length\": 1,\n \"pic\": \"X\",\n \"python_type\": \"str\",\n \"level_88\": {\n \"ACTIVE-ACCT\": \"A\",\n \"FROZEN-ACCT\": \"F\",\n \"CLOSED-ACCT\": \"C\"\n }\n },\n {\n \"name\": \"BALANCE\",\n \"start\": 7,\n \"end\": 16,\n \"length\": 9,\n \"pic\": \"S9(6)V99 SIGN LEADING SEPARATE\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n },\n {\n \"name\": \"DAYS-PAST-DUE\",\n \"start\": 16,\n \"end\": 19,\n \"length\": 3,\n \"pic\": \"9(3)\",\n \"python_type\": \"int\"\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"CLOSED-ACCT and FROZEN-ACCT are level-88 names over STATUS-CODE.\",\n \"Closed and frozen branches precede delinquency and overdrawn checks.\"\n]",
|
| 847 |
+
"response": "{\"code\":\"from decimal import Decimal, InvalidOperation\\n\\ndef migrate(input_record: str) -> str:\\n rec = (input_record or \\\"\\\")\\n rec = rec.ljust(19)[:19]\\n\\n status_code = rec[6:7]\\n balance_raw = rec[7:16].strip()\\n days_raw = rec[16:19].strip()\\n\\n try:\\n balance = Decimal(balance_raw) if balance_raw else Decimal('0')\\n except InvalidOperation:\\n balance = Decimal('0')\\n\\n try:\\n days_past_due = int(days_raw) if days_raw else 0\\n except ValueError:\\n days_past_due = 0\\n\\n category = 'OK'\\n action = 'N'\\n\\n # Preserve COBOL EVALUATE TRUE branch precedence.\\n if status_code == 'C': # CLOSED-ACCT\\n category = 'CL'\\n action = 'N'\\n elif status_code == 'F': # FROZEN-ACCT\\n category = 'FR'\\n action = 'H'\\n elif days_past_due >= 90:\\n category = 'DL'\\n action = 'C'\\n elif balance < 0:\\n category = 'OD'\\n action = 'R'\\n\\n return f\\\"{category}{action}\\\"\\n\"}",
|
| 848 |
+
"code_chars": 947
|
| 849 |
+
}
|
| 850 |
+
],
|
| 851 |
+
"visible": {
|
| 852 |
+
"passed": 0,
|
| 853 |
+
"total": 3,
|
| 854 |
+
"pass_rate": 0.0,
|
| 855 |
+
"failures": [
|
| 856 |
+
{
|
| 857 |
+
"case_id": "visible_1",
|
| 858 |
+
"input_summary": "active account in good standing",
|
| 859 |
+
"expected_summary": "OUT-ACCOUNT-ID=A00001, OUT-CATEGORY=OK, OUT-ACTION=N",
|
| 860 |
+
"actual_summary": "length 3 output: 'OKN'",
|
| 861 |
+
"error": null
|
| 862 |
+
},
|
| 863 |
+
{
|
| 864 |
+
"case_id": "visible_2",
|
| 865 |
+
"input_summary": "overdrawn active account",
|
| 866 |
+
"expected_summary": "OUT-ACCOUNT-ID=A00002, OUT-CATEGORY=OD, OUT-ACTION=R",
|
| 867 |
+
"actual_summary": "length 3 output: 'ODR'",
|
| 868 |
+
"error": null
|
| 869 |
+
},
|
| 870 |
+
{
|
| 871 |
+
"case_id": "visible_3",
|
| 872 |
+
"input_summary": "frozen account",
|
| 873 |
+
"expected_summary": "OUT-ACCOUNT-ID=A00003, OUT-CATEGORY=FR, OUT-ACTION=H",
|
| 874 |
+
"actual_summary": "length 3 output: 'FRH'",
|
| 875 |
+
"error": null
|
| 876 |
+
}
|
| 877 |
+
]
|
| 878 |
+
},
|
| 879 |
+
"final": {
|
| 880 |
+
"public_score": 0.15,
|
| 881 |
+
"accepted": false,
|
| 882 |
+
"components": {
|
| 883 |
+
"hidden_correctness": 0.0,
|
| 884 |
+
"fresh_correctness": 0.0,
|
| 885 |
+
"interface_contract": 1.0,
|
| 886 |
+
"type_and_layout_fidelity": 0.0,
|
| 887 |
+
"anti_hardcoding": 0.0,
|
| 888 |
+
"safety": 1.0
|
| 889 |
+
},
|
| 890 |
+
"hidden_passed": 0,
|
| 891 |
+
"hidden_total": 3,
|
| 892 |
+
"fresh_passed": 0,
|
| 893 |
+
"fresh_total": 6
|
| 894 |
+
},
|
| 895 |
+
"steps": [
|
| 896 |
+
{
|
| 897 |
+
"tool_name": "read_cobol_file",
|
| 898 |
+
"arguments": {
|
| 899 |
+
"filename": "ACCTSTAT.cbl"
|
| 900 |
+
},
|
| 901 |
+
"reward": 0.02,
|
| 902 |
+
"done": false,
|
| 903 |
+
"result": {
|
| 904 |
+
"ok": true,
|
| 905 |
+
"filename": "ACCTSTAT.cbl",
|
| 906 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. ACCTSTAT.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY ACCOUNT_REC.\n PROCEDURE DIVISION.\n EVALUATE TRUE\n WHEN CLOSED-ACCT MOVE 'CL' TO CATEGORY MOVE 'N' TO ACTION\n WHEN FROZEN-ACCT MOVE 'FR' TO CATEGORY MOVE 'H' TO ACTION\n WHEN DAYS-PAST-DUE >= 090 MOVE 'DL' TO CATEGORY MOVE 'C' TO ACTION\n WHEN BALANCE < 0 MOVE 'OD' TO CATEGORY MOVE 'R' TO ACTION\n WHEN OTHER MOVE 'OK' TO CATEGORY MOVE 'N' TO ACTION\n END-EVALUATE\n GOBACK.\n",
|
| 907 |
+
"truncated": false
|
| 908 |
+
}
|
| 909 |
+
},
|
| 910 |
+
{
|
| 911 |
+
"tool_name": "read_copybook",
|
| 912 |
+
"arguments": {
|
| 913 |
+
"filename": "ACCOUNT_REC.cpy"
|
| 914 |
+
},
|
| 915 |
+
"reward": 0.02,
|
| 916 |
+
"done": false,
|
| 917 |
+
"result": {
|
| 918 |
+
"ok": true,
|
| 919 |
+
"filename": "ACCOUNT_REC.cpy",
|
| 920 |
+
"content": " 01 ACCOUNT-RECORD.\n 05 ACCOUNT-ID PIC X(6).\n 05 STATUS-CODE PIC X.\n 88 ACTIVE-ACCT VALUE 'A'.\n 88 FROZEN-ACCT VALUE 'F'.\n 88 CLOSED-ACCT VALUE 'C'.\n 05 BALANCE PIC S9(6)V99 SIGN LEADING SEPARATE.\n 05 DAYS-PAST-DUE PIC 9(3).\n"
|
| 921 |
+
}
|
| 922 |
+
},
|
| 923 |
+
{
|
| 924 |
+
"tool_name": "parse_copybook_layout",
|
| 925 |
+
"arguments": {
|
| 926 |
+
"filename": "ACCOUNT_REC.cpy"
|
| 927 |
+
},
|
| 928 |
+
"reward": 0.03,
|
| 929 |
+
"done": false,
|
| 930 |
+
"result": {
|
| 931 |
+
"ok": true,
|
| 932 |
+
"filename": "ACCOUNT_REC.cpy",
|
| 933 |
+
"record_name": "ACCOUNT-RECORD",
|
| 934 |
+
"total_width": 19,
|
| 935 |
+
"fields": [
|
| 936 |
+
{
|
| 937 |
+
"name": "ACCOUNT-ID",
|
| 938 |
+
"start": 0,
|
| 939 |
+
"end": 6,
|
| 940 |
+
"length": 6,
|
| 941 |
+
"pic": "X(6)",
|
| 942 |
+
"python_type": "str"
|
| 943 |
+
},
|
| 944 |
+
{
|
| 945 |
+
"name": "STATUS-CODE",
|
| 946 |
+
"start": 6,
|
| 947 |
+
"end": 7,
|
| 948 |
+
"length": 1,
|
| 949 |
+
"pic": "X",
|
| 950 |
+
"python_type": "str",
|
| 951 |
+
"level_88": {
|
| 952 |
+
"ACTIVE-ACCT": "A",
|
| 953 |
+
"FROZEN-ACCT": "F",
|
| 954 |
+
"CLOSED-ACCT": "C"
|
| 955 |
+
}
|
| 956 |
+
},
|
| 957 |
+
{
|
| 958 |
+
"name": "BALANCE",
|
| 959 |
+
"start": 7,
|
| 960 |
+
"end": 16,
|
| 961 |
+
"length": 9,
|
| 962 |
+
"pic": "S9(6)V99 SIGN LEADING SEPARATE",
|
| 963 |
+
"python_type": "Decimal",
|
| 964 |
+
"scale": 2
|
| 965 |
+
},
|
| 966 |
+
{
|
| 967 |
+
"name": "DAYS-PAST-DUE",
|
| 968 |
+
"start": 16,
|
| 969 |
+
"end": 19,
|
| 970 |
+
"length": 3,
|
| 971 |
+
"pic": "9(3)",
|
| 972 |
+
"python_type": "int"
|
| 973 |
+
}
|
| 974 |
+
]
|
| 975 |
+
}
|
| 976 |
+
},
|
| 977 |
+
{
|
| 978 |
+
"tool_name": "inspect_business_rules",
|
| 979 |
+
"arguments": {},
|
| 980 |
+
"reward": 0.01,
|
| 981 |
+
"done": false,
|
| 982 |
+
"result": {
|
| 983 |
+
"ok": true,
|
| 984 |
+
"rules": [
|
| 985 |
+
"CLOSED-ACCT and FROZEN-ACCT are level-88 names over STATUS-CODE.",
|
| 986 |
+
"Closed and frozen branches precede delinquency and overdrawn checks."
|
| 987 |
+
]
|
| 988 |
+
}
|
| 989 |
+
},
|
| 990 |
+
{
|
| 991 |
+
"tool_name": "write_python_solution",
|
| 992 |
+
"arguments": {
|
| 993 |
+
"code_chars": 947
|
| 994 |
+
},
|
| 995 |
+
"reward": 0.02,
|
| 996 |
+
"done": false,
|
| 997 |
+
"result": {
|
| 998 |
+
"ok": true,
|
| 999 |
+
"draft_id": 1,
|
| 1000 |
+
"syntax_ok": true,
|
| 1001 |
+
"safety_ok": true,
|
| 1002 |
+
"error": null
|
| 1003 |
+
}
|
| 1004 |
+
},
|
| 1005 |
+
{
|
| 1006 |
+
"tool_name": "run_visible_tests",
|
| 1007 |
+
"arguments": {
|
| 1008 |
+
"draft_id": 1
|
| 1009 |
+
},
|
| 1010 |
+
"reward": 0.0,
|
| 1011 |
+
"done": false,
|
| 1012 |
+
"result": {
|
| 1013 |
+
"ok": true,
|
| 1014 |
+
"draft_id": 1,
|
| 1015 |
+
"passed": 0,
|
| 1016 |
+
"total": 3,
|
| 1017 |
+
"pass_rate": 0.0,
|
| 1018 |
+
"syntax_ok": true,
|
| 1019 |
+
"safety_ok": true,
|
| 1020 |
+
"interface_ok": true,
|
| 1021 |
+
"timed_out": false,
|
| 1022 |
+
"error": null,
|
| 1023 |
+
"failures": [
|
| 1024 |
+
{
|
| 1025 |
+
"case_id": "visible_1",
|
| 1026 |
+
"input_summary": "active account in good standing",
|
| 1027 |
+
"expected_summary": "OUT-ACCOUNT-ID=A00001, OUT-CATEGORY=OK, OUT-ACTION=N",
|
| 1028 |
+
"actual_summary": "length 3 output: 'OKN'",
|
| 1029 |
+
"error": null
|
| 1030 |
+
},
|
| 1031 |
+
{
|
| 1032 |
+
"case_id": "visible_2",
|
| 1033 |
+
"input_summary": "overdrawn active account",
|
| 1034 |
+
"expected_summary": "OUT-ACCOUNT-ID=A00002, OUT-CATEGORY=OD, OUT-ACTION=R",
|
| 1035 |
+
"actual_summary": "length 3 output: 'ODR'",
|
| 1036 |
+
"error": null
|
| 1037 |
+
},
|
| 1038 |
+
{
|
| 1039 |
+
"case_id": "visible_3",
|
| 1040 |
+
"input_summary": "frozen account",
|
| 1041 |
+
"expected_summary": "OUT-ACCOUNT-ID=A00003, OUT-CATEGORY=FR, OUT-ACTION=H",
|
| 1042 |
+
"actual_summary": "length 3 output: 'FRH'",
|
| 1043 |
+
"error": null
|
| 1044 |
+
}
|
| 1045 |
+
]
|
| 1046 |
+
}
|
| 1047 |
+
},
|
| 1048 |
+
{
|
| 1049 |
+
"tool_name": "submit_final",
|
| 1050 |
+
"arguments": {
|
| 1051 |
+
"draft_id": 1
|
| 1052 |
+
},
|
| 1053 |
+
"reward": 0.15,
|
| 1054 |
+
"done": true,
|
| 1055 |
+
"result": {
|
| 1056 |
+
"ok": true,
|
| 1057 |
+
"accepted": false,
|
| 1058 |
+
"episode_done": true,
|
| 1059 |
+
"public_score": 0.15,
|
| 1060 |
+
"components": {
|
| 1061 |
+
"hidden_correctness": 0.0,
|
| 1062 |
+
"fresh_correctness": 0.0,
|
| 1063 |
+
"interface_contract": 1.0,
|
| 1064 |
+
"type_and_layout_fidelity": 0.0,
|
| 1065 |
+
"anti_hardcoding": 0.0,
|
| 1066 |
+
"safety": 1.0
|
| 1067 |
+
},
|
| 1068 |
+
"hidden_passed": 0,
|
| 1069 |
+
"hidden_total": 3,
|
| 1070 |
+
"fresh_passed": 0,
|
| 1071 |
+
"fresh_total": 6,
|
| 1072 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 1073 |
+
}
|
| 1074 |
+
}
|
| 1075 |
+
]
|
| 1076 |
+
},
|
| 1077 |
+
{
|
| 1078 |
+
"policy": "azure-openai",
|
| 1079 |
+
"task_id": "invoice_occurs_001",
|
| 1080 |
+
"family_id": "invoice_occurs_totals",
|
| 1081 |
+
"ticket": {
|
| 1082 |
+
"task_id": "invoice_occurs_001",
|
| 1083 |
+
"family_id": "invoice_occurs_totals",
|
| 1084 |
+
"domain": "invoicing",
|
| 1085 |
+
"ticket": "Migrate INVTOTAL.cbl. Preserve OCCURS stride parsing, item-count bounds, per-line tax rounding, and fixed-width total output.",
|
| 1086 |
+
"available_files": [
|
| 1087 |
+
"INVTOTAL.cbl"
|
| 1088 |
+
],
|
| 1089 |
+
"available_copybooks": [
|
| 1090 |
+
"INVOICE_REC.cpy"
|
| 1091 |
+
],
|
| 1092 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 1093 |
+
"visible_tests": 3,
|
| 1094 |
+
"hidden_tests": 3,
|
| 1095 |
+
"input_width": 44,
|
| 1096 |
+
"output_width": 18,
|
| 1097 |
+
"max_steps": 12,
|
| 1098 |
+
"allowed_tools": [
|
| 1099 |
+
"read_cobol_file",
|
| 1100 |
+
"read_copybook",
|
| 1101 |
+
"parse_copybook_layout",
|
| 1102 |
+
"inspect_business_rules",
|
| 1103 |
+
"write_python_solution",
|
| 1104 |
+
"run_visible_tests",
|
| 1105 |
+
"inspect_diff",
|
| 1106 |
+
"submit_final"
|
| 1107 |
+
]
|
| 1108 |
+
},
|
| 1109 |
+
"model_turns": [
|
| 1110 |
+
{
|
| 1111 |
+
"provider": "azure-openai",
|
| 1112 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"invoice_occurs_001\",\n \"family_id\": \"invoice_occurs_totals\",\n \"domain\": \"invoicing\",\n \"ticket\": \"Migrate INVTOTAL.cbl. Preserve OCCURS stride parsing, item-count bounds, per-line tax rounding, and fixed-width total output.\",\n \"available_files\": [\n \"INVTOTAL.cbl\"\n ],\n \"available_copybooks\": [\n \"INVOICE_REC.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 3,\n \"input_width\": 44,\n \"output_width\": 18,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"INVTOTAL.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. INVTOTAL.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY INVOICE_REC.\\n PROCEDURE DIVISION.\\n PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > ITEM-COUNT\\n COMPUTE LINE-AMOUNT ROUNDED = ITEM-QTY(IDX) * ITEM-PRICE(IDX)\\n IF TAXABLE-FLAG(IDX) = 'Y'\\n COMPUTE LINE-AMOUNT ROUNDED = LINE-AMOUNT * 1.075\\n END-IF\\n ADD LINE-AMOUNT TO INVOICE-TOTAL\\n END-PERFORM\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"INVOICE_REC.cpy\": \" 01 INVOICE-RECORD.\\n 05 INVOICE-ID PIC X(6).\\n 05 ITEM-COUNT PIC 9(2).\\n 05 LINE-ITEM OCCURS 4 TIMES.\\n 10 ITEM-QTY PIC 9(2).\\n 10 ITEM-PRICE PIC 9(4)V99.\\n 10 TAXABLE-FLAG PIC X.\\n\"\n}\n\nParsed layouts:\n{\n \"INVOICE_REC.cpy\": {\n \"ok\": true,\n \"filename\": \"INVOICE_REC.cpy\",\n \"record_name\": \"INVOICE-RECORD\",\n \"total_width\": 44,\n \"fields\": [\n {\n \"name\": \"INVOICE-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"ITEM-COUNT\",\n \"start\": 6,\n \"end\": 8,\n \"length\": 2,\n \"pic\": \"9(2)\",\n \"python_type\": \"int\"\n },\n {\n \"name\": \"LINE-ITEMS\",\n \"start\": 8,\n \"end\": 44,\n \"length\": 36,\n \"pic\": \"OCCURS 4 TIMES\",\n \"python_type\": \"group\",\n \"occurs\": 4,\n \"stride\": 9\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"LINE-ITEM OCCURS 4 TIMES with a 9-byte stride.\",\n \"Only the first ITEM-COUNT entries contribute to the total.\",\n \"Taxable line amounts multiply by 1.075 and round half up per line.\"\n]",
|
| 1113 |
+
"response": "{\"code\":\"from decimal import Decimal, ROUND_HALF_UP\\n\\ndef migrate(input_record: str) -> str:\\n record = (input_record or \\\"\\\")[:44].ljust(44)\\n\\n def parse_int(s: str) -> int:\\n s = s.strip()\\n return int(s) if s else 0\\n\\n def parse_money(s: str) -> Decimal:\\n s = s.strip()\\n if not s:\\n return Decimal('0')\\n return Decimal(s) / Decimal('100')\\n\\n item_count = parse_int(record[6:8])\\n if item_count < 0:\\n item_count = 0\\n if item_count > 4:\\n item_count = 4\\n\\n total = Decimal('0')\\n base = 8\\n stride = 9\\n\\n for idx in range(item_count):\\n off = base + idx * stride\\n qty = parse_int(record[off:off + 2])\\n price = parse_money(record[off + 2:off + 8])\\n taxable = record[off + 8:off + 9]\\n\\n line_amount = (Decimal(qty) * price).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)\\n if taxable == 'Y':\\n line_amount = (line_amount * Decimal('1.075')).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)\\n total += line_amount\\n\\n cents = int(total.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) * 100)\\n return f\\\"{cents:018d}\\\"\\n\"}",
|
| 1114 |
+
"code_chars": 1143
|
| 1115 |
+
}
|
| 1116 |
+
],
|
| 1117 |
+
"visible": {
|
| 1118 |
+
"passed": 0,
|
| 1119 |
+
"total": 3,
|
| 1120 |
+
"pass_rate": 0.0,
|
| 1121 |
+
"failures": [
|
| 1122 |
+
{
|
| 1123 |
+
"case_id": "visible_1",
|
| 1124 |
+
"input_summary": "two taxable and non-taxable lines",
|
| 1125 |
+
"expected_summary": "OUT-INVOICE-ID=I00001, OUT-TOTAL=000036542, OUT-ITEM-COUNT=02, OUT-FLAG=L",
|
| 1126 |
+
"actual_summary": "OUT-INVOICE-ID=000000, OUT-TOTAL=000000036, OUT-ITEM-COUNT=54, OUT-FLAG=2",
|
| 1127 |
+
"error": null
|
| 1128 |
+
},
|
| 1129 |
+
{
|
| 1130 |
+
"case_id": "visible_2",
|
| 1131 |
+
"input_summary": "zero item invoice",
|
| 1132 |
+
"expected_summary": "OUT-INVOICE-ID=I00002, OUT-TOTAL=000000000, OUT-ITEM-COUNT=00, OUT-FLAG=L",
|
| 1133 |
+
"actual_summary": "OUT-INVOICE-ID=000000, OUT-TOTAL=000000000, OUT-ITEM-COUNT=00, OUT-FLAG=0",
|
| 1134 |
+
"error": null
|
| 1135 |
+
},
|
| 1136 |
+
{
|
| 1137 |
+
"case_id": "visible_3",
|
| 1138 |
+
"input_summary": "four item high invoice",
|
| 1139 |
+
"expected_summary": "OUT-INVOICE-ID=I00003, OUT-TOTAL=000351035, OUT-ITEM-COUNT=04, OUT-FLAG=H",
|
| 1140 |
+
"actual_summary": "OUT-INVOICE-ID=000000, OUT-TOTAL=000000351, OUT-ITEM-COUNT=03, OUT-FLAG=5",
|
| 1141 |
+
"error": null
|
| 1142 |
+
}
|
| 1143 |
+
]
|
| 1144 |
+
},
|
| 1145 |
+
"final": {
|
| 1146 |
+
"public_score": 0.23,
|
| 1147 |
+
"accepted": false,
|
| 1148 |
+
"components": {
|
| 1149 |
+
"hidden_correctness": 0.0,
|
| 1150 |
+
"fresh_correctness": 0.0,
|
| 1151 |
+
"interface_contract": 1.0,
|
| 1152 |
+
"type_and_layout_fidelity": 1.0,
|
| 1153 |
+
"anti_hardcoding": 0.0,
|
| 1154 |
+
"safety": 1.0
|
| 1155 |
+
},
|
| 1156 |
+
"hidden_passed": 0,
|
| 1157 |
+
"hidden_total": 3,
|
| 1158 |
+
"fresh_passed": 0,
|
| 1159 |
+
"fresh_total": 6
|
| 1160 |
+
},
|
| 1161 |
+
"steps": [
|
| 1162 |
+
{
|
| 1163 |
+
"tool_name": "read_cobol_file",
|
| 1164 |
+
"arguments": {
|
| 1165 |
+
"filename": "INVTOTAL.cbl"
|
| 1166 |
+
},
|
| 1167 |
+
"reward": 0.02,
|
| 1168 |
+
"done": false,
|
| 1169 |
+
"result": {
|
| 1170 |
+
"ok": true,
|
| 1171 |
+
"filename": "INVTOTAL.cbl",
|
| 1172 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. INVTOTAL.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY INVOICE_REC.\n PROCEDURE DIVISION.\n PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > ITEM-COUNT\n COMPUTE LINE-AMOUNT ROUNDED = ITEM-QTY(IDX) * ITEM-PRICE(IDX)\n IF TAXABLE-FLAG(IDX) = 'Y'\n COMPUTE LINE-AMOUNT ROUNDED = LINE-AMOUNT * 1.075\n END-IF\n ADD LINE-AMOUNT TO INVOICE-TOTAL\n END-PERFORM\n GOBACK.\n",
|
| 1173 |
+
"truncated": false
|
| 1174 |
+
}
|
| 1175 |
+
},
|
| 1176 |
+
{
|
| 1177 |
+
"tool_name": "read_copybook",
|
| 1178 |
+
"arguments": {
|
| 1179 |
+
"filename": "INVOICE_REC.cpy"
|
| 1180 |
+
},
|
| 1181 |
+
"reward": 0.02,
|
| 1182 |
+
"done": false,
|
| 1183 |
+
"result": {
|
| 1184 |
+
"ok": true,
|
| 1185 |
+
"filename": "INVOICE_REC.cpy",
|
| 1186 |
+
"content": " 01 INVOICE-RECORD.\n 05 INVOICE-ID PIC X(6).\n 05 ITEM-COUNT PIC 9(2).\n 05 LINE-ITEM OCCURS 4 TIMES.\n 10 ITEM-QTY PIC 9(2).\n 10 ITEM-PRICE PIC 9(4)V99.\n 10 TAXABLE-FLAG PIC X.\n"
|
| 1187 |
+
}
|
| 1188 |
+
},
|
| 1189 |
+
{
|
| 1190 |
+
"tool_name": "parse_copybook_layout",
|
| 1191 |
+
"arguments": {
|
| 1192 |
+
"filename": "INVOICE_REC.cpy"
|
| 1193 |
+
},
|
| 1194 |
+
"reward": 0.03,
|
| 1195 |
+
"done": false,
|
| 1196 |
+
"result": {
|
| 1197 |
+
"ok": true,
|
| 1198 |
+
"filename": "INVOICE_REC.cpy",
|
| 1199 |
+
"record_name": "INVOICE-RECORD",
|
| 1200 |
+
"total_width": 44,
|
| 1201 |
+
"fields": [
|
| 1202 |
+
{
|
| 1203 |
+
"name": "INVOICE-ID",
|
| 1204 |
+
"start": 0,
|
| 1205 |
+
"end": 6,
|
| 1206 |
+
"length": 6,
|
| 1207 |
+
"pic": "X(6)",
|
| 1208 |
+
"python_type": "str"
|
| 1209 |
+
},
|
| 1210 |
+
{
|
| 1211 |
+
"name": "ITEM-COUNT",
|
| 1212 |
+
"start": 6,
|
| 1213 |
+
"end": 8,
|
| 1214 |
+
"length": 2,
|
| 1215 |
+
"pic": "9(2)",
|
| 1216 |
+
"python_type": "int"
|
| 1217 |
+
},
|
| 1218 |
+
{
|
| 1219 |
+
"name": "LINE-ITEMS",
|
| 1220 |
+
"start": 8,
|
| 1221 |
+
"end": 44,
|
| 1222 |
+
"length": 36,
|
| 1223 |
+
"pic": "OCCURS 4 TIMES",
|
| 1224 |
+
"python_type": "group",
|
| 1225 |
+
"occurs": 4,
|
| 1226 |
+
"stride": 9
|
| 1227 |
+
}
|
| 1228 |
+
]
|
| 1229 |
+
}
|
| 1230 |
+
},
|
| 1231 |
+
{
|
| 1232 |
+
"tool_name": "inspect_business_rules",
|
| 1233 |
+
"arguments": {},
|
| 1234 |
+
"reward": 0.01,
|
| 1235 |
+
"done": false,
|
| 1236 |
+
"result": {
|
| 1237 |
+
"ok": true,
|
| 1238 |
+
"rules": [
|
| 1239 |
+
"LINE-ITEM OCCURS 4 TIMES with a 9-byte stride.",
|
| 1240 |
+
"Only the first ITEM-COUNT entries contribute to the total.",
|
| 1241 |
+
"Taxable line amounts multiply by 1.075 and round half up per line."
|
| 1242 |
+
]
|
| 1243 |
+
}
|
| 1244 |
+
},
|
| 1245 |
+
{
|
| 1246 |
+
"tool_name": "write_python_solution",
|
| 1247 |
+
"arguments": {
|
| 1248 |
+
"code_chars": 1143
|
| 1249 |
+
},
|
| 1250 |
+
"reward": 0.02,
|
| 1251 |
+
"done": false,
|
| 1252 |
+
"result": {
|
| 1253 |
+
"ok": true,
|
| 1254 |
+
"draft_id": 1,
|
| 1255 |
+
"syntax_ok": true,
|
| 1256 |
+
"safety_ok": true,
|
| 1257 |
+
"error": null
|
| 1258 |
+
}
|
| 1259 |
+
},
|
| 1260 |
+
{
|
| 1261 |
+
"tool_name": "run_visible_tests",
|
| 1262 |
+
"arguments": {
|
| 1263 |
+
"draft_id": 1
|
| 1264 |
+
},
|
| 1265 |
+
"reward": 0.0,
|
| 1266 |
+
"done": false,
|
| 1267 |
+
"result": {
|
| 1268 |
+
"ok": true,
|
| 1269 |
+
"draft_id": 1,
|
| 1270 |
+
"passed": 0,
|
| 1271 |
+
"total": 3,
|
| 1272 |
+
"pass_rate": 0.0,
|
| 1273 |
+
"syntax_ok": true,
|
| 1274 |
+
"safety_ok": true,
|
| 1275 |
+
"interface_ok": true,
|
| 1276 |
+
"timed_out": false,
|
| 1277 |
+
"error": null,
|
| 1278 |
+
"failures": [
|
| 1279 |
+
{
|
| 1280 |
+
"case_id": "visible_1",
|
| 1281 |
+
"input_summary": "two taxable and non-taxable lines",
|
| 1282 |
+
"expected_summary": "OUT-INVOICE-ID=I00001, OUT-TOTAL=000036542, OUT-ITEM-COUNT=02, OUT-FLAG=L",
|
| 1283 |
+
"actual_summary": "OUT-INVOICE-ID=000000, OUT-TOTAL=000000036, OUT-ITEM-COUNT=54, OUT-FLAG=2",
|
| 1284 |
+
"error": null
|
| 1285 |
+
},
|
| 1286 |
+
{
|
| 1287 |
+
"case_id": "visible_2",
|
| 1288 |
+
"input_summary": "zero item invoice",
|
| 1289 |
+
"expected_summary": "OUT-INVOICE-ID=I00002, OUT-TOTAL=000000000, OUT-ITEM-COUNT=00, OUT-FLAG=L",
|
| 1290 |
+
"actual_summary": "OUT-INVOICE-ID=000000, OUT-TOTAL=000000000, OUT-ITEM-COUNT=00, OUT-FLAG=0",
|
| 1291 |
+
"error": null
|
| 1292 |
+
},
|
| 1293 |
+
{
|
| 1294 |
+
"case_id": "visible_3",
|
| 1295 |
+
"input_summary": "four item high invoice",
|
| 1296 |
+
"expected_summary": "OUT-INVOICE-ID=I00003, OUT-TOTAL=000351035, OUT-ITEM-COUNT=04, OUT-FLAG=H",
|
| 1297 |
+
"actual_summary": "OUT-INVOICE-ID=000000, OUT-TOTAL=000000351, OUT-ITEM-COUNT=03, OUT-FLAG=5",
|
| 1298 |
+
"error": null
|
| 1299 |
+
}
|
| 1300 |
+
]
|
| 1301 |
+
}
|
| 1302 |
+
},
|
| 1303 |
+
{
|
| 1304 |
+
"tool_name": "submit_final",
|
| 1305 |
+
"arguments": {
|
| 1306 |
+
"draft_id": 1
|
| 1307 |
+
},
|
| 1308 |
+
"reward": 0.23,
|
| 1309 |
+
"done": true,
|
| 1310 |
+
"result": {
|
| 1311 |
+
"ok": true,
|
| 1312 |
+
"accepted": false,
|
| 1313 |
+
"episode_done": true,
|
| 1314 |
+
"public_score": 0.23,
|
| 1315 |
+
"components": {
|
| 1316 |
+
"hidden_correctness": 0.0,
|
| 1317 |
+
"fresh_correctness": 0.0,
|
| 1318 |
+
"interface_contract": 1.0,
|
| 1319 |
+
"type_and_layout_fidelity": 1.0,
|
| 1320 |
+
"anti_hardcoding": 0.0,
|
| 1321 |
+
"safety": 1.0
|
| 1322 |
+
},
|
| 1323 |
+
"hidden_passed": 0,
|
| 1324 |
+
"hidden_total": 3,
|
| 1325 |
+
"fresh_passed": 0,
|
| 1326 |
+
"fresh_total": 6,
|
| 1327 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 1328 |
+
}
|
| 1329 |
+
}
|
| 1330 |
+
]
|
| 1331 |
+
},
|
| 1332 |
+
{
|
| 1333 |
+
"policy": "azure-openai",
|
| 1334 |
+
"task_id": "date_normalization_001",
|
| 1335 |
+
"family_id": "date_normalization",
|
| 1336 |
+
"ticket": {
|
| 1337 |
+
"task_id": "date_normalization_001",
|
| 1338 |
+
"family_id": "date_normalization",
|
| 1339 |
+
"domain": "claims and billing",
|
| 1340 |
+
"ticket": "Migrate DATENORM.cbl. Preserve legacy YYMMDD century-window rules and invalid-date behavior instead of blindly using modern date parsing.",
|
| 1341 |
+
"available_files": [
|
| 1342 |
+
"DATENORM.cbl"
|
| 1343 |
+
],
|
| 1344 |
+
"available_copybooks": [
|
| 1345 |
+
"POLICY_DATE.cpy"
|
| 1346 |
+
],
|
| 1347 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 1348 |
+
"visible_tests": 3,
|
| 1349 |
+
"hidden_tests": 3,
|
| 1350 |
+
"input_width": 21,
|
| 1351 |
+
"output_width": 22,
|
| 1352 |
+
"max_steps": 12,
|
| 1353 |
+
"allowed_tools": [
|
| 1354 |
+
"read_cobol_file",
|
| 1355 |
+
"read_copybook",
|
| 1356 |
+
"parse_copybook_layout",
|
| 1357 |
+
"inspect_business_rules",
|
| 1358 |
+
"write_python_solution",
|
| 1359 |
+
"run_visible_tests",
|
| 1360 |
+
"inspect_diff",
|
| 1361 |
+
"submit_final"
|
| 1362 |
+
]
|
| 1363 |
+
},
|
| 1364 |
+
"model_turns": [
|
| 1365 |
+
{
|
| 1366 |
+
"provider": "azure-openai",
|
| 1367 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"date_normalization_001\",\n \"family_id\": \"date_normalization\",\n \"domain\": \"claims and billing\",\n \"ticket\": \"Migrate DATENORM.cbl. Preserve legacy YYMMDD century-window rules and invalid-date behavior instead of blindly using modern date parsing.\",\n \"available_files\": [\n \"DATENORM.cbl\"\n ],\n \"available_copybooks\": [\n \"POLICY_DATE.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 3,\n \"input_width\": 21,\n \"output_width\": 22,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"DATENORM.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. DATENORM.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY POLICY_DATE.\\n PROCEDURE DIVISION.\\n IF RAW-YY >= WINDOW-YEAR\\n MOVE 19 TO OUT-CENTURY\\n ELSE\\n MOVE 20 TO OUT-CENTURY\\n END-IF\\n PERFORM VALIDATE-MONTH-DAY\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"POLICY_DATE.cpy\": \" 01 POLICY-DATE-RECORD.\\n 05 POLICY-ID PIC X(6).\\n 05 RAW-DATE PIC 9(6).\\n 05 WINDOW-YEAR PIC 9(2).\\n 05 AMOUNT PIC 9(5)V99.\\n\"\n}\n\nParsed layouts:\n{\n \"POLICY_DATE.cpy\": {\n \"ok\": true,\n \"filename\": \"POLICY_DATE.cpy\",\n \"record_name\": \"POLICY-DATE-RECORD\",\n \"total_width\": 21,\n \"fields\": [\n {\n \"name\": \"POLICY-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"RAW-DATE\",\n \"start\": 6,\n \"end\": 12,\n \"length\": 6,\n \"pic\": \"9(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"WINDOW-YEAR\",\n \"start\": 12,\n \"end\": 14,\n \"length\": 2,\n \"pic\": \"9(2)\",\n \"python_type\": \"int\"\n },\n {\n \"name\": \"AMOUNT\",\n \"start\": 14,\n \"end\": 21,\n \"length\": 7,\n \"pic\": \"9(5)V99\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"RAW-DATE is YYMMDD.\",\n \"If YY >= WINDOW-YEAR, century is 19; otherwise century is 20.\",\n \"Invalid dates output 00000000 and valid flag N; amount is preserved.\"\n]",
|
| 1368 |
+
"response": "{\"code\":\"def migrate(input_record: str) -> str:\\n \\\"\\\"\\\"Migrate DATENORM legacy COBOL routine.\\n\\n Input layout (21 chars):\\n 0-5 POLICY-ID\\n 6-11 RAW-DATE (YYMMDD)\\n 12-13 WINDOW-YEAR\\n 14-20 AMOUNT\\n\\n Output width: 22 chars.\\n Legacy behavior preserved:\\n - Century window: if YY >= WINDOW-YEAR => 19xx else 20xx\\n - Invalid dates become 00000000 and valid flag N\\n - Amount is preserved\\n \\\"\\\"\\\"\\n\\n s = input_record or \\\"\\\"\\n s = s.ljust(21)\\n\\n policy_id = s[0:6]\\n raw_date = s[6:12]\\n window_year_str = s[12:14]\\n amount = s[14:21]\\n\\n yy = raw_date[0:2]\\n mm = raw_date[2:4]\\n dd = raw_date[4:6]\\n\\n try:\\n window_year = int(window_year_str)\\n except ValueError:\\n window_year = 0\\n\\n try:\\n yy_int = int(yy)\\n except ValueError:\\n yy_int = -1\\n\\n if yy_int >= window_year:\\n century = \\\"19\\\"\\n else:\\n century = \\\"20\\\"\\n\\n # Validate month/day with leap-year awareness after century expansion.\\n valid = True\\n try:\\n month = int(mm)\\n day = int(dd)\\n year = int(century + yy)\\n if not (1 <= month <= 12):\\n valid = False\\n else:\\n month_lengths = [31, 29 if (year % 400 == 0 or (year % 4 == 0 and year % 100 != 0)) else 28,\\n 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\\n if not (1 <= day <= month_lengths[month - 1]):\\n valid = False\\n except ValueError:\\n valid = False\\n\\n if valid:\\n out_date = century + raw_date\\n valid_flag = \\\"Y\\\"\\n else:\\n out_date = \\\"00000000\\\"\\n valid_flag = \\\"N\\\"\\n\\n # Output width 22: 8-char date + 1-char valid flag + 6-char policy id + 7-char amount = 22\\n return f\\\"{out_date}{valid_flag}{policy_id}{amount}\\\"\\n\"}",
|
| 1369 |
+
"code_chars": 1768
|
| 1370 |
+
}
|
| 1371 |
+
],
|
| 1372 |
+
"visible": {
|
| 1373 |
+
"passed": 0,
|
| 1374 |
+
"total": 3,
|
| 1375 |
+
"pass_rate": 0.0,
|
| 1376 |
+
"failures": [
|
| 1377 |
+
{
|
| 1378 |
+
"case_id": "visible_1",
|
| 1379 |
+
"input_summary": "twentieth century date by window",
|
| 1380 |
+
"expected_summary": "OUT-POLICY-ID=P00001, OUT-DATE=19991231, OUT-VALID=Y, OUT-AMOUNT=0012345",
|
| 1381 |
+
"actual_summary": "OUT-POLICY-ID=199912, OUT-DATE=31YP0000, OUT-VALID=1, OUT-AMOUNT=0012345",
|
| 1382 |
+
"error": null
|
| 1383 |
+
},
|
| 1384 |
+
{
|
| 1385 |
+
"case_id": "visible_2",
|
| 1386 |
+
"input_summary": "twenty-first century date by window",
|
| 1387 |
+
"expected_summary": "OUT-POLICY-ID=P00002, OUT-DATE=20240229, OUT-VALID=Y, OUT-AMOUNT=0000100",
|
| 1388 |
+
"actual_summary": "OUT-POLICY-ID=202402, OUT-DATE=29YP0000, OUT-VALID=2, OUT-AMOUNT=0000100",
|
| 1389 |
+
"error": null
|
| 1390 |
+
},
|
| 1391 |
+
{
|
| 1392 |
+
"case_id": "visible_3",
|
| 1393 |
+
"input_summary": "invalid month",
|
| 1394 |
+
"expected_summary": "OUT-POLICY-ID=P00003, OUT-DATE=00000000, OUT-VALID=N, OUT-AMOUNT=0000999",
|
| 1395 |
+
"actual_summary": "OUT-POLICY-ID=000000, OUT-DATE=00NP0000, OUT-VALID=3, OUT-AMOUNT=0000999",
|
| 1396 |
+
"error": null
|
| 1397 |
+
}
|
| 1398 |
+
]
|
| 1399 |
+
},
|
| 1400 |
+
"final": {
|
| 1401 |
+
"public_score": 0.15,
|
| 1402 |
+
"accepted": false,
|
| 1403 |
+
"components": {
|
| 1404 |
+
"hidden_correctness": 0.0,
|
| 1405 |
+
"fresh_correctness": 0.0,
|
| 1406 |
+
"interface_contract": 1.0,
|
| 1407 |
+
"type_and_layout_fidelity": 0.0,
|
| 1408 |
+
"anti_hardcoding": 0.0,
|
| 1409 |
+
"safety": 1.0
|
| 1410 |
+
},
|
| 1411 |
+
"hidden_passed": 0,
|
| 1412 |
+
"hidden_total": 3,
|
| 1413 |
+
"fresh_passed": 0,
|
| 1414 |
+
"fresh_total": 6
|
| 1415 |
+
},
|
| 1416 |
+
"steps": [
|
| 1417 |
+
{
|
| 1418 |
+
"tool_name": "read_cobol_file",
|
| 1419 |
+
"arguments": {
|
| 1420 |
+
"filename": "DATENORM.cbl"
|
| 1421 |
+
},
|
| 1422 |
+
"reward": 0.02,
|
| 1423 |
+
"done": false,
|
| 1424 |
+
"result": {
|
| 1425 |
+
"ok": true,
|
| 1426 |
+
"filename": "DATENORM.cbl",
|
| 1427 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. DATENORM.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY POLICY_DATE.\n PROCEDURE DIVISION.\n IF RAW-YY >= WINDOW-YEAR\n MOVE 19 TO OUT-CENTURY\n ELSE\n MOVE 20 TO OUT-CENTURY\n END-IF\n PERFORM VALIDATE-MONTH-DAY\n GOBACK.\n",
|
| 1428 |
+
"truncated": false
|
| 1429 |
+
}
|
| 1430 |
+
},
|
| 1431 |
+
{
|
| 1432 |
+
"tool_name": "read_copybook",
|
| 1433 |
+
"arguments": {
|
| 1434 |
+
"filename": "POLICY_DATE.cpy"
|
| 1435 |
+
},
|
| 1436 |
+
"reward": 0.02,
|
| 1437 |
+
"done": false,
|
| 1438 |
+
"result": {
|
| 1439 |
+
"ok": true,
|
| 1440 |
+
"filename": "POLICY_DATE.cpy",
|
| 1441 |
+
"content": " 01 POLICY-DATE-RECORD.\n 05 POLICY-ID PIC X(6).\n 05 RAW-DATE PIC 9(6).\n 05 WINDOW-YEAR PIC 9(2).\n 05 AMOUNT PIC 9(5)V99.\n"
|
| 1442 |
+
}
|
| 1443 |
+
},
|
| 1444 |
+
{
|
| 1445 |
+
"tool_name": "parse_copybook_layout",
|
| 1446 |
+
"arguments": {
|
| 1447 |
+
"filename": "POLICY_DATE.cpy"
|
| 1448 |
+
},
|
| 1449 |
+
"reward": 0.03,
|
| 1450 |
+
"done": false,
|
| 1451 |
+
"result": {
|
| 1452 |
+
"ok": true,
|
| 1453 |
+
"filename": "POLICY_DATE.cpy",
|
| 1454 |
+
"record_name": "POLICY-DATE-RECORD",
|
| 1455 |
+
"total_width": 21,
|
| 1456 |
+
"fields": [
|
| 1457 |
+
{
|
| 1458 |
+
"name": "POLICY-ID",
|
| 1459 |
+
"start": 0,
|
| 1460 |
+
"end": 6,
|
| 1461 |
+
"length": 6,
|
| 1462 |
+
"pic": "X(6)",
|
| 1463 |
+
"python_type": "str"
|
| 1464 |
+
},
|
| 1465 |
+
{
|
| 1466 |
+
"name": "RAW-DATE",
|
| 1467 |
+
"start": 6,
|
| 1468 |
+
"end": 12,
|
| 1469 |
+
"length": 6,
|
| 1470 |
+
"pic": "9(6)",
|
| 1471 |
+
"python_type": "str"
|
| 1472 |
+
},
|
| 1473 |
+
{
|
| 1474 |
+
"name": "WINDOW-YEAR",
|
| 1475 |
+
"start": 12,
|
| 1476 |
+
"end": 14,
|
| 1477 |
+
"length": 2,
|
| 1478 |
+
"pic": "9(2)",
|
| 1479 |
+
"python_type": "int"
|
| 1480 |
+
},
|
| 1481 |
+
{
|
| 1482 |
+
"name": "AMOUNT",
|
| 1483 |
+
"start": 14,
|
| 1484 |
+
"end": 21,
|
| 1485 |
+
"length": 7,
|
| 1486 |
+
"pic": "9(5)V99",
|
| 1487 |
+
"python_type": "Decimal",
|
| 1488 |
+
"scale": 2
|
| 1489 |
+
}
|
| 1490 |
+
]
|
| 1491 |
+
}
|
| 1492 |
+
},
|
| 1493 |
+
{
|
| 1494 |
+
"tool_name": "inspect_business_rules",
|
| 1495 |
+
"arguments": {},
|
| 1496 |
+
"reward": 0.01,
|
| 1497 |
+
"done": false,
|
| 1498 |
+
"result": {
|
| 1499 |
+
"ok": true,
|
| 1500 |
+
"rules": [
|
| 1501 |
+
"RAW-DATE is YYMMDD.",
|
| 1502 |
+
"If YY >= WINDOW-YEAR, century is 19; otherwise century is 20.",
|
| 1503 |
+
"Invalid dates output 00000000 and valid flag N; amount is preserved."
|
| 1504 |
+
]
|
| 1505 |
+
}
|
| 1506 |
+
},
|
| 1507 |
+
{
|
| 1508 |
+
"tool_name": "write_python_solution",
|
| 1509 |
+
"arguments": {
|
| 1510 |
+
"code_chars": 1768
|
| 1511 |
+
},
|
| 1512 |
+
"reward": 0.02,
|
| 1513 |
+
"done": false,
|
| 1514 |
+
"result": {
|
| 1515 |
+
"ok": true,
|
| 1516 |
+
"draft_id": 1,
|
| 1517 |
+
"syntax_ok": true,
|
| 1518 |
+
"safety_ok": true,
|
| 1519 |
+
"error": null
|
| 1520 |
+
}
|
| 1521 |
+
},
|
| 1522 |
+
{
|
| 1523 |
+
"tool_name": "run_visible_tests",
|
| 1524 |
+
"arguments": {
|
| 1525 |
+
"draft_id": 1
|
| 1526 |
+
},
|
| 1527 |
+
"reward": 0.0,
|
| 1528 |
+
"done": false,
|
| 1529 |
+
"result": {
|
| 1530 |
+
"ok": true,
|
| 1531 |
+
"draft_id": 1,
|
| 1532 |
+
"passed": 0,
|
| 1533 |
+
"total": 3,
|
| 1534 |
+
"pass_rate": 0.0,
|
| 1535 |
+
"syntax_ok": true,
|
| 1536 |
+
"safety_ok": true,
|
| 1537 |
+
"interface_ok": true,
|
| 1538 |
+
"timed_out": false,
|
| 1539 |
+
"error": null,
|
| 1540 |
+
"failures": [
|
| 1541 |
+
{
|
| 1542 |
+
"case_id": "visible_1",
|
| 1543 |
+
"input_summary": "twentieth century date by window",
|
| 1544 |
+
"expected_summary": "OUT-POLICY-ID=P00001, OUT-DATE=19991231, OUT-VALID=Y, OUT-AMOUNT=0012345",
|
| 1545 |
+
"actual_summary": "OUT-POLICY-ID=199912, OUT-DATE=31YP0000, OUT-VALID=1, OUT-AMOUNT=0012345",
|
| 1546 |
+
"error": null
|
| 1547 |
+
},
|
| 1548 |
+
{
|
| 1549 |
+
"case_id": "visible_2",
|
| 1550 |
+
"input_summary": "twenty-first century date by window",
|
| 1551 |
+
"expected_summary": "OUT-POLICY-ID=P00002, OUT-DATE=20240229, OUT-VALID=Y, OUT-AMOUNT=0000100",
|
| 1552 |
+
"actual_summary": "OUT-POLICY-ID=202402, OUT-DATE=29YP0000, OUT-VALID=2, OUT-AMOUNT=0000100",
|
| 1553 |
+
"error": null
|
| 1554 |
+
},
|
| 1555 |
+
{
|
| 1556 |
+
"case_id": "visible_3",
|
| 1557 |
+
"input_summary": "invalid month",
|
| 1558 |
+
"expected_summary": "OUT-POLICY-ID=P00003, OUT-DATE=00000000, OUT-VALID=N, OUT-AMOUNT=0000999",
|
| 1559 |
+
"actual_summary": "OUT-POLICY-ID=000000, OUT-DATE=00NP0000, OUT-VALID=3, OUT-AMOUNT=0000999",
|
| 1560 |
+
"error": null
|
| 1561 |
+
}
|
| 1562 |
+
]
|
| 1563 |
+
}
|
| 1564 |
+
},
|
| 1565 |
+
{
|
| 1566 |
+
"tool_name": "submit_final",
|
| 1567 |
+
"arguments": {
|
| 1568 |
+
"draft_id": 1
|
| 1569 |
+
},
|
| 1570 |
+
"reward": 0.15,
|
| 1571 |
+
"done": true,
|
| 1572 |
+
"result": {
|
| 1573 |
+
"ok": true,
|
| 1574 |
+
"accepted": false,
|
| 1575 |
+
"episode_done": true,
|
| 1576 |
+
"public_score": 0.15,
|
| 1577 |
+
"components": {
|
| 1578 |
+
"hidden_correctness": 0.0,
|
| 1579 |
+
"fresh_correctness": 0.0,
|
| 1580 |
+
"interface_contract": 1.0,
|
| 1581 |
+
"type_and_layout_fidelity": 0.0,
|
| 1582 |
+
"anti_hardcoding": 0.0,
|
| 1583 |
+
"safety": 1.0
|
| 1584 |
+
},
|
| 1585 |
+
"hidden_passed": 0,
|
| 1586 |
+
"hidden_total": 3,
|
| 1587 |
+
"fresh_passed": 0,
|
| 1588 |
+
"fresh_total": 6,
|
| 1589 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 1590 |
+
}
|
| 1591 |
+
}
|
| 1592 |
+
]
|
| 1593 |
+
}
|
| 1594 |
+
]
|
| 1595 |
+
}
|
outputs/evals/oracle_model_rollouts.json
ADDED
|
@@ -0,0 +1,1448 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"provider": "oracle-model",
|
| 3 |
+
"max_repairs": 0,
|
| 4 |
+
"task_count": 6,
|
| 5 |
+
"mean_public_score": 1.0,
|
| 6 |
+
"accepted_count": 6,
|
| 7 |
+
"trajectories": [
|
| 8 |
+
{
|
| 9 |
+
"policy": "oracle-model",
|
| 10 |
+
"task_id": "payroll_net_pay_001",
|
| 11 |
+
"family_id": "decimal_copybook_payroll",
|
| 12 |
+
"ticket": {
|
| 13 |
+
"task_id": "payroll_net_pay_001",
|
| 14 |
+
"family_id": "decimal_copybook_payroll",
|
| 15 |
+
"domain": "payroll",
|
| 16 |
+
"ticket": "Migrate PAYROLL.cbl while preserving copybook offsets, implied decimals, signed deductions, bonus condition names, and fixed-width ACH output.",
|
| 17 |
+
"available_files": [
|
| 18 |
+
"PAYROLL.cbl"
|
| 19 |
+
],
|
| 20 |
+
"available_copybooks": [
|
| 21 |
+
"EMPLOYEE_PAY.cpy"
|
| 22 |
+
],
|
| 23 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 24 |
+
"visible_tests": 3,
|
| 25 |
+
"hidden_tests": 5,
|
| 26 |
+
"input_width": 42,
|
| 27 |
+
"output_width": 28,
|
| 28 |
+
"max_steps": 12,
|
| 29 |
+
"allowed_tools": [
|
| 30 |
+
"read_cobol_file",
|
| 31 |
+
"read_copybook",
|
| 32 |
+
"parse_copybook_layout",
|
| 33 |
+
"inspect_business_rules",
|
| 34 |
+
"write_python_solution",
|
| 35 |
+
"run_visible_tests",
|
| 36 |
+
"inspect_diff",
|
| 37 |
+
"submit_final"
|
| 38 |
+
]
|
| 39 |
+
},
|
| 40 |
+
"model_turns": [
|
| 41 |
+
{
|
| 42 |
+
"provider": "oracle-model",
|
| 43 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"payroll_net_pay_001\",\n \"family_id\": \"decimal_copybook_payroll\",\n \"domain\": \"payroll\",\n \"ticket\": \"Migrate PAYROLL.cbl while preserving copybook offsets, implied decimals, signed deductions, bonus condition names, and fixed-width ACH output.\",\n \"available_files\": [\n \"PAYROLL.cbl\"\n ],\n \"available_copybooks\": [\n \"EMPLOYEE_PAY.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 5,\n \"input_width\": 42,\n \"output_width\": 28,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"PAYROLL.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. PAYROLLNET.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY EMPLOYEE_PAY.\\n 01 TAX-AMOUNT PIC 9(7)V99.\\n 01 NET-AMOUNT PIC 9(7)V99.\\n 01 PAY-CATEGORY PIC X.\\n PROCEDURE DIVISION.\\n COMPUTE TAX-AMOUNT ROUNDED = GROSS-PAY * TAX-RATE\\n COMPUTE NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS\\n IF BONUS-ELIGIBLE ADD 50.00 TO NET-AMOUNT END-IF\\n IF NET-AMOUNT < 0 MOVE 0 TO NET-AMOUNT END-IF\\n EVALUATE TRUE\\n WHEN NET-AMOUNT >= 5000.00 MOVE 'H' TO PAY-CATEGORY\\n WHEN NET-AMOUNT >= 2500.00 MOVE 'M' TO PAY-CATEGORY\\n WHEN OTHER MOVE 'L' TO PAY-CATEGORY\\n END-EVALUATE\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"EMPLOYEE_PAY.cpy\": \" 01 EMPLOYEE-PAY-RECORD.\\n 05 EMP-ID PIC X(6).\\n 05 EMP-NAME PIC X(12).\\n 05 GROSS-PAY PIC 9(7)V99.\\n 05 TAX-RATE PIC 9V999.\\n 05 DEDUCTIONS PIC S9(5)V99 SIGN LEADING SEPARATE.\\n 05 BONUS-FLAG PIC X(1).\\n 88 BONUS-ELIGIBLE VALUE 'Y'.\\n 88 NO-BONUS VALUE 'N'.\\n 05 FILLER PIC X(2).\\n\"\n}\n\nParsed layouts:\n{\n \"EMPLOYEE_PAY.cpy\": {\n \"ok\": true,\n \"filename\": \"EMPLOYEE_PAY.cpy\",\n \"record_name\": \"EMPLOYEE-PAY-RECORD\",\n \"total_width\": 42,\n \"fields\": [\n {\n \"name\": \"EMP-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"EMP-NAME\",\n \"start\": 6,\n \"end\": 18,\n \"length\": 12,\n \"pic\": \"X(12)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"GROSS-PAY\",\n \"start\": 18,\n \"end\": 27,\n \"length\": 9,\n \"pic\": \"9(7)V99\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n },\n {\n \"name\": \"TAX-RATE\",\n \"start\": 27,\n \"end\": 31,\n \"length\": 4,\n \"pic\": \"9V999\",\n \"python_type\": \"Decimal\",\n \"scale\": 3\n },\n {\n \"name\": \"DEDUCTIONS\",\n \"start\": 31,\n \"end\": 39,\n \"length\": 8,\n \"pic\": \"S9(5)V99 SIGN LEADING SEPARATE\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n },\n {\n \"name\": \"BONUS-FLAG\",\n \"start\": 39,\n \"end\": 40,\n \"length\": 1,\n \"pic\": \"X(1)\",\n \"python_type\": \"str\",\n \"level_88\": {\n \"BONUS-ELIGIBLE\": \"Y\",\n \"NO-BONUS\": \"N\"\n }\n },\n {\n \"name\": \"FILLER\",\n \"start\": 40,\n \"end\": 42,\n \"length\": 2,\n \"pic\": \"X(2)\",\n \"python_type\": \"str\"\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"Tax is rounded half up to cents after GROSS-PAY * TAX-RATE.\",\n \"NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS.\",\n \"BONUS-ELIGIBLE adds 50.00; negative net pay floors to zero.\",\n \"Output net pay is a 9-digit zero-padded cents field.\"\n]",
|
| 44 |
+
"response": "{\"code\": \"from decimal import Decimal, ROUND_HALF_UP\\n\\n\\ndef migrate(input_record: str) -> str:\\n emp_id = input_record[0:6]\\n emp_name = input_record[6:18]\\n gross = Decimal(int(input_record[18:27])) / Decimal(\\\"100\\\")\\n tax_rate = Decimal(int(input_record[27:31])) / Decimal(\\\"1000\\\")\\n raw_deductions = input_record[31:39]\\n sign = -1 if raw_deductions[0] == \\\"-\\\" else 1\\n deductions = Decimal(sign * int(raw_deductions[1:])) / Decimal(\\\"100\\\")\\n tax = (gross * tax_rate).quantize(Decimal(\\\"0.01\\\"), rounding=ROUND_HALF_UP)\\n net = gross - tax - deductions\\n if input_record[39:40] == \\\"Y\\\":\\n net += Decimal(\\\"50.00\\\")\\n if net < 0:\\n net = Decimal(\\\"0.00\\\")\\n if net >= Decimal(\\\"5000.00\\\"):\\n category = \\\"H\\\"\\n elif net >= Decimal(\\\"2500.00\\\"):\\n category = \\\"M\\\"\\n else:\\n category = \\\"L\\\"\\n cents = int((net * 100).quantize(Decimal(\\\"1\\\"), rounding=ROUND_HALF_UP))\\n return f\\\"{emp_id}{emp_name[:12].ljust(12)}{cents:09d}{category}\\\"\\n\"}",
|
| 45 |
+
"code_chars": 964
|
| 46 |
+
}
|
| 47 |
+
],
|
| 48 |
+
"visible": {
|
| 49 |
+
"passed": 3,
|
| 50 |
+
"total": 3,
|
| 51 |
+
"pass_rate": 1.0,
|
| 52 |
+
"failures": []
|
| 53 |
+
},
|
| 54 |
+
"final": {
|
| 55 |
+
"public_score": 1.0,
|
| 56 |
+
"accepted": true,
|
| 57 |
+
"components": {
|
| 58 |
+
"hidden_correctness": 1.0,
|
| 59 |
+
"fresh_correctness": 1.0,
|
| 60 |
+
"interface_contract": 1.0,
|
| 61 |
+
"type_and_layout_fidelity": 1.0,
|
| 62 |
+
"anti_hardcoding": 1.0,
|
| 63 |
+
"safety": 1.0
|
| 64 |
+
},
|
| 65 |
+
"hidden_passed": 5,
|
| 66 |
+
"hidden_total": 5,
|
| 67 |
+
"fresh_passed": 6,
|
| 68 |
+
"fresh_total": 6
|
| 69 |
+
},
|
| 70 |
+
"steps": [
|
| 71 |
+
{
|
| 72 |
+
"tool_name": "read_cobol_file",
|
| 73 |
+
"arguments": {
|
| 74 |
+
"filename": "PAYROLL.cbl"
|
| 75 |
+
},
|
| 76 |
+
"reward": 0.02,
|
| 77 |
+
"done": false,
|
| 78 |
+
"result": {
|
| 79 |
+
"ok": true,
|
| 80 |
+
"filename": "PAYROLL.cbl",
|
| 81 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. PAYROLLNET.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY EMPLOYEE_PAY.\n 01 TAX-AMOUNT PIC 9(7)V99.\n 01 NET-AMOUNT PIC 9(7)V99.\n 01 PAY-CATEGORY PIC X.\n PROCEDURE DIVISION.\n COMPUTE TAX-AMOUNT ROUNDED = GROSS-PAY * TAX-RATE\n COMPUTE NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS\n IF BONUS-ELIGIBLE ADD 50.00 TO NET-AMOUNT END-IF\n IF NET-AMOUNT < 0 MOVE 0 TO NET-AMOUNT END-IF\n EVALUATE TRUE\n WHEN NET-AMOUNT >= 5000.00 MOVE 'H' TO PAY-CATEGORY\n WHEN NET-AMOUNT >= 2500.00 MOVE 'M' TO PAY-CATEGORY\n WHEN OTHER MOVE 'L' TO PAY-CATEGORY\n END-EVALUATE\n GOBACK.\n",
|
| 82 |
+
"truncated": false
|
| 83 |
+
}
|
| 84 |
+
},
|
| 85 |
+
{
|
| 86 |
+
"tool_name": "read_copybook",
|
| 87 |
+
"arguments": {
|
| 88 |
+
"filename": "EMPLOYEE_PAY.cpy"
|
| 89 |
+
},
|
| 90 |
+
"reward": 0.02,
|
| 91 |
+
"done": false,
|
| 92 |
+
"result": {
|
| 93 |
+
"ok": true,
|
| 94 |
+
"filename": "EMPLOYEE_PAY.cpy",
|
| 95 |
+
"content": " 01 EMPLOYEE-PAY-RECORD.\n 05 EMP-ID PIC X(6).\n 05 EMP-NAME PIC X(12).\n 05 GROSS-PAY PIC 9(7)V99.\n 05 TAX-RATE PIC 9V999.\n 05 DEDUCTIONS PIC S9(5)V99 SIGN LEADING SEPARATE.\n 05 BONUS-FLAG PIC X(1).\n 88 BONUS-ELIGIBLE VALUE 'Y'.\n 88 NO-BONUS VALUE 'N'.\n 05 FILLER PIC X(2).\n"
|
| 96 |
+
}
|
| 97 |
+
},
|
| 98 |
+
{
|
| 99 |
+
"tool_name": "parse_copybook_layout",
|
| 100 |
+
"arguments": {
|
| 101 |
+
"filename": "EMPLOYEE_PAY.cpy"
|
| 102 |
+
},
|
| 103 |
+
"reward": 0.03,
|
| 104 |
+
"done": false,
|
| 105 |
+
"result": {
|
| 106 |
+
"ok": true,
|
| 107 |
+
"filename": "EMPLOYEE_PAY.cpy",
|
| 108 |
+
"record_name": "EMPLOYEE-PAY-RECORD",
|
| 109 |
+
"total_width": 42,
|
| 110 |
+
"fields": [
|
| 111 |
+
{
|
| 112 |
+
"name": "EMP-ID",
|
| 113 |
+
"start": 0,
|
| 114 |
+
"end": 6,
|
| 115 |
+
"length": 6,
|
| 116 |
+
"pic": "X(6)",
|
| 117 |
+
"python_type": "str"
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"name": "EMP-NAME",
|
| 121 |
+
"start": 6,
|
| 122 |
+
"end": 18,
|
| 123 |
+
"length": 12,
|
| 124 |
+
"pic": "X(12)",
|
| 125 |
+
"python_type": "str"
|
| 126 |
+
},
|
| 127 |
+
{
|
| 128 |
+
"name": "GROSS-PAY",
|
| 129 |
+
"start": 18,
|
| 130 |
+
"end": 27,
|
| 131 |
+
"length": 9,
|
| 132 |
+
"pic": "9(7)V99",
|
| 133 |
+
"python_type": "Decimal",
|
| 134 |
+
"scale": 2
|
| 135 |
+
},
|
| 136 |
+
{
|
| 137 |
+
"name": "TAX-RATE",
|
| 138 |
+
"start": 27,
|
| 139 |
+
"end": 31,
|
| 140 |
+
"length": 4,
|
| 141 |
+
"pic": "9V999",
|
| 142 |
+
"python_type": "Decimal",
|
| 143 |
+
"scale": 3
|
| 144 |
+
},
|
| 145 |
+
{
|
| 146 |
+
"name": "DEDUCTIONS",
|
| 147 |
+
"start": 31,
|
| 148 |
+
"end": 39,
|
| 149 |
+
"length": 8,
|
| 150 |
+
"pic": "S9(5)V99 SIGN LEADING SEPARATE",
|
| 151 |
+
"python_type": "Decimal",
|
| 152 |
+
"scale": 2
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"name": "BONUS-FLAG",
|
| 156 |
+
"start": 39,
|
| 157 |
+
"end": 40,
|
| 158 |
+
"length": 1,
|
| 159 |
+
"pic": "X(1)",
|
| 160 |
+
"python_type": "str",
|
| 161 |
+
"level_88": {
|
| 162 |
+
"BONUS-ELIGIBLE": "Y",
|
| 163 |
+
"NO-BONUS": "N"
|
| 164 |
+
}
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"name": "FILLER",
|
| 168 |
+
"start": 40,
|
| 169 |
+
"end": 42,
|
| 170 |
+
"length": 2,
|
| 171 |
+
"pic": "X(2)",
|
| 172 |
+
"python_type": "str"
|
| 173 |
+
}
|
| 174 |
+
]
|
| 175 |
+
}
|
| 176 |
+
},
|
| 177 |
+
{
|
| 178 |
+
"tool_name": "inspect_business_rules",
|
| 179 |
+
"arguments": {},
|
| 180 |
+
"reward": 0.01,
|
| 181 |
+
"done": false,
|
| 182 |
+
"result": {
|
| 183 |
+
"ok": true,
|
| 184 |
+
"rules": [
|
| 185 |
+
"Tax is rounded half up to cents after GROSS-PAY * TAX-RATE.",
|
| 186 |
+
"NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS.",
|
| 187 |
+
"BONUS-ELIGIBLE adds 50.00; negative net pay floors to zero.",
|
| 188 |
+
"Output net pay is a 9-digit zero-padded cents field."
|
| 189 |
+
]
|
| 190 |
+
}
|
| 191 |
+
},
|
| 192 |
+
{
|
| 193 |
+
"tool_name": "write_python_solution",
|
| 194 |
+
"arguments": {
|
| 195 |
+
"code_chars": 964
|
| 196 |
+
},
|
| 197 |
+
"reward": 0.02,
|
| 198 |
+
"done": false,
|
| 199 |
+
"result": {
|
| 200 |
+
"ok": true,
|
| 201 |
+
"draft_id": 1,
|
| 202 |
+
"syntax_ok": true,
|
| 203 |
+
"safety_ok": true,
|
| 204 |
+
"error": null
|
| 205 |
+
}
|
| 206 |
+
},
|
| 207 |
+
{
|
| 208 |
+
"tool_name": "run_visible_tests",
|
| 209 |
+
"arguments": {
|
| 210 |
+
"draft_id": 1
|
| 211 |
+
},
|
| 212 |
+
"reward": 0.05,
|
| 213 |
+
"done": false,
|
| 214 |
+
"result": {
|
| 215 |
+
"ok": true,
|
| 216 |
+
"draft_id": 1,
|
| 217 |
+
"passed": 3,
|
| 218 |
+
"total": 3,
|
| 219 |
+
"pass_rate": 1.0,
|
| 220 |
+
"syntax_ok": true,
|
| 221 |
+
"safety_ok": true,
|
| 222 |
+
"interface_ok": true,
|
| 223 |
+
"timed_out": false,
|
| 224 |
+
"error": null,
|
| 225 |
+
"failures": []
|
| 226 |
+
}
|
| 227 |
+
},
|
| 228 |
+
{
|
| 229 |
+
"tool_name": "submit_final",
|
| 230 |
+
"arguments": {
|
| 231 |
+
"draft_id": 1
|
| 232 |
+
},
|
| 233 |
+
"reward": 1.0,
|
| 234 |
+
"done": true,
|
| 235 |
+
"result": {
|
| 236 |
+
"ok": true,
|
| 237 |
+
"accepted": true,
|
| 238 |
+
"episode_done": true,
|
| 239 |
+
"public_score": 1.0,
|
| 240 |
+
"components": {
|
| 241 |
+
"hidden_correctness": 1.0,
|
| 242 |
+
"fresh_correctness": 1.0,
|
| 243 |
+
"interface_contract": 1.0,
|
| 244 |
+
"type_and_layout_fidelity": 1.0,
|
| 245 |
+
"anti_hardcoding": 1.0,
|
| 246 |
+
"safety": 1.0
|
| 247 |
+
},
|
| 248 |
+
"hidden_passed": 5,
|
| 249 |
+
"hidden_total": 5,
|
| 250 |
+
"fresh_passed": 6,
|
| 251 |
+
"fresh_total": 6,
|
| 252 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 253 |
+
}
|
| 254 |
+
}
|
| 255 |
+
]
|
| 256 |
+
},
|
| 257 |
+
{
|
| 258 |
+
"policy": "oracle-model",
|
| 259 |
+
"task_id": "customer_format_001",
|
| 260 |
+
"family_id": "fixed_width_customer",
|
| 261 |
+
"ticket": {
|
| 262 |
+
"task_id": "customer_format_001",
|
| 263 |
+
"family_id": "fixed_width_customer",
|
| 264 |
+
"domain": "customer master data",
|
| 265 |
+
"ticket": "Migrate CUSTFMT.cbl. Preserve fixed-width name formatting, status mapping, ZIP leading zeros, and zero-padded balance output.",
|
| 266 |
+
"available_files": [
|
| 267 |
+
"CUSTFMT.cbl"
|
| 268 |
+
],
|
| 269 |
+
"available_copybooks": [
|
| 270 |
+
"CUSTOMER_REC.cpy"
|
| 271 |
+
],
|
| 272 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 273 |
+
"visible_tests": 3,
|
| 274 |
+
"hidden_tests": 3,
|
| 275 |
+
"input_width": 40,
|
| 276 |
+
"output_width": 41,
|
| 277 |
+
"max_steps": 12,
|
| 278 |
+
"allowed_tools": [
|
| 279 |
+
"read_cobol_file",
|
| 280 |
+
"read_copybook",
|
| 281 |
+
"parse_copybook_layout",
|
| 282 |
+
"inspect_business_rules",
|
| 283 |
+
"write_python_solution",
|
| 284 |
+
"run_visible_tests",
|
| 285 |
+
"inspect_diff",
|
| 286 |
+
"submit_final"
|
| 287 |
+
]
|
| 288 |
+
},
|
| 289 |
+
"model_turns": [
|
| 290 |
+
{
|
| 291 |
+
"provider": "oracle-model",
|
| 292 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"customer_format_001\",\n \"family_id\": \"fixed_width_customer\",\n \"domain\": \"customer master data\",\n \"ticket\": \"Migrate CUSTFMT.cbl. Preserve fixed-width name formatting, status mapping, ZIP leading zeros, and zero-padded balance output.\",\n \"available_files\": [\n \"CUSTFMT.cbl\"\n ],\n \"available_copybooks\": [\n \"CUSTOMER_REC.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 3,\n \"input_width\": 40,\n \"output_width\": 41,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"CUSTFMT.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. CUSTFMT.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY CUSTOMER_REC.\\n 01 OUTPUT-RECORD.\\n 05 OUT-CUST-ID PIC X(5).\\n 05 OUT-FULL-NAME PIC X(22).\\n 05 OUT-ZIP-CODE PIC 9(5).\\n 05 OUT-STATUS PIC X.\\n 05 OUT-BALANCE PIC 9(6)V99.\\n PROCEDURE DIVISION.\\n STRING LAST-NAME DELIMITED BY SIZE ', ' FIRST-NAME DELIMITED BY SIZE\\n INTO OUT-FULL-NAME\\n EVALUATE STATUS-CODE\\n WHEN 'A' MOVE 'O' TO OUT-STATUS\\n WHEN 'S' MOVE 'S' TO OUT-STATUS\\n WHEN OTHER MOVE 'C' TO OUT-STATUS\\n END-EVALUATE\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"CUSTOMER_REC.cpy\": \" 01 CUSTOMER-RECORD.\\n 05 CUST-ID PIC X(5).\\n 05 FIRST-NAME PIC X(10).\\n 05 LAST-NAME PIC X(12).\\n 05 ZIP-CODE PIC 9(5).\\n 05 STATUS-CODE PIC X.\\n 88 ACTIVE-CUSTOMER VALUE 'A'.\\n 88 SUSPENDED-CUSTOMER VALUE 'S'.\\n 88 CLOSED-CUSTOMER VALUE 'C'.\\n 05 BALANCE-DUE PIC 9(5)V99.\\n\"\n}\n\nParsed layouts:\n{\n \"CUSTOMER_REC.cpy\": {\n \"ok\": true,\n \"filename\": \"CUSTOMER_REC.cpy\",\n \"record_name\": \"CUSTOMER-RECORD\",\n \"total_width\": 40,\n \"fields\": [\n {\n \"name\": \"CUST-ID\",\n \"start\": 0,\n \"end\": 5,\n \"length\": 5,\n \"pic\": \"X(5)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"FIRST-NAME\",\n \"start\": 5,\n \"end\": 15,\n \"length\": 10,\n \"pic\": \"X(10)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"LAST-NAME\",\n \"start\": 15,\n \"end\": 27,\n \"length\": 12,\n \"pic\": \"X(12)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"ZIP-CODE\",\n \"start\": 27,\n \"end\": 32,\n \"length\": 5,\n \"pic\": \"9(5)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"STATUS-CODE\",\n \"start\": 32,\n \"end\": 33,\n \"length\": 1,\n \"pic\": \"X\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"BALANCE-DUE\",\n \"start\": 33,\n \"end\": 40,\n \"length\": 7,\n \"pic\": \"9(5)V99\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"OUT-FULL-NAME is LAST-NAME, comma-space, FIRST-NAME, truncated/padded to 22.\",\n \"A maps to O, S maps to S, anything else maps to C.\",\n \"ZIP stays five digits and OUT-BALANCE is eight zero-padded digits.\"\n]",
|
| 293 |
+
"response": "{\"code\": \"def migrate(input_record: str) -> str:\\n cust_id = input_record[0:5]\\n first = input_record[5:15].rstrip()\\n last = input_record[15:27].rstrip()\\n zip_code = input_record[27:32]\\n status = {\\\"A\\\": \\\"O\\\", \\\"S\\\": \\\"S\\\"}.get(input_record[32:33], \\\"C\\\")\\n balance = int(input_record[33:40])\\n full_name = f\\\"{last}, {first}\\\"[:22].ljust(22)\\n return f\\\"{cust_id}{full_name}{zip_code}{status}{balance:08d}\\\"\\n\"}",
|
| 294 |
+
"code_chars": 405
|
| 295 |
+
}
|
| 296 |
+
],
|
| 297 |
+
"visible": {
|
| 298 |
+
"passed": 3,
|
| 299 |
+
"total": 3,
|
| 300 |
+
"pass_rate": 1.0,
|
| 301 |
+
"failures": []
|
| 302 |
+
},
|
| 303 |
+
"final": {
|
| 304 |
+
"public_score": 1.0,
|
| 305 |
+
"accepted": true,
|
| 306 |
+
"components": {
|
| 307 |
+
"hidden_correctness": 1.0,
|
| 308 |
+
"fresh_correctness": 1.0,
|
| 309 |
+
"interface_contract": 1.0,
|
| 310 |
+
"type_and_layout_fidelity": 1.0,
|
| 311 |
+
"anti_hardcoding": 1.0,
|
| 312 |
+
"safety": 1.0
|
| 313 |
+
},
|
| 314 |
+
"hidden_passed": 3,
|
| 315 |
+
"hidden_total": 3,
|
| 316 |
+
"fresh_passed": 6,
|
| 317 |
+
"fresh_total": 6
|
| 318 |
+
},
|
| 319 |
+
"steps": [
|
| 320 |
+
{
|
| 321 |
+
"tool_name": "read_cobol_file",
|
| 322 |
+
"arguments": {
|
| 323 |
+
"filename": "CUSTFMT.cbl"
|
| 324 |
+
},
|
| 325 |
+
"reward": 0.02,
|
| 326 |
+
"done": false,
|
| 327 |
+
"result": {
|
| 328 |
+
"ok": true,
|
| 329 |
+
"filename": "CUSTFMT.cbl",
|
| 330 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. CUSTFMT.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY CUSTOMER_REC.\n 01 OUTPUT-RECORD.\n 05 OUT-CUST-ID PIC X(5).\n 05 OUT-FULL-NAME PIC X(22).\n 05 OUT-ZIP-CODE PIC 9(5).\n 05 OUT-STATUS PIC X.\n 05 OUT-BALANCE PIC 9(6)V99.\n PROCEDURE DIVISION.\n STRING LAST-NAME DELIMITED BY SIZE ', ' FIRST-NAME DELIMITED BY SIZE\n INTO OUT-FULL-NAME\n EVALUATE STATUS-CODE\n WHEN 'A' MOVE 'O' TO OUT-STATUS\n WHEN 'S' MOVE 'S' TO OUT-STATUS\n WHEN OTHER MOVE 'C' TO OUT-STATUS\n END-EVALUATE\n GOBACK.\n",
|
| 331 |
+
"truncated": false
|
| 332 |
+
}
|
| 333 |
+
},
|
| 334 |
+
{
|
| 335 |
+
"tool_name": "read_copybook",
|
| 336 |
+
"arguments": {
|
| 337 |
+
"filename": "CUSTOMER_REC.cpy"
|
| 338 |
+
},
|
| 339 |
+
"reward": 0.02,
|
| 340 |
+
"done": false,
|
| 341 |
+
"result": {
|
| 342 |
+
"ok": true,
|
| 343 |
+
"filename": "CUSTOMER_REC.cpy",
|
| 344 |
+
"content": " 01 CUSTOMER-RECORD.\n 05 CUST-ID PIC X(5).\n 05 FIRST-NAME PIC X(10).\n 05 LAST-NAME PIC X(12).\n 05 ZIP-CODE PIC 9(5).\n 05 STATUS-CODE PIC X.\n 88 ACTIVE-CUSTOMER VALUE 'A'.\n 88 SUSPENDED-CUSTOMER VALUE 'S'.\n 88 CLOSED-CUSTOMER VALUE 'C'.\n 05 BALANCE-DUE PIC 9(5)V99.\n"
|
| 345 |
+
}
|
| 346 |
+
},
|
| 347 |
+
{
|
| 348 |
+
"tool_name": "parse_copybook_layout",
|
| 349 |
+
"arguments": {
|
| 350 |
+
"filename": "CUSTOMER_REC.cpy"
|
| 351 |
+
},
|
| 352 |
+
"reward": 0.03,
|
| 353 |
+
"done": false,
|
| 354 |
+
"result": {
|
| 355 |
+
"ok": true,
|
| 356 |
+
"filename": "CUSTOMER_REC.cpy",
|
| 357 |
+
"record_name": "CUSTOMER-RECORD",
|
| 358 |
+
"total_width": 40,
|
| 359 |
+
"fields": [
|
| 360 |
+
{
|
| 361 |
+
"name": "CUST-ID",
|
| 362 |
+
"start": 0,
|
| 363 |
+
"end": 5,
|
| 364 |
+
"length": 5,
|
| 365 |
+
"pic": "X(5)",
|
| 366 |
+
"python_type": "str"
|
| 367 |
+
},
|
| 368 |
+
{
|
| 369 |
+
"name": "FIRST-NAME",
|
| 370 |
+
"start": 5,
|
| 371 |
+
"end": 15,
|
| 372 |
+
"length": 10,
|
| 373 |
+
"pic": "X(10)",
|
| 374 |
+
"python_type": "str"
|
| 375 |
+
},
|
| 376 |
+
{
|
| 377 |
+
"name": "LAST-NAME",
|
| 378 |
+
"start": 15,
|
| 379 |
+
"end": 27,
|
| 380 |
+
"length": 12,
|
| 381 |
+
"pic": "X(12)",
|
| 382 |
+
"python_type": "str"
|
| 383 |
+
},
|
| 384 |
+
{
|
| 385 |
+
"name": "ZIP-CODE",
|
| 386 |
+
"start": 27,
|
| 387 |
+
"end": 32,
|
| 388 |
+
"length": 5,
|
| 389 |
+
"pic": "9(5)",
|
| 390 |
+
"python_type": "str"
|
| 391 |
+
},
|
| 392 |
+
{
|
| 393 |
+
"name": "STATUS-CODE",
|
| 394 |
+
"start": 32,
|
| 395 |
+
"end": 33,
|
| 396 |
+
"length": 1,
|
| 397 |
+
"pic": "X",
|
| 398 |
+
"python_type": "str"
|
| 399 |
+
},
|
| 400 |
+
{
|
| 401 |
+
"name": "BALANCE-DUE",
|
| 402 |
+
"start": 33,
|
| 403 |
+
"end": 40,
|
| 404 |
+
"length": 7,
|
| 405 |
+
"pic": "9(5)V99",
|
| 406 |
+
"python_type": "Decimal",
|
| 407 |
+
"scale": 2
|
| 408 |
+
}
|
| 409 |
+
]
|
| 410 |
+
}
|
| 411 |
+
},
|
| 412 |
+
{
|
| 413 |
+
"tool_name": "inspect_business_rules",
|
| 414 |
+
"arguments": {},
|
| 415 |
+
"reward": 0.01,
|
| 416 |
+
"done": false,
|
| 417 |
+
"result": {
|
| 418 |
+
"ok": true,
|
| 419 |
+
"rules": [
|
| 420 |
+
"OUT-FULL-NAME is LAST-NAME, comma-space, FIRST-NAME, truncated/padded to 22.",
|
| 421 |
+
"A maps to O, S maps to S, anything else maps to C.",
|
| 422 |
+
"ZIP stays five digits and OUT-BALANCE is eight zero-padded digits."
|
| 423 |
+
]
|
| 424 |
+
}
|
| 425 |
+
},
|
| 426 |
+
{
|
| 427 |
+
"tool_name": "write_python_solution",
|
| 428 |
+
"arguments": {
|
| 429 |
+
"code_chars": 405
|
| 430 |
+
},
|
| 431 |
+
"reward": 0.02,
|
| 432 |
+
"done": false,
|
| 433 |
+
"result": {
|
| 434 |
+
"ok": true,
|
| 435 |
+
"draft_id": 1,
|
| 436 |
+
"syntax_ok": true,
|
| 437 |
+
"safety_ok": true,
|
| 438 |
+
"error": null
|
| 439 |
+
}
|
| 440 |
+
},
|
| 441 |
+
{
|
| 442 |
+
"tool_name": "run_visible_tests",
|
| 443 |
+
"arguments": {
|
| 444 |
+
"draft_id": 1
|
| 445 |
+
},
|
| 446 |
+
"reward": 0.05,
|
| 447 |
+
"done": false,
|
| 448 |
+
"result": {
|
| 449 |
+
"ok": true,
|
| 450 |
+
"draft_id": 1,
|
| 451 |
+
"passed": 3,
|
| 452 |
+
"total": 3,
|
| 453 |
+
"pass_rate": 1.0,
|
| 454 |
+
"syntax_ok": true,
|
| 455 |
+
"safety_ok": true,
|
| 456 |
+
"interface_ok": true,
|
| 457 |
+
"timed_out": false,
|
| 458 |
+
"error": null,
|
| 459 |
+
"failures": []
|
| 460 |
+
}
|
| 461 |
+
},
|
| 462 |
+
{
|
| 463 |
+
"tool_name": "submit_final",
|
| 464 |
+
"arguments": {
|
| 465 |
+
"draft_id": 1
|
| 466 |
+
},
|
| 467 |
+
"reward": 1.0,
|
| 468 |
+
"done": true,
|
| 469 |
+
"result": {
|
| 470 |
+
"ok": true,
|
| 471 |
+
"accepted": true,
|
| 472 |
+
"episode_done": true,
|
| 473 |
+
"public_score": 1.0,
|
| 474 |
+
"components": {
|
| 475 |
+
"hidden_correctness": 1.0,
|
| 476 |
+
"fresh_correctness": 1.0,
|
| 477 |
+
"interface_contract": 1.0,
|
| 478 |
+
"type_and_layout_fidelity": 1.0,
|
| 479 |
+
"anti_hardcoding": 1.0,
|
| 480 |
+
"safety": 1.0
|
| 481 |
+
},
|
| 482 |
+
"hidden_passed": 3,
|
| 483 |
+
"hidden_total": 3,
|
| 484 |
+
"fresh_passed": 6,
|
| 485 |
+
"fresh_total": 6,
|
| 486 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 487 |
+
}
|
| 488 |
+
}
|
| 489 |
+
]
|
| 490 |
+
},
|
| 491 |
+
{
|
| 492 |
+
"policy": "oracle-model",
|
| 493 |
+
"task_id": "claims_eligibility_001",
|
| 494 |
+
"family_id": "claims_eligibility_branching",
|
| 495 |
+
"ticket": {
|
| 496 |
+
"task_id": "claims_eligibility_001",
|
| 497 |
+
"family_id": "claims_eligibility_branching",
|
| 498 |
+
"domain": "insurance claims",
|
| 499 |
+
"ticket": "Migrate CLMELIG.cbl. Preserve EVALUATE TRUE branch precedence for claim approvals, denials, and manual review reasons.",
|
| 500 |
+
"available_files": [
|
| 501 |
+
"CLMELIG.cbl"
|
| 502 |
+
],
|
| 503 |
+
"available_copybooks": [
|
| 504 |
+
"CLAIM_REC.cpy"
|
| 505 |
+
],
|
| 506 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 507 |
+
"visible_tests": 3,
|
| 508 |
+
"hidden_tests": 3,
|
| 509 |
+
"input_width": 21,
|
| 510 |
+
"output_width": 9,
|
| 511 |
+
"max_steps": 12,
|
| 512 |
+
"allowed_tools": [
|
| 513 |
+
"read_cobol_file",
|
| 514 |
+
"read_copybook",
|
| 515 |
+
"parse_copybook_layout",
|
| 516 |
+
"inspect_business_rules",
|
| 517 |
+
"write_python_solution",
|
| 518 |
+
"run_visible_tests",
|
| 519 |
+
"inspect_diff",
|
| 520 |
+
"submit_final"
|
| 521 |
+
]
|
| 522 |
+
},
|
| 523 |
+
"model_turns": [
|
| 524 |
+
{
|
| 525 |
+
"provider": "oracle-model",
|
| 526 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"claims_eligibility_001\",\n \"family_id\": \"claims_eligibility_branching\",\n \"domain\": \"insurance claims\",\n \"ticket\": \"Migrate CLMELIG.cbl. Preserve EVALUATE TRUE branch precedence for claim approvals, denials, and manual review reasons.\",\n \"available_files\": [\n \"CLMELIG.cbl\"\n ],\n \"available_copybooks\": [\n \"CLAIM_REC.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 3,\n \"input_width\": 21,\n \"output_width\": 9,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"CLMELIG.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. CLMELIG.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY CLAIM_REC.\\n PROCEDURE DIVISION.\\n EVALUATE TRUE\\n WHEN AGE < 18 MOVE 'D' TO DECISION MOVE 'A1' TO REASON\\n WHEN PLAN-CODE = 'B' AND CLAIM-AMOUNT > 1500.00 MOVE 'R' TO DECISION MOVE 'B2' TO REASON\\n WHEN PREAUTH-FLAG = 'N' AND CLAIM-AMOUNT > 1000.00 MOVE 'D' TO DECISION MOVE 'P1' TO REASON\\n WHEN SERVICE-DAYS > 030 MOVE 'R' TO DECISION MOVE 'L1' TO REASON\\n WHEN OTHER MOVE 'A' TO DECISION MOVE 'OK' TO REASON\\n END-EVALUATE\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"CLAIM_REC.cpy\": \" 01 CLAIM-RECORD.\\n 05 CLAIM-ID PIC X(6).\\n 05 AGE PIC 9(3).\\n 05 PLAN-CODE PIC X.\\n 05 SERVICE-DAYS PIC 9(3).\\n 05 PREAUTH-FLAG PIC X.\\n 05 CLAIM-AMOUNT PIC 9(5)V99.\\n\"\n}\n\nParsed layouts:\n{\n \"CLAIM_REC.cpy\": {\n \"ok\": true,\n \"filename\": \"CLAIM_REC.cpy\",\n \"record_name\": \"CLAIM-RECORD\",\n \"total_width\": 21,\n \"fields\": [\n {\n \"name\": \"CLAIM-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"AGE\",\n \"start\": 6,\n \"end\": 9,\n \"length\": 3,\n \"pic\": \"9(3)\",\n \"python_type\": \"int\"\n },\n {\n \"name\": \"PLAN-CODE\",\n \"start\": 9,\n \"end\": 10,\n \"length\": 1,\n \"pic\": \"X\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"SERVICE-DAYS\",\n \"start\": 10,\n \"end\": 13,\n \"length\": 3,\n \"pic\": \"9(3)\",\n \"python_type\": \"int\"\n },\n {\n \"name\": \"PREAUTH-FLAG\",\n \"start\": 13,\n \"end\": 14,\n \"length\": 1,\n \"pic\": \"X\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"CLAIM-AMOUNT\",\n \"start\": 14,\n \"end\": 21,\n \"length\": 7,\n \"pic\": \"9(5)V99\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"Branch order matters: age, plan-B large claim, missing preauth, long service, default approve.\",\n \"Amounts are implied cents; 100000 means 1000.00.\"\n]",
|
| 527 |
+
"response": "{\"code\": \"def migrate(input_record: str) -> str:\\n claim_id = input_record[0:6]\\n age = int(input_record[6:9])\\n plan = input_record[9:10]\\n days = int(input_record[10:13])\\n preauth = input_record[13:14]\\n amount_cents = int(input_record[14:21])\\n if age < 18:\\n decision, reason = \\\"D\\\", \\\"A1\\\"\\n elif plan == \\\"B\\\" and amount_cents > 150000:\\n decision, reason = \\\"R\\\", \\\"B2\\\"\\n elif preauth == \\\"N\\\" and amount_cents > 100000:\\n decision, reason = \\\"D\\\", \\\"P1\\\"\\n elif days > 30:\\n decision, reason = \\\"R\\\", \\\"L1\\\"\\n else:\\n decision, reason = \\\"A\\\", \\\"OK\\\"\\n return f\\\"{claim_id}{decision}{reason}\\\"\\n\"}",
|
| 528 |
+
"code_chars": 623
|
| 529 |
+
}
|
| 530 |
+
],
|
| 531 |
+
"visible": {
|
| 532 |
+
"passed": 3,
|
| 533 |
+
"total": 3,
|
| 534 |
+
"pass_rate": 1.0,
|
| 535 |
+
"failures": []
|
| 536 |
+
},
|
| 537 |
+
"final": {
|
| 538 |
+
"public_score": 1.0,
|
| 539 |
+
"accepted": true,
|
| 540 |
+
"components": {
|
| 541 |
+
"hidden_correctness": 1.0,
|
| 542 |
+
"fresh_correctness": 1.0,
|
| 543 |
+
"interface_contract": 1.0,
|
| 544 |
+
"type_and_layout_fidelity": 1.0,
|
| 545 |
+
"anti_hardcoding": 1.0,
|
| 546 |
+
"safety": 1.0
|
| 547 |
+
},
|
| 548 |
+
"hidden_passed": 3,
|
| 549 |
+
"hidden_total": 3,
|
| 550 |
+
"fresh_passed": 6,
|
| 551 |
+
"fresh_total": 6
|
| 552 |
+
},
|
| 553 |
+
"steps": [
|
| 554 |
+
{
|
| 555 |
+
"tool_name": "read_cobol_file",
|
| 556 |
+
"arguments": {
|
| 557 |
+
"filename": "CLMELIG.cbl"
|
| 558 |
+
},
|
| 559 |
+
"reward": 0.02,
|
| 560 |
+
"done": false,
|
| 561 |
+
"result": {
|
| 562 |
+
"ok": true,
|
| 563 |
+
"filename": "CLMELIG.cbl",
|
| 564 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. CLMELIG.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY CLAIM_REC.\n PROCEDURE DIVISION.\n EVALUATE TRUE\n WHEN AGE < 18 MOVE 'D' TO DECISION MOVE 'A1' TO REASON\n WHEN PLAN-CODE = 'B' AND CLAIM-AMOUNT > 1500.00 MOVE 'R' TO DECISION MOVE 'B2' TO REASON\n WHEN PREAUTH-FLAG = 'N' AND CLAIM-AMOUNT > 1000.00 MOVE 'D' TO DECISION MOVE 'P1' TO REASON\n WHEN SERVICE-DAYS > 030 MOVE 'R' TO DECISION MOVE 'L1' TO REASON\n WHEN OTHER MOVE 'A' TO DECISION MOVE 'OK' TO REASON\n END-EVALUATE\n GOBACK.\n",
|
| 565 |
+
"truncated": false
|
| 566 |
+
}
|
| 567 |
+
},
|
| 568 |
+
{
|
| 569 |
+
"tool_name": "read_copybook",
|
| 570 |
+
"arguments": {
|
| 571 |
+
"filename": "CLAIM_REC.cpy"
|
| 572 |
+
},
|
| 573 |
+
"reward": 0.02,
|
| 574 |
+
"done": false,
|
| 575 |
+
"result": {
|
| 576 |
+
"ok": true,
|
| 577 |
+
"filename": "CLAIM_REC.cpy",
|
| 578 |
+
"content": " 01 CLAIM-RECORD.\n 05 CLAIM-ID PIC X(6).\n 05 AGE PIC 9(3).\n 05 PLAN-CODE PIC X.\n 05 SERVICE-DAYS PIC 9(3).\n 05 PREAUTH-FLAG PIC X.\n 05 CLAIM-AMOUNT PIC 9(5)V99.\n"
|
| 579 |
+
}
|
| 580 |
+
},
|
| 581 |
+
{
|
| 582 |
+
"tool_name": "parse_copybook_layout",
|
| 583 |
+
"arguments": {
|
| 584 |
+
"filename": "CLAIM_REC.cpy"
|
| 585 |
+
},
|
| 586 |
+
"reward": 0.03,
|
| 587 |
+
"done": false,
|
| 588 |
+
"result": {
|
| 589 |
+
"ok": true,
|
| 590 |
+
"filename": "CLAIM_REC.cpy",
|
| 591 |
+
"record_name": "CLAIM-RECORD",
|
| 592 |
+
"total_width": 21,
|
| 593 |
+
"fields": [
|
| 594 |
+
{
|
| 595 |
+
"name": "CLAIM-ID",
|
| 596 |
+
"start": 0,
|
| 597 |
+
"end": 6,
|
| 598 |
+
"length": 6,
|
| 599 |
+
"pic": "X(6)",
|
| 600 |
+
"python_type": "str"
|
| 601 |
+
},
|
| 602 |
+
{
|
| 603 |
+
"name": "AGE",
|
| 604 |
+
"start": 6,
|
| 605 |
+
"end": 9,
|
| 606 |
+
"length": 3,
|
| 607 |
+
"pic": "9(3)",
|
| 608 |
+
"python_type": "int"
|
| 609 |
+
},
|
| 610 |
+
{
|
| 611 |
+
"name": "PLAN-CODE",
|
| 612 |
+
"start": 9,
|
| 613 |
+
"end": 10,
|
| 614 |
+
"length": 1,
|
| 615 |
+
"pic": "X",
|
| 616 |
+
"python_type": "str"
|
| 617 |
+
},
|
| 618 |
+
{
|
| 619 |
+
"name": "SERVICE-DAYS",
|
| 620 |
+
"start": 10,
|
| 621 |
+
"end": 13,
|
| 622 |
+
"length": 3,
|
| 623 |
+
"pic": "9(3)",
|
| 624 |
+
"python_type": "int"
|
| 625 |
+
},
|
| 626 |
+
{
|
| 627 |
+
"name": "PREAUTH-FLAG",
|
| 628 |
+
"start": 13,
|
| 629 |
+
"end": 14,
|
| 630 |
+
"length": 1,
|
| 631 |
+
"pic": "X",
|
| 632 |
+
"python_type": "str"
|
| 633 |
+
},
|
| 634 |
+
{
|
| 635 |
+
"name": "CLAIM-AMOUNT",
|
| 636 |
+
"start": 14,
|
| 637 |
+
"end": 21,
|
| 638 |
+
"length": 7,
|
| 639 |
+
"pic": "9(5)V99",
|
| 640 |
+
"python_type": "Decimal",
|
| 641 |
+
"scale": 2
|
| 642 |
+
}
|
| 643 |
+
]
|
| 644 |
+
}
|
| 645 |
+
},
|
| 646 |
+
{
|
| 647 |
+
"tool_name": "inspect_business_rules",
|
| 648 |
+
"arguments": {},
|
| 649 |
+
"reward": 0.01,
|
| 650 |
+
"done": false,
|
| 651 |
+
"result": {
|
| 652 |
+
"ok": true,
|
| 653 |
+
"rules": [
|
| 654 |
+
"Branch order matters: age, plan-B large claim, missing preauth, long service, default approve.",
|
| 655 |
+
"Amounts are implied cents; 100000 means 1000.00."
|
| 656 |
+
]
|
| 657 |
+
}
|
| 658 |
+
},
|
| 659 |
+
{
|
| 660 |
+
"tool_name": "write_python_solution",
|
| 661 |
+
"arguments": {
|
| 662 |
+
"code_chars": 623
|
| 663 |
+
},
|
| 664 |
+
"reward": 0.02,
|
| 665 |
+
"done": false,
|
| 666 |
+
"result": {
|
| 667 |
+
"ok": true,
|
| 668 |
+
"draft_id": 1,
|
| 669 |
+
"syntax_ok": true,
|
| 670 |
+
"safety_ok": true,
|
| 671 |
+
"error": null
|
| 672 |
+
}
|
| 673 |
+
},
|
| 674 |
+
{
|
| 675 |
+
"tool_name": "run_visible_tests",
|
| 676 |
+
"arguments": {
|
| 677 |
+
"draft_id": 1
|
| 678 |
+
},
|
| 679 |
+
"reward": 0.05,
|
| 680 |
+
"done": false,
|
| 681 |
+
"result": {
|
| 682 |
+
"ok": true,
|
| 683 |
+
"draft_id": 1,
|
| 684 |
+
"passed": 3,
|
| 685 |
+
"total": 3,
|
| 686 |
+
"pass_rate": 1.0,
|
| 687 |
+
"syntax_ok": true,
|
| 688 |
+
"safety_ok": true,
|
| 689 |
+
"interface_ok": true,
|
| 690 |
+
"timed_out": false,
|
| 691 |
+
"error": null,
|
| 692 |
+
"failures": []
|
| 693 |
+
}
|
| 694 |
+
},
|
| 695 |
+
{
|
| 696 |
+
"tool_name": "submit_final",
|
| 697 |
+
"arguments": {
|
| 698 |
+
"draft_id": 1
|
| 699 |
+
},
|
| 700 |
+
"reward": 1.0,
|
| 701 |
+
"done": true,
|
| 702 |
+
"result": {
|
| 703 |
+
"ok": true,
|
| 704 |
+
"accepted": true,
|
| 705 |
+
"episode_done": true,
|
| 706 |
+
"public_score": 1.0,
|
| 707 |
+
"components": {
|
| 708 |
+
"hidden_correctness": 1.0,
|
| 709 |
+
"fresh_correctness": 1.0,
|
| 710 |
+
"interface_contract": 1.0,
|
| 711 |
+
"type_and_layout_fidelity": 1.0,
|
| 712 |
+
"anti_hardcoding": 1.0,
|
| 713 |
+
"safety": 1.0
|
| 714 |
+
},
|
| 715 |
+
"hidden_passed": 3,
|
| 716 |
+
"hidden_total": 3,
|
| 717 |
+
"fresh_passed": 6,
|
| 718 |
+
"fresh_total": 6,
|
| 719 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 720 |
+
}
|
| 721 |
+
}
|
| 722 |
+
]
|
| 723 |
+
},
|
| 724 |
+
{
|
| 725 |
+
"policy": "oracle-model",
|
| 726 |
+
"task_id": "account_status_001",
|
| 727 |
+
"family_id": "account_status_level88",
|
| 728 |
+
"ticket": {
|
| 729 |
+
"task_id": "account_status_001",
|
| 730 |
+
"family_id": "account_status_level88",
|
| 731 |
+
"domain": "banking",
|
| 732 |
+
"ticket": "Migrate ACCTSTAT.cbl. Correctly interpret level-88 status names and preserve branch precedence for account servicing actions.",
|
| 733 |
+
"available_files": [
|
| 734 |
+
"ACCTSTAT.cbl"
|
| 735 |
+
],
|
| 736 |
+
"available_copybooks": [
|
| 737 |
+
"ACCOUNT_REC.cpy"
|
| 738 |
+
],
|
| 739 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 740 |
+
"visible_tests": 3,
|
| 741 |
+
"hidden_tests": 3,
|
| 742 |
+
"input_width": 19,
|
| 743 |
+
"output_width": 9,
|
| 744 |
+
"max_steps": 12,
|
| 745 |
+
"allowed_tools": [
|
| 746 |
+
"read_cobol_file",
|
| 747 |
+
"read_copybook",
|
| 748 |
+
"parse_copybook_layout",
|
| 749 |
+
"inspect_business_rules",
|
| 750 |
+
"write_python_solution",
|
| 751 |
+
"run_visible_tests",
|
| 752 |
+
"inspect_diff",
|
| 753 |
+
"submit_final"
|
| 754 |
+
]
|
| 755 |
+
},
|
| 756 |
+
"model_turns": [
|
| 757 |
+
{
|
| 758 |
+
"provider": "oracle-model",
|
| 759 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"account_status_001\",\n \"family_id\": \"account_status_level88\",\n \"domain\": \"banking\",\n \"ticket\": \"Migrate ACCTSTAT.cbl. Correctly interpret level-88 status names and preserve branch precedence for account servicing actions.\",\n \"available_files\": [\n \"ACCTSTAT.cbl\"\n ],\n \"available_copybooks\": [\n \"ACCOUNT_REC.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 3,\n \"input_width\": 19,\n \"output_width\": 9,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"ACCTSTAT.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. ACCTSTAT.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY ACCOUNT_REC.\\n PROCEDURE DIVISION.\\n EVALUATE TRUE\\n WHEN CLOSED-ACCT MOVE 'CL' TO CATEGORY MOVE 'N' TO ACTION\\n WHEN FROZEN-ACCT MOVE 'FR' TO CATEGORY MOVE 'H' TO ACTION\\n WHEN DAYS-PAST-DUE >= 090 MOVE 'DL' TO CATEGORY MOVE 'C' TO ACTION\\n WHEN BALANCE < 0 MOVE 'OD' TO CATEGORY MOVE 'R' TO ACTION\\n WHEN OTHER MOVE 'OK' TO CATEGORY MOVE 'N' TO ACTION\\n END-EVALUATE\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"ACCOUNT_REC.cpy\": \" 01 ACCOUNT-RECORD.\\n 05 ACCOUNT-ID PIC X(6).\\n 05 STATUS-CODE PIC X.\\n 88 ACTIVE-ACCT VALUE 'A'.\\n 88 FROZEN-ACCT VALUE 'F'.\\n 88 CLOSED-ACCT VALUE 'C'.\\n 05 BALANCE PIC S9(6)V99 SIGN LEADING SEPARATE.\\n 05 DAYS-PAST-DUE PIC 9(3).\\n\"\n}\n\nParsed layouts:\n{\n \"ACCOUNT_REC.cpy\": {\n \"ok\": true,\n \"filename\": \"ACCOUNT_REC.cpy\",\n \"record_name\": \"ACCOUNT-RECORD\",\n \"total_width\": 19,\n \"fields\": [\n {\n \"name\": \"ACCOUNT-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"STATUS-CODE\",\n \"start\": 6,\n \"end\": 7,\n \"length\": 1,\n \"pic\": \"X\",\n \"python_type\": \"str\",\n \"level_88\": {\n \"ACTIVE-ACCT\": \"A\",\n \"FROZEN-ACCT\": \"F\",\n \"CLOSED-ACCT\": \"C\"\n }\n },\n {\n \"name\": \"BALANCE\",\n \"start\": 7,\n \"end\": 16,\n \"length\": 9,\n \"pic\": \"S9(6)V99 SIGN LEADING SEPARATE\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n },\n {\n \"name\": \"DAYS-PAST-DUE\",\n \"start\": 16,\n \"end\": 19,\n \"length\": 3,\n \"pic\": \"9(3)\",\n \"python_type\": \"int\"\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"CLOSED-ACCT and FROZEN-ACCT are level-88 names over STATUS-CODE.\",\n \"Closed and frozen branches precede delinquency and overdrawn checks.\"\n]",
|
| 760 |
+
"response": "{\"code\": \"def migrate(input_record: str) -> str:\\n account_id = input_record[0:6]\\n status = input_record[6:7]\\n raw_balance = input_record[7:16]\\n sign = -1 if raw_balance[0] == \\\"-\\\" else 1\\n balance_cents = sign * int(raw_balance[1:])\\n days = int(input_record[16:19])\\n if status == \\\"C\\\":\\n category, action = \\\"CL\\\", \\\"N\\\"\\n elif status == \\\"F\\\":\\n category, action = \\\"FR\\\", \\\"H\\\"\\n elif days >= 90:\\n category, action = \\\"DL\\\", \\\"C\\\"\\n elif balance_cents < 0:\\n category, action = \\\"OD\\\", \\\"R\\\"\\n else:\\n category, action = \\\"OK\\\", \\\"N\\\"\\n return f\\\"{account_id}{category}{action}\\\"\\n\"}",
|
| 761 |
+
"code_chars": 607
|
| 762 |
+
}
|
| 763 |
+
],
|
| 764 |
+
"visible": {
|
| 765 |
+
"passed": 3,
|
| 766 |
+
"total": 3,
|
| 767 |
+
"pass_rate": 1.0,
|
| 768 |
+
"failures": []
|
| 769 |
+
},
|
| 770 |
+
"final": {
|
| 771 |
+
"public_score": 1.0,
|
| 772 |
+
"accepted": true,
|
| 773 |
+
"components": {
|
| 774 |
+
"hidden_correctness": 1.0,
|
| 775 |
+
"fresh_correctness": 1.0,
|
| 776 |
+
"interface_contract": 1.0,
|
| 777 |
+
"type_and_layout_fidelity": 1.0,
|
| 778 |
+
"anti_hardcoding": 1.0,
|
| 779 |
+
"safety": 1.0
|
| 780 |
+
},
|
| 781 |
+
"hidden_passed": 3,
|
| 782 |
+
"hidden_total": 3,
|
| 783 |
+
"fresh_passed": 6,
|
| 784 |
+
"fresh_total": 6
|
| 785 |
+
},
|
| 786 |
+
"steps": [
|
| 787 |
+
{
|
| 788 |
+
"tool_name": "read_cobol_file",
|
| 789 |
+
"arguments": {
|
| 790 |
+
"filename": "ACCTSTAT.cbl"
|
| 791 |
+
},
|
| 792 |
+
"reward": 0.02,
|
| 793 |
+
"done": false,
|
| 794 |
+
"result": {
|
| 795 |
+
"ok": true,
|
| 796 |
+
"filename": "ACCTSTAT.cbl",
|
| 797 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. ACCTSTAT.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY ACCOUNT_REC.\n PROCEDURE DIVISION.\n EVALUATE TRUE\n WHEN CLOSED-ACCT MOVE 'CL' TO CATEGORY MOVE 'N' TO ACTION\n WHEN FROZEN-ACCT MOVE 'FR' TO CATEGORY MOVE 'H' TO ACTION\n WHEN DAYS-PAST-DUE >= 090 MOVE 'DL' TO CATEGORY MOVE 'C' TO ACTION\n WHEN BALANCE < 0 MOVE 'OD' TO CATEGORY MOVE 'R' TO ACTION\n WHEN OTHER MOVE 'OK' TO CATEGORY MOVE 'N' TO ACTION\n END-EVALUATE\n GOBACK.\n",
|
| 798 |
+
"truncated": false
|
| 799 |
+
}
|
| 800 |
+
},
|
| 801 |
+
{
|
| 802 |
+
"tool_name": "read_copybook",
|
| 803 |
+
"arguments": {
|
| 804 |
+
"filename": "ACCOUNT_REC.cpy"
|
| 805 |
+
},
|
| 806 |
+
"reward": 0.02,
|
| 807 |
+
"done": false,
|
| 808 |
+
"result": {
|
| 809 |
+
"ok": true,
|
| 810 |
+
"filename": "ACCOUNT_REC.cpy",
|
| 811 |
+
"content": " 01 ACCOUNT-RECORD.\n 05 ACCOUNT-ID PIC X(6).\n 05 STATUS-CODE PIC X.\n 88 ACTIVE-ACCT VALUE 'A'.\n 88 FROZEN-ACCT VALUE 'F'.\n 88 CLOSED-ACCT VALUE 'C'.\n 05 BALANCE PIC S9(6)V99 SIGN LEADING SEPARATE.\n 05 DAYS-PAST-DUE PIC 9(3).\n"
|
| 812 |
+
}
|
| 813 |
+
},
|
| 814 |
+
{
|
| 815 |
+
"tool_name": "parse_copybook_layout",
|
| 816 |
+
"arguments": {
|
| 817 |
+
"filename": "ACCOUNT_REC.cpy"
|
| 818 |
+
},
|
| 819 |
+
"reward": 0.03,
|
| 820 |
+
"done": false,
|
| 821 |
+
"result": {
|
| 822 |
+
"ok": true,
|
| 823 |
+
"filename": "ACCOUNT_REC.cpy",
|
| 824 |
+
"record_name": "ACCOUNT-RECORD",
|
| 825 |
+
"total_width": 19,
|
| 826 |
+
"fields": [
|
| 827 |
+
{
|
| 828 |
+
"name": "ACCOUNT-ID",
|
| 829 |
+
"start": 0,
|
| 830 |
+
"end": 6,
|
| 831 |
+
"length": 6,
|
| 832 |
+
"pic": "X(6)",
|
| 833 |
+
"python_type": "str"
|
| 834 |
+
},
|
| 835 |
+
{
|
| 836 |
+
"name": "STATUS-CODE",
|
| 837 |
+
"start": 6,
|
| 838 |
+
"end": 7,
|
| 839 |
+
"length": 1,
|
| 840 |
+
"pic": "X",
|
| 841 |
+
"python_type": "str",
|
| 842 |
+
"level_88": {
|
| 843 |
+
"ACTIVE-ACCT": "A",
|
| 844 |
+
"FROZEN-ACCT": "F",
|
| 845 |
+
"CLOSED-ACCT": "C"
|
| 846 |
+
}
|
| 847 |
+
},
|
| 848 |
+
{
|
| 849 |
+
"name": "BALANCE",
|
| 850 |
+
"start": 7,
|
| 851 |
+
"end": 16,
|
| 852 |
+
"length": 9,
|
| 853 |
+
"pic": "S9(6)V99 SIGN LEADING SEPARATE",
|
| 854 |
+
"python_type": "Decimal",
|
| 855 |
+
"scale": 2
|
| 856 |
+
},
|
| 857 |
+
{
|
| 858 |
+
"name": "DAYS-PAST-DUE",
|
| 859 |
+
"start": 16,
|
| 860 |
+
"end": 19,
|
| 861 |
+
"length": 3,
|
| 862 |
+
"pic": "9(3)",
|
| 863 |
+
"python_type": "int"
|
| 864 |
+
}
|
| 865 |
+
]
|
| 866 |
+
}
|
| 867 |
+
},
|
| 868 |
+
{
|
| 869 |
+
"tool_name": "inspect_business_rules",
|
| 870 |
+
"arguments": {},
|
| 871 |
+
"reward": 0.01,
|
| 872 |
+
"done": false,
|
| 873 |
+
"result": {
|
| 874 |
+
"ok": true,
|
| 875 |
+
"rules": [
|
| 876 |
+
"CLOSED-ACCT and FROZEN-ACCT are level-88 names over STATUS-CODE.",
|
| 877 |
+
"Closed and frozen branches precede delinquency and overdrawn checks."
|
| 878 |
+
]
|
| 879 |
+
}
|
| 880 |
+
},
|
| 881 |
+
{
|
| 882 |
+
"tool_name": "write_python_solution",
|
| 883 |
+
"arguments": {
|
| 884 |
+
"code_chars": 607
|
| 885 |
+
},
|
| 886 |
+
"reward": 0.02,
|
| 887 |
+
"done": false,
|
| 888 |
+
"result": {
|
| 889 |
+
"ok": true,
|
| 890 |
+
"draft_id": 1,
|
| 891 |
+
"syntax_ok": true,
|
| 892 |
+
"safety_ok": true,
|
| 893 |
+
"error": null
|
| 894 |
+
}
|
| 895 |
+
},
|
| 896 |
+
{
|
| 897 |
+
"tool_name": "run_visible_tests",
|
| 898 |
+
"arguments": {
|
| 899 |
+
"draft_id": 1
|
| 900 |
+
},
|
| 901 |
+
"reward": 0.05,
|
| 902 |
+
"done": false,
|
| 903 |
+
"result": {
|
| 904 |
+
"ok": true,
|
| 905 |
+
"draft_id": 1,
|
| 906 |
+
"passed": 3,
|
| 907 |
+
"total": 3,
|
| 908 |
+
"pass_rate": 1.0,
|
| 909 |
+
"syntax_ok": true,
|
| 910 |
+
"safety_ok": true,
|
| 911 |
+
"interface_ok": true,
|
| 912 |
+
"timed_out": false,
|
| 913 |
+
"error": null,
|
| 914 |
+
"failures": []
|
| 915 |
+
}
|
| 916 |
+
},
|
| 917 |
+
{
|
| 918 |
+
"tool_name": "submit_final",
|
| 919 |
+
"arguments": {
|
| 920 |
+
"draft_id": 1
|
| 921 |
+
},
|
| 922 |
+
"reward": 1.0,
|
| 923 |
+
"done": true,
|
| 924 |
+
"result": {
|
| 925 |
+
"ok": true,
|
| 926 |
+
"accepted": true,
|
| 927 |
+
"episode_done": true,
|
| 928 |
+
"public_score": 1.0,
|
| 929 |
+
"components": {
|
| 930 |
+
"hidden_correctness": 1.0,
|
| 931 |
+
"fresh_correctness": 1.0,
|
| 932 |
+
"interface_contract": 1.0,
|
| 933 |
+
"type_and_layout_fidelity": 1.0,
|
| 934 |
+
"anti_hardcoding": 1.0,
|
| 935 |
+
"safety": 1.0
|
| 936 |
+
},
|
| 937 |
+
"hidden_passed": 3,
|
| 938 |
+
"hidden_total": 3,
|
| 939 |
+
"fresh_passed": 6,
|
| 940 |
+
"fresh_total": 6,
|
| 941 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 942 |
+
}
|
| 943 |
+
}
|
| 944 |
+
]
|
| 945 |
+
},
|
| 946 |
+
{
|
| 947 |
+
"policy": "oracle-model",
|
| 948 |
+
"task_id": "invoice_occurs_001",
|
| 949 |
+
"family_id": "invoice_occurs_totals",
|
| 950 |
+
"ticket": {
|
| 951 |
+
"task_id": "invoice_occurs_001",
|
| 952 |
+
"family_id": "invoice_occurs_totals",
|
| 953 |
+
"domain": "invoicing",
|
| 954 |
+
"ticket": "Migrate INVTOTAL.cbl and TAXRATE.cbl. Preserve OCCURS stride parsing, item-count bounds, tax-code lookup behavior, and fixed-width total output.",
|
| 955 |
+
"available_files": [
|
| 956 |
+
"INVTOTAL.cbl",
|
| 957 |
+
"TAXRATE.cbl"
|
| 958 |
+
],
|
| 959 |
+
"available_copybooks": [
|
| 960 |
+
"INVOICE_REC.cpy",
|
| 961 |
+
"TAX_CODE.cpy"
|
| 962 |
+
],
|
| 963 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 964 |
+
"visible_tests": 3,
|
| 965 |
+
"hidden_tests": 4,
|
| 966 |
+
"input_width": 44,
|
| 967 |
+
"output_width": 18,
|
| 968 |
+
"max_steps": 12,
|
| 969 |
+
"allowed_tools": [
|
| 970 |
+
"read_cobol_file",
|
| 971 |
+
"read_copybook",
|
| 972 |
+
"parse_copybook_layout",
|
| 973 |
+
"inspect_business_rules",
|
| 974 |
+
"write_python_solution",
|
| 975 |
+
"run_visible_tests",
|
| 976 |
+
"inspect_diff",
|
| 977 |
+
"submit_final"
|
| 978 |
+
]
|
| 979 |
+
},
|
| 980 |
+
"model_turns": [
|
| 981 |
+
{
|
| 982 |
+
"provider": "oracle-model",
|
| 983 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"invoice_occurs_001\",\n \"family_id\": \"invoice_occurs_totals\",\n \"domain\": \"invoicing\",\n \"ticket\": \"Migrate INVTOTAL.cbl and TAXRATE.cbl. Preserve OCCURS stride parsing, item-count bounds, tax-code lookup behavior, and fixed-width total output.\",\n \"available_files\": [\n \"INVTOTAL.cbl\",\n \"TAXRATE.cbl\"\n ],\n \"available_copybooks\": [\n \"INVOICE_REC.cpy\",\n \"TAX_CODE.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 4,\n \"input_width\": 44,\n \"output_width\": 18,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"INVTOTAL.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. INVTOTAL.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY INVOICE_REC.\\n COPY TAX_CODE.\\n 01 IDX PIC 9 VALUE 0.\\n 01 LINE-AMOUNT PIC 9(7)V99 VALUE 0.\\n 01 TAX-AMOUNT PIC 9(7)V99 VALUE 0.\\n 01 TAX-PERCENT PIC 9V9999 VALUE 0.\\n 01 INVOICE-TOTAL PIC 9(7)V99 VALUE 0.\\n PROCEDURE DIVISION.\\n PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > ITEM-COUNT\\n COMPUTE LINE-AMOUNT ROUNDED = ITEM-QTY(IDX) * ITEM-PRICE(IDX)\\n CALL 'TAXRATE' USING TAX-CODE(IDX) TAX-PERCENT\\n COMPUTE TAX-AMOUNT ROUNDED = LINE-AMOUNT * TAX-PERCENT\\n ADD TAX-AMOUNT TO LINE-AMOUNT\\n ADD LINE-AMOUNT TO INVOICE-TOTAL\\n END-PERFORM\\n GOBACK.\\n\",\n \"TAXRATE.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. TAXRATE.\\n DATA DIVISION.\\n LINKAGE SECTION.\\n 01 LK-TAX-CODE PIC X.\\n 01 LK-TAX-PERCENT PIC 9V9999.\\n PROCEDURE DIVISION USING LK-TAX-CODE LK-TAX-PERCENT.\\n EVALUATE LK-TAX-CODE\\n WHEN 'S' MOVE 0.0725 TO LK-TAX-PERCENT\\n WHEN 'R' MOVE 0.0250 TO LK-TAX-PERCENT\\n WHEN 'L' MOVE 0.1000 TO LK-TAX-PERCENT\\n WHEN OTHER MOVE 0.0000 TO LK-TAX-PERCENT\\n END-EVALUATE\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"INVOICE_REC.cpy\": \" 01 INVOICE-RECORD.\\n 05 INVOICE-ID PIC X(6).\\n 05 ITEM-COUNT PIC 9(2).\\n 05 LINE-ITEM OCCURS 4 TIMES.\\n 10 ITEM-QTY PIC 9(2).\\n 10 ITEM-PRICE PIC 9(4)V99.\\n 10 TAX-CODE PIC X.\\n\",\n \"TAX_CODE.cpy\": \" 01 TAX-CODE-TABLE.\\n 05 TAX-CODE-ENTRY OCCURS 4 TIMES.\\n 10 TAX-CODE-KEY PIC X.\\n 10 TAX-RATE PIC 9V9999.\\n\"\n}\n\nParsed layouts:\n{\n \"INVOICE_REC.cpy\": {\n \"ok\": true,\n \"filename\": \"INVOICE_REC.cpy\",\n \"record_name\": \"INVOICE-RECORD\",\n \"total_width\": 44,\n \"fields\": [\n {\n \"name\": \"INVOICE-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"ITEM-COUNT\",\n \"start\": 6,\n \"end\": 8,\n \"length\": 2,\n \"pic\": \"9(2)\",\n \"python_type\": \"int\"\n },\n {\n \"name\": \"LINE-ITEMS\",\n \"start\": 8,\n \"end\": 44,\n \"length\": 36,\n \"pic\": \"OCCURS 4 TIMES\",\n \"python_type\": \"group\",\n \"occurs\": 4,\n \"stride\": 9\n }\n ]\n },\n \"TAX_CODE.cpy\": {\n \"ok\": true,\n \"filename\": \"TAX_CODE.cpy\",\n \"record_name\": \"INVOICE-RECORD\",\n \"total_width\": 44,\n \"fields\": [\n {\n \"name\": \"INVOICE-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"ITEM-COUNT\",\n \"start\": 6,\n \"end\": 8,\n \"length\": 2,\n \"pic\": \"9(2)\",\n \"python_type\": \"int\"\n },\n {\n \"name\": \"LINE-ITEMS\",\n \"start\": 8,\n \"end\": 44,\n \"length\": 36,\n \"pic\": \"OCCURS 4 TIMES\",\n \"python_type\": \"group\",\n \"occurs\": 4,\n \"stride\": 9\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"LINE-ITEM OCCURS 4 TIMES with a 9-byte stride.\",\n \"Only the first ITEM-COUNT entries contribute to the total.\",\n \"Tax codes are resolved through the separate TAXRATE program; handle all code branches found there.\",\n \"Keep the total, item count, and high/low flag in the fixed-width output layout.\"\n]",
|
| 984 |
+
"response": "{\"code\": \"from decimal import Decimal, ROUND_HALF_UP\\n\\n\\ndef migrate(input_record: str) -> str:\\n invoice_id = input_record[0:6]\\n count = min(int(input_record[6:8]), 4)\\n tax_rates = {\\n \\\"S\\\": Decimal(\\\"0.0725\\\"),\\n \\\"R\\\": Decimal(\\\"0.0250\\\"),\\n \\\"L\\\": Decimal(\\\"0.1000\\\"),\\n }\\n total = Decimal(\\\"0.00\\\")\\n for idx in range(count):\\n start = 8 + idx * 9\\n qty = int(input_record[start:start + 2])\\n price = Decimal(int(input_record[start + 2:start + 8])) / Decimal(\\\"100\\\")\\n tax_code = input_record[start + 8:start + 9]\\n line = (Decimal(qty) * price).quantize(Decimal(\\\"0.01\\\"), rounding=ROUND_HALF_UP)\\n tax = (line * tax_rates.get(tax_code, Decimal(\\\"0.0000\\\"))).quantize(Decimal(\\\"0.01\\\"), rounding=ROUND_HALF_UP)\\n line += tax\\n total += line\\n cents = int((total * 100).quantize(Decimal(\\\"1\\\"), rounding=ROUND_HALF_UP))\\n flag = \\\"H\\\" if total >= Decimal(\\\"1000.00\\\") else \\\"L\\\"\\n return f\\\"{invoice_id}{cents:09d}{count:02d}{flag}\\\"\\n\"}",
|
| 985 |
+
"code_chars": 984
|
| 986 |
+
}
|
| 987 |
+
],
|
| 988 |
+
"visible": {
|
| 989 |
+
"passed": 3,
|
| 990 |
+
"total": 3,
|
| 991 |
+
"pass_rate": 1.0,
|
| 992 |
+
"failures": []
|
| 993 |
+
},
|
| 994 |
+
"final": {
|
| 995 |
+
"public_score": 1.0,
|
| 996 |
+
"accepted": true,
|
| 997 |
+
"components": {
|
| 998 |
+
"hidden_correctness": 1.0,
|
| 999 |
+
"fresh_correctness": 1.0,
|
| 1000 |
+
"interface_contract": 1.0,
|
| 1001 |
+
"type_and_layout_fidelity": 1.0,
|
| 1002 |
+
"anti_hardcoding": 1.0,
|
| 1003 |
+
"safety": 1.0
|
| 1004 |
+
},
|
| 1005 |
+
"hidden_passed": 4,
|
| 1006 |
+
"hidden_total": 4,
|
| 1007 |
+
"fresh_passed": 6,
|
| 1008 |
+
"fresh_total": 6
|
| 1009 |
+
},
|
| 1010 |
+
"steps": [
|
| 1011 |
+
{
|
| 1012 |
+
"tool_name": "read_cobol_file",
|
| 1013 |
+
"arguments": {
|
| 1014 |
+
"filename": "INVTOTAL.cbl"
|
| 1015 |
+
},
|
| 1016 |
+
"reward": 0.02,
|
| 1017 |
+
"done": false,
|
| 1018 |
+
"result": {
|
| 1019 |
+
"ok": true,
|
| 1020 |
+
"filename": "INVTOTAL.cbl",
|
| 1021 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. INVTOTAL.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY INVOICE_REC.\n COPY TAX_CODE.\n 01 IDX PIC 9 VALUE 0.\n 01 LINE-AMOUNT PIC 9(7)V99 VALUE 0.\n 01 TAX-AMOUNT PIC 9(7)V99 VALUE 0.\n 01 TAX-PERCENT PIC 9V9999 VALUE 0.\n 01 INVOICE-TOTAL PIC 9(7)V99 VALUE 0.\n PROCEDURE DIVISION.\n PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > ITEM-COUNT\n COMPUTE LINE-AMOUNT ROUNDED = ITEM-QTY(IDX) * ITEM-PRICE(IDX)\n CALL 'TAXRATE' USING TAX-CODE(IDX) TAX-PERCENT\n COMPUTE TAX-AMOUNT ROUNDED = LINE-AMOUNT * TAX-PERCENT\n ADD TAX-AMOUNT TO LINE-AMOUNT\n ADD LINE-AMOUNT TO INVOICE-TOTAL\n END-PERFORM\n GOBACK.\n",
|
| 1022 |
+
"truncated": false
|
| 1023 |
+
}
|
| 1024 |
+
},
|
| 1025 |
+
{
|
| 1026 |
+
"tool_name": "read_cobol_file",
|
| 1027 |
+
"arguments": {
|
| 1028 |
+
"filename": "TAXRATE.cbl"
|
| 1029 |
+
},
|
| 1030 |
+
"reward": 0.02,
|
| 1031 |
+
"done": false,
|
| 1032 |
+
"result": {
|
| 1033 |
+
"ok": true,
|
| 1034 |
+
"filename": "TAXRATE.cbl",
|
| 1035 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. TAXRATE.\n DATA DIVISION.\n LINKAGE SECTION.\n 01 LK-TAX-CODE PIC X.\n 01 LK-TAX-PERCENT PIC 9V9999.\n PROCEDURE DIVISION USING LK-TAX-CODE LK-TAX-PERCENT.\n EVALUATE LK-TAX-CODE\n WHEN 'S' MOVE 0.0725 TO LK-TAX-PERCENT\n WHEN 'R' MOVE 0.0250 TO LK-TAX-PERCENT\n WHEN 'L' MOVE 0.1000 TO LK-TAX-PERCENT\n WHEN OTHER MOVE 0.0000 TO LK-TAX-PERCENT\n END-EVALUATE\n GOBACK.\n",
|
| 1036 |
+
"truncated": false
|
| 1037 |
+
}
|
| 1038 |
+
},
|
| 1039 |
+
{
|
| 1040 |
+
"tool_name": "read_copybook",
|
| 1041 |
+
"arguments": {
|
| 1042 |
+
"filename": "INVOICE_REC.cpy"
|
| 1043 |
+
},
|
| 1044 |
+
"reward": 0.02,
|
| 1045 |
+
"done": false,
|
| 1046 |
+
"result": {
|
| 1047 |
+
"ok": true,
|
| 1048 |
+
"filename": "INVOICE_REC.cpy",
|
| 1049 |
+
"content": " 01 INVOICE-RECORD.\n 05 INVOICE-ID PIC X(6).\n 05 ITEM-COUNT PIC 9(2).\n 05 LINE-ITEM OCCURS 4 TIMES.\n 10 ITEM-QTY PIC 9(2).\n 10 ITEM-PRICE PIC 9(4)V99.\n 10 TAX-CODE PIC X.\n"
|
| 1050 |
+
}
|
| 1051 |
+
},
|
| 1052 |
+
{
|
| 1053 |
+
"tool_name": "parse_copybook_layout",
|
| 1054 |
+
"arguments": {
|
| 1055 |
+
"filename": "INVOICE_REC.cpy"
|
| 1056 |
+
},
|
| 1057 |
+
"reward": 0.03,
|
| 1058 |
+
"done": false,
|
| 1059 |
+
"result": {
|
| 1060 |
+
"ok": true,
|
| 1061 |
+
"filename": "INVOICE_REC.cpy",
|
| 1062 |
+
"record_name": "INVOICE-RECORD",
|
| 1063 |
+
"total_width": 44,
|
| 1064 |
+
"fields": [
|
| 1065 |
+
{
|
| 1066 |
+
"name": "INVOICE-ID",
|
| 1067 |
+
"start": 0,
|
| 1068 |
+
"end": 6,
|
| 1069 |
+
"length": 6,
|
| 1070 |
+
"pic": "X(6)",
|
| 1071 |
+
"python_type": "str"
|
| 1072 |
+
},
|
| 1073 |
+
{
|
| 1074 |
+
"name": "ITEM-COUNT",
|
| 1075 |
+
"start": 6,
|
| 1076 |
+
"end": 8,
|
| 1077 |
+
"length": 2,
|
| 1078 |
+
"pic": "9(2)",
|
| 1079 |
+
"python_type": "int"
|
| 1080 |
+
},
|
| 1081 |
+
{
|
| 1082 |
+
"name": "LINE-ITEMS",
|
| 1083 |
+
"start": 8,
|
| 1084 |
+
"end": 44,
|
| 1085 |
+
"length": 36,
|
| 1086 |
+
"pic": "OCCURS 4 TIMES",
|
| 1087 |
+
"python_type": "group",
|
| 1088 |
+
"occurs": 4,
|
| 1089 |
+
"stride": 9
|
| 1090 |
+
}
|
| 1091 |
+
]
|
| 1092 |
+
}
|
| 1093 |
+
},
|
| 1094 |
+
{
|
| 1095 |
+
"tool_name": "read_copybook",
|
| 1096 |
+
"arguments": {
|
| 1097 |
+
"filename": "TAX_CODE.cpy"
|
| 1098 |
+
},
|
| 1099 |
+
"reward": 0.02,
|
| 1100 |
+
"done": false,
|
| 1101 |
+
"result": {
|
| 1102 |
+
"ok": true,
|
| 1103 |
+
"filename": "TAX_CODE.cpy",
|
| 1104 |
+
"content": " 01 TAX-CODE-TABLE.\n 05 TAX-CODE-ENTRY OCCURS 4 TIMES.\n 10 TAX-CODE-KEY PIC X.\n 10 TAX-RATE PIC 9V9999.\n"
|
| 1105 |
+
}
|
| 1106 |
+
},
|
| 1107 |
+
{
|
| 1108 |
+
"tool_name": "parse_copybook_layout",
|
| 1109 |
+
"arguments": {
|
| 1110 |
+
"filename": "TAX_CODE.cpy"
|
| 1111 |
+
},
|
| 1112 |
+
"reward": 0.03,
|
| 1113 |
+
"done": false,
|
| 1114 |
+
"result": {
|
| 1115 |
+
"ok": true,
|
| 1116 |
+
"filename": "TAX_CODE.cpy",
|
| 1117 |
+
"record_name": "INVOICE-RECORD",
|
| 1118 |
+
"total_width": 44,
|
| 1119 |
+
"fields": [
|
| 1120 |
+
{
|
| 1121 |
+
"name": "INVOICE-ID",
|
| 1122 |
+
"start": 0,
|
| 1123 |
+
"end": 6,
|
| 1124 |
+
"length": 6,
|
| 1125 |
+
"pic": "X(6)",
|
| 1126 |
+
"python_type": "str"
|
| 1127 |
+
},
|
| 1128 |
+
{
|
| 1129 |
+
"name": "ITEM-COUNT",
|
| 1130 |
+
"start": 6,
|
| 1131 |
+
"end": 8,
|
| 1132 |
+
"length": 2,
|
| 1133 |
+
"pic": "9(2)",
|
| 1134 |
+
"python_type": "int"
|
| 1135 |
+
},
|
| 1136 |
+
{
|
| 1137 |
+
"name": "LINE-ITEMS",
|
| 1138 |
+
"start": 8,
|
| 1139 |
+
"end": 44,
|
| 1140 |
+
"length": 36,
|
| 1141 |
+
"pic": "OCCURS 4 TIMES",
|
| 1142 |
+
"python_type": "group",
|
| 1143 |
+
"occurs": 4,
|
| 1144 |
+
"stride": 9
|
| 1145 |
+
}
|
| 1146 |
+
]
|
| 1147 |
+
}
|
| 1148 |
+
},
|
| 1149 |
+
{
|
| 1150 |
+
"tool_name": "inspect_business_rules",
|
| 1151 |
+
"arguments": {},
|
| 1152 |
+
"reward": 0.01,
|
| 1153 |
+
"done": false,
|
| 1154 |
+
"result": {
|
| 1155 |
+
"ok": true,
|
| 1156 |
+
"rules": [
|
| 1157 |
+
"LINE-ITEM OCCURS 4 TIMES with a 9-byte stride.",
|
| 1158 |
+
"Only the first ITEM-COUNT entries contribute to the total.",
|
| 1159 |
+
"Tax codes are resolved through the separate TAXRATE program; handle all code branches found there.",
|
| 1160 |
+
"Keep the total, item count, and high/low flag in the fixed-width output layout."
|
| 1161 |
+
]
|
| 1162 |
+
}
|
| 1163 |
+
},
|
| 1164 |
+
{
|
| 1165 |
+
"tool_name": "write_python_solution",
|
| 1166 |
+
"arguments": {
|
| 1167 |
+
"code_chars": 984
|
| 1168 |
+
},
|
| 1169 |
+
"reward": 0.02,
|
| 1170 |
+
"done": false,
|
| 1171 |
+
"result": {
|
| 1172 |
+
"ok": true,
|
| 1173 |
+
"draft_id": 1,
|
| 1174 |
+
"syntax_ok": true,
|
| 1175 |
+
"safety_ok": true,
|
| 1176 |
+
"error": null
|
| 1177 |
+
}
|
| 1178 |
+
},
|
| 1179 |
+
{
|
| 1180 |
+
"tool_name": "run_visible_tests",
|
| 1181 |
+
"arguments": {
|
| 1182 |
+
"draft_id": 1
|
| 1183 |
+
},
|
| 1184 |
+
"reward": 0.05,
|
| 1185 |
+
"done": false,
|
| 1186 |
+
"result": {
|
| 1187 |
+
"ok": true,
|
| 1188 |
+
"draft_id": 1,
|
| 1189 |
+
"passed": 3,
|
| 1190 |
+
"total": 3,
|
| 1191 |
+
"pass_rate": 1.0,
|
| 1192 |
+
"syntax_ok": true,
|
| 1193 |
+
"safety_ok": true,
|
| 1194 |
+
"interface_ok": true,
|
| 1195 |
+
"timed_out": false,
|
| 1196 |
+
"error": null,
|
| 1197 |
+
"failures": []
|
| 1198 |
+
}
|
| 1199 |
+
},
|
| 1200 |
+
{
|
| 1201 |
+
"tool_name": "submit_final",
|
| 1202 |
+
"arguments": {
|
| 1203 |
+
"draft_id": 1
|
| 1204 |
+
},
|
| 1205 |
+
"reward": 1.0,
|
| 1206 |
+
"done": true,
|
| 1207 |
+
"result": {
|
| 1208 |
+
"ok": true,
|
| 1209 |
+
"accepted": true,
|
| 1210 |
+
"episode_done": true,
|
| 1211 |
+
"public_score": 1.0,
|
| 1212 |
+
"components": {
|
| 1213 |
+
"hidden_correctness": 1.0,
|
| 1214 |
+
"fresh_correctness": 1.0,
|
| 1215 |
+
"interface_contract": 1.0,
|
| 1216 |
+
"type_and_layout_fidelity": 1.0,
|
| 1217 |
+
"anti_hardcoding": 1.0,
|
| 1218 |
+
"safety": 1.0
|
| 1219 |
+
},
|
| 1220 |
+
"hidden_passed": 4,
|
| 1221 |
+
"hidden_total": 4,
|
| 1222 |
+
"fresh_passed": 6,
|
| 1223 |
+
"fresh_total": 6,
|
| 1224 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 1225 |
+
}
|
| 1226 |
+
}
|
| 1227 |
+
]
|
| 1228 |
+
},
|
| 1229 |
+
{
|
| 1230 |
+
"policy": "oracle-model",
|
| 1231 |
+
"task_id": "date_normalization_001",
|
| 1232 |
+
"family_id": "date_normalization",
|
| 1233 |
+
"ticket": {
|
| 1234 |
+
"task_id": "date_normalization_001",
|
| 1235 |
+
"family_id": "date_normalization",
|
| 1236 |
+
"domain": "claims and billing",
|
| 1237 |
+
"ticket": "Migrate DATENORM.cbl. Preserve legacy YYMMDD century-window rules and invalid-date behavior instead of blindly using modern date parsing.",
|
| 1238 |
+
"available_files": [
|
| 1239 |
+
"DATENORM.cbl"
|
| 1240 |
+
],
|
| 1241 |
+
"available_copybooks": [
|
| 1242 |
+
"POLICY_DATE.cpy"
|
| 1243 |
+
],
|
| 1244 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 1245 |
+
"visible_tests": 3,
|
| 1246 |
+
"hidden_tests": 3,
|
| 1247 |
+
"input_width": 21,
|
| 1248 |
+
"output_width": 22,
|
| 1249 |
+
"max_steps": 12,
|
| 1250 |
+
"allowed_tools": [
|
| 1251 |
+
"read_cobol_file",
|
| 1252 |
+
"read_copybook",
|
| 1253 |
+
"parse_copybook_layout",
|
| 1254 |
+
"inspect_business_rules",
|
| 1255 |
+
"write_python_solution",
|
| 1256 |
+
"run_visible_tests",
|
| 1257 |
+
"inspect_diff",
|
| 1258 |
+
"submit_final"
|
| 1259 |
+
]
|
| 1260 |
+
},
|
| 1261 |
+
"model_turns": [
|
| 1262 |
+
{
|
| 1263 |
+
"provider": "oracle-model",
|
| 1264 |
+
"prompt": "You are migrating a legacy COBOL routine into Python.\n\nReturn only JSON in this shape: {\"code\": \"...python source...\"}.\n\nThe Python source must define migrate(input_record: str) -> str.\n\nTicket:\n{\n \"task_id\": \"date_normalization_001\",\n \"family_id\": \"date_normalization\",\n \"domain\": \"claims and billing\",\n \"ticket\": \"Migrate DATENORM.cbl. Preserve legacy YYMMDD century-window rules and invalid-date behavior instead of blindly using modern date parsing.\",\n \"available_files\": [\n \"DATENORM.cbl\"\n ],\n \"available_copybooks\": [\n \"POLICY_DATE.cpy\"\n ],\n \"expected_callable\": \"migrate(input_record: str) -> str\",\n \"visible_tests\": 3,\n \"hidden_tests\": 3,\n \"input_width\": 21,\n \"output_width\": 22,\n \"max_steps\": 12,\n \"allowed_tools\": [\n \"read_cobol_file\",\n \"read_copybook\",\n \"parse_copybook_layout\",\n \"inspect_business_rules\",\n \"write_python_solution\",\n \"run_visible_tests\",\n \"inspect_diff\",\n \"submit_final\"\n ]\n}\n\nCOBOL files:\n{\n \"DATENORM.cbl\": \" IDENTIFICATION DIVISION.\\n PROGRAM-ID. DATENORM.\\n DATA DIVISION.\\n WORKING-STORAGE SECTION.\\n COPY POLICY_DATE.\\n PROCEDURE DIVISION.\\n IF RAW-YY >= WINDOW-YEAR\\n MOVE 19 TO OUT-CENTURY\\n ELSE\\n MOVE 20 TO OUT-CENTURY\\n END-IF\\n PERFORM VALIDATE-MONTH-DAY\\n GOBACK.\\n\"\n}\n\nCopybooks:\n{\n \"POLICY_DATE.cpy\": \" 01 POLICY-DATE-RECORD.\\n 05 POLICY-ID PIC X(6).\\n 05 RAW-DATE PIC 9(6).\\n 05 WINDOW-YEAR PIC 9(2).\\n 05 AMOUNT PIC 9(5)V99.\\n\"\n}\n\nParsed layouts:\n{\n \"POLICY_DATE.cpy\": {\n \"ok\": true,\n \"filename\": \"POLICY_DATE.cpy\",\n \"record_name\": \"POLICY-DATE-RECORD\",\n \"total_width\": 21,\n \"fields\": [\n {\n \"name\": \"POLICY-ID\",\n \"start\": 0,\n \"end\": 6,\n \"length\": 6,\n \"pic\": \"X(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"RAW-DATE\",\n \"start\": 6,\n \"end\": 12,\n \"length\": 6,\n \"pic\": \"9(6)\",\n \"python_type\": \"str\"\n },\n {\n \"name\": \"WINDOW-YEAR\",\n \"start\": 12,\n \"end\": 14,\n \"length\": 2,\n \"pic\": \"9(2)\",\n \"python_type\": \"int\"\n },\n {\n \"name\": \"AMOUNT\",\n \"start\": 14,\n \"end\": 21,\n \"length\": 7,\n \"pic\": \"9(5)V99\",\n \"python_type\": \"Decimal\",\n \"scale\": 2\n }\n ]\n }\n}\n\nBusiness rules:\n[\n \"RAW-DATE is YYMMDD.\",\n \"If YY >= WINDOW-YEAR, century is 19; otherwise century is 20.\",\n \"Invalid dates output 00000000 and valid flag N; amount is preserved.\"\n]",
|
| 1265 |
+
"response": "{\"code\": \"def is_leap(year: int) -> bool:\\n return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)\\n\\n\\ndef valid_date(year: int, month: int, day: int) -> bool:\\n month_lengths = [31, 29 if is_leap(year) else 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\\n return 1 <= month <= 12 and 1 <= day <= month_lengths[month - 1]\\n\\n\\ndef migrate(input_record: str) -> str:\\n policy_id = input_record[0:6]\\n raw = input_record[6:12]\\n window = int(input_record[12:14])\\n amount = input_record[14:21]\\n yy = int(raw[0:2])\\n mm = int(raw[2:4])\\n dd = int(raw[4:6])\\n year = 1900 + yy if yy >= window else 2000 + yy\\n normalized = f\\\"{year:04d}{mm:02d}{dd:02d}\\\" if valid_date(year, mm, dd) else \\\"00000000\\\"\\n valid = \\\"Y\\\" if normalized != \\\"00000000\\\" else \\\"N\\\"\\n return f\\\"{policy_id}{normalized}{valid}{amount}\\\"\\n\"}",
|
| 1266 |
+
"code_chars": 813
|
| 1267 |
+
}
|
| 1268 |
+
],
|
| 1269 |
+
"visible": {
|
| 1270 |
+
"passed": 3,
|
| 1271 |
+
"total": 3,
|
| 1272 |
+
"pass_rate": 1.0,
|
| 1273 |
+
"failures": []
|
| 1274 |
+
},
|
| 1275 |
+
"final": {
|
| 1276 |
+
"public_score": 1.0,
|
| 1277 |
+
"accepted": true,
|
| 1278 |
+
"components": {
|
| 1279 |
+
"hidden_correctness": 1.0,
|
| 1280 |
+
"fresh_correctness": 1.0,
|
| 1281 |
+
"interface_contract": 1.0,
|
| 1282 |
+
"type_and_layout_fidelity": 1.0,
|
| 1283 |
+
"anti_hardcoding": 1.0,
|
| 1284 |
+
"safety": 1.0
|
| 1285 |
+
},
|
| 1286 |
+
"hidden_passed": 3,
|
| 1287 |
+
"hidden_total": 3,
|
| 1288 |
+
"fresh_passed": 6,
|
| 1289 |
+
"fresh_total": 6
|
| 1290 |
+
},
|
| 1291 |
+
"steps": [
|
| 1292 |
+
{
|
| 1293 |
+
"tool_name": "read_cobol_file",
|
| 1294 |
+
"arguments": {
|
| 1295 |
+
"filename": "DATENORM.cbl"
|
| 1296 |
+
},
|
| 1297 |
+
"reward": 0.02,
|
| 1298 |
+
"done": false,
|
| 1299 |
+
"result": {
|
| 1300 |
+
"ok": true,
|
| 1301 |
+
"filename": "DATENORM.cbl",
|
| 1302 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. DATENORM.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY POLICY_DATE.\n PROCEDURE DIVISION.\n IF RAW-YY >= WINDOW-YEAR\n MOVE 19 TO OUT-CENTURY\n ELSE\n MOVE 20 TO OUT-CENTURY\n END-IF\n PERFORM VALIDATE-MONTH-DAY\n GOBACK.\n",
|
| 1303 |
+
"truncated": false
|
| 1304 |
+
}
|
| 1305 |
+
},
|
| 1306 |
+
{
|
| 1307 |
+
"tool_name": "read_copybook",
|
| 1308 |
+
"arguments": {
|
| 1309 |
+
"filename": "POLICY_DATE.cpy"
|
| 1310 |
+
},
|
| 1311 |
+
"reward": 0.02,
|
| 1312 |
+
"done": false,
|
| 1313 |
+
"result": {
|
| 1314 |
+
"ok": true,
|
| 1315 |
+
"filename": "POLICY_DATE.cpy",
|
| 1316 |
+
"content": " 01 POLICY-DATE-RECORD.\n 05 POLICY-ID PIC X(6).\n 05 RAW-DATE PIC 9(6).\n 05 WINDOW-YEAR PIC 9(2).\n 05 AMOUNT PIC 9(5)V99.\n"
|
| 1317 |
+
}
|
| 1318 |
+
},
|
| 1319 |
+
{
|
| 1320 |
+
"tool_name": "parse_copybook_layout",
|
| 1321 |
+
"arguments": {
|
| 1322 |
+
"filename": "POLICY_DATE.cpy"
|
| 1323 |
+
},
|
| 1324 |
+
"reward": 0.03,
|
| 1325 |
+
"done": false,
|
| 1326 |
+
"result": {
|
| 1327 |
+
"ok": true,
|
| 1328 |
+
"filename": "POLICY_DATE.cpy",
|
| 1329 |
+
"record_name": "POLICY-DATE-RECORD",
|
| 1330 |
+
"total_width": 21,
|
| 1331 |
+
"fields": [
|
| 1332 |
+
{
|
| 1333 |
+
"name": "POLICY-ID",
|
| 1334 |
+
"start": 0,
|
| 1335 |
+
"end": 6,
|
| 1336 |
+
"length": 6,
|
| 1337 |
+
"pic": "X(6)",
|
| 1338 |
+
"python_type": "str"
|
| 1339 |
+
},
|
| 1340 |
+
{
|
| 1341 |
+
"name": "RAW-DATE",
|
| 1342 |
+
"start": 6,
|
| 1343 |
+
"end": 12,
|
| 1344 |
+
"length": 6,
|
| 1345 |
+
"pic": "9(6)",
|
| 1346 |
+
"python_type": "str"
|
| 1347 |
+
},
|
| 1348 |
+
{
|
| 1349 |
+
"name": "WINDOW-YEAR",
|
| 1350 |
+
"start": 12,
|
| 1351 |
+
"end": 14,
|
| 1352 |
+
"length": 2,
|
| 1353 |
+
"pic": "9(2)",
|
| 1354 |
+
"python_type": "int"
|
| 1355 |
+
},
|
| 1356 |
+
{
|
| 1357 |
+
"name": "AMOUNT",
|
| 1358 |
+
"start": 14,
|
| 1359 |
+
"end": 21,
|
| 1360 |
+
"length": 7,
|
| 1361 |
+
"pic": "9(5)V99",
|
| 1362 |
+
"python_type": "Decimal",
|
| 1363 |
+
"scale": 2
|
| 1364 |
+
}
|
| 1365 |
+
]
|
| 1366 |
+
}
|
| 1367 |
+
},
|
| 1368 |
+
{
|
| 1369 |
+
"tool_name": "inspect_business_rules",
|
| 1370 |
+
"arguments": {},
|
| 1371 |
+
"reward": 0.01,
|
| 1372 |
+
"done": false,
|
| 1373 |
+
"result": {
|
| 1374 |
+
"ok": true,
|
| 1375 |
+
"rules": [
|
| 1376 |
+
"RAW-DATE is YYMMDD.",
|
| 1377 |
+
"If YY >= WINDOW-YEAR, century is 19; otherwise century is 20.",
|
| 1378 |
+
"Invalid dates output 00000000 and valid flag N; amount is preserved."
|
| 1379 |
+
]
|
| 1380 |
+
}
|
| 1381 |
+
},
|
| 1382 |
+
{
|
| 1383 |
+
"tool_name": "write_python_solution",
|
| 1384 |
+
"arguments": {
|
| 1385 |
+
"code_chars": 813
|
| 1386 |
+
},
|
| 1387 |
+
"reward": 0.02,
|
| 1388 |
+
"done": false,
|
| 1389 |
+
"result": {
|
| 1390 |
+
"ok": true,
|
| 1391 |
+
"draft_id": 1,
|
| 1392 |
+
"syntax_ok": true,
|
| 1393 |
+
"safety_ok": true,
|
| 1394 |
+
"error": null
|
| 1395 |
+
}
|
| 1396 |
+
},
|
| 1397 |
+
{
|
| 1398 |
+
"tool_name": "run_visible_tests",
|
| 1399 |
+
"arguments": {
|
| 1400 |
+
"draft_id": 1
|
| 1401 |
+
},
|
| 1402 |
+
"reward": 0.05,
|
| 1403 |
+
"done": false,
|
| 1404 |
+
"result": {
|
| 1405 |
+
"ok": true,
|
| 1406 |
+
"draft_id": 1,
|
| 1407 |
+
"passed": 3,
|
| 1408 |
+
"total": 3,
|
| 1409 |
+
"pass_rate": 1.0,
|
| 1410 |
+
"syntax_ok": true,
|
| 1411 |
+
"safety_ok": true,
|
| 1412 |
+
"interface_ok": true,
|
| 1413 |
+
"timed_out": false,
|
| 1414 |
+
"error": null,
|
| 1415 |
+
"failures": []
|
| 1416 |
+
}
|
| 1417 |
+
},
|
| 1418 |
+
{
|
| 1419 |
+
"tool_name": "submit_final",
|
| 1420 |
+
"arguments": {
|
| 1421 |
+
"draft_id": 1
|
| 1422 |
+
},
|
| 1423 |
+
"reward": 1.0,
|
| 1424 |
+
"done": true,
|
| 1425 |
+
"result": {
|
| 1426 |
+
"ok": true,
|
| 1427 |
+
"accepted": true,
|
| 1428 |
+
"episode_done": true,
|
| 1429 |
+
"public_score": 1.0,
|
| 1430 |
+
"components": {
|
| 1431 |
+
"hidden_correctness": 1.0,
|
| 1432 |
+
"fresh_correctness": 1.0,
|
| 1433 |
+
"interface_contract": 1.0,
|
| 1434 |
+
"type_and_layout_fidelity": 1.0,
|
| 1435 |
+
"anti_hardcoding": 1.0,
|
| 1436 |
+
"safety": 1.0
|
| 1437 |
+
},
|
| 1438 |
+
"hidden_passed": 3,
|
| 1439 |
+
"hidden_total": 3,
|
| 1440 |
+
"fresh_passed": 6,
|
| 1441 |
+
"fresh_total": 6,
|
| 1442 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 1443 |
+
}
|
| 1444 |
+
}
|
| 1445 |
+
]
|
| 1446 |
+
}
|
| 1447 |
+
]
|
| 1448 |
+
}
|
outputs/evals/oracle_trajectories.json
ADDED
|
@@ -0,0 +1,1399 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"policy": "oracle",
|
| 3 |
+
"task_count": 6,
|
| 4 |
+
"mean_public_score": 1.0,
|
| 5 |
+
"accepted_count": 6,
|
| 6 |
+
"trajectories": [
|
| 7 |
+
{
|
| 8 |
+
"policy": "oracle",
|
| 9 |
+
"task_id": "payroll_net_pay_001",
|
| 10 |
+
"family_id": "decimal_copybook_payroll",
|
| 11 |
+
"ticket": {
|
| 12 |
+
"task_id": "payroll_net_pay_001",
|
| 13 |
+
"family_id": "decimal_copybook_payroll",
|
| 14 |
+
"domain": "payroll",
|
| 15 |
+
"ticket": "Migrate PAYROLL.cbl while preserving copybook offsets, implied decimals, signed deductions, bonus condition names, and fixed-width ACH output.",
|
| 16 |
+
"available_files": [
|
| 17 |
+
"PAYROLL.cbl"
|
| 18 |
+
],
|
| 19 |
+
"available_copybooks": [
|
| 20 |
+
"EMPLOYEE_PAY.cpy"
|
| 21 |
+
],
|
| 22 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 23 |
+
"visible_tests": 3,
|
| 24 |
+
"hidden_tests": 5,
|
| 25 |
+
"input_width": 42,
|
| 26 |
+
"output_width": 28,
|
| 27 |
+
"max_steps": 12,
|
| 28 |
+
"allowed_tools": [
|
| 29 |
+
"read_cobol_file",
|
| 30 |
+
"read_copybook",
|
| 31 |
+
"parse_copybook_layout",
|
| 32 |
+
"inspect_business_rules",
|
| 33 |
+
"write_python_solution",
|
| 34 |
+
"run_visible_tests",
|
| 35 |
+
"inspect_diff",
|
| 36 |
+
"submit_final"
|
| 37 |
+
]
|
| 38 |
+
},
|
| 39 |
+
"visible": {
|
| 40 |
+
"passed": 3,
|
| 41 |
+
"total": 3,
|
| 42 |
+
"pass_rate": 1.0,
|
| 43 |
+
"failures": []
|
| 44 |
+
},
|
| 45 |
+
"final": {
|
| 46 |
+
"public_score": 1.0,
|
| 47 |
+
"accepted": true,
|
| 48 |
+
"components": {
|
| 49 |
+
"hidden_correctness": 1.0,
|
| 50 |
+
"fresh_correctness": 1.0,
|
| 51 |
+
"interface_contract": 1.0,
|
| 52 |
+
"type_and_layout_fidelity": 1.0,
|
| 53 |
+
"anti_hardcoding": 1.0,
|
| 54 |
+
"safety": 1.0
|
| 55 |
+
},
|
| 56 |
+
"hidden_passed": 5,
|
| 57 |
+
"hidden_total": 5,
|
| 58 |
+
"fresh_passed": 6,
|
| 59 |
+
"fresh_total": 6
|
| 60 |
+
},
|
| 61 |
+
"steps": [
|
| 62 |
+
{
|
| 63 |
+
"tool_name": "read_cobol_file",
|
| 64 |
+
"arguments": {
|
| 65 |
+
"filename": "PAYROLL.cbl"
|
| 66 |
+
},
|
| 67 |
+
"reward": 0.02,
|
| 68 |
+
"done": false,
|
| 69 |
+
"result": {
|
| 70 |
+
"ok": true,
|
| 71 |
+
"filename": "PAYROLL.cbl",
|
| 72 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. PAYROLLNET.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY EMPLOYEE_PAY.\n 01 TAX-AMOUNT PIC 9(7)V99.\n 01 NET-AMOUNT PIC 9(7)V99.\n 01 PAY-CATEGORY PIC X.\n PROCEDURE DIVISION.\n COMPUTE TAX-AMOUNT ROUNDED = GROSS-PAY * TAX-RATE\n COMPUTE NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS\n IF BONUS-ELIGIBLE ADD 50.00 TO NET-AMOUNT END-IF\n IF NET-AMOUNT < 0 MOVE 0 TO NET-AMOUNT END-IF\n EVALUATE TRUE\n WHEN NET-AMOUNT >= 5000.00 MOVE 'H' TO PAY-CATEGORY\n WHEN NET-AMOUNT >= 2500.00 MOVE 'M' TO PAY-CATEGORY\n WHEN OTHER MOVE 'L' TO PAY-CATEGORY\n END-EVALUATE\n GOBACK.\n",
|
| 73 |
+
"truncated": false
|
| 74 |
+
}
|
| 75 |
+
},
|
| 76 |
+
{
|
| 77 |
+
"tool_name": "read_copybook",
|
| 78 |
+
"arguments": {
|
| 79 |
+
"filename": "EMPLOYEE_PAY.cpy"
|
| 80 |
+
},
|
| 81 |
+
"reward": 0.02,
|
| 82 |
+
"done": false,
|
| 83 |
+
"result": {
|
| 84 |
+
"ok": true,
|
| 85 |
+
"filename": "EMPLOYEE_PAY.cpy",
|
| 86 |
+
"content": " 01 EMPLOYEE-PAY-RECORD.\n 05 EMP-ID PIC X(6).\n 05 EMP-NAME PIC X(12).\n 05 GROSS-PAY PIC 9(7)V99.\n 05 TAX-RATE PIC 9V999.\n 05 DEDUCTIONS PIC S9(5)V99 SIGN LEADING SEPARATE.\n 05 BONUS-FLAG PIC X(1).\n 88 BONUS-ELIGIBLE VALUE 'Y'.\n 88 NO-BONUS VALUE 'N'.\n 05 FILLER PIC X(2).\n"
|
| 87 |
+
}
|
| 88 |
+
},
|
| 89 |
+
{
|
| 90 |
+
"tool_name": "parse_copybook_layout",
|
| 91 |
+
"arguments": {
|
| 92 |
+
"filename": "EMPLOYEE_PAY.cpy"
|
| 93 |
+
},
|
| 94 |
+
"reward": 0.03,
|
| 95 |
+
"done": false,
|
| 96 |
+
"result": {
|
| 97 |
+
"ok": true,
|
| 98 |
+
"filename": "EMPLOYEE_PAY.cpy",
|
| 99 |
+
"record_name": "EMPLOYEE-PAY-RECORD",
|
| 100 |
+
"total_width": 42,
|
| 101 |
+
"fields": [
|
| 102 |
+
{
|
| 103 |
+
"name": "EMP-ID",
|
| 104 |
+
"start": 0,
|
| 105 |
+
"end": 6,
|
| 106 |
+
"length": 6,
|
| 107 |
+
"pic": "X(6)",
|
| 108 |
+
"python_type": "str"
|
| 109 |
+
},
|
| 110 |
+
{
|
| 111 |
+
"name": "EMP-NAME",
|
| 112 |
+
"start": 6,
|
| 113 |
+
"end": 18,
|
| 114 |
+
"length": 12,
|
| 115 |
+
"pic": "X(12)",
|
| 116 |
+
"python_type": "str"
|
| 117 |
+
},
|
| 118 |
+
{
|
| 119 |
+
"name": "GROSS-PAY",
|
| 120 |
+
"start": 18,
|
| 121 |
+
"end": 27,
|
| 122 |
+
"length": 9,
|
| 123 |
+
"pic": "9(7)V99",
|
| 124 |
+
"python_type": "Decimal",
|
| 125 |
+
"scale": 2
|
| 126 |
+
},
|
| 127 |
+
{
|
| 128 |
+
"name": "TAX-RATE",
|
| 129 |
+
"start": 27,
|
| 130 |
+
"end": 31,
|
| 131 |
+
"length": 4,
|
| 132 |
+
"pic": "9V999",
|
| 133 |
+
"python_type": "Decimal",
|
| 134 |
+
"scale": 3
|
| 135 |
+
},
|
| 136 |
+
{
|
| 137 |
+
"name": "DEDUCTIONS",
|
| 138 |
+
"start": 31,
|
| 139 |
+
"end": 39,
|
| 140 |
+
"length": 8,
|
| 141 |
+
"pic": "S9(5)V99 SIGN LEADING SEPARATE",
|
| 142 |
+
"python_type": "Decimal",
|
| 143 |
+
"scale": 2
|
| 144 |
+
},
|
| 145 |
+
{
|
| 146 |
+
"name": "BONUS-FLAG",
|
| 147 |
+
"start": 39,
|
| 148 |
+
"end": 40,
|
| 149 |
+
"length": 1,
|
| 150 |
+
"pic": "X(1)",
|
| 151 |
+
"python_type": "str",
|
| 152 |
+
"level_88": {
|
| 153 |
+
"BONUS-ELIGIBLE": "Y",
|
| 154 |
+
"NO-BONUS": "N"
|
| 155 |
+
}
|
| 156 |
+
},
|
| 157 |
+
{
|
| 158 |
+
"name": "FILLER",
|
| 159 |
+
"start": 40,
|
| 160 |
+
"end": 42,
|
| 161 |
+
"length": 2,
|
| 162 |
+
"pic": "X(2)",
|
| 163 |
+
"python_type": "str"
|
| 164 |
+
}
|
| 165 |
+
]
|
| 166 |
+
}
|
| 167 |
+
},
|
| 168 |
+
{
|
| 169 |
+
"tool_name": "inspect_business_rules",
|
| 170 |
+
"arguments": {},
|
| 171 |
+
"reward": 0.01,
|
| 172 |
+
"done": false,
|
| 173 |
+
"result": {
|
| 174 |
+
"ok": true,
|
| 175 |
+
"rules": [
|
| 176 |
+
"Tax is rounded half up to cents after GROSS-PAY * TAX-RATE.",
|
| 177 |
+
"NET-AMOUNT = GROSS-PAY - TAX-AMOUNT - DEDUCTIONS.",
|
| 178 |
+
"BONUS-ELIGIBLE adds 50.00; negative net pay floors to zero.",
|
| 179 |
+
"Output net pay is a 9-digit zero-padded cents field."
|
| 180 |
+
]
|
| 181 |
+
}
|
| 182 |
+
},
|
| 183 |
+
{
|
| 184 |
+
"tool_name": "write_python_solution",
|
| 185 |
+
"arguments": {
|
| 186 |
+
"code_chars": 964
|
| 187 |
+
},
|
| 188 |
+
"reward": 0.02,
|
| 189 |
+
"done": false,
|
| 190 |
+
"result": {
|
| 191 |
+
"ok": true,
|
| 192 |
+
"draft_id": 1,
|
| 193 |
+
"syntax_ok": true,
|
| 194 |
+
"safety_ok": true,
|
| 195 |
+
"error": null
|
| 196 |
+
}
|
| 197 |
+
},
|
| 198 |
+
{
|
| 199 |
+
"tool_name": "run_visible_tests",
|
| 200 |
+
"arguments": {
|
| 201 |
+
"draft_id": 1
|
| 202 |
+
},
|
| 203 |
+
"reward": 0.05,
|
| 204 |
+
"done": false,
|
| 205 |
+
"result": {
|
| 206 |
+
"ok": true,
|
| 207 |
+
"draft_id": 1,
|
| 208 |
+
"passed": 3,
|
| 209 |
+
"total": 3,
|
| 210 |
+
"pass_rate": 1.0,
|
| 211 |
+
"syntax_ok": true,
|
| 212 |
+
"safety_ok": true,
|
| 213 |
+
"interface_ok": true,
|
| 214 |
+
"timed_out": false,
|
| 215 |
+
"error": null,
|
| 216 |
+
"failures": []
|
| 217 |
+
}
|
| 218 |
+
},
|
| 219 |
+
{
|
| 220 |
+
"tool_name": "submit_final",
|
| 221 |
+
"arguments": {
|
| 222 |
+
"draft_id": 1
|
| 223 |
+
},
|
| 224 |
+
"reward": 1.0,
|
| 225 |
+
"done": true,
|
| 226 |
+
"result": {
|
| 227 |
+
"ok": true,
|
| 228 |
+
"accepted": true,
|
| 229 |
+
"episode_done": true,
|
| 230 |
+
"public_score": 1.0,
|
| 231 |
+
"components": {
|
| 232 |
+
"hidden_correctness": 1.0,
|
| 233 |
+
"fresh_correctness": 1.0,
|
| 234 |
+
"interface_contract": 1.0,
|
| 235 |
+
"type_and_layout_fidelity": 1.0,
|
| 236 |
+
"anti_hardcoding": 1.0,
|
| 237 |
+
"safety": 1.0
|
| 238 |
+
},
|
| 239 |
+
"hidden_passed": 5,
|
| 240 |
+
"hidden_total": 5,
|
| 241 |
+
"fresh_passed": 6,
|
| 242 |
+
"fresh_total": 6,
|
| 243 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 244 |
+
}
|
| 245 |
+
}
|
| 246 |
+
]
|
| 247 |
+
},
|
| 248 |
+
{
|
| 249 |
+
"policy": "oracle",
|
| 250 |
+
"task_id": "customer_format_001",
|
| 251 |
+
"family_id": "fixed_width_customer",
|
| 252 |
+
"ticket": {
|
| 253 |
+
"task_id": "customer_format_001",
|
| 254 |
+
"family_id": "fixed_width_customer",
|
| 255 |
+
"domain": "customer master data",
|
| 256 |
+
"ticket": "Migrate CUSTFMT.cbl. Preserve fixed-width name formatting, status mapping, ZIP leading zeros, and zero-padded balance output.",
|
| 257 |
+
"available_files": [
|
| 258 |
+
"CUSTFMT.cbl"
|
| 259 |
+
],
|
| 260 |
+
"available_copybooks": [
|
| 261 |
+
"CUSTOMER_REC.cpy"
|
| 262 |
+
],
|
| 263 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 264 |
+
"visible_tests": 3,
|
| 265 |
+
"hidden_tests": 3,
|
| 266 |
+
"input_width": 40,
|
| 267 |
+
"output_width": 41,
|
| 268 |
+
"max_steps": 12,
|
| 269 |
+
"allowed_tools": [
|
| 270 |
+
"read_cobol_file",
|
| 271 |
+
"read_copybook",
|
| 272 |
+
"parse_copybook_layout",
|
| 273 |
+
"inspect_business_rules",
|
| 274 |
+
"write_python_solution",
|
| 275 |
+
"run_visible_tests",
|
| 276 |
+
"inspect_diff",
|
| 277 |
+
"submit_final"
|
| 278 |
+
]
|
| 279 |
+
},
|
| 280 |
+
"visible": {
|
| 281 |
+
"passed": 3,
|
| 282 |
+
"total": 3,
|
| 283 |
+
"pass_rate": 1.0,
|
| 284 |
+
"failures": []
|
| 285 |
+
},
|
| 286 |
+
"final": {
|
| 287 |
+
"public_score": 1.0,
|
| 288 |
+
"accepted": true,
|
| 289 |
+
"components": {
|
| 290 |
+
"hidden_correctness": 1.0,
|
| 291 |
+
"fresh_correctness": 1.0,
|
| 292 |
+
"interface_contract": 1.0,
|
| 293 |
+
"type_and_layout_fidelity": 1.0,
|
| 294 |
+
"anti_hardcoding": 1.0,
|
| 295 |
+
"safety": 1.0
|
| 296 |
+
},
|
| 297 |
+
"hidden_passed": 3,
|
| 298 |
+
"hidden_total": 3,
|
| 299 |
+
"fresh_passed": 6,
|
| 300 |
+
"fresh_total": 6
|
| 301 |
+
},
|
| 302 |
+
"steps": [
|
| 303 |
+
{
|
| 304 |
+
"tool_name": "read_cobol_file",
|
| 305 |
+
"arguments": {
|
| 306 |
+
"filename": "CUSTFMT.cbl"
|
| 307 |
+
},
|
| 308 |
+
"reward": 0.02,
|
| 309 |
+
"done": false,
|
| 310 |
+
"result": {
|
| 311 |
+
"ok": true,
|
| 312 |
+
"filename": "CUSTFMT.cbl",
|
| 313 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. CUSTFMT.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY CUSTOMER_REC.\n 01 OUTPUT-RECORD.\n 05 OUT-CUST-ID PIC X(5).\n 05 OUT-FULL-NAME PIC X(22).\n 05 OUT-ZIP-CODE PIC 9(5).\n 05 OUT-STATUS PIC X.\n 05 OUT-BALANCE PIC 9(6)V99.\n PROCEDURE DIVISION.\n STRING LAST-NAME DELIMITED BY SIZE ', ' FIRST-NAME DELIMITED BY SIZE\n INTO OUT-FULL-NAME\n EVALUATE STATUS-CODE\n WHEN 'A' MOVE 'O' TO OUT-STATUS\n WHEN 'S' MOVE 'S' TO OUT-STATUS\n WHEN OTHER MOVE 'C' TO OUT-STATUS\n END-EVALUATE\n GOBACK.\n",
|
| 314 |
+
"truncated": false
|
| 315 |
+
}
|
| 316 |
+
},
|
| 317 |
+
{
|
| 318 |
+
"tool_name": "read_copybook",
|
| 319 |
+
"arguments": {
|
| 320 |
+
"filename": "CUSTOMER_REC.cpy"
|
| 321 |
+
},
|
| 322 |
+
"reward": 0.02,
|
| 323 |
+
"done": false,
|
| 324 |
+
"result": {
|
| 325 |
+
"ok": true,
|
| 326 |
+
"filename": "CUSTOMER_REC.cpy",
|
| 327 |
+
"content": " 01 CUSTOMER-RECORD.\n 05 CUST-ID PIC X(5).\n 05 FIRST-NAME PIC X(10).\n 05 LAST-NAME PIC X(12).\n 05 ZIP-CODE PIC 9(5).\n 05 STATUS-CODE PIC X.\n 88 ACTIVE-CUSTOMER VALUE 'A'.\n 88 SUSPENDED-CUSTOMER VALUE 'S'.\n 88 CLOSED-CUSTOMER VALUE 'C'.\n 05 BALANCE-DUE PIC 9(5)V99.\n"
|
| 328 |
+
}
|
| 329 |
+
},
|
| 330 |
+
{
|
| 331 |
+
"tool_name": "parse_copybook_layout",
|
| 332 |
+
"arguments": {
|
| 333 |
+
"filename": "CUSTOMER_REC.cpy"
|
| 334 |
+
},
|
| 335 |
+
"reward": 0.03,
|
| 336 |
+
"done": false,
|
| 337 |
+
"result": {
|
| 338 |
+
"ok": true,
|
| 339 |
+
"filename": "CUSTOMER_REC.cpy",
|
| 340 |
+
"record_name": "CUSTOMER-RECORD",
|
| 341 |
+
"total_width": 40,
|
| 342 |
+
"fields": [
|
| 343 |
+
{
|
| 344 |
+
"name": "CUST-ID",
|
| 345 |
+
"start": 0,
|
| 346 |
+
"end": 5,
|
| 347 |
+
"length": 5,
|
| 348 |
+
"pic": "X(5)",
|
| 349 |
+
"python_type": "str"
|
| 350 |
+
},
|
| 351 |
+
{
|
| 352 |
+
"name": "FIRST-NAME",
|
| 353 |
+
"start": 5,
|
| 354 |
+
"end": 15,
|
| 355 |
+
"length": 10,
|
| 356 |
+
"pic": "X(10)",
|
| 357 |
+
"python_type": "str"
|
| 358 |
+
},
|
| 359 |
+
{
|
| 360 |
+
"name": "LAST-NAME",
|
| 361 |
+
"start": 15,
|
| 362 |
+
"end": 27,
|
| 363 |
+
"length": 12,
|
| 364 |
+
"pic": "X(12)",
|
| 365 |
+
"python_type": "str"
|
| 366 |
+
},
|
| 367 |
+
{
|
| 368 |
+
"name": "ZIP-CODE",
|
| 369 |
+
"start": 27,
|
| 370 |
+
"end": 32,
|
| 371 |
+
"length": 5,
|
| 372 |
+
"pic": "9(5)",
|
| 373 |
+
"python_type": "str"
|
| 374 |
+
},
|
| 375 |
+
{
|
| 376 |
+
"name": "STATUS-CODE",
|
| 377 |
+
"start": 32,
|
| 378 |
+
"end": 33,
|
| 379 |
+
"length": 1,
|
| 380 |
+
"pic": "X",
|
| 381 |
+
"python_type": "str"
|
| 382 |
+
},
|
| 383 |
+
{
|
| 384 |
+
"name": "BALANCE-DUE",
|
| 385 |
+
"start": 33,
|
| 386 |
+
"end": 40,
|
| 387 |
+
"length": 7,
|
| 388 |
+
"pic": "9(5)V99",
|
| 389 |
+
"python_type": "Decimal",
|
| 390 |
+
"scale": 2
|
| 391 |
+
}
|
| 392 |
+
]
|
| 393 |
+
}
|
| 394 |
+
},
|
| 395 |
+
{
|
| 396 |
+
"tool_name": "inspect_business_rules",
|
| 397 |
+
"arguments": {},
|
| 398 |
+
"reward": 0.01,
|
| 399 |
+
"done": false,
|
| 400 |
+
"result": {
|
| 401 |
+
"ok": true,
|
| 402 |
+
"rules": [
|
| 403 |
+
"OUT-FULL-NAME is LAST-NAME, comma-space, FIRST-NAME, truncated/padded to 22.",
|
| 404 |
+
"A maps to O, S maps to S, anything else maps to C.",
|
| 405 |
+
"ZIP stays five digits and OUT-BALANCE is eight zero-padded digits."
|
| 406 |
+
]
|
| 407 |
+
}
|
| 408 |
+
},
|
| 409 |
+
{
|
| 410 |
+
"tool_name": "write_python_solution",
|
| 411 |
+
"arguments": {
|
| 412 |
+
"code_chars": 405
|
| 413 |
+
},
|
| 414 |
+
"reward": 0.02,
|
| 415 |
+
"done": false,
|
| 416 |
+
"result": {
|
| 417 |
+
"ok": true,
|
| 418 |
+
"draft_id": 1,
|
| 419 |
+
"syntax_ok": true,
|
| 420 |
+
"safety_ok": true,
|
| 421 |
+
"error": null
|
| 422 |
+
}
|
| 423 |
+
},
|
| 424 |
+
{
|
| 425 |
+
"tool_name": "run_visible_tests",
|
| 426 |
+
"arguments": {
|
| 427 |
+
"draft_id": 1
|
| 428 |
+
},
|
| 429 |
+
"reward": 0.05,
|
| 430 |
+
"done": false,
|
| 431 |
+
"result": {
|
| 432 |
+
"ok": true,
|
| 433 |
+
"draft_id": 1,
|
| 434 |
+
"passed": 3,
|
| 435 |
+
"total": 3,
|
| 436 |
+
"pass_rate": 1.0,
|
| 437 |
+
"syntax_ok": true,
|
| 438 |
+
"safety_ok": true,
|
| 439 |
+
"interface_ok": true,
|
| 440 |
+
"timed_out": false,
|
| 441 |
+
"error": null,
|
| 442 |
+
"failures": []
|
| 443 |
+
}
|
| 444 |
+
},
|
| 445 |
+
{
|
| 446 |
+
"tool_name": "submit_final",
|
| 447 |
+
"arguments": {
|
| 448 |
+
"draft_id": 1
|
| 449 |
+
},
|
| 450 |
+
"reward": 1.0,
|
| 451 |
+
"done": true,
|
| 452 |
+
"result": {
|
| 453 |
+
"ok": true,
|
| 454 |
+
"accepted": true,
|
| 455 |
+
"episode_done": true,
|
| 456 |
+
"public_score": 1.0,
|
| 457 |
+
"components": {
|
| 458 |
+
"hidden_correctness": 1.0,
|
| 459 |
+
"fresh_correctness": 1.0,
|
| 460 |
+
"interface_contract": 1.0,
|
| 461 |
+
"type_and_layout_fidelity": 1.0,
|
| 462 |
+
"anti_hardcoding": 1.0,
|
| 463 |
+
"safety": 1.0
|
| 464 |
+
},
|
| 465 |
+
"hidden_passed": 3,
|
| 466 |
+
"hidden_total": 3,
|
| 467 |
+
"fresh_passed": 6,
|
| 468 |
+
"fresh_total": 6,
|
| 469 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 470 |
+
}
|
| 471 |
+
}
|
| 472 |
+
]
|
| 473 |
+
},
|
| 474 |
+
{
|
| 475 |
+
"policy": "oracle",
|
| 476 |
+
"task_id": "claims_eligibility_001",
|
| 477 |
+
"family_id": "claims_eligibility_branching",
|
| 478 |
+
"ticket": {
|
| 479 |
+
"task_id": "claims_eligibility_001",
|
| 480 |
+
"family_id": "claims_eligibility_branching",
|
| 481 |
+
"domain": "insurance claims",
|
| 482 |
+
"ticket": "Migrate CLMELIG.cbl. Preserve EVALUATE TRUE branch precedence for claim approvals, denials, and manual review reasons.",
|
| 483 |
+
"available_files": [
|
| 484 |
+
"CLMELIG.cbl"
|
| 485 |
+
],
|
| 486 |
+
"available_copybooks": [
|
| 487 |
+
"CLAIM_REC.cpy"
|
| 488 |
+
],
|
| 489 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 490 |
+
"visible_tests": 3,
|
| 491 |
+
"hidden_tests": 3,
|
| 492 |
+
"input_width": 21,
|
| 493 |
+
"output_width": 9,
|
| 494 |
+
"max_steps": 12,
|
| 495 |
+
"allowed_tools": [
|
| 496 |
+
"read_cobol_file",
|
| 497 |
+
"read_copybook",
|
| 498 |
+
"parse_copybook_layout",
|
| 499 |
+
"inspect_business_rules",
|
| 500 |
+
"write_python_solution",
|
| 501 |
+
"run_visible_tests",
|
| 502 |
+
"inspect_diff",
|
| 503 |
+
"submit_final"
|
| 504 |
+
]
|
| 505 |
+
},
|
| 506 |
+
"visible": {
|
| 507 |
+
"passed": 3,
|
| 508 |
+
"total": 3,
|
| 509 |
+
"pass_rate": 1.0,
|
| 510 |
+
"failures": []
|
| 511 |
+
},
|
| 512 |
+
"final": {
|
| 513 |
+
"public_score": 1.0,
|
| 514 |
+
"accepted": true,
|
| 515 |
+
"components": {
|
| 516 |
+
"hidden_correctness": 1.0,
|
| 517 |
+
"fresh_correctness": 1.0,
|
| 518 |
+
"interface_contract": 1.0,
|
| 519 |
+
"type_and_layout_fidelity": 1.0,
|
| 520 |
+
"anti_hardcoding": 1.0,
|
| 521 |
+
"safety": 1.0
|
| 522 |
+
},
|
| 523 |
+
"hidden_passed": 3,
|
| 524 |
+
"hidden_total": 3,
|
| 525 |
+
"fresh_passed": 6,
|
| 526 |
+
"fresh_total": 6
|
| 527 |
+
},
|
| 528 |
+
"steps": [
|
| 529 |
+
{
|
| 530 |
+
"tool_name": "read_cobol_file",
|
| 531 |
+
"arguments": {
|
| 532 |
+
"filename": "CLMELIG.cbl"
|
| 533 |
+
},
|
| 534 |
+
"reward": 0.02,
|
| 535 |
+
"done": false,
|
| 536 |
+
"result": {
|
| 537 |
+
"ok": true,
|
| 538 |
+
"filename": "CLMELIG.cbl",
|
| 539 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. CLMELIG.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY CLAIM_REC.\n PROCEDURE DIVISION.\n EVALUATE TRUE\n WHEN AGE < 18 MOVE 'D' TO DECISION MOVE 'A1' TO REASON\n WHEN PLAN-CODE = 'B' AND CLAIM-AMOUNT > 1500.00 MOVE 'R' TO DECISION MOVE 'B2' TO REASON\n WHEN PREAUTH-FLAG = 'N' AND CLAIM-AMOUNT > 1000.00 MOVE 'D' TO DECISION MOVE 'P1' TO REASON\n WHEN SERVICE-DAYS > 030 MOVE 'R' TO DECISION MOVE 'L1' TO REASON\n WHEN OTHER MOVE 'A' TO DECISION MOVE 'OK' TO REASON\n END-EVALUATE\n GOBACK.\n",
|
| 540 |
+
"truncated": false
|
| 541 |
+
}
|
| 542 |
+
},
|
| 543 |
+
{
|
| 544 |
+
"tool_name": "read_copybook",
|
| 545 |
+
"arguments": {
|
| 546 |
+
"filename": "CLAIM_REC.cpy"
|
| 547 |
+
},
|
| 548 |
+
"reward": 0.02,
|
| 549 |
+
"done": false,
|
| 550 |
+
"result": {
|
| 551 |
+
"ok": true,
|
| 552 |
+
"filename": "CLAIM_REC.cpy",
|
| 553 |
+
"content": " 01 CLAIM-RECORD.\n 05 CLAIM-ID PIC X(6).\n 05 AGE PIC 9(3).\n 05 PLAN-CODE PIC X.\n 05 SERVICE-DAYS PIC 9(3).\n 05 PREAUTH-FLAG PIC X.\n 05 CLAIM-AMOUNT PIC 9(5)V99.\n"
|
| 554 |
+
}
|
| 555 |
+
},
|
| 556 |
+
{
|
| 557 |
+
"tool_name": "parse_copybook_layout",
|
| 558 |
+
"arguments": {
|
| 559 |
+
"filename": "CLAIM_REC.cpy"
|
| 560 |
+
},
|
| 561 |
+
"reward": 0.03,
|
| 562 |
+
"done": false,
|
| 563 |
+
"result": {
|
| 564 |
+
"ok": true,
|
| 565 |
+
"filename": "CLAIM_REC.cpy",
|
| 566 |
+
"record_name": "CLAIM-RECORD",
|
| 567 |
+
"total_width": 21,
|
| 568 |
+
"fields": [
|
| 569 |
+
{
|
| 570 |
+
"name": "CLAIM-ID",
|
| 571 |
+
"start": 0,
|
| 572 |
+
"end": 6,
|
| 573 |
+
"length": 6,
|
| 574 |
+
"pic": "X(6)",
|
| 575 |
+
"python_type": "str"
|
| 576 |
+
},
|
| 577 |
+
{
|
| 578 |
+
"name": "AGE",
|
| 579 |
+
"start": 6,
|
| 580 |
+
"end": 9,
|
| 581 |
+
"length": 3,
|
| 582 |
+
"pic": "9(3)",
|
| 583 |
+
"python_type": "int"
|
| 584 |
+
},
|
| 585 |
+
{
|
| 586 |
+
"name": "PLAN-CODE",
|
| 587 |
+
"start": 9,
|
| 588 |
+
"end": 10,
|
| 589 |
+
"length": 1,
|
| 590 |
+
"pic": "X",
|
| 591 |
+
"python_type": "str"
|
| 592 |
+
},
|
| 593 |
+
{
|
| 594 |
+
"name": "SERVICE-DAYS",
|
| 595 |
+
"start": 10,
|
| 596 |
+
"end": 13,
|
| 597 |
+
"length": 3,
|
| 598 |
+
"pic": "9(3)",
|
| 599 |
+
"python_type": "int"
|
| 600 |
+
},
|
| 601 |
+
{
|
| 602 |
+
"name": "PREAUTH-FLAG",
|
| 603 |
+
"start": 13,
|
| 604 |
+
"end": 14,
|
| 605 |
+
"length": 1,
|
| 606 |
+
"pic": "X",
|
| 607 |
+
"python_type": "str"
|
| 608 |
+
},
|
| 609 |
+
{
|
| 610 |
+
"name": "CLAIM-AMOUNT",
|
| 611 |
+
"start": 14,
|
| 612 |
+
"end": 21,
|
| 613 |
+
"length": 7,
|
| 614 |
+
"pic": "9(5)V99",
|
| 615 |
+
"python_type": "Decimal",
|
| 616 |
+
"scale": 2
|
| 617 |
+
}
|
| 618 |
+
]
|
| 619 |
+
}
|
| 620 |
+
},
|
| 621 |
+
{
|
| 622 |
+
"tool_name": "inspect_business_rules",
|
| 623 |
+
"arguments": {},
|
| 624 |
+
"reward": 0.01,
|
| 625 |
+
"done": false,
|
| 626 |
+
"result": {
|
| 627 |
+
"ok": true,
|
| 628 |
+
"rules": [
|
| 629 |
+
"Branch order matters: age, plan-B large claim, missing preauth, long service, default approve.",
|
| 630 |
+
"Amounts are implied cents; 100000 means 1000.00."
|
| 631 |
+
]
|
| 632 |
+
}
|
| 633 |
+
},
|
| 634 |
+
{
|
| 635 |
+
"tool_name": "write_python_solution",
|
| 636 |
+
"arguments": {
|
| 637 |
+
"code_chars": 623
|
| 638 |
+
},
|
| 639 |
+
"reward": 0.02,
|
| 640 |
+
"done": false,
|
| 641 |
+
"result": {
|
| 642 |
+
"ok": true,
|
| 643 |
+
"draft_id": 1,
|
| 644 |
+
"syntax_ok": true,
|
| 645 |
+
"safety_ok": true,
|
| 646 |
+
"error": null
|
| 647 |
+
}
|
| 648 |
+
},
|
| 649 |
+
{
|
| 650 |
+
"tool_name": "run_visible_tests",
|
| 651 |
+
"arguments": {
|
| 652 |
+
"draft_id": 1
|
| 653 |
+
},
|
| 654 |
+
"reward": 0.05,
|
| 655 |
+
"done": false,
|
| 656 |
+
"result": {
|
| 657 |
+
"ok": true,
|
| 658 |
+
"draft_id": 1,
|
| 659 |
+
"passed": 3,
|
| 660 |
+
"total": 3,
|
| 661 |
+
"pass_rate": 1.0,
|
| 662 |
+
"syntax_ok": true,
|
| 663 |
+
"safety_ok": true,
|
| 664 |
+
"interface_ok": true,
|
| 665 |
+
"timed_out": false,
|
| 666 |
+
"error": null,
|
| 667 |
+
"failures": []
|
| 668 |
+
}
|
| 669 |
+
},
|
| 670 |
+
{
|
| 671 |
+
"tool_name": "submit_final",
|
| 672 |
+
"arguments": {
|
| 673 |
+
"draft_id": 1
|
| 674 |
+
},
|
| 675 |
+
"reward": 1.0,
|
| 676 |
+
"done": true,
|
| 677 |
+
"result": {
|
| 678 |
+
"ok": true,
|
| 679 |
+
"accepted": true,
|
| 680 |
+
"episode_done": true,
|
| 681 |
+
"public_score": 1.0,
|
| 682 |
+
"components": {
|
| 683 |
+
"hidden_correctness": 1.0,
|
| 684 |
+
"fresh_correctness": 1.0,
|
| 685 |
+
"interface_contract": 1.0,
|
| 686 |
+
"type_and_layout_fidelity": 1.0,
|
| 687 |
+
"anti_hardcoding": 1.0,
|
| 688 |
+
"safety": 1.0
|
| 689 |
+
},
|
| 690 |
+
"hidden_passed": 3,
|
| 691 |
+
"hidden_total": 3,
|
| 692 |
+
"fresh_passed": 6,
|
| 693 |
+
"fresh_total": 6,
|
| 694 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 695 |
+
}
|
| 696 |
+
}
|
| 697 |
+
]
|
| 698 |
+
},
|
| 699 |
+
{
|
| 700 |
+
"policy": "oracle",
|
| 701 |
+
"task_id": "account_status_001",
|
| 702 |
+
"family_id": "account_status_level88",
|
| 703 |
+
"ticket": {
|
| 704 |
+
"task_id": "account_status_001",
|
| 705 |
+
"family_id": "account_status_level88",
|
| 706 |
+
"domain": "banking",
|
| 707 |
+
"ticket": "Migrate ACCTSTAT.cbl. Correctly interpret level-88 status names and preserve branch precedence for account servicing actions.",
|
| 708 |
+
"available_files": [
|
| 709 |
+
"ACCTSTAT.cbl"
|
| 710 |
+
],
|
| 711 |
+
"available_copybooks": [
|
| 712 |
+
"ACCOUNT_REC.cpy"
|
| 713 |
+
],
|
| 714 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 715 |
+
"visible_tests": 3,
|
| 716 |
+
"hidden_tests": 3,
|
| 717 |
+
"input_width": 19,
|
| 718 |
+
"output_width": 9,
|
| 719 |
+
"max_steps": 12,
|
| 720 |
+
"allowed_tools": [
|
| 721 |
+
"read_cobol_file",
|
| 722 |
+
"read_copybook",
|
| 723 |
+
"parse_copybook_layout",
|
| 724 |
+
"inspect_business_rules",
|
| 725 |
+
"write_python_solution",
|
| 726 |
+
"run_visible_tests",
|
| 727 |
+
"inspect_diff",
|
| 728 |
+
"submit_final"
|
| 729 |
+
]
|
| 730 |
+
},
|
| 731 |
+
"visible": {
|
| 732 |
+
"passed": 3,
|
| 733 |
+
"total": 3,
|
| 734 |
+
"pass_rate": 1.0,
|
| 735 |
+
"failures": []
|
| 736 |
+
},
|
| 737 |
+
"final": {
|
| 738 |
+
"public_score": 1.0,
|
| 739 |
+
"accepted": true,
|
| 740 |
+
"components": {
|
| 741 |
+
"hidden_correctness": 1.0,
|
| 742 |
+
"fresh_correctness": 1.0,
|
| 743 |
+
"interface_contract": 1.0,
|
| 744 |
+
"type_and_layout_fidelity": 1.0,
|
| 745 |
+
"anti_hardcoding": 1.0,
|
| 746 |
+
"safety": 1.0
|
| 747 |
+
},
|
| 748 |
+
"hidden_passed": 3,
|
| 749 |
+
"hidden_total": 3,
|
| 750 |
+
"fresh_passed": 6,
|
| 751 |
+
"fresh_total": 6
|
| 752 |
+
},
|
| 753 |
+
"steps": [
|
| 754 |
+
{
|
| 755 |
+
"tool_name": "read_cobol_file",
|
| 756 |
+
"arguments": {
|
| 757 |
+
"filename": "ACCTSTAT.cbl"
|
| 758 |
+
},
|
| 759 |
+
"reward": 0.02,
|
| 760 |
+
"done": false,
|
| 761 |
+
"result": {
|
| 762 |
+
"ok": true,
|
| 763 |
+
"filename": "ACCTSTAT.cbl",
|
| 764 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. ACCTSTAT.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY ACCOUNT_REC.\n PROCEDURE DIVISION.\n EVALUATE TRUE\n WHEN CLOSED-ACCT MOVE 'CL' TO CATEGORY MOVE 'N' TO ACTION\n WHEN FROZEN-ACCT MOVE 'FR' TO CATEGORY MOVE 'H' TO ACTION\n WHEN DAYS-PAST-DUE >= 090 MOVE 'DL' TO CATEGORY MOVE 'C' TO ACTION\n WHEN BALANCE < 0 MOVE 'OD' TO CATEGORY MOVE 'R' TO ACTION\n WHEN OTHER MOVE 'OK' TO CATEGORY MOVE 'N' TO ACTION\n END-EVALUATE\n GOBACK.\n",
|
| 765 |
+
"truncated": false
|
| 766 |
+
}
|
| 767 |
+
},
|
| 768 |
+
{
|
| 769 |
+
"tool_name": "read_copybook",
|
| 770 |
+
"arguments": {
|
| 771 |
+
"filename": "ACCOUNT_REC.cpy"
|
| 772 |
+
},
|
| 773 |
+
"reward": 0.02,
|
| 774 |
+
"done": false,
|
| 775 |
+
"result": {
|
| 776 |
+
"ok": true,
|
| 777 |
+
"filename": "ACCOUNT_REC.cpy",
|
| 778 |
+
"content": " 01 ACCOUNT-RECORD.\n 05 ACCOUNT-ID PIC X(6).\n 05 STATUS-CODE PIC X.\n 88 ACTIVE-ACCT VALUE 'A'.\n 88 FROZEN-ACCT VALUE 'F'.\n 88 CLOSED-ACCT VALUE 'C'.\n 05 BALANCE PIC S9(6)V99 SIGN LEADING SEPARATE.\n 05 DAYS-PAST-DUE PIC 9(3).\n"
|
| 779 |
+
}
|
| 780 |
+
},
|
| 781 |
+
{
|
| 782 |
+
"tool_name": "parse_copybook_layout",
|
| 783 |
+
"arguments": {
|
| 784 |
+
"filename": "ACCOUNT_REC.cpy"
|
| 785 |
+
},
|
| 786 |
+
"reward": 0.03,
|
| 787 |
+
"done": false,
|
| 788 |
+
"result": {
|
| 789 |
+
"ok": true,
|
| 790 |
+
"filename": "ACCOUNT_REC.cpy",
|
| 791 |
+
"record_name": "ACCOUNT-RECORD",
|
| 792 |
+
"total_width": 19,
|
| 793 |
+
"fields": [
|
| 794 |
+
{
|
| 795 |
+
"name": "ACCOUNT-ID",
|
| 796 |
+
"start": 0,
|
| 797 |
+
"end": 6,
|
| 798 |
+
"length": 6,
|
| 799 |
+
"pic": "X(6)",
|
| 800 |
+
"python_type": "str"
|
| 801 |
+
},
|
| 802 |
+
{
|
| 803 |
+
"name": "STATUS-CODE",
|
| 804 |
+
"start": 6,
|
| 805 |
+
"end": 7,
|
| 806 |
+
"length": 1,
|
| 807 |
+
"pic": "X",
|
| 808 |
+
"python_type": "str",
|
| 809 |
+
"level_88": {
|
| 810 |
+
"ACTIVE-ACCT": "A",
|
| 811 |
+
"FROZEN-ACCT": "F",
|
| 812 |
+
"CLOSED-ACCT": "C"
|
| 813 |
+
}
|
| 814 |
+
},
|
| 815 |
+
{
|
| 816 |
+
"name": "BALANCE",
|
| 817 |
+
"start": 7,
|
| 818 |
+
"end": 16,
|
| 819 |
+
"length": 9,
|
| 820 |
+
"pic": "S9(6)V99 SIGN LEADING SEPARATE",
|
| 821 |
+
"python_type": "Decimal",
|
| 822 |
+
"scale": 2
|
| 823 |
+
},
|
| 824 |
+
{
|
| 825 |
+
"name": "DAYS-PAST-DUE",
|
| 826 |
+
"start": 16,
|
| 827 |
+
"end": 19,
|
| 828 |
+
"length": 3,
|
| 829 |
+
"pic": "9(3)",
|
| 830 |
+
"python_type": "int"
|
| 831 |
+
}
|
| 832 |
+
]
|
| 833 |
+
}
|
| 834 |
+
},
|
| 835 |
+
{
|
| 836 |
+
"tool_name": "inspect_business_rules",
|
| 837 |
+
"arguments": {},
|
| 838 |
+
"reward": 0.01,
|
| 839 |
+
"done": false,
|
| 840 |
+
"result": {
|
| 841 |
+
"ok": true,
|
| 842 |
+
"rules": [
|
| 843 |
+
"CLOSED-ACCT and FROZEN-ACCT are level-88 names over STATUS-CODE.",
|
| 844 |
+
"Closed and frozen branches precede delinquency and overdrawn checks."
|
| 845 |
+
]
|
| 846 |
+
}
|
| 847 |
+
},
|
| 848 |
+
{
|
| 849 |
+
"tool_name": "write_python_solution",
|
| 850 |
+
"arguments": {
|
| 851 |
+
"code_chars": 607
|
| 852 |
+
},
|
| 853 |
+
"reward": 0.02,
|
| 854 |
+
"done": false,
|
| 855 |
+
"result": {
|
| 856 |
+
"ok": true,
|
| 857 |
+
"draft_id": 1,
|
| 858 |
+
"syntax_ok": true,
|
| 859 |
+
"safety_ok": true,
|
| 860 |
+
"error": null
|
| 861 |
+
}
|
| 862 |
+
},
|
| 863 |
+
{
|
| 864 |
+
"tool_name": "run_visible_tests",
|
| 865 |
+
"arguments": {
|
| 866 |
+
"draft_id": 1
|
| 867 |
+
},
|
| 868 |
+
"reward": 0.05,
|
| 869 |
+
"done": false,
|
| 870 |
+
"result": {
|
| 871 |
+
"ok": true,
|
| 872 |
+
"draft_id": 1,
|
| 873 |
+
"passed": 3,
|
| 874 |
+
"total": 3,
|
| 875 |
+
"pass_rate": 1.0,
|
| 876 |
+
"syntax_ok": true,
|
| 877 |
+
"safety_ok": true,
|
| 878 |
+
"interface_ok": true,
|
| 879 |
+
"timed_out": false,
|
| 880 |
+
"error": null,
|
| 881 |
+
"failures": []
|
| 882 |
+
}
|
| 883 |
+
},
|
| 884 |
+
{
|
| 885 |
+
"tool_name": "submit_final",
|
| 886 |
+
"arguments": {
|
| 887 |
+
"draft_id": 1
|
| 888 |
+
},
|
| 889 |
+
"reward": 1.0,
|
| 890 |
+
"done": true,
|
| 891 |
+
"result": {
|
| 892 |
+
"ok": true,
|
| 893 |
+
"accepted": true,
|
| 894 |
+
"episode_done": true,
|
| 895 |
+
"public_score": 1.0,
|
| 896 |
+
"components": {
|
| 897 |
+
"hidden_correctness": 1.0,
|
| 898 |
+
"fresh_correctness": 1.0,
|
| 899 |
+
"interface_contract": 1.0,
|
| 900 |
+
"type_and_layout_fidelity": 1.0,
|
| 901 |
+
"anti_hardcoding": 1.0,
|
| 902 |
+
"safety": 1.0
|
| 903 |
+
},
|
| 904 |
+
"hidden_passed": 3,
|
| 905 |
+
"hidden_total": 3,
|
| 906 |
+
"fresh_passed": 6,
|
| 907 |
+
"fresh_total": 6,
|
| 908 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 909 |
+
}
|
| 910 |
+
}
|
| 911 |
+
]
|
| 912 |
+
},
|
| 913 |
+
{
|
| 914 |
+
"policy": "oracle",
|
| 915 |
+
"task_id": "invoice_occurs_001",
|
| 916 |
+
"family_id": "invoice_occurs_totals",
|
| 917 |
+
"ticket": {
|
| 918 |
+
"task_id": "invoice_occurs_001",
|
| 919 |
+
"family_id": "invoice_occurs_totals",
|
| 920 |
+
"domain": "invoicing",
|
| 921 |
+
"ticket": "Migrate INVTOTAL.cbl and TAXRATE.cbl. Preserve OCCURS stride parsing, item-count bounds, tax-code lookup behavior, and fixed-width total output.",
|
| 922 |
+
"available_files": [
|
| 923 |
+
"INVTOTAL.cbl",
|
| 924 |
+
"TAXRATE.cbl"
|
| 925 |
+
],
|
| 926 |
+
"available_copybooks": [
|
| 927 |
+
"INVOICE_REC.cpy",
|
| 928 |
+
"TAX_CODE.cpy"
|
| 929 |
+
],
|
| 930 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 931 |
+
"visible_tests": 3,
|
| 932 |
+
"hidden_tests": 4,
|
| 933 |
+
"input_width": 44,
|
| 934 |
+
"output_width": 18,
|
| 935 |
+
"max_steps": 12,
|
| 936 |
+
"allowed_tools": [
|
| 937 |
+
"read_cobol_file",
|
| 938 |
+
"read_copybook",
|
| 939 |
+
"parse_copybook_layout",
|
| 940 |
+
"inspect_business_rules",
|
| 941 |
+
"write_python_solution",
|
| 942 |
+
"run_visible_tests",
|
| 943 |
+
"inspect_diff",
|
| 944 |
+
"submit_final"
|
| 945 |
+
]
|
| 946 |
+
},
|
| 947 |
+
"visible": {
|
| 948 |
+
"passed": 3,
|
| 949 |
+
"total": 3,
|
| 950 |
+
"pass_rate": 1.0,
|
| 951 |
+
"failures": []
|
| 952 |
+
},
|
| 953 |
+
"final": {
|
| 954 |
+
"public_score": 1.0,
|
| 955 |
+
"accepted": true,
|
| 956 |
+
"components": {
|
| 957 |
+
"hidden_correctness": 1.0,
|
| 958 |
+
"fresh_correctness": 1.0,
|
| 959 |
+
"interface_contract": 1.0,
|
| 960 |
+
"type_and_layout_fidelity": 1.0,
|
| 961 |
+
"anti_hardcoding": 1.0,
|
| 962 |
+
"safety": 1.0
|
| 963 |
+
},
|
| 964 |
+
"hidden_passed": 4,
|
| 965 |
+
"hidden_total": 4,
|
| 966 |
+
"fresh_passed": 6,
|
| 967 |
+
"fresh_total": 6
|
| 968 |
+
},
|
| 969 |
+
"steps": [
|
| 970 |
+
{
|
| 971 |
+
"tool_name": "read_cobol_file",
|
| 972 |
+
"arguments": {
|
| 973 |
+
"filename": "INVTOTAL.cbl"
|
| 974 |
+
},
|
| 975 |
+
"reward": 0.02,
|
| 976 |
+
"done": false,
|
| 977 |
+
"result": {
|
| 978 |
+
"ok": true,
|
| 979 |
+
"filename": "INVTOTAL.cbl",
|
| 980 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. INVTOTAL.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY INVOICE_REC.\n COPY TAX_CODE.\n 01 IDX PIC 9 VALUE 0.\n 01 LINE-AMOUNT PIC 9(7)V99 VALUE 0.\n 01 TAX-AMOUNT PIC 9(7)V99 VALUE 0.\n 01 TAX-PERCENT PIC 9V9999 VALUE 0.\n 01 INVOICE-TOTAL PIC 9(7)V99 VALUE 0.\n PROCEDURE DIVISION.\n PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > ITEM-COUNT\n COMPUTE LINE-AMOUNT ROUNDED = ITEM-QTY(IDX) * ITEM-PRICE(IDX)\n CALL 'TAXRATE' USING TAX-CODE(IDX) TAX-PERCENT\n COMPUTE TAX-AMOUNT ROUNDED = LINE-AMOUNT * TAX-PERCENT\n ADD TAX-AMOUNT TO LINE-AMOUNT\n ADD LINE-AMOUNT TO INVOICE-TOTAL\n END-PERFORM\n GOBACK.\n",
|
| 981 |
+
"truncated": false
|
| 982 |
+
}
|
| 983 |
+
},
|
| 984 |
+
{
|
| 985 |
+
"tool_name": "read_cobol_file",
|
| 986 |
+
"arguments": {
|
| 987 |
+
"filename": "TAXRATE.cbl"
|
| 988 |
+
},
|
| 989 |
+
"reward": 0.02,
|
| 990 |
+
"done": false,
|
| 991 |
+
"result": {
|
| 992 |
+
"ok": true,
|
| 993 |
+
"filename": "TAXRATE.cbl",
|
| 994 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. TAXRATE.\n DATA DIVISION.\n LINKAGE SECTION.\n 01 LK-TAX-CODE PIC X.\n 01 LK-TAX-PERCENT PIC 9V9999.\n PROCEDURE DIVISION USING LK-TAX-CODE LK-TAX-PERCENT.\n EVALUATE LK-TAX-CODE\n WHEN 'S' MOVE 0.0725 TO LK-TAX-PERCENT\n WHEN 'R' MOVE 0.0250 TO LK-TAX-PERCENT\n WHEN 'L' MOVE 0.1000 TO LK-TAX-PERCENT\n WHEN OTHER MOVE 0.0000 TO LK-TAX-PERCENT\n END-EVALUATE\n GOBACK.\n",
|
| 995 |
+
"truncated": false
|
| 996 |
+
}
|
| 997 |
+
},
|
| 998 |
+
{
|
| 999 |
+
"tool_name": "read_copybook",
|
| 1000 |
+
"arguments": {
|
| 1001 |
+
"filename": "INVOICE_REC.cpy"
|
| 1002 |
+
},
|
| 1003 |
+
"reward": 0.02,
|
| 1004 |
+
"done": false,
|
| 1005 |
+
"result": {
|
| 1006 |
+
"ok": true,
|
| 1007 |
+
"filename": "INVOICE_REC.cpy",
|
| 1008 |
+
"content": " 01 INVOICE-RECORD.\n 05 INVOICE-ID PIC X(6).\n 05 ITEM-COUNT PIC 9(2).\n 05 LINE-ITEM OCCURS 4 TIMES.\n 10 ITEM-QTY PIC 9(2).\n 10 ITEM-PRICE PIC 9(4)V99.\n 10 TAX-CODE PIC X.\n"
|
| 1009 |
+
}
|
| 1010 |
+
},
|
| 1011 |
+
{
|
| 1012 |
+
"tool_name": "parse_copybook_layout",
|
| 1013 |
+
"arguments": {
|
| 1014 |
+
"filename": "INVOICE_REC.cpy"
|
| 1015 |
+
},
|
| 1016 |
+
"reward": 0.03,
|
| 1017 |
+
"done": false,
|
| 1018 |
+
"result": {
|
| 1019 |
+
"ok": true,
|
| 1020 |
+
"filename": "INVOICE_REC.cpy",
|
| 1021 |
+
"record_name": "INVOICE-RECORD",
|
| 1022 |
+
"total_width": 44,
|
| 1023 |
+
"fields": [
|
| 1024 |
+
{
|
| 1025 |
+
"name": "INVOICE-ID",
|
| 1026 |
+
"start": 0,
|
| 1027 |
+
"end": 6,
|
| 1028 |
+
"length": 6,
|
| 1029 |
+
"pic": "X(6)",
|
| 1030 |
+
"python_type": "str"
|
| 1031 |
+
},
|
| 1032 |
+
{
|
| 1033 |
+
"name": "ITEM-COUNT",
|
| 1034 |
+
"start": 6,
|
| 1035 |
+
"end": 8,
|
| 1036 |
+
"length": 2,
|
| 1037 |
+
"pic": "9(2)",
|
| 1038 |
+
"python_type": "int"
|
| 1039 |
+
},
|
| 1040 |
+
{
|
| 1041 |
+
"name": "LINE-ITEMS",
|
| 1042 |
+
"start": 8,
|
| 1043 |
+
"end": 44,
|
| 1044 |
+
"length": 36,
|
| 1045 |
+
"pic": "OCCURS 4 TIMES",
|
| 1046 |
+
"python_type": "group",
|
| 1047 |
+
"occurs": 4,
|
| 1048 |
+
"stride": 9
|
| 1049 |
+
}
|
| 1050 |
+
]
|
| 1051 |
+
}
|
| 1052 |
+
},
|
| 1053 |
+
{
|
| 1054 |
+
"tool_name": "read_copybook",
|
| 1055 |
+
"arguments": {
|
| 1056 |
+
"filename": "TAX_CODE.cpy"
|
| 1057 |
+
},
|
| 1058 |
+
"reward": 0.02,
|
| 1059 |
+
"done": false,
|
| 1060 |
+
"result": {
|
| 1061 |
+
"ok": true,
|
| 1062 |
+
"filename": "TAX_CODE.cpy",
|
| 1063 |
+
"content": " 01 TAX-CODE-TABLE.\n 05 TAX-CODE-ENTRY OCCURS 4 TIMES.\n 10 TAX-CODE-KEY PIC X.\n 10 TAX-RATE PIC 9V9999.\n"
|
| 1064 |
+
}
|
| 1065 |
+
},
|
| 1066 |
+
{
|
| 1067 |
+
"tool_name": "parse_copybook_layout",
|
| 1068 |
+
"arguments": {
|
| 1069 |
+
"filename": "TAX_CODE.cpy"
|
| 1070 |
+
},
|
| 1071 |
+
"reward": 0.03,
|
| 1072 |
+
"done": false,
|
| 1073 |
+
"result": {
|
| 1074 |
+
"ok": true,
|
| 1075 |
+
"filename": "TAX_CODE.cpy",
|
| 1076 |
+
"record_name": "INVOICE-RECORD",
|
| 1077 |
+
"total_width": 44,
|
| 1078 |
+
"fields": [
|
| 1079 |
+
{
|
| 1080 |
+
"name": "INVOICE-ID",
|
| 1081 |
+
"start": 0,
|
| 1082 |
+
"end": 6,
|
| 1083 |
+
"length": 6,
|
| 1084 |
+
"pic": "X(6)",
|
| 1085 |
+
"python_type": "str"
|
| 1086 |
+
},
|
| 1087 |
+
{
|
| 1088 |
+
"name": "ITEM-COUNT",
|
| 1089 |
+
"start": 6,
|
| 1090 |
+
"end": 8,
|
| 1091 |
+
"length": 2,
|
| 1092 |
+
"pic": "9(2)",
|
| 1093 |
+
"python_type": "int"
|
| 1094 |
+
},
|
| 1095 |
+
{
|
| 1096 |
+
"name": "LINE-ITEMS",
|
| 1097 |
+
"start": 8,
|
| 1098 |
+
"end": 44,
|
| 1099 |
+
"length": 36,
|
| 1100 |
+
"pic": "OCCURS 4 TIMES",
|
| 1101 |
+
"python_type": "group",
|
| 1102 |
+
"occurs": 4,
|
| 1103 |
+
"stride": 9
|
| 1104 |
+
}
|
| 1105 |
+
]
|
| 1106 |
+
}
|
| 1107 |
+
},
|
| 1108 |
+
{
|
| 1109 |
+
"tool_name": "inspect_business_rules",
|
| 1110 |
+
"arguments": {},
|
| 1111 |
+
"reward": 0.01,
|
| 1112 |
+
"done": false,
|
| 1113 |
+
"result": {
|
| 1114 |
+
"ok": true,
|
| 1115 |
+
"rules": [
|
| 1116 |
+
"LINE-ITEM OCCURS 4 TIMES with a 9-byte stride.",
|
| 1117 |
+
"Only the first ITEM-COUNT entries contribute to the total.",
|
| 1118 |
+
"Tax codes are resolved through the separate TAXRATE program; handle all code branches found there.",
|
| 1119 |
+
"Keep the total, item count, and high/low flag in the fixed-width output layout."
|
| 1120 |
+
]
|
| 1121 |
+
}
|
| 1122 |
+
},
|
| 1123 |
+
{
|
| 1124 |
+
"tool_name": "write_python_solution",
|
| 1125 |
+
"arguments": {
|
| 1126 |
+
"code_chars": 984
|
| 1127 |
+
},
|
| 1128 |
+
"reward": 0.02,
|
| 1129 |
+
"done": false,
|
| 1130 |
+
"result": {
|
| 1131 |
+
"ok": true,
|
| 1132 |
+
"draft_id": 1,
|
| 1133 |
+
"syntax_ok": true,
|
| 1134 |
+
"safety_ok": true,
|
| 1135 |
+
"error": null
|
| 1136 |
+
}
|
| 1137 |
+
},
|
| 1138 |
+
{
|
| 1139 |
+
"tool_name": "run_visible_tests",
|
| 1140 |
+
"arguments": {
|
| 1141 |
+
"draft_id": 1
|
| 1142 |
+
},
|
| 1143 |
+
"reward": 0.05,
|
| 1144 |
+
"done": false,
|
| 1145 |
+
"result": {
|
| 1146 |
+
"ok": true,
|
| 1147 |
+
"draft_id": 1,
|
| 1148 |
+
"passed": 3,
|
| 1149 |
+
"total": 3,
|
| 1150 |
+
"pass_rate": 1.0,
|
| 1151 |
+
"syntax_ok": true,
|
| 1152 |
+
"safety_ok": true,
|
| 1153 |
+
"interface_ok": true,
|
| 1154 |
+
"timed_out": false,
|
| 1155 |
+
"error": null,
|
| 1156 |
+
"failures": []
|
| 1157 |
+
}
|
| 1158 |
+
},
|
| 1159 |
+
{
|
| 1160 |
+
"tool_name": "submit_final",
|
| 1161 |
+
"arguments": {
|
| 1162 |
+
"draft_id": 1
|
| 1163 |
+
},
|
| 1164 |
+
"reward": 1.0,
|
| 1165 |
+
"done": true,
|
| 1166 |
+
"result": {
|
| 1167 |
+
"ok": true,
|
| 1168 |
+
"accepted": true,
|
| 1169 |
+
"episode_done": true,
|
| 1170 |
+
"public_score": 1.0,
|
| 1171 |
+
"components": {
|
| 1172 |
+
"hidden_correctness": 1.0,
|
| 1173 |
+
"fresh_correctness": 1.0,
|
| 1174 |
+
"interface_contract": 1.0,
|
| 1175 |
+
"type_and_layout_fidelity": 1.0,
|
| 1176 |
+
"anti_hardcoding": 1.0,
|
| 1177 |
+
"safety": 1.0
|
| 1178 |
+
},
|
| 1179 |
+
"hidden_passed": 4,
|
| 1180 |
+
"hidden_total": 4,
|
| 1181 |
+
"fresh_passed": 6,
|
| 1182 |
+
"fresh_total": 6,
|
| 1183 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 1184 |
+
}
|
| 1185 |
+
}
|
| 1186 |
+
]
|
| 1187 |
+
},
|
| 1188 |
+
{
|
| 1189 |
+
"policy": "oracle",
|
| 1190 |
+
"task_id": "date_normalization_001",
|
| 1191 |
+
"family_id": "date_normalization",
|
| 1192 |
+
"ticket": {
|
| 1193 |
+
"task_id": "date_normalization_001",
|
| 1194 |
+
"family_id": "date_normalization",
|
| 1195 |
+
"domain": "claims and billing",
|
| 1196 |
+
"ticket": "Migrate DATENORM.cbl. Preserve legacy YYMMDD century-window rules and invalid-date behavior instead of blindly using modern date parsing.",
|
| 1197 |
+
"available_files": [
|
| 1198 |
+
"DATENORM.cbl"
|
| 1199 |
+
],
|
| 1200 |
+
"available_copybooks": [
|
| 1201 |
+
"POLICY_DATE.cpy"
|
| 1202 |
+
],
|
| 1203 |
+
"expected_callable": "migrate(input_record: str) -> str",
|
| 1204 |
+
"visible_tests": 3,
|
| 1205 |
+
"hidden_tests": 3,
|
| 1206 |
+
"input_width": 21,
|
| 1207 |
+
"output_width": 22,
|
| 1208 |
+
"max_steps": 12,
|
| 1209 |
+
"allowed_tools": [
|
| 1210 |
+
"read_cobol_file",
|
| 1211 |
+
"read_copybook",
|
| 1212 |
+
"parse_copybook_layout",
|
| 1213 |
+
"inspect_business_rules",
|
| 1214 |
+
"write_python_solution",
|
| 1215 |
+
"run_visible_tests",
|
| 1216 |
+
"inspect_diff",
|
| 1217 |
+
"submit_final"
|
| 1218 |
+
]
|
| 1219 |
+
},
|
| 1220 |
+
"visible": {
|
| 1221 |
+
"passed": 3,
|
| 1222 |
+
"total": 3,
|
| 1223 |
+
"pass_rate": 1.0,
|
| 1224 |
+
"failures": []
|
| 1225 |
+
},
|
| 1226 |
+
"final": {
|
| 1227 |
+
"public_score": 1.0,
|
| 1228 |
+
"accepted": true,
|
| 1229 |
+
"components": {
|
| 1230 |
+
"hidden_correctness": 1.0,
|
| 1231 |
+
"fresh_correctness": 1.0,
|
| 1232 |
+
"interface_contract": 1.0,
|
| 1233 |
+
"type_and_layout_fidelity": 1.0,
|
| 1234 |
+
"anti_hardcoding": 1.0,
|
| 1235 |
+
"safety": 1.0
|
| 1236 |
+
},
|
| 1237 |
+
"hidden_passed": 3,
|
| 1238 |
+
"hidden_total": 3,
|
| 1239 |
+
"fresh_passed": 6,
|
| 1240 |
+
"fresh_total": 6
|
| 1241 |
+
},
|
| 1242 |
+
"steps": [
|
| 1243 |
+
{
|
| 1244 |
+
"tool_name": "read_cobol_file",
|
| 1245 |
+
"arguments": {
|
| 1246 |
+
"filename": "DATENORM.cbl"
|
| 1247 |
+
},
|
| 1248 |
+
"reward": 0.02,
|
| 1249 |
+
"done": false,
|
| 1250 |
+
"result": {
|
| 1251 |
+
"ok": true,
|
| 1252 |
+
"filename": "DATENORM.cbl",
|
| 1253 |
+
"content": " IDENTIFICATION DIVISION.\n PROGRAM-ID. DATENORM.\n DATA DIVISION.\n WORKING-STORAGE SECTION.\n COPY POLICY_DATE.\n PROCEDURE DIVISION.\n IF RAW-YY >= WINDOW-YEAR\n MOVE 19 TO OUT-CENTURY\n ELSE\n MOVE 20 TO OUT-CENTURY\n END-IF\n PERFORM VALIDATE-MONTH-DAY\n GOBACK.\n",
|
| 1254 |
+
"truncated": false
|
| 1255 |
+
}
|
| 1256 |
+
},
|
| 1257 |
+
{
|
| 1258 |
+
"tool_name": "read_copybook",
|
| 1259 |
+
"arguments": {
|
| 1260 |
+
"filename": "POLICY_DATE.cpy"
|
| 1261 |
+
},
|
| 1262 |
+
"reward": 0.02,
|
| 1263 |
+
"done": false,
|
| 1264 |
+
"result": {
|
| 1265 |
+
"ok": true,
|
| 1266 |
+
"filename": "POLICY_DATE.cpy",
|
| 1267 |
+
"content": " 01 POLICY-DATE-RECORD.\n 05 POLICY-ID PIC X(6).\n 05 RAW-DATE PIC 9(6).\n 05 WINDOW-YEAR PIC 9(2).\n 05 AMOUNT PIC 9(5)V99.\n"
|
| 1268 |
+
}
|
| 1269 |
+
},
|
| 1270 |
+
{
|
| 1271 |
+
"tool_name": "parse_copybook_layout",
|
| 1272 |
+
"arguments": {
|
| 1273 |
+
"filename": "POLICY_DATE.cpy"
|
| 1274 |
+
},
|
| 1275 |
+
"reward": 0.03,
|
| 1276 |
+
"done": false,
|
| 1277 |
+
"result": {
|
| 1278 |
+
"ok": true,
|
| 1279 |
+
"filename": "POLICY_DATE.cpy",
|
| 1280 |
+
"record_name": "POLICY-DATE-RECORD",
|
| 1281 |
+
"total_width": 21,
|
| 1282 |
+
"fields": [
|
| 1283 |
+
{
|
| 1284 |
+
"name": "POLICY-ID",
|
| 1285 |
+
"start": 0,
|
| 1286 |
+
"end": 6,
|
| 1287 |
+
"length": 6,
|
| 1288 |
+
"pic": "X(6)",
|
| 1289 |
+
"python_type": "str"
|
| 1290 |
+
},
|
| 1291 |
+
{
|
| 1292 |
+
"name": "RAW-DATE",
|
| 1293 |
+
"start": 6,
|
| 1294 |
+
"end": 12,
|
| 1295 |
+
"length": 6,
|
| 1296 |
+
"pic": "9(6)",
|
| 1297 |
+
"python_type": "str"
|
| 1298 |
+
},
|
| 1299 |
+
{
|
| 1300 |
+
"name": "WINDOW-YEAR",
|
| 1301 |
+
"start": 12,
|
| 1302 |
+
"end": 14,
|
| 1303 |
+
"length": 2,
|
| 1304 |
+
"pic": "9(2)",
|
| 1305 |
+
"python_type": "int"
|
| 1306 |
+
},
|
| 1307 |
+
{
|
| 1308 |
+
"name": "AMOUNT",
|
| 1309 |
+
"start": 14,
|
| 1310 |
+
"end": 21,
|
| 1311 |
+
"length": 7,
|
| 1312 |
+
"pic": "9(5)V99",
|
| 1313 |
+
"python_type": "Decimal",
|
| 1314 |
+
"scale": 2
|
| 1315 |
+
}
|
| 1316 |
+
]
|
| 1317 |
+
}
|
| 1318 |
+
},
|
| 1319 |
+
{
|
| 1320 |
+
"tool_name": "inspect_business_rules",
|
| 1321 |
+
"arguments": {},
|
| 1322 |
+
"reward": 0.01,
|
| 1323 |
+
"done": false,
|
| 1324 |
+
"result": {
|
| 1325 |
+
"ok": true,
|
| 1326 |
+
"rules": [
|
| 1327 |
+
"RAW-DATE is YYMMDD.",
|
| 1328 |
+
"If YY >= WINDOW-YEAR, century is 19; otherwise century is 20.",
|
| 1329 |
+
"Invalid dates output 00000000 and valid flag N; amount is preserved."
|
| 1330 |
+
]
|
| 1331 |
+
}
|
| 1332 |
+
},
|
| 1333 |
+
{
|
| 1334 |
+
"tool_name": "write_python_solution",
|
| 1335 |
+
"arguments": {
|
| 1336 |
+
"code_chars": 813
|
| 1337 |
+
},
|
| 1338 |
+
"reward": 0.02,
|
| 1339 |
+
"done": false,
|
| 1340 |
+
"result": {
|
| 1341 |
+
"ok": true,
|
| 1342 |
+
"draft_id": 1,
|
| 1343 |
+
"syntax_ok": true,
|
| 1344 |
+
"safety_ok": true,
|
| 1345 |
+
"error": null
|
| 1346 |
+
}
|
| 1347 |
+
},
|
| 1348 |
+
{
|
| 1349 |
+
"tool_name": "run_visible_tests",
|
| 1350 |
+
"arguments": {
|
| 1351 |
+
"draft_id": 1
|
| 1352 |
+
},
|
| 1353 |
+
"reward": 0.05,
|
| 1354 |
+
"done": false,
|
| 1355 |
+
"result": {
|
| 1356 |
+
"ok": true,
|
| 1357 |
+
"draft_id": 1,
|
| 1358 |
+
"passed": 3,
|
| 1359 |
+
"total": 3,
|
| 1360 |
+
"pass_rate": 1.0,
|
| 1361 |
+
"syntax_ok": true,
|
| 1362 |
+
"safety_ok": true,
|
| 1363 |
+
"interface_ok": true,
|
| 1364 |
+
"timed_out": false,
|
| 1365 |
+
"error": null,
|
| 1366 |
+
"failures": []
|
| 1367 |
+
}
|
| 1368 |
+
},
|
| 1369 |
+
{
|
| 1370 |
+
"tool_name": "submit_final",
|
| 1371 |
+
"arguments": {
|
| 1372 |
+
"draft_id": 1
|
| 1373 |
+
},
|
| 1374 |
+
"reward": 1.0,
|
| 1375 |
+
"done": true,
|
| 1376 |
+
"result": {
|
| 1377 |
+
"ok": true,
|
| 1378 |
+
"accepted": true,
|
| 1379 |
+
"episode_done": true,
|
| 1380 |
+
"public_score": 1.0,
|
| 1381 |
+
"components": {
|
| 1382 |
+
"hidden_correctness": 1.0,
|
| 1383 |
+
"fresh_correctness": 1.0,
|
| 1384 |
+
"interface_contract": 1.0,
|
| 1385 |
+
"type_and_layout_fidelity": 1.0,
|
| 1386 |
+
"anti_hardcoding": 1.0,
|
| 1387 |
+
"safety": 1.0
|
| 1388 |
+
},
|
| 1389 |
+
"hidden_passed": 3,
|
| 1390 |
+
"hidden_total": 3,
|
| 1391 |
+
"fresh_passed": 6,
|
| 1392 |
+
"fresh_total": 6,
|
| 1393 |
+
"notes": "Hidden and fresh case details are not revealed to the agent."
|
| 1394 |
+
}
|
| 1395 |
+
}
|
| 1396 |
+
]
|
| 1397 |
+
}
|
| 1398 |
+
]
|
| 1399 |
+
}
|
outputs/evals/score_summary.json
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"policies": {
|
| 3 |
+
"blank_width": {
|
| 4 |
+
"mean_public_score": 0.17666666666666667,
|
| 5 |
+
"accepted_count": 0,
|
| 6 |
+
"task_count": 6
|
| 7 |
+
},
|
| 8 |
+
"identity": {
|
| 9 |
+
"mean_public_score": 0.15,
|
| 10 |
+
"accepted_count": 0,
|
| 11 |
+
"task_count": 6
|
| 12 |
+
},
|
| 13 |
+
"oracle-model": {
|
| 14 |
+
"mean_public_score": 1.0,
|
| 15 |
+
"accepted_count": 6,
|
| 16 |
+
"task_count": 6,
|
| 17 |
+
"role": "oracle_sanity"
|
| 18 |
+
},
|
| 19 |
+
"base Qwen3-14B": {
|
| 20 |
+
"mean_public_score": 0.532,
|
| 21 |
+
"accepted_count": 2,
|
| 22 |
+
"task_count": 6,
|
| 23 |
+
"role": "base_model_before_sft"
|
| 24 |
+
},
|
| 25 |
+
"trained Qwen3-14B LoRA SFT": {
|
| 26 |
+
"mean_public_score": 0.7971166666666667,
|
| 27 |
+
"accepted_count": 4,
|
| 28 |
+
"task_count": 6,
|
| 29 |
+
"role": "trained_model_after_sft",
|
| 30 |
+
"model": "Qwen/Qwen3-14B",
|
| 31 |
+
"method": "Hugging Face TRL LoRA SFT"
|
| 32 |
+
}
|
| 33 |
+
},
|
| 34 |
+
"task_scores": {
|
| 35 |
+
"payroll_net_pay_001": {
|
| 36 |
+
"identity": 0.15,
|
| 37 |
+
"blank_width": 0.15,
|
| 38 |
+
"oracle_model": 1.0,
|
| 39 |
+
"base_qwen3_14b": 0.472
|
| 40 |
+
},
|
| 41 |
+
"customer_format_001": {
|
| 42 |
+
"identity": 0.15,
|
| 43 |
+
"blank_width": 0.15,
|
| 44 |
+
"oracle_model": 1.0,
|
| 45 |
+
"base_qwen3_14b": 0.34
|
| 46 |
+
},
|
| 47 |
+
"claims_eligibility_001": {
|
| 48 |
+
"identity": 0.15,
|
| 49 |
+
"blank_width": 0.23,
|
| 50 |
+
"oracle_model": 1.0,
|
| 51 |
+
"base_qwen3_14b": 1.0
|
| 52 |
+
},
|
| 53 |
+
"account_status_001": {
|
| 54 |
+
"identity": 0.15,
|
| 55 |
+
"blank_width": 0.23,
|
| 56 |
+
"oracle_model": 1.0,
|
| 57 |
+
"base_qwen3_14b": 1.0
|
| 58 |
+
},
|
| 59 |
+
"invoice_occurs_001": {
|
| 60 |
+
"identity": 0.15,
|
| 61 |
+
"blank_width": 0.15,
|
| 62 |
+
"oracle_model": 1.0,
|
| 63 |
+
"base_qwen3_14b": 0.15
|
| 64 |
+
},
|
| 65 |
+
"date_normalization_001": {
|
| 66 |
+
"identity": 0.15,
|
| 67 |
+
"blank_width": 0.15,
|
| 68 |
+
"oracle_model": 1.0,
|
| 69 |
+
"base_qwen3_14b": 0.23
|
| 70 |
+
}
|
| 71 |
+
},
|
| 72 |
+
"judge_table": [
|
| 73 |
+
{
|
| 74 |
+
"policy": "blank_width",
|
| 75 |
+
"role": null,
|
| 76 |
+
"mean_public_score": 0.17666666666666667,
|
| 77 |
+
"accepted_count": 0,
|
| 78 |
+
"task_count": 6
|
| 79 |
+
},
|
| 80 |
+
{
|
| 81 |
+
"policy": "identity",
|
| 82 |
+
"role": null,
|
| 83 |
+
"mean_public_score": 0.15,
|
| 84 |
+
"accepted_count": 0,
|
| 85 |
+
"task_count": 6
|
| 86 |
+
},
|
| 87 |
+
{
|
| 88 |
+
"policy": "oracle-model",
|
| 89 |
+
"role": "oracle_sanity",
|
| 90 |
+
"mean_public_score": 1.0,
|
| 91 |
+
"accepted_count": 6,
|
| 92 |
+
"task_count": 6
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"policy": "base Qwen3-14B",
|
| 96 |
+
"role": "base_model_before_sft",
|
| 97 |
+
"mean_public_score": 0.532,
|
| 98 |
+
"accepted_count": 2,
|
| 99 |
+
"task_count": 6
|
| 100 |
+
},
|
| 101 |
+
{
|
| 102 |
+
"policy": "trained Qwen3-14B LoRA SFT",
|
| 103 |
+
"role": "trained_model_after_sft",
|
| 104 |
+
"mean_public_score": 0.7971166666666667,
|
| 105 |
+
"accepted_count": 4,
|
| 106 |
+
"task_count": 6
|
| 107 |
+
}
|
| 108 |
+
],
|
| 109 |
+
"training_evidence": {
|
| 110 |
+
"model": "Qwen/Qwen3-14B",
|
| 111 |
+
"method": "Hugging Face TRL LoRA SFT",
|
| 112 |
+
"dataset_examples": 15,
|
| 113 |
+
"loss_first": 1.135,
|
| 114 |
+
"loss_last": 0.1924,
|
| 115 |
+
"mean_token_accuracy_first": 0.7938,
|
| 116 |
+
"mean_token_accuracy_last": 0.9483,
|
| 117 |
+
"base_mean_public_score": 0.532,
|
| 118 |
+
"trained_mean_public_score": 0.7971166666666667,
|
| 119 |
+
"base_accepted_count": 2,
|
| 120 |
+
"trained_accepted_count": 4,
|
| 121 |
+
"task_count": 6
|
| 122 |
+
},
|
| 123 |
+
"training_targets": [],
|
| 124 |
+
"evidence_notes": [
|
| 125 |
+
"missing rollout artifact: outputs/evals/azure_gpt54mini_zeroshot_rollouts.json",
|
| 126 |
+
"missing rollout artifact: outputs/evals/azure_gpt54mini_repair1_rollouts.json",
|
| 127 |
+
"historical artifact retained outside current score summary: outputs/evals/historical/azure_gpt54mini_payroll_probe.json",
|
| 128 |
+
"historical artifact retained outside current score summary: outputs/evals/historical/azure_gpt54mini_repair1_rollouts.json",
|
| 129 |
+
"historical artifact retained outside current score summary: outputs/evals/historical/azure_gpt54mini_zeroshot_rollouts.json"
|
| 130 |
+
]
|
| 131 |
+
}
|
outputs/training/hf_job_qwen3_14b_logs.txt
ADDED
|
@@ -0,0 +1,797 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 0 |
0%| | 0/20 [00:00<?, ?it/s][A
|
|
|
|
| 1 |
5%|▌ | 1/20 [00:06<02:07, 6.73s/it][A
|
|
|
|
| 2 |
|
|
|
|
|
|
|
| 3 |
5%|▌ | 1/20 [00:06<02:07, 6.73s/it][A
|
|
|
|
| 4 |
10%|█ | 2/20 [00:12<01:48, 6.04s/it][A
|
|
|
|
| 5 |
|
|
|
|
|
|
|
| 6 |
10%|█ | 2/20 [00:12<01:48, 6.04s/it][A
|
|
|
|
| 7 |
15%|█▌ | 3/20 [00:17<01:38, 5.79s/it][A
|
|
|
|
|
|
|
| 8 |
|
|
|
|
| 9 |
15%|█▌ | 3/20 [00:17<01:38, 5.79s/it][A
|
|
|
|
| 10 |
20%|██ | 4/20 [00:22<01:27, 5.45s/it][A
|
|
|
|
|
|
|
| 11 |
|
|
|
|
| 12 |
20%|██ | 4/20 [00:22<01:27, 5.45s/it][A
|
|
|
|
| 13 |
25%|██▌ | 5/20 [00:29<01:27, 5.85s/it][A
|
|
|
|
| 14 |
|
|
|
|
|
|
|
| 15 |
25%|██▌ | 5/20 [00:29<01:27, 5.85s/it][A
|
|
|
|
| 16 |
30%|███ | 6/20 [00:34<01:19, 5.70s/it][A
|
|
|
|
| 17 |
|
|
|
|
|
|
|
| 18 |
30%|███ | 6/20 [00:34<01:19, 5.70s/it][A
|
|
|
|
| 19 |
35%|███▌ | 7/20 [00:40<01:16, 5.90s/it][A
|
|
|
|
| 20 |
|
|
|
|
|
|
|
| 21 |
35%|███▌ | 7/20 [00:40<01:16, 5.90s/it][A
|
|
|
|
| 22 |
40%|████ | 8/20 [00:45<01:05, 5.43s/it][A
|
|
|
|
| 23 |
|
|
|
|
|
|
|
| 24 |
40%|████ | 8/20 [00:45<01:05, 5.43s/it][A
|
|
|
|
| 25 |
45%|████▌ | 9/20 [00:52<01:06, 6.01s/it][A
|
|
|
|
| 26 |
|
|
|
|
|
|
|
| 27 |
45%|████▌ | 9/20 [00:52<01:06, 6.01s/it][A
|
|
|
|
| 28 |
50%|█████ | 10/20 [00:58<01:00, 6.01s/it][A
|
|
|
|
| 29 |
|
|
|
|
|
|
|
| 30 |
50%|█████ | 10/20 [00:58<01:00, 6.01s/it][A
|
|
|
|
| 31 |
55%|█████▌ | 11/20 [01:04<00:52, 5.83s/it][A
|
|
|
|
| 32 |
|
|
|
|
|
|
|
| 33 |
55%|█████▌ | 11/20 [01:04<00:52, 5.83s/it][A
|
|
|
|
| 34 |
60%|██████ | 12/20 [01:08<00:44, 5.53s/it][A
|
|
|
|
| 35 |
|
|
|
|
|
|
|
| 36 |
60%|██████ | 12/20 [01:08<00:44, 5.53s/it][A
|
|
|
|
| 37 |
65%|██████▌ | 13/20 [01:15<00:40, 5.82s/it][A
|
|
|
|
| 38 |
|
|
|
|
|
|
|
| 39 |
65%|██████▌ | 13/20 [01:15<00:40, 5.82s/it][A
|
|
|
|
| 40 |
70%|███████ | 14/20 [01:21<00:35, 5.86s/it][A
|
|
|
|
|
|
|
| 41 |
|
|
|
|
| 42 |
70%|███████ | 14/20 [01:21<00:35, 5.86s/it][A
|
|
|
|
| 43 |
75%|███████▌ | 15/20 [01:27<00:29, 5.88s/it][A
|
|
|
|
| 44 |
|
|
|
|
|
|
|
| 45 |
75%|███████▌ | 15/20 [01:27<00:29, 5.88s/it][A
|
|
|
|
| 46 |
80%|████████ | 16/20 [01:31<00:22, 5.50s/it][A
|
|
|
|
| 47 |
|
|
|
|
|
|
|
| 48 |
80%|████████ | 16/20 [01:31<00:22, 5.50s/it][A
|
|
|
|
| 49 |
85%|████████▌ | 17/20 [01:38<00:17, 5.81s/it][A
|
|
|
|
| 50 |
|
|
|
|
|
|
|
| 51 |
85%|████████▌ | 17/20 [01:38<00:17, 5.81s/it][A
|
|
|
|
| 52 |
90%|█████████ | 18/20 [01:44<00:12, 6.01s/it][A
|
|
|
|
| 53 |
|
|
|
|
|
|
|
| 54 |
90%|█████████ | 18/20 [01:44<00:12, 6.01s/it][A
|
|
|
|
| 55 |
95%|█████████▌| 19/20 [01:50<00:05, 5.93s/it][A
|
|
|
|
| 56 |
|
|
|
|
|
|
|
| 57 |
95%|█████████▌| 19/20 [01:50<00:05, 5.93s/it][A
|
|
|
|
|
|
|
|
|
|
| 58 |
|
|
|
|
|
|
|
| 59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Downloading numpy (15.9MiB)
|
| 2 |
+
Downloading pillow (6.8MiB)
|
| 3 |
+
Downloading nvidia-cuda-runtime (2.1MiB)
|
| 4 |
+
Downloading networkx (2.0MiB)
|
| 5 |
+
Downloading bitsandbytes (57.8MiB)
|
| 6 |
+
Downloading cuda-bindings (6.0MiB)
|
| 7 |
+
Downloading nvidia-cuda-nvrtc (86.0MiB)
|
| 8 |
+
Downloading fonttools (4.8MiB)
|
| 9 |
+
Downloading nvidia-cusparse (139.2MiB)
|
| 10 |
+
Downloading nvidia-nvshmem-cu13 (57.6MiB)
|
| 11 |
+
Downloading nvidia-nvjitlink (38.8MiB)
|
| 12 |
+
Downloading nvidia-cusparselt-cu13 (162.0MiB)
|
| 13 |
+
Downloading matplotlib (8.4MiB)
|
| 14 |
+
Downloading torch (506.1MiB)
|
| 15 |
+
Downloading pyarrow (46.6MiB)
|
| 16 |
+
Downloading nvidia-cudnn-cu13 (349.1MiB)
|
| 17 |
+
Downloading transformers (9.9MiB)
|
| 18 |
+
Downloading hf-xet (4.0MiB)
|
| 19 |
+
Downloading tokenizers (3.1MiB)
|
| 20 |
+
Downloading sympy (6.0MiB)
|
| 21 |
+
Downloading nvidia-cufft (204.2MiB)
|
| 22 |
+
Downloading triton (179.5MiB)
|
| 23 |
+
Downloading nvidia-cublas (403.5MiB)
|
| 24 |
+
Downloading nvidia-cuda-cupti (10.2MiB)
|
| 25 |
+
Downloading nvidia-curand (56.8MiB)
|
| 26 |
+
Downloading pandas (10.4MiB)
|
| 27 |
+
Downloading nvidia-nccl-cu13 (187.4MiB)
|
| 28 |
+
Downloading setuptools (1.0MiB)
|
| 29 |
+
Downloading nvidia-cusolver (191.6MiB)
|
| 30 |
+
Downloading nvidia-cufile (1.2MiB)
|
| 31 |
+
Downloading pygments (1.2MiB)
|
| 32 |
+
Downloading kiwisolver (1.4MiB)
|
| 33 |
+
Downloading aiohttp (1.7MiB)
|
| 34 |
+
Downloaded nvidia-cufile
|
| 35 |
+
Downloaded kiwisolver
|
| 36 |
+
Downloaded aiohttp
|
| 37 |
+
Downloaded nvidia-cuda-runtime
|
| 38 |
+
Downloaded pygments
|
| 39 |
+
Downloaded setuptools
|
| 40 |
+
Downloaded tokenizers
|
| 41 |
+
Downloaded networkx
|
| 42 |
+
Downloaded hf-xet
|
| 43 |
+
Downloaded fonttools
|
| 44 |
+
Downloaded cuda-bindings
|
| 45 |
+
Downloaded pillow
|
| 46 |
+
Downloaded matplotlib
|
| 47 |
+
Downloaded nvidia-cuda-cupti
|
| 48 |
+
Downloaded sympy
|
| 49 |
+
Downloaded numpy
|
| 50 |
+
Downloaded nvidia-nvjitlink
|
| 51 |
+
Downloaded pandas
|
| 52 |
+
Downloaded transformers
|
| 53 |
+
Downloaded nvidia-curand
|
| 54 |
+
Downloaded nvidia-nvshmem-cu13
|
| 55 |
+
Downloaded bitsandbytes
|
| 56 |
+
Downloaded nvidia-cuda-nvrtc
|
| 57 |
+
Downloaded pyarrow
|
| 58 |
+
Downloaded nvidia-cusparse
|
| 59 |
+
Downloaded nvidia-cusparselt-cu13
|
| 60 |
+
Downloaded nvidia-nccl-cu13
|
| 61 |
+
Downloaded nvidia-cusolver
|
| 62 |
+
Downloaded nvidia-cufft
|
| 63 |
+
Downloaded triton
|
| 64 |
+
Downloaded nvidia-cudnn-cu13
|
| 65 |
+
Downloaded nvidia-cublas
|
| 66 |
+
Downloaded torch
|
| 67 |
+
Installed 84 packages in 450ms
|
| 68 |
+
$ git clone https://github.com/ishangtxl/cobol-modernization-openenv.git /tmp/cobol-modernization-openenv
|
| 69 |
+
Cloning into '/tmp/cobol-modernization-openenv'...
|
| 70 |
+
$ /root/.cache/uv/builds-v0/.tmpQi62S5/bin/python -m pip install -U pip
|
| 71 |
+
Requirement already satisfied: pip in /usr/local/lib/python3.12/site-packages (25.0.1)
|
| 72 |
+
Collecting pip
|
| 73 |
+
Downloading pip-26.0.1-py3-none-any.whl.metadata (4.7 kB)
|
| 74 |
+
Downloading pip-26.0.1-py3-none-any.whl (1.8 MB)
|
| 75 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.8/1.8 MB 202.1 MB/s eta 0:00:00
|
| 76 |
+
Installing collected packages: pip
|
| 77 |
+
Attempting uninstall: pip
|
| 78 |
+
Found existing installation: pip 25.0.1
|
| 79 |
+
Not uninstalling pip at /usr/local/lib/python3.12/site-packages, outside environment /root/.cache/uv/builds-v0/.tmpQi62S5
|
| 80 |
+
Can't uninstall 'pip'. No files were found to uninstall.
|
| 81 |
+
Successfully installed pip-26.0.1
|
| 82 |
+
$ /root/.cache/uv/builds-v0/.tmpQi62S5/bin/python -m pip install -r legacy_cobol_env/training/requirements-gpu.txt
|
| 83 |
+
Requirement already satisfied: accelerate>=1.0.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from -r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (1.13.0)
|
| 84 |
+
Requirement already satisfied: bitsandbytes>=0.43.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from -r legacy_cobol_env/training/requirements-gpu.txt (line 2)) (0.49.2)
|
| 85 |
+
Requirement already satisfied: datasets>=3.0.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from -r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (4.8.4)
|
| 86 |
+
Requirement already satisfied: peft>=0.13.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from -r legacy_cobol_env/training/requirements-gpu.txt (line 4)) (0.19.1)
|
| 87 |
+
Requirement already satisfied: torch>=2.4.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from -r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (2.11.0)
|
| 88 |
+
Requirement already satisfied: transformers>=4.45.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from -r legacy_cobol_env/training/requirements-gpu.txt (line 6)) (5.6.2)
|
| 89 |
+
Requirement already satisfied: trl>=0.12.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from -r legacy_cobol_env/training/requirements-gpu.txt (line 7)) (1.2.0)
|
| 90 |
+
Requirement already satisfied: numpy>=1.17 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (2.4.4)
|
| 91 |
+
Requirement already satisfied: packaging>=20.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (26.2)
|
| 92 |
+
Requirement already satisfied: psutil in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (7.2.2)
|
| 93 |
+
Requirement already satisfied: pyyaml in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (6.0.3)
|
| 94 |
+
Requirement already satisfied: huggingface_hub>=0.21.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (1.12.0)
|
| 95 |
+
Requirement already satisfied: safetensors>=0.4.3 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (0.7.0)
|
| 96 |
+
Requirement already satisfied: filelock in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (3.29.0)
|
| 97 |
+
Requirement already satisfied: typing-extensions>=4.10.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (4.15.0)
|
| 98 |
+
Requirement already satisfied: setuptools<82 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (81.0.0)
|
| 99 |
+
Requirement already satisfied: sympy>=1.13.3 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (1.14.0)
|
| 100 |
+
Requirement already satisfied: networkx>=2.5.1 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (3.6.1)
|
| 101 |
+
Requirement already satisfied: jinja2 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (3.1.6)
|
| 102 |
+
Requirement already satisfied: fsspec>=0.8.5 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (2026.2.0)
|
| 103 |
+
Requirement already satisfied: cuda-toolkit==13.0.2 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (13.0.2)
|
| 104 |
+
Requirement already satisfied: cuda-bindings<14,>=13.0.3 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (13.2.0)
|
| 105 |
+
Requirement already satisfied: nvidia-cudnn-cu13==9.19.0.56 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (9.19.0.56)
|
| 106 |
+
Requirement already satisfied: nvidia-cusparselt-cu13==0.8.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (0.8.0)
|
| 107 |
+
Requirement already satisfied: nvidia-nccl-cu13==2.28.9 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (2.28.9)
|
| 108 |
+
Requirement already satisfied: nvidia-nvshmem-cu13==3.4.5 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (3.4.5)
|
| 109 |
+
Requirement already satisfied: triton==3.6.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (3.6.0)
|
| 110 |
+
Requirement already satisfied: nvidia-cublas==13.1.0.3.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (13.1.0.3)
|
| 111 |
+
Requirement already satisfied: nvidia-cuda-runtime==13.0.96.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (13.0.96)
|
| 112 |
+
Requirement already satisfied: nvidia-cufft==12.0.0.61.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (12.0.0.61)
|
| 113 |
+
Requirement already satisfied: nvidia-cufile==1.15.1.6.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (1.15.1.6)
|
| 114 |
+
Requirement already satisfied: nvidia-cuda-cupti==13.0.85.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (13.0.85)
|
| 115 |
+
Requirement already satisfied: nvidia-curand==10.4.0.35.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (10.4.0.35)
|
| 116 |
+
Requirement already satisfied: nvidia-cusolver==12.0.4.66.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (12.0.4.66)
|
| 117 |
+
Requirement already satisfied: nvidia-cusparse==12.6.3.3.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (12.6.3.3)
|
| 118 |
+
Requirement already satisfied: nvidia-nvjitlink==13.0.88.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (13.0.88)
|
| 119 |
+
Requirement already satisfied: nvidia-cuda-nvrtc==13.0.88.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (13.0.88)
|
| 120 |
+
Requirement already satisfied: nvidia-nvtx==13.0.85.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-toolkit[cublas,cudart,cufft,cufile,cupti,curand,cusolver,cusparse,nvjitlink,nvrtc,nvtx]==13.0.2; platform_system == "Linux"->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (13.0.85)
|
| 121 |
+
Requirement already satisfied: cuda-pathfinder~=1.1 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cuda-bindings<14,>=13.0.3->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (1.5.3)
|
| 122 |
+
Requirement already satisfied: pyarrow>=21.0.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (24.0.0)
|
| 123 |
+
Requirement already satisfied: dill<0.4.2,>=0.3.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (0.4.1)
|
| 124 |
+
Requirement already satisfied: pandas in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (3.0.2)
|
| 125 |
+
Requirement already satisfied: requests>=2.32.2 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (2.33.1)
|
| 126 |
+
Requirement already satisfied: httpx<1.0.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (0.28.1)
|
| 127 |
+
Requirement already satisfied: tqdm>=4.66.3 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (4.67.3)
|
| 128 |
+
Requirement already satisfied: xxhash in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (3.7.0)
|
| 129 |
+
Requirement already satisfied: multiprocess<0.70.20 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (0.70.19)
|
| 130 |
+
Requirement already satisfied: aiohttp!=4.0.0a0,!=4.0.0a1 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from fsspec[http]<=2026.2.0,>=2023.1.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (3.13.5)
|
| 131 |
+
Requirement already satisfied: anyio in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from httpx<1.0.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (4.13.0)
|
| 132 |
+
Requirement already satisfied: certifi in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from httpx<1.0.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (2026.4.22)
|
| 133 |
+
Requirement already satisfied: httpcore==1.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from httpx<1.0.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (1.0.9)
|
| 134 |
+
Requirement already satisfied: idna in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from httpx<1.0.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (3.13)
|
| 135 |
+
Requirement already satisfied: h11>=0.16 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from httpcore==1.*->httpx<1.0.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (0.16.0)
|
| 136 |
+
Requirement already satisfied: hf-xet<2.0.0,>=1.4.3 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=0.21.0->accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (1.4.3)
|
| 137 |
+
Requirement already satisfied: typer in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=0.21.0->accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (0.24.2)
|
| 138 |
+
Requirement already satisfied: regex>=2025.10.22 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from transformers>=4.45.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 6)) (2026.4.4)
|
| 139 |
+
Requirement already satisfied: tokenizers<=0.23.0,>=0.22.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from transformers>=4.45.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 6)) (0.22.2)
|
| 140 |
+
Requirement already satisfied: aiohappyeyeballs>=2.5.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2026.2.0,>=2023.1.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (2.6.1)
|
| 141 |
+
Requirement already satisfied: aiosignal>=1.4.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2026.2.0,>=2023.1.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (1.4.0)
|
| 142 |
+
Requirement already satisfied: attrs>=17.3.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2026.2.0,>=2023.1.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (26.1.0)
|
| 143 |
+
Requirement already satisfied: frozenlist>=1.1.1 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2026.2.0,>=2023.1.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (1.8.0)
|
| 144 |
+
Requirement already satisfied: multidict<7.0,>=4.5 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2026.2.0,>=2023.1.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (6.7.1)
|
| 145 |
+
Requirement already satisfied: propcache>=0.2.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2026.2.0,>=2023.1.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (0.4.1)
|
| 146 |
+
Requirement already satisfied: yarl<2.0,>=1.17.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->fsspec[http]<=2026.2.0,>=2023.1.0->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (1.23.0)
|
| 147 |
+
Requirement already satisfied: charset_normalizer<4,>=2 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from requests>=2.32.2->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (3.4.7)
|
| 148 |
+
Requirement already satisfied: urllib3<3,>=1.26 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from requests>=2.32.2->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (2.6.3)
|
| 149 |
+
Requirement already satisfied: mpmath<1.4,>=1.1.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from sympy>=1.13.3->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (1.3.0)
|
| 150 |
+
Requirement already satisfied: MarkupSafe>=2.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from jinja2->torch>=2.4.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 5)) (3.0.3)
|
| 151 |
+
Requirement already satisfied: python-dateutil>=2.8.2 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from pandas->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (2.9.0.post0)
|
| 152 |
+
Requirement already satisfied: six>=1.5 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas->datasets>=3.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 3)) (1.17.0)
|
| 153 |
+
Requirement already satisfied: click>=8.2.1 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from typer->huggingface_hub>=0.21.0->accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (8.3.3)
|
| 154 |
+
Requirement already satisfied: shellingham>=1.3.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from typer->huggingface_hub>=0.21.0->accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (1.5.4)
|
| 155 |
+
Requirement already satisfied: rich>=12.3.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from typer->huggingface_hub>=0.21.0->accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (15.0.0)
|
| 156 |
+
Requirement already satisfied: annotated-doc>=0.0.2 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from typer->huggingface_hub>=0.21.0->accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (0.0.4)
|
| 157 |
+
Requirement already satisfied: markdown-it-py>=2.2.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from rich>=12.3.0->typer->huggingface_hub>=0.21.0->accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (4.0.0)
|
| 158 |
+
Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from rich>=12.3.0->typer->huggingface_hub>=0.21.0->accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (2.20.0)
|
| 159 |
+
Requirement already satisfied: mdurl~=0.1 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from markdown-it-py>=2.2.0->rich>=12.3.0->typer->huggingface_hub>=0.21.0->accelerate>=1.0.0->-r legacy_cobol_env/training/requirements-gpu.txt (line 1)) (0.1.2)
|
| 160 |
+
$ /root/.cache/uv/builds-v0/.tmpQi62S5/bin/python -m pip install -e .
|
| 161 |
+
Obtaining file:///tmp/cobol-modernization-openenv
|
| 162 |
+
Installing build dependencies: started
|
| 163 |
+
Installing build dependencies: finished with status 'done'
|
| 164 |
+
Checking if build backend supports build_editable: started
|
| 165 |
+
Checking if build backend supports build_editable: finished with status 'done'
|
| 166 |
+
Getting requirements to build editable: started
|
| 167 |
+
Getting requirements to build editable: finished with status 'done'
|
| 168 |
+
Preparing editable metadata (pyproject.toml): started
|
| 169 |
+
Preparing editable metadata (pyproject.toml): finished with status 'done'
|
| 170 |
+
Collecting openenv-core>=0.2.3 (from openenv-legacy-cobol-submission==0.1.0)
|
| 171 |
+
Downloading openenv_core-0.2.3-py3-none-any.whl.metadata (19 kB)
|
| 172 |
+
Collecting openai>=1.0 (from openenv-legacy-cobol-submission==0.1.0)
|
| 173 |
+
Downloading openai-2.32.0-py3-none-any.whl.metadata (31 kB)
|
| 174 |
+
Requirement already satisfied: huggingface_hub>=1.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from openenv-legacy-cobol-submission==0.1.0) (1.12.0)
|
| 175 |
+
Requirement already satisfied: filelock>=3.10.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (3.29.0)
|
| 176 |
+
Requirement already satisfied: fsspec>=2023.5.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (2026.2.0)
|
| 177 |
+
Requirement already satisfied: hf-xet<2.0.0,>=1.4.3 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (1.4.3)
|
| 178 |
+
Requirement already satisfied: httpx<1,>=0.23.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (0.28.1)
|
| 179 |
+
Requirement already satisfied: packaging>=20.9 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (26.2)
|
| 180 |
+
Requirement already satisfied: pyyaml>=5.1 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (6.0.3)
|
| 181 |
+
Requirement already satisfied: tqdm>=4.42.1 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (4.67.3)
|
| 182 |
+
Requirement already satisfied: typer in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (0.24.2)
|
| 183 |
+
Requirement already satisfied: typing-extensions>=4.1.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (4.15.0)
|
| 184 |
+
Requirement already satisfied: anyio in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from httpx<1,>=0.23.0->huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (4.13.0)
|
| 185 |
+
Requirement already satisfied: certifi in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from httpx<1,>=0.23.0->huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (2026.4.22)
|
| 186 |
+
Requirement already satisfied: httpcore==1.* in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from httpx<1,>=0.23.0->huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (1.0.9)
|
| 187 |
+
Requirement already satisfied: idna in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from httpx<1,>=0.23.0->huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (3.13)
|
| 188 |
+
Requirement already satisfied: h11>=0.16 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (0.16.0)
|
| 189 |
+
Collecting distro<2,>=1.7.0 (from openai>=1.0->openenv-legacy-cobol-submission==0.1.0)
|
| 190 |
+
Downloading distro-1.9.0-py3-none-any.whl.metadata (6.8 kB)
|
| 191 |
+
Collecting jiter<1,>=0.10.0 (from openai>=1.0->openenv-legacy-cobol-submission==0.1.0)
|
| 192 |
+
Downloading jiter-0.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (5.2 kB)
|
| 193 |
+
Collecting pydantic<3,>=1.9.0 (from openai>=1.0->openenv-legacy-cobol-submission==0.1.0)
|
| 194 |
+
Downloading pydantic-2.13.3-py3-none-any.whl.metadata (108 kB)
|
| 195 |
+
Collecting sniffio (from openai>=1.0->openenv-legacy-cobol-submission==0.1.0)
|
| 196 |
+
Downloading sniffio-1.3.1-py3-none-any.whl.metadata (3.9 kB)
|
| 197 |
+
Collecting annotated-types>=0.6.0 (from pydantic<3,>=1.9.0->openai>=1.0->openenv-legacy-cobol-submission==0.1.0)
|
| 198 |
+
Downloading annotated_types-0.7.0-py3-none-any.whl.metadata (15 kB)
|
| 199 |
+
Collecting pydantic-core==2.46.3 (from pydantic<3,>=1.9.0->openai>=1.0->openenv-legacy-cobol-submission==0.1.0)
|
| 200 |
+
Downloading pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (6.6 kB)
|
| 201 |
+
Collecting typing-inspection>=0.4.2 (from pydantic<3,>=1.9.0->openai>=1.0->openenv-legacy-cobol-submission==0.1.0)
|
| 202 |
+
Downloading typing_inspection-0.4.2-py3-none-any.whl.metadata (2.6 kB)
|
| 203 |
+
Collecting fastapi>=0.104.0 (from openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 204 |
+
Downloading fastapi-0.136.1-py3-none-any.whl.metadata (28 kB)
|
| 205 |
+
Collecting uvicorn>=0.24.0 (from openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 206 |
+
Downloading uvicorn-0.46.0-py3-none-any.whl.metadata (6.7 kB)
|
| 207 |
+
Requirement already satisfied: requests>=2.25.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (2.33.1)
|
| 208 |
+
Requirement already satisfied: rich>=13.0.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (15.0.0)
|
| 209 |
+
Collecting tomli>=2.3.0 (from openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 210 |
+
Downloading tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl.metadata (10 kB)
|
| 211 |
+
Collecting tomli-w>=1.2.0 (from openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 212 |
+
Downloading tomli_w-1.2.0-py3-none-any.whl.metadata (5.7 kB)
|
| 213 |
+
Collecting websockets>=15.0.1 (from openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 214 |
+
Downloading websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.metadata (6.8 kB)
|
| 215 |
+
Collecting fastmcp>=3.0.0 (from openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 216 |
+
Downloading fastmcp-3.2.4-py3-none-any.whl.metadata (8.1 kB)
|
| 217 |
+
Collecting gradio>=4.0.0 (from openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 218 |
+
Downloading gradio-6.13.0-py3-none-any.whl.metadata (17 kB)
|
| 219 |
+
Collecting starlette>=0.46.0 (from fastapi>=0.104.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 220 |
+
Downloading starlette-1.0.0-py3-none-any.whl.metadata (6.3 kB)
|
| 221 |
+
Requirement already satisfied: annotated-doc>=0.0.2 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from fastapi>=0.104.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (0.0.4)
|
| 222 |
+
Collecting authlib>=1.6.5 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 223 |
+
Downloading authlib-1.7.0-py2.py3-none-any.whl.metadata (10.0 kB)
|
| 224 |
+
Collecting cyclopts>=4.0.0 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 225 |
+
Downloading cyclopts-4.11.0-py3-none-any.whl.metadata (12 kB)
|
| 226 |
+
Collecting exceptiongroup>=1.2.2 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 227 |
+
Downloading exceptiongroup-1.3.1-py3-none-any.whl.metadata (6.7 kB)
|
| 228 |
+
Collecting griffelib>=2.0.0 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 229 |
+
Downloading griffelib-2.0.2-py3-none-any.whl.metadata (1.3 kB)
|
| 230 |
+
Collecting jsonref>=1.1.0 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 231 |
+
Downloading jsonref-1.1.0-py3-none-any.whl.metadata (2.7 kB)
|
| 232 |
+
Collecting jsonschema-path>=0.3.4 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 233 |
+
Downloading jsonschema_path-0.4.5-py3-none-any.whl.metadata (5.9 kB)
|
| 234 |
+
Collecting mcp<2.0,>=1.24.0 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 235 |
+
Downloading mcp-1.27.0-py3-none-any.whl.metadata (8.2 kB)
|
| 236 |
+
Collecting openapi-pydantic>=0.5.1 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 237 |
+
Downloading openapi_pydantic-0.5.1-py3-none-any.whl.metadata (10 kB)
|
| 238 |
+
Collecting opentelemetry-api>=1.20.0 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 239 |
+
Downloading opentelemetry_api-1.41.1-py3-none-any.whl.metadata (1.5 kB)
|
| 240 |
+
Collecting platformdirs>=4.0.0 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 241 |
+
Downloading platformdirs-4.9.6-py3-none-any.whl.metadata (4.7 kB)
|
| 242 |
+
Collecting py-key-value-aio<0.5.0,>=0.4.4 (from py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 243 |
+
Downloading py_key_value_aio-0.4.4-py3-none-any.whl.metadata (15 kB)
|
| 244 |
+
Collecting pyperclip>=1.9.0 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 245 |
+
Downloading pyperclip-1.11.0-py3-none-any.whl.metadata (2.4 kB)
|
| 246 |
+
Collecting python-dotenv>=1.1.0 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 247 |
+
Downloading python_dotenv-1.2.2-py3-none-any.whl.metadata (27 kB)
|
| 248 |
+
Collecting uncalled-for>=0.2.0 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 249 |
+
Downloading uncalled_for-0.3.1-py3-none-any.whl.metadata (2.9 kB)
|
| 250 |
+
Collecting watchfiles>=1.0.0 (from fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 251 |
+
Downloading watchfiles-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.9 kB)
|
| 252 |
+
Collecting httpx-sse>=0.4 (from mcp<2.0,>=1.24.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 253 |
+
Downloading httpx_sse-0.4.3-py3-none-any.whl.metadata (9.7 kB)
|
| 254 |
+
Collecting jsonschema>=4.20.0 (from mcp<2.0,>=1.24.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 255 |
+
Downloading jsonschema-4.26.0-py3-none-any.whl.metadata (7.6 kB)
|
| 256 |
+
Collecting pydantic-settings>=2.5.2 (from mcp<2.0,>=1.24.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 257 |
+
Downloading pydantic_settings-2.14.0-py3-none-any.whl.metadata (3.4 kB)
|
| 258 |
+
Collecting pyjwt>=2.10.1 (from pyjwt[crypto]>=2.10.1->mcp<2.0,>=1.24.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 259 |
+
Downloading pyjwt-2.12.1-py3-none-any.whl.metadata (4.1 kB)
|
| 260 |
+
Collecting python-multipart>=0.0.9 (from mcp<2.0,>=1.24.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 261 |
+
Downloading python_multipart-0.0.26-py3-none-any.whl.metadata (2.1 kB)
|
| 262 |
+
Collecting sse-starlette>=1.6.1 (from mcp<2.0,>=1.24.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 263 |
+
Downloading sse_starlette-3.3.4-py3-none-any.whl.metadata (14 kB)
|
| 264 |
+
Collecting beartype>=0.20.0 (from py-key-value-aio<0.5.0,>=0.4.4->py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 265 |
+
Downloading beartype-0.22.9-py3-none-any.whl.metadata (37 kB)
|
| 266 |
+
Collecting aiofile>=3.5.0 (from py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 267 |
+
Downloading aiofile-3.9.0-py3-none-any.whl.metadata (14 kB)
|
| 268 |
+
Collecting keyring>=25.6.0 (from py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 269 |
+
Downloading keyring-25.7.0-py3-none-any.whl.metadata (21 kB)
|
| 270 |
+
Collecting cachetools>=5.0.0 (from py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 271 |
+
Downloading cachetools-7.0.6-py3-none-any.whl.metadata (5.9 kB)
|
| 272 |
+
Collecting caio<0.10.0,>=0.9.0 (from aiofile>=3.5.0->py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 273 |
+
Downloading caio-0.9.25-cp312-cp312-manylinux_2_34_x86_64.whl.metadata (3.3 kB)
|
| 274 |
+
Collecting cryptography (from authlib>=1.6.5->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 275 |
+
Downloading cryptography-47.0.0-cp311-abi3-manylinux_2_34_x86_64.whl.metadata (4.5 kB)
|
| 276 |
+
Collecting joserfc>=1.6.0 (from authlib>=1.6.5->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 277 |
+
Downloading joserfc-1.6.4-py3-none-any.whl.metadata (3.2 kB)
|
| 278 |
+
Requirement already satisfied: attrs>=23.1.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from cyclopts>=4.0.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (26.1.0)
|
| 279 |
+
Collecting docstring-parser<4.0,>=0.15 (from cyclopts>=4.0.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 280 |
+
Downloading docstring_parser-0.18.0-py3-none-any.whl.metadata (3.5 kB)
|
| 281 |
+
Collecting rich-rst<2.0.0,>=1.3.1 (from cyclopts>=4.0.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 282 |
+
Downloading rich_rst-1.3.2-py3-none-any.whl.metadata (6.1 kB)
|
| 283 |
+
Collecting docutils (from rich-rst<2.0.0,>=1.3.1->cyclopts>=4.0.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 284 |
+
Downloading docutils-0.22.4-py3-none-any.whl.metadata (15 kB)
|
| 285 |
+
Collecting brotli>=1.1.0 (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 286 |
+
Downloading brotli-1.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (6.1 kB)
|
| 287 |
+
Collecting gradio-client==2.5.0 (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 288 |
+
Downloading gradio_client-2.5.0-py3-none-any.whl.metadata (7.1 kB)
|
| 289 |
+
Collecting groovy~=0.1 (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 290 |
+
Downloading groovy-0.1.2-py3-none-any.whl.metadata (6.1 kB)
|
| 291 |
+
Collecting hf-gradio<1.0,>=0.4.1 (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 292 |
+
Downloading hf_gradio-0.4.1-py3-none-any.whl.metadata (428 bytes)
|
| 293 |
+
Requirement already satisfied: jinja2<4.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (3.1.6)
|
| 294 |
+
Requirement already satisfied: markupsafe<4.0,>=2.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (3.0.3)
|
| 295 |
+
Requirement already satisfied: numpy<3.0,>=1.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (2.4.4)
|
| 296 |
+
Collecting orjson~=3.0 (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 297 |
+
Downloading orjson-3.11.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (41 kB)
|
| 298 |
+
Requirement already satisfied: pandas<4.0,>=1.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (3.0.2)
|
| 299 |
+
Requirement already satisfied: pillow<13.0,>=8.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (12.2.0)
|
| 300 |
+
Collecting pydub<1.0 (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 301 |
+
Downloading pydub-0.25.1-py2.py3-none-any.whl.metadata (1.4 kB)
|
| 302 |
+
Collecting pytz>=2017.2 (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 303 |
+
Downloading pytz-2026.1.post1-py2.py3-none-any.whl.metadata (22 kB)
|
| 304 |
+
Collecting safehttpx<0.2.0,>=0.1.7 (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 305 |
+
Downloading safehttpx-0.1.7-py3-none-any.whl.metadata (4.2 kB)
|
| 306 |
+
Collecting semantic-version~=2.0 (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 307 |
+
Downloading semantic_version-2.10.0-py2.py3-none-any.whl.metadata (9.7 kB)
|
| 308 |
+
Collecting tomlkit<0.15.0,>=0.12.0 (from gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 309 |
+
Downloading tomlkit-0.14.0-py3-none-any.whl.metadata (2.8 kB)
|
| 310 |
+
Requirement already satisfied: python-dateutil>=2.8.2 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from pandas<4.0,>=1.0->gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (2.9.0.post0)
|
| 311 |
+
Requirement already satisfied: click>=8.2.1 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from typer->huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (8.3.3)
|
| 312 |
+
Requirement already satisfied: shellingham>=1.3.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from typer->huggingface_hub>=1.0->openenv-legacy-cobol-submission==0.1.0) (1.5.4)
|
| 313 |
+
Collecting cffi>=2.0.0 (from cryptography->authlib>=1.6.5->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 314 |
+
Downloading cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (2.6 kB)
|
| 315 |
+
Collecting pycparser (from cffi>=2.0.0->cryptography->authlib>=1.6.5->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 316 |
+
Downloading pycparser-3.0-py3-none-any.whl.metadata (8.2 kB)
|
| 317 |
+
Collecting jsonschema-specifications>=2023.03.6 (from jsonschema>=4.20.0->mcp<2.0,>=1.24.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 318 |
+
Downloading jsonschema_specifications-2025.9.1-py3-none-any.whl.metadata (2.9 kB)
|
| 319 |
+
Collecting referencing>=0.28.4 (from jsonschema>=4.20.0->mcp<2.0,>=1.24.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 320 |
+
Downloading referencing-0.37.0-py3-none-any.whl.metadata (2.8 kB)
|
| 321 |
+
Collecting rpds-py>=0.25.0 (from jsonschema>=4.20.0->mcp<2.0,>=1.24.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 322 |
+
Downloading rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.1 kB)
|
| 323 |
+
Collecting pathable<0.6.0,>=0.5.0 (from jsonschema-path>=0.3.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 324 |
+
Downloading pathable-0.5.0-py3-none-any.whl.metadata (5.9 kB)
|
| 325 |
+
Collecting SecretStorage>=3.2 (from keyring>=25.6.0->py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 326 |
+
Downloading secretstorage-3.5.0-py3-none-any.whl.metadata (4.0 kB)
|
| 327 |
+
Collecting jeepney>=0.4.2 (from keyring>=25.6.0->py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 328 |
+
Downloading jeepney-0.9.0-py3-none-any.whl.metadata (1.2 kB)
|
| 329 |
+
Collecting jaraco.classes (from keyring>=25.6.0->py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 330 |
+
Downloading jaraco.classes-3.4.0-py3-none-any.whl.metadata (2.6 kB)
|
| 331 |
+
Collecting jaraco.functools (from keyring>=25.6.0->py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 332 |
+
Downloading jaraco_functools-4.4.0-py3-none-any.whl.metadata (3.0 kB)
|
| 333 |
+
Collecting jaraco.context (from keyring>=25.6.0->py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 334 |
+
Downloading jaraco_context-6.1.2-py3-none-any.whl.metadata (4.2 kB)
|
| 335 |
+
Collecting importlib-metadata<8.8.0,>=6.0 (from opentelemetry-api>=1.20.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 336 |
+
Downloading importlib_metadata-8.7.1-py3-none-any.whl.metadata (4.7 kB)
|
| 337 |
+
Collecting zipp>=3.20 (from importlib-metadata<8.8.0,>=6.0->opentelemetry-api>=1.20.0->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 338 |
+
Downloading zipp-3.23.1-py3-none-any.whl.metadata (3.6 kB)
|
| 339 |
+
Collecting email-validator>=2.0.0 (from pydantic[email]>=2.11.7->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 340 |
+
Downloading email_validator-2.3.0-py3-none-any.whl.metadata (26 kB)
|
| 341 |
+
Collecting dnspython>=2.0.0 (from email-validator>=2.0.0->pydantic[email]>=2.11.7->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 342 |
+
Downloading dnspython-2.8.0-py3-none-any.whl.metadata (5.7 kB)
|
| 343 |
+
Requirement already satisfied: six>=1.5 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas<4.0,>=1.0->gradio>=4.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (1.17.0)
|
| 344 |
+
Requirement already satisfied: charset_normalizer<4,>=2 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from requests>=2.25.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (3.4.7)
|
| 345 |
+
Requirement already satisfied: urllib3<3,>=1.26 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from requests>=2.25.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (2.6.3)
|
| 346 |
+
Requirement already satisfied: markdown-it-py>=2.2.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from rich>=13.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (4.0.0)
|
| 347 |
+
Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from rich>=13.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (2.20.0)
|
| 348 |
+
Requirement already satisfied: mdurl~=0.1 in /root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages (from markdown-it-py>=2.2.0->rich>=13.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0) (0.1.2)
|
| 349 |
+
Collecting more-itertools (from jaraco.classes->keyring>=25.6.0->py-key-value-aio[filetree,keyring,memory]<0.5.0,>=0.4.4->fastmcp>=3.0.0->openenv-core>=0.2.3->openenv-legacy-cobol-submission==0.1.0)
|
| 350 |
+
Downloading more_itertools-11.0.2-py3-none-any.whl.metadata (41 kB)
|
| 351 |
+
Downloading openai-2.32.0-py3-none-any.whl (1.2 MB)
|
| 352 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.2/1.2 MB 189.5 MB/s 0:00:00
|
| 353 |
+
Downloading distro-1.9.0-py3-none-any.whl (20 kB)
|
| 354 |
+
Downloading jiter-0.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (353 kB)
|
| 355 |
+
Downloading pydantic-2.13.3-py3-none-any.whl (471 kB)
|
| 356 |
+
Downloading pydantic_core-2.46.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.1 MB)
|
| 357 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.1/2.1 MB 139.5 MB/s 0:00:00
|
| 358 |
+
Downloading annotated_types-0.7.0-py3-none-any.whl (13 kB)
|
| 359 |
+
Downloading openenv_core-0.2.3-py3-none-any.whl (174 kB)
|
| 360 |
+
Downloading fastapi-0.136.1-py3-none-any.whl (117 kB)
|
| 361 |
+
Downloading fastmcp-3.2.4-py3-none-any.whl (728 kB)
|
| 362 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 728.6/728.6 kB 150.8 MB/s 0:00:00
|
| 363 |
+
Downloading mcp-1.27.0-py3-none-any.whl (215 kB)
|
| 364 |
+
Downloading py_key_value_aio-0.4.4-py3-none-any.whl (152 kB)
|
| 365 |
+
Downloading aiofile-3.9.0-py3-none-any.whl (19 kB)
|
| 366 |
+
Downloading caio-0.9.25-cp312-cp312-manylinux_2_34_x86_64.whl (80 kB)
|
| 367 |
+
Downloading authlib-1.7.0-py2.py3-none-any.whl (258 kB)
|
| 368 |
+
Downloading beartype-0.22.9-py3-none-any.whl (1.3 MB)
|
| 369 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.3/1.3 MB 319.7 MB/s 0:00:00
|
| 370 |
+
Downloading cachetools-7.0.6-py3-none-any.whl (13 kB)
|
| 371 |
+
Downloading cyclopts-4.11.0-py3-none-any.whl (208 kB)
|
| 372 |
+
Downloading docstring_parser-0.18.0-py3-none-any.whl (22 kB)
|
| 373 |
+
Downloading rich_rst-1.3.2-py3-none-any.whl (12 kB)
|
| 374 |
+
Downloading exceptiongroup-1.3.1-py3-none-any.whl (16 kB)
|
| 375 |
+
Downloading gradio-6.13.0-py3-none-any.whl (19.7 MB)
|
| 376 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 19.7/19.7 MB 279.0 MB/s 0:00:00
|
| 377 |
+
Downloading gradio_client-2.5.0-py3-none-any.whl (59 kB)
|
| 378 |
+
Downloading groovy-0.1.2-py3-none-any.whl (14 kB)
|
| 379 |
+
Downloading hf_gradio-0.4.1-py3-none-any.whl (4.5 kB)
|
| 380 |
+
Downloading orjson-3.11.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (133 kB)
|
| 381 |
+
Downloading pydub-0.25.1-py2.py3-none-any.whl (32 kB)
|
| 382 |
+
Downloading python_multipart-0.0.26-py3-none-any.whl (28 kB)
|
| 383 |
+
Downloading safehttpx-0.1.7-py3-none-any.whl (9.0 kB)
|
| 384 |
+
Downloading semantic_version-2.10.0-py2.py3-none-any.whl (15 kB)
|
| 385 |
+
Downloading starlette-1.0.0-py3-none-any.whl (72 kB)
|
| 386 |
+
Downloading tomlkit-0.14.0-py3-none-any.whl (39 kB)
|
| 387 |
+
Downloading brotli-1.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (1.4 MB)
|
| 388 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.4/1.4 MB 224.7 MB/s 0:00:00
|
| 389 |
+
Downloading griffelib-2.0.2-py3-none-any.whl (142 kB)
|
| 390 |
+
Downloading httpx_sse-0.4.3-py3-none-any.whl (9.0 kB)
|
| 391 |
+
Downloading joserfc-1.6.4-py3-none-any.whl (70 kB)
|
| 392 |
+
Downloading cryptography-47.0.0-cp311-abi3-manylinux_2_34_x86_64.whl (4.7 MB)
|
| 393 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.7/4.7 MB 360.4 MB/s 0:00:00
|
| 394 |
+
Downloading cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (219 kB)
|
| 395 |
+
Downloading jsonref-1.1.0-py3-none-any.whl (9.4 kB)
|
| 396 |
+
Downloading jsonschema-4.26.0-py3-none-any.whl (90 kB)
|
| 397 |
+
Downloading jsonschema_path-0.4.5-py3-none-any.whl (19 kB)
|
| 398 |
+
Downloading pathable-0.5.0-py3-none-any.whl (16 kB)
|
| 399 |
+
Downloading referencing-0.37.0-py3-none-any.whl (26 kB)
|
| 400 |
+
Downloading jsonschema_specifications-2025.9.1-py3-none-any.whl (18 kB)
|
| 401 |
+
Downloading keyring-25.7.0-py3-none-any.whl (39 kB)
|
| 402 |
+
Downloading jeepney-0.9.0-py3-none-any.whl (49 kB)
|
| 403 |
+
Downloading openapi_pydantic-0.5.1-py3-none-any.whl (96 kB)
|
| 404 |
+
Downloading opentelemetry_api-1.41.1-py3-none-any.whl (69 kB)
|
| 405 |
+
Downloading importlib_metadata-8.7.1-py3-none-any.whl (27 kB)
|
| 406 |
+
Downloading platformdirs-4.9.6-py3-none-any.whl (21 kB)
|
| 407 |
+
Downloading pydantic_settings-2.14.0-py3-none-any.whl (60 kB)
|
| 408 |
+
Downloading email_validator-2.3.0-py3-none-any.whl (35 kB)
|
| 409 |
+
Downloading dnspython-2.8.0-py3-none-any.whl (331 kB)
|
| 410 |
+
Downloading pyjwt-2.12.1-py3-none-any.whl (29 kB)
|
| 411 |
+
Downloading pyperclip-1.11.0-py3-none-any.whl (11 kB)
|
| 412 |
+
Downloading python_dotenv-1.2.2-py3-none-any.whl (22 kB)
|
| 413 |
+
Downloading pytz-2026.1.post1-py2.py3-none-any.whl (510 kB)
|
| 414 |
+
Downloading rpds_py-0.30.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (394 kB)
|
| 415 |
+
Downloading secretstorage-3.5.0-py3-none-any.whl (15 kB)
|
| 416 |
+
Downloading sse_starlette-3.3.4-py3-none-any.whl (14 kB)
|
| 417 |
+
Downloading tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl (253 kB)
|
| 418 |
+
Downloading tomli_w-1.2.0-py3-none-any.whl (6.7 kB)
|
| 419 |
+
Downloading typing_inspection-0.4.2-py3-none-any.whl (14 kB)
|
| 420 |
+
Downloading uncalled_for-0.3.1-py3-none-any.whl (11 kB)
|
| 421 |
+
Downloading uvicorn-0.46.0-py3-none-any.whl (70 kB)
|
| 422 |
+
Downloading watchfiles-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (456 kB)
|
| 423 |
+
Downloading websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (184 kB)
|
| 424 |
+
Downloading zipp-3.23.1-py3-none-any.whl (10 kB)
|
| 425 |
+
Downloading docutils-0.22.4-py3-none-any.whl (633 kB)
|
| 426 |
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 633.2/633.2 kB 180.9 MB/s 0:00:00
|
| 427 |
+
Downloading jaraco.classes-3.4.0-py3-none-any.whl (6.8 kB)
|
| 428 |
+
Downloading jaraco_context-6.1.2-py3-none-any.whl (7.9 kB)
|
| 429 |
+
Downloading jaraco_functools-4.4.0-py3-none-any.whl (10 kB)
|
| 430 |
+
Downloading more_itertools-11.0.2-py3-none-any.whl (71 kB)
|
| 431 |
+
Downloading pycparser-3.0-py3-none-any.whl (48 kB)
|
| 432 |
+
Downloading sniffio-1.3.1-py3-none-any.whl (10 kB)
|
| 433 |
+
Building wheels for collected packages: openenv-legacy-cobol-submission
|
| 434 |
+
Building editable for openenv-legacy-cobol-submission (pyproject.toml): started
|
| 435 |
+
Building editable for openenv-legacy-cobol-submission (pyproject.toml): finished with status 'done'
|
| 436 |
+
Created wheel for openenv-legacy-cobol-submission: filename=openenv_legacy_cobol_submission-0.1.0-0.editable-py3-none-any.whl size=3473 sha256=9b4383c97de11d7e09ec00b3ef1baa48d457bd698dde2a5dadcf518844ea25b3
|
| 437 |
+
Stored in directory: /tmp/pip-ephem-wheel-cache-v0kbbpbx/wheels/7e/65/79/e562943dc6d9280fcc9daecb6a70ad61c29c4a1c92d641e1e1
|
| 438 |
+
Successfully built openenv-legacy-cobol-submission
|
| 439 |
+
Installing collected packages: pytz, pyperclip, pydub, brotli, zipp, websockets, uvicorn, uncalled-for, typing-inspection, tomlkit, tomli-w, tomli, sniffio, semantic-version, rpds-py, python-multipart, python-dotenv, pyjwt, pydantic-core, pycparser, platformdirs, pathable, orjson, more-itertools, jsonref, jiter, jeepney, jaraco.context, httpx-sse, groovy, griffelib, exceptiongroup, docutils, docstring-parser, dnspython, distro, caio, cachetools, beartype, annotated-types, watchfiles, starlette, referencing, pydantic, py-key-value-aio, jaraco.functools, jaraco.classes, importlib-metadata, email-validator, cffi, aiofile, sse-starlette, safehttpx, rich-rst, pydantic-settings, opentelemetry-api, openapi-pydantic, openai, jsonschema-specifications, jsonschema-path, fastapi, cryptography, SecretStorage, jsonschema, joserfc, cyclopts, mcp, keyring, gradio-client, authlib, hf-gradio, gradio, fastmcp, openenv-core, openenv-legacy-cobol-submission
|
| 440 |
+
|
| 441 |
+
Successfully installed SecretStorage-3.5.0 aiofile-3.9.0 annotated-types-0.7.0 authlib-1.7.0 beartype-0.22.9 brotli-1.2.0 cachetools-7.0.6 caio-0.9.25 cffi-2.0.0 cryptography-47.0.0 cyclopts-4.11.0 distro-1.9.0 dnspython-2.8.0 docstring-parser-0.18.0 docutils-0.22.4 email-validator-2.3.0 exceptiongroup-1.3.1 fastapi-0.136.1 fastmcp-3.2.4 gradio-6.13.0 gradio-client-2.5.0 griffelib-2.0.2 groovy-0.1.2 hf-gradio-0.4.1 httpx-sse-0.4.3 importlib-metadata-8.7.1 jaraco.classes-3.4.0 jaraco.context-6.1.2 jaraco.functools-4.4.0 jeepney-0.9.0 jiter-0.14.0 joserfc-1.6.4 jsonref-1.1.0 jsonschema-4.26.0 jsonschema-path-0.4.5 jsonschema-specifications-2025.9.1 keyring-25.7.0 mcp-1.27.0 more-itertools-11.0.2 openai-2.32.0 openapi-pydantic-0.5.1 openenv-core-0.2.3 openenv-legacy-cobol-submission-0.1.0 opentelemetry-api-1.41.1 orjson-3.11.8 pathable-0.5.0 platformdirs-4.9.6 py-key-value-aio-0.4.4 pycparser-3.0 pydantic-2.13.3 pydantic-core-2.46.3 pydantic-settings-2.14.0 pydub-0.25.1 pyjwt-2.12.1 pyperclip-1.11.0 python-dotenv-1.2.2 python-multipart-0.0.26 pytz-2026.1.post1 referencing-0.37.0 rich-rst-1.3.2 rpds-py-0.30.0 safehttpx-0.1.7 semantic-version-2.10.0 sniffio-1.3.1 sse-starlette-3.3.4 starlette-1.0.0 tomli-2.4.1 tomli-w-1.2.0 tomlkit-0.14.0 typing-inspection-0.4.2 uncalled-for-0.3.1 uvicorn-0.46.0 watchfiles-1.1.1 websockets-16.0 zipp-3.23.1
|
| 442 |
+
$ /root/.cache/uv/builds-v0/.tmpQi62S5/bin/python -m legacy_cobol_env.training.build_sft_dataset
|
| 443 |
+
wrote 15 examples to /tmp/cobol-modernization-openenv/legacy_cobol_env/outputs/training/oracle_sft.jsonl
|
| 444 |
+
$ /root/.cache/uv/builds-v0/.tmpQi62S5/bin/python -m legacy_cobol_env.eval.run_model_rollouts --provider local-transformers --max-repairs 2 --output legacy_cobol_env/outputs/evals/base_local_qwen3_14b_all_tasks.json
|
| 445 |
+
|
| 446 |
+
|
| 447 |
+
|
| 448 |
+
|
| 449 |
+
|
| 450 |
+
|
| 451 |
+
|
| 452 |
+
|
| 453 |
+
|
| 454 |
+
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
|
| 458 |
+
|
| 459 |
+
|
| 460 |
+
|
| 461 |
+
|
| 462 |
+
|
| 463 |
+
|
| 464 |
+
|
| 465 |
+
|
| 466 |
+
|
| 467 |
+
|
| 468 |
+
|
| 469 |
+
|
| 470 |
+
|
| 471 |
+
|
| 472 |
+
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
|
| 476 |
+
|
| 477 |
+
|
| 478 |
+
|
| 479 |
+
|
| 480 |
+
|
| 481 |
+
|
| 482 |
+
|
| 483 |
+
|
| 484 |
+
|
| 485 |
+
|
| 486 |
+
|
| 487 |
+
|
| 488 |
+
|
| 489 |
+
|
| 490 |
+
|
| 491 |
+
|
| 492 |
+
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
|
| 496 |
+
|
| 497 |
+
|
| 498 |
+
|
| 499 |
+
|
| 500 |
+
|
| 501 |
+
|
| 502 |
+
|
| 503 |
+
|
| 504 |
+
|
| 505 |
+
|
| 506 |
+
|
| 507 |
+
|
| 508 |
+
|
| 509 |
+
|
| 510 |
+
|
| 511 |
+
|
| 512 |
+
|
| 513 |
+
|
| 514 |
+
|
| 515 |
+
|
| 516 |
+
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
|
| 520 |
+
|
| 521 |
+
|
| 522 |
+
|
| 523 |
+
|
| 524 |
+
|
| 525 |
+
|
| 526 |
+
|
| 527 |
+
|
| 528 |
+
|
| 529 |
+
|
| 530 |
+
|
| 531 |
+
|
| 532 |
+
|
| 533 |
+
|
| 534 |
+
|
| 535 |
+
|
| 536 |
+
|
| 537 |
+
|
| 538 |
+
|
| 539 |
+
|
| 540 |
+
|
| 541 |
+
|
| 542 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 543 |
+
torch._check_is_size(blocksize)
|
| 544 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 545 |
+
torch._check_is_size(blocksize)
|
| 546 |
+
|
| 547 |
+
|
| 548 |
+
|
| 549 |
+
|
| 550 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 551 |
+
torch._check_is_size(blocksize)
|
| 552 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 553 |
+
torch._check_is_size(blocksize)
|
| 554 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 555 |
+
torch._check_is_size(blocksize)
|
| 556 |
+
|
| 557 |
+
|
| 558 |
+
|
| 559 |
+
|
| 560 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 561 |
+
torch._check_is_size(blocksize)
|
| 562 |
+
|
| 563 |
+
|
| 564 |
+
|
| 565 |
+
|
| 566 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 567 |
+
torch._check_is_size(blocksize)
|
| 568 |
+
|
| 569 |
+
|
| 570 |
+
|
| 571 |
+
|
| 572 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 573 |
+
torch._check_is_size(blocksize)
|
| 574 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 575 |
+
torch._check_is_size(blocksize)
|
| 576 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 577 |
+
torch._check_is_size(blocksize)
|
| 578 |
+
|
| 579 |
+
|
| 580 |
+
|
| 581 |
+
|
| 582 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 583 |
+
torch._check_is_size(blocksize)
|
| 584 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 585 |
+
torch._check_is_size(blocksize)
|
| 586 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 587 |
+
torch._check_is_size(blocksize)
|
| 588 |
+
{
|
| 589 |
+
"provider": "local-transformers",
|
| 590 |
+
"task_count": 6,
|
| 591 |
+
"mean_public_score": 0.714,
|
| 592 |
+
"accepted_count": 3
|
| 593 |
+
}
|
| 594 |
+
$ /root/.cache/uv/builds-v0/.tmpQi62S5/bin/python -m legacy_cobol_env.training.train_sft --model-name Qwen/Qwen3-14B --max-seq-length 2048 --num-train-epochs 5 --gradient-accumulation-steps 4 --lora-rank 16 --lora-alpha 32 --output-dir legacy_cobol_env/outputs/training/sft-qwen3-14b-clean
|
| 595 |
+
|
| 596 |
+
|
| 597 |
+
|
| 598 |
+
|
| 599 |
+
|
| 600 |
+
|
| 601 |
+
|
| 602 |
+
|
| 603 |
+
|
| 604 |
+
|
| 605 |
+
{
|
| 606 |
+
"sft_plan": {
|
| 607 |
+
"dataset": "legacy_cobol_env/outputs/training/oracle_sft.jsonl",
|
| 608 |
+
"output_dir": "legacy_cobol_env/outputs/training/sft-qwen3-14b-clean",
|
| 609 |
+
"model_name": "Qwen/Qwen3-14B",
|
| 610 |
+
"max_seq_length": 2048,
|
| 611 |
+
"num_train_epochs": 5.0,
|
| 612 |
+
"learning_rate": 0.0002,
|
| 613 |
+
"per_device_train_batch_size": 1,
|
| 614 |
+
"gradient_accumulation_steps": 4,
|
| 615 |
+
"lora_rank": 16,
|
| 616 |
+
"lora_alpha": 32,
|
| 617 |
+
"lora_dropout": 0.05,
|
| 618 |
+
"load_in_4bit": true,
|
| 619 |
+
"bf16": true,
|
| 620 |
+
"dataset_examples": 15,
|
| 621 |
+
"families": [
|
| 622 |
+
"account_status_level88",
|
| 623 |
+
"claims_eligibility_branching",
|
| 624 |
+
"date_normalization",
|
| 625 |
+
"decimal_copybook_payroll",
|
| 626 |
+
"fixed_width_customer",
|
| 627 |
+
"invoice_occurs_totals"
|
| 628 |
+
],
|
| 629 |
+
"uses_lora": true,
|
| 630 |
+
"training_dependencies": [
|
| 631 |
+
"torch",
|
| 632 |
+
"transformers",
|
| 633 |
+
"datasets",
|
| 634 |
+
"peft",
|
| 635 |
+
"trl",
|
| 636 |
+
"accelerate"
|
| 637 |
+
]
|
| 638 |
+
}
|
| 639 |
+
}
|
| 640 |
+
[transformers] The tokenizer has new PAD/BOS/EOS tokens that differ from the model config and generation config. The model config and generation config were aligned accordingly, being updated with the tokenizer's values. Updated tokens: {'bos_token_id': None, 'pad_token_id': 151643}.
|
| 641 |
+
|
| 642 |
+
|
| 643 |
0%| | 0/20 [00:00<?, ?it/s][A
|
| 644 |
+
|
| 645 |
5%|▌ | 1/20 [00:06<02:07, 6.73s/it][A
|
| 646 |
+
|
| 647 |
|
| 648 |
+
{'loss': '1.135', 'grad_norm': '0.5547', 'learning_rate': '0.0002', 'entropy': '0.5034', 'num_tokens': '8192', 'mean_token_accuracy': '0.7938', 'epoch': '0.2667'}
|
| 649 |
+
|
| 650 |
5%|▌ | 1/20 [00:06<02:07, 6.73s/it][A
|
| 651 |
+
|
| 652 |
10%|█ | 2/20 [00:12<01:48, 6.04s/it][A
|
| 653 |
+
|
| 654 |
|
| 655 |
+
{'loss': '1.044', 'grad_norm': '0.5586', 'learning_rate': '0.00019', 'entropy': '0.4721', 'num_tokens': '1.534e+04', 'mean_token_accuracy': '0.812', 'epoch': '0.5333'}
|
| 656 |
+
|
| 657 |
10%|█ | 2/20 [00:12<01:48, 6.04s/it][A
|
| 658 |
+
|
| 659 |
15%|█▌ | 3/20 [00:17<01:38, 5.79s/it][A
|
| 660 |
+
{'loss': '0.8919', 'grad_norm': '0.5039', 'learning_rate': '0.00018', 'entropy': '0.5121', 'num_tokens': '2.241e+04', 'mean_token_accuracy': '0.8255', 'epoch': '0.8'}
|
| 661 |
+
|
| 662 |
|
| 663 |
+
|
| 664 |
15%|█▌ | 3/20 [00:17<01:38, 5.79s/it][A
|
| 665 |
+
|
| 666 |
20%|██ | 4/20 [00:22<01:27, 5.45s/it][A
|
| 667 |
+
{'loss': '0.8053', 'grad_norm': '0.2988', 'learning_rate': '0.00017', 'entropy': '0.6193', 'num_tokens': '2.855e+04', 'mean_token_accuracy': '0.8334', 'epoch': '1'}
|
| 668 |
+
|
| 669 |
|
| 670 |
+
|
| 671 |
20%|██ | 4/20 [00:22<01:27, 5.45s/it][A
|
| 672 |
+
|
| 673 |
25%|██▌ | 5/20 [00:29<01:27, 5.85s/it][A
|
| 674 |
+
|
| 675 |
|
| 676 |
+
{'loss': '0.7192', 'grad_norm': '0.2393', 'learning_rate': '0.00016', 'entropy': '0.6785', 'num_tokens': '3.637e+04', 'mean_token_accuracy': '0.8479', 'epoch': '1.267'}
|
| 677 |
+
|
| 678 |
25%|██▌ | 5/20 [00:29<01:27, 5.85s/it][A
|
| 679 |
+
|
| 680 |
30%|███ | 6/20 [00:34<01:19, 5.70s/it][A
|
| 681 |
+
|
| 682 |
|
| 683 |
+
{'loss': '0.7439', 'grad_norm': '0.2422', 'learning_rate': '0.00015', 'entropy': '0.7696', 'num_tokens': '4.332e+04', 'mean_token_accuracy': '0.8394', 'epoch': '1.533'}
|
| 684 |
+
|
| 685 |
30%|███ | 6/20 [00:34<01:19, 5.70s/it][A
|
| 686 |
+
|
| 687 |
35%|███▌ | 7/20 [00:40<01:16, 5.90s/it][A
|
| 688 |
+
|
| 689 |
|
| 690 |
+
{'loss': '0.6708', 'grad_norm': '0.2207', 'learning_rate': '0.00014', 'entropy': '0.7893', 'num_tokens': '5.151e+04', 'mean_token_accuracy': '0.8549', 'epoch': '1.8'}
|
| 691 |
+
|
| 692 |
35%|███▌ | 7/20 [00:40<01:16, 5.90s/it][A
|
| 693 |
+
|
| 694 |
40%|████ | 8/20 [00:45<01:05, 5.43s/it][A
|
| 695 |
+
|
| 696 |
|
| 697 |
+
{'loss': '0.6371', 'grad_norm': '0.2441', 'learning_rate': '0.00013', 'entropy': '0.7936', 'num_tokens': '5.71e+04', 'mean_token_accuracy': '0.8601', 'epoch': '2'}
|
| 698 |
+
|
| 699 |
40%|████ | 8/20 [00:45<01:05, 5.43s/it][A
|
| 700 |
+
|
| 701 |
45%|████▌ | 9/20 [00:52<01:06, 6.01s/it][A
|
| 702 |
+
|
| 703 |
|
| 704 |
+
{'loss': '0.5484', 'grad_norm': '0.2578', 'learning_rate': '0.00012', 'entropy': '0.727', 'num_tokens': '6.475e+04', 'mean_token_accuracy': '0.8757', 'epoch': '2.267'}
|
| 705 |
+
|
| 706 |
45%|████▌ | 9/20 [00:52<01:06, 6.01s/it][A
|
| 707 |
+
|
| 708 |
50%|█████ | 10/20 [00:58<01:00, 6.01s/it][A
|
| 709 |
+
|
| 710 |
|
| 711 |
+
{'loss': '0.5467', 'grad_norm': '0.2637', 'learning_rate': '0.00011', 'entropy': '0.7256', 'num_tokens': '7.257e+04', 'mean_token_accuracy': '0.8786', 'epoch': '2.533'}
|
| 712 |
+
|
| 713 |
50%|█████ | 10/20 [00:58<01:00, 6.01s/it][A
|
| 714 |
+
|
| 715 |
55%|█████▌ | 11/20 [01:04<00:52, 5.83s/it][A
|
| 716 |
+
|
| 717 |
|
| 718 |
+
{'loss': '0.4667', 'grad_norm': '0.252', 'learning_rate': '0.0001', 'entropy': '0.5945', 'num_tokens': '7.951e+04', 'mean_token_accuracy': '0.8898', 'epoch': '2.8'}
|
| 719 |
+
|
| 720 |
55%|█████▌ | 11/20 [01:04<00:52, 5.83s/it][A
|
| 721 |
+
|
| 722 |
60%|██████ | 12/20 [01:08<00:44, 5.53s/it][A
|
| 723 |
+
|
| 724 |
|
| 725 |
+
{'loss': '0.4835', 'grad_norm': '0.2773', 'learning_rate': '9e-05', 'entropy': '0.6566', 'num_tokens': '8.566e+04', 'mean_token_accuracy': '0.8901', 'epoch': '3'}
|
| 726 |
+
|
| 727 |
60%|██████ | 12/20 [01:08<00:44, 5.53s/it][A
|
| 728 |
+
|
| 729 |
65%|██████▌ | 13/20 [01:15<00:40, 5.82s/it][A
|
| 730 |
+
|
| 731 |
|
| 732 |
+
{'loss': '0.4375', 'grad_norm': '0.2461', 'learning_rate': '8e-05', 'entropy': '0.5715', 'num_tokens': '9.328e+04', 'mean_token_accuracy': '0.8986', 'epoch': '3.267'}
|
| 733 |
+
|
| 734 |
65%|██████▌ | 13/20 [01:15<00:40, 5.82s/it][A
|
| 735 |
+
|
| 736 |
70%|███████ | 14/20 [01:21<00:35, 5.86s/it][A
|
| 737 |
+
{'loss': '0.4141', 'grad_norm': '0.3359', 'learning_rate': '7e-05', 'entropy': '0.537', 'num_tokens': '1.009e+05', 'mean_token_accuracy': '0.8993', 'epoch': '3.533'}
|
| 738 |
+
|
| 739 |
|
| 740 |
+
|
| 741 |
70%|███████ | 14/20 [01:21<00:35, 5.86s/it][A
|
| 742 |
+
|
| 743 |
75%|███████▌ | 15/20 [01:27<00:29, 5.88s/it][A
|
| 744 |
+
|
| 745 |
|
| 746 |
+
{'loss': '0.3599', 'grad_norm': '0.2578', 'learning_rate': '6e-05', 'entropy': '0.4374', 'num_tokens': '1.084e+05', 'mean_token_accuracy': '0.9111', 'epoch': '3.8'}
|
| 747 |
+
|
| 748 |
75%|███████▌ | 15/20 [01:27<00:29, 5.88s/it][A
|
| 749 |
+
|
| 750 |
80%|████████ | 16/20 [01:31<00:22, 5.50s/it][A
|
| 751 |
+
|
| 752 |
|
| 753 |
+
{'loss': '0.2364', 'grad_norm': '0.2754', 'learning_rate': '5e-05', 'entropy': '0.328', 'num_tokens': '1.142e+05', 'mean_token_accuracy': '0.938', 'epoch': '4'}
|
| 754 |
+
|
| 755 |
80%|████████ | 16/20 [01:31<00:22, 5.50s/it][A
|
| 756 |
+
|
| 757 |
85%|████████▌ | 17/20 [01:38<00:17, 5.81s/it][A
|
| 758 |
+
|
| 759 |
|
| 760 |
+
{'loss': '0.3648', 'grad_norm': '0.2715', 'learning_rate': '4e-05', 'entropy': '0.4187', 'num_tokens': '1.217e+05', 'mean_token_accuracy': '0.9143', 'epoch': '4.267'}
|
| 761 |
+
|
| 762 |
85%|████████▌ | 17/20 [01:38<00:17, 5.81s/it][A
|
| 763 |
+
|
| 764 |
90%|█████████ | 18/20 [01:44<00:12, 6.01s/it][A
|
| 765 |
+
|
| 766 |
|
| 767 |
+
{'loss': '0.2731', 'grad_norm': '0.252', 'learning_rate': '3e-05', 'entropy': '0.3601', 'num_tokens': '1.299e+05', 'mean_token_accuracy': '0.936', 'epoch': '4.533'}
|
| 768 |
+
|
| 769 |
90%|█████████ | 18/20 [01:44<00:12, 6.01s/it][A
|
| 770 |
+
|
| 771 |
95%|█████████▌| 19/20 [01:50<00:05, 5.93s/it][A
|
| 772 |
+
|
| 773 |
|
| 774 |
+
{'loss': '0.2764', 'grad_norm': '0.249', 'learning_rate': '2e-05', 'entropy': '0.3304', 'num_tokens': '1.372e+05', 'mean_token_accuracy': '0.9352', 'epoch': '4.8'}
|
| 775 |
+
|
| 776 |
95%|█████████▌| 19/20 [01:50<00:05, 5.93s/it][A
|
| 777 |
+
|
| 778 |
+
{'loss': '0.1924', 'grad_norm': '0.2734', 'learning_rate': '1e-05', 'entropy': '0.2629', 'num_tokens': '1.428e+05', 'mean_token_accuracy': '0.9483', 'epoch': '5'}
|
| 779 |
+
|
| 780 |
|
| 781 |
+
|
| 782 |
+
|
| 783 |
|
| 784 |
+
{'train_runtime': '115.8', 'train_samples_per_second': '0.648', 'train_steps_per_second': '0.173', 'train_loss': '0.5623', 'epoch': '5'}
|
| 785 |
+
|
| 786 |
+
$ /root/.cache/uv/builds-v0/.tmpQi62S5/bin/python -m legacy_cobol_env.eval.run_model_rollouts --provider local-transformers --max-repairs 2 --output legacy_cobol_env/outputs/evals/sft_local_qwen3_14b_all_tasks.json
|
| 787 |
+
|
| 788 |
+
|
| 789 |
+
|
| 790 |
+
|
| 791 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 792 |
+
torch._check_is_size(blocksize)
|
| 793 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 794 |
+
torch._check_is_size(blocksize)
|
| 795 |
+
|
| 796 |
+
|
| 797 |
+
|
| 798 |
+
|
| 799 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 800 |
+
torch._check_is_size(blocksize)
|
| 801 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 802 |
+
torch._check_is_size(blocksize)
|
| 803 |
+
|
| 804 |
+
|
| 805 |
+
|
| 806 |
+
|
| 807 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 808 |
+
torch._check_is_size(blocksize)
|
| 809 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 810 |
+
torch._check_is_size(blocksize)
|
| 811 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 812 |
+
torch._check_is_size(blocksize)
|
| 813 |
+
|
| 814 |
+
|
| 815 |
+
|
| 816 |
+
|
| 817 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 818 |
+
torch._check_is_size(blocksize)
|
| 819 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 820 |
+
torch._check_is_size(blocksize)
|
| 821 |
+
|
| 822 |
+
|
| 823 |
+
|
| 824 |
+
|
| 825 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 826 |
+
torch._check_is_size(blocksize)
|
| 827 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 828 |
+
torch._check_is_size(blocksize)
|
| 829 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 830 |
+
torch._check_is_size(blocksize)
|
| 831 |
+
|
| 832 |
+
|
| 833 |
+
|
| 834 |
+
|
| 835 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 836 |
+
torch._check_is_size(blocksize)
|
| 837 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 838 |
+
torch._check_is_size(blocksize)
|
| 839 |
+
/root/.cache/uv/archive-v0/_zCg95lZEBKJ9MwE5wW11/lib/python3.12/site-packages/bitsandbytes/backends/cuda/ops.py:468: FutureWarning: _check_is_size will be removed in a future PyTorch release along with guard_size_oblivious. Use _check(i >= 0) instead.
|
| 840 |
+
torch._check_is_size(blocksize)
|
| 841 |
+
{
|
| 842 |
+
"provider": "local-transformers",
|
| 843 |
+
"task_count": 6,
|
| 844 |
+
"mean_public_score": 0.7971166666666667,
|
| 845 |
+
"accepted_count": 4
|
| 846 |
+
}
|
| 847 |
+
Traceback (most recent call last):
|
| 848 |
+
File "//hf_qwen3_14b_train_job_h200.py", line 108, in <module>
|
| 849 |
+
state = json.loads((out / "trainer_state.json").read_text())
|
| 850 |
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| 851 |
+
File "/usr/local/lib/python3.12/pathlib.py", line 1027, in read_text
|
| 852 |
+
with self.open(mode='r', encoding=encoding, errors=errors) as f:
|
| 853 |
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| 854 |
+
File "/usr/local/lib/python3.12/pathlib.py", line 1013, in open
|
| 855 |
+
return io.open(self, mode, buffering, encoding, errors, newline)
|
| 856 |
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| 857 |
+
FileNotFoundError: [Errno 2] No such file or directory: 'legacy_cobol_env/outputs/training/sft-qwen3-14b-clean/trainer_state.json'
|
outputs/training/oracle_sft.jsonl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
outputs/training/qwen3_14b_training_evidence_summary.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"model": "Qwen/Qwen3-14B",
|
| 3 |
+
"method": "Hugging Face TRL LoRA SFT",
|
| 4 |
+
"job_id": "69edbce1d70108f37acdfcdf",
|
| 5 |
+
"hardware": "HF Jobs l40sx1",
|
| 6 |
+
"dataset_examples": 15,
|
| 7 |
+
"loss_first": 1.135,
|
| 8 |
+
"loss_last": 0.1924,
|
| 9 |
+
"mean_token_accuracy_first": 0.7938,
|
| 10 |
+
"mean_token_accuracy_last": 0.9483,
|
| 11 |
+
"base_mean_public_score": 0.532,
|
| 12 |
+
"trained_mean_public_score": 0.7971166666666667,
|
| 13 |
+
"base_accepted_count": 2,
|
| 14 |
+
"trained_accepted_count": 4,
|
| 15 |
+
"task_count": 6
|
| 16 |
+
}
|
outputs/training/sft_loss.csv
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
epoch,loss,mean_token_accuracy
|
| 2 |
+
0.2667,1.135,0.7938
|
| 3 |
+
0.5333,1.044,0.812
|
| 4 |
+
0.8,0.8919,0.8255
|
| 5 |
+
1.0,0.8053,0.8334
|
| 6 |
+
1.267,0.7192,0.8479
|
| 7 |
+
1.533,0.7439,0.8394
|
| 8 |
+
1.8,0.6708,0.8549
|
| 9 |
+
2.0,0.6371,0.8601
|
| 10 |
+
2.267,0.5484,0.8757
|
| 11 |
+
2.533,0.5467,0.8786
|
| 12 |
+
2.8,0.4667,0.8898
|
| 13 |
+
3.0,0.4835,0.8901
|
| 14 |
+
3.267,0.4375,0.8986
|
| 15 |
+
3.533,0.4141,0.8993
|
| 16 |
+
3.8,0.3599,0.9111
|
| 17 |
+
4.0,0.2364,0.938
|
| 18 |
+
4.267,0.3648,0.9143
|
| 19 |
+
4.533,0.2731,0.936
|
| 20 |
+
4.8,0.2764,0.9352
|
| 21 |
+
5.0,0.1924,0.9483
|
outputs/training/sft_run_metadata.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"status": "completed",
|
| 3 |
+
"created_at": "2026-04-26T07:21:05.747000+00:00",
|
| 4 |
+
"model": "Qwen/Qwen3-14B",
|
| 5 |
+
"method": "Hugging Face TRL LoRA SFT",
|
| 6 |
+
"job_id": "69edbce1d70108f37acdfcdf",
|
| 7 |
+
"hardware": "HF Jobs l40sx1",
|
| 8 |
+
"dataset": "legacy_cobol_env/outputs/training/oracle_sft.jsonl",
|
| 9 |
+
"dataset_examples": 15,
|
| 10 |
+
"num_train_epochs": 5,
|
| 11 |
+
"max_seq_length": 2048,
|
| 12 |
+
"lora_rank": 16,
|
| 13 |
+
"lora_alpha": 32,
|
| 14 |
+
"loss_first": 1.135,
|
| 15 |
+
"loss_last": 0.1924,
|
| 16 |
+
"mean_token_accuracy_first": 0.7938,
|
| 17 |
+
"mean_token_accuracy_last": 0.9483,
|
| 18 |
+
"base_mean_public_score": 0.532,
|
| 19 |
+
"trained_mean_public_score": 0.7971166666666667,
|
| 20 |
+
"base_accepted_count": 2,
|
| 21 |
+
"trained_accepted_count": 4,
|
| 22 |
+
"task_count": 6,
|
| 23 |
+
"artifacts": {
|
| 24 |
+
"loss_csv": "outputs/training/sft_loss.csv",
|
| 25 |
+
"loss_plot": "plots/qwen3_14b_loss_curve.png",
|
| 26 |
+
"reward_plot": "plots/qwen3_14b_reward_before_after.png",
|
| 27 |
+
"accepted_plot": "plots/qwen3_14b_accepted_before_after.png",
|
| 28 |
+
"raw_hf_job_log": "outputs/training/hf_job_qwen3_14b_logs.txt",
|
| 29 |
+
"summary": "outputs/training/qwen3_14b_training_evidence_summary.json"
|
| 30 |
+
},
|
| 31 |
+
"note": "Training and local evaluation artifacts were extracted from the HF Jobs run. The raw job log includes a later post-run artifact upload traceback after the training and evaluation summary had been emitted."
|
| 32 |
+
}
|
plots/baseline_scores.svg
ADDED
|
|
plots/model_scores.svg
ADDED
|
|
plots/qwen3_14b_accepted_before_after.png
ADDED
|
plots/qwen3_14b_loss_curve.png
ADDED
|
plots/qwen3_14b_reward_before_after.png
ADDED
|
plots/qwen3_14b_training_reward_evidence_dashboard.png
ADDED
|
Git LFS Details
|
pyproject.toml
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
# All rights reserved.
|
| 3 |
+
#
|
| 4 |
+
# This source code is licensed under the BSD-style license found in the
|
| 5 |
+
# LICENSE file in the root directory of this source tree.
|
| 6 |
+
|
| 7 |
+
[build-system]
|
| 8 |
+
requires = ["setuptools>=45", "wheel"]
|
| 9 |
+
build-backend = "setuptools.build_meta"
|
| 10 |
+
|
| 11 |
+
[project]
|
| 12 |
+
name = "openenv-legacy_cobol_env"
|
| 13 |
+
version = "0.1.0"
|
| 14 |
+
description = "Legacy COBOL migration workbench environment for OpenEnv"
|
| 15 |
+
requires-python = ">=3.10"
|
| 16 |
+
dependencies = [
|
| 17 |
+
"openenv-core>=0.2.3",
|
| 18 |
+
]
|
| 19 |
+
|
| 20 |
+
[project.optional-dependencies]
|
| 21 |
+
dev = [
|
| 22 |
+
"pytest>=8.0.0",
|
| 23 |
+
"pytest-cov>=4.0.0",
|
| 24 |
+
]
|
| 25 |
+
|
| 26 |
+
[project.scripts]
|
| 27 |
+
# Server entry point - enables running via: uv run --project . server
|
| 28 |
+
# or: python -m legacy_cobol_env.server.app
|
| 29 |
+
server = "legacy_cobol_env.server.app:main"
|
| 30 |
+
|
| 31 |
+
[tool.setuptools]
|
| 32 |
+
include-package-data = true
|
| 33 |
+
packages = ["legacy_cobol_env", "legacy_cobol_env.server", "legacy_cobol_env.eval", "legacy_cobol_env.training"]
|
| 34 |
+
package-dir = { "legacy_cobol_env" = ".", "legacy_cobol_env.server" = "server", "legacy_cobol_env.eval" = "eval", "legacy_cobol_env.training" = "training" }
|
server/Dockerfile
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
# All rights reserved.
|
| 3 |
+
#
|
| 4 |
+
# This source code is licensed under the BSD-style license found in the
|
| 5 |
+
# LICENSE file in the root directory of this source tree.
|
| 6 |
+
|
| 7 |
+
# Multi-stage build using openenv-base
|
| 8 |
+
# This Dockerfile is flexible and works for both:
|
| 9 |
+
# - In-repo environments (with local OpenEnv sources)
|
| 10 |
+
# - Standalone environments (with openenv from PyPI/Git)
|
| 11 |
+
# The build script (openenv build) handles context detection and sets appropriate build args.
|
| 12 |
+
|
| 13 |
+
ARG BASE_IMAGE=ghcr.io/meta-pytorch/openenv-base:latest
|
| 14 |
+
FROM ${BASE_IMAGE} AS builder
|
| 15 |
+
|
| 16 |
+
WORKDIR /app
|
| 17 |
+
|
| 18 |
+
# Ensure git is available (required for installing dependencies from VCS)
|
| 19 |
+
RUN apt-get update && \
|
| 20 |
+
apt-get install -y --no-install-recommends git && \
|
| 21 |
+
rm -rf /var/lib/apt/lists/*
|
| 22 |
+
|
| 23 |
+
# Build argument to control whether we're building standalone or in-repo
|
| 24 |
+
ARG BUILD_MODE=in-repo
|
| 25 |
+
ARG ENV_NAME=legacy_cobol_env
|
| 26 |
+
|
| 27 |
+
# Copy environment code (always at root of build context)
|
| 28 |
+
COPY . /app/env
|
| 29 |
+
|
| 30 |
+
# For in-repo builds, openenv is already vendored in the build context
|
| 31 |
+
# For standalone builds, openenv will be installed via pyproject.toml
|
| 32 |
+
WORKDIR /app/env
|
| 33 |
+
|
| 34 |
+
# Ensure uv is available (for local builds where base image lacks it)
|
| 35 |
+
RUN if ! command -v uv >/dev/null 2>&1; then \
|
| 36 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh && \
|
| 37 |
+
mv /root/.local/bin/uv /usr/local/bin/uv && \
|
| 38 |
+
mv /root/.local/bin/uvx /usr/local/bin/uvx; \
|
| 39 |
+
fi
|
| 40 |
+
|
| 41 |
+
# Install dependencies using uv sync
|
| 42 |
+
# If uv.lock exists, use it; otherwise resolve on the fly
|
| 43 |
+
RUN --mount=type=cache,target=/root/.cache/uv \
|
| 44 |
+
if [ -f uv.lock ]; then \
|
| 45 |
+
uv sync --frozen --no-install-project --no-editable; \
|
| 46 |
+
else \
|
| 47 |
+
uv sync --no-install-project --no-editable; \
|
| 48 |
+
fi
|
| 49 |
+
|
| 50 |
+
RUN --mount=type=cache,target=/root/.cache/uv \
|
| 51 |
+
if [ -f uv.lock ]; then \
|
| 52 |
+
uv sync --frozen --no-editable; \
|
| 53 |
+
else \
|
| 54 |
+
uv sync --no-editable; \
|
| 55 |
+
fi
|
| 56 |
+
|
| 57 |
+
# Final runtime stage
|
| 58 |
+
FROM ${BASE_IMAGE}
|
| 59 |
+
|
| 60 |
+
WORKDIR /app
|
| 61 |
+
|
| 62 |
+
# Copy the virtual environment from builder
|
| 63 |
+
COPY --from=builder /app/env/.venv /app/.venv
|
| 64 |
+
|
| 65 |
+
# Copy the environment code
|
| 66 |
+
COPY --from=builder /app/env /app/env
|
| 67 |
+
|
| 68 |
+
# Set PATH to use the virtual environment
|
| 69 |
+
ENV PATH="/app/.venv/bin:$PATH"
|
| 70 |
+
|
| 71 |
+
# Set PYTHONPATH so imports work correctly
|
| 72 |
+
ENV PYTHONPATH="/app/env:$PYTHONPATH"
|
| 73 |
+
|
| 74 |
+
# Health check
|
| 75 |
+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
| 76 |
+
CMD curl -f http://localhost:8000/health || exit 1
|
| 77 |
+
|
| 78 |
+
# Run the FastAPI server
|
| 79 |
+
# The module path is constructed to work with the /app/env structure
|
| 80 |
+
CMD ["sh", "-c", "cd /app/env && uvicorn server.app:app --host 0.0.0.0 --port 8000"]
|