timholy/claude_config/review-integration
Claude Code and agent skill by timholy/claude_config
- community
Checking that the SKILL.md file is still in the repository.
Review a Julia package for dependency-interface compliance, latent bugs, and user friction by reading source, tests, and docs directly
Install
npx vskill@latest install timholy/claude_config/review-integrationSKILL.md
Review the Julia package in the current working directory for issues that the structured /review-design and /review-api skills are designed not to surface. Those skills work from distilled artifacts (a conceptual map, an API inventory) and explicitly assume the code is correct and idiomatic. This skill is the deliberate inverse: read source, tests, and documentation directly, and look for things that only become visible inside the implementation and at the package's seams with the outside world.
Three focus areas:
- Dependency-interface compliance — for each declared dependency, is the package using that dependency's public API correctly and idiomatically? Does the package implement the interfaces it claims to support (Tables, AbstractTrees, AbstractArrays, Iterator protocol, etc.) completely and consistently?
- Latent bugs and suspicious code — paths that look wrong, error handling that masks failures, off-by-ones, type instabilities that change semantics (not just performance), tests that pass for the wrong reason.
- User friction — the kind of paper cuts that don't violate any convention but make the package annoying to use: bad error messages, missing convenience constructors, common tasks that take N steps when they should take one, undocumented preconditions, examples that don't run.
This skill produces a tiered report and an INTEGRATION_REVIEW_PLAN.md that decomposes the agreed-upon findings into chunks consumed by the companion /review-implement skill. Do not implement any changes in this skill — that is /review-implement's job.
The package module name is determined from Project.toml.
Phase 0 — Size preflight
This skill reads source/tests/docs into the main context (unlike /review-design and /review-api, which delegate the bulk read to a distillation subagent). Cost therefore scales with package size, and depth of analysis degrades when the model is asked to read too much in one pass.
Measure the total character count across src/, ext/, test/, docs/src/, README.md, and any examples/ directory:
Apply the attention ceiling (window-independent — reflects how much source the model can read carefully in one pass, not how much fits):
- Under ~250K chars total: proceed to Phase 1 as written.
- ~250K–500K chars: surface the size to the user and offer a strategy menu before proceeding:
- (a) Restrict scope to one or two of 2a–2f (which areas matter most to you?).
- (b) Restrict scope to a subdirectory of
src/(e.g., one major submodule). - (c) Use an
Explore-style subagent for targeted queries per check (loses the "one careful reading pass" benefit but preserves coverage). - (d) Proceed anyway with the understanding that depth will suffer — acceptable for a first-pass scan, not for a thorough review.
- Above ~500K chars: refuse the default mode. Require the user to pick (a), (b), or (c). Do not pretend to do the full review.
These thresholds are about attention, not context capacity: a large context window lets more source fit, but it does not make one careful reading pass of 500K characters any more reliable. If the user wants to push past them, that is their judgment call, and the report should say so.
Record the measurement and the chosen strategy in one line at the top of the eventual report (e.g., "Phase 0: 312K chars total; user chose strategy (a), focusing on 2a and 2c").
Phase 1 — Read directly
Do not invoke pkg-conceptual-mapper or julia-api-inventory — they would defeat the purpose. Instead, read directly:
Project.toml— note every[deps]entry and its declared[compat]bound. These are the dependencies whose interfaces the package consumes.- All files in
src/. Read implementations, not just signatures. Noteusing/importstatements per file — which dependency-provided symbols are actually used where. test/— the test suite is documentation of intended behavior and a good place to spot tests that pass for the wrong reason.README.md,docs/src/, and anyexamples/— the user-facing surface. Examples that no longer run, or that demonstrate awkward idioms, are friction.
For large packages, prioritize: files most central to the package's purpose first, then peripheral utilities. If a file is clearly machine-generated or vendored, note it and move on.
Phase 2 — Checks by focus area
2a. Dependency-interface compliance
Out of scope — delegated to deterministic tooling, do not duplicate:
- "Does the package import non-public symbols from a dependency?" → ExplicitImports.jl (
/freshen-explicit-imports) catches this reliably acrossusing/importand qualified-access forms. - "Are there declared dependencies no longer used in source?" → Aqua.jl's
test_stale_deps(/freshen-aqua) catches this.
If the user has not yet run those skills on this package, mention it in the report's preamble and recommend running them — but do not attempt the same analysis by hand in this skill. Doing so produces noisier, less reliable findings than the tools, and wastes the reading-pass budget on a problem that is already solved.
In scope — qualitative dep-usage questions tooling cannot answer. For each [deps] entry, identify what kind of dependency it is and apply the relevant checks:
- Interface packages (Tables, AbstractTrees, ArrayInterface, SciMLBase, MLJModelInterface, CommonSolve, StatsAPI, etc.): does the package implement the full interface required for its types to function with the broader ecosystem? E.g., a "Tables-compatible" type that defines
Tables.istableandTables.rowsbut notTables.schemawill silently fail in some downstream consumers. Look up the actual interface contract — do not guess. - Generic programming via interfaces and traits, vs representation-dependent code. This is the most valuable check in 2a and the one most worth thinking carefully about. Look for places where the package writes hand-rolled methods that depend on a concrete representation when a generic interface would do. Symptoms:
for i in 1:length(v); v[i]; ...instead offor x in vorfor i in eachindex(v). The explicit-index form silently breaks forOffsetArrays, sparse iteration, generators, etc.if A isa Matrix ... else ... endbranches that could be handled by dispatching onAbstractMatrixor a trait (IndexStyle,ArrayInterface.parent_type).- Direct field access (
x.foo) on a type owned by another package, when an accessor function exists. Field layouts are not API. - Methods specialized on
Vector{T}/Matrix{T}/Arraywhen the operation works for anyAbstractArrayand would benefit from being callable with views, GPU arrays, sparse arrays, dual numbers, etc. (See the user's CLAUDE.md guidance on argument annotations — overly-restrictive types silently exclude valid inputs.) - Hand-coded property dispatch (
Symbol-keyedif/elseif) where multiple dispatch on a wrapper type would be more idiomatic. - Numerical/algorithmic packages (LinearAlgebra, SparseArrays, Statistics, FFTW): is the package using the right entry point? Hand-rolled loops where a Base/stdlib function would do are often less stable as well as slower. Conversely: is the package using a high-level entry point when a lower-level one would compose better with the caller's chosen factorization or storage format?
- Container/iterator packages (DataStructures, OrderedCollections, IterTools): is the package using public constructors and accessors? (Internal-field access is caught by ExplicitImports for qualified accesses, but unqualified field-access on a value of a dep type — e.g.,
x.internal_fieldafterx = SomeDep.Foo()— is not always caught and is worth a manual check.) - Logging, Printf, Dates, Random: standard pitfalls —
printlnin library code (instead of@info/@debugor writing to a passedIO),rand()without a passed RNG (breaks reproducibility for callers),now()instead ofDates.now(UTC)for stored timestamps, etc.
Also check [compat] bounds: is the lower bound of a dependency so old that the package is forced to avoid newer, better APIs? (The inverse — too tight upper bounds — is a separate maintenance question, not an integration concern.)
2b. Implementations of standard Julia interfaces
Independent of declared dependencies, check the package's own types against the implicit interfaces of Base:
- Iterator protocol: if
iterateis defined, arelength/sizedefined when knowable, andIteratorSize/IteratorEltypetraits set when the defaults are wrong? - Indexing: if
getindexis defined, arefirstindex/lastindexdefined? Doesaxesreturn something sensible foreachindexto consume? - AbstractArray subtypes:
size,getindex,setindex!(if mutable),IndexStyle— and do operations likesimilar,copy, broadcasting actually work, or do they fall through to a wrong default? ==defined without matchinghash(Base's==/hashcontract — review-design checks this from the map; here, look for it insidesrc/).showmethods: doesshow(io, ::MIME"text/plain", x)exist for types a user will actually see in the REPL? Doesshow(io, x)produce something parseable or at least round-trippable?convertand constructor methods that return the wrong type: as long asTis concrete, the contract should almost always beconvert(::Type{T}, x)::T(i.e., it should return aT). Example:convert(Vector{Real}, list)should never return aVector{Int}even iflistcontains nothing butInts. However,convert(Real, x)can return anIntsince all instances must have concrete type andRealis not concrete.
2c. Latent bugs and suspicious code
Read with a skeptical eye. Things to flag:
- Bare
catchclauses that swallow exceptions, orcatch eblocks that log-and-continue when the operation cannot meaningfully proceed. tryblocks with nofinallyaround a resource (file handle, lock) that needs deterministic cleanup.- Floating-point comparisons with
==where≈/isapproxis intended. - Off-by-one risks at boundaries (
1:length(x)whereeachindex(x)would be safer;for i in 1:n-1patterns). - Type-unstable code where the instability changes semantics, not just performance — e.g., a function that sometimes returns
Intand sometimesVector{Int}depending on input. - Mutation of a shared default argument value (
function f(x, buf=Float64[])— every caller shares the same buffer). - Tests that assert nothing meaningful:
@test foo(x) !== nothing,@test_nowarnaround a function that never warns anyway, tests that would pass even if the implementation werereturn input. @assertused for input validation (gets compiled out under--check-bounds=noin some settings —throw(ArgumentError(...))is the right tool).eval/@evalat runtime in performance-sensitive paths.- World-age hazards:
@evalfollowed by an immediate call within the same function.
For each, name the file and line, quote the relevant snippet, and explain the failure mode. Distinguish "definitely a bug" from "smells like a bug, worth a closer look."
2d. User friction
Read the README and examples as if you have never seen this package before. For each common task the package supports, count the steps. Flag:
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/review-integration/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/timholy/claude_config/review-integration)