Skip to content

feat(sdk-review): foundation — libs + config + test harness#211

Draft
tiagoek wants to merge 14 commits into
mainfrom
feat/sdk-review-foundation
Draft

feat(sdk-review): foundation — libs + config + test harness#211
tiagoek wants to merge 14 commits into
mainfrom
feat/sdk-review-foundation

Conversation

@tiagoek

@tiagoek tiagoek commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Description

Foundation for the SDK Module Review skill (AFSDK-3937): shared bash/python libraries, config schema, and bats test harness. No behavior change — nothing runs against PRs from this PR alone.

Composes together with #212 (the skill).

Addresses maintainer review (2026-07-07)

All 7 in-scope defects flagged by @bohn-review resolved on this branch:

  • Bug 2rules.yaml.baseline.file now points to the actual location .claude/config/baseline.json (was pointing to .claude/baseline.json)
  • Bug 3 — Rule IDs unified. baseline.json no longer uses PY-/JV- prefix; matches the agnostic form in rules.yaml. Regression test test_baseline_contract.bats asserts the contract.
  • Bug 4 — HTML marker <!-- sdk-review:v1 documented as an intentional prefix (matches many concrete markers like <!-- sdk-review:v1 kind=summary --> via jq contains()).
  • Bug 5hunk-filter.sh and peer-consistency.sh moved to foundation (they are shared libs, not skill-only).
  • Bug 6baseline.json at_commit resolved to the actual origin/main SHA at baseline creation. Added _documentation key explaining the semantic.
  • Bug 7 — Naming inconsistency ast_python_checks.py (file) vs ast-python-checks.py (docstring) normalized to underscore.
  • Bug 8 — Bats tests moved from tests/sdk-review/ to .claude/tests/, keeping the skill self-contained under .claude/ and out of the product test tree.

Bug 1 (rebase on main) deferred to a supervised window — Python pyproject.toml version bump is trivial to resolve, but Java pom.xml conflict resolution needs a careful eye. Will do both together in a follow-up.

What's in this PR

  • .claude/scripts/lib/ — 15 helper libs (JSON emit, tier manager, hunk filter, peer consistency, predicates, baseline snapshot, module aliases parser, GitHub API wrapper, self-skip, suppression, AST helpers, breaking-change detector)
  • .claude/config/rules.yaml, baseline.json, module-aliases.yaml
  • .claude/tests/ — bats harness (test_smoke.bats, test_extended.bats, test_baseline_contract.bats) + fixtures

What's NOT in this PR

Tests

bats .claude/tests/ — 60 tests, all green. Some tests intentionally skip when they need a check script from #212; that's the stack contract.

Related: internal tracking AFSDK-3937.

tiagoek added 14 commits July 7, 2026 17:19
This branch collects incremental sub-PRs for the SDK Module Review skill.
Sub-PRs target this branch; a final PR will merge everything into main.

Batches (see docs/plans/AFSDK-3937/06-INCREMENTAL-DELIVERY.md):
- batch-1: Foundations (libs + config)
- batch-2: AST + detectors
- batch-3: Safety-first checks (secrets, license, disclosure, hardcode, telemetry)
- batch-4: Structural checks (docs, bdd, patterns, versioning, commits)
- batch-5: Depth checks (testing, errors, http, concurrency, deletion, deps, constants, binding, quality-gate, pr-size)
- batch-6: Wire-up (orchestrate, aggregate, workflow, docs, CONTRIBUTING amendments)

Ref: AFSDK-3937
Adds the foundation for the SDK Module Review skill:

## Libs (.claude/scripts/lib/)
- json-emit.sh — findings JSON emitter + status derivation
- diff-added-lines.sh — extract file:line pairs from diff (BSD-safe)
- baseline.sh — apply baseline.json exemptions to reports
- predicates.sh — scope predicates (commit_types, module_shape, REUSE.toml)
- suppression.sh — parse # sdk-review: ignore[<check>] comments
- apply-suppression.sh — filter reports by suppression tuples
- github-api.sh — gh CLI wrapper (auth, comments, check-run, labels)
- detect-language.sh — Python vs Java detection
- detect-modules.sh — module extraction from diff
- tier-manager.sh — apply SHADOW/FLAG/BLOCK/BLOCK_LOCKED tiers
- skill-self-skip.sh — self-review protection (skip skill's own files)
- ast_python_checks.py — Python AST checks (used by errors, telemetry, patterns, constants)
- breaking-detector.py — API-diff detector for BREAKING family

## Config (.claude/config/)
- rules.yaml — 70+ rules with tiers per rule
- module-aliases.yaml — cross-language module name aliases (dms↔documentmanagement)
- baseline.json — per-repo exemptions (REUSE.toml here → LIC-01/02 exempt)

**Standalone testable.** No checks or orchestrator yet — comes in later batches.

Part 1 of 6. Ref: AFSDK-3937
Explain why the alias file contains only one pair (dms ↔ documentmanagement):
after auditing both SDKs, that's the only cross-language module today whose
Python and Java names disagree. Same-name modules (destination, objectstore)
don't need entries — the resolver falls back to the identical name. Include
the full module inventory so future contributors know when to append here.
Adds 57 bats tests + 6 fixture diffs. Tests exercise the libs from batch 1.
All check-specific tests use conditional skip guards so tests skip cleanly
when scripts are not yet present in the current batch.

Part 2 of 6. Ref: AFSDK-3937
The prior comment listed the module inventory as of 2026-07, which:
- Confused readers (looked like the aliases list was incomplete)
- Would age fast (SDK gains modules; comment would drift)
- Duplicated what check-bdd.sh already discovers dynamically from src/

Keep the file to the minimum it needs to do its job: explain what the alias
map is, when to add entries, and the one real cross-language rename today
(dms ↔ documentmanagement). Module discovery is dynamic — no manual list.
The prior 'dms ↔ documentmanagement' alias was speculative: the Java repo
has never had a 'documentmanagement' module. The comment on this file
already stated the correct rule ('add an entry in the SAME PR that
introduces the divergent-name module') — the initial entry violated that
rule by preempting a module that doesn't exist.

Empty the list. Whoever creates 'documentmanagement' on the Java side (or
any other cross-language divergent-name module) adds the alias in that PR.

Discovery of module names is dynamic in check-bdd.sh — the empty list is
the correct starting state.
…nfig/baseline.json

The baseline.file field pointed to .claude/baseline.json but the actual
JSON lives at .claude/config/baseline.json (co-located with rules.yaml
in the config dir). Any consumer of the rules.yaml baseline reference
would have failed to find the file.
…olved

Bug-3: strip PY-/JV- prefix from every rule key. rules.yaml uses agnostic
LIC-01/LIC-02 as canonical rule IDs; baseline.json had drifted to
PY-LIC-01/JV-LIC-01/etc, meaning baseline.sh is_in_line_baseline lookup
never matched. Remove JV-* entries entirely (they belong to cloud-sdk-java's
own baseline, not the Python repo's).

Bug-6: at_commit was 'TBD' placeholder. Resolve to origin/main SHA at
baseline creation time (d19427f). Add top-level _documentation key
explaining the semantic invariant — baseline snapshots pre-existing debt
against canonical main, not against a drifting foundation branch.
Add bats regression test asserting:
1. baseline.json is valid JSON
2. Every rule key in .exemptions appears in rules.yaml
3. at_commit is a real git SHA (not TBD placeholder)

Guards against the drift Bohn caught in review — where baseline.json used
PY-LIC-01 while rules.yaml used LIC-01, causing baseline lookup to always
fail silently.
Empirical dry-run against the 19 open PRs (see docs/plans 09-FP-REMEDIATION)
showed the v2 hunk-attribution primitive was specced but never wired: 84% of
Python findings fired on lines the PR did not touch. This helper closes that
gap. Individual check-*.sh scripts will consume is_line_touched / is_range_touched
in a follow-up commit (per-check surgery to avoid one giant diff).

Both helpers are permissive when $ADDED_LINES_FILE is unset (bats
tests use synthetic diffs without the orchestrate wrapper) so nothing regresses
in the isolated test harness.
peer-consistency.sh is a shared library (like hunk-filter, tier-manager,
predicates). It belongs alongside the other libs in foundation, not
downstream in the skill branch. Moving here so PR reviewers see the
building blocks in the right layer.
…here

File on disk is ast_python_checks.py (Python convention). Docstrings and
bats test descriptions were using ast-python-checks (hyphen), creating
noise for any grep-based automation or reviewer trying to match the
filename.
Per Bohn review — bats tests were sitting in tests/sdk-review/ which
polluted the product test tree (pytest CI runs against tests/, this
tooling uses bats). Moving to .claude/tests/ keeps the skill self-
contained under .claude/ and out of the product test space.

BATS_TEST_DIRNAME hop counts unchanged (both paths are 2 levels deep
from repo root). Verified all 60 bats tests still green.

skill-self-skip.sh: .claude/* already covers .claude/tests/* — kept
legacy tests/sdk-review/* line as belt-and-suspenders.
@tiagoek tiagoek force-pushed the feat/sdk-review-foundation branch from dfb70d7 to f427f66 Compare July 7, 2026 20:59
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.

1 participant