| name | setup |
| description | Use when a repository needs rwyn fully set up: an initial `.rwyn/config.yaml`, declarative `plugins:` transforms, coverage step wiring, representative probes, and setup notes. Trigger for requests about bootstrapping rwyn, adding repo-specific relations like interface-to-source links or generated bindings, or teaching rwyn how a repo is laid out. |
Setup
Use this skill to fully set up or evolve rwyn in a repo. A setup request means
"make rwyn reasonable here" unless the user explicitly narrows the task.
Setup Workflow
- Run
rwyn setup and treat its raw-source inventory as the first evidence packet.
- Read authoritative docs and root command surfaces before writing config.
- Read CI as evidence for what the repo enforces, not as truth to import mechanically.
- Extract a short requirements list first. Do not start by writing commands.
- Build a CI surface ledger and classify every independently scheduled job
before calling the first model complete.
- Map concrete steps to those requirements.
- Start with one
.rwyn/config.yaml.
- Add the fewest steps needed for the first useful model, then continue through
linkages, probes, and coverage before calling setup done.
- Add
plugins: for repo structure the adapters cannot infer on their own.
- Run
rwyn setup inspect after each meaningful config/plugin pass. Treat it
as a factual dossier for the agent: observed repo surfaces, configured model,
coverage evidence, and schema-level alignment gaps. It should not grep for
magic words or infer repo intent from loose text; use the raw source inventory
to run your own searches and make the judgment. Resolve, document, or
intentionally ignore the pointers; do not expect rwyn to make product
judgment for you.
- Add coverage steps for scopeable verification steps and collect initial
coverage data. Start long-running coverage jobs when they are part of the
repo's real verification surface.
- Validate with
rwyn doctor, rwyn build, and representative rwyn plan
and rwyn explain probes.
For a brand-new .rwyn/config.yaml, probe both --uncommitted and --staged
when useful: uncommitted catches first-time files, staged isolates the setup
branch before committing.
Core Boundary
Do not move repo-specific heuristics into rwyn core. If setup exposes a missing
capability, add a generic config or plugin mechanism, then encode the
repository-specific relationship in .rwyn/config.yaml, plugins:, or setup
notes.
Core should provide primitives such as generic step execution, standard artifact
parsers, plugin transforms, graph/runnable semantics, and diagnostics. Repository
layout, custom test scopes, tool-manager invocation, generated-artifact links,
and product-specific commands belong in configuration.
Done Means
Do not stop at a generated config. Setup is complete only when the repo has:
- a checked-in
.rwyn/config.yaml candidate with requirements, stages, steps,
tools, env contracts, inputs, outputs, and coverage steps
- a CI surface ledger where every enforced job is classified as exact,
decomposed, broad substitute, intentionally ignored, infra-only, or unknown
- declarative
plugins: for durable hidden structure such as interface links,
generated bindings, snapshots, lockfiles, test-scope conventions, or package
ownership
- a built graph and a passing
rwyn doctor
- representative
plan and explain probes for each major repo domain
- initial coverage data for scopeable checks, or explicit setup notes for any
coverage jobs still running or blocked by missing tools/env
- a short handoff summary describing what was modeled, what probes showed, what
coverage was collected, and what remains uncertain
Evidence Order
Prefer high-authority raw data before low-level file enumeration.
- Human docs:
README.md
CONTRIBUTING.md
- docs that describe development, CI, tests, releases, or agent workflows
- Root command surfaces:
justfile
Makefile
mise.toml
- language workspace manifests such as
go.mod, go.work, Cargo.toml, package.json, pnpm-workspace.yaml
- CI orchestration:
.circleci/**
.github/workflows/**
- provider-specific scripts referenced by CI
- Domain command surfaces:
- package-level
justfile or Makefile
- domain manifests such as
foundry.toml, crate Cargo.toml, package package.json
- Scripts and generated-artifact tooling:
- scripts that generate bindings, snapshots, docs, lockfiles, test fixtures, or release artifacts
What To Infer
- raw data sources reported by
rwyn setup
- repository requirements before individual commands
- languages in the repo: Go, Rust, Solidity, or mixed
- main test/build/lint commands
- generated artifacts or generated source trees
- source/interface or source/binding relationships
- native coverage commands, long-running coverage jobs, and CI artifacts that can
seed coverage data
Requirement First
The first concrete output should be a concise requirement inventory, for example:
- Go packages build
- Go tests pass
- contracts build
- contracts tests pass
- generated bindings are current
- snapshots or lockfiles are current
- lint/security checks pass
- docs build
- acceptance tests pass
- Rust workspace builds
- Rust tests pass
Only after this list is plausible should you write steps:. A step is evidence for
a requirement, not the requirement itself.
Extraction Method
Extract requirements by triangulating intent, commands, and enforcement.
- Docs answer "what does the repo tell developers they must keep true?"
Look for setup, build, test, security, release, and contribution sections.
- Root command surfaces answer "what are the main local workflows?"
Look for recipes such as
build, test, lint, check, semgrep, docs,
artifact generation, and drift verification.
- Domain command surfaces answer "what specialized guarantees exist?"
For example, contracts may define snapshot, interface, semver, storage, or
upgrade checks that do not appear in root docs.
- CI answers "which of these are enforced gates, and at which lifecycle stage?"
Treat CI as confirmation and prioritization, not as a mechanical importer.
- Scripts answer "what does a named gate actually verify?"
Open scripts when a command name is ambiguous or when it checks generated
artifacts, provenance, versions, or lockfiles.
Record each candidate requirement with its evidence path before writing config:
requirement: contracts tests pass
evidence:
- CONTRIBUTING.md says to run contracts unit tests with `cd contracts && just test`
- contracts/justfile defines `test`
- CI runs contracts test jobs
Step Mapping
When the requirement inventory is plausible, map steps conservatively:
- Use repo-native commands exactly as documented, such as
just build, just lint-go,
cd contracts && just test, or cd rust && just test.
- If CI schedules commands as separate jobs with separate failure surfaces, model
them as separate steps when practical, even if a local aggregate recipe also
exists. Aggregates are useful convenience commands, but they hide runtime cost
and make CI comparison less precise.
- Give independently required steps distinct
satisfies requirements. A shared
aggregate requirement can make separate jobs look like alternatives to the
planner at cheaper stages.
- Prefer stage variants when the repo has a clear local-vs-CI split, such as dev
Forge tests versus CI Forge tests. Give alternatives the same
assertion: so
the planner can pick one for a stage.
- Put tool requirements in
tools: and environment requirements in
required_env:. Do not model tool installation as a fake prerequisite unless
the repo explicitly requires running a setup step.
- Attach
required_env: to the narrow step or coverage step that actually
consumes the variable, not to a broad aggregate or local check that merely
appears near it in CI. If a CI job chains local tests and fork/remote tests
under one shell environment, split the modeled surfaces or explicitly clear
the remote/fork env for the local step.
- If CI builds a repo-local binary and then invokes it by name, model that
binary as a build step with
outputs: and make the consuming step requires:
it. Do not list repo-built binaries in tools: as though they were external
PATH dependencies; render the consuming command so it can find the produced
binary.
- Use
inputs: for the files that can make a step relevant, and outputs: only
for artifacts that other steps consume or generated files whose drift matters.
- Keep source, test, fixture, generated, and build-artifact surfaces separate in
inputs:. A step that consumes deployable/runtime code should usually depend
on source directories, manifests, build config, or produced artifacts, not an
entire package tree that also contains tests. When a test-only probe selects
unrelated runtime, acceptance, or cross-language steps, inspect broad input
globs before changing planner policy.
- If a prerequisite can safely accept the same scope kind as the step that
requires it, mark the prerequisite scopeable too. rwyn propagates scopes
backward only across compatible declared
scope_type values, so setup should
model scope rendering for build or preparation steps instead of expecting
unscoped prerequisite runs.
- Profile fanout is per step, not per domain. Before adding
impacted_by for a
profile group, inspect that step's actual command and CI matrix. Do not copy a
broad feature matrix onto a job that runs once, uses a fixed/default feature,
or sets the relevant feature internally.
- Add a model-validation step for
.rwyn/config.yaml changes so setup changes
select rwyn doctor/rwyn build.
- Add coverage steps for scopeable test steps. Coverage is part of setup, not
an optional later optimization.
CI Surface Reconciliation
Do not stop after modeling the obvious local commands. CI is the best source of
independently enforced failure surfaces.
Create a ledger with one row per independently scheduled CI job or matrix
variant:
job -> command/env/profile -> scripts/artifacts/services -> nearest rwyn step -> classification -> probe/case
Classifications:
exact: a rwyn step runs the same command or the same failure surface.
decomposed: several rwyn steps together cover the job.
broad substitute: a larger step should catch it, with known extra cost.
ignored: intentionally outside rwyn's model, with reason.
infra-only: credentials, runners, deploys, cache, or provider mechanics.
unknown: unresolved; setup is not done.
Model separate jobs as separate steps when they have distinct commands,
profiles, environment, artifacts, services, path layouts, or failure signatures.
Aggregate local recipes are not enough when they hide a CI-only behavior.
Do not create duplicate selectable steps just to preserve CI job labels. When a
CI job is already covered by a canonical rwyn step, map the CI job name to that
step in the ledger, replay data, or history metadata.
Look for CI-only semantic surfaces too. Some repos encode executable metadata in
comments or text directives. If a comment-only diff can change test behavior,
declare semantic_comment_patterns: with path globs and contains: or regex:
instead of hardcoding the ecosystem in rwyn core.
Replay representative historical CI failures when available. For each real
failure, run rwyn plan on the input diff and record whether rwyn selected the
exact job, a defensible substitute, or a miss. Fix setup/config gaps before
changing planner policy.
After writing the first config, run probes for at least:
- a Go source file
- a Solidity source file
- a docs file
- a Rust source file
- the
.rwyn/config.yaml file itself, uncommitted or staged, to verify setup
changes select the model-validation step
Treat surprising probe output as product evidence. Useful checks:
- configured text/docs files may not have graph nodes, but declared input
patterns should still select the relevant steps
- if broad repo gates appear at
save, tighten stage eligibility before adding
more planner policy
- if import fallback over-scopes, prefer coverage data or explicit scope plugins
- scopeable steps should appear as one scoped plan item per step, not as
duplicate confidence-tier items
Linkage Discovery
After the first config exists, search for hidden repo structure before judging
the model complete. Think in artifact classes, not project-specific names.
Look for:
- interface or declaration files that mirror implementation files
- generated bindings, clients, schemas, ABI files, protobuf output, or SDKs
- snapshots, golden files, fixtures, lockfiles, provenance files, or bundled
release artifacts regenerated from source
- source-to-test ownership conventions that can scope tests better than import
fallback
- workspace/package manifests whose changes invalidate a package, crate, module,
or generated tree
- semantic comments or text directives that affect builds, tests, generators,
lint rules, or runtime configuration
- CI artifacts or native reports that can seed coverage, JUnit, trace, or test
ownership data
Use raw repo evidence:
rg -n "interface|binding|generate|generated|snapshot|golden|fixture|lock|provenance|schema|abi|coverage|coverprofile|lcov|junit|trace|scope" .
rg --files | rg "(interfaces?|bindings?|generated|snapshots?|fixtures?|golden|schemas?|abi|coverage|junit|lcov|lock)"
Before editing plugins:, write a candidate table:
source pattern -> target pattern -> plugin type -> evidence -> probe
Add only durable relationships. If the evidence is weak, probe manually first or
leave a setup note instead of encoding a brittle plugin.
After editing plugins:, rebuild and prove each plugin has an effect:
rwyn explain <source-file> should show the plugin edge or derived scope
rwyn plan <demo-diff> should change in the intended direction, such as
selecting a generated-artifact consumer or narrowing a scope
- if
explain shows the relationship but plan ignores it, treat that as a
product or planner gap before adding more configuration
Plugin Rules
Prefer declarative plugins over custom code.
type: relation
Use for existing-file relationships such as interfaces/IThing.sol -> src/Thing.sol.
type: generate
Use when a changed source file should invalidate generated source such as bindings or snapshots.
Prefer normalized_basename matching first. It is simple and usually enough.
Example Patterns
Interface to source:
plugins:
- id: interface-link
type: relation
from: "interfaces/**/*.sol"
to: "src/**/*.sol"
edge: imports
match_rule:
by: normalized_basename
from_strip_prefix: I
Generated bindings:
plugins:
- id: go-bindings
type: generate
from: "src/**/*.sol"
to: "bindings/**/*.go"
match_rule:
by: normalized_basename
Coverage Guidance
- Prefer native coverage outputs the repo already knows how to produce.
- Search repo scripts and CI for LCOV, Go coverprofile, LLVM coverage JSON,
JUnit XML, and Go test JSON artifacts.
- Verify that native coverage tools are available through the repo's normal
toolchain path before launching broad collection. If CI installs a coverage
helper ad hoc, either make that tool explicit in the repo setup/tool manifest
or record the setup as blocked; do not make rwyn core install it implicitly.
- Prefer first-class
kind: coverage steps over loose notes. A coverage step
should name coverage_for, coverage_profile, coverage_format, and
coverage_output; add coverage_junit or coverage_go_test_json when the
native command can emit those artifacts.
- Inspect paths inside native coverage reports before trusting freshness. If a
report emits paths relative to a package/project directory rather than the repo
root, set
coverage_source_root to that repo-relative directory. rwyn should
store atoms as repo-relative files for hashing and graph matching while still
rendering native path scopes relative to the source root.
- Expect native line coverage to include syntactic noise in some languages.
rwyn should filter blank, comment-only, and delimiter-only source lines during
ingestion so agents do not paper over doc-comment or brace atoms with
repo-specific config.
- Model coverage setup as ordinary dependency structure. Generated artifacts,
build caches, fixtures, local services, package discovery, and CI-like prep
should be separate steps connected through
requires, inputs, and
outputs, not shell glue hidden inside one coverage command.
- When native coverage commands need scoped flags or joined glob syntax, model
that declaratively with the step's
scope_flag, scope_join, and scope_type.
Do not add tool-specific coverage behavior to rwyn core.
- Separate dependency inputs from runnable scopes.
inputs should include every
file or artifact that can affect the command, while scope_inputs should list
the files or packages the native runner can accept as one-at-a-time scopes.
Use this when coverage depends on source and test files but can only be
refreshed accurately by running individual tests, packages, crates, modules, or
directories.
- Use a scope type that matches the runner's native target. Test commands often
want the tests that exercise a changed source file. Build commands usually
want the changed file itself, so prefer direct compile/file scopes when the
build runner accepts file targets.
- For Go tests, prefer exact package scopes with
scope_type: go_packages
unless the command intentionally wants recursive ./pkg/... trees. Exact Go
packages avoid rerunning broad parent package trees when only one child package
is stale.
- For Rust LCOV emitted by
cargo llvm-cov, package-level coverage can be a
good first setup target. Use Cargo package scopes when the runner accepts
-p <package>; rwyn can mechanically attribute LCOV records to the nearest
Cargo package manifest even when the LCOV file itself only contains source
paths.
- Make scoped coverage commands consume rwyn scopes as the runner's native target
selector, such as package, crate, test, module, or directory selection. Do not
let
{args} become a trailing generic test argument if the runner has a
separate package/target flag; that silently turns a narrow refresh into a broad
run.
- If a repository has a convenience coverage command that chains multiple native
runners, do not force it into one scoped coverage step when the chained runners
interpret scope flags differently. Model separate coverage steps around the
actual native runner surfaces that can each accept the configured scope.
- Treat coverage scope evidence as explicit when possible. Scoped refreshes
should preserve the requested runnable scopes as report targets; a broad report
with no targets is evidence about the matching changed atoms, not proof that
every co-reported file is an appropriate runnable scope.
- Prefer native per-test or per-package attribution reports when the runner can
emit them. One complete attributed report is usually a better setup seed than
rerunning coverage once per atom, because it preserves the source-to-runnable
scope map mechanically while avoiding thousands of redundant native runs.
- Preserve every native scope dimension the report exposes. If a report links a
changed atom to both a test file and an exact test identity, configure the
covered step to render both instead of collapsing back to file-only scopes. For
Foundry attribution, use
scope_join: foundry_tests on the covered forge test step so rwyn can combine --match-path, --match-contract, and
--match-test mechanically when exact test evidence exists.
- For full or baseline coverage setup, prefer a scopeable coverage step with
scope_inputs over one broad no-scope run. rwyn coverage refresh --all and
requested no-scope refreshes should expand to one job per configured scope, so
the resulting reports become exact source-to-runnable-scope evidence.
- Exception: if the native runner can accept many scopes in one command and emit
precise per-record attribution, set
batch_scopes: true on the coverage step.
That keeps the execution to one native coverage run while preserving narrow
source-to-test evidence in the ingested report. Treat batching as an
optimization, not a reliability assumption: if a batched refresh fails, rwyn
splits the scope set and keeps successful smaller reports while surfacing the
remaining failing scopes for agent investigation.
- If coverage is flaky, prefer
coverage_attempts on the rwyn coverage step
over native retry flags that rewrite coverage artifacts. rwyn should retry the
same complete scoped command, ingest only a successful complete attempt, and
split the scope set only after those attempts fail.
- If one batched coverage run is mechanically correct but too memory-heavy or
opaque, add
batch_size to cap each native run to a bounded number of scopes.
This is a reliability and observability knob, not a semantic change: rwyn will
still preserve requested scopes on each ingested report.
- If a narrow set of scopes is mechanically incompatible with the preferred
coverage mode, keep that fact explicit. Add
scope_exclude to the preferred
coverage step and model a fallback coverage step for the excluded scopes
instead of weakening the whole coverage strategy or hiding the failure.
- Check that coverage steps and the checks they cover select the same native
scope. A coverage step should derive evidence through
coverage_for, not as a
separate unrelated command.
- If a coverage command fails because the repo expects generated artifacts,
build caches, fixtures, or local services first, add explicit prerequisite
steps. Do not make rwyn infer it from a project name or tool name.
- If the repo has both local and CI test recipes, compare them before deciding a
full-coverage command is unreliable. CI recipes often attach workspaces,
generate fixtures, set tags/env, shard packages, retry failures, or emit JUnit
and JSON artifacts that the local recipe omits. Encode those contracts as
steps and dependencies rather than excluding packages first.
- When coverage has its own test profile, feature matrix, fork mode, or upgrade
mode, model those as explicit coverage steps or setup axes. Do not assume the
fastest local test profile is the authoritative full-coverage profile.
- If a runner reports intentional skips as failures, first verify whether that
happens in the native test command or only in coverage. Do not hide arbitrary
failures. If the repo has a stable skip sentinel, keep the handling in config
or a repo plugin: run the native command in a mode that still emits evidence,
then fail the step whenever a failure line is not that known skip sentinel.
Also check whether the feature/env knob that should enable the skipped tests
actually exists; a missing knob is setup evidence, not something rwyn should
guess around.
- Use
profile_groups: for feature-flag or runtime-mode matrices, and mark only
affected steps with impacted_by.profile_groups or specific
impacted_by.profiles entries. Do not apply a profile matrix globally: most
repo checks are profile-insensitive and should continue to run once.
- Treat profiles as test inputs, not stage filters. If a check only proves its
requirement under three profiles, model those profiles on that check. Stage
policy may choose cheaper evidence, but it should not hide the fact that the
requirement has multiple runtime modes.
- Do not choose a hard-coded representative profile. Profile variants are real
command variants. Seed profile-specific coverage so rwyn can mechanically
compare changed file and line atoms against each variant and select the
smallest variant set with evidence; until that evidence exists, expect rwyn to
fall back to all configured variants for the affected step.
- Before launching a large profile or coverage matrix, identify which jobs can
run concurrently. Parallelism is safe only when jobs have satisfied
prerequisites, isolated mutable outputs, and compatible resource limits. Watch
for shared repo files, generated artifacts, build caches, coverage report
filenames, local service ports, RPC quotas, databases, and CPU/memory-heavy
compilers.
- Coverage refresh jobs are serial by default. Add
parallel_safe: true only to
steps whose commands can safely overlap, then use
rwyn coverage refresh --all --background --max-parallel <N> for broad
collection. Do not mark a step parallel-safe just because the test tool
supports parallel tests internally; this flag is about multiple rwyn refresh
jobs running at once.
- If native commands write fixed output paths in the repo, prefer rewriting them
to write into
{run_dir}, {output}, {junit}, or {go_test_json} before
marking them parallel-safe. Use isolated worktrees later only when path
rewriting is not enough.
- Normalize one-off artifacts with
rwyn coverage ingest --input ... --format ... --step ....
- When ingesting retained or external reports for a profiled coverage step, pass
the covered check,
--profile, --coverage-step, and --profile-variant
together. Profile variants are part of freshness; unprofiled evidence should
not accidentally satisfy a feature-flag or runtime-mode matrix.
- Treat coverage as the main test-scoping evidence for scopeable checks.
- Think in coverage atoms, not whole runs. A coverage atom may be a file,
function, line range, or test-derived unit depending on what the native report
exposes. Setup should make stale atoms map back to the narrowest runnable scope
the repo supports; full coverage is the fallback when that linkage is missing.
- Preserve zero-hit evidence. A native report that instruments executable code
with zero hits is useful data, not a failed coverage run. It should become
uncovered evidence, while code with no trustworthy coverage evidence is
missing or unknown.
- Read coverage status as four separate states:
fresh means observed and
current, uncovered means observed with zero hits, stale means observed but
source-changed, and missing means no reliable atom exists yet.
- For net-new or otherwise unobserved changed code, use the scope the planner
already inferred as an exploratory coverage refresh. After the run, zero-hit
code should become
uncovered and stop re-queuing; only stale and missing
atoms should drive refresh work.
- After wiring coverage steps,
rwyn coverage status on representative diffs
should show concrete fresh/uncovered/stale/missing atoms and a refresh queue
for stale or missing data.
- If
rwyn coverage status reports that no coverage atoms were selected for the
current plan, treat that as a plan-scoped empty result, not proof that the
coverage store is empty. Inspect rwyn plan and use
rwyn coverage refresh --all --dry-run for the full configured coverage view.
- Coverage status output is compact by default. Use the summary counts and
per-status previews first; add
--full-statuses only when you need the
complete atom list.
- Run cheap coverage immediately.
- After one coverage step works, execute one representative coverage step per major test
domain. Use a narrow representative diff first, then start broader expensive
coverage collection with
rwyn coverage refresh --all --background when it is
part of the repo's real setup surface. --all should skip fresh atoms and
queue only stale or missing atoms; use --force only when intentionally
reseeding. Continue setup while it runs.
- For scopeable coverage, inspect the dry-run queue before launching the broad
job. A full setup run should show one refresh job per configured runnable scope
when the step has no prior evidence; if it shows one unscoped broad job for a
runner that can run narrower scopes, add or fix
scope_inputs.
- Use
rwyn coverage refresh --step <coverage-step> --scope <scope> when setup
has already identified the stale atoms or package/test scope to refresh.
- After a scoped coverage refresh, immediately run the same command with
--dry-run. The expected result is that the refreshed atoms are fresh and the
refresh queue is empty; if not, fix the scope mapping before collecting broader
coverage.
- Inspect long-running coverage jobs with
rwyn coverage jobs and read the job
log before changing config. Use observed status, elapsed time, log age, log
size, queue progress, ETA, process count, CPU/memory, active child process, and
the log path as setup evidence. Treat orphaned as a completed process that
failed to record a final status. Do not drop to generic process tools unless
rwyn's job view is missing information you need; treat that as a rwyn product
gap to fix.
- Broad coverage queues should make early progress: cheap coverage steps should
run before expensive coverage steps, and independent coverage steps should
continue after one coverage step fails so the run gathers as much evidence as
possible.
- If a coverage run is blocked by missing tools, credentials, or environment,
record the blocker and the exact command that should be resumed.
- Probe at least one cheap coverage step execution. Tool managers may have hidden
activation/trust state that
doctor cannot prove from command -v alone.
- Prefer repo-native commands in config. Tool-manager setup belongs to the
execution environment, not to
.rwyn/config.yaml: establish it with the repo's
normal mechanism, such as shell activation, direnv, Nix, asdf, mise, or a CI
image, and record any blocker.
- If a validation step invokes
rwyn, verify child commands resolve the same
rwyn binary as the parent; inconsistent self-invocation can make graph and
doctor output drift.
- Do not depend on coverage alone for build invalidation or generated artifacts.
Validation Order
rwyn doctor
rwyn build
rwyn setup inspect
rwyn plan --uncommitted
rwyn plan --staged when the setup branch has intentionally staged changes;
do not stage the config just to make rwyn see it
rwyn explain <file> for anything surprising
rwyn coverage status
rwyn coverage refresh, rwyn coverage refresh --all --background, optional
--max-parallel <N> for parallel_safe coverage steps, or native coverage
collection plus rwyn coverage ingest
rwyn verify --dry-run to exercise the beta user loop: plan, coverage
status, scoped refresh queue, and final plan shape without executing refreshes
or checks
If the first config is wrong, tighten it by removing assumptions, not by adding more policy complexity.