Skip to content

refactor(evaluating-skill-quality): split gitapex_check_skill_shape.py into shape_checks package (#1330) - #1450

Merged
tvna merged 18 commits into
mainfrom
claude/gitapex-pr-1330-24wtvs
Aug 30, 2026
Merged

refactor(evaluating-skill-quality): split gitapex_check_skill_shape.py into shape_checks package (#1330)#1450
tvna merged 18 commits into
mainfrom
claude/gitapex-pr-1330-24wtvs

Conversation

@tvna

@tvna tvna commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Summary

Splits skills/evaluating-skill-quality/scripts/gitapex_check_skill_shape.py
(6321 lines) into a shape_checks/ package along its existing check-family
boundaries, behind the same single unchanged CLI entry point, then narrows
or removes that file's blanket xenon complexity-gate exclude in
.github/workflows/test.yml. All 3 planned tasks plus the mandatory
executing-a-branch-plan Step 8 (refactor + adversarial review) are
complete -- see ## Execution log below. Handing off to
drafting-a-pr-to-merge for CI/review drive-to-green.

Facts

  • skills/evaluating-skill-quality/scripts/gitapex_check_skill_shape.py is
    6321 lines (issue refactor(evaluating-skill-quality): split gitapex_check_skill_shape.py, already excluded from the complexity gate at 6149 lines #1330's own Facts section states 6149; corrected during
    this session's re-verification -- drift since the issue was drafted).
  • The xenon complexity-gate exclude for this file exists in exactly one
    place, .github/workflows/test.yml:70-79, with an explicit re-measure
    trigger already stated in its own comment: drop the exclude once
    _parse_manifest and check_shape (currently CC 99/64, rank F, MI 0.00)
    are refactored below rank F.
  • Four test files reach into this module's private names directly and must
    keep working unchanged:
    skills/evaluating-skill-quality/scripts/test_gitapex_check_skill_shape.py,
    tests/test_gitapex_check_skill_shape_properties.py,
    tests/test_gitapex_skill_metadata_sidecar.py,
    tests/test_gitapex_repository_skill_shape.py.

Assumptions

  • The module split's own check-family boundaries (frontmatter, manifest,
    links/portability, citations, field-checks, citation-checks,
    bundled-scripts, skill-deps, lifecycle, execution-requirements) follow the
    function-name groupings already visible in the file, not a redesigned
    taxonomy -- see the task-list file below for the concrete mapping.

Risk / blast radius

This module backs evaluating-skill-quality's own deterministic shape gate,
invoked by SKILL.md, .pre-commit-config.yaml, and CI. A regression here
would silently change (or crash) that gate across every skill in this
repository. Mitigated by: (1) a dedicated differential output-diff script
comparing check_shape()'s results against every real skills/*/SKILL.md
before/after, required to be byte-identical, now hardened against a
BASE_SHA-drift defeat-case found during Step 8's adversarial review; (2) the
existing 4-file, 600+ test suite required to stay green with zero
test-content changes beyond import-path-style updates; (3) executing-a-branch-plan
Step 8's mandatory refactor + adversarial-review pass, complete -- see
Execution log.

Rollback

Revert this PR's merge commit (or the task-list-file commit 71bb051a
onward on this branch, before merge, per the Execution log's own run_id).
No other file outside skills/evaluating-skill-quality/scripts/ and
.github/workflows/test.yml/.gitapex/ssot.json is touched.

Verification

Acceptance Criteria Map (re-verified this session, marker on issue #1330 at
2026-08-29T19:36:24Z):

Criterion Interpretation Planned ops Proof method Residual risk
The file is large (6321 lines, 17+ checks) and already excluded from the complexity gate Split into a shape_checks/ package along check-family boundaries, keeping check_shape() as the single aggregating CLI entry point so no external caller needs to change how it invokes the checker Refactor into skills/evaluating-skill-quality/scripts/shape_checks/ with one submodule per check family; update the imports inside check_shape(); keep every private name the 4 consumer test files reach into importable via a re-export hub pytest suite green with zero test-content changes beyond import-path updates, plus a differential output-diff script proving identical check_shape() results across every real skills/*/SKILL.md before/after. Result: DONE (task-1, commit 034b052) -- 601/601 targeted tests green, differential script PASS across all 29 real skills, ruff+mypy clean. Step 8 added: a recursive bundled-script scan fix (the split moved ~5000 lines one directory deeper, silently narrowing the no-voodoo-constant/script-execution-intent scan scope) and a hardened diff-oracle guard against a post-split BASE_SHA defeat-case -- 629/629 tests green A large mechanical refactor of a load-bearing, heavily-tested file carries real regression risk if done as a rewrite rather than a mechanical split
The file is already excluded from xenon's complexity gate Once individual modules are small enough, narrow or remove the existing blanket --exclude entry so complexity regressions are caught going forward Update .github/workflows/test.yml's xenon invocation to drop or narrow the exclude entry once the split lands xenon run against the new module layout with the narrowed/removed exclude passes clean. Result: DONE (task-2 commit 40f9635 + task-3 commit e460315) -- check_shape/_parse_manifest/_execution_requirements_checks internally decomposed; xenon exclude narrowed from the whole original file (and the interim shape_checks/ glob) down to exactly 2 files (gitapex_check_skill_shape.py, shape_checks/execution_requirements.py). Step 8 independently reproduced a real defeat-case proving the narrowed exclude still catches a genuine complexity regression in every file it no longer names* Realized: gitapex_check_skill_shape.py (check_shape D/22, main C/13) and shape_checks/execution_requirements.py (3 functions C-range) remain a narrower, justified exclude per this row's own residual-risk allowance, with a concrete re-measure trigger recorded in both .github/workflows/test.yml's comment and .gitapex/ssot.json's gate rule text

Follow-up fixes (not their own ACM rows):

  • Discovered via CI's coverage-combine check: task-1's new verify_shape_check_output_diff.py shipped with 0% test coverage against this repo's 90% floor -- added test_verify_shape_check_output_diff.py (commit 14aaa20), now 96% covered.
  • Step 8 refactor pass (commit 07d3d11): narrowed an over-broad mypy exemption the split left behind to each module's own actually-needed error codes (verified empirically per code), and fixed 11 in-file cross-reference comments falsified by the move (e.g. "this file's own X" now pointing at the file X actually moved to).
  • Step 8 adversarial review (commits 9372a16, 6f1680e, 1d1d752): (a) fixed a reorder-detection bug in the diff oracle that reported an empty body on a check-order regression; (b) made the bundled-script scan recursive, restoring detection coverage the split itself silently dropped (corroborated against a sibling scanner's own identical convention, gitapex_scan_execution_requirements_drift.py); (c) closed a real defeat-case where pointing BASE_SHA at a post-split commit made the diff oracle vacuously pass. All three shipped with committed regression tests, not one-off manual checks.

Checklist

  • Tests pass locally
  • Docs updated if behavior changed
  • Issue number cited in every commit
  • If this PR adds/modifies a skills/*/SKILL.md, a docs/superpowers/specs/*.md design doc, a security-relevant skill, or a deterministic checker script (skills/*/scripts/*.py, evals/scripts/*.py, .github/scripts/*.py), a ## Skill audit evidence section discloses the required verdicts/waivers (see .github/scripts/gitapex_gate_skill_audit_disclosure.py)
  • If this PR adds a new Kept-edit-log entry to any evals/*/split.md, that entry discloses a Transfer check line (see .github/scripts/gitapex_gate_transfer_check_disclosure.py)
  • If this PR adds or increases a skills/*/SKILL.md's Stop-boundary bullets or named dispatch branches, evals/<skill>/tasks/*.yaml gained at least as many new fixtures (see .github/scripts/gitapex_gate_skill_branch_fixture_coverage.py)

Skill audit evidence

  • checker-script-adversarial-review: RAN -- executing-a-branch-plan Step 8's mandatory adversarial code-review pass ran against the full accumulated diff, including the gate's own mandatory deterministic-check-script scrutiny: a live defeat-case proving the narrowed xenon exclude still catches a real complexity regression, and a live defeat-case that found and closed a real hole in the differential-verification oracle (a post-split BASE_SHA would have made it vacuously pass). 3 CONFIRMED findings, all fixed with committed regression tests (commits 9372a16, 6f1680e, 1d1d752).
  • deterministic-gate-quality: RAN -- this PR's own change to the cyclomatic-complexity-floor gate (.github/workflows/test.yml / .gitapex/ssot.json, narrowing the xenon --exclude list) was read against skills/evaluating-deterministic-gate-quality/references/dimensions.md, scoped to dimension 15 (fail-closed default on incomplete/malformed input, generalized here to "does the deny path actually fire on a real violation, rather than silently passing"): Step 8's adversarial review constructed two live boundary cases -- a deliberately over-complex (rank F) function added to shape_checks/manifest.py and, separately, to shape_checks/citations.py (neither excluded by the narrowed list) -- and confirmed xenon actually exits 1 (deny) for each, then reverted them and confirmed a clean exit 0. This is a targeted check against the one dimension the gate's own message named, not a full 24-dimension audit of the whole gate.
  • defeat-test-disclosure: RAN -- at least one test was constructed specifically to defeat (not merely exercise the happy path of) new/changed detection logic, for all 3 CONFIRMED findings above -- each shipped with a committed regression test asserting the correct (previously-defeated) outcome, not a one-off manual check: test_verify_shape_check_output_diff.py's reorder-divergence test (commit 1d1d752), its recursive-bundled-script-scan tests (commit 9372a16), and its _assert_pre_split_source BASE_SHA-drift tests (commit 6f1680e).

Merge gate: independent review

This PR is also subject to the independent-review-pending required
status check (see .github/workflows/independent-review-pending.yml /
.github/scripts/gitapex_gate_independent_review_pending.py). It stays
pending/failing until a ## Independent review verdict section naming
this PR's current head commit is recorded in this body --
drafting-a-pr-to-merge's own Step 8 records it once its independent
review completes. There is nothing for you to do here now: do not
pre-fill this section yourself, and do not remove this note.

Independent review verdict

  • Verdict: CLEAN
  • Verified commit: 3701af6

Outer layer (GitHub-native reviewer): did not run. Confirmed via direct
GitHub REST API checks (review history on this PR and on 4 other recent
merged PRs in this repository, all zero reviews) that neither Anthropic's
"Claude Code Review" GitHub App nor GitHub Copilot's
copilot-pull-request-reviewer[bot] is installed/reachable here --
request_copilot_review completed with no reviewer actually added per
the requested_reviewers API. CodeRabbit is present but explicitly
opts out via its own PR comment ("This repository does not receive
automatic reviews because it has fewer than 10 stars"), and the
CodeRabbit/Devin Review commit statuses both report "skipped" for
the same reason. This layer's outcome is disclosed rather than silently
omitted, per this skill's own instruction.

Inner layer (reviewing-an-artifact, default/low effort): ran a 5-axis
fan-out (correctness, blast-radius, reuse-and-simplification, convention,
security) as 5 independent fresh-context dispatches against this PR's
full diff (git diff c9672706e..HEAD, ~670KB), each independently
verified (FABRICATED pre-check, direct code inspection, live-execution
confirmation where applicable) rather than trusted at face value. 8
candidate findings surfaced; all 8 independently confirmed as factually
accurate against the actual code. Disposition:

Fixed and verified:

  • Correctness: shape_checks/bundled_scripts.py's
    _script_execution_intent_offenders matched/deduplicated bundled
    scripts by bare basename only; since the bundled-script scan became
    recursive (this PR's own Step 8 fix), two scripts sharing a basename
    in different scripts/ subdirectories could let one genuinely
    documented file silently satisfy the check for an unrelated,
    undocumented same-named file -- a fail-open false negative,
    live-reproduced with a built fixture. Fixed (basename-collision guard,
    commit 379c0fd) and covered by 3 new regression tests (commit
    3701af6): the false-negative-closed case, the disclosed
    false-positive trade-off when both colliding files are individually
    documented, and a non-colliding control. A second, independent
    fresh-context review of this incremental fix (separate from the
    original 5-axis pass) confirmed it sound and flagged the missing test
    coverage, which commit 3701af6 then closed.
  • Convention: shape_checks/links_portability.py's
    _is_bare_skill_name docstring said "see the module docstring" for a
    stdlib-only claim the module docstring does not actually make (a
    12th instance of the exact dangling-cross-reference class commit
    07d3d11 already fixed 11 other cases of during Step 8, missed by
    that sweep). Fixed (commit 379c0fd).

Confirmed, deliberately not fixed in this PR, with reasoning:

  • Blast-radius: .github/scripts/gitapex_gate_detection_logic_property_coverage.py's
    own _IN_SCOPE_RE only matches gitapex_check_*.py
    directly under scripts/, so none of the new shape_checks/*.py
    files it grades detection logic in are in scope -- a real coverage
    regression, since this same logic living in the pre-split monolith
    WAS in scope. Measured directly: widening that regex as part of this
    PR's own diff would surface 134 new required-Hypothesis-test findings
    across 8 files, because the gate only grades lines a diff adds and
    every line in these new files shows as added here. Because the gate
    is diff-scoped ("a pre-existing gap another PR owns is never this
    diff's failure" -- that file's own docstring), doing this widening as
    a separate follow-up PR after this one merges costs zero new required
    tests instead, since those lines will already be sitting unchanged in
    main by then. Filed as a follow-up task (spawn_task, title "Widen
    detection-logic-property-coverage scope to shape_checks/") rather than
    bundled here, which would have meant either 134 tests or 134
    individually-justified waiver comments for a mechanical,
    differentially-verified split -- exactly the scope creep issue refactor(evaluating-skill-quality): split gitapex_check_skill_shape.py, already excluded from the complexity gate at 6149 lines #1330
    said this PR should not combine with.
  • Reuse: shape_checks/execution_requirements.py's
    _valid_execution_requirements_tools_list duplicates
    shape_checks/skill_dependencies.py's _valid_skill_dependency_list
    byte-for-byte (pre-existing in the monolith, not introduced by this
    diff). No clean shared home exists without violating a stated design
    boundary: shape_checks/constants.py's own module docstring says "No
    detection logic lives here," and hoisting either function into the
    other's module reads oddly at the borrowing call sites. Left as-is;
    worth a dedicated follow-up if this class of duplication recurs.
  • Reuse: shape_checks/execution_requirements.py's three sub-block
    "problems" functions (_execution_requirements_tools_problems,
    _..._packages_problems, _..._network_problems, all newly
    decomposed by this PR's own Step 8) share a common skeleton that
    shape_checks/lifecycle.py's own _lifecycle_sub_block_problems
    already demonstrates a generalized alternative for. No concrete
    failure scenario -- a code-quality opportunity, not a defect -- and
    restructuring three functions whose exact complexity rank this same
    PR just measured and excluded from the cyclomatic-complexity-floor
    gate carries real regression risk disproportionate to a stylistic
    win this close to merge. Left as-is.
  • Reuse: a repeated "count + pluralize + first-offender" formatting
    snippet appears near-verbatim across execution_requirements.py,
    lifecycle.py, and skill_dependencies.py (~8 occurrences). Same
    disposition as above: real but purely stylistic, no failure scenario,
    left as-is.
  • Convention: the new verify_shape_check_output_diff.py does not
    carry this repository's otherwise-universal gitapex_ script-name
    prefix (checked every other skills/*/scripts/*.py and
    .github/scripts/*.py file; this is the only exception). No
    deterministic gate enforces this convention, and a rename would touch
    4 files including its own test file. Left as-is.

Security axis: no CWE-class findings (checked subprocess/git show
invocation safety, dynamic-code-loading trust boundary, YAML-parsing
safety, path-traversal exposure in the recursive bundled-script scan,
and file-write surface -- none present).

This verdict reflects reviewing-an-artifact's own findings and this
session's independent validation of each; it is disclosure for a human
reader, not a self-certifying automated signal.

Related Issue

Closes #1330

Execution log

  • PlanApproved{run_id: 71bb051a}
  • TaskStarted{run_id: 71bb051a, task_id: task-1}
  • TaskFailed{run_id: 71bb051a, task_id: task-1, reason: "1 of 601 targeted tests failed (test_skill_dep_list_item_re_indent_matches_its_docstrings, StopIteration) -- physical-source-scan tests in 2 of the 4 protected consumer test files assumed definitions still lived in gitapex_check_skill_shape.py's own text; commit b2d5c5e7 landed the mechanical move itself clean (differential script PASS, ruff/mypy clean, 600/601 tests)"}
  • TaskCompleted{run_id: 71bb051a, task_id: task-1, commit_sha: 034b0522cc8f0ff3286ad52a9d3b8953a32d234e} (one retry: repointed the 2 physical-source-scan tests at their moved source files per the ACM's own "update any test files that import internal functions directly" -- 601/601 green)
  • TaskStarted{run_id: 71bb051a, task_id: task-1-followup-xenon-interim}
  • TaskCompleted{run_id: 71bb051a, task_id: task-1-followup-xenon-interim, commit_sha: ba0310c8b422a3592d7afde4b3e22db91107aed7} (discovered via the local pre-push gate, not pre-planned: task-1's own pure move exposed pre-existing rank-F complexity in shape_checks/manifest.py and shape_checks/execution_requirements.py that the old single-file exclude was silently covering; widened the exclude to shape_checks/* as an interim state so the branch stays pushable -- task-2/task-3 below narrow or drop it for real)
  • TaskStarted{run_id: 71bb051a, task_id: task-2}
  • StageDeviated{run_id: 71bb051a, task_id: task-2, reason: "the dispatched task-2 agent hit the session's own rate limit mid-task, before it could commit or return a structured result", action: retry} (recovered without a fresh dispatch: the agent's in-progress working-tree edits -- check_shape/_parse_manifest/_execution_requirements_checks already decomposed into shape_checks/orchestrator.py and the other submodules -- were still present and syntactically complete; independently re-verified in the main thread (differential script PASS, 601/601 tests, mypy/ruff clean, xenon measured) before committing, rather than discarded and redispatched)
  • TaskCompleted{run_id: 71bb051a, task_id: task-2, commit_sha: 40f9635f29f6305cd8629c1032c5795b27bbbceb}
  • TaskStarted{run_id: 71bb051a, task_id: task-3}
  • TaskCompleted{run_id: 71bb051a, task_id: task-3, commit_sha: e4603150c1651ab4960506dd6435f9dce1c17ff2} (narrowed the xenon exclude to exactly the 2 remaining offenders; also synced .gitapex/ssot.json's own copy of the exclude string/rule text, a second-copy drift risk found during the task, not pre-planned)
  • TaskStarted{run_id: 71bb051a, task_id: task-1-followup-coverage}
  • TaskCompleted{run_id: 71bb051a, task_id: task-1-followup-coverage, commit_sha: 14aaa2090e24a508ae3d0bab366a08ab98285120} (discovered via CI's coverage-combine check, not pre-planned: verify_shape_check_output_diff.py shipped with 0% coverage against the repo's 90% floor; added a dedicated test file, now 96% covered)
  • TaskStarted{run_id: 71bb051a, task_id: step8-refactor-pass}
  • TaskCompleted{run_id: 71bb051a, task_id: step8-refactor-pass, commit_sha: 07d3d119cddc2b5a83ed0015f2e5d3c01232ba7a} (fresh independent subagent, opus/stronger-reasoning tier: narrowed an over-broad mypy exemption to each module's own actually-needed codes; fixed 11 cross-reference comments falsified by the move; found but explicitly did not fix a bundled-script-scan gate-coverage narrowing, correctly deferred to the adversarial-review pass)
  • TaskStarted{run_id: 71bb051a, task_id: step8-adversarial-review}
  • TaskCompleted{run_id: 71bb051a, task_id: step8-adversarial-review, commit_sha: 1d1d752e12af732cbe9e4cd65f209ecc51cb4c83} (fresh independent subagent, opus/stronger-reasoning tier, separate from the refactor pass: 3 CONFIRMED findings fixed across commits 9372a16/6f1680e6/1d1d752e, each with committed regression tests -- see Skill audit evidence and ACM rows above. Deterministic-gate-scrutiny defeat-cases run live: xenon exclude narrowing (confirmed still catches a real regression) and the diff-oracle's own BASE_SHA trust boundary (found and closed a real hole))

claude added 2 commits August 29, 2026 19:42
…pe.py split (#1330)

Decomposes the re-verified Acceptance Criteria Map into 3 sequential
tasks: mechanical package split, internal decomposition of
check_shape()/_parse_manifest() to drop xenon complexity rank, and
the xenon --exclude update in .github/workflows/test.yml.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ko5RTxm3aEEN18AY9KNjf7
@tvna
tvna deployed to ruleset-verify August 29, 2026 19:46 — with GitHub Actions Active
@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a2fed2bd-d351-4af4-861a-7ebaf2b4d8ed


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.89554% with 24 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.56%. Comparing base (c967270) to head (3701af6).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...ing-skill-quality/scripts/shape_checks/manifest.py 98.39% 10 Missing ⚠️
...skill-quality/scripts/shape_checks/field_checks.py 95.65% 4 Missing ⚠️
...skill-quality/scripts/shape_checks/orchestrator.py 98.01% 3 Missing ⚠️
...ll-quality/scripts/shape_checks/citation_checks.py 98.97% 2 Missing ⚠️
...-skill-quality/scripts/shape_checks/frontmatter.py 96.66% 2 Missing ⚠️
...-quality/scripts/verify_shape_check_output_diff.py 97.67% 2 Missing ⚠️
...ity/scripts/shape_checks/execution_requirements.py 98.95% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1450      +/-   ##
==========================================
- Coverage   99.59%   99.56%   -0.03%     
==========================================
  Files         133      147      +14     
  Lines       23507    24042     +535     
  Branches     2840     2863      +23     
==========================================
+ Hits        23411    23938     +527     
- Misses         96      104       +8     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

tvna commented Aug 29, 2026

Copy link
Copy Markdown
Owner Author

CI status at head 635ff31 (the plan-file-only commit, before Task 1's work lands):

  • pytest-bash-oracle-task-pins failed: test_install_denied_via_command_substitution_literal_adjacency hit AssertionError: oracle timed out running: '$(echo pip) install foo'. This PR's diff at this point is a markdown-only task-list file (docs/superpowers/plans/2026-08-29-claude-gitapex-pr-1330-24wtvs.md) plus a merge from origin/main -- it touches nothing related to the bash-safety oracle or its subprocess timing. The same check's own latest run on main (2026-08-29T19:54:19Z) passed cleanly, and the job log shows unrelated runner-network timeouts around the same window (an agent.api.stepsecurity.io connection timeout), consistent with a transient CI-runner-load flake rather than a real regression. Not this PR's failure; re-ran the failed job once via actions_run_trigger to confirm.
  • independent-review-pending is expected to be red at this stage -- per this PR's own ## Merge gate: independent review note, it stays pending/failing until drafting-a-pr-to-merge's Step 8 records a verdict later in this branch plan's execution. Nothing to do here yet.

This PR is currently under active executing-a-branch-plan execution (Task 1 running) -- see the ## Execution log section and the branch-plan-executing label.


Generated by Claude Code

claude added 4 commits August 29, 2026 20:18
…y into shape_checks package

Mechanical, behavior-preserving move only -- check_shape()/_parse_manifest()'s
own internal decomposition is a separate follow-up task. Verified via a
differential output-diff script over every real skills/*/SKILL.md plus the
full existing test suite (zero test-content changes).

Also extends pyproject.toml's existing gitapex_check_skill_shape mypy
override (issue #684) to shape_checks.skill_dependencies: that module's
_skill_dependency_checks moved verbatim, carrying the one pre-existing
'operator' narrowing gap the override already covered under the old
module name. Verified individually -- every other shape_checks/*.py
submodule is mypy-strict-clean without it.

Known residual: tests/test_gitapex_skill_metadata_sidecar.py::
test_skill_dep_list_item_re_indent_matches_its_docstrings now fails
(StopIteration) because it scans css.__file__'s own source text for
SKILL_DEP_LIST_ITEM_RE's definition line, which now lives in
shape_checks/manifest.py instead. This is not a re-export gap (css.
SKILL_DEP_LIST_ITEM_RE itself still resolves); left unedited per this
task's explicit zero-edits constraint on the four protected test files.
See the task's own structured-output issues field for the proposed
one-line fix.

Refs #1330
…oved source files

test_skill_dep_list_item_re_indent_matches_its_docstrings and
_known_static_check_names() both scanned gitapex_check_skill_shape.py's
own physical source text for definitions that now live in
shape_checks/*.py submodules after the package split. Repoints both at
the correct source file(s); neither test's own assertions or verified
behavior changed.

Refs #1330
)

_parse_manifest and _execution_requirements_checks moved verbatim into
shape_checks/manifest.py and shape_checks/execution_requirements.py,
carrying their pre-existing rank-F complexity out from under the old
single-file exclude. Widens the exclude to shape_checks/* as an interim
state until the internal decomposition task narrows or drops it.

Refs #1330
@tvna
tvna deployed to ruleset-verify August 29, 2026 20:28 — with GitHub Actions Active

tvna commented Aug 29, 2026

Copy link
Copy Markdown
Owner Author

CI status at head ba0310c (Task 1's own commits, before Task 2 lands):

  • pytest-bash-oracle-task-pins and pytest-bash-oracle-hooks-pins both failed with the same symptom class: AssertionError: oracle timed out running: '<command>' (a different specific pinned command each time). This PR's diff at this head still only touches skills/evaluating-skill-quality/scripts/, .github/workflows/test.yml, and .gitapex/ssot.json -- nothing under hooks/ or the bash-safety oracle scripts. main's own latest run of both checks (2026-08-29T20:09:37Z) passed cleanly. Consistent with a transient CI-runner-load timeout on these subprocess-timing tests, not a regression from this PR. Attempted one re-run via actions_run_trigger; the API reports the workflow run itself is still in progress (403 This workflow is already running), so no further action needed here -- will re-check on the next CI event for this head.
  • skill-audit-disclosure failed: expected at this stage. This PR touches skills/evaluating-skill-quality/scripts/*.py, so it requires a checker-script-adversarial-review disclosure, which is deliberately deferred to executing-a-branch-plan Step 8's mandatory adversarial-review pass (not yet run -- Task 2/3 are still in progress). Will be resolved when Step 8 runs and the PR body's ## Skill audit evidence section is updated with the real verdict.
  • independent-review-pending failed: expected, per this PR's own ## Merge gate: independent review note -- nothing to do until drafting-a-pr-to-merge's Step 8 records a verdict.

Generated by Claude Code

tvna commented Aug 29, 2026

Copy link
Copy Markdown
Owner Author

coverage-combine failed at head ba0310c for a real reason (not a flake): the new skills/evaluating-skill-quality/scripts/verify_shape_check_output_diff.py (Task 1's own differential-verification tool) has 0.0% test coverage, and this repository enforces a 90% minimum coverage floor on every file under skills/evaluating-skill-quality/scripts/ (gitapex_gate_evals_scripts_coverage.py, reading pyproject.toml's [tool.coverage.run] source list -- no per-file exemption mechanism exists). This is this PR's own gap to close, not pre-existing debt.

Fix planned: add a dedicated test file for verify_shape_check_output_diff.py once the currently in-flight Task 2 (internal decomposition of check_shape/_parse_manifest/_execution_requirements_checks) finishes and frees the working tree -- queuing it as a follow-up task in this same branch-plan execution rather than interrupting Task 2 mid-flight.


Generated by Claude Code

claude added 2 commits August 29, 2026 23:05
…fest/_execution_requirements_checks

Internally decomposes the 3 named worst-complexity offenders into
smaller delegated functions, without changing any check's detection
logic -- verified via the existing differential output-diff script
(zero difference across all 29 real skills) plus the full test suite
(601 passed).

xenon impact (measured, no exclude): gitapex_check_skill_shape.py and
shape_checks/execution_requirements.py both dropped to module rank C
(from the original file's rank F); shape_checks/manifest.py's module
average is now within the xenon gate's own B threshold despite
_parse_manifest itself remaining rank E individually (down from the
combined CC 99/64 rank F baseline). Two modules (gitapex_check_skill_shape.py,
shape_checks/execution_requirements.py) still exceed the module-average
threshold -- narrowing the CI exclude to just these two is a follow-up
commit.

Refs #1330
@tvna
tvna deployed to ruleset-verify August 29, 2026 23:07 — with GitHub Actions Active
check_shape()/main() (gitapex_check_skill_shape.py) and
shape_checks/execution_requirements.py's own 3 functions are the last
complexity holdouts after issue #1330's split + internal decomposition
(task-2). Every other file under skills/evaluating-skill-quality/scripts/,
including shape_checks/manifest.py despite _parse_manifest itself staying
rank E, now passes the xenon gate with no exclude at all.

Refs #1330
@tvna
tvna deployed to ruleset-verify August 29, 2026 23:12 — with GitHub Actions Active
This PR's own new differential-verification tool (issue #1330) shipped
with 0% test coverage, failing the repo's 90% coverage-combine gate.
Covers each helper (module loading from a temp file, the OLD-module
git-show fetch, the result-tuple reduction) plus main()'s own PASS/FAIL/
crash-reporting branches via monkeypatched _load_old_module/_load_new_module,
so the tests do not depend on the branch's real BASE commit or a real
git-show call. One @pytest.mark.slow end-to-end test still exercises the
real pipeline against this repository's actual git history and working
tree.

Refs #1330
@tvna
tvna deployed to ruleset-verify August 29, 2026 23:15 — with GitHub Actions Active
claude added 3 commits August 29, 2026 23:36
…ointers

Post-split cleanup pass over the shape_checks/ package: no detection
logic, evidence string, rule string, or check order is touched --
verify_shape_check_output_diff.py stays byte-identical across all 29
skills.

Two things the three separately-dispatched split tasks left behind:

1. An over-broad mypy exemption. The split widened one
   [[tool.mypy.overrides]] block to cover both gitapex_check_skill_shape
   and shape_checks.skill_dependencies with the UNION of the two modules'
   disabled error codes. Measured per module, each needs a strict subset:
   the hub needs only attr-defined/arg-type (its "operator" site left with
   _skill_dependency_checks and its "no-untyped-call" sites left with
   check_shape's lambdas, which orchestrator.py now annotates explicitly),
   and skill_dependencies needs only arg-type/operator. Split back into
   two blocks so each lists what its own module actually produces -- a
   newly introduced error of a code a module no longer emits is caught
   again instead of being silently absorbed.

2. Eleven in-file cross-references falsified by the move. Each was true
   while the checker was one file and points at the wrong place now:
   "this file's own EXEC_REQ_NETWORK_MODES" (constants.py),
   "this file's own skill-md-readable check" (orchestrator.py),
   "the references/ loop below this function" (orchestrator.py),
   "_SENTENCE_SPLIT_RE, this file's own sentence tokenizer" and the
   matching "e.g." over-split tolerance note (both constants.py),
   "requires-portability-compatible is checked elsewhere in this file"
   (skill_dependencies.py), "all three abspath calls in this file" (two
   remain in field_checks.py, the third moved to the hub, whose own
   dangling "Same waiver:" now names its source), "this file's four
   dangling-reference resolve checks ... exactly one implementation in
   this file" (now four modules, one package), "first check in this file"
   (orchestrator.py), and two "already report above" comments in
   orchestrator.py naming checks that stayed in check_shape.

Verified: verify_shape_check_output_diff.py PASS (29/29 identical); the
four shape-check test files 615 passed; tests/ 5062 passed;
skills/evaluating-skill-quality/scripts/ 730 passed; ruff check, ruff
format --check, mypy (all seven directory groups) and the xenon
complexity ceiling all clean.

Refs #1330
@tvna
tvna deployed to ruleset-verify August 29, 2026 23:39 — with GitHub Actions Active
claude added 3 commits August 29, 2026 23:51
…#1330)

Adversarial review (executing-a-branch-plan step 8) found a real coverage
narrowing this PR itself caused. no-voodoo-constant and
script-execution-intent-stated enumerate a skill's bundled scripts with a
non-recursive scripts_dir.iterdir(). The non-recursion pre-dates this PR,
but this PR moved ~5000 lines out of scripts/ into a NEW scripts/shape_checks/
subdirectory that iterdir() cannot see -- constants.py (955 lines of nothing
but module-level constants) among them. Every one of those constants fell
out of no-voodoo-constant's scope overnight, without a single check changing.

Verified live, not reasoned: an uncommented constant appended to
shape_checks/constants.py is reported PASS/none by the pre-fix checker and
FAIL/scripts/shape_checks/constants.py:957:... by the fixed one.

Both scans now use scripts_dir.rglob, matching the convention this same
skill's own sibling scanner already established for the identical question
of what a skill's bundled Python scripts are
(gitapex_scan_execution_requirements_drift.py's _bundled_script_trees:
recursive, test_* excluded by basename at any depth, offenders reported by
path relative to scripts_dir because a same-named module can exist in two
subdirectories). _is_ignorable drops dotfiles and __pycache__ -- load-bearing
for the any-extension scan, which would otherwise treat compiled .pyc
bytecode as a bundled script. Offenders are now labelled by path relative to
the skill directory; byte-identical to the old bare scripts/<basename> form
for a flat script.

Detection outcome on this repository's real corpus is unchanged: the
recursive scan finds zero new offenders across all 29 skills, so
verify_shape_check_output_diff.py still reports byte-identical OLD/NEW
output. Five regression tests pin the recursive scope, the at-any-depth
test_* exclusion, the __pycache__ junk filter, and both the nested and flat
evidence labels.
…ff oracle (issue #1330)

Adversarial review found a silent defeat of this PR's own load-bearing
verification. verify_shape_check_output_diff.py fetches the "OLD"
pre-refactor checker with git show BASE_SHA:<path>. Point BASE_SHA at any
POST-split commit and that source is itself shape_checks/-backed: its own
from shape_checks... imports resolve against the same live, on-disk package
the NEW module uses (this script's directory is on sys.path), so OLD and NEW
run identical code and agree unconditionally. The oracle then reports a
clean PASS while proving nothing.

Reproduced live, not theorized. With a deliberate evidence-string regression
injected into shape_checks/orchestrator.py:
  - real BASE_SHA        -> exit 1, all 29 skills reported as differing
  - BASE_SHA moved to a post-split commit -> exit 0, PASS on all 29 skills
Same working tree, same regression, opposite verdict.

_assert_pre_split_source now refuses any fetched OLD source carrying a
shape_checks import, before that source is written out or imported. Matched
as an import statement, not a bare substring, so a prose mention of the
package name in a future pre-split revision cannot trip it -- the import is
what actually makes the comparison vacuous. Raising rather than warning: a
gate that cannot fail is worse than no gate, and propagating out of
_load_old_module is the contract that helper already has for a git show
failure.

Seven regression tests: the guard accepts a stdlib-only pre-split source,
tolerates a prose mention, rejects three post-split import spellings, fails
loudly out of _load_old_module without leaving a half-materialized OLD source
behind, and -- the case that would have caught this class of drift on its own
-- asserts the committed BASE_SHA constant itself still resolves to a
pre-split revision, so the existing end-to-end test cannot start passing for
the wrong reason.
…er (issue #1330)

verify_shape_check_output_diff.py detects a pure check-ORDERING regression
(list comparison is order-sensitive, exit 1) but reports it with an entirely
empty body. Both the OLD-only and NEW-only lists are membership-based
(r not in new_results), so both come back empty whenever the two sides hold
the same result tuples in a different order, and the result-count line does
not fire either because the lengths match. The operator is left with a bare
"OLD and NEW check_shape() output differs." headline and nothing else, on a
gate whose entire job is to say WHAT changed.

Reproduced with two same-length, reordered result lists: exit 1, headline
only, zero detail lines.

This is not a hypothetical shape for this branch. Check order is explicitly
part of the contract this script asserts ("same check name, passed, rule,
and evidence, in the same order"), and reordering results is precisely what
decomposing check_shape() into per-section helpers can get wrong -- the one
regression class the oracle would flag while telling you nothing about it.

The mismatch branch now falls back to the first positional divergence when
neither side has a unique result, printing the index and both tuples. zip
uses strict=False deliberately: the two lists can legitimately differ in
length here (one a strict prefix of the other), which is a diff to report,
not an exception to raise out of the reporting path.

Two regression tests: a pure reorder produces the index and both tuples, and
an ordinary evidence-value difference still takes the OLD-only/NEW-only path
without picking up the reorder wording, so a value change is never
mislabelled as an ordering one.
@tvna
tvna deployed to ruleset-verify August 30, 2026 00:06 — with GitHub Actions Active
@tvna
tvna marked this pull request as ready for review August 30, 2026 00:08
@tvna tvna removed the branch-plan-executing label Aug 30, 2026 — with Claude
…-execution-intent check

drafting-a-pr-to-merge Step 8's inner-layer review (reviewing-an-artifact,
correctness axis) found and live-verified a false negative introduced by
the earlier recursive bundled-script-scan fix (commit 9372a16): once
`_bundled_scripts` scans `scripts/` recursively, two scripts in different
subdirectories can share a basename (e.g. `scripts/bar/tool.py` and
`scripts/foo/tool.py`). `_script_execution_intent_offenders` matched a
doc's "Run `tool.py`" mention purely by bare filename, so documenting one
of the colliding files silently satisfied the check for every other
same-named file too -- an undocumented script could hide behind an
unrelated, documented namesake in a different directory.

Fixes it by treating any basename shared by 2+ scripts as ambiguous: such
a basename can never be marked satisfied via the Run/See paragraph match,
so at least one representative of the colliding group is correctly
flagged (the pre-existing filename-keyed dedup still reports the group
once, not once per file). Re-verified: differential output-diff oracle
still PASS across all 29 real skills (no real skill has this collision),
829 targeted tests green, mypy/ruff clean, xenon clean.

Also fixes a dangling docstring cross-reference in links_portability.py's
`_is_bare_skill_name` ("see the module docstring") left over from the
split -- the module docstring it pointed at says nothing about
stdlib-only design; the 12th instance of the same drift class commit
07d3d11 already fixed 11 other occurrences of.

Refs #1330
@tvna
tvna deployed to ruleset-verify August 30, 2026 00:37 — with GitHub Actions Active
drafting-a-pr-to-merge Step 8s fresh follow-up review (a second,
independent dispatch scoped to commit 379c0fd own small diff)
confirmed the fix sound but flagged it as shipping with no regression
test -- this repository own defeat-test-disclosure convention.

Adds three tests: the false-negative-closed case (an undocumented
scripts/foo/tool.py no longer hides behind a documented, same-named
scripts/bar/tool.py), the disclosed false-positive trade-off (both
colliding files individually documented are still flagged, since the
bare-basename token cannot tell them apart), and a control proving
non-colliding basenames are graded exactly as before.

Refs #1330
@tvna
tvna deployed to ruleset-verify August 30, 2026 00:42 — with GitHub Actions Active
@tvna
tvna marked this pull request as draft August 30, 2026 00:55
@tvna
tvna marked this pull request as ready for review August 30, 2026 02:28
@tvna
tvna merged commit aa33e6f into main Aug 30, 2026
35 of 38 checks passed
@tvna
tvna deleted the claude/gitapex-pr-1330-24wtvs branch August 30, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(evaluating-skill-quality): split gitapex_check_skill_shape.py, already excluded from the complexity gate at 6149 lines

2 participants