Spaces:
Running
Running
Clean repo docs and consolidate project history
Browse files- .gitignore +2 -4
- KNOWLEDGE.md +492 -288
- PROJECT_STATUS.md +124 -323
- README.md +5 -5
- ROADMAP.md +0 -672
- analysis/competition_notes.md +0 -87
- analysis/deep_competitive_gap_report.md +0 -1374
- analysis/grounding_audit.md +0 -77
- analysis/scoring_contract.md +0 -71
- gaps.md +0 -146
- required.md +7 -6
.gitignore
CHANGED
|
@@ -6,7 +6,5 @@ __pycache__/
|
|
| 6 |
.mypy_cache/
|
| 7 |
.ruff_cache/
|
| 8 |
build/
|
| 9 |
-
analysis/
|
| 10 |
-
|
| 11 |
-
analysis/policy_learning_compare_test/
|
| 12 |
-
analysis/policy_learning_runs_smoke/
|
|
|
|
| 6 |
.mypy_cache/
|
| 7 |
.ruff_cache/
|
| 8 |
build/
|
| 9 |
+
analysis/
|
| 10 |
+
.codex-*/
|
|
|
|
|
|
KNOWLEDGE.md
CHANGED
|
@@ -1,424 +1,628 @@
|
|
| 1 |
-
# IT Helpdesk Ticket Routing OpenEnv -
|
| 2 |
|
| 3 |
-
|
| 4 |
|
| 5 |
-
The
|
| 6 |
|
| 7 |
-
|
| 8 |
|
| 9 |
-
|
| 10 |
-
2. working `reset()`, `step()`, and `state()`
|
| 11 |
-
3. at least three difficulty levels
|
| 12 |
-
4. deterministic grading
|
| 13 |
-
5. meaningful reward shaping
|
| 14 |
-
6. a baseline `inference.py`
|
| 15 |
-
7. Docker and metadata that are easy to rerun
|
| 16 |
|
| 17 |
-
|
| 18 |
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
- judge-friendly
|
| 24 |
-
- deterministic to grade
|
| 25 |
-
- naturally multi-step
|
| 26 |
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
-
|
| 30 |
|
| 31 |
-
|
| 32 |
|
| 33 |
-
|
| 34 |
|
| 35 |
-
|
| 36 |
|
| 37 |
-
1.
|
| 38 |
-
2.
|
| 39 |
-
3.
|
| 40 |
-
4.
|
|
|
|
| 41 |
|
| 42 |
-
|
| 43 |
|
| 44 |
-
-
|
| 45 |
-
-
|
| 46 |
-
-
|
| 47 |
-
-
|
| 48 |
-
- App environment name: `it_helpdesk_ticket_routing`
|
| 49 |
|
| 50 |
-
|
| 51 |
|
| 52 |
-
|
| 53 |
-
inference.py
|
| 54 |
-
|
|
| 55 |
-
v
|
| 56 |
-
client.py <----> server/app.py
|
| 57 |
-
|
|
| 58 |
-
v
|
| 59 |
-
server/environment.py
|
| 60 |
-
| | |
|
| 61 |
-
v v v
|
| 62 |
-
grader.py reward.py tasks.py
|
| 63 |
-
|
|
| 64 |
-
v
|
| 65 |
-
data/dataset.json
|
| 66 |
-
```
|
| 67 |
|
| 68 |
-
The
|
| 69 |
|
| 70 |
-
|
| 71 |
-
- `client.py` talks to the app
|
| 72 |
-
- `server/environment.py` manages queue state and episode flow
|
| 73 |
-
- `server/grader.py` scores actions
|
| 74 |
-
- `server/reward.py` computes step and final reward behavior
|
| 75 |
-
- `server/tasks.py` defines the task ladder and loads the dataset
|
| 76 |
-
- `data/dataset.json` stores the labeled helpdesk tickets
|
| 77 |
|
| 78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
-
|
| 81 |
|
| 82 |
-
|
| 83 |
-
- `priority`
|
| 84 |
-
- `assignment_group`
|
| 85 |
-
- `resolution_action`
|
| 86 |
|
| 87 |
-
|
| 88 |
|
| 89 |
-
|
| 90 |
-
- `identity_access`
|
| 91 |
-
- `application_support`
|
| 92 |
-
- `service_request`
|
| 93 |
-
- `spam_phishing`
|
| 94 |
-
- `general_inquiry`
|
| 95 |
-
- `security_compliance`
|
| 96 |
-
- `onboarding`
|
| 97 |
-
- `feature_request`
|
| 98 |
|
| 99 |
-
|
|
|
|
|
|
|
| 100 |
|
| 101 |
-
|
| 102 |
-
- `service_desk`
|
| 103 |
-
- `application_team`
|
| 104 |
-
- `procurement`
|
| 105 |
-
- `security_team`
|
| 106 |
-
- `onboarding_ops`
|
| 107 |
|
| 108 |
-
|
|
|
|
| 109 |
|
| 110 |
-
|
| 111 |
-
- `escalate`
|
| 112 |
-
- `assign`
|
| 113 |
-
- `ignore`
|
| 114 |
-
- `acknowledge`
|
| 115 |
|
| 116 |
-
|
|
|
|
| 117 |
|
| 118 |
-
|
| 119 |
|
| 120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 121 |
|
| 122 |
-
|
| 123 |
|
| 124 |
-
|
| 125 |
-
- `title`
|
| 126 |
-
- `requester`
|
| 127 |
-
- `description`
|
| 128 |
-
- `issue_type`
|
| 129 |
-
- `priority`
|
| 130 |
-
- `assignment_group`
|
| 131 |
-
- `resolution_action`
|
| 132 |
-
- optional `ambiguity_note`
|
| 133 |
-
- optional `related_ticket_id`
|
| 134 |
|
| 135 |
-
|
| 136 |
|
| 137 |
-
|
| 138 |
|
| 139 |
-
|
| 140 |
|
| 141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
|
| 143 |
-
|
| 144 |
-
- visible ticket fields
|
| 145 |
-
- optional ambiguity or follow-up context
|
| 146 |
-
- queue progress
|
| 147 |
-
- score history
|
| 148 |
|
| 149 |
-
##
|
| 150 |
|
| 151 |
-
|
| 152 |
|
| 153 |
-
|
| 154 |
|
| 155 |
-
### `
|
| 156 |
|
| 157 |
-
|
| 158 |
|
| 159 |
-
|
| 160 |
-
2. samples a queue of 3 to 5 tickets
|
| 161 |
-
3. initializes a new episode id and state
|
| 162 |
-
4. returns the first observation
|
| 163 |
|
| 164 |
-
|
| 165 |
|
| 166 |
-
|
|
|
|
|
|
|
|
|
|
| 167 |
|
| 168 |
-
|
| 169 |
-
2. stores the per-ticket score
|
| 170 |
-
3. increments queue progress
|
| 171 |
-
4. returns the next observation or final result
|
| 172 |
|
| 173 |
-
|
| 174 |
|
| 175 |
-
|
| 176 |
|
| 177 |
-
|
|
|
|
|
|
|
|
|
|
| 178 |
|
| 179 |
-
|
| 180 |
|
| 181 |
-
|
| 182 |
-
- the current ticket
|
| 183 |
-
- available investigation tools
|
| 184 |
-
- remaining free investigation budget
|
| 185 |
-
- the latest tool result, when one was requested
|
| 186 |
-
- queue progress counters
|
| 187 |
-
- history
|
| 188 |
-
- reward and done status
|
| 189 |
|
| 190 |
-
|
| 191 |
|
| 192 |
-
|
| 193 |
-
- `tickets_after_current`: how many tickets remain after the current one
|
| 194 |
-
- `queue_position`: 1-based position of the current ticket in the queue
|
| 195 |
|
| 196 |
-
|
| 197 |
|
| 198 |
-
|
| 199 |
-
- seed
|
| 200 |
-
- queue ticket IDs
|
| 201 |
-
- current ticket index
|
| 202 |
-
- per-ticket scores
|
| 203 |
-
- total reward
|
| 204 |
-
- investigation step count
|
| 205 |
|
| 206 |
-
|
| 207 |
|
| 208 |
-
|
| 209 |
|
| 210 |
-
|
| 211 |
|
| 212 |
-
|
| 213 |
|
| 214 |
-
|
| 215 |
|
| 216 |
-
-
|
|
|
|
|
|
|
| 217 |
|
| 218 |
-
###
|
| 219 |
|
| 220 |
-
|
| 221 |
|
| 222 |
-
|
| 223 |
-
- `priority`
|
| 224 |
|
| 225 |
-
|
|
|
|
| 226 |
|
| 227 |
-
-
|
| 228 |
|
| 229 |
-
|
|
|
|
| 230 |
|
| 231 |
-
|
| 232 |
|
| 233 |
-
|
| 234 |
-
- `priority`
|
| 235 |
-
- `assignment_group`
|
| 236 |
-
- `resolution_action`
|
| 237 |
|
| 238 |
-
|
| 239 |
|
| 240 |
-
-
|
| 241 |
|
| 242 |
-
|
| 243 |
|
| 244 |
-
|
| 245 |
|
| 246 |
-
|
| 247 |
-
- `priority` gets exact or proximity credit
|
| 248 |
-
- `assignment_group` gets exact credit
|
| 249 |
-
- `resolution_action` gets exact credit
|
| 250 |
|
| 251 |
-
|
| 252 |
|
| 253 |
-
-
|
| 254 |
-
-
|
| 255 |
-
-
|
| 256 |
-
-
|
|
|
|
| 257 |
|
| 258 |
-
|
| 259 |
|
| 260 |
-
|
| 261 |
-
- Task 2: `issue_type` 60%, `priority` 40%
|
| 262 |
-
- Task 3: `issue_type` 35%, `priority` 20%, `assignment_group` 25%, `resolution_action` 20%
|
| 263 |
|
| 264 |
-
|
| 265 |
|
| 266 |
-
|
|
|
|
|
|
|
|
|
|
| 267 |
|
| 268 |
-
|
| 269 |
|
| 270 |
-
|
| 271 |
|
| 272 |
-
|
| 273 |
|
| 274 |
-
-
|
| 275 |
-
- minus a tiny penalty only if the agent exceeds the free investigation budget for the queue
|
| 276 |
|
| 277 |
-
This
|
| 278 |
|
| 279 |
-
|
| 280 |
|
| 281 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 282 |
|
| 283 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
|
| 285 |
-
- 45 tickets
|
| 286 |
- clear easy examples
|
| 287 |
-
- medium
|
| 288 |
-
-
|
| 289 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 290 |
|
| 291 |
-
|
| 292 |
|
| 293 |
-
|
| 294 |
|
| 295 |
-
|
|
|
|
|
|
|
| 296 |
|
| 297 |
-
|
| 298 |
|
| 299 |
-
|
| 300 |
|
| 301 |
-
|
| 302 |
-
- `Semantic Similarity of IT Support Tickets`
|
| 303 |
-
- `MSDialog`
|
| 304 |
|
| 305 |
-
|
| 306 |
|
| 307 |
-
|
|
|
|
|
|
|
| 308 |
|
| 309 |
-
|
| 310 |
|
| 311 |
-
|
| 312 |
|
| 313 |
-
|
| 314 |
-
2. loads the available tasks
|
| 315 |
-
3. runs one episode for the requested task
|
| 316 |
-
4. picks an action for each ticket
|
| 317 |
-
5. sends the action back through the client
|
| 318 |
-
6. records rewards
|
| 319 |
-
7. prints structured logs for that run
|
| 320 |
|
| 321 |
-
|
|
|
|
|
|
|
| 322 |
|
| 323 |
-
|
| 324 |
-
- LLM mode through an OpenAI-compatible API
|
| 325 |
-
- lightweight investigation-tool calls before the final submit action
|
| 326 |
-
- an explicit local `RUN_ALL_TASKS=1` override when you want the old multi-task sweep
|
| 327 |
|
| 328 |
-
|
| 329 |
|
| 330 |
-
|
| 331 |
-
- `models.py`: typed schema and validation
|
| 332 |
-
- `server/environment.py`: episode engine
|
| 333 |
-
- `server/tasks.py`: task ladder and dataset loader
|
| 334 |
-
- `server/grader.py`: deterministic scoring
|
| 335 |
-
- `server/reward.py`: reward helpers
|
| 336 |
-
- `server/app.py`: OpenEnv app entry point
|
| 337 |
-
- `client.py`: typed multi-step client
|
| 338 |
-
- `openenv.yaml`: environment metadata
|
| 339 |
-
- `server/Dockerfile`: container entry point
|
| 340 |
|
| 341 |
-
|
| 342 |
|
| 343 |
-
|
|
|
|
| 344 |
|
| 345 |
-
###
|
| 346 |
|
| 347 |
-
|
| 348 |
|
| 349 |
-
|
| 350 |
|
| 351 |
-
-
|
| 352 |
-
-
|
| 353 |
-
-
|
| 354 |
-
-
|
| 355 |
-
-
|
| 356 |
|
| 357 |
-
##
|
| 358 |
|
| 359 |
-
|
| 360 |
|
| 361 |
-
|
| 362 |
|
| 363 |
-
|
| 364 |
|
| 365 |
-
|
| 366 |
|
| 367 |
-
|
| 368 |
-
- Task 2: `0.8800`
|
| 369 |
-
- Task 3: `0.9400`
|
| 370 |
-
- Overall: `0.9400`
|
| 371 |
|
| 372 |
-
|
| 373 |
|
| 374 |
-
###
|
| 375 |
|
| 376 |
-
|
|
|
|
| 377 |
|
| 378 |
-
|
| 379 |
-
- the docs consistently describe IT helpdesk ticket routing rather than the old email-triage domain
|
| 380 |
-
- the current local benchmark reference is still `1.0000`, `0.8800`, `0.9400`, overall `0.9400`
|
| 381 |
-
- the remaining work is execution validation, not documentation cleanup
|
| 382 |
|
| 383 |
-
|
|
|
|
| 384 |
|
| 385 |
-
|
| 386 |
|
| 387 |
-
|
| 388 |
-
- explicit judge-facing explanation that scoring is deterministic and only partially fuzzy in declared places
|
| 389 |
-
- an internal grounding note tying the label space to public IT-support datasets
|
| 390 |
-
- a refreshed compliance snapshot in `required.md`
|
| 391 |
|
| 392 |
-
The
|
| 393 |
|
| 394 |
-
|
| 395 |
|
| 396 |
-
|
| 397 |
|
| 398 |
-
|
| 399 |
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
|
|
|
|
|
|
| 405 |
|
| 406 |
-
##
|
| 407 |
|
| 408 |
-
|
| 409 |
|
| 410 |
-
|
| 411 |
-
|
|
|
|
|
|
|
| 412 |
|
| 413 |
-
## One-Minute
|
| 414 |
|
| 415 |
-
If you
|
| 416 |
|
| 417 |
-
-
|
| 418 |
-
- the
|
| 419 |
-
-
|
| 420 |
-
-
|
| 421 |
-
- the
|
| 422 |
-
- the
|
| 423 |
-
- `inference.py` is the baseline agent runner
|
| 424 |
-
- merged-state validation, Docker smoke coverage, clean-copy rerun, and local validator readiness are all now in place
|
|
|
|
| 1 |
+
# IT Helpdesk Ticket Routing OpenEnv - Mentor Guide
|
| 2 |
|
| 3 |
+
This document is written as if I am mentoring someone who only knows basic Python and wants to understand how to build this project well.
|
| 4 |
|
| 5 |
+
The goal is not to teach every code detail. The goal is to explain the real-world thinking behind the project so you understand what you are building, why each piece exists, and how all the parts fit together.
|
| 6 |
|
| 7 |
+
## Start With The Big Picture
|
| 8 |
|
| 9 |
+
This project is a small simulation of an IT helpdesk team.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
+
A company receives support tickets like:
|
| 12 |
|
| 13 |
+
- "I was charged twice after the integration outage"
|
| 14 |
+
- "My admin account is locked and I cannot access payroll"
|
| 15 |
+
- "Can we extend this contractor account for two more weeks?"
|
| 16 |
+
- "We think this email is a phishing attempt"
|
| 17 |
|
| 18 |
+
A human helpdesk lead does not just read those tickets and say "this is category X."
|
| 19 |
+
They also decide:
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
+
- how urgent it is
|
| 22 |
+
- which team should own it
|
| 23 |
+
- what the next action should be
|
| 24 |
+
- whether to gather more information first
|
| 25 |
+
- whether this is big enough to open an incident
|
| 26 |
+
- whether to delay one ticket because a more important cluster is coming
|
| 27 |
|
| 28 |
+
That is why this project is stronger than a simple text classifier. It tries to model a small operational workflow, not just a label lookup.
|
| 29 |
|
| 30 |
+
## What OpenEnv Means In Plain English
|
| 31 |
|
| 32 |
+
OpenEnv is a way of turning a real task into an environment that an agent can interact with step by step.
|
| 33 |
|
| 34 |
+
Instead of asking a model one question and scoring one answer, we create a loop:
|
| 35 |
|
| 36 |
+
1. the environment shows the agent the current situation
|
| 37 |
+
2. the agent chooses an action
|
| 38 |
+
3. the environment changes state
|
| 39 |
+
4. the agent sees the new situation
|
| 40 |
+
5. this continues until the episode ends
|
| 41 |
|
| 42 |
+
That matters because many real jobs are not one-shot question answering. They involve:
|
| 43 |
|
| 44 |
+
- incomplete information
|
| 45 |
+
- intermediate choices
|
| 46 |
+
- trade-offs
|
| 47 |
+
- consequences that show up later
|
|
|
|
| 48 |
|
| 49 |
+
Helpdesk work fits this pattern well.
|
| 50 |
|
| 51 |
+
## The Real-World Problem We Chose
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
+
The business problem is IT helpdesk ticket routing.
|
| 54 |
|
| 55 |
+
In a real company, support work usually has four important decisions:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
|
| 57 |
+
1. `issue_type`
|
| 58 |
+
- What kind of problem is this really?
|
| 59 |
+
- Example: billing issue, access issue, phishing report, onboarding request.
|
| 60 |
+
2. `priority`
|
| 61 |
+
- How urgent is it?
|
| 62 |
+
- Example: low, medium, high, critical.
|
| 63 |
+
3. `assignment_group`
|
| 64 |
+
- Which team should own it?
|
| 65 |
+
- Example: service desk, security team, procurement, onboarding ops.
|
| 66 |
+
4. `resolution_action`
|
| 67 |
+
- What should happen next?
|
| 68 |
+
- Example: fulfill it directly, assign it, escalate it, acknowledge it, or ignore it.
|
| 69 |
|
| 70 |
+
These four decisions are the heart of the benchmark.
|
| 71 |
|
| 72 |
+
## Why This Problem Is Good For A Hackathon
|
|
|
|
|
|
|
|
|
|
| 73 |
|
| 74 |
+
This use case is strong because it has the right mix of realism and clarity.
|
| 75 |
|
| 76 |
+
It is realistic:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
+
- companies really do route tickets like this every day
|
| 79 |
+
- mistakes are costly
|
| 80 |
+
- urgency and ownership matter
|
| 81 |
|
| 82 |
+
It is structured:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
+
- the inputs are messy natural language
|
| 85 |
+
- the outputs are typed and easy to score
|
| 86 |
|
| 87 |
+
It is judge-friendly:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
+
- someone can understand the workflow quickly
|
| 90 |
+
- the labels are concrete
|
| 91 |
|
| 92 |
+
It is agentic:
|
| 93 |
|
| 94 |
+
- the agent can investigate
|
| 95 |
+
- the agent can ask for more info
|
| 96 |
+
- the agent can defer
|
| 97 |
+
- the agent can open an incident
|
| 98 |
+
- earlier decisions can affect later tickets
|
| 99 |
|
| 100 |
+
## The Mental Model: Think Like A Shift Lead
|
| 101 |
|
| 102 |
+
The best way to understand the environment is to imagine you are the helpdesk shift lead for the next 20 minutes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
+
Tickets are arriving in a short queue.
|
| 105 |
|
| 106 |
+
You cannot treat each ticket as if it lives alone.
|
| 107 |
|
| 108 |
+
Sometimes:
|
| 109 |
|
| 110 |
+
- two tickets are part of the same outage
|
| 111 |
+
- one customer keeps opening related follow-ups
|
| 112 |
+
- your security team has limited bandwidth
|
| 113 |
+
- if you ignore a risky ticket now, it will create another ticket later
|
| 114 |
+
- if you open an incident early, later related tickets become easier to manage
|
| 115 |
|
| 116 |
+
That is the real heart of the benchmark.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
|
| 118 |
+
## What The Agent Actually Does
|
| 119 |
|
| 120 |
+
The agent interacts with the environment one step at a time.
|
| 121 |
|
| 122 |
+
For each ticket, it can choose one of several actions.
|
| 123 |
|
| 124 |
+
### 1. `submit`
|
| 125 |
|
| 126 |
+
This means:
|
| 127 |
|
| 128 |
+
"I know enough. Here is my routing decision."
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
+
The agent provides:
|
| 131 |
|
| 132 |
+
- issue type
|
| 133 |
+
- priority
|
| 134 |
+
- assignment group
|
| 135 |
+
- resolution action
|
| 136 |
|
| 137 |
+
Real-world example:
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
+
A ticket says, "A new contractor starts Monday and needs access to the standard onboarding apps."
|
| 140 |
|
| 141 |
+
The agent may decide:
|
| 142 |
|
| 143 |
+
- issue type: `onboarding`
|
| 144 |
+
- priority: `medium`
|
| 145 |
+
- assignment group: `onboarding_ops`
|
| 146 |
+
- resolution action: `fulfill`
|
| 147 |
|
| 148 |
+
### 2. `investigate`
|
| 149 |
|
| 150 |
+
This means:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
+
"I do not want to commit yet. Let me look up one more internal signal."
|
| 153 |
|
| 154 |
+
This is similar to a real support lead opening internal notes, checking a related case, or reviewing requester history before making a decision.
|
|
|
|
|
|
|
| 155 |
|
| 156 |
+
### 3. `request_info`
|
| 157 |
|
| 158 |
+
This means:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
|
| 160 |
+
"The current ticket is missing something important. I want clarification before routing it strongly."
|
| 161 |
|
| 162 |
+
Real-world example:
|
| 163 |
|
| 164 |
+
A customer writes:
|
| 165 |
|
| 166 |
+
"We need help before the board meeting."
|
| 167 |
|
| 168 |
+
That is too vague. You may need to know:
|
| 169 |
|
| 170 |
+
- what system is affected
|
| 171 |
+
- whether it is a live outage
|
| 172 |
+
- whether security is involved
|
| 173 |
|
| 174 |
+
### 4. `defer`
|
| 175 |
|
| 176 |
+
This means:
|
| 177 |
|
| 178 |
+
"I am intentionally pushing this later in the queue because another item is more urgent or I expect better context soon."
|
|
|
|
| 179 |
|
| 180 |
+
This is not the same as ignoring the ticket.
|
| 181 |
+
It is a strategic queue decision.
|
| 182 |
|
| 183 |
+
Real-world example:
|
| 184 |
|
| 185 |
+
You have one ticket about a pricing clarification and another about a company-wide identity lockout.
|
| 186 |
+
You may defer the pricing question so you can stabilize the outage cluster first.
|
| 187 |
|
| 188 |
+
### 5. `open_incident`
|
| 189 |
|
| 190 |
+
This means:
|
|
|
|
|
|
|
|
|
|
| 191 |
|
| 192 |
+
"This is bigger than a normal ticket. I need to reserve incident-handling capacity."
|
| 193 |
|
| 194 |
+
Real-world example:
|
| 195 |
|
| 196 |
+
If multiple customers are reporting the same outage or privileged-access failure, opening an incident early can prevent chaos later in the queue.
|
| 197 |
|
| 198 |
+
## Why The Tools Exist
|
| 199 |
|
| 200 |
+
The investigation tools are there because real support work is rarely solved from the first sentence alone.
|
|
|
|
|
|
|
|
|
|
| 201 |
|
| 202 |
+
The environment includes tools such as:
|
| 203 |
|
| 204 |
+
- related ticket lookup
|
| 205 |
+
- requester history lookup
|
| 206 |
+
- internal routing note lookup
|
| 207 |
+
- queue capacity forecast
|
| 208 |
+
- queue cluster summary
|
| 209 |
|
| 210 |
+
Think of these as controlled windows into the rest of the system.
|
| 211 |
|
| 212 |
+
They matter because some tickets are intentionally incomplete.
|
|
|
|
|
|
|
| 213 |
|
| 214 |
+
For example:
|
| 215 |
|
| 216 |
+
- the visible ticket may look like a normal billing issue
|
| 217 |
+
- the internal routing note may reveal it is actually connected to an application outage
|
| 218 |
+
- the queue cluster summary may reveal there are two more related tickets behind it
|
| 219 |
+
- the capacity forecast may reveal the preferred team is overloaded, so a fallback route becomes reasonable
|
| 220 |
|
| 221 |
+
This is how the project creates decision-making instead of simple label prediction.
|
| 222 |
|
| 223 |
+
## Why Earlier Decisions Affect Later Tickets
|
| 224 |
|
| 225 |
+
This is one of the most important ideas in the whole project.
|
| 226 |
|
| 227 |
+
If your benchmark has no carry-over state, it is often just classification repeated several times.
|
|
|
|
| 228 |
|
| 229 |
+
This project tries to avoid that by making the queue matter.
|
| 230 |
|
| 231 |
+
Examples:
|
| 232 |
|
| 233 |
+
- if you handle an outage ticket well, later tickets from the same cluster become easier to route
|
| 234 |
+
- if you handle it poorly, later tickets can become more urgent or more confused
|
| 235 |
+
- if you open an incident, related tickets may already have incident coverage
|
| 236 |
+
- if you defer too many things, SLA pressure grows
|
| 237 |
+
- if you burn the wrong team's capacity early, later tickets may need fallback routing
|
| 238 |
|
| 239 |
+
In simple terms:
|
| 240 |
+
|
| 241 |
+
the world changes because of what the agent did earlier.
|
| 242 |
+
|
| 243 |
+
That is what makes the benchmark feel more like operations and less like a quiz.
|
| 244 |
+
|
| 245 |
+
## The Three Tasks And Why They Exist
|
| 246 |
+
|
| 247 |
+
All three tasks now use full routing. That is an important design choice.
|
| 248 |
+
|
| 249 |
+
We are not making one task "just classify the issue type" anymore. We keep the core job the same and change how hard the world is.
|
| 250 |
+
|
| 251 |
+
### Task 1: Guided Full Routing
|
| 252 |
+
|
| 253 |
+
This is the easiest version.
|
| 254 |
+
|
| 255 |
+
The ticket is mostly visible.
|
| 256 |
+
The agent still performs full routing, but the world is simpler and more single-ticket.
|
| 257 |
+
|
| 258 |
+
This task teaches:
|
| 259 |
+
|
| 260 |
+
"Can you route a normal helpdesk ticket correctly?"
|
| 261 |
+
|
| 262 |
+
### Task 2: Contextual Full Routing
|
| 263 |
+
|
| 264 |
+
This is the medium version.
|
| 265 |
+
|
| 266 |
+
Now some useful context is hidden unless the agent investigates or asks for more information.
|
| 267 |
+
There is also moderate queue carry-over.
|
| 268 |
+
|
| 269 |
+
This task teaches:
|
| 270 |
+
|
| 271 |
+
"Can you route well when the ticket alone is not enough?"
|
| 272 |
+
|
| 273 |
+
### Task 3: Adaptive Queue Routing
|
| 274 |
+
|
| 275 |
+
This is the hard version.
|
| 276 |
+
|
| 277 |
+
Now the agent must handle:
|
| 278 |
+
|
| 279 |
+
- hidden decisive context
|
| 280 |
+
- queue capacity pressure
|
| 281 |
+
- incidents
|
| 282 |
+
- clustered requests
|
| 283 |
+
- deferrals
|
| 284 |
+
- follow-up tickets created by weak earlier handling
|
| 285 |
+
|
| 286 |
+
This task teaches:
|
| 287 |
+
|
| 288 |
+
"Can you manage the queue like an operator, not just label a ticket?"
|
| 289 |
+
|
| 290 |
+
## What The Dataset Must Do
|
| 291 |
+
|
| 292 |
+
The dataset is not just a list of random support messages.
|
| 293 |
+
|
| 294 |
+
It must teach the benchmark what "good routing" looks like.
|
| 295 |
+
|
| 296 |
+
A useful dataset for this project needs:
|
| 297 |
|
|
|
|
| 298 |
- clear easy examples
|
| 299 |
+
- medium examples where urgency matters
|
| 300 |
+
- ambiguous examples where the wording can mislead a naive policy
|
| 301 |
+
- related tickets that belong to the same cluster
|
| 302 |
+
- tickets where fallback routing can still be acceptable
|
| 303 |
+
- tickets where weak handling should logically create follow-up work
|
| 304 |
+
|
| 305 |
+
Real-world example:
|
| 306 |
+
|
| 307 |
+
If a ticket says:
|
| 308 |
+
|
| 309 |
+
"The seat increase is blocked and finance is also confused about prorating"
|
| 310 |
+
|
| 311 |
+
that is not a perfectly clean one-label case.
|
| 312 |
+
It could pull toward procurement, license operations, or service desk depending on queue pressure and business context.
|
| 313 |
+
|
| 314 |
+
Those are the kinds of examples that make the environment interesting.
|
| 315 |
+
|
| 316 |
+
## How Scoring Works Conceptually
|
| 317 |
+
|
| 318 |
+
The grader should feel like a tough but fair manager.
|
| 319 |
+
|
| 320 |
+
It should not be vague.
|
| 321 |
+
|
| 322 |
+
It should not say:
|
| 323 |
+
|
| 324 |
+
"Anything somewhat close gets points."
|
| 325 |
+
|
| 326 |
+
Instead, it should say:
|
| 327 |
+
|
| 328 |
+
- exact answers get the most credit
|
| 329 |
+
- a few near misses can receive partial credit
|
| 330 |
+
- fallback routes only count when they were explicitly designed to count
|
| 331 |
+
- clearly wrong answers get low or zero credit
|
| 332 |
+
|
| 333 |
+
That is why the grader is deterministic and narrow.
|
| 334 |
+
|
| 335 |
+
This matters for two reasons:
|
| 336 |
+
|
| 337 |
+
1. judges can trust the benchmark
|
| 338 |
+
2. an agent actually gets a meaningful learning signal
|
| 339 |
+
|
| 340 |
+
## Why Reward Is Not Exactly The Same As Grading
|
| 341 |
+
|
| 342 |
+
This is a subtle but important idea.
|
| 343 |
+
|
| 344 |
+
The final rubric score tells us how good the overall episode was.
|
| 345 |
+
|
| 346 |
+
The step reward helps the agent learn during the episode.
|
| 347 |
+
|
| 348 |
+
You can think of it like coaching during a football match:
|
| 349 |
+
|
| 350 |
+
- the final match result is the real outcome
|
| 351 |
+
- the coach's feedback during the game helps the team adjust sooner
|
| 352 |
+
|
| 353 |
+
In this project:
|
| 354 |
+
|
| 355 |
+
- terminal reward reflects overall routing plus queue-management quality
|
| 356 |
+
- step rewards make the environment less sparse
|
| 357 |
+
- unnecessary investigation or poor operational choices can carry penalties
|
| 358 |
+
|
| 359 |
+
So the final score is the verdict, while the step reward is the training signal.
|
| 360 |
+
|
| 361 |
+
## The Difference Between "Correct Ticket Routing" And "Good Queue Management"
|
| 362 |
+
|
| 363 |
+
This difference separates average benchmarks from stronger ones.
|
| 364 |
+
|
| 365 |
+
A ticket can be locally correct but globally poor.
|
| 366 |
+
|
| 367 |
+
Example:
|
| 368 |
+
|
| 369 |
+
- yes, security might be the best owner for a certain ticket
|
| 370 |
+
- but if the security queue is already overloaded and the task explicitly allows a fallback operational route, a smart agent may choose the alternate route
|
| 371 |
+
|
| 372 |
+
That is why this project now includes:
|
| 373 |
+
|
| 374 |
+
- alternate acceptable routes on selected tickets
|
| 375 |
+
- capacity-aware routing
|
| 376 |
+
- queue-management score
|
| 377 |
+
- cluster stabilization and destabilization
|
| 378 |
+
|
| 379 |
+
A good benchmark should reward not just being correct in isolation, but being operationally sensible.
|
| 380 |
+
|
| 381 |
+
## How To Explain The Main Files To A Beginner
|
| 382 |
+
|
| 383 |
+
If you are teaching this project to someone new, use these analogies.
|
| 384 |
+
|
| 385 |
+
### `server/tasks.py`
|
| 386 |
+
|
| 387 |
+
This is the curriculum.
|
| 388 |
+
|
| 389 |
+
It says:
|
| 390 |
+
|
| 391 |
+
- what the tasks are
|
| 392 |
+
- how hard they are
|
| 393 |
+
- what kinds of tickets exist
|
| 394 |
+
|
| 395 |
+
### `data/dataset.json`
|
| 396 |
+
|
| 397 |
+
This is the casebook.
|
| 398 |
+
|
| 399 |
+
It is the collection of real-looking helpdesk scenarios that power the environment.
|
| 400 |
+
|
| 401 |
+
### `server/environment.py`
|
| 402 |
+
|
| 403 |
+
This is the game master.
|
| 404 |
+
|
| 405 |
+
It keeps track of:
|
| 406 |
+
|
| 407 |
+
- which ticket is current
|
| 408 |
+
- what the queue looks like
|
| 409 |
+
- what happened earlier
|
| 410 |
+
- what the next observation should be
|
| 411 |
+
|
| 412 |
+
### `server/grader.py`
|
| 413 |
+
|
| 414 |
+
This is the scorekeeper.
|
| 415 |
+
|
| 416 |
+
It decides how good a routing answer was.
|
| 417 |
+
|
| 418 |
+
### `server/reward.py`
|
| 419 |
+
|
| 420 |
+
This is the coach.
|
| 421 |
+
|
| 422 |
+
It turns raw outcomes into feedback signals the agent can learn from.
|
| 423 |
+
|
| 424 |
+
### `inference.py`
|
| 425 |
+
|
| 426 |
+
This is the example player.
|
| 427 |
+
|
| 428 |
+
It shows how an agent can interact with the environment.
|
| 429 |
+
|
| 430 |
+
### `server/app.py`
|
| 431 |
+
|
| 432 |
+
This is the front desk.
|
| 433 |
+
|
| 434 |
+
It exposes the environment through web endpoints so tools and evaluators can use it.
|
| 435 |
+
|
| 436 |
+
## How I Would Teach A Beginner To Build This Project From Scratch
|
| 437 |
+
|
| 438 |
+
If you were starting from zero, I would teach the build order like this.
|
| 439 |
+
|
| 440 |
+
### Step 1: Choose A Real Workflow
|
| 441 |
+
|
| 442 |
+
Do not start with code.
|
| 443 |
+
Start with the business process.
|
| 444 |
+
|
| 445 |
+
Ask:
|
| 446 |
+
|
| 447 |
+
- who is the user?
|
| 448 |
+
- what decision are they making?
|
| 449 |
+
- what makes that decision hard?
|
| 450 |
+
- what happens if they get it wrong?
|
| 451 |
+
|
| 452 |
+
For us, the answers were:
|
| 453 |
+
|
| 454 |
+
- the user is a helpdesk routing agent
|
| 455 |
+
- the decisions are issue type, priority, owner, and next action
|
| 456 |
+
- the hard parts are ambiguity, queue pressure, and incomplete information
|
| 457 |
+
- mistakes cause delays, wrong ownership, and follow-up work
|
| 458 |
+
|
| 459 |
+
### Step 2: Freeze The Vocabulary
|
| 460 |
+
|
| 461 |
+
Before coding, decide the labels clearly.
|
| 462 |
+
|
| 463 |
+
If the team keeps changing label names midway, everything becomes unstable:
|
| 464 |
+
|
| 465 |
+
- dataset
|
| 466 |
+
- grader
|
| 467 |
+
- prompts
|
| 468 |
+
- docs
|
| 469 |
+
- tests
|
| 470 |
+
|
| 471 |
+
This is why a frozen vocabulary is so important.
|
| 472 |
+
|
| 473 |
+
### Step 3: Build Realistic Example Cases
|
| 474 |
+
|
| 475 |
+
Write tickets the way real people write them:
|
| 476 |
+
|
| 477 |
+
- incomplete
|
| 478 |
+
- emotional
|
| 479 |
+
- slightly messy
|
| 480 |
+
- not perfectly labeled in the text
|
| 481 |
+
|
| 482 |
+
If every ticket literally contains the answer, the benchmark becomes a keyword game.
|
| 483 |
+
|
| 484 |
+
### Step 4: Decide What The Agent Sees Immediately
|
| 485 |
+
|
| 486 |
+
Not everything should be visible at once.
|
| 487 |
+
|
| 488 |
+
Ask:
|
| 489 |
+
|
| 490 |
+
- what would a real support analyst know right away?
|
| 491 |
+
- what would require investigation?
|
| 492 |
+
- what would require asking someone?
|
| 493 |
+
|
| 494 |
+
That decision creates the need for tools and intermediate actions.
|
| 495 |
+
|
| 496 |
+
### Step 5: Add Actions Beyond Final Submission
|
| 497 |
+
|
| 498 |
+
If the only action is "submit the answer," you are probably building classification.
|
| 499 |
+
|
| 500 |
+
To make it feel operational, add actions that shape the path:
|
| 501 |
+
|
| 502 |
+
- investigate
|
| 503 |
+
- ask for clarification
|
| 504 |
+
- defer
|
| 505 |
+
- escalate or open incident
|
| 506 |
+
|
| 507 |
+
These are realistic and easy to explain.
|
| 508 |
+
|
| 509 |
+
### Step 6: Make State Carry Over
|
| 510 |
+
|
| 511 |
+
This is where many projects stay shallow.
|
| 512 |
|
| 513 |
+
You need earlier choices to matter later.
|
| 514 |
|
| 515 |
+
For example:
|
| 516 |
|
| 517 |
+
- capacity should be reduced after use
|
| 518 |
+
- related tickets should react to earlier handling
|
| 519 |
+
- follow-up tickets should appear when earlier work was weak
|
| 520 |
|
| 521 |
+
Without this, you do not really have a sequential benchmark.
|
| 522 |
|
| 523 |
+
### Step 7: Design Deterministic Grading
|
| 524 |
|
| 525 |
+
The grader should be explainable to a judge in under a minute.
|
|
|
|
|
|
|
| 526 |
|
| 527 |
+
That usually means:
|
| 528 |
|
| 529 |
+
- exact match for most things
|
| 530 |
+
- a small number of explicit partial-credit rules
|
| 531 |
+
- no secret fuzzy logic
|
| 532 |
|
| 533 |
+
### Step 8: Add Reward Shaping Carefully
|
| 534 |
|
| 535 |
+
Reward shaping should help learning, not distort the benchmark.
|
| 536 |
|
| 537 |
+
Good shaping:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 538 |
|
| 539 |
+
- rewards useful investigation
|
| 540 |
+
- discourages wasteful probing
|
| 541 |
+
- gently rewards good operational flow
|
| 542 |
|
| 543 |
+
Bad shaping:
|
|
|
|
|
|
|
|
|
|
| 544 |
|
| 545 |
+
- makes a silly exploit better than actually solving the task
|
| 546 |
|
| 547 |
+
### Step 9: Build A Baseline Agent
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 548 |
|
| 549 |
+
Always include a runner that can play the environment.
|
| 550 |
|
| 551 |
+
It does not need to be perfect.
|
| 552 |
+
It just needs to prove the environment works and give judges something concrete to run.
|
| 553 |
|
| 554 |
+
### Step 10: Make It Easy To Validate And Deploy
|
| 555 |
|
| 556 |
+
A good benchmark is not just interesting. It is runnable.
|
| 557 |
|
| 558 |
+
That means:
|
| 559 |
|
| 560 |
+
- clean metadata
|
| 561 |
+
- clear docs
|
| 562 |
+
- Docker support
|
| 563 |
+
- validation passing
|
| 564 |
+
- a landing page that makes sense to a judge
|
| 565 |
|
| 566 |
+
## Common Beginner Mistakes To Avoid
|
| 567 |
|
| 568 |
+
### Mistake 1: Building A Fancy Classifier And Calling It An Environment
|
| 569 |
|
| 570 |
+
If nothing carries over between steps, you probably do not have a true environment yet.
|
| 571 |
|
| 572 |
+
### Mistake 2: Making The Grader Too Fuzzy
|
| 573 |
|
| 574 |
+
If almost every answer gets partial credit, your score stops being trustworthy.
|
| 575 |
|
| 576 |
+
### Mistake 3: Making The Hard Task Easy For Heuristics
|
|
|
|
|
|
|
|
|
|
| 577 |
|
| 578 |
+
If a simple keyword rule gets near-perfect scores, the benchmark will not feel meaningful.
|
| 579 |
|
| 580 |
+
### Mistake 4: Adding Random Complexity Instead Of Business Logic
|
| 581 |
|
| 582 |
+
Harder is not always better.
|
| 583 |
+
Complexity should come from realistic workflow pressure, not arbitrary tricks.
|
| 584 |
|
| 585 |
+
### Mistake 5: Writing Docs Only For Teammates
|
|
|
|
|
|
|
|
|
|
| 586 |
|
| 587 |
+
Hackathon judges are outsiders.
|
| 588 |
+
Your docs must help a smart new reader understand the project quickly.
|
| 589 |
|
| 590 |
+
## How To Talk About This Project In A Demo
|
| 591 |
|
| 592 |
+
If you need to explain the project fast, say this:
|
|
|
|
|
|
|
|
|
|
| 593 |
|
| 594 |
+
"We built an OpenEnv benchmark for IT helpdesk routing. The agent does not just classify tickets. It manages a short operational queue, can investigate hidden context, request clarification, defer work, open incidents, and make routing choices whose consequences affect later tickets. The scoring is deterministic, but the environment still has real trade-offs because queue pressure and related-ticket clusters change what good handling looks like."
|
| 595 |
|
| 596 |
+
That is the shortest honest pitch.
|
| 597 |
|
| 598 |
+
## What Makes This Project Strong Today
|
| 599 |
|
| 600 |
+
The current version is strongest in these areas:
|
| 601 |
|
| 602 |
+
- clear real-world workflow
|
| 603 |
+
- structured, judge-friendly outputs
|
| 604 |
+
- deterministic grading
|
| 605 |
+
- multi-step operational actions
|
| 606 |
+
- queue-level consequences
|
| 607 |
+
- cluster-aware carry-over state
|
| 608 |
+
- clean packaging and validation story
|
| 609 |
|
| 610 |
+
## What Would Make It Even Stronger Later
|
| 611 |
|
| 612 |
+
If this project kept growing after the hackathon, the next upgrades would be:
|
| 613 |
|
| 614 |
+
- make more of the consequences emerge from a general simulator instead of authored rules
|
| 615 |
+
- increase the data diversity further
|
| 616 |
+
- train stronger learned policies instead of relying mainly on deterministic policy search
|
| 617 |
+
- add more business objectives like cost, customer satisfaction, and resolver fatigue
|
| 618 |
|
| 619 |
+
## One-Minute Recap
|
| 620 |
|
| 621 |
+
If you forget everything else, remember this:
|
| 622 |
|
| 623 |
+
- this project simulates helpdesk queue management, not just ticket classification
|
| 624 |
+
- the agent must choose both what the ticket means and what to do next
|
| 625 |
+
- some useful context is hidden and must be uncovered through actions
|
| 626 |
+
- earlier choices affect later tickets
|
| 627 |
+
- the grader is deterministic so the benchmark stays trustworthy
|
| 628 |
+
- the project is built to be understandable, runnable, and useful as an OpenEnv environment
|
|
|
|
|
|
PROJECT_STATUS.md
CHANGED
|
@@ -1,364 +1,165 @@
|
|
| 1 |
# Project Status
|
| 2 |
|
| 3 |
-
This is the canonical
|
| 4 |
|
| 5 |
-
|
| 6 |
|
| 7 |
-
|
|
|
|
| 8 |
|
| 9 |
-
|
| 10 |
|
| 11 |
-
|
| 12 |
|
| 13 |
-
-
|
| 14 |
-
-
|
| 15 |
-
-
|
| 16 |
-
-
|
| 17 |
-
-
|
| 18 |
-
-
|
| 19 |
-
- built `vocabulary.py` with all frozen constants (`ISSUE_TYPES`, `PRIORITIES`, `ASSIGNMENT_GROUPS`, `RESOLUTION_ACTIONS`, `TASK_IDS`)
|
| 20 |
|
| 21 |
-
|
| 22 |
|
| 23 |
-
|
| 24 |
-
- aligned the foundational schema and environment surface
|
| 25 |
-
- froze the core class names and field names
|
| 26 |
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
-
|
| 30 |
-
- `server/tasks.py`
|
| 31 |
-
- `server/grader.py`
|
| 32 |
-
- `server/environment.py`
|
| 33 |
-
- `client.py`
|
| 34 |
-
- `server/app.py`
|
| 35 |
-
- `inference.py`
|
| 36 |
-
- `vocabulary.py`
|
| 37 |
|
| 38 |
-
|
| 39 |
|
| 40 |
-
-
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
-
|
| 43 |
|
| 44 |
-
|
| 45 |
|
| 46 |
-
|
| 47 |
|
| 48 |
-
|
| 49 |
-
- verified `models.py` field names still matched the updated dataset labels after Roopal's audit pass
|
| 50 |
-
- confirmed `server/environment.py` and `client.py` required no changes from the dataset review
|
| 51 |
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
-
|
| 55 |
-
- tightened ambiguity wording in selected tickets
|
| 56 |
-
- reviewed task wording in `server/tasks.py`
|
| 57 |
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
-
|
| 61 |
-
- `ticket-027` kept intentionally ambiguous between `general_inquiry` and `service_request`
|
| 62 |
-
- `ticket-029` was refined to better express seat-expansion versus prorating ambiguity
|
| 63 |
-
- `ticket-040` was kept as `feature_request` while clarifying that some readers could still interpret it as `application_support`
|
| 64 |
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
-
|
| 68 |
-
- Task 2 now explicitly asks for operational priority, not just generic urgency
|
| 69 |
-
- Task 3 wording was refined to describe full helpdesk routing more concretely
|
| 70 |
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
-
|
| 74 |
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
-
|
| 78 |
|
| 79 |
-
|
|
|
|
|
|
|
| 80 |
|
| 81 |
-
|
| 82 |
-
- verified `server/reward.py` trajectory reward logic remained correct against the updated task weights
|
| 83 |
-
- confirmed `inference.py` heuristic action logic was still compatible with the updated grader behavior
|
| 84 |
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
-
|
| 88 |
-
- made task weights explicit
|
| 89 |
-
- refined hard-task partial-credit behavior
|
| 90 |
-
- finished remaining dataset label corrections
|
| 91 |
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
|
| 94 |
-
|
| 95 |
-
- Task 2 weights were fixed at `issue_type` 60% and `priority` 40%
|
| 96 |
-
- Task 3 weights were fixed at `issue_type` 35%, `priority` 20%, `assignment_group` 25%, and `resolution_action` 20%
|
| 97 |
-
- partial-credit pairs were added for `application_support` vs `feature_request`
|
| 98 |
-
- partial-credit pairs were added for `general_inquiry` vs `service_request`
|
| 99 |
|
| 100 |
-
|
|
|
|
|
|
|
|
|
|
| 101 |
|
| 102 |
-
|
| 103 |
|
| 104 |
-
|
| 105 |
|
| 106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
|
| 108 |
-
|
| 109 |
|
| 110 |
-
-
|
| 111 |
-
-
|
| 112 |
-
-
|
| 113 |
-
-
|
| 114 |
|
| 115 |
-
|
| 116 |
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
Status: complete
|
| 133 |
-
|
| 134 |
-
Suyash-side work completed:
|
| 135 |
-
|
| 136 |
-
- scaffolded `tests/` directory structure
|
| 137 |
-
- created `tests/test_environment_smoke.py` with full smoke test coverage:
|
| 138 |
-
- `reset(task_id=1)` returns valid observation with `done=False` and `reward=None`
|
| 139 |
-
- `reset(task_id=2)` and `reset(task_id=3)` return valid observations with correct `allowed_fields`
|
| 140 |
-
- `step()` increments `tickets_processed` by 1 and returns reward in `[0.0, 1.0]`
|
| 141 |
-
- `state` property returns `HelpdeskTicketState` with correct fields after reset and after step
|
| 142 |
-
- seeded resets with the same seed produce identical queue order on repeated calls and across separate env instances
|
| 143 |
-
- all per-ticket scores stay in `[0.0, 1.0]` across a full episode for each task
|
| 144 |
-
- one full episode per task (IDs 1, 2, 3) completes without unhandled exceptions
|
| 145 |
-
- confirmed all smoke tests pass with `pytest tests/test_environment_smoke.py`
|
| 146 |
-
- ran local runtime pass and recorded the results in this status log:
|
| 147 |
-
- server started cleanly on port 8000
|
| 148 |
-
- `GET /health` returned HTTP 200
|
| 149 |
-
- `GET /tasks` returned exactly 3 tasks with IDs 1, 2, 3
|
| 150 |
-
- all 45 dataset records passed `HelpdeskTicketRecord` validation
|
| 151 |
-
- heuristic `inference.py` completed all 3 tasks without exceptions
|
| 152 |
-
- reviewed `required.md` and identified official validation items not yet reflected in runtime or inference behavior:
|
| 153 |
-
- structured `[START]`, `[STEP]`, `[END]` stdout logging not yet fully compliant in `inference.py`
|
| 154 |
-
- `openenv validate` not yet run
|
| 155 |
-
- Docker smoke not yet confirmed
|
| 156 |
-
- `.openenvignore` not yet created
|
| 157 |
-
|
| 158 |
-
Roopal-side work completed:
|
| 159 |
-
|
| 160 |
-
- performed a dataset realism pass on `data/dataset.json`
|
| 161 |
-
- replaced several low-realism spam examples with clearer helpdesk-inbox phrasing
|
| 162 |
-
- cleaned visible mojibake dashes from ticket titles
|
| 163 |
-
- added explicit easy, medium, and hard dataset examples to `README.md`
|
| 164 |
-
|
| 165 |
-
Runtime validation notes recorded from the local repo state:
|
| 166 |
-
|
| 167 |
-
- local `reset()` and `inference.py` validation exposed a UTF-8 BOM issue in dataset loading
|
| 168 |
-
- `server/tasks.py` was updated to read `data/dataset.json` with `utf-8-sig`
|
| 169 |
-
- the heuristic baseline then completed successfully
|
| 170 |
-
|
| 171 |
-
Local heuristic baseline on the validated repo state:
|
| 172 |
-
|
| 173 |
-
- Task 1: `1.0000`
|
| 174 |
-
- Task 2: `0.8800`
|
| 175 |
-
- Task 3: `0.9400`
|
| 176 |
-
- Overall: `0.9400`
|
| 177 |
-
|
| 178 |
-
Shared checkpoint outcome so far:
|
| 179 |
-
|
| 180 |
-
- the first bug triage item was identified and fixed
|
| 181 |
-
- a rerun on the latest fully merged branch is still recommended before treating benchmark numbers as final
|
| 182 |
-
|
| 183 |
-
## April 4, 2026
|
| 184 |
-
|
| 185 |
-
Status: complete
|
| 186 |
-
|
| 187 |
-
Suyash-side work completed:
|
| 188 |
-
|
| 189 |
-
- created `tests/test_api_integration.py` with first-pass integration test coverage:
|
| 190 |
-
- `GET /health` returns HTTP 200 with `{"status": "ok"}`
|
| 191 |
-
- `GET /tasks` returns HTTP 200 with exactly 3 tasks with IDs 1, 2, 3
|
| 192 |
-
- `POST /reset` with `{"task_id": 1, "seed": 42}` returns valid observation JSON with `done=False` and `reward=None`
|
| 193 |
-
- `POST /step` with a valid action returns observation JSON with reward in `[0.0, 1.0]` and increments `tickets_processed`
|
| 194 |
-
- `GET /state` returns current episode state JSON with correct `current_task_id` and `step_count` after reset
|
| 195 |
-
- confirmed first-pass integration tests pass with `pytest tests/test_api_integration.py`
|
| 196 |
-
- audited current `inference.py` stdout against the official `[START]`, `[STEP]`, `[END]` format from `required.md`:
|
| 197 |
-
- `[START]`, `[STEP]`, and per-episode `[END]` all contain the required fields
|
| 198 |
-
- one actionable gap: overall summary reused the `[END]` tag without `task_id` or `final_reward`, making it ambiguous for automated parsers
|
| 199 |
-
- extra fields in all three tags are harmless and require no change
|
| 200 |
-
|
| 201 |
-
Roopal-side work completed:
|
| 202 |
-
|
| 203 |
-
- updated `README.md` to reflect the first local runtime pass
|
| 204 |
-
- recorded the current heuristic baseline in repo docs as a working, non-final benchmark
|
| 205 |
-
- updated `KNOWLEDGE.md` to distinguish consistency validation from runtime validation
|
| 206 |
-
- updated the runtime mental-model notes later merged into `KNOWLEDGE.md`, including the Windows BOM handling detail
|
| 207 |
-
|
| 208 |
-
Documentation fixes made from runtime feedback:
|
| 209 |
-
|
| 210 |
-
- removed stale wording that implied no local runtime pass had happened yet
|
| 211 |
-
- clarified that merged-state reruns still matter before final benchmark recording
|
| 212 |
-
- documented the Windows UTF-8 BOM issue and its handling path in `server/tasks.py`
|
| 213 |
-
|
| 214 |
-
## April 5, 2026
|
| 215 |
-
|
| 216 |
-
Status: complete
|
| 217 |
-
|
| 218 |
-
Suyash-side work completed:
|
| 219 |
-
|
| 220 |
-
- expanded `tests/test_api_integration.py` with full integration coverage:
|
| 221 |
-
- added end-to-end seeded episode test: `POST /reset` → step loop until `done=True` → asserted final trajectory reward in `[0.0, 1.0]`
|
| 222 |
-
- added full episode completion test for all three task IDs (1, 2, 3)
|
| 223 |
-
- added `GET /state` mid-episode test: confirmed `step_count` is 0 after reset and increments to 1 after one step, and `current_task_id` matches the reset `task_id`
|
| 224 |
-
- added heuristic inference regression test: drove the heuristic action loop directly against the `TestClient` app and asserted all 3 tasks complete without error and overall average reward is in `[0.8, 1.0]`
|
| 225 |
-
- confirmed all integration tests pass with `pytest tests/test_api_integration.py`
|
| 226 |
-
- fixed `inference.py` structured logging to match the official format:
|
| 227 |
-
- `[START]` emits `task_id`, `seed`, and contextual fields at the beginning of each episode
|
| 228 |
-
- `[STEP]` emits `step`, `action`, and `reward` for each step
|
| 229 |
-
- per-episode `[END]` emits `task_id` and `final_reward`
|
| 230 |
-
- the final overall summary now also stays structured through a closing `[END]` line with aggregate fields
|
| 231 |
-
- confirmed no stray stdout output interferes with the structured log lines
|
| 232 |
-
- reran heuristic baseline after the logging change and confirmed rewards still match the reference: Task 1 `1.0000`, Task 2 `0.8800`, Task 3 `0.9400`, overall `0.9400`
|
| 233 |
-
|
| 234 |
-
Shared work completed:
|
| 235 |
-
|
| 236 |
-
- reran local runtime validation on the current `main` branch
|
| 237 |
-
- revalidated `/health` and `/tasks`
|
| 238 |
-
- reran heuristic `inference.py` across all 3 tasks
|
| 239 |
-
- confirmed the merged-state local baseline matched the earlier working numbers exactly
|
| 240 |
-
- added `.gitignore` and `.dockerignore` to keep local artifacts out of git status and Docker build context
|
| 241 |
-
|
| 242 |
-
Merged-state heuristic baseline on the current repo state:
|
| 243 |
-
|
| 244 |
-
- Task 1: `1.0000`
|
| 245 |
-
- Task 2: `0.8800`
|
| 246 |
-
- Task 3: `0.9400`
|
| 247 |
-
- Overall: `0.9400`
|
| 248 |
-
|
| 249 |
-
Environment notes:
|
| 250 |
-
|
| 251 |
-
- the Codex shell could run the project virtualenv successfully once Python execution was allowed outside the sandbox
|
| 252 |
-
- Docker was not available in the current shell context, so the Docker smoke test is still pending on a machine with Docker installed
|
| 253 |
-
|
| 254 |
-
Roopal-side documentation work completed:
|
| 255 |
-
|
| 256 |
-
- finalized `README.md` wording around submission readiness
|
| 257 |
-
- finalized `KNOWLEDGE.md` as the judge-facing knowledge guide
|
| 258 |
-
- added concise judge-facing domain explanations to the docs
|
| 259 |
-
|
| 260 |
-
## April 6, 2026
|
| 261 |
-
|
| 262 |
-
Status: complete
|
| 263 |
-
|
| 264 |
-
Suyash-side work completed:
|
| 265 |
-
|
| 266 |
-
- created `.openenvignore` at the repo root excluding: `tests/`, `analysis/`, `bugs/`, `transcripts/`, `.git/`, `__pycache__/`, `.gitignore`, `.dockerignore`
|
| 267 |
-
- confirmed no runtime-required files are excluded: `data/dataset.json`, `server/`, `models.py`, `client.py`, `vocabulary.py`, `inference.py`, `openenv.yaml`, `requirements.txt`, `pyproject.toml`, `server/Dockerfile` all remain in the package
|
| 268 |
-
- ran Docker build and smoke test via GitHub Actions workflow (local Docker unavailable in current shell context):
|
| 269 |
-
- `docker build -t helpdesk-env .` exited with code 0
|
| 270 |
-
- `GET /health` on the running container returned HTTP 200
|
| 271 |
-
- `GET /tasks` on the running container returned 3 tasks with IDs 1, 2, 3
|
| 272 |
-
- `python inference.py` with `ENV_URL=http://localhost:7860` completed all 3 tasks without error
|
| 273 |
-
- ran `openenv validate` against the current repo state and recorded the result
|
| 274 |
-
- verified deployment assumptions:
|
| 275 |
-
- `app_port: 7860` confirmed in `openenv.yaml` and `server/Dockerfile`
|
| 276 |
-
- `/health` responds HTTP 200 on the running server
|
| 277 |
-
- `/docs` (FastAPI auto-docs) accessible on the running server
|
| 278 |
-
- `/ws` endpoint not present; confirmed its absence is not a disqualifier per the official requirements
|
| 279 |
-
- froze all Suyash-owned runtime files: `models.py`, `server/environment.py`, `server/app.py`, `server/reward.py`, `client.py`, `inference.py`, `openenv.yaml`, `server/Dockerfile`, `pyproject.toml`, `requirements.txt`
|
| 280 |
-
|
| 281 |
-
Roopal-side work completed:
|
| 282 |
-
|
| 283 |
-
- audited required submission files and confirmed they are present in the repo
|
| 284 |
-
- completed a stale-claims and outdated-wording pass across the core docs
|
| 285 |
-
- updated `required.md` to reflect that first-pass local execution is no longer the main runtime risk
|
| 286 |
-
- left the remaining work focused on Docker and clean-machine validation rather than documentation cleanup
|
| 287 |
-
|
| 288 |
-
## April 7, 2026
|
| 289 |
-
|
| 290 |
-
Status: complete
|
| 291 |
-
|
| 292 |
-
Suyash-side work completed:
|
| 293 |
-
|
| 294 |
-
- performed clean-copy install-and-run pass from a fresh directory:
|
| 295 |
-
- installed with `pip install -r requirements.txt && pip install .` without errors
|
| 296 |
-
- verified all required files present and non-empty: `models.py`, `vocabulary.py`, `client.py`, `inference.py`, `server/app.py`, `server/environment.py`, `server/reward.py`, `server/grader.py`, `server/tasks.py`, `server/Dockerfile`, `openenv.yaml`, `pyproject.toml`, `requirements.txt`, `data/dataset.json`, `README.md`
|
| 297 |
-
- ran server and heuristic `inference.py` from the clean copy and confirmed clean completion
|
| 298 |
-
- confirmed benchmark numbers match the recorded reference: Task 1 `1.0000`, Task 2 `0.8800`, Task 3 `0.9400`, overall `0.9400`
|
| 299 |
-
- confirmed feature freeze is in effect — no further additions to any Suyash-owned runtime file
|
| 300 |
-
- applied freeze-phase doc and metadata corrections:
|
| 301 |
-
- fixed `ENV_URL` default in `inference.py` from `http://localhost:8000` to `http://localhost:7860`
|
| 302 |
-
- fixed local setup commands in `README.md` to use port `7860`
|
| 303 |
-
- removed unconfirmed `WebSocket /ws` row from the API surface table in `README.md`
|
| 304 |
-
|
| 305 |
-
## April 3, 2026 (Pulled Forward April 4-5 Roopal Scope)
|
| 306 |
-
|
| 307 |
-
Status: complete for the Roopal-owned roadmap items originally scheduled for April 4 and April 5
|
| 308 |
-
|
| 309 |
-
Roopal-side work completed:
|
| 310 |
-
|
| 311 |
-
- expanded `tests/test_grader_unit.py` to lock scorer crispness with exhaustive issue-type and priority-table checks
|
| 312 |
-
- added explicit invariants for task-weight sums, exact-match dominance, and deterministic repeated grading
|
| 313 |
-
- expanded `tests/test_tasks_unit.py` to cover the frozen task difficulty ladder plus dataset coverage across all issue types, priorities, assignment groups, and resolution actions
|
| 314 |
-
- added `analysis/grounding_audit.md` as the internal grounding note requested by the roadmap
|
| 315 |
-
- reviewed candidate issue-type similarity expansions and decided to keep the current similarity map unchanged
|
| 316 |
-
|
| 317 |
-
Decision notes:
|
| 318 |
-
|
| 319 |
-
- scorer fuzziness is now proven by tests to exist only where the declared similarity map or priority table allows it
|
| 320 |
-
- no additional issue-type similarity pairs were adopted in this pass because the reviewed candidates were too operationally fuzzy
|
| 321 |
-
|
| 322 |
-
## April 3, 2026 (Pulled Forward April 6-7 Roopal Scope)
|
| 323 |
-
|
| 324 |
-
Status: complete for the Roopal-owned roadmap items originally scheduled for April 6 and April 7
|
| 325 |
-
|
| 326 |
-
Roopal-side work completed:
|
| 327 |
-
|
| 328 |
-
- added Hugging Face Spaces README frontmatter
|
| 329 |
-
- updated `README.md` with an explicit judge-facing explanation of deterministic, grounded scoring
|
| 330 |
-
- updated `KNOWLEDGE.md` to state clearly that the grader is not fuzzy by default and to reference the grounding audit
|
| 331 |
-
- updated `required.md` with a current compliance snapshot separating already-satisfied requirements from shared pending validation gates
|
| 332 |
-
- completed the final Roopal-side consistency pass across `README.md`, `KNOWLEDGE.md`, and `required.md`
|
| 333 |
-
|
| 334 |
-
Decision notes:
|
| 335 |
-
|
| 336 |
-
- no scorer change was needed from the grounding review, so this pass stayed documentation-only
|
| 337 |
-
- the optional TRL / GRPO README example remains deferred until the shared runtime-validation gates are green
|
| 338 |
-
|
| 339 |
-
## April 6 — Feature Freeze
|
| 340 |
-
|
| 341 |
-
All Suyash-owned runtime files are now frozen. No new features will be added to:
|
| 342 |
-
models.py, server/environment.py, server/app.py, server/reward.py, client.py,
|
| 343 |
-
inference.py, openenv.yaml, server/Dockerfile, pyproject.toml, requirements.txt.
|
| 344 |
-
|
| 345 |
-
Only bug fixes, doc corrections, and metadata updates are permitted after this point.
|
| 346 |
-
|
| 347 |
-
Freeze confirmed: April 6, 2026.
|
| 348 |
-
|
| 349 |
-
## April 7–8, 2026 — Freeze-Phase Doc and Metadata Corrections
|
| 350 |
-
|
| 351 |
-
Status: complete
|
| 352 |
-
|
| 353 |
-
Corrections applied during freeze phase (task 10.2):
|
| 354 |
-
|
| 355 |
-
- Fixed `ENV_URL` default in `inference.py` from `http://localhost:8000` to `http://localhost:7860` to match the actual server port declared in `openenv.yaml`, `server/Dockerfile`, and `server/app.py`.
|
| 356 |
-
- Fixed local setup commands in `README.md` to use port `7860` instead of `8000` (uvicorn start command and curl examples).
|
| 357 |
-
- Fixed `ENV_URL` default value note in `README.md` to `http://localhost:7860`.
|
| 358 |
-
- Removed unconfirmed `WebSocket /ws` row from the API surface table in `README.md`. The `/ws` endpoint is not listed in `openenv.yaml` api.endpoints and was not confirmed present during validation passes. Its absence is not a disqualifier per the April 6 deployment check.
|
| 359 |
-
- Checked in `uv.lock` so the repo satisfies OpenEnv multi-mode deployment validation requirements on the current checkout.
|
| 360 |
-
- Reran local `openenv validate` from the project virtualenv and confirmed the validator now passes.
|
| 361 |
-
- Updated `README.md`, `KNOWLEDGE.md`, and `required.md` so they no longer describe the April 6 to April 7 roadmap items as pending.
|
| 362 |
-
- Removed stale references to `bugs/BUGS_APRIL3.md` and kept the validation narrative self-contained inside `PROJECT_STATUS.md`.
|
| 363 |
-
|
| 364 |
-
No runtime logic was changed. No new features were added. All other files checked (`openenv.yaml`, `pyproject.toml`, `requirements.txt`, `ROADMAP.md`) were found accurate and required no further corrections.
|
|
|
|
| 1 |
# Project Status
|
| 2 |
|
| 3 |
+
This is the canonical repo status file.
|
| 4 |
|
| 5 |
+
It should answer two questions quickly:
|
| 6 |
|
| 7 |
+
1. what the project can do right now
|
| 8 |
+
2. what actually changed during the recent benchmark-upgrade thread
|
| 9 |
|
| 10 |
+
## Current Snapshot
|
| 11 |
|
| 12 |
+
As of April 8, 2026:
|
| 13 |
|
| 14 |
+
- the active branch is `main`
|
| 15 |
+
- the last runtime-changing benchmark checkpoint before this cleanup pass was `1d9d3ee`
|
| 16 |
+
- the latest runtime-changing checkpoint passed `openenv validate`
|
| 17 |
+
- the latest full test checkpoint passed `175` tests
|
| 18 |
+
- the environment now behaves like a real queue-management benchmark, not a single-ticket classifier
|
| 19 |
+
- stale review branches and nonessential planning docs have been removed so the repo stays submission-clean
|
|
|
|
| 20 |
|
| 21 |
+
## What The Project Does Today
|
| 22 |
|
| 23 |
+
The current repo supports:
|
|
|
|
|
|
|
| 24 |
|
| 25 |
+
- full routing on all three tasks: `issue_type`, `priority`, `assignment_group`, and `resolution_action`
|
| 26 |
+
- partial observability that gets harder as the task difficulty rises
|
| 27 |
+
- five action types: `submit`, `investigate`, `request_info`, `defer`, and `open_incident`
|
| 28 |
+
- queue-level carry-over state such as capacity pressure, incident slots, SLA risk, and deferred tickets
|
| 29 |
+
- cluster-aware episodes where one ticket can make later related tickets easier or harder
|
| 30 |
+
- deterministic follow-up tickets when earlier handling was weak or incomplete
|
| 31 |
+
- a terminal score that blends routing quality with queue-management quality
|
| 32 |
+
- a local policy-learning loop that compares and searches over deterministic policies
|
| 33 |
+
- a modern landing page at `/web` instead of the original plain HTML table
|
| 34 |
|
| 35 |
+
## Validation State
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
+
The latest validated runtime state before this cleanup pass included:
|
| 38 |
|
| 39 |
+
- passing `openenv validate`
|
| 40 |
+
- passing full `python -m unittest discover -s tests -p "test_*.py" -v`
|
| 41 |
+
- a passing Hugging Face Space and Docker-ready packaging setup
|
| 42 |
+
- synchronized pushes to both `origin/main` and `space/main`
|
| 43 |
|
| 44 |
+
This cleanup pass is documentation and repo hygiene only. It does not change the environment contract.
|
| 45 |
|
| 46 |
+
## Full Commit Timeline From Git History
|
| 47 |
|
| 48 |
+
The entries below are taken directly from the local `main` history, which matches `origin/main`.
|
| 49 |
|
| 50 |
+
### March 31, 2026
|
|
|
|
|
|
|
| 51 |
|
| 52 |
+
- `10:47 IST` `3752981` `Initial commit`
|
| 53 |
+
- `11:20 IST` `eae2b1d` `March 30 - April 1st : sever/`
|
| 54 |
+
- `11:27 IST` `9e71ac4` `Merge pull request #2 from suyashkumar102/main`
|
| 55 |
+
- `13:29 IST` `61398c0` `April 2nd tasks`
|
| 56 |
+
- `20:28 IST` `7564d6c` `Fix dataset loader for UTF-8 BOM on Windows`
|
| 57 |
|
| 58 |
+
### April 1, 2026
|
|
|
|
|
|
|
| 59 |
|
| 60 |
+
- `18:28 IST` `4f3bed5` `fix openenv.yaml: use git URL for openenv-core dep, matches requirements.txt`
|
| 61 |
+
- `20:11 IST` `969eaef` `Merge pull request #3 from suyashkumar102/main`
|
| 62 |
+
- `20:50 IST` `3b8bf40` `Improve dataset realism and consolidate project status log`
|
| 63 |
+
- `20:59 IST` `1b9e464` `Update docs after first runtime validation pass`
|
| 64 |
|
| 65 |
+
### April 2, 2026
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
+
- `22:16 IST` `5b9f288` `fix: expand inference docstring and add git to Dockerfile`
|
| 68 |
+
- `22:18 IST` `5de9815` `add analysis folder`
|
| 69 |
+
- `22:39 IST` `9e384ef` `Merge pull request #4 from suyashkumar102/main`
|
| 70 |
+
- `23:37 IST` `6753cde` `Finish Roopal April 5-6 docs and repo audit`
|
| 71 |
+
- `23:40 IST` `c35bcc6` `Merge remote-tracking branch 'origin/main' into codex/apr5-apr6-roopal`
|
| 72 |
|
| 73 |
+
### April 3, 2026
|
|
|
|
|
|
|
| 74 |
|
| 75 |
+
- `00:50 IST` `c16104f` `Add GitHub Actions Docker smoke test`
|
| 76 |
+
- `00:55 IST` `54d32f8` `Merge pull request #5 from Roopalgn/codex/apr5-apr6-roopal`
|
| 77 |
+
- `01:19 IST` `7a88607` `Update final submission roadmap`
|
| 78 |
+
- `01:27 IST` `706f85f` `Merge branch 'codex/apr5-apr6-roopal'`
|
| 79 |
+
- `02:20 IST` `6f27f26` `Update final submission roadmap`
|
| 80 |
+
- `02:30 IST` `375aa81` `Update final submission roadmap`
|
| 81 |
+
- `11:47 IST` `ae36543` `Add grader and dataset unit tests with scoring contract`
|
| 82 |
+
- `12:59 IST` `72d2634` `Consolidate requirements docs and align roadmap with official submission rules`
|
| 83 |
+
- `18:19 IST` `6920aae` `Complete Roopal roadmap work for April 4-7`
|
| 84 |
+
- `20:36 IST` `795d5f1` `Update final submission roadmap`
|
| 85 |
+
- `21:44 IST` `82aca6e` `Make inference.py compliant with submission checklist`
|
| 86 |
|
| 87 |
+
### April 4, 2026
|
| 88 |
|
| 89 |
+
- `10:32 IST` `0fd10c5` `add smoke/integration tests, fix logging, openenvignore, status updates`
|
| 90 |
+
- `10:34 IST` `f57e6a7` `fix port 8000->7860 in app.py/openenv.yaml, add pyproject script entry, fix stubs`
|
| 91 |
+
- `10:35 IST` `fd636ad` `gitignore build/ and uv.lock`
|
| 92 |
+
- `10:41 IST` `ca7bdbd` `remove uv.lock from gitignore`
|
| 93 |
+
- `11:45 IST` `32f4c09` `fix inference stdout and README docker port`
|
| 94 |
+
- `11:50 IST` `3707fc3` `Merge pull request #6 from suyashkumar102/main`
|
| 95 |
+
- `12:12 IST` `5dd60ae` `uv.lock`
|
| 96 |
+
- `14:33 IST` `89ca22f` `Clean up internal docs and finalize validation state`
|
| 97 |
|
| 98 |
+
### April 5, 2026
|
| 99 |
|
| 100 |
+
- `20:53 IST` `42dd095` `feat: competitive upgrade for hackathon submission`
|
| 101 |
+
- `20:56 IST` `2a0f057` `docs: add deep competitive gap report and gap analysis`
|
| 102 |
+
- `22:22 IST` `6c5051f` `fix: resolve full test suite failures from PR review`
|
| 103 |
|
| 104 |
+
### April 6, 2026
|
|
|
|
|
|
|
| 105 |
|
| 106 |
+
- `12:42 IST` `c64d203` `Finalize gap fixes and lightweight competitive upgrades`
|
| 107 |
+
- `12:54 IST` `52ab5fa` `Merge branch 'main' into final-submit-gap-fixes`
|
| 108 |
+
- `13:34 IST` `186fd65` `Merge pull request #10 from suyashkumar102/final-submit-gap-fixes`
|
| 109 |
+
- `14:14 IST` `2216a4d` `Add root Dockerfile for Hugging Face Space`
|
| 110 |
+
- `17:09 IST` `8ccf96d` `Ignore action metadata in extra field validation`
|
| 111 |
+
- `21:15 IST` `67ce1eb` `Add policy learning loop and strengthen RL-style environment`
|
| 112 |
|
| 113 |
+
### April 7, 2026
|
|
|
|
|
|
|
|
|
|
| 114 |
|
| 115 |
+
- `11:37 IST` `8ada670` `Use evaluator API_KEY for LLM proxy and strengthen env`
|
| 116 |
+
- `12:15 IST` `2d5c8e6` `Pin python base image digest for stable Docker builds`
|
| 117 |
+
- `13:16 IST` `bfc789d` `Enable proxy LLM mode with API_KEY and real default model`
|
| 118 |
+
- `13:29 IST` `e3cd5c5` `Use AWS public ECR mirror for python base image`
|
| 119 |
+
- `13:57 IST` `ff634dc` `Run all tasks by default and keep task scores inside open interval`
|
| 120 |
+
- `14:09 IST` `e3dfee6` `Clamp grader task scores to open interval`
|
| 121 |
+
- `14:51 IST` `c0d489c` `Keep invalid-action task scores inside open interval`
|
| 122 |
+
- `15:07 IST` `a5859dc` `Normalize remaining score fields into open interval`
|
| 123 |
+
- `15:43 IST` `d6d9493` `Clamp reported task scores to open interval and match sample logs`
|
| 124 |
+
- `21:43 IST` `d378e5d` `Strengthen hard-task investigation and grading`
|
| 125 |
|
| 126 |
+
### April 8, 2026
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
|
| 128 |
+
- `03:59 IST` `8241eb5` `Add queue-planning helpdesk routing mechanics`
|
| 129 |
+
- `07:03 IST` `043d9e1` `Upgrade helpdesk env with queue dynamics and operational actions`
|
| 130 |
+
- `10:06 IST` `454cef3` `Add cluster-aware queue dynamics to helpdesk env`
|
| 131 |
+
- `11:45 IST` `1d9d3ee` `Strengthen queue benchmark and refresh landing page`
|
| 132 |
|
| 133 |
+
## Net Result Of The Thread
|
| 134 |
|
| 135 |
+
Compared with the starting point, the repo is now materially stronger in five ways:
|
| 136 |
|
| 137 |
+
- Phase 2 compliance issues were fixed without breaking the evaluator contract
|
| 138 |
+
- the benchmark became more agentic through queue mutation, operational actions, and downstream consequences
|
| 139 |
+
- the hard task stopped being a near-trivial keyword-routing problem
|
| 140 |
+
- the grader and final reward became more aligned with real queue-management quality
|
| 141 |
+
- the public presentation improved through cleaner docs and a better landing page
|
| 142 |
|
| 143 |
+
This cleanup and publishing pass also:
|
| 144 |
|
| 145 |
+
- expands `PROJECT_STATUS.md` to cover the full repo history instead of only the late-stage sprint
|
| 146 |
+
- rewrites `KNOWLEDGE.md` as a mentor-style guide for a beginner builder
|
| 147 |
+
- removes stale planning and internal analysis docs that no longer reflect the shipped benchmark
|
| 148 |
+
- leaves `required.md` as the retained requirements checklist
|
| 149 |
|
| 150 |
+
## Remaining Optional Gaps
|
| 151 |
|
| 152 |
+
The project is strong, but a few optional upgrades still exist if more time is ever available:
|
| 153 |
+
|
| 154 |
+
- replace more authored queue rules with even more emergent simulator dynamics
|
| 155 |
+
- grow the dataset further with less taxonomy-friendly wording
|
| 156 |
+
- move from policy search toward a more clearly trainable learning setup
|
| 157 |
+
- gather stronger benchmark comparisons against external LLM baselines
|
| 158 |
+
|
| 159 |
+
## Repo Hygiene Notes
|
| 160 |
+
|
| 161 |
+
This cleanup pass also keeps the repo focused by:
|
| 162 |
+
|
| 163 |
+
- retaining `required.md` as the requirement checklist
|
| 164 |
+
- keeping `README.md`, `KNOWLEDGE.md`, and `PROJECT_STATUS.md` as the main public guidance
|
| 165 |
+
- removing stale planning and gap-analysis files that no longer reflect the current state
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README.md
CHANGED
|
@@ -294,7 +294,7 @@ The grader is intentionally narrow and declared, not fully fuzzy.
|
|
| 294 |
|
| 295 |
That scoring policy is now backed by checked-in unit tests in `tests/test_grader_unit.py` and `tests/test_tasks_unit.py`.
|
| 296 |
|
| 297 |
-
The label set and partial-credit choices were also reviewed against public IT-support references
|
| 298 |
|
| 299 |
- `Classification of IT Support Tickets`
|
| 300 |
- `Semantic Similarity of IT Support Tickets`
|
|
@@ -367,7 +367,7 @@ requirements.txt
|
|
| 367 |
README.md
|
| 368 |
KNOWLEDGE.md
|
| 369 |
required.md
|
| 370 |
-
|
| 371 |
```
|
| 372 |
|
| 373 |
## Core Files
|
|
@@ -469,7 +469,7 @@ Current local smoke expectations:
|
|
| 469 |
- rewards remain in range for every task
|
| 470 |
- the hard task now depends much more heavily on investigation behavior, so exact seed-level baseline numbers are no longer treated as the benchmark reference for the repo
|
| 471 |
|
| 472 |
-
The April 6 to April 7 validation pass then closed the remaining
|
| 473 |
|
| 474 |
### Windows note
|
| 475 |
|
|
@@ -530,7 +530,7 @@ An April 6 repo audit also confirmed that all required submission files are pres
|
|
| 530 |
|
| 531 |
- runtime: `models.py`, `client.py`, `inference.py`, `server/app.py`, `server/environment.py`, `server/grader.py`, `server/reward.py`, `server/tasks.py`
|
| 532 |
- data and metadata: `data/dataset.json`, `openenv.yaml`, `pyproject.toml`, `requirements.txt`, `server/Dockerfile`
|
| 533 |
-
- docs and
|
| 534 |
|
| 535 |
Roadmap status through April 7 is complete:
|
| 536 |
|
|
@@ -545,4 +545,4 @@ The remaining April 8 work is operational rather than implementation-heavy:
|
|
| 545 |
- run the final submission-branch sanity slice before pushing
|
| 546 |
- perform the live Hugging Face Space ping and reset check on the deployed submission artifact if a fresh deployment is created
|
| 547 |
|
| 548 |
-
The short TRL / GRPO README example
|
|
|
|
| 294 |
|
| 295 |
That scoring policy is now backed by checked-in unit tests in `tests/test_grader_unit.py` and `tests/test_tasks_unit.py`.
|
| 296 |
|
| 297 |
+
The label set and partial-credit choices were also reviewed against public IT-support references during development, including:
|
| 298 |
|
| 299 |
- `Classification of IT Support Tickets`
|
| 300 |
- `Semantic Similarity of IT Support Tickets`
|
|
|
|
| 367 |
README.md
|
| 368 |
KNOWLEDGE.md
|
| 369 |
required.md
|
| 370 |
+
PROJECT_STATUS.md
|
| 371 |
```
|
| 372 |
|
| 373 |
## Core Files
|
|
|
|
| 469 |
- rewards remain in range for every task
|
| 470 |
- the hard task now depends much more heavily on investigation behavior, so exact seed-level baseline numbers are no longer treated as the benchmark reference for the repo
|
| 471 |
|
| 472 |
+
The April 6 to April 7 validation pass then closed the remaining validation gates with Docker smoke coverage via GitHub Actions, a clean-copy install-and-run rerun, structured inference-log verification, and a passing local `openenv validate` check after checking in `uv.lock`.
|
| 473 |
|
| 474 |
### Windows note
|
| 475 |
|
|
|
|
| 530 |
|
| 531 |
- runtime: `models.py`, `client.py`, `inference.py`, `server/app.py`, `server/environment.py`, `server/grader.py`, `server/reward.py`, `server/tasks.py`
|
| 532 |
- data and metadata: `data/dataset.json`, `openenv.yaml`, `pyproject.toml`, `requirements.txt`, `server/Dockerfile`
|
| 533 |
+
- docs and project guidance: `README.md`, `KNOWLEDGE.md`, `required.md`, `PROJECT_STATUS.md`
|
| 534 |
|
| 535 |
Roadmap status through April 7 is complete:
|
| 536 |
|
|
|
|
| 545 |
- run the final submission-branch sanity slice before pushing
|
| 546 |
- perform the live Hugging Face Space ping and reset check on the deployed submission artifact if a fresh deployment is created
|
| 547 |
|
| 548 |
+
The short TRL / GRPO README example remains intentionally deferred because it is optional and lower priority than benchmark clarity and stability.
|
ROADMAP.md
DELETED
|
@@ -1,672 +0,0 @@
|
|
| 1 |
-
# Hackstreet Boys Final Roadmap
|
| 2 |
-
|
| 3 |
-
## Team
|
| 4 |
-
|
| 5 |
-
- Team name: Hackstreet Boys
|
| 6 |
-
- Members:
|
| 7 |
-
- Roopal Guha Neogi
|
| 8 |
-
- Suyash Kumar
|
| 9 |
-
- Submission deadline: April 8, 2026, 11:59 PM IST
|
| 10 |
-
|
| 11 |
-
## How To Use This File
|
| 12 |
-
|
| 13 |
-
- `PROJECT_STATUS.md` is the canonical log of completed work.
|
| 14 |
-
- This roadmap is the active plan from the verified April 6, 2026 repo state to final submission.
|
| 15 |
-
- `required.md` is now the combined official-requirements and project-compliance file.
|
| 16 |
-
- `KNOWLEDGE.md` defines the current repo truth and judge-facing explanation.
|
| 17 |
-
- `analysis/competition_notes.md` is the merged internal competitive note. Use it to prioritize work, but do not mention competitor repos in public-facing docs.
|
| 18 |
-
- The dated April 3 to April 5 sections below are now historical context; the active execution block is the final 24-hour plan for April 6 to April 7, 2026.
|
| 19 |
-
|
| 20 |
-
## Status As Of April 6, 2026
|
| 21 |
-
|
| 22 |
-
The repo is now in the expected "stabilize and merge" phase rather than the earlier "build core fixes" phase.
|
| 23 |
-
|
| 24 |
-
Completed and locally verified:
|
| 25 |
-
|
| 26 |
-
- all concrete items from `gaps.md`
|
| 27 |
-
- the viable low-risk improvements from `analysis/deep_competitive_gap_report.md`
|
| 28 |
-
- single-task `inference.py` execution with `TASK_ID` support and optional `RUN_ALL_TASKS=1`
|
| 29 |
-
- `state()` exposure of `reward` and `done`
|
| 30 |
-
- richer history with predicted actions and follow-up context
|
| 31 |
-
- lightweight investigate-versus-submit action support with tool-backed context lookup
|
| 32 |
-
- small queue-economics signal without major benchmark redesign
|
| 33 |
-
- `/web` UI route
|
| 34 |
-
- local full test pass:
|
| 35 |
-
- `126 passed, 137 subtests passed`
|
| 36 |
-
- local validator pass:
|
| 37 |
-
- `[OK] meta-AIHack: Ready for multi-mode deployment`
|
| 38 |
-
|
| 39 |
-
Merge recommendation:
|
| 40 |
-
|
| 41 |
-
- mergeable as an incremental submission-ready improvement branch
|
| 42 |
-
- do not block merge on major redesign items that were explicitly out of scope:
|
| 43 |
-
- scenario-family task redesign
|
| 44 |
-
- breaking the issue-type-to-assignment shortcut
|
| 45 |
-
- large dataset expansion
|
| 46 |
-
- full queue simulator / economics redesign
|
| 47 |
-
|
| 48 |
-
## What We Are Optimizing For
|
| 49 |
-
|
| 50 |
-
The highest-value wins from now to submission are:
|
| 51 |
-
|
| 52 |
-
1. **Robustness**
|
| 53 |
-
- prove the env works through unit, smoke, and integration tests
|
| 54 |
-
- make Docker and clean reruns boring and reliable
|
| 55 |
-
|
| 56 |
-
2. **RL improvement**
|
| 57 |
-
- keep the reward deterministic
|
| 58 |
-
- make sure scoring is not "always fuzzy"
|
| 59 |
-
- add only small, safe improvements that strengthen reward quality or episode usefulness
|
| 60 |
-
|
| 61 |
-
3. **Real-world grounding**
|
| 62 |
-
- ground our taxonomy and partial-credit choices against real public support-ticket datasets
|
| 63 |
-
- do this as an audit / evidence layer, not as a late dataset merge
|
| 64 |
-
|
| 65 |
-
4. **Submission readiness**
|
| 66 |
-
- satisfy every requirement from `required.md` and `KNOWLEDGE.md`
|
| 67 |
-
- keep the repo easy for judges to understand and rerun
|
| 68 |
-
|
| 69 |
-
## Current Repo State
|
| 70 |
-
|
| 71 |
-
The repo already has:
|
| 72 |
-
|
| 73 |
-
- locked IT helpdesk routing domain
|
| 74 |
-
- locked vocabulary and task names
|
| 75 |
-
- 3-task difficulty ladder
|
| 76 |
-
- deterministic grading with limited partial credit
|
| 77 |
-
- working heuristic baseline
|
| 78 |
-
- merged local validation on `/health`, `/tasks`, and `inference.py`
|
| 79 |
-
- single-task evaluator-safe inference behavior
|
| 80 |
-
- reward and done fields on `state()`
|
| 81 |
-
- richer observation history and linked-ticket context
|
| 82 |
-
- lightweight investigate / submit split with small built-in tool support
|
| 83 |
-
- local full-suite verification:
|
| 84 |
-
- `126 passed, 137 subtests passed`
|
| 85 |
-
- local validator verification:
|
| 86 |
-
- `[OK] meta-AIHack: Ready for multi-mode deployment`
|
| 87 |
-
|
| 88 |
-
The remaining work should be treated as targeted strengthening, not broad feature invention.
|
| 89 |
-
|
| 90 |
-
## Final 24-Hour Plan
|
| 91 |
-
|
| 92 |
-
**Active window:** April 6 to April 7, 2026
|
| 93 |
-
**Internal target:** open PR, merge to the common `main`, and complete the final smoke checks by April 7, 2026
|
| 94 |
-
**Official deadline:** April 8, 2026, 11:59 PM IST
|
| 95 |
-
|
| 96 |
-
### Must finish before merge
|
| 97 |
-
|
| 98 |
-
- review the final diff and stage only the intended submission files
|
| 99 |
-
- open the merge PR from a dedicated branch
|
| 100 |
-
- merge into the shared `main` after one last reviewer pass
|
| 101 |
-
- rerun the post-merge smoke checks:
|
| 102 |
-
- `pytest`
|
| 103 |
-
- `openenv validate`
|
| 104 |
-
- `/health`
|
| 105 |
-
- `/tasks`
|
| 106 |
-
- one `reset()` / `step()` sanity path
|
| 107 |
-
|
| 108 |
-
### Do not add before merge
|
| 109 |
-
|
| 110 |
-
- no new benchmark redesign work
|
| 111 |
-
- no new dataset expansion
|
| 112 |
-
- no schema churn
|
| 113 |
-
- no reward refactors beyond blocker-level fixes
|
| 114 |
-
- no last-minute inference prompt rewrites
|
| 115 |
-
|
| 116 |
-
### Success condition for April 7, 2026
|
| 117 |
-
|
| 118 |
-
- PR is up
|
| 119 |
-
- PR is reviewed against `gaps.md` and `analysis/deep_competitive_gap_report.md`
|
| 120 |
-
- shared `main` contains the tested gap-fix branch
|
| 121 |
-
- deployment sanity checks are green
|
| 122 |
-
- repo is frozen except for typo-level fixes
|
| 123 |
-
|
| 124 |
-
## Submission Gates That Must Still Hold
|
| 125 |
-
|
| 126 |
-
These come directly from `required.md` and `KNOWLEDGE.md`:
|
| 127 |
-
|
| 128 |
-
- the environment starts correctly
|
| 129 |
-
- `reset()`, `step()`, and `state()` behave correctly
|
| 130 |
-
- 3 tasks exist and remain meaningfully different
|
| 131 |
-
- grader scores stay in `[0.0, 1.0]`
|
| 132 |
-
- `inference.py` runs reproducibly without crashing
|
| 133 |
-
- `inference.py` uses the OpenAI client with `API_BASE_URL`, `MODEL_NAME`, and the evaluator-injected `API_KEY` (`HF_TOKEN` remains a local fallback)
|
| 134 |
-
- structured stdout logs follow the official `[START]`, `[STEP]`, and `[END]` format
|
| 135 |
-
- `openenv validate` passes
|
| 136 |
-
- Docker builds and starts cleanly
|
| 137 |
-
- HF deployment responds cleanly and reset works
|
| 138 |
-
- inference stays inside the official runtime / machine envelope
|
| 139 |
-
- docs and metadata are current
|
| 140 |
-
- the repo is easy for judges to understand and rerun
|
| 141 |
-
|
| 142 |
-
## Scope Decisions
|
| 143 |
-
|
| 144 |
-
### Do Now
|
| 145 |
-
|
| 146 |
-
- add tests:
|
| 147 |
-
- unit
|
| 148 |
-
- smoke
|
| 149 |
-
- integration
|
| 150 |
-
- prove the scorer is crisp where it should be crisp
|
| 151 |
-
- add only safe RL-oriented improvements
|
| 152 |
-
- add external grounding evidence without changing the runtime dataset
|
| 153 |
-
- finish packaging / deployment readiness
|
| 154 |
-
- verify official validation constraints, not just local happy-path behavior
|
| 155 |
-
|
| 156 |
-
### Do Not Do Before Submission
|
| 157 |
-
|
| 158 |
-
- MCP migration
|
| 159 |
-
- transform-based reward refactor
|
| 160 |
-
- large dataset expansion
|
| 161 |
-
- external dataset merge into `data/dataset.json`
|
| 162 |
-
- major schema changes
|
| 163 |
-
- broad prompt / inference rewrites that could disturb the stable baseline
|
| 164 |
-
- dependency churn just for polish
|
| 165 |
-
|
| 166 |
-
## Codex-First Working Rules
|
| 167 |
-
|
| 168 |
-
Because we are using Codex to generate code, we should optimize for small, bounded tasks:
|
| 169 |
-
|
| 170 |
-
1. one prompt = one scoped change set
|
| 171 |
-
2. keep ownership by file group
|
| 172 |
-
3. require tests for any scorer or runtime change
|
| 173 |
-
4. review the diff before accepting generated code
|
| 174 |
-
5. rerun the relevant test slice after each meaningful change
|
| 175 |
-
6. do not ask Codex for a giant multi-file redesign this late
|
| 176 |
-
|
| 177 |
-
## Phased Plan
|
| 178 |
-
|
| 179 |
-
## Phase 1: Test And Robustness Foundation
|
| 180 |
-
|
| 181 |
-
**Window:** April 3 to April 4
|
| 182 |
-
|
| 183 |
-
**Goal:** eliminate the biggest competitive weakness identified in `analysis/competition_notes.md`: lack of checked-in tests.
|
| 184 |
-
|
| 185 |
-
### Must produce
|
| 186 |
-
|
| 187 |
-
- `tests/` with at least:
|
| 188 |
-
- grader unit tests
|
| 189 |
-
- task / dataset loader unit tests
|
| 190 |
-
- reward / score-range unit tests
|
| 191 |
-
- environment smoke tests
|
| 192 |
-
- API integration tests
|
| 193 |
-
|
| 194 |
-
### Test plan
|
| 195 |
-
|
| 196 |
-
#### Unit tests
|
| 197 |
-
|
| 198 |
-
- exact match gives `1.0`
|
| 199 |
-
- unsupported task IDs fail clearly
|
| 200 |
-
- only intended near-miss issue-type pairs get partial credit
|
| 201 |
-
- unrelated wrong issue types get `0.0`
|
| 202 |
-
- priority proximity rules behave exactly as defined
|
| 203 |
-
- assignment group and resolution action remain exact-match only
|
| 204 |
-
- task weights sum and apply correctly
|
| 205 |
-
- dataset loads cleanly with `utf-8-sig`
|
| 206 |
-
|
| 207 |
-
#### Smoke tests
|
| 208 |
-
|
| 209 |
-
- `reset()` returns a valid observation
|
| 210 |
-
- `step()` advances queue progress
|
| 211 |
-
- `state()` reflects runtime state
|
| 212 |
-
- seeded resets are deterministic
|
| 213 |
-
- scores remain in `[0.0, 1.0]`
|
| 214 |
-
- one full episode per task completes without errors
|
| 215 |
-
|
| 216 |
-
#### Integration tests
|
| 217 |
-
|
| 218 |
-
- `/health`
|
| 219 |
-
- `/tasks`
|
| 220 |
-
- `/reset`
|
| 221 |
-
- `/step`
|
| 222 |
-
- `/state`
|
| 223 |
-
- one end-to-end seeded episode over HTTP or client path
|
| 224 |
-
- one heuristic `inference.py` regression check on expected overall behavior
|
| 225 |
-
|
| 226 |
-
### Why this phase matters
|
| 227 |
-
|
| 228 |
-
- addresses the biggest repo-quality gap vs stronger competitors
|
| 229 |
-
- improves robustness
|
| 230 |
-
- gives us safe rails for all later RL and grounding changes
|
| 231 |
-
|
| 232 |
-
## Phase 2: Scoring Calibration And Safe RL Improvements
|
| 233 |
-
|
| 234 |
-
**Window:** April 4 to April 5
|
| 235 |
-
|
| 236 |
-
**Goal:** improve RL usefulness without destabilizing the submission.
|
| 237 |
-
|
| 238 |
-
### Must produce
|
| 239 |
-
|
| 240 |
-
- scorer calibration evidence that the system is not "always fuzzy"
|
| 241 |
-
- only a few safe RL-oriented improvements if tests stay green
|
| 242 |
-
|
| 243 |
-
### Required calibration checks
|
| 244 |
-
|
| 245 |
-
- exact-match path is dominant and clearly tested
|
| 246 |
-
- fuzziness exists only in explicitly defined cases
|
| 247 |
-
- wrong labels outside the similarity map score `0.0`
|
| 248 |
-
- assignment group and resolution action remain exact
|
| 249 |
-
- final episode reward stays bounded and deterministic
|
| 250 |
-
|
| 251 |
-
### Safe improvement candidates from `analysis/competition_notes.md`
|
| 252 |
-
|
| 253 |
-
- expand `ISSUE_TYPE_SIMILARITY` with only a few defensible pairs, if backed by grounding review
|
| 254 |
-
- enrich `history` with:
|
| 255 |
-
- ticket title
|
| 256 |
-
- predicted fields
|
| 257 |
-
- optionally support `queue_size` as a reset kwarg only if the change is tiny and fully tested
|
| 258 |
-
|
| 259 |
-
### Hard stop
|
| 260 |
-
|
| 261 |
-
- if a change touches behavior and shifts baseline numbers unexpectedly, stop and stabilize rather than stacking more changes
|
| 262 |
-
|
| 263 |
-
## Phase 3: Real-World Grounding Audit
|
| 264 |
-
|
| 265 |
-
**Window:** April 5 to April 6
|
| 266 |
-
|
| 267 |
-
**Goal:** add defensible evidence that our taxonomy and partial-credit logic are grounded in real support data, without merging external data into runtime.
|
| 268 |
-
|
| 269 |
-
### Grounding strategy
|
| 270 |
-
|
| 271 |
-
- use real public support datasets as reference material
|
| 272 |
-
- compare their labels / examples against our taxonomy
|
| 273 |
-
- create an internal audit, not a runtime dependency
|
| 274 |
-
|
| 275 |
-
### Recommended grounding references
|
| 276 |
-
|
| 277 |
-
- `Classification of IT Support Tickets` (Zenodo, 2,229 manually classified tickets)
|
| 278 |
-
- `Semantic Similarity of IT Support Tickets` (Zenodo, 300 manually labeled ticket pairs)
|
| 279 |
-
- `MSDialog` for real technical-support conversation patterns and terminology
|
| 280 |
-
|
| 281 |
-
### Must produce
|
| 282 |
-
|
| 283 |
-
- an internal grounding note or checklist that captures:
|
| 284 |
-
- which public datasets were reviewed
|
| 285 |
-
- how our labels map to real-world ticket themes
|
| 286 |
-
- which partial-credit pairs are defensible
|
| 287 |
-
- which proposed similarity pairs were rejected as too fuzzy
|
| 288 |
-
|
| 289 |
-
### Useful output
|
| 290 |
-
|
| 291 |
-
- 10 to 20 grounding examples:
|
| 292 |
-
- real ticket theme
|
| 293 |
-
- closest label in our taxonomy
|
| 294 |
-
- whether it should be exact-match only or partial-credit-adjacent
|
| 295 |
-
|
| 296 |
-
### Why this phase matters
|
| 297 |
-
|
| 298 |
-
- strengthens real-world credibility
|
| 299 |
-
- supports RL reward quality with evidence
|
| 300 |
-
- helps avoid arbitrary or over-fuzzy scorer changes
|
| 301 |
-
|
| 302 |
-
## Phase 4: Packaging, Deployment, And Judge-Facing Polish
|
| 303 |
-
|
| 304 |
-
**Window:** April 6 to April 7
|
| 305 |
-
|
| 306 |
-
**Goal:** close the submission-readiness gaps surfaced in `analysis/competition_notes.md`.
|
| 307 |
-
|
| 308 |
-
### Must produce
|
| 309 |
-
|
| 310 |
-
- Hugging Face Spaces README frontmatter
|
| 311 |
-
- `.openenvignore`
|
| 312 |
-
- `openenv validate` evidence
|
| 313 |
-
- Docker smoke evidence on the merged branch
|
| 314 |
-
- one clean-copy rerun if possible
|
| 315 |
-
- structured inference logging verified against the official format
|
| 316 |
-
- a practical check that inference remains inside the official runtime envelope
|
| 317 |
-
|
| 318 |
-
### Nice-to-have only if green
|
| 319 |
-
|
| 320 |
-
- short TRL / GRPO example in `README.md`
|
| 321 |
-
- concise note in docs that grading is deterministic, partially structured, and not purely fuzzy
|
| 322 |
-
|
| 323 |
-
### Do not do here
|
| 324 |
-
|
| 325 |
-
- no dataset expansion
|
| 326 |
-
- no major inference rewrite
|
| 327 |
-
- no architecture refactor
|
| 328 |
-
|
| 329 |
-
## Phase 5: Freeze And Submit
|
| 330 |
-
|
| 331 |
-
**Window:** April 8
|
| 332 |
-
|
| 333 |
-
**Goal:** submit from a calm, validated repo state.
|
| 334 |
-
|
| 335 |
-
### Final day rules
|
| 336 |
-
|
| 337 |
-
- only typo-level, doc-level, or packaging-only fixes
|
| 338 |
-
- no risky scorer changes
|
| 339 |
-
- no runtime refactors
|
| 340 |
-
- no dataset edits unless they fix a blocker
|
| 341 |
-
- stop risky edits several hours before submission
|
| 342 |
-
- if possible, run the official validator or the closest local equivalent before final push
|
| 343 |
-
|
| 344 |
-
## Ownership From Now Until Submission
|
| 345 |
-
|
| 346 |
-
### Roopal ownership
|
| 347 |
-
|
| 348 |
-
Primary files:
|
| 349 |
-
|
| 350 |
-
- `data/dataset.json`
|
| 351 |
-
- `server/tasks.py`
|
| 352 |
-
- `server/grader.py`
|
| 353 |
-
- `README.md`
|
| 354 |
-
- `KNOWLEDGE.md`
|
| 355 |
-
|
| 356 |
-
Primary responsibilities:
|
| 357 |
-
|
| 358 |
-
- scorer calibration and label quality
|
| 359 |
-
- unit tests around grader / task rules / dataset invariants
|
| 360 |
-
- real-world grounding audit
|
| 361 |
-
- judge-facing explanation of deterministic scoring and real-world realism
|
| 362 |
-
- safe reward-quality improvements only when grounded and tested
|
| 363 |
-
|
| 364 |
-
Concrete deliverables:
|
| 365 |
-
|
| 366 |
-
- grader unit tests
|
| 367 |
-
- grounding mapping note
|
| 368 |
-
- any similarity-matrix update, if justified
|
| 369 |
-
- doc updates if benchmark numbers or scoring explanation change
|
| 370 |
-
- README frontmatter and judge-facing clarity
|
| 371 |
-
- official requirement compliance review through `required.md`
|
| 372 |
-
|
| 373 |
-
### Suyash ownership
|
| 374 |
-
|
| 375 |
-
Primary files:
|
| 376 |
-
|
| 377 |
-
- `models.py`
|
| 378 |
-
- `server/environment.py`
|
| 379 |
-
- `server/app.py`
|
| 380 |
-
- `server/reward.py`
|
| 381 |
-
- `client.py`
|
| 382 |
-
- `inference.py`
|
| 383 |
-
- `openenv.yaml`
|
| 384 |
-
- `server/Dockerfile`
|
| 385 |
-
- `pyproject.toml`
|
| 386 |
-
- `requirements.txt`
|
| 387 |
-
|
| 388 |
-
Primary responsibilities:
|
| 389 |
-
|
| 390 |
-
- smoke and integration tests
|
| 391 |
-
- runtime stability
|
| 392 |
-
- Docker and deployment readiness
|
| 393 |
-
- inference reproducibility
|
| 394 |
-
- clean rerun evidence
|
| 395 |
-
- optional small RL-signal improvements on the runtime side
|
| 396 |
-
|
| 397 |
-
Concrete deliverables:
|
| 398 |
-
|
| 399 |
-
- env smoke tests
|
| 400 |
-
- API integration tests
|
| 401 |
-
- heuristic inference regression path
|
| 402 |
-
- `.openenvignore`
|
| 403 |
-
- Docker smoke confirmation
|
| 404 |
-
- clean-copy rerun if possible
|
| 405 |
-
- structured inference logging compliance
|
| 406 |
-
|
| 407 |
-
### Shared responsibilities
|
| 408 |
-
|
| 409 |
-
- do not rename schemas or vocabulary
|
| 410 |
-
- rerun the benchmark after any behavior-affecting change
|
| 411 |
-
- keep `PROJECT_STATUS.md` honest
|
| 412 |
-
- use the GitHub Actions Docker smoke workflow when local Docker is blocked
|
| 413 |
-
- review Codex-generated diffs before accepting them
|
| 414 |
-
- freeze feature work by the end of April 7
|
| 415 |
-
- do not casually change the `[START]`, `[STEP]`, `[END]` inference log format once implemented
|
| 416 |
-
|
| 417 |
-
## Date-By-Date Execution Plan
|
| 418 |
-
|
| 419 |
-
## April 3, 2026
|
| 420 |
-
|
| 421 |
-
Primary goal:
|
| 422 |
-
|
| 423 |
-
- lock the execution plan and begin test scaffolding immediately
|
| 424 |
-
|
| 425 |
-
Roopal:
|
| 426 |
-
|
| 427 |
-
- finalize the exact scorer behaviors that must be proven by tests
|
| 428 |
-
- list the exact-match-only cases and intended partial-credit cases
|
| 429 |
-
- begin grader and task-loader unit tests
|
| 430 |
-
|
| 431 |
-
Suyash:
|
| 432 |
-
|
| 433 |
-
- scaffold `tests/`
|
| 434 |
-
- begin smoke tests for `reset()`, `step()`, `state()`, and deterministic seeded behavior
|
| 435 |
-
- confirm how integration tests will hit the app cleanly
|
| 436 |
-
- review `required.md` and identify the exact official validation items still not reflected in runtime / inference behavior
|
| 437 |
-
|
| 438 |
-
Shared checkpoint:
|
| 439 |
-
|
| 440 |
-
- test strategy is agreed
|
| 441 |
-
- file ownership is clear
|
| 442 |
-
- no one is making unscoped runtime changes yet
|
| 443 |
-
|
| 444 |
-
## April 4, 2026
|
| 445 |
-
|
| 446 |
-
Primary goal:
|
| 447 |
-
|
| 448 |
-
- land the first complete test layer
|
| 449 |
-
|
| 450 |
-
Roopal:
|
| 451 |
-
|
| 452 |
-
- complete grader, task, and dataset unit tests
|
| 453 |
-
- add explicit tests showing where fuzziness is allowed and where it is not
|
| 454 |
-
|
| 455 |
-
Suyash:
|
| 456 |
-
|
| 457 |
-
- complete smoke tests
|
| 458 |
-
- add first-pass integration tests for `/health`, `/tasks`, `/reset`, and `/step`
|
| 459 |
-
- begin checking how current `inference.py` differs from the official structured logging requirement
|
| 460 |
-
|
| 461 |
-
Shared checkpoint:
|
| 462 |
-
|
| 463 |
-
- checked-in tests exist
|
| 464 |
-
- the repo can prove deterministic scoring and score bounds
|
| 465 |
-
- any failing behavior is triaged before adding improvements
|
| 466 |
-
|
| 467 |
-
## April 5, 2026
|
| 468 |
-
|
| 469 |
-
Primary goal:
|
| 470 |
-
|
| 471 |
-
- improve RL usefulness safely
|
| 472 |
-
|
| 473 |
-
Roopal:
|
| 474 |
-
|
| 475 |
-
- start the grounding audit using the selected public datasets
|
| 476 |
-
- decide whether any additional similarity pairs are truly defensible
|
| 477 |
-
|
| 478 |
-
Suyash:
|
| 479 |
-
|
| 480 |
-
- add integration coverage for full seeded episode flow and `state()`
|
| 481 |
-
- add a light heuristic regression path for `inference.py`
|
| 482 |
-
- optionally enrich observation history if tests are already green
|
| 483 |
-
- bring `inference.py` closer to official structured logging format if the change can be done safely
|
| 484 |
-
|
| 485 |
-
Shared checkpoint:
|
| 486 |
-
|
| 487 |
-
- tests are stable
|
| 488 |
-
- any RL-oriented change is small and justified
|
| 489 |
-
- no baseline drift goes unexplained
|
| 490 |
-
|
| 491 |
-
## April 6, 2026
|
| 492 |
-
|
| 493 |
-
Primary goal:
|
| 494 |
-
|
| 495 |
-
- finish grounding evidence and close packaging gaps
|
| 496 |
-
|
| 497 |
-
Roopal:
|
| 498 |
-
|
| 499 |
-
- finish grounding audit note
|
| 500 |
-
- land only the scorer adjustments supported by audit evidence, if any
|
| 501 |
-
- update docs to reflect deterministic, grounded scoring
|
| 502 |
-
|
| 503 |
-
Suyash:
|
| 504 |
-
|
| 505 |
-
- add `.openenvignore`
|
| 506 |
-
- verify Docker smoke workflow on the merged branch
|
| 507 |
-
- check deployment assumptions around `app_port`, `/docs`, `/health`, `/ws`, and `/web`
|
| 508 |
-
- run `openenv validate` or the closest available validation path
|
| 509 |
-
- verify structured inference logging and runtime-envelope expectations
|
| 510 |
-
|
| 511 |
-
Shared checkpoint:
|
| 512 |
-
|
| 513 |
-
- grounding evidence exists
|
| 514 |
-
- packaging gaps are closed or explicitly blocked
|
| 515 |
-
- benchmark references are still current
|
| 516 |
-
|
| 517 |
-
## April 7, 2026
|
| 518 |
-
|
| 519 |
-
Primary goal:
|
| 520 |
-
|
| 521 |
-
- freeze on a green, submission-ready repo
|
| 522 |
-
|
| 523 |
-
Roopal:
|
| 524 |
-
|
| 525 |
-
- final docs consistency pass across `README.md` and `KNOWLEDGE.md`
|
| 526 |
-
- add a short TRL / GRPO usage example only if everything else is already green
|
| 527 |
-
|
| 528 |
-
Suyash:
|
| 529 |
-
|
| 530 |
-
- do a clean-copy install-and-run pass if possible
|
| 531 |
-
- rerun heuristic baseline if any runtime-side change landed
|
| 532 |
-
- freeze runtime files by end of day
|
| 533 |
-
|
| 534 |
-
Shared checkpoint:
|
| 535 |
-
|
| 536 |
-
- tests are green
|
| 537 |
-
- Docker evidence exists
|
| 538 |
-
- docs, metadata, and runtime tell the same story
|
| 539 |
-
- feature work stops unless the gated competitive-hardening window below is explicitly activated after all required checks are already green
|
| 540 |
-
|
| 541 |
-
## After April 7 If Green: Competitive Hardening Window
|
| 542 |
-
|
| 543 |
-
**Window:** late April 7 to early April 8 only if all required gates are already green
|
| 544 |
-
|
| 545 |
-
**Goal:** improve the repo's competitive position against the strongest submissions by winning on reliability, validation quality, RL usefulness, and judge readability rather than by trying to match their architecture complexity.
|
| 546 |
-
|
| 547 |
-
### Activation rule
|
| 548 |
-
|
| 549 |
-
Activate this block only if all of the following are already true:
|
| 550 |
-
|
| 551 |
-
- smoke, unit, and integration tests are green
|
| 552 |
-
- Docker evidence exists or the blocker is clearly external
|
| 553 |
-
- `openenv validate` has passed or the closest available validator path is already recorded
|
| 554 |
-
- structured inference logging is already compliant or one tiny remaining fix is clearly isolated
|
| 555 |
-
- the benchmark is stable and any behavior-changing diff can still be rerun safely
|
| 556 |
-
|
| 557 |
-
If any of those are not true, skip this entire block and proceed directly to freeze / submission.
|
| 558 |
-
|
| 559 |
-
### Allowed competitive upgrades
|
| 560 |
-
|
| 561 |
-
- strengthen validation proof:
|
| 562 |
-
- add or tighten environment smoke tests
|
| 563 |
-
- add or tighten API integration tests
|
| 564 |
-
- add one lightweight heuristic regression check for `inference.py`
|
| 565 |
-
- strengthen deployment proof:
|
| 566 |
-
- record `openenv validate` evidence
|
| 567 |
-
- record Docker smoke evidence
|
| 568 |
-
- record deployment-assumption checks for `app_port`, `/health`, `/docs`, `/ws`, and `/web`
|
| 569 |
-
- record one clean-copy rerun if practical
|
| 570 |
-
- add only tiny RL-signal improvements if fully tested and benchmark-stable:
|
| 571 |
-
- enrich `history` with ticket title and predicted fields
|
| 572 |
-
- add `queue_size` as a reset kwarg only if the change remains small, bounded, and fully tested
|
| 573 |
-
- add final judge-facing polish only after runtime proof is green:
|
| 574 |
-
- short TRL / GRPO README example
|
| 575 |
-
- concise README note on why our dense deterministic reward is more RL-friendly than binary-only grading
|
| 576 |
-
|
| 577 |
-
### Hard limits
|
| 578 |
-
|
| 579 |
-
- do not add MCP
|
| 580 |
-
- do not add a simulator layer
|
| 581 |
-
- do not add browser or multimodal features
|
| 582 |
-
- do not expand the runtime dataset
|
| 583 |
-
- do not make broad inference rewrites
|
| 584 |
-
- do not stack multiple behavior changes without rerunning the benchmark
|
| 585 |
-
|
| 586 |
-
### Decision rule
|
| 587 |
-
|
| 588 |
-
- if a competitive-hardening change is tiny, tested, and clearly improves trust or judge readability, it is allowed
|
| 589 |
-
- if it adds architectural ambition at the expense of stability, skip it
|
| 590 |
-
- if it causes unexplained baseline drift, revert to the last green state and submit
|
| 591 |
-
|
| 592 |
-
### Ownership
|
| 593 |
-
|
| 594 |
-
Roopal:
|
| 595 |
-
|
| 596 |
-
- final judge-facing README / KNOWLEDGE / `required.md` polish
|
| 597 |
-
- RL-justification wording around deterministic partial credit
|
| 598 |
-
- TRL / GRPO example only after all runtime proof is green
|
| 599 |
-
|
| 600 |
-
Suyash:
|
| 601 |
-
|
| 602 |
-
- validation evidence
|
| 603 |
-
- deployment proof
|
| 604 |
-
- tiny runtime-side RL-signal improvements only if fully tested
|
| 605 |
-
|
| 606 |
-
Shared checkpoint:
|
| 607 |
-
|
| 608 |
-
- the repo is already submission-safe before this block starts
|
| 609 |
-
- every change in this block is optional
|
| 610 |
-
- if time gets tight, cut this whole block first
|
| 611 |
-
|
| 612 |
-
## April 8, 2026
|
| 613 |
-
|
| 614 |
-
Primary goal:
|
| 615 |
-
|
| 616 |
-
- submit early from a calm repo state
|
| 617 |
-
|
| 618 |
-
Morning:
|
| 619 |
-
|
| 620 |
-
- if the repo is already fully green, optionally activate the competitive-hardening window above for one last small, tested improvement
|
| 621 |
-
- run final smoke / test slice on the submission branch
|
| 622 |
-
- verify required files are present
|
| 623 |
-
- verify README and metadata are current
|
| 624 |
-
- run the final validation checklist from `required.md`
|
| 625 |
-
|
| 626 |
-
Afternoon:
|
| 627 |
-
|
| 628 |
-
- only typo-level or packaging-only fixes
|
| 629 |
-
- no risky code changes
|
| 630 |
-
|
| 631 |
-
Final rule:
|
| 632 |
-
|
| 633 |
-
- stop risky edits several hours before 11:59 PM IST
|
| 634 |
-
- submit as soon as the repo is clearly green
|
| 635 |
-
|
| 636 |
-
## Cut Order If Time Gets Tight
|
| 637 |
-
|
| 638 |
-
Cut these first:
|
| 639 |
-
|
| 640 |
-
1. the entire competitive-hardening window after April 7
|
| 641 |
-
1. `queue_size` reset kwarg
|
| 642 |
-
2. richer `history`
|
| 643 |
-
3. TRL / GRPO README example
|
| 644 |
-
4. any optional similarity expansion beyond the most defensible cases
|
| 645 |
-
|
| 646 |
-
Do not cut these:
|
| 647 |
-
|
| 648 |
-
1. tests
|
| 649 |
-
2. scorer crispness checks
|
| 650 |
-
3. Docker / deployment validation
|
| 651 |
-
4. grounding audit evidence
|
| 652 |
-
5. final benchmark sanity rerun if behavior changed
|
| 653 |
-
6. official structured inference logging compliance
|
| 654 |
-
|
| 655 |
-
## Definition Of Done
|
| 656 |
-
|
| 657 |
-
The project is ready when:
|
| 658 |
-
|
| 659 |
-
1. unit, smoke, and integration tests exist and cover the critical paths
|
| 660 |
-
2. scoring is demonstrably deterministic and not fuzzy by default
|
| 661 |
-
3. a grounding audit against real public support datasets exists
|
| 662 |
-
4. the heuristic baseline still runs successfully
|
| 663 |
-
5. the inference path is compliant with the official log format
|
| 664 |
-
6. `openenv validate` and Docker checks are validated
|
| 665 |
-
7. docs and metadata are current and judge-friendly
|
| 666 |
-
8. the repo is frozen and submitted on time
|
| 667 |
-
|
| 668 |
-
## Simple Rule To Remember
|
| 669 |
-
|
| 670 |
-
Roopal owns the labels, scoring truth, grounding, and public clarity.
|
| 671 |
-
Suyash owns the runtime, tests beyond unit scope, packaging, and reproducibility rails.
|
| 672 |
-
Both of you should optimize for a clean, defensible, rerunnable submission rather than last-minute complexity.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
analysis/competition_notes.md
DELETED
|
@@ -1,87 +0,0 @@
|
|
| 1 |
-
# Competition Notes
|
| 2 |
-
|
| 3 |
-
> Internal-only competitive positioning and late-stage prioritization note.
|
| 4 |
-
> Do not cite competitor repos in public-facing docs.
|
| 5 |
-
|
| 6 |
-
## Summary
|
| 7 |
-
|
| 8 |
-
Our strongest comparative advantages are:
|
| 9 |
-
|
| 10 |
-
- a clear 3-task easy-to-hard ladder
|
| 11 |
-
- deterministic, dense partial-credit reward
|
| 12 |
-
- compact judge-friendly architecture
|
| 13 |
-
- a strong heuristic baseline
|
| 14 |
-
|
| 15 |
-
The strongest external competitor pattern is higher simulator depth or broader architecture ambition, especially in long-horizon environments. Our best response is reliability and clarity, not late complexity.
|
| 16 |
-
|
| 17 |
-
## What Matters Most
|
| 18 |
-
|
| 19 |
-
Judges are most likely to reward:
|
| 20 |
-
|
| 21 |
-
1. correctness and rerunnability
|
| 22 |
-
2. real-world domain quality
|
| 23 |
-
3. task and grader quality
|
| 24 |
-
4. reward usefulness for RL
|
| 25 |
-
5. clean packaging and deployment
|
| 26 |
-
6. baseline reproducibility
|
| 27 |
-
|
| 28 |
-
## Key Competitive Read
|
| 29 |
-
|
| 30 |
-
### Where we are strong
|
| 31 |
-
|
| 32 |
-
- helpdesk routing is a real enterprise workflow
|
| 33 |
-
- the task ladder is explicit and curriculum-friendly
|
| 34 |
-
- dense deterministic scoring is more RL-friendly than binary-only grading
|
| 35 |
-
- the repo is easier for judges to understand quickly than heavier simulator-style projects
|
| 36 |
-
|
| 37 |
-
### Where strong competitors can beat us
|
| 38 |
-
|
| 39 |
-
- simulator depth and richer state
|
| 40 |
-
- long-horizon control realism
|
| 41 |
-
- larger datasets or generated scenario breadth
|
| 42 |
-
- broader tooling such as MCP integrations
|
| 43 |
-
|
| 44 |
-
## Priority Responses
|
| 45 |
-
|
| 46 |
-
The highest-value late-stage moves are:
|
| 47 |
-
|
| 48 |
-
1. strengthen validation proof
|
| 49 |
-
2. keep scorer crispness explicit and tested
|
| 50 |
-
3. document grounded scoring clearly
|
| 51 |
-
4. prove Docker and validator readiness
|
| 52 |
-
5. avoid architecture churn
|
| 53 |
-
|
| 54 |
-
## Late-Stage Rules
|
| 55 |
-
|
| 56 |
-
- do not add MCP
|
| 57 |
-
- do not do a reward-architecture refactor
|
| 58 |
-
- do not expand the runtime dataset late
|
| 59 |
-
- do not make broad inference changes
|
| 60 |
-
- only add tiny RL-signal improvements if fully tested and benchmark-stable
|
| 61 |
-
|
| 62 |
-
## Practical Action List
|
| 63 |
-
|
| 64 |
-
### Must keep
|
| 65 |
-
|
| 66 |
-
- unit, smoke, and integration tests
|
| 67 |
-
- scorer crispness checks
|
| 68 |
-
- grounding audit evidence
|
| 69 |
-
- Docker smoke proof
|
| 70 |
-
- `openenv validate` readiness
|
| 71 |
-
- clean judge-facing docs
|
| 72 |
-
|
| 73 |
-
### Nice to have only if fully green
|
| 74 |
-
|
| 75 |
-
- richer history fields
|
| 76 |
-
- `queue_size` reset kwarg
|
| 77 |
-
- short TRL / GRPO README example
|
| 78 |
-
|
| 79 |
-
## Competitor Snapshot
|
| 80 |
-
|
| 81 |
-
The field includes:
|
| 82 |
-
|
| 83 |
-
- simple reference environments that we clearly outperform on realism
|
| 84 |
-
- strong but binary-reward environments where we win on RL signal quality
|
| 85 |
-
- ambitious simulator-style environments that win on technical scope but are harder to judge quickly
|
| 86 |
-
|
| 87 |
-
Our best positioning is not "most complex"; it is "most defensible, trainable, and rerunnable."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
analysis/deep_competitive_gap_report.md
DELETED
|
@@ -1,1374 +0,0 @@
|
|
| 1 |
-
# Deep Codebase Comparison: OpenEnv Reference Environments vs This Helpdesk Project
|
| 2 |
-
|
| 3 |
-
## Scope and Method
|
| 4 |
-
|
| 5 |
-
This report was written from a direct code read, not from README-driven interpretation. I treated the `OpenEnv/envs` directory as the reference baseline you pointed to, and I compared it against the implementation that lives in this repository root plus `server/`.
|
| 6 |
-
|
| 7 |
-
I focused on code that actually defines runtime behavior:
|
| 8 |
-
|
| 9 |
-
- `models.py`
|
| 10 |
-
- `inference.py`
|
| 11 |
-
- `client.py`
|
| 12 |
-
- `vocabulary.py`
|
| 13 |
-
- `server/environment.py`
|
| 14 |
-
- `server/tasks.py`
|
| 15 |
-
- `server/grader.py`
|
| 16 |
-
- `server/reward.py`
|
| 17 |
-
- `server/app.py`
|
| 18 |
-
- `tests/*.py`
|
| 19 |
-
- `data/dataset.json`
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
That reading set is enough to answer the question that matters: what design moves make the strongest reference environments hard to beat, where your project is currently thinner than it looks, and what concrete changes would make your environment competitive instead of merely correct.
|
| 23 |
-
|
| 24 |
-
## Executive Verdict
|
| 25 |
-
|
| 26 |
-
Your project is a clean, readable, deterministic mini-benchmark. It is not yet a high-ceiling agent benchmark.
|
| 27 |
-
|
| 28 |
-
That sounds harsh, but it is also the clearest way to unlock the right next move. Right now your environment behaves much more like a structured multi-label classification task wrapped in OpenEnv than like the richer reference environments that expose hidden state, tool use, long-horizon consequences, multi-step reasoning, or grounded interaction with external systems. The code is good enough as a starter environment. It is not yet strong enough to beat the best reference projects on depth, realism, or benchmark credibility.
|
| 29 |
-
|
| 30 |
-
The good news is that the codebase is small, coherent, and fixable. The bad news is that the gap is not a one-line polish gap. It is a benchmark design gap.
|
| 31 |
-
|
| 32 |
-
The strongest OpenEnv reference environments win for one or more of these reasons:
|
| 33 |
-
|
| 34 |
-
- they expose a real action surface, not just label prediction
|
| 35 |
-
- they make the agent inspect state rather than infer everything from one text blob
|
| 36 |
-
- they reward process, not only end labels
|
| 37 |
-
- they support long-horizon or multi-step behavior
|
| 38 |
-
- they are harder to brute-force with dataset-specific heuristics
|
| 39 |
-
- they are backed by real engines, shells, browsers, tools, or stateful simulators
|
| 40 |
-
- they treat evaluation as a first-class system, not as a tiny helper function
|
| 41 |
-
|
| 42 |
-
Your project currently loses on most of those axes.
|
| 43 |
-
|
| 44 |
-
At the same time, your project has an underrated advantage: the domain is practical, legible, and product-shaped. IT helpdesk routing is a great benchmark domain if you push it harder. It naturally supports ambiguity, policy lookup, account context, queue optimization, escalation rules, duplicates, follow-up chains, customer sentiment, service health, SLA clocks, and partial observability. In other words, the domain is better than the current implementation. The environment has room to grow into something much stronger without abandoning the idea.
|
| 45 |
-
|
| 46 |
-
So the answer is not “throw this away and copy BrowserGym.” The answer is “turn this from a label benchmark into a realistic triage operations environment.”
|
| 47 |
-
|
| 48 |
-
## What the Reference Environments Actually Do Better
|
| 49 |
-
|
| 50 |
-
### 1. They expose richer action spaces
|
| 51 |
-
|
| 52 |
-
The single biggest difference between your code and the strongest reference projects is that the agent in your environment does very little. In your environment, the step is basically “predict some labels for this ticket.” In the stronger reference environments, the agent interacts.
|
| 53 |
-
|
| 54 |
-
`BrowserGymEnvironment` accepts an `action_str` and pushes it into a live browser benchmark. That means the benchmark difficulty comes from action selection in stateful UI space, not just from text classification. `OpenAppEnvironment` similarly supports `click`, `fill`, `select_option`, `goto`, `scroll`, and `send_keys`, and even mixes BrowserGym-style element IDs with raw Playwright CSS selectors for pragmatic reliability. `GitTaskEnvironment` supports clone, list, and git command execution against a Gitea-backed workspace. `Tbench2Environment` supports `exec`, `write`, `view`, `wait`, `kill`, `write_file`, and `evaluate`, which is much closer to real agent work. `FinQAEnvironment` turns the task into tool use over tables, SQL, and answer submission. `REPLEnvironment` exposes code execution with optional recursive LLM calls. `TextArenaEnvironment` takes natural-language moves and advances a game engine.
|
| 55 |
-
|
| 56 |
-
Your environment exposes none of that. The agent does not gather missing evidence. It does not inspect a related ticket. It does not search a KB. It does not look up account tier. It does not check service health. It does not add an internal note. It does not choose between acknowledging first and escalating later. It does not defer. It does not ask for more information. It does not resolve duplicates. It does not manage a queue. It only emits one shot structured output.
|
| 57 |
-
|
| 58 |
-
That makes the benchmark much easier to game, much easier to overfit, and much less diagnostic of real agent competence.
|
| 59 |
-
|
| 60 |
-
### 2. They separate visible observation from hidden truth
|
| 61 |
-
|
| 62 |
-
The strongest reference environments keep some truth state behind the curtain. The agent sees an observation. The environment owns more. That separation is what makes an environment feel like an environment instead of a dataframe with reward labels.
|
| 63 |
-
|
| 64 |
-
In `ChessEnvironment`, the agent observes legal moves, FEN, checks, and result state, but the environment owns board progression, opponent strategy, and trajectory reward accumulation. In `MazeEnvironment`, the environment tracks maze status and legal movement dynamics. In `TextArenaEnvironment`, the wrapped engine owns turn state, raw logs, rewards, role mapping, and step info. In `FinQAEnvironment`, the agent sees the question and tools, but the hidden ground truth answer, question identity, and full structured table data live behind the environment. In `Tbench2Environment`, the hidden truth is in the task files and tests. In `BrowserGymEnvironment`, the browser session and benchmark internals are hidden behind the observation.
|
| 65 |
-
|
| 66 |
-
Your environment has much less hidden truth than it should. The ticket label is hidden, yes, but the benchmark structure is shallow. More importantly, the code already hints at richer hidden structure and then fails to expose or exploit it. `HelpdeskTicketRecord` includes `ambiguity_note` and `related_ticket_id`, but `_build_observation()` throws both away and only exposes `ticket_id`, `title`, `requester`, and `description`. So even though the dataset contains follow-up relationships and ambiguity annotations, the environment does not actually let the agent work with them as structured state. That is a missed opportunity and a design leak at the same time.
|
| 67 |
-
|
| 68 |
-
The dataset is telling you the domain wants threads, ambiguity, and context. The environment currently flattens it back into plain text.
|
| 69 |
-
|
| 70 |
-
### 3. They reward more than a final label match
|
| 71 |
-
|
| 72 |
-
The reference environments do not all have brilliant reward design, but the best ones take reward seriously.
|
| 73 |
-
|
| 74 |
-
`REPLEnvironment` combines an outcome rubric with optional process reward. It can reward successful execution, penalize failures, and separately judge the final answer. `ChessEnvironment` uses a trajectory rubric with exponential discounting to assign credit across a game. `FinQAEnvironment` does robust answer normalization, including boxed answers, percentages, fractions, and multi-value comparisons. `TextArenaEnvironment` overlays auxiliary reward signals such as Wordle greens, yellows, repetitions, and correctness. `Tbench2Environment` evaluates by actually running tests, which is a grounded form of outcome reward.
|
| 75 |
-
|
| 76 |
-
Your reward design is better than “exact match only,” but it is still thin. `grade_action()` uses one handcrafted issue similarity table, one handcrafted priority proximity table, and exact match for assignment group and resolution action. `compute_step_reward()` is just clamping. `compute_trajectory_reward()` averages scores and subtracts an overshoot penalty.
|
| 77 |
-
|
| 78 |
-
That sounds reasonable until you inspect the runtime path. In practice, the overshoot penalty is effectively dead logic. `step()` increments the ticket index once per ticket and sets done when the index reaches queue length. A later `step()` call raises an error. That means `steps_taken` cannot exceed `queue_size` during normal episode execution, so the overshoot branch in `compute_trajectory_reward()` has no meaningful role in the current environment. The code suggests the benchmark penalizes wasteful action loops, but the environment does not actually allow them.
|
| 79 |
-
|
| 80 |
-
The deeper issue is that the reward judges only final fields, not triage quality as a process. There is no penalty for unnecessary escalation unless the final field is wrong. There is no reward for correctly identifying a duplicate and linking it. There is no cost model for routing everything to security “just in case.” There is no SLA-aware penalty for under-prioritizing a time-sensitive issue that still happens to hit some partial-credit similarity. There is no queue-level reward. There is no explanation consistency. There is no tool efficiency score because there are no tools. There is no notion of customer harm, resolver cost, escalation burden, or backlog impact.
|
| 81 |
-
|
| 82 |
-
The strongest environments earn their credibility by making reward a modeling decision. Your reward is still a convenience function.
|
| 83 |
-
|
| 84 |
-
### 4. They support multi-step or long-horizon behavior
|
| 85 |
-
|
| 86 |
-
Even the simpler reference environments tend to have longer horizon than your three-task ladder suggests.
|
| 87 |
-
|
| 88 |
-
`ChessEnvironment` is naturally long horizon. `BrowserGymEnvironment` and `OpenAppEnvironment` are stepwise interactions. `TextArenaEnvironment` proceeds over turns. `Tbench2Environment` supports iterative shell work and explicit evaluation. `REPLEnvironment` supports repeated code execution over an evolving namespace. `FinQAEnvironment` allows repeated tool calls up to `max_steps` before submission. Even `ReasoningGymEnvironment`, which is single-step, supports parameterized dataset generation and configurable tasks.
|
| 89 |
-
|
| 90 |
-
Your environment has multiple steps inside an episode, but they are just a queue of independent tickets. Each step is still one-shot labeling. Tickets do not affect each other. The queue order does not matter. There is no resource constraint. There is no carry-over state except a score list and counters. No later ticket depends on an earlier action. No policy evolves over the episode. No investigation outcome from step one informs step two.
|
| 91 |
-
|
| 92 |
-
So while the environment is technically episodic, it is not operationally long horizon. It is batching.
|
| 93 |
-
|
| 94 |
-
That difference matters. The best agents and best benchmarks separate “can classify one item” from “can operate over a process.” Right now your environment mainly measures the first.
|
| 95 |
-
|
| 96 |
-
### 5. They parameterize tasks rather than freezing one tiny benchmark
|
| 97 |
-
|
| 98 |
-
`ReasoningGymEnvironment` rebuilds datasets from `dataset_name`, `dataset_config`, `dataset_specs`, `seed`, and `size`. `BrowserGymEnvironment` can choose a benchmark and task. `Tbench2Environment` can resolve tasks by task ID or path, even downloading a repo cache if needed. `GitTaskEnvironment` supports task-specific base repo states. `REPLEnvironment` can accept context, task prompt, expected answer, recursion depth, and model parameters at reset. `FinQAEnvironment` iterates over a question bank with real data-backed tools.
|
| 99 |
-
|
| 100 |
-
Your environment has three tasks, but they are not truly different environments. They are the same tickets with a different subset of fields exposed through `allowed_fields`. That is a very weak notion of task diversity. Task difficulty is not created by different data generating processes, different hidden state, different workflows, or different action surfaces. It is created by output dimensionality alone.
|
| 101 |
-
|
| 102 |
-
That means the easy, medium, and hard tasks are less like three tasks and more like one task with three scoring schemas.
|
| 103 |
-
|
| 104 |
-
### 6. They take concurrency and runtime isolation seriously
|
| 105 |
-
|
| 106 |
-
Several reference environments explicitly set `SUPPORTS_CONCURRENT_SESSIONS = True`, including `REPLEnvironment`, `Tbench2Environment`, `ReasoningGymEnvironment`, `MazeEnvironment`, and some others. The framework core in `http_server.py` is built around WebSocket sessions, session capacity, session info, session factories, and asynchronous handling. `MCPEnvironment` has explicit async and sync step paths because the framework authors ran into real event-loop and deadlock issues. `Tbench2DockerEnvironment` handles Docker-in-Docker by copying task directories into containers rather than assuming host bind mounts. `Calendar` builds database sessions per tenant. `GitTaskEnvironment` assumes isolated workspaces. `BrowserGymEnvironment` does cleanup of resources.
|
| 107 |
-
|
| 108 |
-
Your environment inherits some capability from OpenEnv, but your own code does not actually engage with that depth. The server is mostly a minimal `create_app()` call plus a `/tasks` endpoint. There is no custom metadata. No custom concurrency choices. No session isolation logic beyond what the base server gives you. No runtime cleanup concerns because the environment owns almost no external resources. That simplicity is pleasant, but it also means the project is not stress-tested as a real environment service.
|
| 109 |
-
|
| 110 |
-
### 7. They integrate grounded external systems or simulators
|
| 111 |
-
|
| 112 |
-
This is where the biggest credibility gap appears.
|
| 113 |
-
|
| 114 |
-
`FinQAEnvironment` grounds answers in company tables and SQL. `GitTaskEnvironment` grounds tasks in actual repositories. `Tbench2Environment` grounds them in actual shell execution and tests. `BrowserGymEnvironment` grounds tasks in web environments. `TextArenaEnvironment` grounds them in game engines. `ChessEnvironment` grounds them in a real board state. `Calendar` grounds them in a stateful API-backed application.
|
| 115 |
-
|
| 116 |
-
Your environment is grounded in a JSON dataset. That is fine for a prototype, but it is dramatically easier to shortcut. If the environment does not provide tools, latent objects, or stateful consequences, the fastest route to a good score is to learn the labeling policy over the text. That is exactly what your current `inference.py` is doing.
|
| 117 |
-
|
| 118 |
-
If you want to beat more ambitious projects, you need to force the agent to do more than map n-grams to labels.
|
| 119 |
-
|
| 120 |
-
## Deep Audit of Your Current Project
|
| 121 |
-
|
| 122 |
-
### Overall strengths before the critique
|
| 123 |
-
|
| 124 |
-
Before I get more surgical, it is worth naming what is already good:
|
| 125 |
-
|
| 126 |
-
- The codebase is small enough to understand quickly.
|
| 127 |
-
- The naming is clear and the domain is coherent.
|
| 128 |
-
- Pydantic validation is used correctly in the core models.
|
| 129 |
-
- The taxonomy in `vocabulary.py` is readable and operational.
|
| 130 |
-
- The environment is deterministic given a seed.
|
| 131 |
-
- The three-task ladder is a decent pedagogical introduction.
|
| 132 |
-
- The tests, while limited, are not absent.
|
| 133 |
-
- The dataset has at least some intentional ambiguity and follow-up cases.
|
| 134 |
-
|
| 135 |
-
So this is not a bad project. It is a project that has not yet converted a good domain into a hard benchmark.
|
| 136 |
-
|
| 137 |
-
### Domain model and task structure
|
| 138 |
-
|
| 139 |
-
`vocabulary.py` defines a clean label space:
|
| 140 |
-
|
| 141 |
-
- 9 issue types
|
| 142 |
-
- 4 priorities
|
| 143 |
-
- 6 assignment groups
|
| 144 |
-
- 5 resolution actions
|
| 145 |
-
- 3 task IDs
|
| 146 |
-
|
| 147 |
-
The mapping dictionaries immediately reveal one important structural weakness: assignment group is fully determined by issue type. Every issue type maps to exactly one assignment group. That means the “assignment_group” prediction in task 3 is not an independent reasoning problem. Once the model gets issue type right, assignment group is a lookup. That collapses the apparent complexity of the hardest task.
|
| 148 |
-
|
| 149 |
-
The same problem exists, though less absolutely, for resolution action. `ISSUE_TYPE_TO_RESOLUTION_ACTION` already maps every issue type to a default resolution action. The dataset confirms that several issue types only ever use one resolution action:
|
| 150 |
-
|
| 151 |
-
- `feature_request -> acknowledge`
|
| 152 |
-
- `general_inquiry -> acknowledge`
|
| 153 |
-
- `onboarding -> fulfill`
|
| 154 |
-
- `service_request -> assign`
|
| 155 |
-
- `spam_phishing -> ignore`
|
| 156 |
-
|
| 157 |
-
Only a subset of issue types vary their resolution action in practice. So task 3 looks like a four-field prediction problem, but much of it is structurally reducible to issue type plus a few keyword exceptions. That is not how hard triage environments should work if the goal is to test agentic reasoning.
|
| 158 |
-
|
| 159 |
-
`server/tasks.py` compounds this by defining difficulty purely as output field count:
|
| 160 |
-
|
| 161 |
-
- Task 1: issue type only
|
| 162 |
-
- Task 2: issue type plus priority
|
| 163 |
-
- Task 3: full routing
|
| 164 |
-
|
| 165 |
-
The ticket pool is the same across tasks. There is no task-specific curation, no task-family-specific observation, no different process constraints, and no different control surface. The only thing that changes is what the grader will read from the submitted action.
|
| 166 |
-
|
| 167 |
-
That means your easy-medium-hard ladder is mostly a scoring ladder, not an environment ladder.
|
| 168 |
-
|
| 169 |
-
### Observation and state design
|
| 170 |
-
|
| 171 |
-
`HelpdeskTicketObservation` contains:
|
| 172 |
-
|
| 173 |
-
- task metadata
|
| 174 |
-
- `allowed_fields`
|
| 175 |
-
- `current_ticket`
|
| 176 |
-
- queue counts
|
| 177 |
-
- history
|
| 178 |
-
|
| 179 |
-
`current_ticket` exposes only:
|
| 180 |
-
|
| 181 |
-
- `ticket_id`
|
| 182 |
-
- `title`
|
| 183 |
-
- `requester`
|
| 184 |
-
- `description`
|
| 185 |
-
|
| 186 |
-
This is too little for a benchmark that wants to simulate real helpdesk operations, and it is oddly little given what your data already stores. `HelpdeskTicketRecord` also includes:
|
| 187 |
-
|
| 188 |
-
- `ambiguity_note`
|
| 189 |
-
- `related_ticket_id`
|
| 190 |
-
|
| 191 |
-
Those two fields are exactly the sort of structured hints that could turn this from flat classification into contextual triage. Yet `_build_observation()` discards them. That means the dataset contains richer structure than the observation contract.
|
| 192 |
-
|
| 193 |
-
The state is also minimal:
|
| 194 |
-
|
| 195 |
-
- `current_task_id`
|
| 196 |
-
- `seed`
|
| 197 |
-
- `queue_ticket_ids`
|
| 198 |
-
- `current_ticket_index`
|
| 199 |
-
- `per_ticket_scores`
|
| 200 |
-
- `total_reward`
|
| 201 |
-
|
| 202 |
-
This is enough for bookkeeping, but not enough for operational simulation. There is no notion of:
|
| 203 |
-
|
| 204 |
-
- queue ordering rationale
|
| 205 |
-
- account status
|
| 206 |
-
- customer tier
|
| 207 |
-
- outage context
|
| 208 |
-
- prior communication attempts
|
| 209 |
-
- internal notes
|
| 210 |
-
- pending escalations
|
| 211 |
-
- workload or resolver capacity
|
| 212 |
-
- elapsed time or SLA timers
|
| 213 |
-
- deduplication chains
|
| 214 |
-
- partial investigation state
|
| 215 |
-
|
| 216 |
-
The result is that the environment never becomes more informative or more demanding as the episode progresses. The state is a score ledger, not a world model.
|
| 217 |
-
|
| 218 |
-
Compare that with the stronger references:
|
| 219 |
-
|
| 220 |
-
- `BrowserGymState` tracks benchmark, task, URL, goal, max steps, cumulative reward.
|
| 221 |
-
- `REPLState` tracks context, prompt, iteration, namespace keys, final answer, total execution time.
|
| 222 |
-
- `Tbench2State` tracks task, session, command history, terminal readiness, last output.
|
| 223 |
-
- `TextArenaState` tracks turn, raw state, last reward, last info, environment identity.
|
| 224 |
-
- `FinQAState` tracks current question, company, ground truth, question ID.
|
| 225 |
-
|
| 226 |
-
Those states are not just counters. They represent the environment’s evolving operational memory. Yours mostly does not.
|
| 227 |
-
|
| 228 |
-
### Environment lifecycle
|
| 229 |
-
|
| 230 |
-
`HelpdeskTicketRoutingEnvironment.reset()` is straightforward:
|
| 231 |
-
|
| 232 |
-
- coerce `seed`
|
| 233 |
-
- get task definition
|
| 234 |
-
- seed RNG
|
| 235 |
-
- sample a queue size from 3 to 5
|
| 236 |
-
- sample that many tickets from the fixed dataset
|
| 237 |
-
- initialize state
|
| 238 |
-
- return the first observation
|
| 239 |
-
|
| 240 |
-
`step()`:
|
| 241 |
-
|
| 242 |
-
- validates reset happened
|
| 243 |
-
- grades action against current ticket
|
| 244 |
-
- computes reward
|
| 245 |
-
- advances to next ticket
|
| 246 |
-
- if done, computes trajectory reward
|
| 247 |
-
- otherwise returns immediate step reward
|
| 248 |
-
|
| 249 |
-
This is tidy. It is also shallow.
|
| 250 |
-
|
| 251 |
-
There is no environment mutation other than index movement. No internal state changes based on the chosen action. No branching. No action-dependent future ticket behavior. No queue reprioritization. No retries. No note writing. No escalation backlog. No “wrong earlier action causes downstream penalty.” The only environment response is score feedback.
|
| 252 |
-
|
| 253 |
-
A benchmark like this can still be useful, but it sits much closer to supervised evaluation than to agentic interaction. That becomes a competitive problem when the reference set includes environments where actions actually transform the world.
|
| 254 |
-
|
| 255 |
-
One subtle but important weakness is that `step()` does not enforce the task contract tightly. `HelpdeskTicketAction` allows all four fields to be present on any task, and `grade_action()` simply reads the fields relevant to the chosen `task_id`. Extra fields are ignored. That means the environment tells the agent “allowed_fields are X,” but it does not enforce “only X may be submitted.” It is not catastrophic, but it reflects a looser benchmark contract than the environment surface suggests.
|
| 256 |
-
|
| 257 |
-
### Grader and reward design
|
| 258 |
-
|
| 259 |
-
`server/grader.py` is the most benchmark-defining file in the project, and it currently underdelivers relative to its importance.
|
| 260 |
-
|
| 261 |
-
What is good:
|
| 262 |
-
|
| 263 |
-
- it has partial credit for issue-type confusions
|
| 264 |
-
- it has proximity-based scoring for priority
|
| 265 |
-
- task weights sum to 1
|
| 266 |
-
- it is deterministic
|
| 267 |
-
- it is easy to reason about
|
| 268 |
-
|
| 269 |
-
What is weak:
|
| 270 |
-
|
| 271 |
-
- the similarity tables are static, narrow, and handcrafted
|
| 272 |
-
- assignment group and resolution action are exact-match only even though the environment does not expose enough context to make some distinctions fully grounded
|
| 273 |
-
- there is no calibration check on over-escalation
|
| 274 |
-
- there is no queue-level objective
|
| 275 |
-
- there is no policy compliance signal
|
| 276 |
-
- there is no explanation consistency
|
| 277 |
-
- there is no distinction between “reasonable but conservative” and “reckless but lucky”
|
| 278 |
-
|
| 279 |
-
The biggest conceptual weakness is that the reward is local and label-centric. A strong helpdesk environment should care about operational behavior, not just answer key overlap.
|
| 280 |
-
|
| 281 |
-
For example, suppose two actions both get the final resolution action wrong:
|
| 282 |
-
|
| 283 |
-
- one escalates a low-risk general inquiry to security
|
| 284 |
-
- one acknowledges a critical account lockout without escalation
|
| 285 |
-
|
| 286 |
-
Today those mistakes mostly show up as missed fields in a flat weighted sum. But in real operations they are qualitatively different failures. One wastes specialist capacity. The other is a dangerous underreaction. A competitive benchmark should encode that asymmetry.
|
| 287 |
-
|
| 288 |
-
There is also a concrete implementation weakness in `compute_trajectory_reward()`. It computes:
|
| 289 |
-
|
| 290 |
-
- average per-ticket score
|
| 291 |
-
- minus `0.03 * overshoot`
|
| 292 |
-
|
| 293 |
-
But `overshoot = max(0, steps_taken - queue_size)`, and the environment ends the episode when the current ticket index reaches queue length. After that point, further stepping raises an error. So in the normal execution path, overshoot is effectively always zero. The code suggests the environment cares about extra wasted steps, but the environment does not actually permit them. That means part of the trajectory logic is decorative rather than active.
|
| 294 |
-
|
| 295 |
-
In strong benchmarks, reward code usually reveals the benchmark’s philosophy. In your project, the reward code mostly reveals the current label schema.
|
| 296 |
-
|
| 297 |
-
### Dataset design
|
| 298 |
-
|
| 299 |
-
`data/dataset.json` currently holds 45 tickets. The class distribution is not terrible for a prototype, but it is still small:
|
| 300 |
-
|
| 301 |
-
- `application_support`: 9
|
| 302 |
-
- `billing_license`: 7
|
| 303 |
-
- `service_request`: 6
|
| 304 |
-
- `security_compliance`: 5
|
| 305 |
-
- `spam_phishing`: 5
|
| 306 |
-
- `identity_access`: 4
|
| 307 |
-
- `onboarding`: 4
|
| 308 |
-
- `general_inquiry`: 3
|
| 309 |
-
- `feature_request`: 2
|
| 310 |
-
|
| 311 |
-
That is a tiny dataset for any benchmark that hopes to resist memorization or heuristic overfitting. The especially small classes are a concern. A benchmark with 2 feature requests and 3 general inquiries is not meaningfully testing generalization in those categories.
|
| 312 |
-
|
| 313 |
-
The priority distribution is also limited:
|
| 314 |
-
|
| 315 |
-
- critical: 9
|
| 316 |
-
- high: 15
|
| 317 |
-
- medium: 12
|
| 318 |
-
- low: 9
|
| 319 |
-
|
| 320 |
-
That is balanced enough to be usable, but not rich enough to encode the true structure of priority assignment. There is no obvious representation of customer segment, contractual urgency, outage blast radius, legal exposure, dependency graphs, or business calendar sensitivity. Priority is largely being inferred from words in the title and description, which is exactly what a heuristic baseline will exploit.
|
| 321 |
-
|
| 322 |
-
The dataset does have four ambiguous records and three follow-up linked records. That is good. But because the environment does not structurally expose `ambiguity_note` or `related_ticket_id`, those richer cases do not actually become richer environment mechanics. They mostly remain hints for the benchmark designer, not tools for the agent.
|
| 323 |
-
|
| 324 |
-
The follow-up handling is especially underused. Tickets like `ticket-038` and `ticket-045` clearly encode longitudinal customer frustration and repeated failure, which should change triage behavior. But the environment treats them like standalone text blobs. There is no action to inspect previous tickets. No thread retrieval. No stateful consequence from unresolved history. The environment has the seed of longitudinal realism and then does not build on it.
|
| 325 |
-
|
| 326 |
-
There is also no train/eval split, no hidden split, no procedural generation, no adversarial generation, and no OOD slice. The same fixed dataset defines the universe. That is fine for unit tests. It is weak for a benchmark intended to compete.
|
| 327 |
-
|
| 328 |
-
### Inference baseline and benchmark leakage
|
| 329 |
-
|
| 330 |
-
`inference.py` is more important than it may look, because it tells you how easy the benchmark is to shortcut.
|
| 331 |
-
|
| 332 |
-
The heuristic path:
|
| 333 |
-
|
| 334 |
-
- scans ticket text for fixed issue-type keywords in fixed order
|
| 335 |
-
- assigns priority from small keyword buckets
|
| 336 |
-
- assigns resolution action from issue type plus a few escalation and fulfillment keywords
|
| 337 |
-
- assigns assignment group from issue type mapping
|
| 338 |
-
|
| 339 |
-
That baseline is not merely a harmless example. It is a diagnostic of benchmark leakage. The easier it is to hand-author a ruleset that tracks your label policy, the less benchmark headroom you have.
|
| 340 |
-
|
| 341 |
-
And in this codebase, the baseline is not just simple. It is tightly coupled to the environment’s ontology:
|
| 342 |
-
|
| 343 |
-
- it uses the exact taxonomy constants
|
| 344 |
-
- it exploits the one-to-one issue-to-assignment mapping
|
| 345 |
-
- it exploits mostly deterministic issue-to-resolution defaults
|
| 346 |
-
- it assumes priority is keyword-addressable from the visible text alone
|
| 347 |
-
|
| 348 |
-
That means the benchmark currently invites ontology-driven shortcutting.
|
| 349 |
-
|
| 350 |
-
There is an even more concerning signal. The tests describe a heuristic baseline around `0.9400`, but a local code-faithful replay of the rule ordering in PowerShell over the full `data/dataset.json` gives a much weaker picture:
|
| 351 |
-
|
| 352 |
-
- issue type exact accuracy: about `0.7333`
|
| 353 |
-
- priority exact accuracy: about `0.3778`
|
| 354 |
-
- assignment exact accuracy: about `0.7333`
|
| 355 |
-
- resolution exact accuracy: about `0.6889`
|
| 356 |
-
- full task-3 exact match: about `0.2444`
|
| 357 |
-
- approximate weighted average score across tasks 1, 2, and 3: about `0.7344`
|
| 358 |
-
|
| 359 |
-
The exact number is less important than what it implies: the benchmark narrative about heuristic strength and the actual rule behavior appear out of sync. That can happen for several reasons:
|
| 360 |
-
|
| 361 |
-
- the tests are stale relative to current data
|
| 362 |
-
- the claimed baseline was measured on sampled queues rather than the whole dataset
|
| 363 |
-
- the heuristic ordering now creates more collisions than expected
|
| 364 |
-
- the benchmark evolved without a full-baseline recomputation
|
| 365 |
-
|
| 366 |
-
Whatever the cause, it is a warning sign. When benchmark claims and benchmark code diverge, trust in the environment falls.
|
| 367 |
-
|
| 368 |
-
### Test strategy
|
| 369 |
-
|
| 370 |
-
Your project has six test files. That is good relative to many small hackathon projects. But the content of the tests matters more than the count.
|
| 371 |
-
|
| 372 |
-
The most important limitation is that multiple tests stub the OpenEnv types, interfaces, or `create_app()` implementation rather than exercising the real installed framework. `tests/openenv_test_stubs.py` injects fake `openenv.core.env_server.types`. `tests/test_environment_smoke.py` and `tests/test_api_integration.py` patch in a fake `Environment` base class. `tests/test_api_integration.py` also installs a stub `create_app` that returns a small FastAPI app with simplified routes.
|
| 373 |
-
|
| 374 |
-
That means much of the test suite verifies your code against a locally simulated OpenEnv contract, not against the actual `openenv-core` dependency declared in `pyproject.toml`.
|
| 375 |
-
|
| 376 |
-
This is a big competitive weakness because the reference repository’s core is full of behavior that your test harness never touches:
|
| 377 |
-
|
| 378 |
-
- WebSocket `/ws` interactions
|
| 379 |
-
- session handling
|
| 380 |
-
- concurrency settings
|
| 381 |
-
- serialization edge cases
|
| 382 |
-
- metadata and schema endpoints
|
| 383 |
-
- MCP endpoints
|
| 384 |
-
- async step paths
|
| 385 |
-
- actual `EnvClient` protocol semantics
|
| 386 |
-
|
| 387 |
-
Your tests mostly prove that the environment behaves under your own simplified assumptions. That is useful, but it is not the same as proving robust OpenEnv integration.
|
| 388 |
-
|
| 389 |
-
The other limitation is that the tests are mostly shallow-contract tests:
|
| 390 |
-
|
| 391 |
-
- reset returns something valid
|
| 392 |
-
- step increments counts
|
| 393 |
-
- reward is in `[0, 1]`
|
| 394 |
-
- task IDs are present
|
| 395 |
-
- heuristic episodes do not error
|
| 396 |
-
|
| 397 |
-
Those are necessary. They are not sufficient for a competitive benchmark.
|
| 398 |
-
|
| 399 |
-
What is missing includes:
|
| 400 |
-
|
| 401 |
-
- real WebSocket end-to-end tests
|
| 402 |
-
- invalid action contract tests with actual framework validation
|
| 403 |
-
- tests for extra fields on restricted tasks
|
| 404 |
-
- concurrency tests
|
| 405 |
-
- seed reproducibility tests across actual server sessions
|
| 406 |
-
- golden regression tests on full-dataset benchmark score
|
| 407 |
-
- hidden/eval split integrity tests
|
| 408 |
-
- tests for ambiguity and follow-up handling
|
| 409 |
-
- tests that verify the environment is hard in the intended way, not just runnable
|
| 410 |
-
|
| 411 |
-
In short, the current test suite validates operability, not benchmark integrity.
|
| 412 |
-
|
| 413 |
-
## Critical Gaps That Matter Most
|
| 414 |
-
|
| 415 |
-
This section is the most actionable part of the report. If the goal is to beat stronger reference projects, these are the gaps that matter.
|
| 416 |
-
|
| 417 |
-
### Gap 1: The project is benchmarked as an environment, but designed as a classifier
|
| 418 |
-
|
| 419 |
-
The core problem is conceptual. Your code uses the OpenEnv interface, but the actual task shape is still mostly multi-label classification over short ticket text.
|
| 420 |
-
|
| 421 |
-
The better reference environments are hard because the agent has to interact:
|
| 422 |
-
|
| 423 |
-
- `BrowserGymEnvironment` asks the agent to act in a browser.
|
| 424 |
-
- `FinQAEnvironment` asks the agent to inspect tools and query structured data.
|
| 425 |
-
- `REPLEnvironment` asks the agent to iteratively execute code and decide when to finalize.
|
| 426 |
-
- `Tbench2Environment` asks the agent to manipulate a terminal workspace and then survive evaluation.
|
| 427 |
-
- `TextArenaEnvironment` asks the agent to play through game turns.
|
| 428 |
-
|
| 429 |
-
Your environment asks the agent to emit labels. Even when multiple tickets appear in a queue, the agent is still doing the same one-shot operation repeatedly. It is not exploring, not investigating, not mutating meaningful state, not managing resources, and not making action-sequence tradeoffs.
|
| 430 |
-
|
| 431 |
-
That difference is bigger than it looks. Once the benchmark is classifier-shaped, the fastest route to good performance is classifier-shaped too. The environment does not force the agent to behave like an operator. It only asks it to sound like one.
|
| 432 |
-
|
| 433 |
-
That is why the next leap must be architectural, not cosmetic.
|
| 434 |
-
|
| 435 |
-
### Gap 2: The hardest task is structurally easier than it claims
|
| 436 |
-
|
| 437 |
-
Task 3 appears to be a four-field routing task, but the ontology collapses much of the difficulty.
|
| 438 |
-
|
| 439 |
-
`ISSUE_TYPE_TO_ASSIGNMENT_GROUP` is one-to-one. If the agent gets issue type right, assignment group is already implied. That means one quarter of the task-3 score is mostly a lookup rather than a separate judgment call.
|
| 440 |
-
|
| 441 |
-
Resolution action is not fully deterministic, but it is still heavily compressed by issue type defaults. Several issue types have only one action in practice across the dataset. Others vary under small numbers of recognizable phrases such as legal threat, follow-up pressure, or explicit request wording.
|
| 442 |
-
|
| 443 |
-
So the “hard” task is closer to:
|
| 444 |
-
|
| 445 |
-
- infer issue type
|
| 446 |
-
- infer urgency from a few cues
|
| 447 |
-
- apply one deterministic mapping
|
| 448 |
-
- apply one mostly deterministic mapping with a few exceptions
|
| 449 |
-
|
| 450 |
-
That is not trivial, but it is much less rich than real service-desk routing. Real hard cases exist when the same visible ticket text can map to different actions depending on hidden context such as account tier, live incident status, prior history, or internal policy. Your environment does not currently model those cases.
|
| 451 |
-
|
| 452 |
-
### Gap 3: The environment underuses the best parts of its own data
|
| 453 |
-
|
| 454 |
-
Your dataset is more interesting than your observation contract.
|
| 455 |
-
|
| 456 |
-
`HelpdeskTicketRecord` contains `ambiguity_note` and `related_ticket_id`. Those are exactly the kinds of fields that could turn this into a stronger environment:
|
| 457 |
-
|
| 458 |
-
- ambiguity makes decisions less keyword-deterministic
|
| 459 |
-
- related ticket IDs create thread continuity
|
| 460 |
-
- follow-ups create escalation pressure and temporal realism
|
| 461 |
-
|
| 462 |
-
But `_build_observation()` discards them and only exposes the basic ticket text fields.
|
| 463 |
-
|
| 464 |
-
That has two consequences:
|
| 465 |
-
|
| 466 |
-
First, the richer authored structure is lost to the agent. Second, the benchmark stops short of the very complexity the dataset author was already beginning to encode.
|
| 467 |
-
|
| 468 |
-
This is one of the clearest signs that the current project is a first version. The seeds of a deeper environment are already present in the data model. The runtime contract just does not use them.
|
| 469 |
-
|
| 470 |
-
### Gap 4: There is no investigation loop
|
| 471 |
-
|
| 472 |
-
In real helpdesk operations, the visible complaint is rarely the whole decision problem.
|
| 473 |
-
|
| 474 |
-
An operator often needs to know:
|
| 475 |
-
|
| 476 |
-
- whether the requester is on an enterprise contract
|
| 477 |
-
- whether the problem aligns with an active outage
|
| 478 |
-
- whether the user is an admin
|
| 479 |
-
- whether prior tickets already established a root cause
|
| 480 |
-
- whether a security signal exists on the account
|
| 481 |
-
- whether a compliance deadline is legally binding
|
| 482 |
-
- whether the request is actually a duplicate
|
| 483 |
-
|
| 484 |
-
Your environment has no tool loop for this. The agent sees a title, requester, and description, then is expected to decide everything directly.
|
| 485 |
-
|
| 486 |
-
That makes the environment much easier to brute-force and much less realistic than the domains represented by the best reference projects. `FinQAEnvironment` does not ask the model to guess answers from wording alone; it gives tools. `GitTaskEnvironment` gives a repo. `Tbench2Environment` gives a terminal. `BrowserGymEnvironment` gives a browser. Your helpdesk environment gives a paragraph.
|
| 487 |
-
|
| 488 |
-
The fastest path to a stronger benchmark is to add internal tools and make the hardest scenarios impossible to solve reliably without using them.
|
| 489 |
-
|
| 490 |
-
### Gap 5: There is almost no internal economics
|
| 491 |
-
|
| 492 |
-
A good environment usually has some notion of tradeoff or cost even if it is not expressed as money.
|
| 493 |
-
|
| 494 |
-
In your environment:
|
| 495 |
-
|
| 496 |
-
- there is no time budget
|
| 497 |
-
- there is no backlog pressure
|
| 498 |
-
- there is no penalty for over-escalating except field mismatch
|
| 499 |
-
- there is no cost for routing everything to the safest specialist
|
| 500 |
-
- there is no consequence for queue ordering
|
| 501 |
-
- there is no tension between fast response and careful investigation
|
| 502 |
-
|
| 503 |
-
The queue exists, but it is not an economy. It is just a list.
|
| 504 |
-
|
| 505 |
-
That means the environment cannot really test operational judgment. It can only test whether the final labels match the benchmark designer’s answer key. Stronger environments force decisions under constraints. Your current implementation mostly scores unconstrained annotation.
|
| 506 |
-
|
| 507 |
-
### Gap 6: The reward story is thinner than the benchmark story
|
| 508 |
-
|
| 509 |
-
`grade_action()` is neat and deterministic, but it still mainly scores label overlap. It does not score operator quality.
|
| 510 |
-
|
| 511 |
-
There is no difference between:
|
| 512 |
-
|
| 513 |
-
- a cautious but slightly conservative routing choice
|
| 514 |
-
- a reckless underreaction that happens to get some partial credit
|
| 515 |
-
- an unnecessary escalation that wastes the security team
|
| 516 |
-
- a smart intermediate step that gathers evidence before final routing
|
| 517 |
-
|
| 518 |
-
Those distinctions do not exist because the action surface does not allow them and the reward design does not look for them.
|
| 519 |
-
|
| 520 |
-
There is also a direct implementation issue: `compute_trajectory_reward()` includes an overshoot penalty, but because the environment ends when the queue is exhausted and refuses later steps, overshoot does not really happen in the normal path. So part of the trajectory logic looks more meaningful than it actually is.
|
| 521 |
-
|
| 522 |
-
When reward code contains dead or decorative logic, trust in the benchmark drops.
|
| 523 |
-
|
| 524 |
-
### Gap 7: The current benchmark is highly vulnerable to ontology memorization
|
| 525 |
-
|
| 526 |
-
The more the task can be solved by memorizing your ontology and keyword policy, the lower the ceiling of the benchmark.
|
| 527 |
-
|
| 528 |
-
Right now the environment is vulnerable because:
|
| 529 |
-
|
| 530 |
-
- the dataset is small
|
| 531 |
-
- the label space is public and fixed
|
| 532 |
-
- some output fields are deterministic functions of others
|
| 533 |
-
- the observation is a short text blob
|
| 534 |
-
- the heuristic baseline directly encodes the ontology
|
| 535 |
-
- there is no hidden split or generator-based variation
|
| 536 |
-
|
| 537 |
-
The current inference script is a warning sign here. It is not just a demo baseline. It is evidence that a carefully chosen keyword system can cover a large fraction of the problem structure because the problem structure is currently that compressible.
|
| 538 |
-
|
| 539 |
-
If you want to build something harder to game, the benchmark must stop being reducible to a keyword policy plus a few ontology tables.
|
| 540 |
-
|
| 541 |
-
### Gap 8: The tests are too synthetic for the actual risk profile
|
| 542 |
-
|
| 543 |
-
The test suite checks that the environment is runnable. It does not yet prove that the benchmark is trustworthy.
|
| 544 |
-
|
| 545 |
-
The biggest limitation is the heavy use of stubs around the OpenEnv dependency boundary. Several tests replace the real OpenEnv types, interfaces, or `create_app()` implementation. That helps local testability, but it means the suite is not validating actual WebSocket session behavior, actual framework serialization, actual schema generation, or actual concurrency handling.
|
| 546 |
-
|
| 547 |
-
That is a serious gap if the environment is meant to compete with stronger projects. Reference environments are embedded in a framework that supports:
|
| 548 |
-
|
| 549 |
-
- WebSocket sessions
|
| 550 |
-
- session capacity and session info
|
| 551 |
-
- schema endpoints
|
| 552 |
-
- metadata endpoints
|
| 553 |
-
- MCP endpoints
|
| 554 |
-
- sync and async execution paths
|
| 555 |
-
|
| 556 |
-
Your current tests mostly validate business logic under a simplified local harness. That is still useful. It is just not enough to prove benchmark robustness.
|
| 557 |
-
|
| 558 |
-
There is also no strong integrity suite around the benchmark itself. Missing pieces include:
|
| 559 |
-
|
| 560 |
-
- full-dataset regression scoring
|
| 561 |
-
- hidden split integrity
|
| 562 |
-
- adversarial edge-case suites
|
| 563 |
-
- benchmark versioning checks
|
| 564 |
-
- ambiguity and follow-up behavior tests
|
| 565 |
-
- contract tests that verify the hard task is genuinely hard in the intended way
|
| 566 |
-
|
| 567 |
-
If you want the project to be taken seriously, the environment and the benchmark need separate test surfaces.
|
| 568 |
-
|
| 569 |
-
### Gap 9: The benchmark narrative and executable reality are drifting apart
|
| 570 |
-
|
| 571 |
-
A benchmark becomes fragile when people cannot tell which number to trust.
|
| 572 |
-
|
| 573 |
-
Your tests imply a strong heuristic baseline. The environment code and local replay of the actual heuristic rules over the dataset suggest a weaker story. That discrepancy may be caused by stale thresholds, changed data, queue sampling effects, or unrefreshed benchmark assumptions. Whatever the reason, it is not a small issue.
|
| 574 |
-
|
| 575 |
-
Strong benchmarks need executable answers to simple questions:
|
| 576 |
-
|
| 577 |
-
- what is the official baseline?
|
| 578 |
-
- how is it measured?
|
| 579 |
-
- on which split?
|
| 580 |
-
- with what seeds?
|
| 581 |
-
- on which version of the data?
|
| 582 |
-
- under which scenario families?
|
| 583 |
-
|
| 584 |
-
Right now those answers are not fully stabilized in code. The result is that the benchmark is harder to trust than it should be.
|
| 585 |
-
|
| 586 |
-
That may sound administrative, but it is actually competitive. A benchmark that feels ad hoc will lose to a benchmark that feels governed, even if both are interesting.
|
| 587 |
-
|
| 588 |
-
### Gap 10: The project does not yet have a competitive moat
|
| 589 |
-
|
| 590 |
-
The strongest environments in the reference set each have a clear identity:
|
| 591 |
-
|
| 592 |
-
- BrowserGym: browser-native multimodal interaction
|
| 593 |
-
- FinQA: tool-mediated reasoning over structured finance data
|
| 594 |
-
- REPL: iterative code execution and rubric-based finalization
|
| 595 |
-
- TBench2: terminal tasks grounded by executable evaluation
|
| 596 |
-
- Calendar: stateful tool ecosystem over application APIs
|
| 597 |
-
- Chess: adversarial long-horizon board play
|
| 598 |
-
|
| 599 |
-
Your current identity is “helpdesk routing from short ticket text.” That is useful, but not yet distinctive enough to dominate.
|
| 600 |
-
|
| 601 |
-
The domain itself can support a much stronger identity:
|
| 602 |
-
|
| 603 |
-
- service desk triage under partial observability
|
| 604 |
-
- enterprise support operations with tool use and policy constraints
|
| 605 |
-
- multi-ticket queue management under SLA and escalation economics
|
| 606 |
-
|
| 607 |
-
That is the moat you should build. The domain is good enough. The current benchmark shape is not yet deep enough to own it.
|
| 608 |
-
|
| 609 |
-
## What Specific Reference Environments Teach You
|
| 610 |
-
|
| 611 |
-
### BrowserGym: rich observations create real decision space
|
| 612 |
-
|
| 613 |
-
`BrowserGymObservation` includes text, URL, optional screenshot, goal, accessibility tree text, pruned HTML, error strings, and action-error flags. `BrowserGymEnvironment` carefully converts raw benchmark objects into those modalities and preserves additional metadata while filtering large raw fields.
|
| 614 |
-
|
| 615 |
-
The lesson is not “copy browser features.” The lesson is that an observation should support several reasoning strategies at once. Strong environments do not force everything through one narrow channel if the domain can naturally expose more.
|
| 616 |
-
|
| 617 |
-
Your helpdesk environment should likely move from a plain ticket view to a mixed observation view that includes structured context, queue state, optional note previews, and pointers to retrievable evidence. A stronger observation contract makes the environment harder to solve with surface heuristics and easier to use for real agent development.
|
| 618 |
-
|
| 619 |
-
### FinQA: tool use transforms a QA task into an environment
|
| 620 |
-
|
| 621 |
-
`FinQAEnvironment` is one of the most relevant reference environments for your redesign. It takes a question-answering domain that could have been implemented as “read prompt, output answer” and instead builds a tool-mediated workflow:
|
| 622 |
-
|
| 623 |
-
- list tools
|
| 624 |
-
- inspect table descriptions
|
| 625 |
-
- inspect table metadata
|
| 626 |
-
- run SQL queries
|
| 627 |
-
- submit final answer
|
| 628 |
-
|
| 629 |
-
The ground truth is hidden. The agent has to do work. The reward system then normalizes answer formats so the benchmark is measuring reasoning rather than answer string quirks.
|
| 630 |
-
|
| 631 |
-
Your helpdesk project should follow that pattern. The hard task should not be “read ticket and guess routing.” It should be “use service desk tools to investigate and then submit routing.” That would immediately raise the benchmark ceiling.
|
| 632 |
-
|
| 633 |
-
### REPL: process reward and outcome reward should be separate
|
| 634 |
-
|
| 635 |
-
`REPLEnvironment` is instructive because it distinguishes execution quality from final answer quality. The environment tracks iterations, namespace state, execution results, and finalization patterns. The rubric layer then separates outcome reward from process reward.
|
| 636 |
-
|
| 637 |
-
That is directly applicable to helpdesk operations. A strong service desk environment should separately measure:
|
| 638 |
-
|
| 639 |
-
- whether the final routing/action was correct
|
| 640 |
-
- whether the agent investigated responsibly
|
| 641 |
-
- whether the agent made avoidable operational mistakes
|
| 642 |
-
- whether the agent wasted steps or overused escalation
|
| 643 |
-
|
| 644 |
-
Without that split, you cannot tell the difference between good operations and lucky guessing.
|
| 645 |
-
|
| 646 |
-
### TBench2: grounded evaluation is a moat
|
| 647 |
-
|
| 648 |
-
`Tbench2Environment` is powerful because success is not a declared label. It is an executable check. The agent can manipulate a workspace and then call `evaluate`, which runs tests. That style of evaluation is very hard to fake and very easy to defend.
|
| 649 |
-
|
| 650 |
-
Helpdesk will not use pytest in the same way, but the principle transfers cleanly. A stronger helpdesk benchmark should evaluate against hidden operational truth and downstream effects, not just a visible label table. If the environment can compute whether the chosen action violated SLA policy, ignored an active incident, or misrouted a duplicate chain, then benchmark credibility goes up immediately.
|
| 651 |
-
|
| 652 |
-
### Calendar MCP: tool ecosystems can scale if the boundary is clean
|
| 653 |
-
|
| 654 |
-
The Calendar stack shows how a domain can become more realistic without exploding the action schema. The environment exposes tools, request context, user context, and database-backed state. Tool handlers are generic where possible and dynamic routing does a lot of the heavy lifting.
|
| 655 |
-
|
| 656 |
-
For your domain, that is a strong hint that helpdesk should probably become tool-centric. Instead of stuffing everything into one giant action object, expose a small set of operational tools. This will scale better, feel more realistic, and let you design harder scenarios without turning the action model into a kitchen sink.
|
| 657 |
-
|
| 658 |
-
### GitTask: reproducible scenario resets matter
|
| 659 |
-
|
| 660 |
-
`GitTaskEnvironment` is not the most feature-rich environment in the set, but it gets one important thing right: reproducible task state. Reset means something concrete. The environment can put you back into a known repo state efficiently.
|
| 661 |
-
|
| 662 |
-
You need the same discipline in scenario design. Instead of sampling any 3 to 5 tickets from one public pool, define reproducible episode families:
|
| 663 |
-
|
| 664 |
-
- urgent outage follow-up
|
| 665 |
-
- mixed billing queue
|
| 666 |
-
- false-positive security scare
|
| 667 |
-
- onboarding plus access control bundle
|
| 668 |
-
- executive escalation chain
|
| 669 |
-
|
| 670 |
-
Once episodes become scenario-driven rather than ticket-sampled, the benchmark will feel much more intentional.
|
| 671 |
-
|
| 672 |
-
### Chess and TextArena: delayed reward and auxiliary signals are valuable
|
| 673 |
-
|
| 674 |
-
`ChessEnvironment` plus `ChessWinLossRubric` shows how delayed reward can be modeled cleanly across a trajectory. `TextArenaEnvironment` plus its reward providers shows how auxiliary signals can coexist with the main reward without replacing it. Those patterns matter because helpdesk operations are not fully one-shot even when the final routing choice is what gets judged.
|
| 675 |
-
|
| 676 |
-
In a stronger version of your environment, you could preserve a main final reward while also emitting auxiliary channels such as:
|
| 677 |
-
|
| 678 |
-
- evidence quality
|
| 679 |
-
- duplicate-handling quality
|
| 680 |
-
- escalation efficiency
|
| 681 |
-
- SLA awareness
|
| 682 |
-
- customer experience quality
|
| 683 |
-
- policy compliance
|
| 684 |
-
|
| 685 |
-
Even if you keep one main scalar reward for training or evaluation, those auxiliary signals would make the benchmark much more diagnosable.
|
| 686 |
-
|
| 687 |
-
### ReasoningGym and Maze: simplicity is fine if it is honest
|
| 688 |
-
|
| 689 |
-
`ReasoningGymEnvironment` is a simple parameterized single-step environment. `MazeEnvironment` is a simple gridworld. Neither one pretends to be deeper than it is. That honesty is useful as a design lesson.
|
| 690 |
-
|
| 691 |
-
If you want to keep a light version of your current project, that is perfectly reasonable. But then it should be presented as a starter triage benchmark, not as a fully realized agentic operations environment. If you want to claim higher competitive value, the environment itself needs to support that claim with deeper mechanics.
|
| 692 |
-
|
| 693 |
-
## A Concrete Design for Beating the Stronger Projects
|
| 694 |
-
|
| 695 |
-
The right goal is not to imitate the broadest reference project. The right goal is to go much deeper in one domain you already own.
|
| 696 |
-
|
| 697 |
-
You do not need to out-BrowserGym BrowserGym. You do not need to out-TBench2 TBench2. You need to become clearly better at service desk operations simulation than the reference set is today.
|
| 698 |
-
|
| 699 |
-
### North star: build a service operations simulator
|
| 700 |
-
|
| 701 |
-
The strongest future version of this project looks more like an IT service desk simulator than a label prediction benchmark.
|
| 702 |
-
|
| 703 |
-
Core properties of that simulator should be:
|
| 704 |
-
|
| 705 |
-
- partially observed ticket and account state
|
| 706 |
-
- internal tools for investigation
|
| 707 |
-
- scenario families rather than one static pool
|
| 708 |
-
- multi-step resolution workflows
|
| 709 |
-
- queue-level tradeoffs
|
| 710 |
-
- policy-aware reward
|
| 711 |
-
- hidden evaluation truth
|
| 712 |
-
|
| 713 |
-
If you hit those properties, you will not just be polishing the current environment. You will be changing the category of the benchmark.
|
| 714 |
-
|
| 715 |
-
### Proposed visible entities
|
| 716 |
-
|
| 717 |
-
The agent should see richer but still realistic objects, for example:
|
| 718 |
-
|
| 719 |
-
- ticket thread summary
|
| 720 |
-
- current requester details
|
| 721 |
-
- account/org summary
|
| 722 |
-
- queue overview
|
| 723 |
-
- recent internal note previews
|
| 724 |
-
- live incident banner or incident tool access
|
| 725 |
-
- available tools
|
| 726 |
-
- allowed actions
|
| 727 |
-
- task budget and SLA hints
|
| 728 |
-
|
| 729 |
-
That does not mean every observation must be huge. It means the visible world should make the agent reason like an operator instead of like a labeler.
|
| 730 |
-
|
| 731 |
-
### Proposed hidden entities
|
| 732 |
-
|
| 733 |
-
The environment should own hidden state that determines the correct policy:
|
| 734 |
-
|
| 735 |
-
- canonical root-cause category
|
| 736 |
-
- customer tier
|
| 737 |
-
- resolver ownership
|
| 738 |
-
- actual business impact
|
| 739 |
-
- active incident linkage
|
| 740 |
-
- prior unresolved duplicates
|
| 741 |
-
- whether manual escalation is necessary or wasteful
|
| 742 |
-
- whether policy requires a specific handling path
|
| 743 |
-
- whether the ticket is self-servable by documented guidance
|
| 744 |
-
|
| 745 |
-
These hidden variables are what create genuinely hard cases. Two tickets that look similar on the surface should sometimes route differently because the hidden state differs.
|
| 746 |
-
|
| 747 |
-
### Proposed action surface
|
| 748 |
-
|
| 749 |
-
I would split the action space into investigation actions and commitment actions.
|
| 750 |
-
|
| 751 |
-
Investigation actions:
|
| 752 |
-
|
| 753 |
-
- `lookup_requester`
|
| 754 |
-
- `get_account_plan`
|
| 755 |
-
- `get_related_tickets`
|
| 756 |
-
- `check_service_health`
|
| 757 |
-
- `search_kb`
|
| 758 |
-
- `inspect_internal_notes`
|
| 759 |
-
- `get_security_signals`
|
| 760 |
-
- `get_asset_or_license_state`
|
| 761 |
-
|
| 762 |
-
Operational actions:
|
| 763 |
-
|
| 764 |
-
- `add_internal_note`
|
| 765 |
-
- `request_more_info`
|
| 766 |
-
- `merge_duplicate`
|
| 767 |
-
- `set_priority`
|
| 768 |
-
- `assign_group`
|
| 769 |
-
- `escalate`
|
| 770 |
-
- `acknowledge`
|
| 771 |
-
- `submit_final_decision`
|
| 772 |
-
|
| 773 |
-
This preserves your current routing taxonomy while forcing the agent to earn the final answer through interaction.
|
| 774 |
-
|
| 775 |
-
### Proposed task families
|
| 776 |
-
|
| 777 |
-
Replace the current output-field ladder with scenario families.
|
| 778 |
-
|
| 779 |
-
1. **Baseline classification**
|
| 780 |
-
Keep a simple version of the current task for calibration.
|
| 781 |
-
|
| 782 |
-
2. **Priority under operational context**
|
| 783 |
-
Add visible account metadata and SLA hints.
|
| 784 |
-
|
| 785 |
-
3. **Tool-assisted routing**
|
| 786 |
-
Hard cases require evidence retrieval.
|
| 787 |
-
|
| 788 |
-
4. **Follow-up chain handling**
|
| 789 |
-
Correct routing depends on thread history and prior failures.
|
| 790 |
-
|
| 791 |
-
5. **Duplicate resolution**
|
| 792 |
-
The agent must detect and merge with existing tickets or note the linkage.
|
| 793 |
-
|
| 794 |
-
6. **Queue management**
|
| 795 |
-
Multiple tickets compete for limited steps or limited escalation budget.
|
| 796 |
-
|
| 797 |
-
7. **Incident-aware triage**
|
| 798 |
-
Correct behavior depends on checking active incident state.
|
| 799 |
-
|
| 800 |
-
8. **Policy-constrained operations**
|
| 801 |
-
Compliance, security, or executive-account policies change what the correct action is.
|
| 802 |
-
|
| 803 |
-
Now difficulty comes from task structure, not just output dimensionality.
|
| 804 |
-
|
| 805 |
-
### Proposed reward design
|
| 806 |
-
|
| 807 |
-
A strong reward design for this domain should likely have four layers.
|
| 808 |
-
|
| 809 |
-
Layer 1: **final outcome correctness**
|
| 810 |
-
|
| 811 |
-
- correct issue family
|
| 812 |
-
- correct priority
|
| 813 |
-
- correct resolver team
|
| 814 |
-
- correct action
|
| 815 |
-
|
| 816 |
-
Layer 2: **operational policy correctness**
|
| 817 |
-
|
| 818 |
-
- no violation of mandatory escalation rules
|
| 819 |
-
- no unjustified critical priority
|
| 820 |
-
- no missed compliance deadlines
|
| 821 |
-
- no unsupported closure
|
| 822 |
-
|
| 823 |
-
Layer 3: **process quality**
|
| 824 |
-
|
| 825 |
-
- useful tool use
|
| 826 |
-
- correct duplicate inspection
|
| 827 |
-
- efficient evidence gathering
|
| 828 |
-
- no unnecessary specialist escalation
|
| 829 |
-
|
| 830 |
-
Layer 4: **episode economics**
|
| 831 |
-
|
| 832 |
-
- queue-wide quality
|
| 833 |
-
- backlog harm
|
| 834 |
-
- escalation cost
|
| 835 |
-
- SLA miss cost
|
| 836 |
-
|
| 837 |
-
That may sound like a lot, but you do not need to expose all of it as one scalar at once. Some of it can be stored as metadata or auxiliary reward channels first.
|
| 838 |
-
|
| 839 |
-
### Proposed data strategy
|
| 840 |
-
|
| 841 |
-
Do not try to hand-author ten thousand fully custom tickets from scratch. Instead, build a layered data strategy.
|
| 842 |
-
|
| 843 |
-
Layer A: curated seed cases
|
| 844 |
-
|
| 845 |
-
- your best handcrafted exemplars
|
| 846 |
-
- ambiguous pairs
|
| 847 |
-
- follow-up chains
|
| 848 |
-
- adversarial near-neighbors
|
| 849 |
-
|
| 850 |
-
Layer B: templated scenario generation
|
| 851 |
-
|
| 852 |
-
- same underlying issue with different requester tiers
|
| 853 |
-
- same wording with different hidden incident context
|
| 854 |
-
- duplicate vs non-duplicate versions
|
| 855 |
-
- billing dispute with and without outage linkage
|
| 856 |
-
|
| 857 |
-
Layer C: hidden benchmark splits
|
| 858 |
-
|
| 859 |
-
- development split
|
| 860 |
-
- public validation split
|
| 861 |
-
- private evaluation split
|
| 862 |
-
|
| 863 |
-
Layer D: scenario tagging
|
| 864 |
-
|
| 865 |
-
- issue family
|
| 866 |
-
- ambiguity level
|
| 867 |
-
- investigation depth required
|
| 868 |
-
- tool requirement
|
| 869 |
-
- risk class
|
| 870 |
-
- queue pressure
|
| 871 |
-
|
| 872 |
-
This approach gives you scale without giving up control.
|
| 873 |
-
|
| 874 |
-
## File-by-File Improvement Plan for This Repository
|
| 875 |
-
|
| 876 |
-
This section ties the redesign back to the actual code you already have. The point is to show how the current repo can evolve into the stronger benchmark rather than be abandoned.
|
| 877 |
-
|
| 878 |
-
### `models.py`
|
| 879 |
-
|
| 880 |
-
Right now the models encode the benchmark as a label submission problem. That is fine for version one and too restrictive for version two.
|
| 881 |
-
|
| 882 |
-
I would keep the existing validation patterns, but I would expand the schema into typed action families and typed observation payloads.
|
| 883 |
-
|
| 884 |
-
Recommended direction:
|
| 885 |
-
|
| 886 |
-
- keep `HelpdeskTicketRecord`, but add typed visible vs hidden fields
|
| 887 |
-
- replace the loose `current_ticket: Optional[dict[str, str]]` with a ticket-view model
|
| 888 |
-
- split actions into investigation actions and final submission actions
|
| 889 |
-
- add typed structures for tool results, notes, queue items, and thread previews
|
| 890 |
-
- enrich state with scenario metadata, action audit trail, and resource counters
|
| 891 |
-
|
| 892 |
-
Why this matters:
|
| 893 |
-
|
| 894 |
-
As long as the schema itself says “the agent submits optional routing fields,” every other part of the environment will naturally stay classifier-shaped. Schema is architecture. If you want the environment to feel agentic, the models have to make agentic behavior first-class.
|
| 895 |
-
|
| 896 |
-
### `server/environment.py`
|
| 897 |
-
|
| 898 |
-
This file is currently the main reason the benchmark feels thin. It is clean, but it is clean because it has very little world logic.
|
| 899 |
-
|
| 900 |
-
I would evolve it in stages.
|
| 901 |
-
|
| 902 |
-
Stage 1:
|
| 903 |
-
|
| 904 |
-
- expose structured thread/follow-up information
|
| 905 |
-
- enforce task contracts more tightly
|
| 906 |
-
- store full action history, not just scores
|
| 907 |
-
- make scenario metadata visible
|
| 908 |
-
|
| 909 |
-
Stage 2:
|
| 910 |
-
|
| 911 |
-
- add tool dispatch for investigation actions
|
| 912 |
-
- maintain scenario-local hidden state
|
| 913 |
-
- let actions mutate environment state
|
| 914 |
-
- support final decision submission separately from intermediate investigation
|
| 915 |
-
|
| 916 |
-
Stage 3:
|
| 917 |
-
|
| 918 |
-
- add queue-level episodes with budget constraints
|
| 919 |
-
- let earlier choices affect later ticket handling
|
| 920 |
-
- introduce scenario-specific logic for duplicates, incidents, and policy constraints
|
| 921 |
-
|
| 922 |
-
Why this matters:
|
| 923 |
-
|
| 924 |
-
This file should become the simulator, not just the grader entrypoint.
|
| 925 |
-
|
| 926 |
-
### `server/tasks.py`
|
| 927 |
-
|
| 928 |
-
This file needs the most conceptual change after the environment itself.
|
| 929 |
-
|
| 930 |
-
The current task list is:
|
| 931 |
-
|
| 932 |
-
- task 1: issue type only
|
| 933 |
-
- task 2: issue type plus priority
|
| 934 |
-
- task 3: full routing
|
| 935 |
-
|
| 936 |
-
That is too narrow. I would turn `tasks.py` into a scenario-family registry instead.
|
| 937 |
-
|
| 938 |
-
For example:
|
| 939 |
-
|
| 940 |
-
- `single_ticket_classification`
|
| 941 |
-
- `priority_under_sla`
|
| 942 |
-
- `tool_assisted_routing`
|
| 943 |
-
- `duplicate_chain_resolution`
|
| 944 |
-
- `incident_aware_triage`
|
| 945 |
-
- `queue_optimization`
|
| 946 |
-
- `policy_constrained_security_case`
|
| 947 |
-
|
| 948 |
-
Each task family should define:
|
| 949 |
-
|
| 950 |
-
- visible observation contract
|
| 951 |
-
- allowed actions
|
| 952 |
-
- hidden truth generator
|
| 953 |
-
- episode budget
|
| 954 |
-
- reward composition
|
| 955 |
-
- benchmark split membership
|
| 956 |
-
|
| 957 |
-
Why this matters:
|
| 958 |
-
|
| 959 |
-
Right now tasks differ by scoring columns. A strong benchmark needs tasks that differ by problem structure.
|
| 960 |
-
|
| 961 |
-
### `server/grader.py`
|
| 962 |
-
|
| 963 |
-
This file should stop being only a lookup-based scorer and become the place where service-desk policy is encoded.
|
| 964 |
-
|
| 965 |
-
I would keep the basic idea of partial credit, but move from a pure field-overlap worldview to a policy-and-outcome worldview.
|
| 966 |
-
|
| 967 |
-
Examples of richer scoring logic:
|
| 968 |
-
|
| 969 |
-
- small penalty for unnecessary escalation
|
| 970 |
-
- strong penalty for under-prioritizing active access outages
|
| 971 |
-
- reward for correctly linking duplicates
|
| 972 |
-
- reward for choosing acknowledgment before final resolution when that is the right workflow
|
| 973 |
-
- penalty for routing compliance work to general support
|
| 974 |
-
- scenario-aware scoring where the same visible ticket can score differently depending on retrieved evidence
|
| 975 |
-
|
| 976 |
-
Why this matters:
|
| 977 |
-
|
| 978 |
-
The grader is the actual benchmark. It should reflect operational quality, not only taxonomy overlap.
|
| 979 |
-
|
| 980 |
-
### `server/reward.py`
|
| 981 |
-
|
| 982 |
-
This file is a good place to simplify and then rebuild.
|
| 983 |
-
|
| 984 |
-
First, remove or redesign logic that is not meaningfully active, such as the current overshoot penalty that normal episode flow does not really trigger.
|
| 985 |
-
|
| 986 |
-
Then add reward layers deliberately:
|
| 987 |
-
|
| 988 |
-
- final decision score
|
| 989 |
-
- process score
|
| 990 |
-
- economics score
|
| 991 |
-
- optional auxiliary diagnostics
|
| 992 |
-
|
| 993 |
-
Why this matters:
|
| 994 |
-
|
| 995 |
-
A benchmark becomes much easier to improve if the reward code honestly reflects what is being optimized.
|
| 996 |
-
|
| 997 |
-
### `server/app.py`
|
| 998 |
-
|
| 999 |
-
This file is currently fine for a minimal environment, but it should grow once the environment grows.
|
| 1000 |
-
|
| 1001 |
-
Recommended additions:
|
| 1002 |
-
|
| 1003 |
-
- environment metadata endpoint support if you want richer UI or benchmark introspection
|
| 1004 |
-
- possibly custom routes for benchmark info, scenario families, or baseline metadata
|
| 1005 |
-
- cleaner packaging around path setup once the project stabilizes
|
| 1006 |
-
|
| 1007 |
-
Why this matters:
|
| 1008 |
-
|
| 1009 |
-
This is not the highest-priority file, but stronger benchmark ergonomics do help credibility and usability.
|
| 1010 |
-
|
| 1011 |
-
### `data/dataset.json`
|
| 1012 |
-
|
| 1013 |
-
This file should evolve from “the benchmark” into “part of the benchmark.”
|
| 1014 |
-
|
| 1015 |
-
Keep a curated hand-authored slice, but do not let one public JSON file define the whole environment forever.
|
| 1016 |
-
|
| 1017 |
-
Recommended evolution:
|
| 1018 |
-
|
| 1019 |
-
- expand the dataset substantially
|
| 1020 |
-
- add many more feature request and general inquiry cases
|
| 1021 |
-
- add multiple duplicate chains
|
| 1022 |
-
- add hidden context fields
|
| 1023 |
-
- add templated variants of existing scenarios
|
| 1024 |
-
- create a private evaluation bank
|
| 1025 |
-
|
| 1026 |
-
Why this matters:
|
| 1027 |
-
|
| 1028 |
-
A tiny fixed public dataset makes memorization too easy and benchmark claims too brittle.
|
| 1029 |
-
|
| 1030 |
-
### `inference.py`
|
| 1031 |
-
|
| 1032 |
-
This file is useful, but it currently plays several roles at once:
|
| 1033 |
-
|
| 1034 |
-
- demo script
|
| 1035 |
-
- heuristic baseline
|
| 1036 |
-
- optional LLM runner
|
| 1037 |
-
- environment smoke path
|
| 1038 |
-
|
| 1039 |
-
I would separate those responsibilities.
|
| 1040 |
-
|
| 1041 |
-
Recommended structure:
|
| 1042 |
-
|
| 1043 |
-
- one official deterministic baseline runner
|
| 1044 |
-
- one optional tool-using baseline runner once tools exist
|
| 1045 |
-
- one separate example script for simple local usage
|
| 1046 |
-
- one benchmark harness that records split, seed, scenario family, and version
|
| 1047 |
-
|
| 1048 |
-
Why this matters:
|
| 1049 |
-
|
| 1050 |
-
Benchmarks need reproducible baselines more than they need convenient demos.
|
| 1051 |
-
|
| 1052 |
-
### `tests/`
|
| 1053 |
-
|
| 1054 |
-
The most important change after environment design is testing philosophy.
|
| 1055 |
-
|
| 1056 |
-
I would split tests into at least four groups:
|
| 1057 |
-
|
| 1058 |
-
1. **unit tests**
|
| 1059 |
-
Validation, scoring primitives, dataset loaders, tool helpers.
|
| 1060 |
-
|
| 1061 |
-
2. **real integration tests**
|
| 1062 |
-
Actual OpenEnv app, actual serialization, actual WebSocket interactions.
|
| 1063 |
-
|
| 1064 |
-
3. **benchmark regression tests**
|
| 1065 |
-
Fixed scenario suites, stable baseline scores, hidden split checks.
|
| 1066 |
-
|
| 1067 |
-
4. **integrity tests**
|
| 1068 |
-
No task leakage, no duplicate split contamination, no benchmark version drift.
|
| 1069 |
-
|
| 1070 |
-
Why this matters:
|
| 1071 |
-
|
| 1072 |
-
A serious benchmark is a data product, an environment product, and an evaluation product. The tests should reflect all three.
|
| 1073 |
-
|
| 1074 |
-
## Practical Roadmap
|
| 1075 |
-
|
| 1076 |
-
### Phase 1: Make the current environment honest and sturdier
|
| 1077 |
-
|
| 1078 |
-
This is the fastest and cheapest improvement phase. Do this even if you are not ready for a full redesign.
|
| 1079 |
-
|
| 1080 |
-
Goals:
|
| 1081 |
-
|
| 1082 |
-
- expose thread/follow-up structure
|
| 1083 |
-
- tighten task contracts
|
| 1084 |
-
- recompute and stabilize baseline measurements
|
| 1085 |
-
- add a hidden evaluation split
|
| 1086 |
-
- remove decorative reward logic
|
| 1087 |
-
- improve test realism
|
| 1088 |
-
|
| 1089 |
-
Deliverables:
|
| 1090 |
-
|
| 1091 |
-
- stronger observation model
|
| 1092 |
-
- benchmark regression script
|
| 1093 |
-
- real integration tests
|
| 1094 |
-
- scenario-family-aware tasks, even if still text-only
|
| 1095 |
-
|
| 1096 |
-
This phase will not yet make the environment winner-beating, but it will make it much more defensible.
|
| 1097 |
-
|
| 1098 |
-
### Phase 2: Add tool-assisted investigation
|
| 1099 |
-
|
| 1100 |
-
This is the highest-return phase because it changes the category of the benchmark.
|
| 1101 |
-
|
| 1102 |
-
Minimum viable tool set:
|
| 1103 |
-
|
| 1104 |
-
- requester/account lookup
|
| 1105 |
-
- related-ticket retrieval
|
| 1106 |
-
- service health lookup
|
| 1107 |
-
- KB search
|
| 1108 |
-
- final decision submission
|
| 1109 |
-
|
| 1110 |
-
Once those exist, create scenario families where the visible ticket text is insufficient without tool use. That immediately raises the benchmark ceiling and reduces shortcutability.
|
| 1111 |
-
|
| 1112 |
-
### Phase 3: Add operational economics and queue-level behavior
|
| 1113 |
-
|
| 1114 |
-
After tool use works, add:
|
| 1115 |
-
|
| 1116 |
-
- queue-wide episodes
|
| 1117 |
-
- time or action budgets
|
| 1118 |
-
- escalation cost
|
| 1119 |
-
- SLA miss cost
|
| 1120 |
-
- duplicate-handling benefit
|
| 1121 |
-
- specialist-capacity awareness
|
| 1122 |
-
|
| 1123 |
-
This turns the environment from a case-by-case annotation task into an operational management task.
|
| 1124 |
-
|
| 1125 |
-
### Phase 4: Add benchmark governance
|
| 1126 |
-
|
| 1127 |
-
At this point you should formalize:
|
| 1128 |
-
|
| 1129 |
-
- public vs private splits
|
| 1130 |
-
- scenario-family tags
|
| 1131 |
-
- official baselines
|
| 1132 |
-
- benchmark versioning
|
| 1133 |
-
- scorecards by scenario family
|
| 1134 |
-
- release notes for benchmark changes
|
| 1135 |
-
|
| 1136 |
-
This is what makes the project not just interesting, but trustworthy.
|
| 1137 |
-
|
| 1138 |
-
## Prioritized Recommendation List
|
| 1139 |
-
|
| 1140 |
-
If I had to choose only ten improvements, in order, I would choose these:
|
| 1141 |
-
|
| 1142 |
-
1. Stop defining difficulty only by `allowed_fields`.
|
| 1143 |
-
2. Add investigation tools and final submission as separate actions.
|
| 1144 |
-
3. Break the deterministic issue-type-to-assignment shortcut.
|
| 1145 |
-
4. Make resolution depend on hidden operational context more often.
|
| 1146 |
-
5. Surface follow-up and related-ticket structure.
|
| 1147 |
-
6. Expand data and add hidden eval splits.
|
| 1148 |
-
7. Add process-aware reward and remove dead trajectory logic.
|
| 1149 |
-
8. Add queue-level economics and limited budgets.
|
| 1150 |
-
9. Replace stub-heavy integration tests with real framework tests.
|
| 1151 |
-
10. Publish a stable benchmark harness and official baseline measurement.
|
| 1152 |
-
|
| 1153 |
-
## Final Assessment
|
| 1154 |
-
|
| 1155 |
-
After a deep code read, my conclusion is simple:
|
| 1156 |
-
|
| 1157 |
-
Your project is promising, readable, and based on a very strong domain. But in its current form it is still a compact routing benchmark, not yet a high-ceiling service-operations environment.
|
| 1158 |
-
|
| 1159 |
-
The better reference environments in `OpenEnv/envs` are better not because they are bigger for the sake of being bigger, but because they force the agent to operate inside state, tools, or consequences that cannot be collapsed into label mapping so easily.
|
| 1160 |
-
|
| 1161 |
-
The encouraging part is that your domain can support exactly that kind of benchmark. IT helpdesk operations naturally contain ambiguity, hidden context, tool use, policy constraints, long threads, queue pressure, and downstream costs. Very few toy domains offer that combination so cleanly.
|
| 1162 |
-
|
| 1163 |
-
So the right move is not to abandon the project. The right move is to evolve it.
|
| 1164 |
-
|
| 1165 |
-
If you keep the current shape and only add more tickets, you will get a better classifier benchmark. That may be useful, but it probably will not beat the strongest reference projects.
|
| 1166 |
-
|
| 1167 |
-
If you turn this into a tool-assisted, partially observed, multi-step service-operations simulator with stronger reward design and stronger benchmark governance, then you can absolutely build something more compelling than many of the reference environments, because your domain has the right raw material for a benchmark that is both realistic and highly evaluable.
|
| 1168 |
-
|
| 1169 |
-
The domain is already winner material.
|
| 1170 |
-
|
| 1171 |
-
The current implementation is starter material.
|
| 1172 |
-
|
| 1173 |
-
The opportunity is to close that gap deliberately.
|
| 1174 |
-
|
| 1175 |
-
## Appendix A: Comparative Scorecard
|
| 1176 |
-
|
| 1177 |
-
The table below is not a scientific benchmark. It is a code-read scorecard based on the implementations reviewed in this report. The goal is to make the gap tangible.
|
| 1178 |
-
|
| 1179 |
-
| Dimension | Your project now | Strong reference environments |
|
| 1180 |
-
| --- | --- | --- |
|
| 1181 |
-
| Action richness | Low | Medium to very high |
|
| 1182 |
-
| Hidden state depth | Low | Medium to high |
|
| 1183 |
-
| Tool use | None | Present in FinQA, Calendar, TBench2, Git, REPL |
|
| 1184 |
-
| Multistep interaction | Low-medium | Medium to high |
|
| 1185 |
-
| Queue/process economics | Very low | Medium in some envs, high in operational ones |
|
| 1186 |
-
| Reward sophistication | Low-medium | Medium to high |
|
| 1187 |
-
| Benchmark anti-overfitting | Low | Medium |
|
| 1188 |
-
| Runtime realism | Low | Medium to high |
|
| 1189 |
-
| Testing depth | Low-medium | Medium to high at repo scale |
|
| 1190 |
-
| Domain relevance | High | Varies by env |
|
| 1191 |
-
| Potential ceiling | High | Already demonstrated in several envs |
|
| 1192 |
-
|
| 1193 |
-
The most important row here is the last one. Your current implementation is not yet at the same level as the strongest references, but the domain ceiling is absolutely high enough to catch up and possibly surpass them if you execute the redesign well.
|
| 1194 |
-
|
| 1195 |
-
## Appendix B: What You Should Preserve
|
| 1196 |
-
|
| 1197 |
-
When teams hear “major redesign,” they often accidentally throw away the parts that were already working. I do not recommend that here.
|
| 1198 |
-
|
| 1199 |
-
The current project has several strengths that should be preserved as you expand it:
|
| 1200 |
-
|
| 1201 |
-
### 1. Preserve the compactness of the taxonomy
|
| 1202 |
-
|
| 1203 |
-
The label space in `vocabulary.py` is clear and product-shaped. It is not bloated. Even when the environment becomes tool-based and stateful, keep the routing ontology understandable. The problem with the current benchmark is not that the taxonomy is wrong. The problem is that the environment around the taxonomy is too thin.
|
| 1204 |
-
|
| 1205 |
-
### 2. Preserve deterministic core scoring where possible
|
| 1206 |
-
|
| 1207 |
-
Even after you add process reward and hidden context, keep as much deterministic scoring as possible. One reason your current project is easy to debug is that the grader is inspectable. Do not replace everything with opaque LLM judging if you can avoid it. Use explicit hidden truth and rule-based evaluation for most of the benchmark, and reserve softer judging only for areas that truly need it.
|
| 1208 |
-
|
| 1209 |
-
### 3. Preserve readability
|
| 1210 |
-
|
| 1211 |
-
The current codebase is easy to onboard into. That is an asset. Several bigger reference environments are strong, but also much harder to reason about quickly because they wrap external systems or broad framework machinery. As you deepen this project, keep modules well-separated:
|
| 1212 |
-
|
| 1213 |
-
- models
|
| 1214 |
-
- scenario generation
|
| 1215 |
-
- environment runtime
|
| 1216 |
-
- tools
|
| 1217 |
-
- scoring
|
| 1218 |
-
- reward composition
|
| 1219 |
-
- benchmark harness
|
| 1220 |
-
|
| 1221 |
-
That separation will make future iteration much faster.
|
| 1222 |
-
|
| 1223 |
-
### 4. Preserve seeded reproducibility
|
| 1224 |
-
|
| 1225 |
-
Your existing environment is deterministic under a seed, and that is worth keeping. Stronger benchmarks become much easier to trust when a given scenario family plus seed reproduces the same world state. As you add hidden context and generators, make seed behavior even more explicit instead of less.
|
| 1226 |
-
|
| 1227 |
-
### 5. Preserve explicit validation
|
| 1228 |
-
|
| 1229 |
-
The Pydantic validation in the current models is a quiet strength. Keep that discipline. As the action surface grows, validation becomes more important, not less. Tools and action types should reject malformed inputs cleanly so that environment failures are informative rather than muddy.
|
| 1230 |
-
|
| 1231 |
-
## Appendix C: Example Scenario Families for Version 2
|
| 1232 |
-
|
| 1233 |
-
To make the redesign more concrete, here are example scenario families that would feel much closer to a winner-level helpdesk benchmark.
|
| 1234 |
-
|
| 1235 |
-
### Scenario Family 1: Access outage with incident ambiguity
|
| 1236 |
-
|
| 1237 |
-
Visible state:
|
| 1238 |
-
|
| 1239 |
-
- multiple users report being locked out
|
| 1240 |
-
- one requester sounds urgent
|
| 1241 |
-
- another sounds like a normal password reset
|
| 1242 |
-
|
| 1243 |
-
Hidden state:
|
| 1244 |
-
|
| 1245 |
-
- there is an active identity provider outage
|
| 1246 |
-
- some tickets are duplicate symptoms of the same incident
|
| 1247 |
-
|
| 1248 |
-
Tools needed:
|
| 1249 |
-
|
| 1250 |
-
- `check_service_health`
|
| 1251 |
-
- `get_related_tickets`
|
| 1252 |
-
- `lookup_requester_role`
|
| 1253 |
-
|
| 1254 |
-
What this tests:
|
| 1255 |
-
|
| 1256 |
-
- whether the agent distinguishes isolated access issues from systemic incidents
|
| 1257 |
-
- whether it avoids handling every case as an independent ticket
|
| 1258 |
-
- whether it correctly prioritizes executive or admin users without overreacting on every case
|
| 1259 |
-
|
| 1260 |
-
### Scenario Family 2: Billing dispute tied to product defect
|
| 1261 |
-
|
| 1262 |
-
Visible state:
|
| 1263 |
-
|
| 1264 |
-
- customer says they were charged incorrectly
|
| 1265 |
-
- another case mentions checkout failures
|
| 1266 |
-
|
| 1267 |
-
Hidden state:
|
| 1268 |
-
|
| 1269 |
-
- the billing dispute is caused by a known application defect that duplicated transactions
|
| 1270 |
-
|
| 1271 |
-
Tools needed:
|
| 1272 |
-
|
| 1273 |
-
- `search_related_tickets`
|
| 1274 |
-
- `check_service_health`
|
| 1275 |
-
- `read_internal_incident_note`
|
| 1276 |
-
|
| 1277 |
-
What this tests:
|
| 1278 |
-
|
| 1279 |
-
- whether the agent routes based on real causal structure rather than superficial department ownership
|
| 1280 |
-
- whether it recognizes that pure billing handling is insufficient because engineering is involved
|
| 1281 |
-
|
| 1282 |
-
### Scenario Family 3: Compliance deadline with account-context twist
|
| 1283 |
-
|
| 1284 |
-
Visible state:
|
| 1285 |
-
|
| 1286 |
-
- requester references GDPR or legal obligation
|
| 1287 |
-
|
| 1288 |
-
Hidden state:
|
| 1289 |
-
|
| 1290 |
-
- some requests are legitimate deletion requests
|
| 1291 |
-
- some are actually admin-level data export requests misphrased as deletion
|
| 1292 |
-
- some belong to customers on contracts with defined response obligations
|
| 1293 |
-
|
| 1294 |
-
Tools needed:
|
| 1295 |
-
|
| 1296 |
-
- `lookup_contract_tier`
|
| 1297 |
-
- `retrieve_policy_snippet`
|
| 1298 |
-
- `get_account_data_scope`
|
| 1299 |
-
|
| 1300 |
-
What this tests:
|
| 1301 |
-
|
| 1302 |
-
- whether the agent can combine legal wording with account and policy context
|
| 1303 |
-
- whether it overroutes all legal-sounding tickets to the same team
|
| 1304 |
-
|
| 1305 |
-
### Scenario Family 4: Duplicate-heavy queue optimization
|
| 1306 |
-
|
| 1307 |
-
Visible state:
|
| 1308 |
-
|
| 1309 |
-
- ten tickets in a queue
|
| 1310 |
-
- several appear to be related
|
| 1311 |
-
|
| 1312 |
-
Hidden state:
|
| 1313 |
-
|
| 1314 |
-
- six are duplicates of two underlying issues
|
| 1315 |
-
- one low-volume ticket is actually the most SLA-critical
|
| 1316 |
-
|
| 1317 |
-
Tools needed:
|
| 1318 |
-
|
| 1319 |
-
- `search_related_tickets`
|
| 1320 |
-
- `merge_duplicate`
|
| 1321 |
-
- `set_priority`
|
| 1322 |
-
- `submit_queue_plan`
|
| 1323 |
-
|
| 1324 |
-
What this tests:
|
| 1325 |
-
|
| 1326 |
-
- whether the agent can manage a queue as a system
|
| 1327 |
-
- whether it reduces work through linkage
|
| 1328 |
-
- whether it balances urgency against volume
|
| 1329 |
-
|
| 1330 |
-
### Scenario Family 5: Feature request versus broken workflow
|
| 1331 |
-
|
| 1332 |
-
Visible state:
|
| 1333 |
-
|
| 1334 |
-
- customer asks for export filters or better reporting
|
| 1335 |
-
|
| 1336 |
-
Hidden state:
|
| 1337 |
-
|
| 1338 |
-
- in some scenarios the feature genuinely does not exist
|
| 1339 |
-
- in others the feature exists but the customer lacks permissions or is using the wrong path
|
| 1340 |
-
|
| 1341 |
-
Tools needed:
|
| 1342 |
-
|
| 1343 |
-
- `search_kb`
|
| 1344 |
-
- `lookup_plan_features`
|
| 1345 |
-
- `inspect_recent_product_change`
|
| 1346 |
-
|
| 1347 |
-
What this tests:
|
| 1348 |
-
|
| 1349 |
-
- whether the agent treats every request for missing functionality as a feature request
|
| 1350 |
-
- whether it can separate education/support from roadmap input
|
| 1351 |
-
|
| 1352 |
-
## Appendix D: Red Flags to Avoid During the Redesign
|
| 1353 |
-
|
| 1354 |
-
There are a few ways a redesign like this can go wrong. Avoid these.
|
| 1355 |
-
|
| 1356 |
-
### 1. Do not add tools that are merely decorative
|
| 1357 |
-
|
| 1358 |
-
If a hard task can still be solved reliably without using the tools, then the tool surface is just benchmark theater. The hard scenario families should be designed so that retrieved evidence actually changes the correct answer.
|
| 1359 |
-
|
| 1360 |
-
### 2. Do not make every scenario gigantic
|
| 1361 |
-
|
| 1362 |
-
Richer does not mean bloated. Some scenarios should stay compact. The goal is meaningful hidden context, not maximum token count.
|
| 1363 |
-
|
| 1364 |
-
### 3. Do not replace all scoring with LLM judging
|
| 1365 |
-
|
| 1366 |
-
Use explicit hidden truth and deterministic scoring wherever possible. Opaque judging should be a last resort, not a default.
|
| 1367 |
-
|
| 1368 |
-
### 4. Do not let the ontology become a maze
|
| 1369 |
-
|
| 1370 |
-
Your current taxonomy is pleasantly clean. Keep it that way. More realism should come from state and evidence, not from exploding the label space into dozens of nearly indistinguishable categories.
|
| 1371 |
-
|
| 1372 |
-
### 5. Do not forget benchmark governance
|
| 1373 |
-
|
| 1374 |
-
If you add scenario generation but do not formalize splits, baselines, and versioning, you will create a cooler environment without creating a more trustworthy benchmark.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
analysis/grounding_audit.md
DELETED
|
@@ -1,77 +0,0 @@
|
|
| 1 |
-
# Grounding Audit For Taxonomy And Similarity Decisions
|
| 2 |
-
|
| 3 |
-
> Internal note for the roadmap work originally planned for April 5, 2026.
|
| 4 |
-
> Reviewed on April 3, 2026 and pulled forward ahead of schedule.
|
| 5 |
-
|
| 6 |
-
## Goal
|
| 7 |
-
|
| 8 |
-
Ground the current ticket taxonomy and the limited partial-credit policy against real public IT-support data without turning external datasets into a runtime dependency.
|
| 9 |
-
|
| 10 |
-
## Sources Reviewed
|
| 11 |
-
|
| 12 |
-
1. [Classification of IT Support Tickets](https://zenodo.org/records/7648117)
|
| 13 |
-
- Zenodo dataset with 2,229 manually classified support tickets.
|
| 14 |
-
- Dataset description says the tickets were classified by three IT support professionals.
|
| 15 |
-
- The public preview exposes seven coarse categories: `Fileservice`, `Support general`, `Software`, `O365`, `Active Directory`, `Computer-Services`, and `EOL`.
|
| 16 |
-
|
| 17 |
-
2. [Semantic Similarity of IT Support Tickets](https://zenodo.org/records/7426225)
|
| 18 |
-
- Zenodo dataset with 300 ticket pairs manually labeled for semantic similarity.
|
| 19 |
-
- The description says three IT support professionals performed the labeling.
|
| 20 |
-
- This is the best direct grounding for keeping similarity explicit and limited instead of treating the whole label space as fuzzy.
|
| 21 |
-
|
| 22 |
-
3. [MSDialog dataset page](https://ciir.cs.umass.edu/downloads/msdialog/)
|
| 23 |
-
- Technical-support dialog corpus drawn from Microsoft Community.
|
| 24 |
-
- The site reports 35,000 dialogs in `MSDialog-Complete` and 2,199 labeled dialogs with 10,020 utterances in `MSDialog-Intent`.
|
| 25 |
-
- This grounds our use of follow-up cases, clarification-heavy threads, and helpdesk-style conversational language.
|
| 26 |
-
|
| 27 |
-
## Mapping Principle
|
| 28 |
-
|
| 29 |
-
The external datasets validate that real IT support traffic mixes access problems, software incidents, generic support questions, procurement-like requests, and multi-turn follow-ups. Our label set is more operational than the public category sets, so the mappings below are judgment calls based on source descriptions and public previews rather than exact label equivalence.
|
| 30 |
-
|
| 31 |
-
## Grounding Examples
|
| 32 |
-
|
| 33 |
-
1. Active Directory lockout, MFA trouble, or password reset -> `identity_access` -> exact-match dominant, with `onboarding` as the only defensible adjacent label when the request is really about new-user provisioning.
|
| 34 |
-
2. New hire account setup or contractor access provisioning -> `onboarding` -> partial-credit adjacent to `identity_access`, because both can surface as account enablement work before ownership is fully resolved.
|
| 35 |
-
3. Office or application crash, timeout, webhook failure, or migration-script breakage -> `application_support` -> partial-credit adjacent to `feature_request` only when the report reads like a capability gap rather than a break/fix issue.
|
| 36 |
-
4. Feature wishlist or export-format enhancement request -> `feature_request` -> partial-credit adjacent to `application_support` only when the user reports the missing capability as if it were a defect.
|
| 37 |
-
5. Vendor-evaluation question, demo request, or quote request -> `service_request` -> partial-credit adjacent to `general_inquiry` when the request is still exploratory rather than a committed operational action.
|
| 38 |
-
6. Seat expansion or provisioning-style commercial request -> `service_request` -> partial-credit adjacent to `billing_license` when procurement and account-admin signals are mixed in the same ticket.
|
| 39 |
-
7. Refund, invoice discrepancy, subscription cancellation, or payment-admin issue -> `billing_license` -> partial-credit adjacent to `service_request` only in commercial admin cases that overlap with a procurement or seat-change request.
|
| 40 |
-
8. Broad capability question or lightweight product clarification -> `general_inquiry` -> partial-credit adjacent to `service_request` or `feature_request` when the request is vague enough to look like either evaluation or roadmap feedback.
|
| 41 |
-
9. Spam lure or credential-phishing message sent to the inbox -> `spam_phishing` -> partial-credit adjacent to `security_compliance` only for security-themed inbound items, not for normal access or software tickets.
|
| 42 |
-
10. GDPR deletion request, DPA request, audit finding, or mandatory MFA policy notice -> `security_compliance` -> exact-match dominant, with very limited adjacency to `spam_phishing` for suspicious security reports and a low-confidence edge to `billing_license` only in contractual paperwork contexts.
|
| 43 |
-
11. Reopened outage thread or repeated bug report escalation -> `application_support` -> exact-match dominant; the main change across turns is usually `priority`, not `issue_type`.
|
| 44 |
-
12. Repeated lockout complaint or suspension follow-up -> `identity_access` -> exact-match dominant; follow-up behavior is grounded by MSDialog-style multi-turn support flow rather than by adding new label fuzziness.
|
| 45 |
-
|
| 46 |
-
## Review Of Current Similarity Pairs
|
| 47 |
-
|
| 48 |
-
The current `ISSUE_TYPE_SIMILARITY` map stays intentionally small. The defensible themes are:
|
| 49 |
-
|
| 50 |
-
- `billing_license` <-> `service_request`: commercial admin and procurement requests can overlap before the owning team is clear.
|
| 51 |
-
- `application_support` <-> `identity_access`: SSO and login failures can initially look like either app failure or access failure.
|
| 52 |
-
- `application_support` <-> `feature_request`: some users describe missing functionality in bug-report language.
|
| 53 |
-
- `onboarding` <-> `identity_access`: provisioning and account enablement are adjacent in real helpdesk traffic.
|
| 54 |
-
- `general_inquiry` <-> `feature_request`: vague product questions can blur into roadmap requests.
|
| 55 |
-
- `general_inquiry` <-> `service_request`: vendor-evaluation and exploratory capability questions often overlap.
|
| 56 |
-
- `spam_phishing` <-> `security_compliance`: both are security-facing, but they should stay separate from normal access or app-routing labels.
|
| 57 |
-
- `security_compliance` <-> `billing_license`: kept only as a very low-score edge for contract and paperwork overlap; this is the weakest current pair and should not be expanded further without ticket-level evidence.
|
| 58 |
-
|
| 59 |
-
## Candidate Expansions Reviewed And Rejected
|
| 60 |
-
|
| 61 |
-
These pairs were reviewed during the April 5 roadmap pass and are intentionally not being added:
|
| 62 |
-
|
| 63 |
-
- `onboarding` <-> `service_request`: both can involve setup, but the owning teams and next actions diverge too quickly.
|
| 64 |
-
- `feature_request` <-> `service_request`: roadmap asks and procurement actions are operationally different.
|
| 65 |
-
- `security_compliance` <-> `identity_access`: policy obligations may mention accounts, but the compliance workflow is distinct from user access support.
|
| 66 |
-
- `billing_license` <-> `identity_access`: nonpayment or suspension can mention lockout symptoms, but the root-cause owner is different.
|
| 67 |
-
- `application_support` <-> `billing_license`: mixed commercial and outage narratives exist, but broad partial credit here would blur incident handling too much.
|
| 68 |
-
|
| 69 |
-
## Decision
|
| 70 |
-
|
| 71 |
-
No new issue-type similarity pairs should be added from this review.
|
| 72 |
-
|
| 73 |
-
The safest grounded position is:
|
| 74 |
-
|
| 75 |
-
- keep the current limited similarity map,
|
| 76 |
-
- rely on exact-match scoring for most wrong labels,
|
| 77 |
-
- let `priority`, `assignment_group`, and `resolution_action` keep the hard-task routing signal crisp.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
analysis/scoring_contract.md
DELETED
|
@@ -1,71 +0,0 @@
|
|
| 1 |
-
# Scoring Contract
|
| 2 |
-
|
| 3 |
-
> Internal note for test design and scorer review
|
| 4 |
-
|
| 5 |
-
## Goal
|
| 6 |
-
|
| 7 |
-
Make the helpdesk grader deterministic, defensible, and only fuzzy where we can explain why.
|
| 8 |
-
|
| 9 |
-
## Exact-Match-Only Fields
|
| 10 |
-
|
| 11 |
-
These fields should never receive partial credit:
|
| 12 |
-
|
| 13 |
-
- `assignment_group`
|
| 14 |
-
- `resolution_action`
|
| 15 |
-
|
| 16 |
-
If either is wrong, the field score should be exactly `0.0`.
|
| 17 |
-
|
| 18 |
-
## Limited Partial-Credit Fields
|
| 19 |
-
|
| 20 |
-
### `issue_type`
|
| 21 |
-
|
| 22 |
-
`issue_type` can receive partial credit only for explicitly listed near-miss pairs in `server/grader.py`.
|
| 23 |
-
|
| 24 |
-
Implications:
|
| 25 |
-
|
| 26 |
-
- exact match = `1.0`
|
| 27 |
-
- listed near miss = configured partial score
|
| 28 |
-
- unlisted wrong label = `0.0`
|
| 29 |
-
|
| 30 |
-
There should be no hidden semantic fuzziness beyond the declared similarity map.
|
| 31 |
-
|
| 32 |
-
### `priority`
|
| 33 |
-
|
| 34 |
-
`priority` can receive partial credit only for explicitly listed adjacency / proximity pairs in `server/grader.py`.
|
| 35 |
-
|
| 36 |
-
Implications:
|
| 37 |
-
|
| 38 |
-
- exact match = `1.0`
|
| 39 |
-
- defined nearby priority = configured partial score
|
| 40 |
-
- undefined mismatch = `0.0`
|
| 41 |
-
|
| 42 |
-
## Task Weight Contract
|
| 43 |
-
|
| 44 |
-
- Task 1: `issue_type` only
|
| 45 |
-
- Task 2: `issue_type` 60%, `priority` 40%
|
| 46 |
-
- Task 3:
|
| 47 |
-
- `issue_type` 35%
|
| 48 |
-
- `priority` 20%
|
| 49 |
-
- `assignment_group` 25%
|
| 50 |
-
- `resolution_action` 20%
|
| 51 |
-
|
| 52 |
-
The weighted score should always stay in `[0.0, 1.0]`.
|
| 53 |
-
|
| 54 |
-
## What The Tests Must Prove
|
| 55 |
-
|
| 56 |
-
1. exact matches score `1.0`
|
| 57 |
-
2. unsupported task IDs fail clearly
|
| 58 |
-
3. only intended issue-type pairs get partial credit
|
| 59 |
-
4. unrelated issue types get `0.0`
|
| 60 |
-
5. priority proximity follows the declared table exactly
|
| 61 |
-
6. assignment group and resolution action remain exact-only
|
| 62 |
-
7. task weights apply exactly as documented
|
| 63 |
-
8. dataset loading stays robust, including UTF-8 BOM handling
|
| 64 |
-
|
| 65 |
-
## Review Rule
|
| 66 |
-
|
| 67 |
-
Before adding any new similarity pair:
|
| 68 |
-
|
| 69 |
-
1. justify it with a real-world ticket ambiguity
|
| 70 |
-
2. make sure it does not blur clearly distinct operational actions
|
| 71 |
-
3. add or update a test that proves the intended behavior
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gaps.md
DELETED
|
@@ -1,146 +0,0 @@
|
|
| 1 |
-
# Gap Analysis — IT Helpdesk Ticket Routing OpenEnv
|
| 2 |
-
|
| 3 |
-
Deep cross-reference of the codebase against every concrete mentor statement from the bootcamp transcript and Discord Q&A.
|
| 4 |
-
|
| 5 |
-
---
|
| 6 |
-
|
| 7 |
-
## GAP 1 — CRITICAL: `inference.py` runs all 3 tasks in one invocation
|
| 8 |
-
|
| 9 |
-
**Mentor (4/1/26, 9:48 PM, confirmed twice):**
|
| 10 |
-
> "inference.py should execute a single task per run and emit exactly one [START] … [END] block. The evaluation system handles running across multiple tasks, so batching all tasks in one invocation is not expected."
|
| 11 |
-
|
| 12 |
-
**Your code in `inference.py`:**
|
| 13 |
-
```python
|
| 14 |
-
TASKS = list(TASK_IDS) # [1, 2, 3]
|
| 15 |
-
for task_id in TASKS: # loops all 3
|
| 16 |
-
emit_log("START", ...)
|
| 17 |
-
...
|
| 18 |
-
emit_log("END", ...)
|
| 19 |
-
emit_log("END", overall_avg=...) # second END
|
| 20 |
-
```
|
| 21 |
-
|
| 22 |
-
The evaluator calls `inference.py` once per task. Your script ignores that and runs all 3 itself, emitting 3 `[START]`/`[END]` pairs. The evaluator expects exactly one. There is no `TASK_ID` env var read anywhere.
|
| 23 |
-
|
| 24 |
-
---
|
| 25 |
-
|
| 26 |
-
## GAP 2 — CRITICAL: `state()` response is missing `reward` and `done` fields
|
| 27 |
-
|
| 28 |
-
**Mentor (4/1/26, 9:33 PM):**
|
| 29 |
-
> "state() must return minimum: `{ 'observation': ..., 'reward': last_step_reward, 'done': True/False }`"
|
| 30 |
-
|
| 31 |
-
**Your `HelpdeskTicketState` model:**
|
| 32 |
-
```python
|
| 33 |
-
class HelpdeskTicketState(State):
|
| 34 |
-
current_task_id: Optional[int] = None
|
| 35 |
-
seed: Optional[int] = None
|
| 36 |
-
queue_ticket_ids: list[str]
|
| 37 |
-
current_ticket_index: int = 0
|
| 38 |
-
per_ticket_scores: list[float]
|
| 39 |
-
total_reward: float = 0.0
|
| 40 |
-
# NO reward field (last step reward)
|
| 41 |
-
# NO done field
|
| 42 |
-
```
|
| 43 |
-
|
| 44 |
-
`GET /state` returns this model directly. The evaluator checking `state()` for `reward` and `done` will find neither. `total_reward` is the accumulated reward, not the last step reward — which the mentor explicitly said NOT to return.
|
| 45 |
-
|
| 46 |
-
---
|
| 47 |
-
|
| 48 |
-
## GAP 3 — MEDIUM: `history` in observation is too sparse for RL usefulness
|
| 49 |
-
|
| 50 |
-
**Ben (YouTube bootcamp, ~00:31:07):**
|
| 51 |
-
> "process supervision... give these more detailed rewards... enrich history with ticket title, predicted fields"
|
| 52 |
-
|
| 53 |
-
**Your `_build_observation` history:**
|
| 54 |
-
```python
|
| 55 |
-
history.append({"step": i + 1, "score": s})
|
| 56 |
-
# final entry gets: {"step": N, "ticket_id": ..., "score": ..., "breakdown": ...}
|
| 57 |
-
```
|
| 58 |
-
|
| 59 |
-
Non-final history entries only have `step` and `score`. No ticket title, no predicted action fields. The agent cannot learn from history because it cannot see what it predicted or what the ticket was. This directly weakens RL signal quality.
|
| 60 |
-
|
| 61 |
-
---
|
| 62 |
-
|
| 63 |
-
## GAP 4 — MEDIUM: No milestone/delta reward shaping — flat score passthrough
|
| 64 |
-
|
| 65 |
-
**Mentor (4/1/26, 9:34 PM):**
|
| 66 |
-
> "A deterministic terminal grader with partial credit is valid, but it's better to include some intermediate (non-terminal) reward signals as well so the environment provides step-wise feedback. Milestone-based shaping is preferred over dense per-action rewards."
|
| 67 |
-
|
| 68 |
-
**Your `step()` in `environment.py`:**
|
| 69 |
-
```python
|
| 70 |
-
if is_done:
|
| 71 |
-
final_reward = traj_reward # trajectory reward only at end
|
| 72 |
-
else:
|
| 73 |
-
final_reward = step_reward # per-ticket score for non-final steps
|
| 74 |
-
```
|
| 75 |
-
|
| 76 |
-
You do return `step_reward` on non-final steps, which is correct. But `step_reward` is just `compute_step_reward(score)` which is `max(0.0, min(1.0, score))` — identical to the raw score. There is no shaping, no milestone signal, no delta-based signal. This is a quality gap, not a blocker.
|
| 77 |
-
|
| 78 |
-
---
|
| 79 |
-
|
| 80 |
-
## GAP 5 — MEDIUM: `observation.history` doesn't include the predicted action
|
| 81 |
-
|
| 82 |
-
**Your `_build_observation`:**
|
| 83 |
-
```python
|
| 84 |
-
history_entry = {
|
| 85 |
-
"ticket_id": current_ticket.ticket_id,
|
| 86 |
-
"score": score,
|
| 87 |
-
"breakdown": breakdown,
|
| 88 |
-
}
|
| 89 |
-
```
|
| 90 |
-
|
| 91 |
-
The agent's own predicted action is never stored in history. When the agent looks at history to decide its next action, it cannot see what it previously predicted. This is a real RL signal gap — the agent has no memory of its own decisions.
|
| 92 |
-
|
| 93 |
-
---
|
| 94 |
-
|
| 95 |
-
## GAP 6 — LOW: `tickets_remaining` semantics slightly ambiguous
|
| 96 |
-
|
| 97 |
-
**Your `_build_observation`:**
|
| 98 |
-
```python
|
| 99 |
-
tickets_remaining=max(0, queue_size - idx),
|
| 100 |
-
```
|
| 101 |
-
|
| 102 |
-
`idx` is `current_ticket_index` which has already been incremented by `step()` before `_build_observation` is called. During the episode, `tickets_remaining` counts the current ticket as "remaining" even though it is being processed. Minor but could confuse an LLM agent reading the observation.
|
| 103 |
-
|
| 104 |
-
---
|
| 105 |
-
|
| 106 |
-
## GAP 7 — LOW: `openenv.yaml` `entry_point` vs `pyproject.toml` `server` script mismatch
|
| 107 |
-
|
| 108 |
-
**Mentor (3/31/26, 11:27 PM):**
|
| 109 |
-
> "The validator is checking for a specific callable entrypoint. In some setups, it expects a main() function instead of an app object."
|
| 110 |
-
|
| 111 |
-
**Your `pyproject.toml`:**
|
| 112 |
-
```toml
|
| 113 |
-
[project.scripts]
|
| 114 |
-
server = "server.app:main"
|
| 115 |
-
```
|
| 116 |
-
|
| 117 |
-
**Your `openenv.yaml`:**
|
| 118 |
-
```yaml
|
| 119 |
-
entry_point: server.environment:HelpdeskTicketRoutingEnvironment
|
| 120 |
-
```
|
| 121 |
-
|
| 122 |
-
These point to different things. The validator may check `entry_point` in `openenv.yaml` and expect it to match `[project.scripts] server`. This inconsistency could cause validation confusion.
|
| 123 |
-
|
| 124 |
-
---
|
| 125 |
-
|
| 126 |
-
## GAP 8 — LOW: No `/web` UI endpoint — blank HF Space page
|
| 127 |
-
|
| 128 |
-
**Ben (YouTube, ~00:45:08):**
|
| 129 |
-
> "They're small apps and they're based as spaces. So they're deployed with a UI and an API."
|
| 130 |
-
|
| 131 |
-
The echo env example had `/web` for the UI. Your app has no `/web` route. The mentor said UI is optional and not scored, but the HF Space will show a blank page with no UI, which looks unpolished to judges doing Phase 3 human review.
|
| 132 |
-
|
| 133 |
-
---
|
| 134 |
-
|
| 135 |
-
## Summary
|
| 136 |
-
|
| 137 |
-
| # | Gap | Severity | File(s) |
|
| 138 |
-
|---|-----|----------|---------|
|
| 139 |
-
| 1 | `inference.py` runs all 3 tasks, evaluator expects 1 per run | CRITICAL | `inference.py` |
|
| 140 |
-
| 2 | `GET /state` missing `reward` (last step) and `done` fields | CRITICAL | `models.py`, `environment.py` |
|
| 141 |
-
| 3 | `history` missing predicted action — agent has no memory of decisions | MEDIUM | `environment.py` |
|
| 142 |
-
| 4 | No milestone/delta reward shaping — flat score passthrough | MEDIUM | `reward.py` |
|
| 143 |
-
| 5 | `history` non-final entries missing ticket title | MEDIUM | `environment.py` |
|
| 144 |
-
| 6 | `tickets_remaining` semantics slightly ambiguous | LOW | `environment.py` |
|
| 145 |
-
| 7 | `openenv.yaml` `entry_point` vs `pyproject.toml` `server` script mismatch | LOW | `openenv.yaml`, `pyproject.toml` |
|
| 146 |
-
| 8 | No `/web` UI — blank HF Space page | LOW | `server/app.py` |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
required.md
CHANGED
|
@@ -354,7 +354,7 @@ The project is ready when:
|
|
| 354 |
|
| 355 |
## Current Compliance Snapshot
|
| 356 |
|
| 357 |
-
As of April
|
| 358 |
|
| 359 |
- real-world task definition is clear and stable
|
| 360 |
- typed models, `reset()`, `step()`, `state()`, and `openenv.yaml` are present in the repo
|
|
@@ -365,16 +365,17 @@ As of April 7, 2026, the roadmap gates through the end of the freeze window are
|
|
| 365 |
- integration tests now cover `/health`, `/tasks`, `/reset`, `/step`, `/state`, full seeded episodes, and heuristic regression
|
| 366 |
- baseline heuristic results are recorded in the docs
|
| 367 |
- the README now includes Hugging Face Spaces frontmatter and a judge-facing grounded-scoring explanation
|
| 368 |
-
-
|
| 369 |
- `.openenvignore` is present
|
| 370 |
- Docker smoke coverage exists through the checked-in GitHub Actions workflow and recorded April 6 run
|
| 371 |
- `inference.py` structured `[START]`, `[STEP]`, and `[END]` logging is verified
|
| 372 |
- `uv.lock` is checked in and `openenv validate` now passes on the current repo state
|
| 373 |
- a clean-copy install-and-run pass has been completed
|
| 374 |
|
| 375 |
-
The remaining
|
| 376 |
|
| 377 |
-
-
|
| 378 |
-
- the
|
|
|
|
| 379 |
|
| 380 |
-
The
|
|
|
|
| 354 |
|
| 355 |
## Current Compliance Snapshot
|
| 356 |
|
| 357 |
+
As of April 8, 2026, the core submission requirements and the major benchmark upgrades are in place:
|
| 358 |
|
| 359 |
- real-world task definition is clear and stable
|
| 360 |
- typed models, `reset()`, `step()`, `state()`, and `openenv.yaml` are present in the repo
|
|
|
|
| 365 |
- integration tests now cover `/health`, `/tasks`, `/reset`, `/step`, `/state`, full seeded episodes, and heuristic regression
|
| 366 |
- baseline heuristic results are recorded in the docs
|
| 367 |
- the README now includes Hugging Face Spaces frontmatter and a judge-facing grounded-scoring explanation
|
| 368 |
+
- the label space and partial-credit policy were reviewed against public IT-support references during development
|
| 369 |
- `.openenvignore` is present
|
| 370 |
- Docker smoke coverage exists through the checked-in GitHub Actions workflow and recorded April 6 run
|
| 371 |
- `inference.py` structured `[START]`, `[STEP]`, and `[END]` logging is verified
|
| 372 |
- `uv.lock` is checked in and `openenv validate` now passes on the current repo state
|
| 373 |
- a clean-copy install-and-run pass has been completed
|
| 374 |
|
| 375 |
+
The remaining work is optional benchmark expansion rather than submission readiness work:
|
| 376 |
|
| 377 |
+
- make the simulator even more emergent instead of partially authored
|
| 378 |
+
- broaden the data distribution further
|
| 379 |
+
- replace the local policy search loop with a more training-oriented learning setup if needed later
|
| 380 |
|
| 381 |
+
The short TRL / GRPO README example remains optional and is still deferred because it is not required for this project to be understandable, runnable, or judgeable.
|