estate-sweep — the whole public estate through one lint
The 2026-07 drift fix taught the lesson: drift accumulates silently across the
estate (sha256 name-hash minting reached 10 sites before anyone looked). This
skill is the look. It clones/refreshes every public kody-w repo shallow and
runs rapp-drift-lint over each, emitting a per-repo violation tally.
Run it
REPO_LIMIT=0 bash ~/.claude/skills/estate-sweep/scripts/sweep.sh ~/.cache/rapp-estate-sweep
- Workdir
~/.cache/rapp-estate-sweepis reused — re-runs pull instead of re-cloning. REPO_LIMIT=Ncaps the sweep to the first N repos (smoke runs). Unset/0 = full estate.- The script checks that the active
ghaccount iskody-wand WARNS if not — nevergh auth switchon Kody's behalf; surface the warning and stop. - The lint itself comes from
kody-w/rapp-drift-lint(cloned into the workdir unless a path is passed as arg 2).
Read the report, then judge
The output ends with <N> repos dirty, <M> total violations. The sweep NEVER
auto-fixes. For each dirty repo:
- Re-run the lint on that repo alone and read the actual violations.
- Classify: real drift (fix at its real layer) vs. lint false-positive
(fix the lint in
rapp-drift-lint, not the repo). - Fixes are per-repo and traceable — one issue or commit per repo, never a
blind bulk rewrite. Canon: the name is RAPP in prose;
rapp/1is only the lowercase wire tag; identity is never sha256(owner/slug).
Don'ts
- Don't sweep with the work
ghaccount active (kody-w repos 403 under it). - Don't fix anything in the same breath as the sweep — report first.
- Don't touch private repos; the sweep is public-estate only by design.
Run this — do not improvise
This capability's deterministic implementation is a RAPP single-file agent, linked beside this file as estate_sweep_agent.py and embedded as the fenced Python below (sha256 6744b212d9075edc…; a byte-exact copy is also vaulted in the capsule comment at the end of this file). On a host with sandbox execution, run the linked file directly — if it is missing, write the fence contents verbatim to estate_sweep_agent.py first:
python3 estate_sweep_agent.py '{"key": "value"}' # arguments as one JSON object
echo '{"key": "value"}' | python3 estate_sweep_agent.py # or on stdin
python3 estate_sweep_agent.py --tool # emit the JSON tool contract
Treat stdout as a tool result. If it reports missing or unresolved inputs, stop and collect them. If it returns steps, execute those steps in order exactly as returned; if it returns instructions, follow them with the supplied inputs. Otherwise use the result verbatim. Do not invent behavior beyond that output. On a host without code execution, treat the Parameters schema and the code below as the exact specification and never paraphrase a step. Never edit inside the generated markers; a converter-equipped host can instead restore the original file checksum-verified with the installed rapp-agent-converter/scripts/toast.py convert SKILL.md --to agent.
"""EstateSweep -- Clone-and-lint drift sweep across every public kody-w repo using the shared rapp-drift-lint. Use when Kody says "sweep the estate", "estate sweep", "lint all my repos", "is the estate clean", "check everything for drift", or after a canon/spec change that could ripple across the RAPP estate. Read-only — reports per-repo violations; fixing is a separate judgment step.
Generated by the rapp skill from estate-sweep. The RCI capsule at the bottom of this file carries the full original; `toast.py convert` restores it byte-exact."""
import json
import re
import sys
try:
from agents.basic_agent import BasicAgent
except ImportError: # running OUTSIDE the brainstem -- stay executable anyway.
class BasicAgent: # noqa: D101 - minimal stand-in, same contract
def __init__(self, name=None, metadata=None):
if name:
self.name = name
if metadata:
self.metadata = metadata
def perform(self, **kwargs):
return "Not implemented."
def system_context(self):
return None
def to_tool(self):
return {"type": "function", "function": {
"name": self.name,
"description": self.metadata.get("description", ""),
"parameters": self.metadata.get("parameters", {})}}
# The procedural layer, verbatim from the source capability. The brainstem
# returns this to the model, so the skill's instructions still drive behaviour
# -- now behind a typed, deterministic tool contract.
INSTRUCTIONS = "# estate-sweep — the whole public estate through one lint\n\nThe 2026-07 drift fix taught the lesson: drift accumulates silently across the\nestate (sha256 name-hash minting reached 10 sites before anyone looked). This\nskill is the look. It clones/refreshes every public `kody-w` repo shallow and\nruns `rapp-drift-lint` over each, emitting a per-repo violation tally.\n\n## Run it\n\n```\nREPO_LIMIT=0 bash ~/.claude/skills/estate-sweep/scripts/sweep.sh ~/.cache/rapp-estate-sweep\n```\n\n- Workdir `~/.cache/rapp-estate-sweep` is reused — re-runs pull instead of re-cloning.\n- `REPO_LIMIT=N` caps the sweep to the first N repos (smoke runs). Unset/0 = full estate.\n- The script checks that the active `gh` account is `kody-w` and WARNS if not —\n never `gh auth switch` on Kody's behalf; surface the warning and stop.\n- The lint itself comes from `kody-w/rapp-drift-lint` (cloned into the workdir\n unless a path is passed as arg 2).\n\n## Read the report, then judge\n\nThe output ends with `<N> repos dirty, <M> total violations`. The sweep NEVER\nauto-fixes. For each dirty repo:\n\n1. Re-run the lint on that repo alone and read the actual violations.\n2. Classify: real drift (fix at its real layer) vs. lint false-positive\n (fix the lint in `rapp-drift-lint`, not the repo).\n3. Fixes are per-repo and traceable — one issue or commit per repo, never a\n blind bulk rewrite. Canon: the name is RAPP in prose; `rapp/1` is only the\n lowercase wire tag; identity is never sha256(owner/slug).\n\n## Don'ts\n\n- Don't sweep with the work `gh` account active (kody-w repos 403 under it).\n- Don't fix anything in the same breath as the sweep — report first.\n- Don't touch private repos; the sweep is public-estate only by design."
# Ordered commands lifted verbatim from the capability's own documentation.
STEPS = [
{
"cmd": "gh",
"line": 16
},
{
"cmd": "gh auth switch",
"line": 17
},
{
"cmd": "gh",
"line": 35
}
]
class EstateSweepAgent(BasicAgent):
def __init__(self):
self.name = 'EstateSweep'
self.metadata = {
"name": "EstateSweep",
"description": "Clone-and-lint drift sweep across every public kody-w repo using the shared rapp-drift-lint. Use when Kody says \"sweep the estate\", \"estate sweep\", \"lint all my repos\", \"is the estate clean\", \"check everything for drift\", or after a canon/spec change that could ripple across the RAPP estate. Read-only \u2014 reports per-repo violations; fixing is a separate judgment step.",
"parameters": {
"properties": {},
"required": [],
"type": "object"
}
}
super().__init__(name=self.name, metadata=self.metadata)
def perform(self, **kwargs): # toaster:generated-perform
missing = [k for k in self.metadata["parameters"].get("required", [])
if k not in kwargs]
if missing:
return json.dumps({"status": "error",
"missing_required": missing}, indent=2)
resolved, unresolved = [], set()
for step in STEPS:
cmd = step["cmd"]
for key, value in kwargs.items():
for token in ("<" + key.replace("_", "-") + ">",
"<" + key + ">",
"{{" + key + "}}",
"$" + key.upper()):
cmd = cmd.replace(token, str(value))
for leftover in re.findall(r"<[a-zA-Z][a-zA-Z0-9 _.-]{1,40}>", cmd):
unresolved.add(leftover)
resolved.append(cmd)
return json.dumps({"status": "ok",
"steps": resolved,
"unresolved_placeholders": sorted(unresolved),
"note": "Resolved deterministically by the agent; "
"run in order. Nothing was executed here."},
indent=2)
if __name__ == "__main__":
# Standalone entry point: the deterministic layer runs with NO brainstem,
# no framework, no install. This is what lets a "simple SKILL.md" platform
# keep real determinism -- the host model shells out to this file instead
# of improvising the procedure in prose.
# echo '{"arg": "value"}' | python3 estate_sweep_agent.py
# python3 estate_sweep_agent.py '{"arg": "value"}'
# python3 estate_sweep_agent.py --tool # emit the JSON tool contract
_a = sys.argv[1:]
if _a and _a[0] == "--tool":
print(json.dumps(EstateSweepAgent().to_tool(), indent=2))
else:
_raw = _a[0] if _a else (sys.stdin.read().strip() or "{}")
print(EstateSweepAgent().perform(**json.loads(_raw)))
# rci-capsule:v1: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