fix(traces): stop the segment guard zeroing multi-line commands - #2969
fix(traces): stop the segment guard zeroing multi-line commands#2969saksharthakkar wants to merge 1 commit into
Conversation
The `command_executed` segment guard stopped at any newline, including a backslash line continuation, so every multi-line command scored 0. Drop the `\n` term and match `[\s\S]`; `\s(?:uip|$UIP)\s` is what actually separates stacked commands. Adds a 7-control replay matrix (single-line and multi-line shapes) that grades through a copy of coder_eval's haystack matching, and corrects the false claim in tests/README.md that normalization collapses newlines. LLMOPS-3152 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @saksharthakkar's task in 1m 51s —— View job Coder-eval task lint (advisory)2 task YAMLs changed; verdict counts: 0 Critical, 0 High, 0 Medium, 0 Low, 2 OK. Rubric: .claude/commands/lint-task.md. This check is advisory and never blocks merge. Evidence of passing run❌ High — PR body explicitly states "The two graded tasks were not re-run end to end against a tenant" and the test-plan item "Next nightly Claude run scores The author does provide strong indirect evidence: a 7-control × 2-shape matrix test ( Per-task lint
|
|
Claude finished @saksharthakkar's task in 2m 41s —— View job SummaryFixes a regression from PR #2836 where the Change-by-Change Review1.
|
| Area | Status | Notes |
|---|---|---|
| Frontmatter | OK | Task YAML frontmatter unchanged and valid |
| E2E Tests | OK | Existing tasks updated; new regression test added with CI job |
| Skill Body | N/A | No skill files under skills/ modified |
| References & Assets | OK | tests/README.md corrected accurately |
| Repo Hygiene | OK | No secrets, no cross-skill deps, scoped changes, CODEOWNERS not needed (no new skill paths) |
Issues for Manual Review
- The coder_eval
_normalize_shellcopy is pinned to v0.11.5. If coder_eval changes its haystack matching in a future version, this test could diverge. The comment at line 30 documents this — acceptable tradeoff since coder_eval isn't a test dependency. - The final test-plan checkbox ("Next nightly Claude run scores above 0") is pending — worth confirming after merge.
Conclusion
Clean PR. The root-cause analysis is rigorous (shlex behavior with backslash continuations), the fix is minimal (remove \n from the stop list, use [\s\S] for explicitness), and the 7-control × 2-shape matrix is thorough enough to prevent reintroduction. All CI checks pass. No issues found — approve.
Motivation
PR #2836's segment guard stops at any newline, so every backslash-continued command scores 0 —
skill-platform-traces-feedback-list-filtersfell from 1.00 to 0.00 on Claude with identical agent behavior. Dropping the\nterm restores multi-line matching without giving back the batched-call fix #2836 was written for.Summary
The
command_executedsegment guard scopes a lookahead to "the rest of THIS command":The safety net assumed in the #2836 review does not exist. coder_eval matches a raw haystack and a shlex-normalized one, but normalization does not collapse a backslash line continuation:
The escaped newline survives as a literal
'\n'token and" ".join(tokens)puts it straight back — now as a bare newline. Both haystacks keep the line break, so every lookahead dies at the first continuation.Run evidence
2026-08-27_04-13-44(last pre-#2836)skill-platform-traces-feedback-list-filters2026-08-31_04-15-47(post-#2836)Identical agent behavior; #2836 alone flipped it. All three commands in the 08-31 run were correct — just backslash-continued. The sibling task
skill-platform-traces-feedback-list-detailedscored 1.00 in the same run only because its commands happened to be single-line; it carries the same latent bug, so both files are fixed here.Codex is unaffected and keeps the fix it needed: it writes single-line commands and went 6-fail/9 pre-#2836 to 3/3 pass post-#2836.
Why
(?<!\\)\nis not enoughA lookbehind that skips only escaped newlines repairs the raw haystack but not the normalized one, where
\+ newline has already become a bare newline. That mis-splits one merged command into two fake segments and opens a false positive: control B2 below is a single merged command carrying both--span-idand--agent-id, and the criterion that must reject it starts passing. The\nterm buys no scoping that\s(?:uip|$UIP)\sdoes not already provide, so the fix is to remove it rather than narrow it.File-by-file
tests/tasks/uipath-platform/traces/traces_feedback_list_filters_smoke.yaml— all 3command_patternregexes moved to the new guard (8 guard occurrences). The taskdescriptionno longer claims the lookahead stops at a newline.tests/tasks/uipath-platform/traces/traces_feedback_list_detailed_smoke.yaml— same, all 3command_patternregexes (7 guard occurrences). No behavior change today (its commands were single-line), but it removes the latent zero.tests/scripts/test_command_pattern_segment_guard.py(new) — replays a 7-control matrix in single-line and multi-line shape through a faithful copy of coder_eval 0.11.5_match_haystacks/_normalize_shell(raw + shlex-normalized haystacks,re.DOTALL). It reads the shipped regexes out of the task YAML, so it fails red if the\nterm ever comes back, and it pins both rejected alternatives.tests/README.md— corrects the segment-scoping rule: it claimed the grader "also matches a normalized haystack with newlines collapsed to spaces", which is what made the fix(traces): segment-scope list_* graders; stop gating on default sort order #2836 review look sound. Now states the corrected guard and that continuations are not collapsed..github/workflows/test-helpers.yml— newcommand-pattern-guardjob running the matrix, plustests/tasks/uipath-platform/**added to the trigger paths so editing the guarded YAMLs re-runs it.Control matrix
Every control runs in both a single-line and a multi-line (backslash-continued) shape — 14 cells, 42 criterion outcomes.
--span-idand--agent-id--offset 10(page number, not zero-based offset)list detailed&&in one callmain)(?<!\\)\nvariant\nterm)E and F stay green, so #2836's batched-call fix is preserved.
Tests performed
Plus a YAML parse and
re.compile(..., re.DOTALL)over everycommand_patternintests/tasks/uipath-platform/traces/(11 files, 30 patterns — all compile), and a YAML parse of the edited workflow.scripts/check-skill-verbs.pywas not run: it takes a skill directory and this PR changes no skill underskills/orpreview/.The two graded tasks were not re-run end to end against a tenant — a live run needs credentials this change does not affect. The change is to the grader regex only, and the control matrix replays the exact scoring path (
_match_haystacks+re.DOTALLsearch) that a live run would take, including the two real command shapes recorded in runs2026-08-27_04-13-44and2026-08-31_04-15-47.Test plan
command_patternregexes in both traces task YAMLs use the continuation-safe guardgit grep -F '(?!\n|&&' -- tests/tasks/returns nothing(?<!\\)\nvariant are pinned as failing, so neither can quietly return&&, F stacked lines) still grade per commandtests/scripts/suite unchanged and greenskill-platform-traces-feedback-list-filtersabove 0LLMOPS-3152
🤖 Generated with Claude Code