用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/laicluse/agent-fieldkit --skill upstream命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | upstream |
| description | Internal drydry cross-toolbox audit for helpers duplicated by frameworks or libraries. |
| allowed-tools | ["Agent","Read","Glob","Grep","WebSearch","WebFetch(*)","Bash(rg *)","Bash(grep *)","Bash(find *)","Bash(ls *)"] |
The cross-toolbox audit pass behind the drydry pipeline. The premise: DRY violations between operator code and framework code are invisible from a single-codebase view. A homegrown current_user helper looks fine until you remember Devise ships one; the silent drift risk surfaces at the next Devise upgrade. Not user-invocable.
Caller supplies through args:
project_root: path to the project root. Mandatory.framework_hint: optional name of a specific framework to audit (devise, active-job, swiftui, combine, react-router, tanstack-query, ...). When absent, the skill auto-detects from manifests.scope: optional sub-directory; when provided, the audit is limited to that scope.max_helpers_per_framework: optional cap, default 10. Prevents one framework with broad surface from dominating.Return a markdown section the orchestrator folds into the audit artefact:
## Upstream duplication
### Framework: <framework_name> <version_if_known>
- Finding 1
- operator_helper: `<path>:<line>` `<symbol_name>`
- upstream_offering: `<framework_module>.<symbol>` (cite the docs URL)
- duplication_kind: identical | partial | semantic
- drift_hypothesis: <one sentence; the Chapter 4 test must pass>
- upgrade_risk: <what breaks when the framework version moves>
- convergence_path: <replace operator helper with upstream | wrap upstream | keep as documented divergence>
- verifier_command: <runnable command to re-find both sites>
Findings without a verified upstream offering (the verification check failed) are dropped.
When a framework is detected but no findings survive verification, emit the header alone with an explicit empty marker so the orchestrator's fold-in step does not silently omit the framework:
### Framework: <framework_name> <version_if_known>
_no upstream duplications found; the verification pass dropped every candidate. See "## Detection method chosen" for which candidates were inspected._
Walk project_root for known manifest signatures:
| Manifest | Frameworks to consider |
|---|---|
Gemfile / Gemfile.lock | Rails, Devise, Pundit, CanCanCan, Sidekiq, Active Job, dry-rb, RSpec, FactoryBot |
Package.swift / *.xcodeproj | SwiftUI, UIKit, Combine, swift-collections, Vapor |
package.json | React, Next, Remix, TanStack Query, React Router, Vue, Svelte, lodash, date-fns |
pyproject.toml / requirements.txt | Django, Flask, FastAPI, SQLAlchemy, pydantic |
Cargo.toml | actix, axum, serde, tokio |
go.mod | gin, echo, chi, sqlx |
When framework_hint is set, audit only that framework; skip auto-detection. When auto-detecting, parse the manifest and pick the three to five most load-bearing frameworks (the ones whose absence would break the project).
For each framework selected, identify the operator's helper-shaped code: standalone utility modules, "helpers/" directories, Extensions.swift-style files, lib/ directories. Run a grep with framework-relevant signatures (def current_user, func authenticated, useAuth, useToast, formatDate, ...) to find candidates.
Each candidate becomes a tuple (helper_path:line, symbol_name, surface) for the duplication reviewer.
For each framework, decide first whether a live search pass is necessary. The discipline is "verify against the pinned framework version", not "fetch documentation every time". When the project's lock file (Gemfile.lock, Package.resolved, package-lock.json, pyproject.lock) hash for this framework matches the hash recorded in the cache file <project_root>/.drydry/upstream-cache/<framework>-<pinned-version>.md, reuse the cached findings and skip the live search. Invalidate and re-run the live search when (a) no cache exists for this framework or version, (b) the lock-file hash differs, or (c) the pinned version is newer than the current model's training cutoff (in which case the cache cannot be trusted and the search is needed for ground truth).
When a live search is needed, use the host's native research/review capability with this brief (inspire-style for the discovery, ground-style for the verification). In Claude Code this can be an Agent tool pass with WebSearch/WebFetch; in Codex use native browsing/subagents when exposed, otherwise perform the research in the current session and record that limitation in the returned method notes:
You audit a project for duplication of <framework> functionality.
Operator helpers (candidates): <list of tuples>
Tasks:
1. For each candidate, search the <framework> documentation
with browsing/search for an upstream symbol that does the same
job. Cite the canonical docs URL.
2. ground-style verification: confirm the symbol actually exists in
the version of <framework> the project pins (read Gemfile.lock,
Package.resolved, package-lock.json). If you cannot verify the
symbol exists in the pinned version, mark the candidate dropped
and explain why.
3. Classify duplication: identical (operator helper is a thin wrapper
matching upstream signature), partial (overlap with extra concern),
semantic (same purpose, different shape, Type-4).
4. Write a drift hypothesis: what bad thing happens when the
framework version moves and the operator helper does not?
5. Produce a verifier_command (rg or grep) that re-finds both sites.
Return one finding per verified candidate. Drop unverified candidates.
Drop candidates where the duplication is genuinely deliberate (the
operator's helper adds value the upstream does not provide; explain
in one sentence).
Apply max_helpers_per_framework per framework. Write the per-framework findings to <project_root>/.drydry/upstream-cache/<framework>-<pinned-version>.md with a header line that records the lock-file hash; this is what step 3's cache gate will read on the next run. Return the assembled markdown to the caller.
These are seed examples the review brief includes so the search has direction:
current_user helpers that mirror Devise's current_<scope>before_action :authenticate! chains that duplicate Devise's authenticate_<scope>!retry_on from Active Jobassert_difference-style helpers that duplicate ActiveSupport's assert_changesparameterize.task { } wrappers around URLSession that duplicate async/await URLSession APIsObservableObject patterns that duplicate @Observable macro behaviour (Swift 5.9+)Date.FormatStyleString(localized:)useAsync hooks that duplicate TanStack Query's useQuerypermission_requiredannotate / aggregateclean_* patternsThe reviewer uses these as priors, not a closed list.
ground-style discipline). The operator's pinned version, not the latest version.