agentleFS
leather-ioleather-io/mono/.claude/skills/feature-map/SKILL.md

feature-map

Skill28 starsChanged 34 days agoMITView on GitHub

Turn a bug report or route into the extension screen it belongs to, its preconditions, the covering Playwright spec and a reproduction. Use when triaging a bug, writing an E2E repro for a report, or adding a route or an rpc handler to the extension (the feature-map check fails until it has an entry).

4 other projects use a version of this.

Adopted by

Most recently taken up by

  • Other versions4 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 4

    1. onyx-dot-app/onyx★ 33ksame name
    2. langwatch/langwatch★ 5ksame name
    3. onyx-dot-app/onyx-foss★ 320same name
    4. markphelps/agent-plugins★ 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 repository5 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

6 rules. 0 are common, 0 are distinctive, and 6 are very specific to this project.

  • 0

    Common

    Most of the 4 edited versions we read keep these.

  • 0

    Distinctive

    This author's own choices. Worth a look.

  • 6

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Very specific:

    Generate, then find the entry: Run pnpm lt feature-map generate --app extension, then grep extension.md for what you have: a route …

    line 19
  2. Very specific:

    Every entry declares what it is anchored on.

    line 34
  3. Very specific:

    Run pnpm --filter @leather.io/tools build first if pnpm lt reports an unknown command.

    line 65
  4. Very specific:

    Every routed RouteUrls key and every rpc handler file must be claimed by an entry.

    line 69
  5. Very specific:

    Write "back goes to the previous page" when the header back button calls navigate(-1), and say when a control opens a full-page tab from …

    line 93
  6. Very specific:

    After editing a source run check, then generate to refresh your local extension.md.

    line 112

“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “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

Feature map

pnpm lt feature-map generate --app extension writes extension.md next to this file: a generated inventory of the extension, one entry per screen, dialog, dApp method or behavior a user would name. The file is gitignored, so generate it at the start of a session (a few seconds; the first run also builds the tools package). Each entry resolves its anchor, routes or opener, gate, feature flags, params, entry steps, preconditions, selectors, page-object actions and covering specs. The sources are typed TypeScript in apps/extension/tests/feature-map/*.features.ts; they import the real RouteUrls and *Selectors objects, so a rename breaks pnpm --filter @leather.io/extension typecheck.

From a report to a reproduction

  1. Generate, then find the entry. Run pnpm lt feature-map generate --app extension, then grep extension.md for what you have: a route (/send/btc), a RouteUrls key, a selector, or words from the description of what the screen shows.
  2. Read the entry. Routes shows where the router mounts it, which gate wraps it and which LaunchDarkly flags must be on; a dialog or sheet shows Opened by instead: the start route and the page-object action that reveals it. Preconditions gives the session state, network, account type and the mock functions the specs register. Entry lists the click path and deep link.
  3. Open the covering spec and action. Specs are repo-relative paths; Actions link to the page-object method that owns the readiness wait for that screen (see write-extension-e2e). Copy the spec's beforeEach, call the listed actions, then assert on the listed selectors.
  4. Write the repro following the write-extension-e2e skill. Never bypass a page-object action with a raw selector from the entry; the action waits for the data the screen validates against.

Anchors

Every entry declares what it is anchored on. The check enumerates routed RouteUrls keys and rpc handler files and fails when one has no entry; selectors and behavior entries are optional.

anchorUse forEnumerated fromClaimed by
{ kind: 'route' }a screen with a URLRouteUrls keys the routers referencethe entry's routes
{ kind: 'selectors', objects: [...] }a dialog, sheet, banner or badge with no URLexported *Selectors objects in apps/extension/tests/selectorsobjects (whole object 'SwitchAccountSelectors' or members 'HomePageSelectors.NetworkSwitcher')
{ kind: 'rpc', handlers: [...] }a dApp method whose handler opens no approver (open, openSwap, supportedMethods)file basenames in apps/extension/src/background/messaging/rpc-methodshandlers, or a routed entry whose entry[].method the handler registers
{ kind: 'behavior' }something the wallet does with no screen (wallet lock, store migrations, the Ledger flow steps)nothing; hand-authored—

Selector objects are not enforced: a dialog rendered inside a routed screen can live in that screen's entry, and a selectors entry is added when a dialog needs one of its own. Popup-opening rpc methods keep their route anchor; their entry[].method claims the handler. Behaviors are listed under Behaviors in extension.md and skip the gate cross-check; everything else they reference (specs, actions, selectors, mocks) is still validated.

Entries without a route carry startRoute (a RouteUrls value, default /) and open: the page-object action or sequence of actions ('HomePage.goToReceiveDialog', ['SwitchAccountPage.open']) that reveals the screen from the start route. Any public page-object method can be used. Leave open empty when no action reveals the screen (a form must be filled, a storage key set); the specs are then the reproduction. A routed entry may also set open when the screen only renders after an action from its route.

Commands

pnpm lt feature-map generate --app extension                  # write .claude/skills/feature-map/extension.md (gitignored; run before reading)
pnpm lt feature-map check                                      # CI gate: entries, references, route and rpc coverage

Run pnpm --filter @leather.io/tools build first if pnpm lt reports an unknown command.

Adding or changing an entry

  • Every routed RouteUrls key and every rpc handler file must be claimed by an entry. A nested sheet (edit-tx-nonce, recipient-accounts) is listed in the routes of the feature whose route mounts it.
  • specs, actions and open (PageObject.method), preconditions.mocks (mock functions exported from tests/mocks) and entry[].method (an RPC method string) must exist; flags must be keys of FeatureFlags; anchor.objects must name exported *Selectors objects or members and anchor.handlers files under rpc-methods.
  • selectors.ready is the element whose presence means the screen is usable; it is required for route and selectors anchors and may be omitted for rpc anchors without UI and for behaviors. others are the elements a repro will touch on this screen; the control on the previous screen that opens it belongs in the entry steps. Both are *Selectors.Member references, never raw strings, and both must render on this screen in the precondition state (say in the description when one is conditional).
  • preconditions.mocks lists the mock functions that take only a page or context handle: always setupMockApis and mockUnhandledRequests (what globalPage.setupAndUseApiCalls registers), plus the ones the screen's default state needs on top. A mock that setupMockApis already calls fails the check when listed next to it. A variant mock only some covering specs register (mockMixedUtxosForSend) and a mock that needs data arguments (mockLeatherBitcoinTransactions, mockMixedUtxoRequests, mockBnsV2NameLookup, mockFundedStacksAddress, overrideLaunchDarklyFlags, …) is named in the description together with the spec that registers it and what it changes on the screen.
  • preconditions.network is set whenever a covering spec switches network or the screen requires one (swap needs mainnet; most send specs run on testnet4).
  • Descriptions state only what a component, hook or spec shows, with UI strings quoted verbatim. Write "back goes to the previous page" when the header back button calls navigate(-1), and say when a control opens a full-page tab from the popup (Buy, Sell, Send on Ledger); specs run full-page, so they never show that branch.
  • gate must match what the router mounts the route behind (the innermost of AccountGate, OnboardingGate, LedgerStacksGate, LedgerBitcoinGate, or none); the check compares it per mounted path for route anchors, so an entry whose routes sit behind different gates has to be split. For other anchors it documents the gate of the screen that hosts the dialog.
  • entry for an RPC popup is kind: 'rpc' with the method string the dApp calls; the steps say how the test app at localhost:3000 triggers it and that the popup is awaited with context.waitForEvent('page').
  • deepLinkable: false marks a screen that reads router state the previous screen passes (the send confirmations, the sent summaries, the BTC fee sheet, the swap review): a bare URL redirects or throws, so extension.md says so and the specs are the reproduction.
  • specs: [] is allowed; those entries are listed under Uncovered screens in extension.md so E2E work can target them.
  • Whenever a spec, page object, mock or selector under apps/extension/tests changes, or the screen a spec covers changes, proofread the entries that reference it (grep the file path or selector in *.features.ts) and fix their steps, preconditions and description. The check validates references only; wrong prose passes it.
  • After editing a source run check, then generate to refresh your local extension.md; the file is gitignored and never committed.
  • The check validates references, not prose. Every Monday repo:feature-map-fix reads every entry against the source (.github/prompts/feature-map-fix.md), fixes the statements it can prove false and opens or updates the bot/feature-map-fix pull request with a per-row citation; it closes that PR when a run finds nothing. Re-read the cited lines before merging it.

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.