fix(skills): compare skill review findings against base ref baseline - #5000
fix(skills): compare skill review findings against base ref baseline#5000Battleplus wants to merge 4 commits into
Conversation
The skill review CI gate runs review_changed_public_skills.py on the entire package when any file in it changes. Pre-existing findings in unchanged files blocked the PR even though they were not introduced by the change. Now when a base ref is provided (PR-style or push-style), the script extracts the package at the base ref, collects baseline findings, then only fails on newly introduced errors. Pre-existing findings are logged for visibility but do not block. Closes bytedance#4996 Signed-off-by: Battleplus <battleplus@users.noreply.github.com>
|
@Battleplus please fix the unit test error. |
Signed-off-by: Battleplus <3559424769@qq.com>
|
Fixed. The 7 failing tests in Changes: mocked CI should be green on the new push. |
willem-bd
left a comment
There was a problem hiding this comment.
The baseline-diffing direction is right — re-blocking PRs on pre-existing findings in unchanged files (as in #4995) is a real CI problem, and fail-closed behavior when the baseline can't be extracted is the correct default. I have four findings on the implementation: the head-side review now fails open on a CLI crash, the baseline path silently drops the --fail-on error / --fail-on-incomplete gate semantics, finding_key is fragile against line shifts in edited files, and the base-run env prepends a nonexistent harness path. Also noting: the new baseline code paths (extract → diff → new-findings fail / pre-existing pass / baseline-unavailable) have no test coverage — the test changes only stub the new functions so the old tests keep passing, and backend TDD is mandatory in this repo per AGENTS.md.
|
@Battleplus, some unit tests failed; please check them. |
review_env() constructed PYTHONPATH from whatever repo_root was passed. When reviewing the base ref, run_review_json received the tmpdir (base_pkg.parent) as repo_root, producing a nonexistent harness path in PYTHONPATH. Add an env_repo_root parameter so the base review always uses the actual repository root for environment construction. Signed-off-by: Battleplus <3559424769@qq.com>
|
Fixed the two issues in this push: 1. Harness path: Changed to . The base review now uses the real repo root for , so PYTHONPATH points to the genuine directory instead of a nonexistent path inside the temp extraction directory. 2. Temp cleanup: Changed to and added a loop that walks up from the extraction root, removing empty parent directories until it finds a non-empty one. 3. Finding key stability (bonus): Dropped from — pre-existing findings that shift due to unrelated insertions/deletions are no longer falsely flagged as new. Path + rule_id + message is a stable identity. |
… semantics Addresses willem-bd review findings on bytedance#5000: 1. Fail-closed head review: run_review_json now returns the full facts dict or None. None means the review itself failed (CLI crash, invalid JSON, empty output) and is treated as REVIEW FAILED, never as no findings. Previously a head CLI crash produced [] which the gate interpreted as no new findings and passed (fail-open). 2. Preserve original --fail-on error severity semantics: only blocker/error findings gate; new warning/info findings no longer fail the baseline path, matching the pre-baseline CLI behavior. 3. Preserve --fail-on-incomplete semantics: a head review with content not assessed fails even when no new gating finding appears. 4. Stable finding identity: line numbers excluded from finding_key so line shifts from unrelated edits do not turn pre-existing findings into new ones. 5. Baseline review failure is fail-closed: if the base review crashes, all head findings are treated as new rather than silently passing. 6. Fix baseline run crash: run_review_json passes str(package) (absolute path, accepted by the CLI) instead of package.relative_to(repo_root), which raised ValueError for temp-extracted base packages. 7. Temp extraction cleanup walks up removing empty dirs.
|
Addressed all 4 review threads with a substantive rework of the baseline gate (pushed as 4c8d1de): 1. Head-side review fails open (Important): Fixed. 2. Baseline mode silently changes gate semantics (Important): Fixed. The baseline path now preserves the original 3. 4. Nonexistent harness path in base env (Suggestion): Fixed in an earlier push (608aa49) — base review now uses the real Regression tests added: head crash → fail closed, invalid JSON → fail closed, unchanged finding → pass, line-shifted finding → pass (exempt), new error → fail, new info → pass (severity preserved), incomplete head → fail, baseline review crash → all findings treated as new. |
|
Hi @WillemJiang, I've verified the review script tests locally — all 21 tests in |
willem-bd
left a comment
There was a problem hiding this comment.
Round 2 - all four prior findings verified fixed at this head: (1) head review now fails closed (run_review_json returns None on crash/invalid output and main() treats it as failure), (2) finding_gates() + review_incomplete() restore the original --fail-on error / --fail-on-incomplete semantics with tests for both directions, (3) finding_key drops line (keeping message, with the rationale documented), and (4) the base review now runs with the real repo root for cwd/env. The new test suite covering the baseline paths is a solid addition. One residual nit below on the temp-directory cleanup introduced in 608aa49.
| shutil.rmtree(base_pkg, ignore_errors=True) | ||
| # Clean up the temp root left behind by extract_package_at_ref. | ||
| tmp_root = base_pkg.parent | ||
| while tmp_root != tmp_root.parent and not any(tmp_root.iterdir()): |
There was a problem hiding this comment.
[Nit] The temp-dir cleanup climb is unbounded above the mkdtemp root and rmdir() is unguarded. The walk starts at base_pkg.parent and climbs while parents are empty, but it has no upper bound at the tempfile.mkdtemp root - if the shared $TMPDIR happens to be empty, it will rmdir the system temp dir itself (and in a minimal container could keep climbing). Also, tmp_root.rmdir() can raise an uncaught OSError via a TOCTOU race: another process sharing the temp dir creates a file between the iterdir() emptiness check and the rmdir(), and the whole gate then crashes with a traceback (fail-closed, so low impact, but noisy).
Cleaner fix: have extract_package_at_ref return (extracted, tmp_dir) (or attach the root) and shutil.rmtree(tmp_dir, ignore_errors=True) exactly what was created - no climb, no race on directories you don't own.
Why
Closes #4996
The skill review CI gate (
review_changed_public_skills.py) reviews the entire public skill package when any file in it changes. Pre-existing findings in unchanged files block the PR even though they were not introduced by the change.For example, PR #4995 changes one file in
skill-creator, but the CI fails on 4 pre-existingpython-subprocess/secret-env-assignmentfindings in other unchanged files.What changed
When a base ref is provided (
--base-ref/--before), the script now:git archive→ temp directory--format jsonon the base version(path, rule_id, line, message)— only newly introduced findings cause failureWhen no base ref is provided (e.g., direct pushes without comparison), the original behavior is preserved.
Validation
ruff check+ruff format --checkpassfinding_key,extract_package_at_ref,run_review_jsonall verified against live reposkills/public/bootstrapatorigin/mainSurface area