agentleFS
dsviddsvid/claude-skills/skills/mapping/surveyor/SKILL.md

surveyor

Skill0 starsChanged 4 months agoMITView on GitHub

Survey an unfamiliar domain against a written direction — what a thing is for, what related things exist, what they do, and how they relate — and emit provenance-carrying survey records for the cartographer to compile. Use when arriving at an unfamiliar codebase, ecosystem, organisation or document corpus and needing to establish what is there before analysing it; when asked to map, survey, scope or get the lay of the land; or when an existing map needs an area re-surveyed at higher resolution.

1 other project uses a version of this.

Adopted by

Most recently taken up by

  • Other versions1 project uses a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 1

    1. nyanshiba/skills★ 5same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository4 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

11 rules. About 0 are common, 8 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈8

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    A survey without a direction maps forever: Before anything else, get one sentence in writing: *what question is this map being drawn to …

    line 17
  2. Distinctive:

    If the user has not given one, ask for it.

    line 20
  3. Very specific:

    Ask where the map lives, or find it: a map/ directory, an _inventory, an existing index.

    line 63
  4. Distinctive:

    Check the existing index for the areas your direction touches.

    line 76
  5. Distinctive:

    Has someone already answered this?: Search for prior art aimed at *the direction*, not at the subject in general.

    line 106
  6. Distinctive:

    Put the direction, the record schema, the tiers, and the rules in one file, and have every sub-agent read it first.

    line 125
  7. Distinctive:

    Ask which model to fan out on, and default to Sonnet: Ask *here*, not at §0 — only now do you know the fan-out width, so only now can you …

    line 145
  8. Very specific:

    If n or the spread cannot be established, the claim is not_determined, and resolved_by is the recomputation.

    line 350
  9. Very specific:

    Never smooth over a gap: Write it into not_determined with what would resolve it.

    line 360
  10. Distinctive:

    Every claim carries grounding, tier, accessed date: No exceptions — including for your own assertions about tooling and process.

    line 363
  11. Distinctive:

    The map location is the only place you write: If it would sit inside the subject, stop and ask for somewhere else.

    line 405

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Surveyor

Speaks map format v1. Emits survey records for cartographer. Does not draw the map and does not diagnose anything.

Your job is to find out what is there, broadly before deeply, and to record it so that someone who was not present can check every word of it.

0. The direction — no direction, no survey

A survey without a direction maps forever. Before anything else, get one sentence in writing: what question is this map being drawn to answer?

If the user has not given one, ask for it. If they are unsure, propose one from what they have said and get it confirmed. Do not start on a vague brief — the direction is the stopping rule, the fan-out instruction, and the thing every resolution decision is made against.

Record the direction with the records you emit. If the direction changes later, the survey re-fires — a map aimed at an old question is worse than no map, because it looks current.

🛑 Then ask the reach — how far out does this go?

The direction says what to answer; the reach says how far to go to answer it. Separate decisions, both the user's. Ask explicitly, record beside the direction, offer three:

ReachIn scopeThen
InwardThe subject itself — structure, internals, how its parts relateSpend nothing going outward. What points out is a not_determined
OutwardThe ecosystem around it — sibling repos, the people who build it, the tooling, test suites and results corpora living elsewhere§3's enumeration and person-tracing are obliged, not optional; fan-out is wider, so price it
BothBoth, at stated resolutions — the usual answer, and the expensive oneAs above

🛑 A clause inside the direction is not a reach. Measured: a run whose direction explicitly asked "what related repos exist for testing" surveyed the subject thoroughly and its ecosystem barely at all. The words were in every sub-agent's brief and nothing acted on them. A sentence is not a budget.

✅ This is the one breadth question that is front-loadable. Which gaps a run will fail to reach is unknowable now — §7's gate handles that. Which direction it travels is knowable now, and only the user can say.

Reach is a pass, and passes are additive. inward now, outward later is first-class, and often better: a usable map lands sooner, and the user prices the ecosystem once they can see the subject.

  • Say which pass this is — in the hand-over and in the records.
  • 🛑 Without reach, a blank ecosystem and an ecosystem checked-and-empty are indistinguishable. One means go look, the other already answered. §2 reads this field for exactly that.
  • A later pass adds topics beside the earlier ones and compiles normally. Do not re-survey the subject to "re-integrate" it — that is §2's waste.

1. Find the map, and read its conventions

Ask where the map lives, or find it: a map/ directory, an _inventory, an existing index. If there is none, ask where it should go.

Read that location's own CLAUDE.md or README.md every run. Domain conventions belong to the domain, not to this skill — what a map of a codebase contains differs from a map of an organisation. Never import conventions from another run.

If the map declares a format version other than v1, stop and say so. Do not write records it cannot read.

2. Ask what is already known before gathering anything

Check the existing index for the areas your direction touches. It tells you several opposite things, and you need all of them.

  • What to skip. Note each area's resolution. Re-surveying ground already covered at sufficient resolution is the single most common waste.
  • 🛑 What to open. Note each area's coverage (§4) — R1 · 13 listed, 0 opened. A named subject is in the map without being in the survey, and it is the cheapest work available: located already, just never read. Where the direction asks about it, this is your work list, exactly as resolution is your skip list.
  • 🛑 What was never in scope. Read the reach of the passes already run (§0). An area missing from an inward-only map is unmapped, not empty — and it carries no resolution to warn you, because no record was ever written about it. This is the one gap the skip list cannot see, and on a second pass it is usually the whole job.
  • 🛑 What to re-check. Note each entry's volatility and last_checked. A live claim needs re-surveying because it was surveyed before — an open-issue count, a backlog figure, a "currently failing" list. Re-checking a volatile claim is not waste; it is the only thing keeping the map honest.

Build all three lists before gathering anything: skip, open, re-check. A survey that only ever adds new subjects lets the map fill with confident stale numbers that still carry perfect provenance — which is the precise defect this whole format exists to prevent.

Then ask the two questions that repeatedly turn out to matter:

  • What can existing material still be asked? Notes, captures, logs and records already collected often answer the direction without new gathering. Exhaust them first — this is a gate, not a suggestion.
  • Has someone already answered this? Search for prior art aimed at the direction, not at the subject in general. Issue trackers, open PRs, prior write-ups, published work. Finding that the question is already answered is a successful outcome, not a wasted survey.

3. Fan out

For anything more than a couple of subjects, dispatch one sub-agent per subject. They work independently and return a bounded record; you stay uncluttered enough to compile.

Group by arc, not strictly by document. The unit is whatever must be read together and in order to be understood — a set of findings written across one investigation, a thread and the code it argues about. Splitting an arc forces every agent to re-read the others for context; that is the most common way a fan-out costs more than it saves.

Write the brief to a file

Put the direction, the record schema, the tiers, and the rules in one file, and have every sub-agent read it first. Then each dispatch prompt carries only the assignment.

Every sub-agent gets the direction verbatim — that is what the shared file guarantees. They start cold, and without the direction they will report what is interesting rather than what is relevant.

🛑 And the reach on its own line (§0) — "reach: outward. Enumerating the namespace and tracing contributors is in scope and expected." A sub-agent told only its subject surveys only its subject, and a reach buried inside the direction is the clause §0 measured going unread.

Choose the model before dispatching

Sub-agents inherit your model unless the dispatch overrides it, so an expensive session silently fans out expensive agents. Most of the sub-agent job is extraction against a fixed schema, and does not need the model doing the compiling.

Ask which model to fan out on, and default to Sonnet. Ask here, not at §0 — only now do you know the fan-out width, so only now can you price it ("14 subjects across ~40 documents"). Below the fan-out threshold, skip the question. If the user has said "just go", take the default without a round trip.

If the chosen model is unavailable, fall back to your own, say so in one line, and continue. Never fail a survey over a model choice.

Bound what comes back

Sub-agents write their records to disk and return a summary, not the records. Returning both spends the corpus twice and clutters exactly the context the fan-out exists to protect.

Require back, in ~15 lines: where the records were written, counts by status, and only the exceptions — what is contested, what could not be determined, what was unexpected. Everything else is in the file, and you can read it if you need it.

🛑 Read the returned exceptions for referrals, and dispatch late

The fan-out is chosen at the moment of least knowledge, so a subject discovered during the run has nowhere to go — every agent was told to stay in its lane.

When an exception refers work on — "worth a closer look by whoever is mapping X" — check that X was dispatched. If nobody owns it: dispatch a late agent, or say so in the hand-over. Either is fine; silently compiling is not.

⚠ Observed: a referral to "whichever agent is mapping the testing story" — no such agent existed, the orchestrator compiled anyway, and it pointed at the run's single highest-value subject.

Give each one a scope, and mean it

Say which material is theirs and that the rest belongs to other agents. Without that, sub-agents read the whole corpus "for context" — n agents each reading everything is the worst case, and it is the default behaviour.

They may follow a reference out of their assignment to resolve a specific question. They may not go and read around.

Follow references; do not browse. Survey what the material actually points at — what the code imports, what the docs cite, what the issues link. A plausible-sounding name in a listing is not a reference.

🛑 Outward reach (§0): enumerate completely, then read selectively

Outward reach suspends the rule above for counting, never for reading in depth. It obliges the whole set, at R0 if that is all you can afford.

🛑 The territory does not point at itself, so following references cannot get you there. Measured: a subject's source held zero references to the ecosystem owning its test suite, golden corpus, tracer and benchmark harness. Four moves, one call each:

  1. Enumerate the owning namespace in full — not the few you happened to hear about. ⚠ A partial enumeration reads as complete — §4's coverage denominator is what makes it detectable.
  2. 🎯 Rank the people, then follow them. An ecosystem is usually one or two individuals' other repositories, and nothing in the subject links to them. 🛑 Rank over what the subject itself added — on a fork the whole-repo list is the upstream's: measured, the ecosystem's author ranked 84th across the tree and 2nd across the fork's own directories. ⚠ Merge identities first (one person, two emails); <login>@users.noreply… gives you the account name.
  3. Resolve forks to their parent — that is a reference, not a listing.
  4. Then filter by the direction, on what each thing is. Stop enumerating, start choosing — the only point where browsing is a real risk.

⚠ Under inward reach, none of this. It is a not_determined; the user priced it at §0.

4. Breadth before depth

Establish a coarse, accurate frame over the whole territory first, then increase resolution where the direction needs it. Detail bought before the frame exists is detail positioned against nothing.

LevelNameWhat is known
R0NamedIt exists. Name, one-line description, where it lives
R1SketchedWhat it is for, and a guessed relation to the rest
R2SurveyedPurpose and relations verified against source or docs
R3DetailedInternals mapped — structure, parts, how it works

R0 and R1 are legitimate outputs, not failures — provided the level is recorded. A guessed relation is honest at R1 and dishonest at R3, and the only difference is whether you wrote the level down.

🛑 A subject with parts carries its coverage, not just its level

An R-level grades what is known about a subject. It says nothing about how much of the subject was looked at — and a record that names forty files and opens one reads, on the page, exactly like a record that opened forty.

State the coverage beside the level: R2 · 40 engine files named, 1 opened, R1 · 13 repos listed, 0 opened. Same discipline as §5's n on a derived statistic, turned on the survey itself.

⚠ Measured, twice in one run. One record covering a hardware tree listed every engine file and opened none — at R2; the threading and locking rows it was scored against sat one file below that listing. Another put thirteen repos in a single subject.name brace-list — at R1; two of them were the run's highest-value missing rows. Both records admitted the thinness honestly, in prose. Nothing downstream can read prose.

Named is not surveyed, and the denominator is the only thing that makes the difference legible — to the reader, and to §7's gate, which spends it.

5. The survey record — map format v1

One record per subject. This is the contract cartographer consumes; keep the field names.

record: <subject-slug>
direction: <the one-sentence direction this was surveyed against>
reach: inward | outward | both   # §0 — recorded so a later reader knows
                                 # whether a blank ecosystem was a finding
                                 # or simply out of scope
surveyed: <YYYY-MM-DD>
resolution: R0 | R1 | R2 | R3    # §4 — and if the subject has parts, the
                                 # coverage with it: "R2 · 40 named, 1 opened"
subject:
  name: <what it is called>
  kind: <repo | document | service | team | dataset | …>
  location: <url, path, or where it lives>
  summary: <one line — what it is>
purpose: <what it is for, one short paragraph>
relations:
  - to: <other subject>
    nature: <depends on | consumes | supersedes | forked from | discusses | …>
    grounding: source | docs | inferred
    reasoning: <required when grounding is inferred>
claims:
  - statement: <a falsifiable sentence>
    grounding: source | docs | inferred
    tier: T0 | T1 | T2 | T3 | T4
    provenance: <path+lines, URL, verbatim query, snapshot path, or who said it>
    accessed: <YYYY-MM-DD>
    volatility: static | slow | live
not_determined:
  - question: <what could not be established>
    resolved_by: <what would settle it>
unexpected: <free text — anything noticed that the direction did not ask for.
             🛑 LEADS ONLY. Nothing here is a claim, and the cartographer may
             not promote it to one. If it is falsifiable, it belongs in
             `claims:` with full fields — see rule 4>

🛑 Price a resolved_by by the operation, never by its category

A resolver nobody can price is a resolver nobody runs. State it as a concrete operation — the actual command, query or request — so reading it tells you what it costs. "Investigate the build system" is not a resolver; "read subprojects/foo.wrap and record the URL" is.

🛑 The band is how many calls and how long — never "local vs external" or "in scope vs out". One non-mutating request is cheap wherever it lives: an API call, a fetch and a git show all belong in the same band as a grep.

⚠ Measured: a run filed "direct fetch of the org's repository listing" in its most expensive band, 34th of 35, purely because it left the machine. One call, ~2 seconds, the cheapest item in the register — and its output held the run's most valuable finding. The compiler and the human both read the band and believed it. If a resolver is one cheap call, you are the last honest place to notice (§7).

Provenance tiers — record the highest that honestly applies

TierCarries
T4 ImmutableAn upstream content-addressed id — git SHA, DOI, archive URL
T3 SnapshotOur own stored copy of the response, with its path
T2 AddressableA URL, or a verbatim query
T1 DatedWhat was consulted and when, nothing re-fetchable
T0 AssertedNothing. Legitimate for recollection — must be marked

A document is not a query. A URL returns the same thing, updated. A query returns a different population — so record the query verbatim, because a slightly different one silently yields a different answer and nobody can tell which was run.

Human sources are not unprovenanced: record who, when, what exactly was said, and whether it has been tested. Treat it as a hypothesis, and say so.

Derived claims are pinned by the transformation plus its inputs — record the operation and the input artefacts, or it is not reproducible.

🛑 A derived statistic carries its n and its spread, in the statement

Reproducibility is not enough. A median computed over one run and a median computed over eight are both perfectly reproducible, both correctly provenanced, and only one of them means anything.

  • State n in the statement itself, not in the provenance line. A reader comparing two numbers must see what each was computed over without leaving the sentence.
  • State the spread (sd, or range) whenever the claim asserts that two values differ. A difference smaller than the within-group spread is not a difference, and you cannot know that without computing it.
  • 🛑 Never describe a subset as its population. If the figure is run 1, the statement says run 1 — not "the control arm". Naming the subset in one half of a comparison and dropping it in the other is the specific error that produced this rule.
  • If n or the spread cannot be established, the claim is not_determined, and resolved_by is the recomputation.

⚠ Watch the asymmetry that hides this. A recomputation that confirms an existing figure tends to carry n, because a prior claim is there to check against. A recomputation that asserts something new — exactly the one worth most and checked least — tends not to. The novel claim needs it more.

6. Rules

  1. Never smooth over a gap. Write it into not_determined with what would resolve it. A fluent, unsourced map is worse than no map, because it will be believed.
  2. Every claim carries grounding, tier, accessed date. No exceptions — including for your own assertions about tooling and process. Infrastructure prose gets trusted exactly as much as a finding.
  3. Prefer source to documentation. Where they disagree, record both and flag it; the disagreement is itself a finding.
  4. Record, do not conclude. Mechanisms, causes and recommendations are not yours. If a conclusion is forming, write it as an inferred claim with its reasoning. 🛑 unexpected is not the overflow for that. It takes leads — things worth someone's attention — never a falsifiable assertion, and never a number. Anything falsifiable goes in claims: with grounding, tier, provenance, accessed, and (if derived) n, where the schema forces the discipline. Writing it as free text is how an unchecked figure reaches a map wearing the authority of a checked one.
  5. Cheap before expensive, and when something expensive is needed, say what it will cost before starting it.
  6. unexpected is not optional. The thing noticed while chasing something else is often worth more than the thing you were sent for.
  7. 🛑 Write only to the map location. Never edit the domain's own documents or source — surveying must not mutate the territory. You will find stale, wrong and superseded material; that is a record to emit, not a thing to fix. The artefacts you are most tempted to correct are the ones the human relies on most, and a survey that quietly rewrites its own subject has destroyed the evidence for its own findings.
  8. 🛑 The subject is a READ-ONLY ARTEFACT. Observe it; never change it. This is a property of the subject, not a list of banned commands — if an action alters bytes in the territory, it is out of scope, whether or not it appears below. Treat every subject as someone else's, because it usually is.
    • Read-only git is one of your best instruments — log, show, blame, diff, ls-files, rev-parse. Use it freely.
    • Never git-write: commit, add, checkout, switch, branch, stash, merge, rebase, reset, restore, clean, tag, push. 🛑 A checkout is a mutation — "just look at main" can discard uncommitted work and move a branch the human was in the middle of.
    • Never write by any other route either: creating files inside the subject, running builds, installs, formatters or codegen that write into its tree, deleting anything, or "fixing" the stale README you just found wrong. You will find wrong, dead and superseded material — that is a record to emit, never a thing to repair (rule 7).
    • 🛑 Nothing may leave the machine. No PRs, no issues, no comments on the subject's tracker, no publishing — even when what you found is a real bug in it. Emit a record and hand it to the human.
    • The map location is the only place you write. If it would sit inside the subject, stop and ask for somewhere else. If you need a different revision, ask for a worktree or a second clone — do not make one by moving theirs.
    • Why absolute: the subject's origin may be a real public upstream, and a commit puts your output in someone else's history one push from being public and attributed to them. The cost of asking is a sentence; the cost of being wrong is not recoverable by you.

7. Hand over

🛑 First: the cheap-band gate. Show what one more step buys, and ask

Before handing over, re-read every place the run admitted it stopped short, and pull out what a single cheap, non-mutating operation would close (§5). 🛑 Three sources, not one:

  • not_determined: resolvers that price as one cheap call.
  • unexpected: leads naming a concrete target — a repo, a file, a URL. They carry no resolved_by, so nothing else in the format will ever look at them.
  • Coverage shortfalls (§4) — what a record named and did not open, where the direction asks about it directly.

Then stop and put them to the user, with what each would buy:

3 open questions resolve in one call each: enumerate the org's repos (gh api orgs/<org>/repos); read the dependency manifest for the URL it points at; grep the remaining CI workflows for test steps. Plus 13 repos named-and-unopened under one owner, 2 of which the direction asks about. ~2 minutes total. Run them, or hand over as-is?

⚠ Measured: the gate fired, the human said go, eleven resolvers ran and four index entries were superseded — and in the same file, six unexpected: leads with one-call resolvers went unread, one of them the run's single most valuable finding. A gate reading one field of three is a gate on a third of the map.

Placed here deliberately — §0 settles which direction to travel; only now does anyone know what the run actually failed to reach.

  • ✅ Go ⇒ run them and fold the results in as ordinary claims with full provenance. Bounded: one round. Their results authorise no further calls — a survey that resolves recursively has stopped surveying.
  • ✅ Hand over as-is is a fine answer; the entries stay not_determined. The point is that a human priced it, not that it got done.
  • 🛑 Never skip the gate for being small. The likeliest item on it is the one you mis-filed as expensive.

Then hand over

Emit the records to the map location and tell the user, in two or three lines: what was surveyed, at what resolution, what is blank, and what the direction still cannot answer.

Then say the map needs compiling — that is cartographer's job, and records that are never compiled are not a map.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.